PageSourceSearch

https://diagnosticquestions.com/app/build/vendor-bundle.b202dc83.js

js diagnosticquestions.com collected 2026-10-03 20:22:28 UTC 3,521,393 bytes, 103,140 lines download raw bytes

vendor: 4,403 bytes, lines 1-173
1/*!
2 * jQuery JavaScript Library v2.1.0
3 * http://jquery.com/
4 *
5 * Includes Sizzle.js
6 * http://sizzlejs.com/
7 *
8 * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors
9 * Released under the MIT license
10 * http://jquery.org/license
11 *
12 * Date: 2014-01-23T21:10Z
13 */
14
15(function( global, factory ) {
16
17	if ( typeof module === "object" && typeof module.exports === "object" ) {
18		// For CommonJS and CommonJS-like environments where a proper window is present,
19		// execute the factory and get jQuery
20		// For environments that do not inherently posses a window with a document
21		// (such as Node.js), expose a jQuery-making factory as module.exports
22		// This accentuates the need for the creation of a real window
23		// e.g. var jQuery = require("jquery")(window);
24		// See ticket #14549 for more info
25		module.exports = global.document ?
26			factory( global, true ) :
27			function( w ) {
28				if ( !w.document ) {
29					throw new Error( "jQuery requires a window with a document" );
30				}
31				return factory( w );
32			};
33	} else {
34		factory( global );
35	}
36
37// Pass this if window is not defined yet
38}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
39
40// Can't do this because several apps including ASP.NET trace
41// the stack via arguments.caller.callee and Firefox dies if
42// you try to trace through "use strict" call chains. (#13335)
43// Support: Firefox 18+
44//
45
46var arr = [];
47
48var slice = arr.slice;
49
50var concat = arr.concat;
51
52var push = arr.push;
53
54var indexOf = arr.indexOf;
55
56var class2type = {};
57
58var toString = class2type.toString;
59
60var hasOwn = class2type.hasOwnProperty;
61
62var trim = "".trim;
63
64var support = {};
65
66
67
68var
69	// Use the correct document accordingly with window argument (sandbox)
70	document = window.document,
71
72	version = "2.1.0",
73
74	// Define a local copy of jQuery
75	jQuery = function( selector, context ) {
76		// The jQuery object is actually just the init constructor 'enhanced'
77		// Need init if jQuery is called (just allow error to be thrown if not included)
78		return new jQuery.fn.init( selector, context );
79	},
80
81	// Matches dashed string for camelizing
82	rmsPrefix = /^-ms-/,
83	rdashAlpha = /-([\da-z])/gi,
84
85	// Used by jQuery.camelCase as callback to replace()
86	fcamelCase = function( all, letter ) {
87		return letter.toUpperCase();
88	};
89
90jQuery.fn = jQuery.prototype = {
91	// The current version of jQuery being used
92	jquery: version,
93
94	constructor: jQuery,
95
96	// Start with an empty selector
97	selector: "",
98
99	// The default length of a jQuery object is 0
100	length: 0,
101
102	toArray: function() {
103		return slice.call( this );
104	},
105
106	// Get the Nth element in the matched element set OR
107	// Get the whole matched element set as a clean array
108	get: function( num ) {
109		return num != null ?
110
111			// Return a 'clean' array
112			( num < 0 ? this[ num + this.length ] : this[ num ] ) :
113
114			// Return just the object
115			slice.call( this );
116	},
117
118	// Take an array of elements and push it onto the stack
119	// (returning the new matched element set)
120	pushStack: function( elems ) {
121
122		// Build a new jQuery matched element set
123		var ret = jQuery.merge( this.constructor(), elems );
124
125		// Add the old object onto the stack (as a reference)
126		ret.prevObject = this;
127		ret.context = this.context;
128
129		// Return the newly-formed element set
130		return ret;
131	},
132
133	// Execute a callback for every element in the matched set.
134	// (You can seed the arguments with an array of args, but this is
135	// only used internally.)
136	each: function( callback, args ) {
137		return jQuery.each( this, callback, args );
138	},
139
140	map: function( callback ) {
141		return this.pushStack( jQuery.map(this, function( elem, i ) {
142			return callback.call( elem, i, elem );
143		}));
144	},
145
146	slice: function() {
147		return this.pushStack( slice.apply( this, arguments ) );
148	},
149
150	first: function() {
151		return this.eq( 0 );
152	},
153
154	last: function() {
155		return this.eq( -1 );
156	},
157
158	eq: function( i ) {
159		var len = this.length,
160			j = +i + ( i < 0 ? len : 0 );
161		return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );
162	},
163
164	end: function() {
165		return this.prevObject || this.constructor(null);
166	},
167
168	// For internal use only.
169	// Behaves like an Array's method, not like a jQuery method.
170	push: push,
171	sort: arr.sort,
172	splice: arr.splice
173};
vendor: 5,813 bytes, lines 174-398
174
175jQuery.extend = jQuery.fn.extend = function() {
176	var options, name, src, copy, copyIsArray, clone,
177		target = arguments[0] || {},
178		i = 1,
179		length = arguments.length,
180		deep = false;
181
182	// Handle a deep copy situation
183	if ( typeof target === "boolean" ) {
184		deep = target;
185
186		// skip the boolean and the target
187		target = arguments[ i ] || {};
188		i++;
189	}
190
191	// Handle case when target is a string or something (possible in deep copy)
192	if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
193		target = {};
194	}
195
196	// extend jQuery itself if only one argument is passed
197	if ( i === length ) {
198		target = this;
199		i--;
200	}
201
202	for ( ; i < length; i++ ) {
203		// Only deal with non-null/undefined values
204		if ( (options = arguments[ i ]) != null ) {
205			// Extend the base object
206			for ( name in options ) {
207				src = target[ name ];
208				copy = options[ name ];
209
210				// Prevent never-ending loop
211				if ( target === copy ) {
212					continue;
213				}
214
215				// Recurse if we're merging plain objects or arrays
216				if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
217					if ( copyIsArray ) {
218						copyIsArray = false;
219						clone = src && jQuery.isArray(src) ? src : [];
220
221					} else {
222						clone = src && jQuery.isPlainObject(src) ? src : {};
223					}
224
225					// Never move original objects, clone them
226					target[ name ] = jQuery.extend( deep, clone, copy );
227
228				// Don't bring in undefined values
229				} else if ( copy !== undefined ) {
230					target[ name ] = copy;
231				}
232			}
233		}
234	}
235
236	// Return the modified object
237	return target;
238};
239
240jQuery.extend({
241	// Unique for each copy of jQuery on the page
242	expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
243
244	// Assume jQuery is ready without the ready module
245	isReady: true,
246
247	error: function( msg ) {
248		throw new Error( msg );
249	},
250
251	noop: function() {},
252
253	// See test/unit/core.js for details concerning isFunction.
254	// Since version 1.3, DOM methods and functions like alert
255	// aren't supported. They return false on IE (#2968).
256	isFunction: function( obj ) {
257		return jQuery.type(obj) === "function";
258	},
259
260	isArray: Array.isArray,
261
262	isWindow: function( obj ) {
263		return obj != null && obj === obj.window;
264	},
265
266	isNumeric: function( obj ) {
267		// parseFloat NaNs numeric-cast false positives (null|true|false|"")
268		// ...but misinterprets leading-number strings, particularly hex literals ("0x...")
269		// subtraction forces infinities to NaN
270		return obj - parseFloat( obj ) >= 0;
271	},
272
273	isPlainObject: function( obj ) {
274		// Not plain objects:
275		// - Any object or value whose internal [[Class]] property is not "[object Object]"
276		// - DOM nodes
277		// - window
278		if ( jQuery.type( obj ) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
279			return false;
280		}
281
282		// Support: Firefox <20
283		// The try/catch suppresses exceptions thrown when attempting to access
284		// the "constructor" property of certain host objects, ie. |window.location|
285		// https://bugzilla.mozilla.org/show_bug.cgi?id=814622
286		try {
287			if ( obj.constructor &&
288					!hasOwn.call( obj.constructor.prototype, "isPrototypeOf" ) ) {
289				return false;
290			}
291		} catch ( e ) {
292			return false;
293		}
294
295		// If the function hasn't returned already, we're confident that
296		// |obj| is a plain object, created by {} or constructed with new Object
297		return true;
298	},
299
300	isEmptyObject: function( obj ) {
301		var name;
302		for ( name in obj ) {
303			return false;
304		}
305		return true;
306	},
307
308	type: function( obj ) {
309		if ( obj == null ) {
310			return obj + "";
311		}
312		// Support: Android < 4.0, iOS < 6 (functionish RegExp)
313		return typeof obj === "object" || typeof obj === "function" ?
314			class2type[ toString.call(obj) ] || "object" :
315			typeof obj;
316	},
317
318	// Evaluates a script in a global context
319	globalEval: function( code ) {
320		var script,
321			indirect = eval;
322
323		code = jQuery.trim( code );
324
325		if ( code ) {
326			// If the code includes a valid, prologue position
327			// strict mode pragma, execute code by injecting a
328			// script tag into the document.
329			if ( code.indexOf("use strict") === 1 ) {
330				script = document.createElement("script");
331				script.text = code;
332				document.head.appendChild( script ).parentNode.removeChild( script );
333			} else {
334			// Otherwise, avoid the DOM node creation, insertion
335			// and removal by using an indirect global eval
336				indirect( code );
337			}
338		}
339	},
340
341	// Convert dashed to camelCase; used by the css and data modules
342	// Microsoft forgot to hump their vendor prefix (#9572)
343	camelCase: function( string ) {
344		return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
345	},
346
347	nodeName: function( elem, name ) {
348		return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
349	},
350
351	// args is for internal usage only
352	each: function( obj, callback, args ) {
353		var value,
354			i = 0,
355			length = obj.length,
356			isArray = isArraylike( obj );
357
358		if ( args ) {
359			if ( isArray ) {
360				for ( ; i < length; i++ ) {
361					value = callback.apply( obj[ i ], args );
362
363					if ( value === false ) {
364						break;
365					}
366				}
367			} else {
368				for ( i in obj ) {
369					value = callback.apply( obj[ i ], args );
370
371					if ( value === false ) {
372						break;
373					}
374				}
375			}
376
377		// A special, fast, case for the most common use of each
378		} else {
379			if ( isArray ) {
380				for ( ; i < length; i++ ) {
381					value = callback.call( obj[ i ], i, obj[ i ] );
382
383					if ( value === false ) {
384						break;
385					}
386				}
387			} else {
388				for ( i in obj ) {
389					value = callback.call( obj[ i ], i, obj[ i ] );
390
391					if ( value === false ) {
392						break;
393					}
394				}
395			}
396		}
397
398		return obj;
vendor: 60,029 bytes, lines 399-2462
399	},
400
401	trim: function( text ) {
402		return text == null ? "" : trim.call( text );
403	},
404
405	// results is for internal usage only
406	makeArray: function( arr, results ) {
407		var ret = results || [];
408
409		if ( arr != null ) {
410			if ( isArraylike( Object(arr) ) ) {
411				jQuery.merge( ret,
412					typeof arr === "string" ?
413					[ arr ] : arr
414				);
415			} else {
416				push.call( ret, arr );
417			}
418		}
419
420		return ret;
421	},
422
423	inArray: function( elem, arr, i ) {
424		return arr == null ? -1 : indexOf.call( arr, elem, i );
425	},
426
427	merge: function( first, second ) {
428		var len = +second.length,
429			j = 0,
430			i = first.length;
431
432		for ( ; j < len; j++ ) {
433			first[ i++ ] = second[ j ];
434		}
435
436		first.length = i;
437
438		return first;
439	},
440
441	grep: function( elems, callback, invert ) {
442		var callbackInverse,
443			matches = [],
444			i = 0,
445			length = elems.length,
446			callbackExpect = !invert;
447
448		// Go through the array, only saving the items
449		// that pass the validator function
450		for ( ; i < length; i++ ) {
451			callbackInverse = !callback( elems[ i ], i );
452			if ( callbackInverse !== callbackExpect ) {
453				matches.push( elems[ i ] );
454			}
455		}
456
457		return matches;
458	},
459
460	// arg is for internal usage only
461	map: function( elems, callback, arg ) {
462		var value,
463			i = 0,
464			length = elems.length,
465			isArray = isArraylike( elems ),
466			ret = [];
467
468		// Go through the array, translating each of the items to their new values
469		if ( isArray ) {
470			for ( ; i < length; i++ ) {
471				value = callback( elems[ i ], i, arg );
472
473				if ( value != null ) {
474					ret.push( value );
475				}
476			}
477
478		// Go through every key on the object,
479		} else {
480			for ( i in elems ) {
481				value = callback( elems[ i ], i, arg );
482
483				if ( value != null ) {
484					ret.push( value );
485				}
486			}
487		}
488
489		// Flatten any nested arrays
490		return concat.apply( [], ret );
491	},
492
493	// A global GUID counter for objects
494	guid: 1,
495
496	// Bind a function to a context, optionally partially applying any
497	// arguments.
498	proxy: function( fn, context ) {
499		var tmp, args, proxy;
500
501		if ( typeof context === "string" ) {
502			tmp = fn[ context ];
503			context = fn;
504			fn = tmp;
505		}
506
507		// Quick check to determine if target is callable, in the spec
508		// this throws a TypeError, but we will just return undefined.
509		if ( !jQuery.isFunction( fn ) ) {
510			return undefined;
511		}
512
513		// Simulated bind
514		args = slice.call( arguments, 2 );
515		proxy = function() {
516			return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
517		};
518
519		// Set the guid of unique handler to the same of original handler, so it can be removed
520		proxy.guid = fn.guid = fn.guid || jQuery.guid++;
521
522		return proxy;
523	},
524
525	now: Date.now,
526
527	// jQuery.support is not used in Core but other projects attach their
528	// properties to it so it needs to exist.
529	support: support
530});
531
532// Populate the class2type map
533jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
534	class2type[ "[object " + name + "]" ] = name.toLowerCase();
535});
536
537function isArraylike( obj ) {
538	var length = obj.length,
539		type = jQuery.type( obj );
540
541	if ( type === "function" || jQuery.isWindow( obj ) ) {
542		return false;
543	}
544
545	if ( obj.nodeType === 1 && length ) {
546		return true;
547	}
548
549	return type === "array" || length === 0 ||
550		typeof length === "number" && length > 0 && ( length - 1 ) in obj;
551}
552var Sizzle =
553/*!
554 * Sizzle CSS Selector Engine v1.10.16
555 * http://sizzlejs.com/
556 *
557 * Copyright 2013 jQuery Foundation, Inc. and other contributors
558 * Released under the MIT license
559 * http://jquery.org/license
560 *
561 * Date: 2014-01-13
562 */
563(function( window ) {
564
565var i,
566	support,
567	Expr,
568	getText,
569	isXML,
570	compile,
571	outermostContext,
572	sortInput,
573	hasDuplicate,
574
575	// Local document vars
576	setDocument,
577	document,
578	docElem,
579	documentIsHTML,
580	rbuggyQSA,
581	rbuggyMatches,
582	matches,
583	contains,
584
585	// Instance-specific data
586	expando = "sizzle" + -(new Date()),
587	preferredDoc = window.document,
588	dirruns = 0,
589	done = 0,
590	classCache = createCache(),
591	tokenCache = createCache(),
592	compilerCache = createCache(),
593	sortOrder = function( a, b ) {
594		if ( a === b ) {
595			hasDuplicate = true;
596		}
597		return 0;
598	},
599
600	// General-purpose constants
601	strundefined = typeof undefined,
602	MAX_NEGATIVE = 1 << 31,
603
604	// Instance methods
605	hasOwn = ({}).hasOwnProperty,
606	arr = [],
607	pop = arr.pop,
608	push_native = arr.push,
609	push = arr.push,
610	slice = arr.slice,
611	// Use a stripped-down indexOf if we can't use a native one
612	indexOf = arr.indexOf || function( elem ) {
613		var i = 0,
614			len = this.length;
615		for ( ; i < len; i++ ) {
616			if ( this[i] === elem ) {
617				return i;
618			}
619		}
620		return -1;
621	},
622
623	booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
624
625	// Regular expressions
626
627	// Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
628	whitespace = "[\\x20\\t\\r\\n\\f]",
629	// http://www.w3.org/TR/css3-syntax/#characters
630	characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
631
632	// Loosely modeled on CSS identifier characters
633	// An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
634	// Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
635	identifier = characterEncoding.replace( "w", "w#" ),
636
637	// Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors
638	attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace +
639		"*(?:([*^$|!~]?=)" + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]",
640
641	// Prefer arguments quoted,
642	//   then not containing pseudos/brackets,
643	//   then attribute selectors/non-parenthetical expressions,
644	//   then anything else
645	// These preferences are here to reduce the number of selectors
646	//   needing tokenize in the PSEUDO preFilter
647	pseudos = ":(" + characterEncoding + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + attributes.replace( 3, 8 ) + ")*)|.*)\\)|)",
648
649	// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
650	rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
651
652	rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
653	rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
654
655	rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
656
657	rpseudo = new RegExp( pseudos ),
658	ridentifier = new RegExp( "^" + identifier + "$" ),
659
660	matchExpr = {
661		"ID": new RegExp( "^#(" + characterEncoding + ")" ),
662		"CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
663		"TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
664		"ATTR": new RegExp( "^" + attributes ),
665		"PSEUDO": new RegExp( "^" + pseudos ),
666		"CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
667			"*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
668			"*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
669		"bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
670		// For use in libraries implementing .is()
671		// We use this for POS matching in `select`
672		"needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
673			whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
674	},
675
676	rinputs = /^(?:input|select|textarea|button)$/i,
677	rheader = /^h\d$/i,
678
679	rnative = /^[^{]+\{\s*\[native \w/,
680
681	// Easily-parseable/retrievable ID or TAG or CLASS selectors
682	rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
683
684	rsibling = /[+~]/,
685	rescape = /'|\\/g,
686
687	// CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
688	runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
689	funescape = function( _, escaped, escapedWhitespace ) {
690		var high = "0x" + escaped - 0x10000;
691		// NaN means non-codepoint
692		// Support: Firefox
693		// Workaround erroneous numeric interpretation of +"0x"
694		return high !== high || escapedWhitespace ?
695			escaped :
696			high < 0 ?
697				// BMP codepoint
698				String.fromCharCode( high + 0x10000 ) :
699				// Supplemental Plane codepoint (surrogate pair)
700				String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
701	};
702
703// Optimize for push.apply( _, NodeList )
704try {
705	push.apply(
706		(arr = slice.call( preferredDoc.childNodes )),
707		preferredDoc.childNodes
708	);
709	// Support: Android<4.0
710	// Detect silently failing push.apply
711	arr[ preferredDoc.childNodes.length ].nodeType;
712} catch ( e ) {
713	push = { apply: arr.length ?
714
715		// Leverage slice if possible
716		function( target, els ) {
717			push_native.apply( target, slice.call(els) );
718		} :
719
720		// Support: IE<9
721		// Otherwise append directly
722		function( target, els ) {
723			var j = target.length,
724				i = 0;
725			// Can't trust NodeList.length
726			while ( (target[j++] = els[i++]) ) {}
727			target.length = j - 1;
728		}
729	};
730}
731
732function Sizzle( selector, context, results, seed ) {
733	var match, elem, m, nodeType,
734		// QSA vars
735		i, groups, old, nid, newContext, newSelector;
736
737	if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
738		setDocument( context );
739	}
740
741	context = context || document;
742	results = results || [];
743
744	if ( !selector || typeof selector !== "string" ) {
745		return results;
746	}
747
748	if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) {
749		return [];
750	}
751
752	if ( documentIsHTML && !seed ) {
753
754		// Shortcuts
755		if ( (match = rquickExpr.exec( selector )) ) {
756			// Speed-up: Sizzle("#ID")
757			if ( (m = match[1]) ) {
758				if ( nodeType === 9 ) {
759					elem = context.getElementById( m );
760					// Check parentNode to catch when Blackberry 4.6 returns
761					// nodes that are no longer in the document (jQuery #6963)
762					if ( elem && elem.parentNode ) {
763						// Handle the case where IE, Opera, and Webkit return items
764						// by name instead of ID
765						if ( elem.id === m ) {
766							results.push( elem );
767							return results;
768						}
769					} else {
770						return results;
771					}
772				} else {
773					// Context is not a document
774					if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
775						contains( context, elem ) && elem.id === m ) {
776						results.push( elem );
777						return results;
778					}
779				}
780
781			// Speed-up: Sizzle("TAG")
782			} else if ( match[2] ) {
783				push.apply( results, context.getElementsByTagName( selector ) );
784				return results;
785
786			// Speed-up: Sizzle(".CLASS")
787			} else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) {
788				push.apply( results, context.getElementsByClassName( m ) );
789				return results;
790			}
791		}
792
793		// QSA path
794		if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
795			nid = old = expando;
796			newContext = context;
797			newSelector = nodeType === 9 && selector;
798
799			// qSA works strangely on Element-rooted queries
800			// We can work around this by specifying an extra ID on the root
801			// and working up from there (Thanks to Andrew Dupont for the technique)
802			// IE 8 doesn't work on object elements
803			if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
804				groups = tokenize( selector );
805
806				if ( (old = context.getAttribute("id")) ) {
807					nid = old.replace( rescape, "\\$&" );
808				} else {
809					context.setAttribute( "id", nid );
810				}
811				nid = "[id='" + nid + "'] ";
812
813				i = groups.length;
814				while ( i-- ) {
815					groups[i] = nid + toSelector( groups[i] );
816				}
817				newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context;
818				newSelector = groups.join(",");
819			}
820
821			if ( newSelector ) {
822				try {
823					push.apply( results,
824						newContext.querySelectorAll( newSelector )
825					);
826					return results;
827				} catch(qsaError) {
828				} finally {
829					if ( !old ) {
830						context.removeAttribute("id");
831					}
832				}
833			}
834		}
835	}
836
837	// All others
838	return select( selector.replace( rtrim, "$1" ), context, results, seed );
839}
840
841/**
842 * Create key-value caches of limited size
843 * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
844 *	property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
845 *	deleting the oldest entry
846 */
847function createCache() {
848	var keys = [];
849
850	function cache( key, value ) {
851		// Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
852		if ( keys.push( key + " " ) > Expr.cacheLength ) {
853			// Only keep the most recent entries
854			delete cache[ keys.shift() ];
855		}
856		return (cache[ key + " " ] = value);
857	}
858	return cache;
859}
860
861/**
862 * Mark a function for special use by Sizzle
863 * @param {Function} fn The function to mark
864 */
865function markFunction( fn ) {
866	fn[ expando ] = true;
867	return fn;
868}
869
870/**
871 * Support testing using an element
872 * @param {Function} fn Passed the created div and expects a boolean result
873 */
874function assert( fn ) {
875	var div = document.createElement("div");
876
877	try {
878		return !!fn( div );
879	} catch (e) {
880		return false;
881	} finally {
882		// Remove from its parent by default
883		if ( div.parentNode ) {
884			div.parentNode.removeChild( div );
885		}
886		// release memory in IE
887		div = null;
888	}
889}
890
891/**
892 * Adds the same handler for all of the specified attrs
893 * @param {String} attrs Pipe-separated list of attributes
894 * @param {Function} handler The method that will be applied
895 */
896function addHandle( attrs, handler ) {
897	var arr = attrs.split("|"),
898		i = attrs.length;
899
900	while ( i-- ) {
901		Expr.attrHandle[ arr[i] ] = handler;
902	}
903}
904
905/**
906 * Checks document order of two siblings
907 * @param {Element} a
908 * @param {Element} b
909 * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
910 */
911function siblingCheck( a, b ) {
912	var cur = b && a,
913		diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
914			( ~b.sourceIndex || MAX_NEGATIVE ) -
915			( ~a.sourceIndex || MAX_NEGATIVE );
916
917	// Use IE sourceIndex if available on both nodes
918	if ( diff ) {
919		return diff;
920	}
921
922	// Check if b follows a
923	if ( cur ) {
924		while ( (cur = cur.nextSibling) ) {
925			if ( cur === b ) {
926				return -1;
927			}
928		}
929	}
930
931	return a ? 1 : -1;
932}
933
934/**
935 * Returns a function to use in pseudos for input types
936 * @param {String} type
937 */
938function createInputPseudo( type ) {
939	return function( elem ) {
940		var name = elem.nodeName.toLowerCase();
941		return name === "input" && elem.type === type;
942	};
943}
944
945/**
946 * Returns a function to use in pseudos for buttons
947 * @param {String} type
948 */
949function createButtonPseudo( type ) {
950	return function( elem ) {
951		var name = elem.nodeName.toLowerCase();
952		return (name === "input" || name === "button") && elem.type === type;
953	};
954}
955
956/**
957 * Returns a function to use in pseudos for positionals
958 * @param {Function} fn
959 */
960function createPositionalPseudo( fn ) {
961	return markFunction(function( argument ) {
962		argument = +argument;
963		return markFunction(function( seed, matches ) {
964			var j,
965				matchIndexes = fn( [], seed.length, argument ),
966				i = matchIndexes.length;
967
968			// Match elements found at the specified indexes
969			while ( i-- ) {
970				if ( seed[ (j = matchIndexes[i]) ] ) {
971					seed[j] = !(matches[j] = seed[j]);
972				}
973			}
974		});
975	});
976}
977
978/**
979 * Checks a node for validity as a Sizzle context
980 * @param {Element|Object=} context
981 * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
982 */
983function testContext( context ) {
984	return context && typeof context.getElementsByTagName !== strundefined && context;
985}
986
987// Expose support vars for convenience
988support = Sizzle.support = {};
989
990/**
991 * Detects XML nodes
992 * @param {Element|Object} elem An element or a document
993 * @returns {Boolean} True iff elem is a non-HTML XML node
994 */
995isXML = Sizzle.isXML = function( elem ) {
996	// documentElement is verified for cases where it doesn't yet exist
997	// (such as loading iframes in IE - #4833)
998	var documentElement = elem && (elem.ownerDocument || elem).documentElement;
999	return documentElement ? documentElement.nodeName !== "HTML" : false;
1000};
1001
1002/**
1003 * Sets document-related variables once based on the current document
1004 * @param {Element|Object} [doc] An element or document object to use to set the document
1005 * @returns {Object} Returns the current document
1006 */
1007setDocument = Sizzle.setDocument = function( node ) {
1008	var hasCompare,
1009		doc = node ? node.ownerDocument || node : preferredDoc,
1010		parent = doc.defaultView;
1011
1012	// If no document and documentElement is available, return
1013	if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
1014		return document;
1015	}
1016
1017	// Set our document
1018	document = doc;
1019	docElem = doc.documentElement;
1020
1021	// Support tests
1022	documentIsHTML = !isXML( doc );
1023
1024	// Support: IE>8
1025	// If iframe document is assigned to "document" variable and if iframe has been reloaded,
1026	// IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936
1027	// IE6-8 do not support the defaultView property so parent will be undefined
1028	if ( parent && parent !== parent.top ) {
1029		// IE11 does not have attachEvent, so all must suffer
1030		if ( parent.addEventListener ) {
1031			parent.addEventListener( "unload", function() {
1032				setDocument();
1033			}, false );
1034		} else if ( parent.attachEvent ) {
1035			parent.attachEvent( "onunload", function() {
1036				setDocument();
1037			});
1038		}
1039	}
1040
1041	/* Attributes
1042	---------------------------------------------------------------------- */
1043
1044	// Support: IE<8
1045	// Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans)
1046	support.attributes = assert(function( div ) {
1047		div.className = "i";
1048		return !div.getAttribute("className");
1049	});
1050
1051	/* getElement(s)By*
1052	---------------------------------------------------------------------- */
1053
1054	// Check if getElementsByTagName("*") returns only elements
1055	support.getElementsByTagName = assert(function( div ) {
1056		div.appendChild( doc.createComment("") );
1057		return !div.getElementsByTagName("*").length;
1058	});
1059
1060	// Check if getElementsByClassName can be trusted
1061	support.getElementsByClassName = rnative.test( doc.getElementsByClassName ) && assert(function( div ) {
1062		div.innerHTML = "<div class='a'></div><div class='a i'></div>";
1063
1064		// Support: Safari<4
1065		// Catch class over-caching
1066		div.firstChild.className = "i";
1067		// Support: Opera<10
1068		// Catch gEBCN failure to find non-leading classes
1069		return div.getElementsByClassName("i").length === 2;
1070	});
1071
1072	// Support: IE<10
1073	// Check if getElementById returns elements by name
1074	// The broken getElementById methods don't pick up programatically-set names,
1075	// so use a roundabout getElementsByName test
1076	support.getById = assert(function( div ) {
1077		docElem.appendChild( div ).id = expando;
1078		return !doc.getElementsByName || !doc.getElementsByName( expando ).length;
1079	});
1080
1081	// ID find and filter
1082	if ( support.getById ) {
1083		Expr.find["ID"] = function( id, context ) {
1084			if ( typeof context.getElementById !== strundefined && documentIsHTML ) {
1085				var m = context.getElementById( id );
1086				// Check parentNode to catch when Blackberry 4.6 returns
1087				// nodes that are no longer in the document #6963
1088				return m && m.parentNode ? [m] : [];
1089			}
1090		};
1091		Expr.filter["ID"] = function( id ) {
1092			var attrId = id.replace( runescape, funescape );
1093			return function( elem ) {
1094				return elem.getAttribute("id") === attrId;
1095			};
1096		};
1097	} else {
1098		// Support: IE6/7
1099		// getElementById is not reliable as a find shortcut
1100		delete Expr.find["ID"];
1101
1102		Expr.filter["ID"] =  function( id ) {
1103			var attrId = id.replace( runescape, funescape );
1104			return function( elem ) {
1105				var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");
1106				return node && node.value === attrId;
1107			};
1108		};
1109	}
1110
1111	// Tag
1112	Expr.find["TAG"] = support.getElementsByTagName ?
1113		function( tag, context ) {
1114			if ( typeof context.getElementsByTagName !== strundefined ) {
1115				return context.getElementsByTagName( tag );
1116			}
1117		} :
1118		function( tag, context ) {
1119			var elem,
1120				tmp = [],
1121				i = 0,
1122				results = context.getElementsByTagName( tag );
1123
1124			// Filter out possible comments
1125			if ( tag === "*" ) {
1126				while ( (elem = results[i++]) ) {
1127					if ( elem.nodeType === 1 ) {
1128						tmp.push( elem );
1129					}
1130				}
1131
1132				return tmp;
1133			}
1134			return results;
1135		};
1136
1137	// Class
1138	Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
1139		if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) {
1140			return context.getElementsByClassName( className );
1141		}
1142	};
1143
1144	/* QSA/matchesSelector
1145	---------------------------------------------------------------------- */
1146
1147	// QSA and matchesSelector support
1148
1149	// matchesSelector(:active) reports false when true (IE9/Opera 11.5)
1150	rbuggyMatches = [];
1151
1152	// qSa(:focus) reports false when true (Chrome 21)
1153	// We allow this because of a bug in IE8/9 that throws an error
1154	// whenever `document.activeElement` is accessed on an iframe
1155	// So, we allow :focus to pass through QSA all the time to avoid the IE error
1156	// See http://bugs.jquery.com/ticket/13378
1157	rbuggyQSA = [];
1158
1159	if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {
1160		// Build QSA regex
1161		// Regex strategy adopted from Diego Perini
1162		assert(function( div ) {
1163			// Select is set to empty string on purpose
1164			// This is to test IE's treatment of not explicitly
1165			// setting a boolean content attribute,
1166			// since its presence should be enough
1167			// http://bugs.jquery.com/ticket/12359
1168			div.innerHTML = "<select t=''><option selected=''></option></select>";
1169
1170			// Support: IE8, Opera 10-12
1171			// Nothing should be selected when empty strings follow ^= or $= or *=
1172			if ( div.querySelectorAll("[t^='']").length ) {
1173				rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
1174			}
1175
1176			// Support: IE8
1177			// Boolean attributes and "value" are not treated correctly
1178			if ( !div.querySelectorAll("[selected]").length ) {
1179				rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
1180			}
1181
1182			// Webkit/Opera - :checked should return selected option elements
1183			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
1184			// IE8 throws error here and will not see later tests
1185			if ( !div.querySelectorAll(":checked").length ) {
1186				rbuggyQSA.push(":checked");
1187			}
1188		});
1189
1190		assert(function( div ) {
1191			// Support: Windows 8 Native Apps
1192			// The type and name attributes are restricted during .innerHTML assignment
1193			var input = doc.createElement("input");
1194			input.setAttribute( "type", "hidden" );
1195			div.appendChild( input ).setAttribute( "name", "D" );
1196
1197			// Support: IE8
1198			// Enforce case-sensitivity of name attribute
1199			if ( div.querySelectorAll("[name=d]").length ) {
1200				rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
1201			}
1202
1203			// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
1204			// IE8 throws error here and will not see later tests
1205			if ( !div.querySelectorAll(":enabled").length ) {
1206				rbuggyQSA.push( ":enabled", ":disabled" );
1207			}
1208
1209			// Opera 10-11 does not throw on post-comma invalid pseudos
1210			div.querySelectorAll("*,:x");
1211			rbuggyQSA.push(",.*:");
1212		});
1213	}
1214
1215	if ( (support.matchesSelector = rnative.test( (matches = docElem.webkitMatchesSelector ||
1216		docElem.mozMatchesSelector ||
1217		docElem.oMatchesSelector ||
1218		docElem.msMatchesSelector) )) ) {
1219
1220		assert(function( div ) {
1221			// Check to see if it's possible to do matchesSelector
1222			// on a disconnected node (IE 9)
1223			support.disconnectedMatch = matches.call( div, "div" );
1224
1225			// This should fail with an exception
1226			// Gecko does not error, returns false instead
1227			matches.call( div, "[s!='']:x" );
1228			rbuggyMatches.push( "!=", pseudos );
1229		});
1230	}
1231
1232	rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
1233	rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
1234
1235	/* Contains
1236	---------------------------------------------------------------------- */
1237	hasCompare = rnative.test( docElem.compareDocumentPosition );
1238
1239	// Element contains another
1240	// Purposefully does not implement inclusive descendent
1241	// As in, an element does not contain itself
1242	contains = hasCompare || rnative.test( docElem.contains ) ?
1243		function( a, b ) {
1244			var adown = a.nodeType === 9 ? a.documentElement : a,
1245				bup = b && b.parentNode;
1246			return a === bup || !!( bup && bup.nodeType === 1 && (
1247				adown.contains ?
1248					adown.contains( bup ) :
1249					a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
1250			));
1251		} :
1252		function( a, b ) {
1253			if ( b ) {
1254				while ( (b = b.parentNode) ) {
1255					if ( b === a ) {
1256						return true;
1257					}
1258				}
1259			}
1260			return false;
1261		};
1262
1263	/* Sorting
1264	---------------------------------------------------------------------- */
1265
1266	// Document order sorting
1267	sortOrder = hasCompare ?
1268	function( a, b ) {
1269
1270		// Flag for duplicate removal
1271		if ( a === b ) {
1272			hasDuplicate = true;
1273			return 0;
1274		}
1275
1276		// Sort on method existence if only one input has compareDocumentPosition
1277		var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
1278		if ( compare ) {
1279			return compare;
1280		}
1281
1282		// Calculate position if both inputs belong to the same document
1283		compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
1284			a.compareDocumentPosition( b ) :
1285
1286			// Otherwise we know they are disconnected
1287			1;
1288
1289		// Disconnected nodes
1290		if ( compare & 1 ||
1291			(!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
1292
1293			// Choose the first element that is related to our preferred document
1294			if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
1295				return -1;
1296			}
1297			if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
1298				return 1;
1299			}
1300
1301			// Maintain original order
1302			return sortInput ?
1303				( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
1304				0;
1305		}
1306
1307		return compare & 4 ? -1 : 1;
1308	} :
1309	function( a, b ) {
1310		// Exit early if the nodes are identical
1311		if ( a === b ) {
1312			hasDuplicate = true;
1313			return 0;
1314		}
1315
1316		var cur,
1317			i = 0,
1318			aup = a.parentNode,
1319			bup = b.parentNode,
1320			ap = [ a ],
1321			bp = [ b ];
1322
1323		// Parentless nodes are either documents or disconnected
1324		if ( !aup || !bup ) {
1325			return a === doc ? -1 :
1326				b === doc ? 1 :
1327				aup ? -1 :
1328				bup ? 1 :
1329				sortInput ?
1330				( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
1331				0;
1332
1333		// If the nodes are siblings, we can do a quick check
1334		} else if ( aup === bup ) {
1335			return siblingCheck( a, b );
1336		}
1337
1338		// Otherwise we need full lists of their ancestors for comparison
1339		cur = a;
1340		while ( (cur = cur.parentNode) ) {
1341			ap.unshift( cur );
1342		}
1343		cur = b;
1344		while ( (cur = cur.parentNode) ) {
1345			bp.unshift( cur );
1346		}
1347
1348		// Walk down the tree looking for a discrepancy
1349		while ( ap[i] === bp[i] ) {
1350			i++;
1351		}
1352
1353		return i ?
1354			// Do a sibling check if the nodes have a common ancestor
1355			siblingCheck( ap[i], bp[i] ) :
1356
1357			// Otherwise nodes in our document sort first
1358			ap[i] === preferredDoc ? -1 :
1359			bp[i] === preferredDoc ? 1 :
1360			0;
1361	};
1362
1363	return doc;
1364};
1365
1366Sizzle.matches = function( expr, elements ) {
1367	return Sizzle( expr, null, null, elements );
1368};
1369
1370Sizzle.matchesSelector = function( elem, expr ) {
1371	// Set document vars if needed
1372	if ( ( elem.ownerDocument || elem ) !== document ) {
1373		setDocument( elem );
1374	}
1375
1376	// Make sure that attribute selectors are quoted
1377	expr = expr.replace( rattributeQuotes, "='$1']" );
1378
1379	if ( support.matchesSelector && documentIsHTML &&
1380		( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
1381		( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {
1382
1383		try {
1384			var ret = matches.call( elem, expr );
1385
1386			// IE 9's matchesSelector returns false on disconnected nodes
1387			if ( ret || support.disconnectedMatch ||
1388					// As well, disconnected nodes are said to be in a document
1389					// fragment in IE 9
1390					elem.document && elem.document.nodeType !== 11 ) {
1391				return ret;
1392			}
1393		} catch(e) {}
1394	}
1395
1396	return Sizzle( expr, document, null, [elem] ).length > 0;
1397};
1398
1399Sizzle.contains = function( context, elem ) {
1400	// Set document vars if needed
1401	if ( ( context.ownerDocument || context ) !== document ) {
1402		setDocument( context );
1403	}
1404	return contains( context, elem );
1405};
1406
1407Sizzle.attr = function( elem, name ) {
1408	// Set document vars if needed
1409	if ( ( elem.ownerDocument || elem ) !== document ) {
1410		setDocument( elem );
1411	}
1412
1413	var fn = Expr.attrHandle[ name.toLowerCase() ],
1414		// Don't get fooled by Object.prototype properties (jQuery #13807)
1415		val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
1416			fn( elem, name, !documentIsHTML ) :
1417			undefined;
1418
1419	return val !== undefined ?
1420		val :
1421		support.attributes || !documentIsHTML ?
1422			elem.getAttribute( name ) :
1423			(val = elem.getAttributeNode(name)) && val.specified ?
1424				val.value :
1425				null;
1426};
1427
1428Sizzle.error = function( msg ) {
1429	throw new Error( "Syntax error, unrecognized expression: " + msg );
1430};
1431
1432/**
1433 * Document sorting and removing duplicates
1434 * @param {ArrayLike} results
1435 */
1436Sizzle.uniqueSort = function( results ) {
1437	var elem,
1438		duplicates = [],
1439		j = 0,
1440		i = 0;
1441
1442	// Unless we *know* we can detect duplicates, assume their presence
1443	hasDuplicate = !support.detectDuplicates;
1444	sortInput = !support.sortStable && results.slice( 0 );
1445	results.sort( sortOrder );
1446
1447	if ( hasDuplicate ) {
1448		while ( (elem = results[i++]) ) {
1449			if ( elem === results[ i ] ) {
1450				j = duplicates.push( i );
1451			}
1452		}
1453		while ( j-- ) {
1454			results.splice( duplicates[ j ], 1 );
1455		}
1456	}
1457
1458	// Clear input after sorting to release objects
1459	// See https://github.com/jquery/sizzle/pull/225
1460	sortInput = null;
1461
1462	return results;
1463};
1464
1465/**
1466 * Utility function for retrieving the text value of an array of DOM nodes
1467 * @param {Array|Element} elem
1468 */
1469getText = Sizzle.getText = function( elem ) {
1470	var node,
1471		ret = "",
1472		i = 0,
1473		nodeType = elem.nodeType;
1474
1475	if ( !nodeType ) {
1476		// If no nodeType, this is expected to be an array
1477		while ( (node = elem[i++]) ) {
1478			// Do not traverse comment nodes
1479			ret += getText( node );
1480		}
1481	} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
1482		// Use textContent for elements
1483		// innerText usage removed for consistency of new lines (jQuery #11153)
1484		if ( typeof elem.textContent === "string" ) {
1485			return elem.textContent;
1486		} else {
1487			// Traverse its children
1488			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
1489				ret += getText( elem );
1490			}
1491		}
1492	} else if ( nodeType === 3 || nodeType === 4 ) {
1493		return elem.nodeValue;
1494	}
1495	// Do not include comment or processing instruction nodes
1496
1497	return ret;
1498};
1499
1500Expr = Sizzle.selectors = {
1501
1502	// Can be adjusted by the user
1503	cacheLength: 50,
1504
1505	createPseudo: markFunction,
1506
1507	match: matchExpr,
1508
1509	attrHandle: {},
1510
1511	find: {},
1512
1513	relative: {
1514		">": { dir: "parentNode", first: true },
1515		" ": { dir: "parentNode" },
1516		"+": { dir: "previousSibling", first: true },
1517		"~": { dir: "previousSibling" }
1518	},
1519
1520	preFilter: {
1521		"ATTR": function( match ) {
1522			match[1] = match[1].replace( runescape, funescape );
1523
1524			// Move the given value to match[3] whether quoted or unquoted
1525			match[3] = ( match[4] || match[5] || "" ).replace( runescape, funescape );
1526
1527			if ( match[2] === "~=" ) {
1528				match[3] = " " + match[3] + " ";
1529			}
1530
1531			return match.slice( 0, 4 );
1532		},
1533
1534		"CHILD": function( match ) {
1535			/* matches from matchExpr["CHILD"]
1536				1 type (only|nth|...)
1537				2 what (child|of-type)
1538				3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
1539				4 xn-component of xn+y argument ([+-]?\d*n|)
1540				5 sign of xn-component
1541				6 x of xn-component
1542				7 sign of y-component
1543				8 y of y-component
1544			*/
1545			match[1] = match[1].toLowerCase();
1546
1547			if ( match[1].slice( 0, 3 ) === "nth" ) {
1548				// nth-* requires argument
1549				if ( !match[3] ) {
1550					Sizzle.error( match[0] );
1551				}
1552
1553				// numeric x and y parameters for Expr.filter.CHILD
1554				// remember that false/true cast respectively to 0/1
1555				match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
1556				match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
1557
1558			// other types prohibit arguments
1559			} else if ( match[3] ) {
1560				Sizzle.error( match[0] );
1561			}
1562
1563			return match;
1564		},
1565
1566		"PSEUDO": function( match ) {
1567			var excess,
1568				unquoted = !match[5] && match[2];
1569
1570			if ( matchExpr["CHILD"].test( match[0] ) ) {
1571				return null;
1572			}
1573
1574			// Accept quoted arguments as-is
1575			if ( match[3] && match[4] !== undefined ) {
1576				match[2] = match[4];
1577
1578			// Strip excess characters from unquoted arguments
1579			} else if ( unquoted && rpseudo.test( unquoted ) &&
1580				// Get excess from tokenize (recursively)
1581				(excess = tokenize( unquoted, true )) &&
1582				// advance to the next closing parenthesis
1583				(excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
1584
1585				// excess is a negative index
1586				match[0] = match[0].slice( 0, excess );
1587				match[2] = unquoted.slice( 0, excess );
1588			}
1589
1590			// Return only captures needed by the pseudo filter method (type and argument)
1591			return match.slice( 0, 3 );
1592		}
1593	},
1594
1595	filter: {
1596
1597		"TAG": function( nodeNameSelector ) {
1598			var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
1599			return nodeNameSelector === "*" ?
1600				function() { return true; } :
1601				function( elem ) {
1602					return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
1603				};
1604		},
1605
1606		"CLASS": function( className ) {
1607			var pattern = classCache[ className + " " ];
1608
1609			return pattern ||
1610				(pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
1611				classCache( className, function( elem ) {
1612					return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" );
1613				});
1614		},
1615
1616		"ATTR": function( name, operator, check ) {
1617			return function( elem ) {
1618				var result = Sizzle.attr( elem, name );
1619
1620				if ( result == null ) {
1621					return operator === "!=";
1622				}
1623				if ( !operator ) {
1624					return true;
1625				}
1626
1627				result += "";
1628
1629				return operator === "=" ? result === check :
1630					operator === "!=" ? result !== check :
1631					operator === "^=" ? check && result.indexOf( check ) === 0 :
1632					operator === "*=" ? check && result.indexOf( check ) > -1 :
1633					operator === "$=" ? check && result.slice( -check.length ) === check :
1634					operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 :
1635					operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
1636					false;
1637			};
1638		},
1639
1640		"CHILD": function( type, what, argument, first, last ) {
1641			var simple = type.slice( 0, 3 ) !== "nth",
1642				forward = type.slice( -4 ) !== "last",
1643				ofType = what === "of-type";
1644
1645			return first === 1 && last === 0 ?
1646
1647				// Shortcut for :nth-*(n)
1648				function( elem ) {
1649					return !!elem.parentNode;
1650				} :
1651
1652				function( elem, context, xml ) {
1653					var cache, outerCache, node, diff, nodeIndex, start,
1654						dir = simple !== forward ? "nextSibling" : "previousSibling",
1655						parent = elem.parentNode,
1656						name = ofType && elem.nodeName.toLowerCase(),
1657						useCache = !xml && !ofType;
1658
1659					if ( parent ) {
1660
1661						// :(first|last|only)-(child|of-type)
1662						if ( simple ) {
1663							while ( dir ) {
1664								node = elem;
1665								while ( (node = node[ dir ]) ) {
1666									if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
1667										return false;
1668									}
1669								}
1670								// Reverse direction for :only-* (if we haven't yet done so)
1671								start = dir = type === "only" && !start && "nextSibling";
1672							}
1673							return true;
1674						}
1675
1676						start = [ forward ? parent.firstChild : parent.lastChild ];
1677
1678						// non-xml :nth-child(...) stores cache data on `parent`
1679						if ( forward && useCache ) {
1680							// Seek `elem` from a previously-cached index
1681							outerCache = parent[ expando ] || (parent[ expando ] = {});
1682							cache = outerCache[ type ] || [];
1683							nodeIndex = cache[0] === dirruns && cache[1];
1684							diff = cache[0] === dirruns && cache[2];
1685							node = nodeIndex && parent.childNodes[ nodeIndex ];
1686
1687							while ( (node = ++nodeIndex && node && node[ dir ] ||
1688
1689								// Fallback to seeking `elem` from the start
1690								(diff = nodeIndex = 0) || start.pop()) ) {
1691
1692								// When found, cache indexes on `parent` and break
1693								if ( node.nodeType === 1 && ++diff && node === elem ) {
1694									outerCache[ type ] = [ dirruns, nodeIndex, diff ];
1695									break;
1696								}
1697							}
1698
1699						// Use previously-cached element index if available
1700						} else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
1701							diff = cache[1];
1702
1703						// xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
1704						} else {
1705							// Use the same loop as above to seek `elem` from the start
1706							while ( (node = ++nodeIndex && node && node[ dir ] ||
1707								(diff = nodeIndex = 0) || start.pop()) ) {
1708
1709								if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
1710									// Cache the index of each encountered element
1711									if ( useCache ) {
1712										(node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
1713									}
1714
1715									if ( node === elem ) {
1716										break;
1717									}
1718								}
1719							}
1720						}
1721
1722						// Incorporate the offset, then check against cycle size
1723						diff -= last;
1724						return diff === first || ( diff % first === 0 && diff / first >= 0 );
1725					}
1726				};
1727		},
1728
1729		"PSEUDO": function( pseudo, argument ) {
1730			// pseudo-class names are case-insensitive
1731			// http://www.w3.org/TR/selectors/#pseudo-classes
1732			// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
1733			// Remember that setFilters inherits from pseudos
1734			var args,
1735				fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
1736					Sizzle.error( "unsupported pseudo: " + pseudo );
1737
1738			// The user may use createPseudo to indicate that
1739			// arguments are needed to create the filter function
1740			// just as Sizzle does
1741			if ( fn[ expando ] ) {
1742				return fn( argument );
1743			}
1744
1745			// But maintain support for old signatures
1746			if ( fn.length > 1 ) {
1747				args = [ pseudo, pseudo, "", argument ];
1748				return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
1749					markFunction(function( seed, matches ) {
1750						var idx,
1751							matched = fn( seed, argument ),
1752							i = matched.length;
1753						while ( i-- ) {
1754							idx = indexOf.call( seed, matched[i] );
1755							seed[ idx ] = !( matches[ idx ] = matched[i] );
1756						}
1757					}) :
1758					function( elem ) {
1759						return fn( elem, 0, args );
1760					};
1761			}
1762
1763			return fn;
1764		}
1765	},
1766
1767	pseudos: {
1768		// Potentially complex pseudos
1769		"not": markFunction(function( selector ) {
1770			// Trim the selector passed to compile
1771			// to avoid treating leading and trailing
1772			// spaces as combinators
1773			var input = [],
1774				results = [],
1775				matcher = compile( selector.replace( rtrim, "$1" ) );
1776
1777			return matcher[ expando ] ?
1778				markFunction(function( seed, matches, context, xml ) {
1779					var elem,
1780						unmatched = matcher( seed, null, xml, [] ),
1781						i = seed.length;
1782
1783					// Match elements unmatched by `matcher`
1784					while ( i-- ) {
1785						if ( (elem = unmatched[i]) ) {
1786							seed[i] = !(matches[i] = elem);
1787						}
1788					}
1789				}) :
1790				function( elem, context, xml ) {
1791					input[0] = elem;
1792					matcher( input, null, xml, results );
1793					return !results.pop();
1794				};
1795		}),
1796
1797		"has": markFunction(function( selector ) {
1798			return function( elem ) {
1799				return Sizzle( selector, elem ).length > 0;
1800			};
1801		}),
1802
1803		"contains": markFunction(function( text ) {
1804			return function( elem ) {
1805				return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
1806			};
1807		}),
1808
1809		// "Whether an element is represented by a :lang() selector
1810		// is based solely on the element's language value
1811		// being equal to the identifier C,
1812		// or beginning with the identifier C immediately followed by "-".
1813		// The matching of C against the element's language value is performed case-insensitively.
1814		// The identifier C does not have to be a valid language name."
1815		// http://www.w3.org/TR/selectors/#lang-pseudo
1816		"lang": markFunction( function( lang ) {
1817			// lang value must be a valid identifier
1818			if ( !ridentifier.test(lang || "") ) {
1819				Sizzle.error( "unsupported lang: " + lang );
1820			}
1821			lang = lang.replace( runescape, funescape ).toLowerCase();
1822			return function( elem ) {
1823				var elemLang;
1824				do {
1825					if ( (elemLang = documentIsHTML ?
1826						elem.lang :
1827						elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
1828
1829						elemLang = elemLang.toLowerCase();
1830						return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
1831					}
1832				} while ( (elem = elem.parentNode) && elem.nodeType === 1 );
1833				return false;
1834			};
1835		}),
1836
1837		// Miscellaneous
1838		"target": function( elem ) {
1839			var hash = window.location && window.location.hash;
1840			return hash && hash.slice( 1 ) === elem.id;
1841		},
1842
1843		"root": function( elem ) {
1844			return elem === docElem;
1845		},
1846
1847		"focus": function( elem ) {
1848			return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
1849		},
1850
1851		// Boolean properties
1852		"enabled": function( elem ) {
1853			return elem.disabled === false;
1854		},
1855
1856		"disabled": function( elem ) {
1857			return elem.disabled === true;
1858		},
1859
1860		"checked": function( elem ) {
1861			// In CSS3, :checked should return both checked and selected elements
1862			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
1863			var nodeName = elem.nodeName.toLowerCase();
1864			return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
1865		},
1866
1867		"selected": function( elem ) {
1868			// Accessing this property makes selected-by-default
1869			// options in Safari work properly
1870			if ( elem.parentNode ) {
1871				elem.parentNode.selectedIndex;
1872			}
1873
1874			return elem.selected === true;
1875		},
1876
1877		// Contents
1878		"empty": function( elem ) {
1879			// http://www.w3.org/TR/selectors/#empty-pseudo
1880			// :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
1881			//   but not by others (comment: 8; processing instruction: 7; etc.)
1882			// nodeType < 6 works because attributes (2) do not appear as children
1883			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
1884				if ( elem.nodeType < 6 ) {
1885					return false;
1886				}
1887			}
1888			return true;
1889		},
1890
1891		"parent": function( elem ) {
1892			return !Expr.pseudos["empty"]( elem );
1893		},
1894
1895		// Element/input types
1896		"header": function( elem ) {
1897			return rheader.test( elem.nodeName );
1898		},
1899
1900		"input": function( elem ) {
1901			return rinputs.test( elem.nodeName );
1902		},
1903
1904		"button": function( elem ) {
1905			var name = elem.nodeName.toLowerCase();
1906			return name === "input" && elem.type === "button" || name === "button";
1907		},
1908
1909		"text": function( elem ) {
1910			var attr;
1911			return elem.nodeName.toLowerCase() === "input" &&
1912				elem.type === "text" &&
1913
1914				// Support: IE<8
1915				// New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
1916				( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
1917		},
1918
1919		// Position-in-collection
1920		"first": createPositionalPseudo(function() {
1921			return [ 0 ];
1922		}),
1923
1924		"last": createPositionalPseudo(function( matchIndexes, length ) {
1925			return [ length - 1 ];
1926		}),
1927
1928		"eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
1929			return [ argument < 0 ? argument + length : argument ];
1930		}),
1931
1932		"even": createPositionalPseudo(function( matchIndexes, length ) {
1933			var i = 0;
1934			for ( ; i < length; i += 2 ) {
1935				matchIndexes.push( i );
1936			}
1937			return matchIndexes;
1938		}),
1939
1940		"odd": createPositionalPseudo(function( matchIndexes, length ) {
1941			var i = 1;
1942			for ( ; i < length; i += 2 ) {
1943				matchIndexes.push( i );
1944			}
1945			return matchIndexes;
1946		}),
1947
1948		"lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
1949			var i = argument < 0 ? argument + length : argument;
1950			for ( ; --i >= 0; ) {
1951				matchIndexes.push( i );
1952			}
1953			return matchIndexes;
1954		}),
1955
1956		"gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
1957			var i = argument < 0 ? argument + length : argument;
1958			for ( ; ++i < length; ) {
1959				matchIndexes.push( i );
1960			}
1961			return matchIndexes;
1962		})
1963	}
1964};
1965
1966Expr.pseudos["nth"] = Expr.pseudos["eq"];
1967
1968// Add button/input type pseudos
1969for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
1970	Expr.pseudos[ i ] = createInputPseudo( i );
1971}
1972for ( i in { submit: true, reset: true } ) {
1973	Expr.pseudos[ i ] = createButtonPseudo( i );
1974}
1975
1976// Easy API for creating new setFilters
1977function setFilters() {}
1978setFilters.prototype = Expr.filters = Expr.pseudos;
1979Expr.setFilters = new setFilters();
1980
1981function tokenize( selector, parseOnly ) {
1982	var matched, match, tokens, type,
1983		soFar, groups, preFilters,
1984		cached = tokenCache[ selector + " " ];
1985
1986	if ( cached ) {
1987		return parseOnly ? 0 : cached.slice( 0 );
1988	}
1989
1990	soFar = selector;
1991	groups = [];
1992	preFilters = Expr.preFilter;
1993
1994	while ( soFar ) {
1995
1996		// Comma and first run
1997		if ( !matched || (match = rcomma.exec( soFar )) ) {
1998			if ( match ) {
1999				// Don't consume trailing commas as valid
2000				soFar = soFar.slice( match[0].length ) || soFar;
2001			}
2002			groups.push( (tokens = []) );
2003		}
2004
2005		matched = false;
2006
2007		// Combinators
2008		if ( (match = rcombinators.exec( soFar )) ) {
2009			matched = match.shift();
2010			tokens.push({
2011				value: matched,
2012				// Cast descendant combinators to space
2013				type: match[0].replace( rtrim, " " )
2014			});
2015			soFar = soFar.slice( matched.length );
2016		}
2017
2018		// Filters
2019		for ( type in Expr.filter ) {
2020			if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
2021				(match = preFilters[ type ]( match ))) ) {
2022				matched = match.shift();
2023				tokens.push({
2024					value: matched,
2025					type: type,
2026					matches: match
2027				});
2028				soFar = soFar.slice( matched.length );
2029			}
2030		}
2031
2032		if ( !matched ) {
2033			break;
2034		}
2035	}
2036
2037	// Return the length of the invalid excess
2038	// if we're just parsing
2039	// Otherwise, throw an error or return tokens
2040	return parseOnly ?
2041		soFar.length :
2042		soFar ?
2043			Sizzle.error( selector ) :
2044			// Cache the tokens
2045			tokenCache( selector, groups ).slice( 0 );
2046}
2047
2048function toSelector( tokens ) {
2049	var i = 0,
2050		len = tokens.length,
2051		selector = "";
2052	for ( ; i < len; i++ ) {
2053		selector += tokens[i].value;
2054	}
2055	return selector;
2056}
2057
2058function addCombinator( matcher, combinator, base ) {
2059	var dir = combinator.dir,
2060		checkNonElements = base && dir === "parentNode",
2061		doneName = done++;
2062
2063	return combinator.first ?
2064		// Check against closest ancestor/preceding element
2065		function( elem, context, xml ) {
2066			while ( (elem = elem[ dir ]) ) {
2067				if ( elem.nodeType === 1 || checkNonElements ) {
2068					return matcher( elem, context, xml );
2069				}
2070			}
2071		} :
2072
2073		// Check against all ancestor/preceding elements
2074		function( elem, context, xml ) {
2075			var oldCache, outerCache,
2076				newCache = [ dirruns, doneName ];
2077
2078			// We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
2079			if ( xml ) {
2080				while ( (elem = elem[ dir ]) ) {
2081					if ( elem.nodeType === 1 || checkNonElements ) {
2082						if ( matcher( elem, context, xml ) ) {
2083							return true;
2084						}
2085					}
2086				}
2087			} else {
2088				while ( (elem = elem[ dir ]) ) {
2089					if ( elem.nodeType === 1 || checkNonElements ) {
2090						outerCache = elem[ expando ] || (elem[ expando ] = {});
2091						if ( (oldCache = outerCache[ dir ]) &&
2092							oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
2093
2094							// Assign to newCache so results back-propagate to previous elements
2095							return (newCache[ 2 ] = oldCache[ 2 ]);
2096						} else {
2097							// Reuse newcache so results back-propagate to previous elements
2098							outerCache[ dir ] = newCache;
2099
2100							// A match means we're done; a fail means we have to keep checking
2101							if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
2102								return true;
2103							}
2104						}
2105					}
2106				}
2107			}
2108		};
2109}
2110
2111function elementMatcher( matchers ) {
2112	return matchers.length > 1 ?
2113		function( elem, context, xml ) {
2114			var i = matchers.length;
2115			while ( i-- ) {
2116				if ( !matchers[i]( elem, context, xml ) ) {
2117					return false;
2118				}
2119			}
2120			return true;
2121		} :
2122		matchers[0];
2123}
2124
2125function condense( unmatched, map, filter, context, xml ) {
2126	var elem,
2127		newUnmatched = [],
2128		i = 0,
2129		len = unmatched.length,
2130		mapped = map != null;
2131
2132	for ( ; i < len; i++ ) {
2133		if ( (elem = unmatched[i]) ) {
2134			if ( !filter || filter( elem, context, xml ) ) {
2135				newUnmatched.push( elem );
2136				if ( mapped ) {
2137					map.push( i );
2138				}
2139			}
2140		}
2141	}
2142
2143	return newUnmatched;
2144}
2145
2146function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
2147	if ( postFilter && !postFilter[ expando ] ) {
2148		postFilter = setMatcher( postFilter );
2149	}
2150	if ( postFinder && !postFinder[ expando ] ) {
2151		postFinder = setMatcher( postFinder, postSelector );
2152	}
2153	return markFunction(function( seed, results, context, xml ) {
2154		var temp, i, elem,
2155			preMap = [],
2156			postMap = [],
2157			preexisting = results.length,
2158
2159			// Get initial elements from seed or context
2160			elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
2161
2162			// Prefilter to get matcher input, preserving a map for seed-results synchronization
2163			matcherIn = preFilter && ( seed || !selector ) ?
2164				condense( elems, preMap, preFilter, context, xml ) :
2165				elems,
2166
2167			matcherOut = matcher ?
2168				// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
2169				postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
2170
2171					// ...intermediate processing is necessary
2172					[] :
2173
2174					// ...otherwise use results directly
2175					results :
2176				matcherIn;
2177
2178		// Find primary matches
2179		if ( matcher ) {
2180			matcher( matcherIn, matcherOut, context, xml );
2181		}
2182
2183		// Apply postFilter
2184		if ( postFilter ) {
2185			temp = condense( matcherOut, postMap );
2186			postFilter( temp, [], context, xml );
2187
2188			// Un-match failing elements by moving them back to matcherIn
2189			i = temp.length;
2190			while ( i-- ) {
2191				if ( (elem = temp[i]) ) {
2192					matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
2193				}
2194			}
2195		}
2196
2197		if ( seed ) {
2198			if ( postFinder || preFilter ) {
2199				if ( postFinder ) {
2200					// Get the final matcherOut by condensing this intermediate into postFinder contexts
2201					temp = [];
2202					i = matcherOut.length;
2203					while ( i-- ) {
2204						if ( (elem = matcherOut[i]) ) {
2205							// Restore matcherIn since elem is not yet a final match
2206							temp.push( (matcherIn[i] = elem) );
2207						}
2208					}
2209					postFinder( null, (matcherOut = []), temp, xml );
2210				}
2211
2212				// Move matched elements from seed to results to keep them synchronized
2213				i = matcherOut.length;
2214				while ( i-- ) {
2215					if ( (elem = matcherOut[i]) &&
2216						(temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) {
2217
2218						seed[temp] = !(results[temp] = elem);
2219					}
2220				}
2221			}
2222
2223		// Add elements to results, through postFinder if defined
2224		} else {
2225			matcherOut = condense(
2226				matcherOut === results ?
2227					matcherOut.splice( preexisting, matcherOut.length ) :
2228					matcherOut
2229			);
2230			if ( postFinder ) {
2231				postFinder( null, results, matcherOut, xml );
2232			} else {
2233				push.apply( results, matcherOut );
2234			}
2235		}
2236	});
2237}
2238
2239function matcherFromTokens( tokens ) {
2240	var checkContext, matcher, j,
2241		len = tokens.length,
2242		leadingRelative = Expr.relative[ tokens[0].type ],
2243		implicitRelative = leadingRelative || Expr.relative[" "],
2244		i = leadingRelative ? 1 : 0,
2245
2246		// The foundational matcher ensures that elements are reachable from top-level context(s)
2247		matchContext = addCombinator( function( elem ) {
2248			return elem === checkContext;
2249		}, implicitRelative, true ),
2250		matchAnyContext = addCombinator( function( elem ) {
2251			return indexOf.call( checkContext, elem ) > -1;
2252		}, implicitRelative, true ),
2253		matchers = [ function( elem, context, xml ) {
2254			return ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
2255				(checkContext = context).nodeType ?
2256					matchContext( elem, context, xml ) :
2257					matchAnyContext( elem, context, xml ) );
2258		} ];
2259
2260	for ( ; i < len; i++ ) {
2261		if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
2262			matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
2263		} else {
2264			matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
2265
2266			// Return special upon seeing a positional matcher
2267			if ( matcher[ expando ] ) {
2268				// Find the next relative operator (if any) for proper handling
2269				j = ++i;
2270				for ( ; j < len; j++ ) {
2271					if ( Expr.relative[ tokens[j].type ] ) {
2272						break;
2273					}
2274				}
2275				return setMatcher(
2276					i > 1 && elementMatcher( matchers ),
2277					i > 1 && toSelector(
2278						// If the preceding token was a descendant combinator, insert an implicit any-element `*`
2279						tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
2280					).replace( rtrim, "$1" ),
2281					matcher,
2282					i < j && matcherFromTokens( tokens.slice( i, j ) ),
2283					j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
2284					j < len && toSelector( tokens )
2285				);
2286			}
2287			matchers.push( matcher );
2288		}
2289	}
2290
2291	return elementMatcher( matchers );
2292}
2293
2294function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
2295	var bySet = setMatchers.length > 0,
2296		byElement = elementMatchers.length > 0,
2297		superMatcher = function( seed, context, xml, results, outermost ) {
2298			var elem, j, matcher,
2299				matchedCount = 0,
2300				i = "0",
2301				unmatched = seed && [],
2302				setMatched = [],
2303				contextBackup = outermostContext,
2304				// We must always have either seed elements or outermost context
2305				elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
2306				// Use integer dirruns iff this is the outermost matcher
2307				dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
2308				len = elems.length;
2309
2310			if ( outermost ) {
2311				outermostContext = context !== document && context;
2312			}
2313
2314			// Add elements passing elementMatchers directly to results
2315			// Keep `i` a string if there are no elements so `matchedCount` will be "00" below
2316			// Support: IE<9, Safari
2317			// Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
2318			for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
2319				if ( byElement && elem ) {
2320					j = 0;
2321					while ( (matcher = elementMatchers[j++]) ) {
2322						if ( matcher( elem, context, xml ) ) {
2323							results.push( elem );
2324							break;
2325						}
2326					}
2327					if ( outermost ) {
2328						dirruns = dirrunsUnique;
2329					}
2330				}
2331
2332				// Track unmatched elements for set filters
2333				if ( bySet ) {
2334					// They will have gone through all possible matchers
2335					if ( (elem = !matcher && elem) ) {
2336						matchedCount--;
2337					}
2338
2339					// Lengthen the array for every element, matched or not
2340					if ( seed ) {
2341						unmatched.push( elem );
2342					}
2343				}
2344			}
2345
2346			// Apply set filters to unmatched elements
2347			matchedCount += i;
2348			if ( bySet && i !== matchedCount ) {
2349				j = 0;
2350				while ( (matcher = setMatchers[j++]) ) {
2351					matcher( unmatched, setMatched, context, xml );
2352				}
2353
2354				if ( seed ) {
2355					// Reintegrate element matches to eliminate the need for sorting
2356					if ( matchedCount > 0 ) {
2357						while ( i-- ) {
2358							if ( !(unmatched[i] || setMatched[i]) ) {
2359								setMatched[i] = pop.call( results );
2360							}
2361						}
2362					}
2363
2364					// Discard index placeholder values to get only actual matches
2365					setMatched = condense( setMatched );
2366				}
2367
2368				// Add matches to results
2369				push.apply( results, setMatched );
2370
2371				// Seedless set matches succeeding multiple successful matchers stipulate sorting
2372				if ( outermost && !seed && setMatched.length > 0 &&
2373					( matchedCount + setMatchers.length ) > 1 ) {
2374
2375					Sizzle.uniqueSort( results );
2376				}
2377			}
2378
2379			// Override manipulation of globals by nested matchers
2380			if ( outermost ) {
2381				dirruns = dirrunsUnique;
2382				outermostContext = contextBackup;
2383			}
2384
2385			return unmatched;
2386		};
2387
2388	return bySet ?
2389		markFunction( superMatcher ) :
2390		superMatcher;
2391}
2392
2393compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) {
2394	var i,
2395		setMatchers = [],
2396		elementMatchers = [],
2397		cached = compilerCache[ selector + " " ];
2398
2399	if ( !cached ) {
2400		// Generate a function of recursive functions that can be used to check each element
2401		if ( !group ) {
2402			group = tokenize( selector );
2403		}
2404		i = group.length;
2405		while ( i-- ) {
2406			cached = matcherFromTokens( group[i] );
2407			if ( cached[ expando ] ) {
2408				setMatchers.push( cached );
2409			} else {
2410				elementMatchers.push( cached );
2411			}
2412		}
2413
2414		// Cache the compiled function
2415		cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
2416	}
2417	return cached;
2418};
2419
2420function multipleContexts( selector, contexts, results ) {
2421	var i = 0,
2422		len = contexts.length;
2423	for ( ; i < len; i++ ) {
2424		Sizzle( selector, contexts[i], results );
2425	}
2426	return results;
2427}
2428
2429function select( selector, context, results, seed ) {
2430	var i, tokens, token, type, find,
2431		match = tokenize( selector );
2432
2433	if ( !seed ) {
2434		// Try to minimize operations if there is only one group
2435		if ( match.length === 1 ) {
2436
2437			// Take a shortcut and set the context if the root selector is an ID
2438			tokens = match[0] = match[0].slice( 0 );
2439			if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
2440					support.getById && context.nodeType === 9 && documentIsHTML &&
2441					Expr.relative[ tokens[1].type ] ) {
2442
2443				context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
2444				if ( !context ) {
2445					return results;
2446				}
2447				selector = selector.slice( tokens.shift().value.length );
2448			}
2449
2450			// Fetch a seed set for right-to-left matching
2451			i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
2452			while ( i-- ) {
2453				token = tokens[i];
2454
2455				// Abort if we hit a combinator
2456				if ( Expr.relative[ (type = token.type) ] ) {
2457					break;
2458				}
2459				if ( (find = Expr.find[ type ]) ) {
2460					// Search, expanding context for leading sibling combinators
2461					if ( (seed = find(
2462						token.matches[0].replace( runescape, funescape ),
vendor: 15,344 bytes, lines 2463-3035
2463						rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
2464					)) ) {
2465
2466						// If seed is empty or no tokens remain, we can return early
2467						tokens.splice( i, 1 );
2468						selector = seed.length && toSelector( tokens );
2469						if ( !selector ) {
2470							push.apply( results, seed );
2471							return results;
2472						}
2473
2474						break;
2475					}
2476				}
2477			}
2478		}
2479	}
2480
2481	// Compile and execute a filtering function
2482	// Provide `match` to avoid retokenization if we modified the selector above
2483	compile( selector, match )(
2484		seed,
2485		context,
2486		!documentIsHTML,
2487		results,
2488		rsibling.test( selector ) && testContext( context.parentNode ) || context
2489	);
2490	return results;
2491}
2492
2493// One-time assignments
2494
2495// Sort stability
2496support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
2497
2498// Support: Chrome<14
2499// Always assume duplicates if they aren't passed to the comparison function
2500support.detectDuplicates = !!hasDuplicate;
2501
2502// Initialize against the default document
2503setDocument();
2504
2505// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
2506// Detached nodes confoundingly follow *each other*
2507support.sortDetached = assert(function( div1 ) {
2508	// Should return 1, but returns 4 (following)
2509	return div1.compareDocumentPosition( document.createElement("div") ) & 1;
2510});
2511
2512// Support: IE<8
2513// Prevent attribute/property "interpolation"
2514// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
2515if ( !assert(function( div ) {
2516	div.innerHTML = "<a href='#'></a>";
2517	return div.firstChild.getAttribute("href") === "#" ;
2518}) ) {
2519	addHandle( "type|href|height|width", function( elem, name, isXML ) {
2520		if ( !isXML ) {
2521			return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
2522		}
2523	});
2524}
2525
2526// Support: IE<9
2527// Use defaultValue in place of getAttribute("value")
2528if ( !support.attributes || !assert(function( div ) {
2529	div.innerHTML = "<input/>";
2530	div.firstChild.setAttribute( "value", "" );
2531	return div.firstChild.getAttribute( "value" ) === "";
2532}) ) {
2533	addHandle( "value", function( elem, name, isXML ) {
2534		if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
2535			return elem.defaultValue;
2536		}
2537	});
2538}
2539
2540// Support: IE<9
2541// Use getAttributeNode to fetch booleans when getAttribute lies
2542if ( !assert(function( div ) {
2543	return div.getAttribute("disabled") == null;
2544}) ) {
2545	addHandle( booleans, function( elem, name, isXML ) {
2546		var val;
2547		if ( !isXML ) {
2548			return elem[ name ] === true ? name.toLowerCase() :
2549					(val = elem.getAttributeNode( name )) && val.specified ?
2550					val.value :
2551				null;
2552		}
2553	});
2554}
2555
2556return Sizzle;
2557
2558})( window );
2559
2560
2561
2562jQuery.find = Sizzle;
2563jQuery.expr = Sizzle.selectors;
2564jQuery.expr[":"] = jQuery.expr.pseudos;
2565jQuery.unique = Sizzle.uniqueSort;
2566jQuery.text = Sizzle.getText;
2567jQuery.isXMLDoc = Sizzle.isXML;
2568jQuery.contains = Sizzle.contains;
2569
2570
2571
2572var rneedsContext = jQuery.expr.match.needsContext;
2573
2574var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/);
2575
2576
2577
2578var risSimple = /^.[^:#\[\.,]*$/;
2579
2580// Implement the identical functionality for filter and not
2581function winnow( elements, qualifier, not ) {
2582	if ( jQuery.isFunction( qualifier ) ) {
2583		return jQuery.grep( elements, function( elem, i ) {
2584			/* jshint -W018 */
2585			return !!qualifier.call( elem, i, elem ) !== not;
2586		});
2587
2588	}
2589
2590	if ( qualifier.nodeType ) {
2591		return jQuery.grep( elements, function( elem ) {
2592			return ( elem === qualifier ) !== not;
2593		});
2594
2595	}
2596
2597	if ( typeof qualifier === "string" ) {
2598		if ( risSimple.test( qualifier ) ) {
2599			return jQuery.filter( qualifier, elements, not );
2600		}
2601
2602		qualifier = jQuery.filter( qualifier, elements );
2603	}
2604
2605	return jQuery.grep( elements, function( elem ) {
2606		return ( indexOf.call( qualifier, elem ) >= 0 ) !== not;
2607	});
2608}
2609
2610jQuery.filter = function( expr, elems, not ) {
2611	var elem = elems[ 0 ];
2612
2613	if ( not ) {
2614		expr = ":not(" + expr + ")";
2615	}
2616
2617	return elems.length === 1 && elem.nodeType === 1 ?
2618		jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :
2619		jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
2620			return elem.nodeType === 1;
2621		}));
2622};
2623
2624jQuery.fn.extend({
2625	find: function( selector ) {
2626		var i,
2627			len = this.length,
2628			ret = [],
2629			self = this;
2630
2631		if ( typeof selector !== "string" ) {
2632			return this.pushStack( jQuery( selector ).filter(function() {
2633				for ( i = 0; i < len; i++ ) {
2634					if ( jQuery.contains( self[ i ], this ) ) {
2635						return true;
2636					}
2637				}
2638			}) );
2639		}
2640
2641		for ( i = 0; i < len; i++ ) {
2642			jQuery.find( selector, self[ i ], ret );
2643		}
2644
2645		// Needed because $( selector, context ) becomes $( context ).find( selector )
2646		ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
2647		ret.selector = this.selector ? this.selector + " " + selector : selector;
2648		return ret;
2649	},
2650	filter: function( selector ) {
2651		return this.pushStack( winnow(this, selector || [], false) );
2652	},
2653	not: function( selector ) {
2654		return this.pushStack( winnow(this, selector || [], true) );
2655	},
2656	is: function( selector ) {
2657		return !!winnow(
2658			this,
2659
2660			// If this is a positional/relative selector, check membership in the returned set
2661			// so $("p:first").is("p:last") won't return true for a doc with two "p".
2662			typeof selector === "string" && rneedsContext.test( selector ) ?
2663				jQuery( selector ) :
2664				selector || [],
2665			false
2666		).length;
2667	}
2668});
2669
2670
2671// Initialize a jQuery object
2672
2673
2674// A central reference to the root jQuery(document)
2675var rootjQuery,
2676
2677	// A simple way to check for HTML strings
2678	// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
2679	// Strict HTML recognition (#11290: must start with <)
2680	rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
2681
2682	init = jQuery.fn.init = function( selector, context ) {
2683		var match, elem;
2684
2685		// HANDLE: $(""), $(null), $(undefined), $(false)
2686		if ( !selector ) {
2687			return this;
2688		}
2689
2690		// Handle HTML strings
2691		if ( typeof selector === "string" ) {
2692			if ( selector[0] === "<" && selector[ selector.length - 1 ] === ">" && selector.length >= 3 ) {
2693				// Assume that strings that start and end with <> are HTML and skip the regex check
2694				match = [ null, selector, null ];
2695
2696			} else {
2697				match = rquickExpr.exec( selector );
2698			}
2699
2700			// Match html or make sure no context is specified for #id
2701			if ( match && (match[1] || !context) ) {
2702
2703				// HANDLE: $(html) -> $(array)
2704				if ( match[1] ) {
2705					context = context instanceof jQuery ? context[0] : context;
2706
2707					// scripts is true for back-compat
2708					// Intentionally let the error be thrown if parseHTML is not present
2709					jQuery.merge( this, jQuery.parseHTML(
2710						match[1],
2711						context && context.nodeType ? context.ownerDocument || context : document,
2712						true
2713					) );
2714
2715					// HANDLE: $(html, props)
2716					if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
2717						for ( match in context ) {
2718							// Properties of context are called as methods if possible
2719							if ( jQuery.isFunction( this[ match ] ) ) {
2720								this[ match ]( context[ match ] );
2721
2722							// ...and otherwise set as attributes
2723							} else {
2724								this.attr( match, context[ match ] );
2725							}
2726						}
2727					}
2728
2729					return this;
2730
2731				// HANDLE: $(#id)
2732				} else {
2733					elem = document.getElementById( match[2] );
2734
2735					// Check parentNode to catch when Blackberry 4.6 returns
2736					// nodes that are no longer in the document #6963
2737					if ( elem && elem.parentNode ) {
2738						// Inject the element directly into the jQuery object
2739						this.length = 1;
2740						this[0] = elem;
2741					}
2742
2743					this.context = document;
2744					this.selector = selector;
2745					return this;
2746				}
2747
2748			// HANDLE: $(expr, $(...))
2749			} else if ( !context || context.jquery ) {
2750				return ( context || rootjQuery ).find( selector );
2751
2752			// HANDLE: $(expr, context)
2753			// (which is just equivalent to: $(context).find(expr)
2754			} else {
2755				return this.constructor( context ).find( selector );
2756			}
2757
2758		// HANDLE: $(DOMElement)
2759		} else if ( selector.nodeType ) {
2760			this.context = this[0] = selector;
2761			this.length = 1;
2762			return this;
2763
2764		// HANDLE: $(function)
2765		// Shortcut for document ready
2766		} else if ( jQuery.isFunction( selector ) ) {
2767			return typeof rootjQuery.ready !== "undefined" ?
2768				rootjQuery.ready( selector ) :
2769				// Execute immediately if ready is not present
2770				selector( jQuery );
2771		}
2772
2773		if ( selector.selector !== undefined ) {
2774			this.selector = selector.selector;
2775			this.context = selector.context;
2776		}
2777
2778		return jQuery.makeArray( selector, this );
2779	};
2780
2781// Give the init function the jQuery prototype for later instantiation
2782init.prototype = jQuery.fn;
2783
2784// Initialize central reference
2785rootjQuery = jQuery( document );
2786
2787
2788var rparentsprev = /^(?:parents|prev(?:Until|All))/,
2789	// methods guaranteed to produce a unique set when starting from a unique set
2790	guaranteedUnique = {
2791		children: true,
2792		contents: true,
2793		next: true,
2794		prev: true
2795	};
2796
2797jQuery.extend({
2798	dir: function( elem, dir, until ) {
2799		var matched = [],
2800			truncate = until !== undefined;
2801
2802		while ( (elem = elem[ dir ]) && elem.nodeType !== 9 ) {
2803			if ( elem.nodeType === 1 ) {
2804				if ( truncate && jQuery( elem ).is( until ) ) {
2805					break;
2806				}
2807				matched.push( elem );
2808			}
2809		}
2810		return matched;
2811	},
2812
2813	sibling: function( n, elem ) {
2814		var matched = [];
2815
2816		for ( ; n; n = n.nextSibling ) {
2817			if ( n.nodeType === 1 && n !== elem ) {
2818				matched.push( n );
2819			}
2820		}
2821
2822		return matched;
2823	}
2824});
2825
2826jQuery.fn.extend({
2827	has: function( target ) {
2828		var targets = jQuery( target, this ),
2829			l = targets.length;
2830
2831		return this.filter(function() {
2832			var i = 0;
2833			for ( ; i < l; i++ ) {
2834				if ( jQuery.contains( this, targets[i] ) ) {
2835					return true;
2836				}
2837			}
2838		});
2839	},
2840
2841	closest: function( selectors, context ) {
2842		var cur,
2843			i = 0,
2844			l = this.length,
2845			matched = [],
2846			pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
2847				jQuery( selectors, context || this.context ) :
2848				0;
2849
2850		for ( ; i < l; i++ ) {
2851			for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {
2852				// Always skip document fragments
2853				if ( cur.nodeType < 11 && (pos ?
2854					pos.index(cur) > -1 :
2855
2856					// Don't pass non-elements to Sizzle
2857					cur.nodeType === 1 &&
2858						jQuery.find.matchesSelector(cur, selectors)) ) {
2859
2860					matched.push( cur );
2861					break;
2862				}
2863			}
2864		}
2865
2866		return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched );
2867	},
2868
2869	// Determine the position of an element within
2870	// the matched set of elements
2871	index: function( elem ) {
2872
2873		// No argument, return index in parent
2874		if ( !elem ) {
2875			return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
2876		}
2877
2878		// index in selector
2879		if ( typeof elem === "string" ) {
2880			return indexOf.call( jQuery( elem ), this[ 0 ] );
2881		}
2882
2883		// Locate the position of the desired element
2884		return indexOf.call( this,
2885
2886			// If it receives a jQuery object, the first element is used
2887			elem.jquery ? elem[ 0 ] : elem
2888		);
2889	},
2890
2891	add: function( selector, context ) {
2892		return this.pushStack(
2893			jQuery.unique(
2894				jQuery.merge( this.get(), jQuery( selector, context ) )
2895			)
2896		);
2897	},
2898
2899	addBack: function( selector ) {
2900		return this.add( selector == null ?
2901			this.prevObject : this.prevObject.filter(selector)
2902		);
2903	}
2904});
2905
2906function sibling( cur, dir ) {
2907	while ( (cur = cur[dir]) && cur.nodeType !== 1 ) {}
2908	return cur;
2909}
2910
2911jQuery.each({
2912	parent: function( elem ) {
2913		var parent = elem.parentNode;
2914		return parent && parent.nodeType !== 11 ? parent : null;
2915	},
2916	parents: function( elem ) {
2917		return jQuery.dir( elem, "parentNode" );
2918	},
2919	parentsUntil: function( elem, i, until ) {
2920		return jQuery.dir( elem, "parentNode", until );
2921	},
2922	next: function( elem ) {
2923		return sibling( elem, "nextSibling" );
2924	},
2925	prev: function( elem ) {
2926		return sibling( elem, "previousSibling" );
2927	},
2928	nextAll: function( elem ) {
2929		return jQuery.dir( elem, "nextSibling" );
2930	},
2931	prevAll: function( elem ) {
2932		return jQuery.dir( elem, "previousSibling" );
2933	},
2934	nextUntil: function( elem, i, until ) {
2935		return jQuery.dir( elem, "nextSibling", until );
2936	},
2937	prevUntil: function( elem, i, until ) {
2938		return jQuery.dir( elem, "previousSibling", until );
2939	},
2940	siblings: function( elem ) {
2941		return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
2942	},
2943	children: function( elem ) {
2944		return jQuery.sibling( elem.firstChild );
2945	},
2946	contents: function( elem ) {
2947		return elem.contentDocument || jQuery.merge( [], elem.childNodes );
2948	}
2949}, function( name, fn ) {
2950	jQuery.fn[ name ] = function( until, selector ) {
2951		var matched = jQuery.map( this, fn, until );
2952
2953		if ( name.slice( -5 ) !== "Until" ) {
2954			selector = until;
2955		}
2956
2957		if ( selector && typeof selector === "string" ) {
2958			matched = jQuery.filter( selector, matched );
2959		}
2960
2961		if ( this.length > 1 ) {
2962			// Remove duplicates
2963			if ( !guaranteedUnique[ name ] ) {
2964				jQuery.unique( matched );
2965			}
2966
2967			// Reverse order for parents* and prev-derivatives
2968			if ( rparentsprev.test( name ) ) {
2969				matched.reverse();
2970			}
2971		}
2972
2973		return this.pushStack( matched );
2974	};
2975});
2976var rnotwhite = (/\S+/g);
2977
2978
2979
2980// String to Object options format cache
2981var optionsCache = {};
2982
2983// Convert String-formatted options into Object-formatted ones and store in cache
2984function createOptions( options ) {
2985	var object = optionsCache[ options ] = {};
2986	jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) {
2987		object[ flag ] = true;
2988	});
2989	return object;
2990}
2991
2992/*
2993 * Create a callback list using the following parameters:
2994 *
2995 *	options: an optional list of space-separated options that will change how
2996 *			the callback list behaves or a more traditional option object
2997 *
2998 * By default a callback list will act like an event callback list and can be
2999 * "fired" multiple times.
3000 *
3001 * Possible options:
3002 *
3003 *	once:			will ensure the callback list can only be fired once (like a Deferred)
3004 *
3005 *	memory:			will keep track of previous values and will call any callback added
3006 *					after the list has been fired right away with the latest "memorized"
3007 *					values (like a Deferred)
3008 *
3009 *	unique:			will ensure a callback can only be added once (no duplicate in the list)
3010 *
3011 *	stopOnFalse:	interrupt callings when a callback returns false
3012 *
3013 */
3014jQuery.Callbacks = function( options ) {
3015
3016	// Convert options from String-formatted to Object-formatted if needed
3017	// (we check in cache first)
3018	options = typeof options === "string" ?
3019		( optionsCache[ options ] || createOptions( options ) ) :
3020		jQuery.extend( {}, options );
3021
3022	var // Last fire value (for non-forgettable lists)
3023		memory,
3024		// Flag to know if list was already fired
3025		fired,
3026		// Flag to know if list is currently firing
3027		firing,
3028		// First callback to fire (used internally by add and fireWith)
3029		firingStart,
3030		// End of the loop when firing
3031		firingLength,
3032		// Index of currently firing callback (modified by remove if needed)
3033		firingIndex,
3034		// Actual callback list
3035		list = [],
vendor: 5,061 bytes, lines 3036-3213
3036		// Stack of fire calls for repeatable lists
3037		stack = !options.once && [],
3038		// Fire callbacks
3039		fire = function( data ) {
3040			memory = options.memory && data;
3041			fired = true;
3042			firingIndex = firingStart || 0;
3043			firingStart = 0;
3044			firingLength = list.length;
3045			firing = true;
3046			for ( ; list && firingIndex < firingLength; firingIndex++ ) {
3047				if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
3048					memory = false; // To prevent further calls using add
3049					break;
3050				}
3051			}
3052			firing = false;
3053			if ( list ) {
3054				if ( stack ) {
3055					if ( stack.length ) {
3056						fire( stack.shift() );
3057					}
3058				} else if ( memory ) {
3059					list = [];
3060				} else {
3061					self.disable();
3062				}
3063			}
3064		},
3065		// Actual Callbacks object
3066		self = {
3067			// Add a callback or a collection of callbacks to the list
3068			add: function() {
3069				if ( list ) {
3070					// First, we save the current length
3071					var start = list.length;
3072					(function add( args ) {
3073						jQuery.each( args, function( _, arg ) {
3074							var type = jQuery.type( arg );
3075							if ( type === "function" ) {
3076								if ( !options.unique || !self.has( arg ) ) {
3077									list.push( arg );
3078								}
3079							} else if ( arg && arg.length && type !== "string" ) {
3080								// Inspect recursively
3081								add( arg );
3082							}
3083						});
3084					})( arguments );
3085					// Do we need to add the callbacks to the
3086					// current firing batch?
3087					if ( firing ) {
3088						firingLength = list.length;
3089					// With memory, if we're not firing then
3090					// we should call right away
3091					} else if ( memory ) {
3092						firingStart = start;
3093						fire( memory );
3094					}
3095				}
3096				return this;
3097			},
3098			// Remove a callback from the list
3099			remove: function() {
3100				if ( list ) {
3101					jQuery.each( arguments, function( _, arg ) {
3102						var index;
3103						while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
3104							list.splice( index, 1 );
3105							// Handle firing indexes
3106							if ( firing ) {
3107								if ( index <= firingLength ) {
3108									firingLength--;
3109								}
3110								if ( index <= firingIndex ) {
3111									firingIndex--;
3112								}
3113							}
3114						}
3115					});
3116				}
3117				return this;
3118			},
3119			// Check if a given callback is in the list.
3120			// If no argument is given, return whether or not list has callbacks attached.
3121			has: function( fn ) {
3122				return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
3123			},
3124			// Remove all callbacks from the list
3125			empty: function() {
3126				list = [];
3127				firingLength = 0;
3128				return this;
3129			},
3130			// Have the list do nothing anymore
3131			disable: function() {
3132				list = stack = memory = undefined;
3133				return this;
3134			},
3135			// Is it disabled?
3136			disabled: function() {
3137				return !list;
3138			},
3139			// Lock the list in its current state
3140			lock: function() {
3141				stack = undefined;
3142				if ( !memory ) {
3143					self.disable();
3144				}
3145				return this;
3146			},
3147			// Is it locked?
3148			locked: function() {
3149				return !stack;
3150			},
3151			// Call all callbacks with the given context and arguments
3152			fireWith: function( context, args ) {
3153				if ( list && ( !fired || stack ) ) {
3154					args = args || [];
3155					args = [ context, args.slice ? args.slice() : args ];
3156					if ( firing ) {
3157						stack.push( args );
3158					} else {
3159						fire( args );
3160					}
3161				}
3162				return this;
3163			},
3164			// Call all the callbacks with the given arguments
3165			fire: function() {
3166				self.fireWith( this, arguments );
3167				return this;
3168			},
3169			// To know if the callbacks have already been called at least once
3170			fired: function() {
3171				return !!fired;
3172			}
3173		};
3174
3175	return self;
3176};
3177
3178
3179jQuery.extend({
3180
3181	Deferred: function( func ) {
3182		var tuples = [
3183				// action, add listener, listener list, final state
3184				[ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
3185				[ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
3186				[ "notify", "progress", jQuery.Callbacks("memory") ]
3187			],
3188			state = "pending",
3189			promise = {
3190				state: function() {
3191					return state;
3192				},
3193				always: function() {
3194					deferred.done( arguments ).fail( arguments );
3195					return this;
3196				},
3197				then: function( /* fnDone, fnFail, fnProgress */ ) {
3198					var fns = arguments;
3199					return jQuery.Deferred(function( newDefer ) {
3200						jQuery.each( tuples, function( i, tuple ) {
3201							var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
3202							// deferred[ done | fail | progress ] for forwarding actions to newDefer
3203							deferred[ tuple[1] ](function() {
3204								var returned = fn && fn.apply( this, arguments );
3205								if ( returned && jQuery.isFunction( returned.promise ) ) {
3206									returned.promise()
3207										.done( newDefer.resolve )
3208										.fail( newDefer.reject )
3209										.progress( newDefer.notify );
3210								} else {
3211									newDefer[ tuple[ 0 ] + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
3212								}
3213							});
vendor: 4,082 bytes, lines 3214-3363
3214						});
3215						fns = null;
3216					}).promise();
3217				},
3218				// Get a promise for this deferred
3219				// If obj is provided, the promise aspect is added to the object
3220				promise: function( obj ) {
3221					return obj != null ? jQuery.extend( obj, promise ) : promise;
3222				}
3223			},
3224			deferred = {};
3225
3226		// Keep pipe for back-compat
3227		promise.pipe = promise.then;
3228
3229		// Add list-specific methods
3230		jQuery.each( tuples, function( i, tuple ) {
3231			var list = tuple[ 2 ],
3232				stateString = tuple[ 3 ];
3233
3234			// promise[ done | fail | progress ] = list.add
3235			promise[ tuple[1] ] = list.add;
3236
3237			// Handle state
3238			if ( stateString ) {
3239				list.add(function() {
3240					// state = [ resolved | rejected ]
3241					state = stateString;
3242
3243				// [ reject_list | resolve_list ].disable; progress_list.lock
3244				}, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
3245			}
3246
3247			// deferred[ resolve | reject | notify ]
3248			deferred[ tuple[0] ] = function() {
3249				deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
3250				return this;
3251			};
3252			deferred[ tuple[0] + "With" ] = list.fireWith;
3253		});
3254
3255		// Make the deferred a promise
3256		promise.promise( deferred );
3257
3258		// Call given func if any
3259		if ( func ) {
3260			func.call( deferred, deferred );
3261		}
3262
3263		// All done!
3264		return deferred;
3265	},
3266
3267	// Deferred helper
3268	when: function( subordinate /* , ..., subordinateN */ ) {
3269		var i = 0,
3270			resolveValues = slice.call( arguments ),
3271			length = resolveValues.length,
3272
3273			// the count of uncompleted subordinates
3274			remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
3275
3276			// the master Deferred. If resolveValues consist of only a single Deferred, just use that.
3277			deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
3278
3279			// Update function for both resolve and progress values
3280			updateFunc = function( i, contexts, values ) {
3281				return function( value ) {
3282					contexts[ i ] = this;
3283					values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
3284					if ( values === progressValues ) {
3285						deferred.notifyWith( contexts, values );
3286					} else if ( !( --remaining ) ) {
3287						deferred.resolveWith( contexts, values );
3288					}
3289				};
3290			},
3291
3292			progressValues, progressContexts, resolveContexts;
3293
3294		// add listeners to Deferred subordinates; treat others as resolved
3295		if ( length > 1 ) {
3296			progressValues = new Array( length );
3297			progressContexts = new Array( length );
3298			resolveContexts = new Array( length );
3299			for ( ; i < length; i++ ) {
3300				if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
3301					resolveValues[ i ].promise()
3302						.done( updateFunc( i, resolveContexts, resolveValues ) )
3303						.fail( deferred.reject )
3304						.progress( updateFunc( i, progressContexts, progressValues ) );
3305				} else {
3306					--remaining;
3307				}
3308			}
3309		}
3310
3311		// if we're not waiting on anything, resolve the master
3312		if ( !remaining ) {
3313			deferred.resolveWith( resolveContexts, resolveValues );
3314		}
3315
3316		return deferred.promise();
3317	}
3318});
3319
3320
3321// The deferred used on DOM ready
3322var readyList;
3323
3324jQuery.fn.ready = function( fn ) {
3325	// Add the callback
3326	jQuery.ready.promise().done( fn );
3327
3328	return this;
3329};
3330
3331jQuery.extend({
3332	// Is the DOM ready to be used? Set to true once it occurs.
3333	isReady: false,
3334
3335	// A counter to track how many items to wait for before
3336	// the ready event fires. See #6781
3337	readyWait: 1,
3338
3339	// Hold (or release) the ready event
3340	holdReady: function( hold ) {
3341		if ( hold ) {
3342			jQuery.readyWait++;
3343		} else {
3344			jQuery.ready( true );
3345		}
3346	},
3347
3348	// Handle when the DOM is ready
3349	ready: function( wait ) {
3350
3351		// Abort if there are pending holds or we're already ready
3352		if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
3353			return;
3354		}
3355
3356		// Remember that the DOM is ready
3357		jQuery.isReady = true;
3358
3359		// If a normal DOM Ready event fired, decrement, and wait if need be
3360		if ( wait !== true && --jQuery.readyWait > 0 ) {
3361			return;
3362		}
3363
vendor: 4,755 bytes, lines 3364-3549
3364		// If there are functions bound, to execute
3365		readyList.resolveWith( document, [ jQuery ] );
3366
3367		// Trigger any bound ready events
3368		if ( jQuery.fn.trigger ) {
3369			jQuery( document ).trigger("ready").off("ready");
3370		}
3371	}
3372});
3373
3374/**
3375 * The ready event handler and self cleanup method
3376 */
3377function completed() {
3378	document.removeEventListener( "DOMContentLoaded", completed, false );
3379	window.removeEventListener( "load", completed, false );
3380	jQuery.ready();
3381}
3382
3383jQuery.ready.promise = function( obj ) {
3384	if ( !readyList ) {
3385
3386		readyList = jQuery.Deferred();
3387
3388		// Catch cases where $(document).ready() is called after the browser event has already occurred.
3389		// we once tried to use readyState "interactive" here, but it caused issues like the one
3390		// discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
3391		if ( document.readyState === "complete" ) {
3392			// Handle it asynchronously to allow scripts the opportunity to delay ready
3393			setTimeout( jQuery.ready );
3394
3395		} else {
3396
3397			// Use the handy event callback
3398			document.addEventListener( "DOMContentLoaded", completed, false );
3399
3400			// A fallback to window.onload, that will always work
3401			window.addEventListener( "load", completed, false );
3402		}
3403	}
3404	return readyList.promise( obj );
3405};
3406
3407// Kick off the DOM ready check even if the user does not
3408jQuery.ready.promise();
3409
3410
3411
3412
3413// Multifunctional method to get and set values of a collection
3414// The value/s can optionally be executed if it's a function
3415var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
3416	var i = 0,
3417		len = elems.length,
3418		bulk = key == null;
3419
3420	// Sets many values
3421	if ( jQuery.type( key ) === "object" ) {
3422		chainable = true;
3423		for ( i in key ) {
3424			jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
3425		}
3426
3427	// Sets one value
3428	} else if ( value !== undefined ) {
3429		chainable = true;
3430
3431		if ( !jQuery.isFunction( value ) ) {
3432			raw = true;
3433		}
3434
3435		if ( bulk ) {
3436			// Bulk operations run against the entire set
3437			if ( raw ) {
3438				fn.call( elems, value );
3439				fn = null;
3440
3441			// ...except when executing function values
3442			} else {
3443				bulk = fn;
3444				fn = function( elem, key, value ) {
3445					return bulk.call( jQuery( elem ), value );
3446				};
3447			}
3448		}
3449
3450		if ( fn ) {
3451			for ( ; i < len; i++ ) {
3452				fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );
3453			}
3454		}
3455	}
3456
3457	return chainable ?
3458		elems :
3459
3460		// Gets
3461		bulk ?
3462			fn.call( elems ) :
3463			len ? fn( elems[0], key ) : emptyGet;
3464};
3465
3466
3467/**
3468 * Determines whether an object can have data
3469 */
3470jQuery.acceptData = function( owner ) {
3471	// Accepts only:
3472	//  - Node
3473	//    - Node.ELEMENT_NODE
3474	//    - Node.DOCUMENT_NODE
3475	//  - Object
3476	//    - Any
3477	/* jshint -W018 */
3478	return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );
3479};
3480
3481
3482function Data() {
3483	// Support: Android < 4,
3484	// Old WebKit does not have Object.preventExtensions/freeze method,
3485	// return new empty object instead with no [[set]] accessor
3486	Object.defineProperty( this.cache = {}, 0, {
3487		get: function() {
3488			return {};
3489		}
3490	});
3491
3492	this.expando = jQuery.expando + Math.random();
3493}
3494
3495Data.uid = 1;
3496Data.accepts = jQuery.acceptData;
3497
3498Data.prototype = {
3499	key: function( owner ) {
3500		// We can accept data for non-element nodes in modern browsers,
3501		// but we should not, see #8335.
3502		// Always return the key for a frozen object.
3503		if ( !Data.accepts( owner ) ) {
3504			return 0;
3505		}
3506
3507		var descriptor = {},
3508			// Check if the owner object already has a cache key
3509			unlock = owner[ this.expando ];
3510
3511		// If not, create one
3512		if ( !unlock ) {
3513			unlock = Data.uid++;
3514
3515			// Secure it in a non-enumerable, non-writable property
3516			try {
3517				descriptor[ this.expando ] = { value: unlock };
3518				Object.defineProperties( owner, descriptor );
3519
3520			// Support: Android < 4
3521			// Fallback to a less secure definition
3522			} catch ( e ) {
3523				descriptor[ this.expando ] = unlock;
3524				jQuery.extend( owner, descriptor );
3525			}
3526		}
3527
3528		// Ensure the cache object
3529		if ( !this.cache[ unlock ] ) {
3530			this.cache[ unlock ] = {};
3531		}
3532
3533		return unlock;
3534	},
3535	set: function( owner, data, value ) {
3536		var prop,
3537			// There may be an unlock assigned to this node,
3538			// if there is no entry for this "owner", create one inline
3539			// and set the unlock as though an owner entry had always existed
3540			unlock = this.key( owner ),
3541			cache = this.cache[ unlock ];
3542
3543		// Handle: [ owner, key, value ] args
3544		if ( typeof data === "string" ) {
3545			cache[ data ] = value;
3546
3547		// Handle: [ owner, { properties } ] args
3548		} else {
3549			// Fresh assignments by object are shallow copied
vendor: 111,241 bytes, lines 3550-7520
3550			if ( jQuery.isEmptyObject( cache ) ) {
3551				jQuery.extend( this.cache[ unlock ], data );
3552			// Otherwise, copy the properties one-by-one to the cache object
3553			} else {
3554				for ( prop in data ) {
3555					cache[ prop ] = data[ prop ];
3556				}
3557			}
3558		}
3559		return cache;
3560	},
3561	get: function( owner, key ) {
3562		// Either a valid cache is found, or will be created.
3563		// New caches will be created and the unlock returned,
3564		// allowing direct access to the newly created
3565		// empty data object. A valid owner object must be provided.
3566		var cache = this.cache[ this.key( owner ) ];
3567
3568		return key === undefined ?
3569			cache : cache[ key ];
3570	},
3571	access: function( owner, key, value ) {
3572		var stored;
3573		// In cases where either:
3574		//
3575		//   1. No key was specified
3576		//   2. A string key was specified, but no value provided
3577		//
3578		// Take the "read" path and allow the get method to determine
3579		// which value to return, respectively either:
3580		//
3581		//   1. The entire cache object
3582		//   2. The data stored at the key
3583		//
3584		if ( key === undefined ||
3585				((key && typeof key === "string") && value === undefined) ) {
3586
3587			stored = this.get( owner, key );
3588
3589			return stored !== undefined ?
3590				stored : this.get( owner, jQuery.camelCase(key) );
3591		}
3592
3593		// [*]When the key is not a string, or both a key and value
3594		// are specified, set or extend (existing objects) with either:
3595		//
3596		//   1. An object of properties
3597		//   2. A key and value
3598		//
3599		this.set( owner, key, value );
3600
3601		// Since the "set" path can have two possible entry points
3602		// return the expected data based on which path was taken[*]
3603		return value !== undefined ? value : key;
3604	},
3605	remove: function( owner, key ) {
3606		var i, name, camel,
3607			unlock = this.key( owner ),
3608			cache = this.cache[ unlock ];
3609
3610		if ( key === undefined ) {
3611			this.cache[ unlock ] = {};
3612
3613		} else {
3614			// Support array or space separated string of keys
3615			if ( jQuery.isArray( key ) ) {
3616				// If "name" is an array of keys...
3617				// When data is initially created, via ("key", "val") signature,
3618				// keys will be converted to camelCase.
3619				// Since there is no way to tell _how_ a key was added, remove
3620				// both plain key and camelCase key. #12786
3621				// This will only penalize the array argument path.
3622				name = key.concat( key.map( jQuery.camelCase ) );
3623			} else {
3624				camel = jQuery.camelCase( key );
3625				// Try the string as a key before any manipulation
3626				if ( key in cache ) {
3627					name = [ key, camel ];
3628				} else {
3629					// If a key with the spaces exists, use it.
3630					// Otherwise, create an array by matching non-whitespace
3631					name = camel;
3632					name = name in cache ?
3633						[ name ] : ( name.match( rnotwhite ) || [] );
3634				}
3635			}
3636
3637			i = name.length;
3638			while ( i-- ) {
3639				delete cache[ name[ i ] ];
3640			}
3641		}
3642	},
3643	hasData: function( owner ) {
3644		return !jQuery.isEmptyObject(
3645			this.cache[ owner[ this.expando ] ] || {}
3646		);
3647	},
3648	discard: function( owner ) {
3649		if ( owner[ this.expando ] ) {
3650			delete this.cache[ owner[ this.expando ] ];
3651		}
3652	}
3653};
3654var data_priv = new Data();
3655
3656var data_user = new Data();
3657
3658
3659
3660/*
3661	Implementation Summary
3662
3663	1. Enforce API surface and semantic compatibility with 1.9.x branch
3664	2. Improve the module's maintainability by reducing the storage
3665		paths to a single mechanism.
3666	3. Use the same single mechanism to support "private" and "user" data.
3667	4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData)
3668	5. Avoid exposing implementation details on user objects (eg. expando properties)
3669	6. Provide a clear path for implementation upgrade to WeakMap in 2014
3670*/
3671var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
3672	rmultiDash = /([A-Z])/g;
3673
3674function dataAttr( elem, key, data ) {
3675	var name;
3676
3677	// If nothing was found internally, try to fetch any
3678	// data from the HTML5 data-* attribute
3679	if ( data === undefined && elem.nodeType === 1 ) {
3680		name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
3681		data = elem.getAttribute( name );
3682
3683		if ( typeof data === "string" ) {
3684			try {
3685				data = data === "true" ? true :
3686					data === "false" ? false :
3687					data === "null" ? null :
3688					// Only convert to a number if it doesn't change the string
3689					+data + "" === data ? +data :
3690					rbrace.test( data ) ? jQuery.parseJSON( data ) :
3691					data;
3692			} catch( e ) {}
3693
3694			// Make sure we set the data so it isn't changed later
3695			data_user.set( elem, key, data );
3696		} else {
3697			data = undefined;
3698		}
3699	}
3700	return data;
3701}
3702
3703jQuery.extend({
3704	hasData: function( elem ) {
3705		return data_user.hasData( elem ) || data_priv.hasData( elem );
3706	},
3707
3708	data: function( elem, name, data ) {
3709		return data_user.access( elem, name, data );
3710	},
3711
3712	removeData: function( elem, name ) {
3713		data_user.remove( elem, name );
3714	},
3715
3716	// TODO: Now that all calls to _data and _removeData have been replaced
3717	// with direct calls to data_priv methods, these can be deprecated.
3718	_data: function( elem, name, data ) {
3719		return data_priv.access( elem, name, data );
3720	},
3721
3722	_removeData: function( elem, name ) {
3723		data_priv.remove( elem, name );
3724	}
3725});
3726
3727jQuery.fn.extend({
3728	data: function( key, value ) {
3729		var i, name, data,
3730			elem = this[ 0 ],
3731			attrs = elem && elem.attributes;
3732
3733		// Gets all values
3734		if ( key === undefined ) {
3735			if ( this.length ) {
3736				data = data_user.get( elem );
3737
3738				if ( elem.nodeType === 1 && !data_priv.get( elem, "hasDataAttrs" ) ) {
3739					i = attrs.length;
3740					while ( i-- ) {
3741						name = attrs[ i ].name;
3742
3743						if ( name.indexOf( "data-" ) === 0 ) {
3744							name = jQuery.camelCase( name.slice(5) );
3745							dataAttr( elem, name, data[ name ] );
3746						}
3747					}
3748					data_priv.set( elem, "hasDataAttrs", true );
3749				}
3750			}
3751
3752			return data;
3753		}
3754
3755		// Sets multiple values
3756		if ( typeof key === "object" ) {
3757			return this.each(function() {
3758				data_user.set( this, key );
3759			});
3760		}
3761
3762		return access( this, function( value ) {
3763			var data,
3764				camelKey = jQuery.camelCase( key );
3765
3766			// The calling jQuery object (element matches) is not empty
3767			// (and therefore has an element appears at this[ 0 ]) and the
3768			// `value` parameter was not undefined. An empty jQuery object
3769			// will result in `undefined` for elem = this[ 0 ] which will
3770			// throw an exception if an attempt to read a data cache is made.
3771			if ( elem && value === undefined ) {
3772				// Attempt to get data from the cache
3773				// with the key as-is
3774				data = data_user.get( elem, key );
3775				if ( data !== undefined ) {
3776					return data;
3777				}
3778
3779				// Attempt to get data from the cache
3780				// with the key camelized
3781				data = data_user.get( elem, camelKey );
3782				if ( data !== undefined ) {
3783					return data;
3784				}
3785
3786				// Attempt to "discover" the data in
3787				// HTML5 custom data-* attrs
3788				data = dataAttr( elem, camelKey, undefined );
3789				if ( data !== undefined ) {
3790					return data;
3791				}
3792
3793				// We tried really hard, but the data doesn't exist.
3794				return;
3795			}
3796
3797			// Set the data...
3798			this.each(function() {
3799				// First, attempt to store a copy or reference of any
3800				// data that might've been store with a camelCased key.
3801				var data = data_user.get( this, camelKey );
3802
3803				// For HTML5 data-* attribute interop, we have to
3804				// store property names with dashes in a camelCase form.
3805				// This might not apply to all properties...*
3806				data_user.set( this, camelKey, value );
3807
3808				// *... In the case of properties that might _actually_
3809				// have dashes, we need to also store a copy of that
3810				// unchanged property.
3811				if ( key.indexOf("-") !== -1 && data !== undefined ) {
3812					data_user.set( this, key, value );
3813				}
3814			});
3815		}, null, value, arguments.length > 1, null, true );
3816	},
3817
3818	removeData: function( key ) {
3819		return this.each(function() {
3820			data_user.remove( this, key );
3821		});
3822	}
3823});
3824
3825
3826jQuery.extend({
3827	queue: function( elem, type, data ) {
3828		var queue;
3829
3830		if ( elem ) {
3831			type = ( type || "fx" ) + "queue";
3832			queue = data_priv.get( elem, type );
3833
3834			// Speed up dequeue by getting out quickly if this is just a lookup
3835			if ( data ) {
3836				if ( !queue || jQuery.isArray( data ) ) {
3837					queue = data_priv.access( elem, type, jQuery.makeArray(data) );
3838				} else {
3839					queue.push( data );
3840				}
3841			}
3842			return queue || [];
3843		}
3844	},
3845
3846	dequeue: function( elem, type ) {
3847		type = type || "fx";
3848
3849		var queue = jQuery.queue( elem, type ),
3850			startLength = queue.length,
3851			fn = queue.shift(),
3852			hooks = jQuery._queueHooks( elem, type ),
3853			next = function() {
3854				jQuery.dequeue( elem, type );
3855			};
3856
3857		// If the fx queue is dequeued, always remove the progress sentinel
3858		if ( fn === "inprogress" ) {
3859			fn = queue.shift();
3860			startLength--;
3861		}
3862
3863		if ( fn ) {
3864
3865			// Add a progress sentinel to prevent the fx queue from being
3866			// automatically dequeued
3867			if ( type === "fx" ) {
3868				queue.unshift( "inprogress" );
3869			}
3870
3871			// clear up the last queue stop function
3872			delete hooks.stop;
3873			fn.call( elem, next, hooks );
3874		}
3875
3876		if ( !startLength && hooks ) {
3877			hooks.empty.fire();
3878		}
3879	},
3880
3881	// not intended for public consumption - generates a queueHooks object, or returns the current one
3882	_queueHooks: function( elem, type ) {
3883		var key = type + "queueHooks";
3884		return data_priv.get( elem, key ) || data_priv.access( elem, key, {
3885			empty: jQuery.Callbacks("once memory").add(function() {
3886				data_priv.remove( elem, [ type + "queue", key ] );
3887			})
3888		});
3889	}
3890});
3891
3892jQuery.fn.extend({
3893	queue: function( type, data ) {
3894		var setter = 2;
3895
3896		if ( typeof type !== "string" ) {
3897			data = type;
3898			type = "fx";
3899			setter--;
3900		}
3901
3902		if ( arguments.length < setter ) {
3903			return jQuery.queue( this[0], type );
3904		}
3905
3906		return data === undefined ?
3907			this :
3908			this.each(function() {
3909				var queue = jQuery.queue( this, type, data );
3910
3911				// ensure a hooks for this queue
3912				jQuery._queueHooks( this, type );
3913
3914				if ( type === "fx" && queue[0] !== "inprogress" ) {
3915					jQuery.dequeue( this, type );
3916				}
3917			});
3918	},
3919	dequeue: function( type ) {
3920		return this.each(function() {
3921			jQuery.dequeue( this, type );
3922		});
3923	},
3924	clearQueue: function( type ) {
3925		return this.queue( type || "fx", [] );
3926	},
3927	// Get a promise resolved when queues of a certain type
3928	// are emptied (fx is the type by default)
3929	promise: function( type, obj ) {
3930		var tmp,
3931			count = 1,
3932			defer = jQuery.Deferred(),
3933			elements = this,
3934			i = this.length,
3935			resolve = function() {
3936				if ( !( --count ) ) {
3937					defer.resolveWith( elements, [ elements ] );
3938				}
3939			};
3940
3941		if ( typeof type !== "string" ) {
3942			obj = type;
3943			type = undefined;
3944		}
3945		type = type || "fx";
3946
3947		while ( i-- ) {
3948			tmp = data_priv.get( elements[ i ], type + "queueHooks" );
3949			if ( tmp && tmp.empty ) {
3950				count++;
3951				tmp.empty.add( resolve );
3952			}
3953		}
3954		resolve();
3955		return defer.promise( obj );
3956	}
3957});
3958var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source;
3959
3960var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
3961
3962var isHidden = function( elem, el ) {
3963		// isHidden might be called from jQuery#filter function;
3964		// in that case, element will be second argument
3965		elem = el || elem;
3966		return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
3967	};
3968
3969var rcheckableType = (/^(?:checkbox|radio)$/i);
3970
3971
3972
3973(function() {
3974	var fragment = document.createDocumentFragment(),
3975		div = fragment.appendChild( document.createElement( "div" ) );
3976
3977	// #11217 - WebKit loses check when the name is after the checked attribute
3978	div.innerHTML = "<input type='radio' checked='checked' name='t'/>";
3979
3980	// Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3
3981	// old WebKit doesn't clone checked state correctly in fragments
3982	support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
3983
3984	// Make sure textarea (and checkbox) defaultValue is properly cloned
3985	// Support: IE9-IE11+
3986	div.innerHTML = "<textarea>x</textarea>";
3987	support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
3988})();
3989var strundefined = typeof undefined;
3990
3991
3992
3993support.focusinBubbles = "onfocusin" in window;
3994
3995
3996var
3997	rkeyEvent = /^key/,
3998	rmouseEvent = /^(?:mouse|contextmenu)|click/,
3999	rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
4000	rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
4001
4002function returnTrue() {
4003	return true;
4004}
4005
4006function returnFalse() {
4007	return false;
4008}
4009
4010function safeActiveElement() {
4011	try {
4012		return document.activeElement;
4013	} catch ( err ) { }
4014}
4015
4016/*
4017 * Helper functions for managing events -- not part of the public interface.
4018 * Props to Dean Edwards' addEvent library for many of the ideas.
4019 */
4020jQuery.event = {
4021
4022	global: {},
4023
4024	add: function( elem, types, handler, data, selector ) {
4025
4026		var handleObjIn, eventHandle, tmp,
4027			events, t, handleObj,
4028			special, handlers, type, namespaces, origType,
4029			elemData = data_priv.get( elem );
4030
4031		// Don't attach events to noData or text/comment nodes (but allow plain objects)
4032		if ( !elemData ) {
4033			return;
4034		}
4035
4036		// Caller can pass in an object of custom data in lieu of the handler
4037		if ( handler.handler ) {
4038			handleObjIn = handler;
4039			handler = handleObjIn.handler;
4040			selector = handleObjIn.selector;
4041		}
4042
4043		// Make sure that the handler has a unique ID, used to find/remove it later
4044		if ( !handler.guid ) {
4045			handler.guid = jQuery.guid++;
4046		}
4047
4048		// Init the element's event structure and main handler, if this is the first
4049		if ( !(events = elemData.events) ) {
4050			events = elemData.events = {};
4051		}
4052		if ( !(eventHandle = elemData.handle) ) {
4053			eventHandle = elemData.handle = function( e ) {
4054				// Discard the second event of a jQuery.event.trigger() and
4055				// when an event is called after a page has unloaded
4056				return typeof jQuery !== strundefined && jQuery.event.triggered !== e.type ?
4057					jQuery.event.dispatch.apply( elem, arguments ) : undefined;
4058			};
4059		}
4060
4061		// Handle multiple events separated by a space
4062		types = ( types || "" ).match( rnotwhite ) || [ "" ];
4063		t = types.length;
4064		while ( t-- ) {
4065			tmp = rtypenamespace.exec( types[t] ) || [];
4066			type = origType = tmp[1];
4067			namespaces = ( tmp[2] || "" ).split( "." ).sort();
4068
4069			// There *must* be a type, no attaching namespace-only handlers
4070			if ( !type ) {
4071				continue;
4072			}
4073
4074			// If event changes its type, use the special event handlers for the changed type
4075			special = jQuery.event.special[ type ] || {};
4076
4077			// If selector defined, determine special event api type, otherwise given type
4078			type = ( selector ? special.delegateType : special.bindType ) || type;
4079
4080			// Update special based on newly reset type
4081			special = jQuery.event.special[ type ] || {};
4082
4083			// handleObj is passed to all event handlers
4084			handleObj = jQuery.extend({
4085				type: type,
4086				origType: origType,
4087				data: data,
4088				handler: handler,
4089				guid: handler.guid,
4090				selector: selector,
4091				needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
4092				namespace: namespaces.join(".")
4093			}, handleObjIn );
4094
4095			// Init the event handler queue if we're the first
4096			if ( !(handlers = events[ type ]) ) {
4097				handlers = events[ type ] = [];
4098				handlers.delegateCount = 0;
4099
4100				// Only use addEventListener if the special events handler returns false
4101				if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
4102					if ( elem.addEventListener ) {
4103						elem.addEventListener( type, eventHandle, false );
4104					}
4105				}
4106			}
4107
4108			if ( special.add ) {
4109				special.add.call( elem, handleObj );
4110
4111				if ( !handleObj.handler.guid ) {
4112					handleObj.handler.guid = handler.guid;
4113				}
4114			}
4115
4116			// Add to the element's handler list, delegates in front
4117			if ( selector ) {
4118				handlers.splice( handlers.delegateCount++, 0, handleObj );
4119			} else {
4120				handlers.push( handleObj );
4121			}
4122
4123			// Keep track of which events have ever been used, for event optimization
4124			jQuery.event.global[ type ] = true;
4125		}
4126
4127	},
4128
4129	// Detach an event or set of events from an element
4130	remove: function( elem, types, handler, selector, mappedTypes ) {
4131
4132		var j, origCount, tmp,
4133			events, t, handleObj,
4134			special, handlers, type, namespaces, origType,
4135			elemData = data_priv.hasData( elem ) && data_priv.get( elem );
4136
4137		if ( !elemData || !(events = elemData.events) ) {
4138			return;
4139		}
4140
4141		// Once for each type.namespace in types; type may be omitted
4142		types = ( types || "" ).match( rnotwhite ) || [ "" ];
4143		t = types.length;
4144		while ( t-- ) {
4145			tmp = rtypenamespace.exec( types[t] ) || [];
4146			type = origType = tmp[1];
4147			namespaces = ( tmp[2] || "" ).split( "." ).sort();
4148
4149			// Unbind all events (on this namespace, if provided) for the element
4150			if ( !type ) {
4151				for ( type in events ) {
4152					jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
4153				}
4154				continue;
4155			}
4156
4157			special = jQuery.event.special[ type ] || {};
4158			type = ( selector ? special.delegateType : special.bindType ) || type;
4159			handlers = events[ type ] || [];
4160			tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );
4161
4162			// Remove matching events
4163			origCount = j = handlers.length;
4164			while ( j-- ) {
4165				handleObj = handlers[ j ];
4166
4167				if ( ( mappedTypes || origType === handleObj.origType ) &&
4168					( !handler || handler.guid === handleObj.guid ) &&
4169					( !tmp || tmp.test( handleObj.namespace ) ) &&
4170					( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
4171					handlers.splice( j, 1 );
4172
4173					if ( handleObj.selector ) {
4174						handlers.delegateCount--;
4175					}
4176					if ( special.remove ) {
4177						special.remove.call( elem, handleObj );
4178					}
4179				}
4180			}
4181
4182			// Remove generic event handler if we removed something and no more handlers exist
4183			// (avoids potential for endless recursion during removal of special event handlers)
4184			if ( origCount && !handlers.length ) {
4185				if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
4186					jQuery.removeEvent( elem, type, elemData.handle );
4187				}
4188
4189				delete events[ type ];
4190			}
4191		}
4192
4193		// Remove the expando if it's no longer used
4194		if ( jQuery.isEmptyObject( events ) ) {
4195			delete elemData.handle;
4196			data_priv.remove( elem, "events" );
4197		}
4198	},
4199
4200	trigger: function( event, data, elem, onlyHandlers ) {
4201
4202		var i, cur, tmp, bubbleType, ontype, handle, special,
4203			eventPath = [ elem || document ],
4204			type = hasOwn.call( event, "type" ) ? event.type : event,
4205			namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];
4206
4207		cur = tmp = elem = elem || document;
4208
4209		// Don't do events on text and comment nodes
4210		if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
4211			return;
4212		}
4213
4214		// focus/blur morphs to focusin/out; ensure we're not firing them right now
4215		if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
4216			return;
4217		}
4218
4219		if ( type.indexOf(".") >= 0 ) {
4220			// Namespaced trigger; create a regexp to match event type in handle()
4221			namespaces = type.split(".");
4222			type = namespaces.shift();
4223			namespaces.sort();
4224		}
4225		ontype = type.indexOf(":") < 0 && "on" + type;
4226
4227		// Caller can pass in a jQuery.Event object, Object, or just an event type string
4228		event = event[ jQuery.expando ] ?
4229			event :
4230			new jQuery.Event( type, typeof event === "object" && event );
4231
4232		// Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
4233		event.isTrigger = onlyHandlers ? 2 : 3;
4234		event.namespace = namespaces.join(".");
4235		event.namespace_re = event.namespace ?
4236			new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
4237			null;
4238
4239		// Clean up the event in case it is being reused
4240		event.result = undefined;
4241		if ( !event.target ) {
4242			event.target = elem;
4243		}
4244
4245		// Clone any incoming data and prepend the event, creating the handler arg list
4246		data = data == null ?
4247			[ event ] :
4248			jQuery.makeArray( data, [ event ] );
4249
4250		// Allow special events to draw outside the lines
4251		special = jQuery.event.special[ type ] || {};
4252		if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
4253			return;
4254		}
4255
4256		// Determine event propagation path in advance, per W3C events spec (#9951)
4257		// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
4258		if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
4259
4260			bubbleType = special.delegateType || type;
4261			if ( !rfocusMorph.test( bubbleType + type ) ) {
4262				cur = cur.parentNode;
4263			}
4264			for ( ; cur; cur = cur.parentNode ) {
4265				eventPath.push( cur );
4266				tmp = cur;
4267			}
4268
4269			// Only add window if we got to document (e.g., not plain obj or detached DOM)
4270			if ( tmp === (elem.ownerDocument || document) ) {
4271				eventPath.push( tmp.defaultView || tmp.parentWindow || window );
4272			}
4273		}
4274
4275		// Fire handlers on the event path
4276		i = 0;
4277		while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {
4278
4279			event.type = i > 1 ?
4280				bubbleType :
4281				special.bindType || type;
4282
4283			// jQuery handler
4284			handle = ( data_priv.get( cur, "events" ) || {} )[ event.type ] && data_priv.get( cur, "handle" );
4285			if ( handle ) {
4286				handle.apply( cur, data );
4287			}
4288
4289			// Native handler
4290			handle = ontype && cur[ ontype ];
4291			if ( handle && handle.apply && jQuery.acceptData( cur ) ) {
4292				event.result = handle.apply( cur, data );
4293				if ( event.result === false ) {
4294					event.preventDefault();
4295				}
4296			}
4297		}
4298		event.type = type;
4299
4300		// If nobody prevented the default action, do it now
4301		if ( !onlyHandlers && !event.isDefaultPrevented() ) {
4302
4303			if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&
4304				jQuery.acceptData( elem ) ) {
4305
4306				// Call a native DOM method on the target with the same name name as the event.
4307				// Don't do default actions on window, that's where global variables be (#6170)
4308				if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) {
4309
4310					// Don't re-trigger an onFOO event when we call its FOO() method
4311					tmp = elem[ ontype ];
4312
4313					if ( tmp ) {
4314						elem[ ontype ] = null;
4315					}
4316
4317					// Prevent re-triggering of the same event, since we already bubbled it above
4318					jQuery.event.triggered = type;
4319					elem[ type ]();
4320					jQuery.event.triggered = undefined;
4321
4322					if ( tmp ) {
4323						elem[ ontype ] = tmp;
4324					}
4325				}
4326			}
4327		}
4328
4329		return event.result;
4330	},
4331
4332	dispatch: function( event ) {
4333
4334		// Make a writable jQuery.Event from the native event object
4335		event = jQuery.event.fix( event );
4336
4337		var i, j, ret, matched, handleObj,
4338			handlerQueue = [],
4339			args = slice.call( arguments ),
4340			handlers = ( data_priv.get( this, "events" ) || {} )[ event.type ] || [],
4341			special = jQuery.event.special[ event.type ] || {};
4342
4343		// Use the fix-ed jQuery.Event rather than the (read-only) native event
4344		args[0] = event;
4345		event.delegateTarget = this;
4346
4347		// Call the preDispatch hook for the mapped type, and let it bail if desired
4348		if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
4349			return;
4350		}
4351
4352		// Determine handlers
4353		handlerQueue = jQuery.event.handlers.call( this, event, handlers );
4354
4355		// Run delegates first; they may want to stop propagation beneath us
4356		i = 0;
4357		while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
4358			event.currentTarget = matched.elem;
4359
4360			j = 0;
4361			while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
4362
4363				// Triggered event must either 1) have no namespace, or
4364				// 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
4365				if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
4366
4367					event.handleObj = handleObj;
4368					event.data = handleObj.data;
4369
4370					ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
4371							.apply( matched.elem, args );
4372
4373					if ( ret !== undefined ) {
4374						if ( (event.result = ret) === false ) {
4375							event.preventDefault();
4376							event.stopPropagation();
4377						}
4378					}
4379				}
4380			}
4381		}
4382
4383		// Call the postDispatch hook for the mapped type
4384		if ( special.postDispatch ) {
4385			special.postDispatch.call( this, event );
4386		}
4387
4388		return event.result;
4389	},
4390
4391	handlers: function( event, handlers ) {
4392		var i, matches, sel, handleObj,
4393			handlerQueue = [],
4394			delegateCount = handlers.delegateCount,
4395			cur = event.target;
4396
4397		// Find delegate handlers
4398		// Black-hole SVG <use> instance trees (#13180)
4399		// Avoid non-left-click bubbling in Firefox (#3861)
4400		if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) {
4401
4402			for ( ; cur !== this; cur = cur.parentNode || this ) {
4403
4404				// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
4405				if ( cur.disabled !== true || event.type !== "click" ) {
4406					matches = [];
4407					for ( i = 0; i < delegateCount; i++ ) {
4408						handleObj = handlers[ i ];
4409
4410						// Don't conflict with Object.prototype properties (#13203)
4411						sel = handleObj.selector + " ";
4412
4413						if ( matches[ sel ] === undefined ) {
4414							matches[ sel ] = handleObj.needsContext ?
4415								jQuery( sel, this ).index( cur ) >= 0 :
4416								jQuery.find( sel, this, null, [ cur ] ).length;
4417						}
4418						if ( matches[ sel ] ) {
4419							matches.push( handleObj );
4420						}
4421					}
4422					if ( matches.length ) {
4423						handlerQueue.push({ elem: cur, handlers: matches });
4424					}
4425				}
4426			}
4427		}
4428
4429		// Add the remaining (directly-bound) handlers
4430		if ( delegateCount < handlers.length ) {
4431			handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });
4432		}
4433
4434		return handlerQueue;
4435	},
4436
4437	// Includes some event props shared by KeyEvent and MouseEvent
4438	props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
4439
4440	fixHooks: {},
4441
4442	keyHooks: {
4443		props: "char charCode key keyCode".split(" "),
4444		filter: function( event, original ) {
4445
4446			// Add which for key events
4447			if ( event.which == null ) {
4448				event.which = original.charCode != null ? original.charCode : original.keyCode;
4449			}
4450
4451			return event;
4452		}
4453	},
4454
4455	mouseHooks: {
4456		props: "button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
4457		filter: function( event, original ) {
4458			var eventDoc, doc, body,
4459				button = original.button;
4460
4461			// Calculate pageX/Y if missing and clientX/Y available
4462			if ( event.pageX == null && original.clientX != null ) {
4463				eventDoc = event.target.ownerDocument || document;
4464				doc = eventDoc.documentElement;
4465				body = eventDoc.body;
4466
4467				event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
4468				event.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );
4469			}
4470
4471			// Add which for click: 1 === left; 2 === middle; 3 === right
4472			// Note: button is not normalized, so don't use it
4473			if ( !event.which && button !== undefined ) {
4474				event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
4475			}
4476
4477			return event;
4478		}
4479	},
4480
4481	fix: function( event ) {
4482		if ( event[ jQuery.expando ] ) {
4483			return event;
4484		}
4485
4486		// Create a writable copy of the event object and normalize some properties
4487		var i, prop, copy,
4488			type = event.type,
4489			originalEvent = event,
4490			fixHook = this.fixHooks[ type ];
4491
4492		if ( !fixHook ) {
4493			this.fixHooks[ type ] = fixHook =
4494				rmouseEvent.test( type ) ? this.mouseHooks :
4495				rkeyEvent.test( type ) ? this.keyHooks :
4496				{};
4497		}
4498		copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
4499
4500		event = new jQuery.Event( originalEvent );
4501
4502		i = copy.length;
4503		while ( i-- ) {
4504			prop = copy[ i ];
4505			event[ prop ] = originalEvent[ prop ];
4506		}
4507
4508		// Support: Cordova 2.5 (WebKit) (#13255)
4509		// All events should have a target; Cordova deviceready doesn't
4510		if ( !event.target ) {
4511			event.target = document;
4512		}
4513
4514		// Support: Safari 6.0+, Chrome < 28
4515		// Target should not be a text node (#504, #13143)
4516		if ( event.target.nodeType === 3 ) {
4517			event.target = event.target.parentNode;
4518		}
4519
4520		return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
4521	},
4522
4523	special: {
4524		load: {
4525			// Prevent triggered image.load events from bubbling to window.load
4526			noBubble: true
4527		},
4528		focus: {
4529			// Fire native event if possible so blur/focus sequence is correct
4530			trigger: function() {
4531				if ( this !== safeActiveElement() && this.focus ) {
4532					this.focus();
4533					return false;
4534				}
4535			},
4536			delegateType: "focusin"
4537		},
4538		blur: {
4539			trigger: function() {
4540				if ( this === safeActiveElement() && this.blur ) {
4541					this.blur();
4542					return false;
4543				}
4544			},
4545			delegateType: "focusout"
4546		},
4547		click: {
4548			// For checkbox, fire native event so checked state will be right
4549			trigger: function() {
4550				if ( this.type === "checkbox" && this.click && jQuery.nodeName( this, "input" ) ) {
4551					this.click();
4552					return false;
4553				}
4554			},
4555
4556			// For cross-browser consistency, don't fire native .click() on links
4557			_default: function( event ) {
4558				return jQuery.nodeName( event.target, "a" );
4559			}
4560		},
4561
4562		beforeunload: {
4563			postDispatch: function( event ) {
4564
4565				// Support: Firefox 20+
4566				// Firefox doesn't alert if the returnValue field is not set.
4567				if ( event.result !== undefined ) {
4568					event.originalEvent.returnValue = event.result;
4569				}
4570			}
4571		}
4572	},
4573
4574	simulate: function( type, elem, event, bubble ) {
4575		// Piggyback on a donor event to simulate a different one.
4576		// Fake originalEvent to avoid donor's stopPropagation, but if the
4577		// simulated event prevents default then we do the same on the donor.
4578		var e = jQuery.extend(
4579			new jQuery.Event(),
4580			event,
4581			{
4582				type: type,
4583				isSimulated: true,
4584				originalEvent: {}
4585			}
4586		);
4587		if ( bubble ) {
4588			jQuery.event.trigger( e, null, elem );
4589		} else {
4590			jQuery.event.dispatch.call( elem, e );
4591		}
4592		if ( e.isDefaultPrevented() ) {
4593			event.preventDefault();
4594		}
4595	}
4596};
4597
4598jQuery.removeEvent = function( elem, type, handle ) {
4599	if ( elem.removeEventListener ) {
4600		elem.removeEventListener( type, handle, false );
4601	}
4602};
4603
4604jQuery.Event = function( src, props ) {
4605	// Allow instantiation without the 'new' keyword
4606	if ( !(this instanceof jQuery.Event) ) {
4607		return new jQuery.Event( src, props );
4608	}
4609
4610	// Event object
4611	if ( src && src.type ) {
4612		this.originalEvent = src;
4613		this.type = src.type;
4614
4615		// Events bubbling up the document may have been marked as prevented
4616		// by a handler lower down the tree; reflect the correct value.
4617		this.isDefaultPrevented = src.defaultPrevented ||
4618				// Support: Android < 4.0
4619				src.defaultPrevented === undefined &&
4620				src.getPreventDefault && src.getPreventDefault() ?
4621			returnTrue :
4622			returnFalse;
4623
4624	// Event type
4625	} else {
4626		this.type = src;
4627	}
4628
4629	// Put explicitly provided properties onto the event object
4630	if ( props ) {
4631		jQuery.extend( this, props );
4632	}
4633
4634	// Create a timestamp if incoming event doesn't have one
4635	this.timeStamp = src && src.timeStamp || jQuery.now();
4636
4637	// Mark it as fixed
4638	this[ jQuery.expando ] = true;
4639};
4640
4641// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
4642// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
4643jQuery.Event.prototype = {
4644	isDefaultPrevented: returnFalse,
4645	isPropagationStopped: returnFalse,
4646	isImmediatePropagationStopped: returnFalse,
4647
4648	preventDefault: function() {
4649		var e = this.originalEvent;
4650
4651		this.isDefaultPrevented = returnTrue;
4652
4653		if ( e && e.preventDefault ) {
4654			e.preventDefault();
4655		}
4656	},
4657	stopPropagation: function() {
4658		var e = this.originalEvent;
4659
4660		this.isPropagationStopped = returnTrue;
4661
4662		if ( e && e.stopPropagation ) {
4663			e.stopPropagation();
4664		}
4665	},
4666	stopImmediatePropagation: function() {
4667		this.isImmediatePropagationStopped = returnTrue;
4668		this.stopPropagation();
4669	}
4670};
4671
4672// Create mouseenter/leave events using mouseover/out and event-time checks
4673// Support: Chrome 15+
4674jQuery.each({
4675	mouseenter: "mouseover",
4676	mouseleave: "mouseout"
4677}, function( orig, fix ) {
4678	jQuery.event.special[ orig ] = {
4679		delegateType: fix,
4680		bindType: fix,
4681
4682		handle: function( event ) {
4683			var ret,
4684				target = this,
4685				related = event.relatedTarget,
4686				handleObj = event.handleObj;
4687
4688			// For mousenter/leave call the handler if related is outside the target.
4689			// NB: No relatedTarget if the mouse left/entered the browser window
4690			if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
4691				event.type = handleObj.origType;
4692				ret = handleObj.handler.apply( this, arguments );
4693				event.type = fix;
4694			}
4695			return ret;
4696		}
4697	};
4698});
4699
4700// Create "bubbling" focus and blur events
4701// Support: Firefox, Chrome, Safari
4702if ( !support.focusinBubbles ) {
4703	jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
4704
4705		// Attach a single capturing handler on the document while someone wants focusin/focusout
4706		var handler = function( event ) {
4707				jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
4708			};
4709
4710		jQuery.event.special[ fix ] = {
4711			setup: function() {
4712				var doc = this.ownerDocument || this,
4713					attaches = data_priv.access( doc, fix );
4714
4715				if ( !attaches ) {
4716					doc.addEventListener( orig, handler, true );
4717				}
4718				data_priv.access( doc, fix, ( attaches || 0 ) + 1 );
4719			},
4720			teardown: function() {
4721				var doc = this.ownerDocument || this,
4722					attaches = data_priv.access( doc, fix ) - 1;
4723
4724				if ( !attaches ) {
4725					doc.removeEventListener( orig, handler, true );
4726					data_priv.remove( doc, fix );
4727
4728				} else {
4729					data_priv.access( doc, fix, attaches );
4730				}
4731			}
4732		};
4733	});
4734}
4735
4736jQuery.fn.extend({
4737
4738	on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
4739		var origFn, type;
4740
4741		// Types can be a map of types/handlers
4742		if ( typeof types === "object" ) {
4743			// ( types-Object, selector, data )
4744			if ( typeof selector !== "string" ) {
4745				// ( types-Object, data )
4746				data = data || selector;
4747				selector = undefined;
4748			}
4749			for ( type in types ) {
4750				this.on( type, selector, data, types[ type ], one );
4751			}
4752			return this;
4753		}
4754
4755		if ( data == null && fn == null ) {
4756			// ( types, fn )
4757			fn = selector;
4758			data = selector = undefined;
4759		} else if ( fn == null ) {
4760			if ( typeof selector === "string" ) {
4761				// ( types, selector, fn )
4762				fn = data;
4763				data = undefined;
4764			} else {
4765				// ( types, data, fn )
4766				fn = data;
4767				data = selector;
4768				selector = undefined;
4769			}
4770		}
4771		if ( fn === false ) {
4772			fn = returnFalse;
4773		} else if ( !fn ) {
4774			return this;
4775		}
4776
4777		if ( one === 1 ) {
4778			origFn = fn;
4779			fn = function( event ) {
4780				// Can use an empty set, since event contains the info
4781				jQuery().off( event );
4782				return origFn.apply( this, arguments );
4783			};
4784			// Use same guid so caller can remove using origFn
4785			fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
4786		}
4787		return this.each( function() {
4788			jQuery.event.add( this, types, fn, data, selector );
4789		});
4790	},
4791	one: function( types, selector, data, fn ) {
4792		return this.on( types, selector, data, fn, 1 );
4793	},
4794	off: function( types, selector, fn ) {
4795		var handleObj, type;
4796		if ( types && types.preventDefault && types.handleObj ) {
4797			// ( event )  dispatched jQuery.Event
4798			handleObj = types.handleObj;
4799			jQuery( types.delegateTarget ).off(
4800				handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
4801				handleObj.selector,
4802				handleObj.handler
4803			);
4804			return this;
4805		}
4806		if ( typeof types === "object" ) {
4807			// ( types-object [, selector] )
4808			for ( type in types ) {
4809				this.off( type, selector, types[ type ] );
4810			}
4811			return this;
4812		}
4813		if ( selector === false || typeof selector === "function" ) {
4814			// ( types [, fn] )
4815			fn = selector;
4816			selector = undefined;
4817		}
4818		if ( fn === false ) {
4819			fn = returnFalse;
4820		}
4821		return this.each(function() {
4822			jQuery.event.remove( this, types, fn, selector );
4823		});
4824	},
4825
4826	trigger: function( type, data ) {
4827		return this.each(function() {
4828			jQuery.event.trigger( type, data, this );
4829		});
4830	},
4831	triggerHandler: function( type, data ) {
4832		var elem = this[0];
4833		if ( elem ) {
4834			return jQuery.event.trigger( type, data, elem, true );
4835		}
4836	}
4837});
4838
4839
4840var
4841	rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
4842	rtagName = /<([\w:]+)/,
4843	rhtml = /<|&#?\w+;/,
4844	rnoInnerhtml = /<(?:script|style|link)/i,
4845	// checked="checked" or checked
4846	rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
4847	rscriptType = /^$|\/(?:java|ecma)script/i,
4848	rscriptTypeMasked = /^true\/(.*)/,
4849	rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,
4850
4851	// We have to close these tags to support XHTML (#13200)
4852	wrapMap = {
4853
4854		// Support: IE 9
4855		option: [ 1, "<select multiple='multiple'>", "</select>" ],
4856
4857		thead: [ 1, "<table>", "</table>" ],
4858		col: [ 2, "<table><colgroup>", "</colgroup></table>" ],
4859		tr: [ 2, "<table><tbody>", "</tbody></table>" ],
4860		td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
4861
4862		_default: [ 0, "", "" ]
4863	};
4864
4865// Support: IE 9
4866wrapMap.optgroup = wrapMap.option;
4867
4868wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
4869wrapMap.th = wrapMap.td;
4870
4871// Support: 1.x compatibility
4872// Manipulating tables requires a tbody
4873function manipulationTarget( elem, content ) {
4874	return jQuery.nodeName( elem, "table" ) &&
4875		jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ?
4876
4877		elem.getElementsByTagName("tbody")[0] ||
4878			elem.appendChild( elem.ownerDocument.createElement("tbody") ) :
4879		elem;
4880}
4881
4882// Replace/restore the type attribute of script elements for safe DOM manipulation
4883function disableScript( elem ) {
4884	elem.type = (elem.getAttribute("type") !== null) + "/" + elem.type;
4885	return elem;
4886}
4887function restoreScript( elem ) {
4888	var match = rscriptTypeMasked.exec( elem.type );
4889
4890	if ( match ) {
4891		elem.type = match[ 1 ];
4892	} else {
4893		elem.removeAttribute("type");
4894	}
4895
4896	return elem;
4897}
4898
4899// Mark scripts as having already been evaluated
4900function setGlobalEval( elems, refElements ) {
4901	var i = 0,
4902		l = elems.length;
4903
4904	for ( ; i < l; i++ ) {
4905		data_priv.set(
4906			elems[ i ], "globalEval", !refElements || data_priv.get( refElements[ i ], "globalEval" )
4907		);
4908	}
4909}
4910
4911function cloneCopyEvent( src, dest ) {
4912	var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;
4913
4914	if ( dest.nodeType !== 1 ) {
4915		return;
4916	}
4917
4918	// 1. Copy private data: events, handlers, etc.
4919	if ( data_priv.hasData( src ) ) {
4920		pdataOld = data_priv.access( src );
4921		pdataCur = data_priv.set( dest, pdataOld );
4922		events = pdataOld.events;
4923
4924		if ( events ) {
4925			delete pdataCur.handle;
4926			pdataCur.events = {};
4927
4928			for ( type in events ) {
4929				for ( i = 0, l = events[ type ].length; i < l; i++ ) {
4930					jQuery.event.add( dest, type, events[ type ][ i ] );
4931				}
4932			}
4933		}
4934	}
4935
4936	// 2. Copy user data
4937	if ( data_user.hasData( src ) ) {
4938		udataOld = data_user.access( src );
4939		udataCur = jQuery.extend( {}, udataOld );
4940
4941		data_user.set( dest, udataCur );
4942	}
4943}
4944
4945function getAll( context, tag ) {
4946	var ret = context.getElementsByTagName ? context.getElementsByTagName( tag || "*" ) :
4947			context.querySelectorAll ? context.querySelectorAll( tag || "*" ) :
4948			[];
4949
4950	return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
4951		jQuery.merge( [ context ], ret ) :
4952		ret;
4953}
4954
4955// Support: IE >= 9
4956function fixInput( src, dest ) {
4957	var nodeName = dest.nodeName.toLowerCase();
4958
4959	// Fails to persist the checked state of a cloned checkbox or radio button.
4960	if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
4961		dest.checked = src.checked;
4962
4963	// Fails to return the selected option to the default selected state when cloning options
4964	} else if ( nodeName === "input" || nodeName === "textarea" ) {
4965		dest.defaultValue = src.defaultValue;
4966	}
4967}
4968
4969jQuery.extend({
4970	clone: function( elem, dataAndEvents, deepDataAndEvents ) {
4971		var i, l, srcElements, destElements,
4972			clone = elem.cloneNode( true ),
4973			inPage = jQuery.contains( elem.ownerDocument, elem );
4974
4975		// Support: IE >= 9
4976		// Fix Cloning issues
4977		if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&
4978				!jQuery.isXMLDoc( elem ) ) {
4979
4980			// We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
4981			destElements = getAll( clone );
4982			srcElements = getAll( elem );
4983
4984			for ( i = 0, l = srcElements.length; i < l; i++ ) {
4985				fixInput( srcElements[ i ], destElements[ i ] );
4986			}
4987		}
4988
4989		// Copy the events from the original to the clone
4990		if ( dataAndEvents ) {
4991			if ( deepDataAndEvents ) {
4992				srcElements = srcElements || getAll( elem );
4993				destElements = destElements || getAll( clone );
4994
4995				for ( i = 0, l = srcElements.length; i < l; i++ ) {
4996					cloneCopyEvent( srcElements[ i ], destElements[ i ] );
4997				}
4998			} else {
4999				cloneCopyEvent( elem, clone );
5000			}
5001		}
5002
5003		// Preserve script evaluation history
5004		destElements = getAll( clone, "script" );
5005		if ( destElements.length > 0 ) {
5006			setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
5007		}
5008
5009		// Return the cloned set
5010		return clone;
5011	},
5012
5013	buildFragment: function( elems, context, scripts, selection ) {
5014		var elem, tmp, tag, wrap, contains, j,
5015			fragment = context.createDocumentFragment(),
5016			nodes = [],
5017			i = 0,
5018			l = elems.length;
5019
5020		for ( ; i < l; i++ ) {
5021			elem = elems[ i ];
5022
5023			if ( elem || elem === 0 ) {
5024
5025				// Add nodes directly
5026				if ( jQuery.type( elem ) === "object" ) {
5027					// Support: QtWebKit
5028					// jQuery.merge because push.apply(_, arraylike) throws
5029					jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
5030
5031				// Convert non-html into a text node
5032				} else if ( !rhtml.test( elem ) ) {
5033					nodes.push( context.createTextNode( elem ) );
5034
5035				// Convert html into DOM nodes
5036				} else {
5037					tmp = tmp || fragment.appendChild( context.createElement("div") );
5038
5039					// Deserialize a standard representation
5040					tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase();
5041					wrap = wrapMap[ tag ] || wrapMap._default;
5042					tmp.innerHTML = wrap[ 1 ] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[ 2 ];
5043
5044					// Descend through wrappers to the right content
5045					j = wrap[ 0 ];
5046					while ( j-- ) {
5047						tmp = tmp.lastChild;
5048					}
5049
5050					// Support: QtWebKit
5051					// jQuery.merge because push.apply(_, arraylike) throws
5052					jQuery.merge( nodes, tmp.childNodes );
5053
5054					// Remember the top-level container
5055					tmp = fragment.firstChild;
5056
5057					// Fixes #12346
5058					// Support: Webkit, IE
5059					tmp.textContent = "";
5060				}
5061			}
5062		}
5063
5064		// Remove wrapper from fragment
5065		fragment.textContent = "";
5066
5067		i = 0;
5068		while ( (elem = nodes[ i++ ]) ) {
5069
5070			// #4087 - If origin and destination elements are the same, and this is
5071			// that element, do not do anything
5072			if ( selection && jQuery.inArray( elem, selection ) !== -1 ) {
5073				continue;
5074			}
5075
5076			contains = jQuery.contains( elem.ownerDocument, elem );
5077
5078			// Append to fragment
5079			tmp = getAll( fragment.appendChild( elem ), "script" );
5080
5081			// Preserve script evaluation history
5082			if ( contains ) {
5083				setGlobalEval( tmp );
5084			}
5085
5086			// Capture executables
5087			if ( scripts ) {
5088				j = 0;
5089				while ( (elem = tmp[ j++ ]) ) {
5090					if ( rscriptType.test( elem.type || "" ) ) {
5091						scripts.push( elem );
5092					}
5093				}
5094			}
5095		}
5096
5097		return fragment;
5098	},
5099
5100	cleanData: function( elems ) {
5101		var data, elem, events, type, key, j,
5102			special = jQuery.event.special,
5103			i = 0;
5104
5105		for ( ; (elem = elems[ i ]) !== undefined; i++ ) {
5106			if ( jQuery.acceptData( elem ) ) {
5107				key = elem[ data_priv.expando ];
5108
5109				if ( key && (data = data_priv.cache[ key ]) ) {
5110					events = Object.keys( data.events || {} );
5111					if ( events.length ) {
5112						for ( j = 0; (type = events[j]) !== undefined; j++ ) {
5113							if ( special[ type ] ) {
5114								jQuery.event.remove( elem, type );
5115
5116							// This is a shortcut to avoid jQuery.event.remove's overhead
5117							} else {
5118								jQuery.removeEvent( elem, type, data.handle );
5119							}
5120						}
5121					}
5122					if ( data_priv.cache[ key ] ) {
5123						// Discard any remaining `private` data
5124						delete data_priv.cache[ key ];
5125					}
5126				}
5127			}
5128			// Discard any remaining `user` data
5129			delete data_user.cache[ elem[ data_user.expando ] ];
5130		}
5131	}
5132});
5133
5134jQuery.fn.extend({
5135	text: function( value ) {
5136		return access( this, function( value ) {
5137			return value === undefined ?
5138				jQuery.text( this ) :
5139				this.empty().each(function() {
5140					if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
5141						this.textContent = value;
5142					}
5143				});
5144		}, null, value, arguments.length );
5145	},
5146
5147	append: function() {
5148		return this.domManip( arguments, function( elem ) {
5149			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
5150				var target = manipulationTarget( this, elem );
5151				target.appendChild( elem );
5152			}
5153		});
5154	},
5155
5156	prepend: function() {
5157		return this.domManip( arguments, function( elem ) {
5158			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
5159				var target = manipulationTarget( this, elem );
5160				target.insertBefore( elem, target.firstChild );
5161			}
5162		});
5163	},
5164
5165	before: function() {
5166		return this.domManip( arguments, function( elem ) {
5167			if ( this.parentNode ) {
5168				this.parentNode.insertBefore( elem, this );
5169			}
5170		});
5171	},
5172
5173	after: function() {
5174		return this.domManip( arguments, function( elem ) {
5175			if ( this.parentNode ) {
5176				this.parentNode.insertBefore( elem, this.nextSibling );
5177			}
5178		});
5179	},
5180
5181	remove: function( selector, keepData /* Internal Use Only */ ) {
5182		var elem,
5183			elems = selector ? jQuery.filter( selector, this ) : this,
5184			i = 0;
5185
5186		for ( ; (elem = elems[i]) != null; i++ ) {
5187			if ( !keepData && elem.nodeType === 1 ) {
5188				jQuery.cleanData( getAll( elem ) );
5189			}
5190
5191			if ( elem.parentNode ) {
5192				if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {
5193					setGlobalEval( getAll( elem, "script" ) );
5194				}
5195				elem.parentNode.removeChild( elem );
5196			}
5197		}
5198
5199		return this;
5200	},
5201
5202	empty: function() {
5203		var elem,
5204			i = 0;
5205
5206		for ( ; (elem = this[i]) != null; i++ ) {
5207			if ( elem.nodeType === 1 ) {
5208
5209				// Prevent memory leaks
5210				jQuery.cleanData( getAll( elem, false ) );
5211
5212				// Remove any remaining nodes
5213				elem.textContent = "";
5214			}
5215		}
5216
5217		return this;
5218	},
5219
5220	clone: function( dataAndEvents, deepDataAndEvents ) {
5221		dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
5222		deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
5223
5224		return this.map(function() {
5225			return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
5226		});
5227	},
5228
5229	html: function( value ) {
5230		return access( this, function( value ) {
5231			var elem = this[ 0 ] || {},
5232				i = 0,
5233				l = this.length;
5234
5235			if ( value === undefined && elem.nodeType === 1 ) {
5236				return elem.innerHTML;
5237			}
5238
5239			// See if we can take a shortcut and just use innerHTML
5240			if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
5241				!wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) {
5242
5243				value = value.replace( rxhtmlTag, "<$1></$2>" );
5244
5245				try {
5246					for ( ; i < l; i++ ) {
5247						elem = this[ i ] || {};
5248
5249						// Remove element nodes and prevent memory leaks
5250						if ( elem.nodeType === 1 ) {
5251							jQuery.cleanData( getAll( elem, false ) );
5252							elem.innerHTML = value;
5253						}
5254					}
5255
5256					elem = 0;
5257
5258				// If using innerHTML throws an exception, use the fallback method
5259				} catch( e ) {}
5260			}
5261
5262			if ( elem ) {
5263				this.empty().append( value );
5264			}
5265		}, null, value, arguments.length );
5266	},
5267
5268	replaceWith: function() {
5269		var arg = arguments[ 0 ];
5270
5271		// Make the changes, replacing each context element with the new content
5272		this.domManip( arguments, function( elem ) {
5273			arg = this.parentNode;
5274
5275			jQuery.cleanData( getAll( this ) );
5276
5277			if ( arg ) {
5278				arg.replaceChild( elem, this );
5279			}
5280		});
5281
5282		// Force removal if there was no new content (e.g., from empty arguments)
5283		return arg && (arg.length || arg.nodeType) ? this : this.remove();
5284	},
5285
5286	detach: function( selector ) {
5287		return this.remove( selector, true );
5288	},
5289
5290	domManip: function( args, callback ) {
5291
5292		// Flatten any nested arrays
5293		args = concat.apply( [], args );
5294
5295		var fragment, first, scripts, hasScripts, node, doc,
5296			i = 0,
5297			l = this.length,
5298			set = this,
5299			iNoClone = l - 1,
5300			value = args[ 0 ],
5301			isFunction = jQuery.isFunction( value );
5302
5303		// We can't cloneNode fragments that contain checked, in WebKit
5304		if ( isFunction ||
5305				( l > 1 && typeof value === "string" &&
5306					!support.checkClone && rchecked.test( value ) ) ) {
5307			return this.each(function( index ) {
5308				var self = set.eq( index );
5309				if ( isFunction ) {
5310					args[ 0 ] = value.call( this, index, self.html() );
5311				}
5312				self.domManip( args, callback );
5313			});
5314		}
5315
5316		if ( l ) {
5317			fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );
5318			first = fragment.firstChild;
5319
5320			if ( fragment.childNodes.length === 1 ) {
5321				fragment = first;
5322			}
5323
5324			if ( first ) {
5325				scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
5326				hasScripts = scripts.length;
5327
5328				// Use the original fragment for the last item instead of the first because it can end up
5329				// being emptied incorrectly in certain situations (#8070).
5330				for ( ; i < l; i++ ) {
5331					node = fragment;
5332
5333					if ( i !== iNoClone ) {
5334						node = jQuery.clone( node, true, true );
5335
5336						// Keep references to cloned scripts for later restoration
5337						if ( hasScripts ) {
5338							// Support: QtWebKit
5339							// jQuery.merge because push.apply(_, arraylike) throws
5340							jQuery.merge( scripts, getAll( node, "script" ) );
5341						}
5342					}
5343
5344					callback.call( this[ i ], node, i );
5345				}
5346
5347				if ( hasScripts ) {
5348					doc = scripts[ scripts.length - 1 ].ownerDocument;
5349
5350					// Reenable scripts
5351					jQuery.map( scripts, restoreScript );
5352
5353					// Evaluate executable scripts on first document insertion
5354					for ( i = 0; i < hasScripts; i++ ) {
5355						node = scripts[ i ];
5356						if ( rscriptType.test( node.type || "" ) &&
5357							!data_priv.access( node, "globalEval" ) && jQuery.contains( doc, node ) ) {
5358
5359							if ( node.src ) {
5360								// Optional AJAX dependency, but won't run scripts if not present
5361								if ( jQuery._evalUrl ) {
5362									jQuery._evalUrl( node.src );
5363								}
5364							} else {
5365								jQuery.globalEval( node.textContent.replace( rcleanScript, "" ) );
5366							}
5367						}
5368					}
5369				}
5370			}
5371		}
5372
5373		return this;
5374	}
5375});
5376
5377jQuery.each({
5378	appendTo: "append",
5379	prependTo: "prepend",
5380	insertBefore: "before",
5381	insertAfter: "after",
5382	replaceAll: "replaceWith"
5383}, function( name, original ) {
5384	jQuery.fn[ name ] = function( selector ) {
5385		var elems,
5386			ret = [],
5387			insert = jQuery( selector ),
5388			last = insert.length - 1,
5389			i = 0;
5390
5391		for ( ; i <= last; i++ ) {
5392			elems = i === last ? this : this.clone( true );
5393			jQuery( insert[ i ] )[ original ]( elems );
5394
5395			// Support: QtWebKit
5396			// .get() because push.apply(_, arraylike) throws
5397			push.apply( ret, elems.get() );
5398		}
5399
5400		return this.pushStack( ret );
5401	};
5402});
5403
5404
5405var iframe,
5406	elemdisplay = {};
5407
5408/**
5409 * Retrieve the actual display of a element
5410 * @param {String} name nodeName of the element
5411 * @param {Object} doc Document object
5412 */
5413// Called only from within defaultDisplay
5414function actualDisplay( name, doc ) {
5415	var elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),
5416
5417		// getDefaultComputedStyle might be reliably used only on attached element
5418		display = window.getDefaultComputedStyle ?
5419
5420			// Use of this method is a temporary fix (more like optmization) until something better comes along,
5421			// since it was removed from specification and supported only in FF
5422			window.getDefaultComputedStyle( elem[ 0 ] ).display : jQuery.css( elem[ 0 ], "display" );
5423
5424	// We don't have any data stored on the element,
5425	// so use "detach" method as fast way to get rid of the element
5426	elem.detach();
5427
5428	return display;
5429}
5430
5431/**
5432 * Try to determine the default display value of an element
5433 * @param {String} nodeName
5434 */
5435function defaultDisplay( nodeName ) {
5436	var doc = document,
5437		display = elemdisplay[ nodeName ];
5438
5439	if ( !display ) {
5440		display = actualDisplay( nodeName, doc );
5441
5442		// If the simple way fails, read from inside an iframe
5443		if ( display === "none" || !display ) {
5444
5445			// Use the already-created iframe if possible
5446			iframe = (iframe || jQuery( "<iframe frameborder='0' width='0' height='0'/>" )).appendTo( doc.documentElement );
5447
5448			// Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
5449			doc = iframe[ 0 ].contentDocument;
5450
5451			// Support: IE
5452			doc.write();
5453			doc.close();
5454
5455			display = actualDisplay( nodeName, doc );
5456			iframe.detach();
5457		}
5458
5459		// Store the correct default display
5460		elemdisplay[ nodeName ] = display;
5461	}
5462
5463	return display;
5464}
5465var rmargin = (/^margin/);
5466
5467var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
5468
5469var getStyles = function( elem ) {
5470		return elem.ownerDocument.defaultView.getComputedStyle( elem, null );
5471	};
5472
5473
5474
5475function curCSS( elem, name, computed ) {
5476	var width, minWidth, maxWidth, ret,
5477		style = elem.style;
5478
5479	computed = computed || getStyles( elem );
5480
5481	// Support: IE9
5482	// getPropertyValue is only needed for .css('filter') in IE9, see #12537
5483	if ( computed ) {
5484		ret = computed.getPropertyValue( name ) || computed[ name ];
5485	}
5486
5487	if ( computed ) {
5488
5489		if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
5490			ret = jQuery.style( elem, name );
5491		}
5492
5493		// Support: iOS < 6
5494		// A tribute to the "awesome hack by Dean Edwards"
5495		// iOS < 6 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
5496		// this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
5497		if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {
5498
5499			// Remember the original values
5500			width = style.width;
5501			minWidth = style.minWidth;
5502			maxWidth = style.maxWidth;
5503
5504			// Put in the new values to get a computed value out
5505			style.minWidth = style.maxWidth = style.width = ret;
5506			ret = computed.width;
5507
5508			// Revert the changed values
5509			style.width = width;
5510			style.minWidth = minWidth;
5511			style.maxWidth = maxWidth;
5512		}
5513	}
5514
5515	return ret !== undefined ?
5516		// Support: IE
5517		// IE returns zIndex value as an integer.
5518		ret + "" :
5519		ret;
5520}
5521
5522
5523function addGetHookIf( conditionFn, hookFn ) {
5524	// Define the hook, we'll check on the first run if it's really needed.
5525	return {
5526		get: function() {
5527			if ( conditionFn() ) {
5528				// Hook not needed (or it's not possible to use it due to missing dependency),
5529				// remove it.
5530				// Since there are no other hooks for marginRight, remove the whole object.
5531				delete this.get;
5532				return;
5533			}
5534
5535			// Hook needed; redefine it so that the support test is not executed again.
5536
5537			return (this.get = hookFn).apply( this, arguments );
5538		}
5539	};
5540}
5541
5542
5543(function() {
5544	var pixelPositionVal, boxSizingReliableVal,
5545		// Support: Firefox, Android 2.3 (Prefixed box-sizing versions).
5546		divReset = "padding:0;margin:0;border:0;display:block;-webkit-box-sizing:content-box;" +
5547			"-moz-box-sizing:content-box;box-sizing:content-box",
5548		docElem = document.documentElement,
5549		container = document.createElement( "div" ),
5550		div = document.createElement( "div" );
5551
5552	div.style.backgroundClip = "content-box";
5553	div.cloneNode( true ).style.backgroundClip = "";
5554	support.clearCloneStyle = div.style.backgroundClip === "content-box";
5555
5556	container.style.cssText = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px;" +
5557		"margin-top:1px";
5558	container.appendChild( div );
5559
5560	// Executing both pixelPosition & boxSizingReliable tests require only one layout
5561	// so they're executed at the same time to save the second computation.
5562	function computePixelPositionAndBoxSizingReliable() {
5563		// Support: Firefox, Android 2.3 (Prefixed box-sizing versions).
5564		div.style.cssText = "-webkit-box-sizing:border-box;-moz-box-sizing:border-box;" +
5565			"box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;" +
5566			"position:absolute;top:1%";
5567		docElem.appendChild( container );
5568
5569		var divStyle = window.getComputedStyle( div, null );
5570		pixelPositionVal = divStyle.top !== "1%";
5571		boxSizingReliableVal = divStyle.width === "4px";
5572
5573		docElem.removeChild( container );
5574	}
5575
5576	// Use window.getComputedStyle because jsdom on node.js will break without it.
5577	if ( window.getComputedStyle ) {
5578		jQuery.extend(support, {
5579			pixelPosition: function() {
5580				// This test is executed only once but we still do memoizing
5581				// since we can use the boxSizingReliable pre-computing.
5582				// No need to check if the test was already performed, though.
5583				computePixelPositionAndBoxSizingReliable();
5584				return pixelPositionVal;
5585			},
5586			boxSizingReliable: function() {
5587				if ( boxSizingReliableVal == null ) {
5588					computePixelPositionAndBoxSizingReliable();
5589				}
5590				return boxSizingReliableVal;
5591			},
5592			reliableMarginRight: function() {
5593				// Support: Android 2.3
5594				// Check if div with explicit width and no margin-right incorrectly
5595				// gets computed margin-right based on width of container. (#3333)
5596				// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
5597				// This support function is only executed once so no memoizing is needed.
5598				var ret,
5599					marginDiv = div.appendChild( document.createElement( "div" ) );
5600				marginDiv.style.cssText = div.style.cssText = divReset;
5601				marginDiv.style.marginRight = marginDiv.style.width = "0";
5602				div.style.width = "1px";
5603				docElem.appendChild( container );
5604
5605				ret = !parseFloat( window.getComputedStyle( marginDiv, null ).marginRight );
5606
5607				docElem.removeChild( container );
5608
5609				// Clean up the div for other support tests.
5610				div.innerHTML = "";
5611
5612				return ret;
5613			}
5614		});
5615	}
5616})();
5617
5618
5619// A method for quickly swapping in/out CSS properties to get correct calculations.
5620jQuery.swap = function( elem, options, callback, args ) {
5621	var ret, name,
5622		old = {};
5623
5624	// Remember the old values, and insert the new ones
5625	for ( name in options ) {
5626		old[ name ] = elem.style[ name ];
5627		elem.style[ name ] = options[ name ];
5628	}
5629
5630	ret = callback.apply( elem, args || [] );
5631
5632	// Revert the old values
5633	for ( name in options ) {
5634		elem.style[ name ] = old[ name ];
5635	}
5636
5637	return ret;
5638};
5639
5640
5641var
5642	// swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
5643	// see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
5644	rdisplayswap = /^(none|table(?!-c[ea]).+)/,
5645	rnumsplit = new RegExp( "^(" + pnum + ")(.*)$", "i" ),
5646	rrelNum = new RegExp( "^([+-])=(" + pnum + ")", "i" ),
5647
5648	cssShow = { position: "absolute", visibility: "hidden", display: "block" },
5649	cssNormalTransform = {
5650		letterSpacing: 0,
5651		fontWeight: 400
5652	},
5653
5654	cssPrefixes = [ "Webkit", "O", "Moz", "ms" ];
5655
5656// return a css property mapped to a potentially vendor prefixed property
5657function vendorPropName( style, name ) {
5658
5659	// shortcut for names that are not vendor prefixed
5660	if ( name in style ) {
5661		return name;
5662	}
5663
5664	// check for vendor prefixed names
5665	var capName = name[0].toUpperCase() + name.slice(1),
5666		origName = name,
5667		i = cssPrefixes.length;
5668
5669	while ( i-- ) {
5670		name = cssPrefixes[ i ] + capName;
5671		if ( name in style ) {
5672			return name;
5673		}
5674	}
5675
5676	return origName;
5677}
5678
5679function setPositiveNumber( elem, value, subtract ) {
5680	var matches = rnumsplit.exec( value );
5681	return matches ?
5682		// Guard against undefined "subtract", e.g., when used as in cssHooks
5683		Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :
5684		value;
5685}
5686
5687function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
5688	var i = extra === ( isBorderBox ? "border" : "content" ) ?
5689		// If we already have the right measurement, avoid augmentation
5690		4 :
5691		// Otherwise initialize for horizontal or vertical properties
5692		name === "width" ? 1 : 0,
5693
5694		val = 0;
5695
5696	for ( ; i < 4; i += 2 ) {
5697		// both box models exclude margin, so add it if we want it
5698		if ( extra === "margin" ) {
5699			val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
5700		}
5701
5702		if ( isBorderBox ) {
5703			// border-box includes padding, so remove it if we want content
5704			if ( extra === "content" ) {
5705				val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
5706			}
5707
5708			// at this point, extra isn't border nor margin, so remove border
5709			if ( extra !== "margin" ) {
5710				val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
5711			}
5712		} else {
5713			// at this point, extra isn't content, so add padding
5714			val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
5715
5716			// at this point, extra isn't content nor padding, so add border
5717			if ( extra !== "padding" ) {
5718				val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
5719			}
5720		}
5721	}
5722
5723	return val;
5724}
5725
5726function getWidthOrHeight( elem, name, extra ) {
5727
5728	// Start with offset property, which is equivalent to the border-box value
5729	var valueIsBorderBox = true,
5730		val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
5731		styles = getStyles( elem ),
5732		isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
5733
5734	// some non-html elements return undefined for offsetWidth, so check for null/undefined
5735	// svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
5736	// MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
5737	if ( val <= 0 || val == null ) {
5738		// Fall back to computed then uncomputed css if necessary
5739		val = curCSS( elem, name, styles );
5740		if ( val < 0 || val == null ) {
5741			val = elem.style[ name ];
5742		}
5743
5744		// Computed unit is not pixels. Stop here and return.
5745		if ( rnumnonpx.test(val) ) {
5746			return val;
5747		}
5748
5749		// we need the check for style in case a browser which returns unreliable values
5750		// for getComputedStyle silently falls back to the reliable elem.style
5751		valueIsBorderBox = isBorderBox &&
5752			( support.boxSizingReliable() || val === elem.style[ name ] );
5753
5754		// Normalize "", auto, and prepare for extra
5755		val = parseFloat( val ) || 0;
5756	}
5757
5758	// use the active box-sizing model to add/subtract irrelevant styles
5759	return ( val +
5760		augmentWidthOrHeight(
5761			elem,
5762			name,
5763			extra || ( isBorderBox ? "border" : "content" ),
5764			valueIsBorderBox,
5765			styles
5766		)
5767	) + "px";
5768}
5769
5770function showHide( elements, show ) {
5771	var display, elem, hidden,
5772		values = [],
5773		index = 0,
5774		length = elements.length;
5775
5776	for ( ; index < length; index++ ) {
5777		elem = elements[ index ];
5778		if ( !elem.style ) {
5779			continue;
5780		}
5781
5782		values[ index ] = data_priv.get( elem, "olddisplay" );
5783		display = elem.style.display;
5784		if ( show ) {
5785			// Reset the inline display of this element to learn if it is
5786			// being hidden by cascaded rules or not
5787			if ( !values[ index ] && display === "none" ) {
5788				elem.style.display = "";
5789			}
5790
5791			// Set elements which have been overridden with display: none
5792			// in a stylesheet to whatever the default browser style is
5793			// for such an element
5794			if ( elem.style.display === "" && isHidden( elem ) ) {
5795				values[ index ] = data_priv.access( elem, "olddisplay", defaultDisplay(elem.nodeName) );
5796			}
5797		} else {
5798
5799			if ( !values[ index ] ) {
5800				hidden = isHidden( elem );
5801
5802				if ( display && display !== "none" || !hidden ) {
5803					data_priv.set( elem, "olddisplay", hidden ? display : jQuery.css(elem, "display") );
5804				}
5805			}
5806		}
5807	}
5808
5809	// Set the display of most of the elements in a second loop
5810	// to avoid the constant reflow
5811	for ( index = 0; index < length; index++ ) {
5812		elem = elements[ index ];
5813		if ( !elem.style ) {
5814			continue;
5815		}
5816		if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
5817			elem.style.display = show ? values[ index ] || "" : "none";
5818		}
5819	}
5820
5821	return elements;
5822}
5823
5824jQuery.extend({
5825	// Add in style property hooks for overriding the default
5826	// behavior of getting and setting a style property
5827	cssHooks: {
5828		opacity: {
5829			get: function( elem, computed ) {
5830				if ( computed ) {
5831					// We should always get a number back from opacity
5832					var ret = curCSS( elem, "opacity" );
5833					return ret === "" ? "1" : ret;
5834				}
5835			}
5836		}
5837	},
5838
5839	// Don't automatically add "px" to these possibly-unitless properties
5840	cssNumber: {
5841		"columnCount": true,
5842		"fillOpacity": true,
5843		"fontWeight": true,
5844		"lineHeight": true,
5845		"opacity": true,
5846		"order": true,
5847		"orphans": true,
5848		"widows": true,
5849		"zIndex": true,
5850		"zoom": true
5851	},
5852
5853	// Add in properties whose names you wish to fix before
5854	// setting or getting the value
5855	cssProps: {
5856		// normalize float css property
5857		"float": "cssFloat"
5858	},
5859
5860	// Get and set the style property on a DOM Node
5861	style: function( elem, name, value, extra ) {
5862		// Don't set styles on text and comment nodes
5863		if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
5864			return;
5865		}
5866
5867		// Make sure that we're working with the right name
5868		var ret, type, hooks,
5869			origName = jQuery.camelCase( name ),
5870			style = elem.style;
5871
5872		name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );
5873
5874		// gets hook for the prefixed version
5875		// followed by the unprefixed version
5876		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
5877
5878		// Check if we're setting a value
5879		if ( value !== undefined ) {
5880			type = typeof value;
5881
5882			// convert relative number strings (+= or -=) to relative numbers. #7345
5883			if ( type === "string" && (ret = rrelNum.exec( value )) ) {
5884				value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );
5885				// Fixes bug #9237
5886				type = "number";
5887			}
5888
5889			// Make sure that null and NaN values aren't set. See: #7116
5890			if ( value == null || value !== value ) {
5891				return;
5892			}
5893
5894			// If a number was passed in, add 'px' to the (except for certain CSS properties)
5895			if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
5896				value += "px";
5897			}
5898
5899			// Fixes #8908, it can be done more correctly by specifying setters in cssHooks,
5900			// but it would mean to define eight (for every problematic property) identical functions
5901			if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) {
5902				style[ name ] = "inherit";
5903			}
5904
5905			// If a hook was provided, use that value, otherwise just set the specified value
5906			if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {
5907				// Support: Chrome, Safari
5908				// Setting style to blank string required to delete "style: x !important;"
5909				style[ name ] = "";
5910				style[ name ] = value;
5911			}
5912
5913		} else {
5914			// If a hook was provided get the non-computed value from there
5915			if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
5916				return ret;
5917			}
5918
5919			// Otherwise just get the value from the style object
5920			return style[ name ];
5921		}
5922	},
5923
5924	css: function( elem, name, extra, styles ) {
5925		var val, num, hooks,
5926			origName = jQuery.camelCase( name );
5927
5928		// Make sure that we're working with the right name
5929		name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
5930
5931		// gets hook for the prefixed version
5932		// followed by the unprefixed version
5933		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
5934
5935		// If a hook was provided get the computed value from there
5936		if ( hooks && "get" in hooks ) {
5937			val = hooks.get( elem, true, extra );
5938		}
5939
5940		// Otherwise, if a way to get the computed value exists, use that
5941		if ( val === undefined ) {
5942			val = curCSS( elem, name, styles );
5943		}
5944
5945		//convert "normal" to computed value
5946		if ( val === "normal" && name in cssNormalTransform ) {
5947			val = cssNormalTransform[ name ];
5948		}
5949
5950		// Return, converting to number if forced or a qualifier was provided and val looks numeric
5951		if ( extra === "" || extra ) {
5952			num = parseFloat( val );
5953			return extra === true || jQuery.isNumeric( num ) ? num || 0 : val;
5954		}
5955		return val;
5956	}
5957});
5958
5959jQuery.each([ "height", "width" ], function( i, name ) {
5960	jQuery.cssHooks[ name ] = {
5961		get: function( elem, computed, extra ) {
5962			if ( computed ) {
5963				// certain elements can have dimension info if we invisibly show them
5964				// however, it must have a current display style that would benefit from this
5965				return elem.offsetWidth === 0 && rdisplayswap.test( jQuery.css( elem, "display" ) ) ?
5966					jQuery.swap( elem, cssShow, function() {
5967						return getWidthOrHeight( elem, name, extra );
5968					}) :
5969					getWidthOrHeight( elem, name, extra );
5970			}
5971		},
5972
5973		set: function( elem, value, extra ) {
5974			var styles = extra && getStyles( elem );
5975			return setPositiveNumber( elem, value, extra ?
5976				augmentWidthOrHeight(
5977					elem,
5978					name,
5979					extra,
5980					jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
5981					styles
5982				) : 0
5983			);
5984		}
5985	};
5986});
5987
5988// Support: Android 2.3
5989jQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight,
5990	function( elem, computed ) {
5991		if ( computed ) {
5992			// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
5993			// Work around by temporarily setting element display to inline-block
5994			return jQuery.swap( elem, { "display": "inline-block" },
5995				curCSS, [ elem, "marginRight" ] );
5996		}
5997	}
5998);
5999
6000// These hooks are used by animate to expand properties
6001jQuery.each({
6002	margin: "",
6003	padding: "",
6004	border: "Width"
6005}, function( prefix, suffix ) {
6006	jQuery.cssHooks[ prefix + suffix ] = {
6007		expand: function( value ) {
6008			var i = 0,
6009				expanded = {},
6010
6011				// assumes a single number if not a string
6012				parts = typeof value === "string" ? value.split(" ") : [ value ];
6013
6014			for ( ; i < 4; i++ ) {
6015				expanded[ prefix + cssExpand[ i ] + suffix ] =
6016					parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
6017			}
6018
6019			return expanded;
6020		}
6021	};
6022
6023	if ( !rmargin.test( prefix ) ) {
6024		jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
6025	}
6026});
6027
6028jQuery.fn.extend({
6029	css: function( name, value ) {
6030		return access( this, function( elem, name, value ) {
6031			var styles, len,
6032				map = {},
6033				i = 0;
6034
6035			if ( jQuery.isArray( name ) ) {
6036				styles = getStyles( elem );
6037				len = name.length;
6038
6039				for ( ; i < len; i++ ) {
6040					map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
6041				}
6042
6043				return map;
6044			}
6045
6046			return value !== undefined ?
6047				jQuery.style( elem, name, value ) :
6048				jQuery.css( elem, name );
6049		}, name, value, arguments.length > 1 );
6050	},
6051	show: function() {
6052		return showHide( this, true );
6053	},
6054	hide: function() {
6055		return showHide( this );
6056	},
6057	toggle: function( state ) {
6058		if ( typeof state === "boolean" ) {
6059			return state ? this.show() : this.hide();
6060		}
6061
6062		return this.each(function() {
6063			if ( isHidden( this ) ) {
6064				jQuery( this ).show();
6065			} else {
6066				jQuery( this ).hide();
6067			}
6068		});
6069	}
6070});
6071
6072
6073function Tween( elem, options, prop, end, easing ) {
6074	return new Tween.prototype.init( elem, options, prop, end, easing );
6075}
6076jQuery.Tween = Tween;
6077
6078Tween.prototype = {
6079	constructor: Tween,
6080	init: function( elem, options, prop, end, easing, unit ) {
6081		this.elem = elem;
6082		this.prop = prop;
6083		this.easing = easing || "swing";
6084		this.options = options;
6085		this.start = this.now = this.cur();
6086		this.end = end;
6087		this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
6088	},
6089	cur: function() {
6090		var hooks = Tween.propHooks[ this.prop ];
6091
6092		return hooks && hooks.get ?
6093			hooks.get( this ) :
6094			Tween.propHooks._default.get( this );
6095	},
6096	run: function( percent ) {
6097		var eased,
6098			hooks = Tween.propHooks[ this.prop ];
6099
6100		if ( this.options.duration ) {
6101			this.pos = eased = jQuery.easing[ this.easing ](
6102				percent, this.options.duration * percent, 0, 1, this.options.duration
6103			);
6104		} else {
6105			this.pos = eased = percent;
6106		}
6107		this.now = ( this.end - this.start ) * eased + this.start;
6108
6109		if ( this.options.step ) {
6110			this.options.step.call( this.elem, this.now, this );
6111		}
6112
6113		if ( hooks && hooks.set ) {
6114			hooks.set( this );
6115		} else {
6116			Tween.propHooks._default.set( this );
6117		}
6118		return this;
6119	}
6120};
6121
6122Tween.prototype.init.prototype = Tween.prototype;
6123
6124Tween.propHooks = {
6125	_default: {
6126		get: function( tween ) {
6127			var result;
6128
6129			if ( tween.elem[ tween.prop ] != null &&
6130				(!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
6131				return tween.elem[ tween.prop ];
6132			}
6133
6134			// passing an empty string as a 3rd parameter to .css will automatically
6135			// attempt a parseFloat and fallback to a string if the parse fails
6136			// so, simple values such as "10px" are parsed to Float.
6137			// complex values such as "rotate(1rad)" are returned as is.
6138			result = jQuery.css( tween.elem, tween.prop, "" );
6139			// Empty strings, null, undefined and "auto" are converted to 0.
6140			return !result || result === "auto" ? 0 : result;
6141		},
6142		set: function( tween ) {
6143			// use step hook for back compat - use cssHook if its there - use .style if its
6144			// available and use plain properties where available
6145			if ( jQuery.fx.step[ tween.prop ] ) {
6146				jQuery.fx.step[ tween.prop ]( tween );
6147			} else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
6148				jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
6149			} else {
6150				tween.elem[ tween.prop ] = tween.now;
6151			}
6152		}
6153	}
6154};
6155
6156// Support: IE9
6157// Panic based approach to setting things on disconnected nodes
6158
6159Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
6160	set: function( tween ) {
6161		if ( tween.elem.nodeType && tween.elem.parentNode ) {
6162			tween.elem[ tween.prop ] = tween.now;
6163		}
6164	}
6165};
6166
6167jQuery.easing = {
6168	linear: function( p ) {
6169		return p;
6170	},
6171	swing: function( p ) {
6172		return 0.5 - Math.cos( p * Math.PI ) / 2;
6173	}
6174};
6175
6176jQuery.fx = Tween.prototype.init;
6177
6178// Back Compat <1.8 extension point
6179jQuery.fx.step = {};
6180
6181
6182
6183
6184var
6185	fxNow, timerId,
6186	rfxtypes = /^(?:toggle|show|hide)$/,
6187	rfxnum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ),
6188	rrun = /queueHooks$/,
6189	animationPrefilters = [ defaultPrefilter ],
6190	tweeners = {
6191		"*": [ function( prop, value ) {
6192			var tween = this.createTween( prop, value ),
6193				target = tween.cur(),
6194				parts = rfxnum.exec( value ),
6195				unit = parts && parts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
6196
6197				// Starting value computation is required for potential unit mismatches
6198				start = ( jQuery.cssNumber[ prop ] || unit !== "px" && +target ) &&
6199					rfxnum.exec( jQuery.css( tween.elem, prop ) ),
6200				scale = 1,
6201				maxIterations = 20;
6202
6203			if ( start && start[ 3 ] !== unit ) {
6204				// Trust units reported by jQuery.css
6205				unit = unit || start[ 3 ];
6206
6207				// Make sure we update the tween properties later on
6208				parts = parts || [];
6209
6210				// Iteratively approximate from a nonzero starting point
6211				start = +target || 1;
6212
6213				do {
6214					// If previous iteration zeroed out, double until we get *something*
6215					// Use a string for doubling factor so we don't accidentally see scale as unchanged below
6216					scale = scale || ".5";
6217
6218					// Adjust and apply
6219					start = start / scale;
6220					jQuery.style( tween.elem, prop, start + unit );
6221
6222				// Update scale, tolerating zero or NaN from tween.cur()
6223				// And breaking the loop if scale is unchanged or perfect, or if we've just had enough
6224				} while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
6225			}
6226
6227			// Update tween properties
6228			if ( parts ) {
6229				start = tween.start = +start || +target || 0;
6230				tween.unit = unit;
6231				// If a +=/-= token was provided, we're doing a relative animation
6232				tween.end = parts[ 1 ] ?
6233					start + ( parts[ 1 ] + 1 ) * parts[ 2 ] :
6234					+parts[ 2 ];
6235			}
6236
6237			return tween;
6238		} ]
6239	};
6240
6241// Animations created synchronously will run synchronously
6242function createFxNow() {
6243	setTimeout(function() {
6244		fxNow = undefined;
6245	});
6246	return ( fxNow = jQuery.now() );
6247}
6248
6249// Generate parameters to create a standard animation
6250function genFx( type, includeWidth ) {
6251	var which,
6252		i = 0,
6253		attrs = { height: type };
6254
6255	// if we include width, step value is 1 to do all cssExpand values,
6256	// if we don't include width, step value is 2 to skip over Left and Right
6257	includeWidth = includeWidth ? 1 : 0;
6258	for ( ; i < 4 ; i += 2 - includeWidth ) {
6259		which = cssExpand[ i ];
6260		attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
6261	}
6262
6263	if ( includeWidth ) {
6264		attrs.opacity = attrs.width = type;
6265	}
6266
6267	return attrs;
6268}
6269
6270function createTween( value, prop, animation ) {
6271	var tween,
6272		collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
6273		index = 0,
6274		length = collection.length;
6275	for ( ; index < length; index++ ) {
6276		if ( (tween = collection[ index ].call( animation, prop, value )) ) {
6277
6278			// we're done with this property
6279			return tween;
6280		}
6281	}
6282}
6283
6284function defaultPrefilter( elem, props, opts ) {
6285	/* jshint validthis: true */
6286	var prop, value, toggle, tween, hooks, oldfire, display,
6287		anim = this,
6288		orig = {},
6289		style = elem.style,
6290		hidden = elem.nodeType && isHidden( elem ),
6291		dataShow = data_priv.get( elem, "fxshow" );
6292
6293	// handle queue: false promises
6294	if ( !opts.queue ) {
6295		hooks = jQuery._queueHooks( elem, "fx" );
6296		if ( hooks.unqueued == null ) {
6297			hooks.unqueued = 0;
6298			oldfire = hooks.empty.fire;
6299			hooks.empty.fire = function() {
6300				if ( !hooks.unqueued ) {
6301					oldfire();
6302				}
6303			};
6304		}
6305		hooks.unqueued++;
6306
6307		anim.always(function() {
6308			// doing this makes sure that the complete handler will be called
6309			// before this completes
6310			anim.always(function() {
6311				hooks.unqueued--;
6312				if ( !jQuery.queue( elem, "fx" ).length ) {
6313					hooks.empty.fire();
6314				}
6315			});
6316		});
6317	}
6318
6319	// height/width overflow pass
6320	if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
6321		// Make sure that nothing sneaks out
6322		// Record all 3 overflow attributes because IE9-10 do not
6323		// change the overflow attribute when overflowX and
6324		// overflowY are set to the same value
6325		opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
6326
6327		// Set display property to inline-block for height/width
6328		// animations on inline elements that are having width/height animated
6329		display = jQuery.css( elem, "display" );
6330		// Get default display if display is currently "none"
6331		if ( display === "none" ) {
6332			display = defaultDisplay( elem.nodeName );
6333		}
6334		if ( display === "inline" &&
6335				jQuery.css( elem, "float" ) === "none" ) {
6336
6337			style.display = "inline-block";
6338		}
6339	}
6340
6341	if ( opts.overflow ) {
6342		style.overflow = "hidden";
6343		anim.always(function() {
6344			style.overflow = opts.overflow[ 0 ];
6345			style.overflowX = opts.overflow[ 1 ];
6346			style.overflowY = opts.overflow[ 2 ];
6347		});
6348	}
6349
6350	// show/hide pass
6351	for ( prop in props ) {
6352		value = props[ prop ];
6353		if ( rfxtypes.exec( value ) ) {
6354			delete props[ prop ];
6355			toggle = toggle || value === "toggle";
6356			if ( value === ( hidden ? "hide" : "show" ) ) {
6357
6358				// If there is dataShow left over from a stopped hide or show and we are going to proceed with show, we should pretend to be hidden
6359				if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
6360					hidden = true;
6361				} else {
6362					continue;
6363				}
6364			}
6365			orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
6366		}
6367	}
6368
6369	if ( !jQuery.isEmptyObject( orig ) ) {
6370		if ( dataShow ) {
6371			if ( "hidden" in dataShow ) {
6372				hidden = dataShow.hidden;
6373			}
6374		} else {
6375			dataShow = data_priv.access( elem, "fxshow", {} );
6376		}
6377
6378		// store state if its toggle - enables .stop().toggle() to "reverse"
6379		if ( toggle ) {
6380			dataShow.hidden = !hidden;
6381		}
6382		if ( hidden ) {
6383			jQuery( elem ).show();
6384		} else {
6385			anim.done(function() {
6386				jQuery( elem ).hide();
6387			});
6388		}
6389		anim.done(function() {
6390			var prop;
6391
6392			data_priv.remove( elem, "fxshow" );
6393			for ( prop in orig ) {
6394				jQuery.style( elem, prop, orig[ prop ] );
6395			}
6396		});
6397		for ( prop in orig ) {
6398			tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
6399
6400			if ( !( prop in dataShow ) ) {
6401				dataShow[ prop ] = tween.start;
6402				if ( hidden ) {
6403					tween.end = tween.start;
6404					tween.start = prop === "width" || prop === "height" ? 1 : 0;
6405				}
6406			}
6407		}
6408	}
6409}
6410
6411function propFilter( props, specialEasing ) {
6412	var index, name, easing, value, hooks;
6413
6414	// camelCase, specialEasing and expand cssHook pass
6415	for ( index in props ) {
6416		name = jQuery.camelCase( index );
6417		easing = specialEasing[ name ];
6418		value = props[ index ];
6419		if ( jQuery.isArray( value ) ) {
6420			easing = value[ 1 ];
6421			value = props[ index ] = value[ 0 ];
6422		}
6423
6424		if ( index !== name ) {
6425			props[ name ] = value;
6426			delete props[ index ];
6427		}
6428
6429		hooks = jQuery.cssHooks[ name ];
6430		if ( hooks && "expand" in hooks ) {
6431			value = hooks.expand( value );
6432			delete props[ name ];
6433
6434			// not quite $.extend, this wont overwrite keys already present.
6435			// also - reusing 'index' from above because we have the correct "name"
6436			for ( index in value ) {
6437				if ( !( index in props ) ) {
6438					props[ index ] = value[ index ];
6439					specialEasing[ index ] = easing;
6440				}
6441			}
6442		} else {
6443			specialEasing[ name ] = easing;
6444		}
6445	}
6446}
6447
6448function Animation( elem, properties, options ) {
6449	var result,
6450		stopped,
6451		index = 0,
6452		length = animationPrefilters.length,
6453		deferred = jQuery.Deferred().always( function() {
6454			// don't match elem in the :animated selector
6455			delete tick.elem;
6456		}),
6457		tick = function() {
6458			if ( stopped ) {
6459				return false;
6460			}
6461			var currentTime = fxNow || createFxNow(),
6462				remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
6463				// archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)
6464				temp = remaining / animation.duration || 0,
6465				percent = 1 - temp,
6466				index = 0,
6467				length = animation.tweens.length;
6468
6469			for ( ; index < length ; index++ ) {
6470				animation.tweens[ index ].run( percent );
6471			}
6472
6473			deferred.notifyWith( elem, [ animation, percent, remaining ]);
6474
6475			if ( percent < 1 && length ) {
6476				return remaining;
6477			} else {
6478				deferred.resolveWith( elem, [ animation ] );
6479				return false;
6480			}
6481		},
6482		animation = deferred.promise({
6483			elem: elem,
6484			props: jQuery.extend( {}, properties ),
6485			opts: jQuery.extend( true, { specialEasing: {} }, options ),
6486			originalProperties: properties,
6487			originalOptions: options,
6488			startTime: fxNow || createFxNow(),
6489			duration: options.duration,
6490			tweens: [],
6491			createTween: function( prop, end ) {
6492				var tween = jQuery.Tween( elem, animation.opts, prop, end,
6493						animation.opts.specialEasing[ prop ] || animation.opts.easing );
6494				animation.tweens.push( tween );
6495				return tween;
6496			},
6497			stop: function( gotoEnd ) {
6498				var index = 0,
6499					// if we are going to the end, we want to run all the tweens
6500					// otherwise we skip this part
6501					length = gotoEnd ? animation.tweens.length : 0;
6502				if ( stopped ) {
6503					return this;
6504				}
6505				stopped = true;
6506				for ( ; index < length ; index++ ) {
6507					animation.tweens[ index ].run( 1 );
6508				}
6509
6510				// resolve when we played the last frame
6511				// otherwise, reject
6512				if ( gotoEnd ) {
6513					deferred.resolveWith( elem, [ animation, gotoEnd ] );
6514				} else {
6515					deferred.rejectWith( elem, [ animation, gotoEnd ] );
6516				}
6517				return this;
6518			}
6519		}),
6520		props = animation.props;
6521
6522	propFilter( props, animation.opts.specialEasing );
6523
6524	for ( ; index < length ; index++ ) {
6525		result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
6526		if ( result ) {
6527			return result;
6528		}
6529	}
6530
6531	jQuery.map( props, createTween, animation );
6532
6533	if ( jQuery.isFunction( animation.opts.start ) ) {
6534		animation.opts.start.call( elem, animation );
6535	}
6536
6537	jQuery.fx.timer(
6538		jQuery.extend( tick, {
6539			elem: elem,
6540			anim: animation,
6541			queue: animation.opts.queue
6542		})
6543	);
6544
6545	// attach callbacks from options
6546	return animation.progress( animation.opts.progress )
6547		.done( animation.opts.done, animation.opts.complete )
6548		.fail( animation.opts.fail )
6549		.always( animation.opts.always );
6550}
6551
6552jQuery.Animation = jQuery.extend( Animation, {
6553
6554	tweener: function( props, callback ) {
6555		if ( jQuery.isFunction( props ) ) {
6556			callback = props;
6557			props = [ "*" ];
6558		} else {
6559			props = props.split(" ");
6560		}
6561
6562		var prop,
6563			index = 0,
6564			length = props.length;
6565
6566		for ( ; index < length ; index++ ) {
6567			prop = props[ index ];
6568			tweeners[ prop ] = tweeners[ prop ] || [];
6569			tweeners[ prop ].unshift( callback );
6570		}
6571	},
6572
6573	prefilter: function( callback, prepend ) {
6574		if ( prepend ) {
6575			animationPrefilters.unshift( callback );
6576		} else {
6577			animationPrefilters.push( callback );
6578		}
6579	}
6580});
6581
6582jQuery.speed = function( speed, easing, fn ) {
6583	var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
6584		complete: fn || !fn && easing ||
6585			jQuery.isFunction( speed ) && speed,
6586		duration: speed,
6587		easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
6588	};
6589
6590	opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
6591		opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
6592
6593	// normalize opt.queue - true/undefined/null -> "fx"
6594	if ( opt.queue == null || opt.queue === true ) {
6595		opt.queue = "fx";
6596	}
6597
6598	// Queueing
6599	opt.old = opt.complete;
6600
6601	opt.complete = function() {
6602		if ( jQuery.isFunction( opt.old ) ) {
6603			opt.old.call( this );
6604		}
6605
6606		if ( opt.queue ) {
6607			jQuery.dequeue( this, opt.queue );
6608		}
6609	};
6610
6611	return opt;
6612};
6613
6614jQuery.fn.extend({
6615	fadeTo: function( speed, to, easing, callback ) {
6616
6617		// show any hidden elements after setting opacity to 0
6618		return this.filter( isHidden ).css( "opacity", 0 ).show()
6619
6620			// animate to the value specified
6621			.end().animate({ opacity: to }, speed, easing, callback );
6622	},
6623	animate: function( prop, speed, easing, callback ) {
6624		var empty = jQuery.isEmptyObject( prop ),
6625			optall = jQuery.speed( speed, easing, callback ),
6626			doAnimation = function() {
6627				// Operate on a copy of prop so per-property easing won't be lost
6628				var anim = Animation( this, jQuery.extend( {}, prop ), optall );
6629
6630				// Empty animations, or finishing resolves immediately
6631				if ( empty || data_priv.get( this, "finish" ) ) {
6632					anim.stop( true );
6633				}
6634			};
6635			doAnimation.finish = doAnimation;
6636
6637		return empty || optall.queue === false ?
6638			this.each( doAnimation ) :
6639			this.queue( optall.queue, doAnimation );
6640	},
6641	stop: function( type, clearQueue, gotoEnd ) {
6642		var stopQueue = function( hooks ) {
6643			var stop = hooks.stop;
6644			delete hooks.stop;
6645			stop( gotoEnd );
6646		};
6647
6648		if ( typeof type !== "string" ) {
6649			gotoEnd = clearQueue;
6650			clearQueue = type;
6651			type = undefined;
6652		}
6653		if ( clearQueue && type !== false ) {
6654			this.queue( type || "fx", [] );
6655		}
6656
6657		return this.each(function() {
6658			var dequeue = true,
6659				index = type != null && type + "queueHooks",
6660				timers = jQuery.timers,
6661				data = data_priv.get( this );
6662
6663			if ( index ) {
6664				if ( data[ index ] && data[ index ].stop ) {
6665					stopQueue( data[ index ] );
6666				}
6667			} else {
6668				for ( index in data ) {
6669					if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
6670						stopQueue( data[ index ] );
6671					}
6672				}
6673			}
6674
6675			for ( index = timers.length; index--; ) {
6676				if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
6677					timers[ index ].anim.stop( gotoEnd );
6678					dequeue = false;
6679					timers.splice( index, 1 );
6680				}
6681			}
6682
6683			// start the next in the queue if the last step wasn't forced
6684			// timers currently will call their complete callbacks, which will dequeue
6685			// but only if they were gotoEnd
6686			if ( dequeue || !gotoEnd ) {
6687				jQuery.dequeue( this, type );
6688			}
6689		});
6690	},
6691	finish: function( type ) {
6692		if ( type !== false ) {
6693			type = type || "fx";
6694		}
6695		return this.each(function() {
6696			var index,
6697				data = data_priv.get( this ),
6698				queue = data[ type + "queue" ],
6699				hooks = data[ type + "queueHooks" ],
6700				timers = jQuery.timers,
6701				length = queue ? queue.length : 0;
6702
6703			// enable finishing flag on private data
6704			data.finish = true;
6705
6706			// empty the queue first
6707			jQuery.queue( this, type, [] );
6708
6709			if ( hooks && hooks.stop ) {
6710				hooks.stop.call( this, true );
6711			}
6712
6713			// look for any active animations, and finish them
6714			for ( index = timers.length; index--; ) {
6715				if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
6716					timers[ index ].anim.stop( true );
6717					timers.splice( index, 1 );
6718				}
6719			}
6720
6721			// look for any animations in the old queue and finish them
6722			for ( index = 0; index < length; index++ ) {
6723				if ( queue[ index ] && queue[ index ].finish ) {
6724					queue[ index ].finish.call( this );
6725				}
6726			}
6727
6728			// turn off finishing flag
6729			delete data.finish;
6730		});
6731	}
6732});
6733
6734jQuery.each([ "toggle", "show", "hide" ], function( i, name ) {
6735	var cssFn = jQuery.fn[ name ];
6736	jQuery.fn[ name ] = function( speed, easing, callback ) {
6737		return speed == null || typeof speed === "boolean" ?
6738			cssFn.apply( this, arguments ) :
6739			this.animate( genFx( name, true ), speed, easing, callback );
6740	};
6741});
6742
6743// Generate shortcuts for custom animations
6744jQuery.each({
6745	slideDown: genFx("show"),
6746	slideUp: genFx("hide"),
6747	slideToggle: genFx("toggle"),
6748	fadeIn: { opacity: "show" },
6749	fadeOut: { opacity: "hide" },
6750	fadeToggle: { opacity: "toggle" }
6751}, function( name, props ) {
6752	jQuery.fn[ name ] = function( speed, easing, callback ) {
6753		return this.animate( props, speed, easing, callback );
6754	};
6755});
6756
6757jQuery.timers = [];
6758jQuery.fx.tick = function() {
6759	var timer,
6760		i = 0,
6761		timers = jQuery.timers;
6762
6763	fxNow = jQuery.now();
6764
6765	for ( ; i < timers.length; i++ ) {
6766		timer = timers[ i ];
6767		// Checks the timer has not already been removed
6768		if ( !timer() && timers[ i ] === timer ) {
6769			timers.splice( i--, 1 );
6770		}
6771	}
6772
6773	if ( !timers.length ) {
6774		jQuery.fx.stop();
6775	}
6776	fxNow = undefined;
6777};
6778
6779jQuery.fx.timer = function( timer ) {
6780	jQuery.timers.push( timer );
6781	if ( timer() ) {
6782		jQuery.fx.start();
6783	} else {
6784		jQuery.timers.pop();
6785	}
6786};
6787
6788jQuery.fx.interval = 13;
6789
6790jQuery.fx.start = function() {
6791	if ( !timerId ) {
6792		timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );
6793	}
6794};
6795
6796jQuery.fx.stop = function() {
6797	clearInterval( timerId );
6798	timerId = null;
6799};
6800
6801jQuery.fx.speeds = {
6802	slow: 600,
6803	fast: 200,
6804	// Default speed
6805	_default: 400
6806};
6807
6808
6809// Based off of the plugin by Clint Helfers, with permission.
6810// http://blindsignals.com/index.php/2009/07/jquery-delay/
6811jQuery.fn.delay = function( time, type ) {
6812	time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
6813	type = type || "fx";
6814
6815	return this.queue( type, function( next, hooks ) {
6816		var timeout = setTimeout( next, time );
6817		hooks.stop = function() {
6818			clearTimeout( timeout );
6819		};
6820	});
6821};
6822
6823
6824(function() {
6825	var input = document.createElement( "input" ),
6826		select = document.createElement( "select" ),
6827		opt = select.appendChild( document.createElement( "option" ) );
6828
6829	input.type = "checkbox";
6830
6831	// Support: iOS 5.1, Android 4.x, Android 2.3
6832	// Check the default checkbox/radio value ("" on old WebKit; "on" elsewhere)
6833	support.checkOn = input.value !== "";
6834
6835	// Must access the parent to make an option select properly
6836	// Support: IE9, IE10
6837	support.optSelected = opt.selected;
6838
6839	// Make sure that the options inside disabled selects aren't marked as disabled
6840	// (WebKit marks them as disabled)
6841	select.disabled = true;
6842	support.optDisabled = !opt.disabled;
6843
6844	// Check if an input maintains its value after becoming a radio
6845	// Support: IE9, IE10
6846	input = document.createElement( "input" );
6847	input.value = "t";
6848	input.type = "radio";
6849	support.radioValue = input.value === "t";
6850})();
6851
6852
6853var nodeHook, boolHook,
6854	attrHandle = jQuery.expr.attrHandle;
6855
6856jQuery.fn.extend({
6857	attr: function( name, value ) {
6858		return access( this, jQuery.attr, name, value, arguments.length > 1 );
6859	},
6860
6861	removeAttr: function( name ) {
6862		return this.each(function() {
6863			jQuery.removeAttr( this, name );
6864		});
6865	}
6866});
6867
6868jQuery.extend({
6869	attr: function( elem, name, value ) {
6870		var hooks, ret,
6871			nType = elem.nodeType;
6872
6873		// don't get/set attributes on text, comment and attribute nodes
6874		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
6875			return;
6876		}
6877
6878		// Fallback to prop when attributes are not supported
6879		if ( typeof elem.getAttribute === strundefined ) {
6880			return jQuery.prop( elem, name, value );
6881		}
6882
6883		// All attributes are lowercase
6884		// Grab necessary hook if one is defined
6885		if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
6886			name = name.toLowerCase();
6887			hooks = jQuery.attrHooks[ name ] ||
6888				( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook );
6889		}
6890
6891		if ( value !== undefined ) {
6892
6893			if ( value === null ) {
6894				jQuery.removeAttr( elem, name );
6895
6896			} else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
6897				return ret;
6898
6899			} else {
6900				elem.setAttribute( name, value + "" );
6901				return value;
6902			}
6903
6904		} else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
6905			return ret;
6906
6907		} else {
6908			ret = jQuery.find.attr( elem, name );
6909
6910			// Non-existent attributes return null, we normalize to undefined
6911			return ret == null ?
6912				undefined :
6913				ret;
6914		}
6915	},
6916
6917	removeAttr: function( elem, value ) {
6918		var name, propName,
6919			i = 0,
6920			attrNames = value && value.match( rnotwhite );
6921
6922		if ( attrNames && elem.nodeType === 1 ) {
6923			while ( (name = attrNames[i++]) ) {
6924				propName = jQuery.propFix[ name ] || name;
6925
6926				// Boolean attributes get special treatment (#10870)
6927				if ( jQuery.expr.match.bool.test( name ) ) {
6928					// Set corresponding property to false
6929					elem[ propName ] = false;
6930				}
6931
6932				elem.removeAttribute( name );
6933			}
6934		}
6935	},
6936
6937	attrHooks: {
6938		type: {
6939			set: function( elem, value ) {
6940				if ( !support.radioValue && value === "radio" &&
6941					jQuery.nodeName( elem, "input" ) ) {
6942					// Setting the type on a radio button after the value resets the value in IE6-9
6943					// Reset value to default in case type is set after value during creation
6944					var val = elem.value;
6945					elem.setAttribute( "type", value );
6946					if ( val ) {
6947						elem.value = val;
6948					}
6949					return value;
6950				}
6951			}
6952		}
6953	}
6954});
6955
6956// Hooks for boolean attributes
6957boolHook = {
6958	set: function( elem, value, name ) {
6959		if ( value === false ) {
6960			// Remove boolean attributes when set to false
6961			jQuery.removeAttr( elem, name );
6962		} else {
6963			elem.setAttribute( name, name );
6964		}
6965		return name;
6966	}
6967};
6968jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) {
6969	var getter = attrHandle[ name ] || jQuery.find.attr;
6970
6971	attrHandle[ name ] = function( elem, name, isXML ) {
6972		var ret, handle;
6973		if ( !isXML ) {
6974			// Avoid an infinite loop by temporarily removing this function from the getter
6975			handle = attrHandle[ name ];
6976			attrHandle[ name ] = ret;
6977			ret = getter( elem, name, isXML ) != null ?
6978				name.toLowerCase() :
6979				null;
6980			attrHandle[ name ] = handle;
6981		}
6982		return ret;
6983	};
6984});
6985
6986
6987
6988
6989var rfocusable = /^(?:input|select|textarea|button)$/i;
6990
6991jQuery.fn.extend({
6992	prop: function( name, value ) {
6993		return access( this, jQuery.prop, name, value, arguments.length > 1 );
6994	},
6995
6996	removeProp: function( name ) {
6997		return this.each(function() {
6998			delete this[ jQuery.propFix[ name ] || name ];
6999		});
7000	}
7001});
7002
7003jQuery.extend({
7004	propFix: {
7005		"for": "htmlFor",
7006		"class": "className"
7007	},
7008
7009	prop: function( elem, name, value ) {
7010		var ret, hooks, notxml,
7011			nType = elem.nodeType;
7012
7013		// don't get/set properties on text, comment and attribute nodes
7014		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
7015			return;
7016		}
7017
7018		notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
7019
7020		if ( notxml ) {
7021			// Fix name and attach hooks
7022			name = jQuery.propFix[ name ] || name;
7023			hooks = jQuery.propHooks[ name ];
7024		}
7025
7026		if ( value !== undefined ) {
7027			return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ?
7028				ret :
7029				( elem[ name ] = value );
7030
7031		} else {
7032			return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ?
7033				ret :
7034				elem[ name ];
7035		}
7036	},
7037
7038	propHooks: {
7039		tabIndex: {
7040			get: function( elem ) {
7041				return elem.hasAttribute( "tabindex" ) || rfocusable.test( elem.nodeName ) || elem.href ?
7042					elem.tabIndex :
7043					-1;
7044			}
7045		}
7046	}
7047});
7048
7049// Support: IE9+
7050// Selectedness for an option in an optgroup can be inaccurate
7051if ( !support.optSelected ) {
7052	jQuery.propHooks.selected = {
7053		get: function( elem ) {
7054			var parent = elem.parentNode;
7055			if ( parent && parent.parentNode ) {
7056				parent.parentNode.selectedIndex;
7057			}
7058			return null;
7059		}
7060	};
7061}
7062
7063jQuery.each([
7064	"tabIndex",
7065	"readOnly",
7066	"maxLength",
7067	"cellSpacing",
7068	"cellPadding",
7069	"rowSpan",
7070	"colSpan",
7071	"useMap",
7072	"frameBorder",
7073	"contentEditable"
7074], function() {
7075	jQuery.propFix[ this.toLowerCase() ] = this;
7076});
7077
7078
7079
7080
7081var rclass = /[\t\r\n\f]/g;
7082
7083jQuery.fn.extend({
7084	addClass: function( value ) {
7085		var classes, elem, cur, clazz, j, finalValue,
7086			proceed = typeof value === "string" && value,
7087			i = 0,
7088			len = this.length;
7089
7090		if ( jQuery.isFunction( value ) ) {
7091			return this.each(function( j ) {
7092				jQuery( this ).addClass( value.call( this, j, this.className ) );
7093			});
7094		}
7095
7096		if ( proceed ) {
7097			// The disjunction here is for better compressibility (see removeClass)
7098			classes = ( value || "" ).match( rnotwhite ) || [];
7099
7100			for ( ; i < len; i++ ) {
7101				elem = this[ i ];
7102				cur = elem.nodeType === 1 && ( elem.className ?
7103					( " " + elem.className + " " ).replace( rclass, " " ) :
7104					" "
7105				);
7106
7107				if ( cur ) {
7108					j = 0;
7109					while ( (clazz = classes[j++]) ) {
7110						if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
7111							cur += clazz + " ";
7112						}
7113					}
7114
7115					// only assign if different to avoid unneeded rendering.
7116					finalValue = jQuery.trim( cur );
7117					if ( elem.className !== finalValue ) {
7118						elem.className = finalValue;
7119					}
7120				}
7121			}
7122		}
7123
7124		return this;
7125	},
7126
7127	removeClass: function( value ) {
7128		var classes, elem, cur, clazz, j, finalValue,
7129			proceed = arguments.length === 0 || typeof value === "string" && value,
7130			i = 0,
7131			len = this.length;
7132
7133		if ( jQuery.isFunction( value ) ) {
7134			return this.each(function( j ) {
7135				jQuery( this ).removeClass( value.call( this, j, this.className ) );
7136			});
7137		}
7138		if ( proceed ) {
7139			classes = ( value || "" ).match( rnotwhite ) || [];
7140
7141			for ( ; i < len; i++ ) {
7142				elem = this[ i ];
7143				// This expression is here for better compressibility (see addClass)
7144				cur = elem.nodeType === 1 && ( elem.className ?
7145					( " " + elem.className + " " ).replace( rclass, " " ) :
7146					""
7147				);
7148
7149				if ( cur ) {
7150					j = 0;
7151					while ( (clazz = classes[j++]) ) {
7152						// Remove *all* instances
7153						while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
7154							cur = cur.replace( " " + clazz + " ", " " );
7155						}
7156					}
7157
7158					// only assign if different to avoid unneeded rendering.
7159					finalValue = value ? jQuery.trim( cur ) : "";
7160					if ( elem.className !== finalValue ) {
7161						elem.className = finalValue;
7162					}
7163				}
7164			}
7165		}
7166
7167		return this;
7168	},
7169
7170	toggleClass: function( value, stateVal ) {
7171		var type = typeof value;
7172
7173		if ( typeof stateVal === "boolean" && type === "string" ) {
7174			return stateVal ? this.addClass( value ) : this.removeClass( value );
7175		}
7176
7177		if ( jQuery.isFunction( value ) ) {
7178			return this.each(function( i ) {
7179				jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
7180			});
7181		}
7182
7183		return this.each(function() {
7184			if ( type === "string" ) {
7185				// toggle individual class names
7186				var className,
7187					i = 0,
7188					self = jQuery( this ),
7189					classNames = value.match( rnotwhite ) || [];
7190
7191				while ( (className = classNames[ i++ ]) ) {
7192					// check each className given, space separated list
7193					if ( self.hasClass( className ) ) {
7194						self.removeClass( className );
7195					} else {
7196						self.addClass( className );
7197					}
7198				}
7199
7200			// Toggle whole class name
7201			} else if ( type === strundefined || type === "boolean" ) {
7202				if ( this.className ) {
7203					// store className if set
7204					data_priv.set( this, "__className__", this.className );
7205				}
7206
7207				// If the element has a class name or if we're passed "false",
7208				// then remove the whole classname (if there was one, the above saved it).
7209				// Otherwise bring back whatever was previously saved (if anything),
7210				// falling back to the empty string if nothing was stored.
7211				this.className = this.className || value === false ? "" : data_priv.get( this, "__className__" ) || "";
7212			}
7213		});
7214	},
7215
7216	hasClass: function( selector ) {
7217		var className = " " + selector + " ",
7218			i = 0,
7219			l = this.length;
7220		for ( ; i < l; i++ ) {
7221			if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
7222				return true;
7223			}
7224		}
7225
7226		return false;
7227	}
7228});
7229
7230
7231
7232
7233var rreturn = /\r/g;
7234
7235jQuery.fn.extend({
7236	val: function( value ) {
7237		var hooks, ret, isFunction,
7238			elem = this[0];
7239
7240		if ( !arguments.length ) {
7241			if ( elem ) {
7242				hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
7243
7244				if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
7245					return ret;
7246				}
7247
7248				ret = elem.value;
7249
7250				return typeof ret === "string" ?
7251					// handle most common string cases
7252					ret.replace(rreturn, "") :
7253					// handle cases where value is null/undef or number
7254					ret == null ? "" : ret;
7255			}
7256
7257			return;
7258		}
7259
7260		isFunction = jQuery.isFunction( value );
7261
7262		return this.each(function( i ) {
7263			var val;
7264
7265			if ( this.nodeType !== 1 ) {
7266				return;
7267			}
7268
7269			if ( isFunction ) {
7270				val = value.call( this, i, jQuery( this ).val() );
7271			} else {
7272				val = value;
7273			}
7274
7275			// Treat null/undefined as ""; convert numbers to string
7276			if ( val == null ) {
7277				val = "";
7278
7279			} else if ( typeof val === "number" ) {
7280				val += "";
7281
7282			} else if ( jQuery.isArray( val ) ) {
7283				val = jQuery.map( val, function( value ) {
7284					return value == null ? "" : value + "";
7285				});
7286			}
7287
7288			hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
7289
7290			// If set returns undefined, fall back to normal setting
7291			if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
7292				this.value = val;
7293			}
7294		});
7295	}
7296});
7297
7298jQuery.extend({
7299	valHooks: {
7300		select: {
7301			get: function( elem ) {
7302				var value, option,
7303					options = elem.options,
7304					index = elem.selectedIndex,
7305					one = elem.type === "select-one" || index < 0,
7306					values = one ? null : [],
7307					max = one ? index + 1 : options.length,
7308					i = index < 0 ?
7309						max :
7310						one ? index : 0;
7311
7312				// Loop through all the selected options
7313				for ( ; i < max; i++ ) {
7314					option = options[ i ];
7315
7316					// IE6-9 doesn't update selected after form reset (#2551)
7317					if ( ( option.selected || i === index ) &&
7318							// Don't return options that are disabled or in a disabled optgroup
7319							( support.optDisabled ? !option.disabled : option.getAttribute( "disabled" ) === null ) &&
7320							( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
7321
7322						// Get the specific value for the option
7323						value = jQuery( option ).val();
7324
7325						// We don't need an array for one selects
7326						if ( one ) {
7327							return value;
7328						}
7329
7330						// Multi-Selects return an array
7331						values.push( value );
7332					}
7333				}
7334
7335				return values;
7336			},
7337
7338			set: function( elem, value ) {
7339				var optionSet, option,
7340					options = elem.options,
7341					values = jQuery.makeArray( value ),
7342					i = options.length;
7343
7344				while ( i-- ) {
7345					option = options[ i ];
7346					if ( (option.selected = jQuery.inArray( jQuery(option).val(), values ) >= 0) ) {
7347						optionSet = true;
7348					}
7349				}
7350
7351				// force browsers to behave consistently when non-matching value is set
7352				if ( !optionSet ) {
7353					elem.selectedIndex = -1;
7354				}
7355				return values;
7356			}
7357		}
7358	}
7359});
7360
7361// Radios and checkboxes getter/setter
7362jQuery.each([ "radio", "checkbox" ], function() {
7363	jQuery.valHooks[ this ] = {
7364		set: function( elem, value ) {
7365			if ( jQuery.isArray( value ) ) {
7366				return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
7367			}
7368		}
7369	};
7370	if ( !support.checkOn ) {
7371		jQuery.valHooks[ this ].get = function( elem ) {
7372			// Support: Webkit
7373			// "" is returned instead of "on" if a value isn't specified
7374			return elem.getAttribute("value") === null ? "on" : elem.value;
7375		};
7376	}
7377});
7378
7379
7380
7381
7382// Return jQuery for attributes-only inclusion
7383
7384
7385jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
7386	"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
7387	"change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
7388
7389	// Handle event binding
7390	jQuery.fn[ name ] = function( data, fn ) {
7391		return arguments.length > 0 ?
7392			this.on( name, null, data, fn ) :
7393			this.trigger( name );
7394	};
7395});
7396
7397jQuery.fn.extend({
7398	hover: function( fnOver, fnOut ) {
7399		return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
7400	},
7401
7402	bind: function( types, data, fn ) {
7403		return this.on( types, null, data, fn );
7404	},
7405	unbind: function( types, fn ) {
7406		return this.off( types, null, fn );
7407	},
7408
7409	delegate: function( selector, types, data, fn ) {
7410		return this.on( types, selector, data, fn );
7411	},
7412	undelegate: function( selector, types, fn ) {
7413		// ( namespace ) or ( selector, types [, fn] )
7414		return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
7415	}
7416});
7417
7418
7419var nonce = jQuery.now();
7420
7421var rquery = (/\?/);
7422
7423
7424
7425// Support: Android 2.3
7426// Workaround failure to string-cast null input
7427jQuery.parseJSON = function( data ) {
7428	return JSON.parse( data + "" );
7429};
7430
7431
7432// Cross-browser xml parsing
7433jQuery.parseXML = function( data ) {
7434	var xml, tmp;
7435	if ( !data || typeof data !== "string" ) {
7436		return null;
7437	}
7438
7439	// Support: IE9
7440	try {
7441		tmp = new DOMParser();
7442		xml = tmp.parseFromString( data, "text/xml" );
7443	} catch ( e ) {
7444		xml = undefined;
7445	}
7446
7447	if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) {
7448		jQuery.error( "Invalid XML: " + data );
7449	}
7450	return xml;
7451};
7452
7453
7454var
7455	// Document location
7456	ajaxLocParts,
7457	ajaxLocation,
7458
7459	rhash = /#.*$/,
7460	rts = /([?&])_=[^&]*/,
7461	rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg,
7462	// #7653, #8125, #8152: local protocol detection
7463	rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
7464	rnoContent = /^(?:GET|HEAD)$/,
7465	rprotocol = /^\/\//,
7466	rurl = /^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,
7467
7468	/* Prefilters
7469	 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
7470	 * 2) These are called:
7471	 *    - BEFORE asking for a transport
7472	 *    - AFTER param serialization (s.data is a string if s.processData is true)
7473	 * 3) key is the dataType
7474	 * 4) the catchall symbol "*" can be used
7475	 * 5) execution will start with transport dataType and THEN continue down to "*" if needed
7476	 */
7477	prefilters = {},
7478
7479	/* Transports bindings
7480	 * 1) key is the dataType
7481	 * 2) the catchall symbol "*" can be used
7482	 * 3) selection will start with transport dataType and THEN go to "*" if needed
7483	 */
7484	transports = {},
7485
7486	// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
7487	allTypes = "*/".concat("*");
7488
7489// #8138, IE may throw an exception when accessing
7490// a field from window.location if document.domain has been set
7491try {
7492	ajaxLocation = location.href;
7493} catch( e ) {
7494	// Use the href attribute of an A element
7495	// since IE will modify it given document.location
7496	ajaxLocation = document.createElement( "a" );
7497	ajaxLocation.href = "";
7498	ajaxLocation = ajaxLocation.href;
7499}
7500
7501// Segment location into parts
7502ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
7503
7504// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
7505function addToPrefiltersOrTransports( structure ) {
7506
7507	// dataTypeExpression is optional and defaults to "*"
7508	return function( dataTypeExpression, func ) {
7509
7510		if ( typeof dataTypeExpression !== "string" ) {
7511			func = dataTypeExpression;
7512			dataTypeExpression = "*";
7513		}
7514
7515		var dataType,
7516			i = 0,
7517			dataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || [];
7518
7519		if ( jQuery.isFunction( func ) ) {
7520			// For each dataType in the dataTypeExpression
vendor: 4,244 bytes, lines 7521-7671
7521			while ( (dataType = dataTypes[i++]) ) {
7522				// Prepend if requested
7523				if ( dataType[0] === "+" ) {
7524					dataType = dataType.slice( 1 ) || "*";
7525					(structure[ dataType ] = structure[ dataType ] || []).unshift( func );
7526
7527				// Otherwise append
7528				} else {
7529					(structure[ dataType ] = structure[ dataType ] || []).push( func );
7530				}
7531			}
7532		}
7533	};
7534}
7535
7536// Base inspection function for prefilters and transports
7537function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
7538
7539	var inspected = {},
7540		seekingTransport = ( structure === transports );
7541
7542	function inspect( dataType ) {
7543		var selected;
7544		inspected[ dataType ] = true;
7545		jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
7546			var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
7547			if ( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
7548				options.dataTypes.unshift( dataTypeOrTransport );
7549				inspect( dataTypeOrTransport );
7550				return false;
7551			} else if ( seekingTransport ) {
7552				return !( selected = dataTypeOrTransport );
7553			}
7554		});
7555		return selected;
7556	}
7557
7558	return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
7559}
7560
7561// A special extend for ajax options
7562// that takes "flat" options (not to be deep extended)
7563// Fixes #9887
7564function ajaxExtend( target, src ) {
7565	var key, deep,
7566		flatOptions = jQuery.ajaxSettings.flatOptions || {};
7567
7568	for ( key in src ) {
7569		if ( src[ key ] !== undefined ) {
7570			( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];
7571		}
7572	}
7573	if ( deep ) {
7574		jQuery.extend( true, target, deep );
7575	}
7576
7577	return target;
7578}
7579
7580/* Handles responses to an ajax request:
7581 * - finds the right dataType (mediates between content-type and expected dataType)
7582 * - returns the corresponding response
7583 */
7584function ajaxHandleResponses( s, jqXHR, responses ) {
7585
7586	var ct, type, finalDataType, firstDataType,
7587		contents = s.contents,
7588		dataTypes = s.dataTypes;
7589
7590	// Remove auto dataType and get content-type in the process
7591	while ( dataTypes[ 0 ] === "*" ) {
7592		dataTypes.shift();
7593		if ( ct === undefined ) {
7594			ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
7595		}
7596	}
7597
7598	// Check if we're dealing with a known content-type
7599	if ( ct ) {
7600		for ( type in contents ) {
7601			if ( contents[ type ] && contents[ type ].test( ct ) ) {
7602				dataTypes.unshift( type );
7603				break;
7604			}
7605		}
7606	}
7607
7608	// Check to see if we have a response for the expected dataType
7609	if ( dataTypes[ 0 ] in responses ) {
7610		finalDataType = dataTypes[ 0 ];
7611	} else {
7612		// Try convertible dataTypes
7613		for ( type in responses ) {
7614			if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
7615				finalDataType = type;
7616				break;
7617			}
7618			if ( !firstDataType ) {
7619				firstDataType = type;
7620			}
7621		}
7622		// Or just use first one
7623		finalDataType = finalDataType || firstDataType;
7624	}
7625
7626	// If we found a dataType
7627	// We add the dataType to the list if needed
7628	// and return the corresponding response
7629	if ( finalDataType ) {
7630		if ( finalDataType !== dataTypes[ 0 ] ) {
7631			dataTypes.unshift( finalDataType );
7632		}
7633		return responses[ finalDataType ];
7634	}
7635}
7636
7637/* Chain conversions given the request and the original response
7638 * Also sets the responseXXX fields on the jqXHR instance
7639 */
7640function ajaxConvert( s, response, jqXHR, isSuccess ) {
7641	var conv2, current, conv, tmp, prev,
7642		converters = {},
7643		// Work with a copy of dataTypes in case we need to modify it for conversion
7644		dataTypes = s.dataTypes.slice();
7645
7646	// Create converters map with lowercased keys
7647	if ( dataTypes[ 1 ] ) {
7648		for ( conv in s.converters ) {
7649			converters[ conv.toLowerCase() ] = s.converters[ conv ];
7650		}
7651	}
7652
7653	current = dataTypes.shift();
7654
7655	// Convert to each sequential dataType
7656	while ( current ) {
7657
7658		if ( s.responseFields[ current ] ) {
7659			jqXHR[ s.responseFields[ current ] ] = response;
7660		}
7661
7662		// Apply the dataFilter if provided
7663		if ( !prev && isSuccess && s.dataFilter ) {
7664			response = s.dataFilter( response, s.dataType );
7665		}
7666
7667		prev = current;
7668		current = dataTypes.shift();
7669
7670		if ( current ) {
7671
vendor: 9,105 bytes, lines 7672-8002
7672		// There's only work to do if current dataType is non-auto
7673			if ( current === "*" ) {
7674
7675				current = prev;
7676
7677			// Convert response if prev dataType is non-auto and differs from current
7678			} else if ( prev !== "*" && prev !== current ) {
7679
7680				// Seek a direct converter
7681				conv = converters[ prev + " " + current ] || converters[ "* " + current ];
7682
7683				// If none found, seek a pair
7684				if ( !conv ) {
7685					for ( conv2 in converters ) {
7686
7687						// If conv2 outputs current
7688						tmp = conv2.split( " " );
7689						if ( tmp[ 1 ] === current ) {
7690
7691							// If prev can be converted to accepted input
7692							conv = converters[ prev + " " + tmp[ 0 ] ] ||
7693								converters[ "* " + tmp[ 0 ] ];
7694							if ( conv ) {
7695								// Condense equivalence converters
7696								if ( conv === true ) {
7697									conv = converters[ conv2 ];
7698
7699								// Otherwise, insert the intermediate dataType
7700								} else if ( converters[ conv2 ] !== true ) {
7701									current = tmp[ 0 ];
7702									dataTypes.unshift( tmp[ 1 ] );
7703								}
7704								break;
7705							}
7706						}
7707					}
7708				}
7709
7710				// Apply converter (if not an equivalence)
7711				if ( conv !== true ) {
7712
7713					// Unless errors are allowed to bubble, catch and return them
7714					if ( conv && s[ "throws" ] ) {
7715						response = conv( response );
7716					} else {
7717						try {
7718							response = conv( response );
7719						} catch ( e ) {
7720							return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
7721						}
7722					}
7723				}
7724			}
7725		}
7726	}
7727
7728	return { state: "success", data: response };
7729}
7730
7731jQuery.extend({
7732
7733	// Counter for holding the number of active queries
7734	active: 0,
7735
7736	// Last-Modified header cache for next request
7737	lastModified: {},
7738	etag: {},
7739
7740	ajaxSettings: {
7741		url: ajaxLocation,
7742		type: "GET",
7743		isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
7744		global: true,
7745		processData: true,
7746		async: true,
7747		contentType: "application/x-www-form-urlencoded; charset=UTF-8",
7748		/*
7749		timeout: 0,
7750		data: null,
7751		dataType: null,
7752		username: null,
7753		password: null,
7754		cache: null,
7755		throws: false,
7756		traditional: false,
7757		headers: {},
7758		*/
7759
7760		accepts: {
7761			"*": allTypes,
7762			text: "text/plain",
7763			html: "text/html",
7764			xml: "application/xml, text/xml",
7765			json: "application/json, text/javascript"
7766		},
7767
7768		contents: {
7769			xml: /xml/,
7770			html: /html/,
7771			json: /json/
7772		},
7773
7774		responseFields: {
7775			xml: "responseXML",
7776			text: "responseText",
7777			json: "responseJSON"
7778		},
7779
7780		// Data converters
7781		// Keys separate source (or catchall "*") and destination types with a single space
7782		converters: {
7783
7784			// Convert anything to text
7785			"* text": String,
7786
7787			// Text to html (true = no transformation)
7788			"text html": true,
7789
7790			// Evaluate text as a json expression
7791			"text json": jQuery.parseJSON,
7792
7793			// Parse text as xml
7794			"text xml": jQuery.parseXML
7795		},
7796
7797		// For options that shouldn't be deep extended:
7798		// you can add your own custom options here if
7799		// and when you create one that shouldn't be
7800		// deep extended (see ajaxExtend)
7801		flatOptions: {
7802			url: true,
7803			context: true
7804		}
7805	},
7806
7807	// Creates a full fledged settings object into target
7808	// with both ajaxSettings and settings fields.
7809	// If target is omitted, writes into ajaxSettings.
7810	ajaxSetup: function( target, settings ) {
7811		return settings ?
7812
7813			// Building a settings object
7814			ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
7815
7816			// Extending ajaxSettings
7817			ajaxExtend( jQuery.ajaxSettings, target );
7818	},
7819
7820	ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
7821	ajaxTransport: addToPrefiltersOrTransports( transports ),
7822
7823	// Main method
7824	ajax: function( url, options ) {
7825
7826		// If url is an object, simulate pre-1.5 signature
7827		if ( typeof url === "object" ) {
7828			options = url;
7829			url = undefined;
7830		}
7831
7832		// Force options to be an object
7833		options = options || {};
7834
7835		var transport,
7836			// URL without anti-cache param
7837			cacheURL,
7838			// Response headers
7839			responseHeadersString,
7840			responseHeaders,
7841			// timeout handle
7842			timeoutTimer,
7843			// Cross-domain detection vars
7844			parts,
7845			// To know if global events are to be dispatched
7846			fireGlobals,
7847			// Loop variable
7848			i,
7849			// Create the final options object
7850			s = jQuery.ajaxSetup( {}, options ),
7851			// Callbacks context
7852			callbackContext = s.context || s,
7853			// Context for global events is callbackContext if it is a DOM node or jQuery collection
7854			globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?
7855				jQuery( callbackContext ) :
7856				jQuery.event,
7857			// Deferreds
7858			deferred = jQuery.Deferred(),
7859			completeDeferred = jQuery.Callbacks("once memory"),
7860			// Status-dependent callbacks
7861			statusCode = s.statusCode || {},
7862			// Headers (they are sent all at once)
7863			requestHeaders = {},
7864			requestHeadersNames = {},
7865			// The jqXHR state
7866			state = 0,
7867			// Default abort message
7868			strAbort = "canceled",
7869			// Fake xhr
7870			jqXHR = {
7871				readyState: 0,
7872
7873				// Builds headers hashtable if needed
7874				getResponseHeader: function( key ) {
7875					var match;
7876					if ( state === 2 ) {
7877						if ( !responseHeaders ) {
7878							responseHeaders = {};
7879							while ( (match = rheaders.exec( responseHeadersString )) ) {
7880								responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
7881							}
7882						}
7883						match = responseHeaders[ key.toLowerCase() ];
7884					}
7885					return match == null ? null : match;
7886				},
7887
7888				// Raw string
7889				getAllResponseHeaders: function() {
7890					return state === 2 ? responseHeadersString : null;
7891				},
7892
7893				// Caches the header
7894				setRequestHeader: function( name, value ) {
7895					var lname = name.toLowerCase();
7896					if ( !state ) {
7897						name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
7898						requestHeaders[ name ] = value;
7899					}
7900					return this;
7901				},
7902
7903				// Overrides response content-type header
7904				overrideMimeType: function( type ) {
7905					if ( !state ) {
7906						s.mimeType = type;
7907					}
7908					return this;
7909				},
7910
7911				// Status-dependent callbacks
7912				statusCode: function( map ) {
7913					var code;
7914					if ( map ) {
7915						if ( state < 2 ) {
7916							for ( code in map ) {
7917								// Lazy-add the new callback in a way that preserves old ones
7918								statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
7919							}
7920						} else {
7921							// Execute the appropriate callbacks
7922							jqXHR.always( map[ jqXHR.status ] );
7923						}
7924					}
7925					return this;
7926				},
7927
7928				// Cancel the request
7929				abort: function( statusText ) {
7930					var finalText = statusText || strAbort;
7931					if ( transport ) {
7932						transport.abort( finalText );
7933					}
7934					done( 0, finalText );
7935					return this;
7936				}
7937			};
7938
7939		// Attach deferreds
7940		deferred.promise( jqXHR ).complete = completeDeferred.add;
7941		jqXHR.success = jqXHR.done;
7942		jqXHR.error = jqXHR.fail;
7943
7944		// Remove hash character (#7531: and string promotion)
7945		// Add protocol if not provided (prefilters might expect it)
7946		// Handle falsy url in the settings object (#10093: consistency with old signature)
7947		// We also use the url parameter if available
7948		s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" )
7949			.replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
7950
7951		// Alias method option to type as per ticket #12004
7952		s.type = options.method || options.type || s.method || s.type;
7953
7954		// Extract dataTypes list
7955		s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( rnotwhite ) || [ "" ];
7956
7957		// A cross-domain request is in order when we have a protocol:host:port mismatch
7958		if ( s.crossDomain == null ) {
7959			parts = rurl.exec( s.url.toLowerCase() );
7960			s.crossDomain = !!( parts &&
7961				( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||
7962					( parts[ 3 ] || ( parts[ 1 ] === "http:" ? "80" : "443" ) ) !==
7963						( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? "80" : "443" ) ) )
7964			);
7965		}
7966
7967		// Convert data if not already a string
7968		if ( s.data && s.processData && typeof s.data !== "string" ) {
7969			s.data = jQuery.param( s.data, s.traditional );
7970		}
7971
7972		// Apply prefilters
7973		inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
7974
7975		// If request was aborted inside a prefilter, stop there
7976		if ( state === 2 ) {
7977			return jqXHR;
7978		}
7979
7980		// We can fire global events as of now if asked to
7981		fireGlobals = s.global;
7982
7983		// Watch for a new set of requests
7984		if ( fireGlobals && jQuery.active++ === 0 ) {
7985			jQuery.event.trigger("ajaxStart");
7986		}
7987
7988		// Uppercase the type
7989		s.type = s.type.toUpperCase();
7990
7991		// Determine if request has content
7992		s.hasContent = !rnoContent.test( s.type );
7993
7994		// Save the URL in case we're toying with the If-Modified-Since
7995		// and/or If-None-Match header later on
7996		cacheURL = s.url;
7997
7998		// More options handling for requests with no content
7999		if ( !s.hasContent ) {
8000
8001			// If data is available, append data to url
8002			if ( s.data ) {
vendor: 17,837 bytes, lines 8003-8669
8003				cacheURL = ( s.url += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data );
8004				// #9682: remove data so that it's not used in an eventual retry
8005				delete s.data;
8006			}
8007
8008			// Add anti-cache in url if needed
8009			if ( s.cache === false ) {
8010				s.url = rts.test( cacheURL ) ?
8011
8012					// If there is already a '_' parameter, set its value
8013					cacheURL.replace( rts, "$1_=" + nonce++ ) :
8014
8015					// Otherwise add one to the end
8016					cacheURL + ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + nonce++;
8017			}
8018		}
8019
8020		// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
8021		if ( s.ifModified ) {
8022			if ( jQuery.lastModified[ cacheURL ] ) {
8023				jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
8024			}
8025			if ( jQuery.etag[ cacheURL ] ) {
8026				jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
8027			}
8028		}
8029
8030		// Set the correct header, if data is being sent
8031		if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
8032			jqXHR.setRequestHeader( "Content-Type", s.contentType );
8033		}
8034
8035		// Set the Accepts header for the server, depending on the dataType
8036		jqXHR.setRequestHeader(
8037			"Accept",
8038			s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
8039				s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
8040				s.accepts[ "*" ]
8041		);
8042
8043		// Check for headers option
8044		for ( i in s.headers ) {
8045			jqXHR.setRequestHeader( i, s.headers[ i ] );
8046		}
8047
8048		// Allow custom headers/mimetypes and early abort
8049		if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
8050			// Abort if not done already and return
8051			return jqXHR.abort();
8052		}
8053
8054		// aborting is no longer a cancellation
8055		strAbort = "abort";
8056
8057		// Install callbacks on deferreds
8058		for ( i in { success: 1, error: 1, complete: 1 } ) {
8059			jqXHR[ i ]( s[ i ] );
8060		}
8061
8062		// Get transport
8063		transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
8064
8065		// If no transport, we auto-abort
8066		if ( !transport ) {
8067			done( -1, "No Transport" );
8068		} else {
8069			jqXHR.readyState = 1;
8070
8071			// Send global event
8072			if ( fireGlobals ) {
8073				globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
8074			}
8075			// Timeout
8076			if ( s.async && s.timeout > 0 ) {
8077				timeoutTimer = setTimeout(function() {
8078					jqXHR.abort("timeout");
8079				}, s.timeout );
8080			}
8081
8082			try {
8083				state = 1;
8084				transport.send( requestHeaders, done );
8085			} catch ( e ) {
8086				// Propagate exception as error if not done
8087				if ( state < 2 ) {
8088					done( -1, e );
8089				// Simply rethrow otherwise
8090				} else {
8091					throw e;
8092				}
8093			}
8094		}
8095
8096		// Callback for when everything is done
8097		function done( status, nativeStatusText, responses, headers ) {
8098			var isSuccess, success, error, response, modified,
8099				statusText = nativeStatusText;
8100
8101			// Called once
8102			if ( state === 2 ) {
8103				return;
8104			}
8105
8106			// State is "done" now
8107			state = 2;
8108
8109			// Clear timeout if it exists
8110			if ( timeoutTimer ) {
8111				clearTimeout( timeoutTimer );
8112			}
8113
8114			// Dereference transport for early garbage collection
8115			// (no matter how long the jqXHR object will be used)
8116			transport = undefined;
8117
8118			// Cache response headers
8119			responseHeadersString = headers || "";
8120
8121			// Set readyState
8122			jqXHR.readyState = status > 0 ? 4 : 0;
8123
8124			// Determine if successful
8125			isSuccess = status >= 200 && status < 300 || status === 304;
8126
8127			// Get response data
8128			if ( responses ) {
8129				response = ajaxHandleResponses( s, jqXHR, responses );
8130			}
8131
8132			// Convert no matter what (that way responseXXX fields are always set)
8133			response = ajaxConvert( s, response, jqXHR, isSuccess );
8134
8135			// If successful, handle type chaining
8136			if ( isSuccess ) {
8137
8138				// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
8139				if ( s.ifModified ) {
8140					modified = jqXHR.getResponseHeader("Last-Modified");
8141					if ( modified ) {
8142						jQuery.lastModified[ cacheURL ] = modified;
8143					}
8144					modified = jqXHR.getResponseHeader("etag");
8145					if ( modified ) {
8146						jQuery.etag[ cacheURL ] = modified;
8147					}
8148				}
8149
8150				// if no content
8151				if ( status === 204 || s.type === "HEAD" ) {
8152					statusText = "nocontent";
8153
8154				// if not modified
8155				} else if ( status === 304 ) {
8156					statusText = "notmodified";
8157
8158				// If we have data, let's convert it
8159				} else {
8160					statusText = response.state;
8161					success = response.data;
8162					error = response.error;
8163					isSuccess = !error;
8164				}
8165			} else {
8166				// We extract error from statusText
8167				// then normalize statusText and status for non-aborts
8168				error = statusText;
8169				if ( status || !statusText ) {
8170					statusText = "error";
8171					if ( status < 0 ) {
8172						status = 0;
8173					}
8174				}
8175			}
8176
8177			// Set data for the fake xhr object
8178			jqXHR.status = status;
8179			jqXHR.statusText = ( nativeStatusText || statusText ) + "";
8180
8181			// Success/Error
8182			if ( isSuccess ) {
8183				deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
8184			} else {
8185				deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
8186			}
8187
8188			// Status-dependent callbacks
8189			jqXHR.statusCode( statusCode );
8190			statusCode = undefined;
8191
8192			if ( fireGlobals ) {
8193				globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
8194					[ jqXHR, s, isSuccess ? success : error ] );
8195			}
8196
8197			// Complete
8198			completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
8199
8200			if ( fireGlobals ) {
8201				globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
8202				// Handle the global AJAX counter
8203				if ( !( --jQuery.active ) ) {
8204					jQuery.event.trigger("ajaxStop");
8205				}
8206			}
8207		}
8208
8209		return jqXHR;
8210	},
8211
8212	getJSON: function( url, data, callback ) {
8213		return jQuery.get( url, data, callback, "json" );
8214	},
8215
8216	getScript: function( url, callback ) {
8217		return jQuery.get( url, undefined, callback, "script" );
8218	}
8219});
8220
8221jQuery.each( [ "get", "post" ], function( i, method ) {
8222	jQuery[ method ] = function( url, data, callback, type ) {
8223		// shift arguments if data argument was omitted
8224		if ( jQuery.isFunction( data ) ) {
8225			type = type || callback;
8226			callback = data;
8227			data = undefined;
8228		}
8229
8230		return jQuery.ajax({
8231			url: url,
8232			type: method,
8233			dataType: type,
8234			data: data,
8235			success: callback
8236		});
8237	};
8238});
8239
8240// Attach a bunch of functions for handling common AJAX events
8241jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ) {
8242	jQuery.fn[ type ] = function( fn ) {
8243		return this.on( type, fn );
8244	};
8245});
8246
8247
8248jQuery._evalUrl = function( url ) {
8249	return jQuery.ajax({
8250		url: url,
8251		type: "GET",
8252		dataType: "script",
8253		async: false,
8254		global: false,
8255		"throws": true
8256	});
8257};
8258
8259
8260jQuery.fn.extend({
8261	wrapAll: function( html ) {
8262		var wrap;
8263
8264		if ( jQuery.isFunction( html ) ) {
8265			return this.each(function( i ) {
8266				jQuery( this ).wrapAll( html.call(this, i) );
8267			});
8268		}
8269
8270		if ( this[ 0 ] ) {
8271
8272			// The elements to wrap the target around
8273			wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );
8274
8275			if ( this[ 0 ].parentNode ) {
8276				wrap.insertBefore( this[ 0 ] );
8277			}
8278
8279			wrap.map(function() {
8280				var elem = this;
8281
8282				while ( elem.firstElementChild ) {
8283					elem = elem.firstElementChild;
8284				}
8285
8286				return elem;
8287			}).append( this );
8288		}
8289
8290		return this;
8291	},
8292
8293	wrapInner: function( html ) {
8294		if ( jQuery.isFunction( html ) ) {
8295			return this.each(function( i ) {
8296				jQuery( this ).wrapInner( html.call(this, i) );
8297			});
8298		}
8299
8300		return this.each(function() {
8301			var self = jQuery( this ),
8302				contents = self.contents();
8303
8304			if ( contents.length ) {
8305				contents.wrapAll( html );
8306
8307			} else {
8308				self.append( html );
8309			}
8310		});
8311	},
8312
8313	wrap: function( html ) {
8314		var isFunction = jQuery.isFunction( html );
8315
8316		return this.each(function( i ) {
8317			jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
8318		});
8319	},
8320
8321	unwrap: function() {
8322		return this.parent().each(function() {
8323			if ( !jQuery.nodeName( this, "body" ) ) {
8324				jQuery( this ).replaceWith( this.childNodes );
8325			}
8326		}).end();
8327	}
8328});
8329
8330
8331jQuery.expr.filters.hidden = function( elem ) {
8332	// Support: Opera <= 12.12
8333	// Opera reports offsetWidths and offsetHeights less than zero on some elements
8334	return elem.offsetWidth <= 0 && elem.offsetHeight <= 0;
8335};
8336jQuery.expr.filters.visible = function( elem ) {
8337	return !jQuery.expr.filters.hidden( elem );
8338};
8339
8340
8341
8342
8343var r20 = /%20/g,
8344	rbracket = /\[\]$/,
8345	rCRLF = /\r?\n/g,
8346	rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
8347	rsubmittable = /^(?:input|select|textarea|keygen)/i;
8348
8349function buildParams( prefix, obj, traditional, add ) {
8350	var name;
8351
8352	if ( jQuery.isArray( obj ) ) {
8353		// Serialize array item.
8354		jQuery.each( obj, function( i, v ) {
8355			if ( traditional || rbracket.test( prefix ) ) {
8356				// Treat each array item as a scalar.
8357				add( prefix, v );
8358
8359			} else {
8360				// Item is non-scalar (array or object), encode its numeric index.
8361				buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
8362			}
8363		});
8364
8365	} else if ( !traditional && jQuery.type( obj ) === "object" ) {
8366		// Serialize object item.
8367		for ( name in obj ) {
8368			buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
8369		}
8370
8371	} else {
8372		// Serialize scalar item.
8373		add( prefix, obj );
8374	}
8375}
8376
8377// Serialize an array of form elements or a set of
8378// key/values into a query string
8379jQuery.param = function( a, traditional ) {
8380	var prefix,
8381		s = [],
8382		add = function( key, value ) {
8383			// If value is a function, invoke it and return its value
8384			value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
8385			s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
8386		};
8387
8388	// Set traditional to true for jQuery <= 1.3.2 behavior.
8389	if ( traditional === undefined ) {
8390		traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
8391	}
8392
8393	// If an array was passed in, assume that it is an array of form elements.
8394	if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
8395		// Serialize the form elements
8396		jQuery.each( a, function() {
8397			add( this.name, this.value );
8398		});
8399
8400	} else {
8401		// If traditional, encode the "old" way (the way 1.3.2 or older
8402		// did it), otherwise encode params recursively.
8403		for ( prefix in a ) {
8404			buildParams( prefix, a[ prefix ], traditional, add );
8405		}
8406	}
8407
8408	// Return the resulting serialization
8409	return s.join( "&" ).replace( r20, "+" );
8410};
8411
8412jQuery.fn.extend({
8413	serialize: function() {
8414		return jQuery.param( this.serializeArray() );
8415	},
8416	serializeArray: function() {
8417		return this.map(function() {
8418			// Can add propHook for "elements" to filter or add form elements
8419			var elements = jQuery.prop( this, "elements" );
8420			return elements ? jQuery.makeArray( elements ) : this;
8421		})
8422		.filter(function() {
8423			var type = this.type;
8424
8425			// Use .is( ":disabled" ) so that fieldset[disabled] works
8426			return this.name && !jQuery( this ).is( ":disabled" ) &&
8427				rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
8428				( this.checked || !rcheckableType.test( type ) );
8429		})
8430		.map(function( i, elem ) {
8431			var val = jQuery( this ).val();
8432
8433			return val == null ?
8434				null :
8435				jQuery.isArray( val ) ?
8436					jQuery.map( val, function( val ) {
8437						return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
8438					}) :
8439					{ name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
8440		}).get();
8441	}
8442});
8443
8444
8445jQuery.ajaxSettings.xhr = function() {
8446	try {
8447		return new XMLHttpRequest();
8448	} catch( e ) {}
8449};
8450
8451var xhrId = 0,
8452	xhrCallbacks = {},
8453	xhrSuccessStatus = {
8454		// file protocol always yields status code 0, assume 200
8455		0: 200,
8456		// Support: IE9
8457		// #1450: sometimes IE returns 1223 when it should be 204
8458		1223: 204
8459	},
8460	xhrSupported = jQuery.ajaxSettings.xhr();
8461
8462// Support: IE9
8463// Open requests must be manually aborted on unload (#5280)
8464if ( window.ActiveXObject ) {
8465	jQuery( window ).on( "unload", function() {
8466		for ( var key in xhrCallbacks ) {
8467			xhrCallbacks[ key ]();
8468		}
8469	});
8470}
8471
8472support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
8473support.ajax = xhrSupported = !!xhrSupported;
8474
8475jQuery.ajaxTransport(function( options ) {
8476	var callback;
8477
8478	// Cross domain only allowed if supported through XMLHttpRequest
8479	if ( support.cors || xhrSupported && !options.crossDomain ) {
8480		return {
8481			send: function( headers, complete ) {
8482				var i,
8483					xhr = options.xhr(),
8484					id = ++xhrId;
8485
8486				xhr.open( options.type, options.url, options.async, options.username, options.password );
8487
8488				// Apply custom fields if provided
8489				if ( options.xhrFields ) {
8490					for ( i in options.xhrFields ) {
8491						xhr[ i ] = options.xhrFields[ i ];
8492					}
8493				}
8494
8495				// Override mime type if needed
8496				if ( options.mimeType && xhr.overrideMimeType ) {
8497					xhr.overrideMimeType( options.mimeType );
8498				}
8499
8500				// X-Requested-With header
8501				// For cross-domain requests, seeing as conditions for a preflight are
8502				// akin to a jigsaw puzzle, we simply never set it to be sure.
8503				// (it can always be set on a per-request basis or even using ajaxSetup)
8504				// For same-domain requests, won't change header if already provided.
8505				if ( !options.crossDomain && !headers["X-Requested-With"] ) {
8506					headers["X-Requested-With"] = "XMLHttpRequest";
8507				}
8508
8509				// Set headers
8510				for ( i in headers ) {
8511					xhr.setRequestHeader( i, headers[ i ] );
8512				}
8513
8514				// Callback
8515				callback = function( type ) {
8516					return function() {
8517						if ( callback ) {
8518							delete xhrCallbacks[ id ];
8519							callback = xhr.onload = xhr.onerror = null;
8520
8521							if ( type === "abort" ) {
8522								xhr.abort();
8523							} else if ( type === "error" ) {
8524								complete(
8525									// file: protocol always yields status 0; see #8605, #14207
8526									xhr.status,
8527									xhr.statusText
8528								);
8529							} else {
8530								complete(
8531									xhrSuccessStatus[ xhr.status ] || xhr.status,
8532									xhr.statusText,
8533									// Support: IE9
8534									// Accessing binary-data responseText throws an exception
8535									// (#11426)
8536									typeof xhr.responseText === "string" ? {
8537										text: xhr.responseText
8538									} : undefined,
8539									xhr.getAllResponseHeaders()
8540								);
8541							}
8542						}
8543					};
8544				};
8545
8546				// Listen to events
8547				xhr.onload = callback();
8548				xhr.onerror = callback("error");
8549
8550				// Create the abort callback
8551				callback = xhrCallbacks[ id ] = callback("abort");
8552
8553				// Do send the request
8554				// This may raise an exception which is actually
8555				// handled in jQuery.ajax (so no try/catch here)
8556				xhr.send( options.hasContent && options.data || null );
8557			},
8558
8559			abort: function() {
8560				if ( callback ) {
8561					callback();
8562				}
8563			}
8564		};
8565	}
8566});
8567
8568
8569
8570
8571// Install script dataType
8572jQuery.ajaxSetup({
8573	accepts: {
8574		script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
8575	},
8576	contents: {
8577		script: /(?:java|ecma)script/
8578	},
8579	converters: {
8580		"text script": function( text ) {
8581			jQuery.globalEval( text );
8582			return text;
8583		}
8584	}
8585});
8586
8587// Handle cache's special case and crossDomain
8588jQuery.ajaxPrefilter( "script", function( s ) {
8589	if ( s.cache === undefined ) {
8590		s.cache = false;
8591	}
8592	if ( s.crossDomain ) {
8593		s.type = "GET";
8594	}
8595});
8596
8597// Bind script tag hack transport
8598jQuery.ajaxTransport( "script", function( s ) {
8599	// This transport only deals with cross domain requests
8600	if ( s.crossDomain ) {
8601		var script, callback;
8602		return {
8603			send: function( _, complete ) {
8604				script = jQuery("<script>").prop({
8605					async: true,
8606					charset: s.scriptCharset,
8607					src: s.url
8608				}).on(
8609					"load error",
8610					callback = function( evt ) {
8611						script.remove();
8612						callback = null;
8613						if ( evt ) {
8614							complete( evt.type === "error" ? 404 : 200, evt.type );
8615						}
8616					}
8617				);
8618				document.head.appendChild( script[ 0 ] );
8619			},
8620			abort: function() {
8621				if ( callback ) {
8622					callback();
8623				}
8624			}
8625		};
8626	}
8627});
8628
8629
8630
8631
8632var oldCallbacks = [],
8633	rjsonp = /(=)\?(?=&|$)|\?\?/;
8634
8635// Default jsonp settings
8636jQuery.ajaxSetup({
8637	jsonp: "callback",
8638	jsonpCallback: function() {
8639		var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) );
8640		this[ callback ] = true;
8641		return callback;
8642	}
8643});
8644
8645// Detect, normalize options and install callbacks for jsonp requests
8646jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
8647
8648	var callbackName, overwritten, responseContainer,
8649		jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
8650			"url" :
8651			typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data"
8652		);
8653
8654	// Handle iff the expected data type is "jsonp" or we have a parameter to set
8655	if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
8656
8657		// Get callback name, remembering preexisting value associated with it
8658		callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
8659			s.jsonpCallback() :
8660			s.jsonpCallback;
8661
8662		// Insert callback into url or form data
8663		if ( jsonProp ) {
8664			s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
8665		} else if ( s.jsonp !== false ) {
8666			s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
8667		}
8668
8669		// Use data converter to retrieve json after script execution
vendor: 1,849 bytes, lines 8670-8739
8670		s.converters["script json"] = function() {
8671			if ( !responseContainer ) {
8672				jQuery.error( callbackName + " was not called" );
8673			}
8674			return responseContainer[ 0 ];
8675		};
8676
8677		// force json dataType
8678		s.dataTypes[ 0 ] = "json";
8679
8680		// Install callback
8681		overwritten = window[ callbackName ];
8682		window[ callbackName ] = function() {
8683			responseContainer = arguments;
8684		};
8685
8686		// Clean-up function (fires after converters)
8687		jqXHR.always(function() {
8688			// Restore preexisting value
8689			window[ callbackName ] = overwritten;
8690
8691			// Save back as free
8692			if ( s[ callbackName ] ) {
8693				// make sure that re-using the options doesn't screw things around
8694				s.jsonpCallback = originalSettings.jsonpCallback;
8695
8696				// save the callback name for future use
8697				oldCallbacks.push( callbackName );
8698			}
8699
8700			// Call if it was a function and we have a response
8701			if ( responseContainer && jQuery.isFunction( overwritten ) ) {
8702				overwritten( responseContainer[ 0 ] );
8703			}
8704
8705			responseContainer = overwritten = undefined;
8706		});
8707
8708		// Delegate to script
8709		return "script";
8710	}
8711});
8712
8713
8714
8715
8716// data: string of html
8717// context (optional): If specified, the fragment will be created in this context, defaults to document
8718// keepScripts (optional): If true, will include scripts passed in the html string
8719jQuery.parseHTML = function( data, context, keepScripts ) {
8720	if ( !data || typeof data !== "string" ) {
8721		return null;
8722	}
8723	if ( typeof context === "boolean" ) {
8724		keepScripts = context;
8725		context = false;
8726	}
8727	context = context || document;
8728
8729	var parsed = rsingleTag.exec( data ),
8730		scripts = !keepScripts && [];
8731
8732	// Single tag
8733	if ( parsed ) {
8734		return [ context.createElement( parsed[1] ) ];
8735	}
8736
8737	parsed = jQuery.buildFragment( [ data ], context, scripts );
8738
8739	if ( scripts && scripts.length ) {
vendor: 13,330 bytes, lines 8740-9193
8740		jQuery( scripts ).remove();
8741	}
8742
8743	return jQuery.merge( [], parsed.childNodes );
8744};
8745
8746
8747// Keep a copy of the old load method
8748var _load = jQuery.fn.load;
8749
8750/**
8751 * Load a url into a page
8752 */
8753jQuery.fn.load = function( url, params, callback ) {
8754	if ( typeof url !== "string" && _load ) {
8755		return _load.apply( this, arguments );
8756	}
8757
8758	var selector, type, response,
8759		self = this,
8760		off = url.indexOf(" ");
8761
8762	if ( off >= 0 ) {
8763		selector = url.slice( off );
8764		url = url.slice( 0, off );
8765	}
8766
8767	// If it's a function
8768	if ( jQuery.isFunction( params ) ) {
8769
8770		// We assume that it's the callback
8771		callback = params;
8772		params = undefined;
8773
8774	// Otherwise, build a param string
8775	} else if ( params && typeof params === "object" ) {
8776		type = "POST";
8777	}
8778
8779	// If we have elements to modify, make the request
8780	if ( self.length > 0 ) {
8781		jQuery.ajax({
8782			url: url,
8783
8784			// if "type" variable is undefined, then "GET" method will be used
8785			type: type,
8786			dataType: "html",
8787			data: params
8788		}).done(function( responseText ) {
8789
8790			// Save response for use in complete callback
8791			response = arguments;
8792
8793			self.html( selector ?
8794
8795				// If a selector was specified, locate the right elements in a dummy div
8796				// Exclude scripts to avoid IE 'Permission Denied' errors
8797				jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) :
8798
8799				// Otherwise use the full result
8800				responseText );
8801
8802		}).complete( callback && function( jqXHR, status ) {
8803			self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
8804		});
8805	}
8806
8807	return this;
8808};
8809
8810
8811
8812
8813jQuery.expr.filters.animated = function( elem ) {
8814	return jQuery.grep(jQuery.timers, function( fn ) {
8815		return elem === fn.elem;
8816	}).length;
8817};
8818
8819
8820
8821
8822var docElem = window.document.documentElement;
8823
8824/**
8825 * Gets a window from an element
8826 */
8827function getWindow( elem ) {
8828	return jQuery.isWindow( elem ) ? elem : elem.nodeType === 9 && elem.defaultView;
8829}
8830
8831jQuery.offset = {
8832	setOffset: function( elem, options, i ) {
8833		var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
8834			position = jQuery.css( elem, "position" ),
8835			curElem = jQuery( elem ),
8836			props = {};
8837
8838		// Set position first, in-case top/left are set even on static elem
8839		if ( position === "static" ) {
8840			elem.style.position = "relative";
8841		}
8842
8843		curOffset = curElem.offset();
8844		curCSSTop = jQuery.css( elem, "top" );
8845		curCSSLeft = jQuery.css( elem, "left" );
8846		calculatePosition = ( position === "absolute" || position === "fixed" ) &&
8847			( curCSSTop + curCSSLeft ).indexOf("auto") > -1;
8848
8849		// Need to be able to calculate position if either top or left is auto and position is either absolute or fixed
8850		if ( calculatePosition ) {
8851			curPosition = curElem.position();
8852			curTop = curPosition.top;
8853			curLeft = curPosition.left;
8854
8855		} else {
8856			curTop = parseFloat( curCSSTop ) || 0;
8857			curLeft = parseFloat( curCSSLeft ) || 0;
8858		}
8859
8860		if ( jQuery.isFunction( options ) ) {
8861			options = options.call( elem, i, curOffset );
8862		}
8863
8864		if ( options.top != null ) {
8865			props.top = ( options.top - curOffset.top ) + curTop;
8866		}
8867		if ( options.left != null ) {
8868			props.left = ( options.left - curOffset.left ) + curLeft;
8869		}
8870
8871		if ( "using" in options ) {
8872			options.using.call( elem, props );
8873
8874		} else {
8875			curElem.css( props );
8876		}
8877	}
8878};
8879
8880jQuery.fn.extend({
8881	offset: function( options ) {
8882		if ( arguments.length ) {
8883			return options === undefined ?
8884				this :
8885				this.each(function( i ) {
8886					jQuery.offset.setOffset( this, options, i );
8887				});
8888		}
8889
8890		var docElem, win,
8891			elem = this[ 0 ],
8892			box = { top: 0, left: 0 },
8893			doc = elem && elem.ownerDocument;
8894
8895		if ( !doc ) {
8896			return;
8897		}
8898
8899		docElem = doc.documentElement;
8900
8901		// Make sure it's not a disconnected DOM node
8902		if ( !jQuery.contains( docElem, elem ) ) {
8903			return box;
8904		}
8905
8906		// If we don't have gBCR, just use 0,0 rather than error
8907		// BlackBerry 5, iOS 3 (original iPhone)
8908		if ( typeof elem.getBoundingClientRect !== strundefined ) {
8909			box = elem.getBoundingClientRect();
8910		}
8911		win = getWindow( doc );
8912		return {
8913			top: box.top + win.pageYOffset - docElem.clientTop,
8914			left: box.left + win.pageXOffset - docElem.clientLeft
8915		};
8916	},
8917
8918	position: function() {
8919		if ( !this[ 0 ] ) {
8920			return;
8921		}
8922
8923		var offsetParent, offset,
8924			elem = this[ 0 ],
8925			parentOffset = { top: 0, left: 0 };
8926
8927		// Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent
8928		if ( jQuery.css( elem, "position" ) === "fixed" ) {
8929			// We assume that getBoundingClientRect is available when computed position is fixed
8930			offset = elem.getBoundingClientRect();
8931
8932		} else {
8933			// Get *real* offsetParent
8934			offsetParent = this.offsetParent();
8935
8936			// Get correct offsets
8937			offset = this.offset();
8938			if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
8939				parentOffset = offsetParent.offset();
8940			}
8941
8942			// Add offsetParent borders
8943			parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
8944			parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
8945		}
8946
8947		// Subtract parent offsets and element margins
8948		return {
8949			top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
8950			left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true )
8951		};
8952	},
8953
8954	offsetParent: function() {
8955		return this.map(function() {
8956			var offsetParent = this.offsetParent || docElem;
8957
8958			while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position" ) === "static" ) ) {
8959				offsetParent = offsetParent.offsetParent;
8960			}
8961
8962			return offsetParent || docElem;
8963		});
8964	}
8965});
8966
8967// Create scrollLeft and scrollTop methods
8968jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
8969	var top = "pageYOffset" === prop;
8970
8971	jQuery.fn[ method ] = function( val ) {
8972		return access( this, function( elem, method, val ) {
8973			var win = getWindow( elem );
8974
8975			if ( val === undefined ) {
8976				return win ? win[ prop ] : elem[ method ];
8977			}
8978
8979			if ( win ) {
8980				win.scrollTo(
8981					!top ? val : window.pageXOffset,
8982					top ? val : window.pageYOffset
8983				);
8984
8985			} else {
8986				elem[ method ] = val;
8987			}
8988		}, method, val, arguments.length, null );
8989	};
8990});
8991
8992// Add the top/left cssHooks using jQuery.fn.position
8993// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
8994// getComputedStyle returns percent when specified for top/left/bottom/right
8995// rather than make the css module depend on the offset module, we just check for it here
8996jQuery.each( [ "top", "left" ], function( i, prop ) {
8997	jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
8998		function( elem, computed ) {
8999			if ( computed ) {
9000				computed = curCSS( elem, prop );
9001				// if curCSS returns percentage, fallback to offset
9002				return rnumnonpx.test( computed ) ?
9003					jQuery( elem ).position()[ prop ] + "px" :
9004					computed;
9005			}
9006		}
9007	);
9008});
9009
9010
9011// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
9012jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
9013	jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
9014		// margin is only for outerHeight, outerWidth
9015		jQuery.fn[ funcName ] = function( margin, value ) {
9016			var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
9017				extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
9018
9019			return access( this, function( elem, type, value ) {
9020				var doc;
9021
9022				if ( jQuery.isWindow( elem ) ) {
9023					// As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
9024					// isn't a whole lot we can do. See pull request at this URL for discussion:
9025					// https://github.com/jquery/jquery/pull/764
9026					return elem.document.documentElement[ "client" + name ];
9027				}
9028
9029				// Get document width or height
9030				if ( elem.nodeType === 9 ) {
9031					doc = elem.documentElement;
9032
9033					// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],
9034					// whichever is greatest
9035					return Math.max(
9036						elem.body[ "scroll" + name ], doc[ "scroll" + name ],
9037						elem.body[ "offset" + name ], doc[ "offset" + name ],
9038						doc[ "client" + name ]
9039					);
9040				}
9041
9042				return value === undefined ?
9043					// Get width or height on the element, requesting but not forcing parseFloat
9044					jQuery.css( elem, type, extra ) :
9045
9046					// Set width or height on the element
9047					jQuery.style( elem, type, value, extra );
9048			}, type, chainable ? margin : undefined, chainable, null );
9049		};
9050	});
9051});
9052
9053
9054// The number of elements contained in the matched element set
9055jQuery.fn.size = function() {
9056	return this.length;
9057};
9058
9059jQuery.fn.andSelf = jQuery.fn.addBack;
9060
9061
9062
9063
9064// Register as a named AMD module, since jQuery can be concatenated with other
9065// files that may use define, but not via a proper concatenation script that
9066// understands anonymous AMD modules. A named AMD is safest and most robust
9067// way to register. Lowercase jquery is used because AMD module names are
9068// derived from file names, and jQuery is normally delivered in a lowercase
9069// file name. Do this after creating the global so that if an AMD module wants
9070// to call noConflict to hide this version of jQuery, it will work.
9071if ( typeof define === "function" && define.amd ) {
9072	define( "jquery", [], function() {
9073		return jQuery;
9074	});
9075}
9076
9077
9078
9079
9080var
9081	// Map over jQuery in case of overwrite
9082	_jQuery = window.jQuery,
9083
9084	// Map over the $ in case of overwrite
9085	_$ = window.$;
9086
9087jQuery.noConflict = function( deep ) {
9088	if ( window.$ === jQuery ) {
9089		window.$ = _$;
9090	}
9091
9092	if ( deep && window.jQuery === jQuery ) {
9093		window.jQuery = _jQuery;
9094	}
9095
9096	return jQuery;
9097};
9098
9099// Expose jQuery and $ identifiers, even in
9100// AMD (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
9101// and CommonJS for browser emulators (#13566)
9102if ( typeof noGlobal === strundefined ) {
9103	window.jQuery = window.$ = jQuery;
9104}
9105
9106
9107
9108
9109return jQuery;
9110
9111}));
9112
9113
9114
9115let bililiteRange; // create one global variable
9116
9117(function(){
9118	
9119const datakey = Symbol(); // use as the key to modify elements.
9120
9121bililiteRange = function(el){
9122	var ret;
9123	if (el.setSelectionRange){
9124		// Element is an input or textarea 
9125		// note that some input elements do not allow selections
9126		try{
9127			el.selectionStart = el.selectionStart;
9128			ret = new InputRange();
9129		}catch(e){
9130			ret = new NothingRange();
9131		}
9132	}else{
9133		// Standards, with any other kind of element
9134		ret = new W3CRange();
9135	}
9136	ret._el = el;
9137	// determine parent document, as implemented by John McLear <[email protected]>
9138	ret._doc = el.ownerDocument;
9139	ret._win = ret._doc.defaultView;
9140	ret._bounds = [0, ret.length];
9141	
9142	// selection tracking. We want clicks to set the selection to the clicked location but tabbing in or element.focus() should restore
9143	// the selection to what it was.
9144	// There's no good way to do this. I just assume that a mousedown (or a drag and drop
9145	// into the element) within 100 ms of the focus event must have caused the focus, and
9146	// therefore we should not restore the selection.
9147	if (!(el[datakey])){ // we haven't processed this element yet	
9148		const data = createDataObject (el);
9149		startupHooks.forEach ( hook => hook (el, ret, data) );
9150	}	
9151	return ret;
9152}
9153
9154bililiteRange.version = 3.2;
9155
9156const startupHooks = new Set();
9157bililiteRange.addStartupHook = fn => startupHooks.add(fn);
9158startupHooks.add (trackSelection);
9159startupHooks.add (fixInputEvents);
9160startupHooks.add (correctNewlines);
9161
9162function trackSelection (element, range, data){
9163	data.selection = [0,0];
9164	range.listen('focusout', evt => data.selection = range._nativeSelection() );	
9165	range.listen('mousedown', evt => data.mousetime = evt.timeStamp );
9166	range.listen('drop', evt => data.mousetime = evt.timeStamp );
9167	range.listen('focus', evt => {
9168		if ('mousetime' in data && evt.timeStamp - data.mousetime < 100) return;
9169		range._nativeSelect(range._nativeRange(data.selection))
9170	})
9171}
9172
9173function fixInputEvents (element, range, data){
9174	// DOM 3 input events, https://www.w3.org/TR/input-events-1/
9175	// have a data field with the text inserted, but thatisn't enough to fully describe the change;
9176	// we need to know the old text (or at least its length)
9177	// and *where* the new text was inserted.
9178	// So we enhance input events with that information. 
9179	// the "newText" should always be the same as the 'data' field, if it is defined
9180	data.oldText = range.all();
9181	data.liveRanges = new Set();
9182	range.listen('input', evt => {
9183		const newText = range.all();
9184		if (!evt.bililiteRange){
9185			evt.bililiteRange = diff (data.oldText, newText);
9186			if (evt.bililiteRange.unchanged){
9187				// no change. Assume that whatever happened, happened at the selection point (and use whatever data the browser gives us).
9188				evt.bililiteRange.start = range.clone().bounds('selection')[1] - (evt.data || '').length;
9189			}
9190		}
9191		data.oldText = newText;
9192		
9193		// Also update live ranges on this element
9194		data.liveRanges.forEach( rng => {
9195			const start = evt.bililiteRange.start;
9196			const oldend = start + evt.bililiteRange.oldText.length;
9197			const newend = start + evt.bililiteRange.newText.length;
9198			// adjust bounds; this tries to emulate the algorithm that Microsoft Word uses for bookmarks
9199			let [b0, b1] = rng.bounds();
9200			if (b0 <= start){
9201				// no change
9202			}else if (b0 > oldend){
9203				b0  += newend - oldend;
9204			}else{
9205				b0  = newend;
9206			}
9207			if (b1 < start){
9208				// no change
9209			}else if (b1 >= oldend){
9210				b1 += newend - oldend;
9211			}else{
9212				b1 = start;
9213			}
9214			rng.bounds([b0, b1]);				
9215		})
9216	});
9217}
9218
9219function diff (oldText, newText){
9220	// Try to find the changed text, assuming it was a continuous change
9221	if (oldText == newText){
9222		return {
9223			unchanged: true,
9224			start: 0,
9225			oldText,
9226			newText
9227		}
9228	}
9229
9230	const oldlen = oldText.length;
9231	const	newlen = newText.length;
9232	for (var i = 0; i < newlen && i < oldlen; ++i){
9233		if (newText.charAt(i) != oldText.charAt(i)) break;
9234	}
9235	const start = i;
9236	for (i = 0; i < newlen && i < oldlen; ++i){
9237		let newpos = newlen-i-1, oldpos = oldlen-i-1;
9238		if (newpos < start || oldpos < start) break;
9239		if (newText.charAt(newpos) != oldText.charAt(oldpos)) break;
9240	}
9241	const oldend = oldlen-i;
9242	const newend = newlen-i;
9243	return {
9244		start,
9245		oldText: oldText.slice(start, oldend),
9246		newText: newText.slice(start, newend)
9247	}
9248};
9249bililiteRange.diff = diff; // expose
9250
9251function correctNewlines (element, range, data){
9252	// we need to insert newlines rather than create new elements, so character-based calculations work
9253	range.listen('paste', evt => {
9254		if (evt.defaultPrevented) return;
9255		// windows adds \r's to clipboard!
9256		range.clone().bounds('selection').
9257			text(evt.clipboardData.getData("text/plain").replace(/\r/g,''), {inputType: 'insertFromPaste'}).
9258			bounds('endbounds').
9259			select().
9260			scrollIntoView();
9261		evt.preventDefault();
9262	});
9263	range.listen('keydown', function(evt){
9264		if (evt.ctrlKey || evt.altKey || evt.shiftKey || evt.metaKey) return;
9265		if (evt.defaultPrevented) return;
9266		if (evt.key == 'Enter'){
9267			range.clone().bounds('selection').
9268				text('\n', {inputType: 'insertLineBreak'}).
9269				bounds('endbounds').
9270				select().
9271				scrollIntoView();
9272			evt.preventDefault();
9273		}
9274	});
9275}
9276
9277// convenience function for defining input events
9278function inputEventInit(type, oldText, newText, start, inputType){
9279	return {
9280		type,
9281		inputType,
9282		data: newText,
9283		bubbles: true,
9284		bililiteRange: {
9285			unchanged: (oldText == newText),
9286			start,
9287			oldText,
9288			newText
9289		}
9290	};
9291}
9292
9293// base class
9294function Range(){}
9295Range.prototype = {
9296	 // allow use of range[0] and range[1] for start and end of bounds 
9297	get 0(){
9298		return this.bounds()[0];
9299	},
9300	set 0(x){
9301		this.bounds([x, this[1]]);
9302		return x;
9303	},
9304	get 1(){
9305		return this.bounds()[1];
9306	},
9307	set 1(x){
9308		this.bounds([this[0], x]);
9309		return x;
9310	},
9311	all: function(text){
9312		if (arguments.length){
9313			return this.bounds('all').text(text, {inputType: 'insertReplacementText'});
9314		}else{
9315			return this._el[this._textProp];
9316		}
9317	},
9318	bounds: function(s){
9319		if (typeof s === 'number'){
9320			this._bounds = [s,s];
9321		}else if (bililiteRange.bounds[s]){
9322			this.bounds(bililiteRange.bounds[s].apply(this, arguments));
9323		}else if (s && s.bounds){
9324			this._bounds = s.bounds(); // copy bounds from an existing range
9325		}else if (s){
9326			this._bounds = s; // don't do error checking now; things may change at a moment's notice
9327		}else{
9328			// constrain bounds now
9329			var b = [
9330				Math.max(0, Math.min (this.length, this._bounds[0])),
9331				Math.max(0, Math.min (this.length, this._bounds[1]))
9332			];
9333			b[1] = Math.max(b[0], b[1]);
9334			return b;
9335		}
9336		return this; // allow for chaining
9337	},
9338	clone: function(){
9339		return bililiteRange(this._el).bounds(this.bounds());
9340	},
9341	get data(){
9342		return this._el[datakey];
9343	},
9344	dispatch: function(opts = {}){
9345		var event = new Event (opts.type, opts);
9346		event.view = this._win;
9347		for (let prop in opts) try { event[prop] = opts[prop] } catch(e){}; // ignore read-only errors for properties that were copied in the previous line
9348		this._el.dispatchEvent(event); // note that the event handlers will be called synchronously, before the "return this;"
9349		return this;
9350	},
9351	get document() {
9352		return this._doc;
9353	},
9354	dontlisten: function (type, func = console.log){
9355		this._el.removeEventListener(type, func);
9356		return this;
9357	},
9358	get element() {
9359		return this._el
9360	},
9361	get length() {
9362		return this._el[this._textProp].length;
9363	},
9364	live (on = true){
9365		this.data.liveRanges[on ? 'add' : 'delete'](this);
9366		return this;
9367	},
9368	listen: function (type, func = console.log){
9369		this._el.addEventListener(type, func);
9370		return this;
9371	},
9372	scrollIntoView: function(scroller = (top => this._el.scrollTop = top) ){
9373		var top = this.top();
9374		// scroll into position if necessary
9375		if (this._el.scrollTop > top || this._el.scrollTop+this._el.clientHeight < top){
9376			scroller.call(this._el, top);
9377		}
9378		return this;
9379	},
9380	select: function(){
9381		var b = this.data.selection = this.bounds();
9382		if (this._el === this._doc.activeElement){
9383			// only actually select if this element is active!
9384			this._nativeSelect(this._nativeRange(b));
9385		}
9386		this.dispatch({type: 'select', bubbles: true});
9387		return this; // allow for chaining
9388	},
9389	selection: function(text){
9390		if (arguments.length){
9391			return this.bounds('selection').text(text).bounds('endbounds').select();
9392		}else{
9393			return this.bounds('selection').text();
9394		}
9395	},
9396	sendkeys: function (text){
9397		this.data.sendkeysOriginalText = this.text();
9398		this.data.sendkeysBounds = undefined;
9399		function simplechar (rng, c){
9400			if (/^{[^}]*}$/.test(c)) c = c.slice(1,-1);	// deal with unknown {key}s
9401			rng.text(c).bounds('endbounds');
9402		}
9403		text.replace(/{[^}]*}|[^{]+|{/g, part => (bililiteRange.sendkeys[part] || simplechar)(this, part, simplechar) );
9404		this.bounds(this.data.sendkeysBounds);
9405		this.dispatch({type: 'sendkeys', detail: text});
9406		return this;
9407	},
9408	text: function(text, {inputType = 'insertText'} = {}){
9409		if ( text !== undefined ){
9410			let eventparams = [this.text(), text, this[0], inputType];
9411			this.dispatch (inputEventInit('beforeinput',...eventparams));
9412			this._nativeSetText(text, this._nativeRange(this.bounds()));
9413			this[1] = this[0]+text.length;
9414			this.dispatch (inputEventInit('input',...eventparams));
9415			return this; // allow for chaining
9416		}else{
9417			return this._nativeGetText(this._nativeRange(this.bounds()));
9418		}
9419	},
9420	top: function(){
9421		return this._nativeTop(this._nativeRange(this.bounds()));
9422	},
9423	get window() {
9424		return this._win;
9425	},
9426	wrap: function (n){
9427		this._nativeWrap(n, this._nativeRange(this.bounds()));
9428		return this;
9429	},
9430};
9431
9432// allow extensions ala jQuery
9433bililiteRange.prototype = Range.prototype;
9434bililiteRange.extend = function(fns){
9435	Object.assign(bililiteRange.prototype, fns);
9436};
9437
9438bililiteRange.override = (name, fn) => {
9439	const oldfn = bililiteRange.prototype[name];
9440	bililiteRange.prototype[name] = function(){
9441		const oldsuper = this.super;
9442		this.super = oldfn;
9443		const ret = fn.apply(this, arguments);
9444		this.super = oldsuper;
9445		return ret;
9446	};
9447}
9448
9449//bounds functions
9450bililiteRange.bounds = {
9451	all: function() { return [0, this.length] },
9452	start: function() { return 0 },
9453	end: function() { return this.length },
9454	selection: function() {
9455		if (this._el === this._doc.activeElement){
9456			this.bounds ('all'); // first select the whole thing for constraining
9457			return this._nativeSelection();
9458		}else{
9459			return this.data.selection;
9460		}
9461	},
9462	startbounds: function() { return  this[0] },
9463	endbounds: function() { return  this[1] },
9464	union: function (name,...rest) {
9465		const b = this.clone().bounds(...rest);
9466		return [ Math.min(this[0], b[0]), Math.max(this[1], b[1]) ];
9467	},
9468	intersection: function (name,...rest) {
9469		const b = this.clone().bounds(...rest);
9470		return [ Math.max(this[0], b[0]), Math.min(this[1], b[1]) ];
9471	}
9472};
9473
9474// sendkeys functions
9475bililiteRange.sendkeys = {
9476	'{tab}': function (rng, c, simplechar){
9477		simplechar(rng, '\t'); // useful for inserting what would be whitespace
9478	},
9479	'{newline}': function (rng){
9480		rng.text('\n', {inputType: 'insertLineBreak'}).bounds('endbounds');
9481	},
9482	'{backspace}': function (rng){
9483		var b = rng.bounds();
9484		if (b[0] == b[1]) rng.bounds([b[0]-1, b[0]]); // no characters selected; it's just an insertion point. Remove the previous character
9485		rng.text('', {inputType: 'deleteContentBackward'}); // delete the characters and update the selection
9486	},
9487	'{del}': function (rng){
9488		var b = rng.bounds();
9489		if (b[0] == b[1]) rng.bounds([b[0], b[0]+1]); // no characters selected; it's just an insertion point. Remove the next character
9490		rng.text('', {inputType: 'deleteContentForward'}).bounds('endbounds'); // delete the characters and update the selection
9491	},
9492	'{rightarrow}':  function (rng){
9493		var b = rng.bounds();
9494		if (b[0] == b[1]) ++b[1]; // no characters selected; it's just an insertion point. Move to the right
9495		rng.bounds([b[1], b[1]]);
9496	},
9497	'{leftarrow}': function (rng){
9498		var b = rng.bounds();
9499		if (b[0] == b[1]) --b[0]; // no characters selected; it's just an insertion point. Move to the left
9500		rng.bounds([b[0], b[0]]);
9501	},
9502	'{selectall}': function (rng){
9503		rng.bounds('all');
9504	},
9505	'{selection}': function (rng){
9506		// insert the characters without the sendkeys processing
9507		rng.text(rng.data.sendkeysOriginalText).bounds('endbounds');
9508	},
9509	'{mark}': function (rng){
9510		rng.data.sendkeysBounds = rng.bounds();
9511	}
9512};
9513// Synonyms from the DOM standard (http://www.w3.org/TR/DOM-Level-3-Events-key/)
9514bililiteRange.sendkeys['{Enter}'] = bililiteRange.sendkeys['{enter}'] = bililiteRange.sendkeys['{newline}'];
9515bililiteRange.sendkeys['{Backspace}'] = bililiteRange.sendkeys['{backspace}'];
9516bililiteRange.sendkeys['{Delete}'] = bililiteRange.sendkeys['{del}'];
9517bililiteRange.sendkeys['{ArrowRight}'] = bililiteRange.sendkeys['{rightarrow}'];
9518bililiteRange.sendkeys['{ArrowLeft}'] = bililiteRange.sendkeys['{leftarrow}'];
9519
9520// an input element in a standards document. "Native Range" is just the bounds array
9521function InputRange(){}
9522InputRange.prototype = new Range();
9523InputRange.prototype._textProp = 'value';
9524InputRange.prototype._nativeRange = function(bounds) {
9525	return bounds || [0, this.length];
9526};
9527InputRange.prototype._nativeSelect = function (rng){
9528	this._el.setSelectionRange(rng[0], rng[1]);
9529};
9530InputRange.prototype._nativeSelection = function(){
9531	return [this._el.selectionStart, this._el.selectionEnd];
9532};
9533InputRange.prototype._nativeGetText = function(rng){
9534	return this._el.value.substring(rng[0], rng[1]);
9535};
9536InputRange.prototype._nativeSetText = function(text, rng){
9537	var val = this._el.value;
9538	this._el.value = val.substring(0, rng[0]) + text + val.substring(rng[1]);
9539};
9540InputRange.prototype._nativeEOL = function(){
9541	this.text('\n');
9542};
9543InputRange.prototype._nativeTop = function(rng){
9544	if (rng[0] == 0) return 0; // the range starts at the top
9545	// I can't remember where I found this clever hack to find the location of text in a text area
9546	var clone = this._el.cloneNode(true);
9547	clone.style.visibility = 'hidden';
9548	clone.style.position = 'absolute';
9549	this._el.parentNode.insertBefore(clone, this._el);
9550	clone.style.height = '1px';
9551	clone.value = this._el.value.slice(0, rng[0]);
9552	var top = clone.scrollHeight;
9553	// this gives the bottom of the text, so we have to subtract the height of a single line
9554	clone.value = 'X';
9555	top -= clone.scrollHeight;
9556	clone.parentNode.removeChild(clone);
9557	return top;
9558}
9559InputRange.prototype._nativeWrap = function() {throw new Error("Cannot wrap in a text element")};
9560
9561function W3CRange(){}
9562W3CRange.prototype = new Range();
9563W3CRange.prototype._textProp = 'textContent';
9564W3CRange.prototype._nativeRange = function (bounds){
9565	var rng = this._doc.createRange();
9566	rng.selectNodeContents(this._el);
9567	if (bounds){
9568		w3cmoveBoundary (rng, bounds[0], true, this._el);
9569		rng.collapse (true);
9570		w3cmoveBoundary (rng, bounds[1]-bounds[0], false, this._el);
9571	}
9572	return rng;					
9573};
9574W3CRange.prototype._nativeSelect = function (rng){
9575	this._win.getSelection().removeAllRanges();
9576	this._win.getSelection().addRange (rng);
9577};
9578W3CRange.prototype._nativeSelection = function (){
9579	// returns [start, end] for the selection constrained to be in element
9580	var rng = this._nativeRange(); // range of the element to constrain to
9581	if (this._win.getSelection().rangeCount == 0) return [this.length, this.length]; // append to the end
9582	var sel = this._win.getSelection().getRangeAt(0);
9583	return [
9584		w3cstart(sel, rng),
9585		w3cend (sel, rng)
9586	];
9587};
9588W3CRange.prototype._nativeGetText = function (rng){
9589	return rng.toString();
9590};
9591W3CRange.prototype._nativeSetText = function (text, rng){
9592	rng.deleteContents();
9593	rng.insertNode (this._doc.createTextNode(text));
9594	this._el.normalize(); // merge the text with the surrounding text
9595};
9596W3CRange.prototype._nativeEOL = function(){
9597	var rng = this._nativeRange(this.bounds());
9598	rng.deleteContents();
9599	var br = this._doc.createElement('br');
9600	br.setAttribute ('_moz_dirty', ''); // for Firefox
9601	rng.insertNode (br);
9602	rng.insertNode (this._doc.createTextNode('\n'));
9603	rng.collapse (false);
9604};
9605W3CRange.prototype._nativeTop = function(rng){
9606	if (this.length == 0) return 0; // no text, no scrolling
9607	if (rng.toString() == ''){
9608		var textnode = this._doc.createTextNode('X');
9609		rng.insertNode (textnode);
9610	}
9611	var startrng = this._nativeRange([0,1]);
9612	var top = rng.getBoundingClientRect().top - startrng.getBoundingClientRect().top;
9613	if (textnode) textnode.parentNode.removeChild(textnode);
9614	return top;
9615}
9616W3CRange.prototype._nativeWrap = function(n, rng) {
9617	rng.surroundContents(n);
9618};
9619
9620// W3C internals
9621function nextnode (node, root){
9622	//  in-order traversal
9623	// we've already visited node, so get kids then siblings
9624	if (node.firstChild) return node.firstChild;
9625	if (node.nextSibling) return node.nextSibling;
9626	if (node===root) return null;
9627	while (node.parentNode){
9628		// get uncles
9629		node = node.parentNode;
9630		if (node == root) return null;
9631		if (node.nextSibling) return node.nextSibling;
9632	}
9633	return null;
9634}
9635function w3cmoveBoundary (rng, n, bStart, el){
9636	// move the boundary (bStart == true ? start : end) n characters forward, up to the end of element el. Forward only!
9637	// if the start is moved after the end, then an exception is raised
9638	if (n <= 0) return;
9639	var node = rng[bStart ? 'startContainer' : 'endContainer'];
9640	if (node.nodeType == 3){
9641	  // we may be starting somewhere into the text
9642	  n += rng[bStart ? 'startOffset' : 'endOffset'];
9643	}
9644	while (node){
9645		if (node.nodeType == 3){
9646			var length = node.nodeValue.length;
9647			if (n <= length){
9648				rng[bStart ? 'setStart' : 'setEnd'](node, n);
9649				// special case: if we end next to a <br>, include that node.
9650				if (n == length){
9651					// skip past zero-length text nodes
9652					for (var next = nextnode (node, el); next && next.nodeType==3 && next.nodeValue.length == 0; next = nextnode(next, el)){
9653						rng[bStart ? 'setStartAfter' : 'setEndAfter'](next);
9654					}
9655					if (next && next.nodeType == 1 && next.nodeName == "BR") rng[bStart ? 'setStartAfter' : 'setEndAfter'](next);
9656				}
9657				return;
9658			}else{
9659				rng[bStart ? 'setStartAfter' : 'setEndAfter'](node); // skip past this one
9660				n -= length; // and eat these characters
9661			}
9662		}
9663		node = nextnode (node, el);
9664	}
9665}
9666var     START_TO_START                 = 0; // from the w3c definitions
9667var     START_TO_END                   = 1;
9668var     END_TO_END                     = 2;
9669var     END_TO_START                   = 3;
9670// from the Mozilla documentation, for range.compareBoundaryPoints(how, sourceRange)
9671// -1, 0, or 1, indicating whether the corresponding boundary-point of range is respectively before, equal to, or after the corresponding boundary-point of sourceRange. 
9672    // * Range.END_TO_END compares the end boundary-point of sourceRange to the end boundary-point of range.
9673    // * Range.END_TO_START compares the end boundary-point of sourceRange to the start boundary-point of range.
9674    // * Range.START_TO_END compares the start boundary-point of sourceRange to the end boundary-point of range.
9675    // * Range.START_TO_START compares the start boundary-point of sourceRange to the start boundary-point of range. 
9676function w3cstart(rng, constraint){
9677	if (rng.compareBoundaryPoints (START_TO_START, constraint) <= 0) return 0; // at or before the beginning
9678	if (rng.compareBoundaryPoints (END_TO_START, constraint) >= 0) return constraint.toString().length;
9679	rng = rng.cloneRange(); // don't change the original
9680	rng.setEnd (constraint.endContainer, constraint.endOffset); // they now end at the same place
9681	return constraint.toString().length - rng.toString().length;
9682}
9683function w3cend (rng, constraint){
9684	if (rng.compareBoundaryPoints (END_TO_END, constraint) >= 0) return constraint.toString().length; // at or after the end
9685	if (rng.compareBoundaryPoints (START_TO_END, constraint) <= 0) return 0;
9686	rng = rng.cloneRange(); // don't change the original
9687	rng.setStart (constraint.startContainer, constraint.startOffset); // they now start at the same place
9688	return rng.toString().length;
9689}
9690
9691function NothingRange(){}
9692NothingRange.prototype = new Range();
9693NothingRange.prototype._textProp = 'value';
9694NothingRange.prototype._nativeRange = function(bounds) {
9695	return bounds || [0,this.length];
9696};
9697NothingRange.prototype._nativeSelect = function (rng){ // do nothing
9698};
9699NothingRange.prototype._nativeSelection = function(){
9700	return [0,0];
9701};
9702NothingRange.prototype._nativeGetText = function (rng){
9703	return this._el[this._textProp].substring(rng[0], rng[1]);
9704};
9705NothingRange.prototype._nativeSetText = function (text, rng){
9706	var val = this._el[this._textProp];
9707	this._el[this._textProp] = val.substring(0, rng[0]) + text + val.substring(rng[1]);
9708};
9709NothingRange.prototype._nativeEOL = function(){
9710	this.text('\n');
9711};
9712NothingRange.prototype._nativeTop = function(){
9713	return 0;
9714};
9715NothingRange.prototype._nativeWrap = function() {throw new Error("Wrapping not implemented")};
9716
9717
9718// data for elements, similar to jQuery data, but allows for monitoring with custom events
9719const monitored = new Set();
9720
9721function signalMonitor(prop, value, element){
9722	const attr = `data-${prop}`;
9723	element.dispatchEvent(new CustomEvent(attr, {bubbles: true, detail: value}));
9724	try{
9725		element.setAttribute (attr, value); // illegal attribute names will throw. Ignore it			
9726	} finally { /* ignore */ }
9727}
9728
9729function createDataObject (el){
9730	return el[datakey] = new Proxy(new Data(el), {
9731		set(obj, prop, value) {
9732			obj[prop] = value;
9733			if (monitored.has(prop)) signalMonitor(prop, value, obj.sourceElement);
9734			return true; // in strict mode, 'set' returns a success flag 
9735		}
9736	});
9737}
9738
9739var Data = function(el) {
9740	Object.defineProperty(this, 'sourceElement', {
9741		value: el
9742	});
9743}
9744
9745Data.prototype = {};
9746// for use with ex options. JSON.stringify(range.data) should return only the options that were
9747// both defined with bililiteRange.option() *and* actually had a value set on this particular data object.
9748// JSON.stringify (range.data.all) should return all the options that were defined.
9749Object.defineProperty(Data.prototype, 'toJSON', {
9750	value: function(){
9751		let ret = {};
9752		for (let key in Data.prototype) if (this.hasOwnProperty(key)) ret[key] = this[key];
9753		return ret;
9754	}
9755});
9756Object.defineProperty(Data.prototype, 'all', {
9757	get: function(){
9758		let ret = {};
9759		for (let key in Data.prototype) ret[key] = this[key];
9760		return ret;
9761	}
9762});
9763Object.defineProperty(Data.prototype, 'trigger', {
9764	value: function(){
9765		monitored.forEach(prop => signalMonitor (prop, this[prop], this.sourceElement));
9766	}
9767});
9768
9769bililiteRange.createOption = function (name, desc = {}){
9770	desc = Object.assign({
9771		enumerable: true, // use these as the defaults
9772		writable: true,
9773		configurable: true
9774	}, Object.getOwnPropertyDescriptor(Data.prototype, name), desc);
9775	if ('monitored' in desc) monitored[desc.monitored ? 'add' : 'delete'](name);
9776	Object.defineProperty(Data.prototype, name, desc);
9777	return Data.prototype[name]; // return the default value
9778}
9779
9780})();
9781
9782define("bililiteRange", ["jquery"], function(){});
9783
9784/* ========================================================================
9785 * Bootstrap: transition.js v3.3.1
9786 * http://getbootstrap.com/javascript/#transitions
9787 * ========================================================================
9788 * Copyright 2011-2014 Twitter, Inc.
9789 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
9790 * ======================================================================== */
9791
9792
9793+function ($) {
9794  'use strict';
9795
vendor: 66,327 bytes, lines 9796-12087
9796  // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
9797  // ============================================================
9798
9799  function transitionEnd() {
9800    var el = document.createElement('bootstrap')
9801
9802    var transEndEventNames = {
9803      WebkitTransition : 'webkitTransitionEnd',
9804      MozTransition    : 'transitionend',
9805      OTransition      : 'oTransitionEnd otransitionend',
9806      transition       : 'transitionend'
9807    }
9808
9809    for (var name in transEndEventNames) {
9810      if (el.style[name] !== undefined) {
9811        return { end: transEndEventNames[name] }
9812      }
9813    }
9814
9815    return false // explicit for ie8 (  ._.)
9816  }
9817
9818  // http://blog.alexmaccaw.com/css-transitions
9819  $.fn.emulateTransitionEnd = function (duration) {
9820    var called = false
9821    var $el = this
9822    $(this).one('bsTransitionEnd', function () { called = true })
9823    var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
9824    setTimeout(callback, duration)
9825    return this
9826  }
9827
9828  $(function () {
9829    $.support.transition = transitionEnd()
9830
9831    if (!$.support.transition) return
9832
9833    $.event.special.bsTransitionEnd = {
9834      bindType: $.support.transition.end,
9835      delegateType: $.support.transition.end,
9836      handle: function (e) {
9837        if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)
9838      }
9839    }
9840  })
9841
9842}(jQuery);
9843
9844define("bootstrapTransition", ["jquery"], (function (global) {
9845    return function () {
9846        var ret, fn;
9847        return ret || global.$;
9848    };
9849}(this)));
9850
9851/* ========================================================================
9852 * Bootstrap: alert.js v3.3.1
9853 * http://getbootstrap.com/javascript/#alerts
9854 * ========================================================================
9855 * Copyright 2011-2014 Twitter, Inc.
9856 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
9857 * ======================================================================== */
9858
9859
9860+function ($) {
9861  'use strict';
9862
9863  // ALERT CLASS DEFINITION
9864  // ======================
9865
9866  var dismiss = '[data-dismiss="alert"]'
9867  var Alert   = function (el) {
9868    $(el).on('click', dismiss, this.close)
9869  }
9870
9871  Alert.VERSION = '3.3.1'
9872
9873  Alert.TRANSITION_DURATION = 150
9874
9875  Alert.prototype.close = function (e) {
9876    var $this    = $(this)
9877    var selector = $this.attr('data-target')
9878
9879    if (!selector) {
9880      selector = $this.attr('href')
9881      selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
9882    }
9883
9884    var $parent = $(selector)
9885
9886    if (e) e.preventDefault()
9887
9888    if (!$parent.length) {
9889      $parent = $this.closest('.alert')
9890    }
9891
9892    $parent.trigger(e = $.Event('close.bs.alert'))
9893
9894    if (e.isDefaultPrevented()) return
9895
9896    $parent.removeClass('in')
9897
9898    function removeElement() {
9899      // detach from parent, fire event then clean up data
9900      $parent.detach().trigger('closed.bs.alert').remove()
9901    }
9902
9903    $.support.transition && $parent.hasClass('fade') ?
9904      $parent
9905        .one('bsTransitionEnd', removeElement)
9906        .emulateTransitionEnd(Alert.TRANSITION_DURATION) :
9907      removeElement()
9908  }
9909
9910
9911  // ALERT PLUGIN DEFINITION
9912  // =======================
9913
9914  function Plugin(option) {
9915    return this.each(function () {
9916      var $this = $(this)
9917      var data  = $this.data('bs.alert')
9918
9919      if (!data) $this.data('bs.alert', (data = new Alert(this)))
9920      if (typeof option == 'string') data[option].call($this)
9921    })
9922  }
9923
9924  var old = $.fn.alert
9925
9926  $.fn.alert             = Plugin
9927  $.fn.alert.Constructor = Alert
9928
9929
9930  // ALERT NO CONFLICT
9931  // =================
9932
9933  $.fn.alert.noConflict = function () {
9934    $.fn.alert = old
9935    return this
9936  }
9937
9938
9939  // ALERT DATA-API
9940  // ==============
9941
9942  $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)
9943
9944}(jQuery);
9945
9946define("bootstrapAlert", ["jquery","bootstrapTransition"], (function (global) {
9947    return function () {
9948        var ret, fn;
9949        return ret || global.$;
9950    };
9951}(this)));
9952
9953/* ========================================================================
9954 * Bootstrap: button.js v3.3.1
9955 * http://getbootstrap.com/javascript/#buttons
9956 * ========================================================================
9957 * Copyright 2011-2014 Twitter, Inc.
9958 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
9959 * ======================================================================== */
9960
9961
9962+function ($) {
9963  'use strict';
9964
9965  // BUTTON PUBLIC CLASS DEFINITION
9966  // ==============================
9967
9968  var Button = function (element, options) {
9969    this.$element  = $(element)
9970    this.options   = $.extend({}, Button.DEFAULTS, options)
9971    this.isLoading = false
9972  }
9973
9974  Button.VERSION  = '3.3.1'
9975
9976  Button.DEFAULTS = {
9977    loadingText: 'loading...'
9978  }
9979
9980  Button.prototype.setState = function (state) {
9981    var d    = 'disabled'
9982    var $el  = this.$element
9983    var val  = $el.is('input') ? 'val' : 'html'
9984    var data = $el.data()
9985
9986    state = state + 'Text'
9987
9988    if (data.resetText == null) $el.data('resetText', $el[val]())
9989
9990    // push to event loop to allow forms to submit
9991    setTimeout($.proxy(function () {
9992      $el[val](data[state] == null ? this.options[state] : data[state])
9993
9994      if (state == 'loadingText') {
9995        this.isLoading = true
9996        $el.addClass(d).attr(d, d)
9997      } else if (this.isLoading) {
9998        this.isLoading = false
9999        $el.removeClass(d).removeAttr(d)
10000      }
10001    }, this), 0)
10002  }
10003
10004  Button.prototype.toggle = function () {
10005    var changed = true
10006    var $parent = this.$element.closest('[data-toggle="buttons"]')
10007
10008    if ($parent.length) {
10009      var $input = this.$element.find('input')
10010      if ($input.prop('type') == 'radio') {
10011        if ($input.prop('checked') && this.$element.hasClass('active')) changed = false
10012        else $parent.find('.active').removeClass('active')
10013      }
10014      if (changed) $input.prop('checked', !this.$element.hasClass('active')).trigger('change')
10015    } else {
10016      this.$element.attr('aria-pressed', !this.$element.hasClass('active'))
10017    }
10018
10019    if (changed) this.$element.toggleClass('active')
10020  }
10021
10022
10023  // BUTTON PLUGIN DEFINITION
10024  // ========================
10025
10026  function Plugin(option) {
10027    return this.each(function () {
10028      var $this   = $(this)
10029      var data    = $this.data('bs.button')
10030      var options = typeof option == 'object' && option
10031
10032      if (!data) $this.data('bs.button', (data = new Button(this, options)))
10033
10034      if (option == 'toggle') data.toggle()
10035      else if (option) data.setState(option)
10036    })
10037  }
10038
10039  var old = $.fn.button
10040
10041  $.fn.button             = Plugin
10042  $.fn.button.Constructor = Button
10043
10044
10045  // BUTTON NO CONFLICT
10046  // ==================
10047
10048  $.fn.button.noConflict = function () {
10049    $.fn.button = old
10050    return this
10051  }
10052
10053
10054  // BUTTON DATA-API
10055  // ===============
10056
10057  $(document)
10058    .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {
10059      var $btn = $(e.target)
10060      if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
10061      Plugin.call($btn, 'toggle')
10062      e.preventDefault()
10063    })
10064    .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) {
10065      $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type))
10066    })
10067
10068}(jQuery);
10069
10070define("bootstrapButton", ["jquery","bootstrapTransition"], (function (global) {
10071    return function () {
10072        var ret, fn;
10073        return ret || global.$;
10074    };
10075}(this)));
10076
10077/* ========================================================================
10078 * Bootstrap: carousel.js v3.3.1
10079 * http://getbootstrap.com/javascript/#carousel
10080 * ========================================================================
10081 * Copyright 2011-2014 Twitter, Inc.
10082 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
10083 * ======================================================================== */
10084
10085
10086+function ($) {
10087  'use strict';
10088
10089  // CAROUSEL CLASS DEFINITION
10090  // =========================
10091
10092  var Carousel = function (element, options) {
10093    this.$element    = $(element)
10094    this.$indicators = this.$element.find('.carousel-indicators')
10095    this.options     = options
10096    this.paused      =
10097    this.sliding     =
10098    this.interval    =
10099    this.$active     =
10100    this.$items      = null
10101
10102    this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this))
10103
10104    this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element
10105      .on('mouseenter.bs.carousel', $.proxy(this.pause, this))
10106      .on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
10107  }
10108
10109  Carousel.VERSION  = '3.3.1'
10110
10111  Carousel.TRANSITION_DURATION = 600
10112
10113  Carousel.DEFAULTS = {
10114    interval: 5000,
10115    pause: 'hover',
10116    wrap: true,
10117    keyboard: true
10118  }
10119
10120  Carousel.prototype.keydown = function (e) {
10121    if (/input|textarea/i.test(e.target.tagName)) return
10122    switch (e.which) {
10123      case 37: this.prev(); break
10124      case 39: this.next(); break
10125      default: return
10126    }
10127
10128    e.preventDefault()
10129  }
10130
10131  Carousel.prototype.cycle = function (e) {
10132    e || (this.paused = false)
10133
10134    this.interval && clearInterval(this.interval)
10135
10136    this.options.interval
10137      && !this.paused
10138      && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
10139
10140    return this
10141  }
10142
10143  Carousel.prototype.getItemIndex = function (item) {
10144    this.$items = item.parent().children('.item')
10145    return this.$items.index(item || this.$active)
10146  }
10147
10148  Carousel.prototype.getItemForDirection = function (direction, active) {
10149    var delta = direction == 'prev' ? -1 : 1
10150    var activeIndex = this.getItemIndex(active)
10151    var itemIndex = (activeIndex + delta) % this.$items.length
10152    return this.$items.eq(itemIndex)
10153  }
10154
10155  Carousel.prototype.to = function (pos) {
10156    var that        = this
10157    var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active'))
10158
10159    if (pos > (this.$items.length - 1) || pos < 0) return
10160
10161    if (this.sliding)       return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid"
10162    if (activeIndex == pos) return this.pause().cycle()
10163
10164    return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos))
10165  }
10166
10167  Carousel.prototype.pause = function (e) {
10168    e || (this.paused = true)
10169
10170    if (this.$element.find('.next, .prev').length && $.support.transition) {
10171      this.$element.trigger($.support.transition.end)
10172      this.cycle(true)
10173    }
10174
10175    this.interval = clearInterval(this.interval)
10176
10177    return this
10178  }
10179
10180  Carousel.prototype.next = function () {
10181    if (this.sliding) return
10182    return this.slide('next')
10183  }
10184
10185  Carousel.prototype.prev = function () {
10186    if (this.sliding) return
10187    return this.slide('prev')
10188  }
10189
10190  Carousel.prototype.slide = function (type, next) {
10191    var $active   = this.$element.find('.item.active')
10192    var $next     = next || this.getItemForDirection(type, $active)
10193    var isCycling = this.interval
10194    var direction = type == 'next' ? 'left' : 'right'
10195    var fallback  = type == 'next' ? 'first' : 'last'
10196    var that      = this
10197
10198    if (!$next.length) {
10199      if (!this.options.wrap) return
10200      $next = this.$element.find('.item')[fallback]()
10201    }
10202
10203    if ($next.hasClass('active')) return (this.sliding = false)
10204
10205    var relatedTarget = $next[0]
10206    var slideEvent = $.Event('slide.bs.carousel', {
10207      relatedTarget: relatedTarget,
10208      direction: direction
10209    })
10210    this.$element.trigger(slideEvent)
10211    if (slideEvent.isDefaultPrevented()) return
10212
10213    this.sliding = true
10214
10215    isCycling && this.pause()
10216
10217    if (this.$indicators.length) {
10218      this.$indicators.find('.active').removeClass('active')
10219      var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)])
10220      $nextIndicator && $nextIndicator.addClass('active')
10221    }
10222
10223    var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid"
10224    if ($.support.transition && this.$element.hasClass('slide')) {
10225      $next.addClass(type)
10226      $next[0].offsetWidth // force reflow
10227      $active.addClass(direction)
10228      $next.addClass(direction)
10229      $active
10230        .one('bsTransitionEnd', function () {
10231          $next.removeClass([type, direction].join(' ')).addClass('active')
10232          $active.removeClass(['active', direction].join(' '))
10233          that.sliding = false
10234          setTimeout(function () {
10235            that.$element.trigger(slidEvent)
10236          }, 0)
10237        })
10238        .emulateTransitionEnd(Carousel.TRANSITION_DURATION)
10239    } else {
10240      $active.removeClass('active')
10241      $next.addClass('active')
10242      this.sliding = false
10243      this.$element.trigger(slidEvent)
10244    }
10245
10246    isCycling && this.cycle()
10247
10248    return this
10249  }
10250
10251
10252  // CAROUSEL PLUGIN DEFINITION
10253  // ==========================
10254
10255  function Plugin(option) {
10256    return this.each(function () {
10257      var $this   = $(this)
10258      var data    = $this.data('bs.carousel')
10259      var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option)
10260      var action  = typeof option == 'string' ? option : options.slide
10261
10262      if (!data) $this.data('bs.carousel', (data = new Carousel(this, options)))
10263      if (typeof option == 'number') data.to(option)
10264      else if (action) data[action]()
10265      else if (options.interval) data.pause().cycle()
10266    })
10267  }
10268
10269  var old = $.fn.carousel
10270
10271  $.fn.carousel             = Plugin
10272  $.fn.carousel.Constructor = Carousel
10273
10274
10275  // CAROUSEL NO CONFLICT
10276  // ====================
10277
10278  $.fn.carousel.noConflict = function () {
10279    $.fn.carousel = old
10280    return this
10281  }
10282
10283
10284  // CAROUSEL DATA-API
10285  // =================
10286
10287  var clickHandler = function (e) {
10288    var href
10289    var $this   = $(this)
10290    var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7
10291    if (!$target.hasClass('carousel')) return
10292    var options = $.extend({}, $target.data(), $this.data())
10293    var slideIndex = $this.attr('data-slide-to')
10294    if (slideIndex) options.interval = false
10295
10296    Plugin.call($target, options)
10297
10298    if (slideIndex) {
10299      $target.data('bs.carousel').to(slideIndex)
10300    }
10301
10302    e.preventDefault()
10303  }
10304
10305  $(document)
10306    .on('click.bs.carousel.data-api', '[data-slide]', clickHandler)
10307    .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler)
10308
10309  $(window).on('load', function () {
10310    $('[data-ride="carousel"]').each(function () {
10311      var $carousel = $(this)
10312      Plugin.call($carousel, $carousel.data())
10313    })
10314  })
10315
10316}(jQuery);
10317
10318define("bootstrapCarousel", ["jquery","bootstrapTransition"], (function (global) {
10319    return function () {
10320        var ret, fn;
10321        return ret || global.$;
10322    };
10323}(this)));
10324
10325/* ========================================================================
10326 * Bootstrap: collapse.js v3.3.1
10327 * http://getbootstrap.com/javascript/#collapse
10328 * ========================================================================
10329 * Copyright 2011-2014 Twitter, Inc.
10330 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
10331 * ======================================================================== */
10332
10333
10334+function ($) {
10335  'use strict';
10336
10337  // COLLAPSE PUBLIC CLASS DEFINITION
10338  // ================================
10339
10340  var Collapse = function (element, options) {
10341    this.$element      = $(element)
10342    this.options       = $.extend({}, Collapse.DEFAULTS, options)
10343    this.$trigger      = $(this.options.trigger).filter('[href="#' + element.id + '"], [data-target="#' + element.id + '"]')
10344    this.transitioning = null
10345
10346    if (this.options.parent) {
10347      this.$parent = this.getParent()
10348    } else {
10349      this.addAriaAndCollapsedClass(this.$element, this.$trigger)
10350    }
10351
10352    if (this.options.toggle) this.toggle()
10353  }
10354
10355  Collapse.VERSION  = '3.3.1'
10356
10357  Collapse.TRANSITION_DURATION = 350
10358
10359  Collapse.DEFAULTS = {
10360    toggle: true,
10361    trigger: '[data-toggle="collapse"]'
10362  }
10363
10364  Collapse.prototype.dimension = function () {
10365    var hasWidth = this.$element.hasClass('width')
10366    return hasWidth ? 'width' : 'height'
10367  }
10368
10369  Collapse.prototype.show = function () {
10370    if (this.transitioning || this.$element.hasClass('in')) return
10371
10372    var activesData
10373    var actives = this.$parent && this.$parent.find('> .panel').children('.in, .collapsing')
10374
10375    if (actives && actives.length) {
10376      activesData = actives.data('bs.collapse')
10377      if (activesData && activesData.transitioning) return
10378    }
10379
10380    var startEvent = $.Event('show.bs.collapse')
10381    this.$element.trigger(startEvent)
10382    if (startEvent.isDefaultPrevented()) return
10383
10384    if (actives && actives.length) {
10385      Plugin.call(actives, 'hide')
10386      activesData || actives.data('bs.collapse', null)
10387    }
10388
10389    var dimension = this.dimension()
10390
10391    this.$element
10392      .removeClass('collapse')
10393      .addClass('collapsing')[dimension](0)
10394      .attr('aria-expanded', true)
10395
10396    this.$trigger
10397      .removeClass('collapsed')
10398      .attr('aria-expanded', true)
10399
10400    this.transitioning = 1
10401
10402    var complete = function () {
10403      this.$element
10404        .removeClass('collapsing')
10405        .addClass('collapse in')[dimension]('')
10406      this.transitioning = 0
10407      this.$element
10408        .trigger('shown.bs.collapse')
10409    }
10410
10411    if (!$.support.transition) return complete.call(this)
10412
10413    var scrollSize = $.camelCase(['scroll', dimension].join('-'))
10414
10415    this.$element
10416      .one('bsTransitionEnd', $.proxy(complete, this))
10417      .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize])
10418  }
10419
10420  Collapse.prototype.hide = function () {
10421    if (this.transitioning || !this.$element.hasClass('in')) return
10422
10423    var startEvent = $.Event('hide.bs.collapse')
10424    this.$element.trigger(startEvent)
10425    if (startEvent.isDefaultPrevented()) return
10426
10427    var dimension = this.dimension()
10428
10429    this.$element[dimension](this.$element[dimension]())[0].offsetHeight
10430
10431    this.$element
10432      .addClass('collapsing')
10433      .removeClass('collapse in')
10434      .attr('aria-expanded', false)
10435
10436    this.$trigger
10437      .addClass('collapsed')
10438      .attr('aria-expanded', false)
10439
10440    this.transitioning = 1
10441
10442    var complete = function () {
10443      this.transitioning = 0
10444      this.$element
10445        .removeClass('collapsing')
10446        .addClass('collapse')
10447        .trigger('hidden.bs.collapse')
10448    }
10449
10450    if (!$.support.transition) return complete.call(this)
10451
10452    this.$element
10453      [dimension](0)
10454      .one('bsTransitionEnd', $.proxy(complete, this))
10455      .emulateTransitionEnd(Collapse.TRANSITION_DURATION)
10456  }
10457
10458  Collapse.prototype.toggle = function () {
10459    this[this.$element.hasClass('in') ? 'hide' : 'show']()
10460  }
10461
10462  Collapse.prototype.getParent = function () {
10463    return $(this.options.parent)
10464      .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]')
10465      .each($.proxy(function (i, element) {
10466        var $element = $(element)
10467        this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element)
10468      }, this))
10469      .end()
10470  }
10471
10472  Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) {
10473    var isOpen = $element.hasClass('in')
10474
10475    $element.attr('aria-expanded', isOpen)
10476    $trigger
10477      .toggleClass('collapsed', !isOpen)
10478      .attr('aria-expanded', isOpen)
10479  }
10480
10481  function getTargetFromTrigger($trigger) {
10482    var href
10483    var target = $trigger.attr('data-target')
10484      || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
10485
10486    return $(target)
10487  }
10488
10489
10490  // COLLAPSE PLUGIN DEFINITION
10491  // ==========================
10492
10493  function Plugin(option) {
10494    return this.each(function () {
10495      var $this   = $(this)
10496      var data    = $this.data('bs.collapse')
10497      var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
10498
10499      if (!data && options.toggle && option == 'show') options.toggle = false
10500      if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
10501      if (typeof option == 'string') data[option]()
10502    })
10503  }
10504
10505  var old = $.fn.collapse
10506
10507  $.fn.collapse             = Plugin
10508  $.fn.collapse.Constructor = Collapse
10509
10510
10511  // COLLAPSE NO CONFLICT
10512  // ====================
10513
10514  $.fn.collapse.noConflict = function () {
10515    $.fn.collapse = old
10516    return this
10517  }
10518
10519
10520  // COLLAPSE DATA-API
10521  // =================
10522
10523  $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
10524    var $this   = $(this)
10525
10526    if (!$this.attr('data-target')) e.preventDefault()
10527
10528    var $target = getTargetFromTrigger($this)
10529    var data    = $target.data('bs.collapse')
10530    var option  = data ? 'toggle' : $.extend({}, $this.data(), { trigger: this })
10531
10532    Plugin.call($target, option)
10533  })
10534
10535}(jQuery);
10536
10537define("bootstrapCollapse", ["jquery","bootstrapTransition"], (function (global) {
10538    return function () {
10539        var ret, fn;
10540        return ret || global.$;
10541    };
10542}(this)));
10543
10544/* ========================================================================
10545 * Bootstrap: dropdown.js v3.3.1
10546 * http://getbootstrap.com/javascript/#dropdowns
10547 * ========================================================================
10548 * Copyright 2011-2014 Twitter, Inc.
10549 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
10550 * ======================================================================== */
10551
10552
10553+function ($) {
10554  'use strict';
10555
10556  // DROPDOWN CLASS DEFINITION
10557  // =========================
10558
10559  var backdrop = '.dropdown-backdrop'
10560  var toggle   = '[data-toggle="dropdown"]'
10561  var Dropdown = function (element) {
10562    $(element).on('click.bs.dropdown', this.toggle)
10563  }
10564
10565  Dropdown.VERSION = '3.3.1'
10566
10567  Dropdown.prototype.toggle = function (e) {
10568    var $this = $(this)
10569
10570    if ($this.is('.disabled, :disabled')) return
10571
10572    var $parent  = getParent($this)
10573    var isActive = $parent.hasClass('open')
10574
10575    clearMenus()
10576
10577    if (!isActive) {
10578      if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
10579        // if mobile we use a backdrop because click events don't delegate
10580        $('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus)
10581      }
10582
10583      var relatedTarget = { relatedTarget: this }
10584      $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
10585
10586      if (e.isDefaultPrevented()) return
10587
10588      $this
10589        .trigger('focus')
10590        .attr('aria-expanded', 'true')
10591
10592      $parent
10593        .toggleClass('open')
10594        .trigger('shown.bs.dropdown', relatedTarget)
10595    }
10596
10597    return false
10598  }
10599
10600  Dropdown.prototype.keydown = function (e) {
10601    if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return
10602
10603    var $this = $(this)
10604
10605    e.preventDefault()
10606    e.stopPropagation()
10607
10608    if ($this.is('.disabled, :disabled')) return
10609
10610    var $parent  = getParent($this)
10611    var isActive = $parent.hasClass('open')
10612
10613    if ((!isActive && e.which != 27) || (isActive && e.which == 27)) {
10614      if (e.which == 27) $parent.find(toggle).trigger('focus')
10615      return $this.trigger('click')
10616    }
10617
10618    var desc = ' li:not(.divider):visible a'
10619    var $items = $parent.find('[role="menu"]' + desc + ', [role="listbox"]' + desc)
10620
10621    if (!$items.length) return
10622
10623    var index = $items.index(e.target)
10624
10625    if (e.which == 38 && index > 0)                 index--                        // up
10626    if (e.which == 40 && index < $items.length - 1) index++                        // down
10627    if (!~index)                                      index = 0
10628
10629    $items.eq(index).trigger('focus')
10630  }
10631
10632  function clearMenus(e) {
10633    if (e && e.which === 3) return
10634    $(backdrop).remove()
10635    $(toggle).each(function () {
10636      var $this         = $(this)
10637      var $parent       = getParent($this)
10638      var relatedTarget = { relatedTarget: this }
10639
10640      if (!$parent.hasClass('open')) return
10641
10642      $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
10643
10644      if (e.isDefaultPrevented()) return
10645
10646      $this.attr('aria-expanded', 'false')
10647      $parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
10648    })
10649  }
10650
10651  function getParent($this) {
10652    var selector = $this.attr('data-target')
10653
10654    if (!selector) {
10655      selector = $this.attr('href')
10656      selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
10657    }
10658
10659    var $parent = selector && $(selector)
10660
10661    return $parent && $parent.length ? $parent : $this.parent()
10662  }
10663
10664
10665  // DROPDOWN PLUGIN DEFINITION
10666  // ==========================
10667
10668  function Plugin(option) {
10669    return this.each(function () {
10670      var $this = $(this)
10671      var data  = $this.data('bs.dropdown')
10672
10673      if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))
10674      if (typeof option == 'string') data[option].call($this)
10675    })
10676  }
10677
10678  var old = $.fn.dropdown
10679
10680  $.fn.dropdown             = Plugin
10681  $.fn.dropdown.Constructor = Dropdown
10682
10683
10684  // DROPDOWN NO CONFLICT
10685  // ====================
10686
10687  $.fn.dropdown.noConflict = function () {
10688    $.fn.dropdown = old
10689    return this
10690  }
10691
10692
10693  // APPLY TO STANDARD DROPDOWN ELEMENTS
10694  // ===================================
10695
10696  $(document)
10697    .on('click.bs.dropdown.data-api', clearMenus)
10698    .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
10699    .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
10700    .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)
10701    .on('keydown.bs.dropdown.data-api', '[role="menu"]', Dropdown.prototype.keydown)
10702    .on('keydown.bs.dropdown.data-api', '[role="listbox"]', Dropdown.prototype.keydown)
10703
10704}(jQuery);
10705
10706define("bootstrapDropdown", ["jquery","bootstrapTransition"], (function (global) {
10707    return function () {
10708        var ret, fn;
10709        return ret || global.$;
10710    };
10711}(this)));
10712
10713/* ========================================================================
10714 * Bootstrap: modal.js v3.3.1
10715 * http://getbootstrap.com/javascript/#modals
10716 * ========================================================================
10717 * Copyright 2011-2014 Twitter, Inc.
10718 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
10719 * ======================================================================== */
10720
10721
10722+function ($) {
10723  'use strict';
10724
10725  // MODAL CLASS DEFINITION
10726  // ======================
10727
10728  var Modal = function (element, options) {
10729    this.options        = options
10730    this.$body          = $(document.body)
10731    this.$element       = $(element)
10732    this.$backdrop      =
10733    this.isShown        = null
10734    this.scrollbarWidth = 0
10735
10736    if (this.options.remote) {
10737      this.$element
10738        .find('.modal-content')
10739        .load(this.options.remote, $.proxy(function () {
10740          this.$element.trigger('loaded.bs.modal')
10741        }, this))
10742    }
10743  }
10744
10745  Modal.VERSION  = '3.3.1'
10746
10747  Modal.TRANSITION_DURATION = 300
10748  Modal.BACKDROP_TRANSITION_DURATION = 150
10749
10750  Modal.DEFAULTS = {
10751    backdrop: true,
10752    keyboard: true,
10753    show: true
10754  }
10755
10756  Modal.prototype.toggle = function (_relatedTarget) {
10757    return this.isShown ? this.hide() : this.show(_relatedTarget)
10758  }
10759
10760  Modal.prototype.show = function (_relatedTarget) {
10761    var that = this
10762    var e    = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
10763
10764    this.$element.trigger(e)
10765
10766    if (this.isShown || e.isDefaultPrevented()) return
10767
10768    this.isShown = true
10769
10770    this.checkScrollbar()
10771    this.setScrollbar()
10772    this.$body.addClass('modal-open')
10773
10774    this.escape()
10775    this.resize()
10776
10777    this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
10778
10779    this.backdrop(function () {
10780      var transition = $.support.transition && that.$element.hasClass('fade')
10781
10782      if (!that.$element.parent().length) {
10783        that.$element.appendTo(that.$body) // don't move modals dom position
10784      }
10785
10786      that.$element
10787        .show()
10788        .scrollTop(0)
10789
10790      if (that.options.backdrop) that.adjustBackdrop()
10791      that.adjustDialog()
10792
10793      if (transition) {
10794        that.$element[0].offsetWidth // force reflow
10795      }
10796
10797      that.$element
10798        .addClass('in')
10799        .attr('aria-hidden', false)
10800
10801      that.enforceFocus()
10802
10803      var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
10804
10805      transition ?
10806        that.$element.find('.modal-dialog') // wait for modal to slide in
10807          .one('bsTransitionEnd', function () {
10808            that.$element.trigger('focus').trigger(e)
10809          })
10810          .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
10811        that.$element.trigger('focus').trigger(e)
10812    })
10813  }
10814
10815  Modal.prototype.hide = function (e) {
10816    if (e) e.preventDefault()
10817
10818    e = $.Event('hide.bs.modal')
10819
10820    this.$element.trigger(e)
10821
10822    if (!this.isShown || e.isDefaultPrevented()) return
10823
10824    this.isShown = false
10825
10826    this.escape()
10827    this.resize()
10828
10829    $(document).off('focusin.bs.modal')
10830
10831    this.$element
10832      .removeClass('in')
10833      .attr('aria-hidden', true)
10834      .off('click.dismiss.bs.modal')
10835
10836    $.support.transition && this.$element.hasClass('fade') ?
10837      this.$element
10838        .one('bsTransitionEnd', $.proxy(this.hideModal, this))
10839        .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
10840      this.hideModal()
10841  }
10842
10843  Modal.prototype.enforceFocus = function () {
10844    $(document)
10845      .off('focusin.bs.modal') // guard against infinite focus loop
10846      .on('focusin.bs.modal', $.proxy(function (e) {
10847        if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {
10848          this.$element.trigger('focus')
10849        }
10850      }, this))
10851  }
10852
10853  Modal.prototype.escape = function () {
10854    if (this.isShown && this.options.keyboard) {
10855      this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) {
10856        e.which == 27 && this.hide()
10857      }, this))
10858    } else if (!this.isShown) {
10859      this.$element.off('keydown.dismiss.bs.modal')
10860    }
10861  }
10862
10863  Modal.prototype.resize = function () {
10864    if (this.isShown) {
10865      $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this))
10866    } else {
10867      $(window).off('resize.bs.modal')
10868    }
10869  }
10870
10871  Modal.prototype.hideModal = function () {
10872    var that = this
10873    this.$element.hide()
10874    this.backdrop(function () {
10875      that.$body.removeClass('modal-open')
10876      that.resetAdjustments()
10877      that.resetScrollbar()
10878      that.$element.trigger('hidden.bs.modal')
10879    })
10880  }
10881
10882  Modal.prototype.removeBackdrop = function () {
10883    this.$backdrop && this.$backdrop.remove()
10884    this.$backdrop = null
10885  }
10886
10887  Modal.prototype.backdrop = function (callback) {
10888    var that = this
10889    var animate = this.$element.hasClass('fade') ? 'fade' : ''
10890
10891    if (this.isShown && this.options.backdrop) {
10892      var doAnimate = $.support.transition && animate
10893
10894      this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
10895        .prependTo(this.$element)
10896        .on('click.dismiss.bs.modal', $.proxy(function (e) {
10897          if (e.target !== e.currentTarget) return
10898          this.options.backdrop == 'static'
10899            ? this.$element[0].focus.call(this.$element[0])
10900            : this.hide.call(this)
10901        }, this))
10902
10903      if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
10904
10905      this.$backdrop.addClass('in')
10906
10907      if (!callback) return
10908
10909      doAnimate ?
10910        this.$backdrop
10911          .one('bsTransitionEnd', callback)
10912          .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
10913        callback()
10914
10915    } else if (!this.isShown && this.$backdrop) {
10916      this.$backdrop.removeClass('in')
10917
10918      var callbackRemove = function () {
10919        that.removeBackdrop()
10920        callback && callback()
10921      }
10922      $.support.transition && this.$element.hasClass('fade') ?
10923        this.$backdrop
10924          .one('bsTransitionEnd', callbackRemove)
10925          .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
10926        callbackRemove()
10927
10928    } else if (callback) {
10929      callback()
10930    }
10931  }
10932
10933  // these following methods are used to handle overflowing modals
10934
10935  Modal.prototype.handleUpdate = function () {
10936    if (this.options.backdrop) this.adjustBackdrop()
10937    this.adjustDialog()
10938  }
10939
10940  Modal.prototype.adjustBackdrop = function () {
10941    this.$backdrop
10942      .css('height', 0)
10943      .css('height', this.$element[0].scrollHeight)
10944  }
10945
10946  Modal.prototype.adjustDialog = function () {
10947    var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight
10948
10949    this.$element.css({
10950      paddingLeft:  !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '',
10951      paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : ''
10952    })
10953  }
10954
10955  Modal.prototype.resetAdjustments = function () {
10956    this.$element.css({
10957      paddingLeft: '',
10958      paddingRight: ''
10959    })
10960  }
10961
10962  Modal.prototype.checkScrollbar = function () {
10963    this.bodyIsOverflowing = document.body.scrollHeight > document.documentElement.clientHeight
10964    this.scrollbarWidth = this.measureScrollbar()
10965  }
10966
10967  Modal.prototype.setScrollbar = function () {
10968    var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
10969    if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)
10970  }
10971
10972  Modal.prototype.resetScrollbar = function () {
10973    this.$body.css('padding-right', '')
10974  }
10975
10976  Modal.prototype.measureScrollbar = function () { // thx walsh
10977    var scrollDiv = document.createElement('div')
10978    scrollDiv.className = 'modal-scrollbar-measure'
10979    this.$body.append(scrollDiv)
10980    var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
10981    this.$body[0].removeChild(scrollDiv)
10982    return scrollbarWidth
10983  }
10984
10985
10986  // MODAL PLUGIN DEFINITION
10987  // =======================
10988
10989  function Plugin(option, _relatedTarget) {
10990    return this.each(function () {
10991      var $this   = $(this)
10992      var data    = $this.data('bs.modal')
10993      var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
10994
10995      if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
10996      if (typeof option == 'string') data[option](_relatedTarget)
10997      else if (options.show) data.show(_relatedTarget)
10998    })
10999  }
11000
11001  var old = $.fn.modal
11002
11003  $.fn.modal             = Plugin
11004  $.fn.modal.Constructor = Modal
11005
11006
11007  // MODAL NO CONFLICT
11008  // =================
11009
11010  $.fn.modal.noConflict = function () {
11011    $.fn.modal = old
11012    return this
11013  }
11014
11015
11016  // MODAL DATA-API
11017  // ==============
11018
11019  $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
11020    var $this   = $(this)
11021    var href    = $this.attr('href')
11022    var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7
11023    var option  = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
11024
11025    if ($this.is('a')) e.preventDefault()
11026
11027    $target.one('show.bs.modal', function (showEvent) {
11028      if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown
11029      $target.one('hidden.bs.modal', function () {
11030        $this.is(':visible') && $this.trigger('focus')
11031      })
11032    })
11033    Plugin.call($target, option, this)
11034  })
11035
11036}(jQuery);
11037
11038define("bootstrapModal", ["jquery","bootstrapTransition"], (function (global) {
11039    return function () {
11040        var ret, fn;
11041        return ret || global.$;
11042    };
11043}(this)));
11044
11045/* ========================================================================
11046 * Bootstrap: tooltip.js v3.3.1
11047 * http://getbootstrap.com/javascript/#tooltip
11048 * Inspired by the original jQuery.tipsy by Jason Frame
11049 * ========================================================================
11050 * Copyright 2011-2014 Twitter, Inc.
11051 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
11052 * ======================================================================== */
11053
11054
11055+function ($) {
11056  'use strict';
11057
11058  // TOOLTIP PUBLIC CLASS DEFINITION
11059  // ===============================
11060
11061  var Tooltip = function (element, options) {
11062    this.type       =
11063    this.options    =
11064    this.enabled    =
11065    this.timeout    =
11066    this.hoverState =
11067    this.$element   = null
11068
11069    this.init('tooltip', element, options)
11070  }
11071
11072  Tooltip.VERSION  = '3.3.1'
11073
11074  Tooltip.TRANSITION_DURATION = 150
11075
11076  Tooltip.DEFAULTS = {
11077    animation: true,
11078    placement: 'top',
11079    selector: false,
11080    template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
11081    trigger: 'hover focus',
11082    title: '',
11083    delay: 0,
11084    html: false,
11085    container: false,
11086    viewport: {
11087      selector: 'body',
11088      padding: 0
11089    }
11090  }
11091
11092  Tooltip.prototype.init = function (type, element, options) {
11093    this.enabled   = true
11094    this.type      = type
11095    this.$element  = $(element)
11096    this.options   = this.getOptions(options)
11097    this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport)
11098
11099    var triggers = this.options.trigger.split(' ')
11100
11101    for (var i = triggers.length; i--;) {
11102      var trigger = triggers[i]
11103
11104      if (trigger == 'click') {
11105        this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
11106      } else if (trigger != 'manual') {
11107        var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focusin'
11108        var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
11109
11110        this.$element.on(eventIn  + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
11111        this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
11112      }
11113    }
11114
11115    this.options.selector ?
11116      (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
11117      this.fixTitle()
11118  }
11119
11120  Tooltip.prototype.getDefaults = function () {
11121    return Tooltip.DEFAULTS
11122  }
11123
11124  Tooltip.prototype.getOptions = function (options) {
11125    options = $.extend({}, this.getDefaults(), this.$element.data(), options)
11126
11127    if (options.delay && typeof options.delay == 'number') {
11128      options.delay = {
11129        show: options.delay,
11130        hide: options.delay
11131      }
11132    }
11133
11134    return options
11135  }
11136
11137  Tooltip.prototype.getDelegateOptions = function () {
11138    var options  = {}
11139    var defaults = this.getDefaults()
11140
11141    this._options && $.each(this._options, function (key, value) {
11142      if (defaults[key] != value) options[key] = value
11143    })
11144
11145    return options
11146  }
11147
11148  Tooltip.prototype.enter = function (obj) {
11149    var self = obj instanceof this.constructor ?
11150      obj : $(obj.currentTarget).data('bs.' + this.type)
11151
11152    if (self && self.$tip && self.$tip.is(':visible')) {
11153      self.hoverState = 'in'
11154      return
11155    }
11156
11157    if (!self) {
11158      self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
11159      $(obj.currentTarget).data('bs.' + this.type, self)
11160    }
11161
11162    clearTimeout(self.timeout)
11163
11164    self.hoverState = 'in'
11165
11166    if (!self.options.delay || !self.options.delay.show) return self.show()
11167
11168    self.timeout = setTimeout(function () {
11169      if (self.hoverState == 'in') self.show()
11170    }, self.options.delay.show)
11171  }
11172
11173  Tooltip.prototype.leave = function (obj) {
11174    var self = obj instanceof this.constructor ?
11175      obj : $(obj.currentTarget).data('bs.' + this.type)
11176
11177    if (!self) {
11178      self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
11179      $(obj.currentTarget).data('bs.' + this.type, self)
11180    }
11181
11182    clearTimeout(self.timeout)
11183
11184    self.hoverState = 'out'
11185
11186    if (!self.options.delay || !self.options.delay.hide) return self.hide()
11187
11188    self.timeout = setTimeout(function () {
11189      if (self.hoverState == 'out') self.hide()
11190    }, self.options.delay.hide)
11191  }
11192
11193  Tooltip.prototype.show = function () {
11194    var e = $.Event('show.bs.' + this.type)
11195
11196    if (this.hasContent() && this.enabled) {
11197      this.$element.trigger(e)
11198
11199      var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
11200      if (e.isDefaultPrevented() || !inDom) return
11201      var that = this
11202
11203      var $tip = this.tip()
11204
11205      var tipId = this.getUID(this.type)
11206
11207      this.setContent()
11208      $tip.attr('id', tipId)
11209      this.$element.attr('aria-describedby', tipId)
11210
11211      if (this.options.animation) $tip.addClass('fade')
11212
11213      var placement = typeof this.options.placement == 'function' ?
11214        this.options.placement.call(this, $tip[0], this.$element[0]) :
11215        this.options.placement
11216
11217      var autoToken = /\s?auto?\s?/i
11218      var autoPlace = autoToken.test(placement)
11219      if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
11220
11221      $tip
11222        .detach()
11223        .css({ top: 0, left: 0, display: 'block' })
11224        .addClass(placement)
11225        .data('bs.' + this.type, this)
11226
11227      this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
11228
11229      var pos          = this.getPosition()
11230      var actualWidth  = $tip[0].offsetWidth
11231      var actualHeight = $tip[0].offsetHeight
11232
11233      if (autoPlace) {
11234        var orgPlacement = placement
11235        var $container   = this.options.container ? $(this.options.container) : this.$element.parent()
11236        var containerDim = this.getPosition($container)
11237
11238        placement = placement == 'bottom' && pos.bottom + actualHeight > containerDim.bottom ? 'top'    :
11239                    placement == 'top'    && pos.top    - actualHeight < containerDim.top    ? 'bottom' :
11240                    placement == 'right'  && pos.right  + actualWidth  > containerDim.width  ? 'left'   :
11241                    placement == 'left'   && pos.left   - actualWidth  < containerDim.left   ? 'right'  :
11242                    placement
11243
11244        $tip
11245          .removeClass(orgPlacement)
11246          .addClass(placement)
11247      }
11248
11249      var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
11250
11251      this.applyPlacement(calculatedOffset, placement)
11252
11253      var complete = function () {
11254        var prevHoverState = that.hoverState
11255        that.$element.trigger('shown.bs.' + that.type)
11256        that.hoverState = null
11257
11258        if (prevHoverState == 'out') that.leave(that)
11259      }
11260
11261      $.support.transition && this.$tip.hasClass('fade') ?
11262        $tip
11263          .one('bsTransitionEnd', complete)
11264          .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
11265        complete()
11266    }
11267  }
11268
11269  Tooltip.prototype.applyPlacement = function (offset, placement) {
11270    var $tip   = this.tip()
11271    var width  = $tip[0].offsetWidth
11272    var height = $tip[0].offsetHeight
11273
11274    // manually read margins because getBoundingClientRect includes difference
11275    var marginTop = parseInt($tip.css('margin-top'), 10)
11276    var marginLeft = parseInt($tip.css('margin-left'), 10)
11277
11278    // we must check for NaN for ie 8/9
11279    if (isNaN(marginTop))  marginTop  = 0
11280    if (isNaN(marginLeft)) marginLeft = 0
11281
11282    offset.top  = offset.top  + marginTop
11283    offset.left = offset.left + marginLeft
11284
11285    // $.fn.offset doesn't round pixel values
11286    // so we use setOffset directly with our own function B-0
11287    $.offset.setOffset($tip[0], $.extend({
11288      using: function (props) {
11289        $tip.css({
11290          top: Math.round(props.top),
11291          left: Math.round(props.left)
11292        })
11293      }
11294    }, offset), 0)
11295
11296    $tip.addClass('in')
11297
11298    // check to see if placing tip in new offset caused the tip to resize itself
11299    var actualWidth  = $tip[0].offsetWidth
11300    var actualHeight = $tip[0].offsetHeight
11301
11302    if (placement == 'top' && actualHeight != height) {
11303      offset.top = offset.top + height - actualHeight
11304    }
11305
11306    var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
11307
11308    if (delta.left) offset.left += delta.left
11309    else offset.top += delta.top
11310
11311    var isVertical          = /top|bottom/.test(placement)
11312    var arrowDelta          = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
11313    var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'
11314
11315    $tip.offset(offset)
11316    this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
11317  }
11318
11319  Tooltip.prototype.replaceArrow = function (delta, dimension, isHorizontal) {
11320    this.arrow()
11321      .css(isHorizontal ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
11322      .css(isHorizontal ? 'top' : 'left', '')
11323  }
11324
11325  Tooltip.prototype.setContent = function () {
11326    var $tip  = this.tip()
11327    var title = this.getTitle()
11328
11329    $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
11330    $tip.removeClass('fade in top bottom left right')
11331  }
11332
11333  Tooltip.prototype.hide = function (callback) {
11334    var that = this
11335    var $tip = this.tip()
11336    var e    = $.Event('hide.bs.' + this.type)
11337
11338    function complete() {
11339      if (that.hoverState != 'in') $tip.detach()
11340      that.$element
11341        .removeAttr('aria-describedby')
11342        .trigger('hidden.bs.' + that.type)
11343      callback && callback()
11344    }
11345
11346    this.$element.trigger(e)
11347
11348    if (e.isDefaultPrevented()) return
11349
11350    $tip.removeClass('in')
11351
11352    $.support.transition && this.$tip.hasClass('fade') ?
11353      $tip
11354        .one('bsTransitionEnd', complete)
11355        .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
11356      complete()
11357
11358    this.hoverState = null
11359
11360    return this
11361  }
11362
11363  Tooltip.prototype.fixTitle = function () {
11364    var $e = this.$element
11365    if ($e.attr('title') || typeof ($e.attr('data-original-title')) != 'string') {
11366      $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
11367    }
11368  }
11369
11370  Tooltip.prototype.hasContent = function () {
11371    return this.getTitle()
11372  }
11373
11374  Tooltip.prototype.getPosition = function ($element) {
11375    $element   = $element || this.$element
11376
11377    var el     = $element[0]
11378    var isBody = el.tagName == 'BODY'
11379
11380    var elRect    = el.getBoundingClientRect()
11381    if (elRect.width == null) {
11382      // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
11383      elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
11384    }
11385    var elOffset  = isBody ? { top: 0, left: 0 } : $element.offset()
11386    var scroll    = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
11387    var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null
11388
11389    return $.extend({}, elRect, scroll, outerDims, elOffset)
11390  }
11391
11392  Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
11393    return placement == 'bottom' ? { top: pos.top + pos.height,   left: pos.left + pos.width / 2 - actualWidth / 2  } :
11394           placement == 'top'    ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2  } :
11395           placement == 'left'   ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
11396        /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width   }
11397
11398  }
11399
11400  Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
11401    var delta = { top: 0, left: 0 }
11402    if (!this.$viewport) return delta
11403
11404    var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
11405    var viewportDimensions = this.getPosition(this.$viewport)
11406
11407    if (/right|left/.test(placement)) {
11408      var topEdgeOffset    = pos.top - viewportPadding - viewportDimensions.scroll
11409      var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
11410      if (topEdgeOffset < viewportDimensions.top) { // top overflow
11411        delta.top = viewportDimensions.top - topEdgeOffset
11412      } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
11413        delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
11414      }
11415    } else {
11416      var leftEdgeOffset  = pos.left - viewportPadding
11417      var rightEdgeOffset = pos.left + viewportPadding + actualWidth
11418      if (leftEdgeOffset < viewportDimensions.left) { // left overflow
11419        delta.left = viewportDimensions.left - leftEdgeOffset
11420      } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow
11421        delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
11422      }
11423    }
11424
11425    return delta
11426  }
11427
11428  Tooltip.prototype.getTitle = function () {
11429    var title
11430    var $e = this.$element
11431    var o  = this.options
11432
11433    title = $e.attr('data-original-title')
11434      || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)
11435
11436    return title
11437  }
11438
11439  Tooltip.prototype.getUID = function (prefix) {
11440    do prefix += ~~(Math.random() * 1000000)
11441    while (document.getElementById(prefix))
11442    return prefix
11443  }
11444
11445  Tooltip.prototype.tip = function () {
11446    return (this.$tip = this.$tip || $(this.options.template))
11447  }
11448
11449  Tooltip.prototype.arrow = function () {
11450    return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
11451  }
11452
11453  Tooltip.prototype.enable = function () {
11454    this.enabled = true
11455  }
11456
11457  Tooltip.prototype.disable = function () {
11458    this.enabled = false
11459  }
11460
11461  Tooltip.prototype.toggleEnabled = function () {
11462    this.enabled = !this.enabled
11463  }
11464
11465  Tooltip.prototype.toggle = function (e) {
11466    var self = this
11467    if (e) {
11468      self = $(e.currentTarget).data('bs.' + this.type)
11469      if (!self) {
11470        self = new this.constructor(e.currentTarget, this.getDelegateOptions())
11471        $(e.currentTarget).data('bs.' + this.type, self)
11472      }
11473    }
11474
11475    self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
11476  }
11477
11478  Tooltip.prototype.destroy = function () {
11479    var that = this
11480    clearTimeout(this.timeout)
11481    this.hide(function () {
11482      that.$element.off('.' + that.type).removeData('bs.' + that.type)
11483    })
11484  }
11485
11486
11487  // TOOLTIP PLUGIN DEFINITION
11488  // =========================
11489
11490  function Plugin(option) {
11491    return this.each(function () {
11492      var $this    = $(this)
11493      var data     = $this.data('bs.tooltip')
11494      var options  = typeof option == 'object' && option
11495      var selector = options && options.selector
11496
11497      if (!data && option == 'destroy') return
11498      if (selector) {
11499        if (!data) $this.data('bs.tooltip', (data = {}))
11500        if (!data[selector]) data[selector] = new Tooltip(this, options)
11501      } else {
11502        if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
11503      }
11504      if (typeof option == 'string') data[option]()
11505    })
11506  }
11507
11508  var old = $.fn.tooltip
11509
11510  $.fn.tooltip             = Plugin
11511  $.fn.tooltip.Constructor = Tooltip
11512
11513
11514  // TOOLTIP NO CONFLICT
11515  // ===================
11516
11517  $.fn.tooltip.noConflict = function () {
11518    $.fn.tooltip = old
11519    return this
11520  }
11521
11522}(jQuery);
11523
11524define("bootstrapTooltip", ["jquery","bootstrapTransition"], (function (global) {
11525    return function () {
11526        var ret, fn;
11527        return ret || global.$;
11528    };
11529}(this)));
11530
11531/* ========================================================================
11532 * Bootstrap: popover.js v3.3.1
11533 * http://getbootstrap.com/javascript/#popovers
11534 * ========================================================================
11535 * Copyright 2011-2014 Twitter, Inc.
11536 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
11537 * ======================================================================== */
11538
11539
11540+function ($) {
11541  'use strict';
11542
11543  // POPOVER PUBLIC CLASS DEFINITION
11544  // ===============================
11545
11546  var Popover = function (element, options) {
11547    this.init('popover', element, options)
11548  }
11549
11550  if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
11551
11552  Popover.VERSION  = '3.3.1'
11553
11554  Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
11555    placement: 'right',
11556    trigger: 'click',
11557    content: '',
11558    template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
11559  })
11560
11561
11562  // NOTE: POPOVER EXTENDS tooltip.js
11563  // ================================
11564
11565  Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
11566
11567  Popover.prototype.constructor = Popover
11568
11569  Popover.prototype.getDefaults = function () {
11570    return Popover.DEFAULTS
11571  }
11572
11573  Popover.prototype.setContent = function () {
11574    var $tip    = this.tip()
11575    var title   = this.getTitle()
11576    var content = this.getContent()
11577
11578    $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
11579    $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events
11580      this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
11581    ](content)
11582
11583    $tip.removeClass('fade top bottom left right in')
11584
11585    // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
11586    // this manually by checking the contents.
11587    if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
11588  }
11589
11590  Popover.prototype.hasContent = function () {
11591    return this.getTitle() || this.getContent()
11592  }
11593
11594  Popover.prototype.getContent = function () {
11595    var $e = this.$element
11596    var o  = this.options
11597
11598    return $e.attr('data-content')
11599      || (typeof o.content == 'function' ?
11600            o.content.call($e[0]) :
11601            o.content)
11602  }
11603
11604  Popover.prototype.arrow = function () {
11605    return (this.$arrow = this.$arrow || this.tip().find('.arrow'))
11606  }
11607
11608  Popover.prototype.tip = function () {
11609    if (!this.$tip) this.$tip = $(this.options.template)
11610    return this.$tip
11611  }
11612
11613
11614  // POPOVER PLUGIN DEFINITION
11615  // =========================
11616
11617  function Plugin(option) {
11618    return this.each(function () {
11619      var $this    = $(this)
11620      var data     = $this.data('bs.popover')
11621      var options  = typeof option == 'object' && option
11622      var selector = options && options.selector
11623
11624      if (!data && option == 'destroy') return
11625      if (selector) {
11626        if (!data) $this.data('bs.popover', (data = {}))
11627        if (!data[selector]) data[selector] = new Popover(this, options)
11628      } else {
11629        if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
11630      }
11631      if (typeof option == 'string') data[option]()
11632    })
11633  }
11634
11635  var old = $.fn.popover
11636
11637  $.fn.popover             = Plugin
11638  $.fn.popover.Constructor = Popover
11639
11640
11641  // POPOVER NO CONFLICT
11642  // ===================
11643
11644  $.fn.popover.noConflict = function () {
11645    $.fn.popover = old
11646    return this
11647  }
11648
11649}(jQuery);
11650
11651define("bootstrapPopover", ["jquery","bootstrapTooltip","bootstrapTransition"], (function (global) {
11652    return function () {
11653        var ret, fn;
11654        return ret || global.$;
11655    };
11656}(this)));
11657
11658/* ========================================================================
11659 * Bootstrap: scrollspy.js v3.3.1
11660 * http://getbootstrap.com/javascript/#scrollspy
11661 * ========================================================================
11662 * Copyright 2011-2014 Twitter, Inc.
11663 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
11664 * ======================================================================== */
11665
11666
11667+function ($) {
11668  'use strict';
11669
11670  // SCROLLSPY CLASS DEFINITION
11671  // ==========================
11672
11673  function ScrollSpy(element, options) {
11674    var process  = $.proxy(this.process, this)
11675
11676    this.$body          = $('body')
11677    this.$scrollElement = $(element).is('body') ? $(window) : $(element)
11678    this.options        = $.extend({}, ScrollSpy.DEFAULTS, options)
11679    this.selector       = (this.options.target || '') + ' .nav li > a'
11680    this.offsets        = []
11681    this.targets        = []
11682    this.activeTarget   = null
11683    this.scrollHeight   = 0
11684
11685    this.$scrollElement.on('scroll.bs.scrollspy', process)
11686    this.refresh()
11687    this.process()
11688  }
11689
11690  ScrollSpy.VERSION  = '3.3.1'
11691
11692  ScrollSpy.DEFAULTS = {
11693    offset: 10
11694  }
11695
11696  ScrollSpy.prototype.getScrollHeight = function () {
11697    return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
11698  }
11699
11700  ScrollSpy.prototype.refresh = function () {
11701    var offsetMethod = 'offset'
11702    var offsetBase   = 0
11703
11704    if (!$.isWindow(this.$scrollElement[0])) {
11705      offsetMethod = 'position'
11706      offsetBase   = this.$scrollElement.scrollTop()
11707    }
11708
11709    this.offsets = []
11710    this.targets = []
11711    this.scrollHeight = this.getScrollHeight()
11712
11713    var self     = this
11714
11715    this.$body
11716      .find(this.selector)
11717      .map(function () {
11718        var $el   = $(this)
11719        var href  = $el.data('target') || $el.attr('href')
11720        var $href = /^#./.test(href) && $(href)
11721
11722        return ($href
11723          && $href.length
11724          && $href.is(':visible')
11725          && [[$href[offsetMethod]().top + offsetBase, href]]) || null
11726      })
11727      .sort(function (a, b) { return a[0] - b[0] })
11728      .each(function () {
11729        self.offsets.push(this[0])
11730        self.targets.push(this[1])
11731      })
11732  }
11733
11734  ScrollSpy.prototype.process = function () {
11735    var scrollTop    = this.$scrollElement.scrollTop() + this.options.offset
11736    var scrollHeight = this.getScrollHeight()
11737    var maxScroll    = this.options.offset + scrollHeight - this.$scrollElement.height()
11738    var offsets      = this.offsets
11739    var targets      = this.targets
11740    var activeTarget = this.activeTarget
11741    var i
11742
11743    if (this.scrollHeight != scrollHeight) {
11744      this.refresh()
11745    }
11746
11747    if (scrollTop >= maxScroll) {
11748      return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
11749    }
11750
11751    if (activeTarget && scrollTop < offsets[0]) {
11752      this.activeTarget = null
11753      return this.clear()
11754    }
11755
11756    for (i = offsets.length; i--;) {
11757      activeTarget != targets[i]
11758        && scrollTop >= offsets[i]
11759        && (!offsets[i + 1] || scrollTop <= offsets[i + 1])
11760        && this.activate(targets[i])
11761    }
11762  }
11763
11764  ScrollSpy.prototype.activate = function (target) {
11765    this.activeTarget = target
11766
11767    this.clear()
11768
11769    var selector = this.selector +
11770        '[data-target="' + target + '"],' +
11771        this.selector + '[href="' + target + '"]'
11772
11773    var active = $(selector)
11774      .parents('li')
11775      .addClass('active')
11776
11777    if (active.parent('.dropdown-menu').length) {
11778      active = active
11779        .closest('li.dropdown')
11780        .addClass('active')
11781    }
11782
11783    active.trigger('activate.bs.scrollspy')
11784  }
11785
11786  ScrollSpy.prototype.clear = function () {
11787    $(this.selector)
11788      .parentsUntil(this.options.target, '.active')
11789      .removeClass('active')
11790  }
11791
11792
11793  // SCROLLSPY PLUGIN DEFINITION
11794  // ===========================
11795
11796  function Plugin(option) {
11797    return this.each(function () {
11798      var $this   = $(this)
11799      var data    = $this.data('bs.scrollspy')
11800      var options = typeof option == 'object' && option
11801
11802      if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
11803      if (typeof option == 'string') data[option]()
11804    })
11805  }
11806
11807  var old = $.fn.scrollspy
11808
11809  $.fn.scrollspy             = Plugin
11810  $.fn.scrollspy.Constructor = ScrollSpy
11811
11812
11813  // SCROLLSPY NO CONFLICT
11814  // =====================
11815
11816  $.fn.scrollspy.noConflict = function () {
11817    $.fn.scrollspy = old
11818    return this
11819  }
11820
11821
11822  // SCROLLSPY DATA-API
11823  // ==================
11824
11825  $(window).on('load.bs.scrollspy.data-api', function () {
11826    $('[data-spy="scroll"]').each(function () {
11827      var $spy = $(this)
11828      Plugin.call($spy, $spy.data())
11829    })
11830  })
11831
11832}(jQuery);
11833
11834define("bootstrapScrollspy", ["jquery","bootstrapTransition"], (function (global) {
11835    return function () {
11836        var ret, fn;
11837        return ret || global.$;
11838    };
11839}(this)));
11840
11841/* ========================================================================
11842 * Bootstrap: tab.js v3.3.1
11843 * http://getbootstrap.com/javascript/#tabs
11844 * ========================================================================
11845 * Copyright 2011-2014 Twitter, Inc.
11846 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
11847 * ======================================================================== */
11848
11849
11850+function ($) {
11851  'use strict';
11852
11853  // TAB CLASS DEFINITION
11854  // ====================
11855
11856  var Tab = function (element) {
11857    this.element = $(element)
11858  }
11859
11860  Tab.VERSION = '3.3.1'
11861
11862  Tab.TRANSITION_DURATION = 150
11863
11864  Tab.prototype.show = function () {
11865    var $this    = this.element
11866    var $ul      = $this.closest('ul:not(.dropdown-menu)')
11867    var selector = $this.data('target')
11868
11869    if (!selector) {
11870      selector = $this.attr('href')
11871      selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
11872    }
11873
11874    if ($this.parent('li').hasClass('active')) return
11875
11876    var $previous = $ul.find('.active:last a')
11877    var hideEvent = $.Event('hide.bs.tab', {
11878      relatedTarget: $this[0]
11879    })
11880    var showEvent = $.Event('show.bs.tab', {
11881      relatedTarget: $previous[0]
11882    })
11883
11884    $previous.trigger(hideEvent)
11885    $this.trigger(showEvent)
11886
11887    if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return
11888
11889    var $target = $(selector)
11890
11891    this.activate($this.closest('li'), $ul)
11892    this.activate($target, $target.parent(), function () {
11893      $previous.trigger({
11894        type: 'hidden.bs.tab',
11895        relatedTarget: $this[0]
11896      })
11897      $this.trigger({
11898        type: 'shown.bs.tab',
11899        relatedTarget: $previous[0]
11900      })
11901    })
11902  }
11903
11904  Tab.prototype.activate = function (element, container, callback) {
11905    var $active    = container.find('> .active')
11906    var transition = callback
11907      && $.support.transition
11908      && (($active.length && $active.hasClass('fade')) || !!container.find('> .fade').length)
11909
11910    function next() {
11911      $active
11912        .removeClass('active')
11913        .find('> .dropdown-menu > .active')
11914          .removeClass('active')
11915        .end()
11916        .find('[data-toggle="tab"]')
11917          .attr('aria-expanded', false)
11918
11919      element
11920        .addClass('active')
11921        .find('[data-toggle="tab"]')
11922          .attr('aria-expanded', true)
11923
11924      if (transition) {
11925        element[0].offsetWidth // reflow for transition
11926        element.addClass('in')
11927      } else {
11928        element.removeClass('fade')
11929      }
11930
11931      if (element.parent('.dropdown-menu')) {
11932        element
11933          .closest('li.dropdown')
11934            .addClass('active')
11935          .end()
11936          .find('[data-toggle="tab"]')
11937            .attr('aria-expanded', true)
11938      }
11939
11940      callback && callback()
11941    }
11942
11943    $active.length && transition ?
11944      $active
11945        .one('bsTransitionEnd', next)
11946        .emulateTransitionEnd(Tab.TRANSITION_DURATION) :
11947      next()
11948
11949    $active.removeClass('in')
11950  }
11951
11952
11953  // TAB PLUGIN DEFINITION
11954  // =====================
11955
11956  function Plugin(option) {
11957    return this.each(function () {
11958      var $this = $(this)
11959      var data  = $this.data('bs.tab')
11960
11961      if (!data) $this.data('bs.tab', (data = new Tab(this)))
11962      if (typeof option == 'string') data[option]()
11963    })
11964  }
11965
11966  var old = $.fn.tab
11967
11968  $.fn.tab             = Plugin
11969  $.fn.tab.Constructor = Tab
11970
11971
11972  // TAB NO CONFLICT
11973  // ===============
11974
11975  $.fn.tab.noConflict = function () {
11976    $.fn.tab = old
11977    return this
11978  }
11979
11980
11981  // TAB DATA-API
11982  // ============
11983
11984  var clickHandler = function (e) {
11985    e.preventDefault()
11986    Plugin.call($(this), 'show')
11987  }
11988
11989  $(document)
11990    .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler)
11991    .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler)
11992
11993}(jQuery);
11994
11995define("bootstrapTab", ["jquery","bootstrapTransition"], (function (global) {
11996    return function () {
11997        var ret, fn;
11998        return ret || global.$;
11999    };
12000}(this)));
12001
12002/* ========================================================================
12003 * Bootstrap: affix.js v3.3.1
12004 * http://getbootstrap.com/javascript/#affix
12005 * ========================================================================
12006 * Copyright 2011-2014 Twitter, Inc.
12007 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
12008 * ======================================================================== */
12009
12010
12011+function ($) {
12012  'use strict';
12013
12014  // AFFIX CLASS DEFINITION
12015  // ======================
12016
12017  var Affix = function (element, options) {
12018    this.options = $.extend({}, Affix.DEFAULTS, options)
12019
12020    this.$target = $(this.options.target)
12021      .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))
12022      .on('click.bs.affix.data-api',  $.proxy(this.checkPositionWithEventLoop, this))
12023
12024    this.$element     = $(element)
12025    this.affixed      =
12026    this.unpin        =
12027    this.pinnedOffset = null
12028
12029    this.checkPosition()
12030  }
12031
12032  Affix.VERSION  = '3.3.1'
12033
12034  Affix.RESET    = 'affix affix-top affix-bottom'
12035
12036  Affix.DEFAULTS = {
12037    offset: 0,
12038    target: window
12039  }
12040
12041  Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) {
12042    var scrollTop    = this.$target.scrollTop()
12043    var position     = this.$element.offset()
12044    var targetHeight = this.$target.height()
12045
12046    if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false
12047
12048    if (this.affixed == 'bottom') {
12049      if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom'
12050      return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom'
12051    }
12052
12053    var initializing   = this.affixed == null
12054    var colliderTop    = initializing ? scrollTop : position.top
12055    var colliderHeight = initializing ? targetHeight : height
12056
12057    if (offsetTop != null && colliderTop <= offsetTop) return 'top'
12058    if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom'
12059
12060    return false
12061  }
12062
12063  Affix.prototype.getPinnedOffset = function () {
12064    if (this.pinnedOffset) return this.pinnedOffset
12065    this.$element.removeClass(Affix.RESET).addClass('affix')
12066    var scrollTop = this.$target.scrollTop()
12067    var position  = this.$element.offset()
12068    return (this.pinnedOffset = position.top - scrollTop)
12069  }
12070
12071  Affix.prototype.checkPositionWithEventLoop = function () {
12072    setTimeout($.proxy(this.checkPosition, this), 1)
12073  }
12074
12075  Affix.prototype.checkPosition = function () {
12076    if (!this.$element.is(':visible')) return
12077
12078    var height       = this.$element.height()
12079    var offset       = this.options.offset
12080    var offsetTop    = offset.top
12081    var offsetBottom = offset.bottom
12082    var scrollHeight = $('body').height()
12083
12084    if (typeof offset != 'object')         offsetBottom = offsetTop = offset
12085    if (typeof offsetTop == 'function')    offsetTop    = offset.top(this.$element)
12086    if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element)
12087
vendor: 2,644 bytes, lines 12088-12198
12088    var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom)
12089
12090    if (this.affixed != affix) {
12091      if (this.unpin != null) this.$element.css('top', '')
12092
12093      var affixType = 'affix' + (affix ? '-' + affix : '')
12094      var e         = $.Event(affixType + '.bs.affix')
12095
12096      this.$element.trigger(e)
12097
12098      if (e.isDefaultPrevented()) return
12099
12100      this.affixed = affix
12101      this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null
12102
12103      this.$element
12104        .removeClass(Affix.RESET)
12105        .addClass(affixType)
12106        .trigger(affixType.replace('affix', 'affixed') + '.bs.affix')
12107    }
12108
12109    if (affix == 'bottom') {
12110      this.$element.offset({
12111        top: scrollHeight - height - offsetBottom
12112      })
12113    }
12114  }
12115
12116
12117  // AFFIX PLUGIN DEFINITION
12118  // =======================
12119
12120  function Plugin(option) {
12121    return this.each(function () {
12122      var $this   = $(this)
12123      var data    = $this.data('bs.affix')
12124      var options = typeof option == 'object' && option
12125
12126      if (!data) $this.data('bs.affix', (data = new Affix(this, options)))
12127      if (typeof option == 'string') data[option]()
12128    })
12129  }
12130
12131  var old = $.fn.affix
12132
12133  $.fn.affix             = Plugin
12134  $.fn.affix.Constructor = Affix
12135
12136
12137  // AFFIX NO CONFLICT
12138  // =================
12139
12140  $.fn.affix.noConflict = function () {
12141    $.fn.affix = old
12142    return this
12143  }
12144
12145
12146  // AFFIX DATA-API
12147  // ==============
12148
12149  $(window).on('load', function () {
12150    $('[data-spy="affix"]').each(function () {
12151      var $spy = $(this)
12152      var data = $spy.data()
12153
12154      data.offset = data.offset || {}
12155
12156      if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom
12157      if (data.offsetTop    != null) data.offset.top    = data.offsetTop
12158
12159      Plugin.call($spy, data)
12160    })
12161  })
12162
12163}(jQuery);
12164
12165define("bootstrapAffix", ["jquery","bootstrapTransition"], (function (global) {
12166    return function () {
12167        var ret, fn;
12168        return ret || global.$;
12169    };
12170}(this)));
12171
12172define('bootstrap',[
12173    "jquery",
12174    "bootstrapAlert",
12175    "bootstrapButton",
12176    "bootstrapCarousel",
12177    "bootstrapCollapse",
12178    "bootstrapDropdown",
12179    "bootstrapModal",
12180    "bootstrapPopover",
12181    "bootstrapScrollspy",
12182    "bootstrapTab",
12183    "bootstrapTooltip",
12184    "bootstrapTransition",
12185    "bootstrapAffix"
12186], function () {
12187
12188});
12189
12190//! moment.js
12191//! version : 2.31.0
12192//! authors : Tim Wood, Iskren Chernev, Moment.js contributors
12193//! license : MIT
12194//! momentjs.com
12195
12196;(function (global, factory) {
12197    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
12198    typeof define === 'function' && define.amd ? define('moment',
vendor: 183,142 bytes, lines 12198-18106
12198factory) :
12199    global.moment = factory()
12200}(this, (function () { 'use strict';
12201
12202    var hookCallback;
12203
12204    function hooks() {
12205        return hookCallback.apply(null, arguments);
12206    }
12207
12208    // This is done to register the method called with moment()
12209    // without creating circular dependencies.
12210    function setHookCallback(callback) {
12211        hookCallback = callback;
12212    }
12213
12214    function isArray(input) {
12215        return (
12216            input instanceof Array ||
12217            Object.prototype.toString.call(input) === '[object Array]'
12218        );
12219    }
12220
12221    function isObject(input) {
12222        // IE8 will treat undefined and null as object if it wasn't for
12223        // input != null
12224        return (
12225            input != null &&
12226            Object.prototype.toString.call(input) === '[object Object]'
12227        );
12228    }
12229
12230    function hasOwnProp(a, b) {
12231        return Object.prototype.hasOwnProperty.call(a, b);
12232    }
12233
12234    function isObjectEmpty(obj) {
12235        if (Object.getOwnPropertyNames) {
12236            return Object.getOwnPropertyNames(obj).length === 0;
12237        } else {
12238            var k;
12239            for (k in obj) {
12240                if (hasOwnProp(obj, k)) {
12241                    return false;
12242                }
12243            }
12244            return true;
12245        }
12246    }
12247
12248    function isUndefined(input) {
12249        return input === void 0;
12250    }
12251
12252    function isNumber(input) {
12253        return (
12254            typeof input === 'number' ||
12255            Object.prototype.toString.call(input) === '[object Number]'
12256        );
12257    }
12258
12259    function isDate(input) {
12260        return (
12261            input instanceof Date ||
12262            Object.prototype.toString.call(input) === '[object Date]'
12263        );
12264    }
12265
12266    function map(arr, fn) {
12267        var res = [],
12268            i,
12269            arrLen = arr.length;
12270        for (i = 0; i < arrLen; ++i) {
12271            res.push(fn(arr[i], i));
12272        }
12273        return res;
12274    }
12275
12276    function extend(a, b) {
12277        for (var i in b) {
12278            if (hasOwnProp(b, i)) {
12279                a[i] = b[i];
12280            }
12281        }
12282
12283        if (hasOwnProp(b, 'toString')) {
12284            a.toString = b.toString;
12285        }
12286
12287        if (hasOwnProp(b, 'valueOf')) {
12288            a.valueOf = b.valueOf;
12289        }
12290
12291        return a;
12292    }
12293
12294    function createUTC(input, format, locale, strict) {
12295        return createLocalOrUTC(input, format, locale, strict, true).utc();
12296    }
12297
12298    function defaultParsingFlags() {
12299        // We need to deep clone this object.
12300        return {
12301            empty: false,
12302            unusedTokens: [],
12303            unusedInput: [],
12304            overflow: -2,
12305            charsLeftOver: 0,
12306            nullInput: false,
12307            invalidEra: null,
12308            invalidMonth: null,
12309            invalidOffset: null,
12310            invalidFormat: false,
12311            userInvalidated: false,
12312            iso: false,
12313            parsedDateParts: [],
12314            era: null,
12315            meridiem: null,
12316            rfc2822: false,
12317            weekdayMismatch: false,
12318        };
12319    }
12320
12321    function getParsingFlags(m) {
12322        if (m._pf == null) {
12323            m._pf = defaultParsingFlags();
12324        }
12325        return m._pf;
12326    }
12327
12328    var some;
12329    if (Array.prototype.some) {
12330        some = Array.prototype.some;
12331    } else {
12332        some = function (fun) {
12333            var t = Object(this),
12334                len = t.length >>> 0,
12335                i;
12336
12337            for (i = 0; i < len; i++) {
12338                if (i in t && fun.call(this, t[i], i, t)) {
12339                    return true;
12340                }
12341            }
12342
12343            return false;
12344        };
12345    }
12346
12347    function isValid$2(m) {
12348        var flags = null,
12349            parsedParts = false,
12350            isNowValid = m._d && !isNaN(m._d.getTime());
12351        if (isNowValid) {
12352            flags = getParsingFlags(m);
12353            parsedParts = some.call(flags.parsedDateParts, function (i) {
12354                return i != null;
12355            });
12356            isNowValid =
12357                flags.overflow < 0 &&
12358                !flags.empty &&
12359                !flags.invalidEra &&
12360                !flags.invalidMonth &&
12361                !flags.invalidOffset &&
12362                !flags.invalidWeekday &&
12363                !flags.weekdayMismatch &&
12364                !flags.nullInput &&
12365                !flags.invalidFormat &&
12366                !flags.userInvalidated &&
12367                (!flags.meridiem || (flags.meridiem && parsedParts));
12368            if (m._strict) {
12369                isNowValid =
12370                    isNowValid &&
12371                    flags.charsLeftOver === 0 &&
12372                    flags.unusedTokens.length === 0 &&
12373                    flags.bigHour === undefined;
12374            }
12375        }
12376        if (Object.isFrozen == null || !Object.isFrozen(m)) {
12377            m._isValid = isNowValid;
12378        } else {
12379            return isNowValid;
12380        }
12381        return m._isValid;
12382    }
12383
12384    function createInvalid$1(flags) {
12385        var m = createUTC(NaN);
12386        if (flags != null) {
12387            extend(getParsingFlags(m), flags);
12388        } else {
12389            getParsingFlags(m).userInvalidated = true;
12390        }
12391
12392        return m;
12393    }
12394
12395    // Plugins that add properties should also add the key here (null value),
12396    // so we can properly clone ourselves.
12397    var momentProperties = (hooks.momentProperties = []),
12398        updateInProgress = false;
12399
12400    function copyConfig(to, from) {
12401        var i,
12402            prop,
12403            val,
12404            momentPropertiesLen = momentProperties.length;
12405
12406        if (!isUndefined(from._isAMomentObject)) {
12407            to._isAMomentObject = from._isAMomentObject;
12408        }
12409        if (!isUndefined(from._i)) {
12410            to._i = from._i;
12411        }
12412        if (!isUndefined(from._f)) {
12413            to._f = from._f;
12414        }
12415        if (!isUndefined(from._l)) {
12416            to._l = from._l;
12417        }
12418        if (!isUndefined(from._strict)) {
12419            to._strict = from._strict;
12420        }
12421        if (!isUndefined(from._tzm)) {
12422            to._tzm = from._tzm;
12423        }
12424        if (!isUndefined(from._isUTC)) {
12425            to._isUTC = from._isUTC;
12426        }
12427        if (!isUndefined(from._offset)) {
12428            to._offset = from._offset;
12429        }
12430        if (!isUndefined(from._pf)) {
12431            to._pf = getParsingFlags(from);
12432        }
12433        if (!isUndefined(from._locale)) {
12434            to._locale = from._locale;
12435        }
12436
12437        if (momentPropertiesLen > 0) {
12438            for (i = 0; i < momentPropertiesLen; i++) {
12439                prop = momentProperties[i];
12440                val = from[prop];
12441                if (!isUndefined(val)) {
12442                    to[prop] = val;
12443                }
12444            }
12445        }
12446
12447        return to;
12448    }
12449
12450    // Moment prototype object
12451    function Moment(config) {
12452        copyConfig(this, config);
12453        this._d = new Date(config._d != null ? config._d.getTime() : NaN);
12454        if (!this.isValid()) {
12455            this._d = new Date(NaN);
12456        }
12457        // Prevent infinite loop in case updateOffset creates new moment
12458        // objects.
12459        if (updateInProgress === false) {
12460            updateInProgress = true;
12461            hooks.updateOffset(this);
12462            updateInProgress = false;
12463        }
12464    }
12465
12466    function isMoment(obj) {
12467        return (
12468            obj instanceof Moment || (obj != null && obj._isAMomentObject != null)
12469        );
12470    }
12471
12472    function warn(msg) {
12473        if (
12474            hooks.suppressDeprecationWarnings === false &&
12475            typeof console !== 'undefined' &&
12476            console.warn
12477        ) {
12478            console.warn('Deprecation warning: ' + msg);
12479        }
12480    }
12481
12482    function deprecate(msg, fn) {
12483        var firstTime = true;
12484
12485        return extend(function () {
12486            if (hooks.deprecationHandler != null) {
12487                hooks.deprecationHandler(null, msg);
12488            }
12489            if (firstTime) {
12490                var args = [],
12491                    arg,
12492                    i,
12493                    key,
12494                    argLen = arguments.length;
12495                for (i = 0; i < argLen; i++) {
12496                    arg = '';
12497                    if (typeof arguments[i] === 'object') {
12498                        arg += '\n[' + i + '] ';
12499                        for (key in arguments[0]) {
12500                            if (hasOwnProp(arguments[0], key)) {
12501                                arg += key + ': ' + arguments[0][key] + ', ';
12502                            }
12503                        }
12504                        arg = arg.slice(0, -2); // Remove trailing comma and space
12505                    } else {
12506                        arg = arguments[i];
12507                    }
12508                    args.push(arg);
12509                }
12510                warn(
12511                    msg +
12512                        '\nArguments: ' +
12513                        Array.prototype.slice.call(args).join('') +
12514                        '\n' +
12515                        new Error().stack
12516                );
12517                firstTime = false;
12518            }
12519            return fn.apply(this, arguments);
12520        }, fn);
12521    }
12522
12523    var deprecations = {};
12524
12525    function deprecateSimple(name, msg) {
12526        if (hooks.deprecationHandler != null) {
12527            hooks.deprecationHandler(name, msg);
12528        }
12529        if (!deprecations[name]) {
12530            warn(msg + '\n' + new Error().stack);
12531            deprecations[name] = true;
12532        }
12533    }
12534
12535    hooks.suppressDeprecationWarnings = false;
12536    hooks.deprecationHandler = null;
12537
12538    function isFunction(input) {
12539        return (
12540            (typeof Function !== 'undefined' && input instanceof Function) ||
12541            Object.prototype.toString.call(input) === '[object Function]'
12542        );
12543    }
12544
12545    var aliases = {
12546        D: 'date',
12547        dates: 'date',
12548        date: 'date',
12549        d: 'day',
12550        days: 'day',
12551        day: 'day',
12552        e: 'weekday',
12553        weekdays: 'weekday',
12554        weekday: 'weekday',
12555        E: 'isoWeekday',
12556        isoweekdays: 'isoWeekday',
12557        isoweekday: 'isoWeekday',
12558        DDD: 'dayOfYear',
12559        dayofyears: 'dayOfYear',
12560        dayofyear: 'dayOfYear',
12561        h: 'hour',
12562        hours: 'hour',
12563        hour: 'hour',
12564        ms: 'millisecond',
12565        milliseconds: 'millisecond',
12566        millisecond: 'millisecond',
12567        m: 'minute',
12568        minutes: 'minute',
12569        minute: 'minute',
12570        M: 'month',
12571        months: 'month',
12572        month: 'month',
12573        Q: 'quarter',
12574        quarters: 'quarter',
12575        quarter: 'quarter',
12576        s: 'second',
12577        seconds: 'second',
12578        second: 'second',
12579        gg: 'weekYear',
12580        weekyears: 'weekYear',
12581        weekyear: 'weekYear',
12582        GG: 'isoWeekYear',
12583        isoweekyears: 'isoWeekYear',
12584        isoweekyear: 'isoWeekYear',
12585        w: 'week',
12586        weeks: 'week',
12587        week: 'week',
12588        W: 'isoWeek',
12589        isoweeks: 'isoWeek',
12590        isoweek: 'isoWeek',
12591        y: 'year',
12592        years: 'year',
12593        year: 'year',
12594    };
12595
12596    function normalizeUnits(units) {
12597        return typeof units === 'string'
12598            ? aliases[units] || aliases[units.toLowerCase()]
12599            : undefined;
12600    }
12601
12602    function normalizeObjectUnits(inputObject) {
12603        var normalizedInput = {},
12604            normalizedProp,
12605            prop;
12606
12607        for (prop in inputObject) {
12608            if (hasOwnProp(inputObject, prop)) {
12609                normalizedProp = normalizeUnits(prop);
12610                if (normalizedProp) {
12611                    normalizedInput[normalizedProp] = inputObject[prop];
12612                }
12613            }
12614        }
12615
12616        return normalizedInput;
12617    }
12618
12619    var priorities = {
12620        date: 9,
12621        day: 11,
12622        weekday: 11,
12623        isoWeekday: 11,
12624        dayOfYear: 4,
12625        hour: 13,
12626        millisecond: 16,
12627        minute: 14,
12628        month: 8,
12629        quarter: 7,
12630        second: 15,
12631        weekYear: 1,
12632        isoWeekYear: 1,
12633        week: 5,
12634        isoWeek: 5,
12635        year: 1,
12636    };
12637
12638    function getPrioritizedUnits(unitsObj) {
12639        var units = [],
12640            u;
12641        for (u in unitsObj) {
12642            if (hasOwnProp(unitsObj, u)) {
12643                units.push({ unit: u, priority: priorities[u] });
12644            }
12645        }
12646        units.sort(function (a, b) {
12647            return a.priority - b.priority;
12648        });
12649        return units;
12650    }
12651
12652    function zeroFill(number, targetLength, forceSign) {
12653        var absNumber = '' + Math.abs(number),
12654            zerosToFill = targetLength - absNumber.length,
12655            sign = number >= 0;
12656        return (
12657            (sign ? (forceSign ? '+' : '') : '-') +
12658            Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) +
12659            absNumber
12660        );
12661    }
12662
12663    var formattingTokens =
12664            /(\[[^\[]*\])|(\\e)|(\\)?(eHHmm|[Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|N{1,5}|YYYYYY|YYYYY|YYYY|YY|y{2,4}|yo?|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,
12665        localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,
12666        formatFunctions = {},
12667        formatTokenFunctions = {};
12668
12669    // token:    'M'
12670    // padded:   ['MM', 2]
12671    // ordinal:  'Mo'
12672    // callback: function () { this.month() + 1 }
12673    function addFormatToken(token, padded, ordinal, callback) {
12674        var func = callback;
12675        if (typeof callback === 'string') {
12676            func = function () {
12677                return this[callback]();
12678            };
12679        }
12680        if (token) {
12681            formatTokenFunctions[token] = func;
12682        }
12683        if (padded) {
12684            formatTokenFunctions[padded[0]] = function () {
12685                return zeroFill(func.apply(this, arguments), padded[1], padded[2]);
12686            };
12687        }
12688        if (ordinal) {
12689            formatTokenFunctions[ordinal] = function () {
12690                return this.localeData().ordinal(
12691                    func.apply(this, arguments),
12692                    token
12693                );
12694            };
12695        }
12696    }
12697
12698    function removeFormattingTokens(input) {
12699        if (input.match(/\[[\s\S]/)) {
12700            return input.replace(/^\[|\]$/g, '');
12701        }
12702        return input.replace(/\\/g, '');
12703    }
12704
12705    function makeFormatFunction(format) {
12706        var array = format.match(formattingTokens),
12707            i,
12708            length;
12709
12710        for (i = 0, length = array.length; i < length; i++) {
12711            if (formatTokenFunctions[array[i]]) {
12712                array[i] = formatTokenFunctions[array[i]];
12713            } else {
12714                array[i] = removeFormattingTokens(array[i]);
12715            }
12716        }
12717
12718        return function (mom) {
12719            var output = '',
12720                i;
12721            for (i = 0; i < length; i++) {
12722                output += isFunction(array[i])
12723                    ? array[i].call(mom, format)
12724                    : array[i];
12725            }
12726            return output;
12727        };
12728    }
12729
12730    // format date using native date object
12731    function formatMoment(m, format) {
12732        if (!m.isValid()) {
12733            return m.localeData().invalidDate();
12734        }
12735
12736        format = expandFormat(format, m.localeData());
12737        var cacheKey = '$' + format;
12738        if (!hasOwnProp(formatFunctions, cacheKey)) {
12739            formatFunctions[cacheKey] = makeFormatFunction(format);
12740        }
12741
12742        return formatFunctions[cacheKey](m);
12743    }
12744
12745    function expandFormat(format, locale) {
12746        var i = 5;
12747
12748        function replaceLongDateFormatTokens(input) {
12749            return locale.longDateFormat(input) || input;
12750        }
12751
12752        localFormattingTokens.lastIndex = 0;
12753        while (i >= 0 && localFormattingTokens.test(format)) {
12754            format = format.replace(
12755                localFormattingTokens,
12756                replaceLongDateFormatTokens
12757            );
12758            localFormattingTokens.lastIndex = 0;
12759            i -= 1;
12760        }
12761
12762        return format;
12763    }
12764
12765    var match1 = /\d/, //       0 - 9
12766        match2 = /\d\d/, //      00 - 99
12767        match3 = /\d{3}/, //     000 - 999
12768        match4 = /\d{4}/, //    0000 - 9999
12769        match6 = /[+-]?\d{6}/, // -999999 - 999999
12770        match1to2 = /\d\d?/, //       0 - 99
12771        match3to4 = /\d\d\d\d?/, //     999 - 9999
12772        match5to6 = /\d\d\d\d\d\d?/, //   99999 - 999999
12773        match1to3 = /\d{1,3}/, //       0 - 999
12774        match1to4 = /\d{1,4}/, //       0 - 9999
12775        match1to6 = /[+-]?\d{1,6}/, // -999999 - 999999
12776        matchUnsigned = /\d+/, //       0 - inf
12777        matchSigned = /[+-]?\d+/, //    -inf - inf
12778        matchOffset = /Z|[+-]\d\d:?\d\d/gi, // +00:00 -00:00 +0000 -0000 or Z
12779        matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi, // +00 -00 +00:00 -00:00 +0000 -0000 or Z
12780        matchTimestamp = /[+-]?\d+(\.\d{1,3})?/, // 123456789 123456789.123
12781        // any word (or two) characters or numbers including two/three word month in arabic.
12782        // includes scottish gaelic two word and hyphenated months
12783        matchWord =
12784            /[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,
12785        match1to2NoLeadingZero = /^[1-9]\d?/, //         1-99
12786        match1to2HasZero = /^([1-9]\d|\d)/, //           0-99
12787        regexes;
12788
12789    regexes = {};
12790
12791    function addRegexToken(token, regex, strictRegex) {
12792        regexes[token] = isFunction(regex)
12793            ? regex
12794            : function (isStrict, localeData) {
12795                  return isStrict && strictRegex ? strictRegex : regex;
12796              };
12797    }
12798
12799    function getParseRegexForToken(token, config) {
12800        if (!hasOwnProp(regexes, token)) {
12801            return new RegExp(unescapeFormat(token));
12802        }
12803
12804        return regexes[token](config._strict, config._locale);
12805    }
12806
12807    // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
12808    function unescapeFormat(s) {
12809        return regexEscape(
12810            s
12811                .replace('\\', '')
12812                .replace(
12813                    /\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,
12814                    function (matched, p1, p2, p3, p4) {
12815                        return p1 || p2 || p3 || p4;
12816                    }
12817                )
12818        );
12819    }
12820
12821    function regexEscape(s) {
12822        return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
12823    }
12824
12825    function absFloor(number) {
12826        if (number < 0) {
12827            // -0 -> 0
12828            return Math.ceil(number) || 0;
12829        } else {
12830            return Math.floor(number);
12831        }
12832    }
12833
12834    function toInt(argumentForCoercion) {
12835        var coercedNumber = +argumentForCoercion,
12836            value = 0;
12837
12838        if (coercedNumber !== 0 && isFinite(coercedNumber)) {
12839            value = absFloor(coercedNumber);
12840        }
12841
12842        return value;
12843    }
12844
12845    var tokens = {};
12846
12847    function addParseToken(token, callback) {
12848        var i,
12849            func = callback,
12850            tokenLen;
12851        if (typeof token === 'string') {
12852            token = [token];
12853        }
12854        if (isNumber(callback)) {
12855            func = function (input, array) {
12856                array[callback] = toInt(input);
12857            };
12858        }
12859        tokenLen = token.length;
12860        for (i = 0; i < tokenLen; i++) {
12861            tokens[token[i]] = func;
12862        }
12863    }
12864
12865    function addWeekParseToken(token, callback) {
12866        addParseToken(token, function (input, array, config, token) {
12867            config._w = config._w || {};
12868            callback(input, config._w, config, token);
12869        });
12870    }
12871
12872    function addTimeToArrayFromToken(token, input, config) {
12873        if (input != null && hasOwnProp(tokens, token)) {
12874            tokens[token](input, config._a, config, token);
12875        }
12876    }
12877
12878    function isLeapYear(year) {
12879        return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
12880    }
12881
12882    var YEAR = 0,
12883        MONTH = 1,
12884        DATE = 2,
12885        HOUR = 3,
12886        MINUTE = 4,
12887        SECOND = 5,
12888        MILLISECOND = 6,
12889        WEEK = 7,
12890        WEEKDAY = 8;
12891
12892    // FORMATTING
12893
12894    addFormatToken('Y', 0, 0, function () {
12895        var y = this.year();
12896        return y <= 9999 ? zeroFill(y, 4) : '+' + y;
12897    });
12898
12899    addFormatToken(0, ['YY', 2], 0, function () {
12900        return this.year() % 100;
12901    });
12902
12903    addFormatToken(0, ['YYYY', 4], 0, 'year');
12904    addFormatToken(0, ['YYYYY', 5], 0, 'year');
12905    addFormatToken(0, ['YYYYYY', 6, true], 0, 'year');
12906
12907    // PARSING
12908
12909    addRegexToken('Y', matchSigned);
12910    addRegexToken('YY', match1to2, match2);
12911    addRegexToken('YYYY', match1to4, match4);
12912    addRegexToken('YYYYY', match1to6, match6);
12913    addRegexToken('YYYYYY', match1to6, match6);
12914
12915    addParseToken(['YYYYY', 'YYYYYY'], YEAR);
12916    addParseToken('YYYY', function (input, array) {
12917        array[YEAR] =
12918            input.length === 2 ? hooks.parseTwoDigitYear(input) : toInt(input);
12919    });
12920    addParseToken('YY', function (input, array) {
12921        array[YEAR] = hooks.parseTwoDigitYear(input);
12922    });
12923    addParseToken('Y', function (input, array) {
12924        array[YEAR] = parseInt(input, 10);
12925    });
12926
12927    // HELPERS
12928
12929    function daysInYear(year) {
12930        return isLeapYear(year) ? 366 : 365;
12931    }
12932
12933    // HOOKS
12934
12935    hooks.parseTwoDigitYear = function (input) {
12936        return toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
12937    };
12938
12939    // MOMENTS
12940
12941    var getSetYear = makeGetSet('FullYear', true);
12942
12943    function getIsLeapYear() {
12944        return isLeapYear(this.year());
12945    }
12946
12947    function makeGetSet(unit, keepTime) {
12948        return function (value) {
12949            if (value != null) {
12950                set$1(this, unit, value);
12951                hooks.updateOffset(this, keepTime);
12952                return this;
12953            } else {
12954                return get$2(this, unit);
12955            }
12956        };
12957    }
12958
12959    function get$2(mom, unit) {
12960        if (!mom.isValid()) {
12961            return NaN;
12962        }
12963
12964        var d = mom._d,
12965            isUTC = mom._isUTC;
12966
12967        switch (unit) {
12968            case 'Milliseconds':
12969                return isUTC ? d.getUTCMilliseconds() : d.getMilliseconds();
12970            case 'Seconds':
12971                return isUTC ? d.getUTCSeconds() : d.getSeconds();
12972            case 'Minutes':
12973                return isUTC ? d.getUTCMinutes() : d.getMinutes();
12974            case 'Hours':
12975                return isUTC ? d.getUTCHours() : d.getHours();
12976            case 'Date':
12977                return isUTC ? d.getUTCDate() : d.getDate();
12978            case 'Day':
12979                return isUTC ? d.getUTCDay() : d.getDay();
12980            case 'Month':
12981                return isUTC ? d.getUTCMonth() : d.getMonth();
12982            case 'FullYear':
12983                return isUTC ? d.getUTCFullYear() : d.getFullYear();
12984            default:
12985                return NaN; // Just in case
12986        }
12987    }
12988
12989    function set$1(mom, unit, value) {
12990        var d, isUTC, year, month, date;
12991
12992        if (!mom.isValid() || isNaN(value)) {
12993            return;
12994        }
12995
12996        d = mom._d;
12997        isUTC = mom._isUTC;
12998
12999        switch (unit) {
13000            case 'Milliseconds':
13001                return void (isUTC
13002                    ? d.setUTCMilliseconds(value)
13003                    : d.setMilliseconds(value));
13004            case 'Seconds':
13005                return void (isUTC ? d.setUTCSeconds(value) : d.setSeconds(value));
13006            case 'Minutes':
13007                return void (isUTC ? d.setUTCMinutes(value) : d.setMinutes(value));
13008            case 'Hours':
13009                return void (isUTC ? d.setUTCHours(value) : d.setHours(value));
13010            case 'Date':
13011                return void (isUTC ? d.setUTCDate(value) : d.setDate(value));
13012            // case 'Day': // Not real
13013            //    return void (isUTC ? d.setUTCDay(value) : d.setDay(value));
13014            // case 'Month': // Not used because we need to pass two variables
13015            //     return void (isUTC ? d.setUTCMonth(value) : d.setMonth(value));
13016            case 'FullYear':
13017                break; // See below ...
13018            default:
13019                return; // Just in case
13020        }
13021
13022        year = value;
13023        month = mom.month();
13024        date = mom.date();
13025        date = date === 29 && month === 1 && !isLeapYear(year) ? 28 : date;
13026        void (isUTC
13027            ? d.setUTCFullYear(year, month, date)
13028            : d.setFullYear(year, month, date));
13029    }
13030
13031    // MOMENTS
13032
13033    function stringGet(units) {
13034        units = normalizeUnits(units);
13035        if (isFunction(this[units])) {
13036            return this[units]();
13037        }
13038        return this;
13039    }
13040
13041    function stringSet(units, value) {
13042        if (typeof units === 'object') {
13043            units = normalizeObjectUnits(units);
13044            var prioritized = getPrioritizedUnits(units),
13045                i,
13046                prioritizedLen = prioritized.length;
13047            for (i = 0; i < prioritizedLen; i++) {
13048                this[prioritized[i].unit](units[prioritized[i].unit]);
13049            }
13050        } else {
13051            units = normalizeUnits(units);
13052            if (isFunction(this[units])) {
13053                return this[units](value);
13054            }
13055        }
13056        return this;
13057    }
13058
13059    function mod$1(n, x) {
13060        return ((n % x) + x) % x;
13061    }
13062
13063    var indexOf;
13064
13065    if (Array.prototype.indexOf) {
13066        indexOf = Array.prototype.indexOf;
13067    } else {
13068        indexOf = function (o) {
13069            // I know
13070            var i;
13071            for (i = 0; i < this.length; ++i) {
13072                if (this[i] === o) {
13073                    return i;
13074                }
13075            }
13076            return -1;
13077        };
13078    }
13079
13080    function daysInMonth(year, month) {
13081        if (isNaN(year) || isNaN(month)) {
13082            return NaN;
13083        }
13084        var modMonth = mod$1(month, 12);
13085        year += (month - modMonth) / 12;
13086        return modMonth === 1
13087            ? isLeapYear(year)
13088                ? 29
13089                : 28
13090            : 31 - ((modMonth % 7) % 2);
13091    }
13092
13093    // FORMATTING
13094
13095    addFormatToken('M', ['MM', 2], 'Mo', function () {
13096        return this.month() + 1;
13097    });
13098
13099    addFormatToken('MMM', 0, 0, function (format) {
13100        return this.localeData().monthsShort(this, format);
13101    });
13102
13103    addFormatToken('MMMM', 0, 0, function (format) {
13104        return this.localeData().months(this, format);
13105    });
13106
13107    // PARSING
13108
13109    addRegexToken('M', match1to2, match1to2NoLeadingZero);
13110    addRegexToken('MM', match1to2, match2);
13111    addRegexToken('MMM', function (isStrict, locale) {
13112        return locale.monthsShortRegex(isStrict);
13113    });
13114    addRegexToken('MMMM', function (isStrict, locale) {
13115        return locale.monthsRegex(isStrict);
13116    });
13117
13118    addParseToken(['M', 'MM'], function (input, array) {
13119        array[MONTH] = toInt(input) - 1;
13120    });
13121
13122    addParseToken(['MMM', 'MMMM'], function (input, array, config, token) {
13123        var month = config._locale.monthsParse(input, token, config._strict);
13124        // if we didn't find a month name, mark the date as invalid.
13125        if (month != null) {
13126            array[MONTH] = month;
13127        } else {
13128            getParsingFlags(config).invalidMonth = input;
13129        }
13130    });
13131
13132    // LOCALES
13133
13134    var defaultLocaleMonths =
13135            'January_February_March_April_May_June_July_August_September_October_November_December'.split(
13136                '_'
13137            ),
13138        defaultLocaleMonthsShort =
13139            'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
13140        MONTHS_IN_FORMAT = /D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/,
13141        defaultMonthsShortRegex = matchWord,
13142        defaultMonthsRegex = matchWord,
13143        monthsParseProperties = [
13144            'monthsParse',
13145            'longMonthsParse',
13146            'shortMonthsParse',
13147            'monthsRegex',
13148            'monthsShortRegex',
13149            'monthsStrictRegex',
13150            'monthsShortStrictRegex',
13151        ];
13152
13153    function clearMonthsParseCache(locale, config) {
13154        var i, prop;
13155        for (i = 0; i < monthsParseProperties.length; i++) {
13156            prop = monthsParseProperties[i];
13157            if (!hasOwnProp(config, prop)) {
13158                delete locale['_' + prop];
13159            }
13160        }
13161    }
13162
13163    function localeMonths(m, format) {
13164        if (!m) {
13165            return isArray(this._months)
13166                ? this._months
13167                : this._months['standalone'];
13168        }
13169        return isArray(this._months)
13170            ? this._months[m.month()]
13171            : this._months[
13172                  (this._months.isFormat || MONTHS_IN_FORMAT).test(format)
13173                      ? 'format'
13174                      : 'standalone'
13175              ][m.month()];
13176    }
13177
13178    function localeMonthsShort(m, format) {
13179        if (!m) {
13180            return isArray(this._monthsShort)
13181                ? this._monthsShort
13182                : this._monthsShort['standalone'];
13183        }
13184        return isArray(this._monthsShort)
13185            ? this._monthsShort[m.month()]
13186            : this._monthsShort[
13187                  MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'
13188              ][m.month()];
13189    }
13190
13191    function handleStrictParse$1(monthName, format, strict) {
13192        var i,
13193            ii,
13194            mom,
13195            llc = monthName.toLocaleLowerCase();
13196        if (!this._monthsParse) {
13197            // this is not used
13198            this._monthsParse = [];
13199            this._longMonthsParse = [];
13200            this._shortMonthsParse = [];
13201            for (i = 0; i < 12; ++i) {
13202                mom = createUTC([2000, i]);
13203                this._shortMonthsParse[i] = this.monthsShort(
13204                    mom,
13205                    ''
13206                ).toLocaleLowerCase();
13207                this._longMonthsParse[i] = this.months(mom, '').toLocaleLowerCase();
13208            }
13209        }
13210
13211        if (strict) {
13212            if (format === 'MMM') {
13213                ii = indexOf.call(this._shortMonthsParse, llc);
13214                return ii !== -1 ? ii : null;
13215            } else {
13216                ii = indexOf.call(this._longMonthsParse, llc);
13217                return ii !== -1 ? ii : null;
13218            }
13219        } else {
13220            if (format === 'MMM') {
13221                ii = indexOf.call(this._shortMonthsParse, llc);
13222                if (ii !== -1) {
13223                    return ii;
13224                }
13225                ii = indexOf.call(this._longMonthsParse, llc);
13226                return ii !== -1 ? ii : null;
13227            } else {
13228                ii = indexOf.call(this._longMonthsParse, llc);
13229                if (ii !== -1) {
13230                    return ii;
13231                }
13232                ii = indexOf.call(this._shortMonthsParse, llc);
13233                return ii !== -1 ? ii : null;
13234            }
13235        }
13236    }
13237
13238    function localeMonthsParse(monthName, format, strict) {
13239        var i, mom, regex;
13240
13241        if (this._monthsParseExact) {
13242            return handleStrictParse$1.call(this, monthName, format, strict);
13243        }
13244
13245        if (!this._monthsParse) {
13246            this._monthsParse = [];
13247            this._longMonthsParse = [];
13248            this._shortMonthsParse = [];
13249        }
13250
13251        // TODO: add sorting
13252        // Sorting makes sure if one month (or abbr) is a prefix of another
13253        // see sorting in computeMonthsParse
13254        for (i = 0; i < 12; i++) {
13255            // make the regex if we don't have it already
13256            mom = createUTC([2000, i]);
13257            if (strict && !this._longMonthsParse[i]) {
13258                this._longMonthsParse[i] = new RegExp(
13259                    '^' + this.months(mom, '').replace('.', '') + '$',
13260                    'i'
13261                );
13262                this._shortMonthsParse[i] = new RegExp(
13263                    '^' + this.monthsShort(mom, '').replace('.', '') + '$',
13264                    'i'
13265                );
13266            }
13267            if (!strict && !this._monthsParse[i]) {
13268                regex =
13269                    '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
13270                this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
13271            }
13272            // test the regex
13273            if (
13274                strict &&
13275                format === 'MMMM' &&
13276                this._longMonthsParse[i].test(monthName)
13277            ) {
13278                return i;
13279            } else if (
13280                strict &&
13281                format === 'MMM' &&
13282                this._shortMonthsParse[i].test(monthName)
13283            ) {
13284                return i;
13285            } else if (!strict && this._monthsParse[i].test(monthName)) {
13286                return i;
13287            }
13288        }
13289    }
13290
13291    // MOMENTS
13292
13293    function setMonth(mom, value) {
13294        if (!mom.isValid()) {
13295            // No op
13296            return mom;
13297        }
13298
13299        if (typeof value === 'string') {
13300            if (/^\d+$/.test(value)) {
13301                value = toInt(value);
13302            } else {
13303                value = mom.localeData().monthsParse(value);
13304                // TODO: Another silent failure?
13305                if (!isNumber(value)) {
13306                    return mom;
13307                }
13308            }
13309        }
13310
13311        var month = value,
13312            date = mom.date();
13313
13314        date = date < 29 ? date : Math.min(date, daysInMonth(mom.year(), month));
13315        void (mom._isUTC
13316            ? mom._d.setUTCMonth(month, date)
13317            : mom._d.setMonth(month, date));
13318        return mom;
13319    }
13320
13321    function getSetMonth(value) {
13322        if (value != null) {
13323            setMonth(this, value);
13324            hooks.updateOffset(this, true);
13325            return this;
13326        } else {
13327            return get$2(this, 'Month');
13328        }
13329    }
13330
13331    function getDaysInMonth() {
13332        return daysInMonth(this.year(), this.month());
13333    }
13334
13335    function monthsShortRegex(isStrict) {
13336        if (this._monthsParseExact) {
13337            if (!hasOwnProp(this, '_monthsRegex')) {
13338                computeMonthsParse.call(this);
13339            }
13340            if (isStrict) {
13341                return this._monthsShortStrictRegex;
13342            } else {
13343                return this._monthsShortRegex;
13344            }
13345        } else {
13346            if (!hasOwnProp(this, '_monthsShortRegex')) {
13347                this._monthsShortRegex = defaultMonthsShortRegex;
13348            }
13349            return this._monthsShortStrictRegex && isStrict
13350                ? this._monthsShortStrictRegex
13351                : this._monthsShortRegex;
13352        }
13353    }
13354
13355    function monthsRegex(isStrict) {
13356        if (this._monthsParseExact) {
13357            if (!hasOwnProp(this, '_monthsRegex')) {
13358                computeMonthsParse.call(this);
13359            }
13360            if (isStrict) {
13361                return this._monthsStrictRegex;
13362            } else {
13363                return this._monthsRegex;
13364            }
13365        } else {
13366            if (!hasOwnProp(this, '_monthsRegex')) {
13367                this._monthsRegex = defaultMonthsRegex;
13368            }
13369            return this._monthsStrictRegex && isStrict
13370                ? this._monthsStrictRegex
13371                : this._monthsRegex;
13372        }
13373    }
13374
13375    function computeMonthsParse() {
13376        function cmpLenRev(a, b) {
13377            return b.length - a.length;
13378        }
13379
13380        var shortPieces = [],
13381            longPieces = [],
13382            mixedPieces = [],
13383            i,
13384            mom,
13385            shortP,
13386            longP;
13387        for (i = 0; i < 12; i++) {
13388            // make the regex if we don't have it already
13389            mom = createUTC([2000, i]);
13390            shortP = regexEscape(this.monthsShort(mom, ''));
13391            longP = regexEscape(this.months(mom, ''));
13392            shortPieces.push(shortP);
13393            longPieces.push(longP);
13394            mixedPieces.push(longP);
13395            mixedPieces.push(shortP);
13396        }
13397        // Sorting makes sure if one month (or abbr) is a prefix of another it
13398        // will match the longer piece.
13399        shortPieces.sort(cmpLenRev);
13400        longPieces.sort(cmpLenRev);
13401        mixedPieces.sort(cmpLenRev);
13402
13403        this._monthsRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
13404        this._monthsShortRegex = this._monthsRegex;
13405        this._monthsStrictRegex = new RegExp(
13406            '^(' + longPieces.join('|') + ')',
13407            'i'
13408        );
13409        this._monthsShortStrictRegex = new RegExp(
13410            '^(' + shortPieces.join('|') + ')',
13411            'i'
13412        );
13413    }
13414
13415    // FORMATTING
13416
13417    addFormatToken('d', 0, 'do', 'day');
13418
13419    addFormatToken('dd', 0, 0, function (format) {
13420        return this.localeData().weekdaysMin(this, format);
13421    });
13422
13423    addFormatToken('ddd', 0, 0, function (format) {
13424        return this.localeData().weekdaysShort(this, format);
13425    });
13426
13427    addFormatToken('dddd', 0, 0, function (format) {
13428        return this.localeData().weekdays(this, format);
13429    });
13430
13431    addFormatToken('e', 0, 0, 'weekday');
13432    addFormatToken('E', 0, 0, 'isoWeekday');
13433    addFormatToken('eHHmm', 0, 0, function () {
13434        return (
13435            '' +
13436            this.weekday() +
13437            zeroFill(this.hours(), 2) +
13438            zeroFill(this.minutes(), 2)
13439        );
13440    });
13441
13442    // PARSING
13443
13444    addRegexToken('d', match1to2);
13445    addRegexToken('e', match1to2);
13446    addRegexToken('E', match1to2);
13447    addRegexToken('eHHmm', match5to6);
13448    addRegexToken('dd', function (isStrict, locale) {
13449        return locale.weekdaysMinRegex(isStrict);
13450    });
13451    addRegexToken('ddd', function (isStrict, locale) {
13452        return locale.weekdaysShortRegex(isStrict);
13453    });
13454    addRegexToken('dddd', function (isStrict, locale) {
13455        return locale.weekdaysRegex(isStrict);
13456    });
13457
13458    addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config, token) {
13459        var weekday = config._locale.weekdaysParse(input, token, config._strict);
13460        // if we didn't get a weekday name, mark the date as invalid
13461        if (weekday != null) {
13462            week.d = weekday;
13463        } else {
13464            getParsingFlags(config).invalidWeekday = input;
13465        }
13466    });
13467
13468    addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) {
13469        week[token] = toInt(input);
13470    });
13471
13472    addWeekParseToken('eHHmm', function (input, week, config) {
13473        var weekdayEnd = input.length - 4;
13474
13475        week.e = toInt(input.substr(0, weekdayEnd));
13476        config._a[HOUR] = toInt(input.substr(weekdayEnd, 2));
13477        config._a[MINUTE] = toInt(input.substr(weekdayEnd + 2));
13478    });
13479
13480    // HELPERS
13481
13482    function parseWeekday(input, locale) {
13483        if (typeof input !== 'string') {
13484            return input;
13485        }
13486
13487        if (!isNaN(input)) {
13488            return parseInt(input, 10);
13489        }
13490
13491        input = locale.weekdaysParse(input);
13492        if (typeof input === 'number') {
13493            return input;
13494        }
13495
13496        return null;
13497    }
13498
13499    function parseIsoWeekday(input, locale) {
13500        if (typeof input === 'string') {
13501            return locale.weekdaysParse(input) % 7 || 7;
13502        }
13503        return isNaN(input) ? null : input;
13504    }
13505
13506    // LOCALES
13507    function shiftWeekdays(ws, n) {
13508        return ws.slice(n, 7).concat(ws.slice(0, n));
13509    }
13510
13511    var defaultLocaleWeekdays =
13512            'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'),
13513        defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
13514        defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
13515        defaultWeekdaysRegex = matchWord,
13516        defaultWeekdaysShortRegex = matchWord,
13517        defaultWeekdaysMinRegex = matchWord,
13518        weekdaysParseProperties = [
13519            'weekdaysParse',
13520            'fullWeekdaysParse',
13521            'shortWeekdaysParse',
13522            'minWeekdaysParse',
13523            'weekdaysRegex',
13524            'weekdaysShortRegex',
13525            'weekdaysMinRegex',
13526            'weekdaysStrictRegex',
13527            'weekdaysShortStrictRegex',
13528            'weekdaysMinStrictRegex',
13529        ];
13530
13531    function clearWeekdaysParseCache(locale, config) {
13532        var i, prop;
13533        for (i = 0; i < weekdaysParseProperties.length; i++) {
13534            prop = weekdaysParseProperties[i];
13535            if (!hasOwnProp(config, prop)) {
13536                delete locale['_' + prop];
13537            }
13538        }
13539    }
13540
13541    function localeWeekdays(m, format) {
13542        var weekdays = isArray(this._weekdays)
13543            ? this._weekdays
13544            : this._weekdays[
13545                  m && m !== true && this._weekdays.isFormat.test(format)
13546                      ? 'format'
13547                      : 'standalone'
13548              ];
13549        return m === true
13550            ? shiftWeekdays(weekdays, this._week.dow)
13551            : m
13552              ? weekdays[m.day()]
13553              : weekdays;
13554    }
13555
13556    function localeWeekdaysShort(m) {
13557        return m === true
13558            ? shiftWeekdays(this._weekdaysShort, this._week.dow)
13559            : m
13560              ? this._weekdaysShort[m.day()]
13561              : this._weekdaysShort;
13562    }
13563
13564    function localeWeekdaysMin(m) {
13565        return m === true
13566            ? shiftWeekdays(this._weekdaysMin, this._week.dow)
13567            : m
13568              ? this._weekdaysMin[m.day()]
13569              : this._weekdaysMin;
13570    }
13571
13572    function handleStrictParse(weekdayName, format, strict) {
13573        var i,
13574            ii,
13575            mom,
13576            llc = weekdayName.toLocaleLowerCase();
13577        if (!this._weekdaysParse) {
13578            this._weekdaysParse = [];
13579            this._shortWeekdaysParse = [];
13580            this._minWeekdaysParse = [];
13581
13582            for (i = 0; i < 7; ++i) {
13583                mom = createUTC([2000, 1]).day(i);
13584                this._minWeekdaysParse[i] = this.weekdaysMin(
13585                    mom,
13586                    ''
13587                ).toLocaleLowerCase();
13588                this._shortWeekdaysParse[i] = this.weekdaysShort(
13589                    mom,
13590                    ''
13591                ).toLocaleLowerCase();
13592                this._weekdaysParse[i] = this.weekdays(mom, '').toLocaleLowerCase();
13593            }
13594        }
13595
13596        if (strict) {
13597            if (format === 'dddd') {
13598                ii = indexOf.call(this._weekdaysParse, llc);
13599                return ii !== -1 ? ii : null;
13600            } else if (format === 'ddd') {
13601                ii = indexOf.call(this._shortWeekdaysParse, llc);
13602                return ii !== -1 ? ii : null;
13603            } else {
13604                ii = indexOf.call(this._minWeekdaysParse, llc);
13605                return ii !== -1 ? ii : null;
13606            }
13607        } else {
13608            if (format === 'dddd') {
13609                ii = indexOf.call(this._weekdaysParse, llc);
13610                if (ii !== -1) {
13611                    return ii;
13612                }
13613                ii = indexOf.call(this._shortWeekdaysParse, llc);
13614                if (ii !== -1) {
13615                    return ii;
13616                }
13617                ii = indexOf.call(this._minWeekdaysParse, llc);
13618                return ii !== -1 ? ii : null;
13619            } else if (format === 'ddd') {
13620                ii = indexOf.call(this._shortWeekdaysParse, llc);
13621                if (ii !== -1) {
13622                    return ii;
13623                }
13624                ii = indexOf.call(this._weekdaysParse, llc);
13625                if (ii !== -1) {
13626                    return ii;
13627                }
13628                ii = indexOf.call(this._minWeekdaysParse, llc);
13629                return ii !== -1 ? ii : null;
13630            } else {
13631                ii = indexOf.call(this._minWeekdaysParse, llc);
13632                if (ii !== -1) {
13633                    return ii;
13634                }
13635                ii = indexOf.call(this._weekdaysParse, llc);
13636                if (ii !== -1) {
13637                    return ii;
13638                }
13639                ii = indexOf.call(this._shortWeekdaysParse, llc);
13640                return ii !== -1 ? ii : null;
13641            }
13642        }
13643    }
13644
13645    function localeWeekdaysParse(weekdayName, format, strict) {
13646        var i, mom, regex;
13647
13648        if (this._weekdaysParseExact) {
13649            return handleStrictParse.call(this, weekdayName, format, strict);
13650        }
13651
13652        if (!this._weekdaysParse) {
13653            this._weekdaysParse = [];
13654            this._minWeekdaysParse = [];
13655            this._shortWeekdaysParse = [];
13656            this._fullWeekdaysParse = [];
13657        }
13658
13659        for (i = 0; i < 7; i++) {
13660            // make the regex if we don't have it already
13661
13662            mom = createUTC([2000, 1]).day(i);
13663            if (strict && !this._fullWeekdaysParse[i]) {
13664                this._fullWeekdaysParse[i] = new RegExp(
13665                    '^' + this.weekdays(mom, '').replace('.', '\\.?') + '$',
13666                    'i'
13667                );
13668                this._shortWeekdaysParse[i] = new RegExp(
13669                    '^' + this.weekdaysShort(mom, '').replace('.', '\\.?') + '$',
13670                    'i'
13671                );
13672                this._minWeekdaysParse[i] = new RegExp(
13673                    '^' + this.weekdaysMin(mom, '').replace('.', '\\.?') + '$',
13674                    'i'
13675                );
13676            }
13677            if (!this._weekdaysParse[i]) {
13678                regex =
13679                    '^' +
13680                    this.weekdays(mom, '') +
13681                    '|^' +
13682                    this.weekdaysShort(mom, '') +
13683                    '|^' +
13684                    this.weekdaysMin(mom, '');
13685                this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
13686            }
13687            // test the regex
13688            if (
13689                strict &&
13690                format === 'dddd' &&
13691                this._fullWeekdaysParse[i].test(weekdayName)
13692            ) {
13693                return i;
13694            } else if (
13695                strict &&
13696                format === 'ddd' &&
13697                this._shortWeekdaysParse[i].test(weekdayName)
13698            ) {
13699                return i;
13700            } else if (
13701                strict &&
13702                format === 'dd' &&
13703                this._minWeekdaysParse[i].test(weekdayName)
13704            ) {
13705                return i;
13706            } else if (!strict && this._weekdaysParse[i].test(weekdayName)) {
13707                return i;
13708            }
13709        }
13710    }
13711
13712    // MOMENTS
13713
13714    function getSetDayOfWeek(input) {
13715        if (!this.isValid()) {
13716            return input != null ? this : NaN;
13717        }
13718
13719        var day = get$2(this, 'Day');
13720        if (input != null) {
13721            input = parseWeekday(input, this.localeData());
13722            return this.add(input - day, 'd');
13723        } else {
13724            return day;
13725        }
13726    }
13727
13728    function getSetLocaleDayOfWeek(input) {
13729        if (!this.isValid()) {
13730            return input != null ? this : NaN;
13731        }
13732        var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7;
13733        return input == null ? weekday : this.add(input - weekday, 'd');
13734    }
13735
13736    function getSetISODayOfWeek(input) {
13737        if (!this.isValid()) {
13738            return input != null ? this : NaN;
13739        }
13740
13741        // behaves the same as moment#day except
13742        // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
13743        // as a setter, sunday should belong to the previous week.
13744
13745        if (input != null) {
13746            var weekday = parseIsoWeekday(input, this.localeData());
13747            return this.day(this.day() % 7 ? weekday : weekday - 7);
13748        } else {
13749            return this.day() || 7;
13750        }
13751    }
13752
13753    function weekdaysRegex(isStrict) {
13754        if (this._weekdaysParseExact) {
13755            if (!hasOwnProp(this, '_weekdaysRegex')) {
13756                computeWeekdaysParse.call(this);
13757            }
13758            if (isStrict) {
13759                return this._weekdaysStrictRegex;
13760            } else {
13761                return this._weekdaysRegex;
13762            }
13763        } else {
13764            if (!hasOwnProp(this, '_weekdaysRegex')) {
13765                this._weekdaysRegex = defaultWeekdaysRegex;
13766            }
13767            return this._weekdaysStrictRegex && isStrict
13768                ? this._weekdaysStrictRegex
13769                : this._weekdaysRegex;
13770        }
13771    }
13772
13773    function weekdaysShortRegex(isStrict) {
13774        if (this._weekdaysParseExact) {
13775            if (!hasOwnProp(this, '_weekdaysRegex')) {
13776                computeWeekdaysParse.call(this);
13777            }
13778            if (isStrict) {
13779                return this._weekdaysShortStrictRegex;
13780            } else {
13781                return this._weekdaysShortRegex;
13782            }
13783        } else {
13784            if (!hasOwnProp(this, '_weekdaysShortRegex')) {
13785                this._weekdaysShortRegex = defaultWeekdaysShortRegex;
13786            }
13787            return this._weekdaysShortStrictRegex && isStrict
13788                ? this._weekdaysShortStrictRegex
13789                : this._weekdaysShortRegex;
13790        }
13791    }
13792
13793    function weekdaysMinRegex(isStrict) {
13794        if (this._weekdaysParseExact) {
13795            if (!hasOwnProp(this, '_weekdaysRegex')) {
13796                computeWeekdaysParse.call(this);
13797            }
13798            if (isStrict) {
13799                return this._weekdaysMinStrictRegex;
13800            } else {
13801                return this._weekdaysMinRegex;
13802            }
13803        } else {
13804            if (!hasOwnProp(this, '_weekdaysMinRegex')) {
13805                this._weekdaysMinRegex = defaultWeekdaysMinRegex;
13806            }
13807            return this._weekdaysMinStrictRegex && isStrict
13808                ? this._weekdaysMinStrictRegex
13809                : this._weekdaysMinRegex;
13810        }
13811    }
13812
13813    function computeWeekdaysParse() {
13814        function cmpLenRev(a, b) {
13815            return b.length - a.length;
13816        }
13817
13818        var minPieces = [],
13819            shortPieces = [],
13820            longPieces = [],
13821            mixedPieces = [],
13822            i,
13823            mom,
13824            minp,
13825            shortp,
13826            longp;
13827        for (i = 0; i < 7; i++) {
13828            // make the regex if we don't have it already
13829            mom = createUTC([2000, 1]).day(i);
13830            minp = regexEscape(this.weekdaysMin(mom, ''));
13831            shortp = regexEscape(this.weekdaysShort(mom, ''));
13832            longp = regexEscape(this.weekdays(mom, ''));
13833            minPieces.push(minp);
13834            shortPieces.push(shortp);
13835            longPieces.push(longp);
13836            mixedPieces.push(minp);
13837            mixedPieces.push(shortp);
13838            mixedPieces.push(longp);
13839        }
13840        // Sorting makes sure if one weekday (or abbr) is a prefix of another it
13841        // will match the longer piece.
13842        minPieces.sort(cmpLenRev);
13843        shortPieces.sort(cmpLenRev);
13844        longPieces.sort(cmpLenRev);
13845        mixedPieces.sort(cmpLenRev);
13846
13847        this._weekdaysRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
13848        this._weekdaysShortRegex = this._weekdaysRegex;
13849        this._weekdaysMinRegex = this._weekdaysRegex;
13850
13851        this._weekdaysStrictRegex = new RegExp(
13852            '^(' + longPieces.join('|') + ')',
13853            'i'
13854        );
13855        this._weekdaysShortStrictRegex = new RegExp(
13856            '^(' + shortPieces.join('|') + ')',
13857            'i'
13858        );
13859        this._weekdaysMinStrictRegex = new RegExp(
13860            '^(' + minPieces.join('|') + ')',
13861            'i'
13862        );
13863    }
13864
13865    function set(config) {
13866        var prop, i;
13867        clearMonthsParseCache(this, config);
13868        clearWeekdaysParseCache(this, config);
13869        for (i in config) {
13870            if (hasOwnProp(config, i)) {
13871                prop = config[i];
13872                if (isFunction(prop)) {
13873                    this[i] = prop;
13874                } else {
13875                    this['_' + i] = prop;
13876                }
13877            }
13878        }
13879        this._config = config;
13880        // Lenient ordinal parsing accepts just a number in addition to
13881        // number + (possibly) stuff coming from _dayOfMonthOrdinalParse.
13882        // TODO: Remove "ordinalParse" fallback in next major release.
13883        this._dayOfMonthOrdinalParseLenient = new RegExp(
13884            (this._dayOfMonthOrdinalParse.source || this._ordinalParse.source) +
13885                '|' +
13886                /\d{1,2}/.source
13887        );
13888    }
13889
13890    function mergeConfigs(parentConfig, childConfig) {
13891        var res = extend({}, parentConfig),
13892            prop;
13893        for (prop in childConfig) {
13894            if (hasOwnProp(childConfig, prop)) {
13895                if (isObject(parentConfig[prop]) && isObject(childConfig[prop])) {
13896                    res[prop] = {};
13897                    extend(res[prop], parentConfig[prop]);
13898                    extend(res[prop], childConfig[prop]);
13899                } else if (childConfig[prop] != null) {
13900                    res[prop] = childConfig[prop];
13901                } else {
13902                    delete res[prop];
13903                }
13904            }
13905        }
13906        for (prop in parentConfig) {
13907            if (
13908                hasOwnProp(parentConfig, prop) &&
13909                !hasOwnProp(childConfig, prop) &&
13910                isObject(parentConfig[prop])
13911            ) {
13912                // make sure changes to properties don't modify parent config
13913                res[prop] = extend({}, res[prop]);
13914            }
13915        }
13916        return res;
13917    }
13918
13919    function Locale(config) {
13920        if (config != null) {
13921            this.set(config);
13922        }
13923    }
13924
13925    var keys;
13926
13927    if (Object.keys) {
13928        keys = Object.keys;
13929    } else {
13930        keys = function (obj) {
13931            var i,
13932                res = [];
13933            for (i in obj) {
13934                if (hasOwnProp(obj, i)) {
13935                    res.push(i);
13936                }
13937            }
13938            return res;
13939        };
13940    }
13941
13942    var defaultCalendar = {
13943        sameDay: '[Today at] LT',
13944        nextDay: '[Tomorrow at] LT',
13945        nextWeek: 'dddd [at] LT',
13946        lastDay: '[Yesterday at] LT',
13947        lastWeek: '[Last] dddd [at] LT',
13948        sameElse: 'L',
13949    };
13950
13951    function calendar$1(key, mom, now) {
13952        var output = this._calendar[key] || this._calendar['sameElse'];
13953        return isFunction(output) ? output.call(mom, now) : output;
13954    }
13955
13956    var defaultLongDateFormat = {
13957        LTS: 'h:mm:ss A',
13958        LT: 'h:mm A',
13959        L: 'MM/DD/YYYY',
13960        LL: 'MMMM D, YYYY',
13961        LLL: 'MMMM D, YYYY h:mm A',
13962        LLLL: 'dddd, MMMM D, YYYY h:mm A',
13963    };
13964
13965    function longDateFormat(key) {
13966        var format = this._longDateFormat[key],
13967            formatUpper = this._longDateFormat[key.toUpperCase()],
13968            formatCache = this._longDateFormatCache;
13969
13970        if (format || !formatUpper) {
13971            return format;
13972        }
13973
13974        if (
13975            formatCache &&
13976            formatCache[key] &&
13977            formatCache[key].formatUpper === formatUpper
13978        ) {
13979            return formatCache[key].format;
13980        }
13981
13982        format = formatUpper
13983            .match(formattingTokens)
13984            .map(function (tok) {
13985                if (
13986                    tok === 'MMMM' ||
13987                    tok === 'MM' ||
13988                    tok === 'DD' ||
13989                    tok === 'dddd'
13990                ) {
13991                    return tok.slice(1);
13992                }
13993                return tok;
13994            })
13995            .join('');
13996
13997        if (!formatCache) {
13998            formatCache = this._longDateFormatCache = {};
13999        }
14000        formatCache[key] = {
14001            formatUpper: formatUpper,
14002            format: format,
14003        };
14004        return format;
14005    }
14006
14007    var defaultInvalidDate = 'Invalid date';
14008
14009    function invalidDate() {
14010        return this._invalidDate;
14011    }
14012
14013    var defaultOrdinal = '%d',
14014        defaultDayOfMonthOrdinalParse = /\d{1,2}/;
14015
14016    function ordinal(number) {
14017        return this._ordinal.replace('%d', number);
14018    }
14019
14020    var defaultRelativeTime = {
14021        future: 'in %s',
14022        past: '%s ago',
14023        s: 'a few seconds',
14024        ss: '%d seconds',
14025        m: 'a minute',
14026        mm: '%d minutes',
14027        h: 'an hour',
14028        hh: '%d hours',
14029        d: 'a day',
14030        dd: '%d days',
14031        w: 'a week',
14032        ww: '%d weeks',
14033        M: 'a month',
14034        MM: '%d months',
14035        y: 'a year',
14036        yy: '%d years',
14037    };
14038
14039    function relativeTimeWithoutPostformat(
14040        number,
14041        withoutSuffix,
14042        string,
14043        isFuture
14044    ) {
14045        var output = this._relativeTime[string];
14046        return isFunction(output)
14047            ? output(number, withoutSuffix, string, isFuture)
14048            : output.replace(/%d/i, number);
14049    }
14050
14051    function relativeTime$1(number, withoutSuffix, string, isFuture) {
14052        return this.postformat(
14053            relativeTimeWithoutPostformat.call(
14054                this,
14055                number,
14056                withoutSuffix,
14057                string,
14058                isFuture
14059            )
14060        );
14061    }
14062
14063    function pastFutureWithoutPostformat(diff, output) {
14064        var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
14065        return isFunction(format) ? format(output) : format.replace(/%s/i, output);
14066    }
14067
14068    function pastFuture(diff, output) {
14069        return this.postformat(
14070            pastFutureWithoutPostformat.call(this, diff, output)
14071        );
14072    }
14073
14074    function createDate(y, m, d, h, M, s, ms) {
14075        // can't just apply() to create a date:
14076        // https://stackoverflow.com/q/181348
14077        var date;
14078        // the date constructor remaps years 0-99 to 1900-1999
14079        if (y < 100 && y >= 0) {
14080            // preserve leap years using a full 400 year cycle, then reset
14081            date = new Date(y + 400, m, d, h, M, s, ms);
14082            if (isFinite(date.getFullYear())) {
14083                date.setFullYear(y);
14084            }
14085        } else {
14086            date = new Date(y, m, d, h, M, s, ms);
14087        }
14088
14089        return date;
14090    }
14091
14092    function createUTCDate(y) {
14093        var date, args;
14094        // the Date.UTC function remaps years 0-99 to 1900-1999
14095        if (y < 100 && y >= 0) {
14096            args = Array.prototype.slice.call(arguments);
14097            // preserve leap years using a full 400 year cycle, then reset
14098            args[0] = y + 400;
14099            date = new Date(Date.UTC.apply(null, args));
14100            if (isFinite(date.getUTCFullYear())) {
14101                date.setUTCFullYear(y);
14102            }
14103        } else {
14104            date = new Date(Date.UTC.apply(null, arguments));
14105        }
14106
14107        return date;
14108    }
14109
14110    // start-of-first-week - start-of-year
14111    function firstWeekOffset(year, dow, doy) {
14112        var // first-week day -- which january is always in the first week (4 for iso, 1 for other)
14113            fwd = 7 + dow - doy,
14114            // first-week day local weekday -- which local weekday is fwd
14115            fwdlw = (7 + createUTCDate(year, 0, fwd).getUTCDay() - dow) % 7;
14116
14117        return -fwdlw + fwd - 1;
14118    }
14119
14120    // https://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
14121    function dayOfYearFromWeeks(year, week, weekday, dow, doy) {
14122        var localWeekday = (7 + weekday - dow) % 7,
14123            weekOffset = firstWeekOffset(year, dow, doy),
14124            dayOfYear = 1 + 7 * (week - 1) + localWeekday + weekOffset,
14125            resYear,
14126            resDayOfYear;
14127
14128        if (dayOfYear <= 0) {
14129            resYear = year - 1;
14130            resDayOfYear = daysInYear(resYear) + dayOfYear;
14131        } else if (dayOfYear > daysInYear(year)) {
14132            resYear = year + 1;
14133            resDayOfYear = dayOfYear - daysInYear(year);
14134        } else {
14135            resYear = year;
14136            resDayOfYear = dayOfYear;
14137        }
14138
14139        return {
14140            year: resYear,
14141            dayOfYear: resDayOfYear,
14142        };
14143    }
14144
14145    function weekOfYearFromDayOfYear(year, dayOfYear, dow, doy) {
14146        var weekOffset = firstWeekOffset(year, dow, doy),
14147            week = Math.floor((dayOfYear - weekOffset - 1) / 7) + 1,
14148            resWeek,
14149            resYear;
14150
14151        if (week < 1) {
14152            resYear = year - 1;
14153            resWeek = week + weeksInYear(resYear, dow, doy);
14154        } else if (week > weeksInYear(year, dow, doy)) {
14155            resWeek = week - weeksInYear(year, dow, doy);
14156            resYear = year + 1;
14157        } else {
14158            resYear = year;
14159            resWeek = week;
14160        }
14161
14162        return {
14163            week: resWeek,
14164            year: resYear,
14165        };
14166    }
14167
14168    function weekOfYear(mom, dow, doy) {
14169        return weekOfYearFromDayOfYear(mom.year(), mom.dayOfYear(), dow, doy);
14170    }
14171
14172    function weekOfYearFromDate(year, month, date, dow, doy) {
14173        var dayOfYear =
14174            Math.round(
14175                (createUTCDate(year, month, date) - createUTCDate(year, 0, 1)) /
14176                    864e5
14177            ) + 1;
14178
14179        return weekOfYearFromDayOfYear(year, dayOfYear, dow, doy);
14180    }
14181
14182    function weeksInYear(year, dow, doy) {
14183        var weekOffset = firstWeekOffset(year, dow, doy),
14184            weekOffsetNext = firstWeekOffset(year + 1, dow, doy);
14185        return (daysInYear(year) - weekOffset + weekOffsetNext) / 7;
14186    }
14187
14188    // FORMATTING
14189
14190    addFormatToken('w', ['ww', 2], 'wo', 'week');
14191    addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek');
14192
14193    // PARSING
14194
14195    addRegexToken('w', match1to2, match1to2NoLeadingZero);
14196    addRegexToken('ww', match1to2, match2);
14197    addRegexToken('W', match1to2, match1to2NoLeadingZero);
14198    addRegexToken('WW', match1to2, match2);
14199
14200    addWeekParseToken(
14201        ['w', 'ww', 'W', 'WW'],
14202        function (input, week, config, token) {
14203            week[token.substr(0, 1)] = toInt(input);
14204        }
14205    );
14206
14207    // HELPERS
14208
14209    // LOCALES
14210
14211    function localeWeek(mom) {
14212        return weekOfYear(mom, this._week.dow, this._week.doy).week;
14213    }
14214
14215    var defaultLocaleWeek = {
14216        dow: 0, // Sunday is the first day of the week.
14217        doy: 6, // The week that contains Jan 6th is the first week of the year.
14218    };
14219
14220    function localeFirstDayOfWeek() {
14221        return this._week.dow;
14222    }
14223
14224    function localeFirstDayOfYear() {
14225        return this._week.doy;
14226    }
14227
14228    // MOMENTS
14229
14230    function getSetWeek(input) {
14231        var week = this.localeData().week(this);
14232        return input == null ? week : this.add((input - week) * 7, 'd');
14233    }
14234
14235    function getSetISOWeek(input) {
14236        var week = weekOfYear(this, 1, 4).week;
14237        return input == null ? week : this.add((input - week) * 7, 'd');
14238    }
14239
14240    // FORMATTING
14241
14242    function hFormat() {
14243        return this.hours() % 12 || 12;
14244    }
14245
14246    function kFormat() {
14247        return this.hours() || 24;
14248    }
14249
14250    addFormatToken('H', ['HH', 2], 0, 'hour');
14251    addFormatToken('h', ['hh', 2], 0, hFormat);
14252    addFormatToken('k', ['kk', 2], 0, kFormat);
14253
14254    addFormatToken('hmm', 0, 0, function () {
14255        return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2);
14256    });
14257
14258    addFormatToken('hmmss', 0, 0, function () {
14259        return (
14260            '' +
14261            hFormat.apply(this) +
14262            zeroFill(this.minutes(), 2) +
14263            zeroFill(this.seconds(), 2)
14264        );
14265    });
14266
14267    addFormatToken('Hmm', 0, 0, function () {
14268        return '' + this.hours() + zeroFill(this.minutes(), 2);
14269    });
14270
14271    addFormatToken('Hmmss', 0, 0, function () {
14272        return (
14273            '' +
14274            this.hours() +
14275            zeroFill(this.minutes(), 2) +
14276            zeroFill(this.seconds(), 2)
14277        );
14278    });
14279
14280    function meridiem(token, lowercase) {
14281        addFormatToken(token, 0, 0, function () {
14282            return this.localeData().meridiem(
14283                this.hours(),
14284                this.minutes(),
14285                lowercase
14286            );
14287        });
14288    }
14289
14290    meridiem('a', true);
14291    meridiem('A', false);
14292
14293    // PARSING
14294
14295    function matchMeridiem(isStrict, locale) {
14296        return locale._meridiemParse;
14297    }
14298
14299    addRegexToken('a', matchMeridiem);
14300    addRegexToken('A', matchMeridiem);
14301    addRegexToken('H', match1to2, match1to2HasZero);
14302    addRegexToken('h', match1to2, match1to2NoLeadingZero);
14303    addRegexToken('k', match1to2, match1to2NoLeadingZero);
14304    addRegexToken('HH', match1to2, match2);
14305    addRegexToken('hh', match1to2, match2);
14306    addRegexToken('kk', match1to2, match2);
14307
14308    addRegexToken('hmm', match3to4);
14309    addRegexToken('hmmss', match5to6);
14310    addRegexToken('Hmm', match3to4);
14311    addRegexToken('Hmmss', match5to6);
14312
14313    addParseToken(['H', 'HH'], HOUR);
14314    addParseToken(['k', 'kk'], function (input, array, config) {
14315        var kInput = toInt(input);
14316        array[HOUR] = kInput === 24 ? 0 : kInput;
14317    });
14318    addParseToken(['a', 'A'], function (input, array, config) {
14319        config._isPm = config._locale.isPM(input);
14320        config._meridiem = input;
14321    });
14322    addParseToken(['h', 'hh'], function (input, array, config) {
14323        array[HOUR] = toInt(input);
14324        getParsingFlags(config).bigHour = true;
14325    });
14326    addParseToken('hmm', function (input, array, config) {
14327        var pos = input.length - 2;
14328        array[HOUR] = toInt(input.substr(0, pos));
14329        array[MINUTE] = toInt(input.substr(pos));
14330        getParsingFlags(config).bigHour = true;
14331    });
14332    addParseToken('hmmss', function (input, array, config) {
14333        var pos1 = input.length - 4,
14334            pos2 = input.length - 2;
14335        array[HOUR] = toInt(input.substr(0, pos1));
14336        array[MINUTE] = toInt(input.substr(pos1, 2));
14337        array[SECOND] = toInt(input.substr(pos2));
14338        getParsingFlags(config).bigHour = true;
14339    });
14340    addParseToken('Hmm', function (input, array, config) {
14341        var pos = input.length - 2;
14342        array[HOUR] = toInt(input.substr(0, pos));
14343        array[MINUTE] = toInt(input.substr(pos));
14344    });
14345    addParseToken('Hmmss', function (input, array, config) {
14346        var pos1 = input.length - 4,
14347            pos2 = input.length - 2;
14348        array[HOUR] = toInt(input.substr(0, pos1));
14349        array[MINUTE] = toInt(input.substr(pos1, 2));
14350        array[SECOND] = toInt(input.substr(pos2));
14351    });
14352
14353    // LOCALES
14354
14355    function localeIsPM(input) {
14356        // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
14357        // Using charAt should be more compatible.
14358        return (input + '').toLowerCase().charAt(0) === 'p';
14359    }
14360
14361    var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i,
14362        // Setting the hour should keep the time, because the user explicitly
14363        // specified which hour they want. So trying to maintain the same hour (in
14364        // a new timezone) makes sense. Adding/subtracting hours does not follow
14365        // this rule.
14366        getSetHour = makeGetSet('Hours', true);
14367
14368    function localeMeridiem(hours, minutes, isLower) {
14369        if (hours > 11) {
14370            return isLower ? 'pm' : 'PM';
14371        } else {
14372            return isLower ? 'am' : 'AM';
14373        }
14374    }
14375
14376    var baseConfig = {
14377        calendar: defaultCalendar,
14378        longDateFormat: defaultLongDateFormat,
14379        invalidDate: defaultInvalidDate,
14380        ordinal: defaultOrdinal,
14381        dayOfMonthOrdinalParse: defaultDayOfMonthOrdinalParse,
14382        relativeTime: defaultRelativeTime,
14383
14384        months: defaultLocaleMonths,
14385        monthsShort: defaultLocaleMonthsShort,
14386
14387        week: defaultLocaleWeek,
14388
14389        weekdays: defaultLocaleWeekdays,
14390        weekdaysMin: defaultLocaleWeekdaysMin,
14391        weekdaysShort: defaultLocaleWeekdaysShort,
14392
14393        meridiemParse: defaultLocaleMeridiemParse,
14394    };
14395
14396    // internal storage for locale config files
14397    var locales = {},
14398        localeFamilies = {},
14399        globalLocale;
14400
14401    function commonPrefix(arr1, arr2) {
14402        var i,
14403            minl = Math.min(arr1.length, arr2.length);
14404        for (i = 0; i < minl; i += 1) {
14405            if (arr1[i] !== arr2[i]) {
14406                return i;
14407            }
14408        }
14409        return minl;
14410    }
14411
14412    function normalizeLocale(key) {
14413        return key ? key.toLowerCase().replace('_', '-') : key;
14414    }
14415
14416    // pick the locale from the array
14417    // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
14418    // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
14419    function chooseLocale(names) {
14420        var i = 0,
14421            j,
14422            next,
14423            locale,
14424            split;
14425
14426        while (i < names.length) {
14427            split = normalizeLocale(names[i]).split('-');
14428            j = split.length;
14429            next = normalizeLocale(names[i + 1]);
14430            next = next ? next.split('-') : null;
14431            while (j > 0) {
14432                locale = loadLocale(split.slice(0, j).join('-'));
14433                if (locale) {
14434                    return locale;
14435                }
14436                if (
14437                    next &&
14438                    next.length >= j &&
14439                    commonPrefix(split, next) >= j - 1
14440                ) {
14441                    //the next array item is better than a shallower substring of this one
14442                    break;
14443                }
14444                j--;
14445            }
14446            i++;
14447        }
14448        return globalLocale;
14449    }
14450
14451    function isLocaleNameSane(name) {
14452        // Only canonical locale module names are safe to append to the require path.
14453        return typeof name === 'string' && /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(name);
14454    }
14455
14456    function loadLocale(name) {
14457        var oldLocale = null,
14458            aliasedRequire,
14459            normalizedName;
14460
14461        // Preserve exact custom locale names before trying the canonical built-in name.
14462        // Use hasOwnProp rather than a plain lookup so that names like "__proto__",
14463        // "constructor", or "prototype" can't resolve to an inherited Object.prototype
14464        // property instead of a real (or missing) locale entry.
14465        if (hasOwnProp(locales, name)) {
14466            return locales[name];
14467        }
14468
14469        normalizedName = normalizeLocale(name);
14470        if (hasOwnProp(locales, normalizedName)) {
14471            return locales[normalizedName];
14472        }
14473
14474        // TODO: Find a better way to register and load all the locales in Node
14475        if (
14476            typeof module !== 'undefined' &&
14477            module &&
14478            module.exports &&
14479            isLocaleNameSane(normalizedName)
14480        ) {
14481            try {
14482                oldLocale = globalLocale._abbr;
14483                aliasedRequire = require;
14484                aliasedRequire('./locale/' + normalizedName);
14485                getSetGlobalLocale(oldLocale);
14486            } catch (e) {
14487                // mark as not found to avoid repeating expensive file require call causing high CPU
14488                // when trying to find en-US, en_US, en-us for every format call
14489                locales[normalizedName] = null; // null means not found
14490            }
14491        }
14492        if (hasOwnProp(locales, normalizedName)) {
14493            return locales[normalizedName];
14494        }
14495    }
14496
14497    // This function will load locale and then set the global locale.  If
14498    // no arguments are passed in, it will simply return the current global
14499    // locale key.
14500    function getSetGlobalLocale(key, values) {
14501        var data;
14502        if (key) {
14503            if (isUndefined(values)) {
14504                data = getLocale(key);
14505            } else {
14506                data = defineLocale(key, values);
14507            }
14508
14509            if (data) {
14510                // moment.duration._locale = moment._locale = data;
14511                globalLocale = data;
14512            } else {
14513                if (typeof console !== 'undefined' && console.warn) {
14514                    //warn user if arguments are passed but the locale could not be set
14515                    console.warn(
14516                        'Locale ' + key + ' not found. Did you forget to load it?'
14517                    );
14518                }
14519            }
14520        }
14521
14522        return globalLocale._abbr;
14523    }
14524
14525    function defineLocale(name, config) {
14526        if (config !== null) {
14527            var locale,
14528                parentConfig = baseConfig;
14529            config.abbr = name;
14530            if (locales[name] != null) {
14531                deprecateSimple(
14532                    'defineLocaleOverride',
14533                    'use moment.updateLocale(localeName, config) to change ' +
14534                        'an existing locale. moment.defineLocale(localeName, ' +
14535                        'config) should only be used for creating a new locale ' +
14536                        'See http://momentjs.com/guides/#/warnings/define-locale/ for more info.'
14537                );
14538                parentConfig = locales[name]._config;
14539            } else if (config.parentLocale != null) {
14540                if (locales[config.parentLocale] != null) {
14541                    parentConfig = locales[config.parentLocale]._config;
14542                } else {
14543                    locale = loadLocale(config.parentLocale);
14544                    if (locale != null) {
14545                        parentConfig = locale._config;
14546                    } else {
14547                        if (!localeFamilies[config.parentLocale]) {
14548                            localeFamilies[config.parentLocale] = [];
14549                        }
14550                        localeFamilies[config.parentLocale].push({
14551                            name: name,
14552                            config: config,
14553                        });
14554                        return null;
14555                    }
14556                }
14557            }
14558            locales[name] = new Locale(mergeConfigs(parentConfig, config));
14559
14560            if (localeFamilies[name]) {
14561                localeFamilies[name].forEach(function (x) {
14562                    defineLocale(x.name, x.config);
14563                });
14564            }
14565
14566            // backwards compat for now: also set the locale
14567            // make sure we set the locale AFTER all child locales have been
14568            // created, so we won't end up with the child locale set.
14569            getSetGlobalLocale(name);
14570
14571            return locales[name];
14572        } else {
14573            // useful for testing
14574            delete locales[name];
14575            return null;
14576        }
14577    }
14578
14579    function updateLocale(name, config) {
14580        var locale,
14581            tmpLocale = loadLocale(name),
14582            parentConfig = baseConfig;
14583
14584        if (tmpLocale != null) {
14585            name = tmpLocale._abbr;
14586        }
14587
14588        if (config != null) {
14589            if (locales[name] != null && locales[name].parentLocale != null) {
14590                // Update existing child locale in-place to avoid memory-leaks
14591                locales[name].set(mergeConfigs(locales[name]._config, config));
14592            } else {
14593                // MERGE
14594                if (tmpLocale != null) {
14595                    parentConfig = tmpLocale._config;
14596                }
14597                config = mergeConfigs(parentConfig, config);
14598                if (tmpLocale == null) {
14599                    // updateLocale is called for creating a new locale
14600                    // Set abbr so it will have a name (getters return
14601                    // undefined otherwise).
14602                    config.abbr = name;
14603                }
14604                locale = new Locale(config);
14605                locale.parentLocale = locales[name];
14606                locales[name] = locale;
14607            }
14608
14609            // backwards compat for now: also set the locale
14610            getSetGlobalLocale(name);
14611        } else {
14612            // pass null for config to unupdate, useful for tests
14613            if (locales[name] != null) {
14614                if (locales[name].parentLocale != null) {
14615                    locales[name] = locales[name].parentLocale;
14616                    if (name === getSetGlobalLocale()) {
14617                        getSetGlobalLocale(name);
14618                    }
14619                } else if (locales[name] != null) {
14620                    delete locales[name];
14621                }
14622            }
14623        }
14624        return locales[name];
14625    }
14626
14627    // returns locale data
14628    function getLocale(key) {
14629        var locale;
14630
14631        if (key && key._locale && key._locale._abbr) {
14632            key = key._locale._abbr;
14633        }
14634
14635        if (!key) {
14636            return globalLocale;
14637        }
14638
14639        if (!isArray(key)) {
14640            //short-circuit everything else
14641            locale = loadLocale(key);
14642            if (locale) {
14643                return locale;
14644            }
14645            key = [key];
14646        }
14647
14648        return chooseLocale(key);
14649    }
14650
14651    function listLocales() {
14652        return keys(locales);
14653    }
14654
14655    function checkOverflow(m) {
14656        var overflow,
14657            a = m._a;
14658
14659        if (a && getParsingFlags(m).overflow === -2) {
14660            overflow =
14661                a[MONTH] < 0 || a[MONTH] > 11
14662                    ? MONTH
14663                    : a[DATE] < 1 || a[DATE] > daysInMonth(a[YEAR], a[MONTH])
14664                      ? DATE
14665                      : a[HOUR] < 0 ||
14666                          a[HOUR] > 24 ||
14667                          (a[HOUR] === 24 &&
14668                              (a[MINUTE] !== 0 ||
14669                                  a[SECOND] !== 0 ||
14670                                  a[MILLISECOND] !== 0))
14671                        ? HOUR
14672                        : a[MINUTE] < 0 || a[MINUTE] > 59
14673                          ? MINUTE
14674                          : a[SECOND] < 0 || a[SECOND] > 59
14675                            ? SECOND
14676                            : a[MILLISECOND] < 0 || a[MILLISECOND] > 999
14677                              ? MILLISECOND
14678                              : -1;
14679
14680            if (
14681                getParsingFlags(m)._overflowDayOfYear &&
14682                (overflow < YEAR || overflow > DATE)
14683            ) {
14684                overflow = DATE;
14685            }
14686            if (getParsingFlags(m)._overflowWeeks && overflow === -1) {
14687                overflow = WEEK;
14688            }
14689            if (getParsingFlags(m)._overflowWeekday && overflow === -1) {
14690                overflow = WEEKDAY;
14691            }
14692
14693            getParsingFlags(m).overflow = overflow;
14694        }
14695
14696        return m;
14697    }
14698
14699    // iso 8601 regex
14700    // 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)
14701    var extendedIsoRegex =
14702            /^\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)?)?$/,
14703        basicIsoRegex =
14704            /^\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)?)?$/,
14705        tzRegex = /Z|[+-]\d\d(?::?\d\d)?/,
14706        isoDates = [
14707            ['YYYYYY-MM-DD', /[+-]\d{6}-\d\d-\d\d/],
14708            ['YYYY-MM-DD', /\d{4}-\d\d-\d\d/],
14709            ['GGGG-[W]WW-E', /\d{4}-W\d\d-\d/],
14710            ['GGGG-[W]WW', /\d{4}-W\d\d/, false],
14711            ['YYYY-DDD', /\d{4}-\d{3}/],
14712            ['YYYY-MM', /\d{4}-\d\d/, false],
14713            ['YYYYYYMMDD', /[+-]\d{10}/],
14714            ['YYYYMMDD', /\d{8}/],
14715            ['GGGG[W]WWE', /\d{4}W\d{3}/],
14716            ['GGGG[W]WW', /\d{4}W\d{2}/, false],
14717            ['YYYYDDD', /\d{7}/],
14718            ['YYYYMM', /\d{6}/, false],
14719            ['YYYY', /\d{4}/, false],
14720        ],
14721        // iso time formats and regexes
14722        isoTimes = [
14723            ['HH:mm:ss.SSSS', /\d\d:\d\d:\d\d\.\d+/],
14724            ['HH:mm:ss,SSSS', /\d\d:\d\d:\d\d,\d+/],
14725            ['HH:mm:ss', /\d\d:\d\d:\d\d/],
14726            ['HH:mm', /\d\d:\d\d/],
14727            ['HHmmss.SSSS', /\d\d\d\d\d\d\.\d+/],
14728            ['HHmmss,SSSS', /\d\d\d\d\d\d,\d+/],
14729            ['HHmmss', /\d\d\d\d\d\d/],
14730            ['HHmm', /\d\d\d\d/],
14731            ['HH', /\d\d/],
14732        ],
14733        aspNetJsonRegex = /^\/?Date\((-?\d+)/i,
14734        // RFC 2822 regex: For details see https://tools.ietf.org/html/rfc2822#section-3.3
14735        rfc2822 =
14736            /^(?:(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}))$/,
14737        obsOffsets = {
14738            UT: 0,
14739            GMT: 0,
14740            EDT: -4 * 60,
14741            EST: -5 * 60,
14742            CDT: -5 * 60,
14743            CST: -6 * 60,
14744            MDT: -6 * 60,
14745            MST: -7 * 60,
14746            PDT: -7 * 60,
14747            PST: -8 * 60,
14748        };
14749
14750    // date from iso format
14751    function configFromISO(config) {
14752        var i,
14753            l,
14754            string = config._i,
14755            match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string),
14756            allowTime,
14757            dateFormat,
14758            timeFormat,
14759            tzFormat,
14760            isoDatesLen = isoDates.length,
14761            isoTimesLen = isoTimes.length;
14762
14763        if (match) {
14764            getParsingFlags(config).iso = true;
14765            for (i = 0, l = isoDatesLen; i < l; i++) {
14766                if (isoDates[i][1].exec(match[1])) {
14767                    dateFormat = isoDates[i][0];
14768                    allowTime = isoDates[i][2] !== false;
14769                    break;
14770                }
14771            }
14772            if (dateFormat == null) {
14773                config._isValid = false;
14774                return;
14775            }
14776            if (match[3]) {
14777                for (i = 0, l = isoTimesLen; i < l; i++) {
14778                    if (isoTimes[i][1].exec(match[3])) {
14779                        // match[2] should be 'T' or space
14780                        timeFormat = (match[2] || ' ') + isoTimes[i][0];
14781                        break;
14782                    }
14783                }
14784                if (timeFormat == null) {
14785                    config._isValid = false;
14786                    return;
14787                }
14788            }
14789            if (!allowTime && timeFormat != null) {
14790                config._isValid = false;
14791                return;
14792            }
14793            if (match[4]) {
14794                if (tzRegex.exec(match[4])) {
14795                    tzFormat = 'Z';
14796                } else {
14797                    config._isValid = false;
14798                    return;
14799                }
14800            }
14801            config._f = dateFormat + (timeFormat || '') + (tzFormat || '');
14802            configFromStringAndFormat(config);
14803        } else {
14804            config._isValid = false;
14805        }
14806    }
14807
14808    function extractFromRFC2822Strings(
14809        yearStr,
14810        monthStr,
14811        dayStr,
14812        hourStr,
14813        minuteStr,
14814        secondStr
14815    ) {
14816        var result = [
14817            untruncateYear(yearStr),
14818            defaultLocaleMonthsShort.indexOf(monthStr),
14819            parseInt(dayStr, 10),
14820            parseInt(hourStr, 10),
14821            parseInt(minuteStr, 10),
14822        ];
14823
14824        if (secondStr) {
14825            result.push(parseInt(secondStr, 10));
14826        }
14827
14828        return result;
14829    }
14830
14831    function untruncateYear(yearStr) {
14832        var year = parseInt(yearStr, 10);
14833        if (year <= 49) {
14834            return 2000 + year;
14835        } else if (year <= 999) {
14836            return 1900 + year;
14837        }
14838        return year;
14839    }
14840
14841    function preprocessRFC2822(s) {
14842        // Remove comments and folding whitespace and replace multiple-spaces with a single space
14843        return s
14844            .replace(/\([^()]*\)|[\n\t]/g, ' ')
14845            .replace(/(\s\s+)/g, ' ')
14846            .replace(/^\s\s*/, '')
14847            .replace(/\s\s*$/, '');
14848    }
14849
14850    function checkWeekday(weekdayStr, parsedInput, config) {
14851        if (weekdayStr) {
14852            // TODO: Replace the vanilla JS Date object with an independent day-of-week check.
14853            var weekdayProvided = defaultLocaleWeekdaysShort.indexOf(weekdayStr),
14854                weekdayActual = new Date(
14855                    parsedInput[0],
14856                    parsedInput[1],
14857                    parsedInput[2]
14858                ).getDay();
14859            if (weekdayProvided !== weekdayActual) {
14860                getParsingFlags(config).weekdayMismatch = true;
14861                config._isValid = false;
14862                return false;
14863            }
14864        }
14865        return true;
14866    }
14867
14868    function calculateOffset(obsOffset, militaryOffset, numOffset) {
14869        if (obsOffset) {
14870            return obsOffsets[obsOffset];
14871        } else if (militaryOffset) {
14872            // the only allowed military tz is Z
14873            return 0;
14874        } else {
14875            var hm = parseInt(numOffset, 10),
14876                m = hm % 100,
14877                h = (hm - m) / 100;
14878            return h * 60 + m;
14879        }
14880    }
14881
14882    // date and time from ref 2822 format
14883    function configFromRFC2822(config) {
14884        var match = rfc2822.exec(preprocessRFC2822(config._i)),
14885            parsedArray;
14886        if (match) {
14887            parsedArray = extractFromRFC2822Strings(
14888                match[4],
14889                match[3],
14890                match[2],
14891                match[5],
14892                match[6],
14893                match[7]
14894            );
14895            if (!checkWeekday(match[1], parsedArray, config)) {
14896                return;
14897            }
14898
14899            config._a = parsedArray;
14900            config._tzm = calculateOffset(match[8], match[9], match[10]);
14901
14902            config._d = createUTCDate.apply(null, config._a);
14903            config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
14904
14905            getParsingFlags(config).rfc2822 = true;
14906        } else {
14907            config._isValid = false;
14908        }
14909    }
14910
14911    // date from 1) ASP.NET, 2) ISO, 3) RFC 2822 formats, or 4) optional fallback if parsing isn't strict
14912    function configFromString(config) {
14913        var matched = aspNetJsonRegex.exec(config._i);
14914        if (matched !== null) {
14915            config._d = new Date(+matched[1]);
14916            return;
14917        }
14918
14919        configFromISO(config);
14920        if (config._isValid === false) {
14921            delete config._isValid;
14922        } else {
14923            return;
14924        }
14925
14926        configFromRFC2822(config);
14927        if (config._isValid === false) {
14928            delete config._isValid;
14929        } else {
14930            return;
14931        }
14932
14933        if (config._strict) {
14934            config._isValid = false;
14935        } else {
14936            // Final attempt, use Input Fallback
14937            hooks.createFromInputFallback(config);
14938        }
14939    }
14940
14941    hooks.createFromInputFallback = deprecate(
14942        'value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), ' +
14943            'which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are ' +
14944            'discouraged. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.',
14945        function (config) {
14946            config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
14947        }
14948    );
14949
14950    // Pick the first defined of two or three arguments.
14951    function defaults(a, b, c) {
14952        if (a != null) {
14953            return a;
14954        }
14955        if (b != null) {
14956            return b;
14957        }
14958        return c;
14959    }
14960
14961    function currentDateArray(config, now, forWeek) {
14962        var hadWeekContext = Object.prototype.hasOwnProperty.call(
14963                config,
14964                '_isDefaultDatePartsForWeek'
14965            ),
14966            weekContext = config._isDefaultDatePartsForWeek;
14967
14968        // hooks is actually the exported moment object
14969        config._isDefaultDatePartsForWeek = !!forWeek;
14970        try {
14971            return hooks._getDefaultDateParts(config, now, forWeek);
14972        } finally {
14973            if (hadWeekContext) {
14974                config._isDefaultDatePartsForWeek = weekContext;
14975            } else {
14976                delete config._isDefaultDatePartsForWeek;
14977            }
14978        }
14979    }
14980
14981    function currentDateNow(config) {
14982        var now = config._defaultDatePartsNow;
14983
14984        if (!now) {
14985            return hooks.now();
14986        }
14987        if (!now.hasValue) {
14988            now.value = hooks.now();
14989            now.hasValue = true;
14990        }
14991        return now.value;
14992    }
14993
14994    // Internal hook for extensions that supply omitted calendar fields.
14995    function getDefaultDateParts(config, now, forWeek) {
14996        var useWeekDefaults = forWeek || config._isDefaultDatePartsForWeek,
14997            nowValue = useWeekDefaults ? createLocal(now) : new Date(now);
14998        if (useWeekDefaults) {
14999            return [nowValue.year(), nowValue.month(), nowValue.date()];
15000        }
15001        if (config._useUTC) {
15002            return [
15003                nowValue.getUTCFullYear(),
15004                nowValue.getUTCMonth(),
15005                nowValue.getUTCDate(),
15006            ];
15007        }
15008        return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()];
15009    }
15010
15011    hooks._getDefaultDateParts = getDefaultDateParts;
15012
15013    // convert an array to a date.
15014    // the array should mirror the parameters below
15015    // note: all values past the year are optional and will default to the lowest possible value.
15016    // [year, month, day , hour, minute, second, millisecond]
15017    function configFromArray(config) {
15018        var i,
15019            date,
15020            input = [],
15021            now,
15022            currentDate,
15023            expectedWeekday,
15024            yearToUse,
15025            dateIsDefaulted;
15026
15027        if (config._d) {
15028            return;
15029        }
15030
15031        if (
15032            config._a[YEAR] == null ||
15033            config._a[MONTH] == null ||
15034            config._a[DATE] == null
15035        ) {
15036            now = currentDateNow(config);
15037            currentDate = currentDateArray(config, now);
15038        }
15039
15040        //compute day of the year from weeks and weekdays
15041        if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
15042            dayOfYearFromWeekInfo(config, currentDateArray(config, now, true));
15043        }
15044
15045        //if the day of the year is set, figure out what it is
15046        if (config._dayOfYear != null) {
15047            yearToUse =
15048                config._a[YEAR] != null ? config._a[YEAR] : currentDate[YEAR];
15049
15050            if (
15051                config._dayOfYear > daysInYear(yearToUse) ||
15052                config._dayOfYear === 0
15053            ) {
15054                getParsingFlags(config)._overflowDayOfYear = true;
15055            }
15056
15057            date = createUTCDate(yearToUse, 0, config._dayOfYear);
15058            config._a[MONTH] = date.getUTCMonth();
15059            config._a[DATE] = date.getUTCDate();
15060        }
15061
15062        dateIsDefaulted =
15063            config._a[YEAR] == null ||
15064            config._a[MONTH] == null ||
15065            config._a[DATE] == null;
15066
15067        // Default to current date.
15068        // * if no year, month, day of month are given, default to today
15069        // * if day of month is given, default month and year
15070        // * if month is given, default only year
15071        // * if year is given, don't default anything
15072        for (i = 0; i < 3 && config._a[i] == null; ++i) {
15073            config._a[i] = input[i] = currentDate[i];
15074        }
15075
15076        // Zero out whatever was not defaulted, including time
15077        for (; i < 7; i++) {
15078            config._a[i] = input[i] =
15079                config._a[i] == null ? (i === 2 ? 1 : 0) : config._a[i];
15080        }
15081
15082        // Check for 24:00:00.000
15083        if (
15084            config._a[HOUR] === 24 &&
15085            config._a[MINUTE] === 0 &&
15086            config._a[SECOND] === 0 &&
15087            config._a[MILLISECOND] === 0
15088        ) {
15089            config._nextDay = true;
15090            config._a[HOUR] = 0;
15091        }
15092
15093        config._d = (config._useUTC ? createUTCDate : createDate).apply(
15094            null,
15095            input
15096        );
15097        expectedWeekday = config._useUTC
15098            ? config._d.getUTCDay()
15099            : config._d.getDay();
15100
15101        // Apply timezone offset from input. The actual utcOffset can be changed
15102        // with parseZone.
15103        if (config._tzm != null) {
15104            config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
15105        }
15106
15107        if (config._nextDay) {
15108            config._a[HOUR] = 24;
15109        }
15110
15111        // check for mismatching day of week
15112        if (
15113            config._w &&
15114            typeof config._w.d !== 'undefined' &&
15115            !dateIsDefaulted &&
15116            config._w.d !== expectedWeekday
15117        ) {
15118            getParsingFlags(config).weekdayMismatch = true;
15119        }
15120    }
15121
15122    function dayOfYearFromWeekInfo(config, currentDate) {
15123        var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow, curWeek;
15124
15125        w = config._w;
15126        if (w.GG != null || w.W != null || w.E != null) {
15127            dow = 1;
15128            doy = 4;
15129
15130            // TODO: We need to take the current isoWeekYear, but that depends on
15131            // how we interpret now (local, utc, fixed offset). So create
15132            // a now version of current config (take local/utc/offset flags, and
15133            // create now).
15134            weekYear = defaults(
15135                w.GG,
15136                config._a[YEAR],
15137                weekOfYearFromDate(
15138                    currentDate[YEAR],
15139                    currentDate[MONTH],
15140                    currentDate[DATE],
15141                    1,
15142                    4
15143                ).year
15144            );
15145            week = defaults(w.W, 1);
15146            weekday = defaults(w.E, 1);
15147            if (weekday < 1 || weekday > 7) {
15148                weekdayOverflow = true;
15149            }
15150        } else {
15151            dow = config._locale._week.dow;
15152            doy = config._locale._week.doy;
15153
15154            curWeek = weekOfYearFromDate(
15155                currentDate[YEAR],
15156                currentDate[MONTH],
15157                currentDate[DATE],
15158                dow,
15159                doy
15160            );
15161
15162            weekYear = defaults(w.gg, config._a[YEAR], curWeek.year);
15163
15164            // Default to current week.
15165            week = defaults(w.w, curWeek.week);
15166
15167            if (w.d != null) {
15168                // weekday -- low day numbers are considered next week
15169                weekday = w.d;
15170                if (weekday < 0 || weekday > 6) {
15171                    weekdayOverflow = true;
15172                }
15173            } else if (w.e != null) {
15174                // local weekday -- counting starts from beginning of week
15175                weekday = w.e + dow;
15176                if (w.e < 0 || w.e > 6) {
15177                    weekdayOverflow = true;
15178                }
15179            } else {
15180                // default to beginning of week
15181                weekday = dow;
15182            }
15183        }
15184        if (week < 1 || week > weeksInYear(weekYear, dow, doy)) {
15185            getParsingFlags(config)._overflowWeeks = true;
15186        } else if (weekdayOverflow != null) {
15187            getParsingFlags(config)._overflowWeekday = true;
15188        } else {
15189            temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy);
15190            config._a[YEAR] = temp.year;
15191            config._dayOfYear = temp.dayOfYear;
15192        }
15193    }
15194
15195    // constant that refers to the ISO standard
15196    hooks.ISO_8601 = function () {};
15197
15198    // constant that refers to the RFC 2822 form
15199    hooks.RFC_2822 = function () {};
15200
15201    // date from string and format string
15202    function configFromStringAndFormat(config) {
15203        // TODO: Move this to another part of the creation flow to prevent circular deps
15204        if (config._f === hooks.ISO_8601) {
15205            configFromISO(config);
15206            return;
15207        }
15208        if (config._f === hooks.RFC_2822) {
15209            configFromRFC2822(config);
15210            return;
15211        }
15212        config._a = [];
15213        getParsingFlags(config).empty = true;
15214
15215        // This array is used to make a Date, either with `new Date` or `Date.UTC`
15216        var string = '' + config._i,
15217            i,
15218            parsedInput,
15219            tokens,
15220            token,
15221            skipped,
15222            stringLength = string.length,
15223            totalParsedInputLength = 0,
15224            era,
15225            tokenLen;
15226
15227        tokens =
15228            expandFormat(config._f, config._locale).match(formattingTokens) || [];
15229        tokenLen = tokens.length;
15230        for (i = 0; i < tokenLen; i++) {
15231            token = tokens[i];
15232            parsedInput = (string.match(getParseRegexForToken(token, config)) ||
15233                [])[0];
15234            if (parsedInput) {
15235                skipped = string.substr(0, string.indexOf(parsedInput));
15236                if (skipped.length > 0) {
15237                    getParsingFlags(config).unusedInput.push(skipped);
15238                }
15239                string = string.slice(
15240                    string.indexOf(parsedInput) + parsedInput.length
15241                );
15242                totalParsedInputLength += parsedInput.length;
15243            }
15244            // don't parse if it's not a known token
15245            if (formatTokenFunctions[token]) {
15246                if (parsedInput) {
15247                    getParsingFlags(config).empty = false;
15248                } else {
15249                    getParsingFlags(config).unusedTokens.push(token);
15250                }
15251                addTimeToArrayFromToken(token, parsedInput, config);
15252            } else if (config._strict && !parsedInput) {
15253                getParsingFlags(config).unusedTokens.push(token);
15254            }
15255        }
15256
15257        // add remaining unparsed input length to the string
15258        getParsingFlags(config).charsLeftOver =
15259            stringLength - totalParsedInputLength;
15260        if (string.length > 0) {
15261            getParsingFlags(config).unusedInput.push(string);
15262        }
15263
15264        // clear _12h flag if hour is <= 12
15265        if (
15266            config._a[HOUR] <= 12 &&
15267            getParsingFlags(config).bigHour === true &&
15268            config._a[HOUR] > 0
15269        ) {
15270            getParsingFlags(config).bigHour = undefined;
15271        }
15272
15273        getParsingFlags(config).parsedDateParts = config._a.slice(0);
15274        getParsingFlags(config).meridiem = config._meridiem;
15275        // handle meridiem
15276        config._a[HOUR] = meridiemFixWrap(
15277            config._locale,
15278            config._a[HOUR],
15279            config._meridiem
15280        );
15281
15282        // handle era
15283        era = getParsingFlags(config).era;
15284        if (era !== null) {
15285            config._a[YEAR] = config._locale.erasConvertYear(era, config._a[YEAR]);
15286        }
15287
15288        configFromArray(config);
15289        checkOverflow(config);
15290    }
15291
15292    function meridiemFixWrap(locale, hour, meridiem) {
15293        var isPm;
15294
15295        if (meridiem == null) {
15296            // nothing to do
15297            return hour;
15298        }
15299        if (locale.meridiemHour != null) {
15300            return locale.meridiemHour(hour, meridiem);
15301        } else if (locale.isPM != null) {
15302            // Fallback
15303            isPm = locale.isPM(meridiem);
15304            if (isPm && hour < 12) {
15305                hour += 12;
15306            }
15307            if (!isPm && hour === 12) {
15308                hour = 0;
15309            }
15310            return hour;
15311        } else {
15312            // this is not supposed to happen
15313            return hour;
15314        }
15315    }
15316
15317    // date from string and array of format strings
15318    function configFromStringAndArray(config) {
15319        var tempConfig,
15320            bestMoment,
15321            scoreToBeat,
15322            i,
15323            currentScore,
15324            validFormatFound,
15325            bestFormatIsValid = false,
15326            defaultDatePartsNow = {},
15327            configfLen = config._f.length;
15328
15329        if (configfLen === 0) {
15330            getParsingFlags(config).invalidFormat = true;
15331            config._d = new Date(NaN);
15332            return;
15333        }
15334
15335        for (i = 0; i < configfLen; i++) {
15336            currentScore = 0;
15337            validFormatFound = false;
15338            tempConfig = copyConfig({}, config);
15339            if (config._useUTC != null) {
15340                tempConfig._useUTC = config._useUTC;
15341            }
15342            tempConfig._defaultDatePartsNow = defaultDatePartsNow;
15343            tempConfig._f = config._f[i];
15344            configFromStringAndFormat(tempConfig);
15345
15346            if (isValid$2(tempConfig)) {
15347                validFormatFound = true;
15348            }
15349
15350            // if there is any input that was not parsed add a penalty for that format
15351            currentScore += getParsingFlags(tempConfig).charsLeftOver;
15352
15353            //or tokens
15354            currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10;
15355
15356            getParsingFlags(tempConfig).score = currentScore;
15357
15358            if (!bestFormatIsValid) {
15359                if (
15360                    scoreToBeat == null ||
15361                    currentScore < scoreToBeat ||
15362                    validFormatFound
15363                ) {
15364                    scoreToBeat = currentScore;
15365                    bestMoment = tempConfig;
15366                    if (validFormatFound) {
15367                        bestFormatIsValid = true;
15368                    }
15369                }
15370            } else {
15371                if (currentScore < scoreToBeat) {
15372                    scoreToBeat = currentScore;
15373                    bestMoment = tempConfig;
15374                }
15375            }
15376        }
15377
15378        extend(config, bestMoment || tempConfig);
15379    }
15380
15381    function configFromObject(config) {
15382        if (config._d) {
15383            return;
15384        }
15385
15386        var i = normalizeObjectUnits(config._i),
15387            dayOrDate = i.day === undefined ? i.date : i.day;
15388        config._a = map(
15389            [i.year, i.month, dayOrDate, i.hour, i.minute, i.second, i.millisecond],
15390            function (obj) {
15391                return obj && parseInt(obj, 10);
15392            }
15393        );
15394
15395        configFromArray(config);
15396    }
15397
15398    function createFromConfig(config) {
15399        var res = new Moment(checkOverflow(prepareConfig(config)));
15400        if (res._nextDay) {
15401            // Adding is smart enough around DST
15402            res.add(1, 'd');
15403            res._nextDay = undefined;
15404        }
15405
15406        return res;
15407    }
15408
15409    function prepareConfig(config) {
15410        var input = config._i,
15411            format = config._f;
15412
15413        config._locale = config._locale || getLocale(config._l);
15414
15415        if (input === null || (format === undefined && input === '')) {
15416            return createInvalid$1({ nullInput: true });
15417        }
15418
15419        if (typeof input === 'string') {
15420            config._i = input = config._locale.preparse(input);
15421        }
15422
15423        if (isMoment(input)) {
15424            return new Moment(checkOverflow(input));
15425        } else if (isDate(input)) {
15426            config._d = input;
15427        } else if (isArray(format)) {
15428            configFromStringAndArray(config);
15429        } else if (format) {
15430            configFromStringAndFormat(config);
15431        } else {
15432            configFromInput(config);
15433        }
15434
15435        if (!isValid$2(config)) {
15436            config._d = null;
15437        }
15438
15439        return config;
15440    }
15441
15442    function configFromInput(config) {
15443        var input = config._i;
15444        if (isUndefined(input)) {
15445            config._d = new Date(hooks.now());
15446        } else if (isDate(input)) {
15447            config._d = new Date(input.valueOf());
15448        } else if (typeof input === 'string') {
15449            configFromString(config);
15450        } else if (isArray(input)) {
15451            config._a = map(input.slice(0), function (obj) {
15452                return parseInt(obj, 10);
15453            });
15454            configFromArray(config);
15455        } else if (isObject(input)) {
15456            configFromObject(config);
15457        } else if (isNumber(input)) {
15458            // from milliseconds
15459            config._d = new Date(input);
15460        } else {
15461            hooks.createFromInputFallback(config);
15462        }
15463    }
15464
15465    function createLocalOrUTC(input, format, locale, strict, isUTC) {
15466        var c = {};
15467
15468        if (format === true || format === false) {
15469            strict = format;
15470            format = undefined;
15471        }
15472
15473        if (locale === true || locale === false) {
15474            strict = locale;
15475            locale = undefined;
15476        }
15477
15478        if (
15479            (isObject(input) && isObjectEmpty(input)) ||
15480            (isArray(input) && input.length === 0)
15481        ) {
15482            input = undefined;
15483        }
15484        // object construction must be done this way.
15485        // https://github.com/moment/moment/issues/1423
15486        c._isAMomentObject = true;
15487        c._useUTC = c._isUTC = isUTC;
15488        c._l = locale;
15489        c._i = input;
15490        c._f = format;
15491        c._strict = strict;
15492
15493        return createFromConfig(c);
15494    }
15495
15496    function createLocal(input, format, locale, strict) {
15497        return createLocalOrUTC(input, format, locale, strict, false);
15498    }
15499
15500    var prototypeMin = deprecate(
15501            'moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/',
15502            function () {
15503                var other = createLocal.apply(null, arguments);
15504                if (this.isValid() && other.isValid()) {
15505                    return other < this ? this : other;
15506                } else {
15507                    return createInvalid$1();
15508                }
15509            }
15510        ),
15511        prototypeMax = deprecate(
15512            'moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/',
15513            function () {
15514                var other = createLocal.apply(null, arguments);
15515                if (this.isValid() && other.isValid()) {
15516                    return other > this ? this : other;
15517                } else {
15518                    return createInvalid$1();
15519                }
15520            }
15521        );
15522
15523    // Pick a moment m from moments so that m[fn](other) is true for all
15524    // other. This relies on the function fn to be transitive.
15525    //
15526    // moments should either be an array of moment objects or an array, whose
15527    // first element is an array of moment objects.
15528    function pickBy(fn, moments) {
15529        var res, i;
15530        if (moments.length === 1 && isArray(moments[0])) {
15531            moments = moments[0];
15532        }
15533        if (!moments.length) {
15534            return createLocal();
15535        }
15536        for (i = 0; i < moments.length; ++i) {
15537            if (isMoment(moments[i])) {
15538                res = moments[i];
15539                break;
15540            }
15541        }
15542        if (!res) {
15543            return createInvalid$1();
15544        }
15545        for (++i; i < moments.length; ++i) {
15546            if (
15547                isMoment(moments[i]) &&
15548                (!moments[i].isValid() || moments[i][fn](res))
15549            ) {
15550                res = moments[i];
15551            }
15552        }
15553        return res;
15554    }
15555
15556    // TODO: Use [].sort instead?
15557    function min() {
15558        var args = [].slice.call(arguments, 0);
15559
15560        return pickBy('isBefore', args);
15561    }
15562
15563    function max() {
15564        var args = [].slice.call(arguments, 0);
15565
15566        return pickBy('isAfter', args);
15567    }
15568
15569    var now = function () {
15570        return Date.now ? Date.now() : +new Date();
15571    };
15572
15573    var ordering = [
15574        'year',
15575        'quarter',
15576        'month',
15577        'week',
15578        'day',
15579        'hour',
15580        'minute',
15581        'second',
15582        'millisecond',
15583    ];
15584
15585    function isDurationValid(m) {
15586        var key,
15587            unitHasDecimal = false,
15588            i,
15589            orderLen = ordering.length;
15590        for (key in m) {
15591            if (
15592                hasOwnProp(m, key) &&
15593                !(
15594                    indexOf.call(ordering, key) !== -1 &&
15595                    (m[key] == null || !isNaN(m[key]))
15596                )
15597            ) {
15598                return false;
15599            }
15600        }
15601
15602        for (i = 0; i < orderLen; ++i) {
15603            if (m[ordering[i]]) {
15604                if (unitHasDecimal) {
15605                    return false; // only allow non-integers for smallest unit
15606                }
15607                if (parseFloat(m[ordering[i]]) !== toInt(m[ordering[i]])) {
15608                    unitHasDecimal = true;
15609                }
15610            }
15611        }
15612
15613        return true;
15614    }
15615
15616    function isValid$1() {
15617        return this._isValid;
15618    }
15619
15620    function createInvalid() {
15621        return createDuration(NaN);
15622    }
15623
15624    function Duration(duration) {
15625        var normalizedInput = normalizeObjectUnits(duration),
15626            years = normalizedInput.year || 0,
15627            quarters = normalizedInput.quarter || 0,
15628            months = normalizedInput.month || 0,
15629            weeks = normalizedInput.week || normalizedInput.isoWeek || 0,
15630            days = normalizedInput.day || 0,
15631            hours = normalizedInput.hour || 0,
15632            minutes = normalizedInput.minute || 0,
15633            seconds = normalizedInput.second || 0,
15634            milliseconds = normalizedInput.millisecond || 0;
15635
15636        this._isValid = isDurationValid(normalizedInput);
15637
15638        // representation for dateAddRemove
15639        this._milliseconds =
15640            +milliseconds +
15641            seconds * 1e3 + // 1000
15642            minutes * 6e4 + // 1000 * 60
15643            hours * 1000 * 60 * 60; //using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978
15644        // Because of dateAddRemove treats 24 hours as different from a
15645        // day when working around DST, we need to store them separately
15646        this._days = +days + weeks * 7;
15647        // It is impossible to translate months into days without knowing
15648        // which months you are are talking about, so we have to store
15649        // it separately.
15650        this._months = +months + quarters * 3 + years * 12;
15651
15652        this._data = {};
15653
15654        this._locale = getLocale();
15655
15656        this._bubble();
15657    }
15658
15659    function isDuration(obj) {
15660        return obj instanceof Duration;
15661    }
15662
15663    function absRound(number) {
15664        if (number < 0) {
15665            return Math.round(-1 * number) * -1;
15666        } else {
15667            return Math.round(number);
15668        }
15669    }
15670
15671    // compare two arrays, return the number of differences
15672    function compareArrays(array1, array2, dontConvert) {
15673        var len = Math.min(array1.length, array2.length),
15674            lengthDiff = Math.abs(array1.length - array2.length),
15675            diffs = 0,
15676            i;
15677        for (i = 0; i < len; i++) {
15678            if (
15679                (toInt(array1[i]) !== toInt(array2[i]))
15680            ) {
15681                diffs++;
15682            }
15683        }
15684        return diffs + lengthDiff;
15685    }
15686
15687    // FORMATTING
15688
15689    function offset(token, separator) {
15690        addFormatToken(token, 0, 0, function () {
15691            var offset = this.utcOffset(),
15692                sign = '+';
15693            if (offset < 0) {
15694                offset = -offset;
15695                sign = '-';
15696            }
15697            return (
15698                sign +
15699                zeroFill(~~(offset / 60), 2) +
15700                separator +
15701                zeroFill(~~offset % 60, 2)
15702            );
15703        });
15704    }
15705
15706    offset('Z', ':');
15707    offset('ZZ', '');
15708
15709    // PARSING
15710
15711    addRegexToken('Z', matchShortOffset);
15712    addRegexToken('ZZ', matchShortOffset);
15713    addParseToken(['Z', 'ZZ'], function (input, array, config) {
15714        var offset = offsetFromString(matchShortOffset, input);
15715        config._useUTC = true;
15716        config._tzm = offset;
15717        if (offset === null) {
15718            getParsingFlags(config).invalidOffset = input;
15719        }
15720    });
15721
15722    // HELPERS
15723
15724    // timezone chunker
15725    // '+10:00' > ['10',  '00']
15726    // '-1530'  > ['-15', '30']
15727    var chunkOffset = /([\+\-]|\d\d)/gi;
15728
15729    function offsetFromString(matcher, string) {
15730        var matches = (string || '').match(matcher),
15731            chunk,
15732            parts,
15733            minutes;
15734
15735        if (matches === null) {
15736            return null;
15737        }
15738
15739        chunk = matches[matches.length - 1] || [];
15740        parts = (chunk + '').match(chunkOffset) || ['-', 0, 0];
15741        minutes = +(parts[1] * 60) + toInt(parts[2]);
15742
15743        if (
15744            toInt(parts[2]) > 59 ||
15745            (parts[0] === '+' ? minutes > 14 * 60 : minutes > 12 * 60)
15746        ) {
15747            return null;
15748        }
15749
15750        return minutes === 0 ? 0 : parts[0] === '+' ? minutes : -minutes;
15751    }
15752
15753    // Return a moment from input, that is local/utc/zone equivalent to model.
15754    function cloneWithOffset(input, model) {
15755        var res, diff;
15756        if (model._isUTC) {
15757            res = model.clone();
15758            diff =
15759                (isMoment(input) || isDate(input)
15760                    ? input.valueOf()
15761                    : createLocal(input).valueOf()) - res.valueOf();
15762            // Use low-level api, because this fn is low-level api.
15763            res._d.setTime(res._d.valueOf() + diff);
15764            hooks.updateOffset(res, false);
15765            return res;
15766        } else {
15767            return createLocal(input).local();
15768        }
15769    }
15770
15771    function getDateOffset(m) {
15772        // On Firefox.24 Date#getTimezoneOffset returns a floating point.
15773        // https://github.com/moment/moment/pull/1871
15774        return -Math.round(m._d.getTimezoneOffset());
15775    }
15776
15777    // HOOKS
15778
15779    // This function will be called whenever a moment is mutated.
15780    // It is intended to keep the offset in sync with the timezone.
15781    hooks.updateOffset = function () {};
15782
15783    // MOMENTS
15784
15785    // keepLocalTime = true means only change the timezone, without
15786    // affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]-->
15787    // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset
15788    // +0200, so we adjust the time as needed, to be valid.
15789    //
15790    // Keeping the time actually adds/subtracts (one hour)
15791    // from the actual represented time. That is why we call updateOffset
15792    // a second time. In case it wants us to change the offset again
15793    // _changeInProgress == true case, then we have to adjust, because
15794    // there is no such time in the given timezone.
15795    function getSetOffset(input, keepLocalTime, keepMinutes) {
15796        var offset = this._offset || 0,
15797            localAdjust;
15798        if (!this.isValid()) {
15799            return input != null ? this : NaN;
15800        }
15801        if (input != null) {
15802            if (typeof input === 'string') {
15803                input = offsetFromString(matchShortOffset, input);
15804                if (input === null) {
15805                    return this;
15806                }
15807            } else if (Math.abs(input) < 16 && !keepMinutes) {
15808                input = input * 60;
15809            }
15810            if (!this._isUTC && keepLocalTime) {
15811                localAdjust = getDateOffset(this);
15812            }
15813            this._offset = input;
15814            this._isUTC = true;
15815            if (localAdjust != null) {
15816                this.add(localAdjust, 'm');
15817            }
15818            if (offset !== input) {
15819                if (!keepLocalTime || this._changeInProgress) {
15820                    addSubtract$1(
15821                        this,
15822                        createDuration(input - offset, 'm'),
15823                        1,
15824                        false
15825                    );
15826                } else if (!this._changeInProgress) {
15827                    this._changeInProgress = true;
15828                    hooks.updateOffset(this, true);
15829                    this._changeInProgress = null;
15830                }
15831            }
15832            return this;
15833        } else {
15834            return this._isUTC ? offset : getDateOffset(this);
15835        }
15836    }
15837
15838    function getSetZone(input, keepLocalTime) {
15839        if (input != null) {
15840            if (typeof input !== 'string') {
15841                input = -input;
15842            }
15843
15844            this.utcOffset(input, keepLocalTime);
15845
15846            return this;
15847        } else {
15848            return -this.utcOffset();
15849        }
15850    }
15851
15852    function setOffsetToUTC(keepLocalTime) {
15853        return this.utcOffset(0, keepLocalTime);
15854    }
15855
15856    function setOffsetToLocal(keepLocalTime) {
15857        if (this._isUTC) {
15858            this.utcOffset(0, keepLocalTime);
15859            this._isUTC = false;
15860
15861            if (keepLocalTime) {
15862                this.subtract(getDateOffset(this), 'm');
15863            }
15864        }
15865        return this;
15866    }
15867
15868    function setOffsetToParsedOffset() {
15869        if (this._tzm != null) {
15870            this.utcOffset(this._tzm, false, true);
15871        } else if (typeof this._i === 'string') {
15872            var tZone = offsetFromString(matchOffset, this._i);
15873            if (tZone != null) {
15874                this.utcOffset(tZone);
15875            } else {
15876                this.utcOffset(0, true);
15877            }
15878        }
15879        return this;
15880    }
15881
15882    function hasAlignedHourOffset(input) {
15883        if (!this.isValid()) {
15884            return false;
15885        }
15886        input = input ? createLocal(input).utcOffset() : 0;
15887
15888        return (this.utcOffset() - input) % 60 === 0;
15889    }
15890
15891    function isDaylightSavingTime() {
15892        return (
15893            this.utcOffset() > this.clone().month(0).utcOffset() ||
15894            this.utcOffset() > this.clone().month(5).utcOffset()
15895        );
15896    }
15897
15898    function isDaylightSavingTimeShifted() {
15899        if (!isUndefined(this._isDSTShifted)) {
15900            return this._isDSTShifted;
15901        }
15902
15903        var c = {},
15904            other;
15905
15906        copyConfig(c, this);
15907        c = prepareConfig(c);
15908
15909        if (c._a) {
15910            other = c._isUTC ? createUTC(c._a) : createLocal(c._a);
15911            this._isDSTShifted =
15912                this.isValid() && compareArrays(c._a, other.toArray()) > 0;
15913        } else {
15914            this._isDSTShifted = false;
15915        }
15916
15917        return this._isDSTShifted;
15918    }
15919
15920    function isLocal() {
15921        return this.isValid() ? !this._isUTC : false;
15922    }
15923
15924    function isUtcOffset() {
15925        return this.isValid() ? this._isUTC : false;
15926    }
15927
15928    function isUtc() {
15929        return this.isValid() ? this._isUTC && this._offset === 0 : false;
15930    }
15931
15932    // ASP.NET json date format regex
15933    var aspNetRegex = /^(-|\+)?(?:(\d*)[. ])?(\d+):(\d+)(?::(\d+)(\.\d*)?)?$/,
15934        // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
15935        // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
15936        // and further modified to allow for strings containing both week and day
15937        isoRegex =
15938            /^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;
15939
15940    function createDuration(input, key) {
15941        var duration = input,
15942            // matching against regexp is expensive, do it on demand
15943            match = null,
15944            sign,
15945            ret,
15946            diffRes;
15947
15948        if (isDuration(input)) {
15949            duration = {
15950                ms: input._milliseconds,
15951                d: input._days,
15952                M: input._months,
15953            };
15954        } else if (isNumber(input) || !isNaN(+input)) {
15955            duration = {};
15956            if (key) {
15957                duration[key] = +input;
15958            } else {
15959                duration.milliseconds = +input;
15960            }
15961        } else if ((match = aspNetRegex.exec(input))) {
15962            sign = match[1] === '-' ? -1 : 1;
15963            duration = {
15964                y: 0,
15965                d: toInt(match[DATE]) * sign,
15966                h: toInt(match[HOUR]) * sign,
15967                m: toInt(match[MINUTE]) * sign,
15968                s: toInt(match[SECOND]) * sign,
15969                ms: toInt(absRound(match[MILLISECOND] * 1000)) * sign, // the millisecond decimal point is included in the match
15970            };
15971        } else if ((match = isoRegex.exec(input))) {
15972            sign = match[1] === '-' ? -1 : 1;
15973            duration = {
15974                y: parseIso(match[2], sign),
15975                M: parseIso(match[3], sign),
15976                w: parseIso(match[4], sign),
15977                d: parseIso(match[5], sign),
15978                h: parseIso(match[6], sign),
15979                m: parseIso(match[7], sign),
15980                s: parseIso(match[8], sign),
15981            };
15982        } else if (duration == null) {
15983            // checks for null or undefined
15984            duration = {};
15985        } else if (
15986            typeof duration === 'object' &&
15987            ('from' in duration || 'to' in duration)
15988        ) {
15989            diffRes = momentsDifference(
15990                createLocal(duration.from),
15991                createLocal(duration.to)
15992            );
15993
15994            duration = {};
15995            duration.ms = diffRes.milliseconds;
15996            duration.M = diffRes.months;
15997        }
15998
15999        ret = new Duration(duration);
16000
16001        if (isDuration(input) && hasOwnProp(input, '_locale')) {
16002            ret._locale = input._locale;
16003        }
16004
16005        if (isDuration(input) && hasOwnProp(input, '_isValid')) {
16006            ret._isValid = input._isValid;
16007        }
16008
16009        return ret;
16010    }
16011
16012    createDuration.fn = Duration.prototype;
16013    createDuration.invalid = createInvalid;
16014
16015    function parseIso(inp, sign) {
16016        // We'd normally use ~~inp for this, but unfortunately it also
16017        // converts floats to ints.
16018        // inp may be undefined, so careful calling replace on it.
16019        var res = inp && parseFloat(inp.replace(',', '.'));
16020        // apply sign while we're at it
16021        return (isNaN(res) ? 0 : res) * sign;
16022    }
16023
16024    function positiveMomentsDifference(base, other) {
16025        var res = {};
16026
16027        res.months =
16028            other.month() - base.month() + (other.year() - base.year()) * 12;
16029        if (base.clone().add(res.months, 'M').isAfter(other)) {
16030            --res.months;
16031        }
16032
16033        res.milliseconds = +other - +base.clone().add(res.months, 'M');
16034
16035        return res;
16036    }
16037
16038    function momentsDifference(base, other) {
16039        var res;
16040        if (!(base.isValid() && other.isValid())) {
16041            return { milliseconds: 0, months: 0 };
16042        }
16043
16044        other = cloneWithOffset(other, base);
16045        if (base.isBefore(other)) {
16046            res = positiveMomentsDifference(base, other);
16047        } else {
16048            res = positiveMomentsDifference(other, base);
16049            res.milliseconds = -res.milliseconds;
16050            res.months = -res.months;
16051        }
16052
16053        return res;
16054    }
16055
16056    // TODO: remove 'name' arg after deprecation is removed
16057    function createAdder(direction, name) {
16058        return function (val, period) {
16059            var dur, tmp;
16060            //invert the arguments, but complain about it
16061            if (period !== null && !isNaN(+period)) {
16062                deprecateSimple(
16063                    name,
16064                    'moment().' +
16065                        name +
16066                        '(period, number) is deprecated. Please use moment().' +
16067                        name +
16068                        '(number, period). ' +
16069                        'See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info.'
16070                );
16071                tmp = val;
16072                val = period;
16073                period = tmp;
16074            }
16075
16076            dur = createDuration(val, period);
16077            addSubtract$1(this, dur, direction);
16078            return this;
16079        };
16080    }
16081
16082    function addSubtract$1(mom, duration, isAdding, updateOffset) {
16083        var milliseconds = duration._milliseconds,
16084            days = absRound(duration._days),
16085            months = absRound(duration._months);
16086
16087        if (!mom.isValid()) {
16088            // No op
16089            return;
16090        }
16091
16092        updateOffset = updateOffset == null ? true : updateOffset;
16093
16094        if (months) {
16095            setMonth(mom, get$2(mom, 'Month') + months * isAdding);
16096        }
16097        if (days) {
16098            set$1(mom, 'Date', get$2(mom, 'Date') + days * isAdding);
16099        }
16100        if (milliseconds) {
16101            mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding);
16102        }
16103        if (updateOffset) {
16104            hooks.updateOffset(mom, days || months);
16105        }
16106    }
16107
16108    var add$1 = createAdder(1, 'add'),
16109        subtract$1 = createAdder(-1, 'subtract');
16110
16111    function isString(input) {
16112        return typeof input === 'string' || input instanceof String;
16113    }
16114
16115    // type MomentInput = Moment | Date | string | number | (number | string)[] | MomentInputObject | void; // null | undefined
16116    function isMomentInput(input) {
16117        return (
16118            isMoment(input) ||
16119            isDate(input) ||
16120            isString(input) ||
16121            isNumber(input) ||
16122            isNumberOrStringArray(input) ||
16123            isMomentInputObject(input) ||
16124            input === null ||
16125            input === undefined
16126        );
16127    }
16128
16129    function isMomentInputObject(input) {
16130        var objectTest = isObject(input) && !isObjectEmpty(input),
16131            propertyTest = false,
16132            properties = [
16133                'years',
16134                'year',
16135                'y',
16136                'months',
16137                'month',
16138                'M',
16139                'days',
16140                'day',
16141                'd',
16142                'dates',
16143                'date',
16144                'D',
16145                'hours',
16146                'hour',
16147                'h',
16148                'minutes',
16149                'minute',
16150                'm',
16151                'seconds',
16152                'second',
16153                's',
16154                'milliseconds',
16155                'millisecond',
16156                'ms',
16157            ],
16158            i,
16159            property,
16160            propertyLen = properties.length;
16161
16162        for (i = 0; i < propertyLen; i += 1) {
16163            property = properties[i];
16164            propertyTest = propertyTest || hasOwnProp(input, property);
16165        }
16166
16167        return objectTest && propertyTest;
16168    }
16169
16170    function isNumberOrStringArray(input) {
16171        var arrayTest = isArray(input),
16172            dataTypeTest = false;
16173        if (arrayTest) {
16174            dataTypeTest =
16175                input.filter(function (item) {
16176                    return !isNumber(item) && isString(input);
16177                }).length === 0;
16178        }
16179        return arrayTest && dataTypeTest;
16180    }
16181
16182    function isCalendarSpec(input) {
16183        var objectTest = isObject(input) && !isObjectEmpty(input),
16184            propertyTest = false,
16185            properties = [
16186                'sameDay',
16187                'nextDay',
16188                'lastDay',
16189                'nextWeek',
16190                'lastWeek',
16191                'sameElse',
16192            ],
16193            i,
16194            property;
16195
16196        for (i = 0; i < properties.length; i += 1) {
16197            property = properties[i];
16198            propertyTest = propertyTest || hasOwnProp(input, property);
16199        }
16200
16201        return objectTest && propertyTest;
16202    }
16203
16204    function getCalendarFormat(myMoment, now) {
16205        var diff = myMoment.diff(now, 'days', true);
16206        return diff < -6
16207            ? 'sameElse'
16208            : diff < -1
16209              ? 'lastWeek'
16210              : diff < 0
16211                ? 'lastDay'
16212                : diff < 1
16213                  ? 'sameDay'
16214                  : diff < 2
16215                    ? 'nextDay'
16216                    : diff < 7
16217                      ? 'nextWeek'
16218                      : 'sameElse';
16219    }
16220
16221    function calendar(time, formats) {
16222        // Support for single parameter, formats only overload to the calendar function
16223        if (arguments.length === 1) {
16224            if (!arguments[0]) {
16225                time = undefined;
16226                formats = undefined;
16227            } else if (isMomentInput(arguments[0])) {
16228                time = arguments[0];
16229                formats = undefined;
16230            } else if (isCalendarSpec(arguments[0])) {
16231                formats = arguments[0];
16232                time = undefined;
16233            }
16234        }
16235        // We want to compare the start of today, vs this.
16236        // Getting start-of-today depends on whether we're local/utc/offset or not.
16237        var now = time || createLocal(),
16238            sod = cloneWithOffset(now, this).startOf('day'),
16239            format = hooks.calendarFormat(this, sod) || 'sameElse',
16240            output =
16241                formats &&
16242                (isFunction(formats[format])
16243                    ? formats[format].call(this, now)
16244                    : formats[format]);
16245
16246        return this.format(
16247            output || this.localeData().calendar(format, this, createLocal(now))
16248        );
16249    }
16250
16251    function clone$1() {
16252        return new Moment(this);
16253    }
16254
16255    function isAfter(input, units) {
16256        var localInput = isMoment(input) ? input : createLocal(input);
16257        if (!(this.isValid() && localInput.isValid())) {
16258            return false;
16259        }
16260        units = normalizeUnits(units) || 'millisecond';
16261        if (units === 'millisecond') {
16262            return this.valueOf() > localInput.valueOf();
16263        } else {
16264            return localInput.valueOf() < this.clone().startOf(units).valueOf();
16265        }
16266    }
16267
16268    function isBefore(input, units) {
16269        var localInput = isMoment(input) ? input : createLocal(input);
16270        if (!(this.isValid() && localInput.isValid())) {
16271            return false;
16272        }
16273        units = normalizeUnits(units) || 'millisecond';
16274        if (units === 'millisecond') {
16275            return this.valueOf() < localInput.valueOf();
16276        } else {
16277            return this.clone().endOf(units).valueOf() < localInput.valueOf();
16278        }
16279    }
16280
16281    function isBetween(from, to, units, inclusivity) {
16282        var localFrom = isMoment(from) ? from : createLocal(from),
16283            localTo = isMoment(to) ? to : createLocal(to);
16284        if (!(this.isValid() && localFrom.isValid() && localTo.isValid())) {
16285            return false;
16286        }
16287        inclusivity = inclusivity || '()';
16288        return (
16289            (inclusivity[0] === '('
16290                ? this.isAfter(localFrom, units)
16291                : !this.isBefore(localFrom, units)) &&
16292            (inclusivity[1] === ')'
16293                ? this.isBefore(localTo, units)
16294                : !this.isAfter(localTo, units))
16295        );
16296    }
16297
16298    function isSame(input, units) {
16299        var localInput = isMoment(input) ? input : createLocal(input),
16300            inputMs;
16301        if (!(this.isValid() && localInput.isValid())) {
16302            return false;
16303        }
16304        units = normalizeUnits(units) || 'millisecond';
16305        if (units === 'millisecond') {
16306            return this.valueOf() === localInput.valueOf();
16307        } else {
16308            inputMs = localInput.valueOf();
16309            return (
16310                this.clone().startOf(units).valueOf() <= inputMs &&
16311                inputMs <= this.clone().endOf(units).valueOf()
16312            );
16313        }
16314    }
16315
16316    function isSameOrAfter(input, units) {
16317        return this.isSame(input, units) || this.isAfter(input, units);
16318    }
16319
16320    function isSameOrBefore(input, units) {
16321        return this.isSame(input, units) || this.isBefore(input, units);
16322    }
16323
16324    function diff(input, units, asFloat) {
16325        var that, zoneDelta, output;
16326
16327        if (!this.isValid()) {
16328            return NaN;
16329        }
16330
16331        that = cloneWithOffset(input, this);
16332
16333        if (!that.isValid()) {
16334            return NaN;
16335        }
16336
16337        zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4;
16338
16339        units = normalizeUnits(units);
16340
16341        switch (units) {
16342            case 'year':
16343                output = monthDiff(this, that) / 12;
16344                break;
16345            case 'month':
16346                output = monthDiff(this, that);
16347                break;
16348            case 'quarter':
16349                output = monthDiff(this, that) / 3;
16350                break;
16351            case 'second':
16352                output = (this - that) / 1e3;
16353                break; // 1000
16354            case 'minute':
16355                output = (this - that) / 6e4;
16356                break; // 1000 * 60
16357            case 'hour':
16358                output = (this - that) / 36e5;
16359                break; // 1000 * 60 * 60
16360            case 'day':
16361                output = (this - that - zoneDelta) / 864e5;
16362                break; // 1000 * 60 * 60 * 24, negate dst
16363            case 'week':
16364                output = (this - that - zoneDelta) / 6048e5;
16365                break; // 1000 * 60 * 60 * 24 * 7, negate dst
16366            default:
16367                output = this - that;
16368        }
16369
16370        return asFloat ? output : absFloor(output);
16371    }
16372
16373    function monthDiff(a, b) {
16374        if (a.date() < b.date()) {
16375            // end-of-month calculations work correct when the start month has more
16376            // days than the end month.
16377            return -monthDiff(b, a);
16378        }
16379        // difference in months
16380        var wholeMonthDiff = (b.year() - a.year()) * 12 + (b.month() - a.month()),
16381            // b is in (anchor - 1 month, anchor + 1 month)
16382            anchor = a.clone().add(wholeMonthDiff, 'months'),
16383            anchor2,
16384            adjust;
16385
16386        if (b - anchor < 0) {
16387            anchor2 = a.clone().add(wholeMonthDiff - 1, 'months');
16388            // linear across the month
16389            adjust = (b - anchor) / (anchor - anchor2);
16390        } else {
16391            anchor2 = a.clone().add(wholeMonthDiff + 1, 'months');
16392            // linear across the month
16393            adjust = (b - anchor) / (anchor2 - anchor);
16394        }
16395
16396        //check for negative zero, return zero if negative zero
16397        return -(wholeMonthDiff + adjust) || 0;
16398    }
16399
16400    hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ';
16401    hooks.defaultFormatUtc = 'YYYY-MM-DDTHH:mm:ss[Z]';
16402
16403    function toString() {
16404        return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
16405    }
16406
16407    function toISOString$1(keepOffset) {
16408        if (!this.isValid()) {
16409            return null;
16410        }
16411        var utc = keepOffset !== true,
16412            m = utc ? this.clone().utc() : this;
16413        if (m.year() < 0 || m.year() > 9999) {
16414            return formatMoment(
16415                m,
16416                utc
16417                    ? 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]'
16418                    : 'YYYYYY-MM-DD[T]HH:mm:ss.SSSZ'
16419            );
16420        }
16421        if (isFunction(Date.prototype.toISOString)) {
16422            // native implementation is ~50x faster, use it when we can
16423            if (utc) {
16424                return this.toDate().toISOString();
16425            } else {
16426                return new Date(this.valueOf() + this.utcOffset() * 60 * 1000)
16427                    .toISOString()
16428                    .replace('Z', formatMoment(m, 'Z'));
16429            }
16430        }
16431        return formatMoment(
16432            m,
16433            utc ? 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]' : 'YYYY-MM-DD[T]HH:mm:ss.SSSZ'
16434        );
16435    }
16436
16437    /**
16438     * Return a human readable representation of a moment that can
16439     * also be evaluated to get a new moment which is the same
16440     *
16441     * @link https://nodejs.org/dist/latest/docs/api/util.html#util_custom_inspect_function_on_objects
16442     */
16443    function inspect() {
16444        if (!this.isValid()) {
16445            return 'moment.invalid(/* ' + this._i + ' */)';
16446        }
16447        var func = 'moment',
16448            zone = '',
16449            prefix,
16450            year,
16451            datetime,
16452            suffix;
16453        if (!this.isLocal()) {
16454            func = this.utcOffset() === 0 ? 'moment.utc' : 'moment.parseZone';
16455            zone = 'Z';
16456        }
16457        prefix = '[' + func + '("]';
16458        year = 0 <= this.year() && this.year() <= 9999 ? 'YYYY' : 'YYYYYY';
16459        datetime = '-MM-DD[T]HH:mm:ss.SSS';
16460        suffix = zone + '[")]';
16461
16462        return this.format(prefix + year + datetime + suffix);
16463    }
16464
16465    function format(inputString) {
16466        if (!inputString) {
16467            inputString = this.isUtc()
16468                ? hooks.defaultFormatUtc
16469                : hooks.defaultFormat;
16470        }
16471        var output = formatMoment(this, inputString);
16472        return this.localeData().postformat(output);
16473    }
16474
16475    function from(time, withoutSuffix) {
16476        if (
16477            this.isValid() &&
16478            ((isMoment(time) && time.isValid()) || createLocal(time).isValid())
16479        ) {
16480            return createDuration({ to: this, from: time })
16481                .locale(this.locale())
16482                .humanize(!withoutSuffix);
16483        } else {
16484            return this.localeData().invalidDate();
16485        }
16486    }
16487
16488    function fromNow(withoutSuffix) {
16489        return this.from(createLocal(), withoutSuffix);
16490    }
16491
16492    function to(time, withoutSuffix) {
16493        if (
16494            this.isValid() &&
16495            ((isMoment(time) && time.isValid()) || createLocal(time).isValid())
16496        ) {
16497            return createDuration({ from: this, to: time })
16498                .locale(this.locale())
16499                .humanize(!withoutSuffix);
16500        } else {
16501            return this.localeData().invalidDate();
16502        }
16503    }
16504
16505    function toNow(withoutSuffix) {
16506        return this.to(createLocal(), withoutSuffix);
16507    }
16508
16509    // If passed a locale key, it will set the locale for this
16510    // instance.  Otherwise, it will return the locale configuration
16511    // variables for this instance.
16512    function locale(key) {
16513        var newLocaleData;
16514
16515        if (key === undefined) {
16516            return this._locale._abbr;
16517        } else {
16518            newLocaleData = getLocale(key);
16519            if (newLocaleData != null) {
16520                this._locale = newLocaleData;
16521            }
16522            return this;
16523        }
16524    }
16525
16526    var lang = deprecate(
16527        'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.',
16528        function (key) {
16529            if (key === undefined) {
16530                return this.localeData();
16531            } else {
16532                return this.locale(key);
16533            }
16534        }
16535    );
16536
16537    function localeData() {
16538        return this._locale;
16539    }
16540
16541    var MS_PER_SECOND = 1000,
16542        MS_PER_MINUTE = 60 * MS_PER_SECOND,
16543        MS_PER_HOUR = 60 * MS_PER_MINUTE,
16544        MS_PER_400_YEARS = (365 * 400 + 97) * 24 * MS_PER_HOUR;
16545
16546    // actual modulo - handles negative numbers (for dates before 1970):
16547    function mod(dividend, divisor) {
16548        return ((dividend % divisor) + divisor) % divisor;
16549    }
16550
16551    function localStartOfDate(y, m, d) {
16552        // the date constructor remaps years 0-99 to 1900-1999
16553        if (y < 100 && y >= 0) {
16554            // preserve leap years using a full 400 year cycle, then reset
16555            return new Date(y + 400, m, d) - MS_PER_400_YEARS;
16556        } else {
16557            return new Date(y, m, d).valueOf();
16558        }
16559    }
16560
16561    function utcStartOfDate(y, m, d) {
16562        // Date.UTC remaps years 0-99 to 1900-1999
16563        if (y < 100 && y >= 0) {
16564            // preserve leap years using a full 400 year cycle, then reset
16565            return Date.UTC(y + 400, m, d) - MS_PER_400_YEARS;
16566        } else {
16567            return Date.UTC(y, m, d);
16568        }
16569    }
16570
16571    function startOf(units) {
16572        var time, startOfDate;
16573        units = normalizeUnits(units);
16574        if (units === undefined || units === 'millisecond' || !this.isValid()) {
16575            return this;
16576        }
16577
16578        startOfDate = this._isUTC ? utcStartOfDate : localStartOfDate;
16579
16580        switch (units) {
16581            case 'year':
16582                time = startOfDate(this.year(), 0, 1);
16583                break;
16584            case 'quarter':
16585                time = startOfDate(
16586                    this.year(),
16587                    this.month() - (this.month() % 3),
16588                    1
16589                );
16590                break;
16591            case 'month':
16592                time = startOfDate(this.year(), this.month(), 1);
16593                break;
16594            case 'week':
16595                time = startOfDate(
16596                    this.year(),
16597                    this.month(),
16598                    this.date() - this.weekday()
16599                );
16600                break;
16601            case 'isoWeek':
16602                time = startOfDate(
16603                    this.year(),
16604                    this.month(),
16605                    this.date() - (this.isoWeekday() - 1)
16606                );
16607                break;
16608            case 'day':
16609            case 'date':
16610                time = startOfDate(this.year(), this.month(), this.date());
16611                break;
16612            case 'hour':
16613                time = this._d.valueOf();
16614                time -= mod(
16615                    time + (this._isUTC ? 0 : this.utcOffset() * MS_PER_MINUTE),
16616                    MS_PER_HOUR
16617                );
16618                break;
16619            case 'minute':
16620                time = this._d.valueOf();
16621                time -= mod(time, MS_PER_MINUTE);
16622                break;
16623            case 'second':
16624                time = this._d.valueOf();
16625                time -= mod(time, MS_PER_SECOND);
16626                break;
16627        }
16628
16629        this._d.setTime(time);
16630        hooks.updateOffset(this, true);
16631        return this;
16632    }
16633
16634    function endOf(units) {
16635        var time, startOfDate;
16636        units = normalizeUnits(units);
16637        if (units === undefined || units === 'millisecond' || !this.isValid()) {
16638            return this;
16639        }
16640
16641        startOfDate = this._isUTC ? utcStartOfDate : localStartOfDate;
16642
16643        switch (units) {
16644            case 'year':
16645                time = startOfDate(this.year() + 1, 0, 1) - 1;
16646                break;
16647            case 'quarter':
16648                time =
16649                    startOfDate(
16650                        this.year(),
16651                        this.month() - (this.month() % 3) + 3,
16652                        1
16653                    ) - 1;
16654                break;
16655            case 'month':
16656                time = startOfDate(this.year(), this.month() + 1, 1) - 1;
16657                break;
16658            case 'week':
16659                time =
16660                    startOfDate(
16661                        this.year(),
16662                        this.month(),
16663                        this.date() - this.weekday() + 7
16664                    ) - 1;
16665                break;
16666            case 'isoWeek':
16667                time =
16668                    startOfDate(
16669                        this.year(),
16670                        this.month(),
16671                        this.date() - (this.isoWeekday() - 1) + 7
16672                    ) - 1;
16673                break;
16674            case 'day':
16675            case 'date':
16676                time = startOfDate(this.year(), this.month(), this.date() + 1) - 1;
16677                break;
16678            case 'hour':
16679                time = this._d.valueOf();
16680                time +=
16681                    MS_PER_HOUR -
16682                    mod(
16683                        time + (this._isUTC ? 0 : this.utcOffset() * MS_PER_MINUTE),
16684                        MS_PER_HOUR
16685                    ) -
16686                    1;
16687                break;
16688            case 'minute':
16689                time = this._d.valueOf();
16690                time += MS_PER_MINUTE - mod(time, MS_PER_MINUTE) - 1;
16691                break;
16692            case 'second':
16693                time = this._d.valueOf();
16694                time += MS_PER_SECOND - mod(time, MS_PER_SECOND) - 1;
16695                break;
16696        }
16697
16698        this._d.setTime(time);
16699        hooks.updateOffset(this, true);
16700        return this;
16701    }
16702
16703    function valueOf$1() {
16704        return this._d.valueOf() - (this._offset || 0) * 60000;
16705    }
16706
16707    function unix() {
16708        return Math.floor(this.valueOf() / 1000);
16709    }
16710
16711    function toDate() {
16712        return new Date(this.valueOf());
16713    }
16714
16715    function toArray() {
16716        var m = this;
16717        return [
16718            m.year(),
16719            m.month(),
16720            m.date(),
16721            m.hour(),
16722            m.minute(),
16723            m.second(),
16724            m.millisecond(),
16725        ];
16726    }
16727
16728    function toObject() {
16729        var m = this;
16730        return {
16731            years: m.year(),
16732            months: m.month(),
16733            date: m.date(),
16734            hours: m.hours(),
16735            minutes: m.minutes(),
16736            seconds: m.seconds(),
16737            milliseconds: m.milliseconds(),
16738        };
16739    }
16740
16741    function toJSON() {
16742        // new Date(NaN).toJSON() === null
16743        return this.isValid() ? this.toISOString() : null;
16744    }
16745
16746    function isValid() {
16747        return isValid$2(this);
16748    }
16749
16750    function parsingFlags() {
16751        return extend({}, getParsingFlags(this));
16752    }
16753
16754    function invalidAt() {
16755        return getParsingFlags(this).overflow;
16756    }
16757
16758    function creationData() {
16759        return {
16760            input: this._i,
16761            format: this._f,
16762            locale: this._locale,
16763            isUTC: this._isUTC,
16764            strict: this._strict,
16765        };
16766    }
16767
16768    addFormatToken('N', 0, 0, 'eraAbbr');
16769    addFormatToken('NN', 0, 0, 'eraAbbr');
16770    addFormatToken('NNN', 0, 0, 'eraAbbr');
16771    addFormatToken('NNNN', 0, 0, 'eraName');
16772    addFormatToken('NNNNN', 0, 0, 'eraNarrow');
16773
16774    addFormatToken('y', ['y', 1], 'yo', 'eraYear');
16775    addFormatToken('y', ['yy', 2], 0, 'eraYear');
16776    addFormatToken('y', ['yyy', 3], 0, 'eraYear');
16777    addFormatToken('y', ['yyyy', 4], 0, 'eraYear');
16778
16779    addRegexToken('N', matchEraAbbr);
16780    addRegexToken('NN', matchEraAbbr);
16781    addRegexToken('NNN', matchEraAbbr);
16782    addRegexToken('NNNN', matchEraName);
16783    addRegexToken('NNNNN', matchEraNarrow);
16784
16785    addParseToken(
16786        ['N', 'NN', 'NNN', 'NNNN', 'NNNNN'],
16787        function (input, array, config, token) {
16788            var era = config._locale.erasParse(input, token, config._strict);
16789            if (era) {
16790                getParsingFlags(config).era = era;
16791            } else {
16792                getParsingFlags(config).invalidEra = input;
16793            }
16794        }
16795    );
16796
16797    addRegexToken('y', matchUnsigned);
16798    addRegexToken('yy', matchUnsigned);
16799    addRegexToken('yyy', matchUnsigned);
16800    addRegexToken('yyyy', matchUnsigned);
16801    addRegexToken('yo', matchEraYearOrdinal);
16802
16803    addParseToken(['y', 'yy', 'yyy', 'yyyy'], YEAR);
16804    addParseToken(['yo'], function (input, array, config, token) {
16805        var match;
16806        if (config._locale._eraYearOrdinalRegex) {
16807            match = input.match(config._locale._eraYearOrdinalRegex);
16808        }
16809
16810        if (config._locale.eraYearOrdinalParse) {
16811            array[YEAR] = config._locale.eraYearOrdinalParse(input, match);
16812        } else {
16813            array[YEAR] = parseInt(input, 10);
16814        }
16815    });
16816
16817    function localeEras(m, format) {
16818        var i,
16819            l,
16820            date,
16821            eras = this._eras || getLocale('en')._eras;
16822        for (i = 0, l = eras.length; i < l; ++i) {
16823            switch (typeof eras[i].since) {
16824                case 'string':
16825                    // truncate time
16826                    date = hooks(eras[i].since).startOf('day');
16827                    eras[i].since = date.valueOf();
16828                    break;
16829            }
16830
16831            switch (typeof eras[i].until) {
16832                case 'undefined':
16833                    eras[i].until = +Infinity;
16834                    break;
16835                case 'string':
16836                    // truncate time
16837                    date = hooks(eras[i].until).startOf('day').valueOf();
16838                    eras[i].until = date.valueOf();
16839                    break;
16840            }
16841        }
16842        return eras;
16843    }
16844
16845    function localeErasParse(eraName, format, strict) {
16846        var i,
16847            l,
16848            eras = this.eras(),
16849            name,
16850            abbr,
16851            narrow;
16852        eraName = eraName.toUpperCase();
16853
16854        for (i = 0, l = eras.length; i < l; ++i) {
16855            name = eras[i].name.toUpperCase();
16856            abbr = eras[i].abbr.toUpperCase();
16857            narrow = eras[i].narrow.toUpperCase();
16858
16859            if (strict) {
16860                switch (format) {
16861                    case 'N':
16862                    case 'NN':
16863                    case 'NNN':
16864                        if (abbr === eraName) {
16865                            return eras[i];
16866                        }
16867                        break;
16868
16869                    case 'NNNN':
16870                        if (name === eraName) {
16871                            return eras[i];
16872                        }
16873                        break;
16874
16875                    case 'NNNNN':
16876                        if (narrow === eraName) {
16877                            return eras[i];
16878                        }
16879                        break;
16880                }
16881            } else if ([name, abbr, narrow].indexOf(eraName) >= 0) {
16882                return eras[i];
16883            }
16884        }
16885    }
16886
16887    function localeErasConvertYear(era, year) {
16888        var dir = era.since <= era.until ? 1 : -1;
16889        if (year === undefined) {
16890            return hooks(era.since).year();
16891        } else {
16892            return hooks(era.since).year() + (year - era.offset) * dir;
16893        }
16894    }
16895
16896    function getEraName() {
16897        var i,
16898            l,
16899            val,
16900            eras = this.localeData().eras();
16901        for (i = 0, l = eras.length; i < l; ++i) {
16902            // truncate time
16903            val = this.clone().startOf('day').valueOf();
16904
16905            if (eras[i].since <= val && val <= eras[i].until) {
16906                return eras[i].name;
16907            }
16908            if (eras[i].until <= val && val <= eras[i].since) {
16909                return eras[i].name;
16910            }
16911        }
16912
16913        return '';
16914    }
16915
16916    function getEraNarrow() {
16917        var i,
16918            l,
16919            val,
16920            eras = this.localeData().eras();
16921        for (i = 0, l = eras.length; i < l; ++i) {
16922            // truncate time
16923            val = this.clone().startOf('day').valueOf();
16924
16925            if (eras[i].since <= val && val <= eras[i].until) {
16926                return eras[i].narrow;
16927            }
16928            if (eras[i].until <= val && val <= eras[i].since) {
16929                return eras[i].narrow;
16930            }
16931        }
16932
16933        return '';
16934    }
16935
16936    function getEraAbbr() {
16937        var i,
16938            l,
16939            val,
16940            eras = this.localeData().eras();
16941        for (i = 0, l = eras.length; i < l; ++i) {
16942            // truncate time
16943            val = this.clone().startOf('day').valueOf();
16944
16945            if (eras[i].since <= val && val <= eras[i].until) {
16946                return eras[i].abbr;
16947            }
16948            if (eras[i].until <= val && val <= eras[i].since) {
16949                return eras[i].abbr;
16950            }
16951        }
16952
16953        return '';
16954    }
16955
16956    function getEraYear() {
16957        var i,
16958            l,
16959            dir,
16960            val,
16961            eras = this.localeData().eras();
16962        for (i = 0, l = eras.length; i < l; ++i) {
16963            dir = eras[i].since <= eras[i].until ? 1 : -1;
16964
16965            // truncate time
16966            val = this.clone().startOf('day').valueOf();
16967
16968            if (
16969                (eras[i].since <= val && val <= eras[i].until) ||
16970                (eras[i].until <= val && val <= eras[i].since)
16971            ) {
16972                return (
16973                    (this.year() - hooks(eras[i].since).year()) * dir +
16974                    eras[i].offset
16975                );
16976            }
16977        }
16978
16979        return this.year();
16980    }
16981
16982    function erasNameRegex(isStrict) {
16983        if (!hasOwnProp(this, '_erasNameRegex')) {
16984            computeErasParse.call(this);
16985        }
16986        return isStrict ? this._erasNameRegex : this._erasRegex;
16987    }
16988
16989    function erasAbbrRegex(isStrict) {
16990        if (!hasOwnProp(this, '_erasAbbrRegex')) {
16991            computeErasParse.call(this);
16992        }
16993        return isStrict ? this._erasAbbrRegex : this._erasRegex;
16994    }
16995
16996    function erasNarrowRegex(isStrict) {
16997        if (!hasOwnProp(this, '_erasNarrowRegex')) {
16998            computeErasParse.call(this);
16999        }
17000        return isStrict ? this._erasNarrowRegex : this._erasRegex;
17001    }
17002
17003    function matchEraAbbr(isStrict, locale) {
17004        return locale.erasAbbrRegex(isStrict);
17005    }
17006
17007    function matchEraName(isStrict, locale) {
17008        return locale.erasNameRegex(isStrict);
17009    }
17010
17011    function matchEraNarrow(isStrict, locale) {
17012        return locale.erasNarrowRegex(isStrict);
17013    }
17014
17015    function matchEraYearOrdinal(isStrict, locale) {
17016        return locale._eraYearOrdinalRegex || matchUnsigned;
17017    }
17018
17019    function computeErasParse() {
17020        var abbrPieces = [],
17021            namePieces = [],
17022            narrowPieces = [],
17023            mixedPieces = [],
17024            i,
17025            l,
17026            erasName,
17027            erasAbbr,
17028            erasNarrow,
17029            eras = this.eras();
17030
17031        for (i = 0, l = eras.length; i < l; ++i) {
17032            erasName = regexEscape(eras[i].name);
17033            erasAbbr = regexEscape(eras[i].abbr);
17034            erasNarrow = regexEscape(eras[i].narrow);
17035
17036            namePieces.push(erasName);
17037            abbrPieces.push(erasAbbr);
17038            narrowPieces.push(erasNarrow);
17039            mixedPieces.push(erasName);
17040            mixedPieces.push(erasAbbr);
17041            mixedPieces.push(erasNarrow);
17042        }
17043
17044        this._erasRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
17045        this._erasNameRegex = new RegExp('^(' + namePieces.join('|') + ')', 'i');
17046        this._erasAbbrRegex = new RegExp('^(' + abbrPieces.join('|') + ')', 'i');
17047        this._erasNarrowRegex = new RegExp(
17048            '^(' + narrowPieces.join('|') + ')',
17049            'i'
17050        );
17051    }
17052
17053    // FORMATTING
17054
17055    addFormatToken(0, ['gg', 2], 0, function () {
17056        return this.weekYear() % 100;
17057    });
17058
17059    addFormatToken(0, ['GG', 2], 0, function () {
17060        return this.isoWeekYear() % 100;
17061    });
17062
17063    function addWeekYearFormatToken(token, getter) {
17064        addFormatToken(0, [token, token.length], 0, getter);
17065    }
17066
17067    addWeekYearFormatToken('gggg', 'weekYear');
17068    addWeekYearFormatToken('ggggg', 'weekYear');
17069    addWeekYearFormatToken('GGGG', 'isoWeekYear');
17070    addWeekYearFormatToken('GGGGG', 'isoWeekYear');
17071
17072    // ALIASES
17073
17074    // PARSING
17075
17076    addRegexToken('G', matchSigned);
17077    addRegexToken('g', matchSigned);
17078    addRegexToken('GG', match1to2, match2);
17079    addRegexToken('gg', match1to2, match2);
17080    addRegexToken('GGGG', match1to4, match4);
17081    addRegexToken('gggg', match1to4, match4);
17082    addRegexToken('GGGGG', match1to6, match6);
17083    addRegexToken('ggggg', match1to6, match6);
17084
17085    addWeekParseToken(
17086        ['gggg', 'ggggg', 'GGGG', 'GGGGG'],
17087        function (input, week, config, token) {
17088            week[token.substr(0, 2)] = toInt(input);
17089        }
17090    );
17091
17092    addWeekParseToken(['gg', 'GG'], function (input, week, config, token) {
17093        week[token] = hooks.parseTwoDigitYear(input);
17094    });
17095
17096    // MOMENTS
17097
17098    function getSetWeekYear(input) {
17099        return getSetWeekYearHelper.call(
17100            this,
17101            input,
17102            this.week(),
17103            this.weekday() + this.localeData()._week.dow,
17104            this.localeData()._week.dow,
17105            this.localeData()._week.doy
17106        );
17107    }
17108
17109    function getSetISOWeekYear(input) {
17110        return getSetWeekYearHelper.call(
17111            this,
17112            input,
17113            this.isoWeek(),
17114            this.isoWeekday(),
17115            1,
17116            4
17117        );
17118    }
17119
17120    function getISOWeeksInYear() {
17121        return weeksInYear(this.year(), 1, 4);
17122    }
17123
17124    function getISOWeeksInISOWeekYear() {
17125        return weeksInYear(this.isoWeekYear(), 1, 4);
17126    }
17127
17128    function getWeeksInYear() {
17129        var weekInfo = this.localeData()._week;
17130        return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);
17131    }
17132
17133    function getWeeksInWeekYear() {
17134        var weekInfo = this.localeData()._week;
17135        return weeksInYear(this.weekYear(), weekInfo.dow, weekInfo.doy);
17136    }
17137
17138    function getSetWeekYearHelper(input, week, weekday, dow, doy) {
17139        var weeksTarget;
17140        if (input == null) {
17141            return weekOfYear(this, dow, doy).year;
17142        } else {
17143            weeksTarget = weeksInYear(input, dow, doy);
17144            if (week > weeksTarget) {
17145                week = weeksTarget;
17146            }
17147            return setWeekAll.call(this, input, week, weekday, dow, doy);
17148        }
17149    }
17150
17151    function setWeekAll(weekYear, week, weekday, dow, doy) {
17152        var dayOfYearData = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy),
17153            date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear);
17154
17155        this.year(date.getUTCFullYear());
17156        this.month(date.getUTCMonth());
17157        this.date(date.getUTCDate());
17158        return this;
17159    }
17160
17161    // FORMATTING
17162
17163    addFormatToken('Q', 0, 'Qo', 'quarter');
17164
17165    // PARSING
17166
17167    addRegexToken('Q', match1);
17168    addParseToken('Q', function (input, array) {
17169        array[MONTH] = (toInt(input) - 1) * 3;
17170    });
17171
17172    // MOMENTS
17173
17174    function getSetQuarter(input) {
17175        return input == null
17176            ? Math.ceil((this.month() + 1) / 3)
17177            : this.month((input - 1) * 3 + (this.month() % 3));
17178    }
17179
17180    // FORMATTING
17181
17182    addFormatToken('D', ['DD', 2], 'Do', 'date');
17183
17184    // PARSING
17185
17186    addRegexToken('D', match1to2, match1to2NoLeadingZero);
17187    addRegexToken('DD', match1to2, match2);
17188    addRegexToken('Do', function (isStrict, locale) {
17189        // TODO: Remove "ordinalParse" fallback in next major release.
17190        return isStrict
17191            ? locale._dayOfMonthOrdinalParse || locale._ordinalParse
17192            : locale._dayOfMonthOrdinalParseLenient;
17193    });
17194
17195    addParseToken(['D', 'DD'], DATE);
17196    addParseToken('Do', function (input, array) {
17197        array[DATE] = toInt(input.match(match1to2)[0]);
17198    });
17199
17200    // MOMENTS
17201
17202    var getSetDayOfMonth = makeGetSet('Date', true);
17203
17204    // FORMATTING
17205
17206    addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear');
17207
17208    // PARSING
17209
17210    addRegexToken('DDD', match1to3);
17211    addRegexToken('DDDD', match3);
17212    addParseToken(['DDD', 'DDDD'], function (input, array, config) {
17213        config._dayOfYear = toInt(input);
17214    });
17215
17216    // HELPERS
17217
17218    // MOMENTS
17219
17220    function getSetDayOfYear(input) {
17221        var dayOfYear =
17222            Math.round(
17223                (this.clone().startOf('day') - this.clone().startOf('year')) / 864e5
17224            ) + 1;
17225        return input == null ? dayOfYear : this.add(input - dayOfYear, 'd');
17226    }
17227
17228    // FORMATTING
17229
17230    addFormatToken('m', ['mm', 2], 0, 'minute');
17231
17232    // PARSING
17233
17234    addRegexToken('m', match1to2, match1to2HasZero);
17235    addRegexToken('mm', match1to2, match2);
17236    addParseToken(['m', 'mm'], MINUTE);
17237
17238    // MOMENTS
17239
17240    var getSetMinute = makeGetSet('Minutes', false);
17241
17242    // FORMATTING
17243
17244    addFormatToken('s', ['ss', 2], 0, 'second');
17245
17246    // PARSING
17247
17248    addRegexToken('s', match1to2, match1to2HasZero);
17249    addRegexToken('ss', match1to2, match2);
17250    addParseToken(['s', 'ss'], SECOND);
17251
17252    // MOMENTS
17253
17254    var getSetSecond = makeGetSet('Seconds', false);
17255
17256    // FORMATTING
17257
17258    addFormatToken('S', 0, 0, function () {
17259        return ~~(this.millisecond() / 100);
17260    });
17261
17262    addFormatToken(0, ['SS', 2], 0, function () {
17263        return ~~(this.millisecond() / 10);
17264    });
17265
17266    addFormatToken(0, ['SSS', 3], 0, 'millisecond');
17267    addFormatToken(0, ['SSSS', 4], 0, function () {
17268        return this.millisecond() * 10;
17269    });
17270    addFormatToken(0, ['SSSSS', 5], 0, function () {
17271        return this.millisecond() * 100;
17272    });
17273    addFormatToken(0, ['SSSSSS', 6], 0, function () {
17274        return this.millisecond() * 1000;
17275    });
17276    addFormatToken(0, ['SSSSSSS', 7], 0, function () {
17277        return this.millisecond() * 10000;
17278    });
17279    addFormatToken(0, ['SSSSSSSS', 8], 0, function () {
17280        return this.millisecond() * 100000;
17281    });
17282    addFormatToken(0, ['SSSSSSSSS', 9], 0, function () {
17283        return this.millisecond() * 1000000;
17284    });
17285
17286    // PARSING
17287
17288    addRegexToken('S', match1to3, match1);
17289    addRegexToken('SS', match1to3, match2);
17290    addRegexToken('SSS', match1to3, match3);
17291
17292    var token, getSetMillisecond;
17293    for (token = 'SSSS'; token.length <= 9; token += 'S') {
17294        addRegexToken(token, matchUnsigned);
17295    }
17296
17297    function parseMs(input, array) {
17298        array[MILLISECOND] = toInt(('0.' + input) * 1000);
17299    }
17300
17301    for (token = 'S'; token.length <= 9; token += 'S') {
17302        addParseToken(token, parseMs);
17303    }
17304
17305    getSetMillisecond = makeGetSet('Milliseconds', false);
17306
17307    // FORMATTING
17308
17309    addFormatToken('z', 0, 0, 'zoneAbbr');
17310    addFormatToken('zz', 0, 0, 'zoneName');
17311
17312    // MOMENTS
17313
17314    function getZoneAbbr() {
17315        return this._isUTC ? 'UTC' : '';
17316    }
17317
17318    function getZoneName() {
17319        return this._isUTC ? 'Coordinated Universal Time' : '';
17320    }
17321
17322    var proto$2 = Moment.prototype;
17323
17324    proto$2.add = add$1;
17325    proto$2.calendar = calendar;
17326    proto$2.clone = clone$1;
17327    proto$2.diff = diff;
17328    proto$2.endOf = endOf;
17329    proto$2.format = format;
17330    proto$2.from = from;
17331    proto$2.fromNow = fromNow;
17332    proto$2.to = to;
17333    proto$2.toNow = toNow;
17334    proto$2.get = stringGet;
17335    proto$2.invalidAt = invalidAt;
17336    proto$2.isAfter = isAfter;
17337    proto$2.isBefore = isBefore;
17338    proto$2.isBetween = isBetween;
17339    proto$2.isSame = isSame;
17340    proto$2.isSameOrAfter = isSameOrAfter;
17341    proto$2.isSameOrBefore = isSameOrBefore;
17342    proto$2.isValid = isValid;
17343    proto$2.lang = lang;
17344    proto$2.locale = locale;
17345    proto$2.localeData = localeData;
17346    proto$2.max = prototypeMax;
17347    proto$2.min = prototypeMin;
17348    proto$2.parsingFlags = parsingFlags;
17349    proto$2.set = stringSet;
17350    proto$2.startOf = startOf;
17351    proto$2.subtract = subtract$1;
17352    proto$2.toArray = toArray;
17353    proto$2.toObject = toObject;
17354    proto$2.toDate = toDate;
17355    proto$2.toISOString = toISOString$1;
17356    proto$2.inspect = inspect;
17357    if (typeof Symbol !== 'undefined' && Symbol.for != null) {
17358        proto$2[Symbol.for('nodejs.util.inspect.custom')] = function () {
17359            return 'Moment<' + this.format() + '>';
17360        };
17361    }
17362    proto$2.toJSON = toJSON;
17363    proto$2.toString = toString;
17364    proto$2.unix = unix;
17365    proto$2.valueOf = valueOf$1;
17366    proto$2.creationData = creationData;
17367    proto$2.eraName = getEraName;
17368    proto$2.eraNarrow = getEraNarrow;
17369    proto$2.eraAbbr = getEraAbbr;
17370    proto$2.eraYear = getEraYear;
17371    proto$2.year = getSetYear;
17372    proto$2.isLeapYear = getIsLeapYear;
17373    proto$2.weekYear = getSetWeekYear;
17374    proto$2.isoWeekYear = getSetISOWeekYear;
17375    proto$2.quarter = proto$2.quarters = getSetQuarter;
17376    proto$2.month = getSetMonth;
17377    proto$2.daysInMonth = getDaysInMonth;
17378    proto$2.week = proto$2.weeks = getSetWeek;
17379    proto$2.isoWeek = proto$2.isoWeeks = getSetISOWeek;
17380    proto$2.weeksInYear = getWeeksInYear;
17381    proto$2.weeksInWeekYear = getWeeksInWeekYear;
17382    proto$2.isoWeeksInYear = getISOWeeksInYear;
17383    proto$2.isoWeeksInISOWeekYear = getISOWeeksInISOWeekYear;
17384    proto$2.date = getSetDayOfMonth;
17385    proto$2.day = proto$2.days = getSetDayOfWeek;
17386    proto$2.weekday = getSetLocaleDayOfWeek;
17387    proto$2.isoWeekday = getSetISODayOfWeek;
17388    proto$2.dayOfYear = getSetDayOfYear;
17389    proto$2.hour = proto$2.hours = getSetHour;
17390    proto$2.minute = proto$2.minutes = getSetMinute;
17391    proto$2.second = proto$2.seconds = getSetSecond;
17392    proto$2.millisecond = proto$2.milliseconds = getSetMillisecond;
17393    proto$2.utcOffset = getSetOffset;
17394    proto$2.utc = setOffsetToUTC;
17395    proto$2.local = setOffsetToLocal;
17396    proto$2.parseZone = setOffsetToParsedOffset;
17397    proto$2.hasAlignedHourOffset = hasAlignedHourOffset;
17398    proto$2.isDST = isDaylightSavingTime;
17399    proto$2.isLocal = isLocal;
17400    proto$2.isUtcOffset = isUtcOffset;
17401    proto$2.isUtc = isUtc;
17402    proto$2.isUTC = isUtc;
17403    proto$2.zoneAbbr = getZoneAbbr;
17404    proto$2.zoneName = getZoneName;
17405    proto$2.dates = deprecate(
17406        'dates accessor is deprecated. Use date instead.',
17407        getSetDayOfMonth
17408    );
17409    proto$2.months = deprecate(
17410        'months accessor is deprecated. Use month instead',
17411        getSetMonth
17412    );
17413    proto$2.years = deprecate(
17414        'years accessor is deprecated. Use year instead',
17415        getSetYear
17416    );
17417    proto$2.zone = deprecate(
17418        'moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/',
17419        getSetZone
17420    );
17421    proto$2.isDSTShifted = deprecate(
17422        'isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information',
17423        isDaylightSavingTimeShifted
17424    );
17425
17426    function createUnix(input) {
17427        return createLocal(input * 1000);
17428    }
17429
17430    function createInZone() {
17431        return createLocal.apply(null, arguments).parseZone();
17432    }
17433
17434    function preParsePostFormat(string) {
17435        return string;
17436    }
17437
17438    var proto$1 = Locale.prototype;
17439
17440    proto$1.calendar = calendar$1;
17441    proto$1.longDateFormat = longDateFormat;
17442    proto$1.invalidDate = invalidDate;
17443    proto$1.ordinal = ordinal;
17444    proto$1.preparse = preParsePostFormat;
17445    proto$1.postformat = preParsePostFormat;
17446    proto$1.relativeTime = relativeTime$1;
17447    proto$1.pastFuture = pastFuture;
17448    proto$1.set = set;
17449    proto$1.eras = localeEras;
17450    proto$1.erasParse = localeErasParse;
17451    proto$1.erasConvertYear = localeErasConvertYear;
17452    proto$1.erasAbbrRegex = erasAbbrRegex;
17453    proto$1.erasNameRegex = erasNameRegex;
17454    proto$1.erasNarrowRegex = erasNarrowRegex;
17455
17456    proto$1.months = localeMonths;
17457    proto$1.monthsShort = localeMonthsShort;
17458    proto$1.monthsParse = localeMonthsParse;
17459    proto$1.monthsRegex = monthsRegex;
17460    proto$1.monthsShortRegex = monthsShortRegex;
17461    proto$1.week = localeWeek;
17462    proto$1.firstDayOfYear = localeFirstDayOfYear;
17463    proto$1.firstDayOfWeek = localeFirstDayOfWeek;
17464
17465    proto$1.weekdays = localeWeekdays;
17466    proto$1.weekdaysMin = localeWeekdaysMin;
17467    proto$1.weekdaysShort = localeWeekdaysShort;
17468    proto$1.weekdaysParse = localeWeekdaysParse;
17469
17470    proto$1.weekdaysRegex = weekdaysRegex;
17471    proto$1.weekdaysShortRegex = weekdaysShortRegex;
17472    proto$1.weekdaysMinRegex = weekdaysMinRegex;
17473
17474    proto$1.isPM = localeIsPM;
17475    proto$1.meridiem = localeMeridiem;
17476
17477    function get$1(format, index, field, setter) {
17478        var locale = getLocale(),
17479            utc = createUTC().set(setter, index);
17480        return locale[field](utc, format);
17481    }
17482
17483    function listMonthsImpl(format, index, field) {
17484        if (isNumber(format)) {
17485            index = format;
17486            format = undefined;
17487        }
17488
17489        format = format || '';
17490
17491        if (index != null) {
17492            return get$1(format, index, field, 'month');
17493        }
17494
17495        var i,
17496            out = [];
17497        for (i = 0; i < 12; i++) {
17498            out[i] = get$1(format, i, field, 'month');
17499        }
17500        return out;
17501    }
17502
17503    // ()
17504    // (5)
17505    // (fmt, 5)
17506    // (fmt)
17507    // (true)
17508    // (true, 5)
17509    // (true, fmt, 5)
17510    // (true, fmt)
17511    function listWeekdaysImpl(localeSorted, format, index, field) {
17512        if (typeof localeSorted === 'boolean') {
17513            if (isNumber(format)) {
17514                index = format;
17515                format = undefined;
17516            }
17517
17518            format = format || '';
17519        } else {
17520            format = localeSorted;
17521            index = format;
17522            localeSorted = false;
17523
17524            if (isNumber(format)) {
17525                index = format;
17526                format = undefined;
17527            }
17528
17529            format = format || '';
17530        }
17531
17532        var locale = getLocale(),
17533            shift = localeSorted ? locale._week.dow : 0,
17534            i,
17535            out = [];
17536
17537        if (index != null) {
17538            return get$1(format, (index + shift) % 7, field, 'day');
17539        }
17540
17541        for (i = 0; i < 7; i++) {
17542            out[i] = get$1(format, (i + shift) % 7, field, 'day');
17543        }
17544        return out;
17545    }
17546
17547    function listMonths(format, index) {
17548        return listMonthsImpl(format, index, 'months');
17549    }
17550
17551    function listMonthsShort(format, index) {
17552        return listMonthsImpl(format, index, 'monthsShort');
17553    }
17554
17555    function listWeekdays(localeSorted, format, index) {
17556        return listWeekdaysImpl(localeSorted, format, index, 'weekdays');
17557    }
17558
17559    function listWeekdaysShort(localeSorted, format, index) {
17560        return listWeekdaysImpl(localeSorted, format, index, 'weekdaysShort');
17561    }
17562
17563    function listWeekdaysMin(localeSorted, format, index) {
17564        return listWeekdaysImpl(localeSorted, format, index, 'weekdaysMin');
17565    }
17566
17567    getSetGlobalLocale('en', {
17568        eras: [
17569            {
17570                since: '0001-01-01',
17571                until: +Infinity,
17572                offset: 1,
17573                name: 'Anno Domini',
17574                narrow: 'AD',
17575                abbr: 'AD',
17576            },
17577            {
17578                since: '0000-12-31',
17579                until: -Infinity,
17580                offset: 1,
17581                name: 'Before Christ',
17582                narrow: 'BC',
17583                abbr: 'BC',
17584            },
17585        ],
17586        dayOfMonthOrdinalParse: /\d{1,2}(th|st|nd|rd)/,
17587        ordinal: function (number) {
17588            var b = number % 10,
17589                output =
17590                    toInt((number % 100) / 10) === 1
17591                        ? 'th'
17592                        : b === 1
17593                          ? 'st'
17594                          : b === 2
17595                            ? 'nd'
17596                            : b === 3
17597                              ? 'rd'
17598                              : 'th';
17599            return number + output;
17600        },
17601    });
17602
17603    // Side effect imports
17604
17605    hooks.lang = deprecate(
17606        'moment.lang is deprecated. Use moment.locale instead.',
17607        getSetGlobalLocale
17608    );
17609    hooks.langData = deprecate(
17610        'moment.langData is deprecated. Use moment.localeData instead.',
17611        getLocale
17612    );
17613
17614    var mathAbs = Math.abs;
17615
17616    function abs$1() {
17617        var data = this._data;
17618
17619        this._milliseconds = mathAbs(this._milliseconds);
17620        this._days = mathAbs(this._days);
17621        this._months = mathAbs(this._months);
17622
17623        data.milliseconds = mathAbs(data.milliseconds);
17624        data.seconds = mathAbs(data.seconds);
17625        data.minutes = mathAbs(data.minutes);
17626        data.hours = mathAbs(data.hours);
17627        data.months = mathAbs(data.months);
17628        data.years = mathAbs(data.years);
17629
17630        return this;
17631    }
17632
17633    function addSubtract(duration, input, value, direction) {
17634        var other = createDuration(input, value);
17635
17636        duration._milliseconds += direction * other._milliseconds;
17637        duration._days += direction * other._days;
17638        duration._months += direction * other._months;
17639
17640        return duration._bubble();
17641    }
17642
17643    // supports only 2.0-style add(1, 's') or add(duration)
17644    function add(input, value) {
17645        return addSubtract(this, input, value, 1);
17646    }
17647
17648    // supports only 2.0-style subtract(1, 's') or subtract(duration)
17649    function subtract(input, value) {
17650        return addSubtract(this, input, value, -1);
17651    }
17652
17653    function absCeil(number) {
17654        if (number < 0) {
17655            return Math.floor(number);
17656        } else {
17657            return Math.ceil(number);
17658        }
17659    }
17660
17661    function bubble() {
17662        var milliseconds = this._milliseconds,
17663            days = this._days,
17664            months = this._months,
17665            data = this._data,
17666            seconds,
17667            minutes,
17668            hours,
17669            years,
17670            monthsFromDays;
17671
17672        // if we have a mix of positive and negative values, bubble down first
17673        // check: https://github.com/moment/moment/issues/2166
17674        if (!(
17675            (milliseconds >= 0 && days >= 0 && months >= 0) ||
17676            (milliseconds <= 0 && days <= 0 && months <= 0)
17677        )) {
17678            milliseconds += absCeil(monthsToDays(months) + days) * 864e5;
17679            days = 0;
17680            months = 0;
17681        }
17682
17683        // The following code bubbles up values, see the tests for
17684        // examples of what that means.
17685        data.milliseconds = milliseconds % 1000;
17686
17687        seconds = absFloor(milliseconds / 1000);
17688        data.seconds = seconds % 60;
17689
17690        minutes = absFloor(seconds / 60);
17691        data.minutes = minutes % 60;
17692
17693        hours = absFloor(minutes / 60);
17694        data.hours = hours % 24;
17695
17696        days += absFloor(hours / 24);
17697
17698        // convert days to months
17699        monthsFromDays = absFloor(daysToMonths(days));
17700        months += monthsFromDays;
17701        days -= absCeil(monthsToDays(monthsFromDays));
17702
17703        // 12 months -> 1 year
17704        years = absFloor(months / 12);
17705        months %= 12;
17706
17707        data.days = days;
17708        data.months = months;
17709        data.years = years;
17710
17711        return this;
17712    }
17713
17714    function daysToMonths(days) {
17715        // 400 years have 146097 days (taking into account leap year rules)
17716        // 400 years have 12 months === 4800
17717        return (days * 4800) / 146097;
17718    }
17719
17720    function monthsToDays(months) {
17721        // the reverse of daysToMonths
17722        return (months * 146097) / 4800;
17723    }
17724
17725    function as(units) {
17726        if (!this.isValid()) {
17727            return NaN;
17728        }
17729        var days,
17730            months,
17731            milliseconds = this._milliseconds;
17732
17733        units = normalizeUnits(units);
17734
17735        if (units === 'month' || units === 'quarter' || units === 'year') {
17736            days = this._days + milliseconds / 864e5;
17737            months = this._months + daysToMonths(days);
17738            switch (units) {
17739                case 'month':
17740                    return months;
17741                case 'quarter':
17742                    return months / 3;
17743                case 'year':
17744                    return months / 12;
17745            }
17746        } else {
17747            // handle milliseconds separately because of floating point math errors (issue #1867)
17748            days = this._days + Math.round(monthsToDays(this._months));
17749            switch (units) {
17750                case 'week':
17751                    return days / 7 + milliseconds / 6048e5;
17752                case 'day':
17753                    return days + milliseconds / 864e5;
17754                case 'hour':
17755                    return days * 24 + milliseconds / 36e5;
17756                case 'minute':
17757                    return days * 1440 + milliseconds / 6e4;
17758                case 'second':
17759                    return days * 86400 + milliseconds / 1000;
17760                // Math.floor prevents floating point math errors here
17761                case 'millisecond':
17762                    return Math.floor(days * 864e5) + milliseconds;
17763                default:
17764                    throw new Error('Unknown unit ' + units);
17765            }
17766        }
17767    }
17768
17769    function makeAs(alias) {
17770        return function () {
17771            return this.as(alias);
17772        };
17773    }
17774
17775    var asMilliseconds = makeAs('ms'),
17776        asSeconds = makeAs('s'),
17777        asMinutes = makeAs('m'),
17778        asHours = makeAs('h'),
17779        asDays = makeAs('d'),
17780        asWeeks = makeAs('w'),
17781        asMonths = makeAs('M'),
17782        asQuarters = makeAs('Q'),
17783        asYears = makeAs('y'),
17784        valueOf = asMilliseconds;
17785
17786    function clone() {
17787        return createDuration(this);
17788    }
17789
17790    function get(units) {
17791        units = normalizeUnits(units);
17792        return this.isValid() ? this[units + 's']() : NaN;
17793    }
17794
17795    function makeGetter(name) {
17796        return function () {
17797            return this.isValid() ? this._data[name] : NaN;
17798        };
17799    }
17800
17801    var milliseconds = makeGetter('milliseconds'),
17802        seconds = makeGetter('seconds'),
17803        minutes = makeGetter('minutes'),
17804        hours = makeGetter('hours'),
17805        days = makeGetter('days'),
17806        months = makeGetter('months'),
17807        years = makeGetter('years');
17808
17809    function weeks() {
17810        return absFloor(this.days() / 7);
17811    }
17812
17813    var round = Math.round,
17814        thresholds = {
17815            ss: 44, // a few seconds to seconds
17816            s: 45, // seconds to minute
17817            m: 45, // minutes to hour
17818            h: 22, // hours to day
17819            d: 26, // days to month/week
17820            w: null, // weeks to month
17821            M: 11, // months to year
17822        };
17823
17824    // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
17825    function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) {
17826        return relativeTimeWithoutPostformat.call(
17827            locale,
17828            number || 1,
17829            !!withoutSuffix,
17830            string,
17831            isFuture
17832        );
17833    }
17834
17835    function relativeTime(posNegDuration, withoutSuffix, thresholds, locale) {
17836        var duration = createDuration(posNegDuration).abs(),
17837            seconds = round(duration.as('s')),
17838            minutes = round(duration.as('m')),
17839            hours = round(duration.as('h')),
17840            days = round(duration.as('d')),
17841            months = round(duration.as('M')),
17842            weeks = round(duration.as('w')),
17843            years = round(duration.as('y')),
17844            a =
17845                (seconds <= thresholds.ss && ['s', seconds]) ||
17846                (seconds < thresholds.s && ['ss', seconds]) ||
17847                (minutes <= 1 && ['m']) ||
17848                (minutes < thresholds.m && ['mm', minutes]) ||
17849                (hours <= 1 && ['h']) ||
17850                (hours < thresholds.h && ['hh', hours]) ||
17851                (days <= 1 && ['d']) ||
17852                (days < thresholds.d && ['dd', days]);
17853
17854        if (thresholds.w != null) {
17855            a =
17856                a ||
17857                (weeks <= 1 && ['w']) ||
17858                (weeks < thresholds.w && ['ww', weeks]);
17859        }
17860        a = a ||
17861            (months <= 1 && ['M']) ||
17862            (months < thresholds.M && ['MM', months]) ||
17863            (years <= 1 && ['y']) || ['yy', years];
17864
17865        a[2] = withoutSuffix;
17866        a[3] = +posNegDuration > 0;
17867        a[4] = locale;
17868        return substituteTimeAgo.apply(null, a);
17869    }
17870
17871    // This function allows you to set the rounding function for relative time strings
17872    function getSetRelativeTimeRounding(roundingFunction) {
17873        if (roundingFunction === undefined) {
17874            return round;
17875        }
17876        if (typeof roundingFunction === 'function') {
17877            round = roundingFunction;
17878            return true;
17879        }
17880        return false;
17881    }
17882
17883    // This function allows you to set a threshold for relative time strings
17884    function getSetRelativeTimeThreshold(threshold, limit) {
17885        if (thresholds[threshold] === undefined) {
17886            return false;
17887        }
17888        if (limit === undefined) {
17889            return thresholds[threshold];
17890        }
17891        thresholds[threshold] = limit;
17892        if (threshold === 's') {
17893            thresholds.ss = limit - 1;
17894        }
17895        return true;
17896    }
17897
17898    function humanize(argWithSuffix, argThresholds) {
17899        if (!this.isValid()) {
17900            return this.localeData().invalidDate();
17901        }
17902
17903        var withSuffix = false,
17904            th = thresholds,
17905            locale,
17906            output;
17907
17908        if (typeof argWithSuffix === 'object') {
17909            argThresholds = argWithSuffix;
17910            argWithSuffix = false;
17911        }
17912        if (typeof argWithSuffix === 'boolean') {
17913            withSuffix = argWithSuffix;
17914        }
17915        if (typeof argThresholds === 'object') {
17916            th = extend(extend({}, thresholds), argThresholds || {});
17917            if (argThresholds.s != null && argThresholds.ss == null) {
17918                th.ss = argThresholds.s - 1;
17919            }
17920        }
17921
17922        locale = this.localeData();
17923        output = relativeTime(this, !withSuffix, th, locale);
17924
17925        if (withSuffix) {
17926            output = pastFutureWithoutPostformat.call(locale, +this, output);
17927        }
17928
17929        return locale.postformat(output);
17930    }
17931
17932    var abs = Math.abs;
17933
17934    function sign(x) {
17935        return (x > 0) - (x < 0) || +x;
17936    }
17937
17938    function toISOString() {
17939        // for ISO strings we do not use the normal bubbling rules:
17940        //  * milliseconds bubble up until they become hours
17941        //  * days do not bubble at all
17942        //  * months bubble up until they become years
17943        // This is because there is no context-free conversion between hours and days
17944        // (think of clock changes)
17945        // and also not between days and months (28-31 days per month)
17946        if (!this.isValid()) {
17947            return this.localeData().invalidDate();
17948        }
17949
17950        var seconds = abs(this._milliseconds) / 1000,
17951            days = abs(this._days),
17952            months = abs(this._months),
17953            minutes,
17954            hours,
17955            years,
17956            s,
17957            total = this.asSeconds(),
17958            totalSign,
17959            ymSign,
17960            daysSign,
17961            hmsSign;
17962
17963        if (!total) {
17964            // this is the same as C#'s (Noda) and python (isodate)...
17965            // but not other JS (goog.date)
17966            return 'P0D';
17967        }
17968
17969        // 3600 seconds -> 60 minutes -> 1 hour
17970        minutes = absFloor(seconds / 60);
17971        hours = absFloor(minutes / 60);
17972        seconds %= 60;
17973        minutes %= 60;
17974
17975        // 12 months -> 1 year
17976        years = absFloor(months / 12);
17977        months %= 12;
17978
17979        // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
17980        s = seconds ? seconds.toFixed(3).replace(/\.?0+$/, '') : '';
17981
17982        totalSign = total < 0 ? '-' : '';
17983        ymSign = sign(this._months) !== sign(total) ? '-' : '';
17984        daysSign = sign(this._days) !== sign(total) ? '-' : '';
17985        hmsSign = sign(this._milliseconds) !== sign(total) ? '-' : '';
17986
17987        return (
17988            totalSign +
17989            'P' +
17990            (years ? ymSign + years + 'Y' : '') +
17991            (months ? ymSign + months + 'M' : '') +
17992            (days ? daysSign + days + 'D' : '') +
17993            (hours || minutes || seconds ? 'T' : '') +
17994            (hours ? hmsSign + hours + 'H' : '') +
17995            (minutes ? hmsSign + minutes + 'M' : '') +
17996            (seconds ? hmsSign + s + 'S' : '')
17997        );
17998    }
17999
18000    var proto = Duration.prototype;
18001
18002    proto.isValid = isValid$1;
18003    proto.abs = abs$1;
18004    proto.add = add;
18005    proto.subtract = subtract;
18006    proto.as = as;
18007    proto.asMilliseconds = asMilliseconds;
18008    proto.asSeconds = asSeconds;
18009    proto.asMinutes = asMinutes;
18010    proto.asHours = asHours;
18011    proto.asDays = asDays;
18012    proto.asWeeks = asWeeks;
18013    proto.asMonths = asMonths;
18014    proto.asQuarters = asQuarters;
18015    proto.asYears = asYears;
18016    proto.valueOf = valueOf;
18017    proto._bubble = bubble;
18018    proto.clone = clone;
18019    proto.get = get;
18020    proto.milliseconds = milliseconds;
18021    proto.seconds = seconds;
18022    proto.minutes = minutes;
18023    proto.hours = hours;
18024    proto.days = days;
18025    proto.weeks = weeks;
18026    proto.months = months;
18027    proto.years = years;
18028    proto.humanize = humanize;
18029    proto.toISOString = toISOString;
18030    proto.toString = toISOString;
18031    proto.toJSON = toISOString;
18032    proto.locale = locale;
18033    proto.localeData = localeData;
18034
18035    proto.toIsoString = deprecate(
18036        'toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)',
18037        toISOString
18038    );
18039    proto.lang = lang;
18040
18041    // FORMATTING
18042
18043    addFormatToken('X', 0, 0, 'unix');
18044    addFormatToken('x', 0, 0, 'valueOf');
18045
18046    // PARSING
18047
18048    addRegexToken('x', matchSigned);
18049    addRegexToken('X', matchTimestamp);
18050    addParseToken('X', function (input, array, config) {
18051        config._d = new Date(parseFloat(input) * 1000);
18052    });
18053    addParseToken('x', function (input, array, config) {
18054        config._d = new Date(toInt(input));
18055    });
18056
18057    //! moment.js
18058
18059    hooks.version = '2.31.0';
18060
18061    setHookCallback(createLocal);
18062
18063    hooks.fn = proto$2;
18064    hooks.min = min;
18065    hooks.max = max;
18066    hooks.now = now;
18067    hooks.utc = createUTC;
18068    hooks.unix = createUnix;
18069    hooks.months = listMonths;
18070    hooks.isDate = isDate;
18071    hooks.locale = getSetGlobalLocale;
18072    hooks.invalid = createInvalid$1;
18073    hooks.duration = createDuration;
18074    hooks.isMoment = isMoment;
18075    hooks.weekdays = listWeekdays;
18076    hooks.parseZone = createInZone;
18077    hooks.localeData = getLocale;
18078    hooks.isDuration = isDuration;
18079    hooks.monthsShort = listMonthsShort;
18080    hooks.weekdaysMin = listWeekdaysMin;
18081    hooks.defineLocale = defineLocale;
18082    hooks.updateLocale = updateLocale;
18083    hooks.locales = listLocales;
18084    hooks.weekdaysShort = listWeekdaysShort;
18085    hooks.normalizeUnits = normalizeUnits;
18086    hooks.relativeTimeRounding = getSetRelativeTimeRounding;
18087    hooks.relativeTimeThreshold = getSetRelativeTimeThreshold;
18088    hooks.calendarFormat = getCalendarFormat;
18089    hooks.prototype = proto$2;
18090
18091    // currently HTML5 input type only supports 24-hour formats
18092    hooks.HTML5_FMT = {
18093        DATETIME_LOCAL: 'YYYY-MM-DDTHH:mm', // <input type="datetime-local" />
18094        DATETIME_LOCAL_SECONDS: 'YYYY-MM-DDTHH:mm:ss', // <input type="datetime-local" step="1" />
18095        DATETIME_LOCAL_MS: 'YYYY-MM-DDTHH:mm:ss.SSS', // <input type="datetime-local" step="0.001" />
18096        DATE: 'YYYY-MM-DD', // <input type="date" />
18097        TIME: 'HH:mm', // <input type="time" />
18098        TIME_SECONDS: 'HH:mm:ss', // <input type="time" step="1" />
18099        TIME_MS: 'HH:mm:ss.SSS', // <input type="time" step="0.001" />
18100        WEEK: 'GGGG-[W]WW', // <input type="week" />
18101        MONTH: 'YYYY-MM', // <input type="month" />
18102    };
18103
18104    return hooks;
18105
18106})));
18107
18108/*
18109//! version : 3.0.3
18110=========================================================
18111bootstrap-datetimepicker.js
18112https://github.com/Eonasdan/bootstrap-datetimepicker
18113=========================================================
18114The MIT License (MIT)
18115
18116Copyright (c) 2014 Jonathan Peterson
18117
18118Permission is hereby granted, free of charge, to any person obtaining a copy
18119of this software and associated documentation files (the "Software"), to deal
18120in the Software without restriction, including without limitation the rights
18121to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18122copies of the Software, and to permit persons to whom the Software is
18123furnished to do so, subject to the following conditions:
18124
18125The above copyright notice and this permission notice shall be included in
18126all copies or substantial portions of the Software.
18127
18128THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18129IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18130FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18131AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18132LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18133OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
18134THE SOFTWARE.
18135*/
18136;(function (root, factory) {
18137    'use strict';
18138    if (typeof define === 'function' && define.amd) {
18139        // AMD is used - Register as an anonymous module.
18140        define('bootstrapDateTimePicker',['jquery', 'moment'], factory);
18141    } else {
18142        // AMD is not used - Attempt to fetch dependencies from scope.
18143        if (!jQuery) {
18144            throw new Error('bootstrap-datetimepicker requires jQuery to be loaded first');
18145        }
18146        if (!moment) {
18147            throw new Error('bootstrap-datetimepicker requires moment.js to be loaded first');
18148        }
18149        factory(root.jQuery, moment);
18150    }
18151}(this, function ($, moment) {
18152    'use strict';
18153    if (typeof moment === 'undefined') {
18154        throw new Error('momentjs is required');
18155    }
18156
18157    var dpgId = 0,
18158
18159    DateTimePicker = function (element, options) {
18160        var defaults = $.fn.datetimepicker.defaults,
18161
18162            icons = {
18163                time: 'glyphicon glyphicon-time',
18164                date: 'glyphicon glyphicon-calendar',
18165                up: 'glyphicon glyphicon-chevron-up',
18166                down: 'glyphicon glyphicon-chevron-down'
18167            },
18168
18169            picker = this,
18170
18171            dDate,
18172
18173        init = function () {
18174            var icon = false, localeData, rInterval;
18175            picker.options = $.extend({}, defaults, options);
18176            picker.options.icons = $.extend({}, icons, picker.options.icons);
18177
18178            picker.element = $(element);
18179
18180            dataToOptions();
18181
18182            if (!(picker.options.pickTime || picker.options.pickDate)) {
18183                throw new Error('Must choose at least one picker');
18184            }
18185
18186            picker.id = dpgId++;
18187            moment.locale(picker.options.language);
18188            picker.date = moment();
18189            picker.unset = false;
18190            picker.isInput = picker.element.is('input');
18191            picker.component = false;
18192
18193            if (picker.element.hasClass('input-group')) {
18194                if (picker.element.find('.datepickerbutton').size() === 0) {//in case there is more then one 'input-group-addon' Issue #48
18195                    picker.component = picker.element.find('[class^="input-group-"]');
18196                }
18197                else {
18198                    picker.component = picker.element.find('.datepickerbutton');
18199                }
18200            }
18201            picker.format = picker.options.format;
18202
18203            localeData = moment().localeData();
18204
18205            if (!picker.format) {
18206                picker.format = (picker.options.pickDate ? localeData.longDateFormat('L') : '');
18207                if (picker.options.pickDate && picker.options.pickTime) {
18208                    picker.format += ' ';
18209                }
18210                picker.format += (picker.options.pickTime ? localeData.longDateFormat('LT') : '');
18211                if (picker.options.useSeconds) {
18212                    if (localeData.longDateFormat('LT').indexOf(' A') !== -1) {
18213                        picker.format = picker.format.split(' A')[0] + ':ss A';
18214                    }
18215                    else {
18216                        picker.format += ':ss';
18217                    }
18218                }
18219            }
18220            picker.use24hours = picker.format.toLowerCase().indexOf('a') < 1;
18221
18222            if (picker.component) {
18223                icon = picker.component.find('span');
18224            }
18225
18226            if (picker.options.pickTime) {
18227                if (icon) {
18228                    icon.addClass(picker.options.icons.time);
18229                }
18230            }
18231            if (picker.options.pickDate) {
18232                if (icon) {
18233                    icon.removeClass(picker.options.icons.time);
18234                    icon.addClass(picker.options.icons.date);
18235                }
18236            }
18237
18238            picker.options.widgetParent =
18239                typeof picker.options.widgetParent === 'string' && picker.options.widgetParent ||
18240                picker.element.parents().filter(function () {
18241                    return 'scroll' === $(this).css('overflow-y');
18242                }).get(0) ||
18243                'body';
18244
18245            picker.widget = $(getTemplate()).appendTo(picker.options.widgetParent);
18246
18247            picker.minViewMode = picker.options.minViewMode || 0;
18248            if (typeof picker.minViewMode === 'string') {
18249                switch (picker.minViewMode) {
18250                    case 'months':
18251                        picker.minViewMode = 1;
18252                        break;
18253                    case 'years':
18254                        picker.minViewMode = 2;
18255                        break;
18256                    default:
18257                        picker.minViewMode = 0;
18258                        break;
18259                }
18260            }
18261            picker.viewMode = picker.options.viewMode || 0;
18262            if (typeof picker.viewMode === 'string') {
18263                switch (picker.viewMode) {
18264                    case 'months':
18265                        picker.viewMode = 1;
18266                        break;
18267                    case 'years':
18268                        picker.viewMode = 2;
18269                        break;
18270                    default:
18271                        picker.viewMode = 0;
18272                        break;
18273                }
18274            }
18275
18276            picker.viewMode = Math.max(picker.viewMode, picker.minViewMode);
18277
18278            picker.options.disabledDates = indexGivenDates(picker.options.disabledDates);
18279            picker.options.enabledDates = indexGivenDates(picker.options.enabledDates);
18280
18281            picker.startViewMode = picker.viewMode;
18282            picker.setMinDate(picker.options.minDate);
18283            picker.setMaxDate(picker.options.maxDate);
18284            fillDow();
18285            fillMonths();
18286            fillHours();
18287            fillMinutes();
18288            fillSeconds();
18289            update();
18290            showMode();
18291            attachDatePickerEvents();
18292            if (picker.options.defaultDate !== '' && getPickerInput().val() === '') {
18293                picker.setValue(picker.options.defaultDate);
18294            }
18295            if (picker.options.minuteStepping !== 1) {
18296                rInterval = picker.options.minuteStepping;
18297                picker.date.minutes((Math.round(picker.date.minutes() / rInterval) * rInterval) % 60).seconds(0);
18298            }
18299        },
18300
18301        getPickerInput = function () {
18302            var input;
18303
18304            if (picker.isInput) {
18305                return picker.element;
18306            }
18307            input = picker.element.find('.datepickerinput');
18308            if (input.size() === 0) {
18309                input = picker.element.find('input');
18310            }
18311            else if (!input.is('input')) {
18312                throw new Error('CSS class "datepickerinput" cannot be applied to non input element');
18313            }
18314            return input;
18315        },
18316
18317        dataToOptions = function () {
18318            var eData;
18319            if (picker.element.is('input')) {
18320                eData = picker.element.data();
18321            }
18322            else {
18323                eData = picker.element.find('input').data();
18324            }
18325            if (eData.dateFormat !== undefined) {
18326                picker.options.format = eData.dateFormat;
18327            }
18328            if (eData.datePickdate !== undefined) {
18329                picker.options.pickDate = eData.datePickdate;
18330            }
18331            if (eData.datePicktime !== undefined) {
18332                picker.options.pickTime = eData.datePicktime;
18333            }
18334            if (eData.dateUseminutes !== undefined) {
18335                picker.options.useMinutes = eData.dateUseminutes;
18336            }
18337            if (eData.dateUseseconds !== undefined) {
18338                picker.options.useSeconds = eData.dateUseseconds;
18339            }
18340            if (eData.dateUsecurrent !== undefined) {
18341                picker.options.useCurrent = eData.dateUsecurrent;
18342            }
18343            if (eData.dateMinutestepping !== undefined) {
18344                picker.options.minuteStepping = eData.dateMinutestepping;
18345            }
18346            if (eData.dateMindate !== undefined) {
18347                picker.options.minDate = eData.dateMindate;
18348            }
18349            if (eData.dateMaxdate !== undefined) {
18350                picker.options.maxDate = eData.dateMaxdate;
18351            }
18352            if (eData.dateShowtoday !== undefined) {
18353                picker.options.showToday = eData.dateShowtoday;
18354            }
18355            if (eData.dateCollapse !== undefined) {
18356                picker.options.collapse = eData.dateCollapse;
18357            }
18358            if (eData.dateLanguage !== undefined) {
18359                picker.options.language = eData.dateLanguage;
18360            }
18361            if (eData.dateDefaultdate !== undefined) {
18362                picker.options.defaultDate = eData.dateDefaultdate;
18363            }
18364            if (eData.dateDisableddates !== undefined) {
18365                picker.options.disabledDates = eData.dateDisableddates;
18366            }
18367            if (eData.dateEnableddates !== undefined) {
18368                picker.options.enabledDates = eData.dateEnableddates;
18369            }
18370            if (eData.dateIcons !== undefined) {
18371                picker.options.icons = eData.dateIcons;
18372            }
18373            if (eData.dateUsestrict !== undefined) {
18374                picker.options.useStrict = eData.dateUsestrict;
18375            }
18376            if (eData.dateDirection !== undefined) {
18377                picker.options.direction = eData.dateDirection;
18378            }
18379            if (eData.dateSidebyside !== undefined) {
18380                picker.options.sideBySide = eData.dateSidebyside;
18381            }
18382            if (eData.dateDaysofweekdisabled !== undefined) {
18383                picker.options.daysOfWeekDisabled = eData.dateDaysofweekdisabled;
18384            }
18385//            $.each(defaults, function (key) {
18386//                var attributeName = 'date' + key.charAt(0).toUpperCase() + key.slice(1);
18387//                if (eData[attributeName] !== undefined) {
18388//                    picker.options[key] = eData[attributeName];
18389//                }
18390//            });
18391        },
18392
18393        place = function () {
18394            var position = 'absolute',
18395                offset = picker.component ? picker.component.offset() : picker.element.offset(),
18396                $window = $(window),
18397                placePosition;
18398
18399            picker.width = picker.component ? picker.component.outerWidth() : picker.element.outerWidth();
18400            offset.top = offset.top + picker.element.outerHeight();
18401
18402            if (picker.options.direction === 'up') {
18403                placePosition = 'top';
18404            } else if (picker.options.direction === 'bottom') {
18405                placePosition = 'bottom';
18406            } else if (picker.options.direction === 'auto') {
18407                if (offset.top + picker.widget.height() > $window.height() + $window.scrollTop() && picker.widget.height() + picker.element.outerHeight() < offset.top) {
18408                    placePosition = 'top';
18409                } else {
18410                    placePosition = 'bottom';
18411                }
18412            }
18413            if (placePosition === 'top') {
18414                offset.top -= picker.widget.height() + picker.element.outerHeight() + 15;
18415                picker.widget.addClass('top').removeClass('bottom');
18416            } else {
18417                offset.top += 1;
18418                picker.widget.addClass('bottom').removeClass('top');
18419            }
18420
18421            if (picker.options.width !== undefined) {
18422                picker.widget.width(picker.options.width);
18423            }
18424
18425            if (picker.options.orientation === 'left') {
18426                picker.widget.addClass('left-oriented');
18427                offset.left = offset.left - picker.widget.width() + 20;
18428            }
18429
18430            if (isInFixed()) {
18431                position = 'fixed';
18432                offset.top -= $window.scrollTop();
18433                offset.left -= $window.scrollLeft();
18434            }
18435
18436            if ($window.width() < offset.left + picker.widget.outerWidth()) {
18437                offset.right = $window.width() - offset.left - picker.width;
18438                offset.left = 'auto';
18439                picker.widget.addClass('pull-right');
18440            } else {
18441                offset.right = 'auto';
18442                picker.widget.removeClass('pull-right');
18443            }
18444
18445            picker.widget.css({
18446                position: position,
18447                top: offset.top,
18448                left: offset.left,
18449                right: offset.right
18450            });
18451        },
18452
18453        notifyChange = function (oldDate, eventType) {
18454            if (moment(picker.date).isSame(moment(oldDate))) {
18455                return;
18456            }
18457            picker.element.trigger({
18458                type: 'dp.change',
18459                date: moment(picker.date),
18460                oldDate: moment(oldDate)
18461            });
18462
18463            if (eventType !== 'change') {
18464                picker.element.change();
18465            }
18466        },
18467
18468        notifyError = function (date) {
18469            picker.element.trigger({
18470                type: 'dp.error',
18471                date: moment(date, picker.format, picker.options.useStrict)
18472            });
18473        },
18474
18475        update = function (newDate) {
18476            moment.locale(picker.options.language);
18477            var dateStr = newDate;
18478            if (!dateStr) {
18479                dateStr = getPickerInput().val();
18480                if (dateStr) {
18481                    picker.date = moment(dateStr, picker.format, picker.options.useStrict);
18482                }
18483                if (!picker.date) {
18484                    picker.date = moment();
18485                }
18486            }
18487            picker.viewDate = moment(picker.date).startOf('month');
18488            fillDate();
18489            fillTime();
18490        },
18491
18492        fillDow = function () {
18493            moment.locale(picker.options.language);
18494            var html = $('<tr>'), weekdaysMin = moment.weekdaysMin(), i;
18495            if (moment().localeData()._week.dow === 0) { // starts on Sunday
18496                for (i = 0; i < 7; i++) {
18497                    html.append('<th class="dow">' + weekdaysMin[i] + '</th>');
18498                }
18499            } else {
18500                for (i = 1; i < 8; i++) {
18501                    if (i === 7) {
18502                        html.append('<th class="dow">' + weekdaysMin[0] + '</th>');
18503                    } else {
18504                        html.append('<th class="dow">' + weekdaysMin[i] + '</th>');
18505                    }
18506                }
18507            }
18508            picker.widget.find('.datepicker-days thead').append(html);
18509        },
18510
18511        fillMonths = function () {
18512            moment.locale(picker.options.language);
18513            var html = '', i, monthsShort = moment.monthsShort();
18514            for (i = 0; i < 12; i++) {
18515                html += '<span class="month">' + monthsShort[i] + '</span>';
18516            }
18517            picker.widget.find('.datepicker-months td').append(html);
18518        },
18519
18520        fillDate = function () {
18521            if (!picker.options.pickDate) {
18522                return;
18523            }
18524            moment.locale(picker.options.language);
18525            var year = picker.viewDate.year(),
18526                month = picker.viewDate.month(),
18527                startYear = picker.options.minDate.year(),
18528                startMonth = picker.options.minDate.month(),
18529                endYear = picker.options.maxDate.year(),
18530                endMonth = picker.options.maxDate.month(),
18531                currentDate,
18532                prevMonth, nextMonth, html = [], row, clsName, i, days, yearCont, currentYear, months = moment.months();
18533
18534            picker.widget.find('.datepicker-days').find('.disabled').removeClass('disabled');
18535            picker.widget.find('.datepicker-months').find('.disabled').removeClass('disabled');
18536            picker.widget.find('.datepicker-years').find('.disabled').removeClass('disabled');
18537
18538            picker.widget.find('.datepicker-days th:eq(1)').text(
18539                months[month] + ' ' + year);
18540
18541            prevMonth = moment(picker.viewDate, picker.format, picker.options.useStrict).subtract(1, 'months');
18542            days = prevMonth.daysInMonth();
18543            prevMonth.date(days).startOf('week');
18544            if ((year === startYear && month <= startMonth) || year < startYear) {
18545                picker.widget.find('.datepicker-days th:eq(0)').addClass('disabled');
18546            }
18547            if ((year === endYear && month >= endMonth) || year > endYear) {
18548                picker.widget.find('.datepicker-days th:eq(2)').addClass('disabled');
18549            }
18550
18551            nextMonth = moment(prevMonth).add(42, 'd');
18552            while (prevMonth.isBefore(nextMonth)) {
18553                if (prevMonth.weekday() === moment().startOf('week').weekday()) {
18554                    row = $('<tr>');
18555                    html.push(row);
18556                }
18557                clsName = '';
18558                if (prevMonth.year() < year || (prevMonth.year() === year && prevMonth.month() < month)) {
18559                    clsName += ' old';
18560                } else if (prevMonth.year() > year || (prevMonth.year() === year && prevMonth.month() > month)) {
18561                    clsName += ' new';
18562                }
18563                if (prevMonth.isSame(moment({y: picker.date.year(), M: picker.date.month(), d: picker.date.date()}))) {
18564                    clsName += ' active';
18565                }
18566                if (isInDisableDates(prevMonth, 'day') || !isInEnableDates(prevMonth)) {
18567                    clsName += ' disabled';
18568                }
18569                if (picker.options.showToday === true) {
18570                    if (prevMonth.isSame(moment(), 'day')) {
18571                        clsName += ' today';
18572                    }
18573                }
18574                if (picker.options.daysOfWeekDisabled) {
18575                    for (i = 0; i < picker.options.daysOfWeekDisabled.length; i++) {
18576                        if (prevMonth.day() === picker.options.daysOfWeekDisabled[i]) {
18577                            clsName += ' disabled';
18578                            break;
18579                        }
18580                    }
18581                }
18582                row.append('<td class="day' + clsName + '">' + prevMonth.date() + '</td>');
18583
18584                currentDate = prevMonth.date();
18585                prevMonth.add(1, 'd');
18586
18587                if (currentDate === prevMonth.date()) {
18588                    prevMonth.add(1, 'd');
18589                }
18590            }
18591            picker.widget.find('.datepicker-days tbody').empty().append(html);
18592            currentYear = picker.date.year();
18593            months = picker.widget.find('.datepicker-months').find('th:eq(1)').text(year).end().find('span').removeClass('active');
18594            if (currentYear === year) {
18595                months.eq(picker.date.month()).addClass('active');
18596            }
18597            if (year - 1 < startYear) {
18598                picker.widget.find('.datepicker-months th:eq(0)').addClass('disabled');
18599            }
18600            if (year + 1 > endYear) {
18601                picker.widget.find('.datepicker-months th:eq(2)').addClass('disabled');
18602            }
18603            for (i = 0; i < 12; i++) {
18604                if ((year === startYear && startMonth > i) || (year < startYear)) {
18605                    $(months[i]).addClass('disabled');
18606                } else if ((year === endYear && endMonth < i) || (year > endYear)) {
18607                    $(months[i]).addClass('disabled');
18608                }
18609            }
18610
18611            html = '';
18612            year = parseInt(year / 10, 10) * 10;
18613            yearCont = picker.widget.find('.datepicker-years').find(
18614                'th:eq(1)').text(year + '-' + (year + 9)).parents('table').find('td');
18615            picker.widget.find('.datepicker-years').find('th').removeClass('disabled');
18616            if (startYear > year) {
18617                picker.widget.find('.datepicker-years').find('th:eq(0)').addClass('disabled');
18618            }
18619            if (endYear < year + 9) {
18620                picker.widget.find('.datepicker-years').find('th:eq(2)').addClass('disabled');
18621            }
18622            year -= 1;
18623            for (i = -1; i < 11; i++) {
18624                html += '<span class="year' + (i === -1 || i === 10 ? ' old' : '') + (currentYear === year ? ' active' : '') + ((year < startYear || year > endYear) ? ' disabled' : '') + '">' + year + '</span>';
18625                year += 1;
18626            }
18627            yearCont.html(html);
18628        },
18629
18630        fillHours = function () {
18631            moment.locale(picker.options.language);
18632            var table = picker.widget.find('.timepicker .timepicker-hours table'), html = '', current, i, j;
18633            table.parent().hide();
18634            if (picker.use24hours) {
18635                current = 0;
18636                for (i = 0; i < 6; i += 1) {
18637                    html += '<tr>';
18638                    for (j = 0; j < 4; j += 1) {
18639                        html += '<td class="hour">' + padLeft(current.toString()) + '</td>';
18640                        current++;
18641                    }
18642                    html += '</tr>';
18643                }
18644            }
18645            else {
18646                current = 1;
18647                for (i = 0; i < 3; i += 1) {
18648                    html += '<tr>';
18649                    for (j = 0; j < 4; j += 1) {
18650                        html += '<td class="hour">' + padLeft(current.toString()) + '</td>';
18651                        current++;
18652                    }
18653                    html += '</tr>';
18654                }
18655            }
18656            table.html(html);
18657        },
18658
18659        fillMinutes = function () {
18660            var table = picker.widget.find('.timepicker .timepicker-minutes table'), html = '', current = 0, i, j, step = picker.options.minuteStepping;
18661            table.parent().hide();
18662            if (step === 1)  {
18663                step = 5;
18664            }
18665            for (i = 0;
18665 i < Math.ceil(60 / step / 4) ; i++) {
18666                html += '<tr>';
18667                for (j = 0; j < 4; j += 1) {
18668                    if (current < 60) {
18669                        html += '<td class="minute">' + padLeft(current.toString()) + '</td>';
18670                        current += step;
18671                    } else {
18672                        html += '<td></td>';
18673                    }
18674                }
18675                html += '</tr>';
18676            }
18677            table.html(html);
18678        },
18679
18680        fillSeconds = function () {
18681            var table = picker.widget.find('.timepicker .timepicker-seconds table'), html = '', current = 0, i, j;
18682            table.parent().hide();
18683            for (i = 0; i < 3; i++) {
18684                html += '<tr>';
18685                for (j = 0; j < 4; j += 1) {
18686                    html += '<td class="second">' + padLeft(current.toString()) + '</td>';
18687                    current += 5;
18688                }
18689                html += '</tr>';
18690            }
18691            table.html(html);
18692        },
18693
18694        fillTime = function () {
18695            if (!picker.date) {
18696                return;
18697            }
18698            var timeComponents = picker.widget.find('.timepicker span[data-time-component]'),
18699                hour = picker.date.hours(),
18700                period = picker.date.format('A');
18701            if (!picker.use24hours) {
18702                if (hour === 0) {
18703                    hour = 12;
18704                } else if (hour !== 12) {
18705                    hour = hour % 12;
18706                }
18707                picker.widget.find('.timepicker [data-action=togglePeriod]').text(period);
18708            }
18709            timeComponents.filter('[data-time-component=hours]').text(padLeft(hour));
18710            timeComponents.filter('[data-time-component=minutes]').text(padLeft(picker.date.minutes()));
18711            timeComponents.filter('[data-time-component=seconds]').text(padLeft(picker.date.second()));
18712        },
18713
18714        click = function (e) {
18715            e.stopPropagation();
18716            e.preventDefault();
18717            picker.unset = false;
18718            var target = $(e.target).closest('span, td, th'), month, year, step, day, oldDate = moment(picker.date);
18719            if (target.length === 1) {
18720                if (!target.is('.disabled')) {
18721                    switch (target[0].nodeName.toLowerCase()) {
18722                        case 'th':
18723                            switch (target[0].className) {
18724                                case 'picker-switch':
18725                                    showMode(1);
18726                                    break;
18727                                case 'prev':
18728                                case 'next':
18729                                    step = dpGlobal.modes[picker.viewMode].navStep;
18730                                    if (target[0].className === 'prev') {
18731                                        step = step * -1;
18732                                    }
18733                                    picker.viewDate.add(step, dpGlobal.modes[picker.viewMode].navFnc);
18734                                    fillDate();
18735                                    break;
18736                            }
18737                            break;
18738                        case 'span':
18739                            if (target.is('.month')) {
18740                                month = target.parent().find('span').index(target);
18741                                picker.viewDate.month(month);
18742                            } else {
18743                                year = parseInt(target.text(), 10) || 0;
18744                                picker.viewDate.year(year);
18745                            }
18746                            if (picker.viewMode === picker.minViewMode) {
18747                                picker.date = moment({
18748                                    y: picker.viewDate.year(),
18749                                    M: picker.viewDate.month(),
18750                                    d: picker.viewDate.date(),
18751                                    h: picker.date.hours(),
18752                                    m: picker.date.minutes(),
18753                                    s: picker.date.seconds()
18754                                });
18755                                set();
18756                                notifyChange(oldDate, e.type);
18757                            }
18758                            showMode(-1);
18759                            fillDate();
18760                            break;
18761                        case 'td':
18762                            if (target.is('.day')) {
18763                                day = parseInt(target.text(), 10) || 1;
18764                                month = picker.viewDate.month();
18765                                year = picker.viewDate.year();
18766                                if (target.is('.old')) {
18767                                    if (month === 0) {
18768                                        month = 11;
18769                                        year -= 1;
18770                                    } else {
18771                                        month -= 1;
18772                                    }
18773                                } else if (target.is('.new')) {
18774                                    if (month === 11) {
18775                                        month = 0;
18776                                        year += 1;
18777                                    } else {
18778                                        month += 1;
18779                                    }
18780                                }
18781                                picker.date = moment({
18782                                    y: year,
18783                                    M: month,
18784                                    d: day,
18785                                    h: picker.date.hours(),
18786                                    m: picker.date.minutes(),
18787                                    s: picker.date.seconds()
18788                                }
18789                                );
18790                                picker.viewDate = moment({
18791                                    y: year, M: month, d: Math.min(28, day)
18792                                });
18793                                fillDate();
18794                                set();
18795                                notifyChange(oldDate, e.type);
18796                            }
18797                            break;
18798                    }
18799                }
18800            }
18801        },
18802
18803        actions = {
18804            incrementHours: function () {
18805                checkDate('add', 'hours', 1);
18806            },
18807
18808            incrementMinutes: function () {
18809                checkDate('add', 'minutes', picker.options.minuteStepping);
18810            },
18811
18812            incrementSeconds: function () {
18813                checkDate('add', 'seconds', 1);
18814            },
18815
18816            decrementHours: function () {
18817                checkDate('subtract', 'hours', 1);
18818            },
18819
18820            decrementMinutes: function () {
18821                checkDate('subtract', 'minutes', picker.options.minuteStepping);
18822            },
18823
18824            decrementSeconds: function () {
18825                checkDate('subtract', 'seconds', 1);
18826            },
18827
18828            togglePeriod: function () {
18829                var hour = picker.date.hours();
18830                if (hour >= 12) {
18831                    hour -= 12;
18832                } else {
18833                    hour += 12;
18834                }
18835                picker.date.hours(hour);
18836            },
18837
18838            showPicker: function () {
18839                picker.widget.find('.timepicker > div:not(.timepicker-picker)').hide();
18840                picker.widget.find('.timepicker .timepicker-picker').show();
18841            },
18842
18843            showHours: function () {
18844                picker.widget.find('.timepicker .timepicker-picker').hide();
18845                picker.widget.find('.timepicker .timepicker-hours').show();
18846            },
18847
18848            showMinutes: function () {
18849                picker.widget.find('.timepicker .timepicker-picker').hide();
18850                picker.widget.find('.timepicker .timepicker-minutes').show();
18851            },
18852
18853            showSeconds: function () {
18854                picker.widget.find('.timepicker .timepicker-picker').hide();
18855                picker.widget.find('.timepicker .timepicker-seconds').show();
18856            },
18857
18858            selectHour: function (e) {
18859                var hour = parseInt($(e.target).text(), 10);
18860                if (!picker.use24hours) {
18861                    if (picker.date.hours() >= 12) {
18862                        if (hour !== 12) {
18863                            hour += 12;
18864                        }
18865                    } else {
18866                        if (hour === 12) {
18867                            hour = 0;
18868                        }
18869                    }
18870                }
18871                picker.date.hours(hour);
18872                actions.showPicker.call(picker);
18873            },
18874
18875            selectMinute: function (e) {
18876                picker.date.minutes(parseInt($(e.target).text(), 10));
18877                actions.showPicker.call(picker);
18878            },
18879
18880            selectSecond: function (e) {
18881                picker.date.seconds(parseInt($(e.target).text(), 10));
18882                actions.showPicker.call(picker);
18883            }
18884        },
18885
18886        doAction = function (e) {
18887            var oldDate = moment(picker.date),
18888                action = $(e.currentTarget).data('action'),
18889                rv = actions[action].apply(picker, arguments);
18890            stopEvent(e);
18891            if (!picker.date) {
18892                picker.date = moment({y: 1970});
18893            }
18894            set();
18895            fillTime();
18896            notifyChange(oldDate, e.type);
18897            return rv;
18898        },
18899
18900        stopEvent = function (e) {
18901            e.stopPropagation();
18902            e.preventDefault();
18903        },
18904
18905        keydown = function (e) {
18906            if (e.keyCode === 27) { // allow escape to hide picker
18907                picker.hide();
18908            }
18909        },
18910
18911        change = function (e) {
18912            moment.locale(picker.options.language);
18913            var input = $(e.target), oldDate = moment(picker.date), newDate = moment(input.val(), picker.format, picker.options.useStrict);
18914            if (newDate.isValid() && !isInDisableDates(newDate) && isInEnableDates(newDate)) {
18915                update();
18916                picker.setValue(newDate);
18917                notifyChange(oldDate, e.type);
18918                set();
18919            }
18920            else {
18921                picker.viewDate = oldDate;
18922                picker.unset = true;
18923                notifyChange(oldDate, e.type);
18924                notifyError(newDate);
18925            }
18926        },
18927
18928        showMode = function (dir) {
18929            if (dir) {
18930                picker.viewMode = Math.max(picker.minViewMode, Math.min(2, picker.viewMode + dir));
18931            }
18932            picker.widget.find('.datepicker > div').hide().filter('.datepicker-' + dpGlobal.modes[picker.viewMode].clsName).show();
18933        },
18934
18935        attachDatePickerEvents = function () {
18936            var $this, $parent, expanded, closed, collapseData;
18937            picker.widget.on('click', '.datepicker *', $.proxy(click, this)); // this handles date picker clicks
18938            picker.widget.on('click', '[data-action]', $.proxy(doAction, this)); // this handles time picker clicks
18939            picker.widget.on('mousedown', $.proxy(stopEvent, this));
18940            picker.element.on('keydown', $.proxy(keydown, this));
18941            if (picker.options.pickDate && picker.options.pickTime) {
18942                picker.widget.on('click.togglePicker', '.accordion-toggle', function (e) {
18943                    e.stopPropagation();
18944                    $this = $(this);
18945                    $parent = $this.closest('ul');
18946                    expanded = $parent.find('.in');
18947                    closed = $parent.find('.collapse:not(.in)');
18948
18949                    if (expanded && expanded.length) {
18950                        collapseData = expanded.data('collapse');
18951                        if (collapseData && collapseData.transitioning) {
18952                            return;
18953                        }
18954                        expanded.collapse('hide');
18955                        closed.collapse('show');
18956                        $this.find('span').toggleClass(picker.options.icons.time + ' ' + picker.options.icons.date);
18957                        if (picker.component) {
18958                            picker.component.find('span').toggleClass(picker.options.icons.time + ' ' + picker.options.icons.date);
18959                        }
18960                    }
18961                });
18962            }
18963            if (picker.isInput) {
18964                picker.element.on({
18965                    'click': $.proxy(picker.show, this),
18966                    'focus': $.proxy(picker.show, this),
18967                    'change': $.proxy(change, this),
18968                    'blur': $.proxy(picker.hide, this)
18969                });
18970            } else {
18971                picker.element.on({
18972                    'change': $.proxy(change, this)
18973                }, 'input');
18974                if (picker.component) {
18975                    picker.component.on('click', $.proxy(picker.show, this));
18976                    picker.component.on('mousedown', $.proxy(stopEvent, this));
18977                } else {
18978                    picker.element.on('click', $.proxy(picker.show, this));
18979                }
18980            }
18981        },
18982
18983        attachDatePickerGlobalEvents = function () {
18984            $(window).on(
18985                'resize.datetimepicker' + picker.id, $.proxy(place, this));
18986            if (!picker.isInput) {
18987                $(document).on(
18988                    'mousedown.datetimepicker' + picker.id, $.proxy(picker.hide, this));
18989            }
18990        },
18991
18992        detachDatePickerEvents = function () {
18993            picker.widget.off('click', '.datepicker *', picker.click);
18994            picker.widget.off('click', '[data-action]');
18995            picker.widget.off('mousedown', picker.stopEvent);
18996            if (picker.options.pickDate && picker.options.pickTime) {
18997                picker.widget.off('click.togglePicker');
18998            }
18999            if (picker.isInput) {
19000                picker.element.off({
19001                    'focus': picker.show,
19002                    'change': picker.change,
19003                    'click': picker.show,
19004                    'blur' : picker.hide
19005                });
19006            } else {
19007                picker.element.off({
19008                    'change': picker.change
19009                }, 'input');
19010                if (picker.component) {
19011                    picker.component.off('click', picker.show);
19012                    picker.component.off('mousedown', picker.stopEvent);
19013                } else {
19014                    picker.element.off('click', picker.show);
19015                }
19016            }
19017        },
19018
19019        detachDatePickerGlobalEvents = function () {
19020            $(window).off('resize.datetimepicker' + picker.id);
19021            if (!picker.isInput) {
19022                $(document).off('mousedown.datetimepicker' + picker.id);
19023            }
19024        },
19025
19026        isInFixed = function () {
19027            if (picker.element) {
19028                var parents = picker.element.parents(), inFixed = false, i;
19029                for (i = 0; i < parents.length; i++) {
19030                    if ($(parents[i]).css('position') === 'fixed') {
19031                        inFixed = true;
19032                        break;
19033                    }
19034                }
19035                return inFixed;
19036            } else {
19037                return false;
19038            }
19039        },
19040
19041        set = function () {
19042            moment.locale(picker.options.language);
19043            var formatted = '';
19044            if (!picker.unset) {
19045                formatted = moment(picker.date).format(picker.format);
19046            }
19047            getPickerInput().val(formatted);
19048            picker.element.data('date', formatted);
19049            if (!picker.options.pickTime) {
19050                picker.hide();
19051            }
19052        },
19053
19054        checkDate = function (direction, unit, amount) {
19055            moment.locale(picker.options.language);
19056            var newDate;
19057            if (direction === 'add') {
19058                newDate = moment(picker.date);
19059                if (newDate.hours() === 23) {
19060                    newDate.add(amount, unit);
19061                }
19062                newDate.add(amount, unit);
19063            }
19064            else {
19065                newDate = moment(picker.date).subtract(amount, unit);
19066            }
19067            if (isInDisableDates(moment(newDate.subtract(amount, unit))) || isInDisableDates(newDate)) {
19068                notifyError(newDate.format(picker.format));
19069                return;
19070            }
19071
19072            if (direction === 'add') {
19073                picker.date.add(amount, unit);
19074            }
19075            else {
19076                picker.date.subtract(amount, unit);
19077            }
19078            picker.unset = false;
19079        },
19080
19081        isInDisableDates = function (date, timeUnit) {
19082            moment.locale(picker.options.language);
19083            var maxDate = moment(picker.options.maxDate, picker.format, picker.options.useStrict),
19084                minDate = moment(picker.options.minDate, picker.format, picker.options.useStrict);
19085
19086            if (timeUnit) {
19087                maxDate = maxDate.endOf(timeUnit);
19088                minDate = minDate.startOf(timeUnit);
19089            }
19090
19091            if (date.isAfter(maxDate) || date.isBefore(minDate)) {
19092                return true;
19093            }
19094            if (picker.options.disabledDates === false) {
19095                return false;
19096            }
19097            return picker.options.disabledDates[date.format('YYYY-MM-DD')] === true;
19098        },
19099        isInEnableDates = function (date) {
19100            moment.locale(picker.options.language);
19101            if (picker.options.enabledDates === false) {
19102                return true;
19103            }
19104            return picker.options.enabledDates[date.format('YYYY-MM-DD')] === true;
19105        },
19106
19107        indexGivenDates = function (givenDatesArray) {
19108            // Store given enabledDates and disabledDates as keys.
19109            // This way we can check their existence in O(1) time instead of looping through whole array.
19110            // (for example: picker.options.enabledDates['2014-02-27'] === true)
19111            var givenDatesIndexed = {}, givenDatesCount = 0, i;
19112            for (i = 0; i < givenDatesArray.length; i++) {
19113                if (moment.isMoment(givenDatesArray[i]) || givenDatesArray[i] instanceof Date) {
19114                    dDate = moment(givenDatesArray[i]);
19115                } else {
19116                    dDate = moment(givenDatesArray[i], picker.format, picker.options.useStrict);
19117                }
19118                if (dDate.isValid()) {
19119                    givenDatesIndexed[dDate.format('YYYY-MM-DD')] = true;
19120                    givenDatesCount++;
19121                }
19122            }
19123            if (givenDatesCount > 0) {
19124                return givenDatesIndexed;
19125            }
19126            return false;
19127        },
19128
19129        padLeft = function (string) {
19130            string = string.toString();
19131            if (string.length >= 2) {
19132                return string;
19133            }
19134            return '0' + string;
19135        },
19136
19137        getTemplate = function () {
19138            if (picker.options.pickDate && picker.options.pickTime) {
19139                var ret = '';
19140                ret = '<div class="bootstrap-datetimepicker-widget' + (picker.options.sideBySide ? ' timepicker-sbs' : '') + (picker.use24hours ? ' usetwentyfour' : '') + ' dropdown-menu" style="z-index:9999 !important;">';
19141                if (picker.options.sideBySide) {
19142                    ret += '<div class="row">' +
19143                       '<div class="col-sm-6 datepicker">' + dpGlobal.template + '</div>' +
19144                       '<div class="col-sm-6 timepicker">' + tpGlobal.getTemplate() + '</div>' +
19145                     '</div>';
19146                } else {
19147                    ret += '<ul class="list-unstyled">' +
19148                        '<li' + (picker.options.collapse ? ' class="collapse in"' : '') + '>' +
19149                            '<div class="datepicker">' + dpGlobal.template + '</div>' +
19150                        '</li>' +
19151                        '<li class="picker-switch accordion-toggle"><a class="btn" style="width:100%"><span class="' + picker.options.icons.time + '"></span></a></li>' +
19152                        '<li' + (picker.options.collapse ? ' class="collapse"' : '') + '>' +
19153                            '<div class="timepicker">' + tpGlobal.getTemplate() + '</div>' +
19154                        '</li>' +
19155                   '</ul>';
19156                }
19157                ret += '</div>';
19158                return ret;
19159            }
19160            if (picker.options.pickTime) {
19161                return (
19162                    '<div class="bootstrap-datetimepicker-widget dropdown-menu">' +
19163                        '<div class="timepicker">' + tpGlobal.getTemplate() + '</div>' +
19164                    '</div>'
19165                );
19166            }
19167            return (
19168                '<div class="bootstrap-datetimepicker-widget dropdown-menu">' +
19169                    '<div class="datepicker">' + dpGlobal.template + '</div>' +
19170                '</div>'
19171            );
19172        },
19173
19174        dpGlobal = {
19175            modes: [
19176                {
19177                    clsName: 'days',
19178                    navFnc: 'month',
19179                    navStep: 1
19180                },
19181                {
19182                    clsName: 'months',
19183                    navFnc: 'year',
19184                    navStep: 1
19185                },
19186                {
19187                    clsName: 'years',
19188                    navFnc: 'year',
19189                    navStep: 10
19190                }
19191            ],
19192            headTemplate:
19193                    '<thead>' +
19194                        '<tr>' +
19195                            '<th class="prev">&lsaquo;</th><th colspan="5" class="picker-switch"></th><th class="next">&rsaquo;</th>' +
19196                        '</tr>' +
19197                    '</thead>',
19198            contTemplate:
19199                    '<tbody><tr><td colspan="7"></td></tr></tbody>'
19200        },
19201
19202        tpGlobal = {
19203            hourTemplate: '<span data-action="showHours"   data-time-component="hours"   class="timepicker-hour"></span>',
19204            minuteTemplate: '<span data-action="showMinutes" data-time-component="minutes" class="timepicker-minute"></span>',
19205            secondTemplate: '<span data-action="showSeconds"  data-time-component="seconds" class="timepicker-second"></span>'
19206        };
19207
19208        dpGlobal.template =
19209            '<div class="datepicker-days">' +
19210                '<table class="table-condensed">' + dpGlobal.headTemplate + '<tbody></tbody></table>' +
19211            '</div>' +
19212            '<div class="datepicker-months">' +
19213                '<table class="table-condensed">' + dpGlobal.headTemplate + dpGlobal.contTemplate + '</table>' +
19214            '</div>' +
19215            '<div class="datepicker-years">' +
19216                '<table class="table-condensed">' + dpGlobal.headTemplate + dpGlobal.contTemplate + '</table>' +
19217            '</div>';
19218
19219        tpGlobal.getTemplate = function () {
19220            return (
19221                '<div class="timepicker-picker">' +
19222                    '<table class="table-condensed">' +
19223                        '<tr>' +
19224                            '<td><a href="#" class="btn" data-action="incrementHours"><span class="' + picker.options.icons.up + '"></span></a></td>' +
19225                            '<td class="separator"></td>' +
19226                            '<td>' + (picker.options.useMinutes ? '<a href="#" class="btn" data-action="incrementMinutes"><span class="' + picker.options.icons.up + '"></span></a>' : '') + '</td>' +
19227                            (picker.options.useSeconds ?
19228                                '<td class="separator"></td><td><a href="#" class="btn" data-action="incrementSeconds"><span class="' + picker.options.icons.up + '"></span></a></td>' : '') +
19229                            (picker.use24hours ? '' : '<td class="separator"></td>') +
19230                        '</tr>' +
19231                        '<tr>' +
19232                            '<td>' + tpGlobal.hourTemplate + '</td> ' +
19233                            '<td class="separator">:</td>' +
19234                            '<td>' + (picker.options.useMinutes ? tpGlobal.minuteTemplate : '<span class="timepicker-minute">00</span>') + '</td> ' +
19235                            (picker.options.useSeconds ?
19236                                '<td class="separator">:</td><td>' + tpGlobal.secondTemplate + '</td>' : '') +
19237                            (picker.use24hours ? '' : '<td class="separator"></td>' +
19238                            '<td><button type="button" class="btn btn-primary" data-action="togglePeriod"></button></td>') +
19239                        '</tr>' +
19240                        '<tr>' +
19241                            '<td><a href="#" class="btn" data-action="decrementHours"><span class="' + picker.options.icons.down + '"></span></a></td>' +
19242                            '<td class="separator"></td>' +
19243                            '<td>' + (picker.options.useMinutes ? '<a href="#" class="btn" data-action="decrementMinutes"><span class="' + picker.options.icons.down + '"></span></a>' : '') + '</td>' +
19244                            (picker.options.useSeconds ?
19245                                '<td class="separator"></td><td><a href="#" class="btn" data-action="decrementSeconds"><span class="' + picker.options.icons.down + '"></span></a></td>' : '') +
19246                            (picker.use24hours ? '' : '<td class="separator"></td>') +
19247                        '</tr>' +
19248                    '</table>' +
19249                '</div>' +
19250                '<div class="timepicker-hours" data-action="selectHour">' +
19251                    '<table class="table-condensed"></table>' +
19252                '</div>' +
19253                '<div class="timepicker-minutes" data-action="selectMinute">' +
19254                    '<table class="table-condensed"></table>' +
19255                '</div>' +
19256                (picker.options.useSeconds ?
19257                    '<div class="timepicker-seconds" data-action="selectSecond"><table class="table-condensed"></table></div>' : '')
19258            );
19259        };
19260
19261        picker.destroy = function () {
19262            detachDatePickerEvents();
19263            detachDatePickerGlobalEvents();
19264            picker.widget.remove();
19265            picker.element.removeData('DateTimePicker');
19266            if (picker.component) {
19267                picker.component.removeData('DateTimePicker');
19268            }
19269        };
19270
19271        picker.show = function (e) {
19272            if (picker.options.useCurrent) {
19273                if (getPickerInput().val() === '') {
19274                    if (picker.options.minuteStepping !== 1) {
19275                        var mDate = moment(),
19276                        rInterval = picker.options.minuteStepping;
19277                        mDate.minutes((Math.round(mDate.minutes() / rInterval) * rInterval) % 60).seconds(0);
19278                        picker.setValue(mDate.format(picker.format));
19279                    } else {
19280                        picker.setValue(moment().format(picker.format));
19281                    }
19282                    notifyChange('', e.type);
19283                }
19284            }
19285            // if this is a click event on the input field and picker is already open don't hide it
19286            if (e && e.type === 'click' && picker.isInput && picker.widget.hasClass('picker-open')) {
19287                return;
19288            }
19289            if (picker.widget.hasClass('picker-open')) {
19290                picker.widget.hide();
19291                picker.widget.removeClass('picker-open');
19292            }
19293            else {
19294                picker.widget.show();
19295                picker.widget.addClass('picker-open');
19296            }
19297            picker.height = picker.component ? picker.component.outerHeight() : picker.element.outerHeight();
19298            place();
19299            picker.element.trigger({
19300                type: 'dp.show',
19301                date: moment(picker.date)
19302            });
19303            attachDatePickerGlobalEvents();
19304            if (e) {
19305                stopEvent(e);
19306            }
19307        };
19308
19309        picker.disable = function () {
19310            var input = picker.element.find('input');
19311            if (input.prop('disabled')) {
19312                return;
19313            }
19314            input.prop('disabled', true);
19315            detachDatePickerEvents();
19316        };
19317
19318        picker.enable = function () {
19319            var input = picker.element.find('input');
19320            if (!input.prop('disabled')) {
19321                return;
19322            }
19323            input.prop('disabled', false);
19324            attachDatePickerEvents();
19325        };
19326
19327        picker.hide = function () {
19328            // Ignore event if in the middle of a picker transition
19329            var collapse = picker.widget.find('.collapse'), i, collapseData;
19330            for (i = 0; i < collapse.length; i++) {
19331                collapseData = collapse.eq(i).data('collapse');
19332                if (collapseData && collapseData.transitioning) {
19333                    return;
19334                }
19335            }
19336            picker.widget.hide();
19337            picker.widget.removeClass('picker-open');
19338            picker.viewMode = picker.startViewMode;
19339            showMode();
19340            picker.element.trigger({
19341                type: 'dp.hide',
19342                date: moment(picker.date)
19343            });
19344            detachDatePickerGlobalEvents();
19345        };
19346
19347        picker.setValue = function (newDate) {
19348            moment.locale(picker.options.language);
19349            if (!newDate) {
19350                picker.unset = true;
19351                set();
19352            } else {
19353                picker.unset = false;
19354            }
19355            if (!moment.isMoment(newDate)) {
19356                newDate = (newDate instanceof Date) ? moment(newDate) : moment(newDate, picker.format, picker.options.useStrict);
19357            } else {
19358                newDate = newDate.locale(picker.options.language);
19359            }
19360            if (newDate.isValid()) {
19361                picker.date = newDate;
19362                set();
19363                picker.viewDate = moment({y: picker.date.year(), M: picker.date.month()});
19364                fillDate();
19365                fillTime();
19366            }
19367            else {
19368                notifyError(newDate);
19369            }
19370        };
19371
19372        picker.getDate = function () {
19373            if (picker.unset) {
19374                return null;
19375            }
19376            return moment(picker.date);
19377        };
19378
19379        picker.setDate = function (date) {
19380            var oldDate = moment(picker.date);
19381            if (!date) {
19382                picker.setValue(null);
19383            } else {
19384                picker.setValue(date);
19385            }
19386            notifyChange(oldDate, 'function');
19387        };
19388
19389        picker.setDisabledDates = function (dates) {
19390            picker.options.disabledDates = indexGivenDates(dates);
19391            if (picker.viewDate) {
19392                update();
19393            }
19394        };
19395
19396        picker.setEnabledDates = function (dates) {
19397            picker.options.enabledDates = indexGivenDates(dates);
19398            if (picker.viewDate) {
19399                update();
19400            }
19401        };
19402
19403        picker.setMaxDate = function (date) {
19404            if (date === undefined) {
19405                return;
19406            }
19407            if (moment.isMoment(date) || date instanceof Date) {
19408                picker.options.maxDate = moment(date);
19409            } else {
19410                picker.options.maxDate = moment(date, picker.format, picker.options.useStrict);
19411            }
19412            if (picker.viewDate) {
19413                update();
19414            }
19415        };
19416
19417        picker.setMinDate = function (date) {
19418            if (date === undefined) {
19419                return;
19420            }
19421            if (moment.isMoment(date) || date instanceof Date) {
19422                picker.options.minDate = moment(date);
19423            } else {
19424                picker.options.minDate = moment(date, picker.format, picker.options.useStrict);
19425            }
19426            if (picker.viewDate) {
19427                update();
19428            }
19429        };
19430
19431        init();
19432    };
19433
19434    $.fn.datetimepicker = function (options) {
19435        return this.each(function () {
19436            var $this = $(this),
19437                data = $this.data('DateTimePicker');
19438            if (!data) {
19439                $this.data('DateTimePicker', new DateTimePicker(this, options));
19440            }
19441        });
19442    };
19443
19444    $.fn.datetimepicker.defaults = {
19445        format: false,
19446        pickDate: true,
19447        pickTime: true,
19448        useMinutes: true,
19449        useSeconds: false,
19450        useCurrent: true,
19451        minuteStepping: 1,
19452        minDate: moment({y: 1900}),
19453        maxDate: moment().add(100, 'y'),
19454        showToday: true,
19455        collapse: true,
19456        language: moment.locale(),
19457        defaultDate: '',
19458        disabledDates: false,
19459        enabledDates: false,
19460        icons: {},
19461        useStrict: false,
19462        direction: 'auto',
19463        sideBySide: false,
19464        daysOfWeekDisabled: [],
19465        widgetParent: false
19466    };
19467}));
19468
19469/* ===========================================================
19470# bootstrap-tour - v0.9.3
19471# http://bootstraptour.com
19472# ==============================================================
19473# Copyright 2012-2013 Ulrich Sossou
19474#
19475# Licensed under the Apache License, Version 2.0 (the "License");
19476# you may not use this file except in compliance with the License.
19477# You may obtain a copy of the License at
19478#
19479#     http://www.apache.org/licenses/LICENSE-2.0
19480#
19481# Unless required by applicable law or agreed to in writing, software
19482# distributed under the License is distributed on an "AS IS" BASIS,
19483# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19484# See the License for the specific language governing permissions and
19485# limitations under the License.
19486*/
19487(function($, window) {
19488  var Tour, document;
19489  document = window.document;
19490  Tour = (function() {
19491    function Tour(options) {
19492      var storage;
vendor: 19,485 bytes, lines 19493-20051
19493      try {
19494        storage = window.localStorage;
19495      } catch (_error) {
19496        storage = false;
19497      }
19498      this._options = $.extend({
19499        name: "tour",
19500        steps: [],
19501        container: "body",
19502        keyboard: true,
19503        storage: storage,
19504        debug: false,
19505        backdrop: false,
19506        redirect: true,
19507        orphan: false,
19508        duration: false,
19509        basePath: "",
19510        template: "<div class='popover'> <div class='arrow'></div> <h3 class='popover-title'></h3> <div class='popover-content'></div> <div class='popover-navigation'> <div class='btn-group'> <button class='btn btn-sm btn-default' data-role='prev'>&laquo; Prev</button> <button class='btn btn-sm btn-default' data-role='next'>Next &raquo;</button> <button class='btn btn-sm btn-default' data-role='pause-resume' data-pause-text='Pause' data-resume-text='Resume'>Pause</button> </div> <button class='btn btn-sm btn-default' data-role='end'>End tour</button> </div> </div>",
19511        afterSetState: function(key, value) {},
19512        afterGetState: function(key, value) {},
19513        afterRemoveState: function(key) {},
19514        onStart: function(tour) {},
19515        onEnd: function(tour) {},
19516        onShow: function(tour) {},
19517        onShown: function(tour) {},
19518        onHide: function(tour) {},
19519        onHidden: function(tour) {},
19520        onNext: function(tour) {},
19521        onPrev: function(tour) {},
19522        onPause: function(tour, duration) {},
19523        onResume: function(tour, duration) {}
19524      }, options);
19525      this._force = false;
19526      this._inited = false;
19527      this.backdrop = {
19528        overlay: null,
19529        $element: null,
19530        $background: null,
19531        backgroundShown: false,
19532        overlayElementShown: false
19533      };
19534      this;
19535    }
19536
19537    Tour.prototype.addSteps = function(steps) {
19538      var step, _i, _len;
19539      for (_i = 0, _len = steps.length; _i < _len; _i++) {
19540        step = steps[_i];
19541        this.addStep(step);
19542      }
19543      return this;
19544    };
19545
19546    Tour.prototype.addStep = function(step) {
19547      this._options.steps.push(step);
19548      return this;
19549    };
19550
19551    Tour.prototype.getStep = function(i) {
19552      if (this._options.steps[i] != null) {
19553        return $.extend({
19554          id: "step-" + i,
19555          path: "",
19556          placement: "right",
19557          title: "",
19558          content: "<p></p>",
19559          next: i === this._options.steps.length - 1 ? -1 : i + 1,
19560          prev: i - 1,
19561          animation: true,
19562          container: this._options.container,
19563          backdrop: this._options.backdrop,
19564          redirect: this._options.redirect,
19565          orphan: this._options.orphan,
19566          duration: this._options.duration,
19567          template: this._options.template,
19568          onShow: this._options.onShow,
19569          onShown: this._options.onShown,
19570          onHide: this._options.onHide,
19571          onHidden: this._options.onHidden,
19572          onNext: this._options.onNext,
19573          onPrev: this._options.onPrev,
19574          onPause: this._options.onPause,
19575          onResume: this._options.onResume
19576        }, this._options.steps[i]);
19577      }
19578    };
19579
19580    Tour.prototype.init = function(force) {
19581      this._force = force;
19582      if (this.ended()) {
19583        this._debug("Tour ended, init prevented.");
19584        return this;
19585      }
19586      this.setCurrentStep();
19587      this._initMouseNavigation();
19588      this._initKeyboardNavigation();
19589      this._onResize((function(_this) {
19590        return function() {
19591          return _this.showStep(_this._current);
19592        };
19593      })(this));
19594      if (this._current !== null) {
19595        this.showStep(this._current);
19596      }
19597      this._inited = true;
19598      return this;
19599    };
19600
19601    Tour.prototype.start = function(force) {
19602      var promise;
19603      if (force == null) {
19604        force = false;
19605      }
19606      if (!this._inited) {
19607        this.init(force);
19608      }
19609      if (this._current === null) {
19610        promise = this._makePromise(this._options.onStart != null ? this._options.onStart(this) : void 0);
19611        this._callOnPromiseDone(promise, this.showStep, 0);
19612      }
19613      return this;
19614    };
19615
19616    Tour.prototype.next = function() {
19617      var promise;
19618      promise = this.hideStep(this._current);
19619      return this._callOnPromiseDone(promise, this._showNextStep);
19620    };
19621
19622    Tour.prototype.prev = function() {
19623      var promise;
19624      promise = this.hideStep(this._current);
19625      return this._callOnPromiseDone(promise, this._showPrevStep);
19626    };
19627
19628    Tour.prototype.goTo = function(i) {
19629      var promise;
19630      promise = this.hideStep(this._current);
19631      return this._callOnPromiseDone(promise, this.showStep, i);
19632    };
19633
19634    Tour.prototype.end = function() {
19635      var endHelper, promise;
19636      endHelper = (function(_this) {
19637        return function(e) {
19638          $(document).off("click.tour-" + _this._options.name);
19639          $(document).off("keyup.tour-" + _this._options.name);
19640          $(window).off("resize.tour-" + _this._options.name);
19641          _this._setState("end", "yes");
19642          _this._inited = false;
19643          _this._force = false;
19644          _this._clearTimer();
19645          if (_this._options.onEnd != null) {
19646            return _this._options.onEnd(_this);
19647          }
19648        };
19649      })(this);
19650      promise = this.hideStep(this._current);
19651      return this._callOnPromiseDone(promise, endHelper);
19652    };
19653
19654    Tour.prototype.ended = function() {
19655      return !this._force && !!this._getState("end");
19656    };
19657
19658    Tour.prototype.restart = function() {
19659      this._removeState("current_step");
19660      this._removeState("end");
19661      return this.start();
19662    };
19663
19664    Tour.prototype.pause = function() {
19665      var step;
19666      step = this.getStep(this._current);
19667      if (!(step && step.duration)) {
19668        return this;
19669      }
19670      this._paused = true;
19671      this._duration -= new Date().getTime() - this._start;
19672      window.clearTimeout(this._timer);
19673      this._debug("Paused/Stopped step " + (this._current + 1) + " timer (" + this._duration + " remaining).");
19674      if (step.onPause != null) {
19675        return step.onPause(this, this._duration);
19676      }
19677    };
19678
19679    Tour.prototype.resume = function() {
19680      var step;
19681      step = this.getStep(this._current);
19682      if (!(step && step.duration)) {
19683        return this;
19684      }
19685      this._paused = false;
19686      this._start = new Date().getTime();
19687      this._duration = this._duration || step.duration;
19688      this._timer = window.setTimeout((function(_this) {
19689        return function() {
19690          if (_this._isLast()) {
19691            return _this.next();
19692          } else {
19693            return _this.end();
19694          }
19695        };
19696      })(this), this._duration);
19697      this._debug("Started step " + (this._current + 1) + " timer with duration " + this._duration);
19698      if ((step.onResume != null) && this._duration !== step.duration) {
19699        return step.onResume(this, this._duration);
19700      }
19701    };
19702
19703    Tour.prototype.hideStep = function(i) {
19704      var hideStepHelper, promise, step;
19705      step = this.getStep(i);
19706      if (!step) {
19707        return;
19708      }
19709      this._clearTimer();
19710      promise = this._makePromise(step.onHide != null ? step.onHide(this, i) : void 0);
19711      hideStepHelper = (function(_this) {
19712        return function(e) {
19713          var $element;
19714          $element = $(step.element);
19715          if (!($element.data("bs.popover") || $element.data("popover"))) {
19716            $element = $("body");
19717          }
19718          $element.popover("destroy").removeClass("tour-" + _this._options.name + "-element tour-" + _this._options.name + "-" + i + "-element");
19719          if (step.reflex) {
19720            $element.css("cursor", "").off("click.tour-" + _this._options.name);
19721          }
19722          if (step.backdrop) {
19723            _this._hideBackdrop();
19724          }
19725          if (step.onHidden != null) {
19726            return step.onHidden(_this);
19727          }
19728        };
19729      })(this);
19730      this._callOnPromiseDone(promise, hideStepHelper);
19731      return promise;
19732    };
19733
19734    Tour.prototype.showStep = function(i) {
19735      var promise, showStepHelper, skipToPrevious, step;
19736      if (this.ended()) {
19737        this._debug("Tour ended, showStep prevented.");
19738        return this;
19739      }
19740      step = this.getStep(i);
19741      if (!step) {
19742        return;
19743      }
19744      skipToPrevious = i < this._current;
19745      promise = this._makePromise(step.onShow != null ? step.onShow(this, i) : void 0);
19746      showStepHelper = (function(_this) {
19747        return function(e) {
19748          var current_path, path;
19749          _this.setCurrentStep(i);
19750          path = (function() {
19751            switch ({}.toString.call(step.path)) {
19752              case "[object Function]":
19753                return step.path();
19754              case "[object String]":
19755                return this._options.basePath + step.path;
19756              default:
19757                return step.path;
19758            }
19759          }).call(_this);
19760          current_path = [document.location.pathname, document.location.hash].join("");
19761          if (_this._isRedirect(path, current_path)) {
19762            _this._redirect(step, path);
19763            return;
19764          }
19765          if (_this._isOrphan(step)) {
19766            if (!step.orphan) {
19767              _this._debug("Skip the orphan step " + (_this._current + 1) + ". Orphan option is false and the element doesn't exist or is hidden.");
19768              if (skipToPrevious) {
19769                _this._showPrevStep();
19770              } else {
19771                _this._showNextStep();
19772              }
19773              return;
19774            }
19775            _this._debug("Show the orphan step " + (_this._current + 1) + ". Orphans option is true.");
19776          }
19777          if (step.backdrop) {
19778            _this._showBackdrop(!_this._isOrphan(step) ? step.element : void 0);
19779          }
19780          _this._scrollIntoView(step.element, function() {
19781            if (_this.getCurrentStep() !== i) {
19782              return;
19783            }
19784            if ((step.element != null) && step.backdrop) {
19785              _this._showOverlayElement(step.element);
19786            }
19787            _this._showPopover(step, i);
19788            if (step.onShown != null) {
19789              step.onShown(_this);
19790            }
19791            return _this._debug("Step " + (_this._current + 1) + " of " + _this._options.steps.length);
19792          });
19793          if (step.duration) {
19794            return _this.resume();
19795          }
19796        };
19797      })(this);
19798      this._callOnPromiseDone(promise, showStepHelper);
19799      return promise;
19800    };
19801
19802    Tour.prototype.getCurrentStep = function() {
19803      return this._current;
19804    };
19805
19806    Tour.prototype.setCurrentStep = function(value) {
19807      if (value != null) {
19808        this._current = value;
19809        this._setState("current_step", value);
19810      } else {
19811        this._current = this._getState("current_step");
19812        this._current = this._current === null ? null : parseInt(this._current, 10);
19813      }
19814      return this;
19815    };
19816
19817    Tour.prototype._setState = function(key, value) {
19818      var e, keyName;
19819      if (this._options.storage) {
19820        keyName = "" + this._options.name + "_" + key;
19821        try {
19822          this._options.storage.setItem(keyName, value);
19823        } catch (_error) {
19824          e = _error;
19825          if (e.code === DOMException.QUOTA_EXCEEDED_ERR) {
19826            this.debug("LocalStorage quota exceeded. State storage failed.");
19827          }
19828        }
19829        return this._options.afterSetState(keyName, value);
19830      } else {
19831        if (this._state == null) {
19832          this._state = {};
19833        }
19834        return this._state[key] = value;
19835      }
19836    };
19837
19838    Tour.prototype._removeState = function(key) {
19839      var keyName;
19840      if (this._options.storage) {
19841        keyName = "" + this._options.name + "_" + key;
19842        this._options.storage.removeItem(keyName);
19843        return this._options.afterRemoveState(keyName);
19844      } else {
19845        if (this._state != null) {
19846          return delete this._state[key];
19847        }
19848      }
19849    };
19850
19851    Tour.prototype._getState = function(key) {
19852      var keyName, value;
19853      if (this._options.storage) {
19854        keyName = "" + this._options.name + "_" + key;
19855        value = this._options.storage.getItem(keyName);
19856      } else {
19857        if (this._state != null) {
19858          value = this._state[key];
19859        }
19860      }
19861      if (value === void 0 || value === "null") {
19862        value = null;
19863      }
19864      this._options.afterGetState(key, value);
19865      return value;
19866    };
19867
19868    Tour.prototype._showNextStep = function() {
19869      var promise, showNextStepHelper, step;
19870      step = this.getStep(this._current);
19871      showNextStepHelper = (function(_this) {
19872        return function(e) {
19873          return _this.showStep(step.next);
19874        };
19875      })(this);
19876      promise = this._makePromise(step.onNext != null ? step.onNext(this) : void 0);
19877      return this._callOnPromiseDone(promise, showNextStepHelper);
19878    };
19879
19880    Tour.prototype._showPrevStep = function() {
19881      var promise, showPrevStepHelper, step;
19882      step = this.getStep(this._current);
19883      showPrevStepHelper = (function(_this) {
19884        return function(e) {
19885          return _this.showStep(step.prev);
19886        };
19887      })(this);
19888      promise = this._makePromise(step.onPrev != null ? step.onPrev(this) : void 0);
19889      return this._callOnPromiseDone(promise, showPrevStepHelper);
19890    };
19891
19892    Tour.prototype._debug = function(text) {
19893      if (this._options.debug) {
19894        return window.console.log("Bootstrap Tour '" + this._options.name + "' | " + text);
19895      }
19896    };
19897
19898    Tour.prototype._isRedirect = function(path, currentPath) {
19899      return (path != null) && path !== "" && (({}.toString.call(path) === "[object RegExp]" && !path.test(currentPath)) || ({}.toString.call(path) === "[object String]" && path.replace(/\?.*$/, "").replace(/\/?$/, "") !== currentPath.replace(/\/?$/, "")));
19900    };
19901
19902    Tour.prototype._redirect = function(step, path) {
19903      if ($.isFunction(step.redirect)) {
19904        return step.redirect.call(this, path);
19905      } else if (step.redirect === true) {
19906        this._debug("Redirect to " + path);
19907        return document.location.href = path;
19908      }
19909    };
19910
19911    Tour.prototype._isOrphan = function(step) {
19912      return (step.element == null) || !$(step.element).length || $(step.element).is(":hidden") && ($(step.element)[0].namespaceURI !== "http://www.w3.org/2000/svg");
19913    };
19914
19915    Tour.prototype._isLast = function() {
19916      return this._current < this._options.steps.length - 1;
19917    };
19918
19919    Tour.prototype._showPopover = function(step, i) {
19920      var $element, $navigation, $template, $tip, isOrphan, options;
19921      $(".tour-" + this._options.name).remove();
19922      options = $.extend({}, this._options);
19923      $template = $.isFunction(step.template) ? $(step.template(i, step)) : $(step.template);
19924      $navigation = $template.find(".popover-navigation");
19925      isOrphan = this._isOrphan(step);
19926      if (isOrphan) {
19927        step.element = "body";
19928        step.placement = "top";
19929        $template = $template.addClass("orphan");
19930      }
19931      $element = $(step.element);
19932      $template.addClass("tour-" + this._options.name + " tour-" + this._options.name + "-" + i);
19933      $element.addClass("tour-" + this._options.name + "-element tour-" + this._options.name + "-" + i + "-element");
19934      if (step.options) {
19935        $.extend(options, step.options);
19936      }
19937      if (step.reflex && !isOrphan) {
19938        $element.css("cursor", "pointer").on("click.tour-" + this._options.name, (function(_this) {
19939          return function() {
19940            if (_this._isLast()) {
19941              return _this.next();
19942            } else {
19943              return _this.end();
19944            }
19945          };
19946        })(this));
19947      }
19948      if (step.prev < 0) {
19949        $navigation.find("[data-role='prev']").addClass("disabled");
19950      }
19951      if (step.next < 0) {
19952        $navigation.find("[data-role='next']").addClass("disabled");
19953      }
19954      if (!step.duration) {
19955        $navigation.find("[data-role='pause-resume']").remove();
19956      }
19957      step.template = $template.clone().wrap("<div>").parent().html();
19958      $element.popover({
19959        placement: step.placement,
19960        trigger: "manual",
19961        title: step.title,
19962        content: step.content,
19963        html: true,
19964        animation: step.animation,
19965        container: step.container,
19966        template: step.template,
19967        selector: step.element
19968      }).popover("show");
19969      $tip = $element.data("bs.popover") ? $element.data("bs.popover").tip() : $element.data("popover").tip();
19970      $tip.attr("id", step.id);
19971      this._reposition($tip, step);
19972      if (isOrphan) {
19973        return this._center($tip);
19974      }
19975    };
19976
19977    Tour.prototype._reposition = function($tip, step) {
19978      var offsetBottom, offsetHeight, offsetRight, offsetWidth, originalLeft, originalTop, tipOffset;
19979      offsetWidth = $tip[0].offsetWidth;
19980      offsetHeight = $tip[0].offsetHeight;
19981      tipOffset = $tip.offset();
19982      originalLeft = tipOffset.left;
19983      originalTop = tipOffset.top;
19984      offsetBottom = $(document).outerHeight() - tipOffset.top - $tip.outerHeight();
19985      if (offsetBottom < 0) {
19986        tipOffset.top = tipOffset.top + offsetBottom;
19987      }
19988      offsetRight = $("html").outerWidth() - tipOffset.left - $tip.outerWidth();
19989      if (offsetRight < 0) {
19990        tipOffset.left = tipOffset.left + offsetRight;
19991      }
19992      if (tipOffset.top < 0) {
19993        tipOffset.top = 0;
19994      }
19995      if (tipOffset.left < 0) {
19996        tipOffset.left = 0;
19997      }
19998      $tip.offset(tipOffset);
19999      if (step.placement === "bottom" || step.placement === "top") {
20000        if (originalLeft !== tipOffset.left) {
20001          return this._replaceArrow($tip, (tipOffset.left - originalLeft) * 2, offsetWidth, "left");
20002        }
20003      } else {
20004        if (originalTop !== tipOffset.top) {
20005          return this._replaceArrow($tip, (tipOffset.top - originalTop) * 2, offsetHeight, "top");
20006        }
20007      }
20008    };
20009
20010    Tour.prototype._center = function($tip) {
20011      return $tip.css("top", $(window).outerHeight() / 2 - $tip.outerHeight() / 2);
20012    };
20013
20014    Tour.prototype._replaceArrow = function($tip, delta, dimension, position) {
20015      return $tip.find(".arrow").css(position, delta ? 50 * (1 - delta / dimension) + "%" : "");
20016    };
20017
20018    Tour.prototype._scrollIntoView = function(element, callback) {
20019      var $element, $window, counter, offsetTop, scrollTop, windowHeight;
20020      $element = $(element);
20021      if (!$element.length) {
20022        return callback();
20023      }
20024      $window = $(window);
20025      offsetTop = $element.offset().top;
20026      windowHeight = $window.height();
20027      scrollTop = Math.max(0, offsetTop - (windowHeight / 2));
20028      this._debug("Scroll into view. ScrollTop: " + scrollTop + ". Element offset: " + offsetTop + ". Window height: " + windowHeight + ".");
20029      counter = 0;
20030      return $("body,html").stop(true, true).animate({
20031        scrollTop: Math.ceil(scrollTop)
20032      }, (function(_this) {
20033        return function() {
20034          if (++counter === 2) {
20035            callback();
20036            return _this._debug("Scroll into view. Animation end element offset: " + ($element.offset().top) + ". Window height: " + ($window.height()) + ".");
20037          }
20038        };
20039      })(this));
20040    };
20041
20042    Tour.prototype._onResize = function(callback, timeout) {
20043      return $(window).on("resize.tour-" + this._options.name, function() {
20044        clearTimeout(timeout);
20045        return timeout = setTimeout(callback, 100);
20046      });
20047    };
20048
20049    Tour.prototype._initMouseNavigation = function() {
20050      var _this;
20051      _this = this;
20052      return $(document).off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='prev']:not(.disabled)").off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='next']:not(.disabled)").off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='end']").off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='pause-resume']").on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='next']:not(.disabled)", (function(_this) {
20053        return function(e) {
20054          e.preventDefault();
20055          return _this.next();
20056        };
20057      })(this)).on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='prev']:not(.disabled)", (function(_this) {
20058        return function(e) {
20059          e.preventDefault();
20060          return _this.prev();
20061        };
20062      })(this)).on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='end']", (function(_this) {
20063        return function(e) {
20064          e.preventDefault();
20065          return _this.end();
20066        };
20067      })(this)).on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='pause-resume']", function(e) {
20068        var $this;
20069        e.preventDefault();
20070        $this = $(this);
20071        $this.text(_this._paused ? $this.data("pause-text") : $this.data("resume-text"));
20072        if (_this._paused) {
20073          return _this.resume();
20074        } else {
20075          return _this.pause();
20076        }
20077      });
20078    };
20079
20080    Tour.prototype._initKeyboardNavigation = function() {
20081      if (!this._options.keyboard) {
20082        return;
20083      }
20084      return $(document).on("keyup.tour-" + this._options.name, (function(_this) {
20085        return function(e) {
20086          if (!e.which) {
20087            return;
20088          }
20089          switch (e.which) {
20090            case 39:
20091              e.preventDefault();
20092              if (_this._isLast()) {
20093                return _this.next();
20094              } else {
20095                return _this.end();
20096              }
20097              break;
20098            case 37:
20099              e.preventDefault();
20100              if (_this._current > 0) {
20101                return _this.prev();
20102              }
20103              break;
20104            case 27:
20105              e.preventDefault();
20106              return _this.end();
20107          }
20108        };
20109      })(this));
20110    };
20111
20112    Tour.prototype._makePromise = function(result) {
20113      if (result && $.isFunction(result.then)) {
20114        return result;
20115      } else {
20116        return null;
20117      }
20118    };
20119
20120    Tour.prototype._callOnPromiseDone = function(promise, cb, arg) {
20121      if (promise) {
20122        return promise.then((function(_this) {
20123          return function(e) {
20124            return cb.call(_this, arg);
20125          };
20126        })(this));
20127      } else {
20128        return cb.call(this, arg);
20129      }
20130    };
20131
20132    Tour.prototype._showBackdrop = function(element) {
20133      if (this.backdrop.backgroundShown) {
20134        return;
20135      }
20136      this.backdrop = $("<div/>", {
20137        "class": "tour-backdrop"
20138      });
20139      this.backdrop.backgroundShown = true;
20140      return $("body").append(this.backdrop);
20141    };
20142
20143    Tour.prototype._hideBackdrop = function() {
20144      this._hideOverlayElement();
20145      return this._hideBackground();
20146    };
20147
20148    Tour.prototype._hideBackground = function() {
20149      if (this.backdrop) {
20150        this.backdrop.remove();
20151        this.backdrop.overlay = null;
20152        return this.backdrop.backgroundShown = false;
20153      }
20154    };
20155
20156    Tour.prototype._showOverlayElement = function(element) {
20157      var $background, $element, offset;
20158      $element = $(element);
20159      if (!$element || $element.length === 0 || this.backdrop.overlayElementShown) {
20160        return;
20161      }
20162      this.backdrop.overlayElementShown = true;
20163      $background = $("<div/>");
20164      offset = $element.offset();
20165      offset.top = offset.top;
20166      offset.left = offset.left;
20167      $background.width($element.innerWidth()).height($element.innerHe
20167ight()).addClass("tour-step-background").offset(offset);
20168      $element.addClass("tour-step-backdrop");
20169      $("body").append($background);
20170      this.backdrop.$element = $element;
20171      return this.backdrop.$background = $background;
20172    };
20173
20174    Tour.prototype._hideOverlayElement = function() {
20175      if (!this.backdrop.overlayElementShown) {
20176        return;
20177      }
20178      this.backdrop.$element.removeClass("tour-step-backdrop");
20179      this.backdrop.$background.remove();
20180      this.backdrop.$element = null;
20181      this.backdrop.$background = null;
20182      return this.backdrop.overlayElementShown = false;
20183    };
20184
20185    Tour.prototype._clearTimer = function() {
20186      window.clearTimeout(this._timer);
20187      this._timer = null;
20188      return this._duration = null;
20189    };
20190
20191    return Tour;
20192
20193  })();
20194  return window.Tour = Tour;
20195})(jQuery, window);
20196
20197define("bootstrapTour", ["jquery","bootstrapTooltip","bootstrapPopover"], (function (global) {
20198    return function () {
20199        var ret, fn;
20200        return ret || global.$;
20201    };
20202}(this)));
20203
20204!function() {
20205  var d3 = {
20206    version: "3.4.13"
20207  };
20208  if (!Date.now) Date.now = function() {
20209    return +new Date();
20210  };
20211  var d3_arraySlice = [].slice, d3_array = function(list) {
20212    return d3_arraySlice.call(list);
20213  };
20214  var d3_document = document, d3_documentElement = d3_document.documentElement, d3_window = window;
20215  try {
20216    d3_array(d3_documentElement.childNodes)[0].nodeType;
20217  } catch (e) {
20218    d3_array = function(list) {
20219      var i = list.length, array = new Array(i);
20220      while (i--) array[i] = list[i];
20221      return array;
20222    };
20223  }
20224  try {
20225    d3_document.createElement("div").style.setProperty("opacity", 0, "");
20226  } catch (error) {
20227    var d3_element_prototype = d3_window.Element.prototype, d3_element_setAttribute = d3_element_prototype.setAttribute, d3_element_setAttributeNS = d3_element_prototype.setAttributeNS, d3_style_prototype = d3_window.CSSStyleDeclaration.prototype, d3_style_setProperty = d3_style_prototype.setProperty;
20228    d3_element_prototype.setAttribute = function(name, value) {
20229      d3_element_setAttribute.call(this, name, value + "");
20230    };
20231    d3_element_prototype.setAttributeNS = function(space, local, value) {
20232      d3_element_setAttributeNS.call(this, space, local, value + "");
20233    };
20234    d3_style_prototype.setProperty = function(name, value, priority) {
20235      d3_style_setProperty.call(this, name, value + "", priority);
20236    };
20237  }
20238  d3.ascending = d3_ascending;
20239  function d3_ascending(a, b) {
20240    return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
20241  }
vendor: 4,435 bytes, lines 20242-20368
20242  d3.descending = function(a, b) {
20243    return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
20244  };
20245  d3.min = function(array, f) {
20246    var i = -1, n = array.length, a, b;
20247    if (arguments.length === 1) {
20248      while (++i < n && !((a = array[i]) != null && a <= a)) a = undefined;
20249      while (++i < n) if ((b = array[i]) != null && a > b) a = b;
20250    } else {
20251      while (++i < n && !((a = f.call(array, array[i], i)) != null && a <= a)) a = undefined;
20252      while (++i < n) if ((b = f.call(array, array[i], i)) != null && a > b) a = b;
20253    }
20254    return a;
20255  };
20256  d3.max = function(array, f) {
20257    var i = -1, n = array.length, a, b;
20258    if (arguments.length === 1) {
20259      while (++i < n && !((a = array[i]) != null && a <= a)) a = undefined;
20260      while (++i < n) if ((b = array[i]) != null && b > a) a = b;
20261    } else {
20262      while (++i < n && !((a = f.call(array, array[i], i)) != null && a <= a)) a = undefined;
20263      while (++i < n) if ((b = f.call(array, array[i], i)) != null && b > a) a = b;
20264    }
20265    return a;
20266  };
20267  d3.extent = function(array, f) {
20268    var i = -1, n = array.length, a, b, c;
20269    if (arguments.length === 1) {
20270      while (++i < n && !((a = c = array[i]) != null && a <= a)) a = c = undefined;
20271      while (++i < n) if ((b = array[i]) != null) {
20272        if (a > b) a = b;
20273        if (c < b) c = b;
20274      }
20275    } else {
20276      while (++i < n && !((a = c = f.call(array, array[i], i)) != null && a <= a)) a = undefined;
20277      while (++i < n) if ((b = f.call(array, array[i], i)) != null) {
20278        if (a > b) a = b;
20279        if (c < b) c = b;
20280      }
20281    }
20282    return [ a, c ];
20283  };
20284  function d3_number(x) {
20285    return x === null ? NaN : +x;
20286  }
20287  function d3_numeric(x) {
20288    return !isNaN(x);
20289  }
20290  d3.sum = function(array, f) {
20291    var s = 0, n = array.length, a, i = -1;
20292    if (arguments.length === 1) {
20293      while (++i < n) if (d3_numeric(a = +array[i])) s += a;
20294    } else {
20295      while (++i < n) if (d3_numeric(a = +f.call(array, array[i], i))) s += a;
20296    }
20297    return s;
20298  };
20299  d3.mean = function(array, f) {
20300    var s = 0, n = array.length, a, i = -1, j = n;
20301    if (arguments.length === 1) {
20302      while (++i < n) if (d3_numeric(a = d3_number(array[i]))) s += a; else --j;
20303    } else {
20304      while (++i < n) if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) s += a; else --j;
20305    }
20306    return j ? s / j : undefined;
20307  };
20308  d3.quantile = function(values, p) {
20309    var H = (values.length - 1) * p + 1, h = Math.floor(H), v = +values[h - 1], e = H - h;
20310    return e ? v + e * (values[h] - v) : v;
20311  };
20312  d3.median = function(array, f) {
20313    var numbers = [], n = array.length, a, i = -1;
20314    if (arguments.length === 1) {
20315      while (++i < n) if (d3_numeric(a = d3_number(array[i]))) numbers.push(a);
20316    } else {
20317      while (++i < n) if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) numbers.push(a);
20318    }
20319    return numbers.length ? d3.quantile(numbers.sort(d3_ascending), .5) : undefined;
20320  };
20321  function d3_bisector(compare) {
20322    return {
20323      left: function(a, x, lo, hi) {
20324        if (arguments.length < 3) lo = 0;
20325        if (arguments.length < 4) hi = a.length;
20326        while (lo < hi) {
20327          var mid = lo + hi >>> 1;
20328          if (compare(a[mid], x) < 0) lo = mid + 1; else hi = mid;
20329        }
20330        return lo;
20331      },
20332      right: function(a, x, lo, hi) {
20333        if (arguments.length < 3) lo = 0;
20334        if (arguments.length < 4) hi = a.length;
20335        while (lo < hi) {
20336          var mid = lo + hi >>> 1;
20337          if (compare(a[mid], x) > 0) hi = mid; else lo = mid + 1;
20338        }
20339        return lo;
20340      }
20341    };
20342  }
20343  var d3_bisect = d3_bisector(d3_ascending);
20344  d3.bisectLeft = d3_bisect.left;
20345  d3.bisect = d3.bisectRight = d3_bisect.right;
20346  d3.bisector = function(f) {
20347    return d3_bisector(f.length === 1 ? function(d, x) {
20348      return d3_ascending(f(d), x);
20349    } : f);
20350  };
20351  d3.shuffle = function(array) {
20352    var m = array.length, t, i;
20353    while (m) {
20354      i = Math.random() * m-- | 0;
20355      t = array[m], array[m] = array[i], array[i] = t;
20356    }
20357    return array;
20358  };
20359  d3.permute = function(array, indexes) {
20360    var i = indexes.length, permutes = new Array(i);
20361    while (i--) permutes[i] = array[indexes[i]];
20362    return permutes;
20363  };
20364  d3.pairs = function(array) {
20365    var i = 0, n = array.length - 1, p0, p1 = array[0], pairs = new Array(n < 0 ? 0 : n);
20366    while (i < n) pairs[i] = [ p0 = p1, p1 = array[++i] ];
20367    return pairs;
20368  };
vendor: 27,908 bytes, lines 20369-21203
20369  d3.zip = function() {
20370    if (!(n = arguments.length)) return [];
20371    for (var i = -1, m = d3.min(arguments, d3_zipLength), zips = new Array(m); ++i < m; ) {
20372      for (var j = -1, n, zip = zips[i] = new Array(n); ++j < n; ) {
20373        zip[j] = arguments[j][i];
20374      }
20375    }
20376    return zips;
20377  };
20378  function d3_zipLength(d) {
20379    return d.length;
20380  }
20381  d3.transpose = function(matrix) {
20382    return d3.zip.apply(d3, matrix);
20383  };
20384  d3.keys = function(map) {
20385    var keys = [];
20386    for (var key in map) keys.push(key);
20387    return keys;
20388  };
20389  d3.values = function(map) {
20390    var values = [];
20391    for (var key in map) values.push(map[key]);
20392    return values;
20393  };
20394  d3.entries = function(map) {
20395    var entries = [];
20396    for (var key in map) entries.push({
20397      key: key,
20398      value: map[key]
20399    });
20400    return entries;
20401  };
20402  d3.merge = function(arrays) {
20403    var n = arrays.length, m, i = -1, j = 0, merged, array;
20404    while (++i < n) j += arrays[i].length;
20405    merged = new Array(j);
20406    while (--n >= 0) {
20407      array = arrays[n];
20408      m = array.length;
20409      while (--m >= 0) {
20410        merged[--j] = array[m];
20411      }
20412    }
20413    return merged;
20414  };
20415  var abs = Math.abs;
20416  d3.range = function(start, stop, step) {
20417    if (arguments.length < 3) {
20418      step = 1;
20419      if (arguments.length < 2) {
20420        stop = start;
20421        start = 0;
20422      }
20423    }
20424    if ((stop - start) / step === Infinity) throw new Error("infinite range");
20425    var range = [], k = d3_range_integerScale(abs(step)), i = -1, j;
20426    start *= k, stop *= k, step *= k;
20427    if (step < 0) while ((j = start + step * ++i) > stop) range.push(j / k); else while ((j = start + step * ++i) < stop) range.push(j / k);
20428    return range;
20429  };
20430  function d3_range_integerScale(x) {
20431    var k = 1;
20432    while (x * k % 1) k *= 10;
20433    return k;
20434  }
20435  function d3_class(ctor, properties) {
20436    for (var key in properties) {
20437      Object.defineProperty(ctor.prototype, key, {
20438        value: properties[key],
20439        enumerable: false
20440      });
20441    }
20442  }
20443  d3.map = function(object) {
20444    var map = new d3_Map();
20445    if (object instanceof d3_Map) object.forEach(function(key, value) {
20446      map.set(key, value);
20447    }); else for (var key in object) map.set(key, object[key]);
20448    return map;
20449  };
20450  function d3_Map() {
20451    this._ = Object.create(null);
20452  }
20453  var d3_map_proto = "__proto__", d3_map_zero = "\x00";
20454  d3_class(d3_Map, {
20455    has: d3_map_has,
20456    get: function(key) {
20457      return this._[d3_map_escape(key)];
20458    },
20459    set: function(key, value) {
20460      return this._[d3_map_escape(key)] = value;
20461    },
20462    remove: d3_map_remove,
20463    keys: d3_map_keys,
20464    values: function() {
20465      var values = [];
20466      for (var key in this._) values.push(this._[key]);
20467      return values;
20468    },
20469    entries: function() {
20470      var entries = [];
20471      for (var key in this._) entries.push({
20472        key: d3_map_unescape(key),
20473        value: this._[key]
20474      });
20475      return entries;
20476    },
20477    size: d3_map_size,
20478    empty: d3_map_empty,
20479    forEach: function(f) {
20480      for (var key in this._) f.call(this, d3_map_unescape(key), this._[key]);
20481    }
20482  });
20483  function d3_map_escape(key) {
20484    return (key += "") === d3_map_proto || key[0] === d3_map_zero ? d3_map_zero + key : key;
20485  }
20486  function d3_map_unescape(key) {
20487    return (key += "")[0] === d3_map_zero ? key.slice(1) : key;
20488  }
20489  function d3_map_has(key) {
20490    return d3_map_escape(key) in this._;
20491  }
20492  function d3_map_remove(key) {
20493    return (key = d3_map_escape(key)) in this._ && delete this._[key];
20494  }
20495  function d3_map_keys() {
20496    var keys = [];
20497    for (var key in this._) keys.push(d3_map_unescape(key));
20498    return keys;
20499  }
20500  function d3_map_size() {
20501    var size = 0;
20502    for (var key in this._) ++size;
20503    return size;
20504  }
20505  function d3_map_empty() {
20506    for (var key in this._) return false;
20507    return true;
20508  }
20509  d3.nest = function() {
20510    var nest = {}, keys = [], sortKeys = [], sortValues, rollup;
20511    function map(mapType, array, depth) {
20512      if (depth >= keys.length) return rollup ? rollup.call(nest, array) : sortValues ? array.sort(sortValues) : array;
20513      var i = -1, n = array.length, key = keys[depth++], keyValue, object, setter, valuesByKey = new d3_Map(), values;
20514      while (++i < n) {
20515        if (values = valuesByKey.get(keyValue = key(object = array[i]))) {
20516          values.push(object);
20517        } else {
20518          valuesByKey.set(keyValue, [ object ]);
20519        }
20520      }
20521      if (mapType) {
20522        object = mapType();
20523        setter = function(keyValue, values) {
20524          object.set(keyValue, map(mapType, values, depth));
20525        };
20526      } else {
20527        object = {};
20528        setter = function(keyValue, values) {
20529          object[keyValue] = map(mapType, values, depth);
20530        };
20531      }
20532      valuesByKey.forEach(setter);
20533      return object;
20534    }
20535    function entries(map, depth) {
20536      if (depth >= keys.length) return map;
20537      var array = [], sortKey = sortKeys[depth++];
20538      map.forEach(function(key, keyMap) {
20539        array.push({
20540          key: key,
20541          values: entries(keyMap, depth)
20542        });
20543      });
20544      return sortKey ? array.sort(function(a, b) {
20545        return sortKey(a.key, b.key);
20546      }) : array;
20547    }
20548    nest.map = function(array, mapType) {
20549      return map(mapType, array, 0);
20550    };
20551    nest.entries = function(array) {
20552      return entries(map(d3.map, array, 0), 0);
20553    };
20554    nest.key = function(d) {
20555      keys.push(d);
20556      return nest;
20557    };
20558    nest.sortKeys = function(order) {
20559      sortKeys[keys.length - 1] = order;
20560      return nest;
20561    };
20562    nest.sortValues = function(order) {
20563      sortValues = order;
20564      return nest;
20565    };
20566    nest.rollup = function(f) {
20567      rollup = f;
20568      return nest;
20569    };
20570    return nest;
20571  };
20572  d3.set = function(array) {
20573    var set = new d3_Set();
20574    if (array) for (var i = 0, n = array.length; i < n; ++i) set.add(array[i]);
20575    return set;
20576  };
20577  function d3_Set() {
20578    this._ = Object.create(null);
20579  }
20580  d3_class(d3_Set, {
20581    has: d3_map_has,
20582    add: function(key) {
20583      this._[d3_map_escape(key += "")] = true;
20584      return key;
20585    },
20586    remove: d3_map_remove,
20587    values: d3_map_keys,
20588    size: d3_map_size,
20589    empty: d3_map_empty,
20590    forEach: function(f) {
20591      for (var key in this._) f.call(this, d3_map_unescape(key));
20592    }
20593  });
20594  d3.behavior = {};
20595  d3.rebind = function(target, source) {
20596    var i = 1, n = arguments.length, method;
20597    while (++i < n) target[method = arguments[i]] = d3_rebind(target, source, source[method]);
20598    return target;
20599  };
20600  function d3_rebind(target, source, method) {
20601    return function() {
20602      var value = method.apply(source, arguments);
20603      return value === source ? target : value;
20604    };
20605  }
20606  function d3_vendorSymbol(object, name) {
20607    if (name in object) return name;
20608    name = name.charAt(0).toUpperCase() + name.slice(1);
20609    for (var i = 0, n = d3_vendorPrefixes.length; i < n; ++i) {
20610      var prefixName = d3_vendorPrefixes[i] + name;
20611      if (prefixName in object) return prefixName;
20612    }
20613  }
20614  var d3_vendorPrefixes = [ "webkit", "ms", "moz", "Moz", "o", "O" ];
20615  function d3_noop() {}
20616  d3.dispatch = function() {
20617    var dispatch = new d3_dispatch(), i = -1, n = arguments.length;
20618    while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch);
20619    return dispatch;
20620  };
20621  function d3_dispatch() {}
20622  d3_dispatch.prototype.on = function(type, listener) {
20623    var i = type.indexOf("."), name = "";
20624    if (i >= 0) {
20625      name = type.slice(i + 1);
20626      type = type.slice(0, i);
20627    }
20628    if (type) return arguments.length < 2 ? this[type].on(name) : this[type].on(name, listener);
20629    if (arguments.length === 2) {
20630      if (listener == null) for (type in this) {
20631        if (this.hasOwnProperty(type)) this[type].on(name, null);
20632      }
20633      return this;
20634    }
20635  };
20636  function d3_dispatch_event(dispatch) {
20637    var listeners = [], listenerByName = new d3_Map();
20638    function event() {
20639      var z = listeners, i = -1, n = z.length, l;
20640      while (++i < n) if (l = z[i].on) l.apply(this, arguments);
20641      return dispatch;
20642    }
20643    event.on = function(name, listener) {
20644      var l = listenerByName.get(name), i;
20645      if (arguments.length < 2) return l && l.on;
20646      if (l) {
20647        l.on = null;
20648        listeners = listeners.slice(0, i = listeners.indexOf(l)).concat(listeners.slice(i + 1));
20649        listenerByName.remove(name);
20650      }
20651      if (listener) listeners.push(listenerByName.set(name, {
20652        on: listener
20653      }));
20654      return dispatch;
20655    };
20656    return event;
20657  }
20658  d3.event = null;
20659  function d3_eventPreventDefault() {
20660    d3.event.preventDefault();
20661  }
20662  function d3_eventSource() {
20663    var e = d3.event, s;
20664    while (s = e.sourceEvent) e = s;
20665    return e;
20666  }
20667  function d3_eventDispatch(target) {
20668    var dispatch = new d3_dispatch(), i = 0, n = arguments.length;
20669    while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch);
20670    dispatch.of = function(thiz, argumentz) {
20671      return function(e1) {
20672        try {
20673          var e0 = e1.sourceEvent = d3.event;
20674          e1.target = target;
20675          d3.event = e1;
20676          dispatch[e1.type].apply(thiz, argumentz);
20677        } finally {
20678          d3.event = e0;
20679        }
20680      };
20681    };
20682    return dispatch;
20683  }
20684  d3.requote = function(s) {
20685    return s.replace(d3_requote_re, "\\$&");
20686  };
20687  var d3_requote_re = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;
20688  var d3_subclass = {}.__proto__ ? function(object, prototype) {
20689    object.__proto__ = prototype;
20690  } : function(object, prototype) {
20691    for (var property in prototype) object[property] = prototype[property];
20692  };
20693  function d3_selection(groups) {
20694    d3_subclass(groups, d3_selectionPrototype);
20695    return groups;
20696  }
20697  var d3_select = function(s, n) {
20698    return n.querySelector(s);
20699  }, d3_selectAll = function(s, n) {
20700    return n.querySelectorAll(s);
20701  }, d3_selectMatcher = d3_documentElement.matches || d3_documentElement[d3_vendorSymbol(d3_documentElement, "matchesSelector")], d3_selectMatches = function(n, s) {
20702    return d3_selectMatcher.call(n, s);
20703  };
20704  if (typeof Sizzle === "function") {
20705    d3_select = function(s, n) {
20706      return Sizzle(s, n)[0] || null;
20707    };
20708    d3_selectAll = Sizzle;
20709    d3_selectMatches = Sizzle.matchesSelector;
20710  }
20711  d3.selection = function() {
20712    return d3_selectionRoot;
20713  };
20714  var d3_selectionPrototype = d3.selection.prototype = [];
20715  d3_selectionPrototype.select = function(selector) {
20716    var subgroups = [], subgroup, subnode, group, node;
20717    selector = d3_selection_selector(selector);
20718    for (var j = -1, m = this.length; ++j < m; ) {
20719      subgroups.push(subgroup = []);
20720      subgroup.parentNode = (group = this[j]).parentNode;
20721      for (var i = -1, n = group.length; ++i < n; ) {
20722        if (node = group[i]) {
20723          subgroup.push(subnode = selector.call(node, node.__data__, i, j));
20724          if (subnode && "__data__" in node) subnode.__data__ = node.__data__;
20725        } else {
20726          subgroup.push(null);
20727        }
20728      }
20729    }
20730    return d3_selection(subgroups);
20731  };
20732  function d3_selection_selector(selector) {
20733    return typeof selector === "function" ? selector : function() {
20734      return d3_select(selector, this);
20735    };
20736  }
20737  d3_selectionPrototype.selectAll = function(selector) {
20738    var subgroups = [], subgroup, node;
20739    selector = d3_selection_selectorAll(selector);
20740    for (var j = -1, m = this.length; ++j < m; ) {
20741      for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
20742        if (node = group[i]) {
20743          subgroups.push(subgroup = d3_array(selector.call(node, node.__data__, i, j)));
20744          subgroup.parentNode = node;
20745        }
20746      }
20747    }
20748    return d3_selection(subgroups);
20749  };
20750  function d3_selection_selectorAll(selector) {
20751    return typeof selector === "function" ? selector : function() {
20752      return d3_selectAll(selector, this);
20753    };
20754  }
20755  var d3_nsPrefix = {
20756    svg: "http://www.w3.org/2000/svg",
20757    xhtml: "http://www.w3.org/1999/xhtml",
20758    xlink: "http://www.w3.org/1999/xlink",
20759    xml: "http://www.w3.org/XML/1998/namespace",
20760    xmlns: "http://www.w3.org/2000/xmlns/"
20761  };
20762  d3.ns = {
20763    prefix: d3_nsPrefix,
20764    qualify: function(name) {
20765      var i = name.indexOf(":"), prefix = name;
20766      if (i >= 0) {
20767        prefix = name.slice(0, i);
20768        name = name.slice(i + 1);
20769      }
20770      return d3_nsPrefix.hasOwnProperty(prefix) ? {
20771        space: d3_nsPrefix[prefix],
20772        local: name
20773      } : name;
20774    }
20775  };
20776  d3_selectionPrototype.attr = function(name, value) {
20777    if (arguments.length < 2) {
20778      if (typeof name === "string") {
20779        var node = this.node();
20780        name = d3.ns.qualify(name);
20781        return name.local ? node.getAttributeNS(name.space, name.local) : node.getAttribute(name);
20782      }
20783      for (value in name) this.each(d3_selection_attr(value, name[value]));
20784      return this;
20785    }
20786    return this.each(d3_selection_attr(name, value));
20787  };
20788  function d3_selection_attr(name, value) {
20789    name = d3.ns.qualify(name);
20790    function attrNull() {
20791      this.removeAttribute(name);
20792    }
20793    function attrNullNS() {
20794      this.removeAttributeNS(name.space, name.local);
20795    }
20796    function attrConstant() {
20797      this.setAttribute(name, value);
20798    }
20799    function attrConstantNS() {
20800      this.setAttributeNS(name.space, name.local, value);
20801    }
20802    function attrFunction() {
20803      var x = value.apply(this, arguments);
20804      if (x == null) this.removeAttribute(name); else this.setAttribute(name, x);
20805    }
20806    function attrFunctionNS() {
20807      var x = value.apply(this, arguments);
20808      if (x == null) this.removeAttributeNS(name.space, name.local); else this.setAttributeNS(name.space, name.local, x);
20809    }
20810    return value == null ? name.local ? attrNullNS : attrNull : typeof value === "function" ? name.local ? attrFunctionNS : attrFunction : name.local ? attrConstantNS : attrConstant;
20811  }
20812  function d3_collapse(s) {
20813    return s.trim().replace(/\s+/g, " ");
20814  }
20815  d3_selectionPrototype.classed = function(name, value) {
20816    if (arguments.length < 2) {
20817      if (typeof name === "string") {
20818        var node = this.node(), n = (name = d3_selection_classes(name)).length, i = -1;
20819        if (value = node.classList) {
20820          while (++i < n) if (!value.contains(name[i])) return false;
20821        } else {
20822          value = node.getAttribute("class");
20823          while (++i < n) if (!d3_selection_classedRe(name[i]).test(value)) return false;
20824        }
20825        return true;
20826      }
20827      for (value in name) this.each(d3_selection_classed(value, name[value]));
20828      return this;
20829    }
20830    return this.each(d3_selection_classed(name, value));
20831  };
20832  function d3_selection_classedRe(name) {
20833    return new RegExp("(?:^|\\s+)" + d3.requote(name) + "(?:\\s+|$)", "g");
20834  }
20835  function d3_selection_classes(name) {
20836    return (name + "").trim().split(/^|\s+/);
20837  }
20838  function d3_selection_classed(name, value) {
20839    name = d3_selection_classes(name).map(d3_selection_classedName);
20840    var n = name.length;
20841    function classedConstant() {
20842      var i = -1;
20843      while (++i < n) name[i](this, value);
20844    }
20845    function classedFunction() {
20846      var i = -1, x = value.apply(this, arguments);
20847      while (++i < n) name[i](this, x);
20848    }
20849    return typeof value === "function" ? classedFunction : classedConstant;
20850  }
20851  function d3_selection_classedName(name) {
20852    var re = d3_selection_classedRe(name);
20853    return function(node, value) {
20854      if (c = node.classList) return value ? c.add(name) : c.remove(name);
20855      var c = node.getAttribute("class") || "";
20856      if (value) {
20857        re.lastIndex = 0;
20858        if (!re.test(c)) node.setAttribute("class", d3_collapse(c + " " + name));
20859      } else {
20860        node.setAttribute("class", d3_collapse(c.replace(re, " ")));
20861      }
20862    };
20863  }
20864  d3_selectionPrototype.style = function(name, value, priority) {
20865    var n = arguments.length;
20866    if (n < 3) {
20867      if (typeof name !== "string") {
20868        if (n < 2) value = "";
20869        for (priority in name) this.each(d3_selection_style(priority, name[priority], value));
20870        return this;
20871      }
20872      if (n < 2) return d3_window.getComputedStyle(this.node(), null).getPropertyValue(name);
20873      priority = "";
20874    }
20875    return this.each(d3_selection_style(name, value, priority));
20876  };
20877  function d3_selection_style(name, value, priority) {
20878    function styleNull() {
20879      this.style.removeProperty(name);
20880    }
20881    function styleConstant() {
20882      this.style.setProperty(name, value, priority);
20883    }
20884    function styleFunction() {
20885      var x = value.apply(this, arguments);
20886      if (x == null) this.style.removeProperty(name); else this.style.setProperty(name, x, priority);
20887    }
20888    return value == null ? styleNull : typeof value === "function" ? styleFunction : styleConstant;
20889  }
20890  d3_selectionPrototype.property = function(name, value) {
20891    if (arguments.length < 2) {
20892      if (typeof name === "string") return this.node()[name];
20893      for (value in name) this.each(d3_selection_property(value, name[value]));
20894      return this;
20895    }
20896    return this.each(d3_selection_property(name, value));
20897  };
20898  function d3_selection_property(name, value) {
20899    function propertyNull() {
20900      delete this[name];
20901    }
20902    function propertyConstant() {
20903      this[name] = value;
20904    }
20905    function propertyFunction() {
20906      var x = value.apply(this, arguments);
20907      if (x == null) delete this[name]; else this[name] = x;
20908    }
20909    return value == null ? propertyNull : typeof value === "function" ? propertyFunction : propertyConstant;
20910  }
20911  d3_selectionPrototype.text = function(value) {
20912    return arguments.length ? this.each(typeof value === "function" ? function() {
20913      var v = value.apply(this, arguments);
20914      this.textContent = v == null ? "" : v;
20915    } : value == null ? function() {
20916      this.textContent = "";
20917    } : function() {
20918      this.textContent = value;
20919    }) : this.node().textContent;
20920  };
20921  d3_selectionPrototype.html = function(value) {
20922    return arguments.length ? this.each(typeof value === "function" ? function() {
20923      var v = value.apply(this, arguments);
20924      this.innerHTML = v == null ? "" : v;
20925    } : value == null ? function() {
20926      this.innerHTML = "";
20927    } : function() {
20928      this.innerHTML = value;
20929    }) : this.node().innerHTML;
20930  };
20931  d3_selectionPrototype.append = function(name) {
20932    name = d3_selection_creator(name);
20933    return this.select(function() {
20934      return this.appendChild(name.apply(this, arguments));
20935    });
20936  };
20937  function d3_selection_creator(name) {
20938    return typeof name === "function" ? name : (name = d3.ns.qualify(name)).local ? function() {
20939      return this.ownerDocument.createElementNS(name.space, name.local);
20940    } : function() {
20941      return this.ownerDocument.createElementNS(this.namespaceURI, name);
20942    };
20943  }
20944  d3_selectionPrototype.insert = function(name, before) {
20945    name = d3_selection_creator(name);
20946    before = d3_selection_selector(before);
20947    return this.select(function() {
20948      return this.insertBefore(name.apply(this, arguments), before.apply(this, arguments) || null);
20949    });
20950  };
20951  d3_selectionPrototype.remove = function() {
20952    return this.each(function() {
20953      var parent = this.parentNode;
20954      if (parent) parent.removeChild(this);
20955    });
20956  };
20957  d3_selectionPrototype.data = function(value, key) {
20958    var i = -1, n = this.length, group, node;
20959    if (!arguments.length) {
20960      value = new Array(n = (group = this[0]).length);
20961      while (++i < n) {
20962        if (node = group[i]) {
20963          value[i] = node.__data__;
20964        }
20965      }
20966      return value;
20967    }
20968    function bind(group, groupData) {
20969      var i, n = group.length, m = groupData.length, n0 = Math.min(n, m), updateNodes = new Array(m), enterNodes = new Array(m), exitNodes = new Array(n), node, nodeData;
20970      if (key) {
20971        var nodeByKeyValue = new d3_Map(), keyValues = new Array(n), keyValue;
20972        for (i = -1; ++i < n; ) {
20973          if (nodeByKeyValue.has(keyValue = key.call(node = group[i], node.__data__, i))) {
20974            exitNodes[i] = node;
20975          } else {
20976            nodeByKeyValue.set(keyValue, node);
20977          }
20978          keyValues[i] = keyValue;
20979        }
20980        for (i = -1; ++i < m; ) {
20981          if (!(node = nodeByKeyValue.get(keyValue = key.call(groupData, nodeData = groupData[i], i)))) {
20982            enterNodes[i] = d3_selection_dataNode(nodeData);
20983          } else if (node !== true) {
20984            updateNodes[i] = node;
20985            node.__data__ = nodeData;
20986          }
20987          nodeByKeyValue.set(keyValue, true);
20988        }
20989        for (i = -1; ++i < n; ) {
20990          if (nodeByKeyValue.get(keyValues[i]) !== true) {
20991            exitNodes[i] = group[i];
20992          }
20993        }
20994      } else {
20995        for (i = -1; ++i < n0; ) {
20996          node = group[i];
20997          nodeData = groupData[i];
20998          if (node) {
20999            node.__data__ = nodeData;
21000            updateNodes[i] = node;
21001          } else {
21002            enterNodes[i] = d3_selection_dataNode(nodeData);
21003          }
21004        }
21005        for (;i < m; ++i) {
21006          enterNodes[i] = d3_selection_dataNode(groupData[i]);
21007        }
21008        for (;i < n; ++i) {
21009          exitNodes[i] = group[i];
21010        }
21011      }
21012      enterNodes.update = updateNodes;
21013      enterNodes.parentNode = updateNodes.parentNode = exitNodes.parentNode = group.parentNode;
21014      enter.push(enterNodes);
21015      update.push(updateNodes);
21016      exit.push(exitNodes);
21017    }
21018    var enter = d3_selection_enter([]), update = d3_selection([]), exit = d3_selection([]);
21019    if (typeof value === "function") {
21020      while (++i < n) {
21021        bind(group = this[i], value.call(group, group.parentNode.__data__, i));
21022      }
21023    } else {
21024      while (++i < n) {
21025        bind(group = this[i], value);
21026      }
21027    }
21028    update.enter = function() {
21029      return enter;
21030    };
21031    update.exit = function() {
21032      return exit;
21033    };
21034    return update;
21035  };
21036  function d3_selection_dataNode(data) {
21037    return {
21038      __data__: data
21039    };
21040  }
21041  d3_selectionPrototype.datum = function(value) {
21042    return arguments.length ? this.property("__data__", value) : this.property("__data__");
21043  };
21044  d3_selectionPrototype.filter = function(filter) {
21045    var subgroups = [], subgroup, group, node;
21046    if (typeof filter !== "function") filter = d3_selection_filter(filter);
21047    for (var j = 0, m = this.length; j < m; j++) {
21048      subgroups.push(subgroup = []);
21049      subgroup.parentNode = (group = this[j]).parentNode;
21050      for (var i = 0, n = group.length; i < n; i++) {
21051        if ((node = group[i]) && filter.call(node, node.__data__, i, j)) {
21052          subgroup.push(node);
21053        }
21054      }
21055    }
21056    return d3_selection(subgroups);
21057  };
21058  function d3_selection_filter(selector) {
21059    return function() {
21060      return d3_selectMatches(this, selector);
21061    };
21062  }
21063  d3_selectionPrototype.order = function() {
21064    for (var j = -1, m = this.length; ++j < m; ) {
21065      for (var group = this[j], i = group.length - 1, next = group[i], node; --i >= 0; ) {
21066        if (node = group[i]) {
21067          if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next);
21068          next = node;
21069        }
21070      }
21071    }
21072    return this;
21073  };
21074  d3_selectionPrototype.sort = function(comparator) {
21075    comparator = d3_selection_sortComparator.apply(this, arguments);
21076    for (var j = -1, m = this.length; ++j < m; ) this[j].sort(comparator);
21077    return this.order();
21078  };
21079  function d3_selection_sortComparator(comparator) {
21080    if (!arguments.length) comparator = d3_ascending;
21081    return function(a, b) {
21082      return a && b ? comparator(a.__data__, b.__data__) : !a - !b;
21083    };
21084  }
21085  d3_selectionPrototype.each = function(callback) {
21086    return d3_selection_each(this, function(node, i, j) {
21087      callback.call(node, node.__data__, i, j);
21088    });
21089  };
21090  function d3_selection_each(groups, callback) {
21091    for (var j = 0, m = groups.length; j < m; j++) {
21092      for (var group = groups[j], i = 0, n = group.length, node; i < n; i++) {
21093        if (node = group[i]) callback(node, i, j);
21094      }
21095    }
21096    return groups;
21097  }
21098  d3_selectionPrototype.call = function(callback) {
21099    var args = d3_array(arguments);
21100    callback.apply(args[0] = this, args);
21101    return this;
21102  };
21103  d3_selectionPrototype.empty = function() {
21104    return !this.node();
21105  };
21106  d3_selectionPrototype.node = function() {
21107    for (var j = 0, m = this.length; j < m; j++) {
21108      for (var group = this[j], i = 0, n = group.length; i < n; i++) {
21109        var node = group[i];
21110        if (node) return node;
21111      }
21112    }
21113    return null;
21114  };
21115  d3_selectionPrototype.size = function() {
21116    var n = 0;
21117    d3_selection_each(this, function() {
21118      ++n;
21119    });
21120    return n;
21121  };
21122  function d3_selection_enter(selection) {
21123    d3_subclass(selection, d3_selection_enterPrototype);
21124    return selection;
21125  }
21126  var d3_selection_enterPrototype = [];
21127  d3.selection.enter = d3_selection_enter;
21128  d3.selection.enter.prototype = d3_selection_enterPrototype;
21129  d3_selection_enterPrototype.append = d3_selectionPrototype.append;
21130  d3_selection_enterPrototype.empty = d3_selectionPrototype.empty;
21131  d3_selection_enterPrototype.node = d3_selectionPrototype.node;
21132  d3_selection_enterPrototype.call = d3_selectionPrototype.call;
21133  d3_selection_enterPrototype.size = d3_selectionPrototype.size;
21134  d3_selection_enterPrototype.select = function(selector) {
21135    var subgroups = [], subgroup, subnode, upgroup, group, node;
21136    for (var j = -1, m = this.length; ++j < m; ) {
21137      upgroup = (group = this[j]).update;
21138      subgroups.push(subgroup = []);
21139      subgroup.parentNode = group.parentNode;
21140      for (var i = -1, n = group.length; ++i < n; ) {
21141        if (node = group[i]) {
21142          subgroup.push(upgroup[i] = subnode = selector.call(group.parentNode, node.__data__, i, j));
21143          subnode.__data__ = node.__data__;
21144        } else {
21145          subgroup.push(null);
21146        }
21147      }
21148    }
21149    return d3_selection(subgroups);
21150  };
21151  d3_selection_enterPrototype.insert = function(name, before) {
21152    if (arguments.length < 2) before = d3_selection_enterInsertBefore(this);
21153    return d3_selectionPrototype.insert.call(this, name, before);
21154  };
21155  function d3_selection_enterInsertBefore(enter) {
21156    var i0, j0;
21157    return function(d, i, j) {
21158      var group = enter[j].update, n = group.length, node;
21159      if (j != j0) j0 = j, i0 = 0;
21160      if (i >= i0) i0 = i + 1;
21161      while (!(node = group[i0]) && ++i0 < n) ;
21162      return node;
21163    };
21164  }
21165  d3_selectionPrototype.transition = function() {
21166    var id = d3_transitionInheritId || ++d3_transitionId, subgroups = [], subgroup, node, transition = d3_transitionInherit || {
21167      time: Date.now(),
21168      ease: d3_ease_cubicInOut,
21169      delay: 0,
21170      duration: 250
21171    };
21172    for (var j = -1, m = this.length; ++j < m; ) {
21173      subgroups.push(subgroup = []);
21174      for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
21175        if (node = group[i]) d3_transitionNode(node, i, id, transition);
21176        subgroup.push(node);
21177      }
21178    }
21179    return d3_transition(subgroups, id);
21180  };
21181  d3_selectionPrototype.interrupt = function() {
21182    return this.each(d3_selection_interrupt);
21183  };
21184  function d3_selection_interrupt() {
21185    var lock = this.__transition__;
21186    if (lock) ++lock.active;
21187  }
21188  d3.select = function(node) {
21189    var group = [ typeof node === "string" ? d3_select(node, d3_document) : node ];
21190    group.parentNode = d3_documentElement;
21191    return d3_selection([ group ]);
21192  };
21193  d3.selectAll = function(nodes) {
21194    var group = d3_array(typeof nodes === "string" ? d3_selectAll(nodes, d3_document) : nodes);
21195    group.parentNode = d3_documentElement;
21196    return d3_selection([ group ]);
21197  };
21198  var d3_selectionRoot = d3.select(d3_documentElement);
21199  d3_selectionPrototype.on = function(type, listener, capture) {
21200    var n = arguments.length;
21201    if (n < 3) {
21202      if (typeof type !== "string") {
21203        if (n < 2) listener = false;
vendor: 2,326 bytes, lines 21204-21271
21204        for (capture in type) this.each(d3_selection_on(capture, type[capture], listener));
21205        return this;
21206      }
21207      if (n < 2) return (n = this.node()["__on" + type]) && n._;
21208      capture = false;
21209    }
21210    return this.each(d3_selection_on(type, listener, capture));
21211  };
21212  function d3_selection_on(type, listener, capture) {
21213    var name = "__on" + type, i = type.indexOf("."), wrap = d3_selection_onListener;
21214    if (i > 0) type = type.slice(0, i);
21215    var filter = d3_selection_onFilters.get(type);
21216    if (filter) type = filter, wrap = d3_selection_onFilter;
21217    function onRemove() {
21218      var l = this[name];
21219      if (l) {
21220        this.removeEventListener(type, l, l.$);
21221        delete this[name];
21222      }
21223    }
21224    function onAdd() {
21225      var l = wrap(listener, d3_array(arguments));
21226      onRemove.call(this);
21227      this.addEventListener(type, this[name] = l, l.$ = capture);
21228      l._ = listener;
21229    }
21230    function removeAll() {
21231      var re = new RegExp("^__on([^.]+)" + d3.requote(type) + "$"), match;
21232      for (var name in this) {
21233        if (match = name.match(re)) {
21234          var l = this[name];
21235          this.removeEventListener(match[1], l, l.$);
21236          delete this[name];
21237        }
21238      }
21239    }
21240    return i ? listener ? onAdd : onRemove : listener ? d3_noop : removeAll;
21241  }
21242  var d3_selection_onFilters = d3.map({
21243    mouseenter: "mouseover",
21244    mouseleave: "mouseout"
21245  });
21246  d3_selection_onFilters.forEach(function(k) {
21247    if ("on" + k in d3_document) d3_selection_onFilters.remove(k);
21248  });
21249  function d3_selection_onListener(listener, argumentz) {
21250    return function(e) {
21251      var o = d3.event;
21252      d3.event = e;
21253      argumentz[0] = this.__data__;
21254      try {
21255        listener.apply(this, argumentz);
21256      } finally {
21257        d3.event = o;
21258      }
21259    };
21260  }
21261  function d3_selection_onFilter(listener, argumentz) {
21262    var l = d3_selection_onListener(listener, argumentz);
21263    return function(e) {
21264      var target = this, related = e.relatedTarget;
21265      if (!related || related !== target && !(related.compareDocumentPosition(target) & 8)) {
21266        l.call(target, e);
21267      }
21268    };
21269  }
21270  var d3_event_dragSelect = "onselectstart" in d3_document ? null : d3_vendorSymbol(d3_documentElement.style, "userSelect"), d3_event_dragId = 0;
21271  function d3_event_dragSuppress() {
vendor: 23,103 bytes, lines 21272-21873
21272    var name = ".dragsuppress-" + ++d3_event_dragId, click = "click" + name, w = d3.select(d3_window).on("touchmove" + name, d3_eventPreventDefault).on("dragstart" + name, d3_eventPreventDefault).on("selectstart" + name, d3_eventPreventDefault);
21273    if (d3_event_dragSelect) {
21274      var style = d3_documentElement.style, select = style[d3_event_dragSelect];
21275      style[d3_event_dragSelect] = "none";
21276    }
21277    return function(suppressClick) {
21278      w.on(name, null);
21279      if (d3_event_dragSelect) style[d3_event_dragSelect] = select;
21280      if (suppressClick) {
21281        function off() {
21282          w.on(click, null);
21283        }
21284        w.on(click, function() {
21285          d3_eventPreventDefault();
21286          off();
21287        }, true);
21288        setTimeout(off, 0);
21289      }
21290    };
21291  }
21292  d3.mouse = function(container) {
21293    return d3_mousePoint(container, d3_eventSource());
21294  };
21295  var d3_mouse_bug44083 = /WebKit/.test(d3_window.navigator.userAgent) ? -1 : 0;
21296  function d3_mousePoint(container, e) {
21297    if (e.changedTouches) e = e.changedTouches[0];
21298    var svg = container.ownerSVGElement || container;
21299    if (svg.createSVGPoint) {
21300      var point = svg.createSVGPoint();
21301      if (d3_mouse_bug44083 < 0 && (d3_window.scrollX || d3_window.scrollY)) {
21302        svg = d3.select("body").append("svg").style({
21303          position: "absolute",
21304          top: 0,
21305          left: 0,
21306          margin: 0,
21307          padding: 0,
21308          border: "none"
21309        }, "important");
21310        var ctm = svg[0][0].getScreenCTM();
21311        d3_mouse_bug44083 = !(ctm.f || ctm.e);
21312        svg.remove();
21313      }
21314      if (d3_mouse_bug44083) point.x = e.pageX, point.y = e.pageY; else point.x = e.clientX, 
21315      point.y = e.clientY;
21316      point = point.matrixTransform(container.getScreenCTM().inverse());
21317      return [ point.x, point.y ];
21318    }
21319    var rect = container.getBoundingClientRect();
21320    return [ e.clientX - rect.left - container.clientLeft, e.clientY - rect.top - container.clientTop ];
21321  }
21322  d3.touch = function(container, touches, identifier) {
21323    if (arguments.length < 3) identifier = touches, touches = d3_eventSource().changedTouches;
21324    if (touches) for (var i = 0, n = touches.length, touch; i < n; ++i) {
21325      if ((touch = touches[i]).identifier === identifier) {
21326        return d3_mousePoint(container, touch);
21327      }
21328    }
21329  };
21330  d3.behavior.drag = function() {
21331    var event = d3_eventDispatch(drag, "drag", "dragstart", "dragend"), origin = null, mousedown = dragstart(d3_noop, d3.mouse, d3_behavior_dragMouseSubject, "mousemove", "mouseup"), touchstart = dragstart(d3_behavior_dragTouchId, d3.touch, d3_behavior_dragTouchSubject, "touchmove", "touchend");
21332    function drag() {
21333      this.on("mousedown.drag", mousedown).on("touchstart.drag", touchstart);
21334    }
21335    function dragstart(id, position, subject, move, end) {
21336      return function() {
21337        var that = this, target = d3.event.target, parent = that.parentNode, dispatch = event.of(that, arguments), dragged = 0, dragId = id(), dragName = ".drag" + (dragId == null ? "" : "-" + dragId), dragOffset, dragSubject = d3.select(subject()).on(move + dragName, moved).on(end + dragName, ended), dragRestore = d3_event_dragSuppress(), position0 = position(parent, dragId);
21338        if (origin) {
21339          dragOffset = origin.apply(that, arguments);
21340          dragOffset = [ dragOffset.x - position0[0], dragOffset.y - position0[1] ];
21341        } else {
21342          dragOffset = [ 0, 0 ];
21343        }
21344        dispatch({
21345          type: "dragstart"
21346        });
21347        function moved() {
21348          var position1 = position(parent, dragId), dx, dy;
21349          if (!position1) return;
21350          dx = position1[0] - position0[0];
21351          dy = position1[1] - position0[1];
21352          dragged |= dx | dy;
21353          position0 = position1;
21354          dispatch({
21355            type: "drag",
21356            x: position1[0] + dragOffset[0],
21357            y: position1[1] + dragOffset[1],
21358            dx: dx,
21359            dy: dy
21360          });
21361        }
21362        function ended() {
21363          if (!position(parent, dragId)) return;
21364          dragSubject.on(move + dragName, null).on(end + dragName, null);
21365          dragRestore(dragged && d3.event.target === target);
21366          dispatch({
21367            type: "dragend"
21368          });
21369        }
21370      };
21371    }
21372    drag.origin = function(x) {
21373      if (!arguments.length) return origin;
21374      origin = x;
21375      return drag;
21376    };
21377    return d3.rebind(drag, event, "on");
21378  };
21379  function d3_behavior_dragTouchId() {
21380    return d3.event.changedTouches[0].identifier;
21381  }
21382  function d3_behavior_dragTouchSubject() {
21383    return d3.event.target;
21384  }
21385  function d3_behavior_dragMouseSubject() {
21386    return d3_window;
21387  }
21388  d3.touches = function(container, touches) {
21389    if (arguments.length < 2) touches = d3_eventSource().touches;
21390    return touches ? d3_array(touches).map(function(touch) {
21391      var point = d3_mousePoint(container, touch);
21392      point.identifier = touch.identifier;
21393      return point;
21394    }) : [];
21395  };
21396  var π = Math.PI, τ = 2 * π, halfπ = π / 2, ε = 1e-6, ε2 = ε * ε, d3_radians = π / 180, d3_degrees = 180 / π;
21397  function d3_sgn(x) {
21398    return x > 0 ? 1 : x < 0 ? -1 : 0;
21399  }
21400  function d3_cross2d(a, b, c) {
21401    return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]);
21402  }
21403  function d3_acos(x) {
21404    return x > 1 ? 0 : x < -1 ? π : Math.acos(x);
21405  }
21406  function d3_asin(x) {
21407    return x > 1 ? halfπ : x < -1 ? -halfπ : Math.asin(x);
21408  }
21409  function d3_sinh(x) {
21410    return ((x = Math.exp(x)) - 1 / x) / 2;
21411  }
21412  function d3_cosh(x) {
21413    return ((x = Math.exp(x)) + 1 / x) / 2;
21414  }
21415  function d3_tanh(x) {
21416    return ((x = Math.exp(2 * x)) - 1) / (x + 1);
21417  }
21418  function d3_haversin(x) {
21419    return (x = Math.sin(x / 2)) * x;
21420  }
21421  var ρ = Math.SQRT2, ρ2 = 2, ρ4 = 4;
21422  d3.interpolateZoom = function(p0, p1) {
21423    var ux0 = p0[0], uy0 = p0[1], w0 = p0[2], ux1 = p1[0], uy1 = p1[1], w1 = p1[2];
21424    var dx = ux1 - ux0, dy = uy1 - uy0, d2 = dx * dx + dy * dy, d1 = Math.sqrt(d2), b0 = (w1 * w1 - w0 * w0 + ρ4 * d2) / (2 * w0 * ρ2 * d1), b1 = (w1 * w1 - w0 * w0 - ρ4 * d2) / (2 * w1 * ρ2 * d1), r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0), r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1), dr = r1 - r0, S = (dr || Math.log(w1 / w0)) / ρ;
21425    function interpolate(t) {
21426      var s = t * S;
21427      if (dr) {
21428        var coshr0 = d3_cosh(r0), u = w0 / (ρ2 * d1) * (coshr0 * d3_tanh(ρ * s + r0) - d3_sinh(r0));
21429        return [ ux0 + u * dx, uy0 + u * dy, w0 * coshr0 / d3_cosh(ρ * s + r0) ];
21430      }
21431      return [ ux0 + t * dx, uy0 + t * dy, w0 * Math.exp(ρ * s) ];
21432    }
21433    interpolate.duration = S * 1e3;
21434    return interpolate;
21435  };
21436  d3.behavior.zoom = function() {
21437    var view = {
21438      x: 0,
21439      y: 0,
21440      k: 1
21441    }, translate0, center0, center, size = [ 960, 500 ], scaleExtent = d3_behavior_zoomInfinity, mousedown = "mousedown.zoom", mousemove = "mousemove.zoom", mouseup = "mouseup.zoom", mousewheelTimer, touchstart = "touchstart.zoom", touchtime, event = d3_eventDispatch(zoom, "zoomstart", "zoom", "zoomend"), x0, x1, y0, y1;
21442    function zoom(g) {
21443      g.on(mousedown, mousedowned).on(d3_behavior_zoomWheel + ".zoom", mousewheeled).on("dblclick.zoom", dblclicked).on(touchstart, touchstarted);
21444    }
21445    zoom.event = function(g) {
21446      g.each(function() {
21447        var dispatch = event.of(this, arguments), view1 = view;
21448        if (d3_transitionInheritId) {
21449          d3.select(this).transition().each("start.zoom", function() {
21450            view = this.__chart__ || {
21451              x: 0,
21452              y: 0,
21453              k: 1
21454            };
21455            zoomstarted(dispatch);
21456          }).tween("zoom:zoom", function() {
21457            var dx = size[0], dy = size[1], cx = dx / 2, cy = dy / 2, i = d3.interpolateZoom([ (cx - view.x) / view.k, (cy - view.y) / view.k, dx / view.k ], [ (cx - view1.x) / view1.k, (cy - view1.y) / view1.k, dx / view1.k ]);
21458            return function(t) {
21459              var l = i(t), k = dx / l[2];
21460              this.__chart__ = view = {
21461                x: cx - l[0] * k,
21462                y: cy - l[1] * k,
21463                k: k
21464              };
21465              zoomed(dispatch);
21466            };
21467          }).each("end.zoom", function() {
21468            zoomended(dispatch);
21469          });
21470        } else {
21471          this.__chart__ = view;
21472          zoomstarted(dispatch);
21473          zoomed(dispatch);
21474          zoomended(dispatch);
21475        }
21476      });
21477    };
21478    zoom.translate = function(_) {
21479      if (!arguments.length) return [ view.x, view.y ];
21480      view = {
21481        x: +_[0],
21482        y: +_[1],
21483        k: view.k
21484      };
21485      rescale();
21486      return zoom;
21487    };
21488    zoom.scale = function(_) {
21489      if (!arguments.length) return view.k;
21490      view = {
21491        x: view.x,
21492        y: view.y,
21493        k: +_
21494      };
21495      rescale();
21496      return zoom;
21497    };
21498    zoom.scaleExtent = function(_) {
21499      if (!arguments.length) return scaleExtent;
21500      scaleExtent = _ == null ? d3_behavior_zoomInfinity : [ +_[0], +_[1] ];
21501      return zoom;
21502    };
21503    zoom.center = function(_) {
21504      if (!arguments.length) return center;
21505      center = _ && [ +_[0], +_[1] ];
21506      return zoom;
21507    };
21508    zoom.size = function(_) {
21509      if (!arguments.length) return size;
21510      size = _ && [ +_[0], +_[1] ];
21511      return zoom;
21512    };
21513    zoom.x = function(z) {
21514      if (!arguments.length) return x1;
21515      x1 = z;
21516      x0 = z.copy();
21517      view = {
21518        x: 0,
21519        y: 0,
21520        k: 1
21521      };
21522      return zoom;
21523    };
21524    zoom.y = function(z) {
21525      if (!arguments.length) return y1;
21526      y1 = z;
21527      y0 = z.copy();
21528      view = {
21529        x: 0,
21530        y: 0,
21531        k: 1
21532      };
21533      return zoom;
21534    };
21535    function location(p) {
21536      return [ (p[0] - view.x) / view.k, (p[1] - view.y) / view.k ];
21537    }
21538    function point(l) {
21539      return [ l[0] * view.k + view.x, l[1] * view.k + view.y ];
21540    }
21541    function scaleTo(s) {
21542      view.k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], s));
21543    }
21544    function translateTo(p, l) {
21545      l = point(l);
21546      view.x += p[0] - l[0];
21547      view.y += p[1] - l[1];
21548    }
21549    function rescale() {
21550      if (x1) x1.domain(x0.range().map(function(x) {
21551        return (x - view.x) / view.k;
21552      }).map(x0.invert));
21553      if (y1) y1.domain(y0.range().map(function(y) {
21554        return (y - view.y) / view.k;
21555      }).map(y0.invert));
21556    }
21557    function zoomstarted(dispatch) {
21558      dispatch({
21559        type: "zoomstart"
21560      });
21561    }
21562    function zoomed(dispatch) {
21563      rescale();
21564      dispatch({
21565        type: "zoom",
21566        scale: view.k,
21567        translate: [ view.x, view.y ]
21568      });
21569    }
21570    function zoomended(dispatch) {
21571      dispatch({
21572        type: "zoomend"
21573      });
21574    }
21575    function mousedowned() {
21576      var that = this, target = d3.event.target, dispatch = event.of(that, arguments), dragged = 0, subject = d3.select(d3_window).on(mousemove, moved).on(mouseup, ended), location0 = location(d3.mouse(that)), dragRestore = d3_event_dragSuppress();
21577      d3_selection_interrupt.call(that);
21578      zoomstarted(dispatch);
21579      function moved() {
21580        dragged = 1;
21581        translateTo(d3.mouse(that), location0);
21582        zoomed(dispatch);
21583      }
21584      function ended() {
21585        subject.on(mousemove, null).on(mouseup, null);
21586        dragRestore(dragged && d3.event.target === target);
21587        zoomended(dispatch);
21588      }
21589    }
21590    function touchstarted() {
21591      var that = this, dispatch = event.of(that, arguments), locations0 = {}, distance0 = 0, scale0, zoomName = ".zoom-" + d3.event.changedTouches[0].identifier, touchmove = "touchmove" + zoomName, touchend = "touchend" + zoomName, targets = [], subject = d3.select(that), dragRestore = d3_event_dragSuppress();
21592      d3_selection_interrupt.call(that);
21593      started();
21594      zoomstarted(dispatch);
21595      subject.on(mousedown, null).on(touchstart, started);
21596      function relocate() {
21597        var touches = d3.touches(that);
21598        scale0 = view.k;
21599        touches.forEach(function(t) {
21600          if (t.identifier in locations0) locations0[t.identifier] = location(t);
21601        });
21602        return touches;
21603      }
21604      function started() {
21605        var target = d3.event.target;
21606        d3.select(target).on(touchmove, moved).on(touchend, ended);
21607        targets.push(target);
21608        var changed = d3.event.changedTouches;
21609        for (var i = 0, n = changed.length; i < n; ++i) {
21610          locations0[changed[i].identifier] = null;
21611        }
21612        var touches = relocate(), now = Date.now();
21613        if (touches.length === 1) {
21614          if (now - touchtime < 500) {
21615            var p = touches[0], l = locations0[p.identifier];
21616            scaleTo(view.k * 2);
21617            translateTo(p, l);
21618            d3_eventPreventDefault();
21619            zoomed(dispatch);
21620          }
21621          touchtime = now;
21622        } else if (touches.length > 1) {
21623          var p = touches[0], q = touches[1], dx = p[0] - q[0], dy = p[1] - q[1];
21624          distance0 = dx * dx + dy * dy;
21625        }
21626      }
21627      function moved() {
21628        var touches = d3.touches(that), p0, l0, p1, l1;
21629        for (var i = 0, n = touches.length; i < n; ++i, l1 = null) {
21630          p1 = touches[i];
21631          if (l1 = locations0[p1.identifier]) {
21632            if (l0) break;
21633            p0 = p1, l0 = l1;
21634          }
21635        }
21636        if (l1) {
21637          var distance1 = (distance1 = p1[0] - p0[0]) * distance1 + (distance1 = p1[1] - p0[1]) * distance1, scale1 = distance0 && Math.sqrt(distance1 / distance0);
21638          p0 = [ (p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2 ];
21639          l0 = [ (l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2 ];
21640          scaleTo(scale1 * scale0);
21641        }
21642        touchtime = null;
21643        translateTo(p0, l0);
21644        zoomed(dispatch);
21645      }
21646      function ended() {
21647        if (d3.event.touches.length) {
21648          var changed = d3.event.changedTouches;
21649          for (var i = 0, n = changed.length; i < n; ++i) {
21650            delete locations0[changed[i].identifier];
21651          }
21652          for (var identifier in locations0) {
21653            return void relocate();
21654          }
21655        }
21656        d3.selectAll(targets).on(zoomName, null);
21657        subject.on(mousedown, mousedowned).on(touchstart, touchstarted);
21658        dragRestore();
21659        zoomended(dispatch);
21660      }
21661    }
21662    function mousewheeled() {
21663      var dispatch = event.of(this, arguments);
21664      if (mousewheelTimer) clearTimeout(mousewheelTimer); else translate0 = location(center0 = center || d3.mouse(this)), 
21665      d3_selection_interrupt.call(this), zoomstarted(dispatch);
21666      mousewheelTimer = setTimeout(function() {
21667        mousewheelTimer = null;
21668        zoomended(dispatch);
21669      }, 50);
21670      d3_eventPreventDefault();
21671      scaleTo(Math.pow(2, d3_behavior_zoomDelta() * .002) * view.k);
21672      translateTo(center0, translate0);
21673      zoomed(dispatch);
21674    }
21675    function dblclicked() {
21676      var dispatch = event.of(this, arguments), p = d3.mouse(this), l = location(p), k = Math.log(view.k) / Math.LN2;
21677      zoomstarted(dispatch);
21678      scaleTo(Math.pow(2, d3.event.shiftKey ? Math.ceil(k) - 1 : Math.floor(k) + 1));
21679      translateTo(p, l);
21680      zoomed(dispatch);
21681      zoomended(dispatch);
21682    }
21683    return d3.rebind(zoom, event, "on");
21684  };
21685  var d3_behavior_zoomInfinity = [ 0, Infinity ];
21686  var d3_behavior_zoomDelta, d3_behavior_zoomWheel = "onwheel" in d3_document ? (d3_behavior_zoomDelta = function() {
21687    return -d3.event.deltaY * (d3.event.deltaMode ? 120 : 1);
21688  }, "wheel") : "onmousewheel" in d3_document ? (d3_behavior_zoomDelta = function() {
21689    return d3.event.wheelDelta;
21690  }, "mousewheel") : (d3_behavior_zoomDelta = function() {
21691    return -d3.event.detail;
21692  }, "MozMousePixelScroll");
21693  d3.color = d3_color;
21694  function d3_color() {}
21695  d3_color.prototype.toString = function() {
21696    return this.rgb() + "";
21697  };
21698  d3.hsl = d3_hsl;
21699  function d3_hsl(h, s, l) {
21700    return this instanceof d3_hsl ? void (this.h = +h, this.s = +s, this.l = +l) : arguments.length < 2 ? h instanceof d3_hsl ? new d3_hsl(h.h, h.s, h.l) : d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl) : new d3_hsl(h, s, l);
21701  }
21702  var d3_hslPrototype = d3_hsl.prototype = new d3_color();
21703  d3_hslPrototype.brighter = function(k) {
21704    k = Math.pow(.7, arguments.length ? k : 1);
21705    return new d3_hsl(this.h, this.s, this.l / k);
21706  };
21707  d3_hslPrototype.darker = function(k) {
21708    k = Math.pow(.7, arguments.length ? k : 1);
21709    return new d3_hsl(this.h, this.s, k * this.l);
21710  };
21711  d3_hslPrototype.rgb = function() {
21712    return d3_hsl_rgb(this.h, this.s, this.l);
21713  };
21714  function d3_hsl_rgb(h, s, l) {
21715    var m1, m2;
21716    h = isNaN(h) ? 0 : (h %= 360) < 0 ? h + 360 : h;
21717    s = isNaN(s) ? 0 : s < 0 ? 0 : s > 1 ? 1 : s;
21718    l = l < 0 ? 0 : l > 1 ? 1 : l;
21719    m2 = l <= .5 ? l * (1 + s) : l + s - l * s;
21720    m1 = 2 * l - m2;
21721    function v(h) {
21722      if (h > 360) h -= 360; else if (h < 0) h += 360;
21723      if (h < 60) return m1 + (m2 - m1) * h / 60;
21724      if (h < 180) return m2;
21725      if (h < 240) return m1 + (m2 - m1) * (240 - h) / 60;
21726      return m1;
21727    }
21728    function vv(h) {
21729      return Math.round(v(h) * 255);
21730    }
21731    return new d3_rgb(vv(h + 120), vv(h), vv(h - 120));
21732  }
21733  d3.hcl = d3_hcl;
21734  function d3_hcl(h, c, l) {
21735    return this instanceof d3_hcl ? void (this.h = +h, this.c = +c, this.l = +l) : arguments.length < 2 ? h instanceof d3_hcl ? new d3_hcl(h.h, h.c, h.l) : h instanceof d3_lab ? d3_lab_hcl(h.l, h.a, h.b) : d3_lab_hcl((h = d3_rgb_lab((h = d3.rgb(h)).r, h.g, h.b)).l, h.a, h.b) : new d3_hcl(h, c, l);
21736  }
21737  var d3_hclPrototype = d3_hcl.prototype = new d3_color();
21738  d3_hclPrototype.brighter = function(k) {
21739    return new d3_hcl(this.h, this.c, Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)));
21740  };
21741  d3_hclPrototype.darker = function(k) {
21742    return new d3_hcl(this.h, this.c, Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)));
21743  };
21744  d3_hclPrototype.rgb = function() {
21745    return d3_hcl_lab(this.h, this.c, this.l).rgb();
21746  };
21747  function d3_hcl_lab(h, c, l) {
21748    if (isNaN(h)) h = 0;
21749    if (isNaN(c)) c = 0;
21750    return new d3_lab(l, Math.cos(h *= d3_radians) * c, Math.sin(h) * c);
21751  }
21752  d3.lab = d3_lab;
21753  function d3_lab(l, a, b) {
21754    return this instanceof d3_lab ? void (this.l = +l, this.a = +a, this.b = +b) : arguments.length < 2 ? l instanceof d3_lab ? new d3_lab(l.l, l.a, l.b) : l instanceof d3_hcl ? d3_hcl_lab(l.h, l.c, l.l) : d3_rgb_lab((l = d3_rgb(l)).r, l.g, l.b) : new d3_lab(l, a, b);
21755  }
21756  var d3_lab_K = 18;
21757  var d3_lab_X = .95047, d3_lab_Y = 1, d3_lab_Z = 1.08883;
21758  var d3_labPrototype = d3_lab.prototype = new d3_color();
21759  d3_labPrototype.brighter = function(k) {
21760    return new d3_lab(Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)), this.a, this.b);
21761  };
21762  d3_labPrototype.darker = function(k) {
21763    return new d3_lab(Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)), this.a, this.b);
21764  };
21765  d3_labPrototype.rgb = function() {
21766    return d3_lab_rgb(this.l, this.a, this.b);
21767  };
21768  function d3_lab_rgb(l, a, b) {
21769    var y = (l + 16) / 116, x = y + a / 500, z = y - b / 200;
21770    x = d3_lab_xyz(x) * d3_lab_X;
21771    y = d3_lab_xyz(y) * d3_lab_Y;
21772    z = d3_lab_xyz(z) * d3_lab_Z;
21773    return new d3_rgb(d3_xyz_rgb(3.2404542 * x - 1.5371385 * y - .4985314 * z), d3_xyz_rgb(-.969266 * x + 1.8760108 * y + .041556 * z), d3_xyz_rgb(.0556434 * x - .2040259 * y + 1.0572252 * z));
21774  }
21775  function d3_lab_hcl(l, a, b) {
21776    return l > 0 ? new d3_hcl(Math.atan2(b, a) * d3_degrees, Math.sqrt(a * a + b * b), l) : new d3_hcl(NaN, NaN, l);
21777  }
21778  function d3_lab_xyz(x) {
21779    return x > .206893034 ? x * x * x : (x - 4 / 29) / 7.787037;
21780  }
21781  function d3_xyz_lab(x) {
21782    return x > .008856 ? Math.pow(x, 1 / 3) : 7.787037 * x + 4 / 29;
21783  }
21784  function d3_xyz_rgb(r) {
21785    return Math.round(255 * (r <= .00304 ? 12.92 * r : 1.055 * Math.pow(r, 1 / 2.4) - .055));
21786  }
21787  d3.rgb = d3_rgb;
21788  function d3_rgb(r, g, b) {
21789    return this instanceof d3_rgb ? void (this.r = ~~r, this.g = ~~g, this.b = ~~b) : arguments.length < 2 ? r instanceof d3_rgb ? new d3_rgb(r.r, r.g, r.b) : d3_rgb_parse("" + r, d3_rgb, d3_hsl_rgb) : new d3_rgb(r, g, b);
21790  }
21791  function d3_rgbNumber(value) {
21792    return new d3_rgb(value >> 16, value >> 8 & 255, value & 255);
21793  }
21794  function d3_rgbString(value) {
21795    return d3_rgbNumber(value) + "";
21796  }
21797  var d3_rgbPrototype = d3_rgb.prototype = new d3_color();
21798  d3_rgbPrototype.brighter = function(k) {
21799    k = Math.pow(.7, arguments.length ? k : 1);
21800    var r = this.r, g = this.g, b = this.b, i = 30;
21801    if (!r && !g && !b) return new d3_rgb(i, i, i);
21802    if (r && r < i) r = i;
21803    if (g && g < i) g = i;
21804    if (b && b < i) b = i;
21805    return new d3_rgb(Math.min(255, r / k), Math.min(255, g / k), Math.min(255, b / k));
21806  };
21807  d3_rgbPrototype.darker = function(k) {
21808    k = Math.pow(.7, arguments.length ? k : 1);
21809    return new d3_rgb(k * this.r, k * this.g, k * this.b);
21810  };
21811  d3_rgbPrototype.hsl = function() {
21812    return d3_rgb_hsl(this.r, this.g, this.b);
21813  };
21814  d3_rgbPrototype.toString = function() {
21815    return "#" + d3_rgb_hex(this.r) + d3_rgb_hex(this.g) + d3_rgb_hex(this.b);
21816  };
21817  function d3_rgb_hex(v) {
21818    return v < 16 ? "0" + Math.max(0, v).toString(16) : Math.min(255, v).toString(16);
21819  }
21820  function d3_rgb_parse(format, rgb, hsl) {
21821    var r = 0, g = 0, b = 0, m1, m2, color;
21822    m1 = /([a-z]+)\((.*)\)/i.exec(format);
21823    if (m1) {
21824      m2 = m1[2].split(",");
21825      switch (m1[1]) {
21826       case "hsl":
21827        {
21828          return hsl(parseFloat(m2[0]), parseFloat(m2[1]) / 100, parseFloat(m2[2]) / 100);
21829        }
21830
21831       case "rgb":
21832        {
21833          return rgb(d3_rgb_parseNumber(m2[0]), d3_rgb_parseNumber(m2[1]), d3_rgb_parseNumber(m2[2]));
21834        }
21835      }
21836    }
21837    if (color = d3_rgb_names.get(format)) return rgb(color.r, color.g, color.b);
21838    if (format != null && format.charAt(0) === "#" && !isNaN(color = parseInt(format.slice(1), 16))) {
21839      if (format.length === 4) {
21840        r = (color & 3840) >> 4;
21841        r = r >> 4 | r;
21842        g = color & 240;
21843        g = g >> 4 | g;
21844        b = color & 15;
21845        b = b << 4 | b;
21846      } else if (format.length === 7) {
21847        r = (color & 16711680) >> 16;
21848        g = (color & 65280) >> 8;
21849        b = color & 255;
21850      }
21851    }
21852    return rgb(r, g, b);
21853  }
21854  function d3_rgb_hsl(r, g, b) {
21855    var min = Math.min(r /= 255, g /= 255, b /= 255), max = Math.max(r, g, b), d = max - min, h, s, l = (max + min) / 2;
21856    if (d) {
21857      s = l < .5 ? d / (max + min) : d / (2 - max - min);
21858      if (r == max) h = (g - b) / d + (g < b ? 6 : 0); else if (g == max) h = (b - r) / d + 2; else h = (r - g) / d + 4;
21859      h *= 60;
21860    } else {
21861      h = NaN;
21862      s = l > 0 && l < 1 ? 0 : h;
21863    }
21864    return new d3_hsl(h, s, l);
21865  }
21866  function d3_rgb_lab(r, g, b) {
21867    r = d3_rgb_xyz(r);
21868    g = d3_rgb_xyz(g);
21869    b = d3_rgb_xyz(b);
21870    var x = d3_xyz_lab((.4124564 * r + .3575761 * g + .1804375 * b) / d3_lab_X), y = d3_xyz_lab((.2126729 * r + .7151522 * g + .072175 * b) / d3_lab_Y), z = d3_xyz_lab((.0193339 * r + .119192 * g + .9503041 * b) / d3_lab_Z);
21871    return d3_lab(116 * y - 16, 500 * (x - y), 200 * (y - z));
21872  }
21873  function d3_rgb_xyz(r) {
vendor: 5,418 bytes, lines 21874-22071
21874    return (r /= 255) <= .04045 ? r / 12.92 : Math.pow((r + .055) / 1.055, 2.4);
21875  }
21876  function d3_rgb_parseNumber(c) {
21877    var f = parseFloat(c);
21878    return c.charAt(c.length - 1) === "%" ? Math.round(f * 2.55) : f;
21879  }
21880  var d3_rgb_names = d3.map({
21881    aliceblue: 15792383,
21882    antiquewhite: 16444375,
21883    aqua: 65535,
21884    aquamarine: 8388564,
21885    azure: 15794175,
21886    beige: 16119260,
21887    bisque: 16770244,
21888    black: 0,
21889    blanchedalmond: 16772045,
21890    blue: 255,
21891    blueviolet: 9055202,
21892    brown: 10824234,
21893    burlywood: 14596231,
21894    cadetblue: 6266528,
21895    chartreuse: 8388352,
21896    chocolate: 13789470,
21897    coral: 16744272,
21898    cornflowerblue: 6591981,
21899    cornsilk: 16775388,
21900    crimson: 14423100,
21901    cyan: 65535,
21902    darkblue: 139,
21903    darkcyan: 35723,
21904    darkgoldenrod: 12092939,
21905    darkgray: 11119017,
21906    darkgreen: 25600,
21907    darkgrey: 11119017,
21908    darkkhaki: 12433259,
21909    darkmagenta: 9109643,
21910    darkolivegreen: 5597999,
21911    darkorange: 16747520,
21912    darkorchid: 10040012,
21913    darkred: 9109504,
21914    darksalmon: 15308410,
21915    darkseagreen: 9419919,
21916    darkslateblue: 4734347,
21917    darkslategray: 3100495,
21918    darkslategrey: 3100495,
21919    darkturquoise: 52945,
21920    darkviolet: 9699539,
21921    deeppink: 16716947,
21922    deepskyblue: 49151,
21923    dimgray: 6908265,
21924    dimgrey: 6908265,
21925    dodgerblue: 2003199,
21926    firebrick: 11674146,
21927    floralwhite: 16775920,
21928    forestgreen: 2263842,
21929    fuchsia: 16711935,
21930    gainsboro: 14474460,
21931    ghostwhite: 16316671,
21932    gold: 16766720,
21933    goldenrod: 14329120,
21934    gray: 8421504,
21935    green: 32768,
21936    greenyellow: 11403055,
21937    grey: 8421504,
21938    honeydew: 15794160,
21939    hotpink: 16738740,
21940    indianred: 13458524,
21941    indigo: 4915330,
21942    ivory: 16777200,
21943    khaki: 15787660,
21944    lavender: 15132410,
21945    lavenderblush: 16773365,
21946    lawngreen: 8190976,
21947    lemonchiffon: 16775885,
21948    lightblue: 11393254,
21949    lightcoral: 15761536,
21950    lightcyan: 14745599,
21951    lightgoldenrodyellow: 16448210,
21952    lightgray: 13882323,
21953    lightgreen: 9498256,
21954    lightgrey: 13882323,
21955    lightpink: 16758465,
21956    lightsalmon: 16752762,
21957    lightseagreen: 2142890,
21958    lightskyblue: 8900346,
21959    lightslategray: 7833753,
21960    lightslategrey: 7833753,
21961    lightsteelblue: 11584734,
21962    lightyellow: 16777184,
21963    lime: 65280,
21964    limegreen: 3329330,
21965    linen: 16445670,
21966    magenta: 16711935,
21967    maroon: 8388608,
21968    mediumaquamarine: 6737322,
21969    mediumblue: 205,
21970    mediumorchid: 12211667,
21971    mediumpurple: 9662683,
21972    mediumseagreen: 3978097,
21973    mediumslateblue: 8087790,
21974    mediumspringgreen: 64154,
21975    mediumturquoise: 4772300,
21976    mediumvioletred: 13047173,
21977    midnightblue: 1644912,
21978    mintcream: 16121850,
21979    mistyrose: 16770273,
21980    moccasin: 16770229,
21981    navajowhite: 16768685,
21982    navy: 128,
21983    oldlace: 16643558,
21984    olive: 8421376,
21985    olivedrab: 7048739,
21986    orange: 16753920,
21987    orangered: 16729344,
21988    orchid: 14315734,
21989    palegoldenrod: 15657130,
21990    palegreen: 10025880,
21991    paleturquoise: 11529966,
21992    palevioletred: 14381203,
21993    papayawhip: 16773077,
21994    peachpuff: 16767673,
21995    peru: 13468991,
21996    pink: 16761035,
21997    plum: 14524637,
21998    powderblue: 11591910,
21999    purple: 8388736,
22000    red: 16711680,
22001    rosybrown: 12357519,
22002    royalblue: 4286945,
22003    saddlebrown: 9127187,
22004    salmon: 16416882,
22005    sandybrown: 16032864,
22006    seagreen: 3050327,
22007    seashell: 16774638,
22008    sienna: 10506797,
22009    silver: 12632256,
22010    skyblue: 8900331,
22011    slateblue: 6970061,
22012    slategray: 7372944,
22013    slategrey: 7372944,
22014    snow: 16775930,
22015    springgreen: 65407,
22016    steelblue: 4620980,
22017    tan: 13808780,
22018    teal: 32896,
22019    thistle: 14204888,
22020    tomato: 16737095,
22021    turquoise: 4251856,
22022    violet: 15631086,
22023    wheat: 16113331,
22024    white: 16777215,
22025    whitesmoke: 16119285,
22026    yellow: 16776960,
22027    yellowgreen: 10145074
22028  });
22029  d3_rgb_names.forEach(function(key, value) {
22030    d3_rgb_names.set(key, d3_rgbNumber(value));
22031  });
22032  function d3_functor(v) {
22033    return typeof v === "function" ? v : function() {
22034      return v;
22035    };
22036  }
22037  d3.functor = d3_functor;
22038  function d3_identity(d) {
22039    return d;
22040  }
22041  d3.xhr = d3_xhrType(d3_identity);
22042  function d3_xhrType(response) {
22043    return function(url, mimeType, callback) {
22044      if (arguments.length === 2 && typeof mimeType === "function") callback = mimeType, 
22045      mimeType = null;
22046      return d3_xhr(url, mimeType, response, callback);
22047    };
22048  }
22049  function d3_xhr(url, mimeType, response, callback) {
22050    var xhr = {}, dispatch = d3.dispatch("beforesend", "progress", "load", "error"), headers = {}, request = new XMLHttpRequest(), responseType = null;
22051    if (d3_window.XDomainRequest && !("withCredentials" in request) && /^(http(s)?:)?\/\//.test(url)) request = new XDomainRequest();
22052    "onload" in request ? request.onload = request.onerror = respond : request.onreadystatechange = function() {
22053      request.readyState > 3 && respond();
22054    };
22055    function respond() {
22056      var status = request.status, result;
22057      if (!status && d3_xhrHasResponse(request) || status >= 200 && status < 300 || status === 304) {
22058        try {
22059          result = response.call(xhr, request);
22060        } catch (e) {
22061          dispatch.error.call(xhr, e);
22062          return;
22063        }
22064        dispatch.load.call(xhr, result);
22065      } else {
22066        dispatch.error.call(xhr, request);
22067      }
22068    }
22069    request.onprogress = function(event) {
22070      var o = d3.event;
22071      d3.event = event;
vendor: 6,502 bytes, lines 22072-22258
22072      try {
22073        dispatch.progress.call(xhr, request);
22074      } finally {
22075        d3.event = o;
22076      }
22077    };
22078    xhr.header = function(name, value) {
22079      name = (name + "").toLowerCase();
22080      if (arguments.length < 2) return headers[name];
22081      if (value == null) delete headers[name]; else headers[name] = value + "";
22082      return xhr;
22083    };
22084    xhr.mimeType = function(value) {
22085      if (!arguments.length) return mimeType;
22086      mimeType = value == null ? null : value + "";
22087      return xhr;
22088    };
22089    xhr.responseType = function(value) {
22090      if (!arguments.length) return responseType;
22091      responseType = value;
22092      return xhr;
22093    };
22094    xhr.response = function(value) {
22095      response = value;
22096      return xhr;
22097    };
22098    [ "get", "post" ].forEach(function(method) {
22099      xhr[method] = function() {
22100        return xhr.send.apply(xhr, [ method ].concat(d3_array(arguments)));
22101      };
22102    });
22103    xhr.send = function(method, data, callback) {
22104      if (arguments.length === 2 && typeof data === "function") callback = data, data = null;
22105      request.open(method, url, true);
22106      if (mimeType != null && !("accept" in headers)) headers["accept"] = mimeType + ",*/*";
22107      if (request.setRequestHeader) for (var name in headers) request.setRequestHeader(name, headers[name]);
22108      if (mimeType != null && request.overrideMimeType) request.overrideMimeType(mimeType);
22109      if (responseType != null) request.responseType = responseType;
22110      if (callback != null) xhr.on("error", callback).on("load", function(request) {
22111        callback(null, request);
22112      });
22113      dispatch.beforesend.call(xhr, request);
22114      request.send(data == null ? null : data);
22115      return xhr;
22116    };
22117    xhr.abort = function() {
22118      request.abort();
22119      return xhr;
22120    };
22121    d3.rebind(xhr, dispatch, "on");
22122    return callback == null ? xhr : xhr.get(d3_xhr_fixCallback(callback));
22123  }
22124  function d3_xhr_fixCallback(callback) {
22125    return callback.length === 1 ? function(error, request) {
22126      callback(error == null ? request : null);
22127    } : callback;
22128  }
22129  function d3_xhrHasResponse(request) {
22130    var type = request.responseType;
22131    return type && type !== "text" ? request.response : request.responseText;
22132  }
22133  d3.dsv = function(delimiter, mimeType) {
22134    var reFormat = new RegExp('["' + delimiter + "\n]"), delimiterCode = delimiter.charCodeAt(0);
22135    function dsv(url, row, callback) {
22136      if (arguments.length < 3) callback = row, row = null;
22137      var xhr = d3_xhr(url, mimeType, row == null ? response : typedResponse(row), callback);
22138      xhr.row = function(_) {
22139        return arguments.length ? xhr.response((row = _) == null ? response : typedResponse(_)) : row;
22140      };
22141      return xhr;
22142    }
22143    function response(request) {
22144      return dsv.parse(request.responseText);
22145    }
22146    function typedResponse(f) {
22147      return function(request) {
22148        return dsv.parse(request.responseText, f);
22149      };
22150    }
22151    dsv.parse = function(text, f) {
22152      var o;
22153      return dsv.parseRows(text, function(row, i) {
22154        if (o) return o(row, i - 1);
22155        var a = new Function("d", "return {" + row.map(function(name, i) {
22156          return JSON.stringify(name) + ": d[" + i + "]";
22157        }).join(",") + "}");
22158        o = f ? function(row, i) {
22159          return f(a(row), i);
22160        } : a;
22161      });
22162    };
22163    dsv.parseRows = function(text, f) {
22164      var EOL = {}, EOF = {}, rows = [], N = text.length, I = 0, n = 0, t, eol;
22165      function token() {
22166        if (I >= N) return EOF;
22167        if (eol) return eol = false, EOL;
22168        var j = I;
22169        if (text.charCodeAt(j) === 34) {
22170          var i = j;
22171          while (i++ < N) {
22172            if (text.charCodeAt(i) === 34) {
22173              if (text.charCodeAt(i + 1) !== 34) break;
22174              ++i;
22175            }
22176          }
22177          I = i + 2;
22178          var c = text.charCodeAt(i + 1);
22179          if (c === 13) {
22180            eol = true;
22181            if (text.charCodeAt(i + 2) === 10) ++I;
22182          } else if (c === 10) {
22183            eol = true;
22184          }
22185          return text.slice(j + 1, i).replace(/""/g, '"');
22186        }
22187        while (I < N) {
22188          var c = text.charCodeAt(I++), k = 1;
22189          if (c === 10) eol = true; else if (c === 13) {
22190            eol = true;
22191            if (text.charCodeAt(I) === 10) ++I, ++k;
22192          } else if (c !== delimiterCode) continue;
22193          return text.slice(j, I - k);
22194        }
22195        return text.slice(j);
22196      }
22197      while ((t = token()) !== EOF) {
22198        var a = [];
22199        while (t !== EOL && t !== EOF) {
22200          a.push(t);
22201          t = token();
22202        }
22203        if (f && (a = f(a, n++)) == null) continue;
22204        rows.push(a);
22205      }
22206      return rows;
22207    };
22208    dsv.format = function(rows) {
22209      if (Array.isArray(rows[0])) return dsv.formatRows(rows);
22210      var fieldSet = new d3_Set(), fields = [];
22211      rows.forEach(function(row) {
22212        for (var field in row) {
22213          if (!fieldSet.has(field)) {
22214            fields.push(fieldSet.add(field));
22215          }
22216        }
22217      });
22218      return [ fields.map(formatValue).join(delimiter) ].concat(rows.map(function(row) {
22219        return fields.map(function(field) {
22220          return formatValue(row[field]);
22221        }).join(delimiter);
22222      })).join("\n");
22223    };
22224    dsv.formatRows = function(rows) {
22225      return rows.map(formatRow).join("\n");
22226    };
22227    function formatRow(row) {
22228      return row.map(formatValue).join(delimiter);
22229    }
22230    function formatValue(text) {
22231      return reFormat.test(text) ? '"' + text.replace(/\"/g, '""') + '"' : text;
22232    }
22233    return dsv;
22234  };
22235  d3.csv = d3.dsv(",", "text/csv");
22236  d3.tsv = d3.dsv("	", "text/tab-separated-values");
22237  var d3_timer_queueHead, d3_timer_queueTail, d3_timer_interval, d3_timer_timeout, d3_timer_active, d3_timer_frame = d3_window[d3_vendorSymbol(d3_window, "requestAnimationFrame")] || function(callback) {
22238    setTimeout(callback, 17);
22239  };
22240  d3.timer = function(callback, delay, then) {
22241    var n = arguments.length;
22242    if (n < 2) delay = 0;
22243    if (n < 3) then = Date.now();
22244    var time = then + delay, timer = {
22245      c: callback,
22246      t: time,
22247      f: false,
22248      n: null
22249    };
22250    if (d3_timer_queueTail) d3_timer_queueTail.n = timer; else d3_timer_queueHead = timer;
22251    d3_timer_queueTail = timer;
22252    if (!d3_timer_interval) {
22253      d3_timer_timeout = clearTimeout(d3_timer_timeout);
22254      d3_timer_interval = 1;
22255      d3_timer_frame(d3_timer_step);
22256    }
22257  };
22258  function d3_timer_step() {
22259    var now = d3_timer_mark(), delay = d3_timer_sweep() - now;
22260    if (delay > 24) {
22261      if (isFinite(delay)) {
22262        clearTimeout(d3_timer_timeout);
22263        d3_timer_timeout = setTimeout(d3_timer_step, delay);
22264      }
22265      d3_timer_interval = 0;
22266    } else {
22267      d3_timer_interval = 1;
22268      d3_timer_frame(d3_timer_step);
22269    }
22270  }
22271  d3.timer.flush = function() {
22272    d3_timer_mark();
22273    d3_timer_sweep();
22274  };
22275  function d3_timer_mark() {
22276    var now = Date.now();
22277    d3_timer_active = d3_timer_queueHead;
22278    while (d3_timer_active) {
22279      if (now >= d3_timer_active.t) d3_timer_active.f = d3_timer_active.c(now - d3_timer_active.t);
22280      d3_timer_active = d3_timer_active.n;
22281    }
22282    return now;
22283  }
22284  function d3_timer_sweep() {
22285    var t0, t1 = d3_timer_queueHead, time = Infinity;
22286    while (t1) {
22287      if (t1.f) {
22288        t1 = t0 ? t0.n = t1.n : d3_timer_queueHead = t1.n;
22289      } else {
22290        if (t1.t < time) time = t1.t;
22291        t1 = (t0 = t1).n;
22292      }
22293    }
22294    d3_timer_queueTail = t0;
22295    return time;
22296  }
22297  function d3_format_precision(x, p) {
22298    return p - (x ? Math.ceil(Math.log(x) / Math.LN10) : 1);
22299  }
22300  d3.round = function(x, n) {
22301    return n ? Math.round(x * (n = Math.pow(10, n))) / n : Math.round(x);
22302  };
22303  var d3_formatPrefixes = [ "y", "z", "a", "f", "p", "n", "µ", "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y" ].map(d3_formatPrefix);
22304  d3.formatPrefix = function(value, precision) {
22305    var i = 0;
22306    if (value) {
22307      if (value < 0) value *= -1;
22308      if (precision) value = d3.round(value, d3_format_precision(value, precision));
22309      i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10);
22310      i = Math.max(-24, Math.min(24, Math.floor((i - 1) / 3) * 3));
22311    }
22312    return d3_formatPrefixes[8 + i / 3];
22313  };
22314  function d3_formatPrefix(d, i) {
22315    var k = Math.pow(10, abs(8 - i) * 3);
22316    return {
22317      scale: i > 8 ? function(d) {
22318        return d / k;
22319      } : function(d) {
22320        return d * k;
22321      },
22322      symbol: d
22323    };
22324  }
22325  function d3_locale_numberFormat(locale) {
22326    var locale_decimal = locale.decimal, locale_thousands = locale.thousands, locale_grouping = locale.grouping, locale_currency = locale.currency, formatGroup = locale_grouping && locale_thousands ? function(value, width) {
22327      var i = value.length, t = [], j = 0, g = locale_grouping[0], length = 0;
22328      while (i > 0 && g > 0) {
22329        if (length + g + 1 > width) g = Math.max(1, width - length);
22330        t.push(value.substring(i -= g, i + g));
22331        if ((length += g + 1) > width) break;
22332        g = locale_grouping[j = (j + 1) % locale_grouping.length];
22333      }
22334      return t.reverse().join(locale_thousands);
22335    } : d3_identity;
22336    return function(specifier) {
22337      var match = d3_format_re.exec(specifier), fill = match[1] || " ", align = match[2] || ">", sign = match[3] || "-", symbol = match[4] || "", zfill = match[5], width = +match[6], comma = match[7], precision = match[8], type = match[9], scale = 1, prefix = "", suffix = "", integer = false, exponent = true;
22338      if (precision) precision = +precision.substring(1);
22339      if (zfill || fill === "0" && align === "=") {
22340        zfill = fill = "0";
22341        align = "=";
22342      }
22343      switch (type) {
22344       case "n":
22345        comma = true;
22346        type = "g";
22347        break;
22348
22349       case "%":
22350        scale = 100;
22351        suffix = "%";
22352        type = "f";
22353        break;
22354
22355       case "p":
22356        scale = 100;
22357        suffix = "%";
22358        type = "r";
22359        break;
22360
22361       case "b":
22362       case "o":
22363       case "x":
22364       case "X":
22365        if (symbol === "#") prefix = "0" + type.toLowerCase();
22366
22367       case "c":
22368        exponent = false;
22369
22370       case "d":
22371        integer = true;
22372        precision = 0;
22373        break;
22374
22375       case "s":
22376        scale = -1;
22377        type = "r";
22378        break;
22379      }
22380      if (symbol === "$") prefix = locale_currency[0], suffix = locale_currency[1];
22381      if (type == "r" && !precision) type = "g";
22382      if (precision != null) {
22383        if (type == "g") precision = Math.max(1, Math.min(21, precision)); else if (type == "e" || type == "f") precision = Math.max(0, Math.min(20, precision));
22384      }
22385      type = d3_format_types.get(type) || d3_format_typeDefault;
22386      var zcomma = zfill && comma;
22387      return function(value) {
22388        var fullSuffix = suffix;
22389        if (integer && value % 1) return "";
22390        var negative = value < 0 || value === 0 && 1 / value < 0 ? (value = -value, "-") : sign === "-" ? "" : sign;
22391        if (scale < 0) {
22392          var unit = d3.formatPrefix(value, precision);
22393          value = unit.scale(value);
22394          fullSuffix = unit.symbol + suffix;
22395        } else {
22396          value *= scale;
22397        }
22398        value = type(value, precision);
22399        var i = value.lastIndexOf("."), before, after;
22400        if (i < 0) {
22401          var j = exponent ? value.lastIndexOf("e") : -1;
22402          if (j < 0) before = value, after = ""; else before = value.substring(0, j), after = value.substring(j);
22403        } else {
22404          before = value.substring(0, i);
22405          after = locale_decimal + value.substring(i + 1);
22406        }
22407        if (!zfill && comma) before = formatGroup(before, Infinity);
22408        var length = prefix.length + before.length + after.length + (zcomma ? 0 : negative.length), padding = length < width ? new Array(length = width - length + 1).join(fill) : "";
22409        if (zcomma) before = formatGroup(padding + before, padding.length ? width - after.length : Infinity);
22410        negative += prefix;
22411        value = before + after;
22412        return (align === "<" ? negative + value + padding : align === ">" ? padding + negative + value : align === "^" ? padding.substring(0, length >>= 1) + negative + value + padding.substring(length) : negative + (zcomma ? value : padding + value)) + fullSuffix;
22413      };
22414    };
22415  }
22416  var d3_format_re = /(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i;
22417  var d3_format_types = d3.map({
22418    b: function(x) {
22419      return x.toString(2);
22420    },
22421    c: function(x) {
22422      return String.fromCharCode(x);
22423    },
22424    o: function(x) {
22425      return x.toString(8);
22426    },
22427    x: function(x) {
22428      return x.toString(16);
22429    },
22430    X: function(x) {
22431      return x.toString(16).toUpperCase();
22432    },
22433    g: function(x, p) {
22434      return x.toPrecision(p);
22435    },
22436    e: function(x, p) {
22437      return x.toExponential(p);
22438    },
22439    f: function(x, p) {
22440      return x.toFixed(p);
22441    },
22442    r: function(x, p) {
22443      return (x = d3.round(x, d3_format_precision(x, p))).toFixed(Math.max(0, Math.min(20, d3_format_precision(x * (1 + 1e-15), p))));
22444    }
22445  });
22446  function d3_format_typeDefault(x) {
22447    return x + "";
22448  }
22449  var d3_time = d3.time = {}, d3_date = Date;
22450  function d3_date_utc() {
22451    this._ = new Date(arguments.length > 1 ? Date.UTC.apply(this, arguments) : arguments[0]);
22452  }
22453  d3_date_utc.prototype = {
22454    getDate: function() {
22455      return this._.getUTCDate();
22456    },
22457    getDay: function() {
22458      return this._.getUTCDay();
22459    },
22460    getFullYear: function() {
22461      return this._.getUTCFullYear();
22462    },
22463    getHours: function() {
22464      return this._.getUTCHours();
22465    },
22466    getMilliseconds: function() {
22467      return this._.getUTCMilliseconds();
22468    },
22469    getMinutes: function() {
22470      return this._.getUTCMinutes();
22471    },
22472    getMonth: function() {
22473      return this._.getUTCMonth();
22474    },
22475    getSeconds: function() {
22476      return this._.getUTCSeconds();
22477    },
22478    getTime: function() {
22479      return this._.getTime();
22480    },
22481    getTimezoneOffset: function() {
22482      return 0;
22483    },
22484    valueOf: function() {
22485      return this._.valueOf();
22486    },
22487    setDate: function() {
22488      d3_time_prototype.setUTCDate.apply(this._, arguments);
22489    },
22490    setDay: function() {
22491      d3_time_prototype.setUTCDay.apply(this._, arguments);
22492    },
22493    setFullYear: function() {
22494      d3_time_prototype.setUTCFullYear.apply(this._, arguments);
22495    },
22496    setHours: function() {
22497      d3_time_prototype.setUTCHours.apply(this._, arguments);
22498    },
22499    setMilliseconds: function() {
22500      d3_time_prototype.setUTCMilliseconds.apply(this._, arguments);
22501    },
22502    setMinutes: function() {
22503      d3_time_prototype.setUTCMinutes.apply(this._, arguments);
22504    },
22505    setMonth: function() {
22506      d3_time_prototype.setUTCMonth.apply(this._, arguments);
22507    },
22508    setSeconds: function() {
22509      d3_time_prototype.setUTCSeconds.apply(this._, arguments);
22510    },
22511    setTime: function() {
22512      d3_time_prototype.setTime.apply(this._, arguments);
22513    }
22514  };
22515  var d3_time_prototype = Date.prototype;
22516  function d3_time_interval(local, step, number) {
22517    function round(date) {
22518      var d0 = local(date), d1 = offset(d0, 1);
22519      return date - d0 < d1 - date ? d0 : d1;
22520    }
22521    function ceil(date) {
22522      step(date = local(new d3_date(date - 1)), 1);
22523      return date;
22524    }
22525    function offset(date, k) {
22526      step(date = new d3_date(+date), k);
22527      return date;
22528    }
22529    function range(t0, t1, dt) {
22530      var time = ceil(t0), times = [];
22531      if (dt > 1) {
22532        while (time < t1) {
22533          if (!(number(time) % dt)) times.push(new Date(+time));
22534          step(time, 1);
22535        }
22536      } else {
22537        while (time < t1) times.push(new Date(+time)), step(time, 1);
22538      }
22539      return times;
22540    }
22541    function range_utc(t0, t1, dt) {
22542      try {
22543        d3_date = d3_date_utc;
22544        var utc = new d3_date_utc();
22545        utc._ = t0;
22546        return range(utc, t1, dt);
22547      } finally {
22548        d3_date = Date;
22549      }
22550    }
22551    local.floor = local;
22552    local.round = round;
22553    local.ceil = ceil;
22554    local.offset = offset;
22555    local.range = range;
22556    var utc = local.utc = d3_time_interval_utc(local);
22557    utc.floor = utc;
22558    utc.round = d3_time_interval_utc(round);
22559    utc.ceil = d3_time_interval_utc(ceil);
22560    utc.offset = d3_time_interval_utc(offset);
22561    utc.range = range_utc;
22562    return local;
22563  }
22564  function d3_time_interval_utc(method) {
22565    return function(date, k) {
22566      try {
22567        d3_date = d3_date_utc;
22568        var utc = new d3_date_utc();
22569        utc._ = date;
22570        return method(utc, k)._;
22571      } finally {
22572        d3_date = Date;
22573      }
22574    };
22575  }
22576  d3_time.year = d3_time_interval(function(date) {
22577    date = d3_time.day(date);
22578    date.setMonth(0, 1);
22579    return date;
22580  }, function(date, offset) {
22581    date.setFullYear(date.getFullYear() + offset);
22582  }, function(date) {
22583    return date.getFullYear();
22584  });
22585  d3_time.years = d3_time.year.range;
22586  d3_time.years.utc = d3_time.year.utc.range;
22587  d3_time.day = d3_time_interval(function(date) {
22588    var day = new d3_date(2e3, 0);
22589    day.setFullYear(date.getFullYear(), date.getMonth(), date.getDate());
22590    return day;
22591  }, function(date, offset) {
22592    date.setDate(date.getDate() + offset);
22593  }, function(date) {
22594    return date.getDate() - 1;
22595  });
22596  d3_time.days = d3_time.day.range;
22597  d3_time.days.utc = d3_time.day.utc.range;
22598  d3_time.dayOfYear = function(date) {
22599    var year = d3_time.year(date);
22600    return Math.floor((date - year - (date.getTimezoneOffset() - year.getTimezoneOffset()) * 6e4) / 864e5);
22601  };
22602  [ "sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday" ].forEach(function(day, i) {
22603    i = 7 - i;
22604    var interval = d3_time[day] = d3_time_interval(function(date) {
22605      (date = d3_time.day(date)).setDate(date.getDate() - (date.getDay() + i) % 7);
22606      return date;
22607    }, function(date, offset) {
22608      date.setDate(date.getDate() + Math.floor(offset) * 7);
22609    }, function(date) {
22610      var day = d3_time.year(date).getDay();
22611      return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7) - (day !== i);
22612    });
22613    d3_time[day + "s"] = interval.range;
22614    d3_time[day + "s"].utc = interval.utc.range;
22615    d3_time[day + "OfYear"] = function(date) {
22616      var day = d3_time.year(date).getDay();
22617      return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7);
22618    };
22619  });
22620  d3_time.week = d3_time.sunday;
22621  d3_time.weeks = d3_time.sunday.range;
22622  d3_time.weeks.utc = d3_time.sunday.utc.range;
22623  d3_time.weekOfYear = d3_time.sundayOfYear;
22624  function d3_locale_timeFormat(locale) {
22625    var locale_dateTime = locale.dateTime, locale_date = locale.date, locale_time = locale.time, locale_periods = locale.periods, locale_days = locale.days, locale_shortDays = locale.shortDays, locale_months = locale.months, locale_shortMonths = locale.shortMonths;
22626    function d3_time_format(template) {
22627      var n = template.length;
22628      function format(date) {
22629        var string = [], i = -1, j = 0, c, p, f;
22630        while (++i < n) {
22631          if (template.charCodeAt(i) === 37) {
22632            string.push(template.slice(j, i));
22633            if ((p = d3_time_formatPads[c = template.charAt(++i)]) != null) c = template.charAt(++i);
22634            if (f = d3_time_formats[c]) c = f(date, p == null ? c === "e" ? " " : "0" : p);
22635            string.push(c);
22636            j = i + 1;
22637          }
22638        }
22639        string.push(template.slice(j, i));
22640        return string.join("");
22641      }
22642      format.parse = function(string) {
22643        var d = {
22644          y: 1900,
22645          m: 0,
22646          d: 1,
22647          H: 0,
22648          M: 0,
22649          S: 0,
22650          L: 0,
22651          Z: null
22652        }, i = d3_time_parse(d, template, string, 0);
22653        if (i != string.length) return null;
22654        if ("p" in d) d.H = d.H % 12 + d.p * 12;
22655        var localZ = d.Z != null && d3_date !== d3_date_utc, date = new (localZ ? d3_date_utc : d3_date)();
22656        if ("j" in d) date.setFullYear(d.y, 0, d.j); else if ("w" in d && ("W" in d || "U" in d)) {
22657          date.setFullYear(d.y, 0, 1);
22658          date.setFullYear(d.y, 0, "W" in d ? (d.w + 6) % 7 + d.W * 7 - (date.getDay() + 5) % 7 : d.w + d.U * 7 - (date.getDay() + 6) % 7);
22659        } else date.setFullYear(d.y, d.m, d.d);
22660        date.setHours(d.H + (d.Z / 100 | 0), d.M + d.Z % 100, d.S, d.L);
22661        return localZ ? date._ : date;
22662      };
22663      format.toString = function() {
22664        return template;
22665      };
22666      return format;
22667    }
22668    function d3_time_parse(date, template, string, j) {
22669      var c, p, t, i = 0, n = template.length, m = string.length;
22670      while (i < n) {
22671        if (j >= m) return -1;
22672        c = template.charCodeAt(i++);
22673        if (c === 37) {
22674          t = template.charAt(i++);
22675          p = d3_time_parsers[t in d3_time_formatPads ? template.charAt(i++) : t];
22676          if (!p || (j = p(date, string, j)) < 0) return -1;
22677        } else if (c != string.charCodeAt(j++)) {
22678          return -1;
22679        }
22680      }
22681      return j;
22682    }
22683    d3_time_format.utc = function(template) {
22684      var local = d3_time_format(template);
22685      function format(date) {
22686        try {
22687          d3_date = d3_date_utc;
22688          var utc = new d3_date();
22689          utc._ = date;
22690          return local(utc);
22691        } finally {
22692          d3_date = Date;
22693        }
22694      }
22695      format.parse = function(string) {
22696        try {
22697          d3_date = d3_date_utc;
22698          var date = local.parse(string);
22699          return date && date._;
22700        } finally {
22701          d3_date = Date;
22702        }
22703      };
22704      format.toString = local.toString;
22705      return format;
22706    };
22707    d3_time_format.multi = d3_time_format.utc.multi = d3_time_formatMulti;
22708    var d3_time_periodLookup = d3.map(), d3_time_dayRe = d3_time_formatRe(locale_days), d3_time_dayLookup = d3_time_formatLookup(locale_days), d3_time_dayAbbrevRe = d3_time_formatRe(locale_shortDays), d3_time_dayAbbrevLookup = d3_time_formatLookup(locale_shortDays), d3_time_monthRe = d3_time_formatRe(locale_months), d3_time_monthLookup = d3_time_formatLookup(locale_months), d3_time_monthAbbrevRe = d3_time_formatRe(locale_shortMonths), d3_time_monthAbbrevLookup = d3_time_formatLookup(locale_shortMonths);
22709    locale_periods.forEach(function(p, i) {
22710      d3_time_periodLookup.set(p.toLowerCase(), i);
22711    });
22712    var d3_time_formats = {
22713      a: function(d) {
22714        return locale_shortDays[d.getDay()];
22715      },
22716      A: function(d) {
22717        return locale_days[d.getDay()];
22718      },
22719      b: function(d) {
22720        return locale_shortMonths[d.getMonth()];
22721      },
22722      B: function(d) {
22723        return locale_months[d.getMonth()];
22724      },
22725      c: d3_time_format(locale_dateTime),
22726      d: function(d, p) {
22727        return d3_time_formatPad(d.getDate(), p, 2);
22728      },
22729      e: function(d, p) {
22730        return d3_time_formatPad(d.getDate(), p, 2);
22731      },
22732      H: function(d, p) {
22733        return d3_time_formatPad(d.getHours(), p, 2);
22734      },
22735      I: function(d, p) {
22736        return d3_time_formatPad(d.getHours() % 12 || 12, p, 2);
22737      },
22738      j: function(d, p) {
22739        return d3_time_formatPad(1 + d3_time.dayOfYear(d), p, 3);
22740      },
22741      L: function(d, p) {
22742        return d3_time_formatPad(d.getMilliseconds(), p, 3);
22743      },
22744      m: function(d, p) {
22745        return d3_time_formatPad(d.getMonth() + 1, p, 2);
22746      },
22747      M: function(d, p) {
22748        return d3_time_formatPad(d.getMinutes(), p, 2);
22749      },
22750      p: function(d) {
22751        return locale_periods[+(d.getHours() >= 12)];
22752      },
22753      S: function(d, p) {
22754        return d3_time_formatPad(d.getSeconds(), p, 2);
22755      },
22756      U: function(d, p) {
22757        return d3_time_formatPad(d3_time.sundayOfYear(d), p, 2);
22758      },
22759      w: function(d) {
22760        return d.getDay();
22761      },
22762      W: function(d, p) {
22763        return d3_time_formatPad(d3_time.mondayOfYear(d), p, 2);
22764      },
22765      x: d3_time_format(locale_date),
22766      X: d3_time_format(locale_time),
22767      y: function(d, p) {
22768        return d3_time_formatPad(d.getFullYear() % 100, p, 2);
22769      },
22770      Y: function(d, p) {
22771        return d3_time_formatPad(d.getFullYear() % 1e4, p, 4);
22772      },
22773      Z: d3_time_zone,
22774      "%": function() {
22775        return "%";
22776      }
22777    };
22778    var d3_time_parsers = {
22779      a: d3_time_parseWeekdayAbbrev,
22780      A: d3_time_parseWeekday,
22781      b: d3_time_parseMonthAbbrev,
22782      B: d3_time_parseMonth,
22783      c: d3_time_parseLocaleFull,
22784      d: d3_time_parseDay,
22785      e: d3_time_parseDay,
22786      H: d3_time_parseHour24,
22787      I: d3_time_parseHour24,
22788      j: d3_time_parseDayOfYear,
22789      L: d3_time_parseMilliseconds,
22790      m: d3_time_parseMonthNumber,
22791      M: d3_time_parseMinutes,
22792      p: d3_time_parseAmPm,
22793      S: d3_time_parseSeconds,
22794      U: d3_time_parseWeekNumberSunday,
22795      w: d3_time_parseWeekdayNumber,
22796      W: d3_time_parseWeekNumberMonday,
22797      x: d3_time_parseLocaleDate,
22798      X: d3_time_parseLocaleTime,
22799      y: d3_time_parseYear,
22800      Y: d3_time_parseFullYear,
22801      Z: d3_time_parseZone,
22802      "%": d3_time_parseLiteralPercent
22803    };
22804    function d3_time_parseWeekdayAbbrev(date, string, i) {
22805      d3_time_dayAbbrevRe.lastIndex = 0;
22806      var n = d3_time_dayAbbrevRe.exec(string.slice(i));
22807      return n ? (date.w = d3_time_dayAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
22808    }
22809    function d3_time_parseWeekday(date, string, i) {
22810      d3_time_dayRe.lastIndex = 0;
22811      var n = d3_time_dayRe.exec(string.slice(i));
22812      return n ? (date.w = d3_time_dayLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
22813    }
22814    function d3_time_parseMonthAbbrev(date, string, i) {
22815      d3_time_monthAbbrevRe.lastIndex = 0;
22816      var n = d3_time_monthAbbrevRe.exec(string.slice(i));
22817      return n ? (date.m = d3_time_monthAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
22818    }
22819    function d3_time_parseMonth(date, string, i) {
22820      d3_time_monthRe.lastIndex = 0;
22821      var n = d3_time_monthRe.exec(string.slice(i));
22822      return n ? (date.m = d3_time_monthLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
22823    }
22824    function d3_time_parseLocaleFull(date, string, i) {
22825      return d3_time_parse(date, d3_time_formats.c.toString(), string, i);
22826    }
22827    function d3_time_parseLocaleDate(date, string, i) {
22828      return d3_time_parse(date, d3_time_formats.x.toString(), string, i);
22829    }
22830    function d3_time_parseLocaleTime(date, string, i) {
22831      return d3_time_parse(date, d3_time_formats.X.toString(), string, i);
22832    }
22833    function d3_time_parseAmPm(date, string, i) {
22834      var n = d3_time_periodLookup.get(string.slice(i, i += 2).toLowerCase());
22835      return n == null ? -1 : (date.p = n, i);
22836    }
22837    return d3_time_format;
22838  }
22839  var d3_time_formatPads = {
22840    "-": "",
22841    _: " ",
22842    "0": "0"
22843  }, d3_time_numberRe = /^\s*\d+/, d3_time_percentRe = /^%/;
22844  function d3_time_formatPad(value, fill, width) {
22845    var sign = value < 0 ? "-" : "", string = (sign ? -value : value) + "", length = string.length;
22846    return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string);
22847  }
22848  function d3_time_formatRe(names) {
22849    return new RegExp("^(?:" + names.map(d3.requote).join("|") + ")", "i");
22850  }
22851  function d3_time_formatLookup(names) {
22852    var map = new d3_Map(), i = -1, n = names.length;
22853    while (++i < n) map.set(names[i].toLowerCase(), i);
22854    return map;
22855  }
22856  function d3_time_parseWeekdayNumber(date, string, i) {
22857    d3_time_numberRe.lastIndex = 0;
22858    var n = d3_time_numberRe.exec(string.slice(i, i + 1));
22859    return n ? (date.w = +n[0], i + n[0].length) : -1;
22860  }
22861  function d3_time_parseWeekNumberSunday(date, string, i) {
22862    d3_time_numberRe.lastIndex = 0;
22863    var n = d3_time_numberRe.exec(string.slice(i));
22864    return n ? (date.U = +n[0], i + n[0].length) : -1;
22865  }
22866  function d3_time_parseWeekNumberMonday(date, string, i) {
22867    d3_time_numberRe.lastIndex = 0;
22868    var n = d3_time_numberRe.exec(string.slice(i));
22869    return n ? (date.W = +n[0], i + n[0].length) : -1;
22870  }
22871  function d3_time_parseFullYear(date, string, i) {
22872    d3_time_numberRe.lastIndex = 0;
22873    var n = d3_time_numberRe.exec(string.slice(i, i + 4));
22874    return n ? (date.y = +n[0], i + n[0].length) : -1;
22875  }
22876  function d3_time_parseYear(date, string, i) {
22877    d3_time_numberRe.lastIndex = 0;
22878    var n = d3_time_numberRe.exec(string.slice(i, i + 2));
22879    return n ? (date.y = d3_time_expandYear(+n[0]), i + n[0].length) : -1;
22880  }
22881  function d3_time_parseZone(date, string, i) {
22882    return /^[+-]\d{4}$/.test(string = string.slice(i, i + 5)) ? (date.Z = -string, 
22883    i + 5) : -1;
22884  }
22885  function d3_time_expandYear(d) {
22886    return d + (d > 68 ? 1900 : 2e3);
22887  }
22888  function d3_time_parseMonthNumber(date, string, i) {
22889    d3_time_numberRe.lastIndex = 0;
22890    var n = d3_time_numberRe.exec(string.slice(i, i + 2));
22891    return n ? (date.m = n[0] - 1, i + n[0].length) : -1;
22892  }
22893  function d3_time_parseDay(date, string, i) {
22894    d3_time_numberRe.lastIndex = 0;
22895    var n = d3_time_numberRe.exec(string.slice(i, i + 2));
22896    return n ? (date.d = +n[0], i + n[0].length) : -1;
22897  }
22898  function d3_time_parseDayOfYear(date, string, i) {
22899    d3_time_numberRe.lastIndex = 0;
22900    var n = d3_time_numberRe.exec(string.slice(i, i + 3));
22901    return n ? (date.j = +n[0], i + n[0].length) : -1;
22902  }
22903  function d3_time_parseHour24(date, string, i) {
22904    d3_time_numberRe.lastIndex = 0;
22905    var n = d3_time_numberRe.exec(string.slice(i, i + 2));
22906    return n ? (date.H = +n[0], i + n[0].length) : -1;
22907  }
22908  function d3_time_parseMinutes(date, string, i) {
22909    d3_time_numberRe.lastIndex = 0;
22910    var n = d3_time_numberRe.exec(string.slice(i, i + 2));
22911    return n ? (date.M = +n[0], i + n[0].length) : -1;
22912  }
22913  function d3_time_parseSeconds(date, string, i) {
22914    d3_time_numberRe.lastIndex = 0;
22915    var n = d3_time_numberRe.exec(string.slice(i, i + 2));
22916    return n ? (date.S = +n[0], i + n[0].length) : -1;
22917  }
22918  function d3_time_parseMilliseconds(date, string, i) {
22919    d3_time_numberRe.lastIndex = 0;
22920    var n = d3_time_numberRe.exec(string.slice(i, i + 3));
22921    return n ? (date.L = +n[0], i + n[0].length) : -1;
22922  }
22923  function d3_time_zone(d) {
22924    var z = d.getTimezoneOffset(), zs = z > 0 ? "-" : "+", zh = abs(z) / 60 | 0, zm = abs(z) % 60;
22925    return zs + d3_time_formatPad(zh, "0", 2) + d3_time_formatPad(zm, "0", 2);
22926  }
22927  function d3_time_parseLiteralPercent(date, string, i) {
22928    d3_time_percentRe.lastIndex = 0;
22929    var n = d3_time_percentRe.exec(string.slice(i, i + 1));
22930    return n ? i + n[0].length : -1;
22931  }
22932  function d3_time_formatMulti(formats) {
22933    var n = formats.length, i = -1;
22934    while (++i < n) formats[i][0] = this(formats[i][0]);
22935    return function(date) {
22936      var i = 0, f = formats[i];
22937      while (!f[1](date)) f = formats[++i];
22938      return f[0](date);
22939    };
22940  }
22941  d3.locale = function(locale) {
22942    return {
22943      numberFormat: d3_locale_numberFormat(locale),
22944      timeFormat: d3_locale_timeFormat(locale)
22945    };
22946  };
22947  var d3_locale_enUS = d3.locale({
22948    decimal: ".",
22949    thousands: ",",
22950    grouping: [ 3 ],
22951    currency: [ "$", "" ],
22952    dateTime: "%a %b %e %X %Y",
22953    date: "%m/%d/%Y",
22954    time: "%H:%M:%S",
22955    periods: [ "AM", "PM" ],
22956    days: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ],
22957    shortDays: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ],
22958    months: [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ],
22959    shortMonths: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ]
22960  });
22961  d3.format = d3_locale_enUS.numberFormat;
22962  d3.geo = {};
22963  function d3_adder() {}
22964  d3_adder.prototype = {
22965    s: 0,
22966    t: 0,
22967    add: function(y) {
22968      d3_adderSum(y, this.t, d3_adderTemp);
22969      d3_adderSum(d3_adderTemp.s, this.s, this);
22970      if (this.s) this.t += d3_adderTemp.t; else this.s = d3_adderTemp.t;
22971    },
22972    reset: function() {
22973      this.s = this.t = 0;
22974    },
22975    valueOf: function() {
22976      return this.s;
22977    }
22978  };
22979  var d3_adderTemp = new d3_adder();
22980  function d3_adderSum(a, b, o) {
22981    var x = o.s = a + b, bv = x - a, av = x - bv;
22982    o.t = a - av + (b - bv);
22983  }
22984  d3.geo.stream = function(object, listener) {
22985    if (object && d3_geo_streamObjectType.hasOwnProperty(object.type)) {
22986      d3_geo_streamObjectType[object.type](object, listener);
22987    } else {
22988      d3_geo_streamGeometry(object, listener);
22989    }
22990  };
22991  function d3_geo_streamGeometry(geometry, listener) {
22992    if (geometry && d3_geo_streamGeometryType.hasOwnProperty(geometry.type)) {
22993      d3_geo_streamGeometryType[geometry.type](geometry, listener);
22994    }
22995  }
22996  var d3_geo_streamObjectType = {
22997    Feature: function(feature, listener) {
22998      d3_geo_streamGeometry(feature.geometry, listener);
22999    },
23000    FeatureCollection: function(object, listener) {
23001      var features = object.features, i = -1, n = features.length;
23002      while (++i < n) d3_geo_streamGeometry(features[i].geometry, listener);
23003    }
23004  };
23005  var d3_geo_streamGeometryType = {
23006    Sphere: function(object, listener) {
23007      listener.sphere();
23008    },
23009    Point: function(object, listener) {
23010      object = object.coordinates;
23011      listener.point(object[0], object[1], object[2]);
23012    },
23013    MultiPoint: function(object, listener) {
23014      var coordinates = object.coordinates, i = -1, n = coordinates.length;
23015      while (++i < n) object = coordinates[i], listener.point(object[0], object[1], object[2]);
23016    },
23017    LineString: function(object, listener) {
23018      d3_geo_streamLine(object.coordinates, listener, 0);
23019    },
23020    MultiLineString: function(object, listener) {
23021      var coordinates = object.coordinates, i = -1, n = coordinates.length;
23022      while (++i < n) d3_geo_streamLine(coordinates[i], listener, 0);
23023    },
23024    Polygon: function(object, listener) {
23025      d3_geo_streamPolygon(object.coordinates, listener);
23026    },
23027    MultiPolygon: function(object, listener) {
23028      var coordinates = object.coordinates, i = -1, n = coordinates.length;
23029      while (++i < n) d3_geo_streamPolygon(coordinates[i], listener);
23030    },
23031    GeometryCollection: function(object, listener) {
23032      var geometries = object.geometries, i = -1, n = geometries.length;
23033      while (++i < n) d3_geo_streamGeometry(geometries[i], listener);
23034    }
23035  };
23036  function d3_geo_streamLine(coordinates, listener, closed) {
23037    var i = -1, n = coordinates.length - closed, coordinate;
23038    listener.lineStart();
23039    while (++i < n) coordinate = coordinates[i], listener.point(coordinate[0], coordinate[1], coordinate[2]);
23040    listener.lineEnd();
23041  }
23042  function d3_geo_streamPolygon(coordinates, listener) {
23043    var i = -1, n = coordinates.length;
23044    listener.polygonStart();
23045    while (++i < n) d3_geo_streamLine(coordinates[i], listener, 1);
23046    listener.polygonEnd();
23047  }
23048  d3.geo.area = function(object) {
23049    d3_geo_areaSum = 0;
23050    d3.geo.stream(object, d3_geo_area);
23051    return d3_geo_areaSum;
23052  };
23053  var d3_geo_areaSum, d3_geo_areaRingSum = new d3_adder();
23054  var d3_geo_area = {
23055    sphere: function() {
23056      d3_geo_areaSum += 4 * π;
23057    },
23058    point: d3_noop,
23059    lineStart: d3_noop,
23060    lineEnd: d3_noop,
23061    polygonStart: function() {
23062      d3_geo_areaRingSum.reset();
23063      d3_geo_area.lineStart = d3_geo_areaRingStart;
23064    },
23065    polygonEnd: function() {
23066      var area = 2 * d3_geo_areaRingSum;
23067      d3_geo_areaSum += area < 0 ? 4 * π + area : area;
23068      d3_geo_area.lineStart = d3_geo_area.lineEnd = d3_geo_area.point = d3_noop;
23069    }
23070  };
23071  function d3_geo_areaRingStart() {
23072    var λ00, φ00, λ0, cosφ0, sinφ0;
23073    d3_geo_area.point = function(λ, φ) {
23074      d3_geo_area.point = nextPoint;
23075      λ0 = (λ00 = λ) * d3_radians, cosφ0 = Math.cos(φ = (φ00 = φ) * d3_radians / 2 + π / 4), 
vendor: 13,920 bytes, lines 23076-23446
23076      sinφ0 = Math.sin(φ);
23077    };
23078    function nextPoint(λ, φ) {
23079      λ *= d3_radians;
23080      φ = φ * d3_radians / 2 + π / 4;
23081      var dλ = λ - λ0, sdλ = dλ >= 0 ? 1 : -1, adλ = sdλ * dλ, cosφ = Math.cos(φ), sinφ = Math.sin(φ), k = sinφ0 * sinφ, u = cosφ0 * cosφ + k * Math.cos(adλ), v = k * sdλ * Math.sin(adλ);
23082      d3_geo_areaRingSum.add(Math.atan2(v, u));
23083      λ0 = λ, cosφ0 = cosφ, sinφ0 = sinφ;
23084    }
23085    d3_geo_area.lineEnd = function() {
23086      nextPoint(λ00, φ00);
23087    };
23088  }
23089  function d3_geo_cartesian(spherical) {
23090    var λ = spherical[0], φ = spherical[1], cosφ = Math.cos(φ);
23091    return [ cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ) ];
23092  }
23093  function d3_geo_cartesianDot(a, b) {
23094    return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
23095  }
23096  function d3_geo_cartesianCross(a, b) {
23097    return [ a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0] ];
23098  }
23099  function d3_geo_cartesianAdd(a, b) {
23100    a[0] += b[0];
23101    a[1] += b[1];
23102    a[2] += b[2];
23103  }
23104  function d3_geo_cartesianScale(vector, k) {
23105    return [ vector[0] * k, vector[1] * k, vector[2] * k ];
23106  }
23107  function d3_geo_cartesianNormalize(d) {
23108    var l = Math.sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]);
23109    d[0] /= l;
23110    d[1] /= l;
23111    d[2] /= l;
23112  }
23113  function d3_geo_spherical(cartesian) {
23114    return [ Math.atan2(cartesian[1], cartesian[0]), d3_asin(cartesian[2]) ];
23115  }
23116  function d3_geo_sphericalEqual(a, b) {
23117    return abs(a[0] - b[0]) < ε && abs(a[1] - b[1]) < ε;
23118  }
23119  d3.geo.bounds = function() {
23120    var λ0, φ0, λ1, φ1, λ_, λ__, φ__, p0, dλSum, ranges, range;
23121    var bound = {
23122      point: point,
23123      lineStart: lineStart,
23124      lineEnd: lineEnd,
23125      polygonStart: function() {
23126        bound.point = ringPoint;
23127        bound.lineStart = ringStart;
23128        bound.lineEnd = ringEnd;
23129        dλSum = 0;
23130        d3_geo_area.polygonStart();
23131      },
23132      polygonEnd: function() {
23133        d3_geo_area.polygonEnd();
23134        bound.point = point;
23135        bound.lineStart = lineStart;
23136        bound.lineEnd = lineEnd;
23137        if (d3_geo_areaRingSum < 0) λ0 = -(λ1 = 180), φ0 = -(φ1 = 90); else if (dλSum > ε) φ1 = 90; else if (dλSum < -ε) φ0 = -90;
23138        range[0] = λ0, range[1] = λ1;
23139      }
23140    };
23141    function point(λ, φ) {
23142      ranges.push(range = [ λ0 = λ, λ1 = λ ]);
23143      if (φ < φ0) φ0 = φ;
23144      if (φ > φ1) φ1 = φ;
23145    }
23146    function linePoint(λ, φ) {
23147      var p = d3_geo_cartesian([ λ * d3_radians, φ * d3_radians ]);
23148      if (p0) {
23149        var normal = d3_geo_cartesianCross(p0, p), equatorial = [ normal[1], -normal[0], 0 ], inflection = d3_geo_cartesianCross(equatorial, normal);
23150        d3_geo_cartesianNormalize(inflection);
23151        inflection = d3_geo_spherical(inflection);
23152        var dλ = λ - λ_, s = dλ > 0 ? 1 : -1, λi = inflection[0] * d3_degrees * s, antimeridian = abs(dλ) > 180;
23153        if (antimeridian ^ (s * λ_ < λi && λi < s * λ)) {
23154          var φi = inflection[1] * d3_degrees;
23155          if (φi > φ1) φ1 = φi;
23156        } else if (λi = (λi + 360) % 360 - 180, antimeridian ^ (s * λ_ < λi && λi < s * λ)) {
23157          var φi = -inflection[1] * d3_degrees;
23158          if (φi < φ0) φ0 = φi;
23159        } else {
23160          if (φ < φ0) φ0 = φ;
23161          if (φ > φ1) φ1 = φ;
23162        }
23163        if (antimeridian) {
23164          if (λ < λ_) {
23165            if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ;
23166          } else {
23167            if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ;
23168          }
23169        } else {
23170          if (λ1 >= λ0) {
23171            if (λ < λ0) λ0 = λ;
23172            if (λ > λ1) λ1 = λ;
23173          } else {
23174            if (λ > λ_) {
23175              if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ;
23176            } else {
23177              if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ;
23178            }
23179          }
23180        }
23181      } else {
23182        point(λ, φ);
23183      }
23184      p0 = p, λ_ = λ;
23185    }
23186    function lineStart() {
23187      bound.point = linePoint;
23188    }
23189    function lineEnd() {
23190      range[0] = λ0, range[1] = λ1;
23191      bound.point = point;
23192      p0 = null;
23193    }
23194    function ringPoint(λ, φ) {
23195      if (p0) {
23196        var dλ = λ - λ_;
23197        dλSum += abs(dλ) > 180 ? dλ + (dλ > 0 ? 360 : -360) : dλ;
23198      } else λ__ = λ, φ__ = φ;
23199      d3_geo_area.point(λ, φ);
23200      linePoint(λ, φ);
23201    }
23202    function ringStart() {
23203      d3_geo_area.lineStart();
23204    }
23205    function ringEnd() {
23206      ringPoint(λ__, φ__);
23207      d3_geo_area.lineEnd();
23208      if (abs(dλSum) > ε) λ0 = -(λ1 = 180);
23209      range[0] = λ0, range[1] = λ1;
23210      p0 = null;
23211    }
23212    function angle(λ0, λ1) {
23213      return (λ1 -= λ0) < 0 ? λ1 + 360 : λ1;
23214    }
23215    function compareRanges(a, b) {
23216      return a[0] - b[0];
23217    }
23218    function withinRange(x, range) {
23219      return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x;
23220    }
23221    return function(feature) {
23222      φ1 = λ1 = -(λ0 = φ0 = Infinity);
23223      ranges = [];
23224      d3.geo.stream(feature, bound);
23225      var n = ranges.length;
23226      if (n) {
23227        ranges.sort(compareRanges);
23228        for (var i = 1, a = ranges[0], b, merged = [ a ]; i < n; ++i) {
23229          b = ranges[i];
23230          if (withinRange(b[0], a) || withinRange(b[1], a)) {
23231            if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1];
23232            if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0];
23233          } else {
23234            merged.push(a = b);
23235          }
23236        }
23237        var best = -Infinity, dλ;
23238        for (var n = merged.length - 1, i = 0, a = merged[n], b; i <= n; a = b, ++i) {
23239          b = merged[i];
23240          if ((dλ = angle(a[1], b[0])) > best) best = dλ, λ0 = b[0], λ1 = a[1];
23241        }
23242      }
23243      ranges = range = null;
23244      return λ0 === Infinity || φ0 === Infinity ? [ [ NaN, NaN ], [ NaN, NaN ] ] : [ [ λ0, φ0 ], [ λ1, φ1 ] ];
23245    };
23246  }();
23247  d3.geo.centroid = function(object) {
23248    d3_geo_centroidW0 = d3_geo_centroidW1 = d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0;
23249    d3.geo.stream(object, d3_geo_centroid);
23250    var x = d3_geo_centroidX2, y = d3_geo_centroidY2, z = d3_geo_centroidZ2, m = x * x + y * y + z * z;
23251    if (m < ε2) {
23252      x = d3_geo_centroidX1, y = d3_geo_centroidY1, z = d3_geo_centroidZ1;
23253      if (d3_geo_centroidW1 < ε) x = d3_geo_centroidX0, y = d3_geo_centroidY0, z = d3_geo_centroidZ0;
23254      m = x * x + y * y + z * z;
23255      if (m < ε2) return [ NaN, NaN ];
23256    }
23257    return [ Math.atan2(y, x) * d3_degrees, d3_asin(z / Math.sqrt(m)) * d3_degrees ];
23258  };
23259  var d3_geo_centroidW0, d3_geo_centroidW1, d3_geo_centroidX0, d3_geo_centroidY0, d3_geo_centroidZ0, d3_geo_centroidX1, d3_geo_centroidY1, d3_geo_centroidZ1, d3_geo_centroidX2, d3_geo_centroidY2, d3_geo_centroidZ2;
23260  var d3_geo_centroid = {
23261    sphere: d3_noop,
23262    point: d3_geo_centroidPoint,
23263    lineStart: d3_geo_centroidLineStart,
23264    lineEnd: d3_geo_centroidLineEnd,
23265    polygonStart: function() {
23266      d3_geo_centroid.lineStart = d3_geo_centroidRingStart;
23267    },
23268    polygonEnd: function() {
23269      d3_geo_centroid.lineStart = d3_geo_centroidLineStart;
23270    }
23271  };
23272  function d3_geo_centroidPoint(λ, φ) {
23273    λ *= d3_radians;
23274    var cosφ = Math.cos(φ *= d3_radians);
23275    d3_geo_centroidPointXYZ(cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ));
23276  }
23277  function d3_geo_centroidPointXYZ(x, y, z) {
23278    ++d3_geo_centroidW0;
23279    d3_geo_centroidX0 += (x - d3_geo_centroidX0) / d3_geo_centroidW0;
23280    d3_geo_centroidY0 += (y - d3_geo_centroidY0) / d3_geo_centroidW0;
23281    d3_geo_centroidZ0 += (z - d3_geo_centroidZ0) / d3_geo_centroidW0;
23282  }
23283  function d3_geo_centroidLineStart() {
23284    var x0, y0, z0;
23285    d3_geo_centroid.point = function(λ, φ) {
23286      λ *= d3_radians;
23287      var cosφ = Math.cos(φ *= d3_radians);
23288      x0 = cosφ * Math.cos(λ);
23289      y0 = cosφ * Math.sin(λ);
23290      z0 = Math.sin(φ);
23291      d3_geo_centroid.point = nextPoint;
23292      d3_geo_centroidPointXYZ(x0, y0, z0);
23293    };
23294    function nextPoint(λ, φ) {
23295      λ *= d3_radians;
23296      var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), w = Math.atan2(Math.sqrt((w = y0 * z - z0 * y) * w + (w = z0 * x - x0 * z) * w + (w = x0 * y - y0 * x) * w), x0 * x + y0 * y + z0 * z);
23297      d3_geo_centroidW1 += w;
23298      d3_geo_centroidX1 += w * (x0 + (x0 = x));
23299      d3_geo_centroidY1 += w * (y0 + (y0 = y));
23300      d3_geo_centroidZ1 += w * (z0 + (z0 = z));
23301      d3_geo_centroidPointXYZ(x0, y0, z0);
23302    }
23303  }
23304  function d3_geo_centroidLineEnd() {
23305    d3_geo_centroid.point = d3_geo_centroidPoint;
23306  }
23307  function d3_geo_centroidRingStart() {
23308    var λ00, φ00, x0, y0, z0;
23309    d3_geo_centroid.point = function(λ, φ) {
23310      λ00 = λ, φ00 = φ;
23311      d3_geo_centroid.point = nextPoint;
23312      λ *= d3_radians;
23313      var cosφ = Math.cos(φ *= d3_radians);
23314      x0 = cosφ * Math.cos(λ);
23315      y0 = cosφ * Math.sin(λ);
23316      z0 = Math.sin(φ);
23317      d3_geo_centroidPointXYZ(x0, y0, z0);
23318    };
23319    d3_geo_centroid.lineEnd = function() {
23320      nextPoint(λ00, φ00);
23321      d3_geo_centroid.lineEnd = d3_geo_centroidLineEnd;
23322      d3_geo_centroid.point = d3_geo_centroidPoint;
23323    };
23324    function nextPoint(λ, φ) {
23325      λ *= d3_radians;
23326      var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), cx = y0 * z - z0 * y, cy = z0 * x - x0 * z, cz = x0 * y - y0 * x, m = Math.sqrt(cx * cx + cy * cy + cz * cz), u = x0 * x + y0 * y + z0 * z, v = m && -d3_acos(u) / m, w = Math.atan2(m, u);
23327      d3_geo_centroidX2 += v * cx;
23328      d3_geo_centroidY2 += v * cy;
23329      d3_geo_centroidZ2 += v * cz;
23330      d3_geo_centroidW1 += w;
23331      d3_geo_centroidX1 += w * (x0 + (x0 = x));
23332      d3_geo_centroidY1 += w * (y0 + (y0 = y));
23333      d3_geo_centroidZ1 += w * (z0 + (z0 = z));
23334      d3_geo_centroidPointXYZ(x0, y0, z0);
23335    }
23336  }
23337  function d3_true() {
23338    return true;
23339  }
23340  function d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener) {
23341    var subject = [], clip = [];
23342    segments.forEach(function(segment) {
23343      if ((n = segment.length - 1) <= 0) return;
23344      var n, p0 = segment[0], p1 = segment[n];
23345      if (d3_geo_sphericalEqual(p0, p1)) {
23346        listener.lineStart();
23347        for (var i = 0; i < n; ++i) listener.point((p0 = segment[i])[0], p0[1]);
23348        listener.lineEnd();
23349        return;
23350      }
23351      var a = new d3_geo_clipPolygonIntersection(p0, segment, null, true), b = new d3_geo_clipPolygonIntersection(p0, null, a, false);
23352      a.o = b;
23353      subject.push(a);
23354      clip.push(b);
23355      a = new d3_geo_clipPolygonIntersection(p1, segment, null, false);
23356      b = new d3_geo_clipPolygonIntersection(p1, null, a, true);
23357      a.o = b;
23358      subject.push(a);
23359      clip.push(b);
23360    });
23361    clip.sort(compare);
23362    d3_geo_clipPolygonLinkCircular(subject);
23363    d3_geo_clipPolygonLinkCircular(clip);
23364    if (!subject.length) return;
23365    for (var i = 0, entry = clipStartInside, n = clip.length; i < n; ++i) {
23366      clip[i].e = entry = !entry;
23367    }
23368    var start = subject[0], points, point;
23369    while (1) {
23370      var current = start, isSubject = true;
23371      while (current.v) if ((current = current.n) === start) return;
23372      points = current.z;
23373      listener.lineStart();
23374      do {
23375        current.v = current.o.v = true;
23376        if (current.e) {
23377          if (isSubject) {
23378            for (var i = 0, n = points.length; i < n; ++i) listener.point((point = points[i])[0], point[1]);
23379          } else {
23380            interpolate(current.x, current.n.x, 1, listener);
23381          }
23382          current = current.n;
23383        } else {
23384          if (isSubject) {
23385            points = current.p.z;
23386            for (var i = points.length - 1; i >= 0; --i) listener.point((point = points[i])[0], point[1]);
23387          } else {
23388            interpolate(current.x, current.p.x, -1, listener);
23389          }
23390          current = current.p;
23391        }
23392        current = current.o;
23393        points = current.z;
23394        isSubject = !isSubject;
23395      } while (!current.v);
23396      listener.lineEnd();
23397    }
23398  }
23399  function d3_geo_clipPolygonLinkCircular(array) {
23400    if (!(n = array.length)) return;
23401    var n, i = 0, a = array[0], b;
23402    while (++i < n) {
23403      a.n = b = array[i];
23404      b.p = a;
23405      a = b;
23406    }
23407    a.n = b = array[0];
23408    b.p = a;
23409  }
23410  function d3_geo_clipPolygonIntersection(point, points, other, entry) {
23411    this.x = point;
23412    this.z = points;
23413    this.o = other;
23414    this.e = entry;
23415    this.v = false;
23416    this.n = this.p = null;
23417  }
23418  function d3_geo_clip(pointVisible, clipLine, interpolate, clipStart) {
23419    return function(rotate, listener) {
23420      var line = clipLine(listener), rotatedClipStart = rotate.invert(clipStart[0], clipStart[1]);
23421      var clip = {
23422        point: point,
23423        lineStart: lineStart,
23424        lineEnd: lineEnd,
23425        polygonStart: function() {
23426          clip.point = pointRing;
23427          clip.lineStart = ringStart;
23428          clip.lineEnd = ringEnd;
23429          segments = [];
23430          polygon = [];
23431        },
23432        polygonEnd: function() {
23433          clip.point = point;
23434          clip.lineStart = lineStart;
23435          clip.lineEnd = lineEnd;
23436          segments = d3.merge(segments);
23437          var clipStartInside = d3_geo_pointInPolygon(rotatedClipStart, polygon);
23438          if (segments.length) {
23439            if (!polygonStarted) listener.polygonStart(), polygonStarted = true;
23440            d3_geo_clipPolygon(segments, d3_geo_clipSort, clipStartInside, interpolate, listener);
23441          } else if (clipStartInside) {
23442            if (!polygonStarted) listener.polygonStart(), polygonStarted = true;
23443            listener.lineStart();
23444            interpolate(null, null, 1, listener);
23445            listener.lineEnd();
23446          }
vendor: 5,682 bytes, lines 23447-23610
23447          if (polygonStarted) listener.polygonEnd(), polygonStarted = false;
23448          segments = polygon = null;
23449        },
23450        sphere: function() {
23451          listener.polygonStart();
23452          listener.lineStart();
23453          interpolate(null, null, 1, listener);
23454          listener.lineEnd();
23455          listener.polygonEnd();
23456        }
23457      };
23458      function point(λ, φ) {
23459        var point = rotate(λ, φ);
23460        if (pointVisible(λ = point[0], φ = point[1])) listener.point(λ, φ);
23461      }
23462      function pointLine(λ, φ) {
23463        var point = rotate(λ, φ);
23464        line.point(point[0], point[1]);
23465      }
23466      function lineStart() {
23467        clip.point = pointLine;
23468        line.lineStart();
23469      }
23470      function lineEnd() {
23471        clip.point = point;
23472        line.lineEnd();
23473      }
23474      var segments;
23475      var buffer = d3_geo_clipBufferListener(), ringListener = clipLine(buffer), polygonStarted = false, polygon, ring;
23476      function pointRing(λ, φ) {
23477        ring.push([ λ, φ ]);
23478        var point = rotate(λ, φ);
23479        ringListener.point(point[0], point[1]);
23480      }
23481      function ringStart() {
23482        ringListener.lineStart();
23483        ring = [];
23484      }
23485      function ringEnd() {
23486        pointRing(ring[0][0], ring[0][1]);
23487        ringListener.lineEnd();
23488        var clean = ringListener.clean(), ringSegments = buffer.buffer(), segment, n = ringSegments.length;
23489        ring.pop();
23490        polygon.push(ring);
23491        ring = null;
23492        if (!n) return;
23493        if (clean & 1) {
23494          segment = ringSegments[0];
23495          var n = segment.length - 1, i = -1, point;
23496          if (n > 0) {
23497            if (!polygonStarted) listener.polygonStart(), polygonStarted = true;
23498            listener.lineStart();
23499            while (++i < n) listener.point((point = segment[i])[0], point[1]);
23500            listener.lineEnd();
23501          }
23502          return;
23503        }
23504        if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift()));
23505        segments.push(ringSegments.filter(d3_geo_clipSegmentLength1));
23506      }
23507      return clip;
23508    };
23509  }
23510  function d3_geo_clipSegmentLength1(segment) {
23511    return segment.length > 1;
23512  }
23513  function d3_geo_clipBufferListener() {
23514    var lines = [], line;
23515    return {
23516      lineStart: function() {
23517        lines.push(line = []);
23518      },
23519      point: function(λ, φ) {
23520        line.push([ λ, φ ]);
23521      },
23522      lineEnd: d3_noop,
23523      buffer: function() {
23524        var buffer = lines;
23525        lines = [];
23526        line = null;
23527        return buffer;
23528      },
23529      rejoin: function() {
23530        if (lines.length > 1) lines.push(lines.pop().concat(lines.shift()));
23531      }
23532    };
23533  }
23534  function d3_geo_clipSort(a, b) {
23535    return ((a = a.x)[0] < 0 ? a[1] - halfπ - ε : halfπ - a[1]) - ((b = b.x)[0] < 0 ? b[1] - halfπ - ε : halfπ - b[1]);
23536  }
23537  var d3_geo_clipAntimeridian = d3_geo_clip(d3_true, d3_geo_clipAntimeridianLine, d3_geo_clipAntimeridianInterpolate, [ -π, -π / 2 ]);
23538  function d3_geo_clipAntimeridianLine(listener) {
23539    var λ0 = NaN, φ0 = NaN, sλ0 = NaN, clean;
23540    return {
23541      lineStart: function() {
23542        listener.lineStart();
23543        clean = 1;
23544      },
23545      point: function(λ1, φ1) {
23546        var sλ1 = λ1 > 0 ? π : -π, dλ = abs(λ1 - λ0);
23547        if (abs(dλ - π) < ε) {
23548          listener.point(λ0, φ0 = (φ0 + φ1) / 2 > 0 ? halfπ : -halfπ);
23549          listener.point(sλ0, φ0);
23550          listener.lineEnd();
23551          listener.lineStart();
23552          listener.point(sλ1, φ0);
23553          listener.point(λ1, φ0);
23554          clean = 0;
23555        } else if (sλ0 !== sλ1 && dλ >= π) {
23556          if (abs(λ0 - sλ0) < ε) λ0 -= sλ0 * ε;
23557          if (abs(λ1 - sλ1) < ε) λ1 -= sλ1 * ε;
23558          φ0 = d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1);
23559          listener.point(sλ0, φ0);
23560          listener.lineEnd();
23561          listener.lineStart();
23562          listener.point(sλ1, φ0);
23563          clean = 0;
23564        }
23565        listener.point(λ0 = λ1, φ0 = φ1);
23566        sλ0 = sλ1;
23567      },
23568      lineEnd: function() {
23569        listener.lineEnd();
23570        λ0 = φ0 = NaN;
23571      },
23572      clean: function() {
23573        return 2 - clean;
23574      }
23575    };
23576  }
23577  function d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1) {
23578    var cosφ0, cosφ1, sinλ0_λ1 = Math.sin(λ0 - λ1);
23579    return abs(sinλ0_λ1) > ε ? Math.atan((Math.sin(φ0) * (cosφ1 = Math.cos(φ1)) * Math.sin(λ1) - Math.sin(φ1) * (cosφ0 = Math.cos(φ0)) * Math.sin(λ0)) / (cosφ0 * cosφ1 * sinλ0_λ1)) : (φ0 + φ1) / 2;
23580  }
23581  function d3_geo_clipAntimeridianInterpolate(from, to, direction, listener) {
23582    var φ;
23583    if (from == null) {
23584      φ = direction * halfπ;
23585      listener.point(-π, φ);
23586      listener.point(0, φ);
23587      listener.point(π, φ);
23588      listener.point(π, 0);
23589      listener.point(π, -φ);
23590      listener.point(0, -φ);
23591      listener.point(-π, -φ);
23592      listener.point(-π, 0);
23593      listener.point(-π, φ);
23594    } else if (abs(from[0] - to[0]) > ε) {
23595      var s = from[0] < to[0] ? π : -π;
23596      φ = direction * s / 2;
23597      listener.point(-s, φ);
23598      listener.point(0, φ);
23599      listener.point(s, φ);
23600    } else {
23601      listener.point(to[0], to[1]);
23602    }
23603  }
23604  function d3_geo_pointInPolygon(point, polygon) {
23605    var meridian = point[0], parallel = point[1], meridianNormal = [ Math.sin(meridian), -Math.cos(meridian), 0 ], polarAngle = 0, winding = 0;
23606    d3_geo_areaRingSum.reset();
23607    for (var i = 0, n = polygon.length; i < n; ++i) {
23608      var ring = polygon[i], m = ring.length;
23609      if (!m) continue;
23610      var point0 = ring[0], λ0 = point0[0], φ0 = point0[1] / 2 + π / 4, sinφ0 
vendor: 6,958 bytes, lines 23610-23787
23610= Math.sin(φ0), cosφ0 = Math.cos(φ0), j = 1;
23611      while (true) {
23612        if (j === m) j = 0;
23613        point = ring[j];
23614        var λ = point[0], φ = point[1] / 2 + π / 4, sinφ = Math.sin(φ), cosφ = Math.cos(φ), dλ = λ - λ0, sdλ = dλ >= 0 ? 1 : -1, adλ = sdλ * dλ, antimeridian = adλ > π, k = sinφ0 * sinφ;
23615        d3_geo_areaRingSum.add(Math.atan2(k * sdλ * Math.sin(adλ), cosφ0 * cosφ + k * Math.cos(adλ)));
23616        polarAngle += antimeridian ? dλ + sdλ * τ : dλ;
23617        if (antimeridian ^ λ0 >= meridian ^ λ >= meridian) {
23618          var arc = d3_geo_cartesianCross(d3_geo_cartesian(point0), d3_geo_cartesian(point));
23619          d3_geo_cartesianNormalize(arc);
23620          var intersection = d3_geo_cartesianCross(meridianNormal, arc);
23621          d3_geo_cartesianNormalize(intersection);
23622          var φarc = (antimeridian ^ dλ >= 0 ? -1 : 1) * d3_asin(intersection[2]);
23623          if (parallel > φarc || parallel === φarc && (arc[0] || arc[1])) {
23624            winding += antimeridian ^ dλ >= 0 ? 1 : -1;
23625          }
23626        }
23627        if (!j++) break;
23628        λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ, point0 = point;
23629      }
23630    }
23631    return (polarAngle < -ε || polarAngle < ε && d3_geo_areaRingSum < 0) ^ winding & 1;
23632  }
23633  function d3_geo_clipCircle(radius) {
23634    var cr = Math.cos(radius), smallRadius = cr > 0, notHemisphere = abs(cr) > ε, interpolate = d3_geo_circleInterpolate(radius, 6 * d3_radians);
23635    return d3_geo_clip(visible, clipLine, interpolate, smallRadius ? [ 0, -radius ] : [ -π, radius - π ]);
23636    function visible(λ, φ) {
23637      return Math.cos(λ) * Math.cos(φ) > cr;
23638    }
23639    function clipLine(listener) {
23640      var point0, c0, v0, v00, clean;
23641      return {
23642        lineStart: function() {
23643          v00 = v0 = false;
23644          clean = 1;
23645        },
23646        point: function(λ, φ) {
23647          var point1 = [ λ, φ ], point2, v = visible(λ, φ), c = smallRadius ? v ? 0 : code(λ, φ) : v ? code(λ + (λ < 0 ? π : -π), φ) : 0;
23648          if (!point0 && (v00 = v0 = v)) listener.lineStart();
23649          if (v !== v0) {
23650            point2 = intersect(point0, point1);
23651            if (d3_geo_sphericalEqual(point0, point2) || d3_geo_sphericalEqual(point1, point2)) {
23652              point1[0] += ε;
23653              point1[1] += ε;
23654              v = visible(point1[0], point1[1]);
23655            }
23656          }
23657          if (v !== v0) {
23658            clean = 0;
23659            if (v) {
23660              listener.lineStart();
23661              point2 = intersect(point1, point0);
23662              listener.point(point2[0], point2[1]);
23663            } else {
23664              point2 = intersect(point0, point1);
23665              listener.point(point2[0], point2[1]);
23666              listener.lineEnd();
23667            }
23668            point0 = point2;
23669          } else if (notHemisphere && point0 && smallRadius ^ v) {
23670            var t;
23671            if (!(c & c0) && (t = intersect(point1, point0, true))) {
23672              clean = 0;
23673              if (smallRadius) {
23674                listener.lineStart();
23675                listener.point(t[0][0], t[0][1]);
23676                listener.point(t[1][0], t[1][1]);
23677                listener.lineEnd();
23678              } else {
23679                listener.point(t[1][0], t[1][1]);
23680                listener.lineEnd();
23681                listener.lineStart();
23682                listener.point(t[0][0], t[0][1]);
23683              }
23684            }
23685          }
23686          if (v && (!point0 || !d3_geo_sphericalEqual(point0, point1))) {
23687            listener.point(point1[0], point1[1]);
23688          }
23689          point0 = point1, v0 = v, c0 = c;
23690        },
23691        lineEnd: function() {
23692          if (v0) listener.lineEnd();
23693          point0 = null;
23694        },
23695        clean: function() {
23696          return clean | (v00 && v0) << 1;
23697        }
23698      };
23699    }
23700    function intersect(a, b, two) {
23701      var pa = d3_geo_cartesian(a), pb = d3_geo_cartesian(b);
23702      var n1 = [ 1, 0, 0 ], n2 = d3_geo_cartesianCross(pa, pb), n2n2 = d3_geo_cartesianDot(n2, n2), n1n2 = n2[0], determinant = n2n2 - n1n2 * n1n2;
23703      if (!determinant) return !two && a;
23704      var c1 = cr * n2n2 / determinant, c2 = -cr * n1n2 / determinant, n1xn2 = d3_geo_cartesianCross(n1, n2), A = d3_geo_cartesianScale(n1, c1), B = d3_geo_cartesianScale(n2, c2);
23705      d3_geo_cartesianAdd(A, B);
23706      var u = n1xn2, w = d3_geo_cartesianDot(A, u), uu = d3_geo_cartesianDot(u, u), t2 = w * w - uu * (d3_geo_cartesianDot(A, A) - 1);
23707      if (t2 < 0) return;
23708      var t = Math.sqrt(t2), q = d3_geo_cartesianScale(u, (-w - t) / uu);
23709      d3_geo_cartesianAdd(q, A);
23710      q = d3_geo_spherical(q);
23711      if (!two) return q;
23712      var λ0 = a[0], λ1 = b[0], φ0 = a[1], φ1 = b[1], z;
23713      if (λ1 < λ0) z = λ0, λ0 = λ1, λ1 = z;
23714      var δλ = λ1 - λ0, polar = abs(δλ - π) < ε, meridian = polar || δλ < ε;
23715      if (!polar && φ1 < φ0) z = φ0, φ0 = φ1, φ1 = z;
23716      if (meridian ? polar ? φ0 + φ1 > 0 ^ q[1] < (abs(q[0] - λ0) < ε ? φ0 : φ1) : φ0 <= q[1] && q[1] <= φ1 : δλ > π ^ (λ0 <= q[0] && q[0] <= λ1)) {
23717        var q1 = d3_geo_cartesianScale(u, (-w + t) / uu);
23718        d3_geo_cartesianAdd(q1, A);
23719        return [ q, d3_geo_spherical(q1) ];
23720      }
23721    }
23722    function code(λ, φ) {
23723      var r = smallRadius ? radius : π - radius, code = 0;
23724      if (λ < -r) code |= 1; else if (λ > r) code |= 2;
23725      if (φ < -r) code |= 4; else if (φ > r) code |= 8;
23726      return code;
23727    }
23728  }
23729  function d3_geom_clipLine(x0, y0, x1, y1) {
23730    return function(line) {
23731      var a = line.a, b = line.b, ax = a.x, ay = a.y, bx = b.x, by = b.y, t0 = 0, t1 = 1, dx = bx - ax, dy = by - ay, r;
23732      r = x0 - ax;
23733      if (!dx && r > 0) return;
23734      r /= dx;
23735      if (dx < 0) {
23736        if (r < t0) return;
23737        if (r < t1) t1 = r;
23738      } else if (dx > 0) {
23739        if (r > t1) return;
23740        if (r > t0) t0 = r;
23741      }
23742      r = x1 - ax;
23743      if (!dx && r < 0) return;
23744      r /= dx;
23745      if (dx < 0) {
23746        if (r > t1) return;
23747        if (r > t0) t0 = r;
23748      } else if (dx > 0) {
23749        if (r < t0) return;
23750        if (r < t1) t1 = r;
23751      }
23752      r = y0 - ay;
23753      if (!dy && r > 0) return;
23754      r /= dy;
23755      if (dy < 0) {
23756        if (r < t0) return;
23757        if (r < t1) t1 = r;
23758      } else if (dy > 0) {
23759        if (r > t1) return;
23760        if (r > t0) t0 = r;
23761      }
23762      r = y1 - ay;
23763      if (!dy && r < 0) return;
23764      r /= dy;
23765      if (dy < 0) {
23766        if (r > t1) return;
23767        if (r > t0) t0 = r;
23768      } else if (dy > 0) {
23769        if (r < t0) return;
23770        if (r < t1) t1 = r;
23771      }
23772      if (t0 > 0) line.a = {
23773        x: ax + t0 * dx,
23774        y: ay + t0 * dy
23775      };
23776      if (t1 < 1) line.b = {
23777        x: ax + t1 * dx,
23778        y: ay + t1 * dy
23779      };
23780      return line;
23781    };
23782  }
23783  var d3_geo_clipExtentMAX = 1e9;
23784  d3.geo.clipExtent = function() {
23785    var x0, y0, x1, y1, stream, clip, clipExtent = {
23786      stream: function(output) {
23787        if (stream) stream.valid = false;
23788        stream = clip(output);
23789        stream.valid = true;
23790        return stream;
23791      },
23792      extent: function(_) {
23793        if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ];
23794        clip = d3_geo_clipExtent(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]);
23795        if (stream) stream.valid = false, stream = null;
23796        return clipExtent;
23797      }
23798    };
23799    return clipExtent.extent([ [ 0, 0 ], [ 960, 500 ] ]);
23800  };
23801  function d3_geo_clipExtent(x0, y0, x1, y1) {
23802    return function(listener) {
23803      var listener_ = listener, bufferListener = d3_geo_clipBufferListener(), clipLine = d3_geom_clipLine(x0, y0, x1, y1), segments, polygon, ring;
23804      var clip = {
23805        point: point,
23806        lineStart: lineStart,
23807        lineEnd: lineEnd,
23808        polygonStart: function() {
23809          listener = bufferListener;
23810          segments = [];
23811          polygon = [];
23812          clean = true;
23813        },
23814        polygonEnd: function() {
23815          listener = listener_;
23816          segments = d3.merge(segments);
23817          var clipStartInside = insidePolygon([ x0, y1 ]), inside = clean && clipStartInside, visible = segments.length;
23818          if (inside || visible) {
23819            listener.polygonStart();
23820            if (inside) {
23821              listener.lineStart();
23822              interpolate(null, null, 1, listener);
23823              listener.lineEnd();
23824            }
23825            if (visible) {
23826              d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener);
23827            }
23828            listener.polygonEnd();
23829          }
23830          segments = polygon = ring = null;
23831        }
23832      };
23833      function insidePolygon(p) {
23834        var wn = 0, n = polygon.length, y = p[1];
23835        for (var i = 0; i < n; ++i) {
23836          for (var j = 1, v = polygon[i], m = v.length, a = v[0], b; j < m; ++j) {
23837            b = v[j];
23838            if (a[1] <= y) {
23839              if (b[1] > y && d3_cross2d(a, b, p) > 0) ++wn;
23840            } else {
23841              if (b[1] <= y && d3_cross2d(a, b, p) < 0) --wn;
23842            }
23843            a = b;
23844          }
23845        }
23846        return wn !== 0;
23847      }
23848      function interpolate(from, to, direction, listener) {
23849        var a = 0, a1 = 0;
23850        if (from == null || (a = corner(from, direction)) !== (a1 = corner(to, direction)) || comparePoints(from, to) < 0 ^ direction > 0) {
23851          do {
23852            listener.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0);
23853          } while ((a = (a + direction + 4) % 4) !== a1);
23854        } else {
23855          listener.point(to[0], to[1]);
23856        }
23857      }
23858      function pointVisible(x, y) {
23859        return x0 <= x && x <= x1 && y0 <= y && y <= y1;
23860      }
23861      function point(x, y) {
23862        if (pointVisible(x, y)) listener.point(x, y);
23863      }
23864      var x__, y__, v__, x_, y_, v_, first, clean;
23865      function lineStart() {
23866        clip.point = linePoint;
23867        if (polygon) polygon.push(ring = []);
23868        first = true;
23869        v_ = false;
23870        x_ = y_ = NaN;
23871      }
23872      function lineEnd() {
23873        if (segments) {
23874          linePoint(x__, y__);
23875          if (v__ && v_) bufferListener.rejoin();
23876          segments.push(bufferListener.buffer());
23877        }
23878        clip.point = point;
23879        if (v_) listener.lineEnd();
23880      }
23881      function linePoint(x, y) {
23882        x = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, x));
23883        y = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, y));
23884        var v = pointVisible(x, y);
23885        if (polygon) ring.push([ x, y ]);
23886        if (first) {
23887          x__ = x, y__ = y, v__ = v;
23888          first = false;
23889          if (v) {
23890            listener.lineStart();
23891            listener.point(x, y);
23892          }
23893        } else {
23894          if (v && v_) listener.point(x, y); else {
23895            var l = {
23896              a: {
23897                x: x_,
23898                y: y_
23899              },
23900              b: {
23901                x: x,
23902                y: y
23903              }
23904            };
23905            if (clipLine(l)) {
23906              if (!v_) {
23907                listener.lineStart();
23908                listener.point(l.a.x, l.a.y);
23909              }
23910              listener.point(l.b.x, l.b.y);
23911              if (!v) listener.lineEnd();
23912              clean = false;
23913            } else if (v) {
23914              listener.lineStart();
23915              listener.point(x, y);
23916              clean = false;
23917            }
23918          }
23919        }
23920        x_ = x, y_ = y, v_ = v;
23921      }
23922      return clip;
23923    };
23924    function corner(p, direction) {
23925      return abs(p[0] - x0) < ε ? direction > 0 ? 0 : 3 : abs(p[0] - x1) < ε ? direction > 0 ? 2 : 1 : abs(p[1] - y0) < ε ? direction > 0 ? 1 : 0 : direction > 0 ? 3 : 2;
23926    }
23927    function compare(a, b) {
23928      return comparePoints(a.x, b.x);
23929    }
23930    function comparePoints(a, b) {
23931      var ca = corner(a, 1), cb = corner(b, 1);
23932      return ca !== cb ? ca - cb : ca === 0 ? b[1] - a[1] : ca === 1 ? a[0] - b[0] : ca === 2 ? a[1] - b[1] : b[0] - a[0];
23933    }
23934  }
23935  function d3_geo_compose(a, b) {
23936    function compose(x, y) {
23937      return x = a(x, y), b(x[0], x[1]);
23938    }
23939    if (a.invert && b.invert) compose.invert = function(x, y) {
23940      return x = b.invert(x, y), x && a.invert(x[0], x[1]);
23941    };
23942    return compose;
23943  }
23944  function d3_geo_conic(projectAt) {
23945    var φ0 = 0, φ1 = π / 3, m = d3_geo_projectionMutator(projectAt), p = m(φ0, φ1);
23946    p.parallels = function(_) {
23947      if (!arguments.length) return [ φ0 / π * 180, φ1 / π * 180 ];
23948      return m(φ0 = _[0] * π / 180, φ1 = _[1] * π / 180);
23949    };
23950    return p;
23951  }
23952  function d3_geo_conicEqualArea(φ0, φ1) {
23953    var sinφ0 = Math.sin(φ0), n = (sinφ0 + Math.sin(φ1)) / 2, C = 1 + sinφ0 * (2 * n - sinφ0), ρ0 = Math.sqrt(C) / n;
23954    function forward(λ, φ) {
23955      var ρ = Math.sqrt(C - 2 * n * Math.sin(φ)) / n;
23956      return [ ρ * Math.sin(λ *= n), ρ0 - ρ * Math.cos(λ) ];
23957    }
23958    forward.invert = function(x, y) {
23959      var ρ0_y = ρ0 - y;
23960      return [ Math.atan2(x, ρ0_y) / n, d3_asin((C - (x * x + ρ0_y * ρ0_y) * n * n) / (2 * n)) ];
23961    };
23962    return forward;
23963  }
23964  (d3.geo.conicEqualArea = function() {
23965    return d3_geo_conic(d3_geo_conicEqualArea);
23966  }).raw = d3_geo_conicEqualArea;
23967  d3.geo.albers = function() {
23968    return d3.geo.conicEqualArea().rotate([ 96, 0 ]).center([ -.6, 38.7 ]).parallels([ 29.5, 45.5 ]).scale(1070);
23969  };
23970  d3.geo.albersUsa = function() {
23971    var lower48 = d3.geo.albers();
23972    var alaska = d3.geo.conicEqualArea().rotate([ 154, 0 ]).center([ -2, 58.5 ]).parallels([ 55, 65 ]);
23973    var hawaii = d3.geo.conicEqualArea().rotate([ 157, 0 ]).center([ -3, 19.9 ]).parallels([ 8, 18 ]);
23974    var point, pointStream = {
23975      point: function(x, y) {
23976        point = [ x, y ];
23977      }
23978    }, lower48Point, alaskaPoint, hawaiiPoint;
23979    function albersUsa(coordinates) {
23980      var x = coordinates[0], y = coordinates[1];
23981      point = null;
23982      (lower48Point(x, y), point) || (alaskaPoint(x, y), point) || hawaiiPoint(x, y);
23983      return point;
23984    }
23985    albersUsa.invert = function(coordinates) {
23986      var k = lower48.scale(), t = lower48.translate(), x = (coordinates[0] - t[0]) / k, y = (coordinates[1] - t[1]) / k;
23987      return (y >= .12 && y < .234 && x >= -.425 && x < -.214 ? alaska : y >= .166 && y < .234 && x >= -.214 && x < -.115 ? hawaii : lower48).invert(coordinates);
23988    };
23989    albersUsa.stream = function(stream) {
23990      var lower48Stream = lower48.stream(stream), alaskaStream = alaska.stream(stream), hawaiiStream = hawaii.stream(stream);
23991      return {
23992        point: function(x, y) {
23993          lower48Stream.point(x, y);
23994          alaskaStream.point(x, y);
23995          hawaiiStream.point(x, y);
23996        },
23997        sphere: function() {
23998          lower48Stream.sphere();
23999          alaskaStream.sphere();
24000          hawaiiStream.sphere();
24001        },
24002        lineStart: function() {
24003          lower48Stream.lineStart();
24004          alaskaStream.lineStart();
24005          hawaiiStream.lineStart();
24006        },
24007        lineEnd: function() {
24008          lower48Stream.lineEnd();
24009          alaskaStream.lineEnd();
24010          hawaiiStream.lineEnd();
24011        },
24012        polygonStart: function() {
24013          lower48Stream.polygonStart();
24014          alaskaStream.polygonStart();
24015          hawaiiStream.polygonStart();
24016        },
24017        polygonEnd: function() {
24018          lower48Stream.polygonEnd();
24019          alaskaStream.polygonEnd();
24020          hawaiiStream.polygonEnd();
24021        }
24022      };
24023    };
24024    albersUsa.precision = function(_) {
24025      if (!arguments.length) return lower48.precision();
24026      lower48.precision(_);
24027      alaska.precision(_);
24028      hawaii.precision(_);
24029      return albersUsa;
24030    };
24031    albersUsa.scale = function(_) {
24032      if (!arguments.length) return lower48.scale();
24033      lower48.scale(_);
24034      alaska.scale(_ * .35);
24035      hawaii.scale(_);
24036      return albersUsa.translate(lower48.translate());
24037    };
24038    albersUsa.translate = function(_) {
24039      if (!arguments.length) return lower48.translate();
24040      var k = lower48.scale(), x = +_[0], y = +_[1];
24041      lower48Point = lower48.translate(_).clipExtent([ [ x - .455 * k, y - .238 * k ], [ x + .455 * k, y + .238 * k ] ]).stream(pointStream).point;
24042      alaskaPoint = alaska.translate([ x - .307 * k, y + .201 * k ]).clipExtent([ [ x - .425 * k + ε, y + .12 * k + ε ], [ x - .214 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point;
24043      hawaiiPoint = hawaii.translate([ x - .205 * k, y + .212 * k ]).clipExtent([ [ x - .214 * k + ε, y + .166 * k + ε ], [ x - .115 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point;
24044      return albersUsa;
24045    };
24046    return albersUsa.scale(1070);
24047  };
24048  var d3_geo_pathAreaSum, d3_geo_pathAreaPolygon, d3_geo_pathArea = {
24049    point: d3_noop,
24050    lineStart: d3_noop,
24051    lineEnd: d3_noop,
24052    polygonStart: function() {
24053      d3_geo_pathAreaPolygon = 0;
24054      d3_geo_pathArea.lineStart = d3_geo_pathAreaRingStart;
24055    },
24056    polygonEnd: function() {
24057      d3_geo_pathArea.lineStart = d3_geo_pathArea.lineEnd = d3_geo_pathArea.point = d3_noop;
24058      d3_geo_pathAreaSum += abs(d3_geo_pathAreaPolygon / 2);
24059    }
24060  };
24061  function d3_geo_pathAreaRingStart() {
24062    var x00, y00, x0, y0;
24063    d3_geo_pathArea.point = function(x, y) {
24064      d3_geo_pathArea.point = nextPoint;
24065      x00 = x0 = x, y00 = y0 = y;
24066    };
24067    function nextPoint(x, y) {
24068      d3_geo_pathAreaPolygon += y0 * x - x0 * y;
24069      x0 = x, y0 = y;
24070    }
24071    d3_geo_pathArea.lineEnd = function() {
24072      nextPoint(x00, y00);
24073    };
24074  }
24075  var d3_geo_pathBoundsX0, d3_geo_pathBoundsY0, d3_geo_pathBoundsX1, d3_geo_pathBoundsY1;
24076  var d3_geo_pathBounds = {
24077    point: d3_geo_pathBoundsPoint,
24078    lineStart: d3_noop,
24079    lineEnd: d3_noop,
24080    polygonStart: d3_noop,
24081    polygonEnd: d3_noop
24082  };
24083  function d3_geo_pathBoundsPoint(x, y) {
24084    if (x < d3_geo_pathBoundsX0) d3_geo_pathBoundsX0 = x;
24085    if (x > d3_geo_pathBoundsX1) d3_geo_pathBoundsX1 = x;
24086    if (y < d3_geo_pathBoundsY0) d3_geo_pathBoundsY0 = y;
24087    if (y > d3_geo_pathBoundsY1) d3_geo_pathBoundsY1 = y;
24088  }
24089  function d3_geo_pathBuffer() {
24090    var pointCircle = d3_geo_pathBufferCircle(4.5), buffer = [];
24091    var stream = {
24092      point: point,
24093      lineStart: function() {
24094        stream.point = pointLineStart;
24095      },
24096      lineEnd: lineEnd,
24097      polygonStart: function() {
24098        stream.lineEnd = lineEndPolygon;
24099      },
24100      polygonEnd: function() {
24101        stream.lineEnd = lineEnd;
24102        stream.point = point;
24103      },
24104      pointRadius: function(_) {
24105        pointCircle = d3_geo_pathBufferCircle(_);
24106        return stream;
24107      },
24108      result: function() {
24109        if (buffer.length) {
24110          var result = buffer.join("");
24111          buffer = [];
24112          return result;
24113        }
24114      }
24115    };
24116    function point(x, y) {
24117      buffer.push("M", x, ",", y, pointCircle);
24118    }
24119    function pointLineStart(x, y) {
24120      buffer.push("M", x, ",", y);
24121      stream.point = pointLine;
24122    }
24123    function pointLine(x, y) {
24124      buffer.push("L", x, ",", y);
24125    }
24126    function lineEnd() {
24127      stream.point = point;
24128    }
24129    function lineEndPolygon() {
24130      buffer.push("Z");
24131    }
24132    return stream;
24133  }
24134  function d3_geo_pathBufferCircle(radius) {
24135    return "m0," + radius + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius + "a" + radius + "," + radius + " 0 1,1 0," + 2 * radius + "z";
24136  }
24137  var d3_geo_pathCentroid = {
24138    point: d3_geo_pathCentroidPoint,
24139    lineStart: d3_geo_pathCentroidLineStart,
24140    lineEnd: d3_geo_pathCentroidLineEnd,
24141    polygonStart: function() {
24142      d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidRingStart;
24143    },
24144    polygonEnd: function() {
24145      d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint;
24146      d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidLineStart;
24147      d3_geo_pathCentroid.lineEnd = d3_geo_pathCentroidLineEnd;
24148    }
24149  };
24150  function d3_geo_pathCentroidPoint(x, y) {
24151    d3_geo_centroidX0 += x;
24152    d3_geo_centroidY0 += y;
24153    ++d3_geo_centroidZ0;
24154  }
24155  function d3_geo_pathCentroidLineStart() {
24156    var x0, y0;
24157    d3_geo_pathCentroid.point = function(x, y) {
24158      d3_geo_pathCentroid.point = nextPoint;
24159      d3_geo_pathCentroidPoint(x0 = x, y0 = y);
24160    };
24161    function nextPoint(x, y) {
24162      var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy);
24163      d3_geo_centroidX1 += z * (x0 + x) / 2;
24164      d3_geo_centroidY1 += z * (y0 + y) / 2;
24165      d3_geo_centroidZ1 += z;
24166      d3_geo_pathCentroidPoint(x0 = x, y0 = y);
24167    }
24168  }
24169  function d3_geo_pathCentroidLineEnd() {
24170    d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint;
24171  }
24172  function d3_geo_pathCentroidRingStart() {
24173    var x00, y00, x0, y0;
24174    d3_geo_pathCentroid.point = function(x, y) {
24175      d3_geo_pathCentroid.point = nextPoint;
24176      d3_geo_pathCentroidPoint(x00 = x0 = x, y00 = y0 = y);
24177    };
24178    function nextPoint(x, y) {
24179      var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy);
24180      d3_geo_centroidX1 += z * (x0 + x) / 2;
24181      d3_geo_centroidY1 += z * (y0 + y) / 2;
24182      d3_geo_centroidZ1 += z;
24183      z = y0 * x - x0 * y;
24184      d3_geo_centroidX2 += z * (x0 + x);
24185      d3_geo_centroidY2 += z * (y0 + y);
24186      d3_geo_centroidZ2 += z * 3;
24187      d3_geo_pathCentroidPoint(x0 = x, y0 = y);
24188    }
24189    d3_geo_pathCentroid.lineEnd = function() {
24190      nextPoint(x00, y00);
24191    };
24192  }
24193  function d3_geo_pathContext(context) {
24194    var pointRadius = 4.5;
24195    var stream = {
24196      point: point,
24197      lineStart: function() {
24198        stream.point = pointLineStart;
24199      },
24200      lineEnd: lineEnd,
24201      polygonStart: function() {
24202        stream.lineEnd = lineEndPolygon;
24203      },
24204      polygonEnd: function() {
24205        stream.lineEnd = lineEnd;
24206        stream.point = point;
24207      },
24208      pointRadius: function(_) {
24209        pointRadius = _;
24210        return stream;
24211      },
24212      result: d3_noop
24213    };
24214    function point(x, y) {
24215      context.moveTo(x, y);
24216      context.arc(x, y, pointRadius, 0, τ);
24217    }
24218    function pointLineStart(x, y) {
24219      context.moveTo(x, y);
24220      stream.point = pointLine;
24221    }
24222    function pointLine(x, y) {
24223      context.lineTo(x, y);
24224    }
24225    function lineEnd() {
24226      stream.point = point;
24227    }
24228    function lineEndPolygon() {
24229      context.closePath();
24230    }
24231    return stream;
24232  }
24233  function d3_geo_resample(project) {
24234    var δ2 = .5, cosMinDistance = Math.cos(30 * d3_radians), maxDepth = 16;
24235    function resample(stream) {
24236      return (maxDepth ? resampleRecursive : resampleNone)(stream);
24237    }
24238    function resampleNone(stream) {
24239      return d3_geo_transformPoint(stream, function(x, y) {
24240        x = project(x, y);
24241        stream.point(x[0], x[1]);
24242      });
24243    }
24244    function resampleRecursive(stream) {
24245      var λ00, φ00, x00, y00, a00, b00, c00, λ0, x0, y0, a0, b0, c0;
24246      var resample = {
24247        point: point,
24248        lineStart: lineStart,
24249        lineEnd: lineEnd,
24250        polygonStart: function() {
24251          stream.polygonStart();
24252          resample.lineStart = ringStart;
24253        },
24254        polygonEnd: function() {
24255          stream.polygonEnd();
24256          resample.lineStart = lineStart;
24257        }
24258      };
24259      function point(x, y) {
24260        x = project(x, y);
24261        stream.point(x[0], x[1]);
24262      }
24263      function lineStart() {
24264        x0 = NaN;
24265        resample.point = linePoint;
24266        stream.lineStart();
24267      }
24268      function linePoint(λ, φ) {
24269        var c = d3_geo_cartesian([ λ, φ ]), p = project(λ, φ);
24270        resampleLineTo(x0, y0, λ0, a0, b0, c0, x0 = p[0], y0 = p[1], λ0 = λ, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream);
24271        stream.point(x0, y0);
24272      }
24273      function lineEnd() {
24274        resample.point = point;
24275        stream.lineEnd();
24276      }
24277      function ringStart() {
24278        lineStart();
24279        resample.point = ringPoint;
24280        resample.lineEnd = ringEnd;
24281      }
24282      function ringPoint(λ, φ) {
24283        linePoint(λ00 = λ, φ00 = φ), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0;
24284        resample.point = linePoint;
24285      }
24286      function ringEnd() {
24287        resampleLineTo(x0, y0, λ0, a0, b0, c0, x00, y00, λ00, a00, b00, c00, maxDepth, stream);
24288        resample.lineEnd = lineEnd;
24289        lineEnd();
24290      }
24291      return resample;
24292    }
24293    function resampleLineTo(x0, y0, λ0, a0, b0, c0, x1, y1, λ1, a1, b1, c1, depth, stream) {
24294      var dx = x1 - x0, dy = y1 - y0, d2 = dx * dx + dy * dy;
24295      if (d2 > 4 * δ2 && depth--) {
24296        var a = a0 + a1, b = b0 + b1, c = c0 + c1, m = Math.sqrt(a * a + b * b + c * c), φ2 = Math.asin(c /= m), λ2 = abs(abs(c) - 1) < ε || abs(λ0 - λ1) < ε ? (λ0 + λ1) / 2 : Math.atan2(b, a), p = project(λ2, φ2), x2 = p[0], y2 = p[1], dx2 = x2 - x0, dy2 = y2 - y0, dz = dy * dx2 - dx * dy2;
24297        if (dz * dz / d2 > δ2 || abs((dx * dx2 + dy * dy2) / d2 - .5) > .3 || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) {
24298          resampleLineTo(x0, y0, λ0, a0, b0, c0, x2, y2, λ2, a /= m, b /= m, c, depth, stream);
24299          stream.point(x2, y2);
24300          resampleLineTo(x2, y2, λ2, a, b, c, x1, y1, λ1, a1, b1, c1, depth, stream);
24301        }
24302      }
24303    }
24304    resample.precision = function(_) {
24305      if (!arguments.length) return Math.sqrt(δ2);
24306      maxDepth = (δ2 = _ * _) > 0 && 16;
24307      return resample;
24308    };
24309    return resample;
24310  }
24311  d3.geo.path = function() {
24312    var pointRadius = 4.5, projection, context, projectStream, contextStream, cacheStream;
24313    function path(object) {
24314      if (object) {
24315        if (typeof pointRadius === "function") contextStream.pointRadius(+pointRadius.apply(this, arguments));
24316        if (!cacheStream || !cacheStream.valid) cacheStream = projectStream(contextStream);
24317        d3.geo.stream(object, cacheStream);
24318      }
24319      return contextStream.result();
24320    }
24321    path.area = function(object) {
24322      d3_geo_pathAreaSum = 0;
24323      d3.geo.stream(object, projectStream(d3_geo_pathArea));
24324      return d3_geo_pathAreaSum;
24325    };
24326    path.centroid = function(object) {
24327      d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0;
24328      d3.geo.stream(object, projectStream(d3_geo_pathCentroid));
24329      return d3_geo_centroidZ2 ? [ d3_geo_centroidX2 / d3_geo_centroidZ2, d3_geo_centroidY2 / d3_geo_centroidZ2 ] : d3_geo_centroidZ1 ? [ d3_geo_centroidX1 / d3_geo_centroidZ1, d3_geo_centroidY1 / d3_geo_centroidZ1 ] : d3_geo_centroidZ0 ? [ d3_geo_centroidX0 / d3_geo_centroidZ0, d3_geo_centroidY0 / d3_geo_centroidZ0 ] : [ NaN, NaN ];
24330    };
24331    path.bounds = function(object) {
24332      d3_geo_pathBoundsX1 = d3_geo_pathBoundsY1 = -(d3_geo_pathBoundsX0 = d3_geo_pathBoundsY0 = Infinity);
24333      d3.geo.stream(object, projectStream(d3_geo_pathBounds));
24334      return [ [ d3_geo_pathBoundsX0, d3_geo_pathBoundsY0 ], [ d3_geo_pathBoundsX1, d3_geo_pathBoundsY1 ] ];
24335    };
24336    path.projection = function(_) {
24337      if (!arguments.length) return projection;
24338      projectStream = (projection = _) ? _.stream || d3_geo_pathProjectStream(_) : d3_identity;
24339      return reset();
24340    };
24341    path.context = function(_) {
24342      if (!arguments.length) return context;
24343      contextStream = (context = _) == null ? new d3_geo_pathBuffer() : new d3_geo_pathContext(_);
24344      if (typeof pointRadius !== "function") contextStream.pointRadius(pointRadius);
24345      return reset();
24346    };
24347    path.pointRadius = function(_) {
24348      if (!arguments.length) return pointRadius;
24349      pointRadius = typeof _ === "function" ? _ : (contextStream.pointRadius(+_), +_);
24350      return path;
24351    };
24352    function reset() {
24353      cacheStream = null;
24354      return path;
24355    }
24356    return path.projection(d3.geo.albersUsa()).context(null);
24357  };
24358  function d3_geo_pathProjectStream(project) {
24359    var resample = d3_geo_resample(function(x, y) {
24360      return project([ x * d3_degrees, y * d3_degrees ]);
24361    });
24362    return function(stream) {
24363      return d3_geo_projectionRadians(resample(stream));
24364    };
24365  }
24366  d3.geo.transform = function(methods) {
24367    return {
24368      stream: function(stream) {
24369        var transform = new d3_geo_transform(stream);
24370        for (var k in methods) transform[k] = methods[k];
24371        return transform;
24372      }
24373    };
24374  };
24375  function d3_geo_transform(stream) {
24376    this.stream = stream;
24377  }
24378  d3_geo_transform.prototype = {
24379    point: function(x, y) {
24380      this.stream.point(x, y);
24381    },
24382    sphere: function() {
24383      this.stream.sphere();
24384    },
24385    lineStart: function() {
24386      this.stream.lineStart();
24387    },
24388    lineEnd: function() {
24389      this.stream.lineEnd();
24390    },
24391    polygonStart: function() {
24392      this.stream.polygonStart();
24393    },
24394    polygonEnd: function() {
24395      this.stream.polygonEnd();
24396    }
24397  };
24398  function d3_geo_transformPoint(stream, point) {
24399    return {
24400      point: point,
24401      sphere: function() {
24402        stream.sphere();
24403      },
24404      lineStart: function() {
24405        stream.lineStart();
24406      },
24407      lineEnd: function() {
24408        stream.lineEnd();
24409      },
24410      polygonStart: function() {
24411        stream.polygonStart();
24412      },
24413      polygonEnd: function() {
24414        stream.polygonEnd();
24415      }
24416    };
24417  }
24418  d3.geo.projection = d3_geo_projection;
24419  d3.geo.projectionMutator = d3_geo_projectionMutator;
24420  function d3_geo_projection(project) {
24421    return d3_geo_projectionMutator(function() {
24422      return project;
24423    })();
24424  }
24425  function d3_geo_projectionMutator(projectAt) {
24426    var project, rotate, projectRotate, projectResample = d3_geo_resample(function(x, y) {
24427      x = project(x, y);
24428      return [ x[0] * k + δx, δy - x[1] * k ];
24429    }), k = 150, x = 480, y = 250, λ = 0, φ = 0, δλ = 0, δφ = 0, δγ = 0, δx, δy, preclip = d3_geo_clipAntimeridian, postclip = d3_identity, clipAngle = null, clipExtent = null, stream;
24430    function projection(point) {
24431      point = projectRotate(point[0] * d3_radians, point[1] * d3_radians);
24432      return [ point[0] * k + δx, δy - point[1] * k ];
24433    }
24434    function invert(point) {
24435      point = projectRotate.invert((point[0] - δx) / k, (δy - point[1]) / k);
24436      return point && [ point[0] * d3_degrees, point[1] * d3_degrees ];
24437    }
24438    projection.stream = function(output) {
24439      if (stream) stream.valid = false;
24440      stream = d3_geo_projectionRadians(preclip(rotate, projectResample(postclip(output))));
24441      stream.valid = true;
24442      return stream;
24443    };
24444    projection.clipAngle = function(_) {
24445      if (!arguments.length) return clipAngle;
24446      preclip = _ == null ? (clipAngle = _, d3_geo_clipAntimeridian) : d3_geo_clipCircle((clipAngle = +_) * d3_radians);
24447      return invalidate();
24448    };
24449    projection.clipExtent = function(_) {
24450      if (!arguments.length) return clipExtent;
24451      clipExtent = _;
24452      postclip = _ ? d3_geo_clipExtent(_[0][0], _[0][1], _[1][0], _[1][1]) : d3_identity;
24453      return invalidate();
24454    };
24455    projection.scale = function(_) {
24456      if (!arguments.length) return k;
24457      k = +_;
24458      return reset();
24459    };
24460    projection.translate = function(_) {
24461      if (!arguments.length) return [ x, y ];
24462      x = +_[0];
24463      y = +_[1];
24464      return reset();
24465    };
24466    projection.center = function(_) {
24467      if (!arguments.length) return [ λ * d3_degrees, φ * d3_degrees ];
24468      λ = _[0] % 360 * d3_radians;
24469      φ = _[1] % 360 * d3_radians;
24470      return reset();
24471    };
24472    projection.rotate = function(_) {
24473      if (!arguments.length) return [ δλ * d3_degrees, δφ * d3_degrees, δγ * d3_degrees ];
24474      δλ = _[0] % 360 * d3_radians;
24475      δφ = _[1] % 360 * d3_radians;
24476      δγ = _.length > 2 ? _[2] % 360 * d3_radians : 0;
24477      return reset();
24478    };
24479    d3.rebind(projection, projectResample, "precision");
24480    function reset() {
24481      projectRotate = d3_geo_compose(rotate = d3_geo_rotation(δλ, δφ, δγ), project);
24482      var center = project(λ, φ);
24483      δx = x - center[0] * k;
24484      δy = y + center[1] * k;
24485      return invalidate();
24486    }
24487    function invalidate() {
24488      if (stream) stream.valid = false, stream = null;
24489      return projection;
24490    }
24491    return function() {
24492      project = projectAt.apply(this, arguments);
24493      projection.invert = project.invert && invert;
24494      return reset();
24495    };
24496  }
24497  function d3_geo_projectionRadians(stream) {
24498    return d3_geo_transformPoint(stream, function(x, y) {
24499      stream.point(x * d3_radians, y * d3_radians);
24500    });
24501  }
24502  function d3_geo_equirectangular(λ, φ) {
24503    return [ λ, φ ];
24504  }
24505  (d3.geo.equirectangular = function() {
24506    return d3_geo_projection(d3_geo_equirectangular);
24507  }).raw = d3_geo_equirectangular.invert = d3_geo_equirectangular;
24508  d3.geo.rotation = function(rotate) {
24509    rotate = d3_geo_rotation(rotate[0] % 360 * d3_radians, rotate[1] * d3_radians, rotate.length > 2 ? rotate[2] * d3_radians : 0);
24510    function forward(coordinates) {
24511      coordinates = rotate(coordinates[0] * d3_radians, coordinates[1] * d3_radians);
24512      return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates;
24513    }
24514    forward.invert = function(coordinates) {
24515      coordinates = rotate.invert(coordinates[0] * d3_radians, coordinates[1] * d3_radians);
24516      return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates;
24517    };
24518    return forward;
24519  };
24520  function d3_geo_identityRotation(λ, φ) {
24521    return [ λ > π ? λ - τ : λ < -π ? λ + τ : λ, φ ];
24522  }
24523  d3_geo_identityRotation.invert = d3_geo_equirectangular;
24524  function d3_geo_rotation(δλ, δφ, δγ) {
24525    return δλ ? δφ || δγ ? d3_geo_compose(d3_geo_rotationλ(δλ
24525), d3_geo_rotationφγ(δφ, δγ)) : d3_geo_rotationλ(δλ) : δφ || δγ ? d3_geo_rotationφγ(δφ, δγ) : d3_geo_identityRotation;
24526  }
24527  function d3_geo_forwardRotationλ(δλ) {
24528    return function(λ, φ) {
24529      return λ += δλ, [ λ > π ? λ - τ : λ < -π ? λ + τ : λ, φ ];
24530    };
24531  }
24532  function d3_geo_rotationλ(δλ) {
24533    var rotation = d3_geo_forwardRotationλ(δλ);
24534    rotation.invert = d3_geo_forwardRotationλ(-δλ);
24535    return rotation;
24536  }
24537  function d3_geo_rotationφγ(δφ, δγ) {
24538    var cosδφ = Math.cos(δφ), sinδφ = Math.sin(δφ), cosδγ = Math.cos(δγ), sinδγ = Math.sin(δγ);
24539    function rotation(λ, φ) {
24540      var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδφ + x * sinδφ;
24541      return [ Math.atan2(y * cosδγ - k * sinδγ, x * cosδφ - z * sinδφ), d3_asin(k * cosδγ + y * sinδγ) ];
24542    }
24543    rotation.invert = function(λ, φ) {
24544      var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδγ - y * sinδγ;
24545      return [ Math.atan2(y * cosδγ + z * sinδγ, x * cosδφ + k * sinδφ), d3_asin(k * cosδφ - x * sinδφ) ];
24546    };
24547    return rotation;
24548  }
24549  d3.geo.circle = function() {
24550    var origin = [ 0, 0 ], angle, precision = 6, interpolate;
24551    function circle() {
24552      var center = typeof origin === "function" ? origin.apply(this, arguments) : origin, rotate = d3_geo_rotation(-center[0] * d3_radians, -center[1] * d3_radians, 0).invert, ring = [];
24553      interpolate(null, null, 1, {
24554        point: function(x, y) {
24555          ring.push(x = rotate(x, y));
24556          x[0] *= d3_degrees, x[1] *= d3_degrees;
24557        }
24558      });
24559      return {
24560        type: "Polygon",
24561        coordinates: [ ring ]
24562      };
24563    }
24564    circle.origin = function(x) {
24565      if (!arguments.length) return origin;
24566      origin = x;
24567      return circle;
24568    };
24569    circle.angle = function(x) {
24570      if (!arguments.length) return angle;
24571      interpolate = d3_geo_circleInterpolate((angle = +x) * d3_radians, precision * d3_radians);
24572      return circle;
24573    };
24574    circle.precision = function(_) {
24575      if (!arguments.length) return precision;
24576      interpolate = d3_geo_circleInterpolate(angle * d3_radians, (precision = +_) * d3_radians);
24577      return circle;
24578    };
24579    return circle.angle(90);
24580  };
24581  function d3_geo_circleInterpolate(radius, precision) {
24582    var cr = Math.cos(radius), sr = Math.sin(radius);
24583    return function(from, to, direction, listener) {
24584      var step = direction * precision;
24585      if (from != null) {
24586        from = d3_geo_circleAngle(cr, from);
24587        to = d3_geo_circleAngle(cr, to);
24588        if (direction > 0 ? from < to : from > to) from += direction * τ;
24589      } else {
24590        from = radius + direction * τ;
24591        to = radius - .5 * step;
24592      }
24593      for (var point, t = from; direction > 0 ? t > to : t < to; t -= step) {
24594        listener.point((point = d3_geo_spherical([ cr, -sr * Math.cos(t), -sr * Math.sin(t) ]))[0], point[1]);
24595      }
24596    };
24597  }
24598  function d3_geo_circleAngle(cr, point) {
24599    var a = d3_geo_cartesian(point);
24600    a[0] -= cr;
24601    d3_geo_cartesianNormalize(a);
24602    var angle = d3_acos(-a[1]);
24603    return ((-a[2] < 0 ? -angle : angle) + 2 * Math.PI - ε) % (2 * Math.PI);
24604  }
24605  d3.geo.distance = function(a, b) {
24606    var Δλ = (b[0] - a[0]) * d3_radians, φ0 = a[1] * d3_radians, φ1 = b[1] * d3_radians, sinΔλ = Math.sin(Δλ), cosΔλ = Math.cos(Δλ), sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), sinφ1 = Math.sin(φ1), cosφ1 = Math.cos(φ1), t;
24607    return Math.atan2(Math.sqrt((t = cosφ1 * sinΔλ) * t + (t = cosφ0 * sinφ1 - sinφ0 * cosφ1 * cosΔλ) * t), sinφ0 * sinφ1 + cosφ0 * cosφ1 * cosΔλ);
24608  };
24609  d3.geo.graticule = function() {
24610    var x1, x0, X1, X0, y1, y0, Y1, Y0, dx = 10, dy = dx, DX = 90, DY = 360, x, y, X, Y, precision = 2.5;
24611    function graticule() {
24612      return {
24613        type: "MultiLineString",
24614        coordinates: lines()
24615      };
24616    }
24617    function lines() {
24618      return d3.range(Math.ceil(X0 / DX) * DX, X1, DX).map(X).concat(d3.range(Math.ceil(Y0 / DY) * DY, Y1, DY).map(Y)).concat(d3.range(Math.ceil(x0 / dx) * dx, x1, dx).filter(function(x) {
24619        return abs(x % DX) > ε;
24620      }).map(x)).concat(d3.range(Math.ceil(y0 / dy) * dy, y1, dy).filter(function(y) {
24621        return abs(y % DY) > ε;
24622      }).map(y));
24623    }
24624    graticule.lines = function() {
24625      return lines().map(function(coordinates) {
24626        return {
24627          type: "LineString",
24628          coordinates: coordinates
24629        };
24630      });
24631    };
24632    graticule.outline = function() {
24633      return {
24634        type: "Polygon",
24635        coordinates: [ X(X0).concat(Y(Y1).slice(1), X(X1).reverse().slice(1), Y(Y0).reverse().slice(1)) ]
24636      };
24637    };
24638    graticule.extent = function(_) {
24639      if (!arguments.length) return graticule.minorExtent();
24640      return graticule.majorExtent(_).minorExtent(_);
24641    };
24642    graticule.majorExtent = function(_) {
24643      if (!arguments.length) return [ [ X0, Y0 ], [ X1, Y1 ] ];
24644      X0 = +_[0][0], X1 = +_[1][0];
24645      Y0 = +_[0][1], Y1 = +_[1][1];
24646      if (X0 > X1) _ = X0, X0 = X1, X1 = _;
24647      if (Y0 > Y1) _ = Y0, Y0 = Y1, Y1 = _;
24648      return graticule.precision(precision);
24649    };
24650    graticule.minorExtent = function(_) {
24651      if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ];
24652      x0 = +_[0][0], x1 = +_[1][0];
24653      y0 = +_[0][1], y1 = +_[1][1];
24654      if (x0 > x1) _ = x0, x0 = x1, x1 = _;
24655      if (y0 > y1) _ = y0, y0 = y1, y1 = _;
24656      return graticule.precision(precision);
24657    };
24658    graticule.step = function(_) {
24659      if (!arguments.length) return graticule.minorStep();
24660      return graticule.majorStep(_).minorStep(_);
24661    };
24662    graticule.majorStep = function(_) {
24663      if (!arguments.length) return [ DX, DY ];
24664      DX = +_[0], DY = +_[1];
24665      return graticule;
24666    };
24667    graticule.minorStep = function(_) {
24668      if (!arguments.length) return [ dx, dy ];
24669      dx = +_[0], dy = +_[1];
24670      return graticule;
24671    };
24672    graticule.precision = function(_) {
24673      if (!arguments.length) return precision;
24674      precision = +_;
24675      x = d3_geo_graticuleX(y0, y1, 90);
24676      y = d3_geo_graticuleY(x0, x1, precision);
24677      X = d3_geo_graticuleX(Y0, Y1, 90);
24678      Y = d3_geo_graticuleY(X0, X1, precision);
24679      return graticule;
24680    };
24681    return graticule.majorExtent([ [ -180, -90 + ε ], [ 180, 90 - ε ] ]).minorExtent([ [ -180, -80 - ε ], [ 180, 80 + ε ] ]);
24682  };
24683  function d3_geo_graticuleX(y0, y1, dy) {
24684    var y = d3.range(y0, y1 - ε, dy).concat(y1);
24685    return function(x) {
24686      return y.map(function(y) {
24687        return [ x, y ];
24688      });
24689    };
24690  }
24691  function d3_geo_graticuleY(x0, x1, dx) {
24692    var x = d3.range(x0, x1 - ε, dx).concat(x1);
24693    return function(y) {
24694      return x.map(function(x) {
24695        return [ x, y ];
24696      });
24697    };
24698  }
24699  function d3_source(d) {
24700    return d.source;
24701  }
24702  function d3_target(d) {
24703    return d.target;
24704  }
24705  d3.geo.greatArc = function() {
24706    var source = d3_source, source_, target = d3_target, target_;
24707    function greatArc() {
24708      return {
24709        type: "LineString",
24710        coordinates: [ source_ || source.apply(this, arguments), target_ || target.apply(this, arguments) ]
24711      };
24712    }
24713    greatArc.distance = function() {
24714      return d3.geo.distance(source_ || source.apply(this, arguments), target_ || target.apply(this, arguments));
24715    };
24716    greatArc.source = function(_) {
24717      if (!arguments.length) return source;
24718      source = _, source_ = typeof _ === "function" ? null : _;
24719      return greatArc;
24720    };
24721    greatArc.target = function(_) {
24722      if (!arguments.length) return target;
24723      target = _, target_ = typeof _ === "function" ? null : _;
24724      return greatArc;
24725    };
24726    greatArc.precision = function() {
24727      return arguments.length ? greatArc : 0;
24728    };
24729    return greatArc;
24730  };
24731  d3.geo.interpolate = function(source, target) {
24732    return d3_geo_interpolate(source[0] * d3_radians, source[1] * d3_radians, target[0] * d3_radians, target[1] * d3_radians);
24733  };
24734  function d3_geo_interpolate(x0, y0, x1, y1) {
24735    var cy0 = Math.cos(y0), sy0 = Math.sin(y0), cy1 = Math.cos(y1), sy1 = Math.sin(y1), kx0 = cy0 * Math.cos(x0), ky0 = cy0 * Math.sin(x0), kx1 = cy1 * Math.cos(x1), ky1 = cy1 * Math.sin(x1), d = 2 * Math.asin(Math.sqrt(d3_haversin(y1 - y0) + cy0 * cy1 * d3_haversin(x1 - x0))), k = 1 / Math.sin(d);
24736    var interpolate = d ? function(t) {
24737      var B = Math.sin(t *= d) * k, A = Math.sin(d - t) * k, x = A * kx0 + B * kx1, y = A * ky0 + B * ky1, z = A * sy0 + B * sy1;
24738      return [ Math.atan2(y, x) * d3_degrees, Math.atan2(z, Math.sqrt(x * x + y * y)) * d3_degrees ];
24739    } : function() {
24740      return [ x0 * d3_degrees, y0 * d3_degrees ];
24741    };
24742    interpolate.distance = d;
24743    return interpolate;
24744  }
24745  d3.geo.length = function(object) {
24746    d3_geo_lengthSum = 0;
24747    d3.geo.stream(object, d3_geo_length);
24748    return d3_geo_lengthSum;
24749  };
24750  var d3_geo_lengthSum;
24751  var d3_geo_length = {
24752    sphere: d3_noop,
24753    point: d3_noop,
24754    lineStart: d3_geo_lengthLineStart,
24755    lineEnd: d3_noop,
24756    polygonStart: d3_noop,
24757    polygonEnd: d3_noop
24758  };
24759  function d3_geo_lengthLineStart() {
24760    var λ0, sinφ0, cosφ0;
24761    d3_geo_length.point = function(λ, φ) {
24762      λ0 = λ * d3_radians, sinφ0 = Math.sin(φ *= d3_radians), cosφ0 = Math.cos(φ);
24763      d3_geo_length.point = nextPoint;
24764    };
24765    d3_geo_length.lineEnd = function() {
24766      d3_geo_length.point = d3_geo_length.lineEnd = d3_noop;
24767    };
24768    function nextPoint(λ, φ) {
24769      var sinφ = Math.sin(φ *= d3_radians), cosφ = Math.cos(φ), t = abs((λ *= d3_radians) - λ0), cosΔλ = Math.cos(t);
24770      d3_geo_lengthSum += Math.atan2(Math.sqrt((t = cosφ * Math.sin(t)) * t + (t = cosφ0 * sinφ - sinφ0 * cosφ * cosΔλ) * t), sinφ0 * sinφ + cosφ0 * cosφ * cosΔλ);
24771      λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ;
24772    }
24773  }
24774  function d3_geo_azimuthal(scale, angle) {
24775    function azimuthal(λ, φ) {
24776      var cosλ = Math.cos(λ), cosφ = Math.cos(φ), k = scale(cosλ * cosφ);
24777      return [ k * cosφ * Math.sin(λ), k * Math.sin(φ) ];
24778    }
24779    azimuthal.invert = function(x, y) {
24780      var ρ = Math.sqrt(x * x + y * y), c = angle(ρ), sinc = Math.sin(c), cosc = Math.cos(c);
24781      return [ Math.atan2(x * sinc, ρ * cosc), Math.asin(ρ && y * sinc / ρ) ];
24782    };
24783    return azimuthal;
24784  }
24785  var d3_geo_azimuthalEqualArea = d3_geo_azimuthal(function(cosλcosφ) {
24786    return Math.sqrt(2 / (1 + cosλcosφ));
24787  }, function(ρ) {
24788    return 2 * Math.asin(ρ / 2);
24789  });
24790  (d3.geo.azimuthalEqualArea = function() {
24791    return d3_geo_projection(d3_geo_azimuthalEqualArea);
24792  }).raw = d3_geo_azimuthalEqualArea;
24793  var d3_geo_azimuthalEquidistant = d3_geo_azimuthal(function(cosλcosφ) {
24794    var c = Math.acos(cosλcosφ);
24795    return c && c / Math.sin(c);
24796  }, d3_identity);
24797  (d3.geo.azimuthalEquidistant = function() {
24798    return d3_geo_projection(d3_geo_azimuthalEquidistant);
24799  }).raw = d3_geo_azimuthalEquidistant;
24800  function d3_geo_conicConformal(φ0, φ1) {
24801    var cosφ0 = Math.cos(φ0), t = function(φ) {
24802      return Math.tan(π / 4 + φ / 2);
24803    }, n = φ0 === φ1 ? Math.sin(φ0) : Math.log(cosφ0 / Math.cos(φ1)) / Math.log(t(φ1) / t(φ0)), F = cosφ0 * Math.pow(t(φ0), n) / n;
24804    if (!n) return d3_geo_mercator;
24805    function forward(λ, φ) {
24806      if (F > 0) {
24807        if (φ < -halfπ + ε) φ = -halfπ + ε;
24808      } else {
24809        if (φ > halfπ - ε) φ = halfπ - ε;
24810      }
24811      var ρ = F / Math.pow(t(φ), n);
24812      return [ ρ * Math.sin(n * λ), F - ρ * Math.cos(n * λ) ];
24813    }
24814    forward.invert = function(x, y) {
24815      var ρ0_y = F - y, ρ = d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y);
24816      return [ Math.atan2(x, ρ0_y) / n, 2 * Math.atan(Math.pow(F / ρ, 1 / n)) - halfπ ];
24817    };
24818    return forward;
24819  }
24820  (d3.geo.conicConformal = function() {
24821    return d3_geo_conic(d3_geo_conicConformal);
24822  }).raw = d3_geo_conicConformal;
24823  function d3_geo_conicEquidistant(φ0, φ1) {
24824    var cosφ0 = Math.cos(φ0), n = φ0 === φ1 ? Math.sin(φ0) : (cosφ0 - Math.cos(φ1)) / (φ1 - φ0), G = cosφ0 / n + φ0;
24825    if (abs(n) < ε) return d3_geo_equirectangular;
24826    function forward(λ, φ) {
24827      var ρ = G - φ;
24828      return [ ρ * Math.sin(n * λ), G - ρ * Math.cos(n * λ) ];
24829    }
24830    forward.invert = function(x, y) {
24831      var ρ0_y = G - y;
24832      return [ Math.atan2(x, ρ0_y) / n, G - d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y) ];
24833    };
24834    return forward;
24835  }
24836  (d3.geo.conicEquidistant = function() {
24837    return d3_geo_conic(d3_geo_conicEquidistant);
24838  }).raw = d3_geo_conicEquidistant;
24839  var d3_geo_gnomonic = d3_geo_azimuthal(function(cosλcosφ) {
24840    return 1 / cosλcosφ;
24841  }, Math.atan);
24842  (d3.geo.gnomonic = function() {
24843    return d3_geo_projection(d3_geo_gnomonic);
24844  }).raw = d3_geo_gnomonic;
24845  function d3_geo_mercator(λ, φ) {
24846    return [ λ, Math.log(Math.tan(π / 4 + φ / 2)) ];
24847  }
24848  d3_geo_mercator.invert = function(x, y) {
24849    return [ x, 2 * Math.atan(Math.exp(y)) - halfπ ];
24850  };
24851  function d3_geo_mercatorProjection(project) {
24852    var m = d3_geo_projection(project), scale = m.scale, translate = m.translate, clipExtent = m.clipExtent, clipAuto;
24853    m.scale = function() {
24854      var v = scale.apply(m, arguments);
24855      return v === m ? clipAuto ? m.clipExtent(null) : m : v;
24856    };
24857    m.translate = function() {
24858      var v = translate.apply(m, arguments);
24859      return v === m ? clipAuto ? m.clipExtent(null) : m : v;
24860    };
24861    m.clipExtent = function(_) {
24862      var v = clipExtent.apply(m, arguments);
24863      if (v === m) {
24864        if (clipAuto = _ == null) {
24865          var k = π * scale(), t = translate();
24866          clipExtent([ [ t[0] - k, t[1] - k ], [ t[0] + k, t[1] + k ] ]);
24867        }
24868      } else if (clipAuto) {
24869        v = null;
24870      }
24871      return v;
24872    };
24873    return m.clipExtent(null);
24874  }
24875  (d3.geo.mercator = function() {
24876    return d3_geo_mercatorProjection(d3_geo_mercator);
24877  }).raw = d3_geo_mercator;
24878  var d3_geo_orthographic = d3_geo_azimuthal(function() {
24879    return 1;
24880  }, Math.asin);
24881  (d3.geo.orthographic = function() {
24882    return d3_geo_projection(d3_geo_orthographic);
24883  }).raw = d3_geo_orthographic;
24884  var d3_geo_stereographic = d3_geo_azimuthal(function(cosλcosφ) {
24885    return 1 / (1 + cosλcosφ);
24886  }, function(ρ) {
24887    return 2 * Math.atan(ρ);
24888  });
24889  (d3.geo.stereographic = function() {
24890    return d3_geo_projection(d3_geo_stereographic);
24891  }).raw = d3_geo_stereographic;
24892  function d3_geo_transverseMercator(λ, φ) {
24893    return [ Math.log(Math.tan(π / 4 + φ / 2)), -λ ];
24894  }
24895  d3_geo_transverseMercator.invert = function(x, y) {
24896    return [ -y, 2 * Math.atan(Math.exp(x)) - halfπ ];
24897  };
24898  (d3.geo.transverseMercator = function() {
24899    var projection = d3_geo_mercatorProjection(d3_geo_transverseMercator), center = projection.center, rotate = projection.rotate;
24900    projection.center = function(_) {
24901      return _ ? center([ -_[1], _[0] ]) : (_ = center(), [ _[1], -_[0] ]);
24902    };
24903    projection.rotate = function(_) {
24904      return _ ? rotate([ _[0], _[1], _.length > 2 ? _[2] + 90 : 90 ]) : (_ = rotate(), 
24905      [ _[0], _[1], _[2] - 90 ]);
24906    };
24907    return rotate([ 0, 0, 90 ]);
24908  }).raw = d3_geo_transverseMercator;
24909  d3.geom = {};
24910  function d3_geom_pointX(d) {
24911    return d[0];
24912  }
24913  function d3_geom_pointY(d) {
24914    return d[1];
24915  }
24916  d3.geom.hull = function(vertices) {
24917    var x = d3_geom_pointX, y = d3_geom_pointY;
24918    if (arguments.length) return hull(vertices);
24919    function hull(data) {
24920      if (data.length < 3) return [];
24921      var fx = d3_functor(x), fy = d3_functor(y), i, n = data.length, points = [], flippedPoints = [];
24922      for (i = 0; i < n; i++) {
24923        points.push([ +fx.call(this, data[i], i), +fy.call(this, data[i], i), i ]);
24924      }
24925      points.sort(d3_geom_hullOrder);
24926      for (i = 0; i < n; i++) flippedPoints.push([ points[i][0], -points[i][1] ]);
24927      var upper = d3_geom_hullUpper(points), lower = d3_geom_hullUpper(flippedPoints);
24928      var skipLeft = lower[0] === upper[0], skipRight = lower[lower.length - 1] === upper[upper.length - 1], pol
vendor: 23,510 bytes, lines 24928-25623
24928ygon = [];
24929      for (i = upper.length - 1; i >= 0; --i) polygon.push(data[points[upper[i]][2]]);
24930      for (i = +skipLeft; i < lower.length - skipRight; ++i) polygon.push(data[points[lower[i]][2]]);
24931      return polygon;
24932    }
24933    hull.x = function(_) {
24934      return arguments.length ? (x = _, hull) : x;
24935    };
24936    hull.y = function(_) {
24937      return arguments.length ? (y = _, hull) : y;
24938    };
24939    return hull;
24940  };
24941  function d3_geom_hullUpper(points) {
24942    var n = points.length, hull = [ 0, 1 ], hs = 2;
24943    for (var i = 2; i < n; i++) {
24944      while (hs > 1 && d3_cross2d(points[hull[hs - 2]], points[hull[hs - 1]], points[i]) <= 0) --hs;
24945      hull[hs++] = i;
24946    }
24947    return hull.slice(0, hs);
24948  }
24949  function d3_geom_hullOrder(a, b) {
24950    return a[0] - b[0] || a[1] - b[1];
24951  }
24952  d3.geom.polygon = function(coordinates) {
24953    d3_subclass(coordinates, d3_geom_polygonPrototype);
24954    return coordinates;
24955  };
24956  var d3_geom_polygonPrototype = d3.geom.polygon.prototype = [];
24957  d3_geom_polygonPrototype.area = function() {
24958    var i = -1, n = this.length, a, b = this[n - 1], area = 0;
24959    while (++i < n) {
24960      a = b;
24961      b = this[i];
24962      area += a[1] * b[0] - a[0] * b[1];
24963    }
24964    return area * .5;
24965  };
24966  d3_geom_polygonPrototype.centroid = function(k) {
24967    var i = -1, n = this.length, x = 0, y = 0, a, b = this[n - 1], c;
24968    if (!arguments.length) k = -1 / (6 * this.area());
24969    while (++i < n) {
24970      a = b;
24971      b = this[i];
24972      c = a[0] * b[1] - b[0] * a[1];
24973      x += (a[0] + b[0]) * c;
24974      y += (a[1] + b[1]) * c;
24975    }
24976    return [ x * k, y * k ];
24977  };
24978  d3_geom_polygonPrototype.clip = function(subject) {
24979    var input, closed = d3_geom_polygonClosed(subject), i = -1, n = this.length - d3_geom_polygonClosed(this), j, m, a = this[n - 1], b, c, d;
24980    while (++i < n) {
24981      input = subject.slice();
24982      subject.length = 0;
24983      b = this[i];
24984      c = input[(m = input.length - closed) - 1];
24985      j = -1;
24986      while (++j < m) {
24987        d = input[j];
24988        if (d3_geom_polygonInside(d, a, b)) {
24989          if (!d3_geom_polygonInside(c, a, b)) {
24990            subject.push(d3_geom_polygonIntersect(c, d, a, b));
24991          }
24992          subject.push(d);
24993        } else if (d3_geom_polygonInside(c, a, b)) {
24994          subject.push(d3_geom_polygonIntersect(c, d, a, b));
24995        }
24996        c = d;
24997      }
24998      if (closed) subject.push(subject[0]);
24999      a = b;
25000    }
25001    return subject;
25002  };
25003  function d3_geom_polygonInside(p, a, b) {
25004    return (b[0] - a[0]) * (p[1] - a[1]) < (b[1] - a[1]) * (p[0] - a[0]);
25005  }
25006  function d3_geom_polygonIntersect(c, d, a, b) {
25007    var x1 = c[0], x3 = a[0], x21 = d[0] - x1, x43 = b[0] - x3, y1 = c[1], y3 = a[1], y21 = d[1] - y1, y43 = b[1] - y3, ua = (x43 * (y1 - y3) - y43 * (x1 - x3)) / (y43 * x21 - x43 * y21);
25008    return [ x1 + ua * x21, y1 + ua * y21 ];
25009  }
25010  function d3_geom_polygonClosed(coordinates) {
25011    var a = coordinates[0], b = coordinates[coordinates.length - 1];
25012    return !(a[0] - b[0] || a[1] - b[1]);
25013  }
25014  var d3_geom_voronoiEdges, d3_geom_voronoiCells, d3_geom_voronoiBeaches, d3_geom_voronoiBeachPool = [], d3_geom_voronoiFirstCircle, d3_geom_voronoiCircles, d3_geom_voronoiCirclePool = [];
25015  function d3_geom_voronoiBeach() {
25016    d3_geom_voronoiRedBlackNode(this);
25017    this.edge = this.site = this.circle = null;
25018  }
25019  function d3_geom_voronoiCreateBeach(site) {
25020    var beach = d3_geom_voronoiBeachPool.pop() || new d3_geom_voronoiBeach();
25021    beach.site = site;
25022    return beach;
25023  }
25024  function d3_geom_voronoiDetachBeach(beach) {
25025    d3_geom_voronoiDetachCircle(beach);
25026    d3_geom_voronoiBeaches.remove(beach);
25027    d3_geom_voronoiBeachPool.push(beach);
25028    d3_geom_voronoiRedBlackNode(beach);
25029  }
25030  function d3_geom_voronoiRemoveBeach(beach) {
25031    var circle = beach.circle, x = circle.x, y = circle.cy, vertex = {
25032      x: x,
25033      y: y
25034    }, previous = beach.P, next = beach.N, disappearing = [ beach ];
25035    d3_geom_voronoiDetachBeach(beach);
25036    var lArc = previous;
25037    while (lArc.circle && abs(x - lArc.circle.x) < ε && abs(y - lArc.circle.cy) < ε) {
25038      previous = lArc.P;
25039      disappearing.unshift(lArc);
25040      d3_geom_voronoiDetachBeach(lArc);
25041      lArc = previous;
25042    }
25043    disappearing.unshift(lArc);
25044    d3_geom_voronoiDetachCircle(lArc);
25045    var rArc = next;
25046    while (rArc.circle && abs(x - rArc.circle.x) < ε && abs(y - rArc.circle.cy) < ε) {
25047      next = rArc.N;
25048      disappearing.push(rArc);
25049      d3_geom_voronoiDetachBeach(rArc);
25050      rArc = next;
25051    }
25052    disappearing.push(rArc);
25053    d3_geom_voronoiDetachCircle(rArc);
25054    var nArcs = disappearing.length, iArc;
25055    for (iArc = 1; iArc < nArcs; ++iArc) {
25056      rArc = disappearing[iArc];
25057      lArc = disappearing[iArc - 1];
25058      d3_geom_voronoiSetEdgeEnd(rArc.edge, lArc.site, rArc.site, vertex);
25059    }
25060    lArc = disappearing[0];
25061    rArc = disappearing[nArcs - 1];
25062    rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, rArc.site, null, vertex);
25063    d3_geom_voronoiAttachCircle(lArc);
25064    d3_geom_voronoiAttachCircle(rArc);
25065  }
25066  function d3_geom_voronoiAddBeach(site) {
25067    var x = site.x, directrix = site.y, lArc, rArc, dxl, dxr, node = d3_geom_voronoiBeaches._;
25068    while (node) {
25069      dxl = d3_geom_voronoiLeftBreakPoint(node, directrix) - x;
25070      if (dxl > ε) node = node.L; else {
25071        dxr = x - d3_geom_voronoiRightBreakPoint(node, directrix);
25072        if (dxr > ε) {
25073          if (!node.R) {
25074            lArc = node;
25075            break;
25076          }
25077          node = node.R;
25078        } else {
25079          if (dxl > -ε) {
25080            lArc = node.P;
25081            rArc = node;
25082          } else if (dxr > -ε) {
25083            lArc = node;
25084            rArc = node.N;
25085          } else {
25086            lArc = rArc = node;
25087          }
25088          break;
25089        }
25090      }
25091    }
25092    var newArc = d3_geom_voronoiCreateBeach(site);
25093    d3_geom_voronoiBeaches.insert(lArc, newArc);
25094    if (!lArc && !rArc) return;
25095    if (lArc === rArc) {
25096      d3_geom_voronoiDetachCircle(lArc);
25097      rArc = d3_geom_voronoiCreateBeach(lArc.site);
25098      d3_geom_voronoiBeaches.insert(newArc, rArc);
25099      newArc.edge = rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site);
25100      d3_geom_voronoiAttachCircle(lArc);
25101      d3_geom_voronoiAttachCircle(rArc);
25102      return;
25103    }
25104    if (!rArc) {
25105      newArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site);
25106      return;
25107    }
25108    d3_geom_voronoiDetachCircle(lArc);
25109    d3_geom_voronoiDetachCircle(rArc);
25110    var lSite = lArc.site, ax = lSite.x, ay = lSite.y, bx = site.x - ax, by = site.y - ay, rSite = rArc.site, cx = rSite.x - ax, cy = rSite.y - ay, d = 2 * (bx * cy - by * cx), hb = bx * bx + by * by, hc = cx * cx + cy * cy, vertex = {
25111      x: (cy * hb - by * hc) / d + ax,
25112      y: (bx * hc - cx * hb) / d + ay
25113    };
25114    d3_geom_voronoiSetEdgeEnd(rArc.edge, lSite, rSite, vertex);
25115    newArc.edge = d3_geom_voronoiCreateEdge(lSite, site, null, vertex);
25116    rArc.edge = d3_geom_voronoiCreateEdge(site, rSite, null, vertex);
25117    d3_geom_voronoiAttachCircle(lArc);
25118    d3_geom_voronoiAttachCircle(rArc);
25119  }
25120  function d3_geom_voronoiLeftBreakPoint(arc, directrix) {
25121    var site = arc.site, rfocx = site.x, rfocy = site.y, pby2 = rfocy - directrix;
25122    if (!pby2) return rfocx;
25123    var lArc = arc.P;
25124    if (!lArc) return -Infinity;
25125    site = lArc.site;
25126    var lfocx = site.x, lfocy = site.y, plby2 = lfocy - directrix;
25127    if (!plby2) return lfocx;
25128    var hl = lfocx - rfocx, aby2 = 1 / pby2 - 1 / plby2, b = hl / plby2;
25129    if (aby2) return (-b + Math.sqrt(b * b - 2 * aby2 * (hl * hl / (-2 * plby2) - lfocy + plby2 / 2 + rfocy - pby2 / 2))) / aby2 + rfocx;
25130    return (rfocx + lfocx) / 2;
25131  }
25132  function d3_geom_voronoiRightBreakPoint(arc, directrix) {
25133    var rArc = arc.N;
25134    if (rArc) return d3_geom_voronoiLeftBreakPoint(rArc, directrix);
25135    var site = arc.site;
25136    return site.y === directrix ? site.x : Infinity;
25137  }
25138  function d3_geom_voronoiCell(site) {
25139    this.site = site;
25140    this.edges = [];
25141  }
25142  d3_geom_voronoiCell.prototype.prepare = function() {
25143    var halfEdges = this.edges, iHalfEdge = halfEdges.length, edge;
25144    while (iHalfEdge--) {
25145      edge = halfEdges[iHalfEdge].edge;
25146      if (!edge.b || !edge.a) halfEdges.splice(iHalfEdge, 1);
25147    }
25148    halfEdges.sort(d3_geom_voronoiHalfEdgeOrder);
25149    return halfEdges.length;
25150  };
25151  function d3_geom_voronoiCloseCells(extent) {
25152    var x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], x2, y2, x3, y3, cells = d3_geom_voronoiCells, iCell = cells.length, cell, iHalfEdge, halfEdges, nHalfEdges, start, end;
25153    while (iCell--) {
25154      cell = cells[iCell];
25155      if (!cell || !cell.prepare()) continue;
25156      halfEdges = cell.edges;
25157      nHalfEdges = halfEdges.length;
25158      iHalfEdge = 0;
25159      while (iHalfEdge < nHalfEdges) {
25160        end = halfEdges[iHalfEdge].end(), x3 = end.x, y3 = end.y;
25161        start = halfEdges[++iHalfEdge % nHalfEdges].start(), x2 = start.x, y2 = start.y;
25162        if (abs(x3 - x2) > ε || abs(y3 - y2) > ε) {
25163          halfEdges.splice(iHalfEdge, 0, new d3_geom_voronoiHalfEdge(d3_geom_voronoiCreateBorderEdge(cell.site, end, abs(x3 - x0) < ε && y1 - y3 > ε ? {
25164            x: x0,
25165            y: abs(x2 - x0) < ε ? y2 : y1
25166          } : abs(y3 - y1) < ε && x1 - x3 > ε ? {
25167            x: abs(y2 - y1) < ε ? x2 : x1,
25168            y: y1
25169          } : abs(x3 - x1) < ε && y3 - y0 > ε ? {
25170            x: x1,
25171            y: abs(x2 - x1) < ε ? y2 : y0
25172          } : abs(y3 - y0) < ε && x3 - x0 > ε ? {
25173            x: abs(y2 - y0) < ε ? x2 : x0,
25174            y: y0
25175          } : null), cell.site, null));
25176          ++nHalfEdges;
25177        }
25178      }
25179    }
25180  }
25181  function d3_geom_voronoiHalfEdgeOrder(a, b) {
25182    return b.angle - a.angle;
25183  }
25184  function d3_geom_voronoiCircle() {
25185    d3_geom_voronoiRedBlackNode(this);
25186    this.x = this.y = this.arc = this.site = this.cy = null;
25187  }
25188  function d3_geom_voronoiAttachCircle(arc) {
25189    var lArc = arc.P, rArc = arc.N;
25190    if (!lArc || !rArc) return;
25191    var lSite = lArc.site, cSite = arc.site, rSite = rArc.site;
25192    if (lSite === rSite) return;
25193    var bx = cSite.x, by = cSite.y, ax = lSite.x - bx, ay = lSite.y - by, cx = rSite.x - bx, cy = rSite.y - by;
25194    var d = 2 * (ax * cy - ay * cx);
25195    if (d >= -ε2) return;
25196    var ha = ax * ax + ay * ay, hc = cx * cx + cy * cy, x = (cy * ha - ay * hc) / d, y = (ax * hc - cx * ha) / d, cy = y + by;
25197    var circle = d3_geom_voronoiCirclePool.pop() || new d3_geom_voronoiCircle();
25198    circle.arc = arc;
25199    circle.site = cSite;
25200    circle.x = x + bx;
25201    circle.y = cy + Math.sqrt(x * x + y * y);
25202    circle.cy = cy;
25203    arc.circle = circle;
25204    var before = null, node = d3_geom_voronoiCircles._;
25205    while (node) {
25206      if (circle.y < node.y || circle.y === node.y && circle.x <= node.x) {
25207        if (node.L) node = node.L; else {
25208          before = node.P;
25209          break;
25210        }
25211      } else {
25212        if (node.R) node = node.R; else {
25213          before = node;
25214          break;
25215        }
25216      }
25217    }
25218    d3_geom_voronoiCircles.insert(before, circle);
25219    if (!before) d3_geom_voronoiFirstCircle = circle;
25220  }
25221  function d3_geom_voronoiDetachCircle(arc) {
25222    var circle = arc.circle;
25223    if (circle) {
25224      if (!circle.P) d3_geom_voronoiFirstCircle = circle.N;
25225      d3_geom_voronoiCircles.remove(circle);
25226      d3_geom_voronoiCirclePool.push(circle);
25227      d3_geom_voronoiRedBlackNode(circle);
25228      arc.circle = null;
25229    }
25230  }
25231  function d3_geom_voronoiClipEdges(extent) {
25232    var edges = d3_geom_voronoiEdges, clip = d3_geom_clipLine(extent[0][0], extent[0][1], extent[1][0], extent[1][1]), i = edges.length, e;
25233    while (i--) {
25234      e = edges[i];
25235      if (!d3_geom_voronoiConnectEdge(e, extent) || !clip(e) || abs(e.a.x - e.b.x) < ε && abs(e.a.y - e.b.y) < ε) {
25236        e.a = e.b = null;
25237        edges.splice(i, 1);
25238      }
25239    }
25240  }
25241  function d3_geom_voronoiConnectEdge(edge, extent) {
25242    var vb = edge.b;
25243    if (vb) return true;
25244    var va = edge.a, x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], lSite = edge.l, rSite = edge.r, lx = lSite.x, ly = lSite.y, rx = rSite.x, ry = rSite.y, fx = (lx + rx) / 2, fy = (ly + ry) / 2, fm, fb;
25245    if (ry === ly) {
25246      if (fx < x0 || fx >= x1) return;
25247      if (lx > rx) {
25248        if (!va) va = {
25249          x: fx,
25250          y: y0
25251        }; else if (va.y >= y1) return;
25252        vb = {
25253          x: fx,
25254          y: y1
25255        };
25256      } else {
25257        if (!va) va = {
25258          x: fx,
25259          y: y1
25260        }; else if (va.y < y0) return;
25261        vb = {
25262          x: fx,
25263          y: y0
25264        };
25265      }
25266    } else {
25267      fm = (lx - rx) / (ry - ly);
25268      fb = fy - fm * fx;
25269      if (fm < -1 || fm > 1) {
25270        if (lx > rx) {
25271          if (!va) va = {
25272            x: (y0 - fb) / fm,
25273            y: y0
25274          }; else if (va.y >= y1) return;
25275          vb = {
25276            x: (y1 - fb) / fm,
25277            y: y1
25278          };
25279        } else {
25280          if (!va) va = {
25281            x: (y1 - fb) / fm,
25282            y: y1
25283          }; else if (va.y < y0) return;
25284          vb = {
25285            x: (y0 - fb) / fm,
25286            y: y0
25287          };
25288        }
25289      } else {
25290        if (ly < ry) {
25291          if (!va) va = {
25292            x: x0,
25293            y: fm * x0 + fb
25294          }; else if (va.x >= x1) return;
25295          vb = {
25296            x: x1,
25297            y: fm * x1 + fb
25298          };
25299        } else {
25300          if (!va) va = {
25301            x: x1,
25302            y: fm * x1 + fb
25303          }; else if (va.x < x0) return;
25304          vb = {
25305            x: x0,
25306            y: fm * x0 + fb
25307          };
25308        }
25309      }
25310    }
25311    edge.a = va;
25312    edge.b = vb;
25313    return true;
25314  }
25315  function d3_geom_voronoiEdge(lSite, rSite) {
25316    this.l = lSite;
25317    this.r = rSite;
25318    this.a = this.b = null;
25319  }
25320  function d3_geom_voronoiCreateEdge(lSite, rSite, va, vb) {
25321    var edge = new d3_geom_voronoiEdge(lSite, rSite);
25322    d3_geom_voronoiEdges.push(edge);
25323    if (va) d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, va);
25324    if (vb) d3_geom_voronoiSetEdgeEnd(edge, rSite, lSite, vb);
25325    d3_geom_voronoiCells[lSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, lSite, rSite));
25326    d3_geom_voronoiCells[rSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, rSite, lSite));
25327    return edge;
25328  }
25329  function d3_geom_voronoiCreateBorderEdge(lSite, va, vb) {
25330    var edge = new d3_geom_voronoiEdge(lSite, null);
25331    edge.a = va;
25332    edge.b = vb;
25333    d3_geom_voronoiEdges.push(edge);
25334    return edge;
25335  }
25336  function d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, vertex) {
25337    if (!edge.a && !edge.b) {
25338      edge.a = vertex;
25339      edge.l = lSite;
25340      edge.r = rSite;
25341    } else if (edge.l === rSite) {
25342      edge.b = vertex;
25343    } else {
25344      edge.a = vertex;
25345    }
25346  }
25347  function d3_geom_voronoiHalfEdge(edge, lSite, rSite) {
25348    var va = edge.a, vb = edge.b;
25349    this.edge = edge;
25350    this.site = lSite;
25351    this.angle = rSite ? Math.atan2(rSite.y - lSite.y, rSite.x - lSite.x) : edge.l === lSite ? Math.atan2(vb.x - va.x, va.y - vb.y) : Math.atan2(va.x - vb.x, vb.y - va.y);
25352  }
25353  d3_geom_voronoiHalfEdge.prototype = {
25354    start: function() {
25355      return this.edge.l === this.site ? this.edge.a : this.edge.b;
25356    },
25357    end: function() {
25358      return this.edge.l === this.site ? this.edge.b : this.edge.a;
25359    }
25360  };
25361  function d3_geom_voronoiRedBlackTree() {
25362    this._ = null;
25363  }
25364  function d3_geom_voronoiRedBlackNode(node) {
25365    node.U = node.C = node.L = node.R = node.P = node.N = null;
25366  }
25367  d3_geom_voronoiRedBlackTree.prototype = {
25368    insert: function(after, node) {
25369      var parent, grandpa, uncle;
25370      if (after) {
25371        node.P = after;
25372        node.N = after.N;
25373        if (after.N) after.N.P = node;
25374        after.N = node;
25375        if (after.R) {
25376          after = after.R;
25377          while (after.L) after = after.L;
25378          after.L = node;
25379        } else {
25380          after.R = node;
25381        }
25382        parent = after;
25383      } else if (this._) {
25384        after = d3_geom_voronoiRedBlackFirst(this._);
25385        node.P = null;
25386        node.N = after;
25387        after.P = after.L = node;
25388        parent = after;
25389      } else {
25390        node.P = node.N = null;
25391        this._ = node;
25392        parent = null;
25393      }
25394      node.L = node.R = null;
25395      node.U = parent;
25396      node.C = true;
25397      after = node;
25398      while (parent && parent.C) {
25399        grandpa = parent.U;
25400        if (parent === grandpa.L) {
25401          uncle = grandpa.R;
25402          if (uncle && uncle.C) {
25403            parent.C = uncle.C = false;
25404            grandpa.C = true;
25405            after = grandpa;
25406          } else {
25407            if (after === parent.R) {
25408              d3_geom_voronoiRedBlackRotateLeft(this, parent);
25409              after = parent;
25410              parent = after.U;
25411            }
25412            parent.C = false;
25413            grandpa.C = true;
25414            d3_geom_voronoiRedBlackRotateRight(this, grandpa);
25415          }
25416        } else {
25417          uncle = grandpa.L;
25418          if (uncle && uncle.C) {
25419            parent.C = uncle.C = false;
25420            grandpa.C = true;
25421            after = grandpa;
25422          } else {
25423            if (after === parent.L) {
25424              d3_geom_voronoiRedBlackRotateRight(this, parent);
25425              after = parent;
25426              parent = after.U;
25427            }
25428            parent.C = false;
25429            grandpa.C = true;
25430            d3_geom_voronoiRedBlackRotateLeft(this, grandpa);
25431          }
25432        }
25433        parent = after.U;
25434      }
25435      this._.C = false;
25436    },
25437    remove: function(node) {
25438      if (node.N) node.N.P = node.P;
25439      if (node.P) node.P.N = node.N;
25440      node.N = node.P = null;
25441      var parent = node.U, sibling, left = node.L, right = node.R, next, red;
25442      if (!left) next = right; else if (!right) next = left; else next = d3_geom_voronoiRedBlackFirst(right);
25443      if (parent) {
25444        if (parent.L === node) parent.L = next; else parent.R = next;
25445      } else {
25446        this._ = next;
25447      }
25448      if (left && right) {
25449        red = next.C;
25450        next.C = node.C;
25451        next.L = left;
25452        left.U = next;
25453        if (next !== right) {
25454          parent = next.U;
25455          next.U = node.U;
25456          node = next.R;
25457          parent.L = node;
25458          next.R = right;
25459          right.U = next;
25460        } else {
25461          next.U = parent;
25462          parent = next;
25463          node = next.R;
25464        }
25465      } else {
25466        red = node.C;
25467        node = next;
25468      }
25469      if (node) node.U = parent;
25470      if (red) return;
25471      if (node && node.C) {
25472        node.C = false;
25473        return;
25474      }
25475      do {
25476        if (node === this._) break;
25477        if (node === parent.L) {
25478          sibling = parent.R;
25479          if (sibling.C) {
25480            sibling.C = false;
25481            parent.C = true;
25482            d3_geom_voronoiRedBlackRotateLeft(this, parent);
25483            sibling = parent.R;
25484          }
25485          if (sibling.L && sibling.L.C || sibling.R && sibling.R.C) {
25486            if (!sibling.R || !sibling.R.C) {
25487              sibling.L.C = false;
25488              sibling.C = true;
25489              d3_geom_voronoiRedBlackRotateRight(this, sibling);
25490              sibling = parent.R;
25491            }
25492            sibling.C = parent.C;
25493            parent.C = sibling.R.C = false;
25494            d3_geom_voronoiRedBlackRotateLeft(this, parent);
25495            node = this._;
25496            break;
25497          }
25498        } else {
25499          sibling = parent.L;
25500          if (sibling.C) {
25501            sibling.C = false;
25502            parent.C = true;
25503            d3_geom_voronoiRedBlackRotateRight(this, parent);
25504            sibling = parent.L;
25505          }
25506          if (sibling.L && sibling.L.C || sibling.R && sibling.R.C) {
25507            if (!sibling.L || !sibling.L.C) {
25508              sibling.R.C = false;
25509              sibling.C = true;
25510              d3_geom_voronoiRedBlackRotateLeft(this, sibling);
25511              sibling = parent.L;
25512            }
25513            sibling.C = parent.C;
25514            parent.C = sibling.L.C = false;
25515            d3_geom_voronoiRedBlackRotateRight(this, parent);
25516            node = this._;
25517            break;
25518          }
25519        }
25520        sibling.C = true;
25521        node = parent;
25522        parent = parent.U;
25523      } while (!node.C);
25524      if (node) node.C = false;
25525    }
25526  };
25527  function d3_geom_voronoiRedBlackRotateLeft(tree, node) {
25528    var p = node, q = node.R, parent = p.U;
25529    if (parent) {
25530      if (parent.L === p) parent.L = q; else parent.R = q;
25531    } else {
25532      tree._ = q;
25533    }
25534    q.U = parent;
25535    p.U = q;
25536    p.R = q.L;
25537    if (p.R) p.R.U = p;
25538    q.L = p;
25539  }
25540  function d3_geom_voronoiRedBlackRotateRight(tree, node) {
25541    var p = node, q = node.L, parent = p.U;
25542    if (parent) {
25543      if (parent.L === p) parent.L = q; else parent.R = q;
25544    } else {
25545      tree._ = q;
25546    }
25547    q.U = parent;
25548    p.U = q;
25549    p.L = q.R;
25550    if (p.L) p.L.U = p;
25551    q.R = p;
25552  }
25553  function d3_geom_voronoiRedBlackFirst(node) {
25554    while (node.L) node = node.L;
25555    return node;
25556  }
25557  function d3_geom_voronoi(sites, bbox) {
25558    var site = sites.sort(d3_geom_voronoiVertexOrder).pop(), x0, y0, circle;
25559    d3_geom_voronoiEdges = [];
25560    d3_geom_voronoiCells = new Array(sites.length);
25561    d3_geom_voronoiBeaches = new d3_geom_voronoiRedBlackTree();
25562    d3_geom_voronoiCircles = new d3_geom_voronoiRedBlackTree();
25563    while (true) {
25564      circle = d3_geom_voronoiFirstCircle;
25565      if (site && (!circle || site.y < circle.y || site.y === circle.y && site.x < circle.x)) {
25566        if (site.x !== x0 || site.y !== y0) {
25567          d3_geom_voronoiCells[site.i] = new d3_geom_voronoiCell(site);
25568          d3_geom_voronoiAddBeach(site);
25569          x0 = site.x, y0 = site.y;
25570        }
25571        site = sites.pop();
25572      } else if (circle) {
25573        d3_geom_voronoiRemoveBeach(circle.arc);
25574      } else {
25575        break;
25576      }
25577    }
25578    if (bbox) d3_geom_voronoiClipEdges(bbox), d3_geom_voronoiCloseCells(bbox);
25579    var diagram = {
25580      cells: d3_geom_voronoiCells,
25581      edges: d3_geom_voronoiEdges
25582    };
25583    d3_geom_voronoiBeaches = d3_geom_voronoiCircles = d3_geom_voronoiEdges = d3_geom_voronoiCells = null;
25584    return diagram;
25585  }
25586  function d3_geom_voronoiVertexOrder(a, b) {
25587    return b.y - a.y || b.x - a.x;
25588  }
25589  d3.geom.voronoi = function(points) {
25590    var x = d3_geom_pointX, y = d3_geom_pointY, fx = x, fy = y, clipExtent = d3_geom_voronoiClipExtent;
25591    if (points) return voronoi(points);
25592    function voronoi(data) {
25593      var polygons = new Array(data.length), x0 = clipExtent[0][0], y0 = clipExtent[0][1], x1 = clipExtent[1][0], y1 = clipExtent[1][1];
25594      d3_geom_voronoi(sites(data), clipExtent).cells.forEach(function(cell, i) {
25595        var edges = cell.edges, site = cell.site, polygon = polygons[i] = edges.length ? edges.map(function(e) {
25596          var s = e.start();
25597          return [ s.x, s.y ];
25598        }) : site.x >= x0 && site.x <= x1 && site.y >= y0 && site.y <= y1 ? [ [ x0, y1 ], [ x1, y1 ], [ x1, y0 ], [ x0, y0 ] ] : [];
25599        polygon.point = data[i];
25600      });
25601      return polygons;
25602    }
25603    function sites(data) {
25604      return data.map(function(d, i) {
25605        return {
25606          x: Math.round(fx(d, i) / ε) * ε,
25607          y: Math.round(fy(d, i) / ε) * ε,
25608          i: i
25609        };
25610      });
25611    }
25612    voronoi.links = function(data) {
25613      return d3_geom_voronoi(sites(data)).edges.filter(function(edge) {
25614        return edge.l && edge.r;
25615      }).map(function(edge) {
25616        return {
25617          source: data[edge.l.i],
25618          target: data[edge.r.i]
25619        };
25620      });
25621    };
25622    voronoi.triangles = function(data) {
25623      var triangles = [];
vendor: 5,984 bytes, lines 25624-25791
25624      d3_geom_voronoi(sites(data)).cells.forEach(function(cell, i) {
25625        var site = cell.site, edges = cell.edges.sort(d3_geom_voronoiHalfEdgeOrder), j = -1, m = edges.length, e0, s0, e1 = edges[m - 1].edge, s1 = e1.l === site ? e1.r : e1.l;
25626        while (++j < m) {
25627          e0 = e1;
25628          s0 = s1;
25629          e1 = edges[j].edge;
25630          s1 = e1.l === site ? e1.r : e1.l;
25631          if (i < s0.i && i < s1.i && d3_geom_voronoiTriangleArea(site, s0, s1) < 0) {
25632            triangles.push([ data[i], data[s0.i], data[s1.i] ]);
25633          }
25634        }
25635      });
25636      return triangles;
25637    };
25638    voronoi.x = function(_) {
25639      return arguments.length ? (fx = d3_functor(x = _), voronoi) : x;
25640    };
25641    voronoi.y = function(_) {
25642      return arguments.length ? (fy = d3_functor(y = _), voronoi) : y;
25643    };
25644    voronoi.clipExtent = function(_) {
25645      if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent;
25646      clipExtent = _ == null ? d3_geom_voronoiClipExtent : _;
25647      return voronoi;
25648    };
25649    voronoi.size = function(_) {
25650      if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent && clipExtent[1];
25651      return voronoi.clipExtent(_ && [ [ 0, 0 ], _ ]);
25652    };
25653    return voronoi;
25654  };
25655  var d3_geom_voronoiClipExtent = [ [ -1e6, -1e6 ], [ 1e6, 1e6 ] ];
25656  function d3_geom_voronoiTriangleArea(a, b, c) {
25657    return (a.x - c.x) * (b.y - a.y) - (a.x - b.x) * (c.y - a.y);
25658  }
25659  d3.geom.delaunay = function(vertices) {
25660    return d3.geom.voronoi().triangles(vertices);
25661  };
25662  d3.geom.quadtree = function(points, x1, y1, x2, y2) {
25663    var x = d3_geom_pointX, y = d3_geom_pointY, compat;
25664    if (compat = arguments.length) {
25665      x = d3_geom_quadtreeCompatX;
25666      y = d3_geom_quadtreeCompatY;
25667      if (compat === 3) {
25668        y2 = y1;
25669        x2 = x1;
25670        y1 = x1 = 0;
25671      }
25672      return quadtree(points);
25673    }
25674    function quadtree(data) {
25675      var d, fx = d3_functor(x), fy = d3_functor(y), xs, ys, i, n, x1_, y1_, x2_, y2_;
25676      if (x1 != null) {
25677        x1_ = x1, y1_ = y1, x2_ = x2, y2_ = y2;
25678      } else {
25679        x2_ = y2_ = -(x1_ = y1_ = Infinity);
25680        xs = [], ys = [];
25681        n = data.length;
25682        if (compat) for (i = 0; i < n; ++i) {
25683          d = data[i];
25684          if (d.x < x1_) x1_ = d.x;
25685          if (d.y < y1_) y1_ = d.y;
25686          if (d.x > x2_) x2_ = d.x;
25687          if (d.y > y2_) y2_ = d.y;
25688          xs.push(d.x);
25689          ys.push(d.y);
25690        } else for (i = 0; i < n; ++i) {
25691          var x_ = +fx(d = data[i], i), y_ = +fy(d, i);
25692          if (x_ < x1_) x1_ = x_;
25693          if (y_ < y1_) y1_ = y_;
25694          if (x_ > x2_) x2_ = x_;
25695          if (y_ > y2_) y2_ = y_;
25696          xs.push(x_);
25697          ys.push(y_);
25698        }
25699      }
25700      var dx = x2_ - x1_, dy = y2_ - y1_;
25701      if (dx > dy) y2_ = y1_ + dx; else x2_ = x1_ + dy;
25702      function insert(n, d, x, y, x1, y1, x2, y2) {
25703        if (isNaN(x) || isNaN(y)) return;
25704        if (n.leaf) {
25705          var nx = n.x, ny = n.y;
25706          if (nx != null) {
25707            if (abs(nx - x) + abs(ny - y) < .01) {
25708              insertChild(n, d, x, y, x1, y1, x2, y2);
25709            } else {
25710              var nPoint = n.point;
25711              n.x = n.y = n.point = null;
25712              insertChild(n, nPoint, nx, ny, x1, y1, x2, y2);
25713              insertChild(n, d, x, y, x1, y1, x2, y2);
25714            }
25715          } else {
25716            n.x = x, n.y = y, n.point = d;
25717          }
25718        } else {
25719          insertChild(n, d, x, y, x1, y1, x2, y2);
25720        }
25721      }
25722      function insertChild(n, d, x, y, x1, y1, x2, y2) {
25723        var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, right = x >= sx, bottom = y >= sy, i = (bottom << 1) + right;
25724        n.leaf = false;
25725        n = n.nodes[i] || (n.nodes[i] = d3_geom_quadtreeNode());
25726        if (right) x1 = sx; else x2 = sx;
25727        if (bottom) y1 = sy; else y2 = sy;
25728        insert(n, d, x, y, x1, y1, x2, y2);
25729      }
25730      var root = d3_geom_quadtreeNode();
25731      root.add = function(d) {
25732        insert(root, d, +fx(d, ++i), +fy(d, i), x1_, y1_, x2_, y2_);
25733      };
25734      root.visit = function(f) {
25735        d3_geom_quadtreeVisit(f, root, x1_, y1_, x2_, y2_);
25736      };
25737      i = -1;
25738      if (x1 == null) {
25739        while (++i < n) {
25740          insert(root, data[i], xs[i], ys[i], x1_, y1_, x2_, y2_);
25741        }
25742        --i;
25743      } else data.forEach(root.add);
25744      xs = ys = data = d = null;
25745      return root;
25746    }
25747    quadtree.x = function(_) {
25748      return arguments.length ? (x = _, quadtree) : x;
25749    };
25750    quadtree.y = function(_) {
25751      return arguments.length ? (y = _, quadtree) : y;
25752    };
25753    quadtree.extent = function(_) {
25754      if (!arguments.length) return x1 == null ? null : [ [ x1, y1 ], [ x2, y2 ] ];
25755      if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = +_[0][0], y1 = +_[0][1], x2 = +_[1][0], 
25756      y2 = +_[1][1];
25757      return quadtree;
25758    };
25759    quadtree.size = function(_) {
25760      if (!arguments.length) return x1 == null ? null : [ x2 - x1, y2 - y1 ];
25761      if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = y1 = 0, x2 = +_[0], y2 = +_[1];
25762      return quadtree;
25763    };
25764    return quadtree;
25765  };
25766  function d3_geom_quadtreeCompatX(d) {
25767    return d.x;
25768  }
25769  function d3_geom_quadtreeCompatY(d) {
25770    return d.y;
25771  }
25772  function d3_geom_quadtreeNode() {
25773    return {
25774      leaf: true,
25775      nodes: [],
25776      point: null,
25777      x: null,
25778      y: null
25779    };
25780  }
25781  function d3_geom_quadtreeVisit(f, node, x1, y1, x2, y2) {
25782    if (!f(node, x1, y1, x2, y2)) {
25783      var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, children = node.nodes;
25784      if (children[0]) d3_geom_quadtreeVisit(f, children[0], x1, y1, sx, sy);
25785      if (children[1]) d3_geom_quadtreeVisit(f, children[1], sx, y1, x2, sy);
25786      if (children[2]) d3_geom_quadtreeVisit(f, children[2], x1, sy, sx, y2);
25787      if (children[3]) d3_geom_quadtreeVisit(f, children[3], sx, sy, x2, y2);
25788    }
25789  }
25790  d3.interpolateRgb = d3_interpolateRgb;
25791  function d3_interpolateRgb(a, b) {
vendor: 13,311 bytes, lines 25792-26225
25792    a = d3.rgb(a);
25793    b = d3.rgb(b);
25794    var ar = a.r, ag = a.g, ab = a.b, br = b.r - ar, bg = b.g - ag, bb = b.b - ab;
25795    return function(t) {
25796      return "#" + d3_rgb_hex(Math.round(ar + br * t)) + d3_rgb_hex(Math.round(ag + bg * t)) + d3_rgb_hex(Math.round(ab + bb * t));
25797    };
25798  }
25799  d3.interpolateObject = d3_interpolateObject;
25800  function d3_interpolateObject(a, b) {
25801    var i = {}, c = {}, k;
25802    for (k in a) {
25803      if (k in b) {
25804        i[k] = d3_interpolate(a[k], b[k]);
25805      } else {
25806        c[k] = a[k];
25807      }
25808    }
25809    for (k in b) {
25810      if (!(k in a)) {
25811        c[k] = b[k];
25812      }
25813    }
25814    return function(t) {
25815      for (k in i) c[k] = i[k](t);
25816      return c;
25817    };
25818  }
25819  d3.interpolateNumber = d3_interpolateNumber;
25820  function d3_interpolateNumber(a, b) {
25821    a = +a, b = +b;
25822    return function(t) {
25823      return a * (1 - t) + b * t;
25824    };
25825  }
25826  d3.interpolateString = d3_interpolateString;
25827  function d3_interpolateString(a, b) {
25828    var bi = d3_interpolate_numberA.lastIndex = d3_interpolate_numberB.lastIndex = 0, am, bm, bs, i = -1, s = [], q = [];
25829    a = a + "", b = b + "";
25830    while ((am = d3_interpolate_numberA.exec(a)) && (bm = d3_interpolate_numberB.exec(b))) {
25831      if ((bs = bm.index) > bi) {
25832        bs = b.slice(bi, bs);
25833        if (s[i]) s[i] += bs; else s[++i] = bs;
25834      }
25835      if ((am = am[0]) === (bm = bm[0])) {
25836        if (s[i]) s[i] += bm; else s[++i] = bm;
25837      } else {
25838        s[++i] = null;
25839        q.push({
25840          i: i,
25841          x: d3_interpolateNumber(am, bm)
25842        });
25843      }
25844      bi = d3_interpolate_numberB.lastIndex;
25845    }
25846    if (bi < b.length) {
25847      bs = b.slice(bi);
25848      if (s[i]) s[i] += bs; else s[++i] = bs;
25849    }
25850    return s.length < 2 ? q[0] ? (b = q[0].x, function(t) {
25851      return b(t) + "";
25852    }) : function() {
25853      return b;
25854    } : (b = q.length, function(t) {
25855      for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t);
25856      return s.join("");
25857    });
25858  }
25859  var d3_interpolate_numberA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g, d3_interpolate_numberB = new RegExp(d3_interpolate_numberA.source, "g");
25860  d3.interpolate = d3_interpolate;
25861  function d3_interpolate(a, b) {
25862    var i = d3.interpolators.length, f;
25863    while (--i >= 0 && !(f = d3.interpolators[i](a, b))) ;
25864    return f;
25865  }
25866  d3.interpolators = [ function(a, b) {
25867    var t = typeof b;
25868    return (t === "string" ? d3_rgb_names.has(b) || /^(#|rgb\(|hsl\()/.test(b) ? d3_interpolateRgb : d3_interpolateString : b instanceof d3_color ? d3_interpolateRgb : Array.isArray(b) ? d3_interpolateArray : t === "object" && isNaN(b) ? d3_interpolateObject : d3_interpolateNumber)(a, b);
25869  } ];
25870  d3.interpolateArray = d3_interpolateArray;
25871  function d3_interpolateArray(a, b) {
25872    var x = [], c = [], na = a.length, nb = b.length, n0 = Math.min(a.length, b.length), i;
25873    for (i = 0; i < n0; ++i) x.push(d3_interpolate(a[i], b[i]));
25874    for (;i < na; ++i) c[i] = a[i];
25875    for (;i < nb; ++i) c[i] = b[i];
25876    return function(t) {
25877      for (i = 0; i < n0; ++i) c[i] = x[i](t);
25878      return c;
25879    };
25880  }
25881  var d3_ease_default = function() {
25882    return d3_identity;
25883  };
25884  var d3_ease = d3.map({
25885    linear: d3_ease_default,
25886    poly: d3_ease_poly,
25887    quad: function() {
25888      return d3_ease_quad;
25889    },
25890    cubic: function() {
25891      return d3_ease_cubic;
25892    },
25893    sin: function() {
25894      return d3_ease_sin;
25895    },
25896    exp: function() {
25897      return d3_ease_exp;
25898    },
25899    circle: function() {
25900      return d3_ease_circle;
25901    },
25902    elastic: d3_ease_elastic,
25903    back: d3_ease_back,
25904    bounce: function() {
25905      return d3_ease_bounce;
25906    }
25907  });
25908  var d3_ease_mode = d3.map({
25909    "in": d3_identity,
25910    out: d3_ease_reverse,
25911    "in-out": d3_ease_reflect,
25912    "out-in": function(f) {
25913      return d3_ease_reflect(d3_ease_reverse(f));
25914    }
25915  });
25916  d3.ease = function(name) {
25917    var i = name.indexOf("-"), t = i >= 0 ? name.slice(0, i) : name, m = i >= 0 ? name.slice(i + 1) : "in";
25918    t = d3_ease.get(t) || d3_ease_default;
25919    m = d3_ease_mode.get(m) || d3_identity;
25920    return d3_ease_clamp(m(t.apply(null, d3_arraySlice.call(arguments, 1))));
25921  };
25922  function d3_ease_clamp(f) {
25923    return function(t) {
25924      return t <= 0 ? 0 : t >= 1 ? 1 : f(t);
25925    };
25926  }
25927  function d3_ease_reverse(f) {
25928    return function(t) {
25929      return 1 - f(1 - t);
25930    };
25931  }
25932  function d3_ease_reflect(f) {
25933    return function(t) {
25934      return .5 * (t < .5 ? f(2 * t) : 2 - f(2 - 2 * t));
25935    };
25936  }
25937  function d3_ease_quad(t) {
25938    return t * t;
25939  }
25940  function d3_ease_cubic(t) {
25941    return t * t * t;
25942  }
25943  function d3_ease_cubicInOut(t) {
25944    if (t <= 0) return 0;
25945    if (t >= 1) return 1;
25946    var t2 = t * t, t3 = t2 * t;
25947    return 4 * (t < .5 ? t3 : 3 * (t - t2) + t3 - .75);
25948  }
25949  function d3_ease_poly(e) {
25950    return function(t) {
25951      return Math.pow(t, e);
25952    };
25953  }
25954  function d3_ease_sin(t) {
25955    return 1 - Math.cos(t * halfπ);
25956  }
25957  function d3_ease_exp(t) {
25958    return Math.pow(2, 10 * (t - 1));
25959  }
25960  function d3_ease_circle(t) {
25961    return 1 - Math.sqrt(1 - t * t);
25962  }
25963  function d3_ease_elastic(a, p) {
25964    var s;
25965    if (arguments.length < 2) p = .45;
25966    if (arguments.length) s = p / τ * Math.asin(1 / a); else a = 1, s = p / 4;
25967    return function(t) {
25968      return 1 + a * Math.pow(2, -10 * t) * Math.sin((t - s) * τ / p);
25969    };
25970  }
25971  function d3_ease_back(s) {
25972    if (!s) s = 1.70158;
25973    return function(t) {
25974      return t * t * ((s + 1) * t - s);
25975    };
25976  }
25977  function d3_ease_bounce(t) {
25978    return t < 1 / 2.75 ? 7.5625 * t * t : t < 2 / 2.75 ? 7.5625 * (t -= 1.5 / 2.75) * t + .75 : t < 2.5 / 2.75 ? 7.5625 * (t -= 2.25 / 2.75) * t + .9375 : 7.5625 * (t -= 2.625 / 2.75) * t + .984375;
25979  }
25980  d3.interpolateHcl = d3_interpolateHcl;
25981  function d3_interpolateHcl(a, b) {
25982    a = d3.hcl(a);
25983    b = d3.hcl(b);
25984    var ah = a.h, ac = a.c, al = a.l, bh = b.h - ah, bc = b.c - ac, bl = b.l - al;
25985    if (isNaN(bc)) bc = 0, ac = isNaN(ac) ? b.c : ac;
25986    if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360;
25987    return function(t) {
25988      return d3_hcl_lab(ah + bh * t, ac + bc * t, al + bl * t) + "";
25989    };
25990  }
25991  d3.interpolateHsl = d3_interpolateHsl;
25992  function d3_interpolateHsl(a, b) {
25993    a = d3.hsl(a);
25994    b = d3.hsl(b);
25995    var ah = a.h, as = a.s, al = a.l, bh = b.h - ah, bs = b.s - as, bl = b.l - al;
25996    if (isNaN(bs)) bs = 0, as = isNaN(as) ? b.s : as;
25997    if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360;
25998    return function(t) {
25999      return d3_hsl_rgb(ah + bh * t, as + bs * t, al + bl * t) + "";
26000    };
26001  }
26002  d3.interpolateLab = d3_interpolateLab;
26003  function d3_interpolateLab(a, b) {
26004    a = d3.lab(a);
26005    b = d3.lab(b);
26006    var al = a.l, aa = a.a, ab = a.b, bl = b.l - al, ba = b.a - aa, bb = b.b - ab;
26007    return function(t) {
26008      return d3_lab_rgb(al + bl * t, aa + ba * t, ab + bb * t) + "";
26009    };
26010  }
26011  d3.interpolateRound = d3_interpolateRound;
26012  function d3_interpolateRound(a, b) {
26013    b -= a;
26014    return function(t) {
26015      return Math.round(a + b * t);
26016    };
26017  }
26018  d3.transform = function(string) {
26019    var g = d3_document.createElementNS(d3.ns.prefix.svg, "g");
26020    return (d3.transform = function(string) {
26021      if (string != null) {
26022        g.setAttribute("transform", string);
26023        var t = g.transform.baseVal.consolidate();
26024      }
26025      return new d3_transform(t ? t.matrix : d3_transformIdentity);
26026    })(string);
26027  };
26028  function d3_transform(m) {
26029    var r0 = [ m.a, m.b ], r1 = [ m.c, m.d ], kx = d3_transformNormalize(r0), kz = d3_transformDot(r0, r1), ky = d3_transformNormalize(d3_transformCombine(r1, r0, -kz)) || 0;
26030    if (r0[0] * r1[1] < r1[0] * r0[1]) {
26031      r0[0] *= -1;
26032      r0[1] *= -1;
26033      kx *= -1;
26034      kz *= -1;
26035    }
26036    this.rotate = (kx ? Math.atan2(r0[1], r0[0]) : Math.atan2(-r1[0], r1[1])) * d3_degrees;
26037    this.translate = [ m.e, m.f ];
26038    this.scale = [ kx, ky ];
26039    this.skew = ky ? Math.atan2(kz, ky) * d3_degrees : 0;
26040  }
26041  d3_transform.prototype.toString = function() {
26042    return "translate(" + this.translate + ")rotate(" + this.rotate + ")skewX(" + this.skew + ")scale(" + this.scale + ")";
26043  };
26044  function d3_transformDot(a, b) {
26045    return a[0] * b[0] + a[1] * b[1];
26046  }
26047  function d3_transformNormalize(a) {
26048    var k = Math.sqrt(d3_transformDot(a, a));
26049    if (k) {
26050      a[0] /= k;
26051      a[1] /= k;
26052    }
26053    return k;
26054  }
26055  function d3_transformCombine(a, b, k) {
26056    a[0] += k * b[0];
26057    a[1] += k * b[1];
26058    return a;
26059  }
26060  var d3_transformIdentity = {
26061    a: 1,
26062    b: 0,
26063    c: 0,
26064    d: 1,
26065    e: 0,
26066    f: 0
26067  };
26068  d3.interpolateTransform = d3_interpolateTransform;
26069  function d3_interpolateTransform(a, b) {
26070    var s = [], q = [], n, A = d3.transform(a), B = d3.transform(b), ta = A.translate, tb = B.translate, ra = A.rotate, rb = B.rotate, wa = A.skew, wb = B.skew, ka = A.scale, kb = B.scale;
26071    if (ta[0] != tb[0] || ta[1] != tb[1]) {
26072      s.push("translate(", null, ",", null, ")");
26073      q.push({
26074        i: 1,
26075        x: d3_interpolateNumber(ta[0], tb[0])
26076      }, {
26077        i: 3,
26078        x: d3_interpolateNumber(ta[1], tb[1])
26079      });
26080    } else if (tb[0] || tb[1]) {
26081      s.push("translate(" + tb + ")");
26082    } else {
26083      s.push("");
26084    }
26085    if (ra != rb) {
26086      if (ra - rb > 180) rb += 360; else if (rb - ra > 180) ra += 360;
26087      q.push({
26088        i: s.push(s.pop() + "rotate(", null, ")") - 2,
26089        x: d3_interpolateNumber(ra, rb)
26090      });
26091    } else if (rb) {
26092      s.push(s.pop() + "rotate(" + rb + ")");
26093    }
26094    if (wa != wb) {
26095      q.push({
26096        i: s.push(s.pop() + "skewX(", null, ")") - 2,
26097        x: d3_interpolateNumber(wa, wb)
26098      });
26099    } else if (wb) {
26100      s.push(s.pop() + "skewX(" + wb + ")");
26101    }
26102    if (ka[0] != kb[0] || ka[1] != kb[1]) {
26103      n = s.push(s.pop() + "scale(", null, ",", null, ")");
26104      q.push({
26105        i: n - 4,
26106        x: d3_interpolateNumber(ka[0], kb[0])
26107      }, {
26108        i: n - 2,
26109        x: d3_interpolateNumber(ka[1], kb[1])
26110      });
26111    } else if (kb[0] != 1 || kb[1] != 1) {
26112      s.push(s.pop() + "scale(" + kb + ")");
26113    }
26114    n = q.length;
26115    return function(t) {
26116      var i = -1, o;
26117      while (++i < n) s[(o = q[i]).i] = o.x(t);
26118      return s.join("");
26119    };
26120  }
26121  function d3_uninterpolateNumber(a, b) {
26122    b = (b -= a = +a) || 1 / b;
26123    return function(x) {
26124      return (x - a) / b;
26125    };
26126  }
26127  function d3_uninterpolateClamp(a, b) {
26128    b = (b -= a = +a) || 1 / b;
26129    return function(x) {
26130      return Math.max(0, Math.min(1, (x - a) / b));
26131    };
26132  }
26133  d3.layout = {};
26134  d3.layout.bundle = function() {
26135    return function(links) {
26136      var paths = [], i = -1, n = links.length;
26137      while (++i < n) paths.push(d3_layout_bundlePath(links[i]));
26138      return paths;
26139    };
26140  };
26141  function d3_layout_bundlePath(link) {
26142    var start = link.source, end = link.target, lca = d3_layout_bundleLeastCommonAncestor(start, end), points = [ start ];
26143    while (start !== lca) {
26144      start = start.parent;
26145      points.push(start);
26146    }
26147    var k = points.length;
26148    while (end !== lca) {
26149      points.splice(k, 0, end);
26150      end = end.parent;
26151    }
26152    return points;
26153  }
26154  function d3_layout_bundleAncestors(node) {
26155    var ancestors = [], parent = node.parent;
26156    while (parent != null) {
26157      ancestors.push(node);
26158      node = parent;
26159      parent = parent.parent;
26160    }
26161    ancestors.push(node);
26162    return ancestors;
26163  }
26164  function d3_layout_bundleLeastCommonAncestor(a, b) {
26165    if (a === b) return a;
26166    var aNodes = d3_layout_bundleAncestors(a), bNodes = d3_layout_bundleAncestors(b), aNode = aNodes.pop(), bNode = bNodes.pop(), sharedNode = null;
26167    while (aNode === bNode) {
26168      sharedNode = aNode;
26169      aNode = aNodes.pop();
26170      bNode = bNodes.pop();
26171    }
26172    return sharedNode;
26173  }
26174  d3.layout.chord = function() {
26175    var chord = {}, chords, groups, matrix, n, padding = 0, sortGroups, sortSubgroups, sortChords;
26176    function relayout() {
26177      var subgroups = {}, groupSums = [], groupIndex = d3.range(n), subgroupIndex = [], k, x, x0, i, j;
26178      chords = [];
26179      groups = [];
26180      k = 0, i = -1;
26181      while (++i < n) {
26182        x = 0, j = -1;
26183        while (++j < n) {
26184          x += matrix[i][j];
26185        }
26186        groupSums.push(x);
26187        subgroupIndex.push(d3.range(n));
26188        k += x;
26189      }
26190      if (sortGroups) {
26191        groupIndex.sort(function(a, b) {
26192          return sortGroups(groupSums[a], groupSums[b]);
26193        });
26194      }
26195      if (sortSubgroups) {
26196        subgroupIndex.forEach(function(d, i) {
26197          d.sort(function(a, b) {
26198            return sortSubgroups(matrix[i][a], matrix[i][b]);
26199          });
26200        });
26201      }
26202      k = (τ - padding * n) / k;
26203      x = 0, i = -1;
26204      while (++i < n) {
26205        x0 = x, j = -1;
26206        while (++j < n) {
26207          var di = groupIndex[i], dj = subgroupIndex[di][j], v = matrix[di][dj], a0 = x, a1 = x += v * k;
26208          subgroups[di + "-" + dj] = {
26209            index: di,
26210            subindex: dj,
26211            startAngle: a0,
26212            endAngle: a1,
26213            value: v
26214          };
26215        }
26216        groups[di] = {
26217          index: di,
26218          startAngle: x0,
26219          endAngle: x,
26220          value: (x - x0) / k
26221        };
26222        x += padding;
26223      }
26224      i = -1;
26225      while (++i < n) {
vendor: 3,724 bytes, lines 26226-26346
26226        j = i - 1;
26227        while (++j < n) {
26228          var source = subgroups[i + "-" + j], target = subgroups[j + "-" + i];
26229          if (source.value || target.value) {
26230            chords.push(source.value < target.value ? {
26231              source: target,
26232              target: source
26233            } : {
26234              source: source,
26235              target: target
26236            });
26237          }
26238        }
26239      }
26240      if (sortChords) resort();
26241    }
26242    function resort() {
26243      chords.sort(function(a, b) {
26244        return sortChords((a.source.value + a.target.value) / 2, (b.source.value + b.target.value) / 2);
26245      });
26246    }
26247    chord.matrix = function(x) {
26248      if (!arguments.length) return matrix;
26249      n = (matrix = x) && matrix.length;
26250      chords = groups = null;
26251      return chord;
26252    };
26253    chord.padding = function(x) {
26254      if (!arguments.length) return padding;
26255      padding = x;
26256      chords = groups = null;
26257      return chord;
26258    };
26259    chord.sortGroups = function(x) {
26260      if (!arguments.length) return sortGroups;
26261      sortGroups = x;
26262      chords = groups = null;
26263      return chord;
26264    };
26265    chord.sortSubgroups = function(x) {
26266      if (!arguments.length) return sortSubgroups;
26267      sortSubgroups = x;
26268      chords = null;
26269      return chord;
26270    };
26271    chord.sortChords = function(x) {
26272      if (!arguments.length) return sortChords;
26273      sortChords = x;
26274      if (chords) resort();
26275      return chord;
26276    };
26277    chord.chords = function() {
26278      if (!chords) relayout();
26279      return chords;
26280    };
26281    chord.groups = function() {
26282      if (!groups) relayout();
26283      return groups;
26284    };
26285    return chord;
26286  };
26287  d3.layout.force = function() {
26288    var force = {}, event = d3.dispatch("start", "tick", "end"), size = [ 1, 1 ], drag, alpha, friction = .9, linkDistance = d3_layout_forceLinkDistance, linkStrength = d3_layout_forceLinkStrength, charge = -30, chargeDistance2 = d3_layout_forceChargeDistance2, gravity = .1, theta2 = .64, nodes = [], links = [], distances, strengths, charges;
26289    function repulse(node) {
26290      return function(quad, x1, _, x2) {
26291        if (quad.point !== node) {
26292          var dx = quad.cx - node.x, dy = quad.cy - node.y, dw = x2 - x1, dn = dx * dx + dy * dy;
26293          if (dw * dw / theta2 < dn) {
26294            if (dn < chargeDistance2) {
26295              var k = quad.charge / dn;
26296              node.px -= dx * k;
26297              node.py -= dy * k;
26298            }
26299            return true;
26300          }
26301          if (quad.point && dn && dn < chargeDistance2) {
26302            var k = quad.pointCharge / dn;
26303            node.px -= dx * k;
26304            node.py -= dy * k;
26305          }
26306        }
26307        return !quad.charge;
26308      };
26309    }
26310    force.tick = function() {
26311      if ((alpha *= .99) < .005) {
26312        event.end({
26313          type: "end",
26314          alpha: alpha = 0
26315        });
26316        return true;
26317      }
26318      var n = nodes.length, m = links.length, q, i, o, s, t, l, k, x, y;
26319      for (i = 0; i < m; ++i) {
26320        o = links[i];
26321        s = o.source;
26322        t = o.target;
26323        x = t.x - s.x;
26324        y = t.y - s.y;
26325        if (l = x * x + y * y) {
26326          l = alpha * strengths[i] * ((l = Math.sqrt(l)) - distances[i]) / l;
26327          x *= l;
26328          y *= l;
26329          t.x -= x * (k = s.weight / (t.weight + s.weight));
26330          t.y -= y * k;
26331          s.x += x * (k = 1 - k);
26332          s.y += y * k;
26333        }
26334      }
26335      if (k = alpha * gravity) {
26336        x = size[0] / 2;
26337        y = size[1] / 2;
26338        i = -1;
26339        if (k) while (++i < n) {
26340          o = nodes[i];
26341          o.x += (x - o.x) * k;
26342          o.y += (y - o.y) * k;
26343        }
26344      }
26345      if (charge) {
26346        d3_layout_forceAccumulate(q = d3.geom.quadtree(nodes), alph
vendor: 14,132 bytes, lines 26346-26796
26346a, charges);
26347        i = -1;
26348        while (++i < n) {
26349          if (!(o = nodes[i]).fixed) {
26350            q.visit(repulse(o));
26351          }
26352        }
26353      }
26354      i = -1;
26355      while (++i < n) {
26356        o = nodes[i];
26357        if (o.fixed) {
26358          o.x = o.px;
26359          o.y = o.py;
26360        } else {
26361          o.x -= (o.px - (o.px = o.x)) * friction;
26362          o.y -= (o.py - (o.py = o.y)) * friction;
26363        }
26364      }
26365      event.tick({
26366        type: "tick",
26367        alpha: alpha
26368      });
26369    };
26370    force.nodes = function(x) {
26371      if (!arguments.length) return nodes;
26372      nodes = x;
26373      return force;
26374    };
26375    force.links = function(x) {
26376      if (!arguments.length) return links;
26377      links = x;
26378      return force;
26379    };
26380    force.size = function(x) {
26381      if (!arguments.length) return size;
26382      size = x;
26383      return force;
26384    };
26385    force.linkDistance = function(x) {
26386      if (!arguments.length) return linkDistance;
26387      linkDistance = typeof x === "function" ? x : +x;
26388      return force;
26389    };
26390    force.distance = force.linkDistance;
26391    force.linkStrength = function(x) {
26392      if (!arguments.length) return linkStrength;
26393      linkStrength = typeof x === "function" ? x : +x;
26394      return force;
26395    };
26396    force.friction = function(x) {
26397      if (!arguments.length) return friction;
26398      friction = +x;
26399      return force;
26400    };
26401    force.charge = function(x) {
26402      if (!arguments.length) return charge;
26403      charge = typeof x === "function" ? x : +x;
26404      return force;
26405    };
26406    force.chargeDistance = function(x) {
26407      if (!arguments.length) return Math.sqrt(chargeDistance2);
26408      chargeDistance2 = x * x;
26409      return force;
26410    };
26411    force.gravity = function(x) {
26412      if (!arguments.length) return gravity;
26413      gravity = +x;
26414      return force;
26415    };
26416    force.theta = function(x) {
26417      if (!arguments.length) return Math.sqrt(theta2);
26418      theta2 = x * x;
26419      return force;
26420    };
26421    force.alpha = function(x) {
26422      if (!arguments.length) return alpha;
26423      x = +x;
26424      if (alpha) {
26425        if (x > 0) alpha = x; else alpha = 0;
26426      } else if (x > 0) {
26427        event.start({
26428          type: "start",
26429          alpha: alpha = x
26430        });
26431        d3.timer(force.tick);
26432      }
26433      return force;
26434    };
26435    force.start = function() {
26436      var i, n = nodes.length, m = links.length, w = size[0], h = size[1], neighbors, o;
26437      for (i = 0; i < n; ++i) {
26438        (o = nodes[i]).index = i;
26439        o.weight = 0;
26440      }
26441      for (i = 0; i < m; ++i) {
26442        o = links[i];
26443        if (typeof o.source == "number") o.source = nodes[o.source];
26444        if (typeof o.target == "number") o.target = nodes[o.target];
26445        ++o.source.weight;
26446        ++o.target.weight;
26447      }
26448      for (i = 0; i < n; ++i) {
26449        o = nodes[i];
26450        if (isNaN(o.x)) o.x = position("x", w);
26451        if (isNaN(o.y)) o.y = position("y", h);
26452        if (isNaN(o.px)) o.px = o.x;
26453        if (isNaN(o.py)) o.py = o.y;
26454      }
26455      distances = [];
26456      if (typeof linkDistance === "function") for (i = 0; i < m; ++i) distances[i] = +linkDistance.call(this, links[i], i); else for (i = 0; i < m; ++i) distances[i] = linkDistance;
26457      strengths = [];
26458      if (typeof linkStrength === "function") for (i = 0; i < m; ++i) strengths[i] = +linkStrength.call(this, links[i], i); else for (i = 0; i < m; ++i) strengths[i] = linkStrength;
26459      charges = [];
26460      if (typeof charge === "function") for (i = 0; i < n; ++i) charges[i] = +charge.call(this, nodes[i], i); else for (i = 0; i < n; ++i) charges[i] = charge;
26461      function position(dimension, size) {
26462        if (!neighbors) {
26463          neighbors = new Array(n);
26464          for (j = 0; j < n; ++j) {
26465            neighbors[j] = [];
26466          }
26467          for (j = 0; j < m; ++j) {
26468            var o = links[j];
26469            neighbors[o.source.index].push(o.target);
26470            neighbors[o.target.index].push(o.source);
26471          }
26472        }
26473        var candidates = neighbors[i], j = -1, m = candidates.length, x;
26474        while (++j < m) if (!isNaN(x = candidates[j][dimension])) return x;
26475        return Math.random() * size;
26476      }
26477      return force.resume();
26478    };
26479    force.resume = function() {
26480      return force.alpha(.1);
26481    };
26482    force.stop = function() {
26483      return force.alpha(0);
26484    };
26485    force.drag = function() {
26486      if (!drag) drag = d3.behavior.drag().origin(d3_identity).on("dragstart.force", d3_layout_forceDragstart).on("drag.force", dragmove).on("dragend.force", d3_layout_forceDragend);
26487      if (!arguments.length) return drag;
26488      this.on("mouseover.force", d3_layout_forceMouseover).on("mouseout.force", d3_layout_forceMouseout).call(drag);
26489    };
26490    function dragmove(d) {
26491      d.px = d3.event.x, d.py = d3.event.y;
26492      force.resume();
26493    }
26494    return d3.rebind(force, event, "on");
26495  };
26496  function d3_layout_forceDragstart(d) {
26497    d.fixed |= 2;
26498  }
26499  function d3_layout_forceDragend(d) {
26500    d.fixed &= ~6;
26501  }
26502  function d3_layout_forceMouseover(d) {
26503    d.fixed |= 4;
26504    d.px = d.x, d.py = d.y;
26505  }
26506  function d3_layout_forceMouseout(d) {
26507    d.fixed &= ~4;
26508  }
26509  function d3_layout_forceAccumulate(quad, alpha, charges) {
26510    var cx = 0, cy = 0;
26511    quad.charge = 0;
26512    if (!quad.leaf) {
26513      var nodes = quad.nodes, n = nodes.length, i = -1, c;
26514      while (++i < n) {
26515        c = nodes[i];
26516        if (c == null) continue;
26517        d3_layout_forceAccumulate(c, alpha, charges);
26518        quad.charge += c.charge;
26519        cx += c.charge * c.cx;
26520        cy += c.charge * c.cy;
26521      }
26522    }
26523    if (quad.point) {
26524      if (!quad.leaf) {
26525        quad.point.x += Math.random() - .5;
26526        quad.point.y += Math.random() - .5;
26527      }
26528      var k = alpha * charges[quad.point.index];
26529      quad.charge += quad.pointCharge = k;
26530      cx += k * quad.point.x;
26531      cy += k * quad.point.y;
26532    }
26533    quad.cx = cx / quad.charge;
26534    quad.cy = cy / quad.charge;
26535  }
26536  var d3_layout_forceLinkDistance = 20, d3_layout_forceLinkStrength = 1, d3_layout_forceChargeDistance2 = Infinity;
26537  d3.layout.hierarchy = function() {
26538    var sort = d3_layout_hierarchySort, children = d3_layout_hierarchyChildren, value = d3_layout_hierarchyValue;
26539    function hierarchy(root) {
26540      var stack = [ root ], nodes = [], node;
26541      root.depth = 0;
26542      while ((node = stack.pop()) != null) {
26543        nodes.push(node);
26544        if ((childs = children.call(hierarchy, node, node.depth)) && (n = childs.length)) {
26545          var n, childs, child;
26546          while (--n >= 0) {
26547            stack.push(child = childs[n]);
26548            child.parent = node;
26549            child.depth = node.depth + 1;
26550          }
26551          if (value) node.value = 0;
26552          node.children = childs;
26553        } else {
26554          if (value) node.value = +value.call(hierarchy, node, node.depth) || 0;
26555          delete node.children;
26556        }
26557      }
26558      d3_layout_hierarchyVisitAfter(root, function(node) {
26559        var childs, parent;
26560        if (sort && (childs = node.children)) childs.sort(sort);
26561        if (value && (parent = node.parent)) parent.value += node.value;
26562      });
26563      return nodes;
26564    }
26565    hierarchy.sort = function(x) {
26566      if (!arguments.length) return sort;
26567      sort = x;
26568      return hierarchy;
26569    };
26570    hierarchy.children = function(x) {
26571      if (!arguments.length) return children;
26572      children = x;
26573      return hierarchy;
26574    };
26575    hierarchy.value = function(x) {
26576      if (!arguments.length) return value;
26577      value = x;
26578      return hierarchy;
26579    };
26580    hierarchy.revalue = function(root) {
26581      if (value) {
26582        d3_layout_hierarchyVisitBefore(root, function(node) {
26583          if (node.children) node.value = 0;
26584        });
26585        d3_layout_hierarchyVisitAfter(root, function(node) {
26586          var parent;
26587          if (!node.children) node.value = +value.call(hierarchy, node, node.depth) || 0;
26588          if (parent = node.parent) parent.value += node.value;
26589        });
26590      }
26591      return root;
26592    };
26593    return hierarchy;
26594  };
26595  function d3_layout_hierarchyRebind(object, hierarchy) {
26596    d3.rebind(object, hierarchy, "sort", "children", "value");
26597    object.nodes = object;
26598    object.links = d3_layout_hierarchyLinks;
26599    return object;
26600  }
26601  function d3_layout_hierarchyVisitBefore(node, callback) {
26602    var nodes = [ node ];
26603    while ((node = nodes.pop()) != null) {
26604      callback(node);
26605      if ((children = node.children) && (n = children.length)) {
26606        var n, children;
26607        while (--n >= 0) nodes.push(children[n]);
26608      }
26609    }
26610  }
26611  function d3_layout_hierarchyVisitAfter(node, callback) {
26612    var nodes = [ node ], nodes2 = [];
26613    while ((node = nodes.pop()) != null) {
26614      nodes2.push(node);
26615      if ((children = node.children) && (n = children.length)) {
26616        var i = -1, n, children;
26617        while (++i < n) nodes.push(children[i]);
26618      }
26619    }
26620    while ((node = nodes2.pop()) != null) {
26621      callback(node);
26622    }
26623  }
26624  function d3_layout_hierarchyChildren(d) {
26625    return d.children;
26626  }
26627  function d3_layout_hierarchyValue(d) {
26628    return d.value;
26629  }
26630  function d3_layout_hierarchySort(a, b) {
26631    return b.value - a.value;
26632  }
26633  function d3_layout_hierarchyLinks(nodes) {
26634    return d3.merge(nodes.map(function(parent) {
26635      return (parent.children || []).map(function(child) {
26636        return {
26637          source: parent,
26638          target: child
26639        };
26640      });
26641    }));
26642  }
26643  d3.layout.partition = function() {
26644    var hierarchy = d3.layout.hierarchy(), size = [ 1, 1 ];
26645    function position(node, x, dx, dy) {
26646      var children = node.children;
26647      node.x = x;
26648      node.y = node.depth * dy;
26649      node.dx = dx;
26650      node.dy = dy;
26651      if (children && (n = children.length)) {
26652        var i = -1, n, c, d;
26653        dx = node.value ? dx / node.value : 0;
26654        while (++i < n) {
26655          position(c = children[i], x, d = c.value * dx, dy);
26656          x += d;
26657        }
26658      }
26659    }
26660    function depth(node) {
26661      var children = node.children, d = 0;
26662      if (children && (n = children.length)) {
26663        var i = -1, n;
26664        while (++i < n) d = Math.max(d, depth(children[i]));
26665      }
26666      return 1 + d;
26667    }
26668    function partition(d, i) {
26669      var nodes = hierarchy.call(this, d, i);
26670      position(nodes[0], 0, size[0], size[1] / depth(nodes[0]));
26671      return nodes;
26672    }
26673    partition.size = function(x) {
26674      if (!arguments.length) return size;
26675      size = x;
26676      return partition;
26677    };
26678    return d3_layout_hierarchyRebind(partition, hierarchy);
26679  };
26680  d3.layout.pie = function() {
26681    var value = Number, sort = d3_layout_pieSortByValue, startAngle = 0, endAngle = τ;
26682    function pie(data) {
26683      var values = data.map(function(d, i) {
26684        return +value.call(pie, d, i);
26685      });
26686      var a = +(typeof startAngle === "function" ? startAngle.apply(this, arguments) : startAngle);
26687      var k = ((typeof endAngle === "function" ? endAngle.apply(this, arguments) : endAngle) - a) / d3.sum(values);
26688      var index = d3.range(data.length);
26689      if (sort != null) index.sort(sort === d3_layout_pieSortByValue ? function(i, j) {
26690        return values[j] - values[i];
26691      } : function(i, j) {
26692        return sort(data[i], data[j]);
26693      });
26694      var arcs = [];
26695      index.forEach(function(i) {
26696        var d;
26697        arcs[i] = {
26698          data: data[i],
26699          value: d = values[i],
26700          startAngle: a,
26701          endAngle: a += d * k
26702        };
26703      });
26704      return arcs;
26705    }
26706    pie.value = function(x) {
26707      if (!arguments.length) return value;
26708      value = x;
26709      return pie;
26710    };
26711    pie.sort = function(x) {
26712      if (!arguments.length) return sort;
26713      sort = x;
26714      return pie;
26715    };
26716    pie.startAngle = function(x) {
26717      if (!arguments.length) return startAngle;
26718      startAngle = x;
26719      return pie;
26720    };
26721    pie.endAngle = function(x) {
26722      if (!arguments.length) return endAngle;
26723      endAngle = x;
26724      return pie;
26725    };
26726    return pie;
26727  };
26728  var d3_layout_pieSortByValue = {};
26729  d3.layout.stack = function() {
26730    var values = d3_identity, order = d3_layout_stackOrderDefault, offset = d3_layout_stackOffsetZero, out = d3_layout_stackOut, x = d3_layout_stackX, y = d3_layout_stackY;
26731    function stack(data, index) {
26732      if (!(n = data.length)) return data;
26733      var series = data.map(function(d, i) {
26734        return values.call(stack, d, i);
26735      });
26736      var points = series.map(function(d) {
26737        return d.map(function(v, i) {
26738          return [ x.call(stack, v, i), y.call(stack, v, i) ];
26739        });
26740      });
26741      var orders = order.call(stack, points, index);
26742      series = d3.permute(series, orders);
26743      points = d3.permute(points, orders);
26744      var offsets = offset.call(stack, points, index);
26745      var m = series[0].length, n, i, j, o;
26746      for (j = 0; j < m; ++j) {
26747        out.call(stack, series[0][j], o = offsets[j], points[0][j][1]);
26748        for (i = 1; i < n; ++i) {
26749          out.call(stack, series[i][j], o += points[i - 1][j][1], points[i][j][1]);
26750        }
26751      }
26752      return data;
26753    }
26754    stack.values = function(x) {
26755      if (!arguments.length) return values;
26756      values = x;
26757      return stack;
26758    };
26759    stack.order = function(x) {
26760      if (!arguments.length) return order;
26761      order = typeof x === "function" ? x : d3_layout_stackOrders.get(x) || d3_layout_stackOrderDefault;
26762      return stack;
26763    };
26764    stack.offset = function(x) {
26765      if (!arguments.length) return offset;
26766      offset = typeof x === "function" ? x : d3_layout_stackOffsets.get(x) || d3_layout_stackOffsetZero;
26767      return stack;
26768    };
26769    stack.x = function(z) {
26770      if (!arguments.length) return x;
26771      x = z;
26772      return stack;
26773    };
26774    stack.y = function(z) {
26775      if (!arguments.length) return y;
26776      y = z;
26777      return stack;
26778    };
26779    stack.out = function(z) {
26780      if (!arguments.length) return out;
26781      out = z;
26782      return stack;
26783    };
26784    return stack;
26785  };
26786  function d3_layout_stackX(d) {
26787    return d.x;
26788  }
26789  function d3_layout_stackY(d) {
26790    return d.y;
26791  }
26792  function d3_layout_stackOut(d, y0, y) {
26793    d.y0 = y0;
26794    d.y = y;
26795  }
26796  var d3_layout_stackOrders = d3.map({
vendor: 19,113 bytes, lines 26797-27350
26797    "inside-out": function(data) {
26798      var n = data.length, i, j, max = data.map(d3_layout_stackMaxIndex), sums = data.map(d3_layout_stackReduceSum), index = d3.range(n).sort(function(a, b) {
26799        return max[a] - max[b];
26800      }), top = 0, bottom = 0, tops = [], bottoms = [];
26801      for (i = 0; i < n; ++i) {
26802        j = index[i];
26803        if (top < bottom) {
26804          top += sums[j];
26805          tops.push(j);
26806        } else {
26807          bottom += sums[j];
26808          bottoms.push(j);
26809        }
26810      }
26811      return bottoms.reverse().concat(tops);
26812    },
26813    reverse: function(data) {
26814      return d3.range(data.length).reverse();
26815    },
26816    "default": d3_layout_stackOrderDefault
26817  });
26818  var d3_layout_stackOffsets = d3.map({
26819    silhouette: function(data) {
26820      var n = data.length, m = data[0].length, sums = [], max = 0, i, j, o, y0 = [];
26821      for (j = 0; j < m; ++j) {
26822        for (i = 0, o = 0; i < n; i++) o += data[i][j][1];
26823        if (o > max) max = o;
26824        sums.push(o);
26825      }
26826      for (j = 0; j < m; ++j) {
26827        y0[j] = (max - sums[j]) / 2;
26828      }
26829      return y0;
26830    },
26831    wiggle: function(data) {
26832      var n = data.length, x = data[0], m = x.length, i, j, k, s1, s2, s3, dx, o, o0, y0 = [];
26833      y0[0] = o = o0 = 0;
26834      for (j = 1; j < m; ++j) {
26835        for (i = 0, s1 = 0; i < n; ++i) s1 += data[i][j][1];
26836        for (i = 0, s2 = 0, dx = x[j][0] - x[j - 1][0]; i < n; ++i) {
26837          for (k = 0, s3 = (data[i][j][1] - data[i][j - 1][1]) / (2 * dx); k < i; ++k) {
26838            s3 += (data[k][j][1] - data[k][j - 1][1]) / dx;
26839          }
26840          s2 += s3 * data[i][j][1];
26841        }
26842        y0[j] = o -= s1 ? s2 / s1 * dx : 0;
26843        if (o < o0) o0 = o;
26844      }
26845      for (j = 0; j < m; ++j) y0[j] -= o0;
26846      return y0;
26847    },
26848    expand: function(data) {
26849      var n = data.length, m = data[0].length, k = 1 / n, i, j, o, y0 = [];
26850      for (j = 0; j < m; ++j) {
26851        for (i = 0, o = 0; i < n; i++) o += data[i][j][1];
26852        if (o) for (i = 0; i < n; i++) data[i][j][1] /= o; else for (i = 0; i < n; i++) data[i][j][1] = k;
26853      }
26854      for (j = 0; j < m; ++j) y0[j] = 0;
26855      return y0;
26856    },
26857    zero: d3_layout_stackOffsetZero
26858  });
26859  function d3_layout_stackOrderDefault(data) {
26860    return d3.range(data.length);
26861  }
26862  function d3_layout_stackOffsetZero(data) {
26863    var j = -1, m = data[0].length, y0 = [];
26864    while (++j < m) y0[j] = 0;
26865    return y0;
26866  }
26867  function d3_layout_stackMaxIndex(array) {
26868    var i = 1, j = 0, v = array[0][1], k, n = array.length;
26869    for (;i < n; ++i) {
26870      if ((k = array[i][1]) > v) {
26871        j = i;
26872        v = k;
26873      }
26874    }
26875    return j;
26876  }
26877  function d3_layout_stackReduceSum(d) {
26878    return d.reduce(d3_layout_stackSum, 0);
26879  }
26880  function d3_layout_stackSum(p, d) {
26881    return p + d[1];
26882  }
26883  d3.layout.histogram = function() {
26884    var frequency = true, valuer = Number, ranger = d3_layout_histogramRange, binner = d3_layout_histogramBinSturges;
26885    function histogram(data, i) {
26886      var bins = [], values = data.map(valuer, this), range = ranger.call(this, values, i), thresholds = binner.call(this, range, values, i), bin, i = -1, n = values.length, m = thresholds.length - 1, k = frequency ? 1 : 1 / n, x;
26887      while (++i < m) {
26888        bin = bins[i] = [];
26889        bin.dx = thresholds[i + 1] - (bin.x = thresholds[i]);
26890        bin.y = 0;
26891      }
26892      if (m > 0) {
26893        i = -1;
26894        while (++i < n) {
26895          x = values[i];
26896          if (x >= range[0] && x <= range[1]) {
26897            bin = bins[d3.bisect(thresholds, x, 1, m) - 1];
26898            bin.y += k;
26899            bin.push(data[i]);
26900          }
26901        }
26902      }
26903      return bins;
26904    }
26905    histogram.value = function(x) {
26906      if (!arguments.length) return valuer;
26907      valuer = x;
26908      return histogram;
26909    };
26910    histogram.range = function(x) {
26911      if (!arguments.length) return ranger;
26912      ranger = d3_functor(x);
26913      return histogram;
26914    };
26915    histogram.bins = function(x) {
26916      if (!arguments.length) return binner;
26917      binner = typeof x === "number" ? function(range) {
26918        return d3_layout_histogramBinFixed(range, x);
26919      } : d3_functor(x);
26920      return histogram;
26921    };
26922    histogram.frequency = function(x) {
26923      if (!arguments.length) return frequency;
26924      frequency = !!x;
26925      return histogram;
26926    };
26927    return histogram;
26928  };
26929  function d3_layout_histogramBinSturges(range, values) {
26930    return d3_layout_histogramBinFixed(range, Math.ceil(Math.log(values.length) / Math.LN2 + 1));
26931  }
26932  function d3_layout_histogramBinFixed(range, n) {
26933    var x = -1, b = +range[0], m = (range[1] - b) / n, f = [];
26934    while (++x <= n) f[x] = m * x + b;
26935    return f;
26936  }
26937  function d3_layout_histogramRange(values) {
26938    return [ d3.min(values), d3.max(values) ];
26939  }
26940  d3.layout.pack = function() {
26941    var hierarchy = d3.layout.hierarchy().sort(d3_layout_packSort), padding = 0, size = [ 1, 1 ], radius;
26942    function pack(d, i) {
26943      var nodes = hierarchy.call(this, d, i), root = nodes[0], w = size[0], h = size[1], r = radius == null ? Math.sqrt : typeof radius === "function" ? radius : function() {
26944        return radius;
26945      };
26946      root.x = root.y = 0;
26947      d3_layout_hierarchyVisitAfter(root, function(d) {
26948        d.r = +r(d.value);
26949      });
26950      d3_layout_hierarchyVisitAfter(root, d3_layout_packSiblings);
26951      if (padding) {
26952        var dr = padding * (radius ? 1 : Math.max(2 * root.r / w, 2 * root.r / h)) / 2;
26953        d3_layout_hierarchyVisitAfter(root, function(d) {
26954          d.r += dr;
26955        });
26956        d3_layout_hierarchyVisitAfter(root, d3_layout_packSiblings);
26957        d3_layout_hierarchyVisitAfter(root, function(d) {
26958          d.r -= dr;
26959        });
26960      }
26961      d3_layout_packTransform(root, w / 2, h / 2, radius ? 1 : 1 / Math.max(2 * root.r / w, 2 * root.r / h));
26962      return nodes;
26963    }
26964    pack.size = function(_) {
26965      if (!arguments.length) return size;
26966      size = _;
26967      return pack;
26968    };
26969    pack.radius = function(_) {
26970      if (!arguments.length) return radius;
26971      radius = _ == null || typeof _ === "function" ? _ : +_;
26972      return pack;
26973    };
26974    pack.padding = function(_) {
26975      if (!arguments.length) return padding;
26976      padding = +_;
26977      return pack;
26978    };
26979    return d3_layout_hierarchyRebind(pack, hierarchy);
26980  };
26981  function d3_layout_packSort(a, b) {
26982    return a.value - b.value;
26983  }
26984  function d3_layout_packInsert(a, b) {
26985    var c = a._pack_next;
26986    a._pack_next = b;
26987    b._pack_prev = a;
26988    b._pack_next = c;
26989    c._pack_prev = b;
26990  }
26991  function d3_layout_packSplice(a, b) {
26992    a._pack_next = b;
26993    b._pack_prev = a;
26994  }
26995  function d3_layout_packIntersects(a, b) {
26996    var dx = b.x - a.x, dy = b.y - a.y, dr = a.r + b.r;
26997    return .999 * dr * dr > dx * dx + dy * dy;
26998  }
26999  function d3_layout_packSiblings(node) {
27000    if (!(nodes = node.children) || !(n = nodes.length)) return;
27001    var nodes, xMin = Infinity, xMax = -Infinity, yMin = Infinity, yMax = -Infinity, a, b, c, i, j, k, n;
27002    function bound(node) {
27003      xMin = Math.min(node.x - node.r, xMin);
27004      xMax = Math.max(node.x + node.r, xMax);
27005      yMin = Math.min(node.y - node.r, yMin);
27006      yMax = Math.max(node.y + node.r, yMax);
27007    }
27008    nodes.forEach(d3_layout_packLink);
27009    a = nodes[0];
27010    a.x = -a.r;
27011    a.y = 0;
27012    bound(a);
27013    if (n > 1) {
27014      b = nodes[1];
27015      b.x = b.r;
27016      b.y = 0;
27017      bound(b);
27018      if (n > 2) {
27019        c = nodes[2];
27020        d3_layout_packPlace(a, b, c);
27021        bound(c);
27022        d3_layout_packInsert(a, c);
27023        a._pack_prev = c;
27024        d3_layout_packInsert(c, b);
27025        b = a._pack_next;
27026        for (i = 3; i < n; i++) {
27027          d3_layout_packPlace(a, b, c = nodes[i]);
27028          var isect = 0, s1 = 1, s2 = 1;
27029          for (j = b._pack_next; j !== b; j = j._pack_next, s1++) {
27030            if (d3_layout_packIntersects(j, c)) {
27031              isect = 1;
27032              break;
27033            }
27034          }
27035          if (isect == 1) {
27036            for (k = a._pack_prev; k !== j._pack_prev; k = k._pack_prev, s2++) {
27037              if (d3_layout_packIntersects(k, c)) {
27038                break;
27039              }
27040            }
27041          }
27042          if (isect) {
27043            if (s1 < s2 || s1 == s2 && b.r < a.r) d3_layout_packSplice(a, b = j); else d3_layout_packSplice(a = k, b);
27044            i--;
27045          } else {
27046            d3_layout_packInsert(a, c);
27047            b = c;
27048            bound(c);
27049          }
27050        }
27051      }
27052    }
27053    var cx = (xMin + xMax) / 2, cy = (yMin + yMax) / 2, cr = 0;
27054    for (i = 0; i < n; i++) {
27055      c = nodes[i];
27056      c.x -= cx;
27057      c.y -= cy;
27058      cr = Math.max(cr, c.r + Math.sqrt(c.x * c.x + c.y * c.y));
27059    }
27060    node.r = cr;
27061    nodes.forEach(d3_layout_packUnlink);
27062  }
27063  function d3_layout_packLink(node) {
27064    node._pack_next = node._pack_prev = node;
27065  }
27066  function d3_layout_packUnlink(node) {
27067    delete node._pack_next;
27068    delete node._pack_prev;
27069  }
27070  function d3_layout_packTransform(node, x, y, k) {
27071    var children = node.children;
27072    node.x = x += k * node.x;
27073    node.y = y += k * node.y;
27074    node.r *= k;
27075    if (children) {
27076      var i = -1, n = children.length;
27077      while (++i < n) d3_layout_packTransform(children[i], x, y, k);
27078    }
27079  }
27080  function d3_layout_packPlace(a, b, c) {
27081    var db = a.r + c.r, dx = b.x - a.x, dy = b.y - a.y;
27082    if (db && (dx || dy)) {
27083      var da = b.r + c.r, dc = dx * dx + dy * dy;
27084      da *= da;
27085      db *= db;
27086      var x = .5 + (db - da) / (2 * dc), y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc);
27087      c.x = a.x + x * dx + y * dy;
27088      c.y = a.y + x * dy - y * dx;
27089    } else {
27090      c.x = a.x + db;
27091      c.y = a.y;
27092    }
27093  }
27094  d3.layout.tree = function() {
27095    var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = null;
27096    function tree(d, i) {
27097      var nodes = hierarchy.call(this, d, i), root0 = nodes[0], root1 = wrapTree(root0);
27098      d3_layout_hierarchyVisitAfter(root1, firstWalk), root1.parent.m = -root1.z;
27099      d3_layout_hierarchyVisitBefore(root1, secondWalk);
27100      if (nodeSize) d3_layout_hierarchyVisitBefore(root0, sizeNode); else {
27101        var left = root0, right = root0, bottom = root0;
27102        d3_layout_hierarchyVisitBefore(root0, function(node) {
27103          if (node.x < left.x) left = node;
27104          if (node.x > right.x) right = node;
27105          if (node.depth > bottom.depth) bottom = node;
27106        });
27107        var tx = separation(left, right) / 2 - left.x, kx = size[0] / (right.x + separation(right, left) / 2 + tx), ky = size[1] / (bottom.depth || 1);
27108        d3_layout_hierarchyVisitBefore(root0, function(node) {
27109          node.x = (node.x + tx) * kx;
27110          node.y = node.depth * ky;
27111        });
27112      }
27113      return nodes;
27114    }
27115    function wrapTree(root0) {
27116      var root1 = {
27117        A: null,
27118        children: [ root0 ]
27119      }, queue = [ root1 ], node1;
27120      while ((node1 = queue.pop()) != null) {
27121        for (var children = node1.children, child, i = 0, n = children.length; i < n; ++i) {
27122          queue.push((children[i] = child = {
27123            _: children[i],
27124            parent: node1,
27125            children: (child = children[i].children) && child.slice() || [],
27126            A: null,
27127            a: null,
27128            z: 0,
27129            m: 0,
27130            c: 0,
27131            s: 0,
27132            t: null,
27133            i: i
27134          }).a = child);
27135        }
27136      }
27137      return root1.children[0];
27138    }
27139    function firstWalk(v) {
27140      var children = v.children, siblings = v.parent.children, w = v.i ? siblings[v.i - 1] : null;
27141      if (children.length) {
27142        d3_layout_treeShift(v);
27143        var midpoint = (children[0].z + children[children.length - 1].z) / 2;
27144        if (w) {
27145          v.z = w.z + separation(v._, w._);
27146          v.m = v.z - midpoint;
27147        } else {
27148          v.z = midpoint;
27149        }
27150      } else if (w) {
27151        v.z = w.z + separation(v._, w._);
27152      }
27153      v.parent.A = apportion(v, w, v.parent.A || siblings[0]);
27154    }
27155    function secondWalk(v) {
27156      v._.x = v.z + v.parent.m;
27157      v.m += v.parent.m;
27158    }
27159    function apportion(v, w, ancestor) {
27160      if (w) {
27161        var vip = v, vop = v, vim = w, vom = vip.parent.children[0], sip = vip.m, sop = vop.m, sim = vim.m, som = vom.m, shift;
27162        while (vim = d3_layout_treeRight(vim), vip = d3_layout_treeLeft(vip), vim && vip) {
27163          vom = d3_layout_treeLeft(vom);
27164          vop = d3_layout_treeRight(vop);
27165          vop.a = v;
27166          shift = vim.z + sim - vip.z - sip + separation(vim._, vip._);
27167          if (shift > 0) {
27168            d3_layout_treeMove(d3_layout_treeAncestor(vim, v, ancestor), v, shift);
27169            sip += shift;
27170            sop += shift;
27171          }
27172          sim += vim.m;
27173          sip += vip.m;
27174          som += vom.m;
27175          sop += vop.m;
27176        }
27177        if (vim && !d3_layout_treeRight(vop)) {
27178          vop.t = vim;
27179          vop.m += sim - sop;
27180        }
27181        if (vip && !d3_layout_treeLeft(vom)) {
27182          vom.t = vip;
27183          vom.m += sip - som;
27184          ancestor = v;
27185        }
27186      }
27187      return ancestor;
27188    }
27189    function sizeNode(node) {
27190      node.x *= size[0];
27191      node.y = node.depth * size[1];
27192    }
27193    tree.separation = function(x) {
27194      if (!arguments.length) return separation;
27195      separation = x;
27196      return tree;
27197    };
27198    tree.size = function(x) {
27199      if (!arguments.length) return nodeSize ? null : size;
27200      nodeSize = (size = x) == null ? sizeNode : null;
27201      return tree;
27202    };
27203    tree.nodeSize = function(x) {
27204      if (!arguments.length) return nodeSize ? size : null;
27205      nodeSize = (size = x) == null ? null : sizeNode;
27206      return tree;
27207    };
27208    return d3_layout_hierarchyRebind(tree, hierarchy);
27209  };
27210  function d3_layout_treeSeparation(a, b) {
27211    return a.parent == b.parent ? 1 : 2;
27212  }
27213  function d3_layout_treeLeft(v) {
27214    var children = v.children;
27215    return children.length ? children[0] : v.t;
27216  }
27217  function d3_layout_treeRight(v) {
27218    var children = v.children, n;
27219    return (n = children.length) ? children[n - 1] : v.t;
27220  }
27221  function d3_layout_treeMove(wm, wp, shift) {
27222    var change = shift / (wp.i - wm.i);
27223    wp.c -= change;
27224    wp.s += shift;
27225    wm.c += change;
27226    wp.z += shift;
27227    wp.m += shift;
27228  }
27229  function d3_layout_treeShift(v) {
27230    var shift = 0, change = 0, children = v.children, i = children.length, w;
27231    while (--i >= 0) {
27232      w = children[i];
27233      w.z += shift;
27234      w.m += shift;
27235      shift += w.s + (change += w.c);
27236    }
27237  }
27238  function d3_layout_treeAncestor(vim, v, ancestor) {
27239    return vim.a.parent === v.parent ? vim.a : ancestor;
27240  }
27241  d3.layout.cluster = function() {
27242    var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = false;
27243    function cluster(d, i) {
27244      var nodes = hierarchy.call(this, d, i), root = nodes[0], previousNode, x = 0;
27245      d3_layout_hierarchyVisitAfter(root, function(node) {
27246        var children = node.children;
27247        if (children && children.length) {
27248          node.x = d3_layout_clusterX(children);
27249          node.y = d3_layout_clusterY(children);
27250        } else {
27251          node.x = previousNode ? x += separation(node, previousNode) : 0;
27252          node.y = 0;
27253          previousNode = node;
27254        }
27255      });
27256      var left = d3_layout_clusterLeft(root), right = d3_layout_clusterRight(root), x0 = left.x - separation(left, right) / 2, x1 = right.x + separation(right, left) / 2;
27257      d3_layout_hierarchyVisitAfter(root, nodeSize ? function(node) {
27258        node.x = (node.x - root.x) * size[0];
27259        node.y = (root.y - node.y) * size[1];
27260      } : function(node) {
27261        node.x = (node.x - x0) / (x1 - x0) * size[0];
27262        node.y = (1 - (root.y ? node.y / root.y : 1)) * size[1];
27263      });
27264      return nodes;
27265    }
27266    cluster.separation = function(x) {
27267      if (!arguments.length) return separation;
27268      separation = x;
27269      return cluster;
27270    };
27271    cluster.size = function(x) {
27272      if (!arguments.length) return nodeSize ? null : size;
27273      nodeSize = (size = x) == null;
27274      return cluster;
27275    };
27276    cluster.nodeSize = function(x) {
27277      if (!arguments.length) return nodeSize ? size : null;
27278      nodeSize = (size = x) != null;
27279      return cluster;
27280    };
27281    return d3_layout_hierarchyRebind(cluster, hierarchy);
27282  };
27283  function d3_layout_clusterY(children) {
27284    return 1 + d3.max(children, function(child) {
27285      return child.y;
27286    });
27287  }
27288  function d3_layout_clusterX(children) {
27289    return children.reduce(function(x, child) {
27290      return x + child.x;
27291    }, 0) / children.length;
27292  }
27293  function d3_layout_clusterLeft(node) {
27294    var children = node.children;
27295    return children && children.length ? d3_layout_clusterLeft(children[0]) : node;
27296  }
27297  function d3_layout_clusterRight(node) {
27298    var children = node.children, n;
27299    return children && (n = children.length) ? d3_layout_clusterRight(children[n - 1]) : node;
27300  }
27301  d3.layout.treemap = function() {
27302    var hierarchy = d3.layout.hierarchy(), round = Math.round, size = [ 1, 1 ], padding = null, pad = d3_layout_treemapPadNull, sticky = false, stickies, mode = "squarify", ratio = .5 * (1 + Math.sqrt(5));
27303    function scale(children, k) {
27304      var i = -1, n = children.length, child, area;
27305      while (++i < n) {
27306        area = (child = children[i]).value * (k < 0 ? 0 : k);
27307        child.area = isNaN(area) || area <= 0 ? 0 : area;
27308      }
27309    }
27310    function squarify(node) {
27311      var children = node.children;
27312      if (children && children.length) {
27313        var rect = pad(node), row = [], remaining = children.slice(), child, best = Infinity, score, u = mode === "slice" ? rect.dx : mode === "dice" ? rect.dy : mode === "slice-dice" ? node.depth & 1 ? rect.dy : rect.dx : Math.min(rect.dx, rect.dy), n;
27314        scale(remaining, rect.dx * rect.dy / node.value);
27315        row.area = 0;
27316        while ((n = remaining.length) > 0) {
27317          row.push(child = remaining[n - 1]);
27318          row.area += child.area;
27319          if (mode !== "squarify" || (score = worst(row, u)) <= best) {
27320            remaining.pop();
27321            best = score;
27322          } else {
27323            row.area -= row.pop().area;
27324            position(row, u, rect, false);
27325            u = Math.min(rect.dx, rect.dy);
27326            row.length = row.area = 0;
27327            best = Infinity;
27328          }
27329        }
27330        if (row.length) {
27331          position(row, u, rect, true);
27332          row.length = row.area = 0;
27333        }
27334        children.forEach(squarify);
27335      }
27336    }
27337    function stickify(node) {
27338      var children = node.children;
27339      if (children && children.length) {
27340        var rect = pad(node), remaining = children.slice(), child, row = [];
27341        scale(remaining, rect.dx * rect.dy / node.value);
27342        row.area = 0;
27343        while (child = remaining.pop()) {
27344          row.push(child);
27345          row.area += child.area;
27346          if (child.z != null) {
27347            position(row, child.z ? rect.dx : rect.dy, rect, !remaining.length);
27348            row.length = row.area = 0;
27349          }
27350        }
vendor: 12,778 bytes, lines 27351-27745
27351        children.forEach(stickify);
27352      }
27353    }
27354    function worst(row, u) {
27355      var s = row.area, r, rmax = 0, rmin = Infinity, i = -1, n = row.length;
27356      while (++i < n) {
27357        if (!(r = row[i].area)) continue;
27358        if (r < rmin) rmin = r;
27359        if (r > rmax) rmax = r;
27360      }
27361      s *= s;
27362      u *= u;
27363      return s ? Math.max(u * rmax * ratio / s, s / (u * rmin * ratio)) : Infinity;
27364    }
27365    function position(row, u, rect, flush) {
27366      var i = -1, n = row.length, x = rect.x, y = rect.y, v = u ? round(row.area / u) : 0, o;
27367      if (u == rect.dx) {
27368        if (flush || v > rect.dy) v = rect.dy;
27369        while (++i < n) {
27370          o = row[i];
27371          o.x = x;
27372          o.y = y;
27373          o.dy = v;
27374          x += o.dx = Math.min(rect.x + rect.dx - x, v ? round(o.area / v) : 0);
27375        }
27376        o.z = true;
27377        o.dx += rect.x + rect.dx - x;
27378        rect.y += v;
27379        rect.dy -= v;
27380      } else {
27381        if (flush || v > rect.dx) v = rect.dx;
27382        while (++i < n) {
27383          o = row[i];
27384          o.x = x;
27385          o.y = y;
27386          o.dx = v;
27387          y += o.dy = Math.min(rect.y + rect.dy - y, v ? round(o.area / v) : 0);
27388        }
27389        o.z = false;
27390        o.dy += rect.y + rect.dy - y;
27391        rect.x += v;
27392        rect.dx -= v;
27393      }
27394    }
27395    function treemap(d) {
27396      var nodes = stickies || hierarchy(d), root = nodes[0];
27397      root.x = 0;
27398      root.y = 0;
27399      root.dx = size[0];
27400      root.dy = size[1];
27401      if (stickies) hierarchy.revalue(root);
27402      scale([ root ], root.dx * root.dy / root.value);
27403      (stickies ? stickify : squarify)(root);
27404      if (sticky) stickies = nodes;
27405      return nodes;
27406    }
27407    treemap.size = function(x) {
27408      if (!arguments.length) return size;
27409      size = x;
27410      return treemap;
27411    };
27412    treemap.padding = function(x) {
27413      if (!arguments.length) return padding;
27414      function padFunction(node) {
27415        var p = x.call(treemap, node, node.depth);
27416        return p == null ? d3_layout_treemapPadNull(node) : d3_layout_treemapPad(node, typeof p === "number" ? [ p, p, p, p ] : p);
27417      }
27418      function padConstant(node) {
27419        return d3_layout_treemapPad(node, x);
27420      }
27421      var type;
27422      pad = (padding = x) == null ? d3_layout_treemapPadNull : (type = typeof x) === "function" ? padFunction : type === "number" ? (x = [ x, x, x, x ], 
27423      padConstant) : padConstant;
27424      return treemap;
27425    };
27426    treemap.round = function(x) {
27427      if (!arguments.length) return round != Number;
27428      round = x ? Math.round : Number;
27429      return treemap;
27430    };
27431    treemap.sticky = function(x) {
27432      if (!arguments.length) return sticky;
27433      sticky = x;
27434      stickies = null;
27435      return treemap;
27436    };
27437    treemap.ratio = function(x) {
27438      if (!arguments.length) return ratio;
27439      ratio = x;
27440      return treemap;
27441    };
27442    treemap.mode = function(x) {
27443      if (!arguments.length) return mode;
27444      mode = x + "";
27445      return treemap;
27446    };
27447    return d3_layout_hierarchyRebind(treemap, hierarchy);
27448  };
27449  function d3_layout_treemapPadNull(node) {
27450    return {
27451      x: node.x,
27452      y: node.y,
27453      dx: node.dx,
27454      dy: node.dy
27455    };
27456  }
27457  function d3_layout_treemapPad(node, padding) {
27458    var x = node.x + padding[3], y = node.y + padding[0], dx = node.dx - padding[1] - padding[3], dy = node.dy - padding[0] - padding[2];
27459    if (dx < 0) {
27460      x += dx / 2;
27461      dx = 0;
27462    }
27463    if (dy < 0) {
27464      y += dy / 2;
27465      dy = 0;
27466    }
27467    return {
27468      x: x,
27469      y: y,
27470      dx: dx,
27471      dy: dy
27472    };
27473  }
27474  d3.random = {
27475    normal: function(µ, σ) {
27476      var n = arguments.length;
27477      if (n < 2) σ = 1;
27478      if (n < 1) µ = 0;
27479      return function() {
27480        var x, y, r;
27481        do {
27482          x = Math.random() * 2 - 1;
27483          y = Math.random() * 2 - 1;
27484          r = x * x + y * y;
27485        } while (!r || r > 1);
27486        return µ + σ * x * Math.sqrt(-2 * Math.log(r) / r);
27487      };
27488    },
27489    logNormal: function() {
27490      var random = d3.random.normal.apply(d3, arguments);
27491      return function() {
27492        return Math.exp(random());
27493      };
27494    },
27495    bates: function(m) {
27496      var random = d3.random.irwinHall(m);
27497      return function() {
27498        return random() / m;
27499      };
27500    },
27501    irwinHall: function(m) {
27502      return function() {
27503        for (var s = 0, j = 0; j < m; j++) s += Math.random();
27504        return s;
27505      };
27506    }
27507  };
27508  d3.scale = {};
27509  function d3_scaleExtent(domain) {
27510    var start = domain[0], stop = domain[domain.length - 1];
27511    return start < stop ? [ start, stop ] : [ stop, start ];
27512  }
27513  function d3_scaleRange(scale) {
27514    return scale.rangeExtent ? scale.rangeExtent() : d3_scaleExtent(scale.range());
27515  }
27516  function d3_scale_bilinear(domain, range, uninterpolate, interpolate) {
27517    var u = uninterpolate(domain[0], domain[1]), i = interpolate(range[0], range[1]);
27518    return function(x) {
27519      return i(u(x));
27520    };
27521  }
27522  function d3_scale_nice(domain, nice) {
27523    var i0 = 0, i1 = domain.length - 1, x0 = domain[i0], x1 = domain[i1], dx;
27524    if (x1 < x0) {
27525      dx = i0, i0 = i1, i1 = dx;
27526      dx = x0, x0 = x1, x1 = dx;
27527    }
27528    domain[i0] = nice.floor(x0);
27529    domain[i1] = nice.ceil(x1);
27530    return domain;
27531  }
27532  function d3_scale_niceStep(step) {
27533    return step ? {
27534      floor: function(x) {
27535        return Math.floor(x / step) * step;
27536      },
27537      ceil: function(x) {
27538        return Math.ceil(x / step) * step;
27539      }
27540    } : d3_scale_niceIdentity;
27541  }
27542  var d3_scale_niceIdentity = {
27543    floor: d3_identity,
27544    ceil: d3_identity
27545  };
27546  function d3_scale_polylinear(domain, range, uninterpolate, interpolate) {
27547    var u = [], i = [], j = 0, k = Math.min(domain.length, range.length) - 1;
27548    if (domain[k] < domain[0]) {
27549      domain = domain.slice().reverse();
27550      range = range.slice().reverse();
27551    }
27552    while (++j <= k) {
27553      u.push(uninterpolate(domain[j - 1], domain[j]));
27554      i.push(interpolate(range[j - 1], range[j]));
27555    }
27556    return function(x) {
27557      var j = d3.bisect(domain, x, 1, k) - 1;
27558      return i[j](u[j](x));
27559    };
27560  }
27561  d3.scale.linear = function() {
27562    return d3_scale_linear([ 0, 1 ], [ 0, 1 ], d3_interpolate, false);
27563  };
27564  function d3_scale_linear(domain, range, interpolate, clamp) {
27565    var output, input;
27566    function rescale() {
27567      var linear = Math.min(domain.length, range.length) > 2 ? d3_scale_polylinear : d3_scale_bilinear, uninterpolate = clamp ? d3_uninterpolateClamp : d3_uninterpolateNumber;
27568      output = linear(domain, range, uninterpolate, interpolate);
27569      input = linear(range, domain, uninterpolate, d3_interpolate);
27570      return scale;
27571    }
27572    function scale(x) {
27573      return output(x);
27574    }
27575    scale.invert = function(y) {
27576      return input(y);
27577    };
27578    scale.domain = function(x) {
27579      if (!arguments.length) return domain;
27580      domain = x.map(Number);
27581      return rescale();
27582    };
27583    scale.range = function(x) {
27584      if (!arguments.length) return range;
27585      range = x;
27586      return rescale();
27587    };
27588    scale.rangeRound = function(x) {
27589      return scale.range(x).interpolate(d3_interpolateRound);
27590    };
27591    scale.clamp = function(x) {
27592      if (!arguments.length) return clamp;
27593      clamp = x;
27594      return rescale();
27595    };
27596    scale.interpolate = function(x) {
27597      if (!arguments.length) return interpolate;
27598      interpolate = x;
27599      return rescale();
27600    };
27601    scale.ticks = function(m) {
27602      return d3_scale_linearTicks(domain, m);
27603    };
27604    scale.tickFormat = function(m, format) {
27605      return d3_scale_linearTickFormat(domain, m, format);
27606    };
27607    scale.nice = function(m) {
27608      d3_scale_linearNice(domain, m);
27609      return rescale();
27610    };
27611    scale.copy = function() {
27612      return d3_scale_linear(domain, range, interpolate, clamp);
27613    };
27614    return rescale();
27615  }
27616  function d3_scale_linearRebind(scale, linear) {
27617    return d3.rebind(scale, linear, "range", "rangeRound", "interpolate", "clamp");
27618  }
27619  function d3_scale_linearNice(domain, m) {
27620    return d3_scale_nice(domain, d3_scale_niceStep(d3_scale_linearTickRange(domain, m)[2]));
27621  }
27622  function d3_scale_linearTickRange(domain, m) {
27623    if (m == null) m = 10;
27624    var extent = d3_scaleExtent(domain), span = extent[1] - extent[0], step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10)), err = m / span * step;
27625    if (err <= .15) step *= 10; else if (err <= .35) step *= 5; else if (err <= .75) step *= 2;
27626    extent[0] = Math.ceil(extent[0] / step) * step;
27627    extent[1] = Math.floor(extent[1] / step) * step + step * .5;
27628    extent[2] = step;
27629    return extent;
27630  }
27631  function d3_scale_linearTicks(domain, m) {
27632    return d3.range.apply(d3, d3_scale_linearTickRange(domain, m));
27633  }
27634  function d3_scale_linearTickFormat(domain, m, format) {
27635    var range = d3_scale_linearTickRange(domain, m);
27636    if (format) {
27637      var match = d3_format_re.exec(format);
27638      match.shift();
27639      if (match[8] === "s") {
27640        var prefix = d3.formatPrefix(Math.max(abs(range[0]), abs(range[1])));
27641        if (!match[7]) match[7] = "." + d3_scale_linearPrecision(prefix.scale(range[2]));
27642        match[8] = "f";
27643        format = d3.format(match.join(""));
27644        return function(d) {
27645          return format(prefix.scale(d)) + prefix.symbol;
27646        };
27647      }
27648      if (!match[7]) match[7] = "." + d3_scale_linearFormatPrecision(match[8], range);
27649      format = match.join("");
27650    } else {
27651      format = ",." + d3_scale_linearPrecision(range[2]) + "f";
27652    }
27653    return d3.format(format);
27654  }
27655  var d3_scale_linearFormatSignificant = {
27656    s: 1,
27657    g: 1,
27658    p: 1,
27659    r: 1,
27660    e: 1
27661  };
27662  function d3_scale_linearPrecision(value) {
27663    return -Math.floor(Math.log(value) / Math.LN10 + .01);
27664  }
27665  function d3_scale_linearFormatPrecision(type, range) {
27666    var p = d3_scale_linearPrecision(range[2]);
27667    return type in d3_scale_linearFormatSignificant ? Math.abs(p - d3_scale_linearPrecision(Math.max(abs(range[0]), abs(range[1])))) + +(type !== "e") : p - (type === "%") * 2;
27668  }
27669  d3.scale.log = function() {
27670    return d3_scale_log(d3.scale.linear().domain([ 0, 1 ]), 10, true, [ 1, 10 ]);
27671  };
27672  function d3_scale_log(linear, base, positive, domain) {
27673    function log(x) {
27674      return (positive ? Math.log(x < 0 ? 0 : x) : -Math.log(x > 0 ? 0 : -x)) / Math.log(base);
27675    }
27676    function pow(x) {
27677      return positive ? Math.pow(base, x) : -Math.pow(base, -x);
27678    }
27679    function scale(x) {
27680      return linear(log(x));
27681    }
27682    scale.invert = function(x) {
27683      return pow(linear.invert(x));
27684    };
27685    scale.domain = function(x) {
27686      if (!arguments.length) return domain;
27687      positive = x[0] >= 0;
27688      linear.domain((domain = x.map(Number)).map(log));
27689      return scale;
27690    };
27691    scale.base = function(_) {
27692      if (!arguments.length) return base;
27693      base = +_;
27694      linear.domain(domain.map(log));
27695      return scale;
27696    };
27697    scale.nice = function() {
27698      var niced = d3_scale_nice(domain.map(log), positive ? Math : d3_scale_logNiceNegative);
27699      linear.domain(niced);
27700      domain = niced.map(pow);
27701      return scale;
27702    };
27703    scale.ticks = function() {
27704      var extent = d3_scaleExtent(domain), ticks = [], u = extent[0], v = extent[1], i = Math.floor(log(u)), j = Math.ceil(log(v)), n = base % 1 ? 2 : base;
27705      if (isFinite(j - i)) {
27706        if (positive) {
27707          for (;i < j; i++) for (var k = 1; k < n; k++) ticks.push(pow(i) * k);
27708          ticks.push(pow(i));
27709        } else {
27710          ticks.push(pow(i));
27711          for (;i++ < j; ) for (var k = n - 1; k > 0; k--) ticks.push(pow(i) * k);
27712        }
27713        for (i = 0; ticks[i] < u; i++) {}
27714        for (j = ticks.length; ticks[j - 1] > v; j--) {}
27715        ticks = ticks.slice(i, j);
27716      }
27717      return ticks;
27718    };
27719    scale.tickFormat = function(n, format) {
27720      if (!arguments.length) return d3_scale_logFormat;
27721      if (arguments.length < 2) format = d3_scale_logFormat; else if (typeof format !== "function") format = d3.format(format);
27722      var k = Math.max(.1, n / scale.ticks().length), f = positive ? (e = 1e-12, Math.ceil) : (e = -1e-12, 
27723      Math.floor), e;
27724      return function(d) {
27725        return d / pow(f(log(d) + e)) <= k ? format(d) : "";
27726      };
27727    };
27728    scale.copy = function() {
27729      return d3_scale_log(linear.copy(), base, positive, domain);
27730    };
27731    return d3_scale_linearRebind(scale, linear);
27732  }
27733  var d3_scale_logFormat = d3.format(".0e"), d3_scale_logNiceNegative = {
27734    floor: function(x) {
27735      return -Math.ceil(-x);
27736    },
27737    ceil: function(x) {
27738      return -Math.floor(-x);
27739    }
27740  };
27741  d3.scale.pow = function() {
27742    return d3_scale_pow(d3.scale.linear(), 1, [ 0, 1 ]);
27743  };
27744  function d3_scale_pow(linear, exponent, domain) {
27745    var powp = d3_scale_powPow(exponent), powb = d3_scale_powPow(1 / exponent);
vendor: 8,414 bytes, lines 27746-27995
27746    function scale(x) {
27747      return linear(powp(x));
27748    }
27749    scale.invert = function(x) {
27750      return powb(linear.invert(x));
27751    };
27752    scale.domain = function(x) {
27753      if (!arguments.length) return domain;
27754      linear.domain((domain = x.map(Number)).map(powp));
27755      return scale;
27756    };
27757    scale.ticks = function(m) {
27758      return d3_scale_linearTicks(domain, m);
27759    };
27760    scale.tickFormat = function(m, format) {
27761      return d3_scale_linearTickFormat(domain, m, format);
27762    };
27763    scale.nice = function(m) {
27764      return scale.domain(d3_scale_linearNice(domain, m));
27765    };
27766    scale.exponent = function(x) {
27767      if (!arguments.length) return exponent;
27768      powp = d3_scale_powPow(exponent = x);
27769      powb = d3_scale_powPow(1 / exponent);
27770      linear.domain(domain.map(powp));
27771      return scale;
27772    };
27773    scale.copy = function() {
27774      return d3_scale_pow(linear.copy(), exponent, domain);
27775    };
27776    return d3_scale_linearRebind(scale, linear);
27777  }
27778  function d3_scale_powPow(e) {
27779    return function(x) {
27780      return x < 0 ? -Math.pow(-x, e) : Math.pow(x, e);
27781    };
27782  }
27783  d3.scale.sqrt = function() {
27784    return d3.scale.pow().exponent(.5);
27785  };
27786  d3.scale.ordinal = function() {
27787    return d3_scale_ordinal([], {
27788      t: "range",
27789      a: [ [] ]
27790    });
27791  };
27792  function d3_scale_ordinal(domain, ranger) {
27793    var index, range, rangeBand;
27794    function scale(x) {
27795      return range[((index.get(x) || (ranger.t === "range" ? index.set(x, domain.push(x)) : NaN)) - 1) % range.length];
27796    }
27797    function steps(start, step) {
27798      return d3.range(domain.length).map(function(i) {
27799        return start + step * i;
27800      });
27801    }
27802    scale.domain = function(x) {
27803      if (!arguments.length) return domain;
27804      domain = [];
27805      index = new d3_Map();
27806      var i = -1, n = x.length, xi;
27807      while (++i < n) if (!index.has(xi = x[i])) index.set(xi, domain.push(xi));
27808      return scale[ranger.t].apply(scale, ranger.a);
27809    };
27810    scale.range = function(x) {
27811      if (!arguments.length) return range;
27812      range = x;
27813      rangeBand = 0;
27814      ranger = {
27815        t: "range",
27816        a: arguments
27817      };
27818      return scale;
27819    };
27820    scale.rangePoints = function(x, padding) {
27821      if (arguments.length < 2) padding = 0;
27822      var start = x[0], stop = x[1], step = (stop - start) / (Math.max(1, domain.length - 1) + padding);
27823      range = steps(domain.length < 2 ? (start + stop) / 2 : start + step * padding / 2, step);
27824      rangeBand = 0;
27825      ranger = {
27826        t: "rangePoints",
27827        a: arguments
27828      };
27829      return scale;
27830    };
27831    scale.rangeBands = function(x, padding, outerPadding) {
27832      if (arguments.length < 2) padding = 0;
27833      if (arguments.length < 3) outerPadding = padding;
27834      var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = (stop - start) / (domain.length - padding + 2 * outerPadding);
27835      range = steps(start + step * outerPadding, step);
27836      if (reverse) range.reverse();
27837      rangeBand = step * (1 - padding);
27838      ranger = {
27839        t: "rangeBands",
27840        a: arguments
27841      };
27842      return scale;
27843    };
27844    scale.rangeRoundBands = function(x, padding, outerPadding) {
27845      if (arguments.length < 2) padding = 0;
27846      if (arguments.length < 3) outerPadding = padding;
27847      var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = Math.floor((stop - start) / (domain.length - padding + 2 * outerPadding)), error = stop - start - (domain.length - padding) * step;
27848      range = steps(start + Math.round(error / 2), step);
27849      if (reverse) range.reverse();
27850      rangeBand = Math.round(step * (1 - padding));
27851      ranger = {
27852        t: "rangeRoundBands",
27853        a: arguments
27854      };
27855      return scale;
27856    };
27857    scale.rangeBand = function() {
27858      return rangeBand;
27859    };
27860    scale.rangeExtent = function() {
27861      return d3_scaleExtent(ranger.a[0]);
27862    };
27863    scale.copy = function() {
27864      return d3_scale_ordinal(domain, ranger);
27865    };
27866    return scale.domain(domain);
27867  }
27868  d3.scale.category10 = function() {
27869    return d3.scale.ordinal().range(d3_category10);
27870  };
27871  d3.scale.category20 = function() {
27872    return d3.scale.ordinal().range(d3_category20);
27873  };
27874  d3.scale.category20b = function() {
27875    return d3.scale.ordinal().range(d3_category20b);
27876  };
27877  d3.scale.category20c = function() {
27878    return d3.scale.ordinal().range(d3_category20c);
27879  };
27880  var d3_category10 = [ 2062260, 16744206, 2924588, 14034728, 9725885, 9197131, 14907330, 8355711, 12369186, 1556175 ].map(d3_rgbString);
27881  var d3_category20 = [ 2062260, 11454440, 16744206, 16759672, 2924588, 10018698, 14034728, 16750742, 9725885, 12955861, 9197131, 12885140, 14907330, 16234194, 8355711, 13092807, 12369186, 14408589, 1556175, 10410725 ].map(d3_rgbString);
27882  var d3_category20b = [ 3750777, 5395619, 7040719, 10264286, 6519097, 9216594, 11915115, 13556636, 9202993, 12426809, 15186514, 15190932, 8666169, 11356490, 14049643, 15177372, 8077683, 10834324, 13528509, 14589654 ].map(d3_rgbString);
27883  var d3_category20c = [ 3244733, 7057110, 10406625, 13032431, 15095053, 16616764, 16625259, 16634018, 3253076, 7652470, 10607003, 13101504, 7695281, 10394312, 12369372, 14342891, 6513507, 9868950, 12434877, 14277081 ].map(d3_rgbString);
27884  d3.scale.quantile = function() {
27885    return d3_scale_quantile([], []);
27886  };
27887  function d3_scale_quantile(domain, range) {
27888    var thresholds;
27889    function rescale() {
27890      var k = 0, q = range.length;
27891      thresholds = [];
27892      while (++k < q) thresholds[k - 1] = d3.quantile(domain, k / q);
27893      return scale;
27894    }
27895    function scale(x) {
27896      if (!isNaN(x = +x)) return range[d3.bisect(thresholds, x)];
27897    }
27898    scale.domain = function(x) {
27899      if (!arguments.length) return domain;
27900      domain = x.map(d3_number).filter(d3_numeric).sort(d3_ascending);
27901      return rescale();
27902    };
27903    scale.range = function(x) {
27904      if (!arguments.length) return range;
27905      range = x;
27906      return rescale();
27907    };
27908    scale.quantiles = function() {
27909      return thresholds;
27910    };
27911    scale.invertExtent = function(y) {
27912      y = range.indexOf(y);
27913      return y < 0 ? [ NaN, NaN ] : [ y > 0 ? thresholds[y - 1] : domain[0], y < thresholds.length ? thresholds[y] : domain[domain.length - 1] ];
27914    };
27915    scale.copy = function() {
27916      return d3_scale_quantile(domain, range);
27917    };
27918    return rescale();
27919  }
27920  d3.scale.quantize = function() {
27921    return d3_scale_quantize(0, 1, [ 0, 1 ]);
27922  };
27923  function d3_scale_quantize(x0, x1, range) {
27924    var kx, i;
27925    function scale(x) {
27926      return range[Math.max(0, Math.min(i, Math.floor(kx * (x - x0))))];
27927    }
27928    function rescale() {
27929      kx = range.length / (x1 - x0);
27930      i = range.length - 1;
27931      return scale;
27932    }
27933    scale.domain = function(x) {
27934      if (!arguments.length) return [ x0, x1 ];
27935      x0 = +x[0];
27936      x1 = +x[x.length - 1];
27937      return rescale();
27938    };
27939    scale.range = function(x) {
27940      if (!arguments.length) return range;
27941      range = x;
27942      return rescale();
27943    };
27944    scale.invertExtent = function(y) {
27945      y = range.indexOf(y);
27946      y = y < 0 ? NaN : y / kx + x0;
27947      return [ y, y + 1 / kx ];
27948    };
27949    scale.copy = function() {
27950      return d3_scale_quantize(x0, x1, range);
27951    };
27952    return rescale();
27953  }
27954  d3.scale.threshold = function() {
27955    return d3_scale_threshold([ .5 ], [ 0, 1 ]);
27956  };
27957  function d3_scale_threshold(domain, range) {
27958    function scale(x) {
27959      if (x <= x) return range[d3.bisect(domain, x)];
27960    }
27961    scale.domain = function(_) {
27962      if (!arguments.length) return domain;
27963      domain = _;
27964      return scale;
27965    };
27966    scale.range = function(_) {
27967      if (!arguments.length) return range;
27968      range = _;
27969      return scale;
27970    };
27971    scale.invertExtent = function(y) {
27972      y = range.indexOf(y);
27973      return [ domain[y - 1], domain[y] ];
27974    };
27975    scale.copy = function() {
27976      return d3_scale_threshold(domain, range);
27977    };
27978    return scale;
27979  }
27980  d3.scale.identity = function() {
27981    return d3_scale_identity([ 0, 1 ]);
27982  };
27983  function d3_scale_identity(domain) {
27984    function identity(x) {
27985      return +x;
27986    }
27987    identity.invert = identity;
27988    identity.domain = identity.range = function(x) {
27989      if (!arguments.length) return domain;
27990      domain = x.map(identity);
27991      return identity;
27992    };
27993    identity.ticks = function(m) {
27994      return d3_scale_linearTicks(domain, m);
27995    };
27996    identity.tickFormat = function(m, format) {
27997      return d3_scale_linearTickFormat(domain, m, format);
27998    };
27999    identity.copy = function() {
28000      return d3_scale_identity(domain);
28001    };
28002    return identity;
28003  }
28004  d3.svg = {};
28005  d3.svg.arc = function() {
28006    var innerRadius = d3_svg_arcInnerRadius, outerRadius = d3_svg_arcOuterRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle;
28007    function arc() {
28008      var r0 = innerRadius.apply(this, arguments), r1 = outerRadius.apply(this, arguments), a0 = startAngle.apply(this, arguments) + d3_svg_arcOffset, a1 = endAngle.apply(this, arguments) + d3_svg_arcOffset, da = (a1 < a0 && (da = a0, 
28009      a0 = a1, a1 = da), a1 - a0), df = da < π ? "0" : "1", c0 = Math.cos(a0), s0 = Math.sin(a0), c1 = Math.cos(a1), s1 = Math.sin(a1);
28010      return da >= d3_svg_arcMax ? r0 ? "M0," + r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + -r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + r1 + "M0," + r0 + "A" + r0 + "," + r0 + " 0 1,0 0," + -r0 + "A" + r0 + "," + r0 + " 0 1,0 0," + r0 + "Z" : "M0," + r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + -r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + r1 + "Z" : r0 ? "M" + r1 * c0 + "," + r1 * s0 + "A" + r1 + "," + r1 + " 0 " + df + ",1 " + r1 * c1 + "," + r1 * s1 + "L" + r0 * c1 + "," + r0 * s1 + "A" + r0 + "," + r0 + " 0 " + df + ",0 " + r0 * c0 + "," + r0 * s0 + "Z" : "M" + r1 * c0 + "," + r1 * s0 + "A" + r1 + "," + r1 + " 0 " + df + ",1 " + r1 * c1 + "," + r1 * s1 + "L0,0" + "Z";
28011    }
28012    arc.innerRadius = function(v) {
28013      if (!arguments.length) return innerRadius;
28014      innerRadius = d3_functor(v);
28015      return arc;
28016    };
28017    arc.outerRadius = function(v) {
28018      if (!arguments.length) return outerRadius;
28019      outerRadius = d3_functor(v);
28020      return arc;
28021    };
28022    arc.startAngle = function(v) {
28023      if (!arguments.length) return startAngle;
28024      startAngle = d3_functor(v);
28025      return arc;
28026    };
28027    arc.endAngle = function(v) {
28028      if (!arguments.length) return endAngle;
28029      endAngle = d3_functor(v);
28030      return arc;
28031    };
28032    arc.centroid = function() {
28033      var r = (innerRadius.apply(this, arguments) + outerRadius.apply(this, arguments)) / 2, a = (startAngle.apply(this, arguments) + endAngle.apply(this, arguments)) / 2 + d3_svg_arcOffset;
28034      return [ Math.cos(a) * r, Math.sin(a) * r ];
28035    };
28036    return arc;
28037  };
28038  var d3_svg_arcOffset = -halfπ, d3_svg_arcMax = τ - ε;
28039  function d3_svg_arcInnerRadius(d) {
28040    return d.innerRadius;
28041  }
28042  function d3_svg_arcOuterRadius(d) {
28043    return d.outerRadius;
28044  }
28045  function d3_svg_arcStartAngle(d) {
28046    return d.startAngle;
28047  }
28048  function d3_svg_arcEndAngle(d) {
28049    return d.endAngle;
28050  }
28051  function d3_svg_line(projection) {
28052    var x = d3_geom_pointX, y = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, tension = .7;
28053    function line(data) {
28054      var segments = [], points = [], i = -1, n = data.length, d, fx = d3_functor(x), fy = d3_functor(y);
28055      function segment() {
28056        segments.push("M", interpolate(projection(points), tension));
28057      }
28058      while (++i < n) {
28059        if (defined.call(this, d = data[i], i)) {
28060          points.push([ +fx.call(this, d, i), +fy.call(this, d, i) ]);
28061        } else if (points.length) {
28062          segment();
28063          points = [];
28064        }
28065      }
28066      if (points.length) segment();
28067      return segments.length ? segments.join("") : null;
28068    }
28069    line.x = function(_) {
28070      if (!arguments.length) return x;
28071      x = _;
28072      return line;
28073    };
28074    line.y = function(_) {
28075      if (!arguments.length) return y;
28076      y = _;
28077      return line;
28078    };
28079    line.defined = function(_) {
28080      if (!arguments.length) return defined;
28081      defined = _;
28082      return line;
28083    };
28084    line.interpolate = function(_) {
28085      if (!arguments.length) return interpolateKey;
28086      if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key;
28087      return line;
28088    };
28089    line.tension = function(_) {
28090      if (!arguments.length) return tension;
28091      tension = _;
28092      return line;
28093    };
28094    return line;
28095  }
28096  d3.svg.line = function() {
28097    return d3_svg_line(d3_identity);
28098  };
28099  var d3_svg_lineInterpolators = d3.map({
28100    linear: d3_svg_lineLinear,
28101    "linear-closed": d3_svg_lineLinearClosed,
28102    step: d3_svg_lineStep,
28103    "step-before": d3_svg_lineStepBefore,
28104    "step-after": d3_svg_lineStepAfter,
28105    basis: d3_svg_lineBasis,
28106    "basis-open": d3_svg_lineBasisOpen,
28107    "basis-closed": d3_svg_lineBasisClosed,
28108    bundle: d3_svg_lineBundle,
28109    cardinal: d3_svg_lineCardinal,
28110    "cardinal-open": d3_svg_lineCardinalOpen,
28111    "cardinal-closed": d3_svg_lineCardinalClosed,
28112    monotone: d3_svg_lineMonotone
28113  });
vendor: 12,000 bytes, lines 28114-28430
28114  d3_svg_lineInterpolators.forEach(function(key, value) {
28115    value.key = key;
28116    value.closed = /-closed$/.test(key);
28117  });
28118  function d3_svg_lineLinear(points) {
28119    return points.join("L");
28120  }
28121  function d3_svg_lineLinearClosed(points) {
28122    return d3_svg_lineLinear(points) + "Z";
28123  }
28124  function d3_svg_lineStep(points) {
28125    var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ];
28126    while (++i < n) path.push("H", (p[0] + (p = points[i])[0]) / 2, "V", p[1]);
28127    if (n > 1) path.push("H", p[0]);
28128    return path.join("");
28129  }
28130  function d3_svg_lineStepBefore(points) {
28131    var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ];
28132    while (++i < n) path.push("V", (p = points[i])[1], "H", p[0]);
28133    return path.join("");
28134  }
28135  function d3_svg_lineStepAfter(points) {
28136    var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ];
28137    while (++i < n) path.push("H", (p = points[i])[0], "V", p[1]);
28138    return path.join("");
28139  }
28140  function d3_svg_lineCardinalOpen(points, tension) {
28141    return points.length < 4 ? d3_svg_lineLinear(points) : points[1] + d3_svg_lineHermite(points.slice(1, points.length - 1), d3_svg_lineCardinalTangents(points, tension));
28142  }
28143  function d3_svg_lineCardinalClosed(points, tension) {
28144    return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite((points.push(points[0]), 
28145    points), d3_svg_lineCardinalTangents([ points[points.length - 2] ].concat(points, [ points[1] ]), tension));
28146  }
28147  function d3_svg_lineCardinal(points, tension) {
28148    return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineCardinalTangents(points, tension));
28149  }
28150  function d3_svg_lineHermite(points, tangents) {
28151    if (tangents.length < 1 || points.length != tangents.length && points.length != tangents.length + 2) {
28152      return d3_svg_lineLinear(points);
28153    }
28154    var quad = points.length != tangents.length, path = "", p0 = points[0], p = points[1], t0 = tangents[0], t = t0, pi = 1;
28155    if (quad) {
28156      path += "Q" + (p[0] - t0[0] * 2 / 3) + "," + (p[1] - t0[1] * 2 / 3) + "," + p[0] + "," + p[1];
28157      p0 = points[1];
28158      pi = 2;
28159    }
28160    if (tangents.length > 1) {
28161      t = tangents[1];
28162      p = points[pi];
28163      pi++;
28164      path += "C" + (p0[0] + t0[0]) + "," + (p0[1] + t0[1]) + "," + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1];
28165      for (var i = 2; i < tangents.length; i++, pi++) {
28166        p = points[pi];
28167        t = tangents[i];
28168        path += "S" + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1];
28169      }
28170    }
28171    if (quad) {
28172      var lp = points[pi];
28173      path += "Q" + (p[0] + t[0] * 2 / 3) + "," + (p[1] + t[1] * 2 / 3) + "," + lp[0] + "," + lp[1];
28174    }
28175    return path;
28176  }
28177  function d3_svg_lineCardinalTangents(points, tension) {
28178    var tangents = [], a = (1 - tension) / 2, p0, p1 = points[0], p2 = points[1], i = 1, n = points.length;
28179    while (++i < n) {
28180      p0 = p1;
28181      p1 = p2;
28182      p2 = points[i];
28183      tangents.push([ a * (p2[0] - p0[0]), a * (p2[1] - p0[1]) ]);
28184    }
28185    return tangents;
28186  }
28187  function d3_svg_lineBasis(points) {
28188    if (points.length < 3) return d3_svg_lineLinear(points);
28189    var i = 1, n = points.length, pi = points[0], x0 = pi[0], y0 = pi[1], px = [ x0, x0, x0, (pi = points[1])[0] ], py = [ y0, y0, y0, pi[1] ], path = [ x0, ",", y0, "L", d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ];
28190    points.push(points[n - 1]);
28191    while (++i <= n) {
28192      pi = points[i];
28193      px.shift();
28194      px.push(pi[0]);
28195      py.shift();
28196      py.push(pi[1]);
28197      d3_svg_lineBasisBezier(path, px, py);
28198    }
28199    points.pop();
28200    path.push("L", pi);
28201    return path.join("");
28202  }
28203  function d3_svg_lineBasisOpen(points) {
28204    if (points.length < 4) return d3_svg_lineLinear(points);
28205    var path = [], i = -1, n = points.length, pi, px = [ 0 ], py = [ 0 ];
28206    while (++i < 3) {
28207      pi = points[i];
28208      px.push(pi[0]);
28209      py.push(pi[1]);
28210    }
28211    path.push(d3_svg_lineDot4(d3_svg_lineBasisBezier3, px) + "," + d3_svg_lineDot4(d3_svg_lineBasisBezier3, py));
28212    --i;
28213    while (++i < n) {
28214      pi = points[i];
28215      px.shift();
28216      px.push(pi[0]);
28217      py.shift();
28218      py.push(pi[1]);
28219      d3_svg_lineBasisBezier(path, px, py);
28220    }
28221    return path.join("");
28222  }
28223  function d3_svg_lineBasisClosed(points) {
28224    var path, i = -1, n = points.length, m = n + 4, pi, px = [], py = [];
28225    while (++i < 4) {
28226      pi = points[i % n];
28227      px.push(pi[0]);
28228      py.push(pi[1]);
28229    }
28230    path = [ d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ];
28231    --i;
28232    while (++i < m) {
28233      pi = points[i % n];
28234      px.shift();
28235      px.push(pi[0]);
28236      py.shift();
28237      py.push(pi[1]);
28238      d3_svg_lineBasisBezier(path, px, py);
28239    }
28240    return path.join("");
28241  }
28242  function d3_svg_lineBundle(points, tension) {
28243    var n = points.length - 1;
28244    if (n) {
28245      var x0 = points[0][0], y0 = points[0][1], dx = points[n][0] - x0, dy = points[n][1] - y0, i = -1, p, t;
28246      while (++i <= n) {
28247        p = points[i];
28248        t = i / n;
28249        p[0] = tension * p[0] + (1 - tension) * (x0 + t * dx);
28250        p[1] = tension * p[1] + (1 - tension) * (y0 + t * dy);
28251      }
28252    }
28253    return d3_svg_lineBasis(points);
28254  }
28255  function d3_svg_lineDot4(a, b) {
28256    return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
28257  }
28258  var d3_svg_lineBasisBezier1 = [ 0, 2 / 3, 1 / 3, 0 ], d3_svg_lineBasisBezier2 = [ 0, 1 / 3, 2 / 3, 0 ], d3_svg_lineBasisBezier3 = [ 0, 1 / 6, 2 / 3, 1 / 6 ];
28259  function d3_svg_lineBasisBezier(path, x, y) {
28260    path.push("C", d3_svg_lineDot4(d3_svg_lineBasisBezier1, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier1, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, y));
28261  }
28262  function d3_svg_lineSlope(p0, p1) {
28263    return (p1[1] - p0[1]) / (p1[0] - p0[0]);
28264  }
28265  function d3_svg_lineFiniteDifferences(points) {
28266    var i = 0, j = points.length - 1, m = [], p0 = points[0], p1 = points[1], d = m[0] = d3_svg_lineSlope(p0, p1);
28267    while (++i < j) {
28268      m[i] = (d + (d = d3_svg_lineSlope(p0 = p1, p1 = points[i + 1]))) / 2;
28269    }
28270    m[i] = d;
28271    return m;
28272  }
28273  function d3_svg_lineMonotoneTangents(points) {
28274    var tangents = [], d, a, b, s, m = d3_svg_lineFiniteDifferences(points), i = -1, j = points.length - 1;
28275    while (++i < j) {
28276      d = d3_svg_lineSlope(points[i], points[i + 1]);
28277      if (abs(d) < ε) {
28278        m[i] = m[i + 1] = 0;
28279      } else {
28280        a = m[i] / d;
28281        b = m[i + 1] / d;
28282        s = a * a + b * b;
28283        if (s > 9) {
28284          s = d * 3 / Math.sqrt(s);
28285          m[i] = s * a;
28286          m[i + 1] = s * b;
28287        }
28288      }
28289    }
28290    i = -1;
28291    while (++i <= j) {
28292      s = (points[Math.min(j, i + 1)][0] - points[Math.max(0, i - 1)][0]) / (6 * (1 + m[i] * m[i]));
28293      tangents.push([ s || 0, m[i] * s || 0 ]);
28294    }
28295    return tangents;
28296  }
28297  function d3_svg_lineMonotone(points) {
28298    return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineMonotoneTangents(points));
28299  }
28300  d3.svg.line.radial = function() {
28301    var line = d3_svg_line(d3_svg_lineRadial);
28302    line.radius = line.x, delete line.x;
28303    line.angle = line.y, delete line.y;
28304    return line;
28305  };
28306  function d3_svg_lineRadial(points) {
28307    var point, i = -1, n = points.length, r, a;
28308    while (++i < n) {
28309      point = points[i];
28310      r = point[0];
28311      a = point[1] + d3_svg_arcOffset;
28312      point[0] = r * Math.cos(a);
28313      point[1] = r * Math.sin(a);
28314    }
28315    return points;
28316  }
28317  function d3_svg_area(projection) {
28318    var x0 = d3_geom_pointX, x1 = d3_geom_pointX, y0 = 0, y1 = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, interpolateReverse = interpolate, L = "L", tension = .7;
28319    function area(data) {
28320      var segments = [], points0 = [], points1 = [], i = -1, n = data.length, d, fx0 = d3_functor(x0), fy0 = d3_functor(y0), fx1 = x0 === x1 ? function() {
28321        return x;
28322      } : d3_functor(x1), fy1 = y0 === y1 ? function() {
28323        return y;
28324      } : d3_functor(y1), x, y;
28325      function segment() {
28326        segments.push("M", interpolate(projection(points1), tension), L, interpolateReverse(projection(points0.reverse()), tension), "Z");
28327      }
28328      while (++i < n) {
28329        if (defined.call(this, d = data[i], i)) {
28330          points0.push([ x = +fx0.call(this, d, i), y = +fy0.call(this, d, i) ]);
28331          points1.push([ +fx1.call(this, d, i), +fy1.call(this, d, i) ]);
28332        } else if (points0.length) {
28333          segment();
28334          points0 = [];
28335          points1 = [];
28336        }
28337      }
28338      if (points0.length) segment();
28339      return segments.length ? segments.join("") : null;
28340    }
28341    area.x = function(_) {
28342      if (!arguments.length) return x1;
28343      x0 = x1 = _;
28344      return area;
28345    };
28346    area.x0 = function(_) {
28347      if (!arguments.length) return x0;
28348      x0 = _;
28349      return area;
28350    };
28351    area.x1 = function(_) {
28352      if (!arguments.length) return x1;
28353      x1 = _;
28354      return area;
28355    };
28356    area.y = function(_) {
28357      if (!arguments.length) return y1;
28358      y0 = y1 = _;
28359      return area;
28360    };
28361    area.y0 = function(_) {
28362      if (!arguments.length) return y0;
28363      y0 = _;
28364      return area;
28365    };
28366    area.y1 = function(_) {
28367      if (!arguments.length) return y1;
28368      y1 = _;
28369      return area;
28370    };
28371    area.defined = function(_) {
28372      if (!arguments.length) return defined;
28373      defined = _;
28374      return area;
28375    };
28376    area.interpolate = function(_) {
28377      if (!arguments.length) return interpolateKey;
28378      if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key;
28379      interpolateReverse = interpolate.reverse || interpolate;
28380      L = interpolate.closed ? "M" : "L";
28381      return area;
28382    };
28383    area.tension = function(_) {
28384      if (!arguments.length) return tension;
28385      tension = _;
28386      return area;
28387    };
28388    return area;
28389  }
28390  d3_svg_lineStepBefore.reverse = d3_svg_lineStepAfter;
28391  d3_svg_lineStepAfter.reverse = d3_svg_lineStepBefore;
28392  d3.svg.area = function() {
28393    return d3_svg_area(d3_identity);
28394  };
28395  d3.svg.area.radial = function() {
28396    var area = d3_svg_area(d3_svg_lineRadial);
28397    area.radius = area.x, delete area.x;
28398    area.innerRadius = area.x0, delete area.x0;
28399    area.outerRadius = area.x1, delete area.x1;
28400    area.angle = area.y, delete area.y;
28401    area.startAngle = area.y0, delete area.y0;
28402    area.endAngle = area.y1, delete area.y1;
28403    return area;
28404  };
28405  d3.svg.chord = function() {
28406    var source = d3_source, target = d3_target, radius = d3_svg_chordRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle;
28407    function chord(d, i) {
28408      var s = subgroup(this, source, d, i), t = subgroup(this, target, d, i);
28409      return "M" + s.p0 + arc(s.r, s.p1, s.a1 - s.a0) + (equals(s, t) ? curve(s.r, s.p1, s.r, s.p0) : curve(s.r, s.p1, t.r, t.p0) + arc(t.r, t.p1, t.a1 - t.a0) + curve(t.r, t.p1, s.r, s.p0)) + "Z";
28410    }
28411    function subgroup(self, f, d, i) {
28412      var subgroup = f.call(self, d, i), r = radius.call(self, subgroup, i), a0 = startAngle.call(self, subgroup, i) + d3_svg_arcOffset, a1 = endAngle.call(self, subgroup, i) + d3_svg_arcOffset;
28413      return {
28414        r: r,
28415        a0: a0,
28416        a1: a1,
28417        p0: [ r * Math.cos(a0), r * Math.sin(a0) ],
28418        p1: [ r * Math.cos(a1), r * Math.sin(a1) ]
28419      };
28420    }
28421    function equals(a, b) {
28422      return a.a0 == b.a0 && a.a1 == b.a1;
28423    }
28424    function arc(r, p, a) {
28425      return "A" + r + "," + r + " 0 " + +(a > π) + ",1 " + p;
28426    }
28427    function curve(r0, p0, r1, p1) {
28428      return "Q 0,0 " + p1;
28429    }
28430    chord.radius = function(v) {
vendor: 5,564 bytes, lines 28431-28580
28431      if (!arguments.length) return radius;
28432      radius = d3_functor(v);
28433      return chord;
28434    };
28435    chord.source = function(v) {
28436      if (!arguments.length) return source;
28437      source = d3_functor(v);
28438      return chord;
28439    };
28440    chord.target = function(v) {
28441      if (!arguments.length) return target;
28442      target = d3_functor(v);
28443      return chord;
28444    };
28445    chord.startAngle = function(v) {
28446      if (!arguments.length) return startAngle;
28447      startAngle = d3_functor(v);
28448      return chord;
28449    };
28450    chord.endAngle = function(v) {
28451      if (!arguments.length) return endAngle;
28452      endAngle = d3_functor(v);
28453      return chord;
28454    };
28455    return chord;
28456  };
28457  function d3_svg_chordRadius(d) {
28458    return d.radius;
28459  }
28460  d3.svg.diagonal = function() {
28461    var source = d3_source, target = d3_target, projection = d3_svg_diagonalProjection;
28462    function diagonal(d, i) {
28463      var p0 = source.call(this, d, i), p3 = target.call(this, d, i), m = (p0.y + p3.y) / 2, p = [ p0, {
28464        x: p0.x,
28465        y: m
28466      }, {
28467        x: p3.x,
28468        y: m
28469      }, p3 ];
28470      p = p.map(projection);
28471      return "M" + p[0] + "C" + p[1] + " " + p[2] + " " + p[3];
28472    }
28473    diagonal.source = function(x) {
28474      if (!arguments.length) return source;
28475      source = d3_functor(x);
28476      return diagonal;
28477    };
28478    diagonal.target = function(x) {
28479      if (!arguments.length) return target;
28480      target = d3_functor(x);
28481      return diagonal;
28482    };
28483    diagonal.projection = function(x) {
28484      if (!arguments.length) return projection;
28485      projection = x;
28486      return diagonal;
28487    };
28488    return diagonal;
28489  };
28490  function d3_svg_diagonalProjection(d) {
28491    return [ d.x, d.y ];
28492  }
28493  d3.svg.diagonal.radial = function() {
28494    var diagonal = d3.svg.diagonal(), projection = d3_svg_diagonalProjection, projection_ = diagonal.projection;
28495    diagonal.projection = function(x) {
28496      return arguments.length ? projection_(d3_svg_diagonalRadialProjection(projection = x)) : projection;
28497    };
28498    return diagonal;
28499  };
28500  function d3_svg_diagonalRadialProjection(projection) {
28501    return function() {
28502      var d = projection.apply(this, arguments), r = d[0], a = d[1] + d3_svg_arcOffset;
28503      return [ r * Math.cos(a), r * Math.sin(a) ];
28504    };
28505  }
28506  d3.svg.symbol = function() {
28507    var type = d3_svg_symbolType, size = d3_svg_symbolSize;
28508    function symbol(d, i) {
28509      return (d3_svg_symbols.get(type.call(this, d, i)) || d3_svg_symbolCircle)(size.call(this, d, i));
28510    }
28511    symbol.type = function(x) {
28512      if (!arguments.length) return type;
28513      type = d3_functor(x);
28514      return symbol;
28515    };
28516    symbol.size = function(x) {
28517      if (!arguments.length) return size;
28518      size = d3_functor(x);
28519      return symbol;
28520    };
28521    return symbol;
28522  };
28523  function d3_svg_symbolSize() {
28524    return 64;
28525  }
28526  function d3_svg_symbolType() {
28527    return "circle";
28528  }
28529  function d3_svg_symbolCircle(size) {
28530    var r = Math.sqrt(size / π);
28531    return "M0," + r + "A" + r + "," + r + " 0 1,1 0," + -r + "A" + r + "," + r + " 0 1,1 0," + r + "Z";
28532  }
28533  var d3_svg_symbols = d3.map({
28534    circle: d3_svg_symbolCircle,
28535    cross: function(size) {
28536      var r = Math.sqrt(size / 5) / 2;
28537      return "M" + -3 * r + "," + -r + "H" + -r + "V" + -3 * r + "H" + r + "V" + -r + "H" + 3 * r + "V" + r + "H" + r + "V" + 3 * r + "H" + -r + "V" + r + "H" + -3 * r + "Z";
28538    },
28539    diamond: function(size) {
28540      var ry = Math.sqrt(size / (2 * d3_svg_symbolTan30)), rx = ry * d3_svg_symbolTan30;
28541      return "M0," + -ry + "L" + rx + ",0" + " 0," + ry + " " + -rx + ",0" + "Z";
28542    },
28543    square: function(size) {
28544      var r = Math.sqrt(size) / 2;
28545      return "M" + -r + "," + -r + "L" + r + "," + -r + " " + r + "," + r + " " + -r + "," + r + "Z";
28546    },
28547    "triangle-down": function(size) {
28548      var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2;
28549      return "M0," + ry + "L" + rx + "," + -ry + " " + -rx + "," + -ry + "Z";
28550    },
28551    "triangle-up": function(size) {
28552      var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2;
28553      return "M0," + -ry + "L" + rx + "," + ry + " " + -rx + "," + ry + "Z";
28554    }
28555  });
28556  d3.svg.symbolTypes = d3_svg_symbols.keys();
28557  var d3_svg_symbolSqrt3 = Math.sqrt(3), d3_svg_symbolTan30 = Math.tan(30 * d3_radians);
28558  function d3_transition(groups, id) {
28559    d3_subclass(groups, d3_transitionPrototype);
28560    groups.id = id;
28561    return groups;
28562  }
28563  var d3_transitionPrototype = [], d3_transitionId = 0, d3_transitionInheritId, d3_transitionInherit;
28564  d3_transitionPrototype.call = d3_selectionPrototype.call;
28565  d3_transitionPrototype.empty = d3_selectionPrototype.empty;
28566  d3_transitionPrototype.node = d3_selectionPrototype.node;
28567  d3_transitionPrototype.size = d3_selectionPrototype.size;
28568  d3.transition = function(selection) {
28569    return arguments.length ? d3_transitionInheritId ? selection.transition() : selection : d3_selectionRoot.transition();
28570  };
28571  d3.transition.prototype = d3_transitionPrototype;
28572  d3_transitionPrototype.select = function(selector) {
28573    var id = this.id, subgroups = [], subgroup, subnode, node;
28574    selector = d3_selection_selector(selector);
28575    for (var j = -1, m = this.length; ++j < m; ) {
28576      subgroups.push(subgroup = []);
28577      for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
28578        if ((node = group[i]) && (subnode = selector.call(node, node.__data__, i, j))) {
28579          if ("__data__" in node) subnode.__data__ = node.__data__;
28580          d3_transitionNode(subnode, i, id, node.__transition__[id]);
vendor: 4,289 bytes, lines 28581-28695
28581          subgroup.push(subnode);
28582        } else {
28583          subgroup.push(null);
28584        }
28585      }
28586    }
28587    return d3_transition(subgroups, id);
28588  };
28589  d3_transitionPrototype.selectAll = function(selector) {
28590    var id = this.id, subgroups = [], subgroup, subnodes, node, subnode, transition;
28591    selector = d3_selection_selectorAll(selector);
28592    for (var j = -1, m = this.length; ++j < m; ) {
28593      for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
28594        if (node = group[i]) {
28595          transition = node.__transition__[id];
28596          subnodes = selector.call(node, node.__data__, i, j);
28597          subgroups.push(subgroup = []);
28598          for (var k = -1, o = subnodes.length; ++k < o; ) {
28599            if (subnode = subnodes[k]) d3_transitionNode(subnode, k, id, transition);
28600            subgroup.push(subnode);
28601          }
28602        }
28603      }
28604    }
28605    return d3_transition(subgroups, id);
28606  };
28607  d3_transitionPrototype.filter = function(filter) {
28608    var subgroups = [], subgroup, group, node;
28609    if (typeof filter !== "function") filter = d3_selection_filter(filter);
28610    for (var j = 0, m = this.length; j < m; j++) {
28611      subgroups.push(subgroup = []);
28612      for (var group = this[j], i = 0, n = group.length; i < n; i++) {
28613        if ((node = group[i]) && filter.call(node, node.__data__, i, j)) {
28614          subgroup.push(node);
28615        }
28616      }
28617    }
28618    return d3_transition(subgroups, this.id);
28619  };
28620  d3_transitionPrototype.tween = function(name, tween) {
28621    var id = this.id;
28622    if (arguments.length < 2) return this.node().__transition__[id].tween.get(name);
28623    return d3_selection_each(this, tween == null ? function(node) {
28624      node.__transition__[id].tween.remove(name);
28625    } : function(node) {
28626      node.__transition__[id].tween.set(name, tween);
28627    });
28628  };
28629  function d3_transition_tween(groups, name, value, tween) {
28630    var id = groups.id;
28631    return d3_selection_each(groups, typeof value === "function" ? function(node, i, j) {
28632      node.__transition__[id].tween.set(name, tween(value.call(node, node.__data__, i, j)));
28633    } : (value = tween(value), function(node) {
28634      node.__transition__[id].tween.set(name, value);
28635    }));
28636  }
28637  d3_transitionPrototype.attr = function(nameNS, value) {
28638    if (arguments.length < 2) {
28639      for (value in nameNS) this.attr(value, nameNS[value]);
28640      return this;
28641    }
28642    var interpolate = nameNS == "transform" ? d3_interpolateTransform : d3_interpolate, name = d3.ns.qualify(nameNS);
28643    function attrNull() {
28644      this.removeAttribute(name);
28645    }
28646    function attrNullNS() {
28647      this.removeAttributeNS(name.space, name.local);
28648    }
28649    function attrTween(b) {
28650      return b == null ? attrNull : (b += "", function() {
28651        var a = this.getAttribute(name), i;
28652        return a !== b && (i = interpolate(a, b), function(t) {
28653          this.setAttribute(name, i(t));
28654        });
28655      });
28656    }
28657    function attrTweenNS(b) {
28658      return b == null ? attrNullNS : (b += "", function() {
28659        var a = this.getAttributeNS(name.space, name.local), i;
28660        return a !== b && (i = interpolate(a, b), function(t) {
28661          this.setAttributeNS(name.space, name.local, i(t));
28662        });
28663      });
28664    }
28665    return d3_transition_tween(this, "attr." + nameNS, value, name.local ? attrTweenNS : attrTween);
28666  };
28667  d3_transitionPrototype.attrTween = function(nameNS, tween) {
28668    var name = d3.ns.qualify(nameNS);
28669    function attrTween(d, i) {
28670      var f = tween.call(this, d, i, this.getAttribute(name));
28671      return f && function(t) {
28672        this.setAttribute(name, f(t));
28673      };
28674    }
28675    function attrTweenNS(d, i) {
28676      var f = tween.call(this, d, i, this.getAttributeNS(name.space, name.local));
28677      return f && function(t) {
28678        this.setAttributeNS(name.space, name.local, f(t));
28679      };
28680    }
28681    return this.tween("attr." + nameNS, name.local ? attrTweenNS : attrTween);
28682  };
28683  d3_transitionPrototype.style = function(name, value, priority) {
28684    var n = arguments.length;
28685    if (n < 3) {
28686      if (typeof name !== "string") {
28687        if (n < 2) value = "";
28688        for (priority in name) this.style(priority, name[priority], value);
28689        return this;
28690      }
28691      priority = "";
28692    }
28693    function styleNull() {
28694      this.style.removeProperty(name);
28695    }
28696    function styleString(b) {
28697      return b == null ? styleNull : (b += "", function() {
28698        var a = d3_window.getComputedStyle(this, null).getPropertyValue(name), i;
28699        return a !== b && (i = d3_interpolate(a, b), function(t) {
28700          this.style.setProperty(name, i(t), priority);
28701        });
28702      });
28703    }
28704    return d3_transition_tween(this, "style." + name, value, styleString);
28705  };
28706  d3_transitionPrototype.styleTween = function(name, tween, priority) {
28707    if (arguments.length < 3) priority = "";
28708    function styleTween(d, i) {
28709      var f = tween.call(this, d, i, d3_window.getComputedStyle(this, null).getPropertyValue(name));
28710      return f && function(t) {
28711        this.style.setProperty(name, f(t), priority);
28712      };
28713    }
28714    return this.tween("style." + name, styleTween);
28715  };
28716  d3_transitionPrototype.text = function(value) {
28717    return d3_transition_tween(this, "text", value, d3_transition_text);
28718  };
28719  function d3_transition_text(b) {
28720    if (b == null) b = "";
28721    return function() {
28722      this.textContent = b;
28723    };
28724  }
28725  d3_transitionPrototype.remove = function() {
28726    return this.each("end.transition", function() {
28727      var p;
28728      if (this.__transition__.count < 2 && (p = this.parentNode)) p.removeChild(this);
28729    });
28730  };
28731  d3_transitionPrototype.ease = function(value) {
28732    var id = this.id;
28733    if (arguments.length < 1) return this.node().__transition__[id].ease;
28734    if (typeof value !== "function") value = d3.ease.apply(d3, arguments);
28735    return d3_selection_each(this, function(node) {
28736      node.__transition__[id].ease = value;
28737    });
28738  };
28739  d3_transitionPrototype.delay = function(value) {
28740    var id = this.id;
28741    if (arguments.length < 1) return this.node().__transition__[id].delay;
28742    return d3_selection_each(this, typeof value === "function" ? function(node, i, j) {
28743      node.__transition__[id].delay = +value.call(node, node.__data__, i, j);
28744    } : (value = +value, function(node) {
28745      node.__transition__[id].delay = value;
28746    }));
28747  };
28748  d3_transitionPrototype.duration = function(value) {
28749    var id = this.id;
28750    if (arguments.length < 1) return this.node().__transition__[id].duration;
28751    return d3_selection_each(this, typeof value === "function" ? function(node, i, j) {
28752      node.__transition__[id].duration = Math.max(1, value.call(node, node.__data__, i, j));
28753    } : (value = Math.max(1, value), function(node) {
28754      node.__transition__[id].duration = value;
28755    }));
28756  };
28757  d3_transitionPrototype.each = function(type, listener) {
28758    var id = this.id;
28759    if (arguments.length < 2) {
28760      var inherit = d3_transitionInherit, inheritId = d3_transitionInheritId;
28761      d3_transitionInheritId = id;
28762      d3_selection_each(this, function(node, i, j) {
28763        d3_transitionInherit = node.__transition__[id];
28764        type.call(node, node.__data__, i, j);
28765      });
28766      d3_transitionInherit = inherit;
28767      d3_transitionInheritId = inheritId;
28768    } else {
28769      d3_selection_each(this, function(node) {
28770        var transition = node.__transition__[id];
28771        (transition.event || (transition.event = d3.dispatch("start", "end"))).on(type, listener);
28772      });
28773    }
28774    return this;
28775  };
28776  d3_transitionPrototype.transition = function() {
28777    var id0 = this.id, id1 = ++d3_transitionId, subgroups = [], subgroup, group, node, transition;
28778    for (var j = 0, m = this.length; j < m; j++) {
28779      subgroups.push(subgroup = []);
28780      for (var group = this[j], i = 0, n = group.length; i < n; i++) {
28781        if (node = group[i]) {
28782          transition = Object.create(node.__transition__[id0]);
28783          transition.delay += transition.duration;
28784          d3_transitionNode(node, i, id1, transition);
28785        }
28786        subgroup.push(node);
28787      }
28788    }
28789    return d3_transition(subgroups, id1);
28790  };
28791  function d3_transitionNode(node, i, id, inherit) {
28792    var lock = node.__transition__ || (node.__transition__ = {
28793      active: 0,
28794      count: 0
28795    }), transition = lock[id];
28796    if (!transition) {
28797      var time = inherit.time;
28798      transition = lock[id] = {
28799        tween: new d3_Map(),
28800        time: time,
28801        ease: inherit.ease,
28802        delay: inherit.delay,
28803        duration: inherit.duration
28804      };
28805      ++lock.count;
28806      d3.timer(function(elapsed) {
28807        var d = node.__data__, ease = transition.ease, delay = transition.delay, duration = transition.duration, timer = d3_timer_active, tweened = [];
28808        timer.t = delay + time;
28809        if (delay <= elapsed) return start(elapsed - delay);
28810        timer.c = start;
28811        function start(elapsed) {
28812          if (lock.active > id) return stop();
28813          lock.active = id;
28814          transition.event && transition.event.start.call(node, d, i);
vendor: 11,648 bytes, lines 28815-29097
28815          transition.tween.forEach(function(key, value) {
28816            if (value = value.call(node, d, i)) {
28817              tweened.push(value);
28818            }
28819          });
28820          d3.timer(function() {
28821            timer.c = tick(elapsed || 1) ? d3_true : tick;
28822            return 1;
28823          }, 0, time);
28824        }
28825        function tick(elapsed) {
28826          if (lock.active !== id) return stop();
28827          var t = elapsed / duration, e = ease(t), n = tweened.length;
28828          while (n > 0) {
28829            tweened[--n].call(node, e);
28830          }
28831          if (t >= 1) {
28832            transition.event && transition.event.end.call(node, d, i);
28833            return stop();
28834          }
28835        }
28836        function stop() {
28837          if (--lock.count) delete lock[id]; else delete node.__transition__;
28838          return 1;
28839        }
28840      }, 0, time);
28841    }
28842  }
28843  d3.svg.axis = function() {
28844    var scale = d3.scale.linear(), orient = d3_svg_axisDefaultOrient, innerTickSize = 6, outerTickSize = 6, tickPadding = 3, tickArguments_ = [ 10 ], tickValues = null, tickFormat_;
28845    function axis(g) {
28846      g.each(function() {
28847        var g = d3.select(this);
28848        var scale0 = this.__chart__ || scale, scale1 = this.__chart__ = scale.copy();
28849        var ticks = tickValues == null ? scale1.ticks ? scale1.ticks.apply(scale1, tickArguments_) : scale1.domain() : tickValues, tickFormat = tickFormat_ == null ? scale1.tickFormat ? scale1.tickFormat.apply(scale1, tickArguments_) : d3_identity : tickFormat_, tick = g.selectAll(".tick").data(ticks, scale1), tickEnter = tick.enter().insert("g", ".domain").attr("class", "tick").style("opacity", ε), tickExit = d3.transition(tick.exit()).style("opacity", ε).remove(), tickUpdate = d3.transition(tick.order()).style("opacity", 1), tickSpacing = Math.max(innerTickSize, 0) + tickPadding, tickTransform;
28850        var range = d3_scaleRange(scale1), path = g.selectAll(".domain").data([ 0 ]), pathUpdate = (path.enter().append("path").attr("class", "domain"), 
28851        d3.transition(path));
28852        tickEnter.append("line");
28853        tickEnter.append("text");
28854        var lineEnter = tickEnter.select("line"), lineUpdate = tickUpdate.select("line"), text = tick.select("text").text(tickFormat), textEnter = tickEnter.select("text"), textUpdate = tickUpdate.select("text"), sign = orient === "top" || orient === "left" ? -1 : 1, x1, x2, y1, y2;
28855        if (orient === "bottom" || orient === "top") {
28856          tickTransform = d3_svg_axisX, x1 = "x", y1 = "y", x2 = "x2", y2 = "y2";
28857          text.attr("dy", sign < 0 ? "0em" : ".71em").style("text-anchor", "middle");
28858          pathUpdate.attr("d", "M" + range[0] + "," + sign * outerTickSize + "V0H" + range[1] + "V" + sign * outerTickSize);
28859        } else {
28860          tickTransform = d3_svg_axisY, x1 = "y", y1 = "x", x2 = "y2", y2 = "x2";
28861          text.attr("dy", ".32em").style("text-anchor", sign < 0 ? "end" : "start");
28862          pathUpdate.attr("d", "M" + sign * outerTickSize + "," + range[0] + "H0V" + range[1] + "H" + sign * outerTickSize);
28863        }
28864        lineEnter.attr(y2, sign * innerTickSize);
28865        textEnter.attr(y1, sign * tickSpacing);
28866        lineUpdate.attr(x2, 0).attr(y2, sign * innerTickSize);
28867        textUpdate.attr(x1, 0).attr(y1, sign * tickSpacing);
28868        if (scale1.rangeBand) {
28869          var x = scale1, dx = x.rangeBand() / 2;
28870          scale0 = scale1 = function(d) {
28871            return x(d) + dx;
28872          };
28873        } else if (scale0.rangeBand) {
28874          scale0 = scale1;
28875        } else {
28876          tickExit.call(tickTransform, scale1, scale0);
28877        }
28878        tickEnter.call(tickTransform, scale0, scale1);
28879        tickUpdate.call(tickTransform, scale1, scale1);
28880      });
28881    }
28882    axis.scale = function(x) {
28883      if (!arguments.length) return scale;
28884      scale = x;
28885      return axis;
28886    };
28887    axis.orient = function(x) {
28888      if (!arguments.length) return orient;
28889      orient = x in d3_svg_axisOrients ? x + "" : d3_svg_axisDefaultOrient;
28890      return axis;
28891    };
28892    axis.ticks = function() {
28893      if (!arguments.length) return tickArguments_;
28894      tickArguments_ = arguments;
28895      return axis;
28896    };
28897    axis.tickValues = function(x) {
28898      if (!arguments.length) return tickValues;
28899      tickValues = x;
28900      return axis;
28901    };
28902    axis.tickFormat = function(x) {
28903      if (!arguments.length) return tickFormat_;
28904      tickFormat_ = x;
28905      return axis;
28906    };
28907    axis.tickSize = function(x) {
28908      var n = arguments.length;
28909      if (!n) return innerTickSize;
28910      innerTickSize = +x;
28911      outerTickSize = +arguments[n - 1];
28912      return axis;
28913    };
28914    axis.innerTickSize = function(x) {
28915      if (!arguments.length) return innerTickSize;
28916      innerTickSize = +x;
28917      return axis;
28918    };
28919    axis.outerTickSize = function(x) {
28920      if (!arguments.length) return outerTickSize;
28921      outerTickSize = +x;
28922      return axis;
28923    };
28924    axis.tickPadding = function(x) {
28925      if (!arguments.length) return tickPadding;
28926      tickPadding = +x;
28927      return axis;
28928    };
28929    axis.tickSubdivide = function() {
28930      return arguments.length && axis;
28931    };
28932    return axis;
28933  };
28934  var d3_svg_axisDefaultOrient = "bottom", d3_svg_axisOrients = {
28935    top: 1,
28936    right: 1,
28937    bottom: 1,
28938    left: 1
28939  };
28940  function d3_svg_axisX(selection, x0, x1) {
28941    selection.attr("transform", function(d) {
28942      var v0 = x0(d);
28943      return "translate(" + (isFinite(v0) ? v0 : x1(d)) + ",0)";
28944    });
28945  }
28946  function d3_svg_axisY(selection, y0, y1) {
28947    selection.attr("transform", function(d) {
28948      var v0 = y0(d);
28949      return "translate(0," + (isFinite(v0) ? v0 : y1(d)) + ")";
28950    });
28951  }
28952  d3.svg.brush = function() {
28953    var event = d3_eventDispatch(brush, "brushstart", "brush", "brushend"), x = null, y = null, xExtent = [ 0, 0 ], yExtent = [ 0, 0 ], xExtentDomain, yExtentDomain, xClamp = true, yClamp = true, resizes = d3_svg_brushResizes[0];
28954    function brush(g) {
28955      g.each(function() {
28956        var g = d3.select(this).style("pointer-events", "all").style("-webkit-tap-highlight-color", "rgba(0,0,0,0)").on("mousedown.brush", brushstart).on("touchstart.brush", brushstart);
28957        var background = g.selectAll(".background").data([ 0 ]);
28958        background.enter().append("rect").attr("class", "background").style("visibility", "hidden").style("cursor", "crosshair");
28959        g.selectAll(".extent").data([ 0 ]).enter().append("rect").attr("class", "extent").style("cursor", "move");
28960        var resize = g.selectAll(".resize").data(resizes, d3_identity);
28961        resize.exit().remove();
28962        resize.enter().append("g").attr("class", function(d) {
28963          return "resize " + d;
28964        }).style("cursor", function(d) {
28965          return d3_svg_brushCursor[d];
28966        }).append("rect").attr("x", function(d) {
28967          return /[ew]$/.test(d) ? -3 : null;
28968        }).attr("y", function(d) {
28969          return /^[ns]/.test(d) ? -3 : null;
28970        }).attr("width", 6).attr("height", 6).style("visibility", "hidden");
28971        resize.style("display", brush.empty() ? "none" : null);
28972        var gUpdate = d3.transition(g), backgroundUpdate = d3.transition(background), range;
28973        if (x) {
28974          range = d3_scaleRange(x);
28975          backgroundUpdate.attr("x", range[0]).attr("width", range[1] - range[0]);
28976          redrawX(gUpdate);
28977        }
28978        if (y) {
28979          range = d3_scaleRange(y);
28980          backgroundUpdate.attr("y", range[0]).attr("height", range[1] - range[0]);
28981          redrawY(gUpdate);
28982        }
28983        redraw(gUpdate);
28984      });
28985    }
28986    brush.event = function(g) {
28987      g.each(function() {
28988        var event_ = event.of(this, arguments), extent1 = {
28989          x: xExtent,
28990          y: yExtent,
28991          i: xExtentDomain,
28992          j: yExtentDomain
28993        }, extent0 = this.__chart__ || extent1;
28994        this.__chart__ = extent1;
28995        if (d3_transitionInheritId) {
28996          d3.select(this).transition().each("start.brush", function() {
28997            xExtentDomain = extent0.i;
28998            yExtentDomain = extent0.j;
28999            xExtent = extent0.x;
29000            yExtent = extent0.y;
29001            event_({
29002              type: "brushstart"
29003            });
29004          }).tween("brush:brush", function() {
29005            var xi = d3_interpolateArray(xExtent, extent1.x), yi = d3_interpolateArray(yExtent, extent1.y);
29006            xExtentDomain = yExtentDomain = null;
29007            return function(t) {
29008              xExtent = extent1.x = xi(t);
29009              yExtent = extent1.y = yi(t);
29010              event_({
29011                type: "brush",
29012                mode: "resize"
29013              });
29014            };
29015          }).each("end.brush", function() {
29016            xExtentDomain = extent1.i;
29017            yExtentDomain = extent1.j;
29018            event_({
29019              type: "brush",
29020              mode: "resize"
29021            });
29022            event_({
29023              type: "brushend"
29024            });
29025          });
29026        } else {
29027          event_({
29028            type: "brushstart"
29029          });
29030          event_({
29031            type: "brush",
29032            mode: "resize"
29033          });
29034          event_({
29035            type: "brushend"
29036          });
29037        }
29038      });
29039    };
29040    function redraw(g) {
29041      g.selectAll(".resize").attr("transform", function(d) {
29042        return "translate(" + xExtent[+/e$/.test(d)] + "," + yExtent[+/^s/.test(d)] + ")";
29043      });
29044    }
29045    function redrawX(g) {
29046      g.select(".extent").attr("x", xExtent[0]);
29047      g.selectAll(".extent,.n>rect,.s>rect").attr("width", xExtent[1] - xExtent[0]);
29048    }
29049    function redrawY(g) {
29050      g.select(".extent").attr("y", yExtent[0]);
29051      g.selectAll(".extent,.e>rect,.w>rect").attr("height", yExtent[1] - yExtent[0]);
29052    }
29053    function brushstart() {
29054      var target = this, eventTarget = d3.select(d3.event.target), event_ = event.of(target, arguments), g = d3.select(target), resizing = eventTarget.datum(), resizingX = !/^(n|s)$/.test(resizing) && x, resizingY = !/^(e|w)$/.test(resizing) && y, dragging = eventTarget.classed("extent"), dragRestore = d3_event_dragSuppress(), center, origin = d3.mouse(target), offset;
29055      var w = d3.select(d3_window).on("keydown.brush", keydown).on("keyup.brush", keyup);
29056      if (d3.event.changedTouches) {
29057        w.on("touchmove.brush", brushmove).on("touchend.brush", brushend);
29058      } else {
29059        w.on("mousemove.brush", brushmove).on("mouseup.brush", brushend);
29060      }
29061      g.interrupt().selectAll("*").interrupt();
29062      if (dragging) {
29063        origin[0] = xExtent[0] - origin[0];
29064        origin[1] = yExtent[0] - origin[1];
29065      } else if (resizing) {
29066        var ex = +/w$/.test(resizing), ey = +/^n/.test(resizing);
29067        offset = [ xExtent[1 - ex] - origin[0], yExtent[1 - ey] - origin[1] ];
29068        origin[0] = xExtent[ex];
29069        origin[1] = yExtent[ey];
29070      } else if (d3.event.altKey) center = origin.slice();
29071      g.style("pointer-events", "none").selectAll(".resize").style("display", null);
29072      d3.select("body").style("cursor", eventTarget.style("cursor"));
29073      event_({
29074        type: "brushstart"
29075      });
29076      brushmove();
29077      function keydown() {
29078        if (d3.event.keyCode == 32) {
29079          if (!dragging) {
29080            center = null;
29081            origin[0] -= xExtent[1];
29082            origin[1] -= yExtent[1];
29083            dragging = 2;
29084          }
29085          d3_eventPreventDefault();
29086        }
29087      }
29088      function keyup() {
29089        if (d3.event.keyCode == 32 && dragging == 2) {
29090          origin[0] += xExtent[1];
29091          origin[1] += yExtent[1];
29092          dragging = 0;
29093          d3_eventPreventDefault();
29094        }
29095      }
29096      function brushmove() {
29097        var point = d3.mouse(target), moved = false;
vendor: 6,929 bytes, lines 29098-29293
29098        if (offset) {
29099          point[0] += offset[0];
29100          point[1] += offset[1];
29101        }
29102        if (!dragging) {
29103          if (d3.event.altKey) {
29104            if (!center) center = [ (xExtent[0] + xExtent[1]) / 2, (yExtent[0] + yExtent[1]) / 2 ];
29105            origin[0] = xExtent[+(point[0] < center[0])];
29106            origin[1] = yExtent[+(point[1] < center[1])];
29107          } else center = null;
29108        }
29109        if (resizingX && move1(point, x, 0)) {
29110          redrawX(g);
29111          moved = true;
29112        }
29113        if (resizingY && move1(point, y, 1)) {
29114          redrawY(g);
29115          moved = true;
29116        }
29117        if (moved) {
29118          redraw(g);
29119          event_({
29120            type: "brush",
29121            mode: dragging ? "move" : "resize"
29122          });
29123        }
29124      }
29125      function move1(point, scale, i) {
29126        var range = d3_scaleRange(scale), r0 = range[0], r1 = range[1], position = origin[i], extent = i ? yExtent : xExtent, size = extent[1] - extent[0], min, max;
29127        if (dragging) {
29128          r0 -= position;
29129          r1 -= size + position;
29130        }
29131        min = (i ? yClamp : xClamp) ? Math.max(r0, Math.min(r1, point[i])) : point[i];
29132        if (dragging) {
29133          max = (min += position) + size;
29134        } else {
29135          if (center) position = Math.max(r0, Math.min(r1, 2 * center[i] - min));
29136          if (position < min) {
29137            max = min;
29138            min = position;
29139          } else {
29140            max = position;
29141          }
29142        }
29143        if (extent[0] != min || extent[1] != max) {
29144          if (i) yExtentDomain = null; else xExtentDomain = null;
29145          extent[0] = min;
29146          extent[1] = max;
29147          return true;
29148        }
29149      }
29150      function brushend() {
29151        brushmove();
29152        g.style("pointer-events", "all").selectAll(".resize").style("display", brush.empty() ? "none" : null);
29153        d3.select("body").style("cursor", null);
29154        w.on("mousemove.brush", null).on("mouseup.brush", null).on("touchmove.brush", null).on("touchend.brush", null).on("keydown.brush", null).on("keyup.brush", null);
29155        dragRestore();
29156        event_({
29157          type: "brushend"
29158        });
29159      }
29160    }
29161    brush.x = function(z) {
29162      if (!arguments.length) return x;
29163      x = z;
29164      resizes = d3_svg_brushResizes[!x << 1 | !y];
29165      return brush;
29166    };
29167    brush.y = function(z) {
29168      if (!arguments.length) return y;
29169      y = z;
29170      resizes = d3_svg_brushResizes[!x << 1 | !y];
29171      return brush;
29172    };
29173    brush.clamp = function(z) {
29174      if (!arguments.length) return x && y ? [ xClamp, yClamp ] : x ? xClamp : y ? yClamp : null;
29175      if (x && y) xClamp = !!z[0], yClamp = !!z[1]; else if (x) xClamp = !!z; else if (y) yClamp = !!z;
29176      return brush;
29177    };
29178    brush.extent = function(z) {
29179      var x0, x1, y0, y1, t;
29180      if (!arguments.length) {
29181        if (x) {
29182          if (xExtentDomain) {
29183            x0 = xExtentDomain[0], x1 = xExtentDomain[1];
29184          } else {
29185            x0 = xExtent[0], x1 = xExtent[1];
29186            if (x.invert) x0 = x.invert(x0), x1 = x.invert(x1);
29187            if (x1 < x0) t = x0, x0 = x1, x1 = t;
29188          }
29189        }
29190        if (y) {
29191          if (yExtentDomain) {
29192            y0 = yExtentDomain[0], y1 = yExtentDomain[1];
29193          } else {
29194            y0 = yExtent[0], y1 = yExtent[1];
29195            if (y.invert) y0 = y.invert(y0), y1 = y.invert(y1);
29196            if (y1 < y0) t = y0, y0 = y1, y1 = t;
29197          }
29198        }
29199        return x && y ? [ [ x0, y0 ], [ x1, y1 ] ] : x ? [ x0, x1 ] : y && [ y0, y1 ];
29200      }
29201      if (x) {
29202        x0 = z[0], x1 = z[1];
29203        if (y) x0 = x0[0], x1 = x1[0];
29204        xExtentDomain = [ x0, x1 ];
29205        if (x.invert) x0 = x(x0), x1 = x(x1);
29206        if (x1 < x0) t = x0, x0 = x1, x1 = t;
29207        if (x0 != xExtent[0] || x1 != xExtent[1]) xExtent = [ x0, x1 ];
29208      }
29209      if (y) {
29210        y0 = z[0], y1 = z[1];
29211        if (x) y0 = y0[1], y1 = y1[1];
29212        yExtentDomain = [ y0, y1 ];
29213        if (y.invert) y0 = y(y0), y1 = y(y1);
29214        if (y1 < y0) t = y0, y0 = y1, y1 = t;
29215        if (y0 != yExtent[0] || y1 != yExtent[1]) yExtent = [ y0, y1 ];
29216      }
29217      return brush;
29218    };
29219    brush.clear = function() {
29220      if (!brush.empty()) {
29221        xExtent = [ 0, 0 ], yExtent = [ 0, 0 ];
29222        xExtentDomain = yExtentDomain = null;
29223      }
29224      return brush;
29225    };
29226    brush.empty = function() {
29227      return !!x && xExtent[0] == xExtent[1] || !!y && yExtent[0] == yExtent[1];
29228    };
29229    return d3.rebind(brush, event, "on");
29230  };
29231  var d3_svg_brushCursor = {
29232    n: "ns-resize",
29233    e: "ew-resize",
29234    s: "ns-resize",
29235    w: "ew-resize",
29236    nw: "nwse-resize",
29237    ne: "nesw-resize",
29238    se: "nwse-resize",
29239    sw: "nesw-resize"
29240  };
29241  var d3_svg_brushResizes = [ [ "n", "e", "s", "w", "nw", "ne", "se", "sw" ], [ "e", "w" ], [ "n", "s" ], [] ];
29242  var d3_time_format = d3_time.format = d3_locale_enUS.timeFormat;
29243  var d3_time_formatUtc = d3_time_format.utc;
29244  var d3_time_formatIso = d3_time_formatUtc("%Y-%m-%dT%H:%M:%S.%LZ");
29245  d3_time_format.iso = Date.prototype.toISOString && +new Date("2000-01-01T00:00:00.000Z") ? d3_time_formatIsoNative : d3_time_formatIso;
29246  function d3_time_formatIsoNative(date) {
29247    return date.toISOString();
29248  }
29249  d3_time_formatIsoNative.parse = function(string) {
29250    var date = new Date(string);
29251    return isNaN(date) ? null : date;
29252  };
29253  d3_time_formatIsoNative.toString = d3_time_formatIso.toString;
29254  d3_time.second = d3_time_interval(function(date) {
29255    return new d3_date(Math.floor(date / 1e3) * 1e3);
29256  }, function(date, offset) {
29257    date.setTime(date.getTime() + Math.floor(offset) * 1e3);
29258  }, function(date) {
29259    return date.getSeconds();
29260  });
29261  d3_time.seconds = d3_time.second.range;
29262  d3_time.seconds.utc = d3_time.second.utc.range;
29263  d3_time.minute = d3_time_interval(function(date) {
29264    return new d3_date(Math.floor(date / 6e4) * 6e4);
29265  }, function(date, offset) {
29266    date.setTime(date.getTime() + Math.floor(offset) * 6e4);
29267  }, function(date) {
29268    return date.getMinutes();
29269  });
29270  d3_time.minutes = d3_time.minute.range;
29271  d3_time.minutes.utc = d3_time.minute.utc.range;
29272  d3_time.hour = d3_time_interval(function(date) {
29273    var timezone = date.getTimezoneOffset() / 60;
29274    return new d3_date((Math.floor(date / 36e5 - timezone) + timezone) * 36e5);
29275  }, function(date, offset) {
29276    date.setTime(date.getTime() + Math.floor(offset) * 36e5);
29277  }, function(date) {
29278    return date.getHours();
29279  });
29280  d3_time.hours = d3_time.hour.range;
29281  d3_time.hours.utc = d3_time.hour.utc.range;
29282  d3_time.month = d3_time_interval(function(date) {
29283    date = d3_time.day(date);
29284    date.setDate(1);
29285    return date;
29286  }, function(date, offset) {
29287    date.setMonth(date.getMonth() + offset);
29288  }, function(date) {
29289    return date.getMonth();
29290  });
29291  d3_time.months = d3_time.month.range;
29292  d3_time.months.utc = d3_time.month.utc.range;
29293  function d3_time_scale(linear, methods, format) {
29294    function scale(x) {
29295      return linear(x);
29296    }
29297    scale.invert = function(x) {
29298      return d3_time_scaleDate(linear.invert(x));
29299    };
29300    scale.domain = function(x) {
29301      if (!arguments.length) return linear.domain().map(d3_time_scaleDate);
29302      linear.domain(x);
29303      return scale;
29304    };
29305    function tickMethod(extent, count) {
29306      var span = extent[1] - extent[0], target = span / count, i = d3.bisect(d3_time_scaleSteps, target);
29307      return i == d3_time_scaleSteps.length ? [ methods.year, d3_scale_linearTickRange(extent.map(function(d) {
29308        return d / 31536e6;
29309      }), count)[2] ] : !i ? [ d3_time_scaleMilliseconds, d3_scale_linearTickRange(extent, count)[2] ] : methods[target / d3_time_scaleSteps[i - 1] < d3_time_scaleSteps[i] / target ? i - 1 : i];
29310    }
29311    scale.nice = function(interval, skip) {
29312      var domain = scale.domain(), extent = d3_scaleExtent(domain), method = interval == null ? tickMethod(extent, 10) : typeof interval === "number" && tickMethod(extent, interval);
29313      if (method) interval = method[0], skip = method[1];
29314      function skipped(date) {
29315        return !isNaN(date) && !interval.range(date, d3_time_scaleDate(+date + 1), skip).length;
29316      }
29317      return scale.domain(d3_scale_nice(domain, skip > 1 ? {
29318        floor: function(date) {
29319          while (skipped(date = interval.floor(date))) date = d3_time_scaleDate(date - 1);
29320          return date;
29321        },
29322        ceil: function(date) {
29323          while (skipped(date = interval.ceil(date))) date = d3_time_scaleDate(+date + 1);
29324          return date;
29325        }
29326      } : interval));
29327    };
29328    scale.ticks = function(interval, skip) {
29329      var extent = d3_scaleExtent(scale.domain()), method = interval == null ? tickMethod(extent, 10) : typeof interval === "number" ? tickMethod(extent, interval) : !interval.range && [ {
29330        range: interval
29331      }, skip ];
29332      if (method) interval = method[0], skip = method[1];
29333      return interval.range(extent[0], d3_time_scaleDate(+extent[1] + 1), skip < 1 ? 1 : skip);
29334    };
29335    scale.tickFormat = function() {
29336      return format;
29337    };
29338    scale.copy = function() {
29339      return d3_time_scale(linear.copy(), methods, format);
29340    };
29341    return d3_scale_linearRebind(scale, linear);
29342  }
29343  function d3_time_scaleDate(t) {
29344    return new Date(t);
29345  }
29346  var d3_time_scaleSteps = [ 1e3, 5e3, 15e3, 3e4, 6e4, 3e5, 9e5, 18e5, 36e5, 108e5, 216e5, 432e5, 864e5, 1728e5, 6048e5, 2592e6, 7776e6, 31536e6 ];
29347  var d3_time_scaleLocalMethods = [ [ d3_time.second, 1 ], [ d3_time.second, 5 ], [ d3_time.second, 15 ], [ d3_time.second, 30 ], [ d3_time.minute, 1 ], [ d3_time.minute, 5 ], [ d3_time.minute, 15 ], [ d3_time.minute, 30 ], [ d3_time.hour, 1 ], [ d3_time.hour, 3 ], [ d3_time.hour, 6 ], [ d3_time.hour, 12 ], [ d3_time.day, 1 ], [ d3_time.day, 2 ], [ d3_time.week, 1 ], [ d3_time.month, 1 ], [ d3_time.month, 3 ], [ d3_time.year, 1 ] ];
29348  var d3_time_scaleLocalFormat = d3_time_format.multi([ [ ".%L", function(d) {
29349    return d.getMilliseconds();
29350  } ], [ ":%S", function(d) {
29351    return d.getSeconds();
29352  } ], [ "%I:%M", function(d) {
29353    return d.getMinutes();
29354  } ], [ "%I %p", function(d) {
29355    return d.getHours();
29356  } ], [ "%a %d", function(d) {
29357    return d.getDay() && d.getDate() != 1;
29358  } ], [ "%b %d", function(d) {
29359    return d.getDate() != 1;
29360  } ], [ "%B", function(d) {
29361    return d.getMonth();
29362  } ], [ "%Y", d3_true ] ]);
29363  var d3_time_scaleMilliseconds = {
29364    range: function(start, stop, step) {
29365      return d3.range(Math.ceil(start / step) * step, +stop, step).map(d3_time_scaleDate);
29366    },
29367    floor: d3_identity,
29368    ceil: d3_identity
29369  };
29370  d3_time_scaleLocalMethods.year = d3_time.year;
29371  d3_time.scale = function() {
29372    return d3_time_scale(d3.scale.linear(), d3_time_scaleLocalMethods, d3_time_scaleLocalFormat);
29373  };
29374  var d3_time_scaleUtcMethods = d3_time_scaleLocalMethods.map(function(m) {
29375    return [ m[0].utc, m[1] ];
29376  });
29377  var d3_time_scaleUtcFormat = d3_time_formatUtc.multi([ [ ".%L", function(d) {
29378    return d.getUTCMilliseconds();
29379  } ], [ ":%S", function(d) {
29380    return d.getUTCSeconds();
29381  } ], [ "%I:%M", function(d) {
29382    return d.getUTCMinutes();
29383  } ], [ "%I %p", function(d) {
29384    return d.getUTCHours();
29385  } ], [ "%a %d", function(d) {
29386    return d.getUTCDay() && d.getUTCDate() != 1;
29387  } ], [ "%b %d", function(d) {
29388    return d.getUTCDate() != 1;
29389  } ], [ "%B", function(d) {
29390    return d.getUTCMonth();
29391  } ], [ "%Y", d3_true ] ]);
29392  d3_time_scaleUtcMethods.year = d3_time.year.utc;
29393  d3_time.scale.utc = function() {
29394    return d3_time_scale(d3.scale.linear(), d3_time_scaleUtcMethods, d3_time_scaleUtcFormat);
29395  };
29396  d3.text = d3_xhrType(function(request) {
29397    return request.responseText;
29398  });
29399  d3.json = function(url, callback) {
29400    return d3_xhr(url, "application/json", d3_json, callback);
29401  };
29402  function d3_json(request) {
29403    return JSON.parse(request.responseText);
29404  }
29405  d3.html = function(url, callback) {
29406    return d3_xhr(url, "text/html", d3_html, callback);
29407  };
29408  function d3_html(request) {
29409    var range = d3_document.createRange();
29410    range.selectNode(d3_document.body);
29411    return range.createContextualFragment(request.responseText);
29412  }
29413  d3.xml = d3_xhrType(function(request) {
29414    return request.responseXML;
29415  });
29416  if (typeof define === "function" && define.amd) define('d3',d3); else if (typeof module === "object" && module.exports) module.exports = d3;
29417  this.d3 = d3;
29418}();
29419(function (window) {
29420    'use strict';
29421
29422    /*global define, module, exports, require */
29423
29424    var c3 = { version: "0.3.0" };
29425
29426    var c3_chart_fn, c3_chart_internal_fn;
29427
29428    function Chart(config) {
29429        var $$ = this.internal = new ChartInternal(this);
29430        $$.loadConfig(config);
29431        $$.init();
29432
29433        // bind "this" to nested API
29434        (function bindThis(fn, target, argThis) {
29435            for (var key in fn) {
29436                target[key] = fn[key].bind(argThis);
29437                if (Object.keys(fn[key]).length > 0) {
29438                    bindThis(fn[key], target[key], argThis);
29439                }
29440            }
29441        })(c3_chart_fn, this, this);
29442    }
29443
29444    function ChartInternal(api) {
29445        var $$ = this;
29446        $$.d3 = window.d3 ? window.d3 : typeof require !== 'undefined' ? require("d3") : undefined;
29447        $$.api = api;
29448        $$.config = $$.getDefaultConfig();
29449        $$.data = {};
29450        $$.cache = {};
29451        $$.axes = {};
29452    }
29453
29454    c3.generate = function (config) {
29455        return new Chart(config);
29456    };
29457
29458    c3.chart = {
29459        fn: Chart.prototype,
29460        internal: {
29461            fn: ChartInternal.prototype
29462        }
29463    };
29464    c3_chart_fn = c3.chart.fn;
29465    c3_chart_internal_fn = c3.chart.internal.fn;
29466
29467
29468    c3_chart_internal_fn.init = function () {
29469        var $$ = this, config = $$.config;
29470
29471        $$.initParams();
29472
29473        if (config.data_url) {
29474            $$.convertUrlToData(config.data_url, config.data_mimeType, config.data_keys, $$.initWithData);
29475        }
29476        else if (config.data_json) {
29477            $$.initWithData($$.convertJsonToData(config.data_json, config.data_keys));
29478        }
29479        else if (config.data_rows) {
29480            $$.initWithData($$.convertRowsToData(config.data_rows));
29481        }
29482        else if (config.data_columns) {
29483            $$.initWithData($$.convertColumnsToData(config.data_columns));
29484        }
29485        else {
29486            throw Error('url or json or rows or columns is required.');
29487        }
29488    };
29489
29490    c3_chart_internal_fn.initParams = function () {
29491        var $$ = this, d3 = $$.d3, config = $$.config;
29492
29493        // MEMO: clipId needs to be unique because it conflicts when multiple charts exist
29494        $$.clipId = "c3-" + (+new Date()) + '-clip',
29495        $$.clipIdForXAxis = $$.clipId + '-xaxis',
29496        $$.clipIdForYAxis = $$.clipId + '-yaxis',
29497        $$.clipPath = $$.getClipPath($$.clipId),
29498        $$.clipPathForXAxis = $$.getClipPath($$.clipIdForXAxis),
29499        $$.clipPathForYAxis = $$.getClipPath($$.clipIdForYAxis);
29500
29501        $$.dragStart = null;
29502        $$.dragging = false;
29503        $$.cancelClick = false;
29504        $$.mouseover = false;
29505        $$.transiting = false;
29506
29507        $$.color = $$.generateColor();
29508        $$.levelColor = $$.generateLevelColor();
29509
29510        $$.dataTimeFormat = config.data_xLocaltime ? d3.time.format : d3.time.format.utc;
29511        $$.axisTimeFormat = config.axis_x_localtime ? d3.time.format : d3.time.format.utc;
29512        $$.defaultAxisTimeFormat = $$.axisTimeFormat.multi([
29513            [".%L", function (d) { return d.getMilliseconds(); }],
29514            [":%S", function (d) { return d.getSeconds(); }],
29515            ["%I:%M", function (d) { return d.getMinutes(); }],
29516            ["%I %p", function (d) { return d.getHours(); }],
29517            ["%-m/%-d", function (d) { return d.getDay() && d.getDate() !== 1; }],
29518            ["%-m/%-d", function (d) { return d.getDate() !== 1; }],
29519            ["%-m/%-d", function (d) { return d.getMonth(); }],
29520            ["%Y/%-m/%-d", function () { return true; }]
29521        ]);
29522
29523        $$.hiddenTargetIds = [];
29524        $$.hiddenLegendIds = [];
29525
29526        $$.xOrient = config.axis_rotated ? "left" : "bottom";
29527        $$.yOrient = config.axis_rotated ? "bottom" : "left";
29528        $$.y2Orient = config.axis_rotated ? "top" : "right";
29529        $$.subXOrient = config.axis_rotated ? "left" : "bottom";
29530
29531        $$.isLegendRight = config.legend_position === 'right';
29532        $$.isLegendInset = config.legend_position === 'inset';
29533        $$.isLegendTop = config.legend_inset_anchor === 'top-left' || config.legend_inset_anchor === 'top-right';
29534        $$.isLegendLeft = config.legend_inset_anchor === 'top-left' || config.legend_inset_anchor === 'bottom-left';
29535        $$.legendStep = 0;
29536        $$.legendItemWidth = 0;
29537        $$.legendItemHeight = 0;
29538        $$.legendOpacityForHidden = 0.15;
29539
29540        $$.currentMaxTickWidth = 0;
29541
29542        $$.rotated_padding_left = 30;
29543        $$.rotated_padding_right = config.axis_rotated && !config.axis_x_show ? 0 : 30;
29544        $$.rotated_padding_top = 5;
29545
29546        $$.withoutFadeIn = {};
29547
29548        $$.axes.subx = d3.selectAll([]); // needs when excluding subchart.js
29549    };
29550
29551    c3_chart_internal_fn.initWithData = function (data) {
29552        var $$ = this, d3 = $$.d3, config = $$.config;
29553        var main, binding = true;
29554
29555        if ($$.initPie) { $$.initPie(); }
29556        if ($$.initBrush) { $$.initBrush(); }
29557        if ($$.initZoom) { $$.initZoom(); }
29558
29559        $$.selectChart = d3.select(config.bindto);
29560        if ($$.selectChart.empty()) {
29561            $$.selectChart = d3.select(document.createElement('div')).style('opacity', 0);
29562            $$.observeInserted($$.selectChart);
29563            binding = false;
29564        }
29565        $$.selectChart.html("").classed("c3", true);
29566
29567        // Init data as targets
29568        $$.data.xs = {};
29569        $$.data.targets = $$.convertDataToTargets(data);
29570
29571        if (config.data_filter) {
29572            $$.data.targets = $$.data.targets.filter(config.data_filter);
29573        }
29574
29575        // Set targets to hide if needed
29576        if (config.data_hide) {
29577            $$.addHiddenTargetIds(config.data_hide === true ? $$.mapToIds($$.data.targets) : config.data_hide);
29578        }
29579
29580        // when gauge, hide legend // TODO: fix
29581        if ($$.hasType('gauge')) {
29582            config.legend_show = false;
29583        }
29584
29585        // Init sizes and scales
29586        $$.updateSizes();
29587        $$.updateScales();
29588
29589        // Set domains for each scale
29590        $$.x.domain(d3.extent($$.getXDomain($$.data.targets)));
29591        $$.y.domain($$.getYDomain($$.data.targets, 'y'));
29592        $$.y2.domain($$.getYDomain($$.data.targets, 'y2'));
29593        $$.subX.domain($$.x.domain());
29594        $$.subY.domain($$.y.domain());
29595        $$.subY2.domain($$.y2.domain());
29596
29597        // Save original x domain for zoom update
29598        $$.orgXDomain = $$.x.domain();
29599
29600        // Set initialized scales to brush and zoom
29601        if ($$.brush) { $$.brush.scale($$.subX); }
29602        if (config.zoom_enabled) { $$.zoom.scale($$.x); }
29603
29604        /*-- Basic Elements --*/
29605
29606        // Define svgs
29607        $$.svg = $$.selectChart.append("svg")
29608            .style("overflow", "hidden")
29609            .on('mouseenter', function () { return config.onmouseover.call($$); })
29610            .on('mouseleave', function () { return config.onmouseout.call($$); });
29611
29612        // Define defs
29613        $$.defs = $$.svg.append("defs");
29614        $$.defs.append("clipPath").attr("id", $$.clipId).append("rect");
29615        $$.defs.append("clipPath").attr("id", $$.clipIdForXAxis).append("rect");
29616        $$.defs.append("clipPath").attr("id", $$.clipIdForYAxis).append("rect");
29617        $$.updateSvgSize();
29618
29619        // Define regions
29620        main = $$.main = $$.svg.append("g").attr("transform", $$.getTranslate('main'));
29621
29622        if ($$.initSubchart) { $$.initSubchart(); }
29623        if ($$.initTooltip) { $$.initTooltip(); }
29624        if ($$.initLegend) { $$.initLegend(); }
29625
29626        /*-- Main Region --*/
29627
29628        // text when empty
29629        main.append("text")
29630            .attr("class", CLASS.text + ' ' + CLASS.empty)
29631            .attr("text-anchor", "middle") // horizontal centering of text at x position in all browsers.
29632            .attr("dominant-baseline", "middle"); // vertical centering of text at y position in all browsers, except IE.
29633
29634        // Regions
29635        $$.initRegion();
29636
29637        // Grids
29638        $$.initGrid();
29639
29640        // Define g for chart area
29641        main.append('g')
29642            .attr("clip-path", $$.clipPath)
29643            .attr('class', CLASS.chart);
29644
29645        // Cover whole with rects for events
29646        $$.initEventRect();
29647
29648        // Define g for bar chart area
29649        if ($$.initBar) { $$.initBar(); }
29650
29651        // Define g for line chart area
29652        if ($$.initLine) { $$.initLine(); }
29653
29654        // Define g for arc chart area
29655        if ($$.initArc) { $$.initArc(); }
29656        if ($$.initGauge) { $$.initGauge(); }
29657
29658        // Define g for text area
29659        if ($$.initText) { $$.initText(); }
29660
29661        // if zoom privileged, insert rect to forefront
29662        // TODO: is this needed?
29663        main.insert('rect', config.zoom_privileged ? null : 'g.' + CLASS.regions)
29664            .attr('class', CLASS.zoomRect)
29665            .attr('width', $$.width)
29666            .attr('height', $$.height)
29667            .style('opacity', 0)
29668            .on("dblclick.zoom", null);
29669
29670        // Set default extent if defined
29671        if (config.axis_x_default) {
29672            $$.brush.extent(isFunction(config.axis_x_default) ? config.axis_x_default($$.getXDomain()) : config.axis_x_default);
29673        }
29674
29675        // Add Axis
29676        $$.initAxis();
29677
29678        // Set targets
29679        $$.updateTargets($$.data.targets);
29680
29681        // Draw with targets
29682        if (binding) {
29683            $$.updateDimension();
29684            $$.redraw({
29685                withTransform: true,
29686                withUpdateXDomain: true,
29687                withUpdateOrgXDomain: true,
29688                withTransitionForAxis: false
29689            });
29690        }
29691
29692        // Bind resize event
29693        if (window.onresize == null) {
29694            window.onresize = $$.generateResize();
29695        }
29696        if (window.onresize.add) {
29697            window.onresize.add(function () {
29698                config.onresize.call($$);
29699            });
29700            window.onresize.add(function () {
29701                $$.api.flush();
29702            });
29703            window.onresize.add(function () {
29704                config.onresized.call($$);
29705            });
29706        }
29707
29708        // export element of the chart
29709        $$.api.element = $$.selectChart.node();
29710    };
29711
29712    c3_chart_internal_fn.smoothLines = function (el, type) {
29713        var $$ = this;
29714        if (type === 'grid') {
29715            el.each(function () {
29716                var g = $$.d3.select(this),
29717                    x1 = g.attr('x1'),
29718                    x2 = g.attr('x2'),
29719                    y1 = g.attr('y1'),
29720                    y2 = g.attr('y2');
29721                g.attr({
vendor: 9,211 bytes, lines 29722-29937
29722                    'x1': Math.ceil(x1),
29723                    'x2': Math.ceil(x2),
29724                    'y1': Math.ceil(y1),
29725                    'y2': Math.ceil(y2)
29726                });
29727            });
29728        }
29729    };
29730
29731
29732    c3_chart_internal_fn.updateSizes = function () {
29733        var $$ = this, config = $$.config;
29734        var legendHeight = $$.legend ? $$.getLegendHeight() : 0,
29735            legendWidth = $$.legend ? $$.getLegendWidth() : 0,
29736            legendHeightForBottom = $$.isLegendRight || $$.isLegendInset ? 0 : legendHeight,
29737            hasArc = $$.hasArcType(),
29738            xAxisHeight = config.axis_rotated || hasArc ? 0 : $$.getHorizontalAxisHeight('x'),
29739            subchartHeight = config.subchart_show && !hasArc ? (config.subchart_size_height + xAxisHeight) : 0;
29740
29741        $$.currentWidth = $$.getCurrentWidth();
29742        $$.currentHeight = $$.getCurrentHeight();
29743
29744        // for main
29745        $$.margin = config.axis_rotated ? {
29746            top: $$.getHorizontalAxisHeight('y2') + $$.getCurrentPaddingTop(),
29747            right: hasArc ? 0 : $$.getCurrentPaddingRight(),
29748            bottom: $$.getHorizontalAxisHeight('y') + legendHeightForBottom + $$.getCurrentPaddingBottom(),
29749            left: subchartHeight + (hasArc ? 0 : $$.getCurrentPaddingLeft())
29750        } : {
29751            top: 4 + $$.getCurrentPaddingTop(), // for top tick text
29752            right: hasArc ? 0 : $$.getCurrentPaddingRight(),
29753            bottom: xAxisHeight + subchartHeight + legendHeightForBottom + $$.getCurrentPaddingBottom(),
29754            left: hasArc ? 0 : $$.getCurrentPaddingLeft()
29755        };
29756
29757        // for subchart
29758        $$.margin2 = config.axis_rotated ? {
29759            top: $$.margin.top,
29760            right: NaN,
29761            bottom: 20 + legendHeightForBottom,
29762            left: $$.rotated_padding_left
29763        } : {
29764            top: $$.currentHeight - subchartHeight - legendHeightForBottom,
29765            right: NaN,
29766            bottom: xAxisHeight + legendHeightForBottom,
29767            left: $$.margin.left
29768        };
29769
29770        // for legend
29771        $$.margin3 = {
29772            top: 0,
29773            right: NaN,
29774            bottom: 0,
29775            left: 0
29776        };
29777        if ($$.updateSizeForLegend) { $$.updateSizeForLegend(legendHeight, legendWidth); }
29778
29779        $$.width = $$.currentWidth - $$.margin.left - $$.margin.right;
29780        $$.height = $$.currentHeight - $$.margin.top - $$.margin.bottom;
29781        if ($$.width < 0) { $$.width = 0; }
29782        if ($$.height < 0) { $$.height = 0; }
29783
29784        $$.width2 = config.axis_rotated ? $$.margin.left - $$.rotated_padding_left - $$.rotated_padding_right : $$.width;
29785        $$.height2 = config.axis_rotated ? $$.height : $$.currentHeight - $$.margin2.top - $$.margin2.bottom;
29786        if ($$.width2 < 0) { $$.width2 = 0; }
29787        if ($$.height2 < 0) { $$.height2 = 0; }
29788
29789        // for arc
29790        $$.arcWidth = $$.width - ($$.isLegendRight ? legendWidth + 10 : 0);
29791        $$.arcHeight = $$.height - ($$.isLegendRight ? 0 : 10);
29792        if ($$.updateRadius) { $$.updateRadius(); }
29793
29794        if ($$.isLegendRight && hasArc) {
29795            $$.margin3.left = $$.arcWidth / 2 + $$.radiusExpanded * 1.1;
29796        }
29797    };
29798
29799    c3_chart_internal_fn.updateTargets = function (targets) {
29800        var $$ = this, config = $$.config;
29801
29802        /*-- Main --*/
29803
29804        //-- Text --//
29805        $$.updateTargetsForText(targets);
29806
29807        //-- Bar --//
29808        $$.updateTargetsForBar(targets);
29809
29810        //-- Line --//
29811        $$.updateTargetsForLine(targets);
29812
29813        //-- Arc --//
29814        if ($$.updateTargetsForArc) { $$.updateTargetsForArc(targets); }
29815        if ($$.updateTargetsForSubchart) { $$.updateTargetsForSubchart(targets); }
29816
29817        /*-- Show --*/
29818
29819        // Fade-in each chart
29820        $$.svg.selectAll('.' + CLASS.target).filter(function (d) { return $$.isTargetToShow(d.id); })
29821          .transition().duration(config.transition_duration)
29822            .style("opacity", 1);
29823    };
29824
29825    c3_chart_internal_fn.redraw = function (options, transitions) {
29826        var $$ = this, main = $$.main, d3 = $$.d3, config = $$.config;
29827        var areaIndices = $$.getShapeIndices($$.isAreaType), barIndices = $$.getShapeIndices($$.isBarType), lineIndices = $$.getShapeIndices($$.isLineType);
29828        var withY, withSubchart, withTransition, withTransitionForExit, withTransitionForAxis, withTransform, withUpdateXDomain, withUpdateOrgXDomain, withLegend;
29829        var hideAxis = $$.hasArcType();
29830        var drawArea, drawBar, drawLine, xForText, yForText;
29831        var duration, durationForExit, durationForAxis;
29832        var waitForDraw, flow;
29833        var targetsToShow = $$.filterTargetsToShow($$.data.targets), tickValues, i, intervalForCulling;
29834        var xv = $$.xv.bind($$),
29835            cx = ($$.config.axis_rotated ? $$.circleY : $$.circleX).bind($$),
29836            cy = ($$.config.axis_rotated ? $$.circleX : $$.circleY).bind($$);
29837
29838        options = options || {};
29839        withY = getOption(options, "withY", true);
29840        withSubchart = getOption(options, "withSubchart", true);
29841        withTransition = getOption(options, "withTransition", true);
29842        withTransform = getOption(options, "withTransform", false);
29843        withUpdateXDomain = getOption(options, "withUpdateXDomain", false);
29844        withUpdateOrgXDomain = getOption(options, "withUpdateOrgXDomain", false);
29845        withLegend = getOption(options, "withLegend", false);
29846        withTransitionForExit = getOption(options, "withTransitionForExit", withTransition);
29847        withTransitionForAxis = getOption(options, "withTransitionForAxis", withTransition);
29848
29849        duration = withTransition ? config.transition_duration : 0;
29850        durationForExit = withTransitionForExit ? duration : 0;
29851        durationForAxis = withTransitionForAxis ? duration : 0;
29852
29853        transitions = transitions || $$.generateAxisTransitions(durationForAxis);
29854
29855        // update legend and transform each g
29856        if (withLegend && config.legend_show) {
29857            $$.updateLegend($$.mapToIds($$.data.targets), options, transitions);
29858        }
29859
29860        // MEMO: needed for grids calculation
29861        if ($$.isCategorized() && targetsToShow.length === 0) {
29862            $$.x.domain([0, $$.axes.x.selectAll('.tick').size()]);
29863        }
29864
29865        if (targetsToShow.length) {
29866            $$.updateXDomain(targetsToShow, withUpdateXDomain, withUpdateOrgXDomain);
29867            // update axis tick values according to options
29868            if (!config.axis_x_tick_values && (config.axis_x_tick_fit || config.axis_x_tick_count)) {
29869                tickValues = $$.generateTickValues($$.mapTargetsToUniqueXs(targetsToShow), config.axis_x_tick_count);
29870                $$.xAxis.tickValues(tickValues);
29871                $$.subXAxis.tickValues(tickValues);
29872            }
29873        } else {
29874            $$.xAxis.tickValues([]);
29875            $$.subXAxis.tickValues([]);
29876        }
29877
29878        $$.y.domain($$.getYDomain(targetsToShow, 'y'));
29879        $$.y2.domain($$.getYDomain(targetsToShow, 'y2'));
29880
29881        // axes
29882        $$.redrawAxis(transitions, hideAxis);
29883
29884        // Update axis label
29885        $$.updateAxisLabels(withTransition);
29886
29887        // show/hide if manual culling needed
29888        if (withUpdateXDomain && targetsToShow.length) {
29889            if (config.axis_x_tick_culling && tickValues) {
29890                for (i = 1; i < tickValues.length; i++) {
29891                    if (tickValues.length / i < config.axis_x_tick_culling_max) {
29892                        intervalForCulling = i;
29893                        break;
29894                    }
29895                }
29896                $$.svg.selectAll('.' + CLASS.axisX + ' .tick text').each(function (e) {
29897                    var index = tickValues.indexOf(e);
29898                    if (index >= 0) {
29899                        d3.select(this).style('display', index % intervalForCulling ? 'none' : 'block');
29900                    }
29901                });
29902            } else {
29903                $$.svg.selectAll('.' + CLASS.axisX + ' .tick text').style('display', 'block');
29904            }
29905        }
29906
29907        // rotate tick text if needed
29908        if (!config.axis_rotated && config.axis_x_tick_rotate) {
29909            $$.rotateTickText($$.axes.x, transitions.axisX, config.axis_x_tick_rotate);
29910        }
29911
29912        // setup drawer - MEMO: these must be called after axis updated
29913        drawArea = $$.generateDrawArea ? $$.generateDrawArea(areaIndices, false) : undefined;
29914        drawBar = $$.generateDrawBar ? $$.generateDrawBar(barIndices) : undefined;
29915        drawLine = $$.generateDrawLine ? $$.generateDrawLine(lineIndices, false) : undefined;
29916        xForText = $$.generateXYForText(barIndices, true);
29917        yForText = $$.generateXYForText(barIndices, false);
29918
29919        // Update sub domain
29920        $$.subY.domain($$.y.domain());
29921        $$.subY2.domain($$.y2.domain());
29922
29923        // tooltip
29924        $$.tooltip.style("display", "none");
29925
29926        // xgrid focus
29927        $$.updateXgridFocus();
29928
29929        // Data empty label positioning and text.
29930        main.select("text." + CLASS.text + '.' + CLASS.empty)
29931            .attr("x", $$.width / 2)
29932            .attr("y", $$.height / 2)
29933            .text(config.data_empty_label_text)
29934          .transition()
29935            .style('opacity', targetsToShow.length ? 0 : 1);
29936
29937        // grid
29938        $$.redrawGrid(duration, withY);
29939
29940        // rect for regions
29941        $$.redrawRegion(duration);
29942
29943        // bars
29944        $$.redrawBar(durationForExit);
29945
29946        // lines, areas and cricles
29947        $$.redrawLine(durationForExit);
29948        $$.redrawArea(durationForExit);
29949        if (config.point_show) { $$.redrawCircle(); }
29950
29951        // text
29952        if ($$.hasDataLabel()) {
29953            $$.redrawText(durationForExit);
29954        }
29955
29956        // arc
29957        if ($$.redrawArc) { $$.redrawArc(duration, durationForExit, withTransform); }
29958
29959        // subchart
29960        if ($$.redrawSubchart) {
29961            $$.redrawSubchart(withSubchart, transitions, duration, durationForExit, areaIndices, barIndices, lineIndices);
29962        }
29963
29964        // circles for select
29965        main.selectAll('.' + CLASS.selectedCircles)
29966            .filter($$.isBarType.bind($$))
29967            .selectAll('circle')
29968            .remove();
29969
29970        // event rect
29971        if (config.interaction_enabled) {
29972            $$.redrawEventRect();
29973        }
29974
29975        // transition should be derived from one transition
29976        d3.transition().duration(duration).each(function () {
29977            var transitions = [];
29978
29979            $$.addTransitionForBar(transitions, drawBar);
29980            $$.addTransitionForLine(transitions, drawLine);
29981            $$.addTransitionForArea(transitions, drawArea);
29982            if (config.point_show) { $$.addTransitionForCircle(transitions, cx, cy); }
29983            $$.addTransitionForText(transitions, xForText, yForText, options.flow);
29984            $$.addTransitionForRegion(transitions);
29985            $$.addTransitionForGrid(transitions);
29986
29987            // Wait for end of transitions if called from flow API
29988            if (options.flow) {
29989                waitForDraw = $$.generateWait();
29990                transitions.forEach(function (t) {
29991                    waitForDraw.add(t);
29992                });
29993                flow = $$.generateFlow({
29994                    targets: targetsToShow,
29995                    flow: options.flow,
29996                    duration: duration,
29997                    drawBar: drawBar,
29998                    drawLine: drawLine,
29999                    drawArea: drawArea,
30000                    cx: cx,
30001                    cy: cy,
30002                    xv: xv,
30003                    xForText: xForText,
30004                    yForText: yForText
30005                });
30006            }
30007        })
30008        .call(waitForDraw || function () {}, flow || function () {});
30009
30010        // update fadein condition
30011        $$.mapToIds($$.data.targets).forEach(function (id) {
30012            $$.withoutFadeIn[id] = true;
30013        });
30014
30015        if ($$.updateZoom) { $$.updateZoom(); }
30016    };
30017
30018    c3_chart_internal_fn.updateAndRedraw = function (options) {
30019        var $$ = this, config = $$.config, transitions;
30020        options = options || {};
30021        // same with redraw
30022        options.withTransition = getOption(options, "withTransition", true);
30023        options.withTransform = getOption(options, "withTransform", false);
30024        options.withLegend = getOption(options, "withLegend", false);
30025        // NOT same with redraw
30026        options.withUpdateXDomain = true;
30027        options.withUpdateOrgXDomain = true;
30028        options.withTransitionForExit = false;
30029        options.withTransitionForTransform = getOption(options, "withTransitionForTransform", options.withTransition);
30030        // MEMO: this needs to be called before updateLegend and it means this ALWAYS needs to be called)
30031        $$.updateSizes();
30032        // MEMO: called in updateLegend in redraw if withLegend
30033        if (!(options.withLegend && config.legend_show)) {
30034            transitions = $$.generateAxisTransitions(options.withTransitionForAxis ? config.transition_duration : 0);
30035            // Update scales
30036            $$.updateScales();
30037            $$.updateSvgSize();
30038            // Update g positions
30039            $$.transformAll(options.withTransitionForTransform, transitions);
30040        }
30041        // Draw with new sizes & scales
30042        $$.redraw(options, transitions);
30043    };
30044
30045    c3_chart_internal_fn.isTimeSeries = function () {
30046        return this.config.axis_x_type === 'timeseries';
30047    };
30048    c3_chart_internal_fn.isCategorized = function () {
30049        return this.config.axis_x_type.indexOf('categor') >= 0;
30050    };
30051    c3_chart_internal_fn.isCustomX = function () {
vendor: 25,170 bytes, lines 30052-30667
30052        var $$ = this, config = $$.config;
30053        return !$$.isTimeSeries() && (config.data_x || notEmpty(config.data_xs));
30054    };
30055
30056    c3_chart_internal_fn.getTranslate = function (target) {
30057        var $$ = this, config = $$.config, x, y;
30058        if (target === 'main') {
30059            x = asHalfPixel($$.margin.left);
30060            y = asHalfPixel($$.margin.top);
30061        } else if (target === 'context') {
30062            x = asHalfPixel($$.margin2.left);
30063            y = asHalfPixel($$.margin2.top);
30064        } else if (target === 'legend') {
30065            x = $$.margin3.left;
30066            y = $$.margin3.top;
30067        } else if (target === 'x') {
30068            x = 0;
30069            y = config.axis_rotated ? 0 : $$.height;
30070        } else if (target === 'y') {
30071            x = 0;
30072            y = config.axis_rotated ? $$.height : 0;
30073        } else if (target === 'y2') {
30074            x = config.axis_rotated ? 0 : $$.width;
30075            y = config.axis_rotated ? 1 : 0;
30076        } else if (target === 'subx') {
30077            x = 0;
30078            y = config.axis_rotated ? 0 : $$.height2;
30079        } else if (target === 'arc') {
30080            x = $$.arcWidth / 2;
30081            y = $$.arcHeight / 2;
30082        }
30083        return "translate(" + x + "," + y + ")";
30084    };
30085    c3_chart_internal_fn.initialOpacity = function (d) {
30086        return d.value !== null && this.withoutFadeIn[d.id] ? 1 : 0;
30087    };
30088    c3_chart_internal_fn.opacityForCircle = function (d) {
30089        var $$ = this;
30090        return isValue(d.value) ? $$.isScatterType(d) ? 0.5 : 1 : 0;
30091    };
30092    c3_chart_internal_fn.opacityForText = function () {
30093        return this.hasDataLabel() ? 1 : 0;
30094    };
30095    c3_chart_internal_fn.xx = function (d) {
30096        return d ? this.x(d.x) : null;
30097    };
30098    c3_chart_internal_fn.xv = function (d) {
30099        var $$ = this;
30100        return Math.ceil($$.x($$.isTimeSeries() ? $$.parseDate(d.value) : d.value));
30101    };
30102    c3_chart_internal_fn.yv = function (d) {
30103        var $$ = this,
30104            yScale = d.axis && d.axis === 'y2' ? $$.y2 : $$.y;
30105        return Math.ceil(yScale(d.value));
30106    };
30107    c3_chart_internal_fn.subxx = function (d) {
30108        return d ? this.subX(d.x) : null;
30109    };
30110
30111    c3_chart_internal_fn.transformMain = function (withTransition, transitions) {
30112        var $$ = this,
30113            xAxis, yAxis, y2Axis;
30114        if (transitions && transitions.axisX) {
30115            xAxis = transitions.axisX;
30116        } else {
30117            xAxis  = $$.main.select('.' + CLASS.axisX);
30118            if (withTransition) { xAxis = xAxis.transition(); }
30119        }
30120        if (transitions && transitions.axisY) {
30121            yAxis = transitions.axisY;
30122        } else {
30123            yAxis = $$.main.select('.' + CLASS.axisY);
30124            if (withTransition) { yAxis = yAxis.transition(); }
30125        }
30126        if (transitions && transitions.axisY2) {
30127            y2Axis = transitions.axisY2;
30128        } else {
30129            y2Axis = $$.main.select('.' + CLASS.axisY2);
30130            if (withTransition) { y2Axis = y2Axis.transition(); }
30131        }
30132        (withTransition ? $$.main.transition() : $$.main).attr("transform", $$.getTranslate('main'));
30133        xAxis.attr("transform", $$.getTranslate('x'));
30134        yAxis.attr("transform", $$.getTranslate('y'));
30135        y2Axis.attr("transform", $$.getTranslate('y2'));
30136        $$.main.select('.' + CLASS.chartArcs).attr("transform", $$.getTranslate('arc'));
30137    };
30138    c3_chart_internal_fn.transformAll = function (withTransition, transitions) {
30139        var $$ = this;
30140        $$.transformMain(withTransition, transitions);
30141        if ($$.config.subchart_show) { $$.transformContext(withTransition, transitions); }
30142        if ($$.legend) { $$.transformLegend(withTransition); }
30143    };
30144
30145    c3_chart_internal_fn.updateSvgSize = function () {
30146        var $$ = this;
30147        $$.svg.attr('width', $$.currentWidth).attr('height', $$.currentHeight);
30148        $$.svg.select('#' + $$.clipId).select('rect')
30149            .attr('width', $$.width)
30150            .attr('height', $$.height);
30151        $$.svg.select('#' + $$.clipIdForXAxis).select('rect')
30152            .attr('x', $$.getXAxisClipX.bind($$))
30153            .attr('y', $$.getXAxisClipY.bind($$))
30154            .attr('width', $$.getXAxisClipWidth.bind($$))
30155            .attr('height', $$.getXAxisClipHeight.bind($$));
30156        $$.svg.select('#' + $$.clipIdForYAxis).select('rect')
30157            .attr('x', $$.getYAxisClipX.bind($$))
30158            .attr('y', $$.getYAxisClipY.bind($$))
30159            .attr('width', $$.getYAxisClipWidth.bind($$))
30160            .attr('height', $$.getYAxisClipHeight.bind($$));
30161        $$.svg.select('.' + CLASS.zoomRect)
30162            .attr('width', $$.width)
30163            .attr('height', $$.height);
30164        // MEMO: parent div's height will be bigger than svg when <!DOCTYPE html>
30165        $$.selectChart.style('max-height', $$.currentHeight + "px");
30166    };
30167
30168
30169    c3_chart_internal_fn.updateDimension = function () {
30170        var $$ = this;
30171        if ($$.config.axis_rotated) {
30172            $$.axes.x.call($$.xAxis);
30173            $$.axes.subx.call($$.subXAxis);
30174        } else {
30175            $$.axes.y.call($$.yAxis);
30176            $$.axes.y2.call($$.y2Axis);
30177        }
30178        $$.updateSizes();
30179        $$.updateScales();
30180        $$.updateSvgSize();
30181        $$.transformAll(false);
30182    };
30183
30184    c3_chart_internal_fn.observeInserted = function (selection) {
30185        var $$ = this, observer = new MutationObserver(function (mutations) {
30186            mutations.forEach(function (mutation) {
30187                if (mutation.type === 'childList' && mutation.previousSibling) {
30188                    observer.disconnect();
30189                    // need to wait for completion of load because size calculation requires the actual sizes determined after that completion
30190                    var interval = window.setInterval(function () {
30191                        // parentNode will NOT be null when completed
30192                        if (selection.node().parentNode) {
30193                            window.clearInterval(interval);
30194                            $$.updateDimension();
30195                            $$.redraw({
30196                                withTransform: true,
30197                                withUpdateXDomain: true,
30198                                withUpdateOrgXDomain: true,
30199                                withTransition: false,
30200                                withTransitionForTransform: false,
30201                                withLegend: true
30202                            });
30203                            selection.transition().style('opacity', 1);
30204                        }
30205                    }, 10);
30206                }
30207            });
30208        });
30209        observer.observe(selection.node(), {attributes: true, childList: true, characterData: true});
30210    };
30211
30212
30213    c3_chart_internal_fn.generateResize = function () {
30214        var resizeFunctions = [];
30215        function callResizeFunctions() {
30216            resizeFunctions.forEach(function (f) {
30217                f();
30218            });
30219        }
30220        callResizeFunctions.add = function (f) {
30221            resizeFunctions.push(f);
30222        };
30223        return callResizeFunctions;
30224    };
30225
30226    c3_chart_internal_fn.endall = function (transition, callback) {
30227        var n = 0;
30228        transition
30229            .each(function () { ++n; })
30230            .each("end", function () {
30231                if (!--n) { callback.apply(this, arguments); }
30232            });
30233    };
30234    c3_chart_internal_fn.generateWait = function () {
30235        var transitionsToWait = [],
30236            f = function (transition, callback) {
30237                var timer = setInterval(function () {
30238                    var done = 0;
30239                    transitionsToWait.forEach(function (t) {
30240                        if (t.empty()) {
30241                            done += 1;
30242                            return;
30243                        }
30244                        try {
30245                            t.transition();
30246                        } catch (e) {
30247                            done += 1;
30248                        }
30249                    });
30250                    if (done === transitionsToWait.length) {
30251                        clearInterval(timer);
30252                        if (callback) { callback(); }
30253                    }
30254                }, 10);
30255            };
30256        f.add = function (transition) {
30257            transitionsToWait.push(transition);
30258        };
30259        return f;
30260    };
30261
30262    c3_chart_internal_fn.parseDate = function (date) {
30263        var $$ = this, parsedDate;
30264        if (date instanceof Date) {
30265            parsedDate = date;
30266        } else if (typeof date === 'number') {
30267            parsedDate = new Date(date);
30268        } else {
30269            parsedDate = $$.dataTimeFormat($$.config.data_xFormat).parse(date);
30270        }
30271        if (!parsedDate || isNaN(+parsedDate)) {
30272            window.console.error("Failed to parse x '" + date + "' to Date object");
30273        }
30274        return parsedDate;
30275    };
30276
30277    c3_chart_internal_fn.getDefaultConfig = function () {
30278        var config = {
30279            bindto: '#chart',
30280            size_width: undefined,
30281            size_height: undefined,
30282            padding_left: undefined,
30283            padding_right: undefined,
30284            padding_top: undefined,
30285            padding_bottom: undefined,
30286            zoom_enabled: false,
30287            zoom_extent: undefined,
30288            zoom_privileged: false,
30289            zoom_onzoom: function () {},
30290            interaction_enabled: true,
30291            onmouseover: function () {},
30292            onmouseout: function () {},
30293            onresize: function () {},
30294            onresized: function () {},
30295            transition_duration: 350,
30296            data_x: undefined,
30297            data_xs: {},
30298            data_xFormat: '%Y-%m-%d',
30299            data_xLocaltime: true,
30300            data_idConverter: function (id) { return id; },
30301            data_names: {},
30302            data_classes: {},
30303            data_groups: [],
30304            data_axes: {},
30305            data_type: undefined,
30306            data_types: {},
30307            data_labels: {},
30308            data_order: 'desc',
30309            data_regions: {},
30310            data_color: undefined,
30311            data_colors: {},
30312            data_hide: false,
30313            data_filter: undefined,
30314            data_selection_enabled: false,
30315            data_selection_grouped: false,
30316            data_selection_isselectable: function () { return true; },
30317            data_selection_multiple: true,
30318            data_onclick: function () {},
30319            data_onmouseover: function () {},
30320            data_onmouseout: function () {},
30321            data_onselected: function () {},
30322            data_onunselected: function () {},
30323            data_ondragstart: function () {},
30324            data_ondragend: function () {},
30325            data_url: undefined,
30326            data_json: undefined,
30327            data_rows: undefined,
30328            data_columns: undefined,
30329            data_mimeType: undefined,
30330            data_keys: undefined,
30331            // configuration for no plot-able data supplied.
30332            data_empty_label_text: "",
30333            // subchart
30334            subchart_show: false,
30335            subchart_size_height: 60,
30336            subchart_onbrush: function () {},
30337            // color
30338            color_pattern: [],
30339            color_threshold: {},
30340            // legend
30341            legend_show: true,
30342            legend_position: 'bottom',
30343            legend_inset_anchor: 'top-left',
30344            legend_inset_x: 10,
30345            legend_inset_y: 0,
30346            legend_inset_step: undefined,
30347            legend_item_onclick: undefined,
30348            legend_item_onmouseover: undefined,
30349            legend_item_onmouseout: undefined,
30350            legend_equally: false,
30351            // axis
30352            axis_rotated: false,
30353            axis_x_show: true,
30354            axis_x_type: 'indexed',
30355            axis_x_localtime: true,
30356            axis_x_categories: [],
30357            axis_x_tick_centered: false,
30358            axis_x_tick_format: undefined,
30359            axis_x_tick_culling: {},
30360            axis_x_tick_culling_max: 10,
30361            axis_x_tick_count: undefined,
30362            axis_x_tick_fit: true,
30363            axis_x_tick_values: null,
30364            axis_x_tick_rotate: undefined,
30365            axis_x_tick_outer: true,
30366            axis_x_max: null,
30367            axis_x_min: null,
30368            axis_x_padding: {},
30369            axis_x_height: undefined,
30370            axis_x_default: undefined,
30371            axis_x_label: {},
30372            axis_y_show: true,
30373            axis_y_max: undefined,
30374            axis_y_min: undefined,
30375            axis_y_center: undefined,
30376            axis_y_label: {},
30377            axis_y_tick_format: undefined,
30378            axis_y_tick_outer: true,
30379            axis_y_padding: undefined,
30380            axis_y_ticks: 10,
30381            axis_y2_show: false,
30382            axis_y2_max: undefined,
30383            axis_y2_min: undefined,
30384            axis_y2_center: undefined,
30385            axis_y2_label: {},
30386            axis_y2_tick_format: undefined,
30387            axis_y2_tick_outer: true,
30388            axis_y2_padding: undefined,
30389            axis_y2_ticks: 10,
30390            // grid
30391            grid_x_show: false,
30392            grid_x_type: 'tick',
30393            grid_x_lines: [],
30394            grid_y_show: false,
30395            // not used
30396            // grid_y_type: 'tick',
30397            grid_y_lines: [],
30398            grid_y_ticks: 10,
30399            grid_focus_show: true,
30400            // point - point of each data
30401            point_show: true,
30402            point_r: 2.5,
30403            point_focus_expand_enabled: true,
30404            point_focus_expand_r: undefined,
30405            point_select_r: undefined,
30406            line_connect_null: false,
30407            // bar
30408            bar_width: undefined,
30409            bar_width_ratio: 0.6,
30410            bar_width_max: undefined,
30411            bar_zerobased: true,
30412            // area
30413            area_zerobased: true,
30414            // pie
30415            pie_label_show: true,
30416            pie_label_format: undefined,
30417            pie_label_threshold: 0.05,
30418            pie_sort: true,
30419            pie_expand: true,
30420            // gauge
30421            gauge_label_show: true,
30422            gauge_label_format: undefined,
30423            gauge_expand: true,
30424            gauge_min: 0,
30425            gauge_max: 100,
30426            gauge_units: undefined,
30427            gauge_width: undefined,
30428            // donut
30429            donut_label_show: true,
30430            donut_label_format: undefined,
30431            donut_label_threshold: 0.05,
30432            donut_width: undefined,
30433            donut_sort: true,
30434            donut_expand: true,
30435            donut_title: "",
30436            // region - region to change style
30437            regions: [],
30438            // tooltip - show when mouseover on each data
30439            tooltip_show: true,
30440            tooltip_grouped: true,
30441            tooltip_format_title: undefined,
30442            tooltip_format_name: undefined,
30443            tooltip_format_value: undefined,
30444            tooltip_contents: function (d, defaultTitleFormat, defaultValueFormat, color) {
30445                return this.getTooltipContent ? this.getTooltipContent(d, defaultTitleFormat, defaultValueFormat, color) : '';
30446            },
30447            tooltip_init_show: false,
30448            tooltip_init_x: 0,
30449            tooltip_init_position: {top: '0px', left: '50px'}
30450        };
30451
30452        Object.keys(this.additionalConfig).forEach(function (key) {
30453            config[key] = this.additionalConfig[key];
30454        }, this);
30455
30456        return config;
30457    };
30458    c3_chart_internal_fn.additionalConfig = {};
30459
30460    c3_chart_internal_fn.loadConfig = function (config) {
30461        var this_config = this.config, target, keys, read;
30462        function find() {
30463            var key = keys.shift();
30464    //        console.log("key =>", key, ", target =>", target);
30465            if (key && target && typeof target === 'object' && key in target) {
30466                target = target[key];
30467                return find();
30468            }
30469            else if (!key) {
30470                return target;
30471            }
30472            else {
30473                return undefined;
30474            }
30475        }
30476        Object.keys(this_config).forEach(function (key) {
30477            target = config;
30478            keys = key.split('_');
30479            read = find();
30480    //        console.log("CONFIG : ", key, read);
30481            if (isDefined(read)) {
30482                this_config[key] = read;
30483            }
30484        });
30485    };
30486
30487    c3_chart_internal_fn.getScale = function (min, max, forTimeseries) {
30488        return (forTimeseries ? this.d3.time.scale() : this.d3.scale.linear()).range([min, max]);
30489    };
30490    c3_chart_internal_fn.getX = function (min, max, domain, offset) {
30491        var $$ = this,
30492            scale = $$.getScale(min, max, $$.isTimeSeries()),
30493            _scale = domain ? scale.domain(domain) : scale, key;
30494        // Define customized scale if categorized axis
30495        if ($$.isCategorized()) {
30496            offset = offset || function () { return 0; };
30497            scale = function (d, raw) {
30498                var v = _scale(d) + offset(d);
30499                return raw ? v : Math.ceil(v);
30500            };
30501        } else {
30502            scale = function (d, raw) {
30503                var v = _scale(d);
30504                return raw ? v : Math.ceil(v);
30505            };
30506        }
30507        // define functions
30508        for (key in _scale) {
30509            scale[key] = _scale[key];
30510        }
30511        scale.orgDomain = function () {
30512            return _scale.domain();
30513        };
30514        // define custom domain() for categorized axis
30515        if ($$.isCategorized()) {
30516            scale.domain = function (domain) {
30517                if (!arguments.length) {
30518                    domain = this.orgDomain();
30519                    return [domain[0], domain[1] + 1];
30520                }
30521                _scale.domain(domain);
30522                return scale;
30523            };
30524        }
30525        return scale;
30526    };
30527    c3_chart_internal_fn.getY = function (min, max, domain) {
30528        var scale = this.getScale(min, max);
30529        if (domain) { scale.domain(domain); }
30530        return scale;
30531    };
30532    c3_chart_internal_fn.getYScale = function (id) {
30533        return this.getAxisId(id) === 'y2' ? this.y2 : this.y;
30534    };
30535    c3_chart_internal_fn.getSubYScale = function (id) {
30536        return this.getAxisId(id) === 'y2' ? this.subY2 : this.subY;
30537    };
30538    c3_chart_internal_fn.updateScales = function () {
30539        var $$ = this, config = $$.config,
30540            forInit = !$$.x;
30541        // update edges
30542        $$.xMin = config.axis_rotated ? 1 : 0;
30543        $$.xMax = config.axis_rotated ? $$.height : $$.width;
30544        $$.yMin = config.axis_rotated ? 0 : $$.height;
30545        $$.yMax = config.axis_rotated ? $$.width : 1;
30546        $$.subXMin = $$.xMin;
30547        $$.subXMax = $$.xMax;
30548        $$.subYMin = config.axis_rotated ? 0 : $$.height2;
30549        $$.subYMax = config.axis_rotated ? $$.width2 : 1;
30550        // update scales
30551        $$.x = $$.getX($$.xMin, $$.xMax, forInit ? undefined : $$.x.orgDomain(), function () { return $$.xAxis.tickOffset(); });
30552        $$.y = $$.getY($$.yMin, $$.yMax, forInit ? undefined : $$.y.domain());
30553        $$.y2 = $$.getY($$.yMin, $$.yMax, forInit ? undefined : $$.y2.domain());
30554        $$.subX = $$.getX($$.xMin, $$.xMax, $$.orgXDomain, function (d) { return d % 1 ? 0 : $$.subXAxis.tickOffset(); });
30555        $$.subY = $$.getY($$.subYMin, $$.subYMax, forInit ? undefined : $$.subY.domain());
30556        $$.subY2 = $$.getY($$.subYMin, $$.subYMax, forInit ? undefined : $$.subY2.domain());
30557        // update axes
30558        $$.xAxisTickFormat = $$.getXAxisTickFormat();
30559        $$.xAxisTickValues = config.axis_x_tick_values ? config.axis_x_tick_values : (forInit ? undefined : $$.xAxis.tickValues());
30560        $$.xAxis = $$.getXAxis($$.x, $$.xOrient, $$.xAxisTickFormat, $$.xAxisTickValues);
30561        $$.subXAxis = $$.getXAxis($$.subX, $$.subXOrient, $$.xAxisTickFormat, $$.xAxisTickValues);
30562        $$.yAxis = $$.getYAxis($$.y, $$.yOrient, config.axis_y_tick_format, config.axis_y_ticks);
30563        $$.y2Axis = $$.getYAxis($$.y2, $$.y2Orient, config.axis_y2_tick_format, config.axis_y2_ticks);
30564        // Set initialized scales to brush and zoom
30565        if (!forInit) {
30566            if ($$.brush) { $$.brush.scale($$.subX); }
30567            if (config.zoom_enabled) { $$.zoom.scale($$.x); }
30568        }
30569        // update for arc
30570        if ($$.updateArc) { $$.updateArc(); }
30571    };
30572
30573    c3_chart_internal_fn.getYDomainMin = function (targets) {
30574        var $$ = this, config = $$.config,
30575            ids = $$.mapToIds(targets), ys = $$.getValuesAsIdKeyed(targets),
30576            j, k, baseId, idsInGroup, id, hasNegativeValue;
30577        if (config.data_groups.length > 0) {
30578            hasNegativeValue = $$.hasNegativeValueInTargets(targets);
30579            for (j = 0; j < config.data_groups.length; j++) {
30580                // Determine baseId
30581                idsInGroup = config.data_groups[j].filter(function (id) { return ids.indexOf(id) >= 0; });
30582                if (idsInGroup.length === 0) { continue; }
30583                baseId = idsInGroup[0];
30584                // Consider negative values
30585                if (hasNegativeValue && ys[baseId]) {
30586                    ys[baseId].forEach(function (v, i) {
30587                        ys[baseId][i] = v < 0 ? v : 0;
30588                    });
30589                }
30590                // Compute min
30591                for (k = 1; k < idsInGroup.length; k++) {
30592                    id = idsInGroup[k];
30593                    if (! ys[id]) { continue; }
30594                    ys[id].forEach(function (v, i) {
30595                        if ($$.getAxisId(id) === $$.getAxisId(baseId) && ys[baseId] && !(hasNegativeValue && +v > 0)) {
30596                            ys[baseId][i] += +v;
30597                        }
30598                    });
30599                }
30600            }
30601        }
30602        return $$.d3.min(Object.keys(ys).map(function (key) { return $$.d3.min(ys[key]); }));
30603    };
30604    c3_chart_internal_fn.getYDomainMax = function (targets) {
30605        var $$ = this, config = $$.config,
30606            ids = $$.mapToIds(targets), ys = $$.getValuesAsIdKeyed(targets),
30607            j, k, baseId, idsInGroup, id, hasPositiveValue;
30608        if (config.data_groups.length > 0) {
30609            hasPositiveValue = $$.hasPositiveValueInTargets(targets);
30610            for (j = 0; j < config.data_groups.length; j++) {
30611                // Determine baseId
30612                idsInGroup = config.data_groups[j].filter(function (id) { return ids.indexOf(id) >= 0; });
30613                if (idsInGroup.length === 0) { continue; }
30614                baseId = idsInGroup[0];
30615                // Consider positive values
30616                if (hasPositiveValue && ys[baseId]) {
30617                    ys[baseId].forEach(function (v, i) {
30618                        ys[baseId][i] = v > 0 ? v : 0;
30619                    });
30620                }
30621                // Compute max
30622                for (k = 1; k < idsInGroup.length; k++) {
30623                    id = idsInGroup[k];
30624                    if (! ys[id]) { continue; }
30625                    ys[id].forEach(function (v, i) {
30626                        if ($$.getAxisId(id) === $$.getAxisId(baseId) && ys[baseId] && !(hasPositiveValue && +v < 0)) {
30627                            ys[baseId][i] += +v;
30628                        }
30629                    });
30630                }
30631            }
30632        }
30633        return $$.d3.max(Object.keys(ys).map(function (key) { return $$.d3.max(ys[key]); }));
30634    };
30635    c3_chart_internal_fn.getYDomain = function (targets, axisId) {
30636        var $$ = this, config = $$.config,
30637            yTargets = targets.filter(function (d) { return $$.getAxisId(d.id) === axisId; }),
30638            yMin = axisId === 'y2' ? config.axis_y2_min : config.axis_y_min,
30639            yMax = axisId === 'y2' ? config.axis_y2_max : config.axis_y_max,
30640            yDomainMin = isValue(yMin) ? yMin : $$.getYDomainMin(yTargets),
30641            yDomainMax = isValue(yMax) ? yMax : $$.getYDomainMax(yTargets),
30642            domainLength, padding, padding_top, padding_bottom,
30643            center = axisId === 'y2' ? config.axis_y2_center : config.axis_y_center,
30644            yDomainAbs, lengths, diff, ratio, isAllPositive, isAllNegative,
30645            isZeroBased = ($$.hasType('bar', yTargets) && config.bar_zerobased) || ($$.hasType('area', yTargets) && config.area_zerobased),
30646            showHorizontalDataLabel = $$.hasDataLabel() && config.axis_rotated,
30647            showVerticalDataLabel = $$.hasDataLabel() && !config.axis_rotated;
30648        if (yTargets.length === 0) { // use current domain if target of axisId is none
30649            return axisId === 'y2' ? $$.y2.domain() : $$.y.domain();
30650        }
30651        if (yDomainMin === yDomainMax) {
30652            yDomainMin < 0 ? yDomainMax = 0 : yDomainMin = 0;
30653        }
30654        isAllPositive = yDomainMin >= 0 && yDomainMax >= 0;
30655        isAllNegative = yDomainMin <= 0 && yDomainMax <= 0;
30656
30657        // Bar/Area chart should be 0-based if all positive|negative
30658        if (isZeroBased) {
30659            if (isAllPositive) { yDomainMin = 0; }
30660            if (isAllNegative) { yDomainMax = 0; }
30661        }
30662
30663        domainLength = Math.abs(yDomainMax - yDomainMin);
30664        padding = padding_top = padding_bottom = domainLength * 0.1;
30665
30666        if (center) {
30667            yDomainAbs = Math.max(Math.abs(yDomainMin), Math.abs(yDomainMax));
30668            yDomainMax = yDomainAbs - center;
30669            yDomainMin = center - yDomainAbs;
30670        }
30671        // add padding for data label
30672        if (showHorizontalDataLabel) {
30673            lengths = $$.getDataLabelLength(yDomainMin, yDomainMax, axisId, 'width');
30674            diff = diffDomain($$.y.range());
30675            ratio = [lengths[0] / diff, lengths[1] / diff];
30676            padding_top += domainLength * (ratio[1] / (1 - ratio[0] - ratio[1]));
30677            padding_bottom += domainLength * (ratio[0] / (1 - ratio[0] - ratio[1]));
30678        } else if (showVerticalDataLabel) {
30679            lengths = $$.getDataLabelLength(yDomainMin, yDomainMax, axisId, 'height');
30680            padding_top += lengths[1];
30681            padding_bottom += lengths[0];
30682        }
30683        if (axisId === 'y' && config.axis_y_padding) {
30684            padding_top = $$.getAxisPadding(config.axis_y_padding, 'top', padding, domainLength);
30685            padding_bottom = $$.getAxisPadding(config.axis_y_padding, 'bottom', padding, domainLength);
30686        }
30687        if (axisId === 'y2' && config.axis_y2_padding) {
30688            padding_top = $$.getAxisPadding(config.axis_y2_padding, 'top', padding, domainLength);
30689            padding_bottom = $$.getAxisPadding(config.axis_y2_padding, 'bottom', padding, domainLength);
30690        }
30691        // Bar/Area chart should be 0-based if all positive|negative
30692        if (isZeroBased) {
30693            if (isAllPositive) { padding_bottom = yDomainMin; }
30694            if (isAllNegative) { padding_top = -yDomainMax; }
30695        }
30696        return [yDomainMin - padding_bottom, yDomainMax + padding_top];
30697    };
30698    c3_chart_internal_fn.getXDomainMin = function (targets) {
30699        var $$ = this, config = $$.config;
30700        return config.axis_x_min ?
30701            ($$.isTimeSeries() ? this.parseDate(config.axis_x_min) : config.axis_x_min) :
30702        $$.d3.min(targets, function (t) { return $$.d3.min(t.values, function (v) { return v.x; }); });
30703    };
30704    c3_chart_internal_fn.getXDomainMax = function (targets) {
30705        var $$ = this, config = $$.config;
30706        return config.axis_x_max ?
30707            ($$.isTimeSeries() ? this.parseDate(config.axis_x_max) : config.axis_x_max) :
30708        $$.d3.max(targets, function (t) { return $$.d3.max(t.values, function (v) { return v.x; }); });
30709    };
30710    c3_chart_internal_fn.getXDomainPadding = function (targets) {
30711        var $$ = this, config = $$.config,
30712            edgeX = this.getEdgeX(targets), diff = edgeX[1] - edgeX[0],
30713            maxDataCount, padding, paddingLeft, paddingRight;
30714        if ($$.isCategorized()) {
30715            padding = 0;
30716        } else if ($$.hasType('bar', targets)) {
30717            maxDataCount = $$.getMaxDataCount();
30718            padding = maxDataCount > 1 ? (diff / (maxDataCount - 1)) / 2 : 0.5;
30719        } else {
30720            padding = diff * 0.01;
30721        }
30722        if (typeof config.axis_x_padding === 'object' && notEmpty(config.axis_x_padding)) {
30723            paddingLeft = isValue(config.axis_x_padding.left) ? config.axis_x_padding.left : padding;
30724            paddingRight = isValue(config.axis_x_padding.right) ? config.axis_x_padding.right : padding;
30725        } else if (typeof config.axis_x_padding === 'number') {
30726            paddingLeft = paddingRight = config.axis_x_padding;
30727        } else {
30728            paddingLeft = paddingRight = padding;
30729        }
30730        return {left: paddingLeft, right: paddingRight};
30731    };
30732    c3_chart_internal_fn.getXDomain = function (targets) {
30733        var $$ = this,
30734            xDomain = [$$.getXDomainMin(targets), $$.getXDomainMax(targets)],
30735            firstX = xDomain[0], lastX = xDomain[1],
30736            padding = $$.getXDomainPadding(targets),
30737            min = 0, max = 0;
30738        // show center of x domain if min and max are the same
30739        if ((firstX - lastX) === 0 && !$$.isCategorized()) {
30740            firstX = $$.isTimeSeries() ? new Date(firstX.getTime() * 0.5) : -0.5;
30741            lastX = $$.isTimeSeries() ? new Date(lastX.getTime() * 1.5) : 0.5;
30742        }
30743        if (firstX || firstX === 0) {
30744            min = $$.isTimeSeries() ? new Date(firstX.getTime() - padding.left) : firstX - padding.left;
30745        }
30746        if (lastX || lastX === 0) {
30747            max = $$.isTimeSeries() ? new Date(lastX.getTime() + padding.right) : lastX + padding.right;
30748        }
30749        return [min, max];
30750    };
30751    c3_chart_internal_fn.updateXDomain = function (targets, withUpdateXDomain, withUpdateOrgXDomain, domain) {
30752        var $$ = this, config = $$.config;
30753        if (withUpdateOrgXDomain) {
30754            $$.x.domain(domain ? domain : $$.d3.extent($$.getXDomain(targets)));
30755            $$.orgXDomain = $$.x.domain();
30756            if (config.zoom_enabled) { $$.zoom.scale($$.x).updateScaleExtent(); }
30757            $$.subX.domain($$.x.domain());
30758            if ($$.brush) { $$.brush.scale($$.subX); }
30759        }
30760        if (withUpdateXDomain) {
30761            $$.x.domain(domain ? domain : (!$$.brush || $$.brush.empty()) ? $$.orgXDomain : $$.brush.extent());
30762            if (config.zoom_enabled) { $$.zoom.scale($$.x).updateScaleExtent(); }
30763        }
30764        return $$.x.domain();
30765    };
30766
30767    c3_chart_internal_fn.isX = function (key) {
30768        var $$ = this, config = $$.config;
30769        return (config.data_x && key === config.data_x) || (notEmpty(config.data_xs) && hasValue(config.data_xs, key));
30770    };
30771    c3_chart_internal_fn.isNotX = function (key) {
30772        return !this.isX(key);
30773    };
30774    c3_chart_internal_fn.getXKey = function (id) {
30775        var $$ = this, config = $$.config;
30776        return config.data_x ? config.data_x : notEmpty(config.data_xs) ? config.data_xs[id] : null;
30777    };
30778    c3_chart_internal_fn.getXValuesOfXKey = function (key, targets) {
30779        var $$ = this,
30780            xValues, ids = targets && notEmpty(targets) ? $$.mapToIds(targets) : [];
30781        ids.forEach(function (id) {
30782            if ($$.getXKey(id) === key) {
30783                xValues = $$.data.xs[id];
30784            }
30785        });
30786        return xValues;
30787    };
30788    c3_chart_internal_fn.getXValue = function (id, i) {
30789        var $$ = this;
30790        return id in $$.data.xs && $$.data.xs[id] && isValue($$.data.xs[id][i]) ? $$.data.xs[id][i] : i;
30791    };
30792    c3_chart_internal_fn.getOtherTargetXs = function () {
30793        var $$ = this,
30794            idsForX = Object.keys($$.data.xs);
30795        return idsForX.length ? $$.data.xs[idsForX[0]] : null;
30796    };
30797    c3_chart_internal_fn.getOtherTargetX = function (index) {
30798        var xs = this.getOtherTargetXs();
30799        return xs && index < xs.length ? xs[index] : null;
30800    };
30801    c3_chart_internal_fn.addXs = function (xs) {
30802        var $$ = this;
30803        Object.keys(xs).forEach(function (id) {
30804            $$.config.data_xs[id] = xs[id];
30805        });
30806    };
30807    c3_chart_internal_fn.hasMultipleX = function (xs) {
30808        return this.d3.set(Object.keys(xs).map(function (id) { return xs[id]; })).size() > 1;
30809    };
30810    c3_chart_internal_fn.isMultipleX = function () {
30811        var $$ = this, config = $$.config;
30812        return notEmpty(config.data_xs) && $$.hasMultipleX(config.data_xs);
30813    };
30814    c3_chart_internal_fn.addName = function (data) {
30815        var $$ = this, name;
30816        if (data) {
30817            name = $$.config.data_names[data.id];
30818            data.name = name ? name : data.id;
30819        }
30820        return data;
30821    };
30822    c3_chart_internal_fn.getValueOnIndex = function (values, index) {
30823        var valueOnIndex = values.filter(function (v) { return v.index === index; });
30824        return valueOnIndex.length ? valueOnIndex[0] : null;
30825    };
30826    c3_chart_internal_fn.updateTargetX = function (targets, x) {
30827        var $$ = this;
30828        targets.forEach(function (t) {
30829            t.values.forEach(function (v, i) {
30830                v.x = $$.generateTargetX(x[i], t.id, i);
30831            });
30832            $$.data.xs[t.id] = x;
30833        });
30834    };
30835    c3_chart_internal_fn.updateTargetXs = function (targets, xs) {
30836        var $$ = this;
30837        targets.forEach(function (t) {
30838            if (xs[t.id]) {
30839                $$.updateTargetX([t], xs[t.id]);
30840            }
30841        });
30842    };
30843    c3_chart_internal_fn.generateTargetX = function (rawX, id, index) {
30844        var $$ = this, x;
30845        if ($$.isTimeSeries()) {
30846            x = rawX ? $$.parseDate(rawX) : $$.parseDate($$.getXValue(id, index));
30847        }
30848        else if ($$.isCustomX() && !$$.isCategorized()) {
30849            x = isValue(rawX) ? +rawX : $$.getXValue(id, index);
30850        }
30851        else {
30852            x = index;
30853        }
30854        return x;
30855    };
30856    c3_chart_internal_fn.cloneTarget = function (target) {
30857        return {
30858            id : target.id,
30859            id_org : target.id_org,
30860            values : target.values.map(function (d) {
30861                return {x: d.x, value: d.value, id: d.id};
30862            })
30863        };
30864    };
30865    c3_chart_internal_fn.getPrevX = function (i) {
30866        var $$ = this, value = $$.getValueOnIndex($$.data.targets[0].values, i - 1);
30867        return value ? value.x : null;
30868    };
30869    c3_chart_internal_fn.getNextX = function (i) {
30870        var $$ = this, value = $$.getValueOnIndex($$.data.targets[0].values, i + 1);
30871        return value ? value.x : null;
30872    };
30873    c3_chart_internal_fn.getMaxDataCount = function () {
30874        var $$ = this;
30875        return $$.d3.max($$.data.targets, function (t) { return t.values.length; });
30876    };
30877    c3_chart_internal_fn.getMaxDataCountTarget = function (targets) {
30878        var length = targets.length, max = 0, maxTarget;
30879        if (length > 1) {
30880            targets.forEach(function (t) {
30881                if (t.values.length > max) {
30882                    maxTarget = t;
30883                    max = t.values.length;
30884                }
30885            });
30886        } else {
30887            maxTarget = length ? targets[0] : null;
30888        }
30889        return maxTarget;
30890    };
30891    c3_chart_internal_fn.getEdgeX = function (targets) {
30892        var target = this.getMaxDataCountTarget(targets), firstData, lastData;
30893        if (!target) {
30894            return [0, 0];
30895        }
30896        firstData = target.values[0], lastData = target.values[target.values.length - 1];
30897        return [firstData.x, lastData.x];
30898    };
30899    c3_chart_internal_fn.mapToIds = function (targets) {
30900        return targets.map(function (d) { return d.id; });
30901    };
30902    c3_chart_internal_fn.mapToTargetIds = function (ids) {
30903        var $$ = this;
30904        return ids ? (isString(ids) ? [ids] : ids) : $$.mapToIds($$.data.targets);
30905    };
30906    c3_chart_internal_fn.hasTarget = function (targets, id) {
30907        var ids = this.mapToIds(targets), i;
30908        for (i = 0; i < ids.length; i++) {
30909            if (ids[i] === id) {
30910                return true;
30911            }
30912        }
30913        return false;
30914    };
30915    c3_chart_internal_fn.isTargetToShow = function (targetId) {
30916        return this.hiddenTargetIds.indexOf(targetId) < 0;
30917    };
30918    c3_chart_internal_fn.isLegendToShow = function (targetId) {
30919        return this.hiddenLegendIds.indexOf(targetId) < 0;
30920    };
30921    c3_chart_internal_fn.filterTargetsToShow = function (targets) {
30922        var $$ = this;
30923        return targets.filter(function (t) { return $$.isTargetToShow(t.id); });
30924    };
30925    c3_chart_internal_fn.mapTargetsToUniqueXs = function (targets) {
30926        var $$ = this;
30927        var xs = $$.d3.set($$.d3.merge(targets.map(function (t) { return t.values.map(function (v) { return v.x; }); }))).values();
30928        return $$.isTimeSeries() ? xs.map(function (x) { return new Date(x); }) : xs.map(function (x) { return +x; });
30929    };
30930    c3_chart_internal_fn.addHiddenTargetIds = function (targetIds) {
30931        this.hiddenTargetIds = this.hiddenTargetIds.concat(targetIds);
30932    };
30933    c3_chart_internal_fn.removeHiddenTargetIds = function (targetIds) {
30934        this.hiddenTargetIds = this.hiddenTargetIds.filter(function (id) { return targetIds.indexOf(id) < 0; });
30935    };
30936    c3_chart_internal_fn.addHiddenLegendIds = function (targetIds) {
30937        this.hiddenLegendIds = this.hiddenLegendIds.concat(targetIds);
30938    };
30939    c3_chart_internal_fn.removeHiddenLegendIds = function (targetIds) {
30940        this.hiddenLegendIds = this.hiddenLegendIds.filter(function (id) { return targetIds.indexOf(id) < 0; });
30941    };
30942    c3_chart_internal_fn.getValuesAsIdKeyed = function (targets) {
30943        var ys = {};
30944        targets.forEach(function (t) {
30945            ys[t.id] = [];
30946            t.values.forEach(function (v) {
30947                ys[t.id].push(v.value);
30948            });
30949        });
30950        return ys;
30951    };
30952    c3_chart_internal_fn.checkValueInTargets = function (targets, checker) {
30953        var ids = Object.keys(targets), i, j, values;
30954        for (i = 0; i < ids.length; i++) {
30955            values = targets[ids[i]].values;
30956            for (j = 0; j < values.length; j++) {
30957                if (checker(values[j].value)) {
30958                    return true;
30959                }
30960            }
30961        }
30962        return false;
30963    };
30964    c3_chart_internal_fn.hasNegativeValueInTargets = function (targets) {
30965        return this.checkValueInTargets(targets, function (v) { return v < 0; });
30966    };
30967    c3_chart_internal_fn.hasPositiveValueInTargets = function (targets) {
30968        return this.checkValueInTargets(targets, function (v) { return v > 0; });
30969    };
30970    c3_chart_internal_fn.isOrderDesc = function () {
30971        var config = this.config;
30972        return config.data_order && config.data_order.toLowerCase() === 'desc';
30973    };
30974    c3_chart_internal_fn.isOrderAsc = function () {
30975        var config = this.config;
30976        return config.data_order && config.data_order.toLowerCase() === 'asc';
30977    };
30978    c3_chart_internal_fn.orderTargets = function (targets) {
30979        var $$ = this, config = $$.config, orderAsc = $$.isOrderAsc(), orderDesc = $$.isOrderDesc();
30980        if (orderAsc || orderDesc) {
30981            targets.sort(function (t1, t2) {
30982                var reducer = function (p, c) { return p + Math.abs(c.value); };
30983                var t1Sum = t1.values.reduce(reducer, 0),
30984                    t2Sum = t2.values.reduce(reducer, 0);
30985                return orderAsc ? t2Sum - t1Sum : t1Sum - t2Sum;
30986            });
30987        } else if (isFunction(config.data_order)) {
30988            targets.sort(config.data_order);
30989        } // TODO: accept name array for order
30990        return targets;
30991    };
30992    c3_chart_internal_fn.filterSameX = function (targets, x) {
30993        return this.d3.merge(targets.map(function (t) { return t.values; })).filter(function (v) { return v.x - x === 0; });
30994    };
30995    c3_chart_internal_fn.filterRemoveNull = function (data) {
30996        return data.filter(function (d) { return isValue(d.value); });
30997    };
30998    c3_chart_internal_fn.hasDataLabel = function () {
30999        var config = this.config;
31000        if (typeof config.data_labels === 'boolean' && config.data_labels) {
31001            return true;
31002        } else if (typeof config.data_labels === 'object' && notEmpty(config.data_labels)) {
31003            return true;
31004        }
31005        return false;
31006    };
31007    c3_chart_internal_fn.getDataLabelLength = function (min, max, axisId, key) {
31008        var $$ = this,
31009            lengths = [0, 0], paddingCoef = 1.3;
31010        $$.selectChart.select('svg').selectAll('.dummy')
31011            .data([min, max])
31012            .enter().append('text')
31013            .text(function (d) { return $$.formatByAxisId(axisId)(d); })
31014            .each(function (d, i) {
31015                lengths[i] = this.getBoundingClientRect()[key] * paddingCoef;
31016            })
31017            .remove();
31018        return lengths;
31019    };
31020    c3_chart_internal_fn.isNoneArc = function (d) {
31021        return this.hasTarget(this.data.targets, d.id);
31022    },
31023    c3_chart_internal_fn.isArc = function (d) {
31024        return 'data' in d && this.hasTarget(this.data.targets, d.data.id);
31025    };
31026    c3_chart_internal_fn.findSameXOfValues = function (values, index) {
31027        var i, targetX = values[index].x, sames = [];
31028        for (i = index - 1; i >= 0; i--) {
31029            if (targetX !== values[i].x) { break; }
31030            sames.push(values[i]);
31031        }
31032        for (i = index; i < values.length; i++) {
31033            if (targetX !== values[i].x) { break; }
31034            sames.push(values[i]);
31035        }
31036        return sames;
31037    };
31038
31039    c3_chart_internal_fn.findClosestOfValues = function (values, pos, _min, _max) { // MEMO: values must be sorted by x
31040        var $$ = this,
31041            min = _min ? _min : 0,
31042            max = _max ? _max : values.length - 1,
31043            med = Math.floor((max - min) / 2) + min,
31044            value = values[med],
31045            diff = $$.x(value.x) - pos[$$.config.axis_rotated ? 1 : 0],
31046            candidates;
31047
31048        // Update range for search
31049        diff > 0 ? max = med : min = med;
31050
31051        // if candidates are two closest min and max, stop recursive call
31052        if ((max - min) === 1 || (min === 0 && max === 0)) {
31053
31054            // Get candidates that has same min and max index
31055            candidates = [];
31056            if (values[min].x || values[min].x === 0) {
31057                candidates = candidates.concat($$.findSameXOfValues(values, min));
31058            }
31059            if (values[max].x || values[max].x === 0) {
31060                candidates = candidates.concat($$.findSameXOfValues(values, max));
31061            }
31062
31063            // Determine the closest and return
31064            return $$.findClosest(candidates, pos);
31065        }
31066
31067        return $$.findClosestOfValues(values, pos, min, max);
31068    };
31069    c3_chart_internal_fn.findClosestFromTargets = function (targets, pos) {
31070        var $$ = this, candidates;
31071
31072        // map to array of closest points of each target
31073        candidates = targets.map(function (target) {
31074            return $$.findClosestOfValues(target.values, pos);
31075        });
31076
31077        // decide closest point and return
31078        return $$.findClosest(candidates, pos);
31079    };
31080    c3_chart_internal_fn.findClosest = function (values, pos) {
31081        var $$ = this, minDist, closest;
31082        values.forEach(function (v) {
31083            var d = $$.dist(v, pos);
31084            if (d < minDist || ! minDist) {
31085                minDist = d;
31086                closest = v;
31087            }
31088        });
31089        return closest;
31090    };
31091    c3_chart_internal_fn.dist = function (data, pos) {
31092        var $$ = this, config = $$.config,
31093            yScale = $$.getAxisId(data.id) === 'y' ? $$.y : $$.y2,
31094            xIndex = config.axis_rotated ? 1 : 0,
31095            yIndex = config.axis_rotated ? 0 : 1;
31096        return Math.pow($$.x(data.x) - pos[xIndex], 2) + Math.pow(yScale(data.value) - pos[yIndex], 2);
31097    };
31098
31099    c3_chart_internal_fn.convertUrlToData = function (url, mimeType, keys, done) {
31100        var $$ = this, type = mimeType ? mimeType : 'csv';
31101        $$.d3.xhr(url, function (error, data) {
31102            var d;
31103            if (type === 'json') {
31104                d = $$.convertJsonToData(JSON.parse(data.response), keys);
31105            } else {
31106                d = $$.convertCsvToData(data.response);
31107            }
31108            done.call($$, d);
31109        });
31110    };
31111    c3_chart_internal_fn.convertCsvToData = function (csv) {
31112        var d3 = this.d3, rows = d3.csv.parseRows(csv), d;
31113        if (rows.length === 1) {
31114            d = [{}];
31115            rows[0].forEach(function (id) {
31116                d[0][id] = null;
31117            });
31118        } else {
31119            d = d3.csv.parse(csv);
31120        }
31121        return d;
31122    };
31123    c3_chart_internal_fn.convertJsonToData = function (json, keys) {
31124        var $$ = this,
31125            new_rows = [], targetKeys, data;
31126        if (keys) { // when keys specified, json would be an array that includes objects
31127            targetKeys = keys.value;
31128            if (keys.x) {
31129                targetKeys.push(keys.x);
31130                $$.config.data_x = keys.x;
31131            }
31132            new_rows.push(targetKeys);
31133            json.forEach(function (o) {
31134                var new_row = [];
31135                targetKeys.forEach(function (key) {
31136                    // convert undefined to null because undefined data will be removed in convertDataToTargets()
31137                    var v = isUndefined(o[key]) ? null : o[key];
31138                    new_row.push(v);
31139                });
31140                new_rows.push(new_row);
31141            });
31142            data = $$.convertRowsToData(new_rows);
31143        } else {
31144            Object.keys(json).forEach(function (key) {
31145                new_rows.push([key].concat(json[key]));
31146            });
31147            data = $$.convertColumnsToData(new_rows);
31148        }
31149        return data;
31150    };
31151    c3_chart_internal_fn.convertRowsToData = function (rows) {
31152        var keys = rows[0], new_row = {}, new_rows = [], i, j;
31153        for (i = 1; i < rows.length; i++) {
31154            new_row = {};
31155            for (j = 0; j < rows[i].length; j++) {
31156                if (isUndefined(rows[i][j])) {
31157                    throw new Error("Source data is missing a component at (" + i + "," + j + ")!");
31158                }
31159                new_row[keys[j]] = rows[i][j];
31160            }
31161            new_rows.push(new_row);
31162        }
31163        return new_rows;
31164    };
31165    c3_chart_internal_fn.convertColumnsToData = function (columns) {
31166        var new_rows = [], i, j, key;
31167        for (i = 0; i < columns.length; i++) {
31168            key = columns[i][0];
31169            for (j = 1; j < columns[i].length; j++) {
31170                if (isUndefined(new_rows[j - 1])) {
31171                    new_rows[j - 1] = {};
31172                }
31173                if (isUndefined(columns[i][j])) {
31174                    throw new Error("Source data is missing a component at (" + i + "," + j + ")!");
31175                }
31176                new_rows[j - 1][key] = columns[i][j];
31177            }
31178        }
31179        return new_rows;
31180    };
31181    c3_chart_internal_fn.convertDataToTargets = function (data, appendXs) {
31182        var $$ = this, config = $$.config,
31183            ids = $$.d3.keys(data[0]).filter($$.isNotX, $$),
31184            xs = $$.d3.keys(data[0]).filter($$.isX, $$),
31185            targets;
31186
31187        // save x for update data by load when custom x and c3.x API
31188        ids.forEach(function (id) {
31189            var xKey = $$.getXKey(id);
31190
31191            if ($$.isCustomX() || $$.isTimeSeries()) {
31192                // if included in input data
31193                if (xs.indexOf(xKey) >= 0) {
31194                    $$.data.xs[id] = (appendXs && $$.data.xs[id] ? $$.data.xs[id] : []).c
vendor: 4,344 bytes, lines 31194-31305
31194oncat(
31195                        data.map(function (d) { return d[xKey]; })
31196                            .filter(isValue)
31197                            .map(function (rawX, i) { return $$.generateTargetX(rawX, id, i); })
31198                    );
31199                }
31200                // if not included in input data, find from preloaded data of other id's x
31201                else if (config.data_x) {
31202                    $$.data.xs[id] = $$.getOtherTargetXs();
31203                }
31204                // if not included in input data, find from preloaded data
31205                else if (notEmpty(config.data_xs)) {
31206                    $$.data.xs[id] = $$.getXValuesOfXKey(xKey, $$.data.targets);
31207                }
31208                // MEMO: if no x included, use same x of current will be used
31209            } else {
31210                $$.data.xs[id] = data.map(function (d, i) { return i; });
31211            }
31212        });
31213
31214
31215        // check x is defined
31216        ids.forEach(function (id) {
31217            if (!$$.data.xs[id]) {
31218                throw new Error('x is not defined for id = "' + id + '".');
31219            }
31220        });
31221
31222        // convert to target
31223        targets = ids.map(function (id, index) {
31224            var convertedId = config.data_idConverter(id);
31225            return {
31226                id: convertedId,
31227                id_org: id,
31228                values: data.map(function (d, i) {
31229                    var xKey = $$.getXKey(id), rawX = d[xKey], x = $$.generateTargetX(rawX, id, i);
31230                    // use x as categories if custom x and categorized
31231                    if ($$.isCustomX() && $$.isCategorized() && index === 0 && rawX) {
31232                        if (i === 0) { config.axis_x_categories = []; }
31233                        config.axis_x_categories.push(rawX);
31234                    }
31235                    // mark as x = undefined if value is undefined and filter to remove after mapped
31236                    if (isUndefined(d[id]) || $$.data.xs[id].length <= i) {
31237                        x = undefined;
31238                    }
31239                    return {x: x, value: d[id] !== null && !isNaN(d[id]) ? +d[id] : null, id: convertedId};
31240                }).filter(function (v) { return isDefined(v.x); })
31241            };
31242        });
31243
31244        // finish targets
31245        targets.forEach(function (t) {
31246            var i;
31247            // sort values by its x
31248            t.values = t.values.sort(function (v1, v2) {
31249                var x1 = v1.x || v1.x === 0 ? v1.x : Infinity,
31250                    x2 = v2.x || v2.x === 0 ? v2.x : Infinity;
31251                return x1 - x2;
31252            });
31253            // indexing each value
31254            i = 0;
31255            t.values.forEach(function (v) {
31256                v.index = i++;
31257            });
31258            // this needs to be sorted because its index and value.index is identical
31259            $$.data.xs[t.id].sort(function (v1, v2) {
31260                return v1 - v2;
31261            });
31262        });
31263
31264        // set target types
31265        if (config.data_type) {
31266            $$.setTargetType($$.mapToIds(targets).filter(function (id) { return ! (id in config.data_types); }), config.data_type);
31267        }
31268
31269        // cache as original id keyed
31270        targets.forEach(function (d) {
31271            $$.addCache(d.id_org, d);
31272        });
31273
31274        return targets;
31275    };
31276
31277    c3_chart_internal_fn.load = function (targets, args) {
31278        var $$ = this;
31279        if (targets) {
31280            // filter loading targets if needed
31281            if (args.filter) {
31282                targets = targets.filter(args.filter);
31283            }
31284            // set type if args.types || args.type specified
31285            if (args.type || args.types) {
31286                targets.forEach(function (t) {
31287                    $$.setTargetType(t.id, args.types ? args.types[t.id] : args.type);
31288                });
31289            }
31290            // Update/Add data
31291            $$.data.targets.forEach(function (d) {
31292                for (var i = 0; i < targets.length; i++) {
31293                    if (d.id === targets[i].id) {
31294                        d.values = targets[i].values;
31295                        targets.splice(i, 1);
31296                        break;
31297                    }
31298                }
31299            });
31300            $$.data.targets = $$.data.targets.concat(targets); // add remained
31301        }
31302
31303        // Set targets
31304        $$.updateTargets($$.data.targets);
31305
31306        // Redraw with new targets
31307        $$.redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true, withLegend: true});
31308
31309        if (args.done) { args.done(); }
31310    };
31311    c3_chart_internal_fn.loadFromArgs = function (args) {
31312        var $$ = this;
31313        if (args.data) {
31314            $$.load($$.convertDataToTargets(args.data), args);
31315        }
31316        else if (args.url) {
31317            $$.convertUrlToData(args.url, args.mimeType, args.keys, function (data) {
31318                $$.load($$.convertDataToTargets(data), args);
31319            });
31320        }
31321        else if (args.json) {
31322            $$.load($$.convertDataToTargets($$.convertJsonToData(args.json, args.keys)), args);
31323        }
31324        else if (args.rows) {
31325            $$.load($$.convertDataToTargets($$.convertRowsToData(args.rows)), args);
31326        }
31327        else if (args.columns) {
31328            $$.load($$.convertDataToTargets($$.convertColumnsToData(args.columns)), args);
31329        }
31330        else {
31331            $$.load(null, args);
31332        }
31333    };
31334    c3_chart_internal_fn.unload = function (targetIds, done) {
31335        var $$ = this;
31336        if (!done) {
31337            done = function () {};
31338        }
31339        // filter existing target
31340        targetIds = targetIds.filter(function (id) { return $$.hasTarget($$.data.targets, id); });
31341        // If no target, call done and return
31342        if (!targetIds || targetIds.length === 0) {
31343            done();
31344            return;
31345        }
31346        $$.svg.selectAll(targetIds.map(function (id) { return $$.selectorTarget(id); }))
31347            .transition()
31348            .style('opacity', 0)
31349            .remove()
31350            .call($$.endall, done);
31351        targetIds.forEach(function (id) {
31352            // Reset fadein for future load
31353            $$.withoutFadeIn[id] = false;
31354            // Remove target's elements
31355            if ($$.legend) {
31356                $$.legend.selectAll('.' + CLASS.legendItem + $$.getTargetSelectorSuffix(id)).remove();
31357            }
31358            // Remove target
31359            $$.data.targets = $$.data.targets.filter(function (t) {
31360                return t.id !== id;
31361            });
31362        });
31363    };
31364
31365    c3_chart_internal_fn.categoryName = function (i) {
31366        var config = this.config;
31367        return i < config.axis_x_categories.length ? config.axis_x_categories[i] : i;
31368    };
31369
31370    c3_chart_internal_fn.initEventRect = function () {
31371        var $$ = this;
31372        $$.main.select('.' + CLASS.chart).append("g")
31373            .attr("class", CLASS.eventRects)
31374            .style('fill-opacity', 0);
31375    };
31376    c3_chart_internal_fn.redrawEventRect = function () {
31377        var $$ = this, config = $$.config,
31378            eventRectUpdate, maxDataCountTarget,
31379            isMultipleX = $$.isMultipleX();
31380
31381        // rects for mouseover
31382        var eventRects = $$.main.select('.' + CLASS.eventRects)
31383                .style('cursor', config.zoom_enabled ? config.axis_rotated ? 'ns-resize' : 'ew-resize' : null)
31384                .classed(CLASS.eventRectsMultiple, isMultipleX)
31385                .classed(CLASS.eventRectsSingle, !isMultipleX);
31386
31387        // clear old rects
31388        eventRects.selectAll('.' + CLASS.eventRect).remove();
31389
31390        // open as public variable
31391        $$.eventRect = eventRects.selectAll('.' + CLASS.eventRect);
31392
31393        if (isMultipleX) {
31394            eventRectUpdate = $$.eventRect.data([0]);
31395            // enter : only one rect will be added
31396            $$.generateEventRectsForMultipleXs(eventRectUpdate.enter());
31397            // update
31398            $$.updateEventRect(eventRectUpdate);
31399            // exit : not needed because always only one rect exists
31400        }
31401        else {
31402            // Set data and update $$.eventRect
31403            maxDataCountTarget = $$.getMaxDataCountTarget($$.data.targets);
31404            eventRects.datum(maxDataCountTarget ? maxDataCountTarget.values : []);
31405            $$.eventRect = eventRects.selectAll('.' + CLASS.eventRect);
31406            eventRectUpdate = $$.eventRect.data(function (d) { return d; });
31407            // enter
31408            $$.generateEventRectsForSingleX(eventRectUpdate.enter());
31409            // update
31410            $$.updateEventRect(eventRectUpdate);
31411            // exit
31412            eventRectUpdate.exit().remove();
31413        }
31414    };
31415    c3_chart_internal_fn.updateEventRect = function (eventRectUpdate) {
31416        var $$ = this, config = $$.config,
31417            x, y, w, h, rectW, rectX;
31418
31419        // set update selection if null
31420        eventRectUpdate = eventRectUpdate || $$.eventRect.data(function (d) { return d; });
31421
31422        if ($$.isMultipleX()) {
31423            // TODO: rotated not supported yet
31424            x = 0;
31425            y = 0;
31426            w = $$.width;
31427            h = $$.height;
31428        }
31429        else {
31430            if (($$.isCustomX() || $$.isTimeSeries()) && !$$.isCategorized()) {
31431                rectW = function (d) {
31432                    var prevX = $$.getPrevX(d.index), nextX = $$.getNextX(d.index), dx = $$.data.xs[d.id][d.index],
31433                        w = ($$.x(nextX ? nextX : dx) - $$.x(prevX ? prevX : dx)) / 2;
31434                    return w < 0 ? 0 : w;
31435                };
31436                rectX = function (d) {
31437                    var prevX = $$.getPrevX(d.index), dx = $$.data.xs[d.id][d.index];
31438                    return ($$.x(dx) + $$.x(prevX ? prevX : dx)) / 2;
31439                };
31440            } else {
31441                rectW = $$.getEventRectWidth();
31442                rectX = function (d) {
31443                    return $$.x(d.x) - (rectW / 2);
31444                };
31445            }
31446            x = config.axis_rotated ? 0 : rectX;
31447            y = config.axis_rotated ? rectX : 0;
31448            w = config.axis_rotated ? $$.width : rectW;
31449            h = config.axis_rotated ? rectW : $$.height;
31450        }
31451
31452        eventRectUpdate
31453            .attr('class', $$.classEvent.bind($$))
31454            .attr("x", x)
31455            .attr("y", y)
31456            .attr("width", w)
31457            .attr("height", h);
31458    };
31459    c3_chart_internal_fn.generateEventRectsForSingleX = function (eventRectEnter) {
31460        var $$ = this, d3 = $$.d3, config = $$.config;
31461        eventRectEnter.append("rect")
31462            .attr("class", $$.classEvent.bind($$))
31463            .style("cursor", config.data_selection_enabled && config.data_selection_grouped ? "pointer" : null)
31464            .on('mouseover', function (d) {
31465                var index = d.index, selectedData, newData;
31466
31467                if ($$.dragging) { return; } // do nothing if dragging
31468                if ($$.hasArcType()) { return; }
31469
31470                selectedData = $$.data.targets.map(function (t) {
31471                    return $$.addName($$.getValueOnIndex(t.values, index));
31472                });
31473
31474                // Sort selectedData as names order
31475                newData = [];
31476                Object.keys(config.data_names).forEach(function (id) {
31477                    for (var j = 0; j < selectedData.length; j++) {
31478                        if (selectedData[j] && selectedData[j].id === id) {
31479                            newData.push(selectedData[j]);
31480                            selectedData.shift(j);
31481                            break;
31482                        }
31483                    }
31484                });
31485                selectedData = newData.concat(selectedData); // Add remained
31486
31487                // Expand shapes for selection
31488                if (config.point_focus_expand_enabled) { $$.expandCircles(index); }
31489                $$.expandBars(index);
31490
31491                // Call event handler
31492                $$.main.selectAll('.' + CLASS.shape + '-' + index).each(function (d) {
31493                    config.data_onmouseover.call($$, d);
31494                });
31495            })
31496            .on('mouseout', function (d) {
31497                var index = d.index;
31498                if ($$.hasArcType()) { return; }
31499                $$.hideXGridFocus();
31500                $$.hideTooltip();
31501                // Undo expanded shapes
31502                $$.unexpandCircles(index);
31503                $$.unexpandBars();
31504                // Call event handler
31505                $$.main.selectAll('.' + CLASS.shape + '-' + index).each(function (d) {
31506                    config.data_onmouseout.call($$, d);
31507                });
31508            })
31509            .on('mousemove', function (d) {
31510                var selectedData, index = d.index,
31511                    eventRect = $$.svg.select('.' + CLASS.eventRect + '-' + index);
31512
31513                if ($$.dragging) { return; } // do nothing when dragging
31514                if ($$.hasArcType()) { return; }
31515
31516                // Show tooltip
31517                selectedData = $$.filterTargetsToShow($$.data.targets).map(function (t) {
31518                    return $$.addName($$.getValueOnIndex(t.values, index));
31519                });
31520
31521                if (config.tooltip_grouped) {
31522                    $$.showTooltip(selectedData, d3.mouse(this));
31523                    $$.showXGridFocus(selectedData);
31524                }
31525
31526                if (config.tooltip_grouped && (!config.data_selection_enabled || config.data_selection_grouped)) {
31527                    return;
31528                }
31529
31530                $$.main.selectAll('.' + CLASS.shape + '-' + index)
31531                    .each(function () {
31532                        d3.select(this).classed(CLASS.EXPANDED, true);
31533                        if (config.data_selection_enabled) {
31534                            eventRect.style('cursor', config.data_selection_grouped ? 'pointer' : null);
31535                        }
31536                        if (!config.tooltip_grouped) {
31537                            $$.hideXGridFocus();
31538                            $$.hideTooltip();
31539                            if (!config.data_selection_grouped) {
31540                                $$.unexpandCircles(index);
31541                                $$.unexpandBars();
31542                            }
31543                        }
31544                    })
31545                    .filter(function (d) {
31546                        if (this.nodeName === 'circle') {
31547                            return $$.isWithinCircle(this, $$.pointSelectR(d));
31548                        }
31549                        else if (this.nodeName === 'path') {
31550                            return $$.isWithinBar(this);
31551                        }
31552                    })
31553                    .each(function (d) {
31554                        if (config.data_selection_enabled && (config.data_selection_grouped || config.data_selection_isselectable(d))) {
31555                            eventRect.style('cursor', 'pointer');
31556                        }
31557                        if (!config.tooltip_grouped) {
31558                            $$.showTooltip([d], d3.mouse(this));
31559                            $$.showXGridFocus([d]);
31560                            if (config.point_focus_expand_enabled) { $$.expandCircles(index, d.id); }
31561                            $$.expandBars(index, d.id);
31562                        }
31563                    });
31564            })
31565            .on('click', function (d) {
31566                var index = d.index;
31567                if ($$.hasArcType() || !$$.toggleShape) { return; }
31568                if ($$.cancelClick) {
31569                    $$.cancelClick = false;
31570                    return;
31571                }
31572                $$.main.selectAll('.' + CLASS.shape + '-' + index).each(function (d) {
31573                    $$.toggleShape(this, d, index);
31574                });
31575            })
31576            .call(
31577                d3.behavior.drag().origin(Object)
31578                    .on('drag', function () { $$.drag(d3.mouse(this)); })
31579                    .on('dragstart', function () { $$.dragstart(d3.mouse(this)); })
31580                    .on('dragend', function () { $$.dragend(); })
31581            )
31582            .on("dblclick.zoom", null);
31583    };
31584
31585    c3_chart_internal_fn.generateEventRectsForMultipleXs = function (eventRectEnter) {
31586        var $$ = this, d3 = $$.d3, config = $$.config;
31587        eventRectEnter.append('rect')
31588            .attr('x', 0)
31589            .attr('y', 0)
31590            .attr('width', $$.width)
31591            .attr('height', $$.height)
31592            .attr('class', CLASS.eventRect)
31593            .on('mouseout', function () {
31594                if ($$.hasArcType()) { return; }
31595                $$.hideXGridFocus();
31596                $$.hideTooltip();
31597                $$.unexpandCircles();
31598            })
31599            .on('mousemove', function () {
31600                var targetsToShow = $$.filterTargetsToShow($$.data.targets);
31601                var mouse, closest, sameXData, selectedData;
31602
31603                if ($$.dragging) { return; } // do nothing when dragging
31604                if ($$.hasArcType(targetsToShow)) { return; }
31605
31606                mouse = d3.mouse(this);
31607                closest = $$.findClosestFromTargets(targetsToShow, mouse);
31608
31609                if (! closest) { return; }
31610
31611                if ($$.isScatterType(closest)) {
31612                    sameXData = [closest];
31613                } else {
31614                    sameXData = $$.filterSameX(targetsToShow, closest.x);
31615                }
31616
31617                // show tooltip when cursor is close to some point
31618                selectedData = sameXData.map(function (d) {
31619                    return $$.addName(d);
31620                });
31621                $$.showTooltip(selectedData, mouse);
31622
31623                // expand points
31624                if (config.point_focus_expand_enabled) {
31625                    $$.unexpandCircles();
31626                    $$.expandCircles(closest.index, closest.id);
31627                }
31628
31629                // Show xgrid focus line
31630                $$.showXGridFocus(selectedData);
31631
31632                // Show cursor as pointer if point is close to mouse position
31633                if ($$.dist(closest, mouse) < 100) {
31634                    $$.svg.select('.' + CLASS.eventRect).style('cursor', 'pointer');
31635                    if (!$$.mouseover) {
31636                        config.data_onmouseover.call($$, closest);
31637                        $$.mouseover = true;
31638                    }
31639                } else if ($$.mouseover) {
31640                    $$.svg.select('.' + CLASS.eventRect).style('cursor', null);
31641                    config.data_onmouseout.call($$, closest);
31642                    $$.mouseover = false;
31643                }
31644            })
31645            .on('click', function () {
31646                var targetsToShow = $$.filterTargetsToShow($$.data.targets);
31647                var mouse, closest;
31648
31649                if ($$.hasArcType(targetsToShow)) { return; }
31650
31651                mouse = d3.mouse(this);
31652                closest = $$.findClosestFromTargets(targetsToShow, mouse);
31653
31654                if (! closest) { return; }
31655
31656                // select if selection enabled
31657                if ($$.dist(closest, mouse) < 100 && $$.toggleShape) {
31658                    $$.main.select('.' + CLASS.circles + $$.getTargetSelectorSuffix(closest.id)).select('.' + CLASS.circle + '-' + closest.index).each(function () {
31659                        $$.toggleShape(this, closest, closest.index);
31660                    });
31661                }
31662            })
31663            .call(
31664                d3.behavior.drag().origin(Object)
31665                    .on('drag', function () { $$.drag(d3.mouse(this)); })
31666                    .on('dragstart', function () { $$.dragstart(d3.mouse(this)); })
31667                    .on('dragend', function () { $$.dragend(); })
31668            )
31669            .on("dblclick.zoom", null);
31670    };
31671
31672    c3_chart_internal_fn.getCurrentWidth = function () {
31673        var $$ = this, config = $$.config;
31674        return config.size_width ? config.size_width : $$.getParentWidth();
31675    };
31676    c3_chart_internal_fn.getCurrentHeight = function () {
31677        var $$ = this, config = $$.config,
31678            h = config.size_height ? config.size_height : $$.getParentHeight();
31679        return h > 0 ? h : 320;
31680    };
31681    c3_chart_internal_fn.getCurrentPaddingTop = function () {
31682        var config = this.config;
31683        return isValue(config.padding_top) ? config.padding_top : 0;
31684    };
31685    c3_chart_internal_fn.getCurrentPaddingBottom = function () {
31686        var config = this.config;
31687        return isValue(config.padding_bottom) ? config.padding_bottom : 0;
31688    };
31689    c3_chart_internal_fn.getCurrentPaddingLeft = function () {
31690        var $$ = this, config = $$.config;
31691        if (isValue(config.padding_left)) {
31692            return config.padding_left;
31693        } else if (config.axis_rotated) {
31694            return !config.axis_x_show ? 1 : Math.max(ceil10($$.getAxisWidthByAxisId('x')), 40);
31695        } else {
31696            return !config.axis_y_show ? 1 : ceil10($$.getAxisWidthByAxisId('y'));
31697        }
31698    };
31699    c3_chart_internal_fn.getCurrentPaddingRight = function () {
31700        var $$ = this, config = $$.config,
31701            defaultPadding = 10, legendWidthOnRight = $$.isLegendRight ? $$.getLegendWidth() + 20 : 0;
31702        if (isValue(config.padding_right)) {
31703            return config.padding_right + 1; // 1 is needed not to hide tick line
31704        } else if (config.axis_rotated) {
31705            return defaultPadding + legendWidthOnRight;
31706        } else {
31707            return (!config.axis_y2_show ? defaultPadding : ceil10($$.getAxisWidthByAxisId('y2'))) + legendWidthOnRight;
31708        }
31709    };
31710
31711    c3_chart_internal_fn.getParentRectValue = function (key) {
31712        var parent = this.selectChart.node(), v;
31713        while (parent && parent.tagName !== 'BODY') {
31714            v = parent.getBoundingClientRect()[key];
31715            if (v) {
31716                break;
31717            }
31718            parent = parent.parentNode;
31719        }
31720        return v;
31721    };
31722    c3_chart_internal_fn.getParentWidth = function () {
31723        return this.getParentRectValue('width');
31724    };
31725    c3_chart_internal_fn.getParentHeight = function () {
31726        var h = this.selectChart.style('height');
31727        return h.indexOf('px') >
31727 0 ? +h.replace('px', '') : 0;
31728    };
31729
31730
31731    c3_chart_internal_fn.getSvgLeft = function () {
31732        var $$ = this, config = $$.config,
31733            leftAxisClass = config.axis_rotated ? CLASS.axisX : CLASS.axisY,
31734            leftAxis = $$.main.select('.' + leftAxisClass).node(),
31735            svgRect = leftAxis ? leftAxis.getBoundingClientRect() : {right: 0},
31736            chartRect = $$.selectChart.node().getBoundingClientRect(),
31737            hasArc = $$.hasArcType(),
31738            svgLeft = svgRect.right - chartRect.left - (hasArc ? 0 : $$.getCurrentPaddingLeft());
31739        return svgLeft > 0 ? svgLeft : 0;
31740    };
31741
31742
31743    c3_chart_internal_fn.getAxisWidthByAxisId = function (id) {
31744        var $$ = this, position = $$.getAxisLabelPositionById(id);
31745        return position.isInner ? 20 + $$.getMaxTickWidth(id) : 40 + $$.getMaxTickWidth(id);
31746    };
31747    c3_chart_internal_fn.getHorizontalAxisHeight = function (axisId) {
31748        var $$ = this, config = $$.config;
31749        if (axisId === 'x' && !config.axis_x_show) { return 0; }
31750        if (axisId === 'x' && config.axis_x_height) { return config.axis_x_height; }
31751        if (axisId === 'y' && !config.axis_y_show) { return config.legend_show && !$$.isLegendRight && !$$.isLegendInset ? 10 : 1; }
31752        if (axisId === 'y2' && !config.axis_y2_show) { return $$.rotated_padding_top; }
31753        return ($$.getAxisLabelPositionById(axisId).isInner ? 30 : 40) + (axisId === 'y2' ? -10 : 0);
31754    };
31755
31756    c3_chart_internal_fn.getEventRectWidth = function () {
31757        var $$ = this;
31758        var target = $$.getMaxDataCountTarget($$.data.targets),
31759            firstData, lastData, base, maxDataCount, ratio, w;
31760        if (!target) {
31761            return 0;
31762        }
31763        firstData = target.values[0], lastData = target.values[target.values.length - 1];
31764        base = $$.x(lastData.x) - $$.x(firstData.x);
31765        if (base === 0) {
31766            return $$.config.axis_rotated ? $$.height : $$.width;
31767        }
31768        maxDataCount = $$.getMaxDataCount();
31769        ratio = ($$.hasType('bar') ? (maxDataCount - ($$.isCategorized() ? 0.25 : 1)) / maxDataCount : 1);
31770        w = maxDataCount > 1 ? (base * ratio) / (maxDataCount - 1) : base;
31771        return w < 1 ? 1 : w;
31772    };
31773
31774    c3_chart_internal_fn.getShapeIndices = function (typeFilter) {
31775        var $$ = this, config = $$.config,
31776            indices = {}, i = 0, j, k;
31777        $$.filterTargetsToShow($$.data.targets.filter(typeFilter, $$)).forEach(function (d) {
31778            for (j = 0; j < config.data_groups.length; j++) {
31779                if (config.data_groups[j].indexOf(d.id) < 0) { continue; }
31780                for (k = 0; k < config.data_groups[j].length; k++) {
31781                    if (config.data_groups[j][k] in indices) {
31782                        indices[d.id] = indices[config.data_groups[j][k]];
31783                        break;
31784                    }
31785                }
31786            }
31787            if (isUndefined(indices[d.id])) { indices[d.id] = i++; }
31788        });
31789        indices.__max__ = i - 1;
31790        return indices;
31791    };
31792    c3_chart_internal_fn.getShapeX = function (offset, targetsNum, indices, isSub) {
31793        var $$ = this, scale = isSub ? $$.subX : $$.x;
31794        return function (d) {
31795            var index = d.id in indices ? indices[d.id] : 0;
31796            return d.x || d.x === 0 ? scale(d.x) - offset * (targetsNum / 2 - index) : 0;
31797        };
31798    };
31799    c3_chart_internal_fn.getShapeY = function (isSub) {
31800        var $$ = this;
31801        return function (d) {
31802            var scale = isSub ? $$.getSubYScale(d.id) : $$.getYScale(d.id);
31803            return scale(d.value);
31804        };
31805    };
31806    c3_chart_internal_fn.getShapeOffset = function (typeFilter, indices, isSub) {
31807        var $$ = this,
31808            targets = $$.orderTargets($$.filterTargetsToShow($$.data.targets.filter(typeFilter, $$))),
31809            targetIds = targets.map(function (t) { return t.id; });
31810        return function (d, i) {
31811            var scale = isSub ? $$.getSubYScale(d.id) : $$.getYScale(d.id),
31812                y0 = scale(0), offset = y0;
31813            targets.forEach(function (t) {
31814                if (t.id === d.id || indices[t.id] !== indices[d.id]) { return; }
31815                if (targetIds.indexOf(t.id) < targetIds.indexOf(d.id) && t.values[i].value * d.value >= 0) {
31816                    offset += scale(t.values[i].value) - y0;
31817                }
31818            });
31819            return offset;
31820        };
31821    };
31822
31823    c3_chart_internal_fn.getInterpolate = function (d) {
31824        var $$ = this;
31825        return $$.isSplineType(d) ? "cardinal" : $$.isStepType(d) ? "step-after" : "linear";
31826    };
31827
31828    c3_chart_internal_fn.initLine = function () {
31829        var $$ = this;
31830        $$.main.select('.' + CLASS.chart).append("g")
31831            .attr("class", CLASS.chartLines);
31832    };
31833    c3_chart_internal_fn.updateTargetsForLine = function (targets) {
vendor: 14,068 bytes, lines 31834-32150
31834        var $$ = this, config = $$.config,
31835            mainLineUpdate, mainLineEnter,
31836            classChartLine = $$.classChartLine.bind($$),
31837            classLines = $$.classLines.bind($$),
31838            classAreas = $$.classAreas.bind($$),
31839            classCircles = $$.classCircles.bind($$);
31840        mainLineUpdate = $$.main.select('.' + CLASS.chartLines).selectAll('.' + CLASS.chartLine)
31841            .data(targets)
31842            .attr('class', classChartLine);
31843        mainLineEnter = mainLineUpdate.enter().append('g')
31844            .attr('class', classChartLine)
31845            .style('opacity', 0)
31846            .style("pointer-events", "none");
31847        // Lines for each data
31848        mainLineEnter.append('g')
31849            .attr("class", classLines);
31850        // Areas
31851        mainLineEnter.append('g')
31852            .attr('class', classAreas);
31853        // Circles for each data point on lines
31854        mainLineEnter.append('g')
31855            .attr("class", function (d) { return $$.generateClass(CLASS.selectedCircles, d.id); });
31856        mainLineEnter.append('g')
31857            .attr("class", classCircles)
31858            .style("cursor", function (d) { return config.data_selection_isselectable(d) ? "pointer" : null; });
31859        // Update date for selected circles
31860        targets.forEach(function (t) {
31861            $$.main.selectAll('.' + CLASS.selectedCircles + $$.getTargetSelectorSuffix(t.id)).selectAll('.' + CLASS.selectedCircle).each(function (d) {
31862                d.value = t.values[d.index].value;
31863            });
31864        });
31865        // MEMO: can not keep same color...
31866        //mainLineUpdate.exit().remove();
31867    };
31868    c3_chart_internal_fn.redrawLine = function (durationForExit) {
31869        var $$ = this;
31870        $$.mainLine = $$.main.selectAll('.' + CLASS.lines).selectAll('.' + CLASS.line)
31871            .data($$.lineData.bind($$));
31872        $$.mainLine.enter().append('path')
31873            .attr('class', $$.classLine.bind($$))
31874            .style("stroke", $$.color);
31875        $$.mainLine
31876            .style("opacity", $$.initialOpacity.bind($$))
31877            .attr('transform', null);
31878        $$.mainLine.exit().transition().duration(durationForExit)
31879            .style('opacity', 0)
31880            .remove();
31881    };
31882    c3_chart_internal_fn.addTransitionForLine = function (transitions, drawLine) {
31883        var $$ = this;
31884        transitions.push($$.mainLine.transition()
31885                         .attr("d", drawLine)
31886                         .style("stroke", $$.color)
31887                         .style("opacity", 1));
31888    };
31889    c3_chart_internal_fn.generateDrawLine = function (lineIndices, isSub) {
31890        var $$ = this, config = $$.config,
31891            line = $$.d3.svg.line(),
31892            getPoint = $$.generateGetLinePoint(lineIndices, isSub),
31893            yScaleGetter = isSub ? $$.getSubYScale : $$.getYScale,
31894            xValue = function (d) { return (isSub ? $$.subxx : $$.xx).call($$, d); },
31895            yValue = function (d, i) {
31896                return config.data_groups.length > 0 ? getPoint(d, i)[0][1] : yScaleGetter.call($$, d.id)(d.value);
31897            };
31898
31899        line = config.axis_rotated ? line.x(yValue).y(xValue) : line.x(xValue).y(yValue);
31900        if (!config.line_connect_null) { line = line.defined(function (d) { return d.value != null; }); }
31901        return function (d) {
31902            var data = config.line_connect_null ? $$.filterRemoveNull(d.values) : d.values,
31903                x = isSub ? $$.x : $$.subX, y = yScaleGetter.call($$, d.id), x0 = 0, y0 = 0, path;
31904            if ($$.isLineType(d)) {
31905                if (config.data_regions[d.id]) {
31906                    path = $$.lineWithRegions(data, x, y, config.data_regions[d.id]);
31907                } else {
31908                    path = line.interpolate($$.getInterpolate(d))(data);
31909                }
31910            } else {
31911                if (data[0]) {
31912                    x0 = x(data[0].x);
31913                    y0 = y(data[0].value);
31914                }
31915                path = config.axis_rotated ? "M " + y0 + " " + x0 : "M " + x0 + " " + y0;
31916            }
31917            return path ? path : "M 0 0";
31918        };
31919    };
31920    c3_chart_internal_fn.generateGetLinePoint = function (lineIndices, isSub) { // partial duplication of generateGetBarPoints
31921        var $$ = this, config = $$.config,
31922            lineTargetsNum = lineIndices.__max__ + 1,
31923            x = $$.getShapeX(0, lineTargetsNum, lineIndices, !!isSub),
31924            y = $$.getShapeY(!!isSub),
31925            lineOffset = $$.getShapeOffset($$.isLineType, lineIndices, !!isSub),
31926            yScale = isSub ? $$.getSubYScale : $$.getYScale;
31927        return function (d, i) {
31928            var y0 = yScale.call($$, d.id)(0),
31929                offset = lineOffset(d, i) || y0, // offset is for stacked area chart
31930                posX = x(d), posY = y(d);
31931            // fix posY not to overflow opposite quadrant
31932            if (config.axis_rotated) {
31933                if ((0 < d.value && posY < y0) || (d.value < 0 && y0 < posY)) { posY = y0; }
31934            }
31935            // 1 point that marks the line position
31936            return [
31937                [posX, posY - (y0 - offset)]
31938            ];
31939        };
31940    };
31941
31942
31943    c3_chart_internal_fn.lineWithRegions = function (d, x, y, _regions) {
31944        var $$ = this, config = $$.config,
31945            prev = -1, i, j,
31946            s = "M", sWithRegion,
31947            xp, yp, dx, dy, dd, diff, diffx2,
31948            xValue, yValue,
31949            regions = [];
31950
31951        function isWithinRegions(x, regions) {
31952            var i;
31953            for (i = 0; i < regions.length; i++) {
31954                if (regions[i].start < x && x <= regions[i].end) { return true; }
31955            }
31956            return false;
31957        }
31958
31959        // Check start/end of regions
31960        if (isDefined(_regions)) {
31961            for (i = 0; i < _regions.length; i++) {
31962                regions[i] = {};
31963                if (isUndefined(_regions[i].start)) {
31964                    regions[i].start = d[0].x;
31965                } else {
31966                    regions[i].start = $$.isTimeSeries() ? $$.parseDate(_regions[i].start) : _regions[i].start;
31967                }
31968                if (isUndefined(_regions[i].end)) {
31969                    regions[i].end = d[d.length - 1].x;
31970                } else {
31971                    regions[i].end = $$.isTimeSeries() ? $$.parseDate(_regions[i].end) : _regions[i].end;
31972                }
31973            }
31974        }
31975
31976        // Set scales
31977        xValue = config.axis_rotated ? function (d) { return y(d.value); } : function (d) { return x(d.x); };
31978        yValue = config.axis_rotated ? function (d) { return x(d.x); } : function (d) { return y(d.value); };
31979
31980        // Define svg generator function for region
31981        if ($$.isTimeSeries()) {
31982            sWithRegion = function (d0, d1, j, diff) {
31983                var x0 = d0.x.getTime(), x_diff = d1.x - d0.x,
31984                    xv0 = new Date(x0 + x_diff * j),
31985                    xv1 = new Date(x0 + x_diff * (j + diff));
31986                return "M" + x(xv0) + " " + y(yp(j)) + " " + x(xv1) + " " + y(yp(j + diff));
31987            };
31988        } else {
31989            sWithRegion = function (d0, d1, j, diff) {
31990                return "M" + x(xp(j), true) + " " + y(yp(j)) + " " + x(xp(j + diff), true) + " " + y(yp(j + diff));
31991            };
31992        }
31993
31994        // Generate
31995        for (i = 0; i < d.length; i++) {
31996
31997            // Draw as normal
31998            if (isUndefined(regions) || ! isWithinRegions(d[i].x, regions)) {
31999                s += " " + xValue(d[i]) + " " + yValue(d[i]);
32000            }
32001            // Draw with region // TODO: Fix for horizotal charts
32002            else {
32003                xp = $$.getScale(d[i - 1].x, d[i].x, $$.isTimeSeries());
32004                yp = $$.getScale(d[i - 1].value, d[i].value);
32005
32006                dx = x(d[i].x) - x(d[i - 1].x);
32007                dy = y(d[i].value) - y(d[i - 1].value);
32008                dd = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));
32009                diff = 2 / dd;
32010                diffx2 = diff * 2;
32011
32012                for (j = diff; j <= 1; j += diffx2) {
32013                    s += sWithRegion(d[i - 1], d[i], j, diff);
32014                }
32015            }
32016            prev = d[i].x;
32017        }
32018
32019        return s;
32020    };
32021
32022
32023    c3_chart_internal_fn.redrawArea = function (durationForExit) {
32024        var $$ = this, d3 = $$.d3;
32025        $$.mainArea = $$.main.selectAll('.' + CLASS.areas).selectAll('.' + CLASS.area)
32026            .data($$.lineData.bind($$));
32027        $$.mainArea.enter().append('path')
32028            .attr("class", $$.classArea.bind($$))
32029            .style("fill", $$.color)
32030            .style("opacity", function () { $$.orgAreaOpacity = +d3.select(this).style('opacity'); return 0; });
32031        $$.mainArea
32032            .style("opacity", $$.orgAreaOpacity);
32033        $$.mainArea.exit().transition().duration(durationForExit)
32034            .style('opacity', 0)
32035            .remove();
32036    };
32037    c3_chart_internal_fn.addTransitionForArea = function (transitions, drawArea) {
32038        var $$ = this;
32039        transitions.push($$.mainArea.transition()
32040                         .attr("d", drawArea)
32041                         .style("fill", $$.color)
32042                         .style("opacity", $$.orgAreaOpacity));
32043    };
32044    c3_chart_internal_fn.generateDrawArea = function (areaIndices, isSub) {
32045        var $$ = this, config = $$.config, area = $$.d3.svg.area(),
32046            getPoint = $$.generateGetAreaPoint(areaIndices, isSub),
32047            yScaleGetter = isSub ? $$.getSubYScale : $$.getYScale,
32048            xValue = function (d) { return (isSub ? $$.subxx : $$.xx).call($$, d); },
32049            value0 = function (d, i) {
32050                return config.data_groups.length > 0 ? getPoint(d, i)[0][1] : yScaleGetter.call($$, d.id)(0);
32051            },
32052            value1 = function (d, i) {
32053                return config.data_groups.length > 0 ? getPoint(d, i)[1][1] : yScaleGetter.call($$, d.id)(d.value);
32054            };
32055
32056        area = config.axis_rotated ? area.x0(value0).x1(value1).y(xValue) : area.x(xValue).y0(value0).y1(value1);
32057        if (!config.line_connect_null) {
32058            area = area.defined(function (d) { return d.value !== null; });
32059        }
32060
32061        return function (d) {
32062            var data = config.line_connect_null ? $$.filterRemoveNull(d.values) : d.values, x0 = 0, y0 = 0, path;
32063            if ($$.isAreaType(d)) {
32064                path = area.interpolate($$.getInterpolate(d))(data);
32065            } else {
32066                if (data[0]) {
32067                    x0 = $$.x(data[0].x);
32068                    y0 = $$.getYScale(d.id)(data[0].value);
32069                }
32070                path = config.axis_rotated ? "M " + y0 + " " + x0 : "M " + x0 + " " + y0;
32071            }
32072            return path ? path : "M 0 0";
32073        };
32074    };
32075
32076    c3_chart_internal_fn.generateGetAreaPoint = function (areaIndices, isSub) { // partial duplication of generateGetBarPoints
32077        var $$ = this, config = $$.config,
32078            areaTargetsNum = areaIndices.__max__ + 1,
32079            x = $$.getShapeX(0, areaTargetsNum, areaIndices, !!isSub),
32080            y = $$.getShapeY(!!isSub),
32081            areaOffset = $$.getShapeOffset($$.isAreaType, areaIndices, !!isSub),
32082            yScale = isSub ? $$.getSubYScale : $$.getYScale;
32083        return function (d, i) {
32084            var y0 = yScale.call($$, d.id)(0),
32085                offset = areaOffset(d, i) || y0, // offset is for stacked area chart
32086                posX = x(d), posY = y(d);
32087            // fix posY not to overflow opposite quadrant
32088            if (config.axis_rotated) {
32089                if ((0 < d.value && posY < y0) || (d.value < 0 && y0 < posY)) { posY = y0; }
32090            }
32091            // 1 point that marks the area position
32092            return [
32093                [posX, offset],
32094                [posX, posY - (y0 - offset)]
32095            ];
32096        };
32097    };
32098
32099
32100    c3_chart_internal_fn.redrawCircle = function () {
32101        var $$ = this;
32102        $$.mainCircle = $$.main.selectAll('.' + CLASS.circles).selectAll('.' + CLASS.circle)
32103            .data($$.lineOrScatterData.bind($$));
32104        $$.mainCircle.enter().append("circle")
32105            .attr("class", $$.classCircle.bind($$))
32106            .attr("r", $$.pointR.bind($$))
32107            .style("fill", $$.color);
32108        $$.mainCircle
32109            .style("opacity", $$.initialOpacity.bind($$));
32110        $$.mainCircle.exit().remove();
32111    };
32112    c3_chart_internal_fn.addTransitionForCircle = function (transitions, cx, cy) {
32113        var $$ = this;
32114        transitions.push($$.mainCircle.transition()
32115                         .style('opacity', $$.opacityForCircle.bind($$))
32116                         .style("fill", $$.color)
32117                         .attr("cx", cx)
32118                         .attr("cy", cy));
32119        transitions.push($$.main.selectAll('.' + CLASS.selectedCircle).transition()
32120                         .attr("cx", cx)
32121                         .attr("cy", cy));
32122    };
32123    c3_chart_internal_fn.circleX = function (d) {
32124        return d.x || d.x === 0 ? this.x(d.x) : null;
32125    };
32126    c3_chart_internal_fn.circleY = function (d, i) {
32127        var $$ = this,
32128            lineIndices = $$.getShapeIndices($$.isLineType), getPoint = $$.generateGetLinePoint(lineIndices);
32129        return $$.config.data_groups.length > 0 ? getPoint(d, i)[0][1] : $$.getYScale(d.id)(d.value);
32130    };
32131    c3_chart_internal_fn.getCircles = function (i, id) {
32132        var $$ = this;
32133        return (id ? $$.main.selectAll('.' + CLASS.circles + $$.getTargetSelectorSuffix(id)) : $$.main).selectAll('.' + CLASS.circle + (isValue(i) ? '-' + i : ''));
32134    };
32135    c3_chart_internal_fn.expandCircles = function (i, id) {
32136        var $$ = this,
32137            r = $$.pointExpandedR.bind($$);
32138        $$.getCircles(i, id)
32139            .classed(CLASS.EXPANDED, true)
32140            .attr('r', r);
32141    };
32142    c3_chart_internal_fn.unexpandCircles = function (i) {
32143        var $$ = this,
32144            r = $$.pointR.bind($$);
32145        $$.getCircles(i)
32146            .filter(function () { return $$.d3.select(this).classed(CLASS.EXPANDED); })
32147            .classed(CLASS.EXPANDED, false)
32148            .attr('r', r);
32149    };
32150    c3_chart_internal_fn.pointR = function (d) {
32151        var $$ = this, config = $$.config;
32152        return config.point_show && !$$.isStepType(d) ? (isFunction(config.point_r) ? config.point_r(d) : config.point_r) : 0;
32153    };
32154    c3_chart_internal_fn.pointExpandedR = function (d) {
32155        var $$ = this, config = $$.config;
32156        return config.point_focus_expand_enabled ? (config.point_focus_expand_r ? config.point_focus_expand_r : $$.pointR(d) * 1.75) : $$.pointR(d);
32157    };
32158    c3_chart_internal_fn.pointSelectR = function (d) {
32159        var $$ = this, config = $$.config;
32160        return config.point_select_r ? config.point_select_r : $$.pointR(d) * 4;
32161    };
32162    c3_chart_internal_fn.isWithinCircle = function (_this, _r) {
32163        var d3 = this.d3,
32164            mouse = d3.mouse(_this), d3_this = d3.select(_this),
32165            cx = d3_this.attr("cx") * 1, cy = d3_this.attr("cy") * 1;
32166        return Math.sqrt(Math.pow(cx - mouse[0], 2) + Math.pow(cy - mouse[1], 2)) < _r;
32167    };
32168
32169    c3_chart_internal_fn.initBar = function () {
32170        var $$ = this;
32171        $$.main.select('.' + CLASS.chart).append("g")
32172            .attr("class", CLASS.chartBars);
32173    };
32174    c3_chart_internal_fn.updateTargetsForBar = function (targets) {
32175        var $$ = this, config = $$.config,
32176            mainBarUpdate, mainBarEnter,
32177            classChartBar = $$.classChartBar.bind($$),
32178            classBars = $$.classBars.bind($$);
32179        mainBarUpdate = $$.main.select('.' + CLASS.chartBars).selectAll('.' + CLASS.chartBar)
32180            .data(targets)
32181            .attr('class', classChartBar);
32182        mainBarEnter = mainBarUpdate.enter().append('g')
32183            .attr('class', classChartBar)
32184            .style('opacity', 0)
32185            .style("pointer-events", "none");
32186        // Bars for each data
32187        mainBarEnter.append('g')
32188            .attr("class", classBars)
32189            .style("cursor", function (d) { return config.data_selection_isselectable(d) ? "pointer" : null; });
32190
32191    };
32192    c3_chart_internal_fn.redrawBar = function (durationForExit) {
32193        var $$ = this,
32194            barData = $$.barData.bind($$),
32195            classBar = $$.classBar.bind($$),
32196            initialOpacity = $$.initialOpacity.bind($$),
32197            color = function (d) { return $$.color(d.id); };
32198        $$.mainBar = $$.main.selectAll('.' + CLASS.bars).selectAll('.' + CLASS.bar)
32199            .data(barData);
32200        $$.mainBar.enter().append('path')
32201            .attr("class", classBar)
32202            .style("stroke", color)
32203            .style("fill", color);
32204        $$.mainBar
32205            .style("opacity", initialOpacity);
32206        $$.mainBar.exit().transition().duration(durationForExit)
32207            .style('opacity', 0)
32208            .remove();
32209    };
32210    c3_chart_internal_fn.addTransitionForBar = function (transitions, drawBar) {
32211        var $$ = this;
32212        transitions.push($$.mainBar.transition()
32213                         .attr('d', drawBar)
32214                         .style("fill", $$.color)
32215                         .style("opacity", 1));
32216    };
32217    c3_chart_internal_fn.getBarW = function (axis, barTargetsNum) {
32218        var $$ = this, config = $$.config,
32219            w = typeof config.bar_width === 'number' ? config.bar_width : barTargetsNum ? (axis.tickOffset() * 2 * config.bar_width_ratio) / barTargetsNum : 0;
32220        return config.bar_width_max && w > config.bar_width_max ? config.bar_width_max : w;
32221    };
32222    c3_chart_internal_fn.getBars = function (i) {
32223        var $$ = this;
32224        return $$.main.selectAll('.' + CLASS.bar + (isValue(i) ? '-' + i : ''));
32225    };
32226    c3_chart_internal_fn.expandBars = function (i) {
32227        var $$ = this;
32228        $$.getBars(i).classed(CLASS.EXPANDED, true);
32229    };
32230    c3_chart_internal_fn.unexpandBars = function (i) {
32231        var $$ = this;
32232        $$.getBars(i).classed(CLASS.EXPANDED, false);
32233    };
32234    c3_chart_internal_fn.generateDrawBar = function (barIndices, isSub) {
32235        var $$ = this, config = $$.config,
32236            getPoints = $$.generateGetBarPoints(barIndices, isSub);
32237        return function (d, i) {
32238            // 4 points that make a bar
32239            var points = getPoints(d, i);
32240
32241            // switch points if axis is rotated, not applicable for sub chart
32242            var indexX = config.axis_rotated ? 1 : 0;
32243            var indexY = config.axis_rotated ? 0 : 1;
32244
32245            var path = 'M ' + points[0][indexX] + ',' + points[0][indexY] + ' ' +
32246                    'L' + points[1][indexX] + ',' + points[1][indexY] + ' ' +
32247                    'L' + points[2][indexX] + ',' + points[2][indexY] + ' ' +
32248                    'L' + points[3][indexX] + ',' + points[3][indexY] + ' ' +
32249                    'z';
32250
32251            return path;
32252        };
32253    };
32254    c3_chart_internal_fn.generateGetBarPoints = function (barIndices, isSub) {
32255        var $$ = this,
32256            barTargetsNum = barIndices.__max__ + 1,
32257            barW = $$.getBarW($$.xAxis, barTargetsNum),
32258            barX = $$.getShapeX(barW, barTargetsNum, barIndices, !!isSub),
32259            barY = $$.getShapeY(!!isSub),
32260            barOffset = $$.getShapeOffset($$.isBarType, barIndices, !!isSub),
32261            yScale = isSub ? $$.getSubYScale : $$.getYScale;
32262        return function (d, i) {
32263            var y0 = yScale.call($$, d.id)(0),
32264                offset = barOffset(d, i) || y0, // offset is for stacked bar chart
32265                posX = barX(d), posY = barY(d);
32266            // fix posY not to overflow opposite quadrant
32267            if ($$.config.axis_rotated) {
32268                if ((0 < d.value && posY < y0) || (d.value < 0 && y0 < posY)) { posY = y0; }
32269            }
32270            // 4 points that make a bar
32271            return [
32272                [posX, offset],
32273                [posX, posY - (y0 - offset)],
32274                [posX + barW, posY - (y0 - offset)],
32275                [posX + barW, offset]
32276            ];
32277        };
32278    };
32279    c3_chart_internal_fn.isWithinBar = function (_this) {
32280        var d3 = this.d3,
32281            mouse = d3.mouse(_this), box = _this.getBoundingClientRect(),
32282            seg0 = _this.pathSegList.getItem(0), seg1 = _this.pathSegList.getItem(1),
32283            x = seg0.x, y = Math.min(seg0.y, seg1.y), w = box.width, h = box.height, offset = 2,
32284            sx = x - offset, ex = x + w + offset, sy = y + h + offset, ey = y - offset;
32285        return sx < mouse[0] && mouse[0] < ex && ey < mouse[1] && mouse[1] < sy;
32286    };
32287
32288    c3_chart_internal_fn.initText = function () {
32289        var $$ = this;
32290        $$.main.select('.' + CLASS.chart).append("g")
32291            .attr("class", CLASS.chartTexts);
32292        $$.mainText = $$.d3.selectAll([]);
32293    };
32294    c3_chart_internal_fn.updateTargetsForText = function (targets) {
32295        var $$ = this, mainTextUpdate, mainTextEnter,
32296            classChartText = $$.classChartText.bind($$),
32297            classTexts = $$.classTexts.bind($$);
32298        mainTextUpdate = $$.main.select('.' + CLASS.chartTexts).selectAll('.' + CLASS.chartText)
32299            .data(targets)
32300            .attr('class', classChartText);
32301        mainTextEnter = mainTextUpdate.enter().append('g')
32302            .attr('class', classChartText)
32303            .style('opacity', 0)
32304            .style("pointer-events", "none");
32305        mainTextEnter.append('g')
32306            .attr('class', classTexts);
32307    };
32308    c3_chart_internal_fn.redrawText = function (durationForExit) {
32309        var $$ = this, config = $$.config,
32310            barOrLineData = $$.barOrLineData.bind($$),
32311            classText = $$.classText.bind($$);
32312        $$.mainText = $$.main.selectAll('.' + CLASS.texts).selectAll('.' + CLASS.text)
32313            .data(barOrLineData);
32314        $$.mainText.enter().append('text')
32315            .attr("class", classText)
32316            .attr('text-anchor', function (d) { return config.axis_rotated ? (d.value < 0 ? 'end' : 'start') : 'middle'; })
32317            .style("stroke", 'none')
32318            .style("fill", function (d) { return $$.color(d); })
32319            .style("fill-opacity", 0);
32320        $$.mainText
32321            .text(function (d) { return $$.formatByAxisId($$.getAxisId(d.id))(d.value, d.id); });
32322        $$.mainText.exit()
32323            .transition().duration(durationForExit)
32324            .style('fill-opacity', 0)
32325            .remove();
32326    };
32327    c3_chart_internal_fn.addTransitionForText = function (transitions, xForText, yForText, forFlow) {
32328        var $$ = this,
32329            opacityForText = forFlow ? 0 : $$.opacityForText.bind($$);
32330        transitions.push($$.mainText.transition()
32331                         .attr('x', xForText)
32332                         .attr('y', yForText)
32333                         .style("fill", $$.color)
32334                         .style("fill-opacity", opacityForText));
32335    };
32336    c3_chart_internal_fn.getTextRect = function (text, cls) {
32337        var rect;
32338        this.d3.select('body').selectAll('.dummy')
32339            .data([text])
32340          .enter().append('text')
32341            .classed(cls ? cls : "", true)
32342            .text(text)
32343          .each(function () { rect = this.getBoundingClientRect(); })
32344            .remove();
32345        return rect;
32346    };
32347    c3_chart_internal_fn.generateXYForText = function (barIndices, forX) {
32348        var $$ = this,
32349            getPoints = $$.generateGetBarPoints(barIndices, false),
32350            getter = forX ? $$.getXForText : $$.getYForText;
32351        return function (d, i) {
32352            return getter.call($$, getPoints(d, i), d, this);
32353        };
32354    };
32355    c3_chart_internal_fn.getXForText = function (points, d, textElement) {
32356        var $$ = this,
32357            box = textElement.getBoundingClientRect(), xPos, padding;
32358        if ($$.config.axis_rotated) {
32359            padding = $$.isBarType(d) ? 4 : 6;
32360            xPos = points[2][1] + padding * (d.value < 0 ? -1 : 1);
32361        } else {
32362            xPos = $$.hasType('bar') ? (points[2][0] + points[0][0]) / 2 : points[0][0];
32363        }
32364        return xPos > $$.width ? $$.width - box.width : xPos;
32365    };
32366    c3_chart_internal_fn.getYForText = function (points, d, textElement) {
32367        var $$ = this,
32368            box = textElement.getBoundingClientRect(), yPos;
32369        if ($$.config.axis_rotated) {
32370            yPos = (points[0][0] + points[2][0] + box.height * 0.6) / 2;
32371        } else {
32372            yPos = points[2][1] + (d.value < 0 ? box.height : $$.isBarType(d) ? -3 : -6);
32373        }
32374        return yPos < box.height ? box.height : yPos;
32375    };
32376
32377    c3_chart_internal_fn.setTargetType = function (targetIds, type) {
32378        var $$ = this, config = $$.config;
32379        $$.mapToTargetIds(targetIds).forEach(function (id) {
32380            $$.withoutFadeIn[id] = (type === config.data_types[id]);
32381            config.data_types[id] = type;
32382        });
32383        if (!targetIds) {
32384            config.data_type = type;
32385        }
32386    };
32387    c3_chart_internal_fn.hasType = function (type, targets) {
32388        var $$ = this, types = $$.config.data_types, has = false;
32389        (targets || $$.data.targets).forEach(function (t) {
32390            if ((types[t.id] && types[t.id].indexOf(type) >= 0) || (!(t.id in types) && type === 'line')) {
32391                has = true;
32392            }
32393        });
32394        return has;
32395    };
32396    c3_chart_internal_fn.hasArcType = function (targets) {
32397        return this.hasType('pie', targets) || this.hasType('donut', targets) || this.hasType('gauge', targets);
32398    };
32399    c3_chart_internal_fn.isLineType = function (d) {
32400        var config = this.config, id = isString(d) ? d : d.id;
32401        return !config.data_types[id] || ['line', 'spline', 'area', 'area-spline', 'step', 'area-step'].indexOf(config.data_types[id]) >= 0;
32402    };
32403    c3_chart_internal_fn.isStepType = function (d) {
32404        var id = isString(d) ? d : d.id;
32405        return ['step', 'area-step'].indexOf(this.config.data_types[id]) >= 0;
32406    };
32407    c3_chart_internal_fn.isSplineType = function (d) {
32408        var id = isString(d) ? d : d.id;
32409        return ['spline', 'area-spline'].indexOf(this.config.data_types[id]) >= 0;
32410    };
32411    c3_chart_internal_fn.isAreaType = function (d) {
32412        var id = isString(d) ? d : d.id;
32413        return ['area', 'area-spline', 'area-step'].indexOf(this.config.data_types[id]) >= 0;
32414    };
32415    c3_chart_internal_fn.isBarType = function (d) {
32416        var id = isString(d) ? d : d.id;
32417        return this.config.data_types[id] === 'bar';
32418    };
32419    c3_chart_internal_fn.isScatterType = function (d) {
32420        var id = isString(d) ? d : d.id;
32421        return this.config.data_types[id] === 'scatter';
32422    };
32423    c3_chart_internal_fn.isPieType = function (d) {
32424        var id = isString(d) ? d : d.id;
32425        return this.config.data_types[id] === 'pie';
32426    };
32427    c3_chart_internal_fn.isGaugeType = function (d) {
32428        var id = isString(d) ? d : d.id;
32429        return this.config.data_types[id] === 'gauge';
32430    };
32431    c3_chart_internal_fn.isDonutType = function (d) {
32432        var id = isString(d) ? d : d.id;
32433        return this.config.data_types[id] === 'donut';
32434    };
32435    c3_chart_internal_fn.isArcType = function (d) {
32436        return this.isPieType(d) || this.isDonutType(d) || this.isGaugeType(d);
32437    };
32438    c3_chart_internal_fn.lineData = function (d) {
32439        return this.isLineType(d) ? [d] : [];
32440    };
32441    c3_chart_internal_fn.arcData = function (d) {
32442        return this.isArcType(d.data) ? [d] : [];
32443    };
32444    /* not used
32445     function scatterData(d) {
32446     return isScatterType(d) ? d.values : [];
32447     }
32448     */
32449    c3_chart_internal_fn.barData = function (d) {
32450        return this.isBarType(d) ? d.values : [];
32451    };
32452    c3_chart_internal_fn.lineOrScatterData = function (d) {
32453        return this.isLineType(d) || this.isScatterType(d) ? d.values : [];
32454    };
32455    c3_chart_internal_fn.barOrLineData = function (d) {
32456        return this.isBarType(d) || this.isLineType(d) ? d.values : [];
32457    };
32458
32459    c3_chart_internal_fn.initGrid = function () {
32460        var $$ = this, config = $$.config, d3 = $$.d3;
32461        $$.grid = $$.main.append('g')
32462            .attr("clip-path", $$.clipPath)
32463            .attr('class', CLASS.grid);
32464        if (config.grid_x_show) {
32465            $$.grid.append("g").attr("class", CLASS.xgrids);
32466        }
32467        if (config.grid_y_show) {
32468            $$.grid.append('g').attr('class', CLASS.ygrids);
32469        }
32470        $$.grid.append('g').attr("class", CLASS.xgridLines);
32471        $$.grid.append('g').attr('class', CLASS.ygridLines);
32472        if (config.grid_focus_show) {
32473            $$.grid.append('g')
32474                .attr("class", CLASS.xgridFocus)
32475                .append('line')
32476                .attr('class', CLASS.xgridFocus);
32477        }
32478        $$.xgrid = d3.selectAll([]);
32479        $$.xgridLines = d3.selectAll([]);
32480    };
32481
32482    c3_chart_internal_fn.updateXGrid = function (withoutUpdate) {
32483        var $$ = this, config = $$.config, d3 = $$.d3,
32484            xgridData = $$.generateGridData(config.grid_x_type, $$.x),
32485            tickOffset = $$.isCategorized() ? $$.xAxis.tickOffset() : 0;
32486
32487        $$.xgridAttr = config.axis_rotated ? {
32488            'x1': 0,
32489            'x2': $$.width,
32490            'y1': function (d) { return $$.x(d) - tickOffset; },
32491            'y2': function (d) { return $$.x(d) - tickOffset; }
32492        } : {
32493            'x1': function (d) { return $$.x(d) + tickOffset; },
32494            'x2': function (d) { return $$.x(d) + tickOffset; },
32495            'y1': 0,
32496            'y2': $$.height
32497        };
32498
32499        $$.xgrid = $$.main.select('.' + CLASS.xgrids).selectAll('.' + CLASS.xgrid)
32500            .data(xgridData);
32501        $$.xgrid.enter().append('line').attr("class", CLASS.xgrid);
32502        if (!withoutUpdate) {
32503            $$.xgrid.attr($$.xgridAttr)
32504                .style("opacity", function () { return +d3.select(this).attr(config.axis_rotated ? 'y1' : 'x1') === (config.axis_rotated ? $$.height : 0) ? 0 : 1; });
32505        }
32506        $$.xgrid.exit().remove();
32507    };
32508
32509    c3_chart_internal_fn.updateYGrid = function () {
32510        var $$ = this, config = $$.config;
32511        $$.ygrid = $$.main.select('.' + CLASS.ygrids).selectAll('.' + CLASS.ygrid)
32512            .data($$.y.ticks(config.grid_y_ticks));
32513        $$.ygrid.enter().append('line')
32514            .attr('class', CLASS.ygrid);
32515        $$.ygrid.attr("x1", config.axis_rotated ? $$.y : 0)
32516            .attr("x2", config.axis_rotated ? $$.y : $$.width)
32517            .attr("y1", config.axis_rotated ? 0 : $$.y)
32518            .attr("y2", config.axis_rotated ? $$.height : $$.y);
32519        $$.ygrid.exit().remove();
32520        $$.smoothLines($$.ygrid, 'grid');
32521    };
32522
32523
32524    c3_chart_internal_fn.redrawGrid = function (duration, withY) {
32525        var $$ = this, main = $$.main, config = $$.config,
32526            xgridLine, ygridLine, yv;
32527        main.select('line.' + CLASS.xgridFocus).style("visibility", "hidden");
32528        if (config.grid_x_show) {
32529            $$.updateXGrid();
32530        }
32531        $$.xgridLines = main.select('.' + CLASS.xgridLines).selectAll('.' + CLASS.xgridLine)
32532            .data(config.grid_x_lines);
32533        // enter
32534        xgridLine = $$.xgridLines.enter().append('g')
32535            .attr("class", function (d) { return CLASS.xgridLine + (d.class ? ' ' + d.class : ''); });
32536        xgridLine.append('line')
32537            .style("opacity", 0);
32538        xgridLine.append('text')
32539            .attr("text-anchor", "end")
32540            .attr("transform", config.axis_rotated ? "" : "rotate(-90)")
32541            .attr('dx', config.axis_rotated ? 0 : -$$.margin.top)
32542            .attr('dy', -5)
32543            .style("opacity", 0);
32544        // udpate
32545        // done in d3.transition() of the end of this function
32546        // exit
32547        $$.xgridLines.exit().transition().duration(duration)
32548            .style("opacity", 0)
32549            .remove();
32550
32551        // Y-Grid
32552        if (withY && config.grid_y_show) {
32553            $$.updateYGrid();
32554        }
32555        if (withY) {
32556            $$.ygridLines = main.select('.' + CLASS.ygridLines).selectAll('.' + CLASS.ygridLine)
32557                .data(config.grid_y_lines);
32558            // enter
vendor: 4,461 bytes, lines 32559-32651
32559            ygridLine = $$.ygridLines.enter().append('g')
32560                .attr("class", function (d) { return CLASS.ygridLine + (d.class ? ' ' + d.class : ''); });
32561            ygridLine.append('line')
32562                .style("opacity", 0);
32563            ygridLine.append('text')
32564                .attr("text-anchor", "end")
32565                .attr("transform", config.axis_rotated ? "rotate(-90)" : "")
32566                .attr('dx', config.axis_rotated ? 0 : -$$.margin.top)
32567                .attr('dy', -5)
32568                .style("opacity", 0);
32569            // update
32570            yv = $$.yv.bind($$);
32571            $$.ygridLines.select('line')
32572              .transition().duration(duration)
32573                .attr("x1", config.axis_rotated ? yv : 0)
32574                .attr("x2", config.axis_rotated ? yv : $$.width)
32575                .attr("y1", config.axis_rotated ? 0 : yv)
32576                .attr("y2", config.axis_rotated ? $$.height : yv)
32577                .style("opacity", 1);
32578            $$.ygridLines.select('text')
32579              .transition().duration(duration)
32580                .attr("x", config.axis_rotated ? 0 : $$.width)
32581                .attr("y", yv)
32582                .text(function (d) { return d.text; })
32583                .style("opacity", 1);
32584            // exit
32585            $$.ygridLines.exit().transition().duration(duration)
32586                .style("opacity", 0)
32587                .remove();
32588        }
32589    };
32590    c3_chart_internal_fn.addTransitionForGrid = function (transitions) {
32591        var $$ = this, config = $$.config, xv = $$.xv.bind($$);
32592        transitions.push($$.xgridLines.select('line').transition()
32593                         .attr("x1", config.axis_rotated ? 0 : xv)
32594                         .attr("x2", config.axis_rotated ? $$.width : xv)
32595                         .attr("y1", config.axis_rotated ? xv : $$.margin.top)
32596                         .attr("y2", config.axis_rotated ? xv : $$.height)
32597                         .style("opacity", 1));
32598        transitions.push($$.xgridLines.select('text').transition()
32599                         .attr("x", config.axis_rotated ? $$.width : 0)
32600                         .attr("y", xv)
32601                         .text(function (d) { return d.text; })
32602                         .style("opacity", 1));
32603    };
32604    c3_chart_internal_fn.showXGridFocus = function (selectedData) {
32605        var $$ = this, config = $$.config,
32606            dataToShow = selectedData.filter(function (d) { return d && isValue(d.value); }),
32607            focusEl = $$.main.selectAll('line.' + CLASS.xgridFocus),
32608            xx = $$.xx.bind($$);
32609        if (! config.tooltip_show) { return; }
32610        // Hide when scatter plot exists
32611        if ($$.hasType('scatter') || $$.hasArcType()) { return; }
32612        focusEl
32613            .style("visibility", "visible")
32614            .data([dataToShow[0]])
32615            .attr(config.axis_rotated ? 'y1' : 'x1', xx)
32616            .attr(config.axis_rotated ? 'y2' : 'x2', xx);
32617        $$.smoothLines(focusEl, 'grid');
32618    };
32619    c3_chart_internal_fn.hideXGridFocus = function () {
32620        this.main.select('line.' + CLASS.xgridFocus).style("visibility", "hidden");
32621    };
32622    c3_chart_internal_fn.updateXgridFocus = function () {
32623        var $$ = this, config = $$.config;
32624        $$.main.select('line.' + CLASS.xgridFocus)
32625            .attr("x1", config.axis_rotated ? 0 : -10)
32626            .attr("x2", config.axis_rotated ? $$.width : -10)
32627            .attr("y1", config.axis_rotated ? -10 : 0)
32628            .attr("y2", config.axis_rotated ? -10 : $$.height);
32629    };
32630    c3_chart_internal_fn.generateGridData = function (type, scale) {
32631        var $$ = this,
32632            gridData = [], xDomain, firstYear, lastYear, i,
32633            tickNum = $$.main.select("." + CLASS.axisX).selectAll('.tick').size();
32634        if (type === 'year') {
32635            xDomain = $$.getXDomain();
32636            firstYear = xDomain[0].getFullYear();
32637            lastYear = xDomain[1].getFullYear();
32638            for (i = firstYear; i <= lastYear; i++) {
32639                gridData.push(new Date(i + '-01-01 00:00:00'));
32640            }
32641        } else {
32642            gridData = scale.ticks(10);
32643            if (gridData.length > tickNum) { // use only int
32644                gridData = gridData.filter(function (d) { return ("" + d).indexOf('.') < 0; });
32645            }
32646        }
32647        return gridData;
32648    };
32649    c3_chart_internal_fn.getGridFilterToRemove = function (params) {
32650        return params ? function (line) {
32651            var found = false;
32652            [].concat(params).forEach(function (param) {
32653                if ((('value' in param && line.value === params.value) || ('class' in param && line.class === params.class))) {
32654                    found = true;
32655                }
32656            });
32657            return found;
32658        } : function () { return true; };
32659    };
32660    c3_chart_internal_fn.removeGridLines = function (params, forX) {
32661        var $$ = this, config = $$.config,
32662            toRemove = $$.getGridFilterToRemove(params),
32663            toShow = function (line) { return !toRemove(line); },
32664            classLines = forX ? CLASS.xgridLines : CLASS.ygridLines,
32665            classLine = forX ? CLASS.xgridLine : CLASS.ygridLine;
32666        $$.main.select('.' + classLines).selectAll('.' + classLine).filter(toRemove)
32667            .transition().duration(config.transition_duration)
32668            .style('opacity', 0).remove();
32669        if (forX) {
32670            config.grid_x_lines = config.grid_x_lines.filter(toShow);
32671        } else {
32672            config.grid_y_lines = config.grid_y_lines.filter(toShow);
32673        }
32674    };
32675
32676    c3_chart_internal_fn.initTooltip = function () {
32677        var $$ = this, config = $$.config, i;
32678        $$.tooltip = $$.selectChart
32679            .style("position", "relative")
32680            .append("div")
32681            .style("position", "absolute")
32682            .style("pointer-events", "none")
32683            .style("z-index", "10")
32684            .style("display", "none");
32685        // Show tooltip if needed
32686        if (config.tooltip_init_show) {
32687            if ($$.isTimeSeries() && isString(config.tooltip_init_x)) {
32688                config.tooltip_init_x = $$.parseDate(config.tooltip_init_x);
32689                for (i = 0; i < $$.data.targets[0].values.length; i++) {
32690                    if (($$.data.targets[0].values[i].x - config.tooltip_init_x) === 0) { break; }
32691                }
32692                config.tooltip_init_x = i;
32693            }
32694            $$.tooltip.html(config.tooltip_contents.call($$, $$.data.targets.map(function (d) {
32695                return $$.addName(d.values[config.tooltip_init_x]);
32696            }), $$.getXAxisTickFormat(), $$.getYFormat($$.hasArcType()), $$.color));
32697            $$.tooltip.style("top", config.tooltip_init_position.top)
32698                .style("left", config.tooltip_init_position.left)
32699                .style("display", "block");
32700        }
32701    };
32702    c3_chart_internal_fn.getTooltipContent = function (d, defaultTitleFormat, defaultValueFormat, color) {
32703        var $$ = this, config = $$.config,
32704            titleFormat = config.tooltip_format_title || defaultTitleFormat,
32705            nameFormat = config.tooltip_format_name || function (name) { return name; },
32706            valueFormat = config.tooltip_format_value || defaultValueFormat,
32707            text, i, title, value, name, bgcolor;
32708        for (i = 0; i < d.length; i++) {
32709            if (! (d[i] && (d[i].value || d[i].value === 0))) { continue; }
32710
32711            if (! text) {
32712                title = titleFormat ? titleFormat(d[i].x) : d[i].x;
32713                text = "<table class='" + CLASS.tooltip + "'>" + (title || title === 0 ? "<tr><th colspan='2'>" + title + "</th></tr>" : "");
32714            }
32715
32716            name = nameFormat(d[i].name);
32717            value = valueFormat(d[i].value, d[i].ratio, d[i].id, d[i].index);
32718            bgcolor = $$.levelColor ? $$.levelColor(d[i].value) : color(d[i].id);
32719
32720            text += "<tr class='" + CLASS.tooltipName + "-" + d[i].id + "'>";
32721            text += "<td class='name'><span style='background-color:" + bgcolor + "'></span>" + name + "</td>";
32722            text += "<td class='value'>" + value + "</td>";
32723            text += "</tr>";
32724        }
32725        return text + "</table>";
32726    };
32727    c3_chart_internal_fn.showTooltip = function (selectedData, mouse) {
32728        var $$ = this, config = $$.config;
32729        var tWidth, tHeight, svgLeft, tooltipLeft, tooltipRight, tooltipTop, chartRight;
32730        var forArc = $$.hasArcType(),
32731            dataToShow = selectedData.filter(function (d) { return d && isValue(d.value); });
32732        if (dataToShow.length === 0 || !config.tooltip_show) {
32733            return;
32734        }
32735        $$.tooltip.html(config.tooltip_contents.call($$, selectedData, $$.getXAxisTickFormat(), $$.getYFormat(forArc), $$.color)).style("display", "block");
32736
32737        // Get tooltip dimensions
32738        tWidth = $$.tooltip.property('offsetWidth');
32739        tHeight = $$.tooltip.property('offsetHeight');
32740        // Determin tooltip position
32741        if (forArc) {
32742            tooltipLeft = ($$.width / 2) + mouse[0];
32743            tooltipTop = ($$.height / 2) + mouse[1] + 20;
32744        } else {
32745            if (config.axis_rotated) {
32746                svgLeft = $$.getSvgLeft();
32747                tooltipLeft = svgLeft + mouse[0] + 100;
32748                tooltipRight = tooltipLeft + tWidth;
32749                chartRight = $$.getCurrentWidth() - $$.getCurrentPaddingRight();
32750                tooltipTop = $$.x(dataToShow[0].x) + 20;
32751            } else {
32752                svgLeft = $$.getSvgLeft();
32753                tooltipLeft = svgLeft + $$.getCurrentPaddingLeft() + $$.x(dataToShow[0].x) + 20;
32754                tooltipRight = tooltipLeft + tWidth;
32755                chartRight = svgLeft + $$.getCurrentWidth() - $$.getCurrentPaddingRight();
32756                tooltipTop = mouse[1] + 15;
32757            }
32758
32759            if (tooltipRight > chartRight) {
32760                tooltipLeft -= tooltipRight - chartRight;
32761            }
32762            if (tooltipTop + tHeight > $$.getCurrentHeight() && tooltipTop > tHeight + 30) {
32763                tooltipTop -= tHeight + 30;
32764            }
32765        }
32766        // Set tooltip
32767        $$.tooltip
32768            .style("top", tooltipTop + "px")
32769            .style("left", tooltipLeft + 'px');
32770    };
32771    c3_chart_internal_fn.hideTooltip = function () {
32772        this.tooltip.style("display", "none");
32773    };
32774
32775    c3_chart_internal_fn.initLegend = function () {
32776        var $$ = this;
32777        $$.legend = $$.svg.append("g").attr("transform", $$.getTranslate('legend'));
32778        if (!$$.config.legend_show) {
32779            $$.legend.style('visibility', 'hidden');
32780            $$.hiddenLegendIds = $$.mapToIds($$.data.targets);
32781        }
32782        // MEMO: call here to update legend box and tranlate for all
32783        // MEMO: translate will be upated by this, so transform not needed in updateLegend()
32784        $$.updateLegend($$.mapToIds($$.data.targets), {withTransform: false, withTransitionForTransform: false, withTransition: false});
32785    };
32786    c3_chart_internal_fn.updateSizeForLegend = function (legendHeight, legendWidth) {
vendor: 15,326 bytes, lines 32787-33111
32787        var $$ = this, config = $$.config, insetLegendPosition = {
32788            top: $$.isLegendTop ? $$.getCurrentPaddingTop() + config.legend_inset_y + 5.5 : $$.currentHeight - legendHeight - $$.getCurrentPaddingBottom() - config.legend_inset_y,
32789            left: $$.isLegendLeft ? $$.getCurrentPaddingLeft() + config.legend_inset_x + 0.5 : $$.currentWidth - legendWidth - $$.getCurrentPaddingRight() - config.legend_inset_x + 0.5
32790        };
32791        $$.margin3 = {
32792            top: $$.isLegendRight ? 0 : $$.isLegendInset ? insetLegendPosition.top : $$.currentHeight - legendHeight,
32793            right: NaN,
32794            bottom: 0,
32795            left: $$.isLegendRight ? $$.currentWidth - legendWidth : $$.isLegendInset ? insetLegendPosition.left : 0
32796        };
32797    };
32798    c3_chart_internal_fn.transformLegend = function (withTransition) {
32799        var $$ = this;
32800        (withTransition ? $$.legend.transition() : $$.legend).attr("transform", $$.getTranslate('legend'));
32801    };
32802    c3_chart_internal_fn.updateLegendStep = function (step) {
32803        this.legendStep = step;
32804    };
32805    c3_chart_internal_fn.updateLegendItemWidth = function (w) {
32806        this.legendItemWidth = w;
32807    };
32808    c3_chart_internal_fn.updateLegendItemHeight = function (h) {
32809        this.legendItemHeight = h;
32810    };
32811    c3_chart_internal_fn.getLegendWidth = function () {
32812        var $$ = this;
32813        return $$.config.legend_show ? $$.isLegendRight || $$.isLegendInset ? $$.legendItemWidth * ($$.legendStep + 1) : $$.currentWidth : 0;
32814    };
32815    c3_chart_internal_fn.getLegendHeight = function () {
32816        var $$ = this, config = $$.config, h = 0;
32817        if (config.legend_show) {
32818            if ($$.isLegendRight) {
32819                h = $$.currentHeight;
32820            } else if ($$.isLegendInset) {
32821                h = config.legend_inset_step ? Math.max(20, $$.legendItemHeight) * (config.legend_inset_step + 1) : $$.height;
32822            } else {
32823                h = Math.max(20, $$.legendItemHeight) * ($$.legendStep + 1);
32824            }
32825        }
32826        return h;
32827    };
32828    c3_chart_internal_fn.opacityForLegend = function (legendItem) {
32829        var $$ = this;
32830        return legendItem.classed(CLASS.legendItemHidden) ? $$.legendOpacityForHidden : 1;
32831    };
32832    c3_chart_internal_fn.opacityForUnfocusedLegend = function (legendItem) {
32833        var $$ = this;
32834        return legendItem.classed(CLASS.legendItemHidden) ? $$.legendOpacityForHidden : 0.3;
32835    };
32836    c3_chart_internal_fn.toggleFocusLegend = function (id, focus) {
32837        var $$ = this;
32838        $$.legend.selectAll('.' + CLASS.legendItem)
32839            .transition().duration(100)
32840            .style('opacity', function (_id) {
32841                var This = $$.d3.select(this);
32842                if (id && _id !== id) {
32843                    return focus ? $$.opacityForUnfocusedLegend(This) : $$.opacityForLegend(This);
32844                } else {
32845                    return focus ? $$.opacityForLegend(This) : $$.opacityForUnfocusedLegend(This);
32846                }
32847            });
32848    };
32849    c3_chart_internal_fn.revertLegend = function () {
32850        var $$ = this, d3 = $$.d3;
32851        $$.legend.selectAll('.' + CLASS.legendItem)
32852            .transition().duration(100)
32853            .style('opacity', function () { return $$.opacityForLegend(d3.select(this)); });
32854    };
32855    c3_chart_internal_fn.showLegend = function (targetIds) {
32856        var $$ = this, config = $$.config;
32857        if (!config.legend_show) {
32858            config.legend_show = true;
32859            $$.legend.style('visibility', 'visible');
32860        }
32861        $$.removeHiddenLegendIds(targetIds);
32862        $$.legend.selectAll($$.selectorLegends(targetIds))
32863            .style('visibility', 'visible')
32864            .transition()
32865            .style('opacity', function () { return $$.opacityForLegend($$.d3.select(this)); });
32866    };
32867    c3_chart_internal_fn.hideLegend = function (targetIds) {
32868        var $$ = this, config = $$.config;
32869        if (config.legend_show && isEmpty(targetIds)) {
32870            config.legend_show = false;
32871            $$.legend.style('visibility', 'hidden');
32872        }
32873        $$.addHiddenLegendIds(targetIds);
32874        $$.legend.selectAll($$.selectorLegends(targetIds))
32875            .style('opacity', 0)
32876            .style('visibility', 'hidden');
32877    };
32878    c3_chart_internal_fn.updateLegend = function (targetIds, options, transitions) {
32879        var $$ = this, config = $$.config;
32880        var xForLegend, xForLegendText, xForLegendRect, yForLegend, yForLegendText, yForLegendRect;
32881        var paddingTop = 4, paddingRight = 36, maxWidth = 0, maxHeight = 0, posMin = 10;
32882        var l, totalLength = 0, offsets = {}, widths = {}, heights = {}, margins = [0], steps = {}, step = 0;
32883        var withTransition, withTransitionForTransform;
32884        var hasFocused = $$.legend.selectAll('.' + CLASS.legendItemFocused).size();
32885        var texts, rects, tiles;
32886
32887        options = options || {};
32888        withTransition = getOption(options, "withTransition", true);
32889        withTransitionForTransform = getOption(options, "withTransitionForTransform", true);
32890
32891        function updatePositions(textElement, id, reset) {
32892            var box = $$.getTextRect(textElement.textContent, CLASS.legendItem),
32893                itemWidth = Math.ceil((box.width + paddingRight) / 10) * 10,
32894                itemHeight = Math.ceil((box.height + paddingTop) / 10) * 10,
32895                itemLength = $$.isLegendRight || $$.isLegendInset ? itemHeight : itemWidth,
32896                areaLength = $$.isLegendRight || $$.isLegendInset ? $$.getLegendHeight() : $$.getLegendWidth(),
32897                margin, maxLength;
32898
32899            // MEMO: care about condifion of step, totalLength
32900            function updateValues(id, withoutStep) {
32901                if (!withoutStep) {
32902                    margin = (areaLength - totalLength - itemLength) / 2;
32903                    if (margin < posMin) {
32904                        margin = (areaLength - itemLength) / 2;
32905                        totalLength = 0;
32906                        step++;
32907                    }
32908                }
32909                steps[id] = step;
32910                margins[step] = $$.isLegendInset ? 10 : margin;
32911                offsets[id] = totalLength;
32912                totalLength += itemLength;
32913            }
32914
32915            if (reset) {
32916                totalLength = 0;
32917                step = 0;
32918                maxWidth = 0;
32919                maxHeight = 0;
32920            }
32921
32922            if (config.legend_show && !$$.isLegendToShow(id)) {
32923                widths[id] = heights[id] = steps[id] = offsets[id] = 0;
32924                return;
32925            }
32926
32927            widths[id] = itemWidth;
32928            heights[id] = itemHeight;
32929
32930            if (!maxWidth || itemWidth >= maxWidth) { maxWidth = itemWidth; }
32931            if (!maxHeight || itemHeight >= maxHeight) { maxHeight = itemHeight; }
32932            maxLength = $$.isLegendRight || $$.isLegendInset ? maxHeight : maxWidth;
32933
32934            if (config.legend_equally) {
32935                Object.keys(widths).forEach(function (id) { widths[id] = maxWidth; });
32936                Object.keys(heights).forEach(function (id) { heights[id] = maxHeight; });
32937                margin = (areaLength - maxLength * targetIds.length) / 2;
32938                if (margin < posMin) {
32939                    totalLength = 0;
32940                    step = 0;
32941                    targetIds.forEach(function (id) { updateValues(id); });
32942                }
32943                else {
32944                    updateValues(id, true);
32945                }
32946            } else {
32947                updateValues(id);
32948            }
32949        }
32950
32951        if ($$.isLegendRight) {
32952            xForLegend = function (id) { return maxWidth * steps[id]; };
32953            yForLegend = function (id) { return margins[steps[id]] + offsets[id]; };
32954        } else if ($$.isLegendInset) {
32955            xForLegend = function (id) { return maxWidth * steps[id] + 10; };
32956            yForLegend = function (id) { return margins[steps[id]] + offsets[id]; };
32957        } else {
32958            xForLegend = function (id) { return margins[steps[id]] + offsets[id]; };
32959            yForLegend = function (id) { return maxHeight * steps[id]; };
32960        }
32961        xForLegendText = function (id, i) { return xForLegend(id, i) + 14; };
32962        yForLegendText = function (id, i) { return yForLegend(id, i) + 9; };
32963        xForLegendRect = function (id, i) { return xForLegend(id, i) - 4; };
32964        yForLegendRect = function (id, i) { return yForLegend(id, i) - 7; };
32965
32966        // Define g for legend area
32967        l = $$.legend.selectAll('.' + CLASS.legendItem)
32968            .data(targetIds)
32969            .enter().append('g')
32970            .attr('class', function (id) { return $$.generateClass(CLASS.legendItem, id); })
32971            .style('visibility', function (id) { return $$.isLegendToShow(id) ? 'visible' : 'hidden'; })
32972            .style('cursor', 'pointer')
32973            .on('click', function (id) {
32974                config.legend_item_onclick ? config.legend_item_onclick.call($$, id) : $$.api.toggle(id);
32975            })
32976            .on('mouseover', function (id) {
32977                $$.d3.select(this).classed(CLASS.legendItemFocused, true);
32978                if (!$$.transiting) {
32979                    $$.api.focus(id);
32980                }
32981                if (config.legend_item_onmouseover) {
32982                    config.legend_item_onmouseover.call($$, id);
32983                }
32984            })
32985            .on('mouseout', function (id) {
32986                $$.d3.select(this).classed(CLASS.legendItemFocused, false);
32987                if (!$$.transiting) {
32988                    $$.api.revert();
32989                }
32990                if (config.legend_item_onmouseout) {
32991                    config.legend_item_onmouseout.call($$, id);
32992                }
32993            });
32994        l.append('text')
32995            .text(function (id) { return isDefined(config.data_names[id]) ? config.data_names[id] : id; })
32996            .each(function (id, i) { updatePositions(this, id, i === 0); })
32997            .style("pointer-events", "none")
32998            .attr('x', $$.isLegendRight || $$.isLegendInset ? xForLegendText : -200)
32999            .attr('y', $$.isLegendRight || $$.isLegendInset ? -200 : yForLegendText);
33000        l.append('rect')
33001            .attr("class", CLASS.legendItemEvent)
33002            .style('fill-opacity', 0)
33003            .attr('x', $$.isLegendRight || $$.isLegendInset ? xForLegendRect : -200)
33004            .attr('y', $$.isLegendRight || $$.isLegendInset ? -200 : yForLegendRect);
33005        l.append('rect')
33006            .attr("class", CLASS.legendItemTile)
33007            .style("pointer-events", "none")
33008            .style('fill', $$.color)
33009            .attr('x', $$.isLegendRight || $$.isLegendInset ? xForLegendText : -200)
33010            .attr('y', $$.isLegendRight || $$.isLegendInset ? -200 : yForLegend)
33011            .attr('width', 10)
33012            .attr('height', 10);
33013        // Set background for inset legend
33014        if ($$.isLegendInset && maxWidth !== 0) {
33015            $$.legend.insert('g', '.' + CLASS.legendItem)
33016                .attr("class", CLASS.legendBackground)
33017                .append('rect')
33018                .attr('height', $$.getLegendHeight() - 10)
33019                .attr('width', maxWidth * (step + 1) + 10);
33020        }
33021
33022        texts = $$.legend.selectAll('text')
33023            .data(targetIds)
33024            .text(function (id) { return isDefined(config.data_names[id]) ? config.data_names[id] : id; }) // MEMO: needed for update
33025            .each(function (id, i) { updatePositions(this, id, i === 0); });
33026        (withTransition ? texts.transition() : texts)
33027            .attr('x', xForLegendText)
33028            .attr('y', yForLegendText);
33029
33030        rects = $$.legend.selectAll('rect.' + CLASS.legendItemEvent)
33031            .data(targetIds);
33032        (withTransition ? rects.transition() : rects)
33033            .attr('width', function (id) { return widths[id]; })
33034            .attr('height', function (id) { return heights[id]; })
33035            .attr('x', xForLegendRect)
33036            .attr('y', yForLegendRect);
33037
33038        tiles = $$.legend.selectAll('rect.' + CLASS.legendItemTile)
33039            .data(targetIds);
33040        (withTransition ? tiles.transition() : tiles)
33041            .style('fill', $$.color)
33042            .attr('x', xForLegend)
33043            .attr('y', yForLegend);
33044
33045        // toggle legend state
33046        $$.legend.selectAll('.' + CLASS.legendItem)
33047            .classed(CLASS.legendItemHidden, function (id) { return !$$.isTargetToShow(id); })
33048            .transition()
33049            .style('opacity', function (id) {
33050                var This = $$.d3.select(this);
33051                if ($$.isTargetToShow(id)) {
33052                    return !hasFocused || This.classed(CLASS.legendItemFocused) ? $$.opacityForLegend(This) : $$.opacityForUnfocusedLegend(This);
33053                } else {
33054                    return $$.legendOpacityForHidden;
33055                }
33056            });
33057
33058        // Update all to reflect change of legend
33059        $$.updateLegendItemWidth(maxWidth);
33060        $$.updateLegendItemHeight(maxHeight);
33061        $$.updateLegendStep(step);
33062        // Update size and scale
33063        $$.updateSizes();
33064        $$.updateScales();
33065        $$.updateSvgSize();
33066        // Update g positions
33067        $$.transformAll(withTransitionForTransform, transitions);
33068    };
33069
33070    c3_chart_internal_fn.initAxis = function () {
33071        var $$ = this, config = $$.config, main = $$.main;
33072        $$.axes.x = main.append("g")
33073            .attr("class", CLASS.axis + ' ' + CLASS.axisX)
33074            .attr("clip-path", $$.clipPathForXAxis)
33075            .attr("transform", $$.getTranslate('x'))
33076            .style("visibility", config.axis_x_show ? 'visible' : 'hidden');
33077        $$.axes.x.append("text")
33078            .attr("class", CLASS.axisXLabel)
33079            .attr("transform", config.axis_rotated ? "rotate(-90)" : "")
33080            .style("text-anchor", $$.textAnchorForXAxisLabel.bind($$));
33081
33082        $$.axes.y = main.append("g")
33083            .attr("class", CLASS.axis + ' ' + CLASS.axisY)
33084            .attr("clip-path", $$.clipPathForYAxis)
33085            .attr("transform", $$.getTranslate('y'))
33086            .style("visibility", config.axis_y_show ? 'visible' : 'hidden');
33087        $$.axes.y.append("text")
33088            .attr("class", CLASS.axisYLabel)
33089            .attr("transform", config.axis_rotated ? "" : "rotate(-90)")
33090            .style("text-anchor", $$.textAnchorForYAxisLabel.bind($$));
33091
33092        $$.axes.y2 = main.append("g")
33093            .attr("class", CLASS.axis + ' ' + CLASS.axisY2)
33094            // clip-path?
33095            .attr("transform", $$.getTranslate('y2'))
33096            .style("visibility", config.axis_y2_show ? 'visible' : 'hidden');
33097        $$.axes.y2.append("text")
33098            .attr("class", CLASS.axisY2Label)
33099            .attr("transform", config.axis_rotated ? "" : "rotate(-90)")
33100            .style("text-anchor", $$.textAnchorForY2AxisLabel.bind($$));
33101    };
33102    c3_chart_internal_fn.getXAxis = function (scale, orient, tickFormat, tickValues) {
33103        var $$ = this, config = $$.config,
33104            axis = c3_axis($$.d3, $$.isCategorized()).scale(scale).orient(orient);
33105
33106        // Set tick
33107        axis.tickFormat(tickFormat).tickValues(tickValues);
33108        if ($$.isCategorized()) {
33109            axis.tickCentered(config.axis_x_tick_centered);
33110            if (isEmpty(config.axis_x_tick_culling)) {
33111                config.axis_x_tick_culling = false;
33112            }
33113        } else {
33114            // TODO: move this to c3_axis
33115            axis.tickOffset = function () {
33116                var edgeX = $$.getEdgeX($$.data.targets), diff = $$.x(edgeX[1]) - $$.x(edgeX[0]),
33117                    base = diff ? diff : (config.axis_rotated ? $$.height : $$.width);
33118                return (base / $$.getMaxDataCount()) / 2;
33119            };
33120        }
33121
33122        return axis;
33123    };
33124    c3_chart_internal_fn.getYAxis = function (scale, orient, tickFormat, ticks) {
33125        return c3_axis(this.d3).scale(scale).orient(orient).tickFormat(tickFormat).ticks(ticks);
33126    };
33127    c3_chart_internal_fn.getAxisId = function (id) {
33128        var config = this.config;
33129        return id in config.data_axes ? config.data_axes[id] : 'y';
33130    };
33131    c3_chart_internal_fn.getXAxisTickFormat = function () {
33132        var $$ = this, config = $$.config,
33133            format = $$.isTimeSeries() ? $$.defaultAxisTimeFormat : $$.isCategorized() ? $$.categoryName : function (v) { return v < 0 ? v.toFixed(0) : v; };
33134        if (config.axis_x_tick_format) {
33135            if (isFunction(config.axis_x_tick_format)) {
33136                format = config.axis_x_tick_format;
33137            } else if ($$.isTimeSeries()) {
33138                format = function (date) {
33139                    return date ? $$.axisTimeFormat(config.axis_x_tick_format)(date) : "";
33140                };
33141            }
33142        }
33143        return isFunction(format) ? function (v) { return format.call($$, v); } : format;
33144    };
33145    c3_chart_internal_fn.getAxisLabelOptionByAxisId = function (axisId) {
33146        var $$ = this, config = $$.config, option;
33147        if (axisId === 'y') {
33148            option = config.axis_y_label;
33149        } else if (axisId === 'y2') {
33150            option = config.axis_y2_label;
33151        } else if (axisId === 'x') {
33152            option = config.axis_x_label;
33153        }
33154        return option;
33155    };
33156    c3_chart_internal_fn.getAxisLabelText = function (axisId) {
33157        var option = this.getAxisLabelOptionByAxisId(axisId);
33158        return isString(option) ? option : option ? option.text : null;
33159    };
33160    c3_chart_internal_fn.setAxisLabelText = function (axisId, text) {
33161        var $$ = this, config = $$.config,
33162            option = $$.getAxisLabelOptionByAxisId(axisId);
33163        if (isString(option)) {
33164            if (axisId === 'y') {
33165                config.axis_y_label = text;
33166            } else if (axisId === 'y2') {
33167                config.axis_y2_label = text;
33168            } else if (axisId === 'x') {
33169                config.axis_x_label = text;
33170            }
33171        } else if (option) {
33172            option.text = text;
33173        }
33174    };
33175    c3_chart_internal_fn.getAxisLabelPosition = function (axisId, defaultPosition) {
33176        var option = this.getAxisLabelOptionByAxisId(axisId),
33177            position = (option && typeof option === 'object' && option.position) ? option.position : defaultPosition;
33178        return {
33179            isInner: position.indexOf('inner') >= 0,
33180            isOuter: position.indexOf('outer') >= 0,
33181            isLeft: position.indexOf('left') >= 0,
33182            isCenter: position.indexOf('center') >= 0,
33183            isRight: position.indexOf('right') >= 0,
33184            isTop: position.indexOf('top') >= 0,
33185            isMiddle: position.indexOf('middle') >= 0,
33186            isBottom: position.indexOf('bottom') >= 0
33187        };
33188    };
33189    c3_chart_internal_fn.getXAxisLabelPosition = function () {
33190        return this.getAxisLabelPosition('x', this.config.axis_rotated ? 'inner-top' : 'inner-right');
33191    };
33192    c3_chart_internal_fn.getYAxisLabelPosition = function () {
33193        return this.getAxisLabelPosition('y', this.config.axis_rotated ? 'inner-right' : 'inner-top');
33194    };
33195    c3_chart_internal_fn.getY2AxisLabelPosition = function () {
33196        return this.getAxisLabelPosition('y2', this.config.axis_rotated ? 'inner-right' : 'inner-top');
33197    };
33198    c3_chart_internal_fn.getAxisLabelPositionById = function (id) {
33199        return id === 'y2' ? this.getY2AxisLabelPosition() : id === 'y' ? this.getYAxisLabelPosition() : this.getXAxisLabelPosition();
33200    };
33201    c3_chart_internal_fn.textForXAxisLabel = function () {
33202        return this.getAxisLabelText('x');
33203    };
33204    c3_chart_internal_fn.textForYAxisLabel = function () {
33205        return this.getAxisLabelText('y');
33206    };
33207    c3_chart_internal_fn.textForY2AxisLabel = function () {
33208        return this.getAxisLabelText('y2');
33209    };
33210    c3_chart_internal_fn.xForAxisLabel = function (forHorizontal, position) {
33211        var $$ = this;
33212        if (forHorizontal) {
33213            return position.isLeft ? 0 : position.isCenter ? $$.width / 2 : $$.width;
33214        } else {
33215            return position.isBottom ? -$$.height : position.isMiddle ? -$$.height / 2 : 0;
33216        }
33217    };
33218    c3_chart_internal_fn.dxForAxisLabel = function (forHorizontal, position) {
33219        if (forHorizontal) {
33220            return position.isLeft ? "0.5em" : position.isRight ? "-0.5em" : "0";
33221        } else {
33222            return position.isTop ? "-0.5em" : position.isBottom ? "0.5em" : "0";
33223        }
33224    };
33225    c3_chart_internal_fn.textAnchorForAxisLabel = function (forHorizontal, position) {
33226        if (forHorizontal) {
33227            return position.isLeft ? 'start' : position.isCenter ? 'middle' : 'end';
33228        } else {
33229            return position.isBottom ? 'start' : position.isMiddle ? 'middle' : 'end';
33230        }
33231    };
33232    c3_chart_internal_fn.xForXAxisLabel = function () {
33233        return this.xForAxisLabel(!this.config.axis_rotated, this.getXAxisLabelPosition());
33234    };
33235    c3_chart_internal_fn.xForYAxisLabel = function () {
33236        return this.xForAxisLabel(this.config.axis_rotated, this.getYAxisLabelPosition());
33237    };
33238    c3_chart_internal_fn.xForY2AxisLabel = function () {
33239        return this.xForAxisLabel(this.config.axis_rotated, this.getY2AxisLabelPosition());
33240    };
33241    c3_chart_internal_fn.dxForXAxisLabel = function () {
33242        return this.dxForAxisLabel(!this.config.axis_rotated, this.getXAxisLabelPosition());
33243    };
33244    c3_chart_internal_fn.dxForYAxisLabel = function () {
33245        return this.dxForAxisLabel(this.config.axis_rotated, this.getYAxisLabelPosition());
33246    };
33247    c3_chart_internal_fn.dxForY2AxisLabel = function () {
33248        return this.dxForAxisLabel(this.config.axis_rotated, this.getY2AxisLabelPosition());
33249    };
33250    c3_chart_internal_fn.dyForXAxisLabel = function () {
33251        var $$ = this, config = $$.config,
33252            position = $$.getXAxisLabelPosition();
33253        if (config.axis_rotated) {
33254            return position.isInner ? "1.2em" : -25 - $$.getMaxTickWidth('x');
33255        } else {
33256            return position.isInner ? "-0.5em" : config.axis_x_height ? config.axis_x_height - 10 : "3em";
33257        }
33258    };
33259    c3_chart_internal_fn.dyForYAxisLabel = function () {
33260        var $$ = this,
33261            position = $$.getYAxisLabelPosition();
33262        if ($$.config.axis_rotated) {
33263            return position.isInner ? "-0.5em" : "3em";
33264        } else {
33265            return position.isInner ? "1.2em" : -20 - $$.getMaxTickWidth('y');
33266        }
33267    };
33268    c3_chart_internal_fn.dyForY2AxisLabel = function () {
33269        var $$ = this,
33270            position = $$.getY2AxisLabelPosition();
33271        if ($$.config.axis_rotated) {
33272            return position.isInner ? "1.2em" : "-2.2em";
33273        } else {
33274            return position.isInner ? "-0.5em" : 30 + this.getMaxTickWidth('y2');
33275        }
33276    };
33277    c3_chart_internal_fn.textAnchorForXAxisLabel = function () {
33278        var $$ = this;
33279        return $$.textAnchorForAxisLabel(!$$.config.axis_rotated, $$.getXAxisLabelPosition());
33280    };
33281    c3_chart_internal_fn.textAnchorForYAxisLabel = function () {
33282        var $$ = this;
33283        return $$.textAnchorForAxisLabel($$.config.axis_rotated, $$.getYAxisLabelPosition());
33284    };
33285    c3_chart_internal_fn.textAnchorForY2AxisLabel = function () {
33286        var $$ = this;
33287        return $$.textAnchorForAxisLabel($$.config.axis_rotated, $$.getY2AxisLabelPosition());
33288    };
33289
33290    c3_chart_internal_fn.xForRotatedTickText = function (r) {
33291        return 10 * Math.sin(Math.PI * (r / 180));
33292    };
33293    c3_chart_internal_fn.yForRotatedTickText = function (r) {
33294        return 11.5 - 2.5 * (r / 15);
33295    };
33296    c3_chart_internal_fn.rotateTickText = function (axis, transition, rotate) {
33297        axis.selectAll('.tick text')
33298            .style("text-anchor", "start");
33299        transition.selectAll('.tick text')
33300            .attr("y", this.yForRotatedTickText(rotate))
33301            .attr("x", this.xForRotatedTickText(rotate))
33302            .attr("transform", "rotate(" + rotate + ")");
33303    };
33304
33305    c3_chart_internal_fn.getMaxTickWidth = function (id) {
33306        var $$ = this, config = $$.config,
33307            maxWidth = 0, targetsToShow, scale, axis;
33308        if ($$.svg) {
33309            targetsToShow = $$.filterTargetsToShow($$.data.targets);
33310            if (id === 'y') {
33311                scale = $$.y.copy().domain($$.getYDomain(targetsToShow, 'y'));
33312                axis = $$.getYAxis(scale, $$.yOrient, config.axis_y_tick_format, config.axis_y_ticks);
33313            } else if (id === 'y2') {
33314                scale = $$.y2.copy().domain($$.getYDomain(targetsToShow, 'y2'));
33315                axis = $$.getYAxis(scale, $$.y2Orient, config.axis_y2_tick_format, config.axis_y2_ticks);
33316            } else {
33317                scale = $$.x.copy().domain($$.getXDomain(targetsToShow));
33318                axis = $$.getXAxis(scale, $$.xOrient, $$.getXAxisTickFormat(), config.axis_x_tick_values ? config.axis_x_tick_values : $$.xAxis.tickValues());
33319            }
33320            $$.main.append("g").call(axis).each(function () {
33321                $$.d3.select(this).selectAll('text').each(function () {
33322                    var box = this.getBoundingClientRect();
33323                    if (maxWidth < box.width) { maxWidth = box.width; }
33324                });
33325            }).remove();
33326        }
33327        $$.currentMaxTickWidth = maxWidth <= 0 ? $$.currentMaxTickWidth : maxWidth;
33328        return $$.currentMaxTickWidth;
33329    };
33330
33331    c3_chart_internal_fn.updateAxisLabels = function (withTransition) {
33332        var $$ = this;
33333        var axisXLabel = $$.main.select('.' + CLASS.axisX + ' .' + CLASS.axisXLabel),
33334            axisYLabel = $$.main.select('.' + CLASS.axisY + ' .' + CLASS.axisYLabel),
33335            axisY2Label = $$.main.select('.' + CLASS.axisY2 + ' .' + CLASS.axisY2Label);
33336        (withTransition ? axisXLabel.transition() : axisXLabel)
33337            .attr("x", $$.xForXAxisLabel.bind($$))
33338            .attr("dx", $$.dxForXAxisLabel.bind($$))
33339            .attr("dy", $$.dyForXAxisLabel.bind($$))
33340            .text($$.textForXAxisLabel.bind($$));
33341        (withTransition ? axisYLabel.transition() : axisYLabel)
33342            .attr("x", $$.xForYAxisLabel.bind($$))
33343            .attr("dx", $$.dxForYAxisLabel.bind($$))
33344            .attr("dy", $$.dyForYAxisLabel.bind($$))
33345            .text($$.textForYAxisLabel.bind($$));
33346        (withTransition ? axisY2Label.transition() : axisY2Label)
33347            .attr("x", $$.xForY2AxisLabel.bind($$))
33348            .attr("dx", $$.dxForY2AxisLabel.bind($$))
33349            .attr("dy", $$.dyForY2AxisLabel.bind($$))
33350            .text($$.textForY2AxisLabel.bind($$));
33351    };
33352
33353    c3_chart_internal_fn.getAxisPadding = function (padding, key, defaultValue, all) {
33354        var ratio = padding.unit === 'ratio' ? all : 1;
33355        return isValue(padding[key]) ? padding[key] * ratio : defaultValue;
33356    };
33357
33358    c3_chart_internal_fn.generateTickValues = function (xs, tickCount) {
33359        var $$ = this;
33360        var tickValues = xs, targetCount, start, end, count, interval, i, tickValue;
33361        if (tickCount) {
33362            targetCount = isFunction(tickCount) ? tickCount() : tickCount;
33363            // compute ticks according to $$.config.axis_x_tick_count
33364            if (targetCount === 1) {
33365                tickValues = [xs[0]];
33366            } else if (targetCount === 2) {
33367                tickValues = [xs[0], xs[xs.length - 1]];
33368            } else if (targetCount > 2) {
33369                count = targetCount - 2;
33370                start = xs[0];
33371                end = xs[xs.length - 1];
33372                interval = (end - start) / (count + 1);
33373                // re-construct uniqueXs
33374                tickValues = [start];
33375                for (i = 0; i < count; i++) {
33376                    tickValue = +start + interval * (i + 1);
33377                    tickValues.push($$.isTimeSeries() ? new Date(tickValue) : tickValue);
33378                }
33379                tickValues.push(end);
33380            }
33381        }
33382        if (!$$.isTimeSeries()) { tickValues = tickValues.sort(function (a, b) { return a - b; }); }
33383        return tickValues;
33384    };
33385    c3_chart_internal_fn.generateAxisTransitions = function (duration) {
33386        var $$ = this, axes = $$.axes;
33387        return {
33388            axisX: duration ? axes.x.transition().duration(duration) : axes.x,
33389            axisY: duration ? axes.y.transition().duration(duration) : axes.y,
33390            axisY2: duration ? axes.y2.transition().duration(duration) : axes.y2,
33391            axisSubX: duration ? axes.subx.transition().duration(duration) : axes.subx
33392        };
33393    };
33394    c3_chart_internal_fn.redrawAxis = function (transitions, isHidden) {
33395        var $$ = this;
33396        $$.axes.x.style("opacity", isHidden ? 0 : 1);
33397        $$.axes.y.style("opacity", isHidden ? 0 : 1);
33398        $$.axes.y2.style("opacity", isHidden ? 0 : 1);
33399        $$.axes.subx.style("opacity", isHidden ? 0 : 1);
33400        transitions.axisX.call($$.xAxis);
33401        transitions.axisY.call($$.yAxis);
33402        transitions.axisY2.call($$.y2Axis);
33403        transitions.axisSubX.call($$.subXAxis);
33404    };
33405
33406    c3_chart_internal_fn.getClipPath = function (id) {
33407        var isIE9 = window.navigator.appVersion.toLowerCase().indexOf("msie 9.") >= 0;
33408        return "url(" + (isIE9 ? "" : document.URL.split('#')[0]) + "#" + id + ")";
33409    };
33410    c3_chart_internal_fn.getAxisClipX = function (forHorizontal) {
33411        // axis line width + padding for left
33412        return forHorizontal ? -(1 + 30) : -(this.margin.left - 1);
33413    };
33414    c3_chart_internal_fn.getAxisClipY = function (forHorizontal) {
33415        return forHorizontal ? -20 : -4;
33416    };
33417    c3_chart_internal_fn.getXAxisClipX = function () {
33418        var $$ = this;
33419        return $$.getAxisClipX(!$$.config.axis_rotated);
33420    };
33421    c3_chart_internal_fn.getXAxisClipY = function () {
33422        var $$ = this;
33423        return $$.getAxisClipY(!$$.config.axis_rotated);
33424    };
33425    c3_chart_internal_fn.getYAxisClipX = function () {
33426        var $$ = this;
33427        return $$.getAxisClipX($$.config.axis_rotated);
33428    };
33429    c3_chart_internal_fn.getYAxisClipY = function () {
33430        var $$ = this;
33431        return $$.getAxisClipY($$.config.axis_rotated);
33432    };
33433    c3_chart_internal_fn.getAxisClipWidth = function (forHorizontal) {
33434        var $$ = this;
33435        // width + axis line width + padding for left/right
33436        return forHorizontal ? $$.width + 2 + 30 + 30 : $$.margin.left + 20;
33437    };
33438    c3_chart_internal_fn.getAxisClipHeight = function (forHorizontal) {
33439        var $$ = this, config = $$.config;
33440        return forHorizontal ? (config.axis_x_height ? config.axis_x_height : 0) + 80 : $$.height + 8;
33441    };
33442    c3_chart_internal_fn.getXAxisClipWidth = function () {
33443        var $$ = this;
33444        return $$.getAxisClipWidth(!$$.config.axis_rotated);
33445    };
33446    c3_chart_internal_fn.getXAxisClipHeight = function () {
33447        var $$ = this;
33448        return $$.getAxisClipHeight(!$$.config.axis_rotated);
33449    };
33450    c3_chart_internal_fn.getYAxisClipWidth = function () {
33451        var $$ = this;
33452        return $$.getAxisClipWidth($$.config.axis_rotated);
33453    };
33454    c3_chart_internal_fn.getYAxisClipHeight = function () {
33455        var $$ = this;
33456        return $$.getAxisClipHeight($$.config.axis_rotated);
33457    };
33458
33459    c3_chart_internal_fn.initPie = function () {
33460        var $$ = this, d3 = $$.d3, config = $$.config;
33461        $$.pie = d3.layout.pie().value(function (d) {
33462            return d.values.reduce(function (a, b) { return a + b.value; }, 0);
33463        });
33464        if (!config.data_order || !config.pie_sort || !config.donut_sort) {
33465            $$.pie.sort(null);
33466        }
33467    };
33468
33469    c3_chart_internal_fn.updateRadius = function () {
33470        var $$ = this, config = $$.config,
33471            w = config.gauge_width || config.donut_width;
33472        $$.radiusExpanded = Math.min($$.arcWidth, $$.arcHeight) / 2;
33473        $$.radius = $$.radiusExpanded * 0.95;
33474        $$.innerRadiusRatio = w ? ($$.radius - w) / $$.radius : 0.6;
33475        $$.innerRadius = $$.hasType('donut') || $$.hasType('gauge') ? $$.radius * $$.innerRadiusRatio : 0;
33476    };
33477
33478    c3_chart_internal_fn.updateArc = function () {
33479        var $$ = this;
33480        $$.svgArc = $$.getSvgArc();
33481        $$.svgArcExpanded = $$.getSvgArcExpanded();
33482        $$.svgArcExpandedSub = $$.getSvgArcExpanded(0.98);
33483    };
33484
33485    c3_chart_internal_fn.updateAngle = function (d) {
33486        var $$ = this, config = $$.config,
33487            found = false, index = 0;
33488        $$.pie($$.filterTargetsToShow($$.data.targets)).sort($$.descByStartAngle).forEach(function (t) {
33489            if (! found && t.data.id === d.data.id) {
33490                found = true;
33491                d = t;
33492                d.index = index;
33493            }
33494            index++;
33495        });
33496        if (isNaN(d.endAngle)) {
33497            d.endAngle = d.startAngle;
33498        }
33499        if ($$.isGaugeType(d.data)) {
33500            var gMin = config.gauge_min, gMax = config.gauge_max,
33501                gF = Math.abs(gMin) + gMax,
33502                aTic = (Math.PI) / gF;
33503            d.startAngle = (-1 * (Math.PI / 2)) + (aTic * Math.abs(gMin));
33504            d.endAngle = d.startAngle + (aTic * ((d.value > gMax) ? gMax : d.value));
33505        }
33506        return found ? d : null;
33507    };
33508
33509    c3_chart_internal_fn.getSvgArc = function () {
33510        var $$ = this,
33511            arc = $$.d3.svg.arc().outerRadius($$.radius).innerRadius($$.innerRadius),
33512            newArc = function (d, withoutUpdate) {
33513                var updated;
33514                if (withoutUpdate) { return arc(d); } // for interpolate
33515                updated = $$.updateAngle(d);
33516                return updated ? arc(updated) : "M 0 0";
33517            };
33518        // TODO: extends all function
33519        newArc.centroid = arc.centroid;
33520        return newArc;
33521    };
33522
33523    c3_chart_internal_fn.getSvgArcExpanded = function (rate) {
33524        var $$ = this,
33525            arc = $$.d3.svg.arc().outerRadius($$.radiusExpanded * (rate ? rate : 1)).innerRadius($$.innerRadius);
33526        return function (d) {
33527            var updated = $$.updateAngle(d);
33528            return updated ? arc(updated) : "M 0 0";
33529        };
33530    };
33531
33532    c3_chart_internal_fn.getArc = function (d, withoutUpdate, force) {
33533        return force || this.isArcType(d.data) ? this.svgArc(d, withoutUpdate) : "M 0 0";
33534    };
33535
33536
33537    c3_chart_internal_fn.transformForArcLabel = function (d) {
33538        var $$ = this,
33539            updated = $$.updateAngle(d), c, x, y, h, ratio, translate = "";
33540        if (updated && !$$.hasType('gauge')) {
33541            c = this.svgArc.centroid(updated);
33542            x = isNaN(c[0]) ? 0 : c[0];
33543            y = isNaN(c[1]) ? 0 : c[1];
33544            h = Math.sqrt(x * x + y * y);
33545            // TODO: ratio should be an option?
33546            ratio = $$.radius && h ? (36 / $$.radius > 0.375 ? 1.175 - 36 / $$.radius : 0.8) * $$.radius / h : 0;
33547            translate = "translate(" + (x * ratio) +  ',' + (y * ratio) +  ")";
33548        }
33549        return translate;
33550    };
33551
33552    c3_chart_internal_fn.getArcRatio = function (d) {
33553        var $$ = this,
33554            whole = $$.hasType('gauge') ? Math.PI : (Math.PI * 2);
33555        return d ? (d.endAngle - d.startAngle) / whole : null;
33556    };
33557
33558    c3_chart_internal_fn.convertToArcData = function (d) {
33559        return this.addName({
33560            id: d.data.id,
33561            value: d.value,
33562            ratio: this.getArcRatio(d),
33563            index: d.index
33564        });
33565    };
33566
33567    c3_chart_internal_fn.textForArcLabel = function (d) {
33568        var $$ = this,
33569            updated, value, ratio, format;
33570        if (! $$.shouldShowArcLabel()) { return ""; }
33571        updated = $$.updateAngle(d);
33572        value = updated ? updated.value : null;
33573        ratio = $$.getArcRatio(updated);
33574        if (! $$.hasType('gauge') && ! $$.meetsArcLabelThreshold(ratio)) { return ""; }
33575        format = $$.getArcLabelFormat();
33576        return format ? format(value, ratio) : $$.defaultArcValueFormat(value, ratio);
33577    };
33578
33579    c3_chart_internal_fn.expandArc = function (id, withoutFadeOut) {
33580        var $$ = this,
33581            target = $$.svg.selectAll('.' + CLASS.chartArc + $$.selectorTarget(id)),
33582            noneTargets = $$.svg.selectAll('.' + CLASS.arc).filter(function (data) { return data.data.id !== id; });
33583
33584        if ($$.shouldExpand(id)) {
33585            target.selectAll('path')
33586                .transition().duration(50)
33587                .attr("d", $$.svgArcExpanded)
33588                .transition().duration(100)
33589                .attr("d", $$.svgArcExpandedSub)
33590                .each(function (d) {
33591                    if ($$.isDonutType(d.data)) {
33592                        // callback here
33593                    }
33594                });
33595        }
33596        if (!withoutFadeOut) {
33597            noneTargets.style("opacity", 0.3);
33598        }
33599    };
33600
33601    c3_chart_internal_fn.unexpandArc = function (id) {
33602        var $$ = this,
33603            target = $$.svg.selectAll('.' + CLASS.chartArc + $$.selectorTarget(id));
33604        target.selectAll('path.' + CLASS.arc)
33605            .transition().duration(50)
33606            .attr("d", $$.svgArc);
33607        $$.svg.selectAll('.' + CLASS.arc)
33608            .style("opacity", 1);
33609    };
33610
33611    c3_chart_internal_fn.shouldExpand = function (id) {
33612        var $$ = this, config = $$.config;
33613        return ($$.isDonutType(id) && config.donut_expand) || ($$.isGaugeType(id) && config.gauge_expand) || ($$.isPieType(id) && config.pie_expand);
33614    };
33615
33616    c3_chart_internal_fn.shouldShowArcLabel = function () {
33617        var $$ = this, config = $$.config, shouldShow = true;
33618        if ($$.hasType('donut')) {
33619            shouldShow = config.donut_label_show;
33620        } else if ($$.hasType('pie')) {
33621            shouldShow = config.pie_label_show;
33622        }
33623        // when gauge, always true
33624        return shouldShow;
33625    };
33626
33627    c3_chart_internal_fn.meetsArcLabelThreshold = function (ratio) {
33628        var $$ = this, config = $$.config,
33629            threshold = $$.hasType('donut') ? config.donut_label_threshold : config.pie_label_threshold;
33630        return ratio >= threshold;
33631    };
33632
33633    c3_chart_internal_fn.getArcLabelFormat = function () {
33634        var $$ = this, config = $$.config,
33635            format = config.pie_label_format;
33636        if ($$.hasType('gauge')) {
33637            format = config.gauge_label_format;
33638        } else if ($$.hasType('donut')) {
33639            format = config.donut_label_format;
33640        }
33641        return format;
33642    };
33643
33644    c3_chart_internal_fn.getArcTitle = function () {
33645        var $$ = this;
33646        return $$.hasType('donut') ? $$.config.donut_title : "";
33647    };
33648
33649    c3_chart_internal_fn.descByStartAngle = function (a, b) {
33650        return a.startAngle - b.startAngle;
33651    };
33652
33653    c3_chart_internal_fn.updateTargetsForArc = function (targets) {
33654        var $$ = this, main = $$.main,
33655            mainPieUpdate, mainPieEnter,
33656            classChartArc = $$.classChartArc.bind($$),
33657            classArcs = $$.classArcs.bind($$);
33658        mainPieUpdate = main.select('.' + CLASS.chartArcs).selectAll('.' + CLASS.chartArc)
33659            .data($$.pie(targets))
33660            .attr("class", classChartArc);
33661        mainPieEnter = mainPieUpdate.enter().append("g")
33662            .attr("class", classChartArc);
33663        mainPieEnter.append('g')
33664            .attr('class', classArcs);
33665        mainPieEnter.append("text")
33666            .attr("dy", $$.hasType('gauge') ? "-0.35em" : ".35em")
33667            .style("opacity", 0)
33668            .style("text-anchor", "middle")
33669            .style("pointer-events", "none");
33670        // MEMO: can not keep same color..., but not bad to update color in redraw
33671        //mainPieUpdate.exit().remove();
33672    };
33673
33674    c3_chart_internal_fn.initArc = function () {
33675        var $$ = this;
33676        $$.arcs = $$.main.select('.' + CLASS.chart).append("g")
33677            .attr("class", CLASS.chartArcs)
33678            .attr("transform", $$.getTranslate('arc'));
33679        $$.arcs.append('text')
33680            .attr('class', CLASS.chartArcsTitle)
33681            .style("text-anchor", "middle")
33682            .text($$.getArcTitle());
33683    };
33684
33685    c3_chart_internal_fn.redrawArc = function (duration, durationForExit, withTransform) {
33686        var $$ = this, d3 = $$.d3, config = $$.config, main = $$.main,
33687            mainArc;
33688        mainArc = main.selectAll('.' + CLASS.arcs).selectAll('.' + CLASS.arc)
33689            .data($$.arcData.bind($$));
33690        mainArc.enter().append('path')
33691            .attr("class", $$.classArc.bind($$))
33692            .style("fill", function (d) { return $$.color(d.data); })
33693            .style("cursor", function (d) { return config.data_selection_isselectable(d) ? "pointer" : null; })
33694            .style("opacity", 0)
33695            .each(function (d) {
33696                if ($$.isGaugeType(d.data)) {
33697                    d.startAngle = d.endAngle = -1 * (Math.PI / 2);
33698                }
33699                this._current = d;
33700            })
33701            .on('mouseover', function (d) {
33702                var updated, arcData;
33703                if ($$.transiting) { // skip while transiting
33704                    return;
33705                }
33706                updated = $$.updateAngle(d);
33707                arcData = $$.convertToArcData(updated);
33708                // transitions
33709                $$.expandArc(updated.data.id);
33710                $$.toggleFocusLegend(updated.data.id, true);
33711                $$.config.data_onmouseover(arcData, this);
33712            })
33713            .on('mousemove', function (d) {
33714                var updated = $$.updateAngle(d),
33715                    arcData = $$.convertToArcData(updated),
33716                    selectedData = [arcData];
33717                $$.showTooltip(selectedData, d3.mouse(this));
33718            })
33719            .on('mouseout', function (d) {
33720                var updated, arcData;
33721                if ($$.transiting) { // skip while transiting
33722                    return;
33723                }
33724                updated = $$.updateAngle(d);
33725                arcData = $$.convertToArcData(updated);
33726                // transitions
33727                $$.unexpandArc(updated.data.id);
33728                $$.revertLegend();
33729                $$.hideTooltip();
33730                $$.config.data_onmouseout(arcData, this);
33731            })
33732            .on('click', function (d, i) {
33733                var updated, arcData;
33734                if (!$$.toggleShape) {
33735                    return;
33736                }
33737                updated = $$.updateAngle(d);
33738                arcData = $$.convertToArcData(updated);
33739                $$.toggleShape(this, arcData, i); // onclick called in toogleShape()
33740            });
33741        mainArc
33742            .attr("transform", function (d) { return !$$.isGaugeType(d.data) && withTransform ? "scale(0)" : ""; })
33743            .style("opacity", function (d) { return d === this._current ? 0 : 1; })
33744            .each(function () { $$.transiting = true; })
33745            .transition().duration(duration)
33746            .attrTween("d", function (d) {
33747                var updated = $$.updateAngle(d), interpolate;
33748                if (! updated) {
33749                    return function () { return "M 0 0"; };
33750                }
33751                //                if (this._current === d) {
33752                //                    this._current = {
33753                //                        startAngle: Math.PI*2,
33754                //                        endAngle: Math.PI*2,
33755                //                    };
33756                //                }
33757                if (isNaN(this._current.endAngle)) {
33758                    this._current.endAngle = this._current.startAngle;
33759                }
33760                interpolate = d3.interpolate(this._current, updated);
33761                this._current = interpolate(0);
33762                return function (t) { return $$.getArc(interpolate(t), true); };
33763            })
33764            .attr("transform", withTransform ? "scale(1)" : "")
33765            .style("fill", function (d) {
33766                return $$.levelColor ? $$.levelColor(d.data.values[0].value) : $$.color(d.data.id);
33767            }) // Where gauge reading color would receive customization.
33768            .style("opacity", 1)
33769            .call($$.endall, function () {
33770                $$.transiting = false;
33771            });
33772        mainArc.exit().transition().duration(durationForExit)
33773            .style('opacity', 0)
33774            .remove();
33775        main.selectAll('.' + CLASS.chartArc).select('text')
33776            .style("opacity", 0)
33777            .attr('class', function (d) { return $$.isGaugeType(d.data) ? CLASS.gaugeValue : ''; })
33778            .text($$.textForArcLabel.bind($$))
33779            .attr("transform", $$.transformForArcLabel.bind($$))
33780            .transition().duration(duration)
33781            .style("opacity", function (d) { return $$.isTargetToShow(d.data.id) && $$.isArcType(d.data) ? 1 : 0; });
33782        main.select('.' + CLASS.chartArcsTitle)
33783            .style("opacity", $$.hasType('donut') || $$.hasType('gauge') ? 1 : 0);
33784
33785    };
33786    c3_chart_internal_fn.initGauge = function () {
33787        var $$ = this, config = $$.config, arcs = $$.arcs;
33788        if ($$.hasType('gauge')) {
33789            arcs.append('path')
33790                .attr("class", CLASS.chartArcsBackground)
33791                .attr("d", function () {
33792                    var d = {
33793                        data: [{value: config.gauge_max}],
33794                        startAngle: -1 * (Math.PI / 2),
33795                        endAngle: Math.PI / 2
33796                    };
33797                    return $$.getArc(d, true, true);
33798                });
33799            arcs.append("text")
33800                .attr("dy", ".75em")
33801                .attr("class", CLASS.chartArcsGaugeUnit)
33802                .style("text-anchor", "middle")
33803                .style("pointer-events", "none")
33804                .text(config.gauge_label_show ? config.gauge_units : '');
33805            arcs.append("text")
33806                .attr("dx", -1 * ($$.innerRadius + (($$.radius - $$.innerRadius) / 2)) + "px")
33807                .attr("dy", "1.2em")
33808                .attr("class", CLASS.chartArcsGaugeMin)
33809                .style("text-anchor", "middle")
33810                .style("pointer-events", "none")
33811                .text(config.gauge_label_show ? config.gauge_min : '');
33812            arcs.append("text")
33813                .attr("dx", $$.innerRadius + (($$.radius - $$.innerRadius) / 2) + "px")
33814                .attr("dy", "1.2em")
33815                .attr("class", CLASS.chartArcsGaugeMax)
33816                .style("text-anchor", "middle")
33817                .style("pointer-events", "none")
33818                .text(config.gauge_label_show ? config.gauge_max : '');
33819        }
33820    };
33821
33822    c3_chart_internal_fn.initRegion = function () {
33823        var $$ = this;
33824        $$.main.append('g')
33825            .attr("clip-path", $$.clipPath)
33826            .attr("class", CLASS.regions);
33827    };
33828    c3_chart_internal_fn.redrawRegion = function (duration) {
33829        var $$ = this, config = $$.config;
33830        $$.mainRegion = $$.main.select('.' + CLASS.regions).selectAll('.' + CLASS.region)
33831            .data(config.regions);
33832        $$.mainRegion.enter().append('g')
33833            .attr('class', $$.classRegion.bind($$))
33834          .append('rect')
33835            .style("fill-opacity", 0);
33836        $$.mainRegion.exit().transition().duration(duration)
33837            .style("opacity", 0)
33838            .remove();
33839    };
33840    c3_chart_internal_fn.addTransitionForRegion = function (transitions) {
33841        var $$ = this,
33842            x = $$.regionX.bind($$),
33843            y = $$.regionY.bind($$),
33844            w = $$.regionWidth.bind($$),
33845            h = $$.regionHeight.bind($$);
33846        transitions.push($$.mainRegion.selectAll('rect').transition()
33847                         .attr("x", x)
33848                         .attr("y", y)
33849                         .attr("width", w)
33850                         .attr("height", h)
33851                         .style("fill-opacity", function (d) { return isValue(d.opacity) ? d.opacity : 0.1; }));
33852    };
33853    c3_chart_internal_fn.regionX = function (d) {
33854        var $$ = this, config = $$.config,
33855            xPos, yScale = d.axis === 'y' ? $$.y : $$.y2;
33856        if (d.axis === 'y' || d.axis === 'y2') {
33857            xPos = config.axis_rotated ? ('start' in d ? yScale(d.start) : 0) : 0;
33858        } else {
33859            xPos = config.axis_rotated ? 0 : ('start' in d ? $$.x($$.isTimeSeries() ? $$.parseDate(d.start) : d.start) : 0);
33860        }
33861        return xPos;
33862    };
33863    c3_chart_internal_fn.regionY = function (d) {
33864        var $$ = this, config = $$.config,
33865            yPos, yScale = d.axis === 'y' ? $$.y : $$.y2;
33866        if (d.axis === 'y' || d.axis === 'y2') {
33867            yPos = config.axis_rotated ? 0 : ('end' in d ? yScale(d.end) : 0);
33868        } else {
33869            yPos = config.axis_rotated ? ('start' in d ? $$.x($$.isTimeSeries() ? $$.parseDate(d.start) : d.start) : 0) : 0;
33870        }
33871        return yPos;
33872    };
33873    c3_chart_internal_fn.regionWidth = function (d) {
33874        var $$ = this, config = $$.config,
33875            start = $$.regionX(d), end, yScale = d.axis === 'y' ? $$.y : $$.y2;
33876        if (d.axis === 'y' || d.axis === 'y2') {
33877            end = config.axis_rotated ? ('end' in d ? yScale(d.end) : $$.width) : $$.width;
33878        } else {
33879            end = config.axis_rotated ? $$.width : ('end' in d ? $$.x($$.isTimeSeries() ? $$.parseDate(d.end) : d.end) : $$.width);
33880        }
33881        return end < start ? 0 : end - start;
33882    };
33883    c3_chart_internal_fn.regionHeight = function (d) {
33884        var $$ = this, config = $$.config,
33885            start = this.regionY(d), end, yScale = d.axis === 'y' ? $$.y : $$.y2;
33886        if (d.axis === 'y' || d.axis === 'y2') {
33887            end = config.axis_rotated ? $$.height : ('start' in d ? yScale(d.start) : $$.height);
33888        } else {
33889            end = config.axis_rotated ? ('end' in d ? $$.x($$.isTimeSeries() ? $$.parseDate(d.end) : d.end) : $$.height) : $$.height;
33890        }
33891        return end < start ? 0 : end - start;
33892    };
33893    c3_chart_internal_fn.isRegionOnX = function (d) {
33894        return !d.axis || d.axis === 'x';
33895    };
33896
33897    c3_chart_internal_fn.drag = function (mouse) {
33898        var $$ = this, config = $$.config, main = $$.main, d3 = $$.d3;
33899        var sx, sy, mx, my, minX, maxX, minY, maxY;
33900
33901        if ($$.hasArcType()) { return; }
33902        if (! config.data_selection_enabled) { return; } // do nothing if not selectable
33903        if (config.zoom_enabled && ! $$.zoom.altDomain) { return; } // skip if zoomable because of conflict drag dehavior
33904        if (!config.data_selection_multiple) { return; } // skip when single selection because drag is used for multiple selection
33905
33906        sx = $$.dragStart[0];
33907        sy = $$.dragStart[1];
33908        mx = mouse[0];
33909        my = mouse[1];
33910        minX = Math.min(sx, mx);
33911        maxX = Math.max(sx, mx);
33912        minY = (config.data_selection_grouped) ? $$.margin.top : Math.min(sy, my);
33913        maxY = (config.data_selection_grouped) ? $$.height : Math.max(sy, my);
33914
33915        main.select('.' + CLASS.dragarea)
33916            .attr('x', minX)
33917            .attr('y', minY)
33918            .attr('width', maxX - minX)
33919            .attr('height', maxY - minY);
33920        // TODO: binary search when multiple xs
33921        main.selectAll('.' + CLASS.shapes).selectAll('.' + CLASS.shape)
33922            .filter(function (d) { return config.data_selection_isselectable(d); })
33923            .each(function (d, i) {
33924                var shape = d3.select(this),
33925                    isSelected = shape.classed(CLASS.SELECTED),
33926                    isIncluded = shape.classed(CLASS.INCLUDED),
33927                    _x, _y, _w, _h, toggle, isWithin = false, box;
33928                if (shape.classed(CLASS.circle)) {
33929                    _x = shape.attr("cx") * 1;
33930                    _y = shape.attr("cy") * 1;
33931                    toggle = $$.togglePoint;
33932                    isWithin = minX < _x && _x < maxX && minY < _y && _y < maxY;
33933                }
33934                else if (shape.classed(CLASS.bar)) {
33935                    box = getPathBox(this);
33936                    _x = box.x;
33937                    _y = box.y;
33938                    _w = box.width;
33939                    _h = box.height;
33940                    toggle = $$.toggleBar;
33941                    isWithin = !(maxX < _x || _x + _w < minX) && !(maxY < _y || _y + _h < minY);
33942                } else {
33943                    // line/area selection not supported yet
33944                    return;
33945                }
33946                if (isWithin ^ isIncluded) {
33947                    shape.classed(CLASS.INCLUDED, !isIncluded);
33948                    // TODO: included/unincluded callback here
33949                    shape.classed(CLASS.SELECTED, !isSelected);
33950                    toggle.call($$, !isSelected, shape, d, i);
33951                }
33952            });
33953    };
33954
33955    c3_chart_internal_fn.dragstart = function (mouse) {
33956        var $$ = this, config = $$.config;
33957        if ($$.hasArcType()) { return; }
33958        if (! config.data_selection_enabled) { return; } // do nothing if not selectable
33959        $$.dragStart = mouse;
33960        $$.main.select('.' + CLASS.chart).append('rect')
33961            .attr('class', CLASS.dragarea)
33962            .style('opacity', 0.1);
33963        $$.dragging = true;
33964        $$.config.data_ondragstart();
33965    };
33966
33967    c3_chart_internal_fn.dragend = function () {
33968        var $$ = this, config = $$.config;
33969        if ($$.hasArcType()) { return; }
33970        if (! config.data_selection_enabled) { return; } // do nothing if not selectable
33971        $$.main.select('.' + CLASS.dragarea)
33972            .transition().duration(100)
33973            .style('opacity', 0)
33974            .remove();
33975        $$.main.selectAll('.' + CLASS.shape)
33976            .classed(CLASS.INCLUDED, false);
33977        $$.dragging = false;
33978        $$.config.data_ondragend();
33979    };
33980
33981
33982    c3_chart_internal_fn.selectPoint = function (target, d, i) {
33983        var $$ = this, config = $$.config,
33984            cx = (config.axis_rotated ? $$.circleY : $$.circleX).bind($$),
33985            cy = (config.axis_rotated ? $$.circleX : $$.circleY).bind($$),
33986            r = $$.pointSelectR.bind($$);
33987        config.data_onselected.call($$.api, d, target.node());
33988        // add selected-circle on low layer g
33989        $$.main.select('.' + CLASS.selectedCircles + $$.getTargetSelectorSuffix(d.id)).selectAll('.' + CLASS.selectedCircle + '-' + i)
33990            .data([d])
33991            .enter().append('circle')
33992            .attr("class", function () { return $$.generateClass(CLASS.selectedCircle, i); })
33993            .attr("cx", cx)
33994            .attr("cy", cy)
33995            .attr("stroke", function () { return $$.color(d); })
33996            .attr("r", function (d) { return $$.pointSelectR(d) * 1.4; })
33997            .transition().duration(100)
33998            .attr("r", r);
33999    };
34000    c3_chart_internal_fn.unselectPoint = function (target, d, i) {
34001        var $$ = this;
34002        $$.config.data_onunselected(d, target.node());
34003        // remove selected-circle from low layer g
34004        $$.main.select('.' + CLASS.selectedCircles + $$.getTargetSelectorSuffix(d.id)).selectAll('.' + CLASS.selectedCircle + '-' + i)
34005            .transition().duration(100).attr('r', 0)
34006            .remove();
34007    };
34008    c3_chart_internal_fn.togglePoint = function (selected, target, d, i) {
34009        selected ? this.selectPoint(target, d, i) : this.unselectPoint(target, d, i);
34010    };
34011    c3_chart_internal_fn.selectBar = function (target, d) {
34012        var $$ = this;
34013        $$.config.data_onselected.call($$, d, target.node());
34014        target.transition().duration(100)
34015            .style("fill", function () { return $$.d3.rgb($$.color(d)).brighter(0.75); });
34016    };
34017    c3_chart_internal_fn.unselectBar = function (target, d) {
34018        var $$ = this;
34019        $$.config.data_onunselected.call($$, d, target.node());
34020        target.transition().duration(100)
34021            .style("fill", function () { return $$.color(d); });
34022    };
34023    c3_chart_internal_fn.toggleBar = function (selected, target, d, i) {
34024        selected ? this.selectBar(target, d, i) : this.unselectBar(target, d, i);
34025    };
34026    c3_chart_internal_fn.toggleArc = function (selected, target, d, i) {
34027        this.toggleBar(selected, target, d.data, i);
34028    };
34029    c3_chart_internal_fn.getToggle = function (that) {
34030        var $$ = this;
34031        // path selection not supported yet
34032        return that.nodeName === 'circle' ? $$.togglePoint : ($$.d3.select(that).classed(CLASS.bar) ? $$.toggleBar : $$.toggleArc);
34033    };
34034    c3_chart_internal_fn.toggleShape = function (that, d, i) {
34035        var $$ = this, d3 = $$.d3, config = $$.config,
34036            shape = d3.select(that), isSelected = shape.classed(CLASS.SELECTED), isWithin, toggle;
34037        if (that.nodeName === 'circle') {
34038            isWithin = $$.isWithinCircle(that, $$.pointSelectR(d) * 1.5);
34039            toggle = $$.togglePoint;
34040        }
34041        else if (that.nodeName === 'path') {
34042            if (shape.classed(CLASS.bar)) {
34043                isWithin = $$.isWithinBar(that);
34044                toggle = $$.toggleBar;
34045            } else { // would be arc
34046                isWithin = true;
34047                toggle = $$.toggleArc;
34048            }
34049        }
34050        if (config.data_selection_grouped || isWithin) {
34051            if (config.data_selection_enabled && config.data_selection_isselectable(d)) {
34052                if (!config.data_selection_multiple) {
34053                    $$.main.selectAll('.' + CLASS.shapes + (config.data_selection_grouped ? $$.getTargetSelectorSuffix(d.id) : "")).selectAll('.' + CLASS.shape).each(function (d, i) {
34054                        var shape = d3.select(this);
34055                        if (shape.classed(CLASS.SELECTED)) { toggle.call($$, false, shape.classed(CLASS.SELECTED, false), d, i); }
34056                    });
34057                }
34058                shape.classed(CLASS.SELECTED, !isSelected);
34059                toggle.call($$, !isSelected, shape, d, i);
34060            }
34061            $$.config.data_onclick.call($$.api, d, that);
34062        }
34063    };
34064
34065    c3_chart_internal_fn.initBrush = function () {
34066        var $$ = this, d3 = $$.d3;
34067        $$.brush = d3.svg.brush().on("brush", function () { $$.redrawForBrush(); });
34068        $$.brush.update = function () {
34069            if ($$.context) { $$.context.select('.' + CLASS.brush).call(this); }
34070            return this;
34071        };
34072        $$.brush.scale = function (scale) {
34073            return $$.config.axis_rotated ? this.y(scale) : this.x(scale);
34074        };
34075    };
34076    c3_chart_internal_fn.initSubchart = function () {
34077        var $$ = this, config = $$.config,
34078            context = $$.context = $$.svg.append("g").attr("transform", $$.getTranslate('context'));
34079
34080        if (!config.subchart_show) {
34081            context.style('visibility', 'hidden');
34082        }
34083
34084        // Define g for chart area
34085        context.append('g')
34086            .attr("clip-path", $$.clipPath)
34087            .attr('class', CLASS.chart);
34088
34089        // Define g for bar chart area
34090        context.select('.' + CLASS.chart).append("g")
34091            .attr("class", CLASS.chartBars);
34092
34093        // Define g for line chart area
34094        context.select('.' + CLASS.chart).append("g")
34095            .attr("class", CLASS.chartLines);
34096
34097        // Add extent rect for Brush
34098        context.append("g")
34099            .attr("clip-path", $$.clipPath)
34100            .attr("class", CLASS.brush)
34101            .call($$.brush)
34102            .selectAll("rect")
34103            .attr(config.axis_rotated ? "width" : "height", config.axis_rotated ? $$.width2 : $$.height2);
34104
34105        // ATTENTION: This must be called AFTER chart added
34106        // Add Axis
34107        $$.axes.subx = context.append("g")
34108            .attr("class", CLASS.axisX)
34109            .attr("transform", $$.getTranslate('subx'))
34110            .attr("clip-path", config.axis_rotated ? "" : $$.clipPathForXAxis);
34111    };
34112    c3_chart_internal_fn.updateTargetsForSubchart = function (targets) {
34113        var $$ = this, context = $$.context, config = $$.config,
34114            contextLineEnter, contextLineUpdate, contextBarEnter, contextBarUpdate,
34115            classChartBar = $$.classChartBar.bind($$),
34116            classBars = $$.classBars.bind($$),
34117            classChartLine = $$.classChartLine.bind($$),
34118            classLines = $$.classLines.bind($$),
34119            classAreas = $$.classAreas.bind($$);
34120
34121        if (config.subchart_show) {
34122            contextBarUpdate = context.select('.' + CLASS.chartBars).selectAll('.' + CLASS.chartBar)
34123                .data(targets)
34124                .attr('class', classChartBar);
34125            contextBarEnter = contextBarUpdate.enter().append('g')
34126                .style('opacity', 0)
34127                .attr('class', classChartBar);
34128            // Bars for each data
34129            contextBarEnter.append('g')
34130                .attr("class", classBars);
34131
34132            //-- Line --//
34133            contextLineUpdate = context.select('.' + CLASS.chartLines).selectAll('.' + CLASS.chartLine)
34134                .data(targets)
34135                .attr('class', classChartLine);
34136            contextLineEnter = contextLineUpdate.enter().append('g')
34137                .style('opacity', 0)
34138                .attr('class', classChartLine);
34139            // Lines for each data
34140            contextLineEnter.append("g")
34141                .attr("class", classLines);
34142            // Area
34143            contextLineEnter.append("g")
34144                .attr("class", classAreas);
34145        }
34146    };
34147    c3_chart_internal_fn.redrawSubchart = function (withSubchart, transitions, duration, durationForExit, areaIndices, barIndices, lineIndices) {
34148        var $$ = this, d3 = $$.d3, context = $$.context, config = $$.config,
34149            contextLine,  contextArea, contextBar, drawAreaOnSub, drawBarOnSub, drawLineOnSub,
34150            barData = $$.barData.bind($$),
34151            lineData = $$.lineData.bind($$),
34152            classBar = $$.classBar.bind($$),
34153            classLine = $$.classLine.bind($$),
34154            classArea = $$.classArea.bind($$),
34155            initialOpacity = $$.initialOpacity.bind($$);
34156
34157        // subchart
34158        if (config.subchart_show) {
34159            // reflect main chart to extent on subchart if zoomed
34160            if (d3.event && d3.event.type === 'zoom') {
34161                $$.brush.extent($$.x.orgDomain()).update();
34162            }
34163            // update subchart elements if needed
34164            if (withSubchart) {
34165
34166                // rotate tick text if needed
34167                if (!config.axis_rotated && config.axis_x_tick_rotate) {
34168                    $$.rotateTickText($$.axes.subx, transitions.axisSubX, config.axis_x_tick_rotate);
34169                }
34170
34171                // extent rect
34172                if (!$$.brush.empty()) {
34173                    $$.brush.extent($$.x.orgDomain()).update();
34174                }
34175                // setup drawer - MEMO: this must be called after axis updated
34176                drawAreaOnSub = $$.generateDrawArea(areaIndices, true);
34177                drawBarOnSub = $$.generateDrawBar(barIndices, true);
34178                drawLineOnSub = $$.generateDrawLine(lineIndices, true);
34179                // bars
34180                contextBar = context.selectAll('.' + CLASS.bars).selectAll('.' + CLASS.bar)
34181                    .data(barData);
34182                contextBar.enter().append('path')
34183                    .attr("class", classBar)
34184                    .style("stroke", 'none')
34185                    .style("fill", $$.color);
34186                contextBar
34187                    .style("opacity", initialOpacity)
34188                    .transition().duration(duration)
34189                    .attr('d', drawBarOnSub)
34190                    .style('opacity', 1);
34191                contextBar.exit().transition().duration(duration)
34192                    .style('opacity', 0)
34193                    .remove();
34194                // lines
34195                contextLine = context.selectAll('.' + CLASS.lines).selectAll('.' + CLASS.line)
34196                    .data(lineData);
34197                contextLine.enter().append('path')
34198                    .attr('class', classLine)
34199                    .style('stroke', $$.color);
34200                contextLine
34201                    .style("opacity", initialOpacity)
34202                    .transition().duration(duration)
34203                    .attr("d", drawLineOnSub)
34204                    .style('opacity', 1);
34205                contextLine.exit().transition().duration(duration)
34206                    .style('opacity', 0)
34207                    .remove();
34208                // area
34209                contextArea = context.selectAll('.' + CLASS.areas).selectAll('.' + CLASS.area)
34210                    .data(lineData);
34211                contextArea.enter().append('path')
34212                    .attr("class", classArea)
34213                    .style("fill", $$.color)
34214                    .style("opacity", function () { $$.orgAreaOpacity = +d3.select(this).style('opacity'); return 0; });
34215                contextArea
34216                    .style("opacity", 0)
34217                    .transition().duration(duration)
34218                    .attr("d", drawAreaOnSub)
34219                    .style("fill", $$.color)
34220                    .style("opacity", $$.orgAreaOpacity);
34221                contextArea.exit().transition().duration(durationForExit)
34222                    .style('opacity', 0)
34223                    .remove();
34224            }
34225        }
34226    };
34227    c3_chart_internal_fn.redrawForBrush = function () {
34228        var $$ = this, x = $$.x;
34229        $$.redraw({
34230            withTransition: false,
34231            withY: false,
34232            withSubchart: false,
34233            withUpdateXDomain: true
34234        });
34235        $$.config.subchart_onbrush.call($$.api, x.orgDomain());
34236    };
34237    c3_chart_internal_fn.transformContext = function (withTransition, transitions) {
34238        var $$ = this, subXAxis;
34239        if (transitions && transitions.axisSubX) {
34240            subXAxis = transitions.axisSubX;
34241        } else {
34242            subXAxis = $$.context.select('.' + CLASS.axisX);
34243            if (withTransition) { subXAxis = subXAxis.transition(); }
34244        }
34245        $$.context.attr("transform", $$.getTranslate('context'));
34246        subXAxis.attr("transform", $$.getTranslate('subx'));
34247    };
34248
34249    c3_chart_internal_fn.initZoom = function () {
34250        var $$ = this, d3 = $$.d3, config = $$.config;
34251        $$.zoom = d3.behavior.zoom()
34252            .on("zoomstart", function () {
34253                $$.zoom.altDomain = d3.event.sourceEvent.altKey ? $$.x.orgDomain() : null;
34254            })
34255            .on("zoom", function () { $$.redrawForZoom.call($$); });
34256        $$.zoom.scale = function (scale) {
34257            return config.axis_rotated ? this.y(scale) : this.x(scale);
34258        };
34259        $$.zoom.orgScaleExtent = function () {
34260            var extent = config.zoom_extent ? config.zoom_extent : [1, 10];
34261            return [extent[0], Math.max($$.getMaxDataCount() / extent[1], extent[1])];
34262        };
34263        $$.zoom.updateScaleExtent = function () {
34264            var ratio = diffDomain($$.x.orgDomain()) / diffDomain($$.orgXDomain),
34265                extent = this.orgScaleExtent();
34266            this.scaleExtent([extent[0] * ratio, extent[1] * ratio]);
34267            return this;
34268        };
34269    };
34270    c3_chart_internal_fn.updateZoom = function () {
34271        var $$ = this, z = $$.config.zoom_enabled ? $$.zoom : function () {};
34272        $$.main.select('.' + CLASS.zoomRect).call(z);
34273        $$.main.selectAll('.' + CLASS.eventRect).call(z);
34274    };
34275    c3_chart_internal_fn.redrawForZoom = function () {
34276        var $$ = this, d3 = $$.d3, config = $$.config, zoom = $$.zoom, x = $$.x, orgXDomain = $$.orgXDomain;
34277        if (!config.zoom_enabled) {
34278            return;
34279        }
34280        if ($$.filterTargetsToShow($$.data.targets).length === 0) {
34281            return;
34282        }
34283        if (d3.event.sourceEvent.type === 'mousemove' && zoom.altDomain) {
34284            x.domain(zoom.altDomain);
34285            zoom.scale(x).updateScaleExtent();
34286            return;
34287        }
34288        if ($$.isCategorized() && x.orgDomain()[0] === orgXDomain[0]) {
34289            x.domain([orgXDomain[0] - 1e-10, x.orgDomain()[1]]);
34290        }
34291        $$.redraw({
34292            withTransition: false,
34293            withY: false,
34294            withSubchart: false
34295        });
34296        if (d3.event.sourceEvent.type === 'mousemove') {
34297            $$.cancelClick = true;
34298        }
34299        config.zoom_onzoom.call($$.api, x.orgDomain());
34300    };
34301
34302    c3_chart_internal_fn.generateColor = function () {
34303        var $$ = this, config = $$.config, d3 = $$.d3,
34304            colors = config.data_colors,
34305            pattern = notEmpty(config.color_pattern) ? config.color_pattern : d3.scale.category10().range(),
34306            callback = config.data_color,
34307            ids = [];
34308
34309        return function (d) {
34310            var id = d.id || d, color;
34311
34312            // if callback function is provided
34313            if (colors[id] instanceof Function) {
34314                color = colors[id](d);
34315            }
34316            // if specified, choose that color
34317            else if (colors[id]) {
34318                color = colors[id];
34319            }
34320            // if not specified, choose from pattern
34321            else {
34322                if (ids.indexOf(id) < 0) { ids.push(id); }
34323                color = pattern[ids.indexOf(id) % pattern.length];
34324                colors[id] = color;
34325            }
34326            return callback instanceof Function ? callback(color, d) : color;
34327        };
34328    };
34329    c3_chart_internal_fn.generateLevelColor = function () {
34330        var $$ = this, config = $$.config,
34331            colors = config.color_pattern,
34332            threshold = config.color_threshold,
34333            asValue = threshold.unit === 'value',
34334            values = threshold.values && threshold.values.length ? threshold.values : [],
34335            max = threshold.max || 100;
34336        return notEmpty(config.color_threshold) ? function (value) {
34337            var i, v, color = colors[colors.length - 1];
34338            for (i = 0; i < values.length; i++) {
34339                v = asValue ? value : (value * 100 / max);
34340                if (v < values[i]) {
34341                    color = colors[i];
34342                    break;
34343                }
34344            }
34345            return color;
34346        } : null;
34347    };
34348
34349    c3_chart_internal_fn.getYFormat = function (forArc) {
34350        var $$ = this,
34351            formatForY = forArc && !$$.hasType('gauge') ? $$.defaultArcValueFormat : $$.yFormat,
34352            formatForY2 = forArc && !$$.hasType('gauge') ? $$.defaultArcValueFormat : $$.y2Format;
34353        return function (v, ratio, id) {
34354            var format = $$.getAxisId(id) === 'y2' ? formatForY2 : formatForY;
34355            return format.call($$, v, ratio);
34356        };
34357    };
34358    c3_chart_internal_fn.yFormat = function (v) {
34359        var $$ = this, config = $$.config,
34360            format = config.axis_y_tick_format ? config.axis_y_tick_format : $$.defaultValueFormat;
34361        return format(v);
34362    };
34363    c3_chart_internal_fn.y2Format = function (v) {
34364        var $$ = this, config = $$.config,
34365            format = config.axis_y2_tick_format ? config.axis_y2_tick_format : $$.defaultValueFormat;
34366        return format(v);
34367    };
34368    c3_chart_internal_fn.defaultValueFormat = function (v) {
34369        return isValue(v) ? +v : "";
34370    };
34371    c3_chart_internal_fn.defaultArcValueFormat = function (v, ratio) {
34372        return (ratio * 100).toFixed(1) + '%';
34373    };
34374    c3_chart_internal_fn.formatByAxisId = function (axisId) {
34375        var $$ = this, data_labels = $$.config.data_labels,
34376            format = function (v) { return isValue(v) ? +v : ""; };
34377        // find format according to axis id
34378        if (typeof data_labels.format === 'function') {
34379            format = data_labels.format;
34380        } else if (typeof data_labels.format === 'object') {
34381            if (data_labels.format[axisId]) {
34382                format = data_labels.format[axisId];
34383            }
34384        }
34385        return format;
34386    };
34387
34388    c3_chart_internal_fn.hasCaches = function (ids) {
34389        for (var i = 0; i < ids.length; i++) {
34390            if (! (ids[i] in this.cache)) { return false; }
34391        }
34392        return true;
34393    };
34394    c3_chart_internal_fn.addCache = function (id, target) {
34395        this.cache[id] = this.cloneTarget(target);
34396    };
34397    c3_chart_internal_fn.getCaches = function (ids) {
34398        var targets = [], i;
34399        for (i = 0; i < ids.length; i++) {
34400            if (ids[i] in this.cache) { targets.push(this.cloneTarget(this.cache[ids[i]])); }
34401        }
34402        return targets;
34403    };
34404
34405    var CLASS = c3_chart_internal_fn.CLASS = {
34406        target: 'c3-target',
34407        chart: 'c3-chart',
34408        chartLine: 'c3-chart-line',
34409        chartLines: 'c3-chart-lines',
34410        chartBar: 'c3-chart-bar',
34411        chartBars: 'c3-chart-bars',
34412        chartText: 'c3-chart-text',
34413        chartTexts: 'c3-chart-texts',
34414        chartArc: 'c3-chart-arc',
34415        chartArcs: 'c3-chart-arcs',
34416        chartArcsTitle: 'c3-chart-arcs-title',
34417        chartArcsBackground: 'c3-chart-arcs-background',
34418        chartArcsGaugeUnit: 'c3-chart-arcs-gauge-unit',
34419        chartArcsGaugeMax: 'c3-chart-arcs-gauge-max',
34420        chartArcsGaugeMin: 'c3-chart-arcs-gauge-min',
34421        selectedCircle: 'c3-selected-circle',
34422        selectedCircles: 'c3-selected-circles',
34423        eventRect: 'c3-event-rect',
34424        eventRects: 'c3-event-rects',
34425        eventRectsSingle: 'c3-event-rects-single',
34426        eventRectsMultiple: 'c3-event-rects-multiple',
34427        zoomRect: 'c3-zoom-rect',
34428        brush: 'c3-brush',
34429        focused: 'c3-focused',
34430        region: 'c3-region',
34431        regions: 'c3-regions',
34432        tooltip: 'c3-tooltip',
34433        tooltipName: 'c3-tooltip-name',
34434        shape: 'c3-shape',
34435        shapes: 'c3-shapes',
34436        line: 'c3-line',
34437        lines: 'c3-lines',
34438        bar: 'c3-bar',
34439        bars: 'c3-bars',
34440        circle: 'c3-circle',
34441        circles: 'c3-circles',
34442        arc: 'c3-arc',
34443        arcs: 'c3-arcs',
34444        area: 'c3-area',
34445        areas: 'c3-areas',
34446        empty: 'c3-empty',
34447        text: 'c3-text',
34448        texts: 'c3-texts',
34449        gaugeValue: 'c3-gauge-value',
34450        grid: 'c3-grid',
34451        xgrid: 'c3-xgrid',
34452        xgrids: 'c3-xgrids',
34453        xgridLine: 'c3-xgrid-line',
34454        xgridLines: 'c3-xgrid-lines',
34455        xgridFocus: 'c3-xgrid-focus',
34456        ygrid: 'c3-ygrid',
34457        ygrids: 'c3-ygrids',
34458        ygridLine: 'c3-ygrid-line',
34459        ygridLines: 'c3-ygrid-lines',
34460        axis: 'c3-axis',
34461        axisX: 'c3-axis-x',
34462        axisXLabel: 'c3-axis-x-label',
34463        axisY: 'c3-axis-y',
34464        axisYLabel: 'c3-axis-y-label',
34465        axisY2: 'c3-axis-y2',
34466        axisY2Label: 'c3-axis-y2-label',
34467        legendBackground: 'c3-legend-background',
34468        legendItem: 'c3-legend-item',
34469        legendItemEvent: 'c3-legend-item-event',
34470        legendItemTile: 'c3-legend-item-tile',
34471        legendItemHidden: 'c3-legend-item-hidden',
34472        legendItemFocused: 'c3-legend-item-focused',
34473        dragarea: 'c3-dragarea',
34474        EXPANDED: '_expanded_',
34475        SELECTED: '_selected_',
34476        INCLUDED: '_included_'
34477    };
34478    c3_chart_internal_fn.generateClass = function (prefix, targetId) {
34479        return " " + prefix + " " + prefix + this.getTargetSelectorSuffix(targetId);
34480    };
34481    c3_chart_internal_fn.classText = function (d) {
34482        return this.generateClass(CLASS.text, d.index);
34483    };
34484    c3_chart_internal_fn.classTexts = function (d) {
34485        return this.generateClass(CLASS.texts, d.id);
34486    };
34487    c3_chart_internal_fn.classShape = function (d) {
34488        return this.generateClass(CLASS.shape, d.index);
34489    };
34490    c3_chart_internal_fn.classShapes = function (d) {
34491        return this.generateClass(CLASS.shapes, d.id);
34492    };
34493    c3_chart_internal_fn.classLine = function (d) {
34494        return this.classShape(d) + this.generateClass(CLASS.line, d.id);
34495    };
34496    c3_chart_internal_fn.classLines = function (d) {
34497        return this.classShapes(d) + this.generateClass(CLASS.lines, d.id);
34498    };
34499    c3_chart_internal_fn.classCircle = function (d) {
34500        return this.classShape(d) + this.generateClass(CLASS.circle, d.index);
34501    };
34502    c3_chart_internal_fn.classCircles = function (d) {
34503        return this.classShapes(d) + this.generateClass(CLASS.circles, d.id);
34504    };
34505    c3_chart_internal_fn.classBar = function (d) {
34506        return this.classShape(d) + this.generateClass(CLASS.bar, d.index);
34507    };
34508    c3_chart_internal_fn.classBars = function (d) {
34509        return this.classShapes(d) + this.generateClass(CLASS.bars, d.id);
34510    };
34511    c3_chart_internal_fn.classArc = function (d) {
34512        return this.classShape(d.data) + this.generateClass(CLASS.arc, d.data.id);
34513    };
34514    c3_chart_internal_fn.classArcs = function (d) {
34515        return this.classShapes(d.data) + this.generateClass(CLASS.arcs, d.data.id);
34516    };
34517    c3_chart_internal_fn.classArea = function (d) {
34518        return this.classShape(d) + this.generateClass(CLASS.area, d.id);
34519    };
34520    c3_chart_internal_fn.classAreas = function (d) {
34521        return this.classShapes(d) + this.generateClass(CLASS.areas, d.id);
34522    };
34523    c3_chart_internal_fn.classRegion = function (d, i) {
34524        return this.generateClass(CLASS.region, i) + ' ' + ('class' in d ? d.class : '');
34525    };
34526    c3_chart_internal_fn.classEvent = function (d) {
34527        return this.generateClass(CLASS.eventRect, d.index);
34528    };
34529    c3_chart_internal_fn.classTarget = function (id) {
34530        var $$ = this;
34531        var additionalClassSuffix = $$.config.data_classes[id], additionalClass = '';
34532        if (additionalClassSuffix) {
34533            additionalClass = ' ' + CLASS.target + '-' + additionalClassSuffix;
34534        }
34535        return $$.generateClass(CLASS.target, id) + additionalClass;
34536    };
34537    c3_chart_internal_fn.classChartText = function (d) {
34538        return CLASS.chartText + this.classTarget(d.id);
34539    };
34540    c3_chart_internal_fn.classChartLine = function (d) {
34541        return CLASS.chartLine + this.classTarget(d.id);
34542    };
34543    c3_chart_internal_fn.classChartBar = function (d) {
34544        return CLASS.chartBar + this.classTarget(d.id);
34545    };
34546    c3_chart_internal_fn.classChartArc = function (d) {
34547        return CLASS.chartArc + this.classTarget(d.data.id);
34548    };
34549    c3_chart_internal_fn.getTargetSelectorSuffix = function (targetId) {
34550        return targetId || targetId === 0 ? '-' + (targetId.replace ? targetId.replace(/([^a-zA-Z0-9-_])/g, '-') : targetId) : '';
34551    };
34552    c3_chart_internal_fn.selectorTarget = function (id) {
34553        return '.' + CLASS.target + this.getTargetSelectorSuffix(id);
34554    };
34555    c3_chart_internal_fn.selectorTargets = function (ids) {
34556        var $$ = this;
34557        return ids.length ? ids.map(function (id) { return $$.selectorTarget(id); }) : null;
34558    };
34559    c3_chart_internal_fn.selectorLegend = function (id) {
34560        return '.' + CLASS.legendItem + this.getTargetSelectorSuffix(id);
34561    };
34562    c3_chart_internal_fn.selectorLegends = function (ids) {
34563        var $$ = this;
34564        return ids.length ? ids.map(function (id) { return $$.selectorLegend(id); }) : null;
34565    };
34566
34567    var isValue = c3_chart_internal_fn.isValue = function (v) {
34568        return v || v === 0;
34569    },
34570        isFunction = c3_chart_internal_fn.isFunction = function (o) {
34571            return typeof o === 'function';
34572        },
34573        isString = c3_chart_internal_fn.isString = function (o) {
34574            return typeof o === 'string';
34575        },
34576        isUndefined = c3_chart_internal_fn.isUndefined = function (v) {
34577            return typeof v === 'undefined';
34578        },
34579        isDefined = c3_chart_internal_fn.isDefined = function (v) {
34580            return typeof v !== 'undefined';
34581        },
34582        ceil10 = c3_chart_internal_fn.ceil10 = function (v) {
34583            return Math.ceil(v / 10) * 10;
34584        },
34585        asHalfPixel = c3_chart_internal_fn.asHalfPixel = function (n) {
34586            return Math.ceil(n) + 0.5;
34587        },
34588        diffDomain = c3_chart_internal_fn.diffDomain = function (d) {
34589            return d[1] - d[0];
34590        },
34591        isEmpty = c3_chart_internal_fn.isEmpty = function (o) {
34592            return !o || (isString(o) && o.length === 0) || (typeof o === 'object' && Object.keys(o).length === 0);
34593        },
34594        notEmpty = c3_chart_internal_fn.notEmpty = function (o) {
34595            return Object.keys(o).length > 0;
34596        },
34597        getOption = c3_chart_internal_fn.getOption = function (options, key, defaultValue) {
34598            return isDefined(options[key]) ? options[key] : defaultValue;
34599        },
34600        hasValue = c3_chart_internal_fn.hasValue = function (dict, value) {
34601            var found = false;
34602            Object.keys(dict).forEach(function (key) {
34603                if (dict[key] === value) { found = true; }
34604            });
34605            return found;
34606        },
34607        getPathBox = c3_chart_internal_fn.getPathBox = function (path) {
34608            var box = path.getBoundingClientRect(),
34609                items = [path.pathSegList.getItem(0), path.pathSegList.getItem(1)],
34610                minX = items[0].x, minY = Math.min(items[0].y, items[1].y);
34611            return {x: minX, y: minY, width: box.width, height: box.height};
34612        };
34613
34614    c3_chart_fn.focus = function (targetId) {
34615        var $$ = this.internal,
34616            candidates = $$.svg.selectAll($$.selectorTarget(targetId)),
34617            candidatesForNoneArc = candidates.filter($$.isNoneArc.bind($$)),
34618            candidatesForArc = candidates.filter($$.isArc.bind($$));
34619        function focus(targets) {
34620            $$.filterTargetsToShow(targets).transition().duration(100).style('opacity', 1);
34621        }
34622        this.revert();
34623        this.defocus();
34624        focus(candidatesForNoneArc.classed(CLASS.focused, true));
34625        focus(candidatesForArc);
34626        if ($$.hasArcType()) {
34627            $$.expandArc(targetId, true);
34628        }
34629        $$.toggleFocusLegend(targetId, true);
34630    };
34631
34632    c3_chart_fn.defocus = function (targetId) {
34633        var $$ = this.internal,
34634            candidates = $$.svg.selectAll($$.selectorTarget(targetId)),
34635            candidatesForNoneArc = candidates.filter($$.isNoneArc.bind($$)),
34636            candidatesForArc = candidates.filter($$.isArc.bind($$));
34637        function defocus(targets) {
34638            $$.filterTargetsToShow(targets).transition().duration(100).style('opacity', 0.3);
34639        }
34640        this.revert();
34641        defocus(candidatesForNoneArc.classed(CLASS.focused, false));
34642        defocus(candidatesForArc);
34643        if ($$.hasArcType()) {
34644            $$.unexpandArc(targetId);
34645        }
34646        $$.toggleFocusLegend(targetId, false);
34647    };
34648
34649    c3_chart_fn.revert = function (targetId) {
34650        var $$ = this.internal,
34651            candidates = $$.svg.selectAll($$.selectorTarget(targetId)),
34652            candidatesForNoneArc = candidates.filter($$.isNoneArc.bind($$)),
34653            candidatesForArc = candidates.filter($$.isArc.bind($$));
34654        function revert(targets) {
34655            $$.filterTargetsToShow(targets).transition().duration(100).style('opacity', 1);
34656        }
34657        revert(candidatesForNoneArc.classed(CLASS.focused, false));
34658        revert(candidatesForArc);
34659        if ($$.hasArcType()) {
34660            $$.unexpandArc(targetId);
34661        }
34662        $$.revertLegend();
34663    };
34664
34665    c3_chart_fn.show = function (targetIds, options) {
34666        var $$ = this.internal;
34667
34668        targetIds = $$.mapToTargetIds(targetIds);
34669        options = options || {};
34670
34671        $$.removeHiddenTargetIds(targetIds);
34672        $$.svg.selectAll($$.selectorTargets(targetIds))
34673            .transition()
34674            .style('opacity', 1);
34675
34676        if (options.withLegend) {
34677            $$.showLegend(targetIds);
34678        }
34679
34680        $$.redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true, withLegend: true});
34681    };
34682
34683    c3_chart_fn.hide = function (targetIds, options) {
34684        var $$ = this.internal;
34685
34686        targetIds = $$.mapToTargetIds(targetIds);
34687        options = options || {};
34688
34689        $$.addHiddenTargetIds(targetIds);
34690        $$.svg.selectAll($$.selectorTargets(targetIds))
34691            .transition()
34692            .style('opacity', 0);
34693
34694        if (options.withLegend) {
34695            $$.hideLegend(targetIds);
34696        }
34697
34698        $$.redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true, withLegend: true});
34699    };
34700
34701    c3_chart_fn.toggle = function (targetId) {
34702        var $$ = this.internal;
34703        $$.isTargetToShow(targetId) ? this.hide(targetId) : this.show(targetId);
34704    };
34705
34706    c3_chart_fn.zoom = function () {
34707    };
34708    c3_chart_fn.zoom.enable = function (enabled) {
34709        var $$ = this.internal;
34710        $$.config.zoom_enabled = enabled;
34711        $$.updateAndRedraw();
34712    };
34713    c3_chart_fn.unzoom = function () {
34714        var $$ = this.internal;
34715        $$.brush.clear().update();
34716        $$.redraw({withUpdateXDomain: true});
34717    };
34718
34719    c3_chart_fn.load = function (args) {
34720        var $$ = this.internal, config = $$.config;
34721        // update xs if specified
34722        if (args.xs) {
34723            $$.addXs(args.xs);
34724        }
34725        // update classes if exists
vendor: 4,770 bytes, lines 34726-34855
34726        if ('classes' in args) {
34727            Object.keys(args.classes).forEach(function (id) {
34728                config.data_classes[id] = args.classes[id];
34729            });
34730        }
34731        // update categories if exists
34732        if ('categories' in args && $$.isCategorized()) {
34733            config.axis_x_categories = args.categories;
34734        }
34735        // use cache if exists
34736        if ('cacheIds' in args && $$.hasCaches(args.cacheIds)) {
34737            $$.load($$.getCaches(args.cacheIds), args.done);
34738            return;
34739        }
34740        // unload if needed
34741        if ('unload' in args) {
34742            // TODO: do not unload if target will load (included in url/rows/columns)
34743            $$.unload($$.mapToTargetIds((typeof args.unload === 'boolean' && args.unload) ? null : args.unload), function () {
34744                $$.loadFromArgs(args);
34745            });
34746        } else {
34747            $$.loadFromArgs(args);
34748        }
34749    };
34750
34751    c3_chart_fn.unload = function (args) {
34752        var $$ = this.internal;
34753        args = args || {};
34754        $$.unload($$.mapToTargetIds(args.ids), function () {
34755            $$.redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true, withLegend: true});
34756            if (args.done) { args.done(); }
34757        });
34758    };
34759
34760    c3_chart_fn.flow = function (args) {
34761        var $$ = this.internal,
34762            targets, data, notfoundIds = [], orgDataCount = $$.getMaxDataCount(),
34763            dataCount, domain, baseTarget, baseValue, length = 0, tail = 0, diff, to;
34764
34765        if (args.json) {
34766            data = $$.convertJsonToData(args.json, args.keys);
34767        }
34768        else if (args.rows) {
34769            data = $$.convertRowsToData(args.rows);
34770        }
34771        else if (args.columns) {
34772            data = $$.convertColumnsToData(args.columns);
34773        }
34774        else {
34775            return;
34776        }
34777        targets = $$.convertDataToTargets(data, true);
34778
34779        // Update/Add data
34780        $$.data.targets.forEach(function (t) {
34781            var found = false, i, j;
34782            for (i = 0; i < targets.length; i++) {
34783                if (t.id === targets[i].id) {
34784                    found = true;
34785
34786                    if (t.values[t.values.length - 1]) {
34787                        tail = t.values[t.values.length - 1].index + 1;
34788                    }
34789                    length = targets[i].values.length;
34790
34791                    for (j = 0; j < length; j++) {
34792                        targets[i].values[j].index = tail + j;
34793                        if (!$$.isTimeSeries()) {
34794                            targets[i].values[j].x = tail + j;
34795                        }
34796                    }
34797                    t.values = t.values.concat(targets[i].values);
34798
34799                    targets.splice(i, 1);
34800                    break;
34801                }
34802            }
34803            if (!found) { notfoundIds.push(t.id); }
34804        });
34805
34806        // Append null for not found targets
34807        $$.data.targets.forEach(function (t) {
34808            var i, j;
34809            for (i = 0; i < notfoundIds.length; i++) {
34810                if (t.id === notfoundIds[i]) {
34811                    tail = t.values[t.values.length - 1].index + 1;
34812                    for (j = 0; j < length; j++) {
34813                        t.values.push({
34814                            id: t.id,
34815                            index: tail + j,
34816                            x: $$.isTimeSeries() ? $$.getOtherTargetX(tail + j) : tail + j,
34817                            value: null
34818                        });
34819                    }
34820                }
34821            }
34822        });
34823
34824        // Generate null values for new target
34825        if ($$.data.targets.length) {
34826            targets.forEach(function (t) {
34827                var i, missing = [];
34828                for (i = $$.data.targets[0].values[0].index; i < tail; i++) {
34829                    missing.push({
34830                        id: t.id,
34831                        index: i,
34832                        x: $$.isTimeSeries() ? $$.getOtherTargetX(i) : i,
34833                        value: null
34834                    });
34835                }
34836                t.values.forEach(function (v) {
34837                    v.index += tail;
34838                    if (!$$.isTimeSeries()) {
34839                        v.x += tail;
34840                    }
34841                });
34842                t.values = missing.concat(t.values);
34843            });
34844        }
34845        $$.data.targets = $$.data.targets.concat(targets); // add remained
34846
34847        // check data count because behavior needs to change when it's only one
34848        dataCount = $$.getMaxDataCount();
34849        baseTarget = $$.data.targets[0];
34850        baseValue = baseTarget.values[0];
34851
34852        // Update length to flow if needed
34853        if (isDefined(args.to)) {
34854            length = 0;
34855            to = $$.isTimeSeries() ? $$.parseDate(args.to) : args.to;
34856            baseTarget.values.forEach(function (v) {
34857                if (v.x < to) { length++; }
34858            });
34859        } else if (isDefined(args.length)) {
34860            length = args.length;
34861        }
34862
34863        // If only one data, update the domain to flow from left edge of the chart
34864        if (!orgDataCount) {
34865            if ($$.isTimeSeries()) {
34866                if (baseTarget.values.length > 1) {
34867                    diff = baseTarget.values[baseTarget.values.length - 1].x - baseValue.x;
34868                } else {
34869                    diff = baseValue.x - $$.getXDomain($$.data.targets)[0];
34870                }
34871            } else {
34872                diff = 1;
34873            }
34874            domain = [baseValue.x - diff, baseValue.x];
34875            $$.updateXDomain(null, true, true, domain);
34876        } else if (orgDataCount === 1) {
34877            if ($$.isTimeSeries()) {
34878                diff = (baseTarget.values[baseTarget.values.length - 1].x - baseValue.x) / 2;
34879                domain = [new Date(+baseValue.x - diff), new Date(+baseValue.x + diff)];
34880                $$.updateXDomain(null, true, true, domain);
34881            }
34882        }
34883
34884        // Set targets
34885        $$.updateTargets($$.data.targets);
34886
34887        // Redraw with new targets
34888        $$.redraw({
34889            flow: {
34890                index: baseValue.index,
34891                length: length,
34892                duration: isValue(args.duration) ? args.duration : $$.config.transition_duration,
34893                done: args.done,
34894                orgDataCount: orgDataCount,
34895            },
34896            withLegend: true,
34897            withTransition: orgDataCount > 1,
34898        });
34899    };
34900
34901    c3_chart_internal_fn.generateFlow = function (args) {
34902        var $$ = this, config = $$.config, d3 = $$.d3;
34903
34904        return function () {
34905            var targets = args.targets,
34906                flow = args.flow,
34907                drawBar = args.drawBar,
34908                drawLine = args.drawLine,
34909                drawArea = args.drawArea,
34910                cx = args.cx,
34911                cy = args.cy,
34912                xv = args.xv,
34913                xForText = args.xForText,
34914                yForText = args.yForText,
34915                duration = args.duration;
34916
34917            var translateX, scaleX = 1, transform,
34918                flowIndex = flow.index,
34919                flowLength = flow.length,
34920                flowStart = $$.getValueOnIndex($$.data.targets[0].values, flowIndex),
34921                flowEnd = $$.getValueOnIndex($$.data.targets[0].values, flowIndex + flowLength),
34922                orgDomain = $$.x.domain(), domain,
34923                durationForFlow = flow.duration || duration,
34924                done = flow.done || function () {},
34925                wait = $$.generateWait();
34926
34927            var xgrid = $$.xgrid || d3.selectAll([]),
34928                xgridLines = $$.xgridLines || d3.selectAll([]),
34929                mainRegion = $$.mainRegion || d3.selectAll([]),
34930                mainText = $$.mainText || d3.selectAll([]),
34931                mainBar = $$.mainBar || d3.selectAll([]),
34932                mainLine = $$.mainLine || d3.selectAll([]),
34933                mainArea = $$.mainArea || d3.selectAll([]),
34934                mainCircle = $$.mainCircle || d3.selectAll([]);
34935
34936            // remove head data after rendered
34937            $$.data.targets.forEach(function (d) {
34938                d.values.splice(0, flowLength);
34939            });
34940
34941            // update x domain to generate axis elements for flow
34942            domain = $$.updateXDomain(targets, true, true);
34943            // update elements related to x scale
34944            if ($$.updateXGrid) { $$.updateXGrid(true); }
34945
34946            // generate transform to flow
34947            if (!flow.orgDataCount) { // if empty
34948                if ($$.data.targets[0].values.length !== 1) {
34949                    translateX = $$.x(orgDomain[0]) - $$.x(domain[0]);
34950                } else {
34951                    if ($$.isTimeSeries()) {
34952                        flowStart = $$.getValueOnIndex($$.data.targets[0].values, 0);
34953                        flowEnd = $$.getValueOnIndex($$.data.targets[0].values, $$.data.targets[0].values.length - 1);
34954                        translateX = $$.x(flowStart.x) - $$.x(flowEnd.x);
34955                    } else {
34956                        translateX = diffDomain(domain) / 2;
34957                    }
34958                }
34959            } else if (flow.orgDataCount === 1 || flowStart.x === flowEnd.x) {
34960                translateX = $$.x(orgDomain[0]) - $$.x(domain[0]);
34961            } else {
34962                if ($$.isTimeSeries()) {
34963                    translateX = ($$.x(orgDomain[0]) - $$.x(domain[0]));
34964                } else {
34965                    translateX = ($$.x(flowStart.x) - $$.x(flowEnd.x));
34966                }
34967            }
34968            scaleX = (diffDomain(orgDomain) / diffDomain(domain));
34969            transform = 'translate(' + translateX + ',0) scale(' + scaleX + ',1)';
34970
34971            d3.transition().ease('linear').duration(durationForFlow).each(function () {
34972                wait.add($$.axes.x.transition().call($$.xAxis));
34973                wait.add(mainBar.transition().attr('transform', transform));
34974                wait.add(mainLine.transition().attr('transform', transform));
34975                wait.add(mainArea.transition().attr('transform', transform));
34976                wait.add(mainCircle.transition().attr('transform', transform));
34977                wait.add(mainText.transition().attr('transform', transform));
34978                wait.add(mainRegion.filter($$.isRegionOnX).transition().attr('transform', transform));
34979                wait.add(xgrid.transition().attr('transform', transform));
34980                wait.add(xgridLines.transition().attr('transform', transform));
34981            })
34982            .call(wait, function () {
34983                var i, shapes = [], texts = [], eventRects = [];
34984
34985                // remove flowed elements
34986                if (flowLength) {
34987                    for (i = 0;
vendor: 5,652 bytes, lines 34987-35106
34987 i < flowLength; i++) {
34988                        shapes.push('.' + CLASS.shape + '-' + (flowIndex + i));
34989                        texts.push('.' + CLASS.text + '-' + (flowIndex + i));
34990                        eventRects.push('.' + CLASS.eventRect + '-' + (flowIndex + i));
34991                    }
34992                    $$.svg.selectAll('.' + CLASS.shapes).selectAll(shapes).remove();
34993                    $$.svg.selectAll('.' + CLASS.texts).selectAll(texts).remove();
34994                    $$.svg.selectAll('.' + CLASS.eventRects).selectAll(eventRects).remove();
34995                    $$.svg.select('.' + CLASS.xgrid).remove();
34996                }
34997
34998                // draw again for removing flowed elements and reverting attr
34999                xgrid
35000                    .attr('transform', null)
35001                    .attr($$.xgridAttr);
35002                xgridLines
35003                    .attr('transform', null);
35004                xgridLines.select('line')
35005                    .attr("x1", config.axis_rotated ? 0 : xv)
35006                    .attr("x2", config.axis_rotated ? $$.width : xv);
35007                xgridLines.select('text')
35008                    .attr("x", config.axis_rotated ? $$.width : 0)
35009                    .attr("y", xv);
35010                mainBar
35011                    .attr('transform', null)
35012                    .attr("d", drawBar);
35013                mainLine
35014                    .attr('transform', null)
35015                    .attr("d", drawLine);
35016                mainArea
35017                    .attr('transform', null)
35018                    .attr("d", drawArea);
35019                mainCircle
35020                    .attr('transform', null)
35021                    .attr("cx", cx)
35022                    .attr("cy", cy);
35023                mainText
35024                    .attr('transform', null)
35025                    .attr('x', xForText)
35026                    .attr('y', yForText)
35027                    .style('fill-opacity', $$.opacityForText.bind($$));
35028                mainRegion
35029                    .attr('transform', null);
35030                mainRegion.select('rect').filter($$.isRegionOnX)
35031                    .attr("x", $$.regionX.bind($$))
35032                    .attr("width", $$.regionWidth.bind($$));
35033                $$.updateEventRect();
35034
35035                // callback for end of flow
35036                done();
35037            });
35038        };
35039    };
35040
35041    c3_chart_fn.selected = function (targetId) {
35042        var $$ = this.internal, d3 = $$.d3;
35043        return d3.merge(
35044            $$.main.selectAll('.' + CLASS.shapes + $$.getTargetSelectorSuffix(targetId)).selectAll('.' + CLASS.shape)
35045                .filter(function () { return d3.select(this).classed(CLASS.SELECTED); })
35046                .map(function (d) { return d.map(function (d) { var data = d.__data__; return data.data ? data.data : data; }); })
35047        );
35048    };
35049    c3_chart_fn.select = function (ids, indices, resetOther) {
35050        var $$ = this.internal, d3 = $$.d3, config = $$.config;
35051        if (! config.data_selection_enabled) { return; }
35052        $$.main.selectAll('.' + CLASS.shapes).selectAll('.' + CLASS.shape).each(function (d, i) {
35053            var shape = d3.select(this), id = d.data ? d.data.id : d.id,
35054                toggle = $$.getToggle(this).bind($$),
35055                isTargetId = config.data_selection_grouped || !ids || ids.indexOf(id) >= 0,
35056                isTargetIndex = !indices || indices.indexOf(i) >= 0,
35057                isSelected = shape.classed(CLASS.SELECTED);
35058            // line/area selection not supported yet
35059            if (shape.classed(CLASS.line) || shape.classed(CLASS.area)) {
35060                return;
35061            }
35062            if (isTargetId && isTargetIndex) {
35063                if (config.data_selection_isselectable(d) && !isSelected) {
35064                    toggle(true, shape.classed(CLASS.SELECTED, true), d, i);
35065                }
35066            } else if (isDefined(resetOther) && resetOther) {
35067                if (isSelected) {
35068                    toggle(false, shape.classed(CLASS.SELECTED, false), d, i);
35069                }
35070            }
35071        });
35072    };
35073    c3_chart_fn.unselect = function (ids, indices) {
35074        var $$ = this.internal, d3 = $$.d3, config = $$.config;
35075        if (! config.data_selection_enabled) { return; }
35076        $$.main.selectAll('.' + CLASS.shapes).selectAll('.' + CLASS.shape).each(function (d, i) {
35077            var shape = d3.select(this), id = d.data ? d.data.id : d.id,
35078                toggle = $$.getToggle(this).bind($$),
35079                isTargetId = config.data_selection_grouped || !ids || ids.indexOf(id) >= 0,
35080                isTargetIndex = !indices || indices.indexOf(i) >= 0,
35081                isSelected = shape.classed(CLASS.SELECTED);
35082            // line/area selection not supported yet
35083            if (shape.classed(CLASS.line) || shape.classed(CLASS.area)) {
35084                return;
35085            }
35086            if (isTargetId && isTargetIndex) {
35087                if (config.data_selection_isselectable(d)) {
35088                    if (isSelected) {
35089                        toggle(false, shape.classed(CLASS.SELECTED, false), d, i);
35090                    }
35091                }
35092            }
35093        });
35094    };
35095
35096    c3_chart_fn.transform = function (type, targetIds) {
35097        var $$ = this.internal,
35098            options = ['pie', 'donut'].indexOf(type) >= 0 ? {withTransform: true} : null;
35099        $$.transformTo(targetIds, type, options);
35100    };
35101
35102    c3_chart_internal_fn.transformTo = function (targetIds, type, optionsForRedraw) {
35103        var $$ = this,
35104            withTransitionForAxis = !$$.hasArcType(),
35105            options = optionsForRedraw || {withTransitionForAxis: withTransitionForAxis};
35106        options.withTransitionForTransform = false;
35107        $$.transiting = false;
35108        $$.setTargetType(targetIds, type);
35109        $$.updateAndRedraw(options);
35110    };
35111
35112    c3_chart_fn.groups = function (groups) {
35113        var $$ = this.internal, config = $$.config;
35114        if (isUndefined(groups)) { return config.data_groups; }
35115        config.data_groups = groups;
35116        $$.redraw();
35117        return config.data_groups;
35118    };
35119
35120    c3_chart_fn.xgrids = function (grids) {
35121        var $$ = this.internal, config = $$.config;
35122        if (! grids) { return config.grid_x_lines; }
35123        config.grid_x_lines = grids;
35124        $$.redraw();
35125        return config.grid_x_lines;
35126    };
35127    c3_chart_fn.xgrids.add = function (grids) {
35128        var $$ = this.internal;
35129        return this.xgrids($$.config.grid_x_lines.concat(grids ? grids : []));
35130    };
35131    c3_chart_fn.xgrids.remove = function (params) { // TODO: multiple
35132        var $$ = this.internal;
35133        $$.removeGridLines(params, true);
35134    };
35135
35136    c3_chart_fn.ygrids = function (grids) {
35137        var $$ = this.internal, config = $$.config;
35138        if (! grids) { return config.grid_y_lines; }
35139        config.grid_y_lines = grids;
35140        $$.redraw();
35141        return config.grid_y_lines;
35142    };
35143    c3_chart_fn.ygrids.add = function (grids) {
35144        var $$ = this.internal;
35145        return this.ygrids($$.config.grid_y_lines.concat(grids ? grids : []));
35146    };
35147    c3_chart_fn.ygrids.remove = function (params) { // TODO: multiple
35148        var $$ = this.internal;
35149        $$.removeGridLines(params, false);
35150    };
35151
35152    c3_chart_fn.regions = function (regions) {
35153        var $$ = this.internal, config = $$.config;
35154        if (!regions) { return config.regions; }
35155        config.regions = regions;
35156        $$.redraw();
35157        return config.regions;
35158    };
35159    c3_chart_fn.regions.add = function (regions) {
35160        var $$ = this.internal, config = $$.config;
35161        if (!regions) { return config.regions; }
35162        config.regions = config.regions.concat(regions);
35163        $$.redraw();
35164        return config.regions;
35165    };
35166    c3_chart_fn.regions.remove = function (options) {
35167        var $$ = this.internal, config = $$.config,
35168            duration, classes, regions;
35169
35170        options = options || {};
35171        duration = $$.getOption(options, "duration", config.transition_duration);
35172        classes = $$.getOption(options, "classes", [CLASS.region]);
35173
35174        regions = $$.main.select('.' + CLASS.regions).selectAll(classes.map(function (c) { return '.' + c; }));
35175        (duration ? regions.transition().duration(duration) : regions)
35176            .style('opacity', 0)
35177            .remove();
35178
35179        config.regions = config.regions.filter(function (region) {
35180            var found = false;
35181            if (!region.class) {
35182                return true;
35183            }
35184            region.class.split(' ').forEach(function (c) {
35185                if (classes.indexOf(c) >= 0) { found = true; }
35186            });
35187            return !found;
35188        });
35189
35190        return config.regions;
35191    };
35192
35193    c3_chart_fn.data = function () {};
35194    c3_chart_fn.data.get = function (targetId) {
35195        var target = this.data.getAsTarget(targetId);
35196        return isDefined(target) ? target.values.map(function (d) { return d.value; }) : undefined;
35197    };
35198    c3_chart_fn.data.getAsTarget = function (targetId) {
35199        var targets = this.data.targets.filter(function (t) { return t.id === targetId; });
35200        return targets.length > 0 ? targets[0] : undefined;
35201    };
35202    c3_chart_fn.data.names = function (names) {
35203        var $$ = this.internal, config = $$.config;
35204        if (!arguments.length) { return config.data_names; }
35205        Object.keys(names).forEach(function (id) {
35206            config.data_names[id] = names[id];
35207        });
35208        $$.redraw({withLegend: true});
35209        return config.data_names;
35210    };
35211    c3_chart_fn.data.colors = function (colors) {
35212        var $$ = this.internal, config = $$.config;
35213        if (!arguments.length) { return config.data_colors; }
35214        Object.keys(colors).forEach(function (id) {
35215            config.data_colors[id] = colors[id];
35216        });
35217        $$.redraw({withLegend: true});
35218        return config.data_colors;
35219    };
35220
35221    c3_chart_fn.category = function (i, category) {
35222        var $$ = this.internal, config = $$.config;
35223        if (arguments.length > 1) {
35224            config.axis_x_categories[i] = category;
35225            $$.redraw();
35226        }
35227        return config.axis_x_categories[i];
35228    };
35229    c3_chart_fn.categories = function (categories) {
35230        var $$ = this.internal, config = $$.config;
35231        if (!arguments.length) { return config.axis_x_categories; }
35232        config.axis_x_categories = categories;
35233        $$.redraw();
35234        return config.axis_x_categories;
35235    };
35236
35237    // TODO: fix
35238    c3_chart_fn.color = function (id) {
35239        var $$ = this.internal;
35240        return $$.color(id); // more patterns
35241    };
35242
35243    c3_chart_fn.x = function (x) {
35244        var $$ = this.internal;
35245        if (arguments.length) {
35246            $$.updateTargetX($$.data.targets, x);
35247            $$.redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true});
35248        }
35249        return $$.data.xs;
35250    };
35251    c3_chart_fn.xs = function (xs) {
35252        var $$ = this.internal;
35253        if (arguments.length) {
35254            $$.updateTargetXs($$.data.targets, xs);
35255            $$.redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true});
35256        }
35257        return $$.data.xs;
35258    };
35259
35260    c3_chart_fn.axis = function () {};
35261    c3_chart_fn.axis.labels = function (labels) {
35262        var $$ = this.internal;
35263        if (arguments.length) {
35264            Object.keys(labels).forEach(function (axisId) {
35265                $$.setAxisLabelText(axisId, labels[axisId]);
35266            });
35267            $$.updateAxisLabels();
35268        }
35269        // TODO: return some values?
35270    };
35271    c3_chart_fn.axis.max = function (max) {
35272        var $$ = this.internal, config = $$.config;
35273        if (arguments.length) {
35274            if (typeof max === 'object') {
35275                if (isValue(max.x)) { config.axis_x_max = max.x; }
35276                if (isValue(max.y)) { config.axis_y_max = max.y; }
35277                if (isValue(max.y2)) { config.axis_y2_max = max.y2; }
35278            } else {
35279                config.axis_y_max = config.axis_y2_max = max;
35280            }
35281            $$.redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true});
35282        }
35283    };
35284    c3_chart_fn.axis.min = function (min) {
35285        var $$ = this.internal, config = $$.config;
35286        if (arguments.length) {
35287            if (typeof min === 'object') {
35288                if (isValue(min.x)) { config.axis_x_min = min.x; }
35289                if (isValue(min.y)) { config.axis_y_min = min.y; }
35290                if (isValue(min.y2)) { config.axis_y2_min = min.y2; }
35291            } else {
35292                config.axis_y_min = config.axis_y2_min = min;
35293            }
35294            $$.redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true});
35295        }
35296    };
35297    c3_chart_fn.axis.range = function (range) {
35298        if (arguments.length) {
35299            if (isDefined(range.max)) { this.axis.max(range.max); }
35300            if (isDefined(range.min)) { this.axis.min(range.min); }
35301        }
35302    };
35303
35304    c3_chart_fn.legend = function () {};
35305    c3_chart_fn.legend.show = function (targetIds) {
35306        var $$ = this.internal;
35307        $$.showLegend($$.mapToTargetIds(targetIds));
35308        $$.updateAndRedraw({withLegend: true});
35309    };
35310    c3_chart_fn.legend.hide = function (targetIds) {
35311        var $$ = this.internal;
35312        $$.hideLegend($$.mapToTargetIds(targetIds));
35313        $$.updateAndRedraw({withLegend: true});
35314    };
35315
35316    c3_chart_fn.resize = function (size) {
35317        var $$ = this.internal, config = $$.config;
35318        config.size_width = size ? size.width : null;
35319        config.size_height = size ? size.height : null;
35320        this.flush();
35321    };
35322
35323    c3_chart_fn.flush = function () {
35324        var $$ = this.internal;
35325        $$.updateAndRedraw({withLegend: true, withTransition: false, withTransitionForTransform: false});
35326    };
35327
35328    c3_chart_fn.destroy = function () {
35329        var $$ = this.internal;
35330        $$.data.targets = undefined;
35331        $$.data.xs = {};
35332        $$.selectChart.classed('c3', false).html("");
35333        window.onresize = null;
35334    };
35335
35336    // Features:
35337    // 1. category axis
35338    // 2. ceil values of translate/x/y to int for half pixel antialiasing
35339    function c3_axis(d3, isCategory) {
35340        var scale = d3.scale.linear(), orient = "bottom", innerTickSize = 6, outerTickSize = 6, tickPadding = 3, tickValues = null, tickFormat, tickArguments;
35341
35342        var tickOffset = 0, tickCulling = true, tickCentered;
35343
35344        function axisX(selection, x) {
35345            selection.attr("transform", function (d) {
35346                return "translate(" + Math.ceil(x(d) + tickOffset) + ", 0)";
35347            });
35348        }
35349        function axisY(selection, y) {
35350            selection.attr("transform", function (d) {
35351                return "translate(0," + Math.ceil(y(d)) + ")";
35352            });
35353        }
35354        function scaleExtent(domain) {
35355            var start = domain[0], stop = domain[domain.length - 1];
35356            return start < stop ? [ start, stop ] : [ stop, start ];
35357        }
35358        function generateTicks(scale) {
35359            var i, domain, ticks = [];
35360            if (scale.ticks) {
35361                return scale.ticks.apply(scale, tickArguments);
35362            }
35363            domain = scale.domain();
35364            for (i = Math.ceil(domain[0]); i < domain[1]; i++) {
35365                ticks.push(i);
35366            }
35367            if (ticks.length > 0 && ticks[0] > 0) {
35368                ticks.unshift(ticks[0] - (ticks[1] - ticks[0]));
35369            }
35370            return ticks;
35371        }
35372        function copyScale() {
35373            var newScale = scale.copy(), domain;
35374            if (isCategory) {
35375                domain = scale.domain();
35376                newScale.domain([domain[0], domain[1] - 1]);
35377            }
35378            return newScale;
35379        }
35380        function textFormatted(v) {
35381            return tickFormat ? tickFormat(v) : v;
35382        }
35383        function axis(g) {
35384            g.each(function () {
35385                var g = d3.select(this);
35386                var scale0 = this.__chart__ || scale, scale1 = this.__chart__ = copyScale();
35387
35388                var ticks = tickValues ? tickValues : generateTicks(scale1),
35389                    tick = g.selectAll(".tick").data(ticks, scale1),
35390                    tickEnter = tick.enter().insert("g", ".domain").attr("class", "tick").style("opacity", 1e-6),
35391                    // MEMO: No exit transition. The reason is this transition affects max tick width calculation because old tick will be included in the ticks.
35392                    tickExit = tick.exit().remove(),
35393                    tickUpdate = d3.transition(tick).style("opacity", 1),
35394                    tickTransform, tickX;
35395
35396                var range = scale.rangeExtent ? scale.rangeExtent() : scaleExtent(scale.range()),
35397                    path = g.selectAll(".domain").data([ 0 ]),
35398                    pathUpdate = (path.enter().append("path").attr("class", "domain"), d3.transition(path));
35399                tickEnter.append("line");
35400                tickEnter.append("text");
35401
35402                var lineEnter = tickEnter.select("line"),
35403                    lineUpdate = tickUpdate.select("line"),
35404                    text = tick.select("text").text(textFormatted),
35405                    textEnter = tickEnter.select("text"),
35406                    textUpdate = tickUpdate.select("text");
35407
35408                if (isCategory) {
35409                    tickOffset = Math.ceil((scale1(1) - scale1(0)) / 2);
35410                    tickX = tickCentered ? 0 : tickOffset;
35411                } else {
35412                    tickOffset = tickX = 0;
35413                }
35414
35415                function tickSize(d) {
35416                    var tickPosition = scale(d) + tickOffset;
35417                    return range[0] < tickPosition && tickPosition < range[1] ? innerTickSize : 0;
35418                }
35419
35420                switch (orient) {
35421                case "bottom":
35422                    {
35423                        tickTransform = axisX;
35424                        lineEnter.attr("y2", innerTickSize);
35425                        textEnter.attr("y", Math.max(innerTickSize, 0) + tickPadding);
35426                        lineUpdate.attr("x1", tickX).attr("x2", tickX).attr("y2", tickSize);
35427                        textUpdate.attr("x", 0).attr("y", Math.max(innerTickSize, 0) + tickPadding);
35428                        text.attr("dy", ".71em").style("text-anchor", "middle");
35429                        pathUpdate.attr("d", "M" + range[0] + "," + outerTickSize + "V0H" + range[1] + "V" + outerTickSize);
35430                        break;
35431                    }
35432                case "top":
35433                    {
35434                        tickTransform = axisX;
35435                        lineEnter.attr("y2", -innerTickSize);
35436                        textEnter.attr("y", -(Math.max(innerTickSize, 0) + tickPadding));
35437                        lineUpdate.attr("x2", 0).attr("y2", -innerTickSize);
35438                        textUpdate.attr("x", 0).attr("y", -(Math.max(innerTickSize, 0) + tickPadding));
35439                        text.attr("dy", "0em").style("text-anchor", "middle");
35440                        pathUpdate.attr("d", "M" + range[0] + "," + -outerTickSize + "V0H" + range[1] + "V" + -outerTickSize);
35441                        break;
35442                    }
35443                case "left":
35444                    {
35445                        tickTransform = axisY;
35446                        lineEnter.attr("x2", -innerTickSize);
35447                        textEnter.attr("x", -(Math.max(innerTickSize, 0) + tickPadding));
35448                        lineUpdate.attr("x2", -innerTickSize).attr("y2", 0);
35449                        textUpdate.attr("x", -(Math.max(innerTickSize, 0) + tickPadding)).attr("y", tickOffset);
35450                        text.attr("dy", ".32em").style("text-anchor", "end");
35451                        pathUpdate.attr("d", "M" + -outerTickSize + "," + range[0] + "H0V" + range[1] + "H" + -outerTickSize);
35452                        break;
35453                    }
35454                case "right":
35455                    {
35456                        tickTransform = axisY;
35457                        lineEnter.attr("x2", innerTickSize);
35458                        textEnter.attr("x", Math.max(innerTickSize, 0) + tickPadding);
35459                        lineUpdate.attr("x2", innerTickSize).attr("y2", 0);
35460                        textUpdate.attr("x", Math.max(innerTickSize, 0) + tickPadding).attr("y", 0);
35461                        text.attr("dy", ".32em").style("text-anchor", "start");
35462                        pathUpdate.attr("d", "M" + outerTickSize + "," + range[0] + "H0V" + range[1] + "H" + outerTickSize);
35463                        break;
35464                    }
35465                }
35466                if (scale1.rangeBand) {
35467                    var x = scale1, dx = x.rangeBand() / 2;
35468                    scale0 = scale1 = function (d) {
35469                        return x(d) + dx;
35470                    };
35471                } else if (scale0.rangeBand) {
35472                    scale0 = scale1;
35473                } else {
35474                    tickExit.call(tickTransform, scale1);
35475                }
35476                tickEnter.call(tickTransform, scale0);
35477                tickUpdate.call(tickTransform, scale1);
35478            });
35479        }
35480        axis.scale = function (x) {
35481            if (!arguments.length) { return scale; }
35482            scale = x;
35483            return axis;
35484        };
35485        axis.orient = function (x) {
35486            if (!arguments.length) { return orient; }
35487            orient = x in {top: 1, right: 1, bottom: 1, left: 1} ? x + "" : "bottom";
35488            return axis;
35489        };
35490        axis.tickFormat = function (format) {
35491            if (!arguments.length) { return tickFormat; }
35492            tickFormat = format;
35493            return axis;
35494        };
35495        axis.tickCentered = function (isCentered) {
35496            if (!arguments.length) { return tickCentered; }
35497            tickCentered = isCentered;
35498            return axis;
35499        };
35500        axis.tickOffset = function () { // This will be overwritten when normal x axis
35501            return tickOffset;
35502        };
35503        axis.ticks = function () {
35504            if (!arguments.length) { return tickArguments; }
35505            tickArguments = arguments;
35506            return axis;
35507        };
35508        axis.tickCulling = function (culling) {
35509            if (!arguments.length) { return tickCulling; }
35510            tickCulling = culling;
35511            return axis;
35512        };
35513        axis.tickValues = function (x) {
35514            if (typeof x === 'function') {
35515                tickValues = function () {
35516                    return x(scale.domain());
35517                };
35518            }
35519            else {
35520                if (!arguments.length) { return tickValues; }
35521                tickValues = x;
35522            }
35523            return axis;
35524        };
35525        return axis;
35526    }
35527
35528    if (typeof define === 'function' && define.amd) {
35529        define("c3", ["d3"], c3);
35530    } else if ('undefined' !== typeof exports && 'undefined' !== typeof module) {
35531        module.exports = c3;
35532    } else {
35533        window.c3 = c3;
35534    }
35535
35536})(window);
35537
35538/*
35539 * JavaScript Canvas to Blob
35540 * https://github.com/blueimp/JavaScript-Canvas-to-Blob
35541 *
35542 * Copyright 2012, Sebastian Tschan
35543 * https://blueimp.net
35544 *
35545 * Licensed under the MIT license:
35546 * https://opensource.org/licenses/MIT
35547 *
35548 * Based on stackoverflow user Stoive's code snippet:
35549 * http://stackoverflow.com/q/4998908
35550 */
35551
35552/* global define, Uint8Array, ArrayBuffer, module */
35553
35554;(function (window) {
35555  'use strict'
35556
35557  var CanvasPrototype =
35558    window.HTMLCanvasElement && window.HTMLCanvasElement.prototype
35559  var hasBlobConstructor =
35560    window.Blob &&
35561    (function () {
35562      try {
35563        return Boolean(new Blob())
35564      } catch (e) {
35565        return false
35566      }
35567    })()
35568  var hasArrayBufferViewSupport =
35569    hasBlobConstructor &&
35570    window.Uint8Array &&
35571    (function () {
35572      try {
35573        return new Blob([new Uint8Array(100)]).size === 100
35574      } catch (e) {
35575        return false
35576      }
35577    })()
35578  var BlobBuilder =
35579    window.BlobBuilder ||
35580    window.WebKitBlobBuilder ||
35581    window.MozBlobBuilder ||
35582    window.MSBlobBuilder
35583  var dataURIPattern = /^data:((.*?)(;charset=.*?)?)(;base64)?,/
35584  var dataURLtoBlob =
35585    (hasBlobConstructor || BlobBuilder) &&
35586    window.atob &&
35587    window.ArrayBuffer &&
35588    window.Uint8Array &&
35589    function (dataURI) {
35590      var matches,
35591        mediaType,
35592        isBase64,
35593        dataString,
35594        byteString,
35595        arrayBuffer,
35596        intArray,
35597        i,
35598        bb
35599      // Parse the dataURI components as per RFC 2397
35600      matches = dataURI.match(dataURIPattern)
35601      if (!matches) {
35602        throw new Error('invalid data URI')
35603      }
35604      // Default to text/plain;charset=US-ASCII
35605      mediaType = matches[2]
35606        ? matches[1]
35607        : 'text/plain' + (matches[3] || ';charset=US-ASCII')
35608      isBase64 = !!matches[4]
35609      dataString = dataURI.slice(matches[0].length)
35610      if (isBase64) {
35611        // Convert base64 to raw binary data held in a string:
35612        byteString = atob(dataString)
35613      } else {
35614        // Convert base64/URLEncoded data component to raw binary:
35615        byteString = decodeURIComponent(dataString)
35616      }
35617      // Write the bytes of the string to an ArrayBuffer:
35618      arrayBuffer = new ArrayBuffer(byteString.length)
35619      intArray = new Uint8Array(arrayBuffer)
35620      for (i = 0; i < byteString.length; i += 1) {
35621        intArray[i] = byteString.charCodeAt(i)
35622      }
35623      // Write the ArrayBuffer (or ArrayBufferView) to a blob:
35624      if (hasBlobConstructor) {
35625        return new Blob([hasArrayBufferViewSupport ? intArray : arrayBuffer], {
35626          type: mediaType
35627        })
35628      }
35629      bb = new BlobBuilder()
35630      bb.append(arrayBuffer)
35631      return bb.getBlob(mediaType)
35632    }
35633  if (window.HTMLCanvasElement && !CanvasPrototype.toBlob) {
35634    if (CanvasPrototype.mozGetAsFile) {
35635      CanvasPrototype.toBlob = function (callback, type, quality) {
35636        var self = this
35637        setTimeout(function () {
35638          if (quality && CanvasPrototype.toDataURL && dataURLtoBlob) {
35639            callback(dataURLtoBlob(self.toDataURL(type, quality)))
35640          } else {
35641            callback(self.mozGetAsFile('blob', type))
35642          }
35643        })
35644      }
35645    } else if (CanvasPrototype.toDataURL && dataURLtoBlob) {
35646      if (CanvasPrototype.msToBlob) {
35647        CanvasPrototype.toBlob = function (callback, type, quality) {
35648          var self = this
35649          setTimeout(function () {
35650            if (
35651              ((type && type !== 'image/png') || quality) &&
35652              CanvasPrototype.toDataURL &&
35653              dataURLtoBlob
35654            ) {
35655              callback(dataURLtoBlob(self.toDataURL(type, quality)))
35656            } else {
35657              callback(self.msToBlob(type))
35658            }
35659          })
35660        }
35661      } else {
35662        CanvasPrototype.toBlob = function (callback, type, quality) {
35663          var self = this
35664          setTimeout(function () {
35665            callback(dataURLtoBlob(self.toDataURL(type, quality)))
35666          })
35667        }
35668      }
35669    }
35670  }
35671  if (typeof define === 'function' && define.amd) {
35672    define('canvas-to-blob',[],function () {
35673      return dataURLtoBlob
35674    })
35675  } else if (typeof module === 'object' && module.exports) {
35676    module.exports = dataURLtoBlob
35677  } else {
35678    window.dataURLtoBlob = dataURLtoBlob
35679  }
35680})(window)
35681;
35682(function() {
35683  var $, AbstractChosen, Chosen, SelectParser, _ref,
35684    __hasProp = {}.hasOwnProperty,
35685    __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; };
35686
35687  SelectParser = (function() {
35688    function SelectParser() {
35689      this.options_index = 0;
35690      this.parsed = [];
35691    }
35692
35693    SelectParser.prototype.add_node = function(child) {
35694      if (child.nodeName.toUpperCase() === "OPTGROUP") {
35695        return this.add_group(child);
35696      } else {
35697        return this.add_option(child);
35698      }
35699    };
35700
35701    SelectParser.prototype.add_group = function(group) {
35702      var group_position, option, _i, _len, _ref, _results;
35703      group_position = this.parsed.length;
35704      this.parsed.push({
35705        array_index: group_position,
35706        group: true,
35707        label: this.escapeExpression(group.label),
35708        title: group.title ? group.title : void 0,
35709        children: 0,
35710        disabled: group.disabled,
35711        classes: group.className
35712      });
35713      _ref = group.childNodes;
35714      _results = [];
35715      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
35716        option = _ref[_i];
35717        _results.push(this.add_option(option, group_position, group.disabled));
35718      }
35719      return _results;
35720    };
35721
35722    SelectParser.prototype.add_option = function(option, group_position, group_disabled) {
35723      if (option.nodeName.toUpperCase() === "OPTION") {
35724        if (option.text !== "") {
35725          if (group_position != null) {
35726            this.parsed[group_position].children += 1;
35727          }
35728          this.parsed.push({
35729            array_index: this.parsed.length,
35730            options_index: this.options_index,
35731            value: option.value,
35732            text: option.text,
35733            html: option.innerHTML,
35734            title: option.title ? option.title : void 0,
35735            selected: option.selected,
35736            disabled: group_disabled === true ? group_disabled : option.disabled,
35737            group_array_index: group_position,
35738            group_label: group_position != null ? this.parsed[group_position].label : null,
35739            classes: option.className,
35740            style: option.style.cssText
35741          });
35742        } else {
35743          this.parsed.push({
35744            array_index: this.parsed.length,
35745            options_index: this.options_index,
35746            empty: true
35747          });
35748        }
35749        return this.options_index += 1;
35750      }
35751    };
35752
35753    SelectParser.prototype.escapeExpression = function(text) {
35754      var map, unsafe_chars;
35755      if ((text == null) || text === false) {
35756        return "";
35757      }
35758      if (!/[\&\<\>\"\'\`]/.test(text)) {
35759        return text;
35760      }
35761      map = {
35762        "<": "&lt;",
35763        ">": "&gt;",
35764        '"': "&quot;",
35765        "'": "&#x27;",
35766        "`": "&#x60;"
35767      };
35768      unsafe_chars = /&(?!\w+;)|[\<\>\"\'\`]/g;
35769      return text.replace(unsafe_chars, function(chr) {
35770        return map[chr] || "&amp;";
35771      });
35772    };
35773
35774    return SelectParser;
35775
35776  })();
35777
35778  SelectParser.select_to_array = function(select) {
35779    var child, parser, _i, _len, _ref;
35780    parser = new SelectParser();
35781    _ref = select.childNodes;
35782    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
35783      child = _ref[_i];
35784      parser.add_node(child);
35785    }
35786    return parser.parsed;
35787  };
35788
35789  AbstractChosen = (function() {
35790    function AbstractChosen(form_field, options) {
35791      this.form_field = form_field;
35792      this.options = options != null ? options : {};
35793      if (!AbstractChosen.browser_is_supported()) {
35794        return;
35795      }
35796      this.is_multiple = this.form_field.multiple;
35797      this.set_default_text();
35798      this.set_default_values();
35799      this.setup();
35800      this.set_up_html();
35801      this.register_observers();
35802      this.on_ready();
35803    }
35804
35805    AbstractChosen.prototype.set_default_values = function() {
35806      var _this = this;
35807      this.click_test_action = function(evt) {
35808        return _this.test_active_click(evt);
35809      };
35810      this.activate_action = function(evt) {
35811        return _this.activate_field(evt);
35812      };
35813      this.active_field = false;
vendor: 13,148 bytes, lines 35814-36173
35814      this.mouse_on_container = false;
35815      this.results_showing = false;
35816      this.result_highlighted = null;
35817      this.allow_single_deselect = (this.options.allow_single_deselect != null) && (this.form_field.options[0] != null) && this.form_field.options[0].text === "" ? this.options.allow_single_deselect : false;
35818      this.disable_search_threshold = this.options.disable_search_threshold || 0;
35819      this.disable_search = this.options.disable_search || false;
35820      this.enable_split_word_search = this.options.enable_split_word_search != null ? this.options.enable_split_word_search : true;
35821      this.group_search = this.options.group_search != null ? this.options.group_search : true;
35822      this.search_contains = this.options.search_contains || false;
35823      this.single_backstroke_delete = this.options.single_backstroke_delete != null ? this.options.single_backstroke_delete : true;
35824      this.max_selected_options = this.options.max_selected_options || Infinity;
35825      this.inherit_select_classes = this.options.inherit_select_classes || false;
35826      this.display_selected_options = this.options.display_selected_options != null ? this.options.display_selected_options : true;
35827      this.display_disabled_options = this.options.display_disabled_options != null ? this.options.display_disabled_options : true;
35828      this.include_group_label_in_selected = this.options.include_group_label_in_selected || false;
35829      this.max_shown_results = this.options.max_shown_results || Number.POSITIVE_INFINITY;
35830      return this.case_sensitive_search = this.options.case_sensitive_search || false;
35831    };
35832
35833    AbstractChosen.prototype.set_default_text = function() {
35834      if (this.form_field.getAttribute("data-placeholder")) {
35835        this.default_text = this.form_field.getAttribute("data-placeholder");
35836      } else if (this.is_multiple) {
35837        this.default_text = this.options.placeholder_text_multiple || this.options.placeholder_text || AbstractChosen.default_multiple_text;
35838      } else {
35839        this.default_text = this.options.placeholder_text_single || this.options.placeholder_text || AbstractChosen.default_single_text;
35840      }
35841      return this.results_none_found = this.form_field.getAttribute("data-no_results_text") || this.options.no_results_text || AbstractChosen.default_no_result_text;
35842    };
35843
35844    AbstractChosen.prototype.choice_label = function(item) {
35845      if (this.include_group_label_in_selected && (item.group_label != null)) {
35846        return "<b class='group-name'>" + item.group_label + "</b>" + item.html;
35847      } else {
35848        return item.html;
35849      }
35850    };
35851
35852    AbstractChosen.prototype.mouse_enter = function() {
35853      return this.mouse_on_container = true;
35854    };
35855
35856    AbstractChosen.prototype.mouse_leave = function() {
35857      return this.mouse_on_container = false;
35858    };
35859
35860    AbstractChosen.prototype.input_focus = function(evt) {
35861      var _this = this;
35862      if (this.is_multiple) {
35863        if (!this.active_field) {
35864          return setTimeout((function() {
35865            return _this.container_mousedown();
35866          }), 50);
35867        }
35868      } else {
35869        if (!this.active_field) {
35870          return this.activate_field();
35871        }
35872      }
35873    };
35874
35875    AbstractChosen.prototype.input_blur = function(evt) {
35876      var _this = this;
35877      if (!this.mouse_on_container) {
35878        this.active_field = false;
35879        return setTimeout((function() {
35880          return _this.blur_test();
35881        }), 100);
35882      }
35883    };
35884
35885    AbstractChosen.prototype.results_option_build = function(options) {
35886      var content, data, data_content, shown_results, _i, _len, _ref;
35887      content = '';
35888      shown_results = 0;
35889      _ref = this.results_data;
35890      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
35891        data = _ref[_i];
35892        data_content = '';
35893        if (data.group) {
35894          data_content = this.result_add_group(data);
35895        } else {
35896          data_content = this.result_add_option(data);
35897        }
35898        if (data_content !== '') {
35899          shown_results++;
35900          content += data_content;
35901        }
35902        if (options != null ? options.first : void 0) {
35903          if (data.selected && this.is_multiple) {
35904            this.choice_build(data);
35905          } else if (data.selected && !this.is_multiple) {
35906            this.single_set_selected_text(this.choice_label(data));
35907          }
35908        }
35909        if (shown_results >= this.max_shown_results) {
35910          break;
35911        }
35912      }
35913      return content;
35914    };
35915
35916    AbstractChosen.prototype.result_add_option = function(option) {
35917      var classes, option_el;
35918      if (!option.search_match) {
35919        return '';
35920      }
35921      if (!this.include_option_in_results(option)) {
35922        return '';
35923      }
35924      classes = [];
35925      if (!option.disabled && !(option.selected && this.is_multiple)) {
35926        classes.push("active-result");
35927      }
35928      if (option.disabled && !(option.selected && this.is_multiple)) {
35929        classes.push("disabled-result");
35930      }
35931      if (option.selected) {
35932        classes.push("result-selected");
35933      }
35934      if (option.group_array_index != null) {
35935        classes.push("group-option");
35936      }
35937      if (option.classes !== "") {
35938        classes.push(option.classes);
35939      }
35940      option_el = document.createElement("li");
35941      option_el.className = classes.join(" ");
35942      option_el.style.cssText = option.style;
35943      option_el.setAttribute("data-option-array-index", option.array_index);
35944      option_el.innerHTML = option.search_text;
35945      if (option.title) {
35946        option_el.title = option.title;
35947      }
35948      return this.outerHTML(option_el);
35949    };
35950
35951    AbstractChosen.prototype.result_add_group = function(group) {
35952      var classes, group_el;
35953      if (!(group.search_match || group.group_match)) {
35954        return '';
35955      }
35956      if (!(group.active_options > 0)) {
35957        return '';
35958      }
35959      classes = [];
35960      classes.push("group-result");
35961      if (group.classes) {
35962        classes.push(group.classes);
35963      }
35964      group_el = document.createElement("li");
35965      group_el.className = classes.join(" ");
35966      group_el.innerHTML = group.search_text;
35967      if (group.title) {
35968        group_el.title = group.title;
35969      }
35970      return this.outerHTML(group_el);
35971    };
35972
35973    AbstractChosen.prototype.results_update_field = function() {
35974      this.set_default_text();
35975      if (!this.is_multiple) {
35976        this.results_reset_cleanup();
35977      }
35978      this.result_clear_highlight();
35979      this.results_build();
35980      if (this.results_showing) {
35981        return this.winnow_results();
35982      }
35983    };
35984
35985    AbstractChosen.prototype.reset_single_select_options = function() {
35986      var result, _i, _len, _ref, _results;
35987      _ref = this.results_data;
35988      _results = [];
35989      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
35990        result = _ref[_i];
35991        if (result.selected) {
35992          _results.push(result.selected = false);
35993        } else {
35994          _results.push(void 0);
35995        }
35996      }
35997      return _results;
35998    };
35999
36000    AbstractChosen.prototype.results_toggle = function() {
36001      if (this.results_showing) {
36002        return this.results_hide();
36003      } else {
36004        return this.results_show();
36005      }
36006    };
36007
36008    AbstractChosen.prototype.results_search = function(evt) {
36009      if (this.results_showing) {
36010        return this.winnow_results();
36011      } else {
36012        return this.results_show();
36013      }
36014    };
36015
36016    AbstractChosen.prototype.winnow_results = function() {
36017      var escapedSearchText, option, regex, results, results_group, searchText, startpos, text, zregex, _i, _len, _ref;
36018      this.no_results_clear();
36019      results = 0;
36020      searchText = this.get_search_text();
36021      escapedSearchText = searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
36022      zregex = new RegExp(escapedSearchText, 'i');
36023      regex = this.get_search_regex(escapedSearchText);
36024      _ref = this.results_data;
36025      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
36026        option = _ref[_i];
36027        option.search_match = false;
36028        results_group = null;
36029        if (this.include_option_in_results(option)) {
36030          if (option.group) {
36031            option.group_match = false;
36032            option.active_options = 0;
36033          }
36034          if ((option.group_array_index != null) && this.results_data[option.group_array_index]) {
36035            results_group = this.results_data[option.group_array_index];
36036            if (results_group.active_options === 0 && results_group.search_match) {
36037              results += 1;
36038            }
36039            results_group.active_options += 1;
36040          }
36041          option.search_text = option.group ? option.label : option.html;
36042          if (!(option.group && !this.group_search)) {
36043            option.search_match = this.search_string_match(option.search_text, regex);
36044            if (option.search_match && !option.group) {
36045              results += 1;
36046            }
36047            if (option.search_match) {
36048              if (searchText.length) {
36049                startpos = option.search_text.search(zregex);
36050                text = option.search_text.substr(0, startpos + searchText.length) + '</em>' + option.search_text.substr(startpos + searchText.length);
36051                option.search_text = text.substr(0, startpos) + '<em>' + text.substr(startpos);
36052              }
36053              if (results_group != null) {
36054                results_group.group_match = true;
36055              }
36056            } else if ((option.group_array_index != null) && this.results_data[option.group_array_index].search_match) {
36057              option.search_match = true;
36058            }
36059          }
36060        }
36061      }
36062      this.result_clear_highlight();
36063      if (results < 1 && searchText.length) {
36064        this.update_results_content("");
36065        return this.no_results(searchText);
36066      } else {
36067        this.update_results_content(this.results_option_build());
36068        return this.winnow_results_set_highlight();
36069      }
36070    };
36071
36072    AbstractChosen.prototype.get_search_regex = function(escaped_search_string) {
36073      var regex_anchor, regex_flag;
36074      regex_anchor = this.search_contains ? "" : "^";
36075      regex_flag = this.case_sensitive_search ? "" : "i";
36076      return new RegExp(regex_anchor + escaped_search_string, regex_flag);
36077    };
36078
36079    AbstractChosen.prototype.search_string_match = function(search_string, regex) {
36080      var part, parts, _i, _len;
36081      if (regex.test(search_string)) {
36082        return true;
36083      } else if (this.enable_split_word_search && (search_string.indexOf(" ") >= 0 || search_string.indexOf("[") === 0)) {
36084        parts = search_string.replace(/\[|\]/g, "").split(" ");
36085        if (parts.length) {
36086          for (_i = 0, _len = parts.length; _i < _len; _i++) {
36087            part = parts[_i];
36088            if (regex.test(part)) {
36089              return true;
36090            }
36091          }
36092        }
36093      }
36094    };
36095
36096    AbstractChosen.prototype.choices_count = function() {
36097      var option, _i, _len, _ref;
36098      if (this.selected_option_count != null) {
36099        return this.selected_option_count;
36100      }
36101      this.selected_option_count = 0;
36102      _ref = this.form_field.options;
36103      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
36104        option = _ref[_i];
36105        if (option.selected) {
36106          this.selected_option_count += 1;
36107        }
36108      }
36109      return this.selected_option_count;
36110    };
36111
36112    AbstractChosen.prototype.choices_click = function(evt) {
36113      evt.preventDefault();
36114      if (!(this.results_showing || this.is_disabled)) {
36115        return this.results_show();
36116      }
36117    };
36118
36119    AbstractChosen.prototype.keyup_checker = function(evt) {
36120      var stroke, _ref;
36121      stroke = (_ref = evt.which) != null ? _ref : evt.keyCode;
36122      this.search_field_scale();
36123      switch (stroke) {
36124        case 8:
36125          if (this.is_multiple && this.backstroke_length < 1 && this.choices_count() > 0) {
36126            return this.keydown_backstroke();
36127          } else if (!this.pending_backstroke) {
36128            this.result_clear_highlight();
36129            return this.results_search();
36130          }
36131          break;
36132        case 13:
36133          evt.preventDefault();
36134          if (this.results_showing) {
36135            return this.result_select(evt);
36136          }
36137          break;
36138        case 27:
36139          if (this.results_showing) {
36140            this.results_hide();
36141          }
36142          return true;
36143        case 9:
36144        case 38:
36145        case 40:
36146        case 16:
36147        case 91:
36148        case 17:
36149        case 18:
36150          break;
36151        default:
36152          return this.results_search();
36153      }
36154    };
36155
36156    AbstractChosen.prototype.clipboard_event_checker = function(evt) {
36157      var _this = this;
36158      return setTimeout((function() {
36159        return _this.results_search();
36160      }), 50);
36161    };
36162
36163    AbstractChosen.prototype.container_width = function() {
36164      if (this.options.width != null) {
36165        return this.options.width;
36166      } else {
36167        return "" + this.form_field.offsetWidth + "px";
36168      }
36169    };
36170
36171    AbstractChosen.prototype.include_option_in_results = function(option) {
36172      if (this.is_multiple && (!this.display_selected_options && option.selected)) {
36173        return false;
vendor: 1,446 bytes, lines 36174-36215
36174      }
36175      if (!this.display_disabled_options && option.disabled) {
36176        return false;
36177      }
36178      if (option.empty) {
36179        return false;
36180      }
36181      return true;
36182    };
36183
36184    AbstractChosen.prototype.search_results_touchstart = function(evt) {
36185      this.touch_started = true;
36186      return this.search_results_mouseover(evt);
36187    };
36188
36189    AbstractChosen.prototype.search_results_touchmove = function(evt) {
36190      this.touch_started = false;
36191      return this.search_results_mouseout(evt);
36192    };
36193
36194    AbstractChosen.prototype.search_results_touchend = function(evt) {
36195      if (this.touch_started) {
36196        return this.search_results_mouseup(evt);
36197      }
36198    };
36199
36200    AbstractChosen.prototype.outerHTML = function(element) {
36201      var tmp;
36202      if (element.outerHTML) {
36203        return element.outerHTML;
36204      }
36205      tmp = document.createElement("div");
36206      tmp.appendChild(element);
36207      return tmp.innerHTML;
36208    };
36209
36210    AbstractChosen.browser_is_supported = function() {
36211      if ("Microsoft Internet Explorer" === window.navigator.appName) {
36212        return document.documentMode >= 8;
36213      }
36214      if (/iP(od|hone)/i.test(window.navigator.userAgent) || /IEMobile/i.test(window.navigator.userAgent) || /Windows Phone/i.test(window.navigator.userAgent) || /BlackBerry/i.test(window.navigator.userAgent) || /BB10/i.test(window.navigator.userAgent) || /Android.*Mobile/i.test(window.navigator.userAgent)) {
36215        return false
vendor: 25,590 bytes, lines 36215-36938
36215;
36216      }
36217      return true;
36218    };
36219
36220    AbstractChosen.default_multiple_text = "Select Some Options";
36221
36222    AbstractChosen.default_single_text = "Select an Option";
36223
36224    AbstractChosen.default_no_result_text = "No results match";
36225
36226    return AbstractChosen;
36227
36228  })();
36229
36230  $ = jQuery;
36231
36232  $.fn.extend({
36233    chosen: function(options) {
36234      if (!AbstractChosen.browser_is_supported()) {
36235        return this;
36236      }
36237      return this.each(function(input_field) {
36238        var $this, chosen;
36239        $this = $(this);
36240        chosen = $this.data('chosen');
36241        if (options === 'destroy') {
36242          if (chosen instanceof Chosen) {
36243            chosen.destroy();
36244          }
36245          return;
36246        }
36247        if (!(chosen instanceof Chosen)) {
36248          $this.data('chosen', new Chosen(this, options));
36249        }
36250      });
36251    }
36252  });
36253
36254  Chosen = (function(_super) {
36255    __extends(Chosen, _super);
36256
36257    function Chosen() {
36258      _ref = Chosen.__super__.constructor.apply(this, arguments);
36259      return _ref;
36260    }
36261
36262    Chosen.prototype.setup = function() {
36263      this.form_field_jq = $(this.form_field);
36264      this.current_selectedIndex = this.form_field.selectedIndex;
36265      return this.is_rtl = this.form_field_jq.hasClass("chosen-rtl");
36266    };
36267
36268    Chosen.prototype.set_up_html = function() {
36269      var container_classes, container_props;
36270      container_classes = ["chosen-container"];
36271      container_classes.push("chosen-container-" + (this.is_multiple ? "multi" : "single"));
36272      if (this.inherit_select_classes && this.form_field.className) {
36273        container_classes.push(this.form_field.className);
36274      }
36275      if (this.is_rtl) {
36276        container_classes.push("chosen-rtl");
36277      }
36278      container_props = {
36279        'class': container_classes.join(' '),
36280        'style': "width: " + (this.container_width()) + ";",
36281        'title': this.form_field.title
36282      };
36283      if (this.form_field.id.length) {
36284        container_props.id = this.form_field.id.replace(/[^\w]/g, '_') + "_chosen";
36285      }
36286      this.container = $("<div />", container_props);
36287      if (this.is_multiple) {
36288        this.container.html('<ul class="chosen-choices"><li class="search-field"><input type="text" value="' + this.default_text + '" class="default" autocomplete="off" style="width:25px;" /></li></ul><div class="chosen-drop"><ul class="chosen-results"></ul></div>');
36289      } else {
36290        this.container.html('<a class="chosen-single chosen-default"><span>' + this.default_text + '</span><div><b></b></div></a><div class="chosen-drop"><div class="chosen-search"><input type="text" autocomplete="off" /></div><ul class="chosen-results"></ul></div>');
36291      }
36292      this.form_field_jq.hide().after(this.container);
36293      this.dropdown = this.container.find('div.chosen-drop').first();
36294      this.search_field = this.container.find('input').first();
36295      this.search_results = this.container.find('ul.chosen-results').first();
36296      this.search_field_scale();
36297      this.search_no_results = this.container.find('li.no-results').first();
36298      if (this.is_multiple) {
36299        this.search_choices = this.container.find('ul.chosen-choices').first();
36300        this.search_container = this.container.find('li.search-field').first();
36301      } else {
36302        this.search_container = this.container.find('div.chosen-search').first();
36303        this.selected_item = this.container.find('.chosen-single').first();
36304      }
36305      this.results_build();
36306      this.set_tab_index();
36307      return this.set_label_behavior();
36308    };
36309
36310    Chosen.prototype.on_ready = function() {
36311      return this.form_field_jq.trigger("chosen:ready", {
36312        chosen: this
36313      });
36314    };
36315
36316    Chosen.prototype.register_observers = function() {
36317      var _this = this;
36318      this.container.bind('touchstart.chosen', function(evt) {
36319        _this.container_mousedown(evt);
36320        return evt.preventDefault();
36321      });
36322      this.container.bind('touchend.chosen', function(evt) {
36323        _this.container_mouseup(evt);
36324        return evt.preventDefault();
36325      });
36326      this.container.bind('mousedown.chosen', function(evt) {
36327        _this.container_mousedown(evt);
36328      });
36329      this.container.bind('mouseup.chosen', function(evt) {
36330        _this.container_mouseup(evt);
36331      });
36332      this.container.bind('mouseenter.chosen', function(evt) {
36333        _this.mouse_enter(evt);
36334      });
36335      this.container.bind('mouseleave.chosen', function(evt) {
36336        _this.mouse_leave(evt);
36337      });
36338      this.search_results.bind('mouseup.chosen', function(evt) {
36339        _this.search_results_mouseup(evt);
36340      });
36341      this.search_results.bind('mouseover.chosen', function(evt) {
36342        _this.search_results_mouseover(evt);
36343      });
36344      this.search_results.bind('mouseout.chosen', function(evt) {
36345        _this.search_results_mouseout(evt);
36346      });
36347      this.search_results.bind('mousewheel.chosen DOMMouseScroll.chosen', function(evt) {
36348        _this.search_results_mousewheel(evt);
36349      });
36350      this.search_results.bind('touchstart.chosen', function(evt) {
36351        _this.search_results_touchstart(evt);
36352      });
36353      this.search_results.bind('touchmove.chosen', function(evt) {
36354        _this.search_results_touchmove(evt);
36355      });
36356      this.search_results.bind('touchend.chosen', function(evt) {
36357        _this.search_results_touchend(evt);
36358      });
36359      this.form_field_jq.bind("chosen:updated.chosen", function(evt) {
36360        _this.results_update_field(evt);
36361      });
36362      this.form_field_jq.bind("chosen:activate.chosen", function(evt) {
36363        _this.activate_field(evt);
36364      });
36365      this.form_field_jq.bind("chosen:open.chosen", function(evt) {
36366        _this.container_mousedown(evt);
36367      });
36368      this.form_field_jq.bind("chosen:close.chosen", function(evt) {
36369        _this.input_blur(evt);
36370      });
36371      this.search_field.bind('blur.chosen', function(evt) {
36372        _this.input_blur(evt);
36373      });
36374      this.search_field.bind('keyup.chosen', function(evt) {
36375        _this.keyup_checker(evt);
36376      });
36377      this.search_field.bind('keydown.chosen', function(evt) {
36378        _this.keydown_checker(evt);
36379      });
36380      this.search_field.bind('focus.chosen', function(evt) {
36381        _this.input_focus(evt);
36382      });
36383      this.search_field.bind('cut.chosen', function(evt) {
36384        _this.clipboard_event_checker(evt);
36385      });
36386      this.search_field.bind('paste.chosen', function(evt) {
36387        _this.clipboard_event_checker(evt);
36388      });
36389      if (this.is_multiple) {
36390        return this.search_choices.bind('click.chosen', function(evt) {
36391          _this.choices_click(evt);
36392        });
36393      } else {
36394        return this.container.bind('click.chosen', function(evt) {
36395          evt.preventDefault();
36396        });
36397      }
36398    };
36399
36400    Chosen.prototype.destroy = function() {
36401      $(this.container[0].ownerDocument).unbind("click.chosen", this.click_test_action);
36402      if (this.search_field[0].tabIndex) {
36403        this.form_field_jq[0].tabIndex = this.search_field[0].tabIndex;
36404      }
36405      this.container.remove();
36406      this.form_field_jq.removeData('chosen');
36407      return this.form_field_jq.show();
36408    };
36409
36410    Chosen.prototype.search_field_disabled = function() {
36411      this.is_disabled = this.form_field_jq[0].disabled;
36412      if (this.is_disabled) {
36413        this.container.addClass('chosen-disabled');
36414        this.search_field[0].disabled = true;
36415        if (!this.is_multiple) {
36416          this.selected_item.unbind("focus.chosen", this.activate_action);
36417        }
36418        return this.close_field();
36419      } else {
36420        this.container.removeClass('chosen-disabled');
36421        this.search_field[0].disabled = false;
36422        if (!this.is_multiple) {
36423          return this.selected_item.bind("focus.chosen", this.activate_action);
36424        }
36425      }
36426    };
36427
36428    Chosen.prototype.container_mousedown = function(evt) {
36429      if (!this.is_disabled) {
36430        if (evt && evt.type === "mousedown" && !this.results_showing) {
36431          evt.preventDefault();
36432        }
36433        if (!((evt != null) && ($(evt.target)).hasClass("search-choice-close"))) {
36434          if (!this.active_field) {
36435            if (this.is_multiple) {
36436              this.search_field.val("");
36437            }
36438            $(this.container[0].ownerDocument).bind('click.chosen', this.click_test_action);
36439            this.results_show();
36440          } else if (!this.is_multiple && evt && (($(evt.target)[0] === this.selected_item[0]) || $(evt.target).parents("a.chosen-single").length)) {
36441            evt.preventDefault();
36442            this.results_toggle();
36443          }
36444          return this.activate_field();
36445        }
36446      }
36447    };
36448
36449    Chosen.prototype.container_mouseup = function(evt) {
36450      if (evt.target.nodeName === "ABBR" && !this.is_disabled) {
36451        return this.results_reset(evt);
36452      }
36453    };
36454
36455    Chosen.prototype.search_results_mousewheel = function(evt) {
36456      var delta;
36457      if (evt.originalEvent) {
36458        delta = evt.originalEvent.deltaY || -evt.originalEvent.wheelDelta || evt.originalEvent.detail;
36459      }
36460      if (delta != null) {
36461        evt.preventDefault();
36462        if (evt.type === 'DOMMouseScroll') {
36463          delta = delta * 40;
36464        }
36465        return this.search_results.scrollTop(delta + this.search_results.scrollTop());
36466      }
36467    };
36468
36469    Chosen.prototype.blur_test = function(evt) {
36470      if (!this.active_field && this.container.hasClass("chosen-container-active")) {
36471        return this.close_field();
36472      }
36473    };
36474
36475    Chosen.prototype.close_field = function() {
36476      $(this.container[0].ownerDocument).unbind("click.chosen", this.click_test_action);
36477      this.active_field = false;
36478      this.results_hide();
36479      this.container.removeClass("chosen-container-active");
36480      this.clear_backstroke();
36481      this.show_search_field_default();
36482      return this.search_field_scale();
36483    };
36484
36485    Chosen.prototype.activate_field = function() {
36486      this.container.addClass("chosen-container-active");
36487      this.active_field = true;
36488      this.search_field.val(this.search_field.val());
36489      return this.search_field.focus();
36490    };
36491
36492    Chosen.prototype.test_active_click = function(evt) {
36493      var active_container;
36494      active_container = $(evt.target).closest('.chosen-container');
36495      if (active_container.length && this.container[0] === active_container[0]) {
36496        return this.active_field = true;
36497      } else {
36498        return this.close_field();
36499      }
36500    };
36501
36502    Chosen.prototype.results_build = function() {
36503      this.parsing = true;
36504      this.selected_option_count = null;
36505      this.results_data = SelectParser.select_to_array(this.form_field);
36506      if (this.is_multiple) {
36507        this.search_choices.find("li.search-choice").remove();
36508      } else if (!this.is_multiple) {
36509        this.single_set_selected_text();
36510        if (this.disable_search || this.form_field.options.length <= this.disable_search_threshold) {
36511          this.search_field[0].readOnly = true;
36512          this.container.addClass("chosen-container-single-nosearch");
36513        } else {
36514          this.search_field[0].readOnly = false;
36515          this.container.removeClass("chosen-container-single-nosearch");
36516        }
36517      }
36518      this.update_results_content(this.results_option_build({
36519        first: true
36520      }));
36521      this.search_field_disabled();
36522      this.show_search_field_default();
36523      this.search_field_scale();
36524      return this.parsing = false;
36525    };
36526
36527    Chosen.prototype.result_do_highlight = function(el) {
36528      var high_bottom, high_top, maxHeight, visible_bottom, visible_top;
36529      if (el.length) {
36530        this.result_clear_highlight();
36531        this.result_highlight = el;
36532        this.result_highlight.addClass("highlighted");
36533        maxHeight = parseInt(this.search_results.css("maxHeight"), 10);
36534        visible_top = this.search_results.scrollTop();
36535        visible_bottom = maxHeight + visible_top;
36536        high_top = this.result_highlight.position().top + this.search_results.scrollTop();
36537        high_bottom = high_top + this.result_highlight.outerHeight();
36538        if (high_bottom >= visible_bottom) {
36539          return this.search_results.scrollTop((high_bottom - maxHeight) > 0 ? high_bottom - maxHeight : 0);
36540        } else if (high_top < visible_top) {
36541          return this.search_results.scrollTop(high_top);
36542        }
36543      }
36544    };
36545
36546    Chosen.prototype.result_clear_highlight = function() {
36547      if (this.result_highlight) {
36548        this.result_highlight.removeClass("highlighted");
36549      }
36550      return this.result_highlight = null;
36551    };
36552
36553    Chosen.prototype.results_show = function() {
36554      if (this.is_multiple && this.max_selected_options <= this.choices_count()) {
36555        this.form_field_jq.trigger("chosen:maxselected", {
36556          chosen: this
36557        });
36558        return false;
36559      }
36560      this.container.addClass("chosen-with-drop");
36561      this.results_showing = true;
36562      this.search_field.focus();
36563      this.search_field.val(this.search_field.val());
36564      this.winnow_results();
36565      return this.form_field_jq.trigger("chosen:showing_dropdown", {
36566        chosen: this
36567      });
36568    };
36569
36570    Chosen.prototype.update_results_content = function(content) {
36571      return this.search_results.html(content);
36572    };
36573
36574    Chosen.prototype.results_hide = function() {
36575      if (this.results_showing) {
36576        this.result_clear_highlight();
36577        this.container.removeClass("chosen-with-drop");
36578        this.form_field_jq.trigger("chosen:hiding_dropdown", {
36579          chosen: this
36580        });
36581      }
36582      return this.results_showing = false;
36583    };
36584
36585    Chosen.prototype.set_tab_index = function(el) {
36586      var ti;
36587      if (this.form_field.tabIndex) {
36588        ti = this.form_field.tabIndex;
36589        this.form_field.tabIndex = -1;
36590        return this.search_field[0].tabIndex = ti;
36591      }
36592    };
36593
36594    Chosen.prototype.set_label_behavior = function() {
36595      var _this = this;
36596      this.form_field_label = this.form_field_jq.parents("label");
36597      if (!this.form_field_label.length && this.form_field.id.length) {
36598        this.form_field_label = $("label[for='" + this.form_field.id + "']");
36599      }
36600      if (this.form_field_label.length > 0) {
36601        return this.form_field_label.bind('click.chosen', function(evt) {
36602          if (_this.is_multiple) {
36603            return _this.container_mousedown(evt);
36604          } else {
36605            return _this.activate_field();
36606          }
36607        });
36608      }
36609    };
36610
36611    Chosen.prototype.show_search_field_default = function() {
36612      if (this.is_multiple && this.choices_count() < 1 && !this.active_field) {
36613        this.search_field.val(this.default_text);
36614        return this.search_field.addClass("default");
36615      } else {
36616        this.search_field.val("");
36617        return this.search_field.removeClass("default");
36618      }
36619    };
36620
36621    Chosen.prototype.search_results_mouseup = function(evt) {
36622      var target;
36623      target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first();
36624      if (target.length) {
36625        this.result_highlight = target;
36626        this.result_select(evt);
36627        return this.search_field.focus();
36628      }
36629    };
36630
36631    Chosen.prototype.search_results_mouseover = function(evt) {
36632      var target;
36633      target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first();
36634      if (target) {
36635        return this.result_do_highlight(target);
36636      }
36637    };
36638
36639    Chosen.prototype.search_results_mouseout = function(evt) {
36640      if ($(evt.target).hasClass("active-result" || $(evt.target).parents('.active-result').first())) {
36641        return this.result_clear_highlight();
36642      }
36643    };
36644
36645    Chosen.prototype.choice_build = function(item) {
36646      var choice, close_link,
36647        _this = this;
36648      choice = $('<li />', {
36649        "class": "search-choice"
36650      }).html("<span>" + (this.choice_label(item)) + "</span>");
36651      if (item.disabled) {
36652        choice.addClass('search-choice-disabled');
36653      } else {
36654        close_link = $('<a />', {
36655          "class": 'search-choice-close',
36656          'data-option-array-index': item.array_index
36657        });
36658        close_link.bind('click.chosen', function(evt) {
36659          return _this.choice_destroy_link_click(evt);
36660        });
36661        choice.append(close_link);
36662      }
36663      return this.search_container.before(choice);
36664    };
36665
36666    Chosen.prototype.choice_destroy_link_click = function(evt) {
36667      evt.preventDefault();
36668      evt.stopPropagation();
36669      if (!this.is_disabled) {
36670        return this.choice_destroy($(evt.target));
36671      }
36672    };
36673
36674    Chosen.prototype.choice_destroy = function(link) {
36675      if (this.result_deselect(link[0].getAttribute("data-option-array-index"))) {
36676        this.show_search_field_default();
36677        if (this.is_multiple && this.choices_count() > 0 && this.search_field.val().length < 1) {
36678          this.results_hide();
36679        }
36680        link.parents('li').first().remove();
36681        return this.search_field_scale();
36682      }
36683    };
36684
36685    Chosen.prototype.results_reset = function() {
36686      this.reset_single_select_options();
36687      this.form_field.options[0].selected = true;
36688      this.single_set_selected_text();
36689      this.show_search_field_default();
36690      this.results_reset_cleanup();
36691      this.form_field_jq.trigger("change");
36692      if (this.active_field) {
36693        return this.results_hide();
36694      }
36695    };
36696
36697    Chosen.prototype.results_reset_cleanup = function() {
36698      this.current_selectedIndex = this.form_field.selectedIndex;
36699      return this.selected_item.find("abbr").remove();
36700    };
36701
36702    Chosen.prototype.result_select = function(evt) {
36703      var high, item;
36704      if (this.result_highlight) {
36705        high = this.result_highlight;
36706        this.result_clear_highlight();
36707        if (this.is_multiple && this.max_selected_options <= this.choices_count()) {
36708          this.form_field_jq.trigger("chosen:maxselected", {
36709            chosen: this
36710          });
36711          return false;
36712        }
36713        if (this.is_multiple) {
36714          high.removeClass("active-result");
36715        } else {
36716          this.reset_single_select_options();
36717        }
36718        high.addClass("result-selected");
36719        item = this.results_data[high[0].getAttribute("data-option-array-index")];
36720        item.selected = true;
36721        this.form_field.options[item.options_index].selected = true;
36722        this.selected_option_count = null;
36723        if (this.is_multiple) {
36724          this.choice_build(item);
36725        } else {
36726          this.single_set_selected_text(this.choice_label(item));
36727        }
36728        if (!((evt.metaKey || evt.ctrlKey) && this.is_multiple)) {
36729          this.results_hide();
36730        }
36731        this.show_search_field_default();
36732        if (this.is_multiple || this.form_field.selectedIndex !== this.current_selectedIndex) {
36733          this.form_field_jq.trigger("change", {
36734            'selected': this.form_field.options[item.options_index].value
36735          });
36736        }
36737        this.current_selectedIndex = this.form_field.selectedIndex;
36738        evt.preventDefault();
36739        return this.search_field_scale();
36740      }
36741    };
36742
36743    Chosen.prototype.single_set_selected_text = function(text) {
36744      if (text == null) {
36745        text = this.default_text;
36746      }
36747      if (text === this.default_text) {
36748        this.selected_item.addClass("chosen-default");
36749      } else {
36750        this.single_deselect_control_build();
36751        this.selected_item.removeClass("chosen-default");
36752      }
36753      return this.selected_item.find("span").html(text);
36754    };
36755
36756    Chosen.prototype.result_deselect = function(pos) {
36757      var result_data;
36758      result_data = this.results_data[pos];
36759      if (!this.form_field.options[result_data.options_index].disabled) {
36760        result_data.selected = false;
36761        this.form_field.options[result_data.options_index].selected = false;
36762        this.selected_option_count = null;
36763        this.result_clear_highlight();
36764        if (this.results_showing) {
36765          this.winnow_results();
36766        }
36767        this.form_field_jq.trigger("change", {
36768          deselected: this.form_field.options[result_data.options_index].value
36769        });
36770        this.search_field_scale();
36771        return true;
36772      } else {
36773        return false;
36774      }
36775    };
36776
36777    Chosen.prototype.single_deselect_control_build = function() {
36778      if (!this.allow_single_deselect) {
36779        return;
36780      }
36781      if (!this.selected_item.find("abbr").length) {
36782        this.selected_item.find("span").first().after("<abbr class=\"search-choice-close\"></abbr>");
36783      }
36784      return this.selected_item.addClass("chosen-single-with-deselect");
36785    };
36786
36787    Chosen.prototype.get_search_text = function() {
36788      return $('<div/>').text($.trim(this.search_field.val())).html();
36789    };
36790
36791    Chosen.prototype.winnow_results_set_highlight = function() {
36792      var do_high, selected_results;
36793      selected_results = !this.is_multiple ? this.search_results.find(".result-selected.active-result") : [];
36794      do_high = selected_results.length ? selected_results.first() : this.search_results.find(".active-result").first();
36795      if (do_high != null) {
36796        return this.result_do_highlight(do_high);
36797      }
36798    };
36799
36800    Chosen.prototype.no_results = function(terms) {
36801      var no_results_html;
36802      no_results_html = $('<li class="no-results">' + this.results_none_found + ' "<span></span>"</li>');
36803      no_results_html.find("span").first().html(terms);
36804      this.search_results.append(no_results_html);
36805      return this.form_field_jq.trigger("chosen:no_results", {
36806        chosen: this
36807      });
36808    };
36809
36810    Chosen.prototype.no_results_clear = function() {
36811      return this.search_results.find(".no-results").remove();
36812    };
36813
36814    Chosen.prototype.keydown_arrow = function() {
36815      var next_sib;
36816      if (this.results_showing && this.result_highlight) {
36817        next_sib = this.result_highlight.nextAll("li.active-result").first();
36818        if (next_sib) {
36819          return this.result_do_highlight(next_sib);
36820        }
36821      } else {
36822        return this.results_show();
36823      }
36824    };
36825
36826    Chosen.prototype.keyup_arrow = function() {
36827      var prev_sibs;
36828      if (!this.results_showing && !this.is_multiple) {
36829        return this.results_show();
36830      } else if (this.result_highlight) {
36831        prev_sibs = this.result_highlight.prevAll("li.active-result");
36832        if (prev_sibs.length) {
36833          return this.result_do_highlight(prev_sibs.first());
36834        } else {
36835          if (this.choices_count() > 0) {
36836            this.results_hide();
36837          }
36838          return this.result_clear_highlight();
36839        }
36840      }
36841    };
36842
36843    Chosen.prototype.keydown_backstroke = function() {
36844      var next_available_destroy;
36845      if (this.pending_backstroke) {
36846        this.choice_destroy(this.pending_backstroke.find("a").first());
36847        return this.clear_backstroke();
36848      } else {
36849        next_available_destroy = this.search_container.siblings("li.search-choice").last();
36850        if (next_available_destroy.length && !next_available_destroy.hasClass("search-choice-disabled")) {
36851          this.pending_backstroke = next_available_destroy;
36852          if (this.single_backstroke_delete) {
36853            return this.keydown_backstroke();
36854          } else {
36855            return this.pending_backstroke.addClass("search-choice-focus");
36856          }
36857        }
36858      }
36859    };
36860
36861    Chosen.prototype.clear_backstroke = function() {
36862      if (this.pending_backstroke) {
36863        this.pending_backstroke.removeClass("search-choice-focus");
36864      }
36865      return this.pending_backstroke = null;
36866    };
36867
36868    Chosen.prototype.keydown_checker = function(evt) {
36869      var stroke, _ref1;
36870      stroke = (_ref1 = evt.which) != null ? _ref1 : evt.keyCode;
36871      this.search_field_scale();
36872      if (stroke !== 8 && this.pending_backstroke) {
36873        this.clear_backstroke();
36874      }
36875      switch (stroke) {
36876        case 8:
36877          this.backstroke_length = this.search_field.val().length;
36878          break;
36879        case 9:
36880          if (this.results_showing && !this.is_multiple) {
36881            this.result_select(evt);
36882          }
36883          this.mouse_on_container = false;
36884          break;
36885        case 13:
36886          if (this.results_showing) {
36887            evt.preventDefault();
36888          }
36889          break;
36890        case 32:
36891          if (this.disable_search) {
36892            evt.preventDefault();
36893          }
36894          break;
36895        case 38:
36896          evt.preventDefault();
36897          this.keyup_arrow();
36898          break;
36899        case 40:
36900          evt.preventDefault();
36901          this.keydown_arrow();
36902          break;
36903      }
36904    };
36905
36906    Chosen.prototype.search_field_scale = function() {
36907      var div, f_width, h, style, style_block, styles, w, _i, _len;
36908      if (this.is_multiple) {
36909        h = 0;
36910        w = 0;
36911        style_block = "position:absolute; left: -1000px; top: -1000px; display:none;";
36912        styles = ['font-size', 'font-style', 'font-weight', 'font-family', 'line-height', 'text-transform', 'letter-spacing'];
36913        for (_i = 0, _len = styles.length; _i < _len; _i++) {
36914          style = styles[_i];
36915          style_block += style + ":" + this.search_field.css(style) + ";";
36916        }
36917        div = $('<div />', {
36918          'style': style_block
36919        });
36920        div.text(this.search_field.val());
36921        $('body').append(div);
36922        w = div.width() + 25;
36923        div.remove();
36924        f_width = this.container.outerWidth();
36925        if (w > f_width - 10) {
36926          w = f_width - 10;
36927        }
36928        return this.search_field.css({
36929          'width': w + 'px'
36930        });
36931      }
36932    };
36933
36934    return Chosen;
36935
36936  })(AbstractChosen);
36937
36938}).call(this);
36939
36940define("chosen", ["jquery"], (function (global) {
36941    return function () {
36942        var ret, fn;
36943        return ret || global.$;
36944    };
36945}(this)));
36946
36947/*
36948 * For the given element hide children with an index greater than n.
36949 *
36950 * Examples:
36951 *
36952 * 1. For compacting a list
36953 *
36954 * <ul class="foo">
36955 *     <li>1st Child</li>
36956 *     <li>2nd Child</li>
36957 *     <li>3rd Child</li>
36958 *     <li>4th Child</li>
36959 *     <li>5th Child</li>
36960 * </ul>
36961 * 
36962 * $('.foo').compactChildren();
36963 *
36964 * 2. Set options for all matched elements by passing arguments to compactChildren().
36965 *
36966 * $('.foo').compactChildren({ numberChildren: 5 });
36967 * 
36968 * 3. Set global defaults values using the CompactChildren.defaults object.
36969 *
36970 * CompactChildren.defaults.numberChildren = false
36971 *
36972 * TODO
36973 * 1. Allow users to provide selectors for their own more and fewer links.
36974 */
36975
36976; (function ($, window, document, undefined) {
36977
36978    'use strict';
36979    var pluginName = 'compactChildren',
36980    Plugin = function (element, options) {
36981        this.element = element;
36982        this.$element = $(element);
36983        this.options = options;
36984        this.metadata = this.$element.data();
36985
36986        this._name = pluginName;
36987    };
36988
36989    Plugin.prototype = {
36990        defaults: {
36991            numberChildren: 3,
36992            moreElement: ''
36993        },
36994
36995        init: function () {
36996
36997            this.config = $.extend(
36998                {},
36999                this.defaults,
37000                this.options,
37001                this.metadata);
37002
37003            // If less child elements than 
37004            if (this.$element.children().length < this.config.numberChildren + 1){
37005                return this;
37006            }
37007
37008            this._hideChildren();
37009
37010            this._addMoreLink();
37011
37012            this._addFewerLink();
37013
37014            return this;
37015        },
37016
37017        _hideChildren: function () {
37018            var index = this.config.numberChildren - 1;
37019            this.$element.children(':gt(' + index + ')').hide();
37020        },
37021
37022        _showChildren: function () {
37023            this.$element.children().show();
37024        },
37025
37026        _addMoreLink: function () {
37027
37028            var self = this;
37029
37030            // Insert link into DOM
37031            self.$element.append('<small class="js-compact-children-more"><a href="#">More</a> <i class="icon-caret-down"></i></small>');
37032
37033            // Create a delegate event as we cannot be sure the link has been added yet
37034            self.$element.on('click', '.js-compact-children-more', function (event) {
37035                event.preventDefault();
37036                self._showChildren();
37037                self._hideLink('.js-compact-children-more');
37038                self._showLink('.js-compact-children-fewer')
37039            });
37040
37041        },
37042
37043        _addFewerLink: function () {
37044
37045            var self = this;
37046
37047            self.$element.append('<small class="js-compact-children-fewer" style="display: none;"><a href="#">Fewer</a> <i class="icon-caret-up"></i></small>');
37048
37049            self.$element.on('click', '.js-compact-children-fewer', function (event) {
37050                event.preventDefault();
37051                self._hideChildren();
37052                self._hideLink('.js-compact-children-fewer');
37053                self._showLink('.js-compact-children-more');
37054            });
37055
37056        },
37057
37058        _hideLink: function (selector) {
37059            this.$element.children(selector).hide();
37060        },
37061
37062        _showLink: function (selector) {
37063            this.$element.children(selector).show();
37064        }
37065
37066    };
37067
37068    Plugin.defaults = Plugin.prototype.defaults;
37069
37070    $.fn[pluginName] = function (options) {
37071        return this.each(function () {
37072            new Plugin(this, options).init();
37073        });
37074    };
37075
37076    //Expose the plugin class so it can be modified
37077    window.CompactChildren = Plugin;
37078
37079})(jQuery, window, document);
37080
37081define("compactChildren", ["jquery"], (function (global) {
37082    return function () {
37083        var ret, fn;
37084        return ret || global.$;
37085    };
37086}(this)));
37087
37088/*
37089 *  cropit - v0.1.9
37090 *  Customizable crop and zoom.
37091 *  https://github.com/scottcheng/cropit
37092 *
37093 *  Made by Scott Cheng
37094 *  Based on https://github.com/yufeiliu/simple_image_uploader
37095 *  Under MIT License
37096 */
37097(function($) {
37098    var Zoomer;
37099    Zoomer = function() {
37100        function Zoomer() {}
37101        Zoomer.prototype.setup = function(imageSize, previewSize, exportZoom, options) {
37102            var heightRatio, widthRatio;
37103            if (exportZoom == null) {
37104                exportZoom = 1;
37105            }
37106            widthRatio = previewSize.w / imageSize.w;
37107            heightRatio = previewSize.h / imageSize.h;
37108            if ((options != null ? options.fitWidth : void 0) && !(options != null ? options.fitHeight : void 0)) {
37109                this.minZoom = widthRatio;
37110            } else if ((options != null ? options.fitHeight : void 0) && !(options != null ? options.fitWidth : void 0)) {
37111                this.minZoom = heightRatio;
37112            } else if ((options != null ? options.fitWidth : void 0) && (options != null ? options.fitHeight : void 0)) {
37113                this.minZoom = widthRatio < heightRatio ? widthRatio : heightRatio;
37114            } else {
37115                this.minZoom = widthRatio < heightRatio ? heightRatio : widthRatio;
37116            }
37117            return this.maxZoom = this.minZoom < 1 / exportZoom ? 1 / exportZoom : this.minZoom;
37118        };
37119        Zoomer.prototype.getZoom = function(sliderPos) {
37120            if (!(this.minZoom && this.maxZoom)) {
37121                return null;
37122            }
37123            return sliderPos * (this.maxZoom - this.minZoom) + this.minZoom;
37124        };
37125        Zoomer.prototype.getSliderPos = function(zoom) {
37126            if (!(this.minZoom && this.maxZoom)) {
37127                return null;
37128            }
37129            if (this.minZoom === this.maxZoom) {
37130                return 0;
37131            } else {
37132                return (zoom - this.minZoom) / (this.maxZoom - this.minZoom);
37133            }
37134        };
37135        Zoomer.prototype.isZoomable = function() {
37136            if (!(this.minZoom && this.maxZoom)) {
37137                return null;
37138            }
37139            return this.minZoom !== this.maxZoom;
37140        };
37141        Zoomer.prototype.fixZoom = function(zoom) {
37142            if (zoom < this.minZoom) {
37143                return this.minZoom;
37144            }
37145            if (zoom > this.maxZoom) {
37146                return this.maxZoom;
37147            }
37148            return zoom;
37149        };
37150        return Zoomer;
37151    }();
37152    var Cropit;
37153    Cropit = function() {
37154        Cropit._DEFAULTS = {
37155            exportZoom: 1,
37156            imageBackground: false,
37157            imageBackgroundBorderWidth: 0,
37158            imageState: null,
37159            allowCrossOrigin: false
37160        };
37161        Cropit.PREVIEW_EVENTS = function() {
37162            return [ "mousedown", "mouseup", "mouseleave", "touchstart", "touchend", "touchcancel", "touchleave" ].map(function(type) {
37163                return "" + type + ".cropit";
37164            }).join(" ");
37165        }();
37166        Cropit.PREVIEW_MOVE_EVENTS = "mousemove.cropit touchmove.cropit";
37167        Cropit.ZOOM_INPUT_EVENTS = function() {
37168            return [ "mousemove", "touchmove", "change" ].map(function(type) {
37169                return "" + type + ".cropit";
37170            }).join(" ");
37171        }();
37172        function Cropit(element, options) {
37173            var dynamicDefaults;
37174            this.element = element;
37175            this.$el = $(this.element);
37176            dynamicDefaults = {
37177                $fileInput: this.$("input.cropit-image-input"),
37178                $preview: this.$(".cropit-image-preview"),
37179                $zoomSlider: this.$("input.cropit-image-zoom-input"),
37180                $previewContainer: this.$(".cropit-image-preview-container")
37181            };
37182            this.options = $.extend({}, Cropit._DEFAULTS, dynamicDefaults, options);
37183            this.init();
37184        }
37185        Cropit.prototype.init = function() {
37186            var $previewContainer, _ref, _ref1, _ref2;
37187            this.image = new Image();
37188            if (this.options.allowCrossOrigin) {
37189                this.image.crossOrigin = "Anonymous";
37190            }
37191            if ($.isArray(this.options.imageBackgroundBorderWidth)) {
37192                this.imageBgBorderWidthArray = this.options.imageBackgroundBorderWidth;
37193            } else {
37194                this.imageBgBorderWidthArray = [];
37195                [ 0, 1, 2, 3 ].forEach(function(_this) {
37196                    return function(i) {
37197                        return _this.imageBgBorderWidthArray[i] = _this.options.imageBackgroundBorderWidth;
37198                    };
37199                }(this));
37200            }
37201            this.$fileInput = this.options.$fileInput.attr({
37202                accept: "image/*"
37203            });
37204            this.$preview = this.options.$preview.css({
37205                backgroundRepeat: "no-repeat"
37206            });
37207            this.$zoomSlider = this.options.$zoomSlider.attr({
37208                min: 0,
37209                max: 1,
37210                step: .01
37211            });
37212            this.previewSize = {
37213                w: this.options.width || this.$preview.width(),
37214                h: this.options.height || this.$preview.height()
37215            };
37216            if (this.options.width) {
37217                this.$preview.width(this.previewSize.w);
37218            }
37219            if (this.options.height) {
37220                this.$preview.height(this.previewSize.h);
37221            }
37222            if (this.options.imageBackground) {
37223                $previewContainer = this.options.$previewContainer;
37224                this.$imageBg = $("<img />").addClass("cropit-image-background").attr("alt", "").css("position", "absolute");
37225                this.$imageBgContainer = $("<div />").addClass("cropit-image-background-container").css({
37226                    position: "absolute",
37227                    zIndex: 0,
37228                    left: -this.imageBgBorderWidthArray[3] + window.parseInt(this.$preview.css("border-left-width")),
37229                    top: -this.imageBgBorderWidthArray[0] + window.parseInt(this.$preview.css("border-top-width")),
37230                    width: this.previewSize.w + this.imageBgBorderWidthArray[1] + this.imageBgBorderWidthArray[3],
37231                    height: this.previewSize.h + this.imageBgBorderWidthArray[0] + this.imageBgBorderWidthArray[2]
37232                }).append(this.$imageBg);
37233                if (this.imageBgBorderWidthArray[0] > 0) {
37234                    this.$imageBgContainer.css({
37235                        overflow: "hidden"
37236                    });
37237                }
37238                $previewContainer.css("position", "relative").prepend(this.$imageBgContainer);
37239                this.$preview.css("position", "relative");
37240                this.$preview.hover(function(_this) {
37241                    return function() {
37242                        return _this.$imageBg.addClass("cropit-preview-hovered");
37243                    };
37244                }(this), function(_this) {
37245                    return function() {
37246                        return _this.$imageBg.removeClass("cropit-preview-hovered");
37247                    };
37248                }(this));
37249            }
37250            this.initialOffset = {
37251                x: 0,
37252                y: 0
37253            };
37254            this.initialZoom = 0;
37255            this.initialZoomSliderPos = 0;
37256            this.imageLoaded = false;
37257            this.moveContinue = false;
37258            this.zoomer = new Zoomer();
37259            this.bindListeners();
37260            this.$zoomSlider.val(this.initialZoomSliderPos);
37261            this.setOffset(((_ref = this.options.imageState) != null ? _ref.offset : void 0) || this.initialOffset);
37262            this.zoom = ((_ref1 = this.options.imageState) != null ? _ref1.zoom : void 0) || this.initialZoom;
37263            return this.loadImage(((_ref2 = this.options.imageState) != null ? _ref2.src : void 0) || null);
37264        };
37265        Cropit.prototype.bindListeners = function() {
37266            this.$fileInput.on("change.cropit", this.onFileChange.bind(this));
37267            this.$preview.on(Cropit.PREVIEW_EVENTS, this.onPreviewEvent.bind(this));
37268            return this.$zoomSlider.on(Cropit.ZOOM_INPUT_EVENTS, this.onZoomSliderChange.bind(this));
37269        };
37270        Cropit.prototype.unbindListeners = function() {
37271            this.$fileInput.off("change.cropit");
37272            this.$preview.off(Cropit.PREVIEW_EVENTS);
37273            return this.$zoomSlider.off(Cropit.ZOOM_INPUT_EVENTS);
37274        };
37275        Cropit.prototype.reset = function() {
37276            this.zoom = this.initialZoom;
37277            return this.offset = this.initialOffset;
37278        };
37279        Cropit.prototype.onFileChange = function() {
37280            var file, fileReader, _base;
37281            if (typeof (_base = this.options).onFileChange === "function") {
37282                _base.onFileChange();
37283            }
37284            fileReader = new FileReader();
37285            file = this.$fileInput.get(0).files[0];
37286            if (file != null ? file.type.match("image") : void 0) {
37287                this.setImageLoadingClass();
37288                fileReader.readAsDataURL(file);
37289                fileReader.onload = this.onFileReaderLoaded.bind(this);
37290                return fileReader.onerror = this.onFileReaderError.bind(this);
37291            }
37292        };
37293        Cropit.prototype.onFileReaderLoaded = function(e) {
37294            this.reset();
37295            return this.loadImage(e.target.result);
37296        };
37297        Cropit.prototype.onFileReaderError = function() {
37298            var _base;
37299            return typeof (_base = this.options).onFileReaderError === "function" ? _base.onFileReaderError() : void 0;
37300        };
37301        Cropit.prototype.loadImage = function(imageSrc) {
37302            var _base;
37303            this.imageSrc = imageSrc;
37304            if (!this.imageSrc) {
37305                return;
37306            }
37307            if (typeof (_base = this.options).onImageLoading === "function") {
37308                _base.onImageLoading();
37309            }
37310            this.setImageLoadingClass();
37311            this.image.onload = this.onImageLoaded.bind(this);
37312            this.image.onerror = this.onImageError.bind(this);
37313            return this.image.src = this.imageSrc;
37314        };
37315        Cropit.prototype.onImageLoaded = function() {
37316            var _base;
37317            this.setImageLoadedClass();
37318            this.setOffset(this.offset);
37319            this.$preview.css("background-image", "url(" + this.imageSrc + ")");
37320            if (this.options.imageBackground) {
37321                this.$imageBg.attr("src", this.imageSrc);
37322            }
37323            this.imageSize = {
37324                w: this.image.width,
37325                h: this.image.height
37326            };
37327            this.setupZoomer();
37328            this.imageLoaded = true;
37329            return typeof (_base = this.options).onImageLoaded === "function" ? _base.onImageLoaded() : void 0;
37330        };
37331        Cropit.prototype.onImageError = function() {
37332            var _base;
37333            return typeof (_base = this.options).onImageError === "function" ? _base.onImageError() : void 0;
37334        };
37335        Cropit.prototype.setImageLoadingClass = function() {
37336            return this.$preview.removeClass("cropit-image-loaded").addClass("cropit-image-loading");
37337        };
37338        Cropit.prototype.setImageLoadedClass = function() {
37339            return this.$preview.removeClass("cropit-image-loading").addClass("cropit-image-loaded");
37340        };
37341        Cropit.prototype.getEventPosition = function(e) {
37342            var _ref, _ref1, _ref2, _ref3;
37343            if ((_ref = e.originalEvent) != null ? (_ref1 = _ref.touches) != null ? _ref1[0] : void 0 : void 0) {
37344                e = (_ref2 = e.originalEvent) != null ? (_ref3 = _ref2.touches) != null ? _ref3[0] : void 0 : void 0;
37345            }
37346            if (e.clientX && e.clientY) {
37347                return {
37348                    x: e.clientX,
37349                    y: e.clientY
37350                };
37351            }
37352        };
37353        Cropit.prototype.onPreviewEvent = function(e) {
37354            if (!this.imageLoaded) {
37355                return;
37356            }
37357            this.moveContinue = false;
37358            this.$preview.off(Cropit.PREVIEW_MOVE_EVENTS);
37359            if (e.type === "mousedown" || e.type === "touchstart") {
37360                this.origin = this.getEventPosition(e);
37361                this.moveContinue = true;
37362                this.$preview.on(Cropit.PREVIEW_MOVE_EVENTS, this.onMove.bind(this));
37363            } else {
37364                $(document.body).focus();
37365            }
37366            e.stopPropagation();
37367            return false;
37368        };
37369        Cropit.prototype.onMove = function(e) {
37370            var eventPosition;
37371            eventPosition = this.getEventPosition(e);
37372            if (this.moveContinue && eventPosition) {
37373                this.setOffset({
37374                    x: this.offset.x + eventPosition.x - this.origin.x,
37375                    y: this.offset.y + eventPosition.y - this.origin.y
37376                });
37377            }
37378            this.origin = eventPosition;
37379            e.stopPropagation();
37380            return false;
37381        };
37382        Cropit.prototype.setOffset = function(position) {
37383            this.offset = this.fixOffset(position);
37384            this.$preview.css("background-position", "" + this.offset.x + "px " + this.offset.y + "px");
37385            if (this.options.imageBackground) {
37386                return this.$imageBg.css({
37387                    left: this.offset.x + this.imageBgBorderWidthArray[3],
37388                    top: this.offset.y + this.imageBgBorderWidthArray[0]
37389                });
37390            }
37391        };
37392        Cropit.prototype.fixOffset = function(offset) {
37393            var ret;
37394            if (!this.imageLoaded) {
37395                return offset;
37396            }
37397            ret = {
37398                x: offset.x,
37399                y: offset.y
37400            };
37401            if (this.imageSize.w * this.zoom <= this.previewSize.w) {
37402                ret.x = 0;
37403            } else if (ret.x > 0) {
37404                ret.x = 0;
37405            } else if (ret.x + this.imageSize.w * this.zoom < this.previewSize.w) {
37406                ret.x = this.previewSize.w - this.imageSize.w * this.zoom;
37407            }
37408            if (this.imageSize.h * this.zoom <= this.previewSize.h) {
37409                ret.y = 0;
37410            } else if (ret.y > 0) {
37411                ret.y = 0;
37412            } else if (ret.y + this.imageSize.h * this.zoom < this.previewSize.h) {
37413                ret.y = this.previewSize.h - this.imageSize.h * this.zoom;
37414            }
37415            ret.x = this.round(ret.x);
37416            ret.y = this.round(ret.y);
37417            return ret;
37418        };
37419        Cropit.prototype.onZoomSliderChange = function() {
37420            var newZoom;
37421            if (!this.imageLoaded) {
37422                return;
37423            }
37424            this.zoomSliderPos = Number(this.$zoomSlider.val());
37425            newZoom = this.zoomer.getZoom(this.zoomSliderPos);
37426            return this.setZoom(newZoom);
37427        };
37428        Cropit.prototype.enableZoomSlider = function() {
37429            var _base;
37430            this.$zoomSlider.removeAttr("disabled");
37431            return typeof (_base = this.options).onZoomEnabled === "function" ? _base.onZoomEnabled() : void 0;
37432        };
37433        Cropit.prototype.disableZoomSlider = function() {
37434            var _base;
37435            this.$zoomSlider.attr("disabled", true);
37436            return typeof (_base = this.options).onZoomDisabled === "function" ? _base.onZoomDisabled() : void 0;
37437        };
37438        Cropit.prototype.setupZoomer = function() {
37439            this.zoomer.setup(this.imageSize, this.previewSize, this.options.exportZoom, this.options);
37440            this.zoom = this.fixZoom(this.zoom);
37441            this.setZoom(this.zoom);
37442            if (this.isZoomable()) {
37443                return this.enableZoomSlider();
37444            } else {
37445                return this.disableZoomSlider();
37446            }
37447        };
37448        Cropit.prototype.setZoom = function(newZoom) {
37449            var newX, newY, oldZoom, updatedHeight, updatedWidth;
37450            newZoom = this.fixZoom(newZoom);
37451            updatedWidth = this.round(this.imageSize.w * newZoom);
37452            updatedHeight = this.round(this.imageSize.h * newZoom);
37453            oldZoom = this.zoom;
37454            newX = this.previewSize.w / 2 - (this.previewSize.w / 2 - this.offset.x) * newZoom / oldZoom;
37455            newY = this.previewSize.h / 2 - (this.previewSize.h / 2 - this.offset.y) * newZoom / oldZoom;
37456            this.zoom = newZoom;
37457            this.setOffset({
37458                x: newX,
37459                y: newY
37460            });
37461            this.zoomSliderPos = this.zoomer.getSliderPos(this.zoom);
37462            this.$zoomSlider.val(this.zoomSliderPos);
37463            this.$preview.css("background-size", "" + updatedWidth + "px " + updatedHeight + "px");
37464            if (this.options.imageBackground) {
37465                return this.$imageBg.css({
37466                    width: updatedWidth,
37467                    height: updatedHeight
37468                });
37469            }
37470        };
37471        Cropit.prototype.fixZoom = function(zoom) {
37472            return this.zoomer.fixZoom(zoom);
37473        };
37474        Cropit.prototype.isZoomable = function() {
37475            return this.zoomer.isZoomable();
37476        };
37477        Cropit.prototype.getCroppedImageData = function(exportOptions) {
37478            var canvas, canvasContext, croppedSize, exportDefaults, exportZoom;
37479            if (!this.imageSrc) {
37480                return null;
37481            }
37482            exportDefaults = {
37483                type: "image/png",
37484                quality: .75,
37485                originalSize: false,
37486                fillBg: "#fff"
37487            };
37488            exportOptions = $.extend({}, exportDefaults, exportOptions);
37489            croppedSize = {
37490                w: this.previewSize.w,
37491                h: this.previewSize.h
37492            };
37493            if (this.options.fitHeight && !this.options.fitWidth && this.imageSize.w * this.zoom < this.previewSize.w) {
37494                croppedSize.w = this.imageSize.w * this.zoom;
37495            } else if (this.options.fitWidth && !this.options.fitHeight && this.imageSize.h * this.zoom < this.previewSize.h) {
37496                croppedSize.h = this.imageSize.h * this.zoom;
37497            }
37498            exportZoom = exportOptions.originalSize ? 1 / this.zoom : this.options.exportZoom;
37499            canvas = $("<canvas />").attr({
37500                width: croppedSize.w * exportZoom,
37501                height: croppedSize.h * exportZoom
37502            }).get(0);
37503            canvasContext = canvas.getContext("2d");
37504            if (exportOptions.type === "image/jpeg") {
37505                canvasContext.fillStyle = exportOptions.fillBg;
37506                canvasContext.fillRect(0, 0, canvas.width, canvas.height);
37507            }
37508            canvasContext.drawImage(this.image, this.offset.x * exportZoom, this.offset.y * exportZoom, this.zoom * exportZoom * this.imageSize.w, this.zoom * exportZoom * this.imageSize.h);
37509            return canvas.toDataURL(exportOptions.type, exportOptions.quality);
37510        };
37511        Cropit.prototype.getImageState = function() {
37512            return {
37513                src: this.imageSrc,
37514                offset: this.offset,
37515                zoom: this.zoom
37516            };
37517        };
37518        Cropit.prototype.getImageSrc = function() {
37519            return this.imageSrc;
37520        };
37521        Cropit.prototype.getOffset = function() {
37522            return this.offset;
37523        };
37524        Cropit.prototype.getZoom = function() {
37525            return this.zoom;
37526        };
37527        Cropit.prototype.getImageSize = function() {
37528            if (!this.imageSize) {
37529                return null;
37530            }
37531            return {
37532                width: this.imageSize.w,
37533                height: this.imageSize.h
37534            };
37535        };
37536        Cropit.prototype.getPreviewSize = function() {
37537            return {
37538                width: this.previewSize.w,
37539                height: this.previewSize.h
37540            };
37541        };
37542        Cropit.prototype.setPreviewSize = function(size) {
37543            if (!((size != null ? size.width : void 0) > 0 && (size != null ? size.height : void 0) > 0)) {
37544                return;
37545            }
37546            this.previewSize = {
37547                w: size.width,
37548                h: size.height
37549            };
37550            this.$preview.css({
37551                width: this.previewSize.w,
37552                height: this.previewSize.h
37553            });
37554            if (this.options.imageBackground) {
37555                this.$imageBgContainer.css({
37556                    width: this.previewSize.w + this.imageBgBorderWidthArray[1] + this.imageBgBorderWidthArray[3],
37557                    height: this.previewSize.h + this.imageBgBorderWidthArray[0] + this.imageBgBorderWidthArray[2]
37558                });
37559            }
37560            if (this.imageLoaded) {
37561                return this.setupZoomer();
37562            }
37563        };
37564        Cropit.prototype.disable = function() {
37565            this.unbindListeners();
37566            this.disableZoomSlider();
37567            return this.$el.addClass("cropit-disabled");
37568        };
37569        Cropit.prototype.reenable = function() {
37570            this.bindListeners();
37571            this.enableZoomSlider();
37572            return this.$el.removeClass("cropit-disabled");
37573        };
37574        Cropit.prototype.round = function(x) {
37575            return Math.round(x * 1e5) / 1e5;
37576        };
37577        Cropit.prototype.$ = function(selector) {
37578            if (!this.$el) {
37579                return null;
37580            }
37581            return this.$el.find(selector);
37582        };
37583        return Cropit;
37584    }();
37585    var dataKey, methods;
37586    dataKey = "cropit";
37587    methods = {
37588        init: function(options) {
37589            return this.each(function() {
37590                var cropit;
37591                if (!$.data(this, dataKey)) {
37592                    cropit = new Cropit(this, options);
37593                    return $.data(this, dataKey, cropit);
37594                }
37595            });
37596        },
37597        destroy: function() {
37598            return this.each(function() {
37599                return $.removeData(this, dataKey);
37600            });
37601        },
37602        isZoomable: function() {
37603            var cropit;
37604            cropit = this.first().data(dataKey);
37605            return cropit != null ? cropit.isZoomable() : void 0;
37606        },
37607        "export": function(options) {
37608            var cropit;
37609            cropit = this.first().data(dataKey);
37610            return cropit != null ? cropit.getCroppedImageData(options) : void 0;
37611        },
37612        imageState: function() {
37613            var cropit;
37614            cropit = this.first().data(dataKey);
37615            return cropit != null ? cropit.getImageState() : void 0;
37616        },
37617        imageSrc: function(newImageSrc) {
37618            var cropit;
37619            if (newImageSrc != null) {
37620                return this.each(function() {
37621                    var cropit;
37622                    cropit = $.data(this, dataKey);
37623                    if (cropit != null) {
37624                        cropit.reset();
37625                    }
37626                    return cropit != null ? cropit.loadImage(newImageSrc) : void 0;
37627                });
37628            } else {
37629                cropit = this.first().data(dataKey);
37630                return cropit != null ? cropit.getImageSrc() : void 0;
37631            }
37632        },
37633        offset: function(newOffset) {
37634            var cropit;
37635            if (newOffset != null && newOffset.x != null && newOffset.y != null) {
37636                return this.each(function() {
37637                    var cropit;
37638                    cropit = $.data(this, dataKey);
37639                    return cropit != null ? cropit.setOffset(newOffset) : void 0;
37640                });
37641            } else {
37642                cropit = this.first().data(dataKey);
37643                return cropit != null ? cropit.getOffset() : void 0;
37644            }
37645        },
37646        zoom: function(newZoom) {
37647            var cropit;
37648            if (newZoom != null) {
37649                return this.each(function() {
37650                    var cropit;
37651                    cropit = $.data(this, dataKey);
37652                    return cropit != null ? cropit.setZoom(newZoom) : void 0;
37653                });
37654            } else {
37655                cropit = this.first().data(dataKey);
37656                return cropit != null ? cropit.getZoom() : void 0;
37657            }
37658        },
37659        imageSize: function() {
37660            var cropit;
37661            cropit = this.first().data(dataKey);
37662            return cropit != null ? cropit.getImageSize() : void 0;
37663        },
37664        previewSize: function(newSize) {
37665            var cropit;
37666            if (newSize != null) {
37667                return this.each(function() {
37668                    var cropit;
37669                    cropit = $.data(this, dataKey);
37670                    return cropit != null ? cropit.setPreviewSize(newSize) : void 0;
37671                });
37672            } else {
37673                cropit = this.first().data(dataKey);
37674                return cropit != null ? cropit.getPreviewSize() : void 0;
37675            }
37676        },
37677        disable: function() {
37678            return this.each(function() {
37679                var cropit;
37680                cropit = $.data(this, dataKey);
37681                return cropit.disable();
37682            });
37683        },
37684        reenable: function() {
37685            return this.each(function() {
37686                var cropit;
37687                cropit = $.data(this, dataKey);
37688                return cropit.reenable();
37689            });
37690        }
37691    };
37692    $.fn.cropit = function(method) {
37693        if (methods[method]) {
37694            return methods[method].apply(this, [].slice.call(arguments, 1));
37695        } else {
37696            return methods.init.apply(this, arguments);
37697        }
37698    };
37699})(window.jQuery);
37700define("cropit", ["jquery"], function(){});
37701
37702/*jslint indent:4, white:true, nomen:true, plusplus:true */
37703/*global define:false, require:false, exports:false, module:false, signals:false */
37704
37705/** @license
37706 * JS Signals <http://millermedeiros.github.com/js-signals/>
37707 * Released under the MIT license
37708 * Author: Miller Medeiros
37709 * Version: 0.8.1 - Build: 266 (2012/07/31 03:33 PM)
37710 */
37711
37712(function(global){
37713
37714    // SignalBinding -------------------------------------------------
37715    //================================================================
37716
37717    /**
37718     * Object that represents a binding between a Signal and a listener function.
37719     * <br />- <strong>
37719This is an internal constructor and shouldn't be called by regular users.</strong>
37720     * <br />- inspired by Joa Ebert AS3 SignalBinding and Robert Penner's Slot classes.
37721     * @author Miller Medeiros
37722     * @constructor
37723     * @internal
37724     * @name SignalBinding
37725     * @param {Signal} signal Reference to Signal object that listener is currently bound to.
37726     * @param {Function} listener Handler function bound to the signal.
37727     * @param {boolean} isOnce If binding should be executed just once.
37728     * @param {Object} [listenerContext] Context on which listener will be executed (object that should represent the `this` variable inside listener function).
37729     * @param {Number} [priority] The priority level of the event listener. (default = 0).
37730     */
37731    function SignalBinding(signal, listener, isOnce, listenerContext, priority) {
37732
37733        /**
37734         * Handler function bound to the signal.
37735         * @type Function
37736         * @private
37737         */
37738        this._listener = listener;
37739
37740        /**
37741         * If binding should be executed just once.
37742         * @type boolean
37743         * @private
37744         */
37745        this._isOnce = isOnce;
37746
37747        /**
37748         * Context on which listener will be executed (object that should represent the `this` variable inside listener function).
37749         * @memberOf SignalBinding.prototype
37750         * @name context
37751         * @type Object|undefined|null
37752         */
37753        this.context = listenerContext;
37754
37755        /**
37756         * Reference to Signal object that listener is currently bound to.
37757         * @type Signal
37758         * @private
37759         */
37760        this._signal = signal;
37761
37762        /**
37763         * Listener priority
37764         * @type Number
37765         * @private
37766         */
37767        this._priority = priority || 0;
37768    }
37769
37770    SignalBinding.prototype = {
37771
37772        /**
37773         * If binding is active and should be executed.
37774         * @type boolean
37775         */
37776        active : true,
37777
37778        /**
37779         * Default parameters passed to listener during `Signal.dispatch` and `SignalBinding.execute`. (curried parameters)
37780         * @type Array|null
37781         */
37782        params : null,
37783
37784        /**
37785         * Call listener passing arbitrary parameters.
37786         * <p>If binding was added using `Signal.addOnce()` it will be automatically removed from signal dispatch queue, this method is used internally for the signal dispatch.</p>
37787         * @param {Array} [paramsArr] Array of parameters that should be passed to the listener
37788         * @return {*} Value returned by the listener.
37789         */
37790        execute : function (paramsArr) {
37791            var handlerReturn, params;
37792            if (this.active && !!this._listener) {
37793                params = this.params? this.params.concat(paramsArr) : paramsArr;
37794                handlerReturn = this._listener.apply(this.context, params);
37795                if (this._isOnce) {
37796                    this.detach();
37797                }
37798            }
37799            return handlerReturn;
37800        },
37801
37802        /**
37803         * Detach binding from signal.
37804         * - alias to: mySignal.remove(myBinding.getListener());
37805         * @return {Function|null} Handler function bound to the signal or `null` if binding was previously detached.
37806         */
37807        detach : function () {
37808            return this.isBound()? this._signal.remove(this._listener, this.context) : null;
37809        },
37810
37811        /**
37812         * @return {Boolean} `true` if binding is still bound to the signal and have a listener.
37813         */
37814        isBound : function () {
37815            return (!!this._signal && !!this._listener);
37816        },
37817
37818        /**
37819         * @return {Function} Handler function bound to the signal.
37820         */
37821        getListener : function () {
37822            return this._listener;
37823        },
37824
37825        /**
37826         * Delete instance properties
37827         * @private
37828         */
37829        _destroy : function () {
37830            delete this._signal;
37831            delete this._listener;
37832            delete this.context;
37833        },
37834
37835        /**
37836         * @return {boolean} If SignalBinding will only be executed once.
37837         */
37838        isOnce : function () {
37839            return this._isOnce;
37840        },
37841
37842        /**
37843         * @return {string} String representation of the object.
37844         */
37845        toString : function () {
37846            return '[SignalBinding isOnce:' + this._isOnce +', isBound:'+ this.isBound() +', active:' + this.active + ']';
37847        }
37848
37849    };
37850
37851
37852/*global SignalBinding:false*/
37853
37854    // Signal --------------------------------------------------------
37855    //================================================================
37856
37857    function validateListener(listener, fnName) {
37858        if (typeof listener !== 'function') {
37859            throw new Error( 'listener is a required param of {fn}() and should be a Function.'.replace('{fn}', fnName) );
37860        }
37861    }
37862
37863    /**
37864     * Custom event broadcaster
37865     * <br />- inspired by Robert Penner's AS3 Signals.
37866     * @name Signal
37867     * @author Miller Medeiros
37868     * @constructor
37869     */
37870    function Signal() {
37871        /**
37872         * @type Array.<SignalBinding>
37873         * @private
37874         */
37875        this._bindings = [];
37876        this._prevParams = null;
37877    }
37878
37879    Signal.prototype = {
37880
37881        /**
37882         * Signals Version Number
vendor: 9,593 bytes, lines 37883-38141
37883         * @type String
37884         * @const
37885         */
37886        VERSION : '0.8.1',
37887
37888        /**
37889         * If Signal should keep record of previously dispatched parameters and
37890         * automatically execute listener during `add()`/`addOnce()` if Signal was
37891         * already dispatched before.
37892         * @type boolean
37893         */
37894        memorize : false,
37895
37896        /**
37897         * @type boolean
37898         * @private
37899         */
37900        _shouldPropagate : true,
37901
37902        /**
37903         * If Signal is active and should broadcast events.
37904         * <p><strong>IMPORTANT:</strong> Setting this property during a dispatch will only affect the next dispatch, if you want to stop the propagation of a signal use `halt()` instead.</p>
37905         * @type boolean
37906         */
37907        active : true,
37908
37909        /**
37910         * @param {Function} listener
37911         * @param {boolean} isOnce
37912         * @param {Object} [listenerContext]
37913         * @param {Number} [priority]
37914         * @return {SignalBinding}
37915         * @private
37916         */
37917        _registerListener : function (listener, isOnce, listenerContext, priority) {
37918
37919            var prevIndex = this._indexOfListener(listener, listenerContext),
37920                binding;
37921
37922            if (prevIndex !== -1) {
37923                binding = this._bindings[prevIndex];
37924                if (binding.isOnce() !== isOnce) {
37925                    throw new Error('You cannot add'+ (isOnce? '' : 'Once') +'() then add'+ (!isOnce? '' : 'Once') +'() the same listener without removing the relationship first.');
37926                }
37927            } else {
37928                binding = new SignalBinding(this, listener, isOnce, listenerContext, priority);
37929                this._addBinding(binding);
37930            }
37931
37932            if(this.memorize && this._prevParams){
37933                binding.execute(this._prevParams);
37934            }
37935
37936            return binding;
37937        },
37938
37939        /**
37940         * @param {SignalBinding} binding
37941         * @private
37942         */
37943        _addBinding : function (binding) {
37944            //simplified insertion sort
37945            var n = this._bindings.length;
37946            do { --n; } while (this._bindings[n] && binding._priority <= this._bindings[n]._priority);
37947            this._bindings.splice(n + 1, 0, binding);
37948        },
37949
37950        /**
37951         * @param {Function} listener
37952         * @return {number}
37953         * @private
37954         */
37955        _indexOfListener : function (listener, context) {
37956            var n = this._bindings.length,
37957                cur;
37958            while (n--) {
37959                cur = this._bindings[n];
37960                if (cur._listener === listener && cur.context === context) {
37961                    return n;
37962                }
37963            }
37964            return -1;
37965        },
37966
37967        /**
37968         * Check if listener was attached to Signal.
37969         * @param {Function} listener
37970         * @param {Object} [context]
37971         * @return {boolean} if Signal has the specified listener.
37972         */
37973        has : function (listener, context) {
37974            return this._indexOfListener(listener, context) !== -1;
37975        },
37976
37977        /**
37978         * Add a listener to the signal.
37979         * @param {Function} listener Signal handler function.
37980         * @param {Object} [listenerContext] Context on which listener will be executed (object that should represent the `this` variable inside listener function).
37981         * @param {Number} [priority] The priority level of the event listener. Listeners with higher priority will be executed before listeners with lower priority. Listeners with same priority level will be executed at the same order as they were added. (default = 0)
37982         * @return {SignalBinding} An Object representing the binding between the Signal and listener.
37983         */
37984        add : function (listener, listenerContext, priority) {
37985            validateListener(listener, 'add');
37986            return this._registerListener(listener, false, listenerContext, priority);
37987        },
37988
37989        /**
37990         * Add listener to the signal that should be removed after first execution (will be executed only once).
37991         * @param {Function} listener Signal handler function.
37992         * @param {Object} [listenerContext] Context on which listener will be executed (object that should represent the `this` variable inside listener function).
37993         * @param {Number} [priority] The priority level of the event listener. Listeners with higher priority will be executed before listeners with lower priority. Listeners with same priority level will be executed at the same order as they were added. (default = 0)
37994         * @return {SignalBinding} An Object representing the binding between the Signal and listener.
37995         */
37996        addOnce : function (listener, listenerContext, priority) {
37997            validateListener(listener, 'addOnce');
37998            return this._registerListener(listener, true, listenerContext, priority);
37999        },
38000
38001        /**
38002         * Remove a single listener from the dispatch queue.
38003         * @param {Function} listener Handler function that should be removed.
38004         * @param {Object} [context] Execution context (since you can add the same handler multiple times if executing in a different context).
38005         * @return {Function} Listener handler function.
38006         */
38007        remove : function (listener, context) {
38008            validateListener(listener, 'remove');
38009
38010            var i = this._indexOfListener(listener, context);
38011            if (i !== -1) {
38012                this._bindings[i]._destroy(); //no reason to a SignalBinding exist if it isn't attached to a signal
38013                this._bindings.splice(i, 1);
38014            }
38015            return listener;
38016        },
38017
38018        /**
38019         * Remove all listeners from the Signal.
38020         */
38021        removeAll : function () {
38022            var n = this._bindings.length;
38023            while (n--) {
38024                this._bindings[n]._destroy();
38025            }
38026            this._bindings.length = 0;
38027        },
38028
38029        /**
38030         * @return {number} Number of listeners attached to the Signal.
38031         */
38032        getNumListeners : function () {
38033            return this._bindings.length;
38034        },
38035
38036        /**
38037         * Stop propagation of the event, blocking the dispatch to next listeners on the queue.
38038         * <p><strong>IMPORTANT:</strong> should be called only during signal dispatch, calling it before/after dispatch won't affect signal broadcast.</p>
38039         * @see Signal.prototype.disable
38040         */
38041        halt : function () {
38042            this._shouldPropagate = false;
38043        },
38044
38045        /**
38046         * Dispatch/Broadcast Signal to all listeners added to the queue.
38047         * @param {...*} [params] Parameters that should be passed to each handler.
38048         */
38049        dispatch : function (params) {
38050            if (! this.active) {
38051                return;
38052            }
38053
38054            var paramsArr = Array.prototype.slice.call(arguments),
38055                n = this._bindings.length,
38056                bindings;
38057
38058            if (this.memorize) {
38059                this._prevParams = paramsArr;
38060            }
38061
38062            if (! n) {
38063                //should come after memorize
38064                return;
38065            }
38066
38067            bindings = this._bindings.slice(); //clone array in case add/remove items during dispatch
38068            this._shouldPropagate = true; //in case `halt` was called before dispatch or during the previous dispatch.
38069
38070            //execute all callbacks until end of the list or until a callback returns `false` or stops propagation
38071            //reverse loop since listeners with higher priority will be added at the end of the list
38072            do { n--; } while (bindings[n] && this._shouldPropagate && bindings[n].execute(paramsArr) !== false);
38073        },
38074
38075        /**
38076         * Forget memorized arguments.
38077         * @see Signal.memorize
38078         */
38079        forget : function(){
38080            this._prevParams = null;
38081        },
38082
38083        /**
38084         * Remove all bindings from signal and destroy any reference to external objects (destroy Signal object).
38085         * <p><strong>IMPORTANT:</strong> calling any method on the signal instance after calling dispose will throw errors.</p>
38086         */
38087        dispose : function () {
38088            this.removeAll();
38089            delete this._bindings;
38090            delete this._prevParams;
38091        },
38092
38093        /**
38094         * @return {string} String representation of the object.
38095         */
38096        toString : function () {
38097            return '[Signal active:'+ this.active +' numListeners:'+ this.getNumListeners() +']';
38098        }
38099
38100    };
38101
38102
38103    // Namespace -----------------------------------------------------
38104    //================================================================
38105
38106    /**
38107     * Signals namespace
38108     * @namespace
38109     * @name signals
38110     */
38111    var signals = Signal;
38112
38113    /**
38114     * Custom event broadcaster
38115     * @see Signal
38116     */
38117    // alias for backwards compatibility (see #gh-44)
38118    signals.Signal = Signal;
38119
38120
38121
38122    //exports to multiple environments
38123    if(typeof define === 'function' && define.amd){ //AMD
38124        define('signals',[],function () { return signals; });
38125    } else if (typeof module !== 'undefined' && module.exports){ //node
38126        module.exports = signals;
38127    } else { //browser
38128        //use string because of Google closure compiler ADVANCED_MODE
38129        /*jslint sub:true */
38130        global['signals'] = signals;
38131    }
38132
38133}(this));
38134
38135/** @license
38136 * crossroads <http://millermedeiros.github.com/crossroads.js/>
38137 * Author: Miller Medeiros | MIT License
38138 * v0.12.2 (2015/07/31 18:37)
38139 */
38140
38141(function () {
38142var factory = function (signals) {
38143
38144    var crossroads,
38145        _hasOptionalGroupBug,
38146        UNDEF;
38147
38148    // Helpers -----------
38149    //====================
38150
38151    // IE 7-8 capture optional groups as empty strings while other browsers
38152    // capture as `undefined`
38153    _hasOptionalGroupBug = (/t(.+)?/).exec('t')[1] === '';
38154
38155    function arrayIndexOf(arr, val) {
38156        if (arr.indexOf) {
38157            return arr.indexOf(val);
38158        } else {
38159            //Array.indexOf doesn't work on IE 6-7
38160            var n = arr.length;
38161            while (n--) {
38162                if (arr[n] === val) {
38163                    return n;
38164                }
38165            }
38166            return -1;
38167        }
38168    }
38169
38170    function arrayRemove(arr, item) {
38171        var i = arrayIndexOf(arr, item);
38172        if (i !== -1) {
38173            arr.splice(i, 1);
38174        }
38175    }
38176
38177    function isKind(val, kind) {
38178        return '[object '+ kind +']' === Object.prototype.toString.call(val);
38179    }
38180
38181    function isRegExp(val) {
38182        return isKind(val, 'RegExp');
38183    }
38184
38185    function isArray(val) {
38186        return isKind(val, 'Array');
38187    }
38188
38189    function isFunction(val) {
38190        return typeof val === 'function';
38191    }
38192
38193    //borrowed from AMD-utils
38194    function typecastValue(val) {
38195        var r;
38196        if (val === null || val === 'null') {
38197            r = null;
38198        } else if (val === 'true') {
38199            r = true;
38200        } else if (val === 'false') {
38201            r = false;
38202        } else if (val === UNDEF || val === 'undefined') {
38203            r = UNDEF;
38204        } else if (val === '' || isNaN(val)) {
38205            //isNaN('') returns false
38206            r = val;
38207        } else {
38208            //parseFloat(null || '') returns NaN
38209            r = parseFloat(val);
38210        }
38211        return r;
38212    }
38213
38214    function typecastArrayValues(values) {
38215        var n = values.length,
38216            result = [];
38217        while (n--) {
38218            result[n] = typecastValue(values[n]);
38219        }
38220        return result;
38221    }
38222
38223    // borrowed from MOUT
38224    function decodeQueryString(queryStr, shouldTypecast) {
38225        var queryArr = (queryStr || '').replace('?', '').split('&'),
38226            reg = /([^=]+)=(.+)/,
38227            i = -1,
38228            obj = {},
38229            equalIndex, cur, pValue, pName;
38230
38231        while ((cur = queryArr[++i])) {
38232            equalIndex = cur.indexOf('=');
38233            pName = cur.substring(0, equalIndex);
38234            pValue = decodeURIComponent(cur.substring(equalIndex + 1));
38235            if (shouldTypecast !== false) {
38236                pValue = typecastValue(pValue);
38237            }
38238            if (pName in obj){
38239                if(isArray(obj[pName])){
38240                    obj[pName].push(pValue);
38241                } else {
38242                    obj[pName] = [obj[pName], pValue];
38243                }
38244            } else {
38245                obj[pName] = pValue;
38246           }
38247        }
38248        return obj;
38249    }
38250
38251
38252    // Crossroads --------
38253    //====================
38254
38255    /**
38256     * @constructor
38257     */
38258    function Crossroads() {
38259        this.bypassed = new signals.Signal();
38260        this.routed = new signals.Signal();
38261        this._routes = [];
38262        this._prevRoutes = [];
38263        this._piped = [];
38264        this.resetState();
38265    }
38266
38267    Crossroads.prototype = {
38268
38269        greedy : false,
38270
38271        greedyEnabled : true,
38272
38273        ignoreCase : true,
38274
38275        ignoreState : false,
38276
38277        shouldTypecast : false,
38278
38279        normalizeFn : null,
38280
38281        resetState : function(){
38282            this._prevRoutes.length = 0;
38283            this._prevMatchedRequest = null;
38284            this._prevBypassedRequest = null;
38285        },
38286
38287        create : function () {
38288            return new Crossroads();
38289        },
38290
38291        addRoute : function (pattern, callback, priority) {
38292            var route = new Route(pattern, callback, priority, this);
38293            this._sortedInsert(route);
38294            return route;
38295        },
38296
38297        removeRoute : function (route) {
38298            arrayRemove(this._routes, route);
38299            route._destroy();
38300        },
38301
38302        removeAllRoutes : function () {
38303            var n = this.getNumRoutes();
38304            while (n--) {
38305                this._routes[n]._destroy();
38306            }
38307            this._routes.length = 0;
38308        },
38309
38310        parse : function (request, defaultArgs) {
38311            request = request || '';
38312            defaultArgs = defaultArgs || [];
38313
38314            // should only care about different requests if ignoreState isn't true
38315            if ( !this.ignoreState &&
38316                (request === this._prevMatchedRequest ||
38317                 request === this._prevBypassedRequest) ) {
38318                return;
38319            }
38320
38321            var routes = this._getMatchedRoutes(request),
38322                i = 0,
38323                n = routes.length,
38324                cur;
38325
38326            if (n) {
38327                this._prevMatchedRequest = request;
38328
38329                this._notifyPrevRoutes(routes, request);
38330                this._prevRoutes = routes;
38331                //should be incremental loop, execute routes in order
38332                while (i < n) {
38333                    cur = routes[i];
38334                    cur.route.matched.dispatch.apply(cur.route.matched, defaultArgs.concat(cur.params));
38335                    cur.isFirst = !i;
38336                    this.routed.dispatch.apply(this.routed, defaultArgs.concat([request, cur]));
38337                    i += 1;
38338                }
38339            } else {
38340                this._prevBypassedRequest = request;
38341                this.bypassed.dispatch.apply(this.bypassed, defaultArgs.concat([request]));
38342            }
38343
38344            this._pipeParse(request, defaultArgs);
38345        },
38346
38347        _notifyPrevRoutes : function(matchedRoutes, request) {
38348            var i = 0, prev;
38349            while (prev = this._prevRoutes[i++]) {
38350                //check if switched exist since route may be disposed
38351                if(prev.route.switched && this._didSwitch(prev.route, matchedRoutes)) {
38352                    prev.route.switched.dispatch(request);
38353                }
38354            }
38355        },
38356
38357        _didSwitch : function (route, matchedRoutes){
38358            var matched,
38359                i = 0;
38360            while (matched = matchedRoutes[i++]) {
38361                // only dispatch switched if it is going to a different route
38362                if (matched.route === route) {
38363                    return false;
38364                }
38365            }
38366            return true;
38367        },
38368
38369        _pipeParse : function(request, defaultArgs) {
38370            var i = 0, route;
38371            while (route = this._piped[i++]) {
38372                route.parse(request, defaultArgs);
38373            }
38374        },
38375
38376        getNumRoutes : function () {
38377            return this._routes.length;
38378        },
38379
38380        _sortedInsert : function (route) {
38381            //simplified insertion sort
38382            var routes = this._routes,
38383                n = routes.length;
38384            do { --n; } while (routes[n] && route._priority <= routes[n]._priority);
38385            routes.splice(n+1, 0, route);
38386        },
38387
38388        _getMatchedRoutes : function (request) {
38389            var res = [],
38390                routes = this._routes,
38391                n = routes.length,
38392                route;
38393            //should be decrement loop since higher priorities are added at the end of array
38394            while (route = routes[--n]) {
38395                if ((!res.length || this.greedy || route.greedy) && route.match(request)) {
38396                    res.push({
38397                        route : route,
38398                        params : route._getParamsArray(request)
38399                    });
38400                }
38401                if (!this.greedyEnabled && res.length) {
38402                    break;
38403                }
38404            }
38405            return res;
38406        },
38407
38408        pipe : function (otherRouter) {
38409            this._piped.push(otherRouter);
38410        },
38411
38412        unpipe : function (otherRouter) {
38413            arrayRemove(this._piped, otherRouter);
38414        },
38415
38416        toString : function () {
38417            return '[crossroads numRoutes:'+ this.getNumRoutes() +']';
38418        }
38419    };
38420
38421    //"static" instance
38422    crossroads = new Crossroads();
38423    crossroads.VERSION = '0.12.2';
38424
38425    crossroads.NORM_AS_ARRAY = function (req, vals) {
38426        return [vals.vals_];
38427    };
38428
38429    crossroads.NORM_AS_OBJECT = function (req, vals) {
38430        return [vals];
38431    };
38432
38433
38434    // Route --------------
38435    //=====================
38436
38437    /**
38438     * @constructor
38439     */
38440    function Route(pattern, callback, priority, router) {
38441        var isRegexPattern = isRegExp(pattern),
38442            patternLexer = router.patternLexer;
38443        this._router = router;
38444        this._pattern = pattern;
38445        this._paramsIds = isRegexPattern? null : patternLexer.getParamIds(pattern);
38446        this._optionalParamsIds = isRegexPattern? null : patternLexer.getOptionalParamsIds(pattern);
38447        this._matchRegexp = isRegexPattern? pattern : patternLexer.compilePattern(pattern, router.ignoreCase);
38448        this.matched = new signals.Signal();
38449        this.switched = new signals.Signal();
38450        if (callback) {
38451            this.matched.add(callback);
38452        }
38453        this._priority = priority || 0;
38454    }
38455
38456    Route.prototype = {
38457
38458        greedy : false,
38459
38460        rules : void(0),
38461
38462        match : function (request) {
38463            request = request || '';
38464            return this._matchRegexp.test(request) && this._validateParams(request); //validate params even if regexp because of `request_` rule.
38465        },
38466
38467        _validateParams : function (request) {
38468            var rules = this.rules,
38469                values = this._getParamsObject(request),
38470                key;
38471            for (key in rules) {
38472                // normalize_ isn't a validation rule... (#39)
38473                if(key !== 'normalize_' && rules.hasOwnProperty(key) && ! this._isValidParam(request, key, values)){
38474                    return false;
38475                }
38476            }
38477            return true;
38478        },
38479
38480        _isValidParam : function (request, prop, values) {
38481            var validationRule = this.rules[prop],
38482                val = values[prop],
38483                isValid = false,
38484                isQuery = (prop.indexOf('?') === 0);
38485
38486            if (val == null && this._optionalParamsIds && arrayIndexOf(this._optionalParamsIds, prop) !== -1) {
38487                isValid = true;
38488            }
38489            else if (isRegExp(validationRule)) {
38490                if (isQuery) {
38491                    val = values[prop +'_']; //use raw string
38492                }
38493                isValid = validationRule.test(val);
38494            }
38495            else if (isArray(validationRule)) {
38496                if (isQuery) {
38497                    val = values[prop +'_']; //use raw string
38498                }
38499                isValid = this._isValidArrayRule(validationRule, val);
38500            }
38501            else if (isFunction(validationRule)) {
38502                isValid = validationRule(val, request, values);
38503            }
38504
38505            return isValid; //fail silently if validationRule is from an unsupported type
38506        },
38507
38508        _isValidArrayRule : function (arr, val) {
38509            if (! this._router.ignoreCase) {
38510                return arrayIndexOf(arr, val) !== -1;
38511            }
38512
38513            if (typeof val === 'string') {
38514                val = val.toLowerCase();
38515            }
38516
38517            var n = arr.length,
38518                item,
38519                compareVal;
38520
38521            while (n--) {
38522                item = arr[n];
38523                compareVal = (typeof item === 'string')? item.toLowerCase() : item;
38524                if (compareVal === val) {
38525                    return true;
38526                }
38527            }
38528            return false;
38529        },
38530
38531        _getParamsObject : function (request) {
38532            var shouldTypecast = this._router.shouldTypecast,
38533                values = this._router.patternLexer.getParamValues(request, this._matchRegexp, shouldTypecast),
38534                o = {},
38535                n = values.length,
38536                param, val;
38537            while (n--) {
38538                val = values[n];
38539                if (this._paramsIds) {
38540                    param = this._paramsIds[n];
38541                    if (param.indexOf('?') === 0 && val) {
38542                        //make a copy of the original string so array and
38543                        //RegExp validation can be applied properly
38544                        o[param +'_'] = val;
38545                        //update vals_ array as well since it will be used
38546                        //during dispatch
38547                        val = decodeQueryString(val, shouldTypecast);
38548                        values[n] = val;
38549                    }
38550                    // IE will capture optional groups as empty strings while other
38551                    // browsers will capture `undefined` so normalize behavior.
38552                    // see: #gh-58, #gh-59, #gh-60
38553                    if ( _hasOptionalGroupBug && val === '' && arrayIndexOf(this._optionalParamsIds, param) !== -1 ) {
38554                        val = void(0);
38555                        values[n] = val;
38556                    }
38557                    o[param] = val;
38558                }
38559                //alias to paths and for RegExp pattern
38560                o[n] = val;
38561            }
38562            o.request_ = shouldTypecast? typecastValue(request) : request;
38563            o.vals_ = values;
38564            return o;
38565        },
38566
38567        _getParamsArray : function (request) {
38568            var norm = this.rules? this.rules.normalize_ : null,
38569                params;
38570            norm = norm || this._router.normalizeFn; // default normalize
38571            if (norm && isFunction(norm)) {
38572                params = norm(request, this._getParamsObject(request));
38573            } else {
38574                params = this._getParamsObject(request).vals_;
38575            }
38576            return params;
38577        },
38578
38579        interpolate : function(replacements) {
38580            var str = this._router.patternLexer.interpolate(this._pattern, replacements);
38581            if (! this._validateParams(str) ) {
38582                throw new Error('Generated string doesn\'t validate against `Route.rules`.');
38583            }
38584            return str;
38585        },
38586
38587        dispose : function () {
38588            this._router.removeRoute(this);
38589        },
38590
38591        _destroy : function () {
38592            this.matched.dispose();
38593            this.switched.dispose();
38594            this.matched = this.switched = this._pattern = this._matchRegexp = null;
38595        },
38596
38597        toString : function () {
38598            return '[Route pattern:"'+ this._pattern +'", numListeners:'+ this.matched.getNumListeners() +']';
38599        }
38600
38601    };
38602
38603
38604
38605    // Pattern Lexer ------
38606    //=====================
38607
38608    Crossroads.prototype.patternLexer = (function () {
38609
38610        var
38611            //match chars that should be escaped on string regexp
38612            ESCAPE_CHARS_REGEXP = /[\\.+*?\^$\[\](){}\/'#]/g,
38613
38614            //trailing slashes (begin/end of string)
38615            LOOSE_SLASHES_REGEXP = /^\/|\/$/g,
38616            LEGACY_SLASHES_REGEXP = /\/$/g,
38617
38618            //params - everything between `{ }` or `: :`
38619            PARAMS_REGEXP = /(?:\{|:)([^}:]+)(?:\}|:)/g,
38620
38621            //used to save params during compile (avoid escaping things that
38622            //shouldn't be escaped).
38623            TOKENS = {
38624                'OS' : {
38625                    //optional slashes
38626                    //slash between `::` or `}:` or `\w:` or `:{?` or `}{?` or `\w{?`
38627                    rgx : /([:}]|\w(?=\/))\/?(:|(?:\{\?))/g,
38628                    save : '$1{{id}}$2',
38629                    res : '\\/?'
38630                },
38631                'RS' : {
38632                    //required slashes
38633                    //used to insert slash between `:{` and `}{`
38634                    rgx : /([:}])\/?(\{)/g,
38635                    save : '$1{{id}}$2',
38636                    res : '\\/'
38637                },
38638                'RQ' : {
38639                    //required query string - everything in between `{? }`
38640                    rgx : /\{\?([^}]+)\}/g,
38641                    //everything from `?` till `#` or end of string
38642                    res : '\\?([^#]+)'
38643                },
38644                'OQ' : {
38645                    //optional query string - everything in between `:? :`
38646                    rgx : /:\?([^:]+):/g,
38647                    //everything from `?` till `#` or end of string
38648                    res : '(?:\\?([^#]*))?'
38649                },
38650                'OR' : {
38651                    //optional rest - everything in between `: *:`
38652                    rgx : /:([^:]+)\*:/g,
38653                    res : '(.*)?' // optional group to avoid passing empty string as captured
38654                },
38655                'RR' : {
38656                    //rest param - everything in between `{ *}`
38657                    rgx : /\{([^}]+)\*\}/g,
38658                    res : '(.+)'
38659                },
38660                // required/optional params should come after rest segments
38661                'RP' : {
38662                    //required params - everything between `{ }`
38663                    rgx : /\{([^}]+)\}/g,
38664                    res : '([^\\/?]+)'
38665                },
38666                'OP' : {
38667                    //optional params - everything between `: :`
38668                    rgx : /:([^:]+):/g,
38669                    res : '([^\\/?]+)?\/?'
38670                }
38671            },
38672
38673            LOOSE_SLASH = 1,
38674            STRICT_SLASH = 2,
38675            LEGACY_SLASH = 3,
38676
38677            _slashMode = LOOSE_SLASH;
38678
38679
38680        function precompileTokens(){
38681            var key, cur;
38682            for (key in TOKENS) {
38683                if (TOKENS.hasOwnProperty(key)) {
38684                    cur = TOKENS[key];
38685                    cur.id = '__CR_'+ key +'__';
38686                    cur.save = ('save' in cur)? cur.save.replace('{{id}}', cur.id) : cur.id;
38687                    cur.rRestore = new RegExp(cur.id, 'g');
38688                }
38689            }
38690        }
38691        precompileTokens();
38692
38693
38694        function captureVals(regex, pattern) {
38695            var vals = [], match;
38696            // very important to reset lastIndex since RegExp can have "g" flag
38697            // and multiple runs might affect the result, specially if matching
38698            // same string multiple times on IE 7-8
38699            regex.lastIndex = 0;
38700            while (match = regex.exec(pattern)) {
38701                vals.push(match[1]);
38702            }
38703            return vals;
38704        }
38705
38706        function getParamIds(pattern) {
38707            return captureVals(PARAMS_REGEXP, pattern);
38708        }
38709
38710        function getOptionalParamsIds(pattern) {
38711            return captureVals(TOKENS.OP.rgx, pattern);
38712        }
38713
38714        function compilePattern(pattern, ignoreCase) {
38715            pattern = pattern || '';
38716
38717            if(pattern){
38718                if (_slashMode === LOOSE_SLASH) {
38719                    pattern = pattern.replace(LOOSE_SLASHES_REGEXP, '');
38720                }
38721                else if (_slashMode === LEGACY_SLASH) {
38722                    pattern = pattern.replace(LEGACY_SLASHES_REGEXP, '');
38723                }
38724
38725                //save tokens
38726                pattern = replaceTokens(pattern, 'rgx', 'save');
38727                //regexp escape
38728                pattern = pattern.replace(ESCAPE_CHARS_REGEXP, '\\$&');
38729                //restore tokens
38730                pattern = replaceTokens(pattern, 'rRestore', 'res');
38731
38732                if (_slashMode === LOOSE_SLASH) {
38733                    pattern = '\\/?'+ pattern;
38734                }
38735            }
38736
38737            if (_slashMode !== STRICT_SLASH) {
38738                //single slash is treated as empty and end slash is optional
38739                pattern += '\\/?';
38740            }
38741            return new RegExp('^'+ pattern + '$', ignoreCase? 'i' : '');
38742        }
38743
38744        function replaceTokens(pattern, regexpName, replaceName) {
38745            var cur, key;
38746            for (key in TOKENS) {
38747                if (TOKENS.hasOwnProperty(key)) {
38748                    cur = TOKENS[key];
38749                    pattern = pattern.replace(cur[regexpName], cur[replaceName]);
38750                }
38751            }
38752            return pattern;
38753        }
38754
38755        function getParamValues(request, regexp, shouldTypecast) {
38756            var vals = regexp.exec(request);
38757            if (vals) {
38758                vals.shift();
38759                if (shouldTypecast) {
38760                    vals = typecastArrayValues(vals);
38761                }
38762            }
38763            return vals;
38764        }
38765
38766        function interpolate(pattern, replacements) {
38767            // default to an empty object because pattern might have just
38768            // optional arguments
38769            replacements = replacements || {};
38770            if (typeof pattern !== 'string') {
38771                throw new Error('Route pattern should be a string.');
38772            }
38773
38774            var replaceFn = function(match, prop){
38775                    var val;
38776                    prop = (prop.substr(0, 1) === '?')? prop.substr(1) : prop;
38777                    if (replacements[prop] != null) {
38778                        if (typeof replacements[prop] === 'object') {
38779                            var queryParts = [], rep;
38780                            for(var key in replacements[prop]) {
38781                                rep = replacements[prop][key];
38782                                if (isArray(rep)) {
38783                                    for (var k in rep) {
38784                                        if ( key.slice(-2) == '[]' ) {
38785                                            queryParts.push(encodeURI(key.slice(0, -2)) + '[]=' + encodeURI(rep[k]));
38786                                        } else {
38787                                            queryParts.push(encodeURI(key + '=' + rep[k]));
38788                                        }
38789                                    }
38790                                }
38791                                else {
38792                                    queryParts.push(encodeURI(key + '=' + rep));
38793                                }
38794                            }
38795                            val = '?' + queryParts.join('&');
38796                        } else {
38797                            // make sure value is a string see #gh-54
38798                            val = String(replacements[prop]);
38799                        }
38800
38801                        if (match.indexOf('*') === -1 && val.indexOf('/') !== -1) {
38802                            throw new Error('Invalid value "'+ val +'" for segment "'+ match +'".');
38803                        }
38804                    }
38805                    else if (match.indexOf('{') !== -1) {
38806                        throw new Error('The segment '+ match +' is required.');
38807                    }
38808                    else {
38809                        val = '';
38810                    }
38811                    return val;
38812                };
38813
38814            if (! TOKENS.OS.trail) {
38815                TOKENS.OS.trail = new RegExp('(?:'+ TOKENS.OS.id +')+$');
38816            }
38817
38818            return pattern
38819                        .replace(TOKENS.OS.rgx, TOKENS.OS.save)
38820                        .replace(PARAMS_REGEXP, replaceFn)
38821                        .replace(TOKENS.OS.trail, '') // remove trailing
38822                        .replace(TOKENS.OS.rRestore, '/'); // add slash between segments
38823        }
38824
38825        //API
38826        return {
38827            strict : function(){
38828                _slashMode = STRICT_SLASH;
38829            },
38830            loose : function(){
38831                _slashMode = LOOSE_SLASH;
38832            },
38833            legacy : function(){
38834                _slashMode = LEGACY_SLASH;
38835            },
38836            getParamIds : getParamIds,
38837            getOptionalParamsIds : getOptionalParamsIds,
38838            getParamValues : getParamValues,
38839            compilePattern : compilePattern,
38840            interpolate : interpolate
38841        };
38842
38843    }());
38844
38845
38846    return crossroads;
38847};
38848
38849if (typeof define === 'function' && define.amd) {
38850    define('crossroads',['signals'], factory);
38851} else if (typeof module !== 'undefined' && module.exports) { //Node
38852    module.exports = factory(require('signals'));
38853} else {
38854    /*jshint sub:true */
38855    window['crossroads'] = factory(window['signals']);
38856}
38857
38858}());
38859
38860
38861define('dataFilterProcessor',[],
38862function () {
38863    
38864    return {
38865
38866        currentParams: [],
38867
38868        previousParams: [],
38869
38870        clearParams: function () {
38871            this.currentParams = [];
38872            this.previousParams = [];
38873        },
38874
38875        calDifference: function(previousParams, currentParams, processCohorts) {
38876            var deletedCohorts = [],
38877                addedCohorts = [];
38878            var iPrevious = 0,
38879                iCurrent = 0;
38880            while (iPrevious < previousParams.length || iCurrent < currentParams.length) {
38881                if (iPrevious >= previousParams.length) {
38882                    //put into added box
38883                    addedCohorts.push(currentParams[iCurrent]);
38884                    iCurrent++;
38885                }
38886                else if (iCurrent >= currentParams.length) {
38887                    //put into deleted box
38888                    deletedCohorts.push(previousParams[iPrevious]);
38889                    iPrevious++;
38890                }
38891                else if (this.isSameCohort(previousParams[iPrevious], currentParams[iCurrent])) {
38892                    iPrevious++;
38893                    iCurrent++;
38894                }
38895                else {
38896                    //put into deleted box
38897                    deletedCohorts.push(previousParams[iPrevious]);
38898                    iPrevious++;
38899                }
38900            }
38901
38902            processCohorts(deletedCohorts, addedCohorts);
38903        },
38904
38905        processFilterParams: function(params, processCohorts) {
38906            if (params == null) {
38907                params = '';
38908            }
38909
38910            var result = { notEmpty: false, filling: "" };
38911
38912            // split the url;
38913            var parameters = params.split('/');
38914
38915            // group the params by filter
38916            var paramsGroups = [], size = 7;
38917
38918            while (parameters.length > 0)
38919                paramsGroups.push(parameters.splice(0, size));
38920
38921            var lastLength = paramsGroups[paramsGroups.length - 1].length;
38922            if (lastLength < 7 && lastLength > 1) {
38923                // fill the params if incomplete
38924                for (var i = lastLength - 1; i < 7; i++) {
38925                    paramsGroups[paramsGroups.length - 1].push("");
38926                    result.filling += '/';
38927                }
38928            } else if (lastLength <= 1) {
38929                paramsGroups.pop(paramsGroups[paramsGroups.length - 1]);
38930            }
38931
38932            this.previousParams = this.currentParams;
38933            this.currentParams = paramsGroups;
38934
38935            this.calDifference(this.previousParams, this.currentParams, processCohorts);
38936
38937            result.notEmpty = this.currentParams.length > 0;
38938
38939            return result;
38940        },
38941
38942        getFilterFromParams: function(params) {
38943            var filter = {};
38944
38945            // 0 userfilter
38946            filter.userfilter = params[0];
38947
38948            switch (filter.userfilter) {
38949                case 'Country':
38950                    var country_region = params[1].split('_');
38951                    filter.selectedcountry = country_region[0];
38952                    if (country_region[1] != '') {
38953                        filter.selectedregion = country_region[1];
38954                    }
38955                    break;
38956                case 'Group':
38957                    filter.selectedgroupid = params[1];
38958                    break;
38959                case 'Department':
38960                    var temp = params[1].split('-');
38961                    filter.selecteddepartmentid = temp[0];
38962                    if (temp[1] != null) {
38963                        filter.isfilteredbyyeargroup = true;
38964                        filter.selectedyeargroupid = temp[1];
38965                    }
38966                    break;
38967                case 'Teacher':
38968                    filter.selectedteacherid = params[1];
38969                    break;
38970                case 'Student':
38971                    filter.selecteduserid = params[1];
38972                    break;
38973                case 'School':
38974                    filter.selectedschoolid = params[1];
38975                    break;
38976                case 'Assignment':
38977                    filter.selectedassignmentid = params[1];
38978                    break;
38979                default:
38980                    break;
38981            }
38982
38983
38984            // 2 start date
38985            if (params[2] != '') {
38986                filter.IsFilteredByDateRange = true;
38987                filter.StartDate = this.DateStringFromUrl(params[2]);
38988            }
38989
38990            // 3 end date
38991            if (params[3] != '') {
38992                filter.IsFilteredByDateRange = true;
38993                filter.EndDate = this.DateStringFromUrl(params[3]);
38994            }
38995
38996            // 4, 5 age range
38997            if (params[4] != '') {
38998                filter.IsFilteredByAgeRange = true;
38999                filter.AgeRangeYoungest = params[4];
39000            }
39001
39002            // 3 end date
39003            if (params[5] != '') {
39004                filter.IsFilteredByAgeRange = true;
39005                filter.AgeRangeOldest = params[5];
39006            }
39007
39008            // 6 gender and extension
39009            if (params[6] != '') {
39010                var extendParams = params[6].split('_');
39011                var i = 0;
39012                if (extendParams[i] != '') {
39013                    filter.GenderFilter = params[6] == 'M' ? 'Male' : 'Female';
39014                }
39015                i++;
39016                if (extendParams[i] == 'T') {
39017                    filter.IsOnlyShowCompletedAttempts = true;
39018                    i++;
39019                }
39020                if (extendParams[i] == 'LQ') {
39021                    filter.IsFilteredByLiveQuiz = true;
39022                    filter.SelectedLiveQuizId = extendParams[i + 1];
39023                }
39024
39025            }
39026
39027            return filter;
39028        },
39029
39030        getUrlFromFilter: function(filter) {
39031
39032            if (filter == null)
39033                return 'All///////';
39034
39035            var url = '';
39036
39037            url += filter.userfilter;
39038            url += '/';
39039
39040            switch (filter.userfilter) {
39041                case 'Country':
39042                    url += filter.selectedcountry;
39043                    url += '_';
39044                    if (filter.selectedregion != null)
39045                        url += filter.selectedregion;
39046                    break;
39047                case 'Group':
39048                    url += filter.selectedgroupid;
39049                    break;
39050                case 'Department':
39051                    url += filter.selecteddepartmentid;
39052                    if (filter.isfilteredbyyeargroup) {
39053                        url = url + '-' + filter.selectedyeargroupid;
39054                    }
39055                    break;
39056                case 'Teacher':
39057                    url += filter.selectedteacherid;
39058                    break;
39059                case 'Student':
39060                    url += filter.selecteduserid;
39061                    break;
39062                case 'School':
39063                    url += filter.selectedschoolid;
39064                    break;
39065                case 'Assignment':
39066                    url += filter.selectedassignmentid;
39067                default:
39068                    break;
39069            }
39070            url += '/';
39071
39072            if (filter.StartDate != null)
39073                url += this.UrlFromDateString(filter.StartDate);
39074            url += '/';
39075
39076            if (filter.EndDate != null)
39077                url += this.UrlFromDateString(filter.EndDate);
39078            url += '/';
39079
39080            if (filter.AgeRangeYoungest != null)
39081                url += filter.AgeRangeYoungest;
39082            url += '/';
39083
39084            if (filter.AgeRangeOldest != null)
39085                url += filter.AgeRangeOldest;
39086            url += '/';
39087
39088            if (filter.GenderFilter != null && filter.GenderFilter != 'All') {
39089                url += filter.GenderFilter == 'Male' ? 'M' : 'F';
39090            }
39091            if (filter.IsOnlyShowCompletedAttempts == true) {
39092                url += '_T';
39093            }
39094            if (filter.IsFilteredByLiveQuiz == true) {
39095                url += '_LQ_' + filter.SelectedLiveQuizId;
39096            }
39097            url += '/';
39098
39099            return url;
39100        },
39101
39102        UrlFromDateString: function(dateString) {
39103            var dateurl = dateString;
39104            dateurl = dateurl.replace('/', '');
39105            dateurl = dateurl.replace('/', '');
39106            dateurl = dateurl.replace(' ', '');
39107            dateurl = dateurl.replace(':', '');
39108            return dateurl;
39109        },
39110
39111        DateStringFromUrl: function(dateUrl) {
39112            var dateString = dateUrl.substring(0, 2) + '/'
39113                + dateUrl.substring(2, 4) + '/'
39114                + dateUrl.substring(4, 8) + ' '
39115                + dateUrl.substring(8, 10) + ':'
39116                + dateUrl.substring(10, 12);
39117            return dateString;
39118        },
39119
39120        getUniqueCohortName: function(candidate, existing) {
39121            for (var i = 0; i < existing.length; i++) {
39122                if (existing[i] == candidate) {
39123                    return this.tryName(candidate, 2, existing);
39124                }
39125            }
39126            return candidate;
39127        },
39128
39129        tryName: function(candidate, num, existing) {
39130            for (var i = 0; i < existing.length; i++) {
39131                if (existing[i] == candidate + ' ' + num) {
39132                    return this.tryName(candidate, num + 1, existing);
39133                }
39134            }
39135            return candidate + ' ' + num;
39136        },
39137
39138        getDateRangeString: function(filter) {
39139            var result = "";
39140
39141            result += filter.StartDate + " to " + filter.EndDate + "\n";
39142
39143            return result;
39144        },
39145        
39146        getFilterDetailString: function(filter) {
39147            var result = [];
39148
39149            if (filter.GenderFilter != null && filter.GenderFilter != "All")
39150                result.push(filter.GenderFilter);
39151            
39152            if (filter.IsFilteredByDateRange)
39153                result.push(filter.StartDate + " - " + filter.EndDate);
39154            
39155            if (filter.IsFilteredByAgeRange)
39156                result.push((filter.AgeRangeYoungest == null ? "Any" : filter.AgeRangeYoungest) + " - " + (filter.AgeRangeOldest == null ? "Any" : filter.AgeRangeOldest));
39157
39158            if (result.length == 0) {
39159                return '&nbsp;';
39160            }
39161            return result.join('&nbsp;&nbsp;|&nbsp;&nbsp;');
39162        },
39163
39164        getCohortNameByUrl: function(url, existing) {
39165            for (var i = 0; i < existing.length; i++) {
39166                if (existing[i].url == url)
39167                    return existing[i].name;
39168            }
39169            return null;
39170        },
39171
39172        isSameCohort: function(params1, params2)
39173        {
39174            for(var i = 0; i < params1.length; i++)
39175            {
39176                if (params1[i] != params2[i])
39177                    return false;
39178            }
39179            return true;
39180        },
39181
39182        union_arrays: function(x, y) {
39183            var obj = {};
39184            for (var i = x.length-1; i >= 0; -- i)
39185                obj[x[i]] = x[i];
39186            for (var i = y.length-1; i >= 0; -- i)
39187                obj[y[i]] = y[i];
39188            var res = []
39189            for (var k in obj) {
39190                if (obj.hasOwnProperty(k))  // <-- optional
39191                    res.push(obj[k]);
39192            }
39193            return res;
39194        }
39195
39196    }
39197});
39198define('dataFilter',['jquery', 'bootstrap'], (function ($) {
39199
39200    //constructor
39201    var dataFilter = function () {
39202
39203    };
39204
39205    //public method
39206    dataFilter.prototype.init = function () {
39207        
39208        $('.js-set-deadline').click(function () {
39209            if (this.checked) {
39210                $('.js-date-entry').removeClass('hide');
39211            } else {
39212                $('.js-date-entry').addClass('hide');
39213            }
39214        });
39215
39216        $('#startDateTimePicker').datetimepicker({
39217            icons: {
39218                time: "icon-time",
39219                date: "icon-calendar",
39220                up: "icon-chevron-up",
39221                down: "icon-chevron-down"
39222            },
39223            format: "DD/MM/YYYY HH:mm"
39224        });
39225
39226        $('#endDateTimePicker').datetimepicker({
39227            icons: {
39228                time: "icon-time",
39229                date: "icon-calendar",
39230                up: "icon-chevron-up",
39231                down: "icon-chevron-down"
39232            },
39233            format: "DD/MM/YYYY HH:mm"
39234        });
39235
39236        $('#startDateTimePicker').on("dp.change", function (e) {
39237            $('#endDateTimePicker').data("DateTimePicker").setMinDate(e.date);
39238        });
39239
39240        $('.js-set-age-range').click(function () {
39241            if (this.checked) {
39242                $('.js-age-entry').removeClass('hide');
39243            } else {
39244                $('.js-age-entry').addClass('hide');
39245            }
39246        });
39247
39248        $('.js-delete-filter-table-row').click(function (event) {
39249            event.preventDefault();
39250            $(this).closest('tr').remove();
39251        });
39252        
39253        $('#UserFilter').change(function () {
39254
39255            switch (this.value) {
39256                case "Group":
39257                    $('#SelectedGroupId').removeClass('hide');
39258                    $('.js-filter-dropdown').not('#SelectedGroupId').addClass('hide');
39259                    break;
39260                case "Teacher":
39261                    $('#SelectedTeacherId').removeClass('hide');
39262                    $('.js-filter-dropdown').not('#SelectedTeacherId').addClass('hide');
39263                    break;
39264                case "Country":
39265                    $('#SelectedCountry').removeClass('hide');
39266                    $('#SelectedRegion').removeClass('hide');
39267                    $('.js-filter-dropdown').not('#SelectedCountry,#SelectedRegion').addClass('hide');
39268                    break;
39269                case "Student":
39270                    $('#SelectedUserId').removeClass('hide');
39271                    $('.js-filter-dropdown').not('#SelectedUserId').addClass('hide');
39272                    break;
39273                default:
39274                    $('.js-filter-dropdown').addClass('hide');
39275                    break;
39276            };
39277
39278            SwitchLoadDropDownItems(this.value);
39279
39280        });
39281
39282        $('#SelectedCountry').change(function () {
39283            LoadRegionsDropDown(this.value);
39284        });
39285
39286
39287        $('input:radio[name=toggleCountsPercentage]').change(function () {
39288
39289            if (this.value == 'counts') {
39290                $('.js-answer-dots').addClass('hide');
39291                $('.js-answer-count').removeClass('hide');
39292                $('.js-answer-percentage').addClass('hide');
39293            } else if (this.value == 'percentage') {
39294                $('.js-answer-dots').addClass('hide');
39295                $('.js-answer-count').addClass('hide');
39296                $('.js-answer-percentage').removeClass('hide');
39297            } else {
39298                $('.js-answer-dots').removeClass('hide');
39299                $('.js-answer-count').addClass('hide');
39300                $('.js-answer-percentage').addClass('hide');
39301            }
39302        });
39303
39304        SwitchLoadDropDownItems($('#UserFilter').val());
39305
39306
39307    };
39308
39309    function SwitchLoadDropDownItems(userFilterValue) {
39310
39311        switch (userFilterValue) {
39312            case "Group":
39313                LoadDropDownItems('#SelectedGroupId', '/Data/LoadGroups')
39314                break;
39315            case "Teacher":
39316                LoadDropDownItems('#SelectedTeacherId', '/Data/LoadTeachers')
39317                break;
39318            case "Country":
39319                LoadDropDownItems('#SelectedCountry', '/Data/LoadCountries')
39320                if ($('#SelectedCountry').val() != "")
39321                    LoadRegionsDropDown($('#SelectedCountry').val());
39322                break;
39323            case "Student":
39324                LoadDropDownItems('#SelectedUserId', '/Data/LoadStudents')
39325                break;
39326            default:
39327                break;
39328        };
39329
39330    }
39331
39332    function LoadRegionsDropDown(countryname) {
39333        var model = { countryname: countryname };
39334        var id = '#SelectedRegion'
39335
39336        $.ajax({
39337            url: '/Data/LoadRegions',
39338            type: 'POST',
39339            data: JSON.stringify(model),
39340            datatype: 'json',
39341            processData: false,
39342            contentType: 'application/json; charset=utf-8',
39343            success: function (data) {
39344                var dropDown = $(id);
39345                var selectedValue = $(dropDown).val();
39346
39347                $(dropDown).empty();
39348
39349                $(document.createElement('option'))
39350                    .attr('value', '')
39351                    .text('Choose...')
39352                    .appendTo(dropDown);
39353
39354                $(data).each(function () {
39355                    $(document.createElement('option'))
39356                        .attr('value', this.Value)
39357                        .text(this.Text)
39358                        .appendTo(dropDown);
39359                });
39360
39361                $(dropDown).val(selectedValue);
39362                $(dropDown).data('listed', true);
39363            }
39364        });
39365    }
39366    
39367    function LoadDropDownItems(id, url) {
39368        if (!($(id).data('listed') === true)) {
39369            $.getJSON(url, function (data) {
39370                var dropDown = $(id);
39371                var selectedValue = $(dropDown).val();
39372
39373                $(dropDown).empty();
39374
39375                $(document.createElement('option'))
39376                    .attr('value', '')
39377                    .text('Choose...')
39378                    .appendTo(dropDown);
39379
39380                $(data).each(function () {
39381                    $(document.createElement('option'))
39382                        .attr('value', this.Value)
39383                        .text(this.Text)
39384                        .appendTo(dropDown);
39385                });
39386
39387                $(dropDown).val(selectedValue);
39388                $(dropDown).data('listed', true);
39389            });
39390        }
39391    };
39392
39393    //public module
39394    return dataFilter;
39395
39396}));
39397
39398(function (exports) {
39399    function copyOwnFrom(target, source) {
39400        Object.getOwnPropertyNames(source).forEach(function(propName) {
39401            Object.defineProperty(target, propName,
39402                Object.getOwnPropertyDescriptor(source, propName));
39403        });
39404        return target;
39405    }
39406    
39407    function Symbol(name, props) {
39408        this.name = name;
39409        if (props) {
39410            copyOwnFrom(this, props);
39411        }
39412        Object.freeze(this);
39413    }
39414    /** We don’t want the mutable Object.prototype in the prototype chain */
39415    Symbol.prototype = Object.create(null);
39416    Symbol.prototype.constructor = Symbol;
39417    /**
39418     * Without Object.prototype in the prototype chain, we need toString()
39419     * in order to display symbols.
39420     */
39421    Symbol.prototype.toString = function () {
39422        return "|"+this.name+"|";
39423    };
39424    Object.freeze(Symbol.prototype);
39425
39426    Enum = function (obj) {
39427        if (arguments.length === 1 && obj !== null && typeof obj === "object") {
39428            Object.keys(obj).forEach(function (name) {
39429                this[name] = new Symbol(name, obj[name]);
39430            }, this);
39431        } else {
39432            Array.prototype.forEach.call(arguments, function (name) {
39433                this[name] = new Symbol(name);
39434            }, this);
39435        }
39436        Object.freeze(this);
39437    }
39438    Enum.prototype.symbols = function() {
39439        return Object.keys(this).map(
39440            function(key) {
39441                return this[key];
39442            }, this
39443        );
39444    }
39445    Enum.prototype.contains = function(sym) {
39446        if (! sym instanceof Symbol) return false;
39447        return this[sym.name] === sym;
39448    }
39449    exports.Enum = Enum;
39450    exports.Symbol = Symbol;
39451}(typeof exports === "undefined" ? this.enums = {} : exports));
39452// Explanation of this pattern: http://www.2ality.com/2011/08/universal-modules.html;
39453define("enums", (function (global) {
39454    return function () {
39455        var ret, fn;
39456        return ret || global.enums;
39457    };
39458}(this)));
39459
39460/* build: `node build.js modules=ALL exclude=gestures` */
39461/*! Fabric.js Copyright 2008-2013, Printio (Juriy Zaytsev, Maxim Chernyak) */
39462
39463var fabric = fabric || { version: "1.3.7" };
39464if (typeof exports !== 'undefined') {
39465  exports.fabric = fabric;
39466}
39467
39468if (typeof document !== 'undefined' && typeof window !== 'undefined') {
39469  fabric.document = document;
39470  fabric.window = window;
39471}
39472else {
39473  // assume we're running under node.js when document/window are not present
39474  fabric.document = require("jsdom").jsdom("<!DOCTYPE html><html><head></head><body></body></html>");
39475  fabric.window = fabric.document.createWindow();
39476}
39477
39478/**
39479 * True when in environment that supports touch events
39480 * @type boolean
39481 */
39482fabric.isTouchSupported = "ontouchstart" in fabric.document.documentElement;
39483
39484/**
39485 * True when in environment that's probably Node.js
39486 * @type boolean
39487 */
39488fabric.isLikelyNode = typeof Buffer !== 'undefined' && typeof window === 'undefined';
39489
39490
39491/*!
39492 * Copyright (c) 2009 Simo Kinnunen.
39493 * Licensed under the MIT license.
39494 */
39495
39496var Cufon = (function() {
39497
39498  /** @ignore */
39499  var api = function() {
39500    return api.replace.apply(null, arguments);
39501  };
39502
39503  /** @ignore */
39504  var DOM = api.DOM = {
39505
39506    ready: (function() {
39507
39508      var complete = false, readyStatus = { loaded: 1, complete: 1 };
39509
39510      var queue = [], /** @ignore */ perform = function() {
39511        if (complete) return;
39512        complete = true;
39513        for (var fn; fn = queue.shift(); fn());
39514      };
39515
39516      // Gecko, Opera, WebKit r26101+
39517
39518      if (fabric.document.addEventListener) {
39519        fabric.document.addEventListener('DOMContentLoaded', perform, false);
39520        fabric.window.addEventListener('pageshow', perform, false); // For cached Gecko pages
39521      }
39522
39523      // Old WebKit, Internet Explorer
39524
39525      if (!fabric.window.opera && fabric.document.readyState) (function() {
39526        readyStatus[fabric.document.readyState] ? perform() : setTimeout(arguments.callee, 10);
39527      })();
39528
39529      // Internet Explorer
39530
39531      if (fabric.document.readyState && fabric.document.createStyleSheet) (function() {
39532        try {
39533          fabric.document.body.doScroll('left');
39534          perform();
39535        }
39536        catch (e) {
39537          setTimeout(arguments.callee, 1);
39538        }
39539      })();
39540
39541      addEvent(fabric.window, 'load', perform); // Fallback
39542
39543      return function(listener) {
39544        if (!arguments.length) perform();
39545        else complete ? listener() : queue.push(listener);
39546      };
39547
39548    })()
39549
39550  };
39551
39552  /** @ignore */
39553  var CSS = api.CSS = /** @ignore */ {
39554
39555    /** @ignore */
39556    Size: function(value, base) {
39557
39558      this.value = parseFloat(value);
39559      this.unit = String(value).match(/[a-z%]*$/)[0] || 'px';
39560
39561      /** @ignore */
39562      this.convert = function(value) {
39563        return value / base * this.value;
39564      };
39565
39566      /** @ignore */
39567      this.convertFrom = function(value) {
39568        return value / this.value * base;
39569      };
39570
39571      /** @ignore */
39572      this.toString = function() {
39573        return this.value + this.unit;
39574      };
39575
39576    },
39577
39578    /** @ignore */
39579    getStyle: function(el) {
39580      return new Style(el.style);
39581      /*
39582      var view = document.defaultView;
39583      if (view && view.getComputedStyle) return new Style(view.getComputedStyle(el, null));
39584      if (el.currentStyle) return new Style(el.currentStyle);
39585      return new Style(el.style);
39586      */
39587    },
39588
39589    quotedList: cached(function(value) {
39590      // doesn't work properly with empty quoted strings (""), but
39591      // it's not worth the extra code.
39592      var list = [], re = /\s*((["'])([\s\S]*?[^\\])\2|[^,]+)\s*/g, match;
39593      while (match = re.exec(value)) list.push(match[3] || match[1]);
39594      return list;
39595    }),
39596
39597    ready: (function() {
39598
39599      var complete = false;
39600
39601      var queue = [], perform = function() {
39602        complete = true;
39603        for (var fn; fn = queue.shift(); fn());
39604      };
39605
39606      // Safari 2 does not include <style> elements in document.styleSheets.
39607      // Safari 2 also does not support Object.prototype.propertyIsEnumerable.
39608
39609      var styleElements = Object.prototype.propertyIsEnumerable ? elementsByTagName('style') : { length: 0 };
39610      var linkElements = elementsByTagName('link');
39611
39612      DOM.ready(function() {
39613        // These checks are actually only needed for WebKit-based browsers, but don't really hurt other browsers.
39614        var linkStyles = 0, link;
39615        for (var i = 0, l = linkElements.length; link = linkElements[i], i < l; ++i) {
39616          // WebKit does not load alternate stylesheets.
39617          if (!link.disabled && link.rel.toLowerCase() == 'stylesheet') ++linkStyles;
39618        }
39619        if (fabric.document.styleSheets.length >= styleElements.length + linkStyles) perform();
39620        else setTimeout(arguments.callee, 10);
39621      });
39622
39623      return function(listener) {
39624        if (complete) listener();
39625        else queue.push(listener);
39626      };
39627
39628    })(),
39629
39630    /** @ignore */
39631    supports: function(property, value) {
39632      var checker = fabric.document.createElement('span').style;
39633      if (checker[property] === undefined) return false;
39634      checker[property] = value;
39635      return checker[property] === value;
39636    },
39637
39638    /** @ignore */
39639    textAlign: function(word, style, position, wordCount) {
39640      if (style.get('textAlign') == 'right') {
39641        if (position > 0) word = ' ' + word;
39642      }
39643      else if (position < wordCount - 1) word += ' ';
39644      return word;
39645    },
39646
39647    /** @ignore */
39648    textDecoration: function(el, style) {
39649      if (!style) style = this.getStyle(el);
39650      var types = {
39651        underline: null,
39652        overline: null,
39653        'line-through': null
39654      };
39655      for (var search = el; search.parentNode && search.parentNode.nodeType == 1; ) {
39656        var foundAll = true;
39657        for (var type in types) {
39658          if (types[type]) continue;
39659          if (style.get('textDecoration').indexOf(type) != -1) types[type] = style.get('color');
39660          foundAll = false;
39661        }
39662        if (foundAll) break; // this is rather unlikely to happen
39663        style = this.getStyle(search = search.parentNode);
39664      }
39665      return types;
39666    },
39667
39668    textShadow: cached(function(value) {
39669      if (value == 'none') return null;
39670      var shadows = [], currentShadow = {}, result, offCount = 0;
39671      var re = /(#[a-f0-9]+|[a-z]+\(.*?\)|[a-z]+)|(-?[\d.]+[a-z%]*)|,/ig;
39672      while (result = re.exec(value)) {
39673        if (result[0] == ',') {
39674          shadows.push(currentShadow);
39675          currentShadow = {}, offCount = 0;
39676        }
39677        else if (result[1]) {
39678          currentShadow.color = result[1];
39679        }
39680        else {
39681          currentShadow[[ 'offX', 'offY', 'blur' ][offCount++]] = result[2];
39682        }
39683      }
39684      shadows.push(currentShadow);
39685      return shadows;
39686    }),
39687
39688    color: cached(function(value) {
39689      var parsed = {};
39690      parsed.color = value.replace(/^rgba\((.*?),\s*([\d.]+)\)/, function($0, $1, $2) {
39691        parsed.opacity = parseFloat($2);
39692        return 'rgb(' + $1 + ')';
39693      });
39694      return parsed;
39695    }),
39696
39697    /** @ignore */
39698    textTransform: function(text, style) {
39699      return text[{
39700        uppercase: 'toUpperCase',
39701        lowercase: 'toLowerCase'
39702      }[style.get('textTransform')] || 'toString']();
39703    }
39704
39705  };
39706
39707  function Font(data) {
39708
39709    var face = this.face = data.face;
39710    this.glyphs = data.glyphs;
39711    this.w = data.w;
39712    this.baseSize = parseInt(face['units-per-em'], 10);
39713
39714    this.family = face['font-family'].toLowerCase();
39715    this.weight = face['font-weight'];
39716    this.style = face['font-style'] || 'normal';
39717
39718    this.viewBox = (function () {
39719      var parts = face.bbox.split(/\s+/);
39720      var box = {
39721        minX: parseInt(parts[0], 10),
39722        minY: parseInt(parts[1], 10),
39723        maxX: parseInt(parts[2], 10),
39724        maxY: parseInt(parts[3], 10)
39725      };
39726      box.width = box.maxX - box.minX,
39727      box.height = box.maxY - box.minY;
39728      /** @ignore */
39729      box.toString = function() {
39730        return [ this.minX, this.minY, this.width, this.height ].join(' ');
39731      };
39732      return box;
39733    })();
39734
39735    this.ascent = -parseInt(face.ascent, 10);
39736    this.descent = -parseInt(face.descent, 10);
39737
39738    this.height = -this.ascent + this.descent;
39739
39740  }
39741
39742  function FontFamily() {
39743
39744    var styles = {}, mapping = {
39745      oblique: 'italic',
39746      italic: 'oblique'
39747    };
39748
39749    this.add = function(font) {
39750      (styles[font.style] || (styles[font.style] = {}))[font.weight] = font;
39751    };
39752
39753    /** @ignore */
39754    this.get = function(style, weight) {
39755      var weights = styles[style] || styles[mapping[style]]
39756        || styles.normal || styles.italic || styles.oblique;
39757      if (!weights) return null;
39758      // we don't have to worry about "bolder" and "lighter"
39759      // because IE's currentStyle returns a numeric value for it,
39760      // and other browsers use the computed value anyway
39761      weight = {
39762        normal: 400,
39763        bold: 700
39764      }[weight] || parseInt(weight, 10);
39765      if (weights[weight]) return weights[weight];
39766      // http://www.w3.org/TR/CSS21/fonts.html#propdef-font-weight
39767      // Gecko uses x99/x01 for lighter/bolder
39768      var up = {
39769        1: 1,
39770        99: 0
39771      }[weight % 100], alts = [], min, max;
39772      if (up === undefined) up = weight > 400;
39773      if (weight == 500) weight = 400;
39774      for (var alt in weights) {
39775        alt = parseInt(alt, 10);
39776        if (!min || alt < min) min = alt;
39777        if (!max || alt > max) max = alt;
39778        alts.push(alt);
39779      }
39780      if (weight < min) weight = min;
39781      if (weight > max) weight = max;
39782      alts.sort(function(a, b) {
39783        return (up
39784          ? (a > weight && b > weight) ? a < b : a > b
39785          : (a < weight && b < weight) ? a > b : a < b) ? -1 : 1;
39786      });
39787      return weights[alts[0]];
39788    };
39789
39790  }
39791
39792  function HoverHandler() {
39793
39794    function contains(node, anotherNode) {
39795      if (node.contains) return node.contains(anotherNode);
39796      return node.compareDocumentPosition(anotherNode) & 16;
39797    }
39798
39799    function onOverOut(e) {
39800      var related = e.relatedTarget;
39801      if (!related || contains(this, related)) return;
39802      trigger(this);
39803    }
39804
39805    function onEnterLeave(e) {
39806      trigger(this);
39807    }
39808
39809    function trigger(el) {
39810      // A timeout is needed so that the event can actually "happen"
39811      // before replace is triggered. This ensures that styles are up
39812      // to date.
39813      setTimeout(function() {
39814        api.replace(el, sharedStorage.get(el).options, true);
39815      }, 10);
39816    }
39817
39818    this.attach = function(el) {
39819      if (el.onmouseenter === undefined) {
39820        addEvent(el, 'mouseover', onOverOut);
39821        addEvent(el, 'mouseout', onOverOut);
39822      }
39823      else {
39824        addEvent(el, 'mouseenter', onEnterLeave);
39825        addEvent(el, 'mouseleave', onEnterLeave);
39826      }
39827    };
39828
39829  }
39830
39831  function Storage() {
39832
39833    var map = {}, at = 0;
39834
39835    function identify(el) {
39836      return el.cufid || (el.cufid = ++at);
39837    }
39838
39839    /** @ignore */
39840    this.get = function(el) {
39841      var id = identify(el);
39842      return map[id] || (map[id] = {});
39843    };
39844
39845  }
39846
39847  function Style(style) {
39848
39849    var custom = {}, sizes = {};
39850
39851    this.get = function(property) {
39852      return custom[property] != undefined ? custom[property] : style[property];
39853    };
39854
39855    this.getSize = function(property, base) {
39856      return sizes[property] || (sizes[property] = new CSS.Size(this.get(property), base));
39857    };
39858
39859    this.extend = function(styles) {
39860      for (var property in styles) custom[property] = styles[property];
39861      return this;
39862    };
39863
39864  }
39865
39866  function addEvent(el, type, listener) {
39867    if (el.addEventListener) {
39868      el.addEventListener(type, listener, false);
39869    }
39870    else if (el.attachEvent) {
39871      el.attachEvent('on' + type, function() {
39872        return listener.call(el, fabric.window.event);
39873      });
39874    }
39875  }
39876
39877  function attach(el, options) {
39878    var storage = sharedStorage.get(el);
39879    if (storage.options) return el;
39880    if (options.hover && options.hoverables[el.nodeName.toLowerCase()]) {
39881      hoverHandler.attach(el);
39882    }
39883    storage.options = options;
39884    return el;
39885  }
39886
39887  function cached(fun) {
39888    var cache = {};
39889    return function(key) {
39890      if (!cache.hasOwnProperty(key)) cache[key] = fun.apply(null, arguments);
39891      return cache[key];
39892    };
39893  }
39894
39895  function getFont(el, style) {
39896    if (!style) style = CSS.getStyle(el);
39897    var families = CSS.quotedList(style.get('fontFamily').toLowerCase()), family;
39898    for (var i = 0, l = families.length; i < l; ++i) {
39899      family = families[i];
39900      if (fonts[family]) return fonts[family].get(style.get('fontStyle'), style.get('fontWeight'));
39901    }
39902    return null;
39903  }
39904
39905  function elementsByTagName(query) {
39906    return fabric.document.getElementsByTagName(query);
39907  }
39908
39909  function merge() {
39910    var merged = {}, key;
39911    for (var i = 0, l = arguments.length; i < l; ++i) {
39912      for (key in arguments[i]) merged[key] = arguments[i][key];
39913    }
39914    return merged;
39915  }
39916
39917  function process(font, text, style, options, node, el) {
39918
39919    var separate = options.separate;
39920    if (separate == 'none') return engines[options.engine].apply(null, arguments);
39921    var fragment = fabric.document.createDocumentFragment(), processed;
39922    var parts = text.split(separators[separate]), needsAligning = (separate == 'words');
39923    if (needsAligning && HAS_BROKEN_REGEXP) {
39924      // @todo figure out a better way to do this
39925      if (/^\s/.test(text)) parts.unshift('');
39926      if (/\s$/.test(text)) parts.push('');
39927    }
39928    for (var i = 0, l = parts.length; i < l; ++i) {
39929      processed = engines[options.engine](font,
39930        needsAligning ? CSS.textAlign(parts[i], style, i, l) : parts[i],
39931        style, options, node, el, i < l - 1);
39932      if (processed) fragment.appendChild(processed);
39933    }
39934    return fragment;
39935  }
39936
39937  /** @ignore */
39938  function replaceElement(el, options) {
39939    var font, style, nextNode, redraw;
39940    for (var node = attach(el, options).firstChild; node; node = nextNode) {
39941      nextNode = node.nextSibling;
39942      redraw = false;
39943      if (node.nodeType == 1) {
39944        if (!node.firstChild) continue;
39945        if (!/cufon/.test(node.className)) {
39946          arguments.callee(node, options);
39947          continue;
39948        }
39949        else redraw = true;
39950      }
39951      if (!style) style = CSS.getStyle(el).extend(options);
39952      if (!font) font = getFont(el, style);
39953
39954      if (!font) continue;
39955      if (redraw) {
39956        engines[options.engine](font, null, style, options, node, el);
39957        continue;
39958      }
39959      var text = node.data;
39960      //for some reason, the carriage return is not stripped by IE but "\n" is, so let's keep \r as a new line marker...
39961      if (typeof G_vmlCanvasManager != 'undefined') {
39962          text = text.replace(/\r/g, "\n");
39963      }
39964      if (text === '') continue;
39965      var processed = process(font, text, style, options, node, el);
39966      if (processed) node.parentNode.replaceChild(processed, node);
39967      else node.parentNode.removeChild(node);
39968    }
39969  }
39970
39971  var HAS_BROKEN_REGEXP = ' '.split(/\s+/).length == 0;
39972
39973  var sharedStorage = new Storage();
39974  var hoverHandler = new HoverHandler();
39975  var replaceHistory = [];
39976
39977  var engines = {}, fonts = {}, defaultOptions = {
39978    engine: null,
39979    //fontScale: 1,
39980    //fontScaling: false,
39981    hover: false,
39982    hoverables: {
39983      a: true
39984    },
39985    printable: true,
39986    //rotation: 0,
39987    //selectable: false,
39988    selector: (
39989        fabric.window.Sizzle
39990      ||  (fabric.window.jQuery && function(query) { return jQuery(query); }) // avoid noConflict issues
39991      ||  (fabric.window.dojo && dojo.query)
39992      ||  (fabric.window.$$ && function(query) { return $$(query); })
39993      ||  (fabric.window.$ && function(query) { return $(query); })
39994      ||  (fabric.document.querySelectorAll && function(query) { return fabric.document.querySelectorAll(query); })
39995      ||  elementsByTagName
39996    ),
39997    separate: 'words', // 'none' and 'characters' are also accepted
39998    textShadow: 'none'
39999  };
40000
40001  var separators = {
40002    words: /\s+/,
40003    characters: ''
40004  };
40005
40006  /** @ignore */
40007  api.now = function() {
40008    DOM.ready();
40009    return api;
40010  };
40011
40012  /** @ignore */
40013  api.refresh = function() {
40014    var currentHistory = replaceHistory.splice(0, replaceHistory.length);
40015    for (var i = 0, l = currentHistory.length; i < l; ++i) {
40016      api.replace.apply(null, currentHistory[i]);
40017    }
40018    return api;
40019  };
40020
40021  /** @ignore */
40022  api.registerEngine = function(id, engine) {
40023    if (!engine) return api;
40024    engines[id] = engine;
40025    return api.set('engine', id);
40026  };
40027
40028  /** @ignore */
40029  api.registerFont = function(data) {
40030    var font = new Font(data), family = font.family;
40031    if (!fonts[family]) fonts[family] = new FontFamily();
40032    fonts[family].add(font);
40033    return api.set('fontFamily', '"' + family + '"');
40034  };
40035
40036  /** @ignore */
40037  api.replace = function(elements, options, ignoreHistory) {
40038    options = merge(defaultOptions, options);
40039    if (!options.engine) return api; // there's no browser support so we'll just stop here
40040    if (typeof options.textShadow == 'string' && options.textShadow)
40041      options.textShadow = CSS.textShadow(options.textShadow);
40042    if (!ignoreHistory) replaceHistory.push(arguments);
40043    if (elements.nodeType || typeof elements == 'string') elements = [ elements ];
40044    CSS.ready(function() {
40045      for (var i = 0, l = elements.length; i < l; ++i) {
40046        var el = elements[i];
40047        if (typeof el == 'string') api.replace(options.selector(el), options, true);
40048        else replaceElement(el, options);
40049      }
40050    });
40051    return api;
40052  };
40053
40054  /** @ignore */
40055  api.replaceElement = function(el, options) {
40056    options = merge(defaultOptions, options);
40057    if (typeof options.textShadow == 'string' && options.textShadow)
40058      options.textShadow = CSS.textShadow(options.textShadow);
40059    return replaceElement(el, options);
40060  };
40061
40062  api.engines = engines;
40063  api.fonts = fonts;
40064  /** @ignore */
40065  api.getOptions = function() {
40066    return merge(defaultOptions);
40067  };
40068
40069  /** @ignore */
40070  api.set = function(option, value) {
40071    defaultOptions[option] = value;
40072    return api;
40073  };
40074
40075  return api;
40076
40077})();
40078
40079Cufon.registerEngine('canvas', (function() {
40080
40081  // Safari 2 doesn't support .apply() on native methods
40082  var HAS_INLINE_BLOCK = Cufon.CSS.supports('display', 'inline-block');
40083
40084  // Firefox 2 w/ non-strict doctype (almost standards mode)
40085  var HAS_BROKEN_LINEHEIGHT = !HAS_INLINE_BLOCK && (fabric.document.compatMode == 'BackCompat' || /frameset|transitional/i.test(fabric.document.doctype.publicId));
40086
40087  var styleSheet = fabric.document.createElement('style');
40088  styleSheet.type = 'text/css';
40089
40090    var textNode = fabric.document.createTextNode(
40091        '.cufon-canvas{text-indent:0}' +
40092        '@media screen,projection{' +
40093          '.cufon-canvas{display:inline;display:inline-block;position:relative;vertical-align:middle' +
40094          (HAS_BROKEN_LINEHEIGHT
40095            ? ''
40096            : ';font-size:1px;line-height:1px') +
40097          '}.cufon-canvas .cufon-alt{display:-moz-inline-box;display:inline-block;width:0;height:0;overflow:hidden}' +
40098          (HAS_INLINE_BLOCK
40099            ? '.cufon-canvas canvas{position:relative}'
40100            : '.cufon-canvas canvas{position:absolute}') +
40101        '}' +
40102        '@media print{' +
40103          '.cufon-canvas{padding:0 !important}' +
40104          '.cufon-canvas canvas{display:none}' +
40105          '.cufon-canvas .cufon-alt{display:inline}' +
40106        '}'
40107      )
40108
40109  try {
40110      styleSheet.appendChild(textNode);
40111  } catch(e) {
40112      //IE8- can't do this...
40113      styleSheet.setAttribute("type", "text/css");
40114      styleSheet.styleSheet.cssText = textNode.data;
40115  }
40116  fabric.document.getElementsByTagName('head')[0].appendChild(styleSheet);
40117
40118  function generateFromVML(path, context) {
40119    var atX = 0, atY = 0;
40120    var code = [], re = /([mrvxe])([^a-z]*)/g, match;
40121    generate: for (var i = 0; match = re.exec(path); ++i) {
40122      var c = match[2].split(',');
40123      switch (match[1]) {
40124        case 'v':
40125          code[i] = { m: 'bezierCurveTo', a: [ atX + ~~c[0], atY + ~~c[1], atX + ~~c[2], atY + ~~c[3], atX += ~~c[4], atY += ~~c[5] ] };
40126          break;
40127        case 'r':
40128          code[i] = { m: 'lineTo', a: [ atX += ~~c[0], atY += ~~c[1] ] };
40129          break;
40130        case 'm':
40131          code[i] = { m: 'moveTo', a: [ atX = ~~c[0], atY = ~~c[1] ] };
40132          break;
40133        case 'x':
40134          code[i] = { m: 'closePath', a: [] };
40135          break;
40136        case 'e':
40137          break generate;
40138      }
40139      context[code[i].m].apply(context, code[i].a);
40140    }
40141    return code;
40142  }
40143
40144  function interpret(code, context) {
40145    for (var i = 0, l = code.length; i < l; ++i) {
40146      var line = code[i];
40147      context[line.m].apply(context, line.a);
40148    }
40149  }
40150
40151  return function(font, text, style, options, node, el) {
40152
40153    var redraw = (text === null);
40154
40155    var viewBox = font.viewBox;
40156
40157    var size = style.getSize('fontSize', font.baseSize);
40158
40159    var letterSpacing = style.get('letterSpacing');
40160    letterSpacing = (letterSpacing == 'normal') ? 0 : size.convertFrom(parseInt(letterSpacing, 10));
40161
40162    var expandTop = 0, expandRight = 0, expandBottom = 0, expandLeft = 0;
40163    var shadows = options.textShadow, shadowOffsets = [];
40164
40165    Cufon.textOptions.shadowOffsets = [ ];
40166    Cufon.textOptions.shadows = null;
40167
40168    if (shadows) {
40169      Cufon.textOptions.shadows = shadows;
40170      for (var i = 0, l = shadows.length; i < l; ++i) {
40171        var shadow = shadows[i];
40172        var x = size.convertFrom(parseFloat(shadow.offX));
40173        var y = size.convertFrom(parseFloat(shadow.offY));
40174        shadowOffsets[i] = [ x, y ];
40175        //if (y < expandTop) expandTop = y;
40176        //if (x > expandRight) expandRight = x;
40177        //if (y > expandBottom) expandBottom = y;
40178        //if (x < expandLeft) expandLeft = x;
40179      }
40180    }
40181
40182    var chars = Cufon.CSS.textTransform(redraw ? node.alt : text, style).split('');
40183
40184    var width = 0, lastWidth = null;
40185
40186    var maxWidth = 0, lines = 1, lineWidths = [ ];
40187    for (var i = 0, l = chars.length; i < l; ++i) {
40188      if (chars[i] === '\n') {
40189        lines++;
40190        if (width > maxWidth) {
40191          maxWidth = width;
40192        }
40193        lineWidths.push(width);
40194        width = 0;
40195        continue;
40196      }
40197      var glyph = font.glyphs[chars[i]] || font.missingGlyph;
40198      if (!glyph) continue;
40199      width += lastWidth = Number(glyph.w || font.w) + letterSpacing;
40200    }
40201    lineWidths.push(width);
40202
40203    width = Math.max(maxWidth, width);
40204
40205    var lineOffsets = [ ];
40206    for (var i = lineWidths.length; i--; ) {
40207      lineOffsets[i] = width - lineWidths[i];
40208    }
40209
40210    if (lastWidth === null) return null; // there's nothing to render
40211
40212    expandRight += (viewBox.width - lastWidth);
40213    expandLeft += viewBox.minX;
40214
40215    var wrapper, canvas;
40216
40217    if (redraw) {
40218      wrapper = node;
40219      canvas = node.firstChild;
40220    }
40221    else {
40222      wrapper = fabric.document.createElement('span');
40223      wrapper.className = 'cufon cufon-canvas';
40224      wrapper.alt = text;
40225
40226      canvas = fabric.document.createElement('canvas');
40227      wrapper.appendChild(canvas);
40228
40229      if (options.printable) {
40230        var print = fabric.document.createElement('span');
40231        print.className = 'cufon-alt';
40232        print.appendChild(fabric.document.createTextNode(text));
40233        wrapper.appendChild(print);
40234      }
40235    }
40236
40237    var wStyle = wrapper.style;
40238    var cStyle = canvas.style || { };
40239
40240    var height = size.convert(viewBox.height - expandTop + expandBottom);
40241    var roundedHeight = Math.ceil(height);
40242    var roundingFactor = roundedHeight / height;
40243
40244    canvas.width = Math.ceil(size.convert(width + expandRight - expandLeft) * roundingFactor);
40245    canvas.height = roundedHeight;
40246
40247    expandTop += viewBox.minY;
40248
40249    cStyle.top = Math.round(size.convert(expandTop - font.ascent)) + 'px';
40250    cStyle.left = Math.round(size.convert(expandLeft)) + 'px';
40251
40252    var _width = Math.ceil(size.convert(width * roundingFactor));
40253    var wrapperWidth = _width + 'px';
40254    var _height = size.convert(font.height);
40255    var totalLineHeight = (options.lineHeight - 1) * size.convert(-font.ascent / 5) * (lines - 1);
40256
40257    Cufon.textOptions.width = _width;
40258    Cufon.textOptions.height = (_height * lines) + totalLineHeight;
40259    Cufon.textOptions.lines = lines;
40260    Cufon.textOptions.totalLineHeight = totalLineHeight;
40261
40262    if (HAS_INLINE_BLOCK) {
40263      wStyle.width = wrapperWidth;
40264      wStyle.height = _height + 'px';
40265    }
40266    else {
40267      wStyle.paddingLeft = wrapperWidth;
40268      wStyle.paddingBottom = (_height - 1) + 'px';
40269    }
40270
40271    var g = Cufon.textOptions.context || canvas.getContext('2d'),
40272        scale = roundedHeight / viewBox.height;
40273
40274    Cufon.textOptions.fontAscent = font.ascent * scale;
40275    Cufon.textOptions.boundaries = null;
40276
40277    for (var offsets = Cufon.textOptions.shadowOffsets, i = shadowOffsets.length; i--; ) {
40278      offsets[i] = [ shadowOffsets[i][0] * scale, shadowOffsets[i][1] * scale ];
40279    }
40280
40281    g.save();
40282    g.scale(scale, scale);
40283
40284    g.translate(
40285      // we're at the center of an object and need to jump to the top left corner
40286      // where first character is to be drawn
40287      -expandLeft - ((1/scale * canvas.width) / 2) + (Cufon.fonts[font.family].offsetLeft || 0),
40288      -expandTop - ((Cufon.textOptions.height / scale) / 2) + (Cufon.fonts[font.family].offsetTop || 0)
40289    );
40290
40291    g.lineWidth = font.face['underline-thickness'];
40292
40293    g.save();
40294
40295    function line(y, color) {
40296      g.strokeStyle = color;
40297
40298      g.beginPath();
40299
40300      g.moveTo(0, y);
40301      g.lineTo(width, y);
40302
40303      g.stroke();
40304    }
40305
40306    var textDecoration = Cufon.getTextDecoration(options),
40307        isItalic = options.fontStyle === 'italic';
40308
40309    function renderBackground() {
40310      g.save();
40311
40312      var left = 0, lineNum = 0, boundaries = [{ left: 0 }];
40313
40314      if (options.backgroundColor) {
40315        g.save();
40316        g.fillStyle = options.backgroundColor;
40317        g.translate(0, font.ascent);
40318        g.fillRect(0, 0, width + 10, (-font.ascent + font.descent) * lines);
40319        g.restore();
40320      }
40321
40322      if (options.textAlign === 'right') {
40323        g.translate(lineOffsets[lineNum], 0);
40324        boundaries[0].left = lineOffsets[lineNum] * scale;
40325      }
40326      else if (options.textAlign === 'center') {
40327        g.translate(lineOffsets[lineNum] / 2, 0);
40328        boundaries[0].left = lineOffsets[lineNum] / 2 * scale;
40329      }
40330
40331      for (var i = 0, l = chars.length; i < l; ++i) {
40332        if (chars[i] === '\n') {
40333
40334          lineNum++;
40335
40336          var topOffset = -font.ascent - ((font.ascent / 5) * options.lineHeight);
40337          var boundary = boundaries[boundaries.length - 1];
40338          var nextBoundary = { left: 0 };
40339
40340          boundary.width = left * scale;
40341          boundary.height = (-font.ascent + font.descent) * scale;
40342
40343          if (options.textAlign === 'right') {
40344            g.translate(-width, topOffset);
40345            g.translate(lineOffsets[lineNum], 0);
40346            nextBoundary.left = lineOffsets[lineNum] * scale;
40347          }
40348          else if (options.textAlign === 'center') {
40349            // offset to the start of text in previous line AND half of its offset
40350            // (essentially moving caret to the left edge of bounding box)
40351            g.translate(-left - (lineOffsets[lineNum - 1] / 2), topOffset);
40352            g.translate(lineOffsets[lineNum] / 2, 0);
40353            nextBoundary.left = lineOffsets[lineNum] / 2 * scale;
40354          }
40355          else {
40356            g.translate(-left, topOffset);
40357          }
40358
40359          /* push next boundary (for the next line) */
40360          boundaries.push(nextBoundary);
40361
40362          left = 0;
40363
40364          continue;
40365        }
40366        var glyph = font.glyphs[chars[i]] || font.missingGlyph;
40367        if (!glyph) continue;
40368
40369        var charWidth = Number(glyph.w || font.w) + letterSpacing;
40370
40371        // only draw text-background when there's some kind of value
40372        if (options.textBackgroundColor) {
40373          g.save();
40374          g.fillStyle = options.textBackgroundColor;
40375          g.translate(0, font.ascent);
40376          g.fillRect(0, 0, charWidth + 10, -font.ascent + font.descent);
40377          g.restore();
40378        }
40379
40380        g.translate(charWidth, 0);
40381        left += charWidth;
40382
40383        if (i == l-1) {
40384          boundaries[boundaries.length - 1].width = left * scale;
40385          boundaries[boundaries.length - 1].height = (-font.ascent + font.descent) * scale;
40386        }
40387      }
40388      g.restore();
40389
40390      Cufon.textOptions.boundaries = boundaries;
40391    }
40392
40393    function renderText(color) {
40394      g.fillStyle = color || Cufon.textOptions.color || style.get('color');
40395
40396      var left = 0, lineNum = 0;
40397
40398      if (options.textAlign === 'right') {
40399        g.translate(lineOffsets[lineNum], 0);
40400      }
40401      else if (options.textAlign === 'center') {
40402        g.translate(lineOffsets[lineNum] / 2, 0);
40403      }
40404
40405      for (var i = 0, l = chars.length; i < l; ++i) {
40406        if (chars[i] === '\n') {
40407
40408          lineNum++;
40409
40410          var topOffset = -font.ascent - ((font.ascent / 5) * options.lineHeight);
40411
40412          if (options.textAlign === 'right') {
40413            g.translate(-width, topOffset);
40414            g.translate(lineOffsets[lineNum], 0);
40415          }
40416          else if (options.textAlign === 'center') {
40417            // offset to the start of text in previous line AND half of its offset
40418            // (essentially moving caret to the left edge of bounding box)
40419            g.translate(-left - (lineOffsets[lineNum - 1] / 2), topOffset);
40420            g.translate(lineOffsets[lineNum] / 2, 0);
40421          }
40422          else {
40423            g.translate(-left, topOffset);
40424          }
40425
40426          left = 0;
40427
40428          continue;
40429        }
40430        var glyph = font.glyphs[chars[i]] || font.missingGlyph;
40431        if (!glyph) continue;
40432
40433        var charWidth = Number(glyph.w || font.w) + letterSpacing;
40434
40435        if (textDecoration) {
40436          g.save();
40437          g.strokeStyle = g.fillStyle;
40438
40439          // add 2x more thickness — closer to SVG rendering
40440          g.lineWidth += g.lineWidth;
40441
40442          g.beginPath();
40443          if (textDecoration.underline) {
40444            g.moveTo(0, -font.face['underline-position'] + 0.5);
40445            g.lineTo(charWidth, -font.face['underline-position'] + 0.5);
40446          }
40447          if (textDecoration.overline) {
40448            g.moveTo(0, font.ascent + 0.5);
40449            g.lineTo(charWidth, font.ascent + 0.5);
40450          }
40451          if (textDecoration['line-through']) {
40452            g.moveTo(0, -font.descent + 0.5);
40453            g.lineTo(charWidth, -font.descent + 0.5);
40454          }
40455          g.stroke();
40456          g.restore();
40457        }
40458
40459        if (isItalic) {
40460          g.save();
40461          g.transform(1, 0, -0.25, 1, 0, 0);
40462        }
40463
40464        g.beginPath();
40465        if (glyph.d) {
40466          if (glyph.code) interpret(glyph.code, g);
40467          else glyph.code = generateFromVML('m' + glyph.d, g);
40468        }
40469
40470        g.fill();
40471
40472        if (options.strokeStyle) {
40473          g.closePath();
40474          g.save();
40475          g.lineWidth = options.strokeWidth;
40476          g.strokeStyle = options.strokeStyle;
40477          g.stroke();
40478          g.restore();
40479        }
40480
40481        if (isItalic) {
40482          g.restore();
40483        }
40484
40485        g.translate(charWidth, 0);
40486        left += charWidth;
40487      }
40488    }
40489
40490    g.save();
40491    renderBackground();
40492    if (shadows) {
40493      for (var i = 0, l = shadows.length; i < l; ++i) {
40494        var shadow = shadows[i];
40495        g.save();
40496        g.translate.apply(g, shadowOffsets[i]);
40497        renderText(shadow.color);
40498        g.restore();
40499      }
40500    }
40501    renderText();
40502    g.restore();
40503    g.restore();
40504    g.restore();
40505
40506    return wrapper;
40507
40508  };
40509
40510})());
40511
40512Cufon.registerEngine('vml', (function() {
40513
40514  if (!fabric.document.namespaces) return;
40515
40516  var canvasEl = fabric.document.createElement('canvas');
40517  if (canvasEl && canvasEl.getContext && canvasEl.getContext.apply) return;
40518
40519  if (fabric.document.namespaces.cvml == null) {
40520    fabric.document.namespaces.add('cvml', 'urn:schemas-microsoft-com:vml');
40521  }
40522
40523  var check = fabric.document.createElement('cvml:shape');
40524  check.style.behavior = 'url(#default#VML)';
40525  if (!check.coordsize) return; // VML isn't supported
40526  check = null;
40527
40528  fabric.document.write('<style type="text/css">' +
40529    '.cufon-vml-canvas{text-indent:0}' +
40530    '@media screen{' +
40531      'cvml\\:shape,cvml\\:shadow{behavior:url(#default#VML);display:block;antialias:true;position:absolute}' +
40532      '.cufon-vml-canvas{position:absolute;text-align:left}' +
40533      '.cufon-vml{display:inline-block;position:relative;vertical-align:middle}' +
40534      '.cufon-vml .cufon-alt{position:absolute;left:-10000in;font-size:1px}' +
40535      'a .cufon-vml{cursor:pointer}' +
40536    '}' +
40537    '@media print{' +
40538      '.cufon-vml *{display:none}' +
40539      '.cufon-vml .cufon-alt{display:inline}' +
40540    '}' +
40541  '</style>');
40542
40543  function getFontSizeInPixels(el, value) {
40544    return getSizeInPixels(el, /(?:em|ex|%)$/i.test(value) ? '1em' : value);
40545  }
40546
40547  // Original by Dead Edwards.
40548  // Combined with getFontSizeInPixels it also works with relative units.
40549  function getSizeInPixels(el, value) {
40550    if (/px$/i.test(value)) return parseFloat(value);
40551    var style = el.style.left, runtimeStyle = el.runtimeStyle.left;
40552    el.runtimeStyle.left = el.currentStyle.left;
40553    el.style.left = value;
40554    var result = el.style.pixelLeft;
40555    el.style.left = style;
40556    el.runtimeStyle.left = runtimeStyle;
40557    return result;
40558  }
40559
40560  return function(font, text, style, options, node, el, hasNext) {
40561    var redraw = (text === null);
40562
40563    if (redraw) text = node.alt;
40564
40565    // @todo word-spacing, text-decoration
40566
40567    var viewBox = font.viewBox;
40568
40569    var size = style.computedFontSize ||
40570      (style.computedFontSize = new Cufon.CSS.Size(getFontSizeInPixels(el, style.get('fontSize')) + 'px', font.baseSize));
40571
40572    var letterSpacing = style.computedLSpacing;
40573
40574    if (letterSpacing == undefined) {
40575      letterSpacing = style.get('letterSpacing');
40576      style.computedLSpacing = letterSpacing =
40577        (letterSpacing == 'normal') ? 0 : ~~size.convertFrom(getSizeInPixels(el, letterSpacing));
40578    }
40579
40580    var wrapper, canvas;
40581
40582    if (redraw) {
40583      wrapper = node;
40584      canvas = node.firstChild;
40585    }
40586    else {
40587      wrapper = fabric.document.createElement('span');
40588      wrapper.className = 'cufon cufon-vml';
40589      wrapper.alt = text;
40590
40591      canvas = fabric.document.createElement('span');
40592      canvas.className = 'cufon-vml-canvas';
40593      wrapper.appendChild(canvas);
40594
40595      if (options.printable) {
40596        var print = fabric.document.createElement('span');
40597        print.className = 'cufon-alt';
40598        print.appendChild(fabric.document.createTextNode(text));
40599        wrapper.appendChild(print);
40600      }
40601
40602      // ie6, for some reason, has trouble rendering the last VML element in the document.
40603      // we can work around this by injecting a dummy element where needed.
40604      // @todo find a better solution
40605      if (!hasNext) wrapper.appendChild(fabric.document.createElement('cvml:shape'));
40606    }
40607
40608    var wStyle = wrapper.style;
40609    var cStyle = canvas.style;
40610
40611    var height = size.convert(viewBox.height), roundedHeight = Math.ceil(height);
40612    var roundingFactor = roundedHeight / height;
40613    var minX = viewBox.minX, minY = viewBox.minY;
40614
40615    cStyle.height = roundedHeight;
40616    cStyle.top = Math.round(size.convert(minY - font.ascent));
40617    cStyle.left = Math.round(size.convert(minX));
40618
40619    wStyle.height = size.convert(font.height) + 'px';
40620
40621    var textDecoration = Cufon.getTextDecoration(options);
40622
40623    var color = style.get('color');
40624
40625    var chars = Cufon.CSS.textTransform(text, style).split('');
40626
40627    var width = 0, offsetX = 0, advance = null;
40628
40629    var glyph, shape, shadows = options.textShadow;
40630
40631    // pre-calculate width
40632    for (var i = 0, k = 0, l = chars.length; i < l; ++i) {
40633      glyph = font.glyphs[chars[i]] || font.missingGlyph;
40634      if (glyph) width += advance = ~~(glyph.w || font.w) + letterSpacing;
40635    }
40636
40637    if (advance === null) return null;
40638
40639    var fullWidth = -minX + width + (viewBox.width - advance);
40640
40641    var shapeWidth = size.convert(fullWidth * roundingFactor), roundedShapeWidth = Math.round(shapeWidth);
40642
40643    var coordSize = fullWidth + ',' + viewBox.height, coordOrigin;
40644    var stretch = 'r' + coordSize + 'nsnf';
40645
40646    for (i = 0; i < l; ++i) {
40647
40648      glyph = font.glyphs[chars[i]] || font.missingGlyph;
40649      if (!glyph) continue;
40650
40651      if (redraw) {
40652        // some glyphs may be missing so we can't use i
40653        shape = canvas.childNodes[k];
40654        if (shape.firstChild) shape.removeChild(shape.firstChild); // shadow
40655      }
40656      else {
40657        shape = fabric.document.createElement('cvml:shape');
40658        canvas.appendChild(shape);
40659      }
40660
40661      shape.stroked = 'f';
40662      shape.coordsize = coordSize;
40663      shape.coordorigin = coordOrigin = (minX - offsetX) + ',' + minY;
40664      shape.path = (glyph.d ? 'm' + glyph.d + 'xe' : '') + 'm' + co
40664ordOrigin + stretch;
40665      shape.fillcolor = color;
40666
40667      // it's important to not set top/left or IE8 will grind to a halt
40668      var sStyle = shape.style;
40669      sStyle.width = roundedShapeWidth;
40670      sStyle.height = roundedHeight;
40671
40672      if (shadows) {
40673        // due to the limitations of the VML shadow element there
40674        // can only be two visible shadows. opacity is shared
40675        // for all shadows.
40676        var shadow1 = shadows[0], shadow2 = shadows[1];
40677        var color1 = Cufon.CSS.color(shadow1.color), color2;
40678        var shadow = fabric.document.createElement('cvml:shadow');
40679        shadow.on = 't';
40680        shadow.color = color1.color;
40681        shadow.offset = shadow1.offX + ',' + shadow1.offY;
40682        if (shadow2) {
40683          color2 = Cufon.CSS.color(shadow2.color);
40684          shadow.type = 'double';
40685          shadow.color2 = color2.color;
40686          shadow.offset2 = shadow2.offX + ',' + shadow2.offY;
40687        }
40688        shadow.opacity = color1.opacity || (color2 && color2.opacity) || 1;
40689        shape.appendChild(shadow);
40690      }
40691
40692      offsetX += ~~(glyph.w || font.w) + letterSpacing;
40693
40694      ++k;
40695
40696    }
40697
40698    wStyle.width = Math.max(Math.ceil(size.convert(width * roundingFactor)), 0);
40699
40700    return wrapper;
40701
40702  };
40703
40704})());
40705
40706Cufon.getTextDecoration = function(options) {
40707  return {
40708    underline: options.textDecoration === 'underline',
40709    overline: options.textDecoration === 'overline',
40710    'line-through': options.textDecoration === 'line-through'
40711  };
40712};
40713
40714if (typeof exports != 'undefined') {
40715  exports.Cufon = Cufon;
40716}
40717
40718
40719/*
40720    json2.js
40721    2011-10-19
40722
40723    Public Domain.
40724
40725    NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
40726
40727    See http://www.JSON.org/js.html
40728
40729
40730    This code should be minified before deployment.
40731    See http://javascript.crockford.com/jsmin.html
40732
40733    USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
40734    NOT CONTROL.
40735
40736
40737    This file creates a global JSON object containing two methods: stringify
40738    and parse.
40739
40740        JSON.stringify(value, replacer, space)
40741            value       any JavaScript value, usually an object or array.
40742
40743            replacer    an optional parameter that determines how object
40744                        values are stringified for objects. It can be a
40745                        function or an array of strings.
40746
40747            space       an optional parameter that specifies the indentation
40748                        of nested structures. If it is omitted, the text will
40749                        be packed without extra whitespace. If it is a number,
40750                        it will specify the number of spaces to indent at each
40751                        level. If it is a string (such as '\t' or '&nbsp;'),
40752                        it contains the characters used to indent at each level.
40753
40754            This method produces a JSON text from a JavaScript value.
40755
40756            When an object value is found, if the object contains a toJSON
40757            method, its toJSON method will be called and the result will be
40758            stringified. A toJSON method does not serialize: it returns the
40759            value represented by the name/value pair that should be serialized,
40760            or undefined if nothing should be serialized. The toJSON method
40761            will be passed the key associated with the value, and this will be
40762            bound to the value
40763
40764            For example, this would serialize Dates as ISO strings.
40765
40766                Date.prototype.toJSON = function (key) {
40767                    function f(n) {
40768                        // Format integers to have at least two digits.
40769                        return n < 10 ? '0' + n : n;
40770                    }
40771
40772                    return this.getUTCFullYear()   + '-' +
40773                         f(this.getUTCMonth() + 1) + '-' +
40774                         f(this.getUTCDate())      + 'T' +
40775                         f(this.getUTCHours())     + ':' +
40776                         f(this.getUTCMinutes())   + ':' +
40777                         f(this.getUTCSeconds())   + 'Z';
40778                };
40779
40780            You can provide an optional replacer method. It will be passed the
40781            key and value of each member, with this bound to the containing
40782            object. The value that is returned from your method will be
40783            serialized. If your method returns undefined, then the member will
40784            be excluded from the serialization.
40785
40786            If the replacer parameter is an array of strings, then it will be
40787            used to select the members to be serialized. It filters the results
40788            such that only members with keys listed in the replacer array are
40789            stringified.
40790
40791            Values that do not have JSON representations, such as undefined or
40792            functions, will not be serialized. Such values in objects will be
40793            dropped; in arrays they will be replaced with null. You can use
40794            a replacer function to replace those with JSON values.
40795            JSON.stringify(undefined) returns undefined.
40796
40797            The optional space parameter produces a stringification of the
40798            value that is filled with line breaks and indentation to make it
40799            easier to read.
40800
40801            If the space parameter is a non-empty string, then that string will
40802            be used for indentation. If the space parameter is a number, then
40803            the indentation will be that many spaces.
40804
40805            Example:
40806
40807            text = JSON.stringify(['e', {pluribus: 'unum'}]);
40808            // text is '["e",{"pluribus":"unum"}]'
40809
40810
40811            text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
40812            // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
40813
40814            text = JSON.stringify([new Date()], function (key, value) {
40815                return this[key] instanceof Date ?
40816                    'Date(' + this[key] + ')' : value;
40817            });
40818            // text is '["Date(---current time---)"]'
40819
40820
40821        JSON.parse(text, reviver)
40822            This method parses a JSON text to produce an object or array.
40823            It can throw a SyntaxError exception.
40824
40825            The optional reviver parameter is a function that can filter and
40826            transform the results. It receives each of the keys and values,
40827            and its return value is used instead of the original value.
40828            If it returns what it received, then the structure is not modified.
40829            If it returns undefined then the member is deleted.
40830
40831            Example:
40832
40833            // Parse the text. Values that look like ISO date strings will
40834            // be converted to Date objects.
40835
40836            myData = JSON.parse(text, function (key, value) {
40837                var a;
40838                if (typeof value === 'string') {
40839                    a =
40840/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
40841                    if (a) {
40842                        return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
40843                            +a[5], +a[6]));
40844                    }
40845                }
40846                return value;
40847            });
40848
40849            myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
40850                var d;
40851                if (typeof value === 'string' &&
40852                        value.slice(0, 5) === 'Date(' &&
40853                        value.slice(-1) === ')') {
40854                    d = new Date(value.slice(5, -1));
40855                    if (d) {
40856                        return d;
40857                    }
40858                }
40859                return value;
40860            });
40861
40862
40863    This is a reference implementation. You are free to copy, modify, or
40864    redistribute.
40865*/
40866
40867/*jslint evil: true, regexp: true */
40868
40869/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
40870    call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
40871    getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
40872    lastIndex, length, parse, prototype, push, replace, slice, stringify,
40873    test, toJSON, toString, valueOf
40874*/
40875
40876
40877// Create a JSON object only if one does not already exist. We create the
40878// methods in a closure to avoid creating global variables.
40879
40880var JSON;
40881if (!JSON) {
40882    JSON = {};
40883}
40884
40885(function () {
40886    'use strict';
40887
40888    function f(n) {
40889        // Format integers to have at least two digits.
40890        return n < 10 ? '0' + n : n;
40891    }
40892
40893    if (typeof Date.prototype.toJSON !== 'function') {
40894
40895        /** @ignore */
40896        Date.prototype.toJSON = function (key) {
40897
40898            return isFinite(this.valueOf())
40899                ? this.getUTCFullYear()     + '-' +
40900                    f(this.getUTCMonth() + 1) + '-' +
40901                    f(this.getUTCDate())      + 'T' +
40902                    f(this.getUTCHours())     + ':' +
40903                    f(this.getUTCMinutes())   + ':' +
40904                    f(this.getUTCSeconds())   + 'Z'
40905                : null;
40906        };
40907
40908        String.prototype.toJSON      =
40909            Number.prototype.toJSON  =
40910            /** @ignore */
40911            Boolean.prototype.toJSON = function (key) {
40912                return this.valueOf();
40913            };
40914    }
40915
40916    var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
40917        escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
40918        gap,
40919        indent,
40920        meta = {    // table of character substitutions
40921            '\b': '\\b',
40922            '\t': '\\t',
40923            '\n': '\\n',
40924            '\f': '\\f',
40925            '\r': '\\r',
40926            '"' : '\\"',
40927            '\\': '\\\\'
40928        },
40929        rep;
40930
40931
40932    function quote(string) {
40933
vendor: 9,025 bytes, lines 40934-41193
40934// If the string contains no control characters, no quote characters, and no
40935// backslash characters, then we can safely slap some quotes around it.
40936// Otherwise we must also replace the offending characters with safe escape
40937// sequences.
40938
40939        escapable.lastIndex = 0;
40940        return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
40941            var c = meta[a];
40942            return typeof c === 'string'
40943                ? c
40944                : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
40945        }) + '"' : '"' + string + '"';
40946    }
40947
40948
40949    function str(key, holder) {
40950
40951// Produce a string from holder[key].
40952
40953        var i,          // The loop counter.
40954            k,          // The member key.
40955            v,          // The member value.
40956            length,
40957            mind = gap,
40958            partial,
40959            value = holder[key];
40960
40961// If the value has a toJSON method, call it to obtain a replacement value.
40962
40963        if (value && typeof value === 'object' &&
40964                typeof value.toJSON === 'function') {
40965            value = value.toJSON(key);
40966        }
40967
40968// If we were called with a replacer function, then call the replacer to
40969// obtain a replacement value.
40970
40971        if (typeof rep === 'function') {
40972            value = rep.call(holder, key, value);
40973        }
40974
40975// What happens next depends on the value's type.
40976
40977        switch (typeof value) {
40978        case 'string':
40979            return quote(value);
40980
40981        case 'number':
40982
40983// JSON numbers must be finite. Encode non-finite numbers as null.
40984
40985            return isFinite(value) ? String(value) : 'null';
40986
40987        case 'boolean':
40988        case 'null':
40989
40990// If the value is a boolean or null, convert it to a string. Note:
40991// typeof null does not produce 'null'. The case is included here in
40992// the remote chance that this gets fixed someday.
40993
40994            return String(value);
40995
40996// If the type is 'object', we might be dealing with an object or an array or
40997// null.
40998
40999        case 'object':
41000
41001// Due to a specification blunder in ECMAScript, typeof null is 'object',
41002// so watch out for that case.
41003
41004            if (!value) {
41005                return 'null';
41006            }
41007
41008// Make an array to hold the partial results of stringifying this object value.
41009
41010            gap += indent;
41011            partial = [];
41012
41013// Is the value an array?
41014
41015            if (Object.prototype.toString.apply(value) === '[object Array]') {
41016
41017// The value is an array. Stringify every element. Use null as a placeholder
41018// for non-JSON values.
41019
41020                length = value.length;
41021                for (i = 0; i < length; i += 1) {
41022                    partial[i] = str(i, value) || 'null';
41023                }
41024
41025// Join all of the elements together, separated with commas, and wrap them in
41026// brackets.
41027
41028                v = partial.length === 0
41029                    ? '[]'
41030                    : gap
41031                    ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']'
41032                    : '[' + partial.join(',') + ']';
41033                gap = mind;
41034                return v;
41035            }
41036
41037// If the replacer is an array, use it to select the members to be stringified.
41038
41039            if (rep && typeof rep === 'object') {
41040                length = rep.length;
41041                for (i = 0; i < length; i += 1) {
41042                    if (typeof rep[i] === 'string') {
41043                        k = rep[i];
41044                        v = str(k, value);
41045                        if (v) {
41046                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
41047                        }
41048                    }
41049                }
41050            } else {
41051
41052// Otherwise, iterate through all of the keys in the object.
41053
41054                for (k in value) {
41055                    if (Object.prototype.hasOwnProperty.call(value, k)) {
41056                        v = str(k, value);
41057                        if (v) {
41058                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
41059                        }
41060                    }
41061                }
41062            }
41063
41064// Join all of the member texts together, separated with commas,
41065// and wrap them in braces.
41066
41067            v = partial.length === 0
41068                ? '{}'
41069                : gap
41070                ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}'
41071                : '{' + partial.join(',') + '}';
41072            gap = mind;
41073            return v;
41074        }
41075    }
41076
41077// If the JSON object does not yet have a stringify method, give it one.
41078
41079    if (typeof JSON.stringify !== 'function') {
41080        /** @ignore */
41081        JSON.stringify = function (value, replacer, space) {
41082
41083// The stringify method takes a value and an optional replacer, and an optional
41084// space parameter, and returns a JSON text. The replacer can be a function
41085// that can replace values, or an array of strings that will select the keys.
41086// A default replacer method can be provided. Use of the space parameter can
41087// produce text that is more easily readable.
41088
41089            var i;
41090            gap = '';
41091            indent = '';
41092
41093// If the space parameter is a number, make an indent string containing that
41094// many spaces.
41095
41096            if (typeof space === 'number') {
41097                for (i = 0; i < space; i += 1) {
41098                    indent += ' ';
41099                }
41100
41101// If the space parameter is a string, it will be used as the indent string.
41102
41103            } else if (typeof space === 'string') {
41104                indent = space;
41105            }
41106
41107// If there is a replacer, it must be a function or an array.
41108// Otherwise, throw an error.
41109
41110            rep = replacer;
41111            if (replacer && typeof replacer !== 'function' &&
41112                    (typeof replacer !== 'object' ||
41113                    typeof replacer.length !== 'number')) {
41114                throw new Error('JSON.stringify');
41115            }
41116
41117// Make a fake root object containing our value under the key of ''.
41118// Return the result of stringifying the value.
41119
41120            return str('', {'': value});
41121        };
41122    }
41123
41124
41125// If the JSON object does not yet have a parse method, give it one.
41126
41127    if (typeof JSON.parse !== 'function') {
41128        /** @ignore */
41129        JSON.parse = function (text, reviver) {
41130
41131// The parse method takes a text and an optional reviver function, and returns
41132// a JavaScript value if the text is a valid JSON text.
41133
41134            var j;
41135
41136            function walk(holder, key) {
41137
41138// The walk method is used to recursively walk the resulting structure so
41139// that modifications can be made.
41140
41141                var k, v, value = holder[key];
41142                if (value && typeof value === 'object') {
41143                    for (k in value) {
41144                        if (Object.prototype.hasOwnProperty.call(value, k)) {
41145                            v = walk(value, k);
41146                            if (v !== undefined) {
41147                                value[k] = v;
41148                            } else {
41149                                delete value[k];
41150                            }
41151                        }
41152                    }
41153                }
41154                return reviver.call(holder, key, value);
41155            }
41156
41157
41158// Parsing happens in four stages. In the first stage, we replace certain
41159// Unicode characters with escape sequences. JavaScript handles many characters
41160// incorrectly, either silently deleting them, or treating them as line endings.
41161
41162            text = String(text);
41163            cx.lastIndex = 0;
41164            if (cx.test(text)) {
41165                text = text.replace(cx, function (a) {
41166                    return '\\u' +
41167                        ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
41168                });
41169            }
41170
41171// In the second stage, we run the text against regular expressions that look
41172// for non-JSON patterns. We are especially concerned with '()' and 'new'
41173// because they can cause invocation, and '=' because it can cause mutation.
41174// But just to be safe, we want to reject all unexpected forms.
41175
41176// We split the second stage into 4 regexp operations in order to work around
41177// crippling inefficiencies in IE's and Safari's regexp engines. First we
41178// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
41179// replace all simple value tokens with ']' characters. Third, we delete all
41180// open brackets that follow a colon or comma or that begin the text. Finally,
41181// we look to see that the remaining characters are only whitespace or ']' or
41182// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
41183
41184            if (/^[\],:{}\s]*$/
41185                    .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
41186                        .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
41187                        .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
41188
41189// In the third stage we use the eval function to compile the text into a
41190// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
41191// in JavaScript: it can begin a block or an object literal. We wrap the text
41192// in parens to eliminate the ambiguity.
41193
41194                j = eval('(' + text + ')');
41195
41196// In the optional fourth stage, we recursively walk the new structure, passing
41197// each name/value pair to a reviver function for possible transformation.
41198
41199                return typeof reviver === 'function'
41200                    ? walk({'': j}, '')
41201                    : j;
41202            }
41203
41204// If the text is not JSON parseable, then a SyntaxError is thrown.
41205
41206            throw new SyntaxError('JSON.parse');
41207        };
41208    }
41209}());
41210
41211/**
41212 * Wrapper around `console.log` (when available)
41213 * @param {Any} values Values to log
41214 */
41215fabric.log = function() { };
41216
41217/**
41218 * Wrapper around `console.warn` (when available)
41219 * @param {Any} Values to log as a warning
41220 */
41221fabric.warn = function() { };
41222
41223if (typeof console !== 'undefined') {
41224  if (typeof console.log !== 'undefined' && console.log.apply) {
41225    fabric.log = function() {
41226      return console.log.apply(console, arguments);
41227    };
41228  }
41229  if (typeof console.warn !== 'undefined' && console.warn.apply) {
41230    fabric.warn = function() {
41231      return console.warn.apply(console, arguments);
41232    };
41233  }
41234}
41235
41236
41237(function(){
41238
41239  /**
41240   * @private
41241   * @param {String} eventName
41242   * @param {Function} handler
41243   */
41244  function _removeEventListener(eventName, handler) {
41245    if (!this.__eventListeners[eventName]) return;
41246
41247    if (handler) {
41248      fabric.util.removeFromArray(this.__eventListeners[eventName], handler);
41249    }
41250    else {
41251      this.__eventListeners[eventName].length = 0;
41252    }
41253  }
41254
41255  /**
41256   * Observes specified event
41257   * @deprecated `observe` deprecated since 0.8.34 (use `on` instead)
41258   * @memberOf fabric.Observable
41259   * @alias on
41260   * @param {String|Object} eventName Event name (eg. 'after:render') or object with key/value pairs (eg. {'after:render': handler, 'selection:cleared': handler})
41261   * @param {Function} handler Function that receives a notification when an event of the specified type occurs
41262   * @return {Self} thisArg
41263   * @chainable
41264   */
41265  function observe(eventName, handler) {
41266    if (!this.__eventListeners) {
41267      this.__eventListeners = { };
41268    }
41269    // one object with key/value pairs was passed
41270    if (arguments.length === 1) {
41271      for (var prop in eventName) {
41272        this.on(prop, eventName[prop]);
41273      }
41274    }
41275    else {
41276      if (!this.__eventListeners[eventName]) {
41277        this.__eventListeners[eventName] = [ ];
41278      }
41279      this.__eventListeners[eventName].push(handler);
41280    }
41281    return this;
41282  }
41283
41284  /**
41285   * Stops event observing for a particular event handler
41286   * @deprecated `stopObserving` deprecated since 0.8.34 (use `off` instead)
41287   * @memberOf fabric.Observable
41288   * @alias off
41289   * @param {String|Object} eventName Event name (eg. 'after:render') or object with key/value pairs (eg. {'after:render': handler, 'selection:cleared': handler})
41290   * @param {Function} handler Function to be deleted from EventListeners
41291   * @return {Self} thisArg
41292   * @chainable
41293   */
41294  function stopObserving(eventName, handler) {
41295    if (!this.__eventListeners) return;
41296
41297    // one object with key/value pairs was passed
41298    if (arguments.length === 1 && typeof arguments[0] === 'object') {
41299      for (var prop in eventName) {
41300        _removeEventListener.call(this, prop, eventName[prop]);
41301      }
41302    }
41303    else {
41304      _removeEventListener.call(this, eventName, handler);
41305    }
41306    return this;
41307  }
41308
41309  /**
41310   * Fires event with an optional options object
41311   * @deprecated `fire` deprecated since 1.0.7 (use `trigger` instead)
41312   * @memberOf fabric.Observable
41313   * @alias trigger
41314   * @param {String} eventName Event name to fire
41315   * @param {Object} [options] Options object
41316   * @return {Self} thisArg
41317   * @chainable
41318   */
41319  function fire(eventName, options) {
41320    if (!this.__eventListeners) return;
41321
41322    var listenersForEvent = this.__eventListeners[eventName];
41323    if (!listenersForEvent) return;
41324    for (var i = 0, len = listenersForEvent.length; i < len; i++) {
41325      // avoiding try/catch for perf. reasons
41326      listenersForEvent[i].call(this, options || { });
41327    }
41328    return this;
41329  }
41330
41331  /**
41332   * @namespace fabric.Observable
41333   * @tutorial {@link http://fabricjs.com/fabric-intro-part-2/#events}
41334   * @see {@link http://fabricjs.com/events/|Events demo}
41335   */
41336  fabric.Observable = {
41337    observe: observe,
41338    stopObserving: stopObserving,
41339    fire: fire,
41340
41341    on: observe,
41342    off: stopObserving,
41343    trigger: fire
41344  };
41345})();
41346
41347
41348/**
41349 * @namespace fabric.Collection
41350 */
41351fabric.Collection = {
41352
41353  /**
41354   * Adds objects to collection, then renders canvas (if `renderOnAddRemove` is not `false`)
41355   * Objects should be instances of (or inherit from) fabric.Object
41356   * @param [...] Zero or more fabric instances
41357   * @return {Self} thisArg
41358   */
41359  add: function () {
41360    this._objects.push.apply(this._objects, arguments);
41361    for (var i = arguments.length; i--; ) {
41362      this._onObjectAdded(arguments[i]);
41363    }
41364    this.renderOnAddRemove && this.renderAll();
41365    return this;
41366  },
41367
41368  /**
41369   * Inserts an object into collection at specified index, then renders canvas (if `renderOnAddRemove` is not `false`)
41370   * An object should be an instance of (or inherit from) fabric.Object
41371   * @param {Object} object Object to insert
41372   * @param {Number} index Index to insert object at
41373   * @param {Boolean} nonSplicing When `true`, no splicing (shifting) of objects occurs
41374   * @return {Self} thisArg
41375   */
41376  insertAt: function (object, index, nonSplicing) {
41377    var objects = this.getObjects();
41378    if (nonSplicing) {
41379      objects[index] = object;
41380    }
41381    else {
41382      objects.splice(index, 0, object);
41383    }
41384    this._onObjectAdded(object);
41385    this.renderOnAddRemove && this.renderAll();
41386    return this;
41387  },
41388
41389  /**
41390   * Removes an object from a collection, then renders canvas (if `renderOnAddRemove` is not `false`)
41391   * @param {Object} object Object to remove
41392   * @return {Self} thisArg
41393   */
41394  remove: function(object) {
41395    var objects = this.getObjects(),
41396        index = objects.indexOf(object);
41397
41398    // only call onObjectRemoved if an object was actually removed
41399    if (index !== -1) {
41400      objects.splice(index, 1);
41401      this._onObjectRemoved(object);
41402    }
41403
41404    this.renderOnAddRemove && this.renderAll();
41405    return object;
41406  },
41407
41408  /**
41409   * Executes given function for each object in this group
41410   * @param {Function} callback
41411   *                   Callback invoked with current object as first argument,
41412   *                   index - as second and an array of all objects - as third.
41413   *                   Iteration happens in reverse order (for performance reasons).
41414   *                   Callback is invoked in a context of Global Object (e.g. `window`)
41415   *                   when no `context` argument is given
41416   *
41417   * @param {Object} context Context (aka thisObject)
41418   * @return {Self} thisArg
41419   */
41420  forEachObject: function(callback, context) {
41421    var objects = this.getObjects(),
41422        i = objects.length;
41423    while (i--) {
41424      callback.call(context, objects[i], i, objects);
41425    }
41426    return this;
41427  },
41428
41429  /**
41430   * Returns object at specified index
41431   * @param {Number} index
41432   * @return {Self} thisArg
41433   */
41434  item: function (index) {
41435    return this.getObjects()[index];
41436  },
41437
41438  /**
41439   * Returns true if collection contains no objects
41440   * @return {Boolean} true if collection is empty
41441   */
41442  isEmpty: function () {
41443    return this.getObjects().length === 0;
41444  },
41445
41446  /**
41447   * Returns a size of a collection (i.e: length of an array containing its objects)
41448   * @return {Number} Collection size
41449   */
41450  size: function() {
41451    return this.getObjects().length;
41452  },
41453
41454  /**
41455   * Returns true if collection contains an object
41456   * @param {Object} object Object to check against
41457   * @return {Boolean} `true` if collection contains an object
41458   */
41459  contains: function(object) {
41460    return this.getObjects().indexOf(object) > -1;
41461  },
41462
41463  /**
41464   * Returns number representation of a collection complexity
41465   * @return {Number} complexity
41466   */
41467  complexity: function () {
41468    return this.getObjects().reduce(function (memo, current) {
41469      memo += current.complexity ? current.complexity() : 0;
41470      return memo;
41471    }, 0);
41472  }
41473};
41474
41475
41476(function(global) {
41477
41478  var sqrt = Math.sqrt,
41479      atan2 = Math.atan2;
41480
41481  /**
41482   * @namespace fabric.util
41483   */
41484  fabric.util = { };
41485
41486  /**
41487   * Removes value from an array.
41488   * Presence of value (and its position in an array) is determined via `Array.prototype.indexOf`
41489   * @static
41490   * @memberOf fabric.util
41491   * @param {Array} array
41492   * @param {Any} value
41493   * @return {Array} original array
41494   */
41495  function removeFromArray(array, value) {
41496    var idx = array.indexOf(value);
41497    if (idx !== -1) {
41498      array.splice(idx, 1);
41499    }
41500    return array;
41501  }
41502
41503  /**
41504   * Returns random number between 2 specified ones.
41505   * @static
41506   * @memberOf fabric.util
41507   * @param {Number} min lower limit
41508   * @param {Number} max upper limit
41509   * @return {Number} random value (between min and max)
41510   */
41511  function getRandomInt(min, max) {
41512    return Math.floor(Math.random() * (max - min + 1)) + min;
41513  }
41514
41515  var PiBy180 = Math.PI / 180;
41516
41517  /**
41518   * Transforms degrees to radians.
41519   * @static
41520   * @memberOf fabric.util
41521   * @param {Number} degrees value in degrees
41522   * @return {Number} value in radians
41523   */
41524  function degreesToRadians(degrees) {
41525    return degrees * PiBy180;
41526  }
41527
41528  /**
41529   * Transforms radians to degrees.
41530   * @static
41531   * @memberOf fabric.util
41532   * @param {Number} radians value in radians
41533   * @return {Number} value in degrees
41534   */
41535  function radiansToDegrees(radians) {
41536    return radians / PiBy180;
41537  }
41538
41539  /**
41540   * Rotates `point` around `origin` with `radians`
41541   * @static
41542   * @memberOf fabric.util
41543   * @param {fabric.Point} The point to rotate
41544   * @param {fabric.Point} The origin of the rotation
41545   * @param {Number} The radians of the angle for the rotation
41546   * @return {fabric.Point} The new rotated point
41547   */
41548  function rotatePoint(point, origin, radians) {
41549    var sin = Math.sin(radians),
41550        cos = Math.cos(radians);
41551
41552    point.subtractEquals(origin);
41553
41554    var rx = point.x * cos - point.y * sin;
41555    var ry = point.x * sin + point.y * cos;
41556
41557    return new fabric.Point(rx, ry).addEquals(origin);
41558  }
41559
41560  /**
41561   * A wrapper around Number#toFixed, which contrary to native method returns number, not string.
41562   * @static
41563   * @memberOf fabric.util
41564   * @param {Number | String} number number to operate on
41565   * @param {Number} fractionDigits number of fraction digits to "leave"
41566   * @return {Number}
41567   */
41568   function toFixed(number, fractionDigits) {
41569     return parseFloat(Number(number).toFixed(fractionDigits));
41570   }
41571
41572   /**
41573    * Function which always returns `false`.
41574    * @static
41575    * @memberOf fabric.util
41576    * @return {Boolean}
41577    */
41578   function falseFunction() {
41579     return false;
41580   }
41581
41582  /**
41583    * Returns klass "Class" object of given namespace
41584    * @memberOf fabric.util
41585    * @param {String} type Type of object (eg. 'circle')
41586    * @param {String} namespace Namespace to get klass "Class" object from
41587    * @return {Object} klass "Class"
41588    */
41589  function getKlass(type, namespace) {
41590    // capitalize first letter only
41591    type = fabric.util.string.camelize(type.charAt(0).toUpperCase() + type.slice(1));
41592    return resolveNamespace(namespace)[type];
41593  }
41594
41595  /**
41596    * Returns object of given namespace
41597    * @memberOf fabric.util
41598    * @param {String} namespace Namespace string e.g. 'fabric.Image.filter' or 'fabric'
41599    * @return {Object} Object for given namespace (default fabric)
41600    */
41601  function resolveNamespace(namespace) {
41602    if (!namespace) return fabric;
41603
41604    var parts = namespace.split('.'),
41605        len = parts.length,
41606        obj = global || fabric.window;
41607
41608    for (var i = 0; i < len; ++i) {
41609      obj = obj[parts[i]];
41610    }
41611
41612    return obj;
41613  }
41614
41615  /**
41616    * Loads image element from given url and passes it to a callback
41617    * @memberOf fabric.util
41618    * @param {String} url URL representing an image
41619    * @param {Function} callback Callback; invoked with loaded image
41620    * @param {Any} context optional Context to invoke callback in
41621    */
41622  function loadImage(url, callback, context) {
41623    if (url) {
41624      var img = fabric.util.createImage();
41625      /** @ignore */
41626      img.onload = function () {
41627        callback && callback.call(context, img);
41628        img = img.onload = null;
41629      };
41630      img.src = url;
41631    }
41632    else {
41633      callback && callback.call(context, url);
41634    }
41635  }
41636
41637  /**
41638   * Creates corresponding fabric instances from their object representations
41639   * @static
41640   * @memberOf fabric.util
41641   * @param {Array} objects Objects to enliven
41642   * @param {Function} callback Callback to invoke when all objects are created
41643   * @param {Function} [reviver] Method for further parsing of object elements, called after each fabric object created.
41644   */
41645  function enlivenObjects(objects, callback, namespace, reviver) {
41646
41647    function onLoaded() {
41648      if (++numLoadedObjects === numTotalObjects) {
41649        if (callback) {
41650          callback(enlivenedObjects);
41651        }
41652      }
41653    }
41654
41655    var enlivenedObjects = [ ],
41656        numLoadedObjects = 0,
41657        numTotalObjects = objects.length;
41658
41659    objects.forEach(function (o, index) {
41660      // if sparse array
41661      if (!o || !o.type) {
41662        onLoaded();
41663        return;
41664      }
41665      var klass = fabric.util.getKlass(o.type, namespace);
41666      if (klass.async) {
41667        klass.fromObject(o, function (obj, error) {
41668          if (!error) {
41669            enlivenedObjects[index] = obj;
41670            reviver && reviver(o, enlivenedObjects[index]);
41671          }
41672          onLoaded();
41673        });
41674      }
41675      else {
41676        enlivenedObjects[index] = klass.fromObject(o);
41677        reviver && reviver(o, enlivenedObjects[index]);
41678        onLoaded();
41679      }
41680    });
41681  }
41682
41683  /**
41684   * Groups SVG elements (usually those retrieved from SVG document)
41685   * @static
41686   * @memberOf fabric.util
41687   * @param {Array} elements SVG elements to group
41688   * @param {Object} [options] Options object
41689   * @return {fabric.Object|fabric.PathGroup}
41690   */
41691  function groupSVGElements(elements, options, path) {
41692    var object;
41693
41694    if (elements.length > 1) {
41695      object = new fabric.PathGroup(elements, options);
41696    }
41697    else {
41698      object = elements[0];
41699    }
41700
41701    if (typeof path !== 'undefined') {
41702      object.setSourcePath(path);
41703    }
41704    return object;
41705  }
41706
41707  /**
41708   * Populates an object with properties of another object
41709   * @static
41710   * @memberOf fabric.util
41711   * @param {Object} source Source object
41712   * @param {Object} destination Destination object
41713   * @return {Array} properties Propertie names to include
41714   */
41715  function populateWithProperties(source, destination, properties) {
41716    if (properties && Object.prototype.toString.call(properties) === '[object Array]') {
41717      for (var i = 0, len = properties.length; i < len; i++) {
41718        if (properties[i] in source) {
41719          destination[properties[i]] = source[properties[i]];
41720        }
41721      }
41722    }
41723  }
41724
41725  /**
41726   * Draws a dashed line between two points
41727   *
41728   * This method is used to draw dashed line around selection area.
41729   * See <a href="http://stackoverflow.com/questions/4576724/dotted-stroke-in-canvas">dotted stroke in canvas</a>
41730   *
41731   * @param ctx {Canvas} context
41732   * @param x {Number} start x coordinate
41733   * @param y {Number} start y coordinate
41734   * @param x2 {Number} end x coordinate
41735   * @param y2 {Number} end y coordinate
41736   * @param da {Array} dash array pattern
41737   */
41738  function drawDashedLine(ctx, x, y, x2, y2, da) {
41739    var dx = x2 - x,
41740        dy = y2 - y,
41741        len = sqrt(dx*dx + dy*dy),
41742        rot = atan2(dy, dx),
41743        dc = da.length,
41744        di = 0,
41745        draw = true;
41746
41747    ctx.save();
41748    ctx.translate(x, y);
41749    ctx.moveTo(0, 0);
41750    ctx.rotate(rot);
41751
41752    x = 0;
41753    while (len > x) {
41754      x += da[di++ % dc];
41755      if (x > len) {
41756        x = len;
41757      }
41758      ctx[draw ? 'lineTo' : 'moveTo'](x, 0);
41759      draw = !draw;
41760    }
41761
41762    ctx.restore();
41763  }
41764
41765  /**
41766   * Creates canvas element and initializes it via excanvas if necessary
41767   * @static
41768   * @memberOf fabric.util
41769   * @param {CanvasElement} [canvasEl] optional canvas element to initialize; when not given, element is created implicitly
41770   * @return {CanvasElement} initialized canvas element
41771   */
41772  function createCanvasElement(canvasEl) {
41773    canvasEl || (canvasEl = fabric.document.createElement('canvas'));
41774    if (!canvasEl.getContext && typeof G_vmlCanvasManager !== 'undefined') {
41775      G_vmlCanvasManager.initElement(canvasEl);
41776    }
41777    return canvasEl;
41778  }
41779
41780  /**
41781   * Creates image element (works on client and node)
41782   * @static
41783   * @memberOf fabric.util
41784   * @return {HTMLImageElement} HTML image element
41785   */
41786  function createImage() {
41787    return fabric.isLikelyNode
41788      ? new (require('canvas').Image)()
41789      : fabric.document.createElement('img');
41790  }
41791
41792  /**
41793   * Creates accessors (getXXX, setXXX) for a "class", based on "stateProperties" array
41794   * @static
41795   * @memberOf fabric.util
41796   * @param {Object} klass "Class" to create accessors for
41797   */
41798  function createAccessors(klass) {
41799    var proto = klass.prototype;
41800
41801    for (var i = proto.stateProperties.length; i--; ) {
41802
41803      var propName = proto.stateProperties[i],
41804          capitalizedPropName = propName.charAt(0).toUpperCase() + propName.slice(1),
41805          setterName = 'set' + capitalizedPropName,
41806          getterName = 'get' + capitalizedPropName;
41807
41808      // using `new Function` for better introspection
41809      if (!proto[getterName]) {
41810        proto[getterName] = (function(property) {
41811          return new Function('return this.get("' + property + '")');
41812        })(propName);
41813      }
41814      if (!proto[setterName]) {
41815        proto[setterName] = (function(property) {
41816          return new Function('value', 'return this.set("' + property + '", value)');
41817        })(propName);
41818      }
41819    }
41820  }
41821
41822  /**
41823   * @static
41824   * @memberOf fabric.util
41825   * @param {fabric.Object} receiver Object implementing `clipTo` method
41826   * @param {CanvasRenderingContext2D} ctx Context to clip
41827   */
41828  function clipContext(receiver, ctx) {
41829    ctx.save();
41830    ctx.beginPath();
41831    receiver.clipTo(ctx);
41832    ctx.clip();
41833  }
41834
41835  /**
41836   * Multiply matrix A by matrix B to nest transformations
41837   * @static
41838   * @memberOf fabric.util
41839   * @param  {Array} matrixA First transformMatrix
41840   * @param  {Array} matrixB Second transformMatrix
41841   * @return {Array} The product of the two transform matrices
41842   */
41843  function multiplyTransformMatrices(matrixA, matrixB) {
41844    // Matrix multiply matrixA * matrixB
41845    var a = [
41846      [matrixA[0], matrixA[2], matrixA[4]],
41847      [matrixA[1], matrixA[3], matrixA[5]],
41848      [0         , 0         , 1         ]
41849    ];
41850
41851    var b = [
41852      [matrixB[0], matrixB[2], matrixB[4]],
41853      [matrixB[1], matrixB[3], matrixB[5]],
41854      [0         , 0         , 1         ]
41855    ];
41856
41857    var result = [];
41858    for (var r=0; r<3; r++) {
41859      result[r] = [];
41860      for (var c=0; c<3; c++) {
41861        var sum = 0;
41862        for (var k=0; k<3; k++) {
41863          sum += a[r][k]*b[k][c];
41864        }
41865
41866        result[r][c] = sum;
41867      }
41868    }
41869
41870    return [
41871      result[0][0],
41872      result[1][0],
41873      result[0][1],
41874      result[1][1],
41875      result[0][2],
41876      result[1][2]
41877    ];
41878  }
41879
41880  function getFunctionBody(fn) {
41881    return (String(fn).match(/function[^{]*\{([\s\S]*)\}/) || {})[1];
41882  }
41883
41884  function drawArc(ctx, x, y, coords) {
41885    var rx = coords[0];
41886    var ry = coords[1];
41887    var rot = coords[2];
41888    var large = coords[3];
41889    var sweep = coords[4];
41890    var ex = coords[5];
41891    var ey = coords[6];
41892    var segs = arcToSegments(ex, ey, rx, ry, large, sweep, rot, x, y);
41893    for (var i=0; i<segs.length; i++) {
41894     var bez = segmentToBezier.apply(this, segs[i]);
41895     ctx.bezierCurveTo.apply(ctx, bez);
41896    }
41897  }
41898
41899  var arcToSegmentsCache = { },
41900      segmentToBezierCache = { },
41901      _join = Array.prototype.join,
41902      argsString;
41903
41904  // Generous contribution by Raph Levien, from libsvg-0.1.0.tar.gz
41905  function arcToSegments(x, y, rx, ry, large, sweep, rotateX, ox, oy) {
41906    argsString = _join.call(arguments);
41907    if (arcToSegmentsCache[argsString]) {
41908      return arcToSegmentsCache[argsString];
41909    }
41910
41911    var th = rotateX * (Math.PI/180);
41912    var sin_th = Math.sin(th);
41913    var cos_th = Math.cos(th);
41914    rx = Math.abs(rx);
41915    ry = Math.abs(ry);
41916    var px = cos_th * (ox - x) * 0.5 + sin_th * (oy - y) * 0.5;
41917    var py = cos_th * (oy - y) * 0.5 - sin_th * (ox - x) * 0.5;
41918    var pl = (px*px) / (rx*rx) + (py*py) / (ry*ry);
41919    if (pl > 1) {
41920      pl = Math.sqrt(pl);
41921      rx *= pl;
41922      ry *= pl;
41923    }
41924
41925    var a00 = cos_th / rx;
41926    var a01 = sin_th / rx;
41927    var a10 = (-sin_th) / ry;
41928    var a11 = (cos_th) / ry;
41929    var x0 = a00 * ox + a01 * oy;
41930    var y0 = a10 * ox + a11 * oy;
41931    var x1 = a00 * x + a01 * y;
41932    var y1 = a10 * x + a11 * y;
41933
41934    var d = (x1-x0) * (x1-x0) + (y1-y0) * (y1-y0);
41935    var sfactor_sq = 1 / d - 0.25;
41936    if (sfactor_sq < 0) sfactor_sq = 0;
41937    var sfactor = Math.sqrt(sfactor_sq);
41938    if (sweep === large) sfactor = -sfactor;
41939    var xc = 0.5 * (x0 + x1) - sfactor * (y1-y0);
41940    var yc = 0.5 * (y0 + y1) + sfactor * (x1-x0);
41941
41942    var th0 = Math.atan2(y0-yc, x0-xc);
41943    var th1 = Math.atan2(y1-yc, x1-xc);
41944
41945    var th_arc = th1-th0;
41946    if (th_arc < 0 && sweep === 1){
41947      th_arc += 2*Math.PI;
41948    } else if (th_arc > 0 && sweep === 0) {
41949      th_arc -= 2 * Math.PI;
41950    }
41951
41952    var segments = Math.ceil(Math.abs(th_arc / (Math.PI * 0.5 + 0.001)));
41953    var result = [];
41954    for (var i=0; i<segments; i++) {
41955      var th2 = th0 + i * th_arc / segments;
41956      var th3 = th0 + (i+1) * th_arc / segments;
41957      result[i] = [xc, yc, th2, th3, rx, ry, sin_th, cos_th];
41958    }
41959
41960    arcToSegmentsCache[argsString] = result;
41961    return result;
41962  }
41963
41964  function segmentToBezier(cx, cy, th0, th1, rx, ry, sin_th, cos_th) {
41965    argsString = _join.call(arguments);
41966    if (segmentToBezierCache[argsString]) {
41967      return segmentToBezierCache[argsString];
41968    }
41969
41970    var a00 = cos_th * rx;
41971    var a01 = -sin_th * ry;
41972    var a10 = sin_th * rx;
41973    var a11 = cos_th * ry;
41974
41975    var th_half = 0.5 * (th1 - th0);
41976    var t = (8/3) * Math.sin(th_half * 0.5) * Math.sin(th_half * 0.5) / Math.sin(th_half);
41977    var x1 = cx + Math.cos(th0) - t * Math.sin(th0);
41978    var y1 = cy + Math.sin(th0) + t * Math.cos(th0);
41979    var x3 = cx + Math.cos(th1);
41980    var y3 = cy + Math.sin(th1);
41981    var x2 = x3 + t * Math.sin(th1);
41982    var y2 = y3 - t * Math.cos(th1);
41983
41984    segmentToBezierCache[argsString] = [
41985      a00 * x1 + a01 * y1,      a10 * x1 + a11 * y1,
41986      a00 * x2 + a01 * y2,      a10 * x2 + a11 * y2,
41987      a00 * x3 + a01 * y3,      a10 * x3 + a11 * y3
41988    ];
41989
41990    return segmentToBezierCache[argsString];
41991  }
41992
41993  fabric.util.removeFromArray = removeFromArray;
41994  fabric.util.degreesToRadians = degreesToRadians;
41995  fabric.util.radiansToDegrees = radiansToDegrees;
41996  fabric.util.rotatePoint = rotatePoint;
41997  fabric.util.toFixed = toFixed;
41998  fabric.util.getRandomInt = getRandomInt;
41999  fabric.util.falseFunction = falseFunction;
42000  fabric.util.getKlass = getKlass;
42001  fabric.util.resolveNamespace = resolveNamespace;
42002  fabric.util.loadImage = loadImage;
42003  fabric.util.enlivenObjects = enlivenObjects;
42004  fabric.util.groupSVGElements = groupSVGElements;
42005  fabric.util.populateWithProperties = populateWithProperties;
42006  fabric.util.drawDashedLine = drawDashedLine;
42007  fabric.util.createCanvasElement = createCanvasElement;
42008  fabric.util.createImage = createImage;
42009  fabric.util.createAccessors = createAccessors;
42010  fabric.util.clipContext = clipContext;
42011  fabric.util.multiplyTransformMatrices = multiplyTransformMatrices;
42012  fabric.util.getFunctionBody = getFunctionBody;
42013  fabric.util.drawArc = drawArc;
42014
42015})(typeof exports !== 'undefined' ? exports : this);
42016
42017
42018(function() {
42019
42020  var slice = Array.prototype.slice;
42021
42022  /* _ES5_COMPAT_START_ */
42023
42024  if (!Array.prototype.indexOf) {
42025    /**
42026     * Finds index of an element in an array
42027     * @param {Any} searchElement
42028     * @param {Number} [fromIndex]
42029     * @return {Number}
42030     */
42031    Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {
42032      if (this === void 0 || this === null) {
42033        throw new TypeError();
42034      }
42035      var t = Object(this), len = t.length >>> 0;
42036      if (len === 0) {
42037        return -1;
42038      }
42039      var n = 0;
42040      if (arguments.length > 0) {
42041        n = Number(arguments[1]);
42042        if (n !== n) { // shortcut for verifying if it's NaN
42043          n = 0;
42044        }
42045        else if (n !== 0 && n !== Number.POSITIVE_INFINITY && n !== Number.NEGATIVE_INFINITY) {
42046          n = (n > 0 || -1) * Math.floor(Math.abs(n));
42047        }
42048      }
42049      if (n >= len) {
42050        return -1;
42051      }
42052      var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
42053      for (; k < len; k++) {
42054        if (k in t && t[k] === searchElement) {
42055          return k;
42056        }
42057      }
42058      return -1;
42059    };
42060  }
42061
42062  if (!Array.prototype.forEach) {
42063    /**
42064     * Iterates an array, invoking callback for each element
42065     * @param {Function} fn Callback to invoke for each element
42066     * @param {Object} [context] Context to invoke callback in
42067     * @return {Array}
42068     */
42069    Array.prototype.forEach = function(fn, context) {
42070      for (var i = 0, len = this.length >>> 0; i < len; i++) {
42071        if (i in this) {
42072          fn.call(context, this[i], i, this);
42073        }
42074      }
42075    };
42076  }
42077
42078  if (!Array.prototype.map) {
42079    /**
42080     * Returns a result of iterating over an array, invoking callback for each element
42081     * @param {Function} fn Callback to invoke for each element
42082     * @param {Object} [context] Context to invoke callback in
42083     * @return {Array}
42084     */
42085    Array.prototype.map = function(fn, context) {
42086      var result = [ ];
42087      for (var i = 0, len = this.length >>> 0; i < len; i++) {
42088        if (i in this) {
42089          result[i] = fn.call(context, this[i], i, this);
42090        }
42091      }
42092      return result;
42093    };
42094  }
42095
42096  if (!Array.prototype.every) {
42097    /**
42098     * Returns true if a callback returns truthy value for all elements in an array
42099     * @param {Function} fn Callback to invoke for each element
42100     * @param {Object} [context] Context to invoke callback in
42101     * @return {Boolean}
42102     */
42103    Array.prototype.every = function(fn, context) {
42104      for (var i = 0, len = this.length >>> 0; i < len; i++) {
42105        if (i in this && !fn.call(context, this[i], i, this)) {
42106          return false;
42107        }
42108      }
42109      return true;
42110    };
42111  }
42112
42113  if (!Array.prototype.some) {
42114    /**
42115     * Returns true if a callback returns truthy value for at least one element in an array
42116     * @param {Function} fn Callback to invoke for each element
42117     * @param {Object} [context] Context to invoke callback in
42118     * @return {Boolean}
42119     */
42120    Array.prototype.some = function(fn, context) {
42121      for (var i = 0, len = this.length >>> 0; i < len; i++) {
42122        if (i in this && fn.call(context, this[i], i, this)) {
42123          return true;
42124        }
42125      }
42126      return false;
42127    };
42128  }
42129
42130  if (!Array.prototype.filter) {
42131    /**
42132     * Returns the result of iterating over elements in an array
42133     * @param {Function} fn Callback to invoke for each element
42134     * @param {Object} [context] Context to invoke callback in
42135     * @return {Array}
42136     */
42137    Array.prototype.filter = function(fn, context) {
42138      var result = [ ], val;
42139      for (var i = 0, len = this.length >>> 0; i < len; i++) {
42140        if (i in this) {
42141          val = this[i]; // in case fn mutates this
42142          if (fn.call(context, val, i, this)) {
42143            result.push(val);
42144          }
42145        }
42146      }
42147      return result;
42148    };
42149  }
42150
42151  if (!Array.prototype.reduce) {
42152    /**
42153     * Returns "folded" (reduced) result of iterating over elements in an array
42154     * @param {Function} fn Callback to invoke for each element
42155     * @param {Object} [context] Context to invoke callback in
42156     * @return {Any}
42157     */
42158    Array.prototype.reduce = function(fn /*, initial*/) {
42159      var len = this.length >>> 0,
42160          i = 0,
42161          rv;
42162
42163      if (arguments.length > 1) {
42164        rv = arguments[1];
42165      }
42166      else {
42167        do {
42168          if (i in this) {
42169            rv = this[i++];
42170            break;
42171          }
42172          // if array contains no values, no initial value to return
42173          if (++i >= len) {
42174            throw new TypeError();
42175          }
42176        }
42177        while (true);
42178      }
42179      for (; i < len; i++) {
42180        if (i in this) {
42181          rv = fn.call(null, rv, this[i], i, this);
42182        }
42183      }
42184      return rv;
42185    };
42186  }
42187
42188  /* _ES5_COMPAT_END_ */
42189
42190  /**
42191   * Invokes method on all items in a given array
42192   * @memberOf fabric.util.array
42193   * @param {Array} array Array to iterate over
42194   * @param {String} method Name of a method to invoke
42195   * @return {Array}
42196   */
42197  function invoke(array, method) {
42198    var args = slice.call(arguments, 2), result = [ ];
42199    for (var i = 0, len = array.length; i < len; i++) {
42200      result[i] = args.length ? array[i][method].apply(array[i], args) : array[i][method].call(array[i]);
42201    }
42202    return result;
42203  }
42204
42205  /**
42206   * Finds maximum value in array (not necessarily "first" one)
42207   * @memberOf fabric.util.array
42208   * @param {Array} array Array to iterate over
42209   * @param {String} byProperty
42210   * @return {Any}
42211   */
42212  function max(array, byProperty) {
42213    if (!array || array.length === 0) return undefined;
42214
42215    var i = array.length - 1,
42216        result = byProperty ? array[i][byProperty] : array[i];
42217    if (byProperty) {
42218      while (i--) {
42219        if (array[i][byProperty] >= result) {
42220          result = array[i][byProperty];
42221        }
42222      }
42223    }
42224    else {
42225      while (i--) {
42226        if (array[i] >= result) {
42227          result = array[i];
42228        }
42229      }
42230    }
42231    return result;
42232  }
42233
42234  /**
42235   * Finds minimum value in array (not necessarily "first" one)
42236   * @memberOf fabric.util.array
42237   * @param {Array} array Array to iterate over
42238   * @param {String} byProperty
42239   * @return {Any}
42240   */
42241  function min(array, byProperty) {
42242    if (!array || array.length === 0) return undefined;
42243
42244    var i = array.length - 1,
42245        result = byProperty ? array[i][byProperty] : array[i];
42246
42247    if (byProperty) {
42248      while (i--) {
42249        if (array[i][byProperty] < result) {
42250          result = array[i][byProperty];
42251        }
42252      }
42253    }
42254    else {
42255      while (i--) {
42256        if (array[i] < result) {
42257          result = array[i];
42258        }
42259      }
42260    }
42261    return result;
42262  }
42263
42264  /**
42265   * @namespace fabric.util.array
42266   */
42267  fabric.util.array = {
42268    invoke: invoke,
42269    min: min,
42270    max: max
42271  };
42272
42273})();
42274
42275
42276(function(){
42277
42278  /**
42279   * Copies all enumerable properties of one object to another
42280   * @memberOf fabric.util.object
42281   * @param {Object} destination Where to copy to
42282   * @param {Object} source Where to copy from
42283   * @return {Object}
42284   */
42285  function extend(destination, source) {
42286    // JScript DontEnum bug is not taken care of
42287    for (var property in source) {
42288      destination[property] = source[property];
42289    }
42290    return destination;
42291  }
42292
42293  /**
42294   * Creates an empty object and copies all enumerable properties of another object to it
42295   * @memberOf fabric.util.object
42296   * @param {Object} object Object to clone
42297   * @return {Object}
42298   */
42299  function clone(object) {
42300    return extend({ }, object);
42301  }
42302
42303  /** @namespace fabric.util.object */
42304  fabric.util.object = {
42305    extend: extend,
42306    clone: clone
42307  };
42308
42309})();
42310
42311
42312(function() {
42313
42314/* _ES5_COMPAT_START_ */
42315if (!String.prototype.trim) {
42316  /**
42317   * Trims a string (removing whitespace from the beginning and the end)
42318   * @function external:String#trim
42319   * @see <a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/Trim">String#trim on MDN</a>
42320   */
42321  String.prototype.trim = function () {
42322    // this trim is not fully ES3 or ES5 compliant, but it should cover most cases for now
42323    return this.replace(/^[\s\xA0]+/, '').replace(/[\s\xA0]+$/, '');
42324  };
42325}
42326/* _ES5_COMPAT_END_ */
42327
42328/**
42329 * Camelizes a string
42330 * @memberOf fabric.util.string
42331 * @param {String} string String to camelize
42332 * @return {String} Camelized version of a string
42333 */
42334function camelize(string) {
42335  return string.replace(/-+(.)?/g, function(match, character) {
42336    return character ? character.toUpperCase() : '';
42337  });
42338}
42339
42340/**
42341 * Capitalizes a string
42342 * @memberOf fabric.util.string
42343 * @param {String} string String to capitalize
42344 * @return {String} Capitalized version of a string
42345 */
42346function capitalize(string) {
42347  return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();
42348}
42349
42350/**
42351 * Escapes XML in a string
42352 * @memberOf fabric.util.string
42353 * @param {String} string String to escape
42354 * @return {String} Escaped version of a string
42355 */
42356function escapeXml(string) {
42357  return string.replace(/&/g, '&amp;')
42358     .replace(/"/g, '&quot;')
42359     .replace(/'/g, '&apos;')
42360     .replace(/</g, '&lt;')
42361     .replace(/>/g, '&gt;');
42362}
42363
42364/**
42365 * String utilities
42366 * @namespace fabric.util.string
42367 */
42368fabric.util.string = {
42369  camelize: camelize,
42370  capitalize: capitalize,
42371  escapeXml: escapeXml
42372};
42373}());
42374
42375
42376/* _ES5_COMPAT_START_ */
42377(function() {
42378
42379  var slice = Array.prototype.slice,
42380      apply = Function.prototype.apply,
42381      Dummy = function() { };
42382
42383  if (!Function.prototype.bind) {
42384    /**
42385     * Cross-browser approximation of ES5 Function.prototype.bind (not fully spec conforming)
42386     * @see <a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind">Function#bind on MDN</a>
42387     * @param {Object} thisArg Object to bind function to
42388     * @param {Any[]} [...] Values to pass to a bound function
42389     * @return {Function}
42390     */
42391    Function.prototype.bind = function(thisArg) {
42392      var fn = this, args = slice.call(arguments, 1), bound;
42393      if (args.length) {
42394        bound = function() {
42395          return apply.call(fn, this instanceof Dummy ? this : thisArg, args.concat(slice.call(arguments)));
42396        };
42397      }
42398      else {
42399        /** @ignore */
42400        bound = function() {
42401          return apply.call(fn, this instanceof Dummy ? this : thisArg, arguments);
42402        };
42403      }
42404      Dummy.prototype = this.prototype;
42405      bound.prototype = new Dummy();
42406
42407      return bound;
42408    };
42409  }
42410
42411})();
42412/* _ES5_COMPAT_END_ */
42413
42414
42415(function() {
42416
42417  var slice = Array.prototype.slice, emptyFunction = function() { };
42418
42419  var IS_DONTENUM_BUGGY = (function(){
42420    for (var p in { toString: 1 }) {
42421      if (p === 'toString') return false;
42422    }
42423    return true;
42424  })();
42425
42426  /** @ignore */
42427  var addMethods = function(klass, source, parent) {
42428    for (var property in source) {
42429
42430      if (property in klass.prototype &&
42431          typeof klass.prototype[property] === 'function' &&
42432          (source[property] + '').indexOf('callSuper') > -1) {
42433
42434        klass.prototype[property] = (function(property) {
42435          return function() {
42436
42437            var superclass = this.constructor.superclass;
42438            this.constructor.superclass = parent;
42439            var returnValue = source[property].apply(this, arguments);
42440            this.constructor.superclass = superclass;
42441
42442            if (property !== 'initialize') {
42443              return returnValue;
42444            }
42445          };
42446        })(property);
42447      }
42448      else {
42449        klass.prototype[property] = source[property];
42450      }
42451
42452      if (IS_DONTENUM_BUGGY) {
42453        if (source.toString !== Object.prototype.toString) {
42454          klass.prototype.toString = source.toString;
42455        }
42456        if (source.valueOf !== Object.prototype.valueOf) {
42457          klass.prototype.valueOf = source.valueOf;
42458        }
42459      }
42460    }
42461  };
42462
42463  function Subclass() { }
42464
42465  function callSuper(methodName) {
42466    var fn = this.constructor.superclass.prototype[methodName];
42467    return (arguments.length > 1)
42468      ? fn.apply(this, slice.call(arguments, 1))
42469      : fn.call(this);
42470  }
42471
42472  /**
42473   * Helper for creation of "classes".
42474   * @memberOf fabric.util
42475   * @param parent optional "Class" to inherit from
42476   * @param properties Properties shared by all instances of this class
42477   *                  (be careful modifying objects defined here as this would affect all instances)
42478   */
42479  function createClass() {
42480    var parent = null,
42481        properties = slice.call(arguments, 0);
42482
42483    if (typeof properties[0] === 'function') {
42484      parent = properties.shift();
42485    }
42486    function klass() {
42487      this.initialize.apply(this, arguments);
42488    }
42489
42490    klass.superclass = parent;
42491    klass.subclasses = [ ];
42492
42493    if (parent) {
42494      Subclass.prototype = parent.prototype;
42495      klass.prototype = new Subclass();
42496      parent.subclasses.push(klass);
42497    }
42498    for (var i = 0, length = properties.length; i < length; i++) {
42499      addMethods(klass, properties[i], parent);
42500    }
42501    if (!klass.prototype.initialize) {
42502      klass.prototype.initialize = emptyFunction;
42503    }
42504    klass.prototype.constructor = klass;
42505    klass.prototype.callSuper = callSuper;
42506    return klass;
42507  }
42508
42509  fabric.util.createClass = createClass;
42510})();
42511
42512
42513(function () {
42514
42515  /* EVENT HANDLING */
42516
42517  function areHostMethods(object) {
42518    var methodNames = Array.prototype.slice.call(arguments, 1),
42519        t, i, len = methodNames.length;
42520    for (i = 0; i < len; i++) {
42521      t = typeof object[methodNames[i]];
42522      if (!(/^(?:function|object|unknown)$/).test(t)) return false;
42523    }
42524    return true;
42525  }
42526  var getUniqueId = (function () {
42527    var uid = 0;
42528    return function (element) {
42529      return element.__uniqueID || (element.__uniqueID = 'uniqueID__' + uid++);
42530    };
42531  })();
42532
42533  /** @ignore */
42534  var getElement, setElement;
42535
42536  (function () {
42537    var elements = { };
42538    /** @ignore */
42539    getElement = function (uid) {
42540      return elements[uid];
42541    };
42542    /** @ignore */
42543    setElement = function (uid, element) {
42544      elements[uid] = element;
42545    };
42546  })();
42547
42548  function createListener(uid, handler) {
42549    return {
42550      handler: handler,
42551      wrappedHandler: createWrappedHandler(uid, handler)
42552    };
42553  }
42554
42555  function createWrappedHandler(uid, handler) {
42556    return function (e) {
42557      handler.call(getElement(uid), e || fabric.window.event);
42558    };
42559  }
42560
42561  function createDispatcher(uid, eventName) {
42562    return function (e) {
42563      if (handlers[uid] && handlers[uid][eventName]) {
42564        var handlersForEvent = handlers[uid][eventName];
42565        for (var i = 0, len = handlersForEvent.length; i < len; i++) {
42566          handlersForEvent[i].call(this, e || fabric.window.event);
42567        }
42568      }
42569    };
42570  }
42571
42572  var shouldUseAddListenerRemoveListener = (
42573        areHostMethods(fabric.document.documentElement, 'addEventListener', 'removeEventListener') &&
42574        areHostMethods(fabric.window, 'addEventListener', 'removeEventListener')),
42575
42576      shouldUseAttachEventDetachEvent = (
42577        areHostMethods(fabric.document.documentElement, 'attachEvent', 'detachEvent') &&
42578        areHostMethods(fabric.window, 'attachEvent', 'detachEvent')),
42579
42580      // IE branch
42581      listeners = { },
42582
42583      // DOM L0 branch
42584      handlers = { },
42585
42586      addListener, removeListener;
42587
42588  if (shouldUseAddListenerRemoveListener) {
42589    /** @ignore */
42590    addListener = function (element, eventName, handler) {
42591      element.addEventListener(eventName, handler, false);
42592    };
42593    /** @ignore */
42594    removeListener = function (element, eventName, handler) {
42595      element.removeEventListener(eventName, handler, false);
42596    };
42597  }
42598
42599  else if (shouldUseAttachEventDetachEvent) {
42600    /** @ignore */
42601    addListener = function (element, eventName, handler) {
42602      var uid = getUniqueId(element);
42603      setElement(uid, element);
42604      if (!listeners[uid]) {
42605        listeners[uid] = { };
42606      }
42607      if (!listeners[uid][eventName]) {
42608        listeners[uid][eventName] = [ ];
42609
42610      }
42611      var listener = createListener(uid, handler);
42612      listeners[uid][eventName].push(listener);
42613      element.attachEvent('on' + eventName, listener.wrappedHandler);
42614    };
42615    /** @ignore */
42616    removeListener = function (element, eventName, handler) {
42617      var uid = getUniqueId(element), listener;
42618      if (listeners[uid] && listeners[uid][eventName]) {
42619        for (var i = 0, len = listeners[uid][eventName].length; i < len; i++) {
42620          listener = listeners[uid][eventName][i];
42621          if (listener && listener.handler === handler) {
42622            element.detachEvent('on' + eventName, listener.wrappedHandler);
42623            listeners[uid][eventName][i] = null;
42624          }
42625        }
42626      }
42627    };
42628  }
42629  else {
42630    /** @ignore */
42631    addListener = function (element, eventName, handler) {
42632      var uid = getUniqueId(element);
42633      if (!handlers[uid]) {
42634        handlers[uid] = { };
42635      }
42636      if (!handlers[uid][eventName]) {
42637        handlers[uid][eventName] = [ ];
42638        var existingHandler = element['on' + eventName];
42639        if (existingHandler) {
42640          handlers[uid][eventName].push(existingHandler);
42641        }
42642        element['on' + eventName] = createDispatcher(uid, eventName);
42643      }
42644      handlers[uid][eventName].push(handler);
42645    };
42646    /** @ignore */
42647    removeListener = function (element, eventName, handler) {
42648      var uid = getUniqueId(element);
42649      if (handlers[uid] && handlers[uid][eventName]) {
42650        var handlersForEvent = handlers[uid][eventName];
42651        for (var i = 0, len = handlersForEvent.length; i < len; i++) {
42652          if (handlersForEvent[i] === handler) {
42653            handlersForEvent.splice(i, 1);
42654          }
42655        }
42656      }
42657    };
42658  }
42659
42660  /**
42661   * Adds an event listener to an element
42662   * @function
42663   * @memberOf fabric.util
42664   * @param {HTMLElement} element
42665   * @param {String} eventName
42666   * @param {Function} handler
42667   */
42668  fabric.util.addListener = addListener;
42669
42670  /**
42671   * Removes an event listener from an element
42672   * @function
42673   * @memberOf fabric.util
42674   * @param {HTMLElement} element
42675   * @param {String} eventName
42676   * @param {Function} handler
42677   */
42678  fabric.util.removeListener = removeListener;
42679
42680  /**
42681   * Cross-browser wrapper for getting event's coordinates
42682   * @memberOf fabric.util
42683   * @param {Event} event Event object
42684   * @param {HTMLCanvasElement} upperCanvasEl &lt;canvas> element on which object selection is drawn
42685   */
42686  function getPointer(event, upperCanvasEl) {
42687    event || (event = fabric.window.event);
42688
42689    var element = event.target || (typeof event.srcElement !== 'unknown' ? event.srcElement : null),
42690        body = fabric.document.body || {scrollLeft: 0, scrollTop: 0},
42691        docElement = fabric.document.documentElement,
42692        orgElement = element,
42693        scrollLeft = 0,
42694        scrollTop = 0,
42695        firstFixedAncestor;
42696
42697    while (element && element.parentNode && !firstFixedAncestor) {
42698      element = element.parentNode;
42699
42700      if (element !== fabric.document &&
42701          fabric.util.getElementStyle(element, 'position') === 'fixed') {
42702        firstFixedAncestor = element;
42703      }
42704
42705      if (element !== fabric.document &&
42706          orgElement !== upperCanvasEl &&
42707          fabric.util.getElementStyle(element, 'position') === 'absolute') {
42708        scrollLeft = 0;
42709        scrollTop = 0;
42710      }
42711      else if (element === fabric.document) {
42712        scrollLeft = body.scrollLeft || docElement.scrollLeft || 0;
42713        scrollTop = body.scrollTop ||  docElement.scrollTop || 0;
42714      }
42715      else {
42716        scrollLeft += element.scrollLeft || 0;
42717        scrollTop += element.scrollTop || 0;
42718      }
42719    }
42720
42721    return {
42722      x: pointerX(event) + scrollLeft,
42723      y: pointerY(event) + scrollTop
42724    };
42725  }
42726
42727  var pointerX = function(event) {
42728    // looks like in IE (<9) clientX at certain point (apparently when mouseup fires on VML element)
42729    // is represented as COM object, with all the consequences, like "unknown" type and error on [[Get]]
42730    // need to investigate later
42731    return (typeof event.clientX !== 'unknown' ? event.clientX : 0);
42732  };
42733
42734  var pointerY = function(event) {
42735    return (typeof event.clientY !== 'unknown' ? event.clientY : 0);
42736  };
42737
42738  if (fabric.isTouchSupported) {
42739    pointerX = function(event) {
42740      if (event.type !== 'touchend') {
42741        return (event.touches && event.touches[0] ?
42742          (event.touches[0].pageX - (event.touches[0].pageX - event.touches[0].clientX)) || event.clientX : event.clientX);
42743      }
42744      return (event.changedTouches && event.changedTouches[0]
42745        ? (event.changedTouches[0].pageX - (event.changedTouches[0].pageX - event.changedTouches[0].clientX)) || event.clientX : event.clientX);
42746    };
42747    pointerY = function(event) {
42748      if (event.type !== 'touchend') {
42749        return (event.touches && event.touches[0]
42750          ? (event.touches[0].pageY - (event.touches[0].pageY - event.touches[0].clientY)) || event.clientY : event.clientY);
42751      }
42752      return (event.changedTouches && event.changedTouches[0]
42753        ? (event.changedTouches[0].pageY - (event.changedTouches[0].pageY - event.changedTouches[0].clientY)) || event.clientY : event.clientY);
42754    };
42755  }
42756
42757  fabric.util.getPointer = getPointer;
42758
42759  fabric.util.object.extend(fabric.util, fabric.Observable);
42760
42761})();
42762
42763
42764(function () {
42765
42766  /**
42767   * Cross-browser wrapper for setting element's style
42768   * @memberOf fabric.util
42769   * @param {HTMLElement} element
42770   * @param {Object} styles
42771   * @return {HTMLElement} Element that was passed as a first argument
42772   */
42773  function setStyle(element, styles) {
42774    var elementStyle = element.style;
42775    if (!elementStyle) {
42776      return element;
42777    }
42778    if (typeof styles === 'string') {
42779      element.style.cssText += ';' + styles;
42780      return styles.indexOf('opacity') > -1
42781        ? setOpacity(element, styles.match(/opacity:\s*(\d?\.?\d*)/)[1])
42782        : element;
42783    }
42784    for (var property in styles) {
42785      if (property === 'opacity') {
42786        setOpacity(element, styles[property]);
42787      }
42788      else {
42789        var normalizedProperty = (property === 'float' || property === 'cssFloat')
42790          ? (typeof elementStyle.styleFloat === 'undefined' ? 'cssFloat' : 'styleFloat')
42791          : property;
42792        elementStyle[normalizedProperty] = styles[property];
42793      }
42794    }
42795    return element;
42796  }
42797
42798  var parseEl = fabric.document.createElement('div'),
42799      supportsOpacity = typeof parseEl.style.opacity === 'string',
42800      supportsFilters = typeof parseEl.style.filter === 'string',
42801      reOpacity = /alpha\s*\(\s*opacity\s*=\s*([^\)]+)\)/,
42802
42803      /** @ignore */
42804      setOpacity = function (element) { return element; };
42805
42806  if (supportsOpacity) {
42807    /** @ignore */
42808    setOpacity = function(element, value) {
42809      element.style.opacity = value;
42810      return element;
42811    };
42812  }
42813  else if (supportsFilters) {
42814    /** @ignore */
42815    setOpacity = function(element, value) {
42816      var es = element.style;
42817      if (element.currentStyle && !element.currentStyle.hasLayout) {
42818        es.zoom = 1;
42819      }
42820      if (reOpacity.test(es.filter)) {
42821        value = value >= 0.9999 ? '' : ('alpha(opacity=' + (value * 100) + ')');
42822        es.filter = es.filter.replace(reOpacity, value);
42823      }
42824      else {
42825        es.filter += ' alpha(opacity=' + (value * 100) + ')';
42826      }
42827      return element;
42828    };
42829  }
42830
42831  fabric.util.setStyle = setStyle;
42832
42833})();
42834
42835
42836(function() {
42837
42838  var _slice = Array.prototype.slice;
42839
42840  /**
42841   * Takes id and returns an element with that id (if one exists in a document)
42842   * @memberOf fabric.util
42843   * @param {String|HTMLElement}
42843 id
42844   * @return {HTMLElement|null}
42845   */
42846  function getById(id) {
42847    return typeof id === 'string' ? fabric.document.getElementById(id) : id;
42848  }
42849
42850  /**
42851   * Converts an array-like object (e.g. arguments or NodeList) to an array
42852   * @memberOf fabric.util
42853   * @param {Object} arrayLike
42854   * @return {Array}
42855   */
42856  var toArray = function(arrayLike) {
42857    return _slice.call(arrayLike, 0);
42858  };
42859
42860  var sliceCanConvertNodelists;
42861  try {
42862    sliceCanConvertNodelists = toArray(fabric.document.childNodes) instanceof Array;
42863  }
42864  catch(err) { }
42865
42866  if (!sliceCanConvertNodelists) {
42867    toArray = function(arrayLike) {
42868      var arr = new Array(arrayLike.length), i = arrayLike.length;
42869      while (i--) {
42870        arr[i] = arrayLike[i];
42871      }
42872      return arr;
42873    };
42874  }
42875
42876  /**
42877   * Creates specified element with specified attributes
42878   * @memberOf fabric.util
42879   * @param {String} tagName Type of an element to create
42880   * @param {Object} [attributes] Attributes to set on an element
42881   * @return {HTMLElement} Newly created element
42882   */
42883  function makeElement(tagName, attributes) {
42884    var el = fabric.document.createElement(tagName);
42885    for (var prop in attributes) {
42886      if (prop === 'class') {
42887        el.className = attributes[prop];
42888      }
42889      else if (prop === 'for') {
42890        el.htmlFor = attributes[prop];
42891      }
42892      else {
42893        el.setAttribute(prop, attributes[prop]);
42894      }
42895    }
42896    return el;
42897  }
42898
42899  /**
42900   * Adds class to an element
42901   * @memberOf fabric.util
42902   * @param {HTMLElement} element Element to add class to
42903   * @param {String} className Class to add to an element
42904   */
42905  function addClass(element, className) {
42906    if ((' ' + element.className + ' ').indexOf(' ' + className + ' ') === -1) {
42907      element.className += (element.className ? ' ' : '') + className;
42908    }
42909  }
42910
42911  /**
42912   * Wraps element with another element
42913   * @memberOf fabric.util
42914   * @param {HTMLElement} element Element to wrap
42915   * @param {HTMLElement|String} wrapper Element to wrap with
42916   * @param {Object} [attributes] Attributes to set on a wrapper
42917   * @return {HTMLElement} wrapper
42918   */
42919  function wrapElement(element, wrapper, attributes) {
42920    if (typeof wrapper === 'string') {
42921      wrapper = makeElement(wrapper, attributes);
42922    }
42923    if (element.parentNode) {
42924      element.parentNode.replaceChild(wrapper, element);
42925    }
42926    wrapper.appendChild(element);
42927    return wrapper;
42928  }
42929
42930  /**
42931   * Returns offset for a given element
42932   * @function
42933   * @memberOf fabric.util
42934   * @param {HTMLElement} element Element to get offset for
42935   * @return {Object} Object with "left" and "top" properties
42936   */
42937  function getElementOffset(element) {
42938    var docElem, win,
42939        box = {left: 0, top: 0},
42940        doc = element && element.ownerDocument,
42941        offset = {left: 0, top: 0},
42942        offsetAttributes = {
42943           'borderLeftWidth': 'left',
42944           'borderTopWidth':  'top',
42945           'paddingLeft':     'left',
42946           'paddingTop':      'top'
42947        };
42948
42949    if (!doc){
42950      return {left: 0, top: 0};
42951    }
42952
42953    for (var attr in offsetAttributes) {
42954      offset[offsetAttributes[attr]] += parseInt(getElementStyle(element, attr), 10) || 0;
42955    }
42956
42957    docElem = doc.documentElement;
42958    if ( typeof element.getBoundingClientRect !== "undefined" ) {
42959      box = element.getBoundingClientRect();
42960    }
42961    if(doc != null && doc === doc.window){
42962      win = doc;
42963    } else {
42964      win = doc.nodeType === 9 && (doc.defaultView || doc.parentWindow);
42965    }
42966    return {
42967      left: box.left + (win.pageXOffset || docElem.scrollLeft) - (docElem.clientLeft || 0) + offset.left,
42968      top: box.top + (win.pageYOffset || docElem.scrollTop) - (docElem.clientTop || 0)  + offset.top
42969    };
42970  }
42971
42972  /**
42973  * Returns style attribute value of a given element
42974  * @memberOf fabric.util
42975  * @param {HTMLElement} element Element to get style attribute for
42976  * @param {String} attr Style attribute to get for element
42977  * @return {String} Style attribute value of the given element.
42978  */
42979  function getElementStyle(element, attr) {
42980    if (!element.style) {
42981      element.style = { };
42982    }
42983
42984    if (fabric.document.defaultView && fabric.document.defaultView.getComputedStyle) {
42985      return fabric.document.defaultView.getComputedStyle(element, null)[attr];
42986    }
42987    else {
42988      var value = element.style[attr];
42989      if (!value && element.currentStyle) value = element.currentStyle[attr];
42990      return value;
42991    }
42992  }
42993
42994  (function () {
42995    var style = fabric.document.documentElement.style;
42996
42997    var selectProp = 'userSelect' in style
42998      ? 'userSelect'
42999      : 'MozUserSelect' in style
43000        ? 'MozUserSelect'
43001        : 'WebkitUserSelect' in style
43002          ? 'WebkitUserSelect'
43003          : 'KhtmlUserSelect' in style
43004            ? 'KhtmlUserSelect'
43005            : '';
43006
43007    /**
43008     * Makes element unselectable
43009     * @memberOf fabric.util
43010     * @param {HTMLElement} element Element to make unselectable
43011     * @return {HTMLElement} Element that was passed in
43012     */
43013    function makeElementUnselectable(element) {
43014      if (typeof element.onselectstart !== 'undefined') {
43015        element.onselectstart = fabric.util.falseFunction;
43016      }
43017      if (selectProp) {
43018        element.style[selectProp] = 'none';
43019      }
43020      else if (typeof element.unselectable === 'string') {
43021        element.unselectable = 'on';
43022      }
43023      return element;
43024    }
43025
43026    /**
43027     * Makes element selectable
43028     * @memberOf fabric.util
43029     * @param {HTMLElement} element Element to make selectable
43030     * @return {HTMLElement} Element that was passed in
43031     */
43032    function makeElementSelectable(element) {
43033      if (typeof element.onselectstart !== 'undefined') {
43034        element.onselectstart = null;
43035      }
43036      if (selectProp) {
43037        element.style[selectProp] = '';
43038      }
43039      else if (typeof element.unselectable === 'string') {
43040        element.unselectable = '';
43041      }
43042      return element;
43043    }
43044
43045    fabric.util.makeElementUnselectable = makeElementUnselectable;
43046    fabric.util.makeElementSelectable = makeElementSelectable;
43047  })();
43048
43049  (function() {
43050
43051    /**
43052     * Inserts a script element with a given url into a document; invokes callback, when that script is finished loading
43053     * @memberOf fabric.util
43054     * @param {String} url URL of a script to load
43055     * @param {Function} callback Callback to execute when script is finished loading
43056     */
43057    function getScript(url, callback) {
43058      var headEl = fabric.document.getElementsByTagName("head")[0],
43059          scriptEl = fabric.document.createElement('script'),
43060          loading = true;
43061
43062      /** @ignore */
43063      scriptEl.onload = /** @ignore */ scriptEl.onreadystatechange = function(e) {
43064        if (loading) {
43065          if (typeof this.readyState === 'string' &&
43066              this.readyState !== 'loaded' &&
43067              this.readyState !== 'complete') return;
43068          loading = false;
43069          callback(e || fabric.window.event);
43070          scriptEl = scriptEl.onload = scriptEl.onreadystatechange = null;
43071        }
43072      };
43073      scriptEl.src = url;
43074      headEl.appendChild(scriptEl);
43075      // causes issue in Opera
43076      // headEl.removeChild(scriptEl);
43077    }
43078
43079    fabric.util.getScript = getScript;
43080  })();
43081
43082  fabric.util.getById = getById;
43083  fabric.util.toArray = toArray;
43084  fabric.util.makeElement = makeElement;
43085  fabric.util.addClass = addClass;
43086  fabric.util.wrapElement = wrapElement;
43087  fabric.util.getElementOffset = getElementOffset;
43088  fabric.util.getElementStyle = getElementStyle;
43089
43090})();
43091
43092
43093(function(){
43094
43095  function addParamToUrl(url, param) {
43096    return url + (/\?/.test(url) ? '&' : '?') + param;
43097  }
43098
43099  var makeXHR = (function() {
43100    var factories = [
43101      function() { return new ActiveXObject("Microsoft.XMLHTTP"); },
43102      function() { return new ActiveXObject("Msxml2.XMLHTTP"); },
43103      function() { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); },
43104      function() { return new XMLHttpRequest(); }
43105    ];
43106    for (var i = factories.length; i--; ) {
43107      try {
43108        var req = factories[i]();
43109        if (req) {
43110          return factories[i];
43111        }
43112      }
43113      catch (err) { }
43114    }
43115  })();
43116
43117  function emptyFn() { }
43118
43119  /**
43120   * Cross-browser abstraction for sending XMLHttpRequest
43121   * @memberOf fabric.util
43122   * @param {String} url URL to send XMLHttpRequest to
43123   * @param {Object} [options] Options object
43124   * @param {String} [options.method="GET"]
43125   * @param {Function} options.onComplete Callback to invoke when request is completed
43126   * @return {XMLHttpRequest} request
43127   */
43128  function request(url, options) {
43129
43130    options || (options = { });
43131
43132    var method = options.method ? options.method.toUpperCase() : 'GET',
43133        onComplete = options.onComplete || function() { },
43134        xhr = makeXHR(),
43135        body;
43136
43137    /** @ignore */
43138    xhr.onreadystatechange = function() {
43139      if (xhr.readyState === 4) {
43140        onComplete(xhr);
43141        xhr.onreadystatechange = emptyFn;
43142      }
43143    };
43144
43145    if (method === 'GET') {
43146      body = null;
43147      if (typeof options.parameters === 'string') {
43148        url = addParamToUrl(url, options.parameters);
43149      }
43150    }
43151
43152    xhr.open(method, url, true);
43153
43154    if (method === 'POST' || method === 'PUT') {
43155      xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
43156    }
43157
43158    xhr.send(body);
43159    return xhr;
43160  }
43161
43162  fabric.util.request = request;
43163})();
43164
43165
43166(function() {
43167
43168   /**
43169    * Changes value from one to another within certain period of time, invoking callbacks as value is being changed.
43170    * @memberOf fabric.util
43171    * @param {Object} [options] Animation options
43172    * @param {Function} [options.onChange] Callback; invoked on every value change
43173    * @param {Function} [options.onComplete] Callback; invoked when value change is completed
43174    * @param {Number} [options.startValue=0] Starting value
43175    * @param {Number} [options.endValue=100] Ending value
43176    * @param {Number} [options.byValue=100] Value to modify the property by
43177    * @param {Function} [options.easing] Easing function
43178    * @param {Number} [options.duration=500] Duration of change
43179    */
43180  function animate(options) {
43181
43182    options || (options = { });
43183
43184    var start = +new Date(),
43185      duration = options.duration || 500,
43186      finish = start + duration, time,
43187      onChange = options.onChange || function() { },
43188      abort = options.abort || function() { return false; },
43189      easing = options.easing || function(t, b, c, d) {return -c * Math.cos(t/d * (Math.PI/2)) + c + b;},
43190      startValue = 'startValue' in options ? options.startValue : 0,
43191      endValue = 'endValue' in options ? options.endValue : 100,
43192      byValue = options.byValue || endValue - startValue;
43193
43194    options.onStart && options.onStart();
43195
43196    (function tick() {
43197      time = +new Date();
43198      var currentTime = time > finish ? duration : (time - start);
43199      if (abort()) {
43200        options.onComplete && options.onComplete();
43201        return;
43202      }
43203      onChange(easing(currentTime, startValue, byValue, duration));
43204      if (time > finish) {
43205        options.onComplete && options.onComplete();
43206        return;
43207      }
43208      requestAnimFrame(tick);
43209    })();
43210  }
43211
43212  var _requestAnimFrame = fabric.window.requestAnimationFrame       ||
43213                          fabric.window.webkitRequestAnimationFrame ||
43214                          fabric.window.mozRequestAnimationFrame    ||
43215                          fabric.window.oRequestAnimationFrame      ||
43216                          fabric.window.msRequestAnimationFrame     ||
43217                          function(callback) {
43218                            fabric.window.setTimeout(callback, 1000 / 60);
43219                          };
43220  /**
43221    * requestAnimationFrame polyfill based on http://paulirish.com/2011/requestanimationframe-for-smart-animating/
43222    * @memberOf fabric.util
43223    * @param {Function} callback Callback to invoke
43224    * @param {DOMElement} element optional Element to associate with animation
43225    */
43226  var requestAnimFrame = function() {
43227    return _requestAnimFrame.apply(fabric.window, arguments);
43228  };
43229
43230  fabric.util.animate = animate;
43231  fabric.util.requestAnimFrame = requestAnimFrame;
43232
43233})();
43234
43235
43236(function() {
43237
43238  /**
43239   * Quadratic easing in
43240   * @memberOf fabric.util.ease
43241   */
43242  function easeInQuad(t, b, c, d) {
43243    return c*(t/=d)*t + b;
43244  }
43245
43246  /**
43247   * Quadratic easing out
43248   * @memberOf fabric.util.ease
43249   */
43250  function easeOutQuad(t, b, c, d) {
43251    return -c *(t/=d)*(t-2) + b;
43252  }
43253
43254  /**
43255   * Quadratic easing in and out
43256   * @memberOf fabric.util.ease
43257   */
43258  function easeInOutQuad(t, b, c, d) {
43259    t /= (d/2);
43260    if (t < 1) return c/2*t*t + b;
43261    return -c/2 * ((--t)*(t-2) - 1) + b;
43262  }
43263
43264  /**
43265   * Cubic easing in
43266   * @memberOf fabric.util.ease
43267   */
43268  function easeInCubic(t, b, c, d) {
43269    return c*(t/=d)*t*t + b;
43270  }
43271
43272  /**
43273   * Cubic easing out
43274   * @memberOf fabric.util.ease
43275   */
43276  function easeOutCubic(t, b, c, d) {
43277    return c*((t=t/d-1)*t*t + 1) + b;
43278  }
43279
43280  /**
43281   * Cubic easing in and out
43282   * @memberOf fabric.util.ease
43283   */
43284  function easeInOutCubic(t, b, c, d) {
43285    t /= d/2;
43286    if (t < 1) return c/2*t*t*t + b;
43287    return c/2*((t-=2)*t*t + 2) + b;
43288  }
43289
43290  /**
43291   * Quartic easing in
43292   * @memberOf fabric.util.ease
43293   */
43294  function easeInQuart(t, b, c, d) {
43295    return c*(t/=d)*t*t*t + b;
43296  }
43297
43298  /**
43299   * Quartic easing out
43300   * @memberOf fabric.util.ease
43301   */
43302  function easeOutQuart(t, b, c, d) {
43303    return -c * ((t=t/d-1)*t*t*t - 1) + b;
43304  }
43305
43306  /**
43307   * Quartic easing in and out
43308   * @memberOf fabric.util.ease
43309   */
43310  function easeInOutQuart(t, b, c, d) {
43311    t /= d/2;
43312    if (t < 1) return c/2*t*t*t*t + b;
43313    return -c/2 * ((t-=2)*t*t*t - 2) + b;
43314  }
43315
43316  /**
43317   * Quintic easing in
43318   * @memberOf fabric.util.ease
43319   */
43320  function easeInQuint(t, b, c, d) {
43321    return c*(t/=d)*t*t*t*t + b;
43322  }
43323
43324  /**
43325   * Quintic easing out
43326   * @memberOf fabric.util.ease
43327   */
43328  function easeOutQuint(t, b, c, d) {
43329    return c*((t=t/d-1)*t*t*t*t + 1) + b;
43330  }
43331
43332  /**
43333   * Quintic easing in and out
43334   * @memberOf fabric.util.ease
43335   */
43336  function easeInOutQuint(t, b, c, d) {
43337    t /= d/2;
43338    if (t < 1) return c/2*t*t*t*t*t + b;
43339    return c/2*((t-=2)*t*t*t*t + 2) + b;
43340  }
43341
43342  /**
43343   * Sinusoidal easing in
43344   * @memberOf fabric.util.ease
43345   */
43346  function easeInSine(t, b, c, d) {
43347    return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
43348  }
43349
43350  /**
43351   * Sinusoidal easing out
43352   * @memberOf fabric.util.ease
43353   */
43354  function easeOutSine(t, b, c, d) {
43355    return c * Math.sin(t/d * (Math.PI/2)) + b;
43356  }
43357
43358  /**
43359   * Sinusoidal easing in and out
43360   * @memberOf fabric.util.ease
43361   */
43362  function easeInOutSine(t, b, c, d) {
43363    return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
43364  }
43365
43366  /**
43367   * Exponential easing in
43368   * @memberOf fabric.util.ease
43369   */
43370  function easeInExpo(t, b, c, d) {
43371    return (t===0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
43372  }
43373
43374  /**
43375   * Exponential easing out
43376   * @memberOf fabric.util.ease
43377   */
43378  function easeOutExpo(t, b, c, d) {
43379    return (t===d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
43380  }
43381
43382  /**
43383   * Exponential easing in and out
43384   * @memberOf fabric.util.ease
43385   */
43386  function easeInOutExpo(t, b, c, d) {
43387    if (t===0) return b;
43388    if (t===d) return b+c;
43389    t /= d/2;
43390    if (t < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
43391    return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
43392  }
43393
43394  /**
43395   * Circular easing in
43396   * @memberOf fabric.util.ease
43397   */
43398  function easeInCirc(t, b, c, d) {
43399    return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
43400  }
43401
43402  /**
43403   * Circular easing out
43404   * @memberOf fabric.util.ease
43405   */
43406  function easeOutCirc(t, b, c, d) {
43407    return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
43408  }
43409
43410  /**
43411   * Circular easing in and out
43412   * @memberOf fabric.util.ease
43413   */
43414  function easeInOutCirc(t, b, c, d) {
43415    t /= d/2;
43416    if (t < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
43417    return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
43418  }
43419
43420  /**
43421   * Elastic easing in
43422   * @memberOf fabric.util.ease
43423   */
43424  function easeInElastic(t, b, c, d) {
43425    var s=1.70158;var p=0;var a=c;
43426    if (t===0) return b;
43427    t /= d;
43428    if (t===1) return b+c;
43429    if (!p) p=d*0.3;
43430    if (a < Math.abs(c)) { a=c; s=p/4; }
43431    else s = p/(2*Math.PI) * Math.asin (c/a);
43432    return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
43433  }
43434
43435  /**
43436   * Elastic easing out
43437   * @memberOf fabric.util.ease
43438   */
43439  function easeOutElastic(t, b, c, d) {
43440    var s=1.70158;var p=0;var a=c;
43441    if (t===0) return b;
43442    t /= d;
43443    if (t===1) return b+c;
43444    if (!p) p=d*0.3;
43445    if (a < Math.abs(c)) { a=c; s=p/4; }
43446    else s = p/(2*Math.PI) * Math.asin (c/a);
43447    return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
43448  }
43449
43450  /**
43451   * Elastic easing in and out
43452   * @memberOf fabric.util.ease
43453   */
43454  function easeInOutElastic(t, b, c, d) {
43455    var s=1.70158;var p=0;var a=c;
43456    if (t===0) return b;
43457    t /= d/2;
43458    if (t===2) return b+c;
43459    if (!p) p=d*(0.3*1.5);
43460    if (a < Math.abs(c)) { a=c; s=p/4; }
43461    else s = p/(2*Math.PI) * Math.asin (c/a);
43462    if (t < 1) return -0.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
43463    return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*0.5 + c + b;
43464  }
43465
43466  /**
43467   * Backwards easing in
43468   * @memberOf fabric.util.ease
43469   */
43470  function easeInBack(t, b, c, d, s) {
43471    if (s === undefined) s = 1.70158;
43472    return c*(t/=d)*t*((s+1)*t - s) + b;
43473  }
43474
43475  /**
43476   * Backwards easing out
43477   * @memberOf fabric.util.ease
43478   */
43479  function easeOutBack(t, b, c, d, s) {
43480    if (s === undefined) s = 1.70158;
43481    return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
43482  }
43483
43484  /**
43485   * Backwards easing in and out
43486   * @memberOf fabric.util.ease
43487   */
43488  function easeInOutBack(t, b, c, d, s) {
43489    if (s === undefined) s = 1.70158;
43490    t /= d/2;
43491    if (t < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
43492    return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
43493  }
43494
43495  /**
43496   * Bouncing easing in
43497   * @memberOf fabric.util.ease
43498   */
43499  function easeInBounce(t, b, c, d) {
43500    return c - easeOutBounce (d-t, 0, c, d) + b;
43501  }
43502
43503  /**
43504   * Bouncing easing out
43505   * @memberOf fabric.util.ease
43506   */
43507  function easeOutBounce(t, b, c, d) {
43508    if ((t/=d) < (1/2.75)) {
43509      return c*(7.5625*t*t) + b;
43510    } else if (t < (2/2.75)) {
43511      return c*(7.5625*(t-=(1.5/2.75))*t + 0.75) + b;
43512    } else if (t < (2.5/2.75)) {
43513      return c*(7.5625*(t-=(2.25/2.75))*t + 0.9375) + b;
43514    } else {
43515      return c*(7.5625*(t-=(2.625/2.75))*t + 0.984375) + b;
43516    }
43517  }
43518
43519  /**
43520   * Bouncing easing in and out
43521   * @memberOf fabric.util.ease
43522   */
43523  function easeInOutBounce(t, b, c, d) {
43524    if (t < d/2) return easeInBounce (t*2, 0, c, d) * 0.5 + b;
43525    return easeOutBounce (t*2-d, 0, c, d) * 0.5 + c*0.5 + b;
43526  }
43527
43528  /**
43529   * Easing functions
43530   * See <a href="http://gizma.com/easing/">Easing Equations by Robert Penner</a>
43531   * @namespace fabric.util.ease
43532   */
43533  fabric.util.ease = {
43534    easeInQuad: easeInQuad,
43535    easeOutQuad: easeOutQuad,
43536    easeInOutQuad: easeInOutQuad,
43537    easeInCubic: easeInCubic,
43538    easeOutCubic: easeOutCubic,
43539    easeInOutCubic: easeInOutCubic,
43540    easeInQuart: easeInQuart,
43541    easeOutQuart: easeOutQuart,
43542    easeInOutQuart: easeInOutQuart,
43543    easeInQuint: easeInQuint,
43544    easeOutQuint: easeOutQuint,
43545    easeInOutQuint: easeInOutQuint,
43546    easeInSine: easeInSine,
43547    easeOutSine: easeOutSine,
43548    easeInOutSine: easeInOutSine,
43549    easeInExpo: easeInExpo,
43550    easeOutExpo: easeOutExpo,
43551    easeInOutExpo: easeInOutExpo,
43552    easeInCirc: easeInCirc,
43553    easeOutCirc: easeOutCirc,
43554    easeInOutCirc: easeInOutCirc,
43555    easeInElastic: easeInElastic,
43556    easeOutElastic: easeOutElastic,
43557    easeInOutElastic: easeInOutElastic,
43558    easeInBack: easeInBack,
43559    easeOutBack: easeOutBack,
43560    easeInOutBack: easeInOutBack,
43561    easeInBounce: easeInBounce,
43562    easeOutBounce: easeOutBounce,
43563    easeInOutBounce: easeInOutBounce
43564  };
43565
43566}());
43567
43568
43569(function(global) {
43570
43571  "use strict";
43572
43573  /**
43574   * @name fabric
43575   * @namespace
43576   */
43577
43578  var fabric = global.fabric || (global.fabric = { }),
43579      extend = fabric.util.object.extend,
43580      capitalize = fabric.util.string.capitalize,
43581      clone = fabric.util.object.clone,
43582      toFixed = fabric.util.toFixed,
43583      multiplyTransformMatrices = fabric.util.multiplyTransformMatrices;
43584
43585  fabric.SHARED_ATTRIBUTES = [
43586    "transform",
43587    "fill", "fill-opacity", "fill-rule",
43588    "opacity",
43589    "stroke", "stroke-dasharray", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width"
43590  ];
43591
43592  var attributesMap = {
43593    'fill-opacity':     'fillOpacity',
43594    'fill-rule':        'fillRule',
43595    'font-family':      'fontFamily',
43596    'font-size':        'fontSize',
43597    'font-style':       'fontStyle',
43598    'font-weight':      'fontWeight',
43599    'cx':               'left',
43600    'x':                'left',
43601    'r':                'radius',
43602    'stroke-dasharray': 'strokeDashArray',
43603    'stroke-linecap':   'strokeLineCap',
43604    'stroke-linejoin':  'strokeLineJoin',
43605    'stroke-miterlimit':'strokeMiterLimit',
43606    'stroke-opacity':   'strokeOpacity',
43607    'stroke-width':     'strokeWidth',
43608    'text-decoration':  'textDecoration',
43609    'cy':               'top',
43610    'y':                'top',
43611    'transform':        'transformMatrix'
43612  };
43613
43614  var colorAttributes = {
43615    'stroke': 'strokeOpacity',
43616    'fill':   'fillOpacity'
43617  };
43618
43619  function normalizeAttr(attr) {
43620    // transform attribute names
43621    if (attr in attributesMap) {
43622      return attributesMap[attr];
43623    }
43624    return attr;
43625  }
43626
43627  function normalizeValue(attr, value, parentAttributes) {
43628    var isArray;
43629
43630    if ((attr === 'fill' || attr === 'stroke') && value === 'none') {
43631      value = '';
43632    }
43633    else if (attr === 'fillRule') {
43634      value = (value === 'evenodd') ? 'destination-over' : value;
43635    }
43636    else if (attr === 'strokeDashArray') {
43637      value = value.replace(/,/g, ' ').split(/\s+/);
43638    }
43639    else if (attr === 'transformMatrix') {
43640      if (parentAttributes && parentAttributes.transformMatrix) {
43641        value = multiplyTransformMatrices(
43642          parentAttributes.transformMatrix, fabric.parseTransformAttribute(value));
43643      }
43644      else {
43645        value = fabric.parseTransformAttribute(value);
43646      }
43647    }
43648
43649    isArray = Object.prototype.toString.call(value) === '[object Array]';
43650
43651    // TODO: need to normalize em, %, pt, etc. to px (!)
43652    var parsed = isArray ? value.map(parseFloat) : parseFloat(value);
43653
43654    return (!isArray && isNaN(parsed) ? value : parsed);
43655  }
43656
43657  /**
43658   * @private
43659   * @param {Object} attributes Array of attributes to parse
43660   */
43661  function _setStrokeFillOpacity(attributes) {
43662    for (var attr in colorAttributes) {
43663
43664      if (!attributes[attr] || typeof attributes[colorAttributes[attr]] === 'undefined') continue;
43665
43666      if (attributes[attr].indexOf('url(') === 0) continue;
43667
43668      var color = new fabric.Color(attributes[attr]);
43669      attributes[attr] = color.setAlpha(toFixed(color.getAlpha() * attributes[colorAttributes[attr]], 2)).toRgba();
43670
43671      delete attributes[colorAttributes[attr]];
43672    }
43673    return attributes;
43674  }
43675
43676  /**
43677   * Returns an object of attributes' name/value, given element and an array of attribute names;
43678   * Parses parent "g" nodes recursively upwards.
43679   * @static
43680   * @memberOf fabric
43681   * @param {DOMElement} element Element to parse
43682   * @param {Array} attributes Array of attributes to parse
43683   * @return {Object} object containing parsed attributes' names/values
43684   */
43685  function parseAttributes(element, attributes) {
43686
43687    if (!element) {
43688      return;
43689    }
43690
43691    var value,
43692        parentAttributes = { };
43693
43694    // if there's a parent container (`g` node), parse its attributes recursively upwards
43695    if (element.parentNode && /^g$/i.test(element.parentNode.nodeName)) {
43696      parentAttributes = fabric.parseAttributes(element.parentNode, attributes);
43697    }
43698
43699    var ownAttributes = attributes.reduce(function(memo, attr) {
43700      value = element.getAttribute(attr);
43701      if (value) {
43702        attr = normalizeAttr(attr);
43703        value = normalizeValue(attr, value, parentAttributes);
43704
43705        memo[attr] = value;
43706      }
43707      return memo;
43708    }, { });
43709
43710    // add values parsed from style, which take precedence over attributes
43711    // (see: http://www.w3.org/TR/SVG/styling.html#UsingPresentationAttributes)
43712
43713    ownAttributes = extend(ownAttributes,
43714      extend(getGlobalStylesForElement(element), fabric.parseStyleAttribute(element)));
43715    return _setStrokeFillOpacity(extend(parentAttributes, ownAttributes));
43716  }
43717
43718  /**
43719   * Parses "transform" attribute, returning an array of values
43720   * @static
43721   * @function
43722   * @memberOf fabric
43723   * @param attributeValue {String} string containing attribute value
43724   * @return {Array} array of 6 elements representing transformation matrix
43725   */
43726  fabric.parseTransformAttribute = (function() {
43727    function rotateMatrix(matrix, args) {
43728      var angle = args[0];
43729
43730      matrix[0] = Math.cos(angle);
43731      matrix[1] = Math.sin(angle);
43732      matrix[2] = -Math.sin(angle);
43733      matrix[3] = Math.cos(angle);
43734    }
43735
43736    function scaleMatrix(matrix, args) {
43737      var multiplierX = args[0],
43738          multiplierY = (args.length === 2) ? args[1] : args[0];
43739
43740      matrix[0] = multiplierX;
43741      matrix[3] = multiplierY;
43742    }
43743
43744    function skewXMatrix(matrix, args) {
43745      matrix[2] = args[0];
43746    }
43747
43748    function skewYMatrix(matrix, args) {
43749      matrix[1] = args[0];
43750    }
43751
43752    function translateMatrix(matrix, args) {
43753      matrix[4] = args[0];
43754      if (args.length === 2) {
43755        matrix[5] = args[1];
43756      }
43757    }
43758
43759    // identity matrix
43760    var iMatrix = [
43761          1, // a
43762          0, // b
43763          0, // c
43764          1, // d
43765          0, // e
43766          0  // f
43767        ],
43768
43769        // == begin transform regexp
43770        number = '(?:[-+]?\\d+(?:\\.\\d+)?(?:e[-+]?\\d+)?)',
43771        comma_wsp = '(?:\\s+,?\\s*|,\\s*)',
43772
43773        skewX = '(?:(skewX)\\s*\\(\\s*(' + number + ')\\s*\\))',
43774        skewY = '(?:(skewY)\\s*\\(\\s*(' + number + ')\\s*\\))',
43775        rotate = '(?:(rotate)\\s*\\(\\s*(' + number + ')(?:' + comma_wsp + '(' + number + ')' + comma_wsp + '(' + number + '))?\\s*\\))',
43776        scale = '(?:(scale)\\s*\\(\\s*(' + number + ')(?:' + comma_wsp + '(' + number + '))?\\s*\\))',
43777        translate = '(?:(translate)\\s*\\(\\s*(' + number + ')(?:' + comma_wsp + '(' + number + '))?\\s*\\))',
43778
43779        matrix = '(?:(matrix)\\s*\\(\\s*' +
43780                  '(' + number + ')' + comma_wsp +
43781                  '(' + number + ')' + comma_wsp +
43782                  '(' + number + ')' + comma_wsp +
43783                  '(' + number + ')' + comma_wsp +
43784                  '(' + number + ')' + comma_wsp +
43785                  '(' + number + ')' +
43786                  '\\s*\\))',
43787
43788        transform = '(?:' +
43789                    matrix + '|' +
43790                    translate + '|' +
43791                    scale + '|' +
43792                    rotate + '|' +
43793                    skewX + '|' +
43794                    skewY +
43795                    ')',
43796
43797        transforms = '(?:' + transform + '(?:' + comma_wsp + transform + ')*' + ')',
43798
43799        transform_list = '^\\s*(?:' + transforms + '?)\\s*$',
43800
43801        // http://www.w3.org/TR/SVG/coords.html#TransformAttribute
43802        reTransformList = new RegExp(transform_list),
43803        // == end transform regexp
43804
43805        reTransform = new RegExp(transform, 'g');
43806
43807    return function(attributeValue) {
43808
43809      // start with identity matrix
43810      var matrix = iMatrix.concat();
43811      var matrices = [ ];
43812
43813      // return if no argument was given or
43814      // an argument does not match transform attribute regexp
43815      if (!attributeValue || (attributeValue && !reTransformList.test(attributeValue))) {
43816        return matrix;
43817      }
43818
43819      attributeValue.replace(reTransform, function(match) {
43820
43821        var m = new RegExp(transform).exec(match).filter(function (match) {
43822              return (match !== '' && match != null);
43823            }),
43824            operation = m[1],
43825            args = m.slice(2).map(parseFloat);
43826
43827        switch(operation) {
43828          case 'translate':
43829            translateMatrix(matrix, args);
43830            break;
43831          case 'rotate':
43832            rotateMatrix(matrix, args);
43833            break;
43834          case 'scale':
43835            scaleMatrix(matrix, args);
43836            break;
43837          case 'skewX':
43838            skewXMatrix(matrix, args);
43839            break;
43840          case 'skewY':
43841            skewYMatrix(matrix, args);
43842            break;
43843          case 'matrix':
43844            matrix = args;
43845            break;
43846        }
43847
43848        // snapshot current matrix into matrices array
43849        matrices.push(matrix.concat());
43850        // reset
43851        matrix = iMatrix.concat();
43852      });
43853
43854      var combinedMatrix = matrices[0];
43855      while (matrices.length > 1) {
43856        matrices.shift();
43857        combinedMatrix = fabric.util.multiplyTransformMatrices(combinedMatrix, matrices[0]);
43858      }
43859      return combinedMatrix;
43860    };
43861  })();
43862
43863  /**
43864   * Parses "points" attribute, returning an array of values
43865   * @static
43866   * @memberOf fabric
43867   * @param points {String} points attribute string
43868   * @return {Array} array of points
43869   */
43870  function parsePointsAttribute(points) {
43871
43872    // points attribute is required and must not be empty
43873    if (!points) return null;
43874
43875    points = points.trim();
43876    var asPairs = points.indexOf(',') > -1;
43877
43878    points = points.split(/\s+/);
43879    var parsedPoints = [ ], i, len;
43880
43881    // points could look like "10,20 30,40" or "10 20 30 40"
43882    if (asPairs) {
43883      i = 0;
43884      len = points.length;
43885      for (; i < len; i++) {
43886        var pair = points[i].split(',');
43887        parsedPoints.push({ x: parseFloat(pair[0]), y: parseFloat(pair[1]) });
43888      }
43889    }
43890    else {
43891      i = 0;
43892      len = points.length;
43893      for (; i < len; i+=2) {
43894        parsedPoints.push({ x: parseFloat(points[i]), y: parseFloat(points[i+1]) });
43895      }
43896    }
43897
43898    // odd number of points is an error
43899    if (parsedPoints.length % 2 !== 0) {
43900      // return null;
43901    }
43902
43903    return parsedPoints;
43904  }
43905
43906  function parseFontDeclaration(value, oStyle) {
43907
43908    // TODO: support non-px font size
43909    var match = value.match(/(normal|italic)?\s*(normal|small-caps)?\s*(normal|bold|bolder|lighter|100|200|300|400|500|600|700|800|900)?\s*(\d+)px(?:\/(normal|[\d\.]+))?\s+(.*)/);
43910
43911    if (!match) return;
43912
43913    var fontStyle = match[1];
43914    // Font variant is not used
43915    // var fontVariant = match[2];
43916    var fontWeight = match[3];
43917    var fontSize = match[4];
43918    var lineHeight = match[5];
43919    var fontFamily = match[6];
43920
43921    if (fontStyle) {
43922      oStyle.fontStyle = fontStyle;
43923    }
43924    if (fontWeight) {
43925      oStyle.fontSize = isNaN(parseFloat(fontWeight)) ? fontWeight : parseFloat(fontWeight);
43926    }
43927    if (fontSize) {
43928      oStyle.fontSize = parseFloat(fontSize);
43929    }
43930    if (fontFamily) {
43931      oStyle.fontFamily = fontFamily;
43932    }
43933    if (lineHeight) {
43934      oStyle.lineHeight = lineHeight === 'normal' ? 1 : lineHeight;
43935    }
43936  }
43937
43938  /**
43939   * Parses "style" attribute, retuning an object with values
43940   * @static
43941   * @memberOf fabric
43942   * @param {SVGElement} element Element to parse
43943   * @return {Object} Objects with values parsed from style attribute of an element
43944   */
43945  function parseStyleAttribute(element) {
43946    var oStyle = { },
43947        style = element.getAttribute('style'),
43948        attr, value;
43949
43950    if (!style) return oStyle;
43951
43952    if (typeof style === 'string') {
43953      style.replace(/;$/, '').split(';').forEach(function (chunk) {
43954        var pair = chunk.split(':');
43955
43956        attr = normalizeAttr(pair[0].trim().toLowerCase());
43957        value = normalizeValue(attr, pair[1].trim());
43958
43959        if (attr === 'font') {
43960          parseFontDeclaration(value, oStyle);
43961        }
43962        else {
43963          oStyle[attr] = value;
43964        }
43965      });
43966    }
43967    else {
43968      for (var prop in style) {
43969        if (typeof style[prop] === 'undefined') continue;
43970
43971        attr = normalizeAttr(prop.toLowerCase());
43972        value = normalizeValue(attr, style[prop]);
43973
43974        if (attr === 'font') {
43975          parseFontDeclaration(value, oStyle);
43976        }
43977        else {
43978          oStyle[attr] = value;
43979        }
43980      }
43981    }
43982
43983    return oStyle;
43984  }
43985
43986  function resolveGradients(instances) {
43987    for (var i = instances.length; i--; ) {
43988      var instanceFillValue = instances[i].get('fill');
43989
43990      if (/^url\(/.test(instanceFillValue)) {
43991
43992        var gradientId = instanceFillValue.slice(5, instanceFillValue.length - 1);
43993
43994        if (fabric.gradientDefs[gradientId]) {
43995          instances[i].set('fill',
43996            fabric.Gradient.fromElement(fabric.gradientDefs[gradientId], instances[i]));
43997        }
43998      }
43999    }
44000  }
44001
44002  /**
44003   * Transforms an array of svg elements to corresponding fabric.* 
44003instances
44004   * @static
44005   * @memberOf fabric
44006   * @param {Array} elements Array of elements to parse
44007   * @param {Function} callback Being passed an array of fabric instances (transformed from SVG elements)
44008   * @param {Object} [options] Options object
44009   * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created.
44010   */
44011  function parseElements(elements, callback, options, reviver) {
44012    var instances = new Array(elements.length), i = elements.length;
44013
44014    function checkIfDone() {
44015      if (--i === 0) {
44016        instances = instances.filter(function(el) {
44017          return el != null;
44018        });
44019        resolveGradients(instances);
44020        callback(instances);
44021      }
44022    }
44023
44024    for (var index = 0, el, len = elements.length; index < len; index++) {
44025      el = elements[index];
44026      var klass = fabric[capitalize(el.tagName)];
44027      if (klass && klass.fromElement) {
44028        try {
44029          if (klass.async) {
44030            klass.fromElement(el, (function(index, el) {
44031              return function(obj) {
44032                reviver && reviver(el, obj);
44033                instances.splice(index, 0, obj);
44034                checkIfDone();
44035              };
44036            })(index, el), options);
44037          }
44038          else {
44039            var obj = klass.fromElement(el, options);
44040            reviver && reviver(el, obj);
44041            instances.splice(index, 0, obj);
44042            checkIfDone();
44043          }
44044        }
44045        catch(err) {
44046          fabric.log(err);
44047        }
44048      }
44049      else {
44050        checkIfDone();
44051      }
44052    }
44053  }
44054
44055  /**
44056   * Returns CSS rules for a given SVG document
44057   * @static
44058   * @function
44059   * @memberOf fabric
44060   * @param {SVGDocument} doc SVG document to parse
44061   * @return {Object} CSS rules of this document
44062   */
44063  function getCSSRules(doc) {
44064    var styles = doc.getElementsByTagName('style'),
44065        allRules = { },
44066        rules;
44067
44068    // very crude parsing of style contents
44069    for (var i = 0, len = styles.length; i < len; i++) {
44070      var styleContents = styles[0].textContent;
44071
44072      // remove comments
44073      styleContents = styleContents.replace(/\/\*[\s\S]*?\*\//g, '');
44074
44075      rules = styleContents.match(/[^{]*\{[\s\S]*?\}/g);
44076      rules = rules.map(function(rule) { return rule.trim(); });
44077
44078      rules.forEach(function(rule) {
44079        var match = rule.match(/([\s\S]*?)\s*\{([^}]*)\}/);
44080        rule = match[1];
44081        var declaration = match[2].trim(),
44082            propertyValuePairs = declaration.replace(/;$/, '').split(/\s*;\s*/);
44083
44084        if (!allRules[rule]) {
44085          allRules[rule] = { };
44086        }
44087
44088        for (var i = 0, len = propertyValuePairs.length; i < len; i++) {
44089          var pair = propertyValuePairs[i].split(/\s*:\s*/),
44090              property = pair[0],
44091              value = pair[1];
44092
44093          allRules[rule][property] = value;
44094        }
44095      });
44096    }
44097
44098    return allRules;
44099  }
44100
44101  /**
44102   * @private
44103   */
44104  function getGlobalStylesForElement(element) {
44105    var nodeName = element.nodeName,
44106        className = element.getAttribute('class'),
44107        id = element.getAttribute('id'),
44108        styles = { };
44109
44110    for (var rule in fabric.cssRules) {
44111      var ruleMatchesElement = (className && new RegExp('^\\.' + className).test(rule)) ||
44112                               (id && new RegExp('^#' + id).test(rule)) ||
44113                               (new RegExp('^' + nodeName).test(rule));
44114
44115      if (ruleMatchesElement) {
44116        for (var property in fabric.cssRules[rule]) {
44117          styles[property] = fabric.cssRules[rule][property];
44118        }
44119      }
44120    }
44121
44122    return styles;
44123  }
44124
44125  /**
44126   * Parses an SVG document, converts it to an array of corresponding fabric.* 
44126instances and passes them to a callback
44127   * @static
44128   * @function
44129   * @memberOf fabric
44130   * @param {SVGDocument} doc SVG document to parse
44131   * @param {Function} callback Callback to call when parsing is finished; It's being passed an array of elements (parsed from a document).
44132   * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created.
44133   */
44134  fabric.parseSVGDocument = (function() {
44135
44136    var reAllowedSVGTagNames = /^(path|circle|polygon|polyline|ellipse|rect|line|image|text)$/;
44137
44138    // http://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute
44139    // \d doesn't quite cut it (as we need to match an actual float number)
44140
44141    // matches, e.g.: +14.56e-12, etc.
44142    var reNum = '(?:[-+]?\\d+(?:\\.\\d+)?(?:e[-+]?\\d+)?)';
44143
44144    var reViewBoxAttrValue = new RegExp(
44145      '^' +
44146      '\\s*(' + reNum + '+)\\s*,?' +
44147      '\\s*(' + reNum + '+)\\s*,?' +
44148      '\\s*(' + reNum + '+)\\s*,?' +
44149      '\\s*(' + reNum + '+)\\s*' +
44150      '$'
44151    );
44152
44153    function hasAncestorWithNodeName(element, nodeName) {
44154      while (element && (element = element.parentNode)) {
44155        if (nodeName.test(element.nodeName)) {
44156          return true;
44157        }
44158      }
44159      return false;
44160    }
44161
44162    return function(doc, callback, reviver) {
44163      if (!doc) return;
44164
44165      var startTime = new Date(),
44166          descendants = fabric.util.toArray(doc.getElementsByTagName('*'));
44167
44168      if (descendants.length === 0) {
44169        // we're likely in node, where "o3-xml" library fails to gEBTN("*")
44170        // https://github.com/ajaxorg/node-o3-xml/issues/21
44171        descendants = doc.selectNodes("//*[name(.)!='svg']");
44172        var arr = [ ];
44173        for (var i = 0, len = descendants.length; i < len; i++) {
44174          arr[i] = descendants[i];
44175        }
44176        descendants = arr;
44177      }
44178
44179      var elements = descendants.filter(function(el) {
44180        return reAllowedSVGTagNames.test(el.tagName) &&
44181              !hasAncestorWithNodeName(el, /^(?:pattern|defs)$/); // http://www.w3.org/TR/SVG/struct.html#DefsElement
44182      });
44183
44184      if (!elements || (elements && !elements.length)) return;
44185
44186      var viewBoxAttr = doc.getAttribute('viewBox'),
44187          widthAttr = doc.getAttribute('width'),
44188          heightAttr = doc.getAttribute('height'),
44189          width = null,
44190          height = null,
44191          minX,
44192          minY;
44193
44194      if (viewBoxAttr && (viewBoxAttr = viewBoxAttr.match(reViewBoxAttrValue))) {
44195        minX = parseInt(viewBoxAttr[1], 10);
44196        minY = parseInt(viewBoxAttr[2], 10);
44197        width = parseInt(viewBoxAttr[3], 10);
44198        height = parseInt(viewBoxAttr[4], 10);
44199      }
44200
44201      // values of width/height attributes overwrite those extracted from viewbox attribute
44202      width = widthAttr ? parseFloat(widthAttr) : width;
44203      height = heightAttr ? parseFloat(heightAttr) : height;
44204
44205      var options = {
44206        width: width,
44207        height: height
44208      };
44209
44210      fabric.gradientDefs = fabric.getGradientDefs(doc);
44211      fabric.cssRules = getCSSRules(doc);
44212
44213      // Precedence of rules:   style > class > attribute
44214
44215      fabric.parseElements(elements, function(instances) {
44216        fabric.documentParsingTime = new Date() - startTime;
44217        if (callback) {
44218          callback(instances, options);
44219        }
44220      }, clone(options), reviver);
44221    };
44222  })();
44223
44224   /**
44225    * Used for caching SVG documents (loaded via `fabric.Canvas#loadSVGFromURL`)
44226    * @namespace
44227    */
44228   var svgCache = {
44229
44230     /**
44231      * @param {String} name
44232      * @param {Function} callback
44233      */
44234     has: function (name, callback) {
44235       callback(false);
44236     },
44237
44238     /**
44239      * @param {String} url
44240      * @param {Function} callback
44241      */
44242     get: function () {
44243       /* NOOP */
44244     },
44245
44246     /**
44247      * @param {String} url
44248      * @param {Object} object
44249      */
44250     set: function () {
44251       /* NOOP */
44252     }
44253   };
44254
44255   /**
44256    * Takes url corresponding to an SVG document, and parses it into a set of fabric objects. Note that SVG is fetched via XMLHttpRequest, so it needs to conform to SOP (Same Origin Policy)
44257    * @memberof fabric
44258    * @param {String} url
44259    * @param {Function} callback
44260    * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created.
44261    */
44262   function loadSVGFromURL(url, callback, reviver) {
44263
44264     url = url.replace(/^\n\s*/, '').trim();
44265
44266     svgCache.has(url, function (hasUrl) {
44267       if (hasUrl) {
44268         svgCache.get(url, function (value) {
44269           var enlivedRecord = _enlivenCachedObject(value);
44270           callback(enlivedRecord.objects, enlivedRecord.options);
44271         });
44272       }
44273       else {
44274         new fabric.util.request(url, {
44275           method: 'get',
44276           onComplete: onComplete
44277         });
44278       }
44279     });
44280
44281     function onComplete(r) {
44282
44283       var xml = r.responseXML;
44284       if (!xml.documentElement && fabric.window.ActiveXObject && r.responseText) {
44285         xml = new ActiveXObject('Microsoft.XMLDOM');
44286         xml.async = 'false';
44287         //IE chokes on DOCTYPE
44288         xml.loadXML(r.responseText.replace(/<!DOCTYPE[\s\S]*?(\[[\s\S]*\])*?>/i,''));
44289       }
44290       if (!xml.documentElement) return;
44291
44292       fabric.parseSVGDocument(xml.documentElement, function (results, options) {
44293         svgCache.set(url, {
44294           objects: fabric.util.array.invoke(results, 'toObject'),
44295           options: options
44296         });
44297         callback(results, options);
44298       }, reviver);
44299     }
44300   }
44301
44302  /**
44303   * @private
44304   */
44305  function _enlivenCachedObject(cachedObject) {
44306
44307   var objects = cachedObject.objects,
44308       options = cachedObject.options;
44309
44310   objects = objects.map(function (o) {
44311     return fabric[capitalize(o.type)].fromObject(o);
44312   });
44313
44314   return ({ objects: objects, options: options });
44315  }
44316
44317  /**
44318    * Takes string corresponding to an SVG document, and parses it into a set of fabric objects
44319    * @memberof fabric
44320    * @param {String} string
44321    * @param {Function} callback
44322    * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created.
44323    */
44324  function loadSVGFromString(string, callback, reviver) {
44325    string = string.trim();
44326    var doc;
44327    if (typeof DOMParser !== 'undefined') {
44328      var parser = new DOMParser();
44329      if (parser && parser.parseFromString) {
44330        doc = parser.parseFromString(string, 'text/xml');
44331      }
44332    }
44333    else if (fabric.window.ActiveXObject) {
44334      doc = new ActiveXObject('Microsoft.XMLDOM');
44335      doc.async = 'false';
44336      //IE chokes on DOCTYPE
44337      doc.loadXML(string.replace(/<!DOCTYPE[\s\S]*?(\[[\s\S]*\])*?>/i,''));
44338    }
44339
44340    fabric.parseSVGDocument(doc.documentElement, function (results, options) {
44341      callback(results, options);
44342    }, reviver);
44343  }
44344
44345  /**
44346   * Creates markup containing SVG font faces
44347   * @param {Array} objects Array of fabric objects
44348   * @return {String}
44349   */
44350  function createSVGFontFacesMarkup(objects) {
44351    var markup = '';
44352
44353    for (var i = 0, len = objects.length; i < len; i++) {
44354      if (objects[i].type !== 'text' || !objects[i].path) continue;
44355
44356      markup += [
44357        '@font-face {',
44358          'font-family: ', objects[i].fontFamily, '; ',
44359          'src: url(\'', objects[i].path, '\')',
44360        '}'
44361      ].join('');
44362    }
44363
44364    if (markup) {
44365      markup = [
44366        '<style type="text/css">',
44367          '<![CDATA[',
44368            markup,
44369          ']]>',
44370        '</style>'
44371      ].join('');
44372    }
44373
44374    return markup;
44375  }
44376
44377  /**
44378   * Creates markup containing SVG referenced elements like patterns, gradients etc.
44379   * @param {fabric.Canvas} canvas instance of fabric.Canvas
44380   * @return {String}
44381   */
44382  function createSVGRefElementsMarkup(canvas) {
44383    var markup = '';
44384
44385    if (canvas.backgroundColor && canvas.backgroundColor.source) {
44386      markup = [
44387        '<pattern x="0" y="0" id="backgroundColorPattern" ',
44388          'width="', canvas.backgroundColor.source.width,
44389          '" height="', canvas.backgroundColor.source.height,
44390          '" patternUnits="userSpaceOnUse">',
44391        '<image x="0" y="0" ',
44392        'width="', canvas.backgroundColor.source.width,
44393        '" height="', canvas.backgroundColor.source.height,
44394        '" xlink:href="', canvas.backgroundColor.source.src,
44395        '"></image></pattern>'
44396      ].join('');
44397    }
44398
44399    return markup;
44400  }
44401
44402  /**
44403   * Parses an SVG document, returning all of the gradient declarations found in it
44404   * @static
44405   * @function
44406   * @memberOf fabric
44407   * @param {SVGDocument} doc SVG document to parse
44408   * @return {Object} Gradient definitions; key corresponds to element id, value -- to gradient definition element
44409   */
44410  function getGradientDefs(doc) {
44411    var linearGradientEls = doc.getElementsByTagName('linearGradient'),
44412        radialGradientEls = doc.getElementsByTagName('radialGradient'),
44413        el, i,
44414        gradientDefs = { };
44415
44416    i = linearGradientEls.length;
44417    for (; i--; ) {
44418      el = linearGradientEls[i];
44419      gradientDefs[el.getAttribute('id')] = el;
44420    }
44421
44422    i = radialGradientEls.length;
44423    for (; i--; ) {
44424      el = radialGradientEls[i];
44425      gradientDefs[el.getAttribute('id')] = el;
44426    }
44427
44428    return gradientDefs;
44429  }
44430
44431  extend(fabric, {
44432
44433    parseAttributes:            parseAttributes,
44434    parseElements:              parseElements,
44435    parseStyleAttribute:        parseStyleAttribute,
44436    parsePointsAttribute:       parsePointsAttribute,
44437    getCSSRules:                getCSSRules,
44438
44439    loadSVGFromURL:             loadSVGFromURL,
44440    loadSVGFromString:          loadSVGFromString,
44441
44442    createSVGFontFacesMarkup:   createSVGFontFacesMarkup,
44443    createSVGRefElementsMarkup: createSVGRefElementsMarkup,
44444
44445    getGradientDefs:            getGradientDefs
44446  });
44447
44448})(typeof exports !== 'undefined' ? exports : this);
44449
44450
44451(function(global) {
44452
44453  "use strict";
44454
44455  /* Adaptation of work of Kevin Lindsey ([email protected]) */
44456
44457  var fabric = global.fabric || (global.fabric = { });
44458
44459  if (fabric.Point) {
44460    fabric.warn('fabric.Point is already defined');
44461    return;
44462  }
44463
44464  fabric.Point = Point;
44465
44466  /**
44467   * Point class
44468   * @class fabric.Point
44469   * @memberOf fabric
44470   * @constructor
44471   * @param {Number} x
44472   * @param {Number} y
44473   * @return {fabric.Point} thisArg
44474   */
44475  function Point(x, y) {
44476    this.x = x;
44477    this.y = y;
44478  }
44479
44480  Point.prototype = /** @lends fabric.Point.prototype */ {
44481
44482    constructor: Point,
44483
44484    /**
44485     * Adds another point to this one and returns another one
44486     * @param {fabric.Point} that
44487     * @return {fabric.Point} new Point instance with added values
44488     */
44489    add: function (that) {
44490      return new Point(this.x + that.x, this.y + that.y);
44491    },
44492
44493    /**
44494     * Adds another point to this one
44495     * @param {fabric.Point} that
44496     * @return {fabric.Point} thisArg
44497     */
44498    addEquals: function (that) {
44499      this.x += that.x;
44500      this.y += that.y;
44501      return this;
44502    },
44503
44504    /**
44505     * Adds value to this point and returns a new one
44506     * @param {Number} scalar
44507     * @return {fabric.Point} new Point with added value
44508     */
44509    scalarAdd: function (scalar) {
44510      return new Point(this.x + scalar, this.y + scalar);
44511    },
44512
44513    /**
44514     * Adds value to this point
44515     * @param {Number} scalar
44516     * @param {fabric.Point} thisArg
44517     */
44518    scalarAddEquals: function (scalar) {
44519      this.x += scalar;
44520      this.y += scalar;
44521      return this;
44522    },
44523
44524    /**
44525     * Subtracts another point from this point and returns a new one
44526     * @param {fabric.Point} that
44527     * @return {fabric.Point} new Point object with subtracted values
44528     */
44529    subtract: function (that) {
44530      return new Point(this.x - that.x, this.y - that.y);
44531    },
44532
44533    /**
44534     * Subtracts another point from this point
44535     * @param {fabric.Point} that
44536     * @return {fabric.Point} thisArg
44537     */
44538    subtractEquals: function (that) {
44539      this.x -= that.x;
44540      this.y -= that.y;
44541      return this;
44542    },
44543
44544    /**
44545     * Subtracts value from this point and returns a new one
44546     * @param {Number} scalar
44547     * @return {fabric.Point}
44548     */
44549    scalarSubtract: function (scalar) {
44550      return new Point(this.x - scalar, this.y - scalar);
44551    },
44552
44553    /**
44554     * Subtracts value from this point
44555     * @param {Number} scalar
44556     * @return {fabric.Point} thisArg
44557     */
44558    scalarSubtractEquals: function (scalar) {
44559      this.x -= scalar;
44560      this.y -= scalar;
44561      return this;
44562    },
44563
44564    /**
vendor: 19,368 bytes, lines 44565-45278
44565     * Miltiplies this point by a value and returns a new one
44566     * @param {Number} scalar
44567     * @return {fabric.Point}
44568     */
44569    multiply: function (scalar) {
44570      return new Point(this.x * scalar, this.y * scalar);
44571    },
44572
44573    /**
44574     * Miltiplies this point by a value
44575     * @param {Number} scalar
44576     * @return {fabric.Point} thisArg
44577     */
44578    multiplyEquals: function (scalar) {
44579      this.x *= scalar;
44580      this.y *= scalar;
44581      return this;
44582    },
44583
44584    /**
44585     * Divides this point by a value and returns a new one
44586     * @param {Number} scalar
44587     * @return {fabric.Point}
44588     */
44589    divide: function (scalar) {
44590      return new Point(this.x / scalar, this.y / scalar);
44591    },
44592
44593    /**
44594     * Divides this point by a value
44595     * @param {Number} scalar
44596     * @return {fabric.Point} thisArg
44597     */
44598    divideEquals: function (scalar) {
44599      this.x /= scalar;
44600      this.y /= scalar;
44601      return this;
44602    },
44603
44604    /**
44605     * Returns true if this point is equal to another one
44606     * @param {fabric.Point} that
44607     * @return {Boolean}
44608     */
44609    eq: function (that) {
44610      return (this.x === that.x && this.y === that.y);
44611    },
44612
44613    /**
44614     * Returns true if this point is less than another one
44615     * @param {fabric.Point} that
44616     * @return {Boolean}
44617     */
44618    lt: function (that) {
44619      return (this.x < that.x && this.y < that.y);
44620    },
44621
44622    /**
44623     * Returns true if this point is less than or equal to another one
44624     * @param {fabric.Point} that
44625     * @return {Boolean}
44626     */
44627    lte: function (that) {
44628      return (this.x <= that.x && this.y <= that.y);
44629    },
44630
44631    /**
44632
44633     * Returns true if this point is greater another one
44634     * @param {fabric.Point} that
44635     * @return {Boolean}
44636     */
44637    gt: function (that) {
44638      return (this.x > that.x && this.y > that.y);
44639    },
44640
44641    /**
44642     * Returns true if this point is greater than or equal to another one
44643     * @param {fabric.Point} that
44644     * @return {Boolean}
44645     */
44646    gte: function (that) {
44647      return (this.x >= that.x && this.y >= that.y);
44648    },
44649
44650    /**
44651     * Returns new point which is the result of linear interpolation with this one and another one
44652     * @param {fabric.Point} that
44653     * @param {Number} t
44654     * @return {fabric.Point}
44655     */
44656    lerp: function (that, t) {
44657      return new Point(this.x + (that.x - this.x) * t, this.y + (that.y - this.y) * t);
44658    },
44659
44660    /**
44661     * Returns distance from this point and another one
44662     * @param {fabric.Point} that
44663     * @return {Number}
44664     */
44665    distanceFrom: function (that) {
44666      var dx = this.x - that.x,
44667          dy = this.y - that.y;
44668      return Math.sqrt(dx * dx + dy * dy);
44669    },
44670
44671    /**
44672     * Returns the point between this point and another one
44673     * @param {fabric.Point} that
44674     * @return {fabric.Point}
44675     */
44676    midPointFrom: function (that) {
44677      return new Point(this.x + (that.x - this.x)/2, this.y + (that.y - this.y)/2);
44678    },
44679
44680    /**
44681     * Returns a new point which is the min of this and another one
44682     * @param {fabric.Point} that
44683     * @return {fabric.Point}
44684     */
44685    min: function (that) {
44686      return new Point(Math.min(this.x, that.x), Math.min(this.y, that.y));
44687    },
44688
44689    /**
44690     * Returns a new point which is the max of this and another one
44691     * @param {fabric.Point} that
44692     * @return {fabric.Point}
44693     */
44694    max: function (that) {
44695      return new Point(Math.max(this.x, that.x), Math.max(this.y, that.y));
44696    },
44697
44698    /**
44699     * Returns string representation of this point
44700     * @return {String}
44701     */
44702    toString: function () {
44703      return this.x + "," + this.y;
44704    },
44705
44706    /**
44707     * Sets x/y of this point
44708     * @param {Number} x
44709     * @return {Number} y
44710     */
44711    setXY: function (x, y) {
44712      this.x = x;
44713      this.y = y;
44714    },
44715
44716    /**
44717     * Sets x/y of this point from another point
44718     * @param {fabric.Point} that
44719     */
44720    setFromPoint: function (that) {
44721      this.x = that.x;
44722      this.y = that.y;
44723    },
44724
44725    /**
44726     * Swaps x/y of this point and another point
44727     * @param {fabric.Point} that
44728     */
44729    swap: function (that) {
44730      var x = this.x,
44731          y = this.y;
44732      this.x = that.x;
44733      this.y = that.y;
44734      that.x = x;
44735      that.y = y;
44736    }
44737  };
44738
44739})(typeof exports !== 'undefined' ? exports : this);
44740
44741
44742(function(global) {
44743
44744  "use strict";
44745
44746  /* Adaptation of work of Kevin Lindsey ([email protected]) */
44747
44748  var fabric = global.fabric || (global.fabric = { });
44749
44750  if (fabric.Intersection) {
44751    fabric.warn('fabric.Intersection is already defined');
44752    return;
44753  }
44754
44755  /**
44756   * Intersection class
44757   * @class fabric.Intersection
44758   * @memberOf fabric
44759   * @constructor
44760   */
44761  function Intersection(status) {
44762    this.status = status;
44763    this.points = [];
44764  }
44765
44766  fabric.Intersection = Intersection;
44767
44768  fabric.Intersection.prototype = /** @lends fabric.Intersection.prototype */ {
44769
44770    /**
44771     * Appends a point to intersection
44772     * @param {fabric.Point} point
44773     */
44774    appendPoint: function (point) {
44775      this.points.push(point);
44776    },
44777
44778    /**
44779     * Appends points to intersection
44780     * @param {Array} points
44781     */
44782    appendPoints: function (points) {
44783      this.points = this.points.concat(points);
44784    }
44785  };
44786
44787  /**
44788   * Checks if one line intersects another
44789   * @static
44790   * @param {fabric.Point} a1
44791   * @param {fabric.Point} a2
44792   * @param {fabric.Point} b1
44793   * @param {fabric.Point} b2
44794   * @return {fabric.Intersection}
44795   */
44796  fabric.Intersection.intersectLineLine = function (a1, a2, b1, b2) {
44797    var result,
44798        ua_t = (b2.x - b1.x) * (a1.y - b1.y) - (b2.y - b1.y) * (a1.x - b1.x),
44799        ub_t = (a2.x - a1.x) * (a1.y - b1.y) - (a2.y - a1.y) * (a1.x - b1.x),
44800        u_b = (b2.y - b1.y) * (a2.x - a1.x) - (b2.x - b1.x) * (a2.y - a1.y);
44801    if (u_b !== 0) {
44802      var ua = ua_t / u_b,
44803          ub = ub_t / u_b;
44804      if (0 <= ua && ua <= 1 && 0 <= ub && ub <= 1) {
44805        result = new Intersection("Intersection");
44806        result.points.push(new fabric.Point(a1.x + ua * (a2.x - a1.x), a1.y + ua * (a2.y - a1.y)));
44807      }
44808      else {
44809        result = new Intersection();
44810      }
44811    }
44812    else {
44813      if (ua_t === 0 || ub_t === 0) {
44814        result = new Intersection("Coincident");
44815      }
44816      else {
44817        result = new Intersection("Parallel");
44818      }
44819    }
44820    return result;
44821  };
44822
44823  /**
44824   * Checks if line intersects polygon
44825   * @static
44826   * @param {fabric.Point} a1
44827   * @param {fabric.Point} a2
44828   * @param {Array} points
44829   * @return {fabric.Intersection}
44830   */
44831  fabric.Intersection.intersectLinePolygon = function(a1,a2,points){
44832    var result = new Intersection(),
44833        length = points.length;
44834
44835    for (var i = 0; i < length; i++) {
44836      var b1 = points[i],
44837          b2 = points[(i+1) % length],
44838          inter = Intersection.intersectLineLine(a1, a2, b1, b2);
44839
44840      result.appendPoints(inter.points);
44841    }
44842    if (result.points.length > 0) {
44843      result.status = "Intersection";
44844    }
44845    return result;
44846  };
44847
44848  /**
44849   * Checks if polygon intersects another polygon
44850   * @static
44851   * @param {Array} points1
44852   * @param {Array} points2
44853   * @return {fabric.Intersection}
44854   */
44855  fabric.Intersection.intersectPolygonPolygon = function (points1, points2) {
44856    var result = new Intersection(),
44857        length = points1.length;
44858
44859    for (var i = 0; i < length; i++) {
44860      var a1 = points1[i],
44861          a2 = points1[(i+1) % length],
44862          inter = Intersection.intersectLinePolygon(a1, a2, points2);
44863
44864      result.appendPoints(inter.points);
44865    }
44866    if (result.points.length > 0) {
44867      result.status = "Intersection";
44868    }
44869    return result;
44870  };
44871
44872  /**
44873   * Checks if polygon intersects rectangle
44874   * @static
44875   * @param {Array} points
44876   * @param {Number} r1
44877   * @param {Number} r2
44878   * @return {fabric.Intersection}
44879   */
44880  fabric.Intersection.intersectPolygonRectangle = function (points, r1, r2) {
44881    var min = r1.min(r2),
44882        max = r1.max(r2),
44883        topRight = new fabric.Point(max.x, min.y),
44884        bottomLeft = new fabric.Point(min.x, max.y),
44885        inter1 = Intersection.intersectLinePolygon(min, topRight, points),
44886        inter2 = Intersection.intersectLinePolygon(topRight, max, points),
44887        inter3 = Intersection.intersectLinePolygon(max, bottomLeft, points),
44888        inter4 = Intersection.intersectLinePolygon(bottomLeft, min, points),
44889        result = new Intersection();
44890
44891    result.appendPoints(inter1.points);
44892    result.appendPoints(inter2.points);
44893    result.appendPoints(inter3.points);
44894    result.appendPoints(inter4.points);
44895
44896    if (result.points.length > 0) {
44897      result.status = "Intersection";
44898    }
44899    return result;
44900  };
44901
44902})(typeof exports !== 'undefined' ? exports : this);
44903
44904
44905(function(global) {
44906
44907  "use strict";
44908
44909  var fabric = global.fabric || (global.fabric = { });
44910
44911  if (fabric.Color) {
44912    fabric.warn('fabric.Color is already defined.');
44913    return;
44914  }
44915
44916  /**
44917   * Color class
44918   * The purpose of {@link fabric.Color} is to abstract and encapsulate common color operations;
44919   * {@link fabric.Color} is a constructor and creates instances of {@link fabric.Color} objects.
44920   *
44921   * @class fabric.Color
44922   * @param {String} color optional in hex or rgb(a) format
44923   * @return {fabric.Color} thisArg
44924   * @tutorial {@link http://fabricjs.com/fabric-intro-part-2/#colors}
44925   */
44926  function Color(color) {
44927    if (!color) {
44928      this.setSource([0, 0, 0, 1]);
44929    }
44930    else {
44931      this._tryParsingColor(color);
44932    }
44933  }
44934
44935  fabric.Color = Color;
44936
44937  fabric.Color.prototype = /** @lends fabric.Color.prototype */ {
44938
44939    /**
44940     * @private
44941     * @param {String|Array} color Color value to parse
44942     */
44943    _tryParsingColor: function(color) {
44944      var source;
44945
44946      if (color in Color.colorNameMap) {
44947        color = Color.colorNameMap[color];
44948      }
44949
44950      source = Color.sourceFromHex(color);
44951
44952      if (!source) {
44953        source = Color.sourceFromRgb(color);
44954      }
44955      if (!source) {
44956        source = Color.sourceFromHsl(color);
44957      }
44958      if (source) {
44959        this.setSource(source);
44960      }
44961    },
44962
44963    /**
44964     * Adapted from <a href="https://rawgithub.com/mjijackson/mjijackson.github.com/master/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript.html">https://github.com/mjijackson</a>
44965     * @private
44966     * @param {Number} r Red color value
44967     * @param {Number} g Green color value
44968     * @param {Number} b Blue color value
44969     * @return {Array} Hsl color
44970     */
44971    _rgbToHsl: function(r, g, b) {
44972      r /= 255, g /= 255, b /= 255;
44973
44974      var h, s, l,
44975          max = fabric.util.array.max([r, g, b]),
44976          min = fabric.util.array.min([r, g, b]);
44977
44978      l = (max + min) / 2;
44979
44980      if (max === min) {
44981        h = s = 0; // achromatic
44982      }
44983      else {
44984        var d = max - min;
44985        s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
44986        switch (max) {
44987          case r:
44988            h = (g - b) / d + (g < b ? 6 : 0);
44989            break;
44990          case g:
44991            h = (b - r) / d + 2;
44992            break;
44993          case b:
44994            h = (r - g) / d + 4;
44995            break;
44996        }
44997        h /= 6;
44998      }
44999
45000      return [
45001        Math.round(h * 360),
45002        Math.round(s * 100),
45003        Math.round(l * 100)
45004      ];
45005    },
45006
45007    /**
45008     * Returns source of this color (where source is an array representation; ex: [200, 200, 100, 1])
45009     * @return {Array}
45010     */
45011    getSource: function() {
45012      return this._source;
45013    },
45014
45015    /**
45016     * Sets source of this color (where source is an array representation; ex: [200, 200, 100, 1])
45017     * @param {Array} source
45018     */
45019    setSource: function(source) {
45020      this._source = source;
45021    },
45022
45023    /**
45024     * Returns color represenation in RGB format
45025     * @return {String} ex: rgb(0-255,0-255,0-255)
45026     */
45027    toRgb: function() {
45028      var source = this.getSource();
45029      return 'rgb(' + source[0] + ',' + source[1] + ',' + source[2] + ')';
45030    },
45031
45032    /**
45033     * Returns color represenation in RGBA format
45034     * @return {String} ex: rgba(0-255,0-255,0-255,0-1)
45035     */
45036    toRgba: function() {
45037      var source = this.getSource();
45038      return 'rgba(' + source[0] + ',' + source[1] + ',' + source[2] + ',' + source[3] + ')';
45039    },
45040
45041    /**
45042     * Returns color represenation in HSL format
45043     * @return {String} ex: hsl(0-360,0%-100%,0%-100%)
45044     */
45045    toHsl: function() {
45046      var source = this.getSource(),
45047          hsl = this._rgbToHsl(source[0], source[1], source[2]);
45048
45049      return 'hsl(' + hsl[0] + ',' + hsl[1] + '%,' + hsl[2] + '%)';
45050    },
45051
45052    /**
45053     * Returns color represenation in HSLA format
45054     * @return {String} ex: hsla(0-360,0%-100%,0%-100%,0-1)
45055     */
45056    toHsla: function() {
45057      var source = this.getSource(),
45058          hsl = this._rgbToHsl(source[0], source[1], source[2]);
45059
45060      return 'hsla(' + hsl[0] + ',' + hsl[1] + '%,' + hsl[2] + '%,' + source[3] + ')';
45061    },
45062
45063    /**
45064     * Returns color represenation in HEX format
45065     * @return {String} ex: FF5555
45066     */
45067    toHex: function() {
45068      var source = this.getSource();
45069
45070      var r = source[0].toString(16);
45071      r = (r.length === 1) ? ('0' + r) : r;
45072
45073      var g = source[1].toString(16);
45074      g = (g.length === 1) ? ('0' + g) : g;
45075
45076      var b = source[2].toString(16);
45077      b = (b.length === 1) ? ('0' + b) : b;
45078
45079      return r.toUpperCase() + g.toUpperCase() + b.toUpperCase();
45080    },
45081
45082    /**
45083     * Gets value of alpha channel for this color
45084     * @return {Number} 0-1
45085     */
45086    getAlpha: function() {
45087      return this.getSource()[3];
45088    },
45089
45090    /**
45091     * Sets value of alpha channel for this color
45092     * @param {Number} alpha Alpha value 0-1
45093     * @return {fabric.Color} thisArg
45094     */
45095    setAlpha: function(alpha) {
45096      var source = this.getSource();
45097      source[3] = alpha;
45098      this.setSource(source);
45099      return this;
45100    },
45101
45102    /**
45103     * Transforms color to its grayscale representation
45104     * @return {fabric.Color} thisArg
45105     */
45106    toGrayscale: function() {
45107      var source = this.getSource(),
45108          average = parseInt((source[0] * 0.3 + source[1] * 0.59 + source[2] * 0.11).toFixed(0), 10),
45109          currentAlpha = source[3];
45110      this.setSource([average, average, average, currentAlpha]);
45111      return this;
45112    },
45113
45114    /**
45115     * Transforms color to its black and white representation
45116     * @param {Number} threshold
45117     * @return {fabric.Color} thisArg
45118     */
45119    toBlackWhite: function(threshold) {
45120      var source = this.getSource(),
45121          average = (source[0] * 0.3 + source[1] * 0.59 + source[2] * 0.11).toFixed(0),
45122          currentAlpha = source[3];
45123
45124      threshold = threshold || 127;
45125
45126      average = (Number(average) < Number(threshold)) ? 0 : 255;
45127      this.setSource([average, average, average, currentAlpha]);
45128      return this;
45129    },
45130
45131    /**
45132     * Overlays color with another color
45133     * @param {String|fabric.Color} otherColor
45134     * @return {fabric.Color} thisArg
45135     */
45136    overlayWith: function(otherColor) {
45137      if (!(otherColor instanceof Color)) {
45138        otherColor = new Color(otherColor);
45139      }
45140
45141      var result = [],
45142          alpha = this.getAlpha(),
45143          otherAlpha = 0.5,
45144          source = this.getSource(),
45145          otherSource = otherColor.getSource();
45146
45147      for (var i = 0; i < 3; i++) {
45148        result.push(Math.round((source[i] * (1 - otherAlpha)) + (otherSource[i] * otherAlpha)));
45149      }
45150
45151      result[3] = alpha;
45152      this.setSource(result);
45153      return this;
45154    }
45155  };
45156
45157  /**
45158   * Regex matching color in RGB or RGBA formats (ex: rgb(0, 0, 0), rgba(255, 100, 10, 0.5), rgba( 255 , 100 , 10 , 0.5 ), rgb(1,1,1), rgba(100%, 60%, 10%, 0.5))
45159   * @static
45160   * @field
45161   * @memberOf fabric.Color
45162   */
45163  fabric.Color.reRGBa = /^rgba?\(\s*(\d{1,3}\%?)\s*,\s*(\d{1,3}\%?)\s*,\s*(\d{1,3}\%?)\s*(?:\s*,\s*(\d+(?:\.\d+)?)\s*)?\)$/;
45164
45165  /**
45166   * Regex matching color in HSL or HSLA formats (ex: hsl(200, 80%, 10%), hsla(300, 50%, 80%, 0.5), hsla( 300 , 50% , 80% , 0.5 ))
45167   * @static
45168   * @field
45169   * @memberOf fabric.Color
45170   */
45171  fabric.Color.reHSLa = /^hsla?\(\s*(\d{1,3})\s*,\s*(\d{1,3}\%)\s*,\s*(\d{1,3}\%)\s*(?:\s*,\s*(\d+(?:\.\d+)?)\s*)?\)$/;
45172
45173  /**
45174   * Regex matching color in HEX format (ex: #FF5555, 010155, aff)
45175   * @static
45176   * @field
45177   * @memberOf fabric.Color
45178   */
45179  fabric.Color.reHex = /^#?([0-9a-f]{6}|[0-9a-f]{3})$/i;
45180
45181  /**
45182   * Map of the 17 basic color names with HEX code
45183   * @static
45184   * @field
45185   * @memberOf fabric.Color
45186   * @see: http://www.w3.org/TR/CSS2/syndata.html#color-units
45187   */
45188  fabric.Color.colorNameMap = {
45189    'aqua':    '#00FFFF',
45190    'black':   '#000000',
45191    'blue':    '#0000FF',
45192    'fuchsia': '#FF00FF',
45193    'gray':    '#808080',
45194    'green':   '#008000',
45195    'lime':    '#00FF00',
45196    'maroon':  '#800000',
45197    'navy':    '#000080',
45198    'olive':   '#808000',
45199    'orange':  '#FFA500',
45200    'purple':  '#800080',
45201    'red':     '#FF0000',
45202    'silver':  '#C0C0C0',
45203    'teal':    '#008080',
45204    'white':   '#FFFFFF',
45205    'yellow':  '#FFFF00'
45206  };
45207
45208  /**
45209   * @private
45210   * @param {Number} p
45211   * @param {Number} q
45212   * @param {Number} t
45213   * @return {Number}
45214   */
45215  function hue2rgb(p, q, t){
45216    if (t < 0) t += 1;
45217    if (t > 1) t -= 1;
45218    if (t < 1/6) return p + (q - p) * 6 * t;
45219    if (t < 1/2) return q;
45220    if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
45221    return p;
45222  }
45223
45224  /**
45225   * Returns new color object, when given a color in RGB format
45226   * @memberOf fabric.Color
45227   * @param {String} color Color value ex: rgb(0-255,0-255,0-255)
45228   * @return {fabric.Color}
45229   */
45230  fabric.Color.fromRgb = function(color) {
45231    return Color.fromSource(Color.sourceFromRgb(color));
45232  };
45233
45234  /**
45235   * Returns array represenatation (ex: [100, 100, 200, 1]) of a color that's in RGB or RGBA format
45236   * @memberOf fabric.Color
45237   * @param {String} color Color value ex: rgb(0-255,0-255,0-255), rgb(0%-100%,0%-100%,0%-100%)
45238   * @return {Array} source
45239   */
45240  fabric.Color.sourceFromRgb = function(color) {
45241    var match = color.match(Color.reRGBa);
45242    if (match) {
45243      var r = parseInt(match[1], 10) / (/%$/.test(match[1]) ? 100 : 1) * (/%$/.test(match[1]) ? 255 : 1),
45244          g = parseInt(match[2], 10) / (/%$/.test(match[2]) ? 100 : 1) * (/%$/.test(match[2]) ? 255 : 1),
45245          b = parseInt(match[3], 10) / (/%$/.test(match[3]) ? 100 : 1) * (/%$/.test(match[3]) ? 255 : 1);
45246
45247      return [
45248        parseInt(r, 10),
45249        parseInt(g, 10),
45250        parseInt(b, 10),
45251        match[4] ? parseFloat(match[4]) : 1
45252      ];
45253    }
45254  };
45255
45256  /**
45257   * Returns new color object, when given a color in RGBA format
45258   * @static
45259   * @function
45260   * @memberOf fabric.Color
45261   * @param {String} color
45262   * @return {fabric.Color}
45263   */
45264  fabric.Color.fromRgba = Color.fromRgb;
45265
45266  /**
45267   * Returns new color object, when given a color in HSL format
45268   * @param {String} color Color value ex: hsl(0-260,0%-100%,0%-100%)
45269   * @memberOf fabric.Color
45270   * @return {fabric.Color}
45271   */
45272  fabric.Color.fromHsl = function(color) {
45273    return Color.fromSource(Color.sourceFromHsl(color));
45274  };
45275
45276  /**
45277   * Returns array represenatation (ex: [100, 100, 200, 1]) of a color that's in HSL or HSLA format.
45278   * Adapted from <a href="https://rawgithub.com/mjijackson/mjijackson.github.com/master/2008/02/rgb-to-hsl-
45278and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript.html">https://github.com/mjijackson</a>
45279   * @memberOf fabric.Color
45280   * @param {String} color Color value ex: hsl(0-360,0%-100%,0%-100%) or hsla(0-360,0%-100%,0%-100%, 0-1)
45281   * @return {Array} source
45282   * @see http://http://www.w3.org/TR/css3-color/#hsl-color
45283   */
45284  fabric.Color.sourceFromHsl = function(color) {
45285    var match = color.match(Color.reHSLa);
45286    if (!match) return;
45287
45288    var h = (((parseFloat(match[1]) % 360) + 360) % 360) / 360,
45289        s = parseFloat(match[2]) / (/%$/.test(match[2]) ? 100 : 1),
45290        l = parseFloat(match[3]) / (/%$/.test(match[3]) ? 100 : 1),
45291        r, g, b;
45292
45293    if (s === 0) {
45294      r = g = b = l;
45295    }
45296    else {
45297      var q = l <= 0.5 ? l * (s + 1) : l + s - l * s;
45298      var p = l * 2 - q;
45299
45300      r = hue2rgb(p, q, h + 1/3);
45301      g = hue2rgb(p, q, h);
45302      b = hue2rgb(p, q, h - 1/3);
45303    }
45304
45305    return [
45306      Math.round(r * 255),
45307      Math.round(g * 255),
45308      Math.round(b * 255),
45309      match[4] ? parseFloat(match[4]) : 1
45310    ];
45311  };
45312
45313  /**
45314   * Returns new color object, when given a color in HSLA format
45315   * @static
45316   * @function
45317   * @memberOf fabric.Color
45318   * @param {String} color
45319   * @return {fabric.Color}
45320   */
45321  fabric.Color.fromHsla = Color.fromHsl;
45322
45323  /**
45324   * Returns new color object, when given a color in HEX format
45325   * @static
45326   * @memberOf fabric.Color
45327   * @param {String} color Color value ex: FF5555
45328   * @return {fabric.Color}
45329   */
45330  fabric.Color.fromHex = function(color) {
45331    return Color.fromSource(Color.sourceFromHex(color));
45332  };
45333
45334  /**
45335   * Returns array represenatation (ex: [100, 100, 200, 1]) of a color that's in HEX format
45336   * @static
45337   * @memberOf fabric.Color
45338   * @param {String} color ex: FF5555
45339   * @return {Array} source
45340   */
45341  fabric.Color.sourceFromHex = function(color) {
45342    if (color.match(Color.reHex)) {
45343      var value = color.slice(color.indexOf('#') + 1),
45344          isShortNotation = (value.length === 3),
45345          r = isShortNotation ? (value.charAt(0) + value.charAt(0)) : value.substring(0, 2),
45346          g = isShortNotation ? (value.charAt(1) + value.charAt(1)) : value.substring(2, 4),
45347          b = isShortNotation ? (value.charAt(2) + value.charAt(2)) : value.substring(4, 6);
45348
45349      return [
45350        parseInt(r, 16),
45351        parseInt(g, 16),
45352        parseInt(b, 16),
45353        1
45354      ];
45355    }
45356  };
45357
45358  /**
45359   * Returns new color object, when given color in array representation (ex: [200, 100, 100, 0.5])
45360   * @static
45361   * @memberOf fabric.Color
45362   * @param {Array} source
45363   * @return {fabric.Color}
45364   */
45365  fabric.Color.fromSource = function(source) {
45366    var oColor = new Color();
45367    oColor.setSource(source);
45368    return oColor;
45369  };
45370
45371})(typeof exports !== 'undefined' ? exports : this);
45372
45373
45374(function() {
45375
45376  /* _FROM_SVG_START_ */
45377  function getColorStop(el) {
45378    var style = el.getAttribute('style'),
45379        offset = el.getAttribute('offset'),
45380        color, opacity;
45381
45382    // convert percents to absolute values
45383    offset = parseFloat(offset) / (/%$/.test(offset) ? 100 : 1);
45384
45385    if (style) {
45386      var keyValuePairs = style.split(/\s*;\s*/);
45387
45388      if (keyValuePairs[keyValuePairs.length-1] === '') {
45389        keyValuePairs.pop();
45390      }
45391
45392      for (var i = keyValuePairs.length; i--; ) {
45393
45394        var split = keyValuePairs[i].split(/\s*:\s*/),
45395            key = split[0].trim(),
45396            value = split[1].trim();
45397
45398        if (key === 'stop-color') {
45399          color = value;
45400        }
45401        else if (key === 'stop-opacity') {
45402          opacity = value;
45403        }
45404      }
45405    }
45406
45407    if (!color) {
45408      color = el.getAttribute('stop-color') || 'rgb(0,0,0)';
45409    }
45410    if (!opacity) {
45411      opacity = el.getAttribute('stop-opacity');
45412    }
45413
45414    // convert rgba color to rgb color - alpha value has no affect in svg
45415    color = new fabric.Color(color).toRgb();
45416
45417    return {
45418      offset: offset,
45419      color: color,
45420      opacity: isNaN(parseFloat(opacity)) ? 1 : parseFloat(opacity)
45421    };
45422  }
45423  /* _FROM_SVG_END_ */
45424
45425  /**
45426   * Gradient class
45427   * @class fabric.Gradient
45428   * @tutorial {@link http://fabricjs.com/fabric-intro-part-2/#gradients}
45429   */
45430  fabric.Gradient = fabric.util.createClass(/** @lends fabric.Gradient.prototype */ {
45431
45432    /**
45433     * Constructor
45434     * @param {Object} [options] Options object with type, coords, gradientUnits and colorStops
45435     * @return {fabric.Gradient} thisArg
45436     */
45437    initialize: function(options) {
45438      options || (options = { });
45439
45440      var coords = { };
45441
45442      this.id = fabric.Object.__uid++;
45443      this.type = options.type || 'linear';
45444
45445      coords = {
45446        x1: options.coords.x1 || 0,
45447        y1: options.coords.y1 || 0,
45448        x2: options.coords.x2 || 0,
45449        y2: options.coords.y2 || 0
45450      };
45451
45452      if (this.type === 'radial') {
45453        coords.r1 = options.coords.r1 || 0;
45454        coords.r2 = options.coords.r2 || 0;
45455      }
45456
45457      this.coords = coords;
45458      this.gradientUnits = options.gradientUnits || 'objectBoundingBox';
45459      this.colorStops = options.colorStops.slice();
45460    },
45461
45462    /**
45463     * Adds another colorStop
45464     * @param {Object} colorStop Object with offset and color
45465     * @return {fabric.Gradient} thisArg
45466     */
45467    addColorStop: function(colorStop) {
45468      for (var position in colorStop) {
45469        var color = new fabric.Color(colorStop[position]);
45470        this.colorStops.push({offset: position, color: color.toRgb(), opacity: color.getAlpha()});
45471      }
45472      return this;
45473    },
45474
45475    /**
45476     * Returns object representation of a gradient
45477     * @return {Object}
45478     */
45479    toObject: function() {
45480      return {
45481        type: this.type,
45482        coords: this.coords,
45483        gradientUnits: this.gradientUnits,
45484        colorStops: this.colorStops
45485      };
45486    },
45487
45488    /* _TO_SVG_START_ */
45489    /**
45490     * Returns SVG representation of an gradient
45491     * @param {Object} object Object to create a gradient for
45492     * @param {Boolean} normalize Whether coords should be normalized
45493     * @return {String} SVG representation of an gradient (linear/radial)
45494     */
45495    toSVG: function(object, normalize) {
45496      var coords = fabric.util.object.clone(this.coords),
45497          markup;
45498
45499      // colorStops must be sorted ascending
45500      this.colorStops.sort(function(a, b) {
45501        return a.offset - b.offset;
45502      });
45503
45504      if (normalize && this.gradientUnits === 'userSpaceOnUse') {
45505        coords.x1 += object.width / 2;
45506        coords.y1 += object.height / 2;
45507        coords.x2 += object.width / 2;
45508        coords.y2 += object.height / 2;
45509      }
45510      else if (this.gradientUnits === 'objectBoundingBox') {
45511        _convertValuesToPercentUnits(object, coords);
45512      }
45513
45514      if (this.type === 'linear') {
45515        markup = [
45516          '<linearGradient ',
45517            'id="SVGID_', this.id,
45518            '" gradientUnits="', this.gradientUnits,
45519            '" x1="', coords.x1,
45520            '" y1="', coords.y1,
45521            '" x2="', coords.x2,
45522            '" y2="', coords.y2,
45523          '">'
45524        ];
45525      }
45526      else if (this.type === 'radial') {
45527        markup = [
45528          '<radialGradient ',
45529            'id="SVGID_', this.id,
45530            '" gradientUnits="', this.gradientUnits,
45531            '" cx="', coords.x2,
45532            '" cy="', coords.y2,
45533            '" r="', coords.r2,
45534            '" fx="', coords.x1,
45535            '" fy="', coords.y1,
45536          '">'
45537        ];
45538      }
45539
45540      for (var i = 0; i < this.colorStops.length; i++) {
45541        markup.push(
45542          '<stop ',
45543            'offset="', (this.colorStops[i].offset * 100) + '%',
45544            '" style="stop-color:', this.colorStops[i].color,
45545            (this.colorStops[i].opacity ? ';stop-opacity: ' + this.colorStops[i].opacity : ';'),
45546          '"/>'
45547        );
45548      }
45549
45550      markup.push((this.type === 'linear' ? '</linearGradient>' : '</radialGradient>'));
45551
45552      return markup.join('');
45553    },
45554    /* _TO_SVG_END_ */
45555
45556    /**
45557     * Returns an instance of CanvasGradient
45558     * @param {CanvasRenderingContext2D} ctx Context to render on
45559     * @return {CanvasGradient}
45560     */
45561    toLive: function(ctx) {
45562      var gradient;
45563
45564      if (!this.type) return;
45565
45566      if (this.type === 'linear') {
45567        gradient = ctx.createLinearGradient(
45568          this.coords.x1, this.coords.y1, this.coords.x2, this.coords.y2);
45569      }
45570      else if (this.type === 'radial') {
45571        gradient = ctx.createRadialGradient(
45572          this.coords.x1, this.coords.y1, this.coords.r1, this.coords.x2, this.coords.y2, this.coords.r2);
45573      }
45574
45575      for (var i = 0, len = this.colorStops.length; i < len; i++) {
45576        var color = this.colorStops[i].color,
45577            opacity = this.colorStops[i].opacity,
45578            offset = this.colorStops[i].offset;
45579
45580        if (typeof opacity !== 'undefined') {
45581          color = new fabric.Color(color).setAlpha(opacity).toRgba();
45582        }
45583        gradient.addColorStop(parseFloat(offset), color);
45584      }
45585
45586      return gradient;
45587    }
45588  });
45589
45590  fabric.util.object.extend(fabric.Gradient, {
45591
45592    /* _FROM_SVG_START_ */
45593    /**
45594     * Returns {@link fabric.Gradient} instance from an SVG element
45595     * @static
45596     * @memberof fabric.Gradient
45597     * @param {SVGGradientElement} el SVG gradient element
45598     * @param {fabric.Object} instance
45599     * @return {fabric.Gradient} Gradient instance
45600     * @see http://www.w3.org/TR/SVG/pservers.html#LinearGradientElement
45601     * @see http://www.w3.org/TR/SVG/pservers.html#RadialGradientElement
45602     */
45603    fromElement: function(el, instance) {
45604
45605      /**
45606       *  @example:
45607       *
45608       *  <linearGradient id="linearGrad1">
45609       *    <stop offset="0%" stop-color="white"/>
45610       *    <stop offset="100%" stop-color="black"/>
45611       *  </linearGradient>
45612       *
45613       *  OR
45614       *
45615       *  <linearGradient id="linearGrad2">
45616       *    <stop offset="0" style="stop-color:rgb(255,255,255)"/>
45617       *    <stop offset="1" style="stop-color:rgb(0,0,0)"/>
45618       *  </linearGradient>
45619       *
45620       *  OR
45621       *
45622       *  <radialGradient id="radialGrad1">
45623       *    <stop offset="0%" stop-color="white" stop-opacity="1" />
45624       *    <stop offset="50%" stop-color="black" stop-opacity="0.5" />
45625       *    <stop offset="100%" stop-color="white" stop-opacity="1" />
45626       *  </radialGradient>
45627       *
45628       *  OR
45629       *
45630       *  <radialGradient id="radialGrad2">
45631       *    <stop offset="0" stop-color="rgb(255,255,255)" />
45632       *    <stop offset="0.5" stop-color="rgb(0,0,0)" />
45633       *    <stop offset="1" stop-color="rgb(255,255,255)" />
45634       *  </radialGradient>
45635       *
45636       */
45637
45638      var colorStopEls = el.getElementsByTagName('stop'),
45639          type = (el.nodeName === 'linearGradient' ? 'linear' : 'radial'),
45640          gradientUnits = el.getAttribute('gradientUnits') || 'objectBoundingBox',
45641          colorStops = [],
45642          coords = { };
45643
45644      if (type === 'linear') {
45645        coords = {
45646          x1: el.getAttribute('x1') || 0,
45647          y1: el.getAttribute('y1') || 0,
45648          x2: el.getAttribute('x2') || '100%',
45649          y2: el.getAttribute('y2') || 0
45650        };
45651      }
45652      else if (type === 'radial') {
45653        coords = {
45654          x1: el.getAttribute('fx') || el.getAttribute('cx') || '50%',
45655          y1: el.getAttribute('fy') || el.getAttribute('cy') || '50%',
45656          r1: 0,
45657          x2: el.getAttribute('cx') || '50%',
45658          y2: el.getAttribute('cy') || '50%',
45659          r2: el.getAttribute('r') || '50%'
45660        };
45661      }
45662
45663      for (var i = colorStopEls.length; i--; ) {
45664        colorStops.push(getColorStop(colorStopEls[i]));
45665      }
45666
45667      _convertPercentUnitsToValues(instance, coords);
45668
45669      return new fabric.Gradient({
45670        type: type,
45671        coords: coords,
45672        gradientUnits: gradientUnits,
45673        colorStops: colorStops
45674      });
45675    },
45676    /* _FROM_SVG_END_ */
45677
45678    /**
45679     * Returns {@link fabric.Gradient} instance from its object representation
45680     * @static
45681     * @memberof fabric.Gradient
45682     * @param {Object} obj
45683     * @param {Object} [options] Options object
45684     */
45685    forObject: function(obj, options) {
45686      options || (options = { });
45687      _convertPercentUnitsToValues(obj, options);
45688      return new fabric.Gradient(options);
45689    }
45690  });
45691
45692  /**
45693   * @private
45694   */
45695  function _convertPercentUnitsToValues(object, options) {
45696    for (var prop in options) {
45697      if (typeof options[prop] === 'string' && /^\d+%$/.test(options[prop])) {
45698        var percents = parseFloat(options[prop], 10);
45699        if (prop === 'x1' || prop === 'x2' || prop === 'r2') {
45700          options[prop] = fabric.util.toFixed(object.width * percents / 100, 2);
45701        }
45702        else if (prop === 'y1' || prop === 'y2') {
45703          options[prop] = fabric.util.toFixed(object.height * percents / 100, 2);
45704        }
45705      }
45706      // normalize rendering point (should be from top/left corner rather than center of the shape)
45707      if (prop === 'x1' || prop === 'x2') {
45708        options[prop] -= fabric.util.toFixed(object.width / 2, 2);
45709      }
45710      else if (prop === 'y1' || prop === 'y2') {
45711        options[prop] -= fabric.util.toFixed(object.height / 2, 2);
45712      }
45713    }
45714  }
45715
45716  /* _TO_SVG_START_ */
45717  /**
45718   * @private
45719   */
45720  function _convertValuesToPercentUnits(object, options) {
45721    for (var prop in options) {
45722      // normalize rendering point (should be from center rather than top/left corner of the shape)
45723      if (prop === 'x1' || prop === 'x2') {
45724        options[prop] += fabric.util.toFixed(object.width / 2, 2);
45725      }
45726      else if (prop === 'y1' || prop === 'y2') {
45727        options[prop] += fabric.util.toFixed(object.height / 2, 2);
45728      }
45729      // convert to percent units
45730      if (prop === 'x1' || prop === 'x2' || prop === 'r2') {
45731        options[prop] = fabric.util.toFixed(options[prop] / object.width * 100, 2) + '%';
45732      }
45733      else if (prop === 'y1' || prop === 'y2') {
45734        options[prop] = fabric.util.toFixed(options[prop] / object.height * 100, 2) + '%';
45735      }
45736    }
45737  }
45738  /* _TO_SVG_END_ */
45739
45740})();
45741
45742
45743/**
45744 * Pattern class
45745 * @class fabric.Pattern
45746 * @see {@link http://fabricjs.com/patterns/|Pattern demo}
45747 * @see {@link http://fabricjs.com/dynamic-patterns/|DynamicPattern demo}
45748 */
45749fabric.Pattern = fabric.util.createClass(/** @lends fabric.Pattern.prototype */ {
45750
45751  /**
45752   * Repeat property of a pattern (one of repeat, repeat-x, repeat-y or no-repeat)
45753   * @type String
45754   * @default
45755   */
45756  repeat: 'repeat',
45757
45758  /**
45759   * Pattern horizontal offset from object's left/top corner
45760   * @type Number
45761   * @default
45762   */
45763  offsetX: 0,
45764
45765  /**
45766   * Pattern vertical offset from object's left/top corner
45767   * @type Number
45768   * @default
45769   */
45770  offsetY: 0,
45771
45772  /**
45773   * Constructor
45774   * @param {Object} [options] Options object
45775   * @return {fabric.Pattern} thisArg
45776   */
45777  initialize: function(options) {
45778    options || (options = { });
45779
45780    this.id = fabric.Object.__uid++;
45781
45782    if (options.source) {
45783      if (typeof options.source === 'string') {
45784        // function string
45785        if (typeof fabric.util.getFunctionBody(options.source) !== 'undefined') {
45786          this.source = new Function(fabric.util.getFunctionBody(options.source));
45787        }
45788        else {
45789          // img src string
45790          var _this = this;
45791          this.source = fabric.util.createImage();
45792          fabric.util.loadImage(options.source, function(img) {
45793            _this.source = img;
45794          });
45795        }
45796      }
45797      else {
45798        // img element
45799        this.source = options.source;
45800      }
45801    }
45802    if (options.repeat) {
45803      this.repeat = options.repeat;
45804    }
45805    if (options.offsetX) {
45806      this.offsetX = options.offsetX;
45807    }
45808    if (options.offsetY) {
45809      this.offsetY = options.offsetY;
45810    }
45811  },
45812
45813  /**
45814   * Returns object representation of a pattern
45815   * @return {Object} Object representation of a pattern instance
45816   */
45817  toObject: function() {
45818
45819    var source;
45820
45821    // callback
45822    if (typeof this.source === 'function') {
45823      source = String(this.source);
45824    }
45825    // <img> element
45826    else if (typeof this.source.src === 'string') {
45827      source = this.source.src;
45828    }
45829
45830    return {
45831      source: source,
45832      repeat: this.repeat,
45833      offsetX: this.offsetX,
45834      offsetY: this.offsetY
45835    };
45836  },
45837
45838  /* _TO_SVG_START_ */
45839  /**
45840   * Returns SVG representation of a pattern
45841   * @param {fabric.Object} object
45842   * @return {String} SVG representation of a pattern
45843   */
45844  toSVG: function(object) {
45845    var patternSource = typeof this.source === 'function' ? this.source() : this.source;
45846    var patternWidth = patternSource.width / object.getWidth();
45847    var patternHeight = patternSource.height / object.getHeight();
45848    var patternImgSrc = '';
45849
45850    if (patternSource.src) {
45851      patternImgSrc = patternSource.src;
45852    }
45853    else if (patternSource.toDataURL) {
45854      patternImgSrc = patternSource.toDataURL();
45855    }
45856
45857    return '<pattern id="SVGID_' + this.id +
45858                  '" x="' + this.offsetX +
45859                  '" y="' + this.offsetY +
45860                  '" width="' + patternWidth +
45861                  '" height="' + patternHeight + '">' +
45862             '<image x="0" y="0"' +
45863                    ' width="' + patternSource.width +
45864                    '" height="' + patternSource.height +
45865                    '" xlink:href="' + patternImgSrc +
45866             '"></image>' +
45867           '</pattern>';
45868  },
45869  /* _TO_SVG_END_ */
45870
45871  /**
45872   * Returns an instance of CanvasPattern
45873   * @param {CanvasRenderingContext2D} ctx Context to create pattern
45874   * @return {CanvasPattern}
45875   */
45876  toLive: function(ctx) {
45877    var source = typeof this.source === 'function' ? this.source() : this.source;
45878    return ctx.createPattern(source, this.repeat);
45879  }
45880});
45881
45882
45883(function(global) {
45884
45885  "use strict";
45886
45887  var fabric = global.fabric || (global.fabric = { });
45888
45889  if (fabric.Shadow) {
45890    fabric.warn('fabric.Shadow is already defined.');
45891    return;
45892  }
45893
45894  /**
45895   * Shadow class
45896   * @class fabric.Shadow
45897   * @see {@link http://fabricjs.com/shadows/|Shadow demo}
45898   */
45899  fabric.Shadow = fabric.util.createClass(/** @lends fabric.Shadow.prototype */ {
45900
45901    /**
45902     * Shadow color
45903     * @type String
45904     * @default
45905     */
45906    color: 'rgb(0,0,0)',
45907
45908    /**
45909     * Shadow blur
45910     * @type Number
45911     */
45912    blur: 0,
45913
45914    /**
45915     * Shadow horizontal offset
45916     * @type Number
45917     * @default
45918     */
45919    offsetX: 0,
45920
45921    /**
45922     * Shadow vertical offset
45923     * @type Number
45924     * @default
45925     */
45926    offsetY: 0,
45927
45928    /**
45929     * Whether the shadow should affect stroke operations
45930     * @type Boolean
45931     * @default
45932     */
45933    affectStroke: false,
45934
45935    /**
45936     * Constructor
45937     * @param {Object|String} [options] Options object with any of color, blur, offsetX, offsetX properties or string (e.g. "rgba(0,0,0,0.2) 2px 2px 10px, "2px 2px 10px rgba(0,0,0,0.2)")
45938     * @return {fabric.Shadow} thisArg
45939     */
45940    initialize: function(options) {
45941      if (typeof options === 'string') {
45942        options = this._parseShadow(options);
45943      }
45944
45945      for (var prop in options) {
45946        this[prop] = options[prop];
45947      }
45948
45949      this.id = fabric.Object.__uid++;
45950    },
45951
45952    /**
45953     * @private
45954     * @param {String} shadow Shadow value to parse
45955     * @return {Object} Shadow object with color, offsetX, offsetY and blur
45956     */
45957    _parseShadow: function(shadow) {
45958      var shadowStr = shadow.trim();
45959
45960      var offsetsAndBlur = fabric.Shadow.reOffsetsAndBlur.exec(shadowStr) || [ ],
45961          color = shadowStr.replace(fabric.Shadow.reOffsetsAndBlur, '') || 'rgb(0,0,0)';
45962
45963      return {
45964        color: color.trim(),
45965        offsetX: parseInt(offsetsAndBlur[1], 10) || 0,
45966        offsetY: parseInt(offsetsAndBlur[2], 10) || 0,
45967        blur: parseInt(offsetsAndBlur[3], 10) || 0
45968      };
45969    },
45970
45971    /**
45972     * Returns a string representation of an instance
45973     * @see http://www.w3.org/TR/css-text-decor-3/#text-shadow
45974     * @return {String} Returns CSS3 text-shadow declaration
45975     */
45976    toString: function() {
45977      return [this.offsetX, this.offsetY, this.blur, this.color].join('px ');
45978    },
45979
45980    /* _TO_SVG_START_ */
45981    /**
45982     * Returns SVG representation of a shadow
45983     * @param {fabric.Object} object
45984     * @return {String} SVG representation of a shadow
45985     */
45986    toSVG: function(object) {
45987      var mode = 'SourceAlpha';
45988
45989      if (object && (object.fill === this.color || object.stroke === this.color)) {
45990        mode = 'SourceGraphic';
45991      }
45992
45993      return (
45994        '<filter id="SVGID_' + this.id + '" y="-40%" height="180%">' +
45995          '<feGaussianBlur in="' + mode + '" stdDeviation="' +
45996            (this.blur ? this.blur / 3 : 0) +
45997          '"></feGaussianBlur>' +
45998          '<feOffset dx="' + this.offsetX + '" dy="' + this.offsetY + '"></feOffset>' +
45999          '<feMerge>' +
46000            '<feMergeNode></feMergeNode>' +
46001            '<feMergeNode in="SourceGraphic"></feMergeNode>' +
46002          '</feMerge>' +
46003        '</filter>');
46004    },
46005    /* _TO_SVG_END_ */
46006
46007    /**
46008     * Returns object representation of a shadow
46009     * @return {Object} Object representation of a shadow instance
46010     */
46011    toObject: function() {
46012      return {
46013        color: this.color,
46014        blur: this.blur,
46015        offsetX: this.offsetX,
46016        offsetY: this.offsetY
46017      };
46018    }
46019  });
46020
46021  /**
46022   * Regex matching shadow offsetX, offsetY and blur (ex: "2px 2px 10px rgba(0,0,0,0.2)", "rgb(0,255,0) 2px 2px")
46023   * @static
46024   * @field
46025   * @memberOf fabric.Shadow
46026   */
46027  fabric.Shadow.reOffsetsAndBlur = /(?:\s|^)(-?\d+(?:px)?(?:\s?|$))?(-?\d+(?:px)?(?:\s?|$))?(\d+(?:px)?)?(?:\s?|$)(?:$|\s)/;
46028
46029})(typeof exports !== 'undefined' ? exports : this);
46030
46031
46032(function () {
46033
46034  "use strict";
46035
46036  if (fabric.StaticCanvas) {
46037    fabric.warn('fabric.StaticCanvas is already defined.');
46038    return;
46039  }
46040
46041  // aliases for faster resolution
46042  var extend = fabric.util.object.extend,
46043      getElementOffset = fabric.util.getElementOffset,
46044      removeFromArray = fabric.util.removeFromArray,
46045      removeListener = fabric.util.removeListener,
46046
46047      CANVAS_INIT_ERROR = new Error('Could not initialize `canvas` element');
46048
46049  /**
46050   * Static canvas class
46051   * @class fabric.StaticCanvas
46052   * @mixes fabric.Collection
46053   * @mixes fabric.Observable
46054   * @see {@link http://fabricjs.com/static_canvas/|StaticCanvas demo}
46055   * @fires before:render
46056   * @fires after:render
46057   * @fires canvas:cleared
46058   * @fires object:added
46059   * @fires object:removed
46060   */
46061  fabric.StaticCanvas = fabric.util.createClass(/** @lends fabric.StaticCanvas.prototype */ {
46062
46063    /**
46064     * Constructor
46065     * @param {HTMLElement | String} el &lt;canvas> element to initialize instance on
46066     * @param {Object} [options] Options object
46067     * @return {Object} thisArg
46068     */
46069    initialize: function(el, options) {
46070      options || (options = { });
46071
46072      this._initStatic(el, options);
46073      fabric.StaticCanvas.activeInstance = this;
46074    },
46075
46076    /**
46077     * Background color of canvas instance
46078     * @type String
46079     * @default
46080     */
46081    backgroundColor: '',
46082
46083    /**
46084     * Background image of canvas instance
46085     * Should be set via {@link fabric.StaticCanvas#setBackgroundImage}
46086     * @type String
46087     * @default
46088     */
46089    backgroundImage: '',
46090
46091    /**
46092     * Opacity of the background image of the canvas instance
46093     * @type Float
46094     * @default
46095     */
46096    backgroundImageOpacity: 1,
46097
46098    /**
46099     * Indicates whether the background image should be stretched to fit the
46100     * dimensions of the canvas instance.
46101     * @type Boolean
46102     * @default
46103     */
46104    backgroundImageStretch: true,
46105
46106    /**
46107     * Overlay image of canvas instance
46108     * Should be set via {@link fabric.StaticCanvas#setOverlayImage}
46109     * @type String
46110     * @default
46111     */
46112    overlayImage: '',
46113
46114    /**
46115     * Left offset of overlay image (if present)
46116     * @type Number
46117     * @default
46118     */
46119    overlayImageLeft: 0,
46120
46121    /**
46122     * Top offset of overlay image (if present)
46123     * @type Number
46124     * @default
46125     */
46126    overlayImageTop: 0,
46127
46128    /**
46129     * Indicates whether toObject/toDatalessObject should include default values
46130     * @type Boolean
46131     * @default
46132     */
46133    includeDefaultValues: true,
46134
46135    /**
46136     * Indicates whether objects' state should be saved
46137     * @type Boolean
46138     * @default
46139     */
46140    stateful: true,
46141
46142    /**
46143     * Indicates whether {@link fabric.Collection.add}, {@link fabric.Collection.insertAt} and {@link fabric.Collection.remove} should also re-render canvas.
46144     * Disabling this option could give a great performance boost when adding/removing a lot of objects to/from canvas at once
46145     * (followed by a manual rendering after addition/deletion)
46146     * @type Boolean
46147     * @default
46148     */
46149    renderOnAddRemove: true,
46150
46151    /**
46152     * Function that determines clipping of entire canvas area
46153     * Being passed context as first argument. See clipping canvas area in {@link https://github.com/kangax/fabric.js/wiki/FAQ}
46154     * @type Function
46155     * @default
46156     */
46157    clipTo: null,
46158
46159    /**
46160     * Indicates whether object controls (borders/controls) are rendered above overlay image
46161     * @type Boolean
46162     * @default
46163     */
46164    controlsAboveOverlay: false,
46165
46166    /**
46167     * Indicates whether the browser can be scrolled when using a touchscreen and dragging on the canvas
46168     * @type Boolean
46169     * @default
46170     */
46171     allowTouchScrolling: false,
46172
46173    /**
46174     * Callback; invoked right before object is about to be scaled/rotated
46175     * @param {fabric.Object} target Object that's about to be scaled/rotated
46176     */
46177    onBeforeScaleRotate: function () {
46178      /* NOOP */
46179    },
46180
46181    /**
46182     * @private
46183     * @param {HTMLElement | String} el &lt;canvas> element to initialize instance on
46184     * @param {Object} [options] Options object
46185     */
46186    _initStatic: function(el, options) {
46187      this._objects = [];
46188
46189      this._createLowerCanvas(el);
46190      this._initOptions(options);
46191
46192      if (options.overlayImage) {
46193        this.setOverlayImage(options.overlayImage, this.renderAll.bind(this));
46194      }
46195      if (options.backgroundImage) {
46196        this.setBackgroundImage(options.backgroundImage, this.renderAll.bind(this));
46197      }
46198      if (options.backgroundColor) {
46199        this.setBackgroundColor(options.backgroundColor, this.renderAll.bind(this));
46200      }
46201      this.calcOffset();
46202    },
46203
46204    /**
46205     * Calculates canvas element offset relative to the document
46206     * This method is also attached as "resize" event handler of window
46207     * @return {fabric.Canvas} instance
46208     * @chainable
46209     */
46210    calcOffset: function () {
46211      this._offset = getElementOffset(this.lowerCanvasEl);
46212      return this;
46213    },
46214
46215    /**
46216     * Sets {@link fabric.StaticCanvas#overlayImage|overlay image} for this canvas
46217     * @param {String} url url of an image to set overlay to
46218     * @param {Function} callback callback to invoke when image is loaded and set as an overlay
46219     * @param {Object} [options] Optional options to set for the overlay image
46220     * @param {Number} [options.overlayImageLeft] {@link fabric.StaticCanvas#overlayImageLeft|Left offset} of overlay image
46221     * @param {Number} [options.overlayImageTop] {@link fabric.StaticCanvas#overlayImageTop|Top offset} of overlay image
46222     * @return {fabric.Canvas} thisArg
46223     * @chainable
46224     * @see {@link http://jsfiddle.net/fabricjs/MnzHT/|jsFiddle demo}
46225     * @example <caption>Normal overlayImage</caption>
46226     * canvas.setOverlayImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas));
46227     * @example <caption>Displaced overlayImage (left and top != 0)</caption>
46228     * canvas.setOverlayImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas), {
46229     *   overlayImageLeft: 100,
46230     *   overlayImageTop: 100
46231     * });
46232     */
46233    setOverlayImage: function (url, callback, options) { // TODO (kangax): test callback
46234      fabric.util.loadImage(url, function(img) {
46235        this.overlayImage = img;
46236        if (options && ('overlayImageLeft' in options)) {
46237          this.overlayImageLeft = options.overlayImageLeft;
46238        }
46239        if (options && ('overlayImageTop' in options)) {
46240          this.overlayImageTop = options.overlayImageTop;
46241        }
46242        callback && callback();
46243      }, this);
46244
46245      return this;
46246    },
46247
46248    /**
46249     * Sets {@link fabric.StaticCanvas#backgroundImage|background image} for this canvas
46250     * @param {String} url URL of an image to set background to
46251     * @param {Function} callback callback to invoke when image is loaded and set as background
46252     * @param {Object} [options] Optional options to set for the background image
46253     * @param {Float} [options.backgroundImageOpacity] {@link fabric.StaticCanvas#backgroundImageOpacity|Opacity} of the background image of the canvas instance
46254     * @param {Boolean} [options.backgroundImageStretch] Indicates whether the background image should be {@link fabric.StaticCanvas#backgroundImageStretch|strechted} to fit the canvas
46255     * @return {fabric.Canvas} thisArg
46256     * @chainable
46257     * @see {@link http://jsfiddle.net/fabricjs/YH9yD/|jsFiddle demo}
46258     * @example <caption>Normal backgroundImage</caption>
46259     * canvas.setBackgroundImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas));
46260     * @example <caption>Stretched backgroundImage with opacity</caption>
46261     * canvas.setBackgroundImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas), {
46262     *   backgroundImageOpacity: 0.5,
46263     *   backgroundImageStretch: true
46264     * });
46265     */
46266    setBackgroundImage: function (url, callback, options) {
46267      fabric.util.loadImage(url, function(img) {
46268        this.backgroundImage = img;
46269        if (options && ('backgroundImageOpacity' in options)) {
46270          this.backgroundImageOpacity = options.backgroundImageOpacity;
46271        }
46272        if (options && ('backgroundImageStretch' in options)) {
46273          this.backgroundImageStretch = options.backgroundImageStretch;
46274        }
46275        callback && callback();
46276      }, this);
46277
46278      return this;
46279    },
46280
46281    /**
46282     * Sets {@link fabric.StaticCanvas#backgroundColor|background color} for this canvas
46283     * @param {String|fabric.Pattern} backgroundColor Color or pattern to set background color to
46284     * @param {Function} callback callback to invoke when background color is set
46285     * @return {fabric.Canvas} thisArg
46286     * @chainable
46287     * @see {@link http://jsfiddle.net/fabricjs/hXzvk/|jsFiddle demo}
46288     * @example <caption>Normal backgroundColor - color value</caption>
46289     * canvas.setBackgroundColor('rgba(255, 73, 64, 0.6)', canvas.renderAll.bind(canvas));
46290     * @example <caption>fabric.Pattern used as backgroundColor</caption>
46291     * canvas.setBackgroundColor({
46292     *   source: 'http://fabricjs.com/assets/escheresque_ste.png'
46293     * }, canvas.renderAll.bind(canvas));
46294     */
46295    setBackgroundColor: function(backgroundColor, callback) {
46296      if (backgroundColor.source) {
46297        var _this = this;
46298        fabric.util.loadImage(backgroundColor.source, function(img) {
46299          _this.backgroundColor = new fabric.Pattern({
46300            source: img,
46301            repeat: backgroundColor.repeat
46302          });
46303          callback && callback();
46304        });
46305      }
46306      else {
46307        this.backgroundColor = backgroundColor;
46308        callback && callback();
46309      }
46310
46311      return this;
46312    },
46313
46314    /**
46315     * @private
46316     */
46317    _createCanvasElement: function() {
46318      var element = fabric.document.createElement('canvas');
46319      if (!element.style) {
46320        element.style = { };
46321      }
46322      if (!element) {
46323        throw CANVAS_INIT_ERROR;
46324      }
46325      this._initCanvasElement(element);
46326      return element;
46327    },
46328
46329    /**
46330     * @private
46331     * @param {HTMLElement} element
46332     */
46333    _initCanvasElement: function(element) {
46334      fabric.util.createCanvasElement(element);
46335
46336      if (typeof element.getContext === 'undefined') {
46337        throw CANVAS_INIT_ERROR;
46338      }
46339    },
46340
46341    /**
46342     * @private
46343     * @param {Object} [options] Options object
46344     */
46345    _initOptions: function (options) {
46346      for (var prop in options) {
46347        this[prop] = options[prop];
46348      }
46349
46350      this.width = parseInt(this.lowerCanvasEl.width, 10) || 0;
46351      this.height = parseInt(this.lowerCanvasEl.height, 10) || 0;
46352
46353      if (!this.lowerCanvasEl.style) return;
46354
46355      this.lowerCanvasEl.style.width = this.width + 'px';
46356      this.lowerCanvasEl.style.height = this.height + 'px';
46357    },
46358
46359    /**
46360     * Creates a bottom canvas
46361     * @private
46362     * @param {HTMLElement} [canvasEl]
46363     */
46364    _createLowerCanvas: function (canvasEl) {
46365      this.lowerCanvasEl = fabric.util.getById(canvasEl) || this._createCanvasElement();
46366      this._initCanvasElement(this.lowerCanvasEl);
46367
46368      fabric.util.addClass(this.lowerCanvasEl, 'lower-canvas');
46369
46370      if (this.interactive) {
46371        this._applyCanvasStyle(this.lowerCanvasEl);
46372      }
46373
46374      this.contextContainer = this.lowerCanvasEl.getContext('2d');
46375    },
46376
46377    /**
46378     * Returns canvas width (in px)
46379     * @return {Number}
46380     */
46381    getWidth: function () {
46382      return this.width;
46383    },
46384
46385    /**
46386     * Returns canvas height (in px)
46387     * @return {Number}
46388     */
46389    getHeight: function () {
46390      return this.height;
46391    },
46392
46393    /**
46394     * Sets width of this canvas instance
46395     * @param {Number} width value to set width to
46396     * @return {fabric.Canvas} instance
46397     * @chainable true
46398     */
46399    setWidth: function (value) {
46400      return this._setDimension('width', value);
46401    },
46402
46403    /**
46404     * Sets height of this canvas instance
46405     * @param {Number} height value to set height to
46406     * @return {fabric.Canvas} instance
46407     * @chainable true
46408     */
46409    setHeight: function (value) {
46410      return this._setDimension('height', value);
46411    },
46412
46413    /**
46414     * Sets dimensions (width, height) of this canvas instance
46415     * @param {Object} dimensions Object with width/height properties
46416     * @param {Number} [dimensions.width] Width of canvas element
46417     * @param {Number} [dimensions.height] Height of canvas element
46418     * @return {fabric.Canvas} thisArg
46419     * @chainable
46420     */
46421    setDimensions: function(dimensions) {
46422      for (var prop in dimensions) {
46423        this._setDimension(prop, dimensions[prop]);
46424      }
46425      return this;
46426    },
46427
46428    /**
46429     * Helper for setting width/height
46430     * @private
46431     * @param {String} prop property (width|height)
46432     * @param {Number} value value to set property to
46433     * @return {fabric.Canvas} instance
46434     * @chainable true
46435     */
46436    _setDimension: function (prop, value) {
46437      this.lowerCanvasEl[prop] = value;
46438      this.lowerCanvasEl.style[prop] = value + 'px';
46439
46440      if (this.upperCanvasEl) {
46441        this.upperCanvasEl[prop] = value;
46442        this.upperCanvasEl.style[prop] = value + 'px';
46443      }
46444
46445      if (this.cacheCanvasEl) {
46446        this.cacheCanvasEl[prop] = value;
46447      }
46448
46449      if (this.wrapperEl) {
46450        this.wrapperEl.style[prop] = value + 'px';
46451      }
46452
46453      this[prop] = value;
46454
46455      this.calcOffset();
46456      this.renderAll();
46457
46458      return this;
46459    },
46460
46461    /**
46462     * Returns &lt;canvas> element corresponding to this instance
46463     * @return {HTMLCanvasElement}
46464     */
46465    getElement: function () {
46466      return this.lowerCanvasEl;
46467    },
46468
46469    /**
46470     * Returns currently selected object, if any
46471     * @return {fabric.Object}
46472     */
46473    getActiveObject: function() {
46474      return null;
46475    },
46476
46477    /**
46478     * Returns currently selected group of object, if any
46479     * @return {fabric.Group}
46480     */
46481    getActiveGroup: function() {
46482      return null;
46483    },
46484
46485    /**
46486     * Given a context, renders an object on that context
46487     * @param {CanvasRenderingContext2D} ctx Context to render object on
46488     * @param {fabric.Object} object Object to render
46489     * @private
46490     */
46491    _draw: function (ctx, object) {
46492      if (!object) return;
46493
46494      if (this.controlsAboveOverlay) {
46495        var hasBorders = object.hasBorders, hasControls = object.hasControls;
46496        object.hasBorders = object.hasControls = false;
46497        object.render(ctx);
46498        object.hasBorders = hasBorders;
46499        object.hasControls = hasControls;
46500      }
46501      else {
46502        object.render(ctx);
46503      }
46504    },
46505
46506    /**
46507     * @private
46508     * @param {fabric.Object} obj Object that was added
46509     */
46510    _onObjectAdded: function(obj) {
46511      this.stateful && obj.setupState();
46512      obj.setCoords();
46513      obj.canvas = this;
46514      this.fire('object:added', { target: obj });
46515      obj.fire('added');
46516    },
46517
46518    /**
46519     * @private
46520     * @param {fabric.Object} obj Object that was removed
46521     */
46522    _onObjectRemoved: function(obj) {
46523      this.fire('object:removed', { target: obj });
46524      obj.fire('removed');
46525    },
46526
46527    /**
46528     * Returns an array of objects this instance has
46529     * @return {Array}
46530     */
46531    getObjects: function () {
46532      return this._objects;
46533    },
46534
46535    /**
46536     * Clears specified context of canvas element
46537     * @param {CanvasRenderingContext2D} ctx Context to clear
46538     * @return {fabric.Canvas} thisArg
46539     * @chainable
46540     */
46541    clearContext: function(ctx) {
46542      ctx.clearRect(0, 0, this.width, this.height);
46543      return this;
46544    },
46545
46546    /**
46547     * Returns context of canvas where objects are drawn
46548     * @return {CanvasRenderingContext2D}
46549     */
46550    getContext: function () {
46551      return this.contextContainer;
46552    },
46553
46554    /**
46555     * Clears all contexts (background, main, top) of an instance
46556     * @return {fabric.Canvas} thisArg
46557     * @chainable
46558     */
46559    clear: function () {
46560      this._objects.length = 0;
46561      if (this.discardActiveGroup) {
46562        this.discardActiveGroup();
46563      }
46564      if (this.discardActiveObject) {
46565        this.discardActiveObject();
46566      }
46567      this.clearContext(this.contextContainer);
46568      if (this.contextTop) {
46569        this.clearContext(this.contextTop);
46570      }
46571      this.fire('canvas:cleared');
46572      this.renderAll();
46573      return this;
46574    },
46575
46576    /**
46577     * Renders both the top canvas and the secondary container canvas.
46578     * @param {Boolean} [allOnTop] Whether we want to force all images to be rendered on the top canvas
46579     * @return {fabric.Canvas} instance
46580     * @chainable
46581     */
46582    renderAll: function (allOnTop) {
46583
46584      var canvasToDrawOn = this[(allOnTop === true && this.interactive) ? 'contextTop' : 'contextContainer'];
46585
46586      if (this.contextTop && this.selection && !this._groupSelector) {
46587        this.clearContext(this.contextTop);
46588      }
46589
46590      if (!allOnTop) {
46591        this.clearContext(canvasToDrawOn);
46592      }
46593
46594      this.fire('before:render');
46595
46596      if (this.clipTo) {
46597        fabric.util.clipContext(this, canvasToDrawOn);
46598      }
46599
46600      if (this.backgroundColor) {
46601        canvasToDrawOn.fillStyle = this.backgroundColor.toLive
46602          ? this.backgroundColor.toLive(canvasToDrawOn)
46603          : this.backgroundColor;
46604
46605        canvasToDrawOn.fillRect(
46606          this.backgroundColor.offsetX || 0,
46607          this.backgroundColor.offsetY || 0,
46608          this.width,
46609          this.height);
46610      }
46611
46612      if (typeof this.backgroundImage === 'object') {
46613        this._drawBackroundImage(canvasToDrawOn);
46614      }
46615
46616      var activeGroup = this.getActiveGroup();
46617      for (var i = 0, length = this._objects.length; i < length; ++i) {
46618        if (!activeGroup ||
46619            (activeGroup && this._objects[i] && !activeGroup.contains(this._objects[i]))) {
46620          this._draw(canvasToDrawOn, this._objects[i]);
46621        }
46622      }
46623
46624      // delegate rendering to group selection (if one exists)
46625      if (activeGroup) {
46626        //Store objects in group preserving order, then replace
46627        var sortedObjects = [];
46628        this.forEachObject(function (object) {
46629            if (activeGroup.contains(object)) {
46630                sortedObjects.push(object);
46631            }
46632        });
46633        activeGroup._set('objects', sortedObjects);
46634        this._draw(canvasToDrawOn, activeGroup);
46635      }
46636
46637      if (this.clipTo) {
46638        canvasToDrawOn.restore();
46639      }
46640
46641      if (this.overlayImage) {
46642        canvasToDrawOn.drawImage(this.overlayImage, this.overlayImageLeft, this.overlayImageTop);
46643      }
46644
46645      if (this.controlsAboveOverlay && this.interactive) {
46646        this.drawControls(canvasToDrawOn);
46647      }
46648
46649      this.fire('after:render');
46650
46651      return this;
46652    },
46653
46654    /**
46655     * @private
46656     * @param {CanvasRenderingContext2D} canvasToDrawOn Context to render on
46657     */
46658    _drawBackroundImage: function(canvasToDrawOn) {
46659      canvasToDrawOn.save();
46660      canvasToDrawOn.globalAlpha = this.backgroundImageOpacity;
46661
46662      if (this.backgroundImageStretch) {
46663        canvasToDrawOn.drawImage(this.backgroundImage, 0, 0, this.width, this.height);
46664      }
46665      else {
46666        canvasToDrawOn.drawImage(this.backgroundImage, 0, 0);
46667      }
46668      canvasToDrawOn.restore();
46669    },
46670
46671    /**
46672     * Method to render only the top canvas.
46673     * Also used to render the group selection box.
46674     * @return {fabric.Canvas} thisArg
46675     * @chainable
46676     */
46677    renderTop: function () {
46678      var ctx = this.contextTop || this.contextContainer;
46679      this.clearContext(ctx);
46680
46681      // we render the top context - last object
46682      if (this.selection && this._groupSelector) {
46683        this._drawSelection();
46684      }
46685
46686      // delegate rendering to group selection if one exists
46687      // used for drawing selection borders/controls
46688      var activeGroup = this.getActiveGroup();
46689      if (activeGroup) {
46690        activeGroup.render(ctx);
46691      }
46692
46693      if (this.overlayImage) {
46694        ctx.drawImage(this.overlayImage, this.overlayImageLeft, this.overlayImageTop);
46695      }
46696
46697      this.fire('after:render');
46698
46699      return this;
46700    },
46701
46702    /**
46703     * Returns coordinates of a center of canvas.
46704     * Returned value is an object with top and left properties
46705     * @return {Object} object with "top" and "left" number values
46706     */
46707    getCenter: function () {
46708      return {
46709        top: this.getHeight() / 2,
46710        left: this.getWidth() / 2
46711      };
46712    },
46713
46714    /**
46715     * Centers object horizontally.
46716     * You might need to call `setCoords` on an object after centering, to update controls area.
46717     * @param {fabric.Object} object Object to center
46718     * @return {fabric.Canvas} thisArg
46719     */
46720    centerObjectH: function (object) {
46721      object.set('left', this.getCenter().left);
46722      this.renderAll();
46723      return this;
46724    },
46725
46726    /**
46727     * Centers object vertically.
46728     * You might need to call `setCoords` on an object after centering, to update controls area.
46729     * @param {fabric.Object} object Object to center
46730     * @return {fabric.Canvas} thisArg
46731     * @chainable
46732     */
46733    centerObjectV: function (object) {
46734      object.set('top', this.getCenter().top);
46735      this.renderAll();
46736      return this;
46737    },
46738
46739    /**
46740     * Centers object vertically and horizontally.
46741     * You might need to call `setCoords` on an object after centering, to update controls area.
46742     * @param {fabric.Object} object Object to center
46743     * @return {fabric.Canvas} thisArg
46744     * @chainable
46745     */
46746    centerObject: function (object) {
46747      return this.centerObjectH(object).centerObjectV(object);
46748    },
46749
46750    /**
46751     * Returs dataless JSON representation of canvas
46752     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output
46753     * @return {String} json string
46754     */
46755    toDatalessJSON: function (propertiesToInclude) {
46756      return this.toDatalessObject(propertiesToInclude);
46757    },
46758
46759    /**
46760     * Returns object representation of canvas
46761     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output
46762     * @return {Object} object representation of an instance
46763     */
46764    toObject: function (propertiesToInclude) {
46765      return this._toObjectMethod('toObject', propertiesToInclude);
46766    },
46767
46768    /**
46769     * Returns dataless object representation of canvas
46770     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output
46771     * @return {Object} object representation of an instance
46772     */
46773    toDatalessObject: function (propertiesToInclude) {
46774      return this._toObjectMethod('toDatalessObject', propertiesToInclude);
46775    },
46776
46777    /**
46778     * @private
46779     */
46780    _toObjectMethod: function (methodName, propertiesToInclude) {
46781
46782      var activeGroup = this.getActiveGroup();
46783      if (activeGroup) {
46784        this.discardActiveGroup();
46785      }
46786      var data = {
46787        objects: this.getObjects().map(function (instance) {
46788          // TODO (kangax): figure out how to clean this up
46789          var originalValue;
46790          if (!this.includeDefaultValues) {
46791            originalValue = instance.includeDefaultValues;
46792            instance.includeDefaultValues = false;
46793          }
46794          var object = instance[methodName](propertiesToInclude);
46795          if (!this.includeDefaultValues) {
46796            instance.includeDefaultValues = originalValue;
46797          }
46798          return object;
46799        }, this),
46800        background: (this.backgroundColor && this.backgroundColor.toObject)
46801                      ? this.backgroundColor.toObject()
46802                      : this.backgroundColor
46803      };
46804      if (this.backgroundImage) {
46805        data.backgroundImage = this.backgroundImage.src;
46806        data.backgroundImageOpacity = this.backgroundImageOpacity;
46807        data.backgroundImageStretch = this.backgroundImageStretch;
46808      }
46809      if (this.overlayImage) {
46810        data.overlayImage = this.overlayImage.src;
46811        data.overlayImageLeft = this.overlayImageLeft;
46812        data.overlayImageTop = this.overlayImageTop;
46813      }
46814      fabric.util.populateWithProperties(this, data, propertiesToInclude);
46815      if (activeGroup) {
46816        this.setActiveGroup(new fabric.Group(activeGroup.getObjects()));
46817        activeGroup.forEachObject(function(o) { o.set('active', true) });
46818      }
46819      return data;
46820    },
46821
46822    /* _TO_SVG_START_ */
46823    /**
46824     * Returns SVG representation of canvas
46825     * @function
46826     * @param {Object} [options] Options object for SVG output
46827     * @param {Boolean} [options.suppressPreamble=false] If true xml tag is not included
46828     * @param {Object} [options.viewBox] SVG viewbox object
46829     * @param {Number} [options.viewBox.x] x-cooridnate of viewbox
46830     * @param {Number} [options.viewBox.y] y-coordinate of viewbox
46831     * @param {Number} [options.viewBox.width] Width of viewbox
46832     * @param {Number} [options.viewBox.height] Height of viewbox
46833     * @param {String} [options.encoding=UTF-8] Encoding of SVG output
46834     * @param {Function} [reviver] Method for further parsing of svg elements, called after each fabric object c
46834onverted into svg representation.
46835     * @return {String} SVG string
46836     * @tutorial {@link http://fabricjs.com/fabric-intro-part-3/#serialization}
46837     * @see {@link http://jsfiddle.net/fabricjs/jQ3ZZ/|jsFiddle demo}
46838     * @example <caption>Normal SVG output</caption>
46839     * var svg = canvas.toSVG();
46840     * @example <caption>SVG output without preamble (without &lt;?xml ../>)</caption>
46841     * var svg = canvas.toSVG({suppressPreamble: true});
46842     * @example <caption>SVG output with viewBox attribute</caption>
46843     * var svg = canvas.toSVG({
46844     *   viewBox: {
46845     *     x: 100,
46846     *     y: 100,
46847     *     width: 200,
46848     *     height: 300
46849     *   }
46850     * });
46851     * @example <caption>SVG output with different encoding (default: UTF-8)</caption>
46852     * var svg = canvas.toSVG({encoding: 'ISO-8859-1'});
46853     * @example <caption>Modify SVG output with reviver function</caption>
46854     * var svg = canvas.toSVG(null, function(svg) {
46855     *   return svg.replace('stroke-dasharray: ; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; ', '');
46856     * });
46857     */
46858    toSVG: function(options, reviver) {
46859      options || (options = { });
46860      var markup = [];
46861
46862      if (!options.suppressPreamble) {
46863        markup.push(
46864          '<?xml version="1.0" encoding="', (options.encoding || 'UTF-8'), '" standalone="no" ?>',
46865            '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" ',
46866              '"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n'
46867        );
46868      }
46869      markup.push(
46870          '<svg ',
46871            'xmlns="http://www.w3.org/2000/svg" ',
46872            'xmlns:xlink="http://www.w3.org/1999/xlink" ',
46873            'version="1.1" ',
46874            'width="', (options.viewBox ? options.viewBox.width : this.width), '" ',
46875            'height="', (options.viewBox ? options.viewBox.height : this.height), '" ',
46876            (this.backgroundColor && !this.backgroundColor.source ? 'style="background-color: ' + this.backgroundColor +'" ' : null),
46877            (options.viewBox ? 'viewBox="' + options.viewBox.x + ' ' + options.viewBox.y + ' ' + options.viewBox.width + ' ' + options.viewBox.height + '" ' : null),
46878            'xml:space="preserve">',
46879          '<desc>Created with Fabric.js ', fabric.version, '</desc>',
46880          '<defs>', fabric.createSVGFontFacesMarkup(this.getObjects()), fabric.createSVGRefElementsMarkup(this), '</defs>'
46881      );
46882
46883      if (this.backgroundColor && this.backgroundColor.source) {
46884        markup.push(
46885          '<rect x="0" y="0" ',
46886            'width="', (this.backgroundColor.repeat === 'repeat-y' || this.backgroundColor.repeat === 'no-repeat' ? this.backgroundColor.source.width : this.width),
46887            '" height="', (this.backgroundColor.repeat === 'repeat-x' || this.backgroundColor.repeat === 'no-repeat' ? this.backgroundColor.source.height : this.height),
46888            '" fill="url(#backgroundColorPattern)"',
46889          '></rect>'
46890        );
46891      }
46892
46893      if (this.backgroundImage) {
46894        markup.push(
46895          '<image x="0" y="0" ',
46896            'width="', (this.backgroundImageStretch ? this.width : this.backgroundImage.width),
46897            '" height="', (this.backgroundImageStretch ? this.height : this.backgroundImage.height),
46898            '" preserveAspectRatio="', (this.backgroundImageStretch ? 'none' : 'defer'),
46899            '" xlink:href="', this.backgroundImage.src,
46900            '" style="opacity:', this.backgroundImageOpacity,
46901          '"></image>'
46902        );
46903      }
46904
46905      if (this.overlayImage) {
46906        markup.push(
46907          '<image x="', this.overlayImageLeft,
46908            '" y="', this.overlayImageTop,
46909            '" width="', this.overlayImage.width,
46910            '" height="', this.overlayImage.height,
46911            '" xlink:href="', this.overlayImage.src,
46912          '"></image>'
46913        );
46914      }
46915
46916      var activeGroup = this.getActiveGroup();
46917      if (activeGroup) {
46918        this.discardActiveGroup();
46919      }
46920      for (var i = 0, objects = this.getObjects(), len = objects.length; i < len; i++) {
46921        markup.push(objects[i].toSVG(reviver));
46922      }
46923      if (activeGroup) {
46924        this.setActiveGroup(new fabric.Group(activeGroup.getObjects()));
46925        activeGroup.forEachObject(function(o) { o.set('active', true) });
46926      }
46927      markup.push('</svg>');
46928
46929      return markup.join('');
46930    },
46931    /* _TO_SVG_END_ */
46932
46933    /**
46934     * Removes an object from canvas and returns it
46935     * @param {fabric.Object} object Object to remove
46936     * @return {fabric.Object} removed object
46937     */
46938    remove: function (object) {
46939      // removing active object should fire "selection:cleared" events
46940      if (this.getActiveObject() === object) {
46941        this.fire('before:selection:cleared', { target: object });
46942        this.discardActiveObject();
46943        this.fire('selection:cleared');
46944      }
46945
46946      return fabric.Collection.remove.call(this, object);
46947    },
46948
46949    /**
46950     * Moves an object to the bottom of the stack of drawn objects
46951     * @param {fabric.Object} object Object to send to back
46952     * @return {fabric.Canvas} thisArg
46953     * @chainable
46954     */
46955    sendToBack: function (object) {
46956      removeFromArray(this._objects, object);
46957      this._objects.unshift(object);
46958      return this.renderAll && this.renderAll();
46959    },
46960
46961    /**
46962     * Moves an object to the top of the stack of drawn objects
46963     * @param {fabric.Object} object Object to send
46964     * @return {fabric.Canvas} thisArg
46965     * @chainable
46966     */
46967    bringToFront: function (object) {
46968      removeFromArray(this._objects, object);
46969      this._objects.push(object);
46970      return this.renderAll && this.renderAll();
46971    },
46972
46973    /**
46974     * Moves an object down in stack of drawn objects
46975     * @param {fabric.Object} object Object to send
46976     * @param {Boolean} [intersecting] If `true`, send object behind next lower intersecting object
46977     * @return {fabric.Canvas} thisArg
46978     * @chainable
46979     */
46980    sendBackwards: function (object, intersecting) {
46981      var idx = this._objects.indexOf(object);
46982
46983      // if object is not on the bottom of stack
46984      if (idx !== 0) {
46985        var newIdx;
46986
46987        if (intersecting) {
46988          newIdx = idx;
46989
46990          // traverse down the stack looking for the nearest intersecting object
46991          for (var i=idx-1; i>=0; --i) {
46992
46993            var isIntersecting = object.intersectsWithObject(this._objects[i]) ||
46994                                 object.isContainedWithinObject(this._objects[i]) ||
46995                                 this._objects[i].isContainedWithinObject(object);
46996
46997            if (isIntersecting) {
46998              newIdx = i;
46999              break;
47000            }
47001          }
47002        }
47003        else {
47004          newIdx = idx-1;
47005        }
47006
47007        removeFromArray(this._objects, object);
47008        this._objects.splice(newIdx, 0, object);
47009        this.renderAll && this.renderAll();
47010      }
47011      return this;
47012    },
47013
47014    /**
47015     * Moves an object up in stack of drawn objects
47016     * @param {fabric.Object} object Object to send
47017     * @param {Boolean} [intersecting] If `true`, send object in front of next upper intersecting object
47018     * @return {fabric.Canvas} thisArg
47019     * @chainable
47020     */
47021    bringForward: function (object, intersecting) {
47022      var idx = this._objects.indexOf(object);
47023
47024      // if object is not on top of stack (last item in an array)
47025      if (idx !== this._objects.length-1) {
47026        var newIdx;
47027
47028        if (intersecting) {
47029          newIdx = idx;
47030
47031          // traverse up the stack looking for the nearest intersecting object
47032          for (var i = idx + 1; i < this._objects.length; ++i) {
47033
47034            var isIntersecting = object.intersectsWithObject(this._objects[i]) ||
47035                                 object.isContainedWithinObject(this._objects[i]) ||
47036                                 this._objects[i].isContainedWithinObject(object);
47037
47038            if (isIntersecting) {
47039              newIdx = i;
47040              break;
47041            }
47042          }
47043        }
47044        else {
47045          newIdx = idx+1;
47046        }
47047
47048        removeFromArray(this._objects, object);
47049        this._objects.splice(newIdx, 0, object);
47050        this.renderAll && this.renderAll();
47051      }
47052      return this;
47053    },
47054
47055    /**
47056     * Moves an object to specified level in stack of drawn objects
47057     * @param {fabric.Object} object Object to send
47058     * @param {Number} index Position to move to
47059     * @return {fabric.Canvas} thisArg
47060     * @chainable
47061     */
47062    moveTo: function (object, index) {
47063      removeFromArray(this._objects, object);
47064      this._objects.splice(index, 0, object);
47065      return this.renderAll && this.renderAll();
47066    },
47067
47068    /**
47069     * Clears a canvas element and removes all event handlers.
47070     * @return {fabric.Canvas} thisArg
47071     * @chainable
47072     */
47073    dispose: function () {
47074      this.clear();
47075
47076      if (!this.interactive) return this;
47077
47078      if (fabric.isTouchSupported) {
47079        removeListener(this.upperCanvasEl, 'touchstart', this._onMouseDown);
47080        removeListener(this.upperCanvasEl, 'touchmove', this._onMouseMove);
47081        if (typeof Event !== 'undefined' && 'remove' in Event) {
47082          Event.remove(this.upperCanvasEl, 'gesture', this._onGesture);
47083        }
47084      }
47085      else {
47086        removeListener(this.upperCanvasEl, 'mousedown', this._onMouseDown);
47087        removeListener(this.upperCanvasEl, 'mousemove', this._onMouseMove);
47088        removeListener(fabric.window, 'resize', this._onResize);
47089      }
47090      return this;
47091    },
47092
47093    /**
47094     * Returns a string representation of an instance
47095     * @return {String} string representation of an instance
47096     */
47097    toString: function () {
47098      return '#<fabric.Canvas (' + this.complexity() + '): '+
47099               '{ objects: ' + this.getObjects().length + ' }>';
47100    }
47101  });
47102
47103  extend(fabric.StaticCanvas.prototype, fabric.Observable);
47104  extend(fabric.StaticCanvas.prototype, fabric.Collection);
47105  extend(fabric.StaticCanvas.prototype, fabric.DataURLExporter);
47106
47107  extend(fabric.StaticCanvas, /** @lends fabric.StaticCanvas */ {
47108
47109    /**
47110     * @static
47111     * @type String
47112     * @default
47113     */
47114    EMPTY_JSON: '{"objects": [], "background": "white"}',
47115
47116    /**
47117     * Provides a way to check support of some of the canvas methods
47118     * (either those of HTMLCanvasElement itself, or rendering context)
47119     *
47120     * @param methodName {String} Method to check support for;
47121     *                            Could be one of "getImageData", "toDataURL", "toDataURLWithQuality" or "setLineDash"
47122     * @return {Boolean | null} `true` if method is supported (or at least exists),
47123     *                          `null` if canvas element or context can not be initialized
47124     */
47125    supports: function (methodName) {
47126      var el = fabric.util.createCanvasElement();
47127
47128      if (!el || !el.getContext) {
47129        return null;
47130      }
47131
47132      var ctx = el.getContext('2d');
47133      if (!ctx) {
47134        return null;
47135      }
47136
47137      switch (methodName) {
47138
47139        case 'getImageData':
47140          return typeof ctx.getImageData !== 'undefined';
47141
47142        case 'setLineDash':
47143          return typeof ctx.setLineDash !== 'undefined';
47144
47145        case 'toDataURL':
47146          return typeof el.toDataURL !== 'undefined';
47147
47148        case 'toDataURLWithQuality':
47149          try {
47150            el.toDataURL('image/jpeg', 0);
47151            return true;
47152          }
47153          catch (e) { }
47154          return false;
47155
47156        default:
47157          return null;
47158      }
47159    }
47160  });
47161
47162  /**
47163   * Returns JSON representation of canvas
47164   * @function
47165   * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output
47166   * @return {String} JSON string
47167   * @tutorial {@link http://fabricjs.com/fabric-intro-part-3/#serialization}
47168   * @see {@link http://jsfiddle.net/fabricjs/pec86/|jsFiddle demo}
47169   * @example <caption>JSON without additional properties</caption>
47170   * var json = canvas.toJSON();
47171   * @example <caption>JSON with additional properties included</caption>
47172   * var json = canvas.toJSON(['lockMovementX', 'lockMovementY', 'lockRotation', 'lockScalingX', 'lockScalingY', 'lockUniScaling']);
47173   * @example <caption>JSON without default values</caption>
47174   * canvas.includeDefaultValues = false;
47175   * var json = canvas.toJSON();
47176   */
47177  fabric.StaticCanvas.prototype.toJSON = fabric.StaticCanvas.prototype.toObject;
47178
47179})();
47180
47181
47182/**
47183 * BaseBrush class
47184 * @class fabric.BaseBrush
47185 * @see {@link http://fabricjs.com/freedrawing/|Freedrawing demo}
47186 */
47187fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype */ {
47188
47189  /**
47190   * Color of a brush
47191   * @type String
47192   * @default
47193   */
47194  color:            'rgb(0, 0, 0)',
47195
47196  /**
47197   * Width of a brush
47198   * @type Number
47199   * @default
47200   */
47201  width:            1,
47202
47203  /**
47204   * Shadow object representing shadow of this shape.
47205   * <b>Backwards incompatibility note:</b> This property replaces "shadowColor" (String), "shadowOffsetX" (Number),
47206   * "shadowOffsetY" (Number) and "shadowBlur" (Number) since v1.2.12
47207   * @type fabric.Shadow
47208   * @default
47209   */
47210  shadow:          null,
47211
47212  /**
47213   * Line endings style of a brush (one of "butt", "round", "square")
47214   * @type String
47215   * @default
47216   */
47217  strokeLineCap:    'round',
47218
47219  /**
47220   * Corner style of a brush (one of "bevil", "round", "miter")
47221   * @type String
47222   * @default
47223   */
47224  strokeLineJoin:   'round',
47225
47226  /**
47227   * Sets shadow of an object
47228   * @param {Object|String} [options] Options object or string (e.g. "2px 2px 10px rgba(0,0,0,0.2)")
47229   * @return {fabric.Object} thisArg
47230   * @chainable
47231   */
47232  setShadow: function(options) {
47233    this.shadow = new fabric.Shadow(options);
47234    return this;
47235  },
47236
47237  /**
47238   * Sets brush styles
47239   * @private
47240   */
47241  _setBrushStyles: function() {
47242    var ctx = this.canvas.contextTop;
47243
47244    ctx.strokeStyle = this.color;
47245    ctx.lineWidth = this.width;
47246    ctx.lineCap = this.strokeLineCap;
47247    ctx.lineJoin = this.strokeLineJoin;
47248  },
47249
47250  /**
47251   * Sets brush shadow styles
47252   * @private
47253   */
47254  _setShadow: function() {
47255    if (!this.shadow) return;
47256
47257    var ctx = this.canvas.contextTop;
47258
47259    ctx.shadowColor = this.shadow.color;
47260    ctx.shadowBlur = this.shadow.blur;
47261    ctx.shadowOffsetX = this.shadow.offsetX;
47262    ctx.shadowOffsetY = this.shadow.offsetY;
47263  },
47264
47265  /**
47266   * Removes brush shadow styles
47267   * @private
47268   */
47269  _resetShadow: function() {
47270    var ctx = this.canvas.contextTop;
47271
47272    ctx.shadowColor = '';
47273    ctx.shadowBlur = ctx.shadowOffsetX = ctx.shadowOffsetY = 0;
47274  }
47275});
47276
47277
47278(function() {
47279
47280  var utilMin = fabric.util.array.min,
47281      utilMax = fabric.util.array.max;
47282
47283  /**
47284   * PencilBrush class
47285   * @class fabric.PencilBrush
47286   * @extends fabric.BaseBrush
47287   */
47288  fabric.PencilBrush = fabric.util.createClass(fabric.BaseBrush, /** @lends fabric.PencilBrush.prototype */ {
47289
47290    /**
47291     * Constructor
47292     * @param {fabric.Canvas} canvas
47293     * @return {fabric.PencilBrush} Instance of a pencil brush
47294     */
47295    initialize: function(canvas) {
47296      this.canvas = canvas;
47297      this._points = [ ];
47298    },
47299
47300    /**
47301     * Inovoked on mouse down
47302     * @param {Object} pointer
47303     */
47304    onMouseDown: function(pointer) {
47305      this._prepareForDrawing(pointer);
47306      // capture coordinates immediately
47307      // this allows to draw dots (when movement never occurs)
47308      this._captureDrawingPath(pointer);
47309      this._render();
47310    },
47311
47312    /**
47313     * Inovoked on mouse move
47314     * @param {Object} pointer
47315     */
47316    onMouseMove: function(pointer) {
47317      this._captureDrawingPath(pointer);
47318      // redraw curve
47319      // clear top canvas
47320      this.canvas.clearContext(this.canvas.contextTop);
47321      this._render();
47322    },
47323
47324    /**
47325     * Invoked on mouse up
47326     */
47327    onMouseUp: function() {
47328      this._finalizeAndAddPath();
47329    },
47330
47331    /**
47332     * @param {Object} pointer
47333     */
47334    _prepareForDrawing: function(pointer) {
47335
47336      var p = new fabric.Point(pointer.x, pointer.y);
47337
47338      this._reset();
47339      this._addPoint(p);
47340
47341      this.canvas.contextTop.moveTo(p.x, p.y);
47342    },
47343
47344    /**
47345     * @private
47346     * @param {fabric.Point} point
47347     */
47348    _addPoint: function(point) {
47349      this._points.push(point);
47350    },
47351
47352    /**
47353     * Clear points array and set contextTop canvas
47354     * style.
47355     *
47356     * @private
47357     *
47358     */
47359    _reset: function() {
47360      this._points.length = 0;
47361
47362      this._setBrushStyles();
47363      this._setShadow();
47364    },
47365
47366    /**
47367     * @private
47368     *
47369     * @param point {pointer} (fabric.util.pointer) actual mouse position
47370     *   related to the canvas.
47371     */
47372    _captureDrawingPath: function(pointer) {
47373      var pointerPoint = new fabric.Point(pointer.x, pointer.y);
47374      this._addPoint(pointerPoint);
47375    },
47376
47377    /**
47378     * Draw a smooth path on the topCanvas using quadraticCurveTo
47379     *
47380     * @private
47381     */
47382    _render: function() {
47383      var ctx  = this.canvas.contextTop;
47384      ctx.beginPath();
47385
47386      var p1 = this._points[0];
47387      var p2 = this._points[1];
47388      
47389      //if we only have 2 points in the path and they are the same
47390      //it means that the user only clicked the canvas without moving the mouse
47391      //then we should be drawing a dot. A path isn't drawn between two identical dots
47392      //that's why we set them apart a bit
47393      if (this._points.length === 2 && p1.x === p2.x && p1.y === p2.y) {
47394          p1.x -= 0.5;
47395          p2.x += 0.5;
47396      }
47397      ctx.moveTo(p1.x, p1.y);
47398
47399      for (var i = 1, len = this._points.length; i < len; i++) {
47400        // we pick the point between pi+1 & pi+2 as the
47401        // end point and p1 as our control point.
47402        var midPoint = p1.midPointFrom(p2);
47403        ctx.quadraticCurveTo(p1.x, p1.y, midPoint.x, midPoint.y);
47404
47405        p1 = this._points[i];
47406        p2 = this._points[i+1];
47407      }
47408      // Draw last line as a straight line while
47409      // we wait for the next point to be able to calculate
47410      // the bezier control point
47411      ctx.lineTo(p1.x, p1.y);
47412      ctx.stroke();
47413    },
47414
47415    /**
47416     * Return an SVG path based on our captured points and their bounding box
47417     *
47418     * @private
47419     */
47420    _getSVGPathData: function() {
47421      this.box = this.getPathBoundingBox(this._points);
47422      return this.convertPointsToSVGPath(
47423        this._points, this.box.minx, this.box.maxx, this.box.miny, this.box.maxy);
47424     },
47425
47426     /**
47427      * Returns bounding box of a path based on given points
47428      * @param {Array} points
47429      * @return {Object} object with minx, miny, maxx, maxy
47430      */
47431     getPathBoundingBox: function(points) {
47432      var xBounds = [],
47433          yBounds = [],
47434          p1 = points[0],
47435          p2 = points[1],
47436          startPoint = p1;
47437
47438      for (var i = 1, len = points.length; i < len; i++) {
47439        var midPoint = p1.midPointFrom(p2);
47440        // with startPoint, p1 as control point, midpoint as end point
47441        xBounds.push(startPoint.x);
47442        xBounds.push(midPoint.x);
47443        yBounds.push(startPoint.y);
47444        yBounds.push(midPoint.y);
47445
47446        p1 = points[i];
47447        p2 = points[i+1];
47448        startPoint = midPoint;
47449     } // end for
47450
47451     xBounds.push(p1.x);
47452     yBounds.push(p1.y);
47453
47454     return {
47455       minx: utilMin(xBounds),
47456       miny: utilMin(yBounds),
47457       maxx: utilMax(xBounds),
47458       maxy: utilMax(yBounds)
47459     };
47460    },
47461
47462    /**
47463     * Converts points to SVG path
47464     * @param {Array} points Array of points
47465     * @return {String} SVG path
47466     */
47467    convertPointsToSVGPath: function(points, minX, maxX, minY) {
47468      var path = [];
47469      var p1 = new fabric.Point(points[0].x - minX, points[0].y - minY);
47470      var p2 = new fabric.Point(points[1].x - minX, points[1].y - minY);
47471
47472      path.push('M ', points[0].x - minX, ' ', points[0].y - minY, ' ');
47473      for (var i = 1, len = points.length; i < len; i++) {
47474        var midPoint = p1.midPointFrom(p2);
47475        // p1 is our bezier control point
47476        // midpoint is our endpoint
47477        // start point is p(i-1) value.
47478        path.push('Q ', p1.x, ' ', p1.y, ' ', midPoint.x, ' ', midPoint.y, ' ');
47479        p1 = new fabric.Point(points[i].x - minX, points[i].y - minY);
47480        if ((i+1) < points.length) {
47481          p2 = new fabric.Point(points[i+1].x - minX, points[i+1].y - minY);
47482        }
47483      }
47484      path.push('L ', p1.x, ' ', p1.y, ' ');
47485      return path;
47486    },
47487
47488    /**
47489     * Creates fabric.Path object to add on canvas
47490     * @param {String} pathData Path data
47491     * @return {fabric.Path} path to add on canvas
47492     */
47493    createPath: function(pathData) {
47494      var path = new fabric.Path(pathData);
47495      path.fill = null;
47496      path.stroke = this.color;
47497      path.strokeWidth = this.width;
47498      path.strokeLineCap = this.strokeLineCap;
47499      path.strokeLineJoin = this.strokeLineJoin;
47500
47501      if (this.shadow) {
47502        this.shadow.affectStroke = true;
47503        path.setShadow(this.shadow);
47504      }
47505
47506      return path;
47507    },
47508
47509    /**
47510     * On mouseup after drawing the path on contextTop canvas
47511     * we use the points captured to create an new fabric path object
47512     * and add it to the fabric canvas.
47513     *
47514     */
47515    _finalizeAndAddPath: function() {
47516      var ctx = this.canvas.contextTop;
47517      ctx.closePath();
47518
47519      var pathData = this._getSVGPathData().join('');
47520      if (pathData === "M 0 0 Q 0 0 0 0 L 0 0") {
47521        // do not create 0 width/height paths, as they are
47522        // rendered inconsistently across browsers
47523        // Firefox 4, for example, renders a dot,
47524        // whereas Chrome 10 renders nothing
47525        this.canvas.renderAll();
47526        return;
47527      }
47528
47529      // set path origin coordinates based on our bounding box
47530      var originLeft = this.box.minx  + (this.box.maxx - this.box.minx) /2;
47531      var originTop = this.box.miny  + (this.box.maxy - this.box.miny) /2;
47532
47533      this.canvas.contextTop.arc(originLeft, originTop, 3, 0, Math.PI * 2, false);
47534
47535      var path = this.createPath(pathData);
47536      path.set({ left: originLeft, top: originTop });
47537
47538      this.canvas.add(path);
47539      path.setCoords();
47540
47541      this.canvas.clearContext(this.canvas.contextTop);
47542      this._resetShadow();
47543      this.canvas.renderAll();
47544
47545      // fire event 'path' created
47546      this.canvas.fire('path:created', { path: path });
47547    }
47548  });
47549})();
47550
47551
47552/**
47553 * CircleBrush class
47554 * @class fabric.CircleBrush
47555 */
47556fabric.CircleBrush = fabric.util.createClass(fabric.BaseBrush, /** @lends fabric.CircleBrush.prototype */ {
47557
47558  /**
47559   * Width of a brush
47560   * @type Number
47561   * @default
47562   */
47563  width: 10,
47564
47565  /**
47566   * Constructor
47567   * @param {fabric.Canvas} canvas
47568   * @return {fabric.CircleBrush} Instance of a circle brush
47569   */
47570  initialize: function(canvas) {
47571    this.canvas = canvas;
47572    this.points = [ ];
47573  },
47574  /**
47575  * Invoked inside on mouse down and mouse move
47576  * @param {Object} pointer
47577  */
47578  drawDot: function(pointer) {
47579    var point = this.addPoint(pointer);
47580    var ctx = this.canvas.contextTop;
47581
47582    ctx.fillStyle = point.fill;
47583    ctx.beginPath();
47584    ctx.arc(point.x, point.y, point.radius, 0, Math.PI * 2, false);
47585    ctx.closePath();
47586    ctx.fill();
47587  },
47588
47589  /**
47590   * Invoked on mouse down
47591   */
47592  onMouseDown: function(pointer) {
47593    this.points.length = 0;
47594    this.canvas.clearContext(this.canvas.contextTop);
47595    this._setShadow();
47596    this.drawDot(pointer);
47597  },
47598
47599  /**
47600   * Invoked on mouse move
47601   * @param {Object} pointer
47602   */
47603  onMouseMove: function(pointer) {
47604    this.drawDot(pointer);
47605  },
47606
47607  /**
47608   * Invoked on mouse up
47609   */
47610  onMouseUp: function() {
47611    var originalRenderOnAddRemove = this.canvas.renderOnAddRemove;
47612    this.canvas.renderOnAddRemove = false;
vendor: 9,591 bytes, lines 47613-48008
47613
47614    var circles = [ ];
47615
47616    for (var i = 0, len = this.points.length; i < len; i++) {
47617      var point = this.points[i];
47618      var circle = new fabric.Circle({
47619        radius: point.radius,
47620        left: point.x,
47621        top: point.y,
47622        fill: point.fill
47623      });
47624
47625      this.shadow && circle.setShadow(this.shadow);
47626
47627      circles.push(circle);
47628    }
47629    var group = new fabric.Group(circles);
47630
47631    this.canvas.add(group);
47632    this.canvas.fire('path:created', { path: group });
47633
47634    this.canvas.clearContext(this.canvas.contextTop);
47635    this._resetShadow();
47636    this.canvas.renderOnAddRemove = originalRenderOnAddRemove;
47637    this.canvas.renderAll();
47638  },
47639
47640  /**
47641   * @param {Object} pointer
47642   * @return {fabric.Point} Just added pointer point
47643   */
47644  addPoint: function(pointer) {
47645    var pointerPoint = new fabric.Point(pointer.x, pointer.y);
47646
47647    var circleRadius = fabric.util.getRandomInt(
47648                        Math.max(0, this.width - 20), this.width + 20) / 2;
47649
47650    var circleColor = new fabric.Color(this.color)
47651                        .setAlpha(fabric.util.getRandomInt(0, 100) / 100)
47652                        .toRgba();
47653
47654    pointerPoint.radius = circleRadius;
47655    pointerPoint.fill = circleColor;
47656
47657    this.points.push(pointerPoint);
47658
47659    return pointerPoint;
47660  }
47661});
47662
47663
47664/**
47665 * SprayBrush class
47666 * @class fabric.SprayBrush
47667 */
47668fabric.SprayBrush = fabric.util.createClass( fabric.BaseBrush, /** @lends fabric.SprayBrush.prototype */ {
47669
47670  /**
47671   * Width of a spray
47672   * @type Number
47673   * @default
47674   */
47675  width:              10,
47676
47677  /**
47678   * Density of a spray (number of dots per chunk)
47679   * @type Number
47680   * @default
47681   */
47682  density:            20,
47683
47684  /**
47685   * Width of spray dots
47686   * @type Number
47687   * @default
47688   */
47689  dotWidth:           1,
47690
47691  /**
47692   * Width variance of spray dots
47693   * @type Number
47694   * @default
47695   */
47696  dotWidthVariance:   1,
47697
47698  /**
47699   * Whether opacity of a dot should be random
47700   * @type Boolean
47701   * @default
47702   */
47703  randomOpacity:        false,
47704
47705  /**
47706   * Whether overlapping dots (rectangles) should be removed (for performance reasons)
47707   * @type Boolean
47708   * @default
47709   */
47710  optimizeOverlapping:  true,
47711
47712  /**
47713   * Constructor
47714   * @param {fabric.Canvas} canvas
47715   * @return {fabric.SprayBrush} Instance of a spray brush
47716   */
47717  initialize: function(canvas) {
47718    this.canvas = canvas;
47719    this.sprayChunks = [ ];
47720  },
47721
47722  /**
47723   * Invoked on mouse down
47724   * @param {Object} pointer
47725   */
47726  onMouseDown: function(pointer) {
47727    this.sprayChunks.length = 0;
47728    this.canvas.clearContext(this.canvas.contextTop);
47729    this._setShadow();
47730
47731    this.addSprayChunk(pointer);
47732    this.render();
47733  },
47734
47735  /**
47736   * Invoked on mouse move
47737   * @param {Object} pointer
47738   */
47739  onMouseMove: function(pointer) {
47740    this.addSprayChunk(pointer);
47741    this.render();
47742  },
47743
47744  /**
47745   * Invoked on mouse up
47746   */
47747  onMouseUp: function() {
47748    var originalRenderOnAddRemove = this.canvas.renderOnAddRemove;
47749    this.canvas.renderOnAddRemove = false;
47750
47751    var rects = [ ];
47752
47753    for (var i = 0, ilen = this.sprayChunks.length; i < ilen; i++) {
47754      var sprayChunk = this.sprayChunks[i];
47755
47756      for (var j = 0, jlen = sprayChunk.length; j < jlen; j++) {
47757
47758        var rect = new fabric.Rect({
47759          width: sprayChunk[j].width,
47760          height: sprayChunk[j].width,
47761          left: sprayChunk[j].x + 1,
47762          top: sprayChunk[j].y + 1,
47763          fill: this.color
47764        });
47765
47766        this.shadow && rect.setShadow(this.shadow);
47767        rects.push(rect);
47768      }
47769    }
47770
47771    if (this.optimizeOverlapping) {
47772      rects = this._getOptimizedRects(rects);
47773    }
47774
47775    var group = new fabric.Group(rects);
47776    this.canvas.add(group);
47777    this.canvas.fire('path:created', { path: group });
47778
47779    this.canvas.clearContext(this.canvas.contextTop);
47780    this._resetShadow();
47781    this.canvas.renderOnAddRemove = originalRenderOnAddRemove;
47782    this.canvas.renderAll();
47783  },
47784
47785  _getOptimizedRects: function(rects) {
47786
47787    // avoid creating duplicate rects at the same coordinates
47788    var uniqueRects = { }, key;
47789
47790    for (var i = 0, len = rects.length; i < len; i++) {
47791      key = rects[i].left + '' + rects[i].top;
47792      if (!uniqueRects[key]) {
47793        uniqueRects[key] = rects[i];
47794      }
47795    }
47796    var uniqueRectsArray = [ ];
47797    for (key in uniqueRects) {
47798      uniqueRectsArray.push(uniqueRects[key]);
47799    }
47800
47801    return uniqueRectsArray;
47802  },
47803
47804  /**
47805   * Renders brush
47806   */
47807  render: function() {
47808    var ctx = this.canvas.contextTop;
47809    ctx.fillStyle = this.color;
47810    ctx.save();
47811
47812    for (var i = 0, len = this.sprayChunkPoints.length; i < len; i++) {
47813      var point = this.sprayChunkPoints[i];
47814      if (typeof point.opacity !== 'undefined') {
47815        ctx.globalAlpha = point.opacity;
47816      }
47817      ctx.fillRect(point.x, point.y, point.width, point.width);
47818    }
47819    ctx.restore();
47820  },
47821
47822  /**
47823   * @param {Object} pointer
47824   */
47825  addSprayChunk: function(pointer) {
47826    this.sprayChunkPoints = [ ];
47827
47828    var x, y, width, radius = this.width / 2;
47829
47830    for (var i = 0; i < this.density; i++) {
47831
47832      x = fabric.util.getRandomInt(pointer.x - radius, pointer.x + radius);
47833      y = fabric.util.getRandomInt(pointer.y - radius, pointer.y + radius);
47834
47835      if (this.dotWidthVariance) {
47836        width = fabric.util.getRandomInt(
47837          // bottom clamp width to 1
47838          Math.max(1, this.dotWidth - this.dotWidthVariance),
47839          this.dotWidth + this.dotWidthVariance);
47840      }
47841      else {
47842        width = this.dotWidth;
47843      }
47844
47845      var point = { x: x, y: y, width: width };
47846
47847      if (this.randomOpacity) {
47848        point.opacity = fabric.util.getRandomInt(0, 100) / 100;
47849      }
47850
47851      this.sprayChunkPoints.push(point);
47852    }
47853
47854    this.sprayChunks.push(this.sprayChunkPoints);
47855  }
47856});
47857
47858
47859/**
47860 * PatternBrush class
47861 * @class fabric.PatternBrush
47862 * @extends fabric.BaseBrush
47863 */
47864fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fabric.PatternBrush.prototype */ {
47865
47866  getPatternSrc: function() {
47867
47868    var dotWidth = 20,
47869        dotDistance = 5,
47870        patternCanvas = fabric.document.createElement('canvas'),
47871        patternCtx = patternCanvas.getContext('2d');
47872
47873    patternCanvas.width = patternCanvas.height = dotWidth + dotDistance;
47874
47875    patternCtx.fillStyle = this.color;
47876    patternCtx.beginPath();
47877    patternCtx.arc(dotWidth / 2, dotWidth / 2, dotWidth / 2, 0, Math.PI * 2, false);
47878    patternCtx.closePath();
47879    patternCtx.fill();
47880
47881    return patternCanvas;
47882  },
47883
47884  getPatternSrcFunction: function() {
47885    return String(this.getPatternSrc).replace('this.color', '"' + this.color + '"');
47886  },
47887
47888  /**
47889   * Creates "pattern" instance property
47890   */
47891  getPattern: function() {
47892    return this.canvas.contextTop.createPattern(this.source || this.getPatternSrc(), 'repeat');
47893  },
47894
47895  /**
47896   * Sets brush styles
47897   */
47898  _setBrushStyles: function() {
47899    this.callSuper('_setBrushStyles');
47900    this.canvas.contextTop.strokeStyle = this.getPattern();
47901  },
47902
47903  /**
47904   * Creates path
47905   */
47906  createPath: function(pathData) {
47907    var path = this.callSuper('createPath', pathData);
47908    path.stroke = new fabric.Pattern({
47909      source: this.source || this.getPatternSrcFunction()
47910    });
47911    return path;
47912  }
47913});
47914
47915
47916(function() {
47917
47918  var getPointer = fabric.util.getPointer,
47919      degreesToRadians = fabric.util.degreesToRadians,
47920      radiansToDegrees = fabric.util.radiansToDegrees,
47921      atan2 = Math.atan2,
47922      abs = Math.abs,
47923      min = Math.min,
47924      max = Math.max,
47925
47926      STROKE_OFFSET = 0.5;
47927
47928  /**
47929   * Canvas class
47930   * @class fabric.Canvas
47931   * @extends fabric.StaticCanvas
47932   * @tutorial {@link http://fabricjs.com/fabric-intro-part-1/#canvas}
47933   *
47934   * @fires object:modified
47935   * @fires object:rotating
47936   * @fires object:scaling
47937   * @fires object:moving
47938   * @fires object:selected
47939   *
47940   * @fires before:selection:cleared
47941   * @fires selection:cleared
47942   * @fires selection:created
47943   *
47944   * @fires path:created
47945   * @fires mouse:down
47946   * @fires mouse:move
47947   * @fires mouse:up
47948   *
47949   */
47950  fabric.Canvas = fabric.util.createClass(fabric.StaticCanvas, /** @lends fabric.Canvas.prototype */ {
47951
47952    /**
47953     * Constructor
47954     * @param {HTMLElement | String} el &lt;canvas> element to initialize instance on
47955     * @param {Object} [options] Options object
47956     * @return {Object} thisArg
47957     */
47958    initialize: function(el, options) {
47959      options || (options = { });
47960
47961      this._initStatic(el, options);
47962      this._initInteractive();
47963      this._createCacheCanvas();
47964
47965      fabric.Canvas.activeInstance = this;
47966    },
47967
47968    /**
47969     * When true, objects can be transformed by one side (unproportionally)
47970     * @type Boolean
47971     * @default
47972     */
47973    uniScaleTransform:      false,
47974
47975    /**
47976     * When true, objects use center point as the origin of scale transformation.
47977     * <b>Backwards incompatibility note:</b> This property replaces "centerTransform" (Boolean).
47978     * @since 1.3.4
47979     * @type Boolean
47980     * @default
47981     */
47982    centeredScaling:        false,
47983
47984    /**
47985     * When true, objects use center point as the origin of rotate transformation.
47986     * <b>Backwards incompatibility note:</b> This property replaces "centerTransform" (Boolean).
47987     * @since 1.3.4
47988     * @type Boolean
47989     * @default
47990     */
47991    centeredRotation:       false,
47992
47993    /**
47994     * Indicates that canvas is interactive. This property should not be changed.
47995     * @type Boolean
47996     * @default
47997     */
47998    interactive:            true,
47999
48000    /**
48001     * Indicates whether group selection should be enabled
48002     * @type Boolean
48003     * @default
48004     */
48005    selection:              true,
48006
48007    /**
48008     * Color of selection
48009     * @type String
48010     * @default
48011     */
48012    selectionColor:         'rgba(100, 100, 255, 0.3)', // blue
48013
48014    /**
48015     * Default dash array pattern
48016     * If not empty the selection border is dashed
48017     * @type Array
48018     */
48019    selectionDashArray:     [ ],
48020
48021    /**
48022     * Color of the border of selection (usually slightly darker than color of selection itself)
48023     * @type String
48024     * @default
48025     */
48026    selectionBorderColor:   'rgba(255, 255, 255, 0.3)',
48027
48028    /**
48029     * Width of a line used in object/group selection
48030     * @type Number
48031     * @default
48032     */
48033    selectionLineWidth:     1,
48034
48035    /**
48036     * Default cursor value used when hovering over an object on canvas
48037     * @type String
48038     * @default
48039     */
48040    hoverCursor:            'move',
48041
48042    /**
48043     * Default cursor value used when moving an object on canvas
48044     * @type String
48045     * @default
48046     */
48047    moveCursor:             'move',
48048
48049    /**
48050     * Default cursor value used for the entire canvas
48051     * @type String
48052     * @default
48053     */
48054    defaultCursor:          'default',
48055
48056    /**
48057     * Cursor value used during free drawing
48058     * @type String
48059     * @default
48060     */
48061    freeDrawingCursor:      'crosshair',
48062
48063    /**
48064     * Cursor value used for rotation point
48065     * @type String
48066     * @default
48067     */
48068    rotationCursor:         'crosshair',
48069
48070    /**
48071     * Default element class that's given to wrapper (div) element of canvas
48072     * @type String
48073     * @default
48074     */
48075    containerClass:         'canvas-container',
48076
48077    /**
48078     * When true, object detection happens on per-pixel basis rather than on per-bounding-box
48079     * @type Boolean
48080     * @default
48081     */
48082    perPixelTargetFind:     false,
48083
48084    /**
48085     * Number of pixels around target pixel to tolerate (consider active) during object detection
48086     * @type Number
48087     * @default
48088     */
48089    targetFindTolerance:    0,
48090
48091    /**
48092     * When true, target detection is skipped when hovering over canvas. This can be used to improve performance.
48093     * @type Boolean
48094     * @default
48095     */
48096    skipTargetFind:         false,
48097
48098    /**
48099     * @private
48100     */
48101    _initInteractive: function() {
48102      this._currentTransform = null;
48103      this._groupSelector = null;
48104      this._initWrapperElement();
48105      this._createUpperCanvas();
48106      this._initEvents();
48107
48108      this.freeDrawingBrush = fabric.PencilBrush && new fabric.PencilBrush(this);
48109
48110      this.calcOffset();
48111    },
48112
48113    /**
48114     * Resets the current transform to its original values and chooses the type of resizing based on the event
48115     * @private
48116     * @param {Event} e Event object fired on mousemove
48117     */
48118    _resetCurrentTransform: function(e) {
48119      var t = this._currentTransform;
48120
48121      t.target.set({
48122        'scaleX': t.original.scaleX,
48123        'scaleY': t.original.scaleY,
48124        'left': t.original.left,
48125        'top': t.original.top
48126      });
48127
48128      if (this._shouldCenterTransform(e, t.target)) {
48129        if (t.action === 'rotate') {
48130          this._setOriginToCenter(t.target);
48131        }
48132        else {
48133          if (t.originX !== 'center') {
48134            if (t.originX === 'right') {
48135              t.mouseXSign = -1;
48136            }
48137            else {
48138              t.mouseXSign = 1;
48139            }
48140          }
48141          if (t.originY !== 'center') {
48142            if (t.originY === 'bottom') {
48143              t.mouseYSign = -1;
48144            }
48145            else {
48146              t.mouseYSign = 1;
48147            }
48148          }
48149
48150          t.originX = 'center';
48151          t.originY = 'center';
48152        }
48153      }
48154      else {
48155        t.originX = t.original.originX;
48156        t.originY = t.original.originY;
48157      }
48158    },
48159
48160    /**
48161     * Checks if point is contained within an area of given object
48162     * @param {Event} e Event object
48163     * @param {fabric.Object} target Object to test against
48164     * @return {Boolean} true if point is contained within an area of given object
48165     */
48166    containsPoint: function (e, target) {
48167      var pointer = this.getPointer(e),
48168          xy = this._normalizePointer(target, pointer);
48169
48170      // http://www.geog.ubc.ca/courses/klink/gis.notes/ncgia/u32.html
48171      // http://idav.ucdavis.edu/~okreylos/TAship/Spring2000/PointInPolygon.html
48172      return (target.containsPoint(xy) || target._findTargetCorner(e, this._offset));
48173    },
48174
48175    /**
48176     * @private
48177     */
48178    _normalizePointer: function (object, pointer) {
48179      var activeGroup = this.getActiveGroup(),
48180          x = pointer.x,
48181          y = pointer.y;
48182
48183      var isObjectInGroup = (
48184        activeGroup &&
48185        object.type !== 'group' &&
48186        activeGroup.contains(object)
48187      );
48188
48189      if (isObjectInGroup) {
48190        x -= activeGroup.left;
48191        y -= activeGroup.top;
48192      }
48193      return { x: x, y: y };
48194    },
48195
48196    /**
48197     * Returns true if object is transparent at a certain location
48198     * @param {fabric.Object} target Object to check
48199     * @param {Number} x Left coordinate
48200     * @param {Number} y Top coordinate
48201     * @return {Boolean}
48202     */
48203    isTargetTransparent: function (target, x, y) {
48204      var cacheContext = this.contextCache;
48205
48206      var hasBorders = target.hasBorders,
48207          transparentCorners = target.transparentCorners;
48208
48209      target.hasBorders = target.transparentCorners = false;
48210
48211      this._draw(cacheContext, target);
48212
48213      target.hasBorders = hasBorders;
48214      target.transparentCorners = transparentCorners;
48215
48216      // If tolerance is > 0 adjust start coords to take into account. If moves off Canvas fix to 0
48217      if (this.targetFindTolerance > 0) {
48218        if (x > this.targetFindTolerance) {
48219          x -= this.targetFindTolerance;
48220        }
48221        else {
48222          x = 0;
48223        }
48224        if (y > this.targetFindTolerance) {
48225          y -= this.targetFindTolerance;
48226        }
48227        else {
48228          y = 0;
48229        }
48230      }
48231
48232      var isTransparent = true;
48233      var imageData = cacheContext.getImageData(
48234        x, y, (this.targetFindTolerance * 2) || 1, (this.targetFindTolerance * 2) || 1);
48235
48236      // Split image data - for tolerance > 1, pixelDataSize = 4;
48237      for (var i = 3, l = imageData.data.length; i < l; i += 4) {
48238        var temp = imageData.data[i];
48239        isTransparent = temp <= 0;
48240        if (isTransparent === false) break; //Stop if colour found
48241      }
48242
48243      imageData = null;
48244      this.clearContext(cacheContext);
48245
48246      return isTransparent;
48247    },
48248
48249    /**
48250     * @private
48251     * @param {Event} e Event object
48252     * @param {fabric.Object} target
48253     */
48254    _shouldClearSelection: function (e, target) {
48255      var activeGroup = this.getActiveGroup();
48256
48257      return (
48258        !target || (
48259        target &&
48260        activeGroup &&
48261        !activeGroup.contains(target) &&
48262        activeGroup !== target &&
48263        !e.shiftKey) || (
48264        target &&
48265        !target.evented)
48266      );
48267    },
48268
48269    /**
48270     * @private
48271     * @param {Event} e Event object
48272     * @param {fabric.Object} target
48273     */
48274    _shouldCenterTransform: function (e, target) {
48275      if (!target) return;
48276
48277      var t = this._currentTransform,
48278          centerTransform;
48279
48280      if (t.action === 'scale' || t.action === 'scaleX' || t.action === 'scaleY') {
48281        centerTransform = this.centeredScaling || target.centeredScaling;
48282      }
48283      else if (t.action === 'rotate') {
48284        centerTransform = this.centeredRotation || target.centeredRotation;
48285      }
48286
48287      return centerTransform ? !e.altKey : e.altKey;
48288    },
48289
48290    /**
48291     * @private
48292     * @param {Event} e Event object
48293     * @param {fabric.Object} target
48294     */
48295    _setupCurrentTransform: function (e, target) {
48296      if (!target) return;
48297
48298      var action = 'drag',
48299          corner,
48300          pointer = getPointer(e, target.canvas.upperCanvasEl);
48301
48302      corner = target._findTargetCorner(e, this._offset);
48303      if (corner) {
48304        action = (corner === 'ml' || corner === 'mr')
48305          ? 'scaleX'
48306          : (corner === 'mt' || corner === 'mb')
48307            ? 'scaleY'
48308            : corner === 'mtr'
48309              ? 'rotate'
48310              : 'scale';
48311      }
48312
48313      var originX = target.originX,
48314          originY = target.originY;
48315
48316      if (corner === 'ml' || corner === 'tl' || corner === 'bl') {
48317        originX = "right";
48318      }
48319      else if (corner === 'mr' || corner === 'tr' || corner === 'br') {
48320        originX = "left";
48321      }
48322
48323      if (corner === 'tl' || corner === 'mt' || corner === 'tr') {
48324        originY = "bottom";
48325      }
48326      else if (corner === 'bl' || corner === 'mb' || corner === 'br') {
48327        originY = "top";
48328      }
48329
48330      this._currentTransform = {
48331        target: target,
48332        action: action,
48333        scaleX: target.scaleX,
48334        scaleY: target.scaleY,
48335        offsetX: pointer.x - target.left,
48336        offsetY: pointer.y - target.top,
48337        originX: originX,
48338        originY: originY,
48339        ex: pointer.x,
48340        ey: pointer.y,
48341        left: target.left,
48342        top: target.top,
48343        theta: degreesToRadians(target.angle),
48344        width: target.width * target.scaleX,
48345        mouseXSign: 1,
48346        mouseYSign: 1
48347      };
48348
48349      this._currentTransform.original = {
48350        left: target.left,
48351        top: target.top,
48352        scaleX: target.scaleX,
48353        scaleY: target.scaleY,
48354        originX: originX,
48355        originY: originY
48356      };
48357
48358      this._resetCurrentTransform(e);
48359    },
48360
48361    /**
48362     * @private
48363     * @param {Event} e Event object
48364     * @param {fabric.Object} target
48365     * @return {Boolean}
48366     */
48367    _shouldHandleGroupLogic: function(e, target) {
48368      var activeObject = this.getActiveObject();
48369      return e.shiftKey &&
48370            (this.getActiveGroup() || (activeObject && activeObject !== target))
48371            && this.selection;
48372    },
48373
48374    /**
48375     * @private
48376     * @param {Event} e Event object
48377     * @param {fabric.Object} target
48378     */
48379    _handleGroupLogic: function (e, target) {
48380      if (target === this.getActiveGroup()) {
48381        // if it's a group, find target again, this time skipping group
48382        target = this.findTarget(e, true);
48383        // if even object is not found, bail out
48384        if (!target || target.isType('group')) {
48385          return;
48386        }
48387      }
48388      var activeGroup = this.getActiveGroup();
48389      if (activeGroup) {
48390        if (activeGroup.contains(target)) {
48391          activeGroup.removeWithUpdate(target);
48392          this._resetObjectTransform(activeGroup);
48393          target.set('active', false);
48394          if (activeGroup.size() === 1) {
48395            // remove group alltogether if after removal it only contains 1 object
48396            this.discardActiveGroup();
48397          }
48398        }
48399        else {
48400          activeGroup.addWithUpdate(target);
48401          this._resetObjectTransform(activeGroup);
48402        }
48403        this.fire('selection:created', { target: activeGroup, e: e });
48404        activeGroup.set('active', true);
48405      }
48406      else {
48407        // group does not exist
48408        if (this._activeObject) {
48409          // only if there's an active object
48410          if (target !== this._activeObject) {
48411            // and that object is not the actual target
48412            var objects = this.getObjects();
48413            var isActiveLower = objects.indexOf(this._activeObject) < objects.indexOf(target);
48414            var group = new fabric.Group(
48415              isActiveLower ? [ target, this._activeObject ] : [ this._activeObject, target ]);
48416
48417            this.setActiveGroup(group);
48418            this._activeObject = null;
48419            activeGroup = this.getActiveGroup();
48420            this.fire('selection:created', { target: activeGroup, e: e });
48421          }
48422        }
48423        // activate target object in any case
48424        target.set('active', true);
48425      }
48426
48427      if (activeGroup) {
48428        activeGroup.saveCoords();
48429      }
48430    },
48431
48432    /**
48433     * Translates object by "setting" its left/top
48434     * @private
48435     * @param x {Number} pointer's x coordinate
48436     * @param y {Number} pointer's y coordinate
48437     */
48438    _translateObject: function (x, y) {
48439      var target = this._currentTransform.target;
48440
48441      if (!target.get('lockMovementX')) {
48442        target.set('left', x - this._currentTransform.offsetX);
48443      }
48444      if (!target.get('lockMovementY')) {
48445        target.set('top', y - this._currentTransform.offsetY);
48446      }
48447    },
48448
48449    /**
48450     * Scales object by invoking its scaleX/scaleY methods
48451     * @private
48452     * @param x {Number} pointer's x coordinate
48453     * @param y {Number} pointer's y coordinate
48454     * @param by {String} Either 'x' or 'y' - specifies dimension constraint by which to scale an object.
48455     *                    When not provided, an object is scaled by both dimensions equally
48456     */
48457    _scaleObject: function (x, y, by) {
48458      var t = this._currentTransform,
48459          offset = this._offset,
48460          target = t.target;
48461
48462      var lockScalingX = target.get('lockScalingX'),
48463          lockScalingY = target.get('lockScalingY');
48464
48465      if (lockScalingX && lockScalingY) return;
48466
48467      // Get the constraint point
48468      var constraintPosition = target.translateToOriginPoint(target.getCenterPoint(), t.originX, t.originY);
48469      var localMouse = target.toLocalPoint(new fabric.Point(x - offset.left, y - offset.top), t.originX, t.originY);
48470
48471      if (t.originX === 'right') {
48472        localMouse.x *= -1;
48473      }
48474      else if (t.originX === 'center') {
48475        localMouse.x *= t.mouseXSign * 2;
48476
48477        if (localMouse.x < 0) {
48478          t.mouseXSign = -t.mouseXSign;
48479        }
48480      }
48481
48482      if (t.originY === 'bottom') {
48483        localMouse.y *= -1;
48484      }
48485      else if (t.originY === 'center') {
48486        localMouse.y *= t.mouseYSign * 2;
48487
48488        if (localMouse.y < 0) {
48489          t.mouseYSign = -t.mouseYSign;
48490        }
48491      }
48492
48493      // adjust the mouse coordinates when dealing with padding
48494      if (abs(localMouse.x) > target.padding) {
48495        if (localMouse.x < 0 ) {
48496          localMouse.x += target.padding;
48497        } else {
48498          localMouse.x -= target.padding;
48499        }
48500      } else { // mouse is within the padding, set to 0
48501        localMouse.x = 0;
48502      }
48503
48504      if (abs(localMouse.y) > target.padding) {
48505        if (localMouse.y < 0 ) {
48506          localMouse.y += target.padding;
48507        } else {
48508          localMouse.y -= target.padding;
48509        }
48510      } else {
48511        localMouse.y = 0;
48512      }
48513
48514      // Actually scale the object
48515      var newScaleX = target.scaleX, newScaleY = target.scaleY;
48516      if (by === 'equally' && !lockScalingX && !lockScalingY) {
48517        var dist = localMouse.y + localMouse.x;
48518        var lastDist = (target.height + (target.strokeWidth)) * t.original.scaleY +
48519                       (target.width + (target.strokeWidth)) * t.original.scaleX;
48520
48521        // We use t.scaleX/Y instead of target.scaleX/Y because the object may have a min scale and we'll loose the proportions
48522        newScaleX = t.original.scaleX * dist/lastDist;
48523        newScaleY = t.original.scaleY * dist/lastDist;
48524
48525        target.set('scaleX', newScaleX);
48526        target.set('scaleY', newScaleY);
48527      }
48528      else if (!by) {
48529        newScaleX = localMouse.x/(target.width+target.strokeWidth);
48530        newScaleY = localMouse.y/(target.height+target.strokeWidth);
48531
48532        lockScalingX || target.set('scaleX', newScaleX);
48533        lockScalingY || target.set('scaleY', newScaleY);
48534      }
48535      else if (by === 'x' && !target.get('lockUniScaling')) {
48536        newScaleX = localMouse.x/(target.width + target.strokeWidth);
48537        lockScalingX || target.set('scaleX', newScaleX);
48538      }
48539      else if (by === 'y' && !target.get('lockUniScaling')) {
48540        newScaleY = localMouse.y/(target.height + target.strokeWidth);
48541        lockScalingY || target.set('scaleY', newScaleY);
48542      }
48543
48544      // Check if we flipped
48545      if (newScaleX < 0)
48546      {
48547        if (t.originX === 'left')
48548          t.originX = 'right';
48549        else if (t.originX === 'right')
48550          t.originX = 'left';
48551      }
48552
48553      if (newScaleY < 0)
48554      {
48555        if (t.originY === 'top')
48556          t.originY = 'bottom';
48557        else if (t.originY === 'bottom')
48558          t.originY = 'top';
48559      }
48560
48561      // Make sure the constraints apply
48562      target.setPositionByOrigin(constraintPosition, t.originX, t.originY);
48563    },
48564
48565    /**
48566     * Rotates object by invoking its rotate method
48567     * @private
48568     * @param x {Number} pointer's x coordinate
48569     * @param y {Number} pointer's y coordinate
48570     */
48571    _rotateObject: function (x, y) {
48572
48573      var t = this._currentTransform,
48574          o = this._offset;
48575
48576      if (t.target.get('lockRotation')) return;
48577
48578      var lastAngle = atan2(t.ey - t.top - o.top, t.ex - t.left - o.left),
48579          curAngle = atan2(y - t.top - o.top, x - t.left - o.left),
48580          angle = radiansToDegrees(curAngle - lastAngle + t.theta);
48581
48582      // normalize angle to positive value
48583      if (angle < 0) {
48584        angle = 360 + angle;
48585      }
48586
48587      t.target.angle = angle;
48588    },
48589
48590    /**
48591     * @private
48592     */
48593    _setCursor: function (value) {
48594      this.upperCanvasEl.style.cursor = value;
48595    },
48596
48597    /**
48598     * @private
48599     */
48600    _resetObjectTransform: function (target) {
48601      target.scaleX = 1;
48602      target.scaleY = 1;
48603      target.setAngle(0);
48604    },
48605
48606    /**
48607     * @private
48608     */
48609    _drawSelection: function () {
48610      var ctx = this.contextTop,
48611          groupSelector = this._groupSelector,
48612          left = groupSelector.left,
48613          top = groupSelector.top,
48614          aleft = abs(left),
48615          atop = abs(top);
48616
48617      ctx.fillStyle = this.selectionColor;
48618
48619      ctx.fillRect(
48620        groupSelector.ex - ((left > 0) ? 0 : -left),
48621        groupSelector.ey - ((top > 0) ? 0 : -top),
48622        aleft,
48623        atop
48624      );
48625
48626      ctx.lineWidth = this.selectionLineWidth;
48627      ctx.strokeStyle = this.selectionBorderColor;
48628
48629      // selection border
48630      if (this.selectionDashArray.length > 1) {
48631
48632        var px = groupSelector.ex + STROKE_OFFSET - ((left > 0) ? 0: aleft);
48633        var py = groupSelector.ey + STROKE_OFFSET - ((top > 0) ? 0: atop);
48634
48635        ctx.beginPath();
48636
48637        fabric.util.drawDashedLine(ctx, px, py, px+aleft, py, this.selectionDashArray);
48638        fabric.util.drawDashedLine(ctx, px, py+atop-1, px+aleft, py+atop-1, this.selectionDashArray);
48639        fabric.util.drawDashedLine(ctx, px, py, px, py+atop, this.selectionDashArray);
48640        fabric.util.drawDashedLine(ctx, px+aleft-1, py, px+aleft-1, py+atop, this.selectionDashArray);
48641
48642        ctx.closePath();
48643        ctx.stroke();
48644      }
48645      else {
48646        ctx.strokeRect(
48647          groupSelector.ex + STROKE_OFFSET - ((left > 0) ? 0 : aleft),
48648          groupSelector.ey + STROKE_OFFSET - ((top > 0) ? 0 : atop),
48649          aleft,
48650          atop
48651        );
48652      }
48653    },
48654
48655    /**
48656     * @private
48657     */
48658    _findSelectedObjects: function (e) {
48659      var group = [ ],
48660          x1 = this._groupSelector.ex,
48661          y1 = this._groupSelector.ey,
48662          x2 = x1 + this._groupSelector.left,
48663          y2 = y1 + this._groupSelector.top,
48664          currentObject,
48665          selectionX1Y1 = new fabric.Point(min(x1, x2), min(y1, y2)),
48666          selectionX2Y2 = new fabric.Point(max(x1, x2), max(y1, y2)),
48667          isClick = x1 === x2 && y1 === y2;
48668
48669      for (var i = this._objects.length; i--; ) {
48670        currentObject = this._objects[i];
48671
48672        if (!currentObject) continue;
48673
48674        if (currentObject.intersectsWithRect(selectionX1Y1, selectionX2Y2) ||
48675            currentObject.isContainedWithinRect(selectionX1Y1, selectionX2Y2) ||
48676            currentObject.containsPoint(selectionX1Y1) ||
48677            currentObject.containsPoint(selectionX2Y2)) {
48678
48679          if (this.selection && currentObject.selectable) {
48680            currentObject.set('active', true);
48681            group.push(currentObject);
48682
48683            // only add one object if it's a click
48684            if (isClick) break;
48685          }
48686        }
48687      }
48688
48689      // do not create group for 1 element only
48690      if (group.length === 1) {
48691        this.setActiveObject(group[0], e);
48692      }
48693      else if (group.length > 1) {
48694        group = new fabric.Group(group.reverse());
48695        this.setActiveGroup(group);
48696        group.saveCoords();
48697        this.fire('selection:created', { target: group });
48698        this.renderAll();
48699      }
48700    },
48701
48702    /**
48703     * Method that determines what object we are clicking on
48704     * @param {Event} e mouse event
48705     * @param {Boolean} skipGroup when true, group is skipped and only objects are traversed through
48706     */
48707    findTarget: function (e, skipGroup) {
48708      if (this.skipTargetFind) return;
48709
48710      var target,
48711          pointer = this.getPointer(e);
48712
48713      if (this.controlsAboveOverlay &&
48714          this.lastRenderedObjectWithControlsAboveOverlay &&
48715          this.lastRenderedObjectWithControlsAboveOverlay.visible &&
48716          this.containsPoint(e, this.lastRenderedObjectWithControlsAboveOverlay) &&
48717          this.lastRenderedObjectWithControlsAboveOverlay._findTargetCorner(e, this._offset)) {
48718        target = this.lastRenderedObjectWithControlsAboveOverlay;
48719        return target;
48720      }
48721
48722      // first check current group (if one exists)
48723      var activeGroup = this.getActiveGroup();
48724      if (activeGroup && !skipGroup && this.containsPoint(e, activeGroup)) {
48725        target = activeGroup;
48726        return target;
48727      }
48728
48729      // then check all of the objects on canvas
48730      // Cache all targets where their bounding box contains point.
48731      var possibleTargets = [];
48732
48733      for (var i = this._objects.length; i--; ) {
48734
48735        if (this._objects[i] &&
48736            this._objects[i].visible &&
48737            this._objects[i].evented &&
48738            this.containsPoint(e, this._objects[i])) {
48739
48740          if (this.perPixelTargetFind || this._objects[i].perPixelTargetFind) {
48741            possibleTargets[possibleTargets.length] = this._objects[i];
48742          }
48743          else {
48744            target = this._objects[i];
48745            this.relatedTarget = target;
48746            break;
48747          }
48748        }
48749      }
48750      for (var j = 0, len = possibleTargets.length; j < len; j++) {
48751        pointer = this.getPointer(e);
48752        var isTransparent = this.isTargetTransparent(possibleTargets[j], pointer.x, pointer.y);
48753        if (!isTransparent) {
48754          target = possibleTargets[j];
48755          this.relatedTarget = target;
48756          break;
48757        }
48758      }
48759
48760      return target;
48761    },
48762
48763    /**
48764     * Returns pointer coordinates relative to canvas.
48765     * @param {Event} e
48766     * @return {Object} object with "x" and "y" number values
48767     */
48768    getPointer: function (e) {
48769      var pointer = getPointer(e, this.upperCanvasEl);
48770      return {
48771        x: pointer.x - this._offset.left,
48772        y: pointer.y - this._offset.top
48773      };
48774    },
48775
48776    /**
48777     * @private
48778     * @param {HTMLElement|String} canvasEl Canvas element
48779     * @throws {CANVAS_INIT_ERROR} If canvas can not be initialized
48780     */
48781    _createUpperCanvas: function () {
48782      var lowerCanvasClass = this.lowerCanvasEl.className.replace(/\s*lower-canvas\s*/, '');
48783
48784      this.upperCanvasEl = this._createCanvasElement();
48785      fabric.util.addClass(this.upperCanvasEl, 'upper-canvas ' + lowerCanvasClass);
48786
48787      this.wrapperEl.appendChild(this.upperCanvasEl);
48788
48789      this._copyCanvasStyle(this.lowerCanvasEl, this.upperCanvasEl);
48790      this._applyCanvasStyle(this.upperCanvasEl);
48791      this.contextTop = this.upperCanvasEl.getContext('2d');
48792    },
48793
48794    /**
48795     * @private
48796     */
48797    _createCacheCanvas: function () {
48798      this.cacheCanvasEl = this._createCanvasElement();
48799      this.cacheCanvasEl.setAttribute('width', this.width);
48800      this.cacheCanvasEl.setAttribute('height', this.height);
48801      this.contextCache = this.cacheCanvasEl.getContext('2d');
48802    },
48803
48804    /**
48805     * @private
48806     * @param {Number} width
48807     * @param {Number} height
48808     */
48809    _initWrapperElement: function () {
48810      this.wrapperEl = fabric.util.wrapElement(this.lowerCanvasEl, 'div', {
48811        'class': this.containerClass
48812      });
48813      fabric.util.setStyle(this.wrapperEl, {
48814        width: this.getWidth() + 'px',
48815        height: this.getHeight() + 'px',
48816        position: 'relative'
48817      });
48818      fabric.util.makeElementUnselectable(this.wrapperEl);
48819    },
48820
48821    /**
48822     * @private
48823     * @param {Element} element
48824     */
48825    _applyCanvasStyle: function (element) {
48826      var width = this.getWidth() || element.width,
48827          height = this.getHeight() || element.height;
48828
48829      fabric.util.setStyle(element, {
48830        position: 'absolute',
48831        width: width + 'px',
48832        height: height + 'px',
48833        left: 0,
48834        top: 0
48835      });
48836      element.width = width;
48837      element.height = height;
48838      fabric.util.makeElementUnselectable(element);
48839    },
48840
48841    /**
48842     * Copys the the entire inline style from one element (fromEl) to another (toEl)
48843     * @private
48844     * @param {Element} fromEl Element style is copied from
48845     * @param {Element} toEl Element copied style is applied to
48846     */
48847    _copyCanvasStyle: function (fromEl, toEl) {
48848      toEl.style.cssText = fromEl.style.cssText;
48849    },
48850
48851    /**
48852     * Returns context of canvas where object selection is drawn
48853     * @return {CanvasRenderingContext2D}
48854     */
48855    getSelectionContext: function() {
48856      return this.contextTop;
48857    },
48858
48859    /**
48860     * Returns &lt;canvas> element on which object selection is drawn
48861     * @return {HTMLCanvasElement}
48862     */
48863    getSelectionElement: function () {
48864      return this.upperCanvasEl;
48865    },
48866
48867    /**
48868     * Sets given object as the only active object on canvas
48869     * @param {fabric.Object} object Object to set as an active one
48870     * @param {Event} [e] Event (passed along when firing "object:selected")
48871     * @return {fabric.Canvas} thisArg
48872     * @chainable
48873     */
48874    setActiveObject: function (object, e) {
48875      if (this._activeObject) {
48876        this._activeObject.set('active', false);
48877      }
48878      this._activeObject = object;
48879      object.set('active', true);
48880
48881      this.renderAll();
48882
48883      this.fire('object:selected', { target: object, e: e });
48884      object.fire('selected', { e: e });
48885      return this;
48886    },
48887
48888    /**
48889     * Returns currently active object
48890     * @return {fabric.Object} active object
48891     */
48892    getActiveObject: function () {
48893      return this._activeObject;
48894    },
48895
48896    /**
48897     * Discards currently active object
48898     * @return {fabric.Canvas} thisArg
48899     * @chainable
48900     */
48901    discardActiveObject: function () {
48902      if (this._activeObject) {
48903        this._activeObject.set('active', false);
48904      }
48905      this._activeObject = null;
48906      return this;
48907    },
48908
48909    /**
48910     * Sets active group to a speicified one
48911     * @param {fabric.Group} group Group to set as a current one
48912     * @return {fabric.Canvas} thisArg
48913     * @chainable
48914     */
48915    setActiveGroup: function (group) {
48916      this._activeGroup = group;
48917      if (group) {
48918        group.canvas = this;
48919        group.set('active', true);
48920      }
48921      return this;
48922    },
48923
48924    /**
48925     * Returns currently active group
48926     * @return {fabric.Group} Current group
48927     */
48928    getActiveGroup: function () {
48929      return this._activeGroup;
48930    },
48931
48932    /**
48933     * Removes currently active group
48934     * @return {fabric.Canvas} thisArg
48935     */
48936    discardActiveGroup: function () {
48937      var g = this.getActiveGroup();
48938      if (g) {
48939        g.destroy();
48940      }
48941      return this.setActiveGroup(null);
48942    },
48943
48944    /**
48945     * Deactivates all objects on canvas, removing any active group or object
48946     * @return {fabric.Canvas} thisArg
48947     */
48948    deactivateAll: function () {
48949      var allObjects = this.getObjects(),
48950          i = 0,
48951          len = allObjects.length;
48952      for ( ; i < len; i++) {
48953        allObjects[i].set('active', false);
48954      }
48955      this.discardActiveGroup();
48956      this.discardActiveObject();
48957      return this;
48958    },
48959
48960    /**
48961     * Deactivates all objects and dispatches appropriate events
48962     * @return {fabric.Canvas} thisArg
48963     */
48964    deactivateAllWithDispatch: function () {
48965      var activeObject = this.getActiveGroup() || this.getActiveObject();
48966      if (activeObject) {
48967        this.fire('before:selection:cleared', { target: activeObject });
48968      }
48969      this.deactivateAll();
48970      if (activeObject) {
48971        this.fire('selection:cleared');
48972      }
48973      return this;
48974    },
48975
48976    /**
48977     * Draws objects' controls (borders/controls)
48978     * @param {CanvasRenderingContext2D} ctx Context to render controls on
48979     */
48980    drawControls: function(ctx) {
48981      var activeGroup = this.getActiveGroup();
48982      if (activeGroup) {
48983        ctx.save();
48984        fabric.Group.prototype.transform.call(activeGroup, ctx);
48985        activeGroup.drawBorders(ctx).drawControls(ctx);
48986        ctx.restore();
48987      }
48988      else {
48989        for (var i = 0, len = this._objects.length; i < len; ++i) {
48990          if (!this._objects[i] || !this._objects[i].active) continue;
48991
48992          ctx.save();
48993          fabric.Object.prototype.transform.call(this._objects[i], ctx);
48994          this._objects[i].drawBorders(ctx).drawControls(ctx);
48995          ctx.restore();
48996
48997          this.lastRenderedObjectWithControlsAboveOverlay = this._objects[i];
48998        }
48999      }
49000    }
49001  });
49002
49003  // copying static properties manually to work around Opera's bug,
49004  // where "prototype" property is enumerable and overrides existing prototype
49005  for (var prop in fabric.StaticCanvas) {
49006    if (prop !== 'prototype') {
49007      fabric.Canvas[prop] = fabric.StaticCanvas[prop];
49008    }
49009  }
49010
49011  if (fabric.isTouchSupported) {
49012    /** @ignore */
49013    fabric.Canvas.prototype._setCursorFromEvent = function() { };
49014  }
49015
49016  /**
49017   * @class fabric.Element
49018   * @alias fabric.Canvas
49019   * @deprecated Use {@link fabric.Canvas} instead.
49020   * @constructor
49021   */
49022  fabric.Element = fabric.Canvas;
49023})();
49024
49025
49026(function(){
49027
49028  var cursorMap = [
49029      'n-resize',
49030      'ne-resize',
49031      'e-resize',
49032      'se-resize',
49033      's-resize',
49034      'sw-resize',
49035      'w-resize',
49036      'nw-resize'
49037  ],
49038  cursorOffset = {
49039    'mt': 0, // n
49040    'tr': 1, // ne
49041    'mr': 2, // e
49042    'br': 3, // se
49043    'mb': 4, // s
49044    'bl': 5, // sw
49045    'ml': 6, // w
49046    'tl': 7 // nw
49047  },
49048  addListener = fabric.util.addListener,
49049  removeListener = fabric.util.removeListener,
49050  getPointer = fabric.util.getPointer;
49051
49052  fabric.util.object.extend(fabric.Canvas.prototype, /** @lends fabric.Canvas.prototype */ {
49053
49054    /**
49055     * Adds mouse listeners to canvas
49056     * @private
49057     */
49058    _initEvents: function () {
49059      var _this = this;
49060
49061      this._onMouseDown = this._onMouseDown.bind(this);
49062      this._onMouseMove = this._onMouseMove.bind(this);
49063      this._onMouseUp = this._onMouseUp.bind(this);
49064      this._onResize = this._onResize.bind(this);
49065
49066      this._onGesture = function(e, s) {
49067        _this.__onTransformGesture(e, s);
49068      };
49069
49070      addListener(fabric.window, 'resize', this._onResize);
49071
49072      if (fabric.isTouchSupported) {
49073        addListener(this.upperCanvasEl, 'touchstart', this._onMouseDown);
49074        addListener(this.upperCanvasEl, 'touchmove', this._onMouseMove);
49075
49076        if (typeof Event !== 'undefined' && 'add' in Event) {
49077          Event.add(this.upperCanvasEl, 'gesture', this._onGesture);
49078        }
49079      }
49080      else {
49081        addListener(this.upperCanvasEl, 'mousedown', this._onMouseDown);
49082        addListener(this.upperCanvasEl, 'mousemove', this._onMouseMove);
49083      }
49084    },
49085
49086    /**
49087     * @private
49088     * @param {Event} e Event object fired on mousedown
49089     */
49090    _onMouseDown: function (e) {
49091      this.__onMouseDown(e);
49092
49093      !fabric.isTouchSupported && addListener(fabric.document, 'mouseup', this._onMouseUp);
49094      fabric.isTouchSupported && addListener(fabric.document, 'touchend', this._onMouseUp);
49095
49096      !fabric.isTouchSupported && addListener(fabric.document, 'mousemove', this._onMouseMove);
49097      fabric.isTouchSupported && addListener(fabric.document, 'touchmove', this._onMouseMove);
49098
49099      !fabric.isTouchSupported && removeListener(this.upperCanvasEl, 'mousemove', this._onMouseMove);
49100      fabric.isTouchSupported && removeListener(this.upperCanvasEl, 'touchmove', this._onMouseMove);
49101    },
49102
49103    /**
49104     * @private
49105     * @param {Event} e Event object fired on mouseup
49106     */
49107    _onMouseUp: function (e) {
49108      this.__onMouseUp(e);
49109
49110      !fabric.isTouchSupported && removeListener(fabric.document, 'mouseup', this._onMouseUp);
49111      fabric.isTouchSupported && removeListener(fabric.document, 'touchend', this._onMouseUp);
49112
49113      !fabric.isTouchSupported && removeListener(fabric.document, 'mousemove', this._onMouseMove);
49114      fabric.isTouchSupported && removeListener(fabric.document, 'touchmove', this._onMouseMove);
49115
49116      !fabric.isTouchSupported && addListener(this.upperCanvasEl, 'mousemove', this._onMouseMove);
49117      fabric.isTouchSupported && addListener(this.upperCanvasEl, 'touchmove', this._onMouseMove);
49118    },
49119
49120    /**
49121     * @private
49122     * @param {Event} e Event object fired on mousemove
49123     */
49124    _onMouseMove: function (e) {
49125      !this.allowTouchScrolling && e.preventDefault && e.preventDefault();
49126      this.__onMouseMove(e);
49127    },
49128
49129    /**
49130     * @private
49131     */
49132    _onResize: function () {
49133      this.calcOffset();
49134    },
49135
49136    /**
49137     * Decides whether the canvas should be redrawn in mouseup and mousedown events.
49138     * @private
49139     * @param {Object} target
49140     * @param {Object} pointer
49141     */
49142    _shouldRender: function(target, pointer) {
49143      var activeObject = this.getActiveGroup() || this.getActiveObject();
49144
49145      return (
49146        (target && (
49147        target.isMoving ||
49148        target !== activeObject)) ||
49149        (!target && activeObject) ||
49150        (pointer &&
49151        this._previousPointer &&
49152        this.selection && (
49153        pointer.x !== this._previousPointer.x ||
49154        pointer.y !== this._previousPointer.y))
49155      );
49156    },
49157
49158    /**
49159     * Method that defines the actions when mouse is released on canvas.
49160     * The method resets the currentTransform parameters, store the image corner
49161     * position in the image object and render the canvas on top.
49162     * @private
49163     * @param {Event} e Event object fired on mouseup
49164     */
49165    __onMouseUp: function (e) {
49166      var target,
49167          pointer,
49168          render;
49169
49170      if (this.isDrawingMode && this._isCurrentlyDrawing) {
49171        this._isCurrentlyDrawing = false;
49172        if (this.clipTo) {
49173          this.contextTop.restore();
49174        }
49175        this.freeDrawingBrush.onMouseUp();
49176        this.fire('mouse:up', { e: e });
49177        return;
49178      }
49179
49180      if (this._currentTransform) {
49181
49182        var transform = this._currentTransform;
49183
49184        target = transform.target;
49185        if (target._scaling) {
49186          target._scaling = false;
49187        }
49188
49189        target.setCoords();
49190
49191        // only fire :modified event if target coordinates were changed during mousedown-mouseup
49192        if (this.stateful && target.hasStateChanged()) {
49193          this.fire('object:modified', { target: target });
49194          target.fire('modified');
49195        }
49196
49197        if (this._previousOriginX && this._previousOriginY) {
49198
49199          var originPoint = target.translateToOriginPoint(
49200            target.getCenterPoint(),
49201            this._previousOriginX,
49202            this._previousOriginY);
49203
49204          target.originX = this._previousOriginX;
49205          target.originY = this._previousOriginY;
49206
49207          target.left = originPoint.x;
49208          target.top = originPoint.y;
49209
49210          this._previousOriginX = null;
49211          this._previousOriginY = null;
49212        }
49213      }
49214      else {
49215        pointer = this.getPointer(e);
49216      }
49217
49218      render = this._shouldRender(target, pointer);
49219
49220      if (this.selection && this._groupSelector) {
49221        // group selection was completed, determine its bounds
49222        this._findSelectedObjects(e);
49223      }
49224
49225      var activeGroup = this.getActiveGroup();
49226      if (activeGroup) {
49227        activeGroup.setObjectsCoords();
49228        activeGroup.isMoving = false;
49229        this._setCursor(this.defaultCursor);
49230      }
49231
49232      // clear selection and current transformation
49233      this._groupSelector = null;
49234      this._currentTransform = null;
49235
49236      if (target) {
49237        target.isMoving = false;
49238      }
49239
49240      render && this.renderAll();
49241
49242      this._setCursorFromEvent(e, target);
49243
49244      var _this = this;
49245      setTimeout(function () {
49246        _this._setCursorFromEvent(e, target);
49247      }, 50);
49248
49249      this.fire('mouse:up', { target: target, e: e });
49250      target && target.fire('mouseup', { e: e });
49251    },
49252
49253    /**
49254     * @private
49255     * @param {Event} e Event object fired on mousedown
49256     */
49257    _onMouseDownInDrawingMode: function(e) {
49258      this._isCurrentlyDrawing = true;
49259      this.discardActiveObject().renderAll();
49260      if (this.clipTo) {
49261        fabric.util.clipContext(this, this.contextTop);
49262      }
49263      this.freeDrawingBrush.onMouseDown(this.getPointer(e));
49264      this.fire('mouse:down', { e: e });
49265    },
49266
49267    /**
49268     * Method that defines the actions when mouse is clic ked on canvas.
49269     * The method inits the currentTransform parameters and renders all the
49270     * canvas so the current image can be placed on the top canvas and the rest
49271     * in on the container one.
49272     * @private
49273     * @param {Event} e Event object fired on mousedown
49274     */
49275    __onMouseDown: function (e) {
49276      // accept only left clicks
49277      var isLeftClick  = 'which' in e ? e.which === 1 : e.button === 1;
49278      if (!isLeftClick && !fabric.isTouchSupported) return;
49279
49280      if (this.isDrawingMode) {
49281        this._onMouseDownInDrawingMode(e);
49282        return;
49283      }
49284
49285      // ignore if some object is being transformed at this moment
49286      if (this._currentTransform) return;
49287
49288      var target = this.findTarget(e),
49289          pointer = this.getPointer(e),
49290          corner,
49291          render;
49292
49293      // save pointer for check in __onMouseUp event
49294      this._previousPointer = pointer;
49295
49296      render = this._shouldRender(target, pointer);
49297
49298      if (this._shouldClearSelection(e, target)) {
49299        if (this.selection) {
49300          this._groupSelector = {
49301            ex: pointer.x,
49302            ey: pointer.y,
49303            top: 0,
49304            left: 0
49305          };
49306        }
49307        this.deactivateAllWithDispatch();
49308        target && target.selectable && this.setActiveObject(target, e);
49309      }
49310      else if (this._shouldHandleGroupLogic(e, target)) {
49311        this._handleGroupLogic(e, target);
49312        target = this.getActiveGroup();
49313      }
49314      else {
49315        // determine if it's a drag or rotate case
49316        this.stateful && target.saveState();
49317
49318        if ((corner = target._findTargetCorner(e, this._offset))) {
49319          this.onBeforeScaleRotate(target);
49320        }
49321
49322        if (target !== this.getActiveGroup() && target !== this.getActiveObject()) {
49323          this.deactivateAll();
49324          this.setActiveObject(target, e);
49325        }
49326
49327        this._setupCurrentTransform(e, target);
49328      }
49329      // we must renderAll so that active image is placed on the top canvas
49330      render && this.renderAll();
49331
49332      this.fire('mouse:down', { target: target, e: e });
49333      target && target.fire('mousedown', { e: e });
49334    },
49335
49336    /**
49337     * @private
49338     * @param {Object} target Object for that origin is set to center
49339     */
49340    _setOriginToCenter: function(target) {
49341      this._previousOriginX = this._currentTransform.target.originX;
49342      this._previousOriginY = this._currentTransform.target.originY;
49343
49344      var center = target.getCenterPoint();
49345
49346      target.originX = 'center';
49347      target.originY = 'center';
49348
49349      target.left = center.x;
49350      target.top = center.y;
49351
49352      this._currentTransform.left = target.left;
49353      this._currentTransform.top = target.top;
49354    },
49355
49356    /**
49357     * @private
49358     * @param {Object} target Object for that center is set to origin
49359     */
49360    _setCenterToOrigin: function(target) {
49361      var originPoint = target.translateToOriginPoint(
49362        target.getCenterPoint(),
49363        this._previousOriginX,
49364        this._previousOriginY);
49365
49366      target.originX = this._previousOriginX;
49367      target.originY = this._previousOriginY;
49368
49369      target.left = originPoint.x;
49370      target.top = originPoint.y;
49371
49372      this._previousOriginX = null;
49373      this._previousOriginY = null;
49374    },
49375
49376    /**
49377      * Method that defines the actions when mouse is hovering the canvas.
49378      * The currentTransform parameter will definde whether the user is rotating/scaling/translating
49379      * an image or neither of them (only hovering). A group selection is also possible and would cancel
49380      * all any other type of action.
49381      * In case of an image transformation only the top canvas will be rendered.
49382      * @private
49383      * @param {Event} e Event object fired on mousemove
49384      */
49385    __onMouseMove: function (e) {
49386      var target, pointer;
49387
49388      if (this.isDrawingMode) {
49389        if (this._isCurrentlyDrawing) {
49390          pointer = this.getPointer(e);
49391          this.freeDrawingBrush.onMouseMove(pointer);
49392        }
49393        this.upperCanvasEl.style.cursor = this.freeDrawingCursor;
49394        this.fire('mouse:move', { e: e });
49395        return;
49396      }
49397
49398      var groupSelector = this._groupSelector;
49399
49400      // We initially clicked in an empty area, so we draw a box for multiple selection.
49401      if (groupSelector) {
49402        pointer = getPointer(e, this.upperCanvasEl);
49403
49404        groupSelector.left = pointer.x - this._offset.left - groupSelector.ex;
49405        groupSelector.top = pointer.y - this._offset.top - groupSelector.ey;
49406        this.renderTop();
49407      }
49408      else if (!this._currentTransform) {
49409
49410        // alias style to elimintate unnecessary lookup
49411        var style = this.upperCanvasEl.style;
49412
49413        // Here we are hovering the canvas then we will determine
49414        // what part of the pictures we are hovering to change the caret symbol.
49415        // We won't do that while dragging or rotating in order to improve the
49416        // performance.
49417        target = this.findTarget(e);
49418
49419        if (!target || target && !target.selectable) {
49420          // no target - set default cursor
49421          style.cursor = this.defaultCursor;
49422        }
49423        else {
49424          // set proper cursor
49425          this._setCursorFromEvent(e, target);
49426        }
49427      }
49428      else {
49429        // object is being transformed (scaled/rotated/moved/etc.)
49430        pointer = getPointer(e, this.upperCanvasEl);
49431
49432        var x = pointer.x,
49433            y = pointer.y,
49434            reset = false,
49435            centerTransform,
49436            transform = this._currentTransform;
49437
49438        target = transform.target;
49439        target.isMoving = true;
49440
49441        if (transform.action === 'scale' || transform.action === 'scaleX' || transform.action === 'scaleY') {
49442          centerTransform = this._shouldCenterTransform(e, target);
49443
49444             // Switch from a normal resize to center-based
49445          if ((centerTransform && (transform.originX !== 'center' || transform.originY !== 'center')) ||
49446             // Switch from center-based resize to normal one
49447             (!centerTransform && transform.originX === 'center' && transform.originY === 'center')
49448          ) {
49449            this._resetCurrentTransform(e);
49450            reset = true;
49451          }
49452        }
49453
49454        if (transform.action === 'rotate') {
49455          this._rotateObject(x, y);
49456
49457          this.fire('object:rotating', { target: target, e: e });
49458          target.fire('rotating', { e: e });
49459        }
49460        else if (transform.action === 'scale') {
49461          // rotate object only if shift key is not pressed
49462          // and if it is not a group we are transforming
49463          if ((e.shiftKey || this.uniScaleTransform) && !target.get('lockUniScaling')) {
49464            transform.currentAction = 'scale';
49465            this._scaleObject(x, y);
49466          }
49467          else {
49468            // Switch from a normal resize to proportional
49469            if (!reset && transform.currentAction === 'scale') {
49470              this._resetCurrentTransform(e, target);
49471            }
49472
49473            transform.currentAction = 'scaleEqually';
49474            this._scaleObject(x, y, 'equally');
49475          }
49476
49477          this.fire('object:scaling', { target: target, e: e });
49478          target.fire('scaling', { e: e });
49479        }
49480        else if (transform.action === 'scaleX') {
49481          this._scaleObject(x, y, 'x');
49482
49483          this.fire('object:scaling', { target: target, e: e});
49484          target.fire('scaling', { e: e });
49485        }
49486        else if (transform.action === 'scaleY') {
49487          this._scaleObject(x, y, 'y');
49488
49489          this.fire('object:scaling', { target: target, e: e});
49490          target.fire('scaling', { e: e });
49491        }
49492        else {
49493          this._translateObject(x, y);
49494
49495          this.fire('object:moving', { target: target, e: e});
49496          target.fire('moving', { e: e });
49497          this._setCursor(this.moveCursor);
49498        }
49499
49500        this.renderAll();
49501      }
49502      this.fire('mouse:move', { target: target, e: e });
49503      target && target.fire('mousemove', { e: e });
49504    },
49505
49506    /**
49507     * Sets the cursor depending on where the canvas is being hovered.
49508     * Note: very buggy in Opera
49509     * @param {Event} e Event object
49510     * @param {Object} target Object that the mouse is hovering, if so.
49511     */
49512    _setCursorFromEvent: function (e, target) {
49513      var s = this.upperCanvasEl.style;
49514      if (!target) {
49515        s.cursor = this.defaultCursor;
49516        return false;
49517      }
49518      else {
49519        var activeGroup = this.getActiveGroup();
49520        // only show proper corner when group selection is not active
49521        var corner = target._findTargetCorner
49522                      && (!activeGroup || !activeGroup.contains(target))
49523                      && target._findTargetCorner(e, this._offset);
49524
49525        if (!corner) {
49526          s.cursor = target.hoverCursor || this.hoverCursor;
49527        }
49528        else {
49529          if (corner in cursorOffset) {
49530            var n = Math.round((target.getAngle() % 360) / 45);
49531            if (n<0) {
49532              n += 8; // full circle ahead
49533            }
49534            n += cursorOffset[corner];
49535            // normalize n to be from 0 to 7
49536            n %= 8;
49537            s.cursor = cursorMap[n];
49538          }
49539          else if (corner === 'mtr' && target.hasRotatingPoint) {
49540            s.cursor = this.rotationCursor;
49541          }
49542          else {
49543            s.cursor = this.defaultCursor;
49544            return false;
49545          }
49546        }
49547      }
49548      return true;
49549    }
49550  });
49551})();
49552
49553
49554fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ {
49555
49556  /**
49557   * Exports canvas element to a dataurl image. Note that when multiplier is used, cropping is scaled appropriately
49558   * @param {Object} [options] Options object
49559   * @param {String} [options.format=png] The format of the output image. Either "jpeg" or "png"
49560   * @param {Number} [options.quality=1] Quality level (0..1). Only used for jpeg.
49561   * @param {Number} [options.multiplier=1] Multiplier to scale by
49562   * @param {Number} [options.left] Cropping left offset. Introduced in v1.2.14
49563   * @param {Number} [options.top] Cropping top offset. Introduced in v1.2.14
49564   * @param {Number} [options.width] Cropping width. Introduced in v1.2.14
49565   * @param {Number} [options.height] Cropping height. Introduced in v1.2.14
49566   * @return {String} Returns a data: URL containing a representation of the object in the format specified by options.format
49567   * @see {@link http://jsfiddle.net/fabricjs/NfZVb/|jsFiddle demo}
49568   * @example <caption>Generate jpeg dataURL with lower quality</caption>
49569   * var dataURL = canvas.toDataURL({
49570   *   format: 'jpeg',
49571   *   quality: 0.8
49572   * });
49573   * @example <caption>Generate cropped png dataURL (clipping of canvas)</caption>
49574   * var dataURL = canvas.toDataURL({
49575   *   format: 'png',
49576   *   left: 100,
49577   *   top: 100,
49578   *   width: 200,
49579   *   height: 200
49580   * });
49581   * @example <caption>Generate double scaled png dataURL</caption>
49582   * var dataURL = canvas.toDataURL({
49583   *   format: 'png',
49584   *   multiplier: 2
49585   * });
49586   */
49587  toDataURL: function (options) {
49588    options || (options = { });
49589
49590    var format = options.format || 'png',
49591        quality = options.quality || 1,
49592        multiplier = options.multiplier || 1,
49593        cropping = {
49594          left: options.left,
49595          top: options.top,
49596          width: options.width,
49597          height: options.height
49598        };
49599
49600    if (multiplier !== 1) {
49601      return this.__toDataURLWithMultiplier(format, quality, cropping, multiplier);
49602    }
49603    else {
49604      return this.__toDataURL(format, quality, cropping);
49605    }
49606  },
49607
49608  /**
49609   * @private
49610   */
49611  __toDataURL: function(format, quality, cropping) {
49612
49613    this.renderAll(true);
49614
49615    var canvasEl = this.upperCanvasEl || this.lowerCanvasEl;
49616    var croppedCanvasEl = this.__getCroppedCanvas(canvasEl, cropping);
49617
49618    // to avoid common confusion https://github.com/kangax/fabric.js/issues/806
49619    if (format === 'jpg') {
49620      format = 'jpeg';
49621    }
49622
49623    var data = (fabric.StaticCanvas.supports('toDataURLWithQuality'))
49624              ? (croppedCanvasEl || canvasEl).toDataURL('image/' + format, quality)
49625              : (croppedCanvasEl || canvasEl).toDataURL('image/' + format);
49626
49627    this.contextTop && this.clearContext(this.contextTop);
49628    this.renderAll();
49629
49630    if (croppedCanvasEl) {
49631      croppedCanvasEl = null;
49632    }
49633
49634    return data;
49635  },
49636
49637  /**
49638   * @private
49639   */
49640  __getCroppedCanvas: function(canvasEl, cropping) {
49641
49642    var croppedCanvasEl,
49643        croppedCtx;
49644
49645    var shouldCrop = 'left' in cropping ||
49646                     'top' in cropping ||
49647                     'width' in cropping ||
49648                     'height' in cropping;
49649
49650    if (shouldCrop) {
49651
49652      croppedCanvasEl = fabric.util.createCanvasElement();
49653      croppedCtx = croppedCanvasEl.getContext('2d');
49654
49655      croppedCanvasEl.width = cropping.width || this.width;
49656      croppedCanvasEl.height = cropping.height || this.height;
49657
49658      croppedCtx.drawImage(canvasEl, -cropping.left || 0, -cropping.top || 0);
49659    }
49660
49661    return croppedCanvasEl;
49662  },
49663
49664  /**
49665   * @private
49666   */
49667  __toDataURLWithMultiplier: function(format, quality, cropping, multiplier) {
49668
49669    var origWidth = this.getWidth(),
49670        origHeight = this.getHeight(),
49671        scaledWidth = origWidth * multiplier,
49672        scaledHeight = origHeight * multiplier,
49673        activeObject = this.getActiveObject(),
49674        activeGroup = this.getActiveGroup(),
49675
49676        ctx = this.contextTop || this.contextContainer;
49677
49678    this.setWidth(scaledWidth).setHeight(scaledHeight);
49679    ctx.scale(multiplier, multiplier);
49680
49681    if (cropping.left) {
49682      cropping.left *= multiplier;
49683    }
49684    if (cropping.top) {
49685      cropping.top *= multiplier;
49686    }
49687    if (cropping.width) {
49688      cropping.width *= multiplier;
49689    }
49690    if (cropping.height) {
49691      cropping.height *= multiplier;
49692    }
49693
49694    if (activeGroup) {
49695      // not removing group due to complications with restoring it with correct state afterwords
49696      this._tempRemoveBordersControlsFromGroup(activeGroup);
49697    }
49698    else if (activeObject && this.deactivateAll) {
49699      this.deactivateAll();
49700    }
49701
49702    // restoring width, height for `renderAll` to draw
49703    // background properly (while context is scaled)
49704    this.width = origWidth;
49705    this.height = origHeight;
49706
49707    this.renderAll(true);
49708
49709    var data = this.__toDataURL(format, quality, cropping);
49710
49711    ctx.scale(1 / multiplier,  1 / multiplier);
49712    this.setWidth(origWidth).setHeight(origHeight);
49713
49714    if (activeGroup) {
49715      this._restoreBordersControlsOnGroup(activeGroup);
49716    }
49717    else if (activeObject && this.setActiveObject) {
49718      this.setActiveObject(activeObject);
49719    }
49720
49721    this.contextTop && this.clearContext(this.contextTop);
49722    this.renderAll();
49723
49724    return data;
49725  },
49726
49727  /**
49728   * Exports canvas element to a dataurl image (allowing to change image size via multiplier).
49729   * @deprecated since 1.0.13
49730   * @param {String} format (png|jpeg)
49731   * @param {Number} multiplier
49732   * @param {Number} quality (0..1)
49733   * @return {String}
49734   */
49735  toDataURLWithMultiplier: function (format, multiplier, quality) {
49736    return this.toDataURL({
49737      format: format,
49738      multiplier: multiplier,
49739      quality: quality
49740    });
49741  },
49742
49743  /**
49744   * @private
49745   */
49746  _tempRemoveBordersControlsFromGroup: function(group) {
49747    group.origHasControls = group.hasControls;
49748    group.origBorderColor = group.borderColor;
49749
49750    group.hasControls = true;
49751    group.borderColor = 'rgba(0,0,0,0)';
49752
49753    group.forEachObject(function(o) {
49754      o.origBorderColor = o.borderColor;
49755      o.borderColor = 'rgba(0,0,0,0)';
49756    });
49757  },
49758
49759  /**
49760   * @private
49761   */
49762  _restoreBordersControlsOnGroup: function(group) {
49763    group.hideControls = group.origHideControls;
49764    group.borderColor = group.origBorderColor;
49765
49766    group.forEachObject(function(o) {
49767      o.borderColor = o.origBorderColor;
49768      delete o.origBorderColor;
49769    });
49770  }
49771});
49772
49773
49774fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ {
49775
49776  /**
49777   * Populates canvas with data from the specified dataless JSON.
49778   * JSON format must conform to the one of {@link fabric.Canvas#toDatalessJSON}
49779   * @deprecated since 1.2.2
49780   * @param {String|Object} json JSON string or object
49781   * @param {Function} callback Callback, invoked when json is parsed
49782   *                            and corresponding objects (e.g: {@link fabric.Image})
49783   *                            are initialized
49784   * @param {Function} [reviver] Method for further parsing of JSON elements, called after each fabric object created.
49785   * @return {fabric.Canvas} instance
49786   * @chainable
49787   * @tutorial {@link http://fabricjs.com/fabric-intro-part-3/#deserialization}
49788   */
49789  loadFromDatalessJSON: function (json, callback, reviver) {
49790    return this.loadFromJSON(json, callback, reviver);
49791  },
49792
49793  /**
49794   * Populates canvas with data from the specified JSON.
49795   * JSON format must conform to the one of {@link fabric.Canvas#toJSON}
49796   * @param {String|Object} json JSON string or object
49797   * @param {Function} callback Callback, invoked when json is parsed
49798   *                            and corresponding objects (e.g: {@link fabric.Image})
49799   *                            are initialized
49800   * @param {Function} [reviver] Method for further parsing of JSON elements, called after each fabric object created.
49801   * @return {fabric.Canvas} instance
49802   * @chainable
49803   * @tutorial {@link http://fabricjs.com/fabric-intro-part-3/#deserialization}
49804   * @see {@link http://jsfiddle.net/fabricjs/fmgXt/|jsFiddle demo}
49805   * @example <caption>loadFromJSON</caption>
49806   * canvas.loadFromJSON(json, canvas.renderAll.bind(canvas));
49807   * @example <caption>loadFromJSON with reviver</caption>
49808   * canvas.loadFromJSON(json, canvas.renderAll.bind(canvas), function(o, object) {
49809   *   // `o` = json object
49810   *   // `object` = fabric.Object instance
49811   *   // ... do some stuff ...
49812   * });
49813   */
49814  loadFromJSON: function (json, callback, reviver) {
49815    if (!json) return;
49816
49817    // serialize if it wasn't already
49818    var serialized = (typeof json === 'string')
49819      ? JSON.parse(json)
49820      : json;
49821
49822    this.clear();
49823
49824    var _this = this;
49825    this._enlivenObjects(serialized.objects, function () {
49826      _this._setBgOverlayImages(serialized, callback);
49827    }, reviver);
49828
49829    return this;
49830  },
49831
49832  _setBgOverlayImages: function(serialized, callback) {
49833
49834    var _this = this,
49835        backgroundPatternLoaded,
49836        backgroundImageLoaded,
49837        overlayImageLoaded;
49838
49839    var cbIfLoaded = function () {
49840      callback && backgroundImageLoaded && overlayImageLoaded && backgroundPatternLoaded && callback();
49841    };
49842
49843    if (serialized.backgroundImage) {
49844      this.setBackgroundImage(serialized.backgroundImage, function() {
49845
49846        _this.backgroundImageOpacity = serialized.backgroundImageOpacity;
49847        _this.backgroundImageStretch = serialized.backgroundImageStretch;
49848
49849        _this.renderAll();
49850
49851        backgroundImageLoaded = true;
49852
49853        cbIfLoaded();
49854      });
49855    }
49856    else {
49857      backgroundImageLoaded = true;
49858    }
49859
49860    if (serialized.overlayImage) {
49861      this.setOverlayImage(serialized.overlayImage, function() {
49862
49863        _this.overlayImageLeft = serialized.overlayImageLeft || 0;
49864        _this.overlayImageTop = serialized.overlayImageTop || 0;
49865
49866        _this.renderAll();
49867        overlayImageLoaded = true;
49868
49869        cbIfLoaded();
49870      });
49871    }
49872    else {
49873      overlayImageLoaded = true;
49874    }
49875
49876    if (serialized.background) {
49877      this.setBackgroundColor(serialized.background, function() {
49878
49879        _this.renderAll();
49880        backgroundPatternLoaded = true;
49881
49882        cbIfLoaded();
49883      });
49884    }
49885    else {
49886      backgroundPatternLoaded = true;
49887    }
49888
49889    if (!serialized.backgroundImage && !serialized.overlayImage && !serialized.background) {
49890      callback && callback();
49891    }
49892  },
49893
49894  /**
49895   * @private
49896   * @param {Array} objects
49897   * @param {Function} callback
49898   * @param {Function} [reviver]
49899   */
49900  _enlivenObjects: function (objects, callback, reviver) {
49901    var _this = this;
49902
49903    if (objects.length === 0) {
49904      callback && callback();
49905    }
49906
49907    var renderOnAddRemove = this.renderOnAddRemove;
49908    this.renderOnAddRemove = false;
49909
49910    fabric.util.enlivenObjects(objects, function(enlivenedObjects) {
49911      enlivenedObjects.forEach(function(obj, index) {
49912        _this.insertAt(obj, index, true);
49913      });
49914
49915      _this.renderOnAddRemove = renderOnAddRemove;
49916      callback && callback();
49917    }, null, reviver);
49918  },
49919
49920  /**
49921   * @private
49922   * @param {String} format
49923   * @param {Function} callback
49924   */
49925  _toDataURL: function (format, callback) {
49926    this.clone(function (clone) {
49927      callback(clone.toDataURL(format));
49928    });
49929  },
49930
49931  /**
49932   * @private
49933   * @param {String} format
49934   * @param {Number} multiplier
49935   * @param {Function} callback
49936   */
49937  _toDataURLWithMultiplier: function (format, multiplier, callback) {
49938    this.clone(function (clone) {
49939      callback(clone.toDataURLWithMultiplier(format, multiplier));
49940    });
49941  },
49942
49943  /**
49944   * Clones canvas instance
49945   * @param {Object} [callback] Receives cloned instance as a first argument
49946   */
49947  clone: function (callback) {
49948    var data = JSON.stringify(this);
49949    this.cloneWithoutData(function(clone) {
49950      clone.loadFromJSON(data, function() {
49951        callback && callback(clone);
49952      });
49953    });
49954  },
49955
49956  /**
49957   * Clones canvas instance without cloning existing data.
49958   * This essentially copies canvas dimensions, clipping properties, etc.
49959   * but leaves data empty (so that you can populate it with your own)
49960   * @param {Object} [callback] Receives cloned instance as a first argument
49961   */
49962  cloneWithoutData: function(callback) {
49963    var el = fabric.document.createElement('canvas');
49964
49965    el.width = this.getWidth();
49966    el.height = this.getHeight();
49967
49968    var clone = new fabric.Canvas(el);
49969    clone.clipTo = this.clipTo;
49970    if (this.backgroundImage) {
49971      clone.setBackgroundImage(this.backgroundImage.src, function() {
49972        clone.renderAll();
49973        callback && callback(clone);
49974      });
49975      clone.backgroundImageOpacity = this.backgroundImageOpacity;
49976      clone.backgroundImageStretch = this.backgroundImageStretch;
49977    }
49978    else {
49979      callback && callback(clone);
49980    }
49981  }
49982});
49983
49984
49985(function(global) {
49986
49987  "use strict";
49988
49989  var fabric = global.fabric || (global.fabric = { }),
49990      extend = fabric.util.object.extend,
49991      toFixed = fabric.util.toFixed,
49992      capitalize = fabric.util.string.capitalize,
49993      degreesToRadians = fabric.util.degreesToRadians,
49994      supportsLineDash = fabric.StaticCanvas.supports('setLineDash');
49995
49996  if (fabric.Object) {
49997    return;
49998  }
49999
50000  /**
50001   * Root object class from which all 2d shape classes inherit from
50002   * @class fabric.Object
50003   * @tutorial {@link http://fabricjs.com/fabric-intro-part-1/#objects}
50004   *
50005   * @fires added
50006   * @fires removed
50007   *
50008   * @fires selected
50009   * @fires modified
50010   * @fires rotating
50011   * @fires scaling
50012   * @fires moving
50013   *
50014   * @fires mousedown
50015   * @fires mouseup
50016   */
50017  fabric.Object = fabric.util.createClass(/** @lends fabric.Object.prototype */ {
50018
50019    /**
50020     * Retrieves object's {@link fabric.Object#clipTo|clipping function}
50021     * @method getClipTo
50022     * @memberOf fabric.Object.prototype
50023     * @return {Function}
50024     */
50025
50026    /**
50027     * Sets object's {@link fabric.Object#clipTo|clipping function}
50028     * @method setClipTo
50029     * @memberOf fabric.Object.prototype
50030     * @param {Function} clipTo Clipping function
50031     * @return {fabric.Object} thisArg
50032     * @chainable
50033     */
50034
50035    /**
50036     * Retrieves object's {@link fabric.Object#transformMatrix|transformMatrix}
50037     * @method getTransformMatrix
50038     * @memberOf fabric.Object.prototype
50039     * @return {Array} transformMatrix
50040     */
50041
50042    /**
50043     * Sets object's {@link fabric.Object#transformMatrix|transformMatrix}
50044     * @method setTransformMatrix
50045     * @memberOf fabric.Object.prototype
50046     * @param {Array} transformMatrix
50047     * @return {fabric.Object} thisArg
50048     * @chainable
50049     */
50050
50051    /**
50052     * Retrieves object's {@link fabric.Object#visible|visible} state
50053     * @method getVisible
50054     * @memberOf fabric.Object.prototype
50055     * @return {Boolean} True if visible
50056     */
50057
50058    /**
50059     * Sets object's {@link fabric.Object#visible|visible} state
50060     * @method setVisible
50061     * @memberOf fabric.Object.prototype
50062     * @param {Boolean} value visible value
50063     * @return {fabric.Object} thisArg
50064     * @chainable
50065     */
50066
50067    /**
50068     * Retrieves object's {@link fabric.Object#shadow|shadow}
50069     * @method getShadow
50070     * @memberOf fabric.Object.prototype
50071     * @return {Object} Shadow instance
50072     */
50073
50074    /**
50075     * Retrieves object's {@link fabric.Object#stroke|stroke}
50076     * @method getStroke
50077     * @memberOf fabric.Object.prototype
50078     * @return {String} stroke value
50079     */
50080
50081    /**
50082     * Sets object's {@link fabric.Object#stroke|stroke}
50083     * @method setStroke
50084     * @memberOf fabric.Object.prototype
50085     * @param {String} value stroke value
50086     * @return {fabric.Object} thisArg
50087     * @chainable
50088     */
50089
50090    /**
50091     * Retrieves object's {@link fabric.Object#strokeWidth|strokeWidth}
50092     * @method getStrokeWidth
50093     * @memberOf fabric.Object.prototype
50094     * @return {Number} strokeWidth value
50095     */
50096
50097    /**
50098     * Sets object's {@link fabric.Object#strokeWidth|strokeWidth}
50099     * @method setStrokeWidth
50100     * @memberOf fabric.Object.prototype
50101     * @param {Number} value strokeWidth value
50102     * @return {fabric.Object} thisArg
50103     * @chainable
50104     */
50105
50106    /**
50107     * Retrieves object's {@link fabric.Object#originX|originX}
50108     * @method getOriginX
50109     * @memberOf fabric.Object.prototype
50110     * @return {String} originX value
50111     */
50112
50113    /**
50114     * Sets object's {@link fabric.Object#originX|originX}
50115     * @method setOriginX
50116     * @memberOf fabric.Object.prototype
50117     * @param {String} value originX value
50118     * @return {fabric.Object} thisArg
50119     * @chainable
50120     */
50121
50122    /**
50123     * Retrieves object's {@link fabric.Object#originY|originY}
50124     * @method getOriginY
50125     * @memberOf fabric.Object.prototype
50126     * @return {String} originY value
50127     */
50128
50129    /**
50130     * Sets object's {@link fabric.Object#originY|originY}
50131     * @method setOriginY
50132     * @memberOf fabric.Object.prototype
50133     * @param {String} value originY value
50134     * @return {fabric.Object} thisArg
50135     * @chainable
50136     */
50137
50138    /**
50139     * Retrieves object's {@link fabric.Object#fill|fill}
50140     * @method getFill
50141     * @memberOf fabric.Object.prototype
50142     * @return {String} Fill value
50143     */
50144
50145    /**
50146     * Sets object's {@link fabric.Object#fill|fill}
50147     * @method setFill
50148     * @memberOf fabric.Object.prototype
50149     * @param {String} value Fill value
50150     * @return {fabric.Object} thisArg
50151     * @chainable
50152     */
50153
50154    /**
50155     * Retrieves object's {@link fabric.Object#opacity|opacity}
50156     * @method getOpacity
50157     * @memberOf fabric.Object.prototype
50158     * @return {Number} Opacity value (0-1)
50159     */
50160
50161    /**
50162     * Sets object's {@link fabric.Object#opacity|opacity}
50163     * @method setOpacity
50164     * @memberOf fabric.Object.prototype
50165     * @param {Number} value Opacity value (0-1)
50166     * @return {fabric.Object} thisArg
50167     * @chainable
50168     */
50169
50170    /**
50171     * Retrieves object's {@link fabric.Object#angle|angle} (in degrees)
50172     * @method getAngle
50173     * @memberOf fabric.Object.prototype
50174     * @return {Number}
50175     */
50176
50177    /**
50178     * Sets object's {@link fabric.Object#angle|angle}
50179     * @method setAngle
50180     * @memberOf fabric.Object.prototype
50181     * @param {Number} value Angle value (in degrees)
50182     * @return {fabric.Object} thisArg
50183     * @chainable
50184     */
50185
50186    /**
50187     * Retrieves object's {@link fabric.Object#top|top position}
50188     * @method getTop
50189     * @memberOf fabric.Object.prototype
50190     * @return {Number} Top value (in pixels)
50191     */
50192
50193    /**
50194     * Sets object's {@link fabric.Object#top|top position}
50195     * @method setTop
50196     * @memberOf fabric.Object.prototype
50197     * @param {Number} value Top value (in pixels)
50198     * @return {fabric.Object} thisArg
50199     * @chainable
50200     */
50201
50202    /**
50203     * Retrieves object's {@link fabric.Object#left|left position}
50204     * @method getLeft
50205     * @memberOf fabric.Object.prototype
50206     * @return {Number} Left value (in pixels)
50207     */
50208
50209    /**
50210     * Sets object's {@link fabric.Object#left|left position}
50211     * @method setLeft
50212     * @memberOf fabric.Object.prototype
50213     * @param {Number} value Left value (in pixels)
50214     * @return {fabric.Object} thisArg
50215     * @chainable
50216     */
50217
50218    /**
50219     * Retrieves object's {@link fabric.Object#scaleX|scaleX} value
50220     * @method getScaleX
50221     * @memberOf fabric.Object.prototype
50222     * @return {Number} scaleX value
50223     */
50224
50225    /**
50226     * Sets object's {@link fabric.Object#scaleX|scaleX} value
50227     * @method setScaleX
50228     * @memberOf fabric.Object.prototype
50229     * @param {Number} value scaleX value
50230     * @return {fabric.Object} thisArg
50231     * @chainable
50232     */
50233
50234    /**
50235     * Retrieves object's {@link fabric.Object#scaleY|scaleY} value
50236     * @method getScaleY
50237     * @memberOf fabric.Object.prototype
50238     * @return {Number} scaleY value
50239     */
50240
50241    /**
50242     * Sets object's {@link fabric.Object#scaleY|scaleY} value
50243     * @method setScaleY
50244     * @memberOf fabric.Object.prototype
50245     * @param {Number} value scaleY value
50246     * @return {fabric.Object} thisArg
50247     * @chainable
50248     */
50249
50250    /**
50251     * Retrieves object's {@link fabric.Object#flipX|flipX} value
50252     * @method getFlipX
50253     * @memberOf fabric.Object.prototype
50254     * @return {Boolean} flipX value
50255     */
50256
50257    /**
50258     * Sets object's {@link fabric.Object#flipX|flipX} value
50259     * @method setFlipX
50260     * @memberOf fabric.Object.prototype
50261     * @param {Boolean} value flipX value
50262     * @return {fabric.Object} thisArg
50263     * @chainable
50264     */
50265
50266    /**
50267     * Retrieves object's {@link fabric.Object#flipY|flipY} value
50268     * @method getFlipY
50269     * @memberOf fabric.Object.prototype
50270     * @return {Boolean} flipY value
50271     */
50272
50273    /**
50274     * Sets object's {@link fabric.Object#flipY|flipY} value
50275     * @method setFlipY
50276     * @memberOf fabric.Object.prototype
50277     * @param {Boolean} value flipY value
50278     * @return {fabric.Object} thisArg
50279     * @chainable
50280     */
50281
50282    /**
50283     * Type of an object (rect, circle, path, etc.)
50284     * @type String
50285     * @default
50286     */
50287    type:                     'object',
50288
50289    /**
50290     * Horizontal origin of transformation of an object (one of "left", "right", "center")
50291     * @type String
50292     * @default
50293     */
50294    originX:                  'center',
50295
50296    /**
50297     * Vertical origin of transformation of an object (one of "top", "bottom", "center")
50298     * @type String
50299     * @default
50300     */
50301    originY:                  'center',
50302
50303    /**
50304     * Top position of an object. Note that by default it's relative to object center. You can change this by setting originY={top/center/bottom}
50305     * @type Number
50306     * @default
50307     */
50308    top:                      0,
50309
50310    /**
50311     * Left position of an object. Note that by default it's relative to object center. You can change this by setting originX={left/center/right}
50312     * @type Number
50313     * @default
50314     */
50315    left:                     0,
50316
50317    /**
50318     * Object width
50319     * @type Number
50320     * @default
50321     */
50322    width:                    0,
50323
50324    /**
50325     * Object height
50326     * @type Number
50327     * @default
50328     */
50329    height:                   0,
50330
50331    /**
50332     * Object scale factor (horizontal)
50333     * @type Number
50334     * @default
50335     */
50336    scaleX:                   1,
50337
50338    /**
50339     * Object scale factor (vertical)
50340     * @type Number
50341     * @default
50342     */
50343    scaleY:                   1,
50344
50345    /**
50346     * When true, an object is rendered as flipped horizontally
50347     * @type Boolean
50348     * @default
50349     */
50350    flipX:                    false,
50351
50352    /**
50353     * When true, an object is rendered as flipped vertically
50354     * @type Boolean
50355     * @default
50356     */
50357    flipY:                    false,
50358
50359    /**
50360     * Opacity of an object
50361     * @type Number
50362     * @default
50363     */
50364    opacity:                  1,
50365
50366    /**
50367     * Angle of rotation of an object (in degrees)
50368     * @type Number
50369     * @default
50370     */
50371    angle:                    0,
50372
50373    /**
50374     * Size of object's controlling corners (in pixels)
50375     * @type Number
50376     * @default
50377     */
50378    cornerSize:               12,
50379
50380    /**
50381     * When true, object's controlling corners are rendered as transparent inside (i.e. stroke instead of fill)
50382     * @type Boolean
50383     * @default
50384     */
50385    transparentCorners:       true,
50386
50387    /**
50388     * Default cursor value used when hovering over this object on canvas
50389     * @type String
50390     * @default
50391     */
50392    hoverCursor:              null,
50393
50394    /**
50395     * Padding between object and its controlling borders (in pixels)
50396     * @type Number
50397     * @default
50398     */
50399    padding:                  0,
50400
50401    /**
50402     * Color of controlling borders of an object (when it's active)
50403     * @type String
50404     * @default
50405     */
50406    borderColor:              'rgba(102,153,255,0.75)',
50407
50408    /**
50409     * Color of controlling corners of an object (when it's active)
50410     * @type String
50411     * @default
50412     */
50413    cornerColor:              'rgba(102,153,255,0.5)',
50414
50415    /**
50416     * When true, this object will use center point as the origin of transformation
50417     * when being scaled via the controls.
50418     * <b>Backwards incompatibility note:</b> This property replaces "centerTransform" (Boolean).
50419     * @since 1.3.4
50420     * @type Boolean
50421     * @default
50422     */
50423    centeredScaling:          false,
50424
50425    /**
50426     * When true, this object will use center point as the origin of transformation
50427     * when being rotated via the controls.
50428     * <b>Backwards incompatibility note:</b> This property replaces "centerTransform" (Boolean).
50429     * @since 1.3.4
50430     * @type Boolean
50431     * @default
50432     */
50433    centeredRotation:         false,
50434
50435    /**
50436     * Color of object's fill
50437     * @type String
50438     * @default
50439     */
50440    fill:                     'rgb(0,0,0)',
50441
50442    /**
50443     * Fill rule used to fill an object
50444     * @type String
50445     * @default
50446     */
50447    fillRule:                 'source-over',
50448
50449    /**
50450     * Background color of an object. Only works with text objects at the moment.
50451     * @type String
50452     * @default
50453     */
50454    backgroundColor:          '',
50455
50456    /**
50457     * When defined, an object is rendered via stroke and this property specifies its color
50458     * @type String
50459     * @default
50460     */
50461    stroke:                   null,
50462
50463    /**
50464     * Width of a stroke used to render this object
50465     * @type Number
50466     * @default
50467     */
50468    strokeWidth:              1,
50469
50470    /**
50471     * Array specifying dash pattern of an object's stroke (stroke must be defined)
50472     * @type Array
50473     */
50474    strokeDashArray:          null,
50475
50476    /**
50477     * Line endings style of an object's stroke (one of "butt", "round", "square")
50478     * @type String
50479     * @default
50480     */
50481    strokeLineCap:            'butt',
50482
50483    /**
50484     * Corner style of an object's stroke (one of "bevil", "round", "miter")
50485     * @type String
50486     * @default
50487     */
50488    strokeLineJoin:           'miter',
50489
50490    /**
50491     * Maximum miter length (used for strokeLineJoin = "miter") of an object's stroke
50492     * @type Number
50493     * @default
50494     */
50495    strokeMiterLimit:         10,
50496
50497    /**
50498     * Shadow object representing shadow of this shape
50499     * @type fabric.Shadow
50500     * @default
50501     */
50502    shadow:                   null,
50503
50504    /**
50505     * Opacity of object's controlling borders when object is active and moving
50506     * @type Number
50507     * @default
50508     */
50509    borderOpacityWhenMoving:  0.4,
50510
50511    /**
50512     * Scale factor of object's controlling borders
50513     * @type Number
50514     * @default
50515     */
50516    borderScaleFactor:        1,
50517
50518    /**
50519     * Transform matrix (similar to SVG's transform matrix)
50520     * @type Array
50521     */
50522    transformMatrix:          null,
50523
50524    /**
50525     * Minimum allowed scale value of an object
50526     * @type Number
50527     * @default
50528     */
50529    minScaleLimit:            0.01,
50530
50531    /**
50532     * When set to `false`, an object can not be selected for modification (using either point-click-based or group-based selection).
50533     * But events still fire on it.
50534     * @type Boolean
50535     * @default
50536     */
50537    selectable:               true,
50538
50539    /**
50540     * When set to `false`, an object can not be a target of events. All events propagate through it. Introduced in v1.3.4
50541     * @type Boolean
50542     * @default
50543     */
50544    evented:                  true,
50545
50546    /**
50547     * When set to `false`, an object is not rendered on canvas
50548     * @type Boolean
50549     * @default
50550     */
50551    visible:                  true,
50552
50553    /**
50554     * When set to `false`, object's controls are not displayed and can not be used to manipulate object
50555     * @type Boolean
50556     * @default
50557     */
50558    hasControls:              true,
50559
50560    /**
50561     * When set to `false`, object's controlling borders are not rendered
50562     * @type Boolean
50563     * @default
50564     */
50565    hasBorders:               true,
50566
50567    /**
50568     * When set to `false`, object's controlling rotating point will not be visible or selectable
50569     * @type Boolean
50570     * @default
50571     */
50572    hasRotatingPoint:         true,
50573
50574    /**
50575     * Offset for object's controlling rotating point (when enabled via `hasRotatingPoint`)
50576     * @type Number
50577     * @default
50578     */
50579    rotatingPointOffset:      40,
50580
50581    /**
50582     * When set to `true`, objects are "found" on canvas on per-pixel basis rather than according to bounding box
50583     * @type Boolean
50584     * @default
50585     */
50586    perPixelTargetFind:       false,
50587
50588    /**
50589     * When `false`, default object's values are not included in its serialization
50590     * @type Boolean
50591     * @default
50592     */
50593    includeDefaultValues:     true,
50594
50595    /**
50596     * Function that determines clipping of an object (context is passed as a first argument)
50597     * @type Function
50598     */
50599    clipTo:                   null,
50600
50601    /**
50602     * When `true`, object horizontal movement is locked
50603     * @type Boolean
50604     * @default
50605     */
50606    lockMovementX:            false,
50607
50608    /**
50609     * When `true`, object vertical movement is locked
50610     * @type Boolean
50611     * @default
50612     */
50613    lockMovementY:            false,
50614
50615    /**
50616     * When `true`, object rotation is locked
50617     * @type Boolean
50618     * @default
50619     */
50620    lockRotation:             false,
50621
50622    /**
50623     * When `true`, object horizontal scaling is locked
50624     * @type Boolean
50625     * @default
50626     */
50627    lockScalingX:             false,
50628
50629    /**
50630     * When `true`, object vertical scaling is locked
50631     * @type Boolean
50632     * @default
50633     */
50634    lockScalingY:             false,
50635
50636    /**
50637     * When `true`, object non-uniform scaling is locked
50638     * @type Boolean
50639     * @default
50640     */
50641    lockUniScaling:           false,
50642
50643    /**
50644     * List of properties to consider when checking if state
50645     * of an object is changed (fabric.Object#hasStateChanged)
50646     * as well as for history (undo/redo) purposes
50647     * @type Array
50648     */
50649    stateProperties:  (
50650      'top left width height scaleX scaleY flipX flipY originX originY transformMatrix ' +
50651      'stroke strokeWidth strokeDashArray strokeLineCap strokeLineJoin strokeMiterLimit ' +
50652      'angle opacity fill fillRule shadow clipTo visible backgroundColor'
50653    ).split(' '),
50654
50655    /**
50656     * Constructor
50657     * @param {Object} [options] Options object
50658     */
50659    initialize: function(options) {
50660      if (options) {
50661        this.setOptions(options);
50662      }
50663    },
50664
50665    /**
50666     * @private
50667     */
50668    _initGradient: function(options) {
50669      if (options.fill && options.fill.colorStops && !(options.fill instanceof fabric.Gradient)) {
50670        this.set('fill', new fabric.Gradient(options.fill));
50671      }
50672    },
50673
50674    /**
50675     * @private
50676     */
50677    _initPattern: function(options) {
50678      if (options.fill && options.fill.source && !(options.fill instanceof fabric.Pattern)) {
50679        this.set('fill', new fabric.Pattern(options.fill));
50680      }
50681      if (options.stroke && options.stroke.source && !(options.stroke instanceof fabric.Pattern)) {
50682        this.set('stroke', new fabric.Pattern(options.stroke));
50683      }
50684    },
50685
50686    /**
50687     * @private
50688     */
50689    _initClipping: function(options) {
50690      if (!options.clipTo || typeof options.clipTo !== 'string') return;
50691
50692      var functionBody = fabric.util.getFunctionBody(options.clipTo);
50693      if (typeof functionBody !== 'undefined') {
50694        this.clipTo = new Function('ctx', functionBody);
50695      }
50696    },
50697
50698    /**
50699     * Sets object's properties from options
50700     * @param {Object} [options] Options object
50701     */
50702    setOptions: function(options) {
50703      for (var prop in options) {
50704        this.set(prop, options[prop]);
50705      }
50706      this._initGradient(options);
50707      this._initPattern(options);
50708      this._initClipping(options);
50709    },
50710
50711    /**
50712     * Transforms context when rendering an object
50713     * @param {CanvasRenderingContext2D} ctx Context
50714     * @param {Boolean} fromLeft When true, context is transformed to object's top/left corner. This is used when rendering text on Node
50715     */
50716    transform: function(ctx, fromLeft) {
50717      ctx.globalAlpha = this.opacity;
50718
50719      var center = fromLeft ? this._getLeftTopCoords() : this.getCenterPoint();
50720      ctx.translate(center.x, center.y);
50721      ctx.rotate(degreesToRadians(this.angle));
50722      ctx.scale(
50723        this.scaleX * (this.flipX ? -1 : 1),
50724        this.scaleY * (this.flipY ? -1 : 1)
50725      );
50726    },
50727
50728    /**
50729     * Returns an object representation of an instance
50730     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output
50731     * @return {Object} Object representation of an instance
50732     */
50733    toObject: function(propertiesToInclude) {
50734
50735      var NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS;
50736
50737      var object = {
50738        type:               this.type,
50739        originX:            this.originX,
50740        originY:            this.originY,
50741        left:               toFixed(this.left, NUM_FRACTION_DIGITS),
50742        top:                toFixed(this.top, NUM_FRACTION_DIGITS),
50743        width:              toFixed(this.width, NUM_FRACTION_DIGITS),
50744        height:             toFixed(this.height, NUM_FRACTION_DIGITS),
50745        fill:               (this.fill && this.fill.toObject) ? this.fill.toObject() : this.fill,
50746        stroke:             (this.stroke && this.stroke.toObject) ? this.stroke.toObject() : this.stroke,
50747        strokeWidth:        toFixed(this.strokeWidth, NUM_FRACTION_DIGITS),
50748        strokeDashArray:    this.strokeDashArray,
50749        strokeLineCap:      this.strokeLineCap,
50750        strokeLineJoin:     this.strokeLineJoin,
50751        strokeMiterLimit:   toFixed(this.strokeMiterLimit, NUM_FRACTION_DIGITS),
50752        scaleX:             toFixed(this.scaleX, NUM_FRACTION_DIGITS),
50753        scaleY:             toFixed(this.scaleY, NUM_FRACTION_DIGITS),
50754        angle:              toFixed(this.getAngle(), NUM_FRACTION_DIGITS),
50755        flipX:              this.flipX,
50756        flipY:              this.flipY,
50757        opacity:            toFixed(this.opacity, NUM_FRACTION_DIGITS),
50758        shadow:             (this.shadow && this.shadow.toObject) ? this.shadow.toObject() : this.shadow,
50759        visible:            this.visible,
50760        clipTo:             this.clipTo && String(this.clipTo),
50761        backgroundColor:    this.backgroundColor
50762      };
50763
50764      if (!this.includeDefaultValues) {
50765        object = this._removeDefaultValues(object);
50766      }
50767
50768      fabric.util.populateWithProperties(this, object, propertiesToInclude);
50769
50770      return object;
50771    },
50772
50773    /**
50774     * Returns (dataless) object representation of an instance
50775     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output
50776     * @return {Object} Object representation of an instance
50777     */
50778    toDatalessObject: function(propertiesToInclude) {
50779      // will be overwritten by subclasses
50780      return this.toObject(propertiesToInclude);
50781    },
50782
50783    /* _TO_SVG_START_ */
50784    /**
50785     * Returns styles-string for svg-export
50786     * @return {String}
50787     */
50788    getSvgStyles: function() {
50789
50790      var fill = this.fill
50791        ? (this.fill.toLive ? 'url(#SVGID_' + this.fill.id + ')' : this.fill)
50792        : 'none';
50793
50794      var stroke = this.stroke
50795        ? (this.stroke.toLive ? 'url(#SVGID_' + this.stroke.id + ')' : this.stroke)
50796        : 'none';
50797
50798      var strokeWidth = this.strokeWidth ? this.strokeWidth : '0';
50799      var strokeDashArray = this.strokeDashArray ? this.strokeDashArray.join(' ') : '';
50800      var strokeLineCap = this.strokeLineCap ? this.strokeLineCap : 'butt';
50801      var strokeLineJoin = this.strokeLineJoin ? this.strokeLineJoin : 'miter';
50802      var strokeMiterLimit = this.strokeMiterLimit ? this.strokeMiterLimit : '4';
50803      var opacity = typeof this.opacity !== 'undefined' ? this.opacity : '1';
50804
50805      var visibility = this.visible ? '' : " visibility: hidden;";
50806      var filter = this.shadow && this.type !== 'text' ? 'filter: url(#SVGID_' + this.shadow.id + ');' : '';
50807
50808      return [
50809        "stroke: ", stroke, "; ",
50810        "stroke-width: ", strokeWidth, "; ",
50811        "stroke-dasharray: ", strokeDashArray, "; ",
50812        "stroke-linecap: ", strokeLineCap, "; ",
50813        "stroke-linejoin: ", strokeLineJoin, "; ",
50814        "stroke-miterlimit: ", strokeMiterLimit, "; ",
50815        "fill: ", fill, "; ",
50816        "opacity: ", opacity, ";",
50817        filter,
50818        visibility
50819      ].join('');
50820    },
50821
50822    /**
50823     * Returns transform-string for svg-export
50824     * @return {String}
50825     */
50826    getSvgTransform: function() {
50827      var angle = this.getAngle();
50828      var center = this.getCenterPoint();
50829
50830      var NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS;
50831
50832      var translatePart = "translate(" +
50833                            toFixed(center.x, NUM_FRACTION_DIGITS) +
50834                            " " +
50835                            toFixed(center.y, NUM_FRACTION_DIGITS) +
50836                          ")";
50837
50838      var anglePart = angle !== 0
50839        ? (" rotate(" + toFixed(angle, NUM_FRACTION_DIGITS) + ")")
50840        : '';
50841
50842      var scalePart = (this.scaleX === 1 && this.scaleY === 1)
50843        ? '' :
50844        (" scale(" +
50845          toFixed(this.scaleX, NUM_FRACTION_DIGITS) +
50846          " " +
50847          toFixed(this.scaleY, NUM_FRACTION_DIGITS) +
50848        ")");
50849
50850      var flipXPart = this.flipX ? "matrix(-1 0 0 1 0 0) " : "";
50851      var flipYPart = this.flipY ? "matrix(1 0 0 -1 0 0)" : "";
50852
50853      return [ translatePart, anglePart, scalePart, flipXPart, flipYPart ].join('');
50854    },
50855
50856    _createBaseSVGMarkup: function() {
50857      var markup = [ ];
50858
50859      if (this.fill && this.fill.toLive) {
50860        markup.push(this.fill.toSVG(this, false));
50861      }
50862      if (this.stroke && this.stroke.toLive) {
50863        markup.push(this.stroke.toSVG(this, false));
50864      }
50865      if (this.shadow) {
50866        markup.push(this.shadow.toSVG(this));
50867      }
50868      return markup;
50869    },
50870    /* _TO_SVG_END_ */
50871
50872    /**
50873     * @private
50874     * @param {Object} object
50875     */
50876    _removeDefaultValues: function(object) {
50877      var prototype = fabric.util.getKlass(object.type).prototype;
50878      var stateProperties = prototype.stateProperties;
50879
50880      stateProperties.forEach(function(prop) {
50881        if (object[prop] === prototype[prop]) {
50882          delete object[prop];
50883        }
50884      });
50885
50886      return object;
50887    },
50888
50889    /**
50890     * Returns a string representation of an instance
50891     * @return {String}
50892     */
50893    toString: function() {
50894      return "#<fabric." + capitalize(this.type) + ">";
50895    },
50896
50897    /**
50898     * Basic getter
50899     * @param {String} property Property name
50900     * @return {Any} value of a property
50901     */
50902    get: function(property) {
50903      return this[property];
50904    },
50905
50906    /**
50907     * Sets property to a given value. When changing position/dimension -related properties (left, top, scale, angle, etc.) `set` does not update position of object's borders/controls. If you need to update those, call `setCoords()`.
50908     * @param {String|Object} key Property name or object (if object, iterate over the object properties)
50909     * @param {Object|Function} value Property value (if function, the value is passed into it and its return value is used as a new one)
50910     * @return {fabric.Object} thisArg
50911     * @chainable
50912     */
50913    set: function(key, value) {
50914      if (typeof key === 'object') {
50915        for (var prop in key) {
50916          this._set(prop, key[prop]);
50917        }
50918      }
50919      else {
50920        if (typeof value === 'function' && key !== 'clipTo') {
50921          this._set(key, value(this.get(key)));
50922        }
50923        else {
50924          this._set(key, value);
50925        }
50926      }
50927      return this;
50928    },
50929
50930    /**
50931     * @private
50932     * @param {String} key
50933     * @param {Any} value
50934     * @return {fabric.Object} thisArg
50935     */
50936    _set: function(key, value) {
50937      var shouldConstrainValue = (key === 'scaleX' || key === 'scaleY');
50938
50939      if (shouldConstrainValue) {
50940        value = this._constrainScale(value);
50941      }
50942      if (key === 'scaleX' && value < 0) {
50943        this.flipX = !this.flipX;
50944        value *= -1;
50945      }
50946      else if (key === 'scaleY' && value < 0) {
50947        this.flipY = !this.flipY;
50948        value *= -1;
50949      }
50950      else if (key === 'width' || key === 'height') {
50951        this.minScaleLimit = toFixed(Math.min(0.1, 1/Math.max(this.width, this.height)), 2);
50952      }
50953      else if (key === 'shadow' && value && !(value instanceof fabric.Shadow)) {
50954        value = new fabric.Shadow(value);
50955      }
50956
50957      this[key] = value;
50958
50959      return this;
50960    },
50961
50962    /**
50963     * Toggles specified property from `true` to `false` or from `false` to `true`
50964     * @param {String} property Property to toggle
50965     * @return {fabric.Object} thisArg
50966     * @chainable
50967     */
50968    toggle: function(property) {
50969      var value = this.get(property);
50970      if (typeof value === 'boolean') {
50971        this.set(property, !value);
50972      }
50973      return this;
50974    },
50975
50976    /**
50977     * Sets sourcePath of an object
50978     * @param {String} value Value to set sourcePath to
50979     * @return {fabric.Object} thisArg
50980     * @chainable
50981     */
50982    setSourcePath: function(value) {
50983      this.sourcePath = value;
50984      return this;
50985    },
50986
50987    /**
50988     * Renders an object on a specified context
50989     * @param {CanvasRenderingContext2D} ctx Context to render on
50990     * @param {Boolean} [noTransform] When true, context is not transformed
50991     */
50992    render: function(ctx, noTransform) {
50993      // do not render if width/height are zeros or object is not visible
50994      if (this.width === 0 || this.height === 0 || !this.visible) return;
50995
50996      ctx.save();
50997
50998      var m = this.transformMatrix;
50999      if (m && !this.group) {
51000        ctx.setTransform(m[0], m[1], m[2], m[3], m[4], m[5]);
51001      }
51002
51003      if (!noTransform) {
51004        this.transform(ctx);
51005      }
51006
51007      if (this.stroke) {
51008        ctx.lineWidth = this.strokeWidth;
51009        ctx.lineCap = this.strokeLineCap;
51010        ctx.lineJoin = this.strokeLineJoin;
51011        ctx.miterLimit = this.strokeMiterLimit;
51012        ctx.strokeStyle = this.stroke.toLive
51013          ? this.stroke.toLive(ctx)
51014          : this.stroke;
51015      }
51016
51017      if (this.fill) {
51018        ctx.fillStyle = this.fill.toLive
51019          ? this.fill.toLive(ctx)
51020          : this.fill;
51021      }
51022
51023      if (m && this.group) {
51024        ctx.translate(-this.group.width/2, -this.group.height/2);
51025        ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]);
51026      }
51027
51028      this._setShadow(ctx);
51029      this.clipTo && fabric.util.clipContext(this, ctx);
51030      this._render(ctx, noTransform);
51031      this.clipTo && ctx.restore();
51032      this._removeShadow(ctx);
51033
51034      if (this.active && !noTransform) {
51035        this.drawBorders(ctx);
51036        this.drawControls(ctx);
51037      }
51038      ctx.restore();
51039    },
51040
51041    /**
51042     * @private
51043     * @param {CanvasRenderingContext2D} ctx Context to render on
51044     */
51045    _setShadow: function(ctx) {
51046      if (!this.shadow) return;
51047
51048      ctx.shadowColor = this.shadow.color;
51049      ctx.shadowBlur = this.shadow.blur;
51050      ctx.shadowOffsetX = this.shadow.offsetX;
51051      ctx.shadowOffsetY = this.shadow.offsetY;
51052    },
51053
51054    /**
51055     * @private
51056     * @param {CanvasRenderingContext2D} ctx Context to render on
51057     */
51058    _removeShadow: function(ctx) {
51059      ctx.shadowColor = '';
51060      ctx.shadowBlur = ctx.shadowOffsetX = ctx.shadowOffsetY = 0;
51061    },
51062
51063    /**
51064     * @private
51065     * @param {CanvasRenderingContext2D} ctx Context to render on
51066     */
51067    _renderFill: function(ctx) {
51068      if (!this.fill) return;
51069
51070      if (this.fill.toLive) {
51071        ctx.save();
51072        ctx.translate(
51073          -this.width / 2 + this.fill.offsetX || 0,
51074          -this.height / 2 + this.fill.offsetY || 0);
51075      }
51076      ctx.fill();
51077      if (this.fill.toLive) {
51078        ctx.restore();
51079      }
51080      if (this.shadow && !this.shadow.affectStroke) {
51081        this._removeShadow(ctx);
51082      }
51083    },
51084
51085    /**
51086     * @private
51087     * @param {CanvasRenderingContext2D} ctx Context to render on
51088     */
51089    _renderStroke: function(ctx) {
51090      if (!this.stroke) return;
51091
51092      ctx.save();
51093      if (this.strokeDashArray) {
51094        // Spec requires the concatenation of two copies the dash list when the number of elements is odd
51095        if (1 & this.strokeDashArray.length) {
51096          this.strokeDashArray.push.apply(this.strokeDashArray, this.strokeDashArray);
51097        }
51098
51099        if (supportsLineDash) {
51100          ctx.setLineDash(this.strokeDashArray);
51101          this._stroke && this._stroke(ctx);
51102        }
51103        else {
51104          this._renderDashedStroke && this._renderDashedStroke(ctx);
51105        }
51106        ctx.stroke();
51107      }
51108      else {
51109        this._stroke ? this._stroke(ctx) : ctx.stroke();
51110      }
51111      this._removeShadow(ctx);
51112      ctx.restore();
51113    },
51114
51115    /**
51116     * Clones an instance
51117     * @param {Function} callback Callback is invoked with a clone as a first argument
51118     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output
51119     * @return {fabric.Object} clone of an instance
51120     */
51121    clone: function(callback, propertiesToInclude) {
51122      if (this.constructor.fromObject) {
51123        return this.constructor.fromObject(this.toObject(propertiesToInclude), callback);
51124      }
51125      return new fabric.Object(this.toObject(propertiesToInclude));
51126    },
51127
51128    /**
51129     * Creates an instance of fabric.Image out of an object
51130     * @param callback {Function} callback, invoked with an instance as a first argument
51131     * @return {fabric.Object} thisArg
51132     */
51133    cloneAsImage: function(callback) {
51134      var dataUrl = this.toDataURL();
51135      fabric.util.loadImage(dataUrl, function(img) {
51136        if (callback) {
51137          callback(new fabric.Image(img));
51138        }
51139      });
51140      return this;
51141    },
51142
51143    /**
51144     * Converts an object into a data-url-like string
51145     * @param {Object} options Options object
51146     * @param {String} [options.format=png] The format of the output image. Either "jpeg" or "png"
51147     * @param {Number} [options.quality=1] Quality level (0..1). Only used for jpeg.
51148     * @param {Number} [options.multiplier=1] Multiplier to scale by
51149     * @param {Number} [options.left] Cropping left offset. Introduced in v1.2.14
51150     * @param {Number} [options.top] Cropping top offset. Introduced in v1.2.14
51151     * @param {Number} [options.width] Cropping width. Introduced in v1.2.14
51152     * @param {Number} [options.height] Cropping height. Introduced in v1.2.14
51153     * @return {String} Returns a data: URL containing a representation of the object in the format specified by options.format
51154     */
51155    toDataURL: function(options) {
51156      options || (options = { });
51157
51158      var el = fabric.util.createCanvasElement(),
51159          boundingRect = this.getBoundingRect();
51160
51161      el.width = boundingRect.width;
51162      el.height = boundingRect.height;
51163
51164      fabric.util.wrapElement(el, 'div');
51165      var canvas = new fabric.Canvas(el);
51166
51167      // to avoid common confusion https://github.com/kangax/fabric.js/issues/806
51168      if (options.format === 'jpg') {
51169        options.format = 'jpeg';
51170      }
51171
51172      if (options.format === 'jpeg') {
51173        canvas.backgroundColor = '#fff';
51174      }
51175
51176      var origParams = {
51177        active: this.get('active'),
51178        left: this.getLeft(),
51179        top: this.getTop()
51180      };
51181
51182      this.set('active', false);
51183      this.setPositionByOrigin(new fabric.Point(el.width / 2, el.height / 2), 'center', 'center');
51184
51185      canvas.add(this);
51186      var data = canvas.toDataURL(options);
51187
51188      this.set(origParams).setCoords();
51189
51190      canvas.dispose();
51191      canvas = null;
51192
51193      return data;
51194    },
51195
51196    /**
51197     * Returns true if specified type is identical to the type of an instance
51198     * @param type {String} type Type to check against
51199     * @return {Boolean}
51200     */
51201    isType: function(type) {
51202      return this.type === type;
51203    },
51204
51205    /**
51206     * Returns complexity of an instance
51207     * @return {Number} complexity of this instance
51208     */
51209    complexity: function() {
51210      return 0;
51211    },
51212
51213    /**
51214     * Returns a JSON representation of an instance
51215     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output
51216     * @return {Object} JSON
51217     */
51218    toJSON: function(propertiesToInclude) {
51219      // delegate, not alias
51220      return this.toObject(propertiesToInclude);
51221    },
51222
51223    /**
51224     * Sets gradient (fill or stroke) of an object
51225     * <b>Backwards incompatibility note:</b> This method was named "setGradientFill" until v1.1.0
51226     * @param {String} property Property name 'stroke' or 'fill'
51227     * @param {Object} [options] Options object
51228     * @param {String} [options.type] Type of gradient 'radial' or 'linear'
51229     * @param {Number} [options.x1=0] x-coordinate of start point
51230     * @param {Number} [options.y1=0] y-coordinate of start point
51231     * @param {Number} [options.x2=0] x-coordinate of end point
51232     * @param {Number} [options.y2=0] y-coordinate of end point
51233     * @param {Number} [options.r1=0] Radius of start point (only for radial gradients)
51234     * @param {Number} [options.r2=0] Radius of end point (only for radial gradients)
51235     * @param {Object} [options.colorStops] Color stops object eg. {0: 'ff0000', 1: '000000'}
51236     * @return {fabric.Object} thisArg
51237     * @chainable
51238     * @see {@link http://jsfiddle.net/fabricjs/58y8b/|jsFiddle demo}
51239     * @example <caption>Set linear gradient</caption>
51240     * object.setGradient('fill', {
51241     *   type: 'linear',
51242     *   x1: -object.width / 2,
51243     *   y1: 0,
51244     *   x2: object.width / 2,
51245     *   y2: 0,
51246     *   colorStops: {
51247     *     0: 'red',
51248     *     0.5: '#005555',
51249     *     1: 'rgba(0,0,255,0.5)'
51250     *   }
51251     * });
51252     * canvas.renderAll();
51253     * @example <caption>Set radial gradient</caption>
51254     * object.setGradient('fill', {
51255     *   type: 'radial',
51256     *   x1: 0,
51257     *   y1: 0,
51258     *   x2: 0,
51259     *   y2: 0,
51260     *   r1: object.width / 2,
51261     *   r2: 10,
51262     *   colorStops: {
51263     *     0: 'red',
51264     *     0.5: '#005555',
51265     *     1: 'rgba(0,0,255,0.5)'
51266     *   }
51267     * });
51268     * canvas.renderAll();
51269     */
51270    setGradient: function(property, options) {
51271      options || (options = { });
51272
51273      var gradient = {colorStops: []};
51274
51275      gradient.type = options.type || (options.r1 || options.r2 ? 'radial' : 'linear');
51276      gradient.coords = {
51277        x1: options.x1,
51278        y1: options.y1,
51279        x2: options.x2,
51280        y2: options.y2
51281      };
51282
51283      if (options.r1 || options.r2) {
51284        gradient.coords.r1 = options.r1;
51285        gradient.coords.r2 = options.r2;
51286      }
51287
51288      for (var position in options.colorStops) {
51289        var color = new fabric.Color(options.colorStops[position]);
51290        gradient.colorStops.push({offset: position, color: color.toRgb(), opacity: color.getAlpha()});
51291      }
51292
51293      return this.set(property, fabric.Gradient.forObject(this, gradient));
51294    },
51295
51296    /**
51297     * Sets pattern fill of an object
51298     * @param {Object} options Options object
51299     * @param {(String|HTMLImageElement)} options.source Pattern source
51300     * @param {String} [options.repeat=repeat] Repeat property of a pattern (one of repeat, repeat-x, repeat-y or no-repeat)
51301     * @param {Number} [options.offsetX=0] Pattern horizontal offset from object's left/top corner
51302     * @param {Number} [options.offsetY=0] Pattern vertical offset from object's left/top corner
51303     * @return {fabric.Object} thisArg
51304     * @chainable
51305     * @see {@link http://jsfiddle.net/fabricjs/QT3pa/|jsFiddle demo}
51306     * @example <caption>Set pattern</caption>
51307     * fabric.util.loadImage('http://fabricjs.com/assets/escheresque_ste.png', function(img) {
51308     *   object.setPatternFill({
51309     *     source: img,
51310     *     repeat: 'repeat'
51311     *   });
51312     *   canvas.renderAll();
51313     * });
51314     */
51315    setPatternFill: function(options) {
51316      return this.set('fill', new fabric.Pattern(options));
51317    },
51318
51319    /**
51320     * Sets {@link fabric.Object#shadow|shadow} of an object
51321     * @param {Object|String} [options] Options object or string (e.g. "2px 2px 10px rgba(0,0,0,0.2)")
51322     * @param {String} [options.color=rgb(0,0,0)] Shadow color
51323     * @param {Number} [options.blur=0] Shadow blur
51324     * @param {Number} [options.offsetX=0] Shadow horizontal offset
51325     * @param {Number} [options.offsetY=0] Shadow vertical offset
51326     * @return {fabric.Object} thisArg
51327     * @chainable
51328     * @see {@link http://jsfiddle.net/fabricjs/7gvJG/|jsFiddle demo}
51329     * @example <caption>Set shadow with string notation</caption>
51330     * object.setShadow('2px 2px 10px rgba(0,0,0,0.2)');
51331     * canvas.renderAll();
51332     * @example <caption>Set shadow with object notation</caption>
51333     * object.setShadow({
51334     *   color: 'red',
51335     *   blur: 10,
51336     *   offsetX: 20,
51337     *   offsetY: 20
51338     * });
51339     * canvas.renderAll();
51340     */
51341    setShadow: function(options) {
51342      return this.set('shadow', new fabric.Shadow(options));
51343    },
51344
51345    /**
51346     * Sets "color" of an instance (alias of `set('fill', &hellip;)`)
51347     * @param {String} color Color value
51348     * @return {fabric.Text} thisArg
51349     * @chainable
51350     */
51351    setColor: function(color) {
51352      this.set('fill', color);
51353      return this;
51354    },
51355
51356    /**
51357     * Centers object horizontally on canvas to which it was added last.
51358     * You might need to call `setCoords` on an object after centering, to update controls area.
51359     * @return {fabric.Object} thisArg
51360     * @chainable
51361     */
51362    centerH: function () {
51363      this.canvas.centerObjectH(this);
51364      return this;
51365    },
51366
51367    /**
51368     * Centers object vertically on canvas to which it was added last.
51369     * You might need to call `setCoords` on an object after centering, to update controls area.
51370     * @return {fabric.Object} thisArg
51371     * @chainable
51372     */
51373    centerV: function () {
51374      this.canvas.centerObjectV(this);
51375      return this;
51376    },
51377
51378    /**
51379     * Centers object vertically and horizontally on canvas to which is was added last
51380     * You might need to call `setCoords` on an object after centering, to update controls area.
51381     * @return {fabric.Object} thisArg
51382     * @chainable
51383     */
51384    center: function () {
51385      return this.centerH().centerV();
51386    },
51387
51388    /**
51389     * Removes object from canvas to which it was added last
51390     * @return {fabric.Object} thisArg
51391     * @chainable
51392     */
51393    remove: function() {
51394      return this.canvas.remove(this);
51395    },
51396
51397    /**
51398     * Moves an object to the bottom of the stack of drawn objects
51399     * @return {fabric.Object} thisArg
51400     * @chainable
51401     */
51402    sendToBack: function() {
51403      if (this.group) {
51404        fabric.StaticCanvas.prototype.sendToBack.call(this.group, this);
51405      }
51406      else {
51407        this.canvas.sendToBack(this);
51408      }
51409      return this;
51410    },
51411
51412    /**
51413     * Moves an object to the top of the stack of drawn objects
51414     * @return {fabric.Object} thisArg
51415     * @chainable
51416     */
51417    bringToFront: function() {
51418      if (this.group) {
51419        fabric.StaticCanvas.prototype.bringToFront.call(this.group, this);
51420      }
51421      else {
51422        this.canvas.bringToFront(this);
51423      }
51424      return this;
51425    },
51426
51427    /**
51428     * Moves an object down in stack of drawn objects
51429     * @param {Boolean} [intersecting] If `true`, send object behind next lower intersecting object
51430     * @return {fabric.Object} thisArg
51431     * @chainable
51432     */
51433    sendBackwards: function(intersecting) {
51434      if (this.group) {
51435        fabric.StaticCanvas.prototype.sendBackwards.call(this.group, this, intersecting);
51436      }
51437      else {
51438        this.canvas.sendBackwards(this, intersecting);
51439      }
51440      return this;
51441    },
51442
51443    /**
51444     * Moves an object up in stack of drawn objects
51445     * @param {Boolean} [intersecting] If `true`, send object in front of next upper intersecting object
51446     * @return {fabric.Object} thisArg
51447     * @chainable
51448     */
51449    bringForward: function(intersecting) {
51450      if (this.group) {
51451        fabric.StaticCanvas.prototype.bringForward.call(this.group, this, intersecting);
51452      }
51453      else {
51454        this.canvas.bringForward(this, intersecting);
51455      }
51456      return this;
51457    },
51458
51459    /**
51460     * Moves an object to specified level in stack of drawn objects
51461     * @param {Number} index New position of object
51462     * @return {fabric.Object} thisArg
51463     * @chainable
51464     */
51465    moveTo: function(index) {
51466      if (this.group) {
51467        fabric.StaticCanvas.prototype.moveTo.call(this.group, this, index);
51468      }
51469      else {
51470        this.canvas.moveTo(this, index);
51471      }
51472      return this;
51473    }
51474  });
51475
51476  fabric.util.createAccessors(fabric.Object);
51477
51478  /**
51479   * Alias for {@link fabric.Object.prototype.setAngle}
51480   * @alias rotate -> setAngle
51481   * @memberof fabric.Object
51482   */
51483  fabric.Object.prototype.rotate = fabric.Object.prototype.setAngle;
51484
51485  extend(fabric.Object.prototype, fabric.Observable);
51486
51487  /**
51488   * Defines the number of fraction digits to use when serializing object values.
51489   * You can use it to increase/decrease precision of such values like left, top, scaleX, scaleY, etc.
51490   * @static
51491   * @memberof fabric.Object
51492   * @constant
51493   * @type Number
51494   */
51495  fabric.Object.NUM_FRACTION_DIGITS = 2;
51496
51497  /**
51498   * Unique id used internally when creating SVG elements
51499   * @static
51500   * @memberof fabric.Object
51501   * @type Number
51502   */
51503  fabric.Object.__uid = 0;
51504
51505})(typeof exports !== 'undefined' ? exports : this);
51506
51507
51508(function() {
51509
51510  var degreesToRadians = fabric.util.degreesToRadians;
51511
51512  fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {
51513
51514    /**
51515     * Translates the coordinates from origin to center coordinates (based on the object's dimensions)
51516     * @param {fabric.Point} point The point which corresponds to the originX and originY params
51517     * @param {String} originX Horizontal origin: 'left', 'center' or 'right'
51518     * @param {String} originY Vertical origin: 'top', 'center' or 'bottom'
51519     * @return {fabric.Point}
51520     */
51521    translateToCenterPoint: function(point, originX, originY) {
51522      var cx = point.x, cy = point.y;
51523
51524      if ( originX === "left" ) {
51525        cx = point.x + ( this.getWidth() + (this.strokeWidth*this.scaleX) )/ 2;
51526      }
51527      else if ( originX === "right" ) {
51528        cx = point.x - ( this.getWidth() + (this.strokeWidth*this.scaleX) ) / 2;
51529      }
51530
51531      if ( originY === "top" ) {
51532        cy = point.y +( this.getHeight() + (this.strokeWidth*this.scaleY) ) / 2;
51533      }
51534      else if ( originY === "bottom" ) {
51535        cy = point.y - ( this.getHeight() + (this.strokeWidth*this.scaleY) )  / 2;
51536      }
51537
51538      // Apply the reverse rotation to the point (it's already scaled properly)
51539      return fabric.util.rotatePoint(new fabric.Point(cx, cy), point, degreesToRadians(this.angle));
51540    },
51541
51542    /**
51543     * Translates the coordinates from center to origin coordinates (based on the object's dimensions)
51544     * @param {fabric.Point} point The point which corresponds to center of the object
51545     * @param {String} originX Horizontal origin: 'left', 'center' or 'right'
51546     * @param {String} originY Vertical origin: 'top', 'center' or 'bottom'
51547     * @return {fabric.Point}
51548     */
51549    translateToOriginPoint: function(center, originX, originY) {
51550      var x = center.x, y = center.y;
51551
51552      // Get the point coordinates
51553      if ( originX === "left" ) {
51554        x = center.x - ( this.getWidth() + (this.strokeWidth*this.scaleX) ) / 2;
51555      }
51556      else if ( originX === "right" ) {
51557        x = center.x + ( this.getWidth() + (this.strokeWidth*this.scaleX) ) / 2;
51558      }
51559      if ( originY === "top" ) {
51560        y = center.y - ( this.getHeight() + (this.strokeWidth*this.scaleY) )/ 2;
51561      }
51562      else if ( originY === "bottom" ) {
51563        y = center.y + ( this.getHeight() + (this.strokeWidth*this.scaleY) )/ 2;
51564      }
51565
51566      // Apply the rotation to the point (it's already scaled properly)
51567      return fabric.util.rotatePoint(new fabric.Point(x, y), center, degreesToRadians(this.angle));
51568    },
51569
51570    /**
51571     * Returns the real center coordinates of the object
51572     * @return {fabric.Point}
51573     */
51574    getCenterPoint: function() {
51575      var leftTop = new fabric.Point(this.left, this.top);
51576      return this.translateToCenterPoint(leftTop, this.originX, this.originY);
51577    },
51578
51579    /**
51580     * Returns the coordinates of the object based on center coordinates
51581     * @param {fabric.Point} point The point which corresponds to the originX and originY params
51582     * @return {fabric.Point}
51583     */
51584    // getOriginPoint: function(center) {
51585    //   return this.translateToOriginPoint(center, this.originX, this.originY);
51586    // },
51587
51588    /**
51589     * Returns the coordinates of the object as if it has a different origin
51590     * @param {String} originX Horizontal origin: 'left', 'center' or 'right'
51591     * @param {String} originY Vertical origin: 'top', 'center' or 'bottom'
51592     * @return {fabric.Point}
51593     */
51594    getPointByOrigin: function(originX, originY) {
51595      var center = this.getCenterPoint();
51596      return this.translateToOriginPoint(center, originX, originY);
51597    },
51598
51599    /**
51600     * Returns the point in local coordinates
51601     * @param {fabric.Point} The point relative to the global coordinate system
51602     * @return {fabric.Point}
51603     */
51604    toLocalPoint: function(point, originX, originY) {
51605      var center = this.getCenterPoint();
51606
51607      var x, y;
51608      if (originX !== undefined && originY !== undefined) {
51609        if ( originX === "left" ) {
51610          x = center.x - (this.getWidth() + this.strokeWidth*this.scaleX) / 2;
51611        }
51612        else if ( originX === "right" ) {
51613          x = center.x + (this.getWidth() + this.strokeWidth*this.scaleX)/ 2;
51614        }
51615        else {
51616          x = center.x;
51617        }
51618
51619        if ( originY === "top" ) {
51620          y = center.y - (this.getHeight() + this.strokeWidth*this.scaleY) / 2;
51621        }
51622        else if ( originY === "bottom" ) {
51623          y = center.y + (this.getHeight() + this.strokeWidth*this.scaleY)/ 2;
51624        }
51625        else {
51626          y = center.y;
51627        }
51628      }
51629      else {
51630        x = this.left;
51631        y = this.top;
51632      }
51633
51634      return fabric.util.rotatePoint(new fabric.Point(point.x, point.y), center, -degreesToRadians(this.angle))
51635        .subtractEquals(new fabric.Point(x, y));
51636    },
51637
51638    /**
51639     * Returns the point in global coordinates
51640     * @param {fabric.Point} The point relative to the local coordinate system
51641     * @return {fabric.Point}
51642     */
51643    // toGlobalPoint: function(point) {
51644    //   return fabric.util.rotatePoint(point, this.getCenterPoint(), degreesToRadians(this.angle)).addEquals(new fabric.Point(this.left, this.top));
51645    // },
51646
51647    /**
51648     * Sets the position of the object taking into consideration the object's origin
51649     * @param {fabric.Point} point The new position of the object
51650     * @param {String} originX Horizontal origin: 'left', 'center' or 'right'
51651     * @param {String} originY Vertical origin: 'top', 'center' or 'bottom'
51652     * @return {void}
51653     */
51654    setPositionByOrigin: function(pos, originX, originY) {
51655      var center = this.translateToCenterPoint(pos, originX, originY);
51656      var position = this.translateToOriginPoint(center, this.originX, this.originY);
51657
51658      this.set('left', position.x);
51659      this.set('top', position.y);
51660    },
51661
51662    /**
51663     * @param {String} to One of left, center, right
51664     */
51665    adjustPosition: function(to) {
51666      var angle = degreesToRadians(this.angle);
51667      var hypotHalf = this.getWidth() / 2;
51668      var xHalf = Math.cos(angle) * hypotHalf;
51669      var yHalf = Math.sin(angle) * hypotHalf;
51670      var hypotFull = this.getWidth();
51671      var xFull = Math.cos(angle) * hypotFull;
51672      var yFull = Math.sin(angle) * hypotFull;
51673
51674      if (this.originX === 'center' && to === 'left' ||
51675          this.originX === 'right' && to === 'center') {
51676        // move half left
51677        this.left -= xHalf;
51678        this.top -= yHalf;
51679      }
51680      else if (this.originX === 'left' && to === 'center' ||
51681               this.originX === 'center' && to === 'right') {
51682        // move half right
51683        this.left += xHalf;
51684        this.top += yHalf;
51685      }
51686      else if (this.originX === 'left' && to === 'right') {
51687        // move full right
51688        this.left += xFull;
51689        this.top += yFull;
51690      }
51691      else if (this.originX === 'right' && to === 'left') {
51692        // move full left
51693        this.left -= xFull;
51694        this.top -= yFull;
51695      }
51696
51697      this.setCoords();
51698      this.originX = to;
51699    },
51700
51701    /**
51702     * @private
51703     */
51704    _getLeftTopCoords: function() {
51705      return this.translateToOriginPoint(this.getCenterPoint(), 'left', 'center');
51706    }
51707  });
51708
51709})();
51710
51711
51712(function() {
51713
51714  var degreesToRadians = fabric.util.degreesToRadians;
51715
51716  fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {
51717
51718    /**
51719     * Object containing coordinates of object's controls
51720     * @type Object
51721     * @default
51722     */
51723    oCoords: null,
51724
51725    /**
51726     * Checks if object intersects with an area formed by 2 points
51727     * @param {Object} pointTL top-left point of area
51728     * @param {Object} pointBR bottom-right point of area
51729     * @return {Boolean} true if object intersects with an area formed by 2 points
51730     */
51731    intersectsWithRect: function(pointTL, pointBR) {
51732      var oCoords = this.oCoords,
51733          tl = new fabric.Point(oCoords.tl.x, oCoords.tl.y),
51734          tr = new fabric.Point(oCoords.tr.x, oCoords.tr.y),
51735          bl = new fabric.Point(oCoords.bl.x, oCoords.bl.y),
51736          br = new fabric.Point(oCoords.br.x, oCoords.br.y);
51737
51738      var intersection = fabric.Intersection.intersectPolygonRectangle(
51739        [tl, tr, br, bl],
51740        pointTL,
51741        pointBR
51742      );
51743      return intersection.status === 'Intersection';
51744    },
51745
51746    /**
51747     * Checks if object intersects with another object
51748     * @param {Object} other Object to test
51749     * @return {Boolean} true if object intersects with another object
51750     */
51751    intersectsWithObject: function(other) {
51752      // extracts coords
51753      function getCoords(oCoords) {
51754        return {
51755          tl: new fabric.Point(oCoords.tl.x, oCoords.tl.y),
51756          tr: new fabric.Point(oCoords.tr.x, oCoords.tr.y),
51757          bl: new fabric.Point(oCoords.bl.x, oCoords.bl.y),
51758          br: new fabric.Point(oCoords.br.x, oCoords.br.y)
51759        };
51760      }
51761      var thisCoords = getCoords(this.oCoords),
51762          otherCoords = getCoords(other.oCoords);
51763
51764      var intersection = fabric.Intersection.intersectPolygonPolygon(
51765        [thisCoords.tl, thisCoords.tr, thisCoords.br, thisCoords.bl],
51766        [otherCoords.tl, otherCoords.tr, otherCoords.br, otherCoords.bl]
51767      );
51768
51769      return intersection.status === 'Intersection';
51770    },
51771
51772    /**
51773     * Checks if object is fully contained within area of another object
51774     * @param {Object} other Object to test
51775     * @return {Boolean} true if object is fully contained within area of another object
51776     */
51777    isContainedWithinObject: function(other) {
51778      var boundingRect = other.getBoundingRect(),
51779          point1 = new fabric.Point(boundingRect.left, boundingRect.top),
51780          point2 = new fabric.Point(boundingRect.left + boundingRect.width, boundingRect.top + boundingRect.height);
51781
51782      return this.isContainedWithinRect(point1, point2);
51783    },
51784
51785    /**
51786     * Checks if object is fully contained within area formed by 2 points
51787     * @param {Object} pointTL top-left point of area
51788     * @param {Object} pointBR bottom-right point of area
51789     * @return {Boolean} true if object is fully contained within area formed by 2 points
51790     */
51791    isContainedWithinRect: function(pointTL, pointBR) {
51792      var boundingRect = this.getBoundingRect();
51793
51794      return (
51795        boundingRect.left > pointTL.x &&
51796        boundingRect.left + boundingRect.width < pointBR.x &&
51797        boundingRect.top > pointTL.y &&
51798        boundingRect.top + boundingRect.height < pointBR.y
51799      );
51800    },
51801
51802    /**
51803     * Checks if point is inside the object
51804     * @param {Object} point
51805     * @return {Boolean} true if point is inside the object
51806     */
51807    containsPoint: function(point) {
51808      var lines = this._getImageLines(this.oCoords),
51809          xPoints = this._findCrossPoints(point, lines);
51810
51811      // if xPoints is odd then point is inside the object
51812      return (xPoints !== 0 && xPoints % 2 === 1);
51813    },
51814
51815    /**
51816     * Method that returns an object with the object edges in it, given the coordinates of the corners
51817     * @private
51818     * @param {Object} oCoords Coordinates of the object corners
51819     */
51820    _getImageLines: function(oCoords) {
51821      return {
51822        topline: {
51823          o: oCoords.tl,
51824          d: oCoords.tr
51825        },
51826        rightline: {
51827          o: oCoords.tr,
51828          d: oCoords.br
51829        },
51830        bottomline: {
51831          o: oCoords.br,
51832          d: oCoords.bl
51833        },
51834        leftline: {
51835          o: oCoords.bl,
51836          d: oCoords.tl
51837        }
51838      };
51839    },
51840
51841    /**
51842     * Helper method to determine how many cross points are between the 4 object edges
51843     * and the horizontal line determined by a point on canvas
51844     * @private
51845     * @param {Object} point
51846     * @param {Object} oCoords Coordinates of the image being evaluated
51847     */
51848    _findCrossPoints: function(point, oCoords) {
51849      var b1, b2, a1, a2, xi, yi,
51850          xcount = 0,
51851          iLine;
51852
51853      for (var lineKey in oCoords) {
51854        iLine = oCoords[lineKey];
51855        // optimisation 1: line below point. no cross
51856        if ((iLine.o.y < point.y) && (iLine.d.y < point.y)) {
51857          continue;
51858        }
51859        // optimisation 2: line above point. no cross
51860        if ((iLine.o.y >= point.y) && (iLine.d.y >= point.y)) {
51861          continue;
51862        }
51863        // optimisation 3: vertical line case
51864        if ((iLine.o.x === iLine.d.x) && (iLine.o.x >= point.x)) {
51865          xi = iLine.o.x;
51866          yi = point.y;
51867        }
51868        // calculate the intersection point
51869        else {
51870          b1 = 0;
51871          b2 = (iLine.d.y - iLine.o.y) / (iLine.d.x - iLine.o.x);
51872          a1 = point.y- b1 * point.x;
51873          a2 = iLine.o.y - b2 * iLine.o.x;
51874
51875          xi = - (a1 - a2) / (b1 - b2);
51876          yi = a1 + b1 * xi;
51877        }
51878        // dont count xi < point.x cases
51879        if (xi >= point.x) {
51880          xcount += 1;
51881        }
51882        // optimisation 4: specific for square images
51883        if (xcount === 2) {
51884          break;
51885        }
51886      }
51887      return xcount;
51888    },
51889
51890    /**
51891     * Returns width of an object's bounding rectangle
51892     * @deprecated since 1.0.4
51893     * @return {Number} width value
51894     */
51895    getBoundingRectWidth: function() {
51896      return this.getBoundingRect().width;
51897    },
51898
51899    /**
51900     * Returns height of an object's bounding rectangle
51901     * @deprecated since 1.0.4
51902     * @return {Number} height value
51903     */
51904    getBoundingRectHeight: function() {
51905      return this.getBoundingRect().height;
51906    },
51907
51908    /**
51909     * Returns coordinates of object's bounding rectangle (left, top, width, height)
51910     * @return {Object} Object with left, top, width, height properties
51911     */
51912    getBoundingRect: function() {
51913      this.oCoords || this.setCoords();
51914
51915      var xCoords = [this.oCoords.tl.x, this.oCoords.tr.x, this.oCoords.br.x, this.oCoords.bl.x];
51916      var minX = fabric.util.array.min(xCoords);
51917      var maxX = fabric.util.array.max(xCoords);
51918      var width = Math.abs(minX - maxX);
51919
51920      var yCoords = [this.oCoords.tl.y, this.oCoords.tr.y, this.oCoords.br.y, this.oCoords.bl.y];
51921      var minY = fabric.util.array.min(yCoords);
51922      var maxY = fabric.util.array.max(yCoords);
51923      var height = Math.abs(minY - maxY);
51924
51925      return {
51926        left: minX,
51927        top: minY,
51928        width: width,
51929        height: height
51930      };
51931    },
51932
51933    /**
51934     * Returns width of an object
51935     * @return {Number} width value
51936     */
51937    getWidth: function() {
51938      return this.width * this.scaleX;
51939    },
51940
51941    /**
51942     * Returns height of an object
51943     * @return {Number} height value
51944     */
51945    getHeight: function() {
51946      return this.height * this.scaleY;
51947    },
51948
51949    /**
51950     * Makes sure the scale is valid and modifies it if necessary
51951     * @private
51952     * @param {Number} value
51953     * @return {Number}
51954     */
51955    _constrainScale: function(value) {
51956      if (Math.abs(value) < this.minScaleLimit) {
51957        if (value < 0)
51958          return -this.minScaleLimit;
51959        else
51960          return this.minScaleLimit;
51961      }
51962
51963      return value;
51964    },
51965
51966    /**
51967     * Scales an object (equally by x and y)
51968     * @param value {Number} scale factor
51969     * @return {fabric.Object} thisArg
51970     * @chainable
51971     */
51972    scale: function(value) {
51973      value = this._constrainScale(value);
51974
51975      if (value < 0) {
51976        this.flipX = !this.flipX;
51977        this.flipY = !this.flipY;
51978        value *= -1;
51979      }
51980
51981      this.scaleX = value;
51982      this.scaleY = value;
51983      this.setCoords();
51984      return this;
51985    },
51986
51987    /**
51988     * Scales an object to a given width, with respect to bounding box (scaling by x/y equally)
51989     * @param value {Number} new width value
51990     * @return {fabric.Object} thisArg
51991     * @chainable
51992     */
51993    scaleToWidth: function(value) {
51994      // adjust to bounding rect factor so that rotated shapes would fit as well
51995      var boundingRectFactor = this.getBoundingRectWidth() / this.getWidth();
51996      return this.scale(value / this.width / boundingRectFactor);
51997    },
51998
51999    /**
52000     * Scales an object to a given height, with respect to bounding box (scaling by x/y equally)
52001     * @param value {Number} new height value
52002     * @return {fabric.Object} thisArg
52003     * @chainable
52004     */
52005    scaleToHeight: function(value) {
52006      // adjust to bounding rect factor so that rotated shapes would fit as well
52007      var boundingRectFactor = this.getBoundingRectHeight() / this.getHeight();
52008      return this.scale(value / this.height / boundingRectFactor);
52009    },
52010
52011    /**
52012     * Sets corner position coordinates based on current angle, width and height
52013     * @return {fabric.Object} thisArg
52014     * @chainable
52015     */
52016    setCoords: function() {
52017
52018      var strokeWidth = this.strokeWidth > 1 ? this.strokeWidth : 0,
52019          padding = this.padding,
52020          theta = degreesToRadians(this.angle);
52021
52022      this.currentWidth = (this.width + strokeWidth) * this.scaleX + padding * 2;
52023      this.currentHeight = (this.height + strokeWidth) * this.scaleY + padding * 2;
52024
52025      // If width is negative, make postive. Fixes path selection issue
52026      if (this.currentWidth < 0) {
52027        this.currentWidth = Math.abs(this.currentWidth);
52028      }
52029
52030      var _hypotenuse = Math.sqrt(
52031        Math.pow(this.currentWidth / 2, 2) +
52032        Math.pow(this.currentHeight / 2, 2));
52033
52034      var _angle = Math.atan(isFinite(this.currentHeight / this.currentWidth) ? this.currentHeight / this.currentWidth : 0);
52035
52036      // offset added for rotate and scale actions
52037      var offsetX = Math.cos(_angle + theta) * _hypotenuse,
52038          offsetY = Math.sin(_angle + theta) * _hypotenuse,
52039          sinTh = Math.sin(theta),
52040          cosTh = Math.cos(theta);
52041
52042      var coords = this.getCenterPoint();
52043      var tl = {
52044        x: coords.x - offsetX,
52045        y: coords.y - offsetY
52046      };
52047      var tr = {
52048        x: tl.x + (this.currentWidth * cosTh),
52049        y: tl.y + (this.currentWidth * sinTh)
52050      };
52051      var br = {
52052        x: tr.x - (this.currentHeight * sinTh),
52053        y: tr.y + (this.currentHeight * cosTh)
52054      };
52055      var bl = {
52056        x: tl.x - (this.currentHeight * sinTh),
52057        y: tl.y + (this.currentHeight * cosTh)
52058      };
52059      var ml = {
52060        x: tl.x - (this.currentHeight/2 * sinTh),
52061        y: tl.y + (this.currentHeight/2 * cosTh)
52062      };
52063      var mt = {
52064        x: tl.x + (this.currentWidth/2 * cosTh),
52065        y: tl.y + (this.currentWidth/2 * sinTh)
52066      };
52067      var mr = {
52068        x: tr.x - (this.currentHeight/2 * sinTh),
52069        y: tr.y + (this.currentHeight/2 * cosTh)
52070      };
52071      var mb = {
52072        x: bl.x + (this.currentWidth/2 * cosTh),
52073        y: bl.y + (this.currentWidth/2 * sinTh)
52074      };
52075      var mtr = {
52076        x: mt.x,
52077        y: mt.y
52078      };
52079
52080      // debugging
52081
52082      // setTimeout(function() {
52083      //   canvas.contextTop.fillStyle = 'green';
52084      //   canvas.contextTop.fillRect(mb.x, mb.y, 3, 3);
52085      //   canvas.contextTop.fillRect(bl.x, bl.y, 3, 3);
52086      //   canvas.contextTop.fillRect(br.x, br.y, 3, 3);
52087      //   canvas.contextTop.fillRect(tl.x, tl.y, 3, 3);
52088      //   canvas.contextTop.fillRect(tr.x, tr.y, 3, 3);
52089      //   canvas.contextTop.fillRect(ml.x, ml.y, 3, 3);
52090      //   canvas.contextTop.fillRect(mr.x, mr.y, 3, 3);
52091      //   canvas.contextTop.fillRect(mt.x, mt.y, 3, 3);
52092      // }, 50);
52093
52094      this.oCoords = {
52095        // corners
52096        tl: tl, tr: tr, br: br, bl: bl,
52097        // middle
52098        ml: ml, mt: mt, mr: mr, mb: mb,
52099        // rotating point
52100        mtr: mtr
52101      };
52102
52103      // set coordinates of the draggable boxes in the corners used to scale/rotate the image
52104      this._setCornerCoords && this._setCornerCoords();
52105
52106      return this;
52107    }
52108  });
52109})();
52110
52111
52112/*
52113  Depends on `stateProperties`
52114*/
52115fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {
52116
52117  /**
52118   * Returns true if object state (one of its state properties) was changed
52119   * @return {Boolean} true if instance' state has changed since `{@link fabric.Object#saveState}` was called
52120   */
52121  hasStateChanged: function() {
52122    return this.stateProperties.some(function(prop) {
52123      return this.get(prop) !== this.originalState[prop];
52124    }, this);
52125  },
52126
52127  /**
52128   * Saves state of an object
52129   * @param {Object} [options] Object with additional `stateProperties` array to include when saving state
52130   * @return {fabric.Object} thisArg
52131   */
52132  saveState: function(options) {
52133    this.stateProperties.forEach(function(prop) {
52134      this.originalState[prop] = this.get(prop);
52135    }, this);
52136
52137    if (options && options.stateProperties) {
52138      options.stateProperties.forEach(function(prop) {
52139        this.originalState[prop] = this.get(prop);
52140      }, this);
52141    }
52142
52143    return this;
52144  },
52145
52146  /**
52147   * Setups state of an object
52148   * @return {fabric.Object} thisArg
52149   */
52150  setupState: function() {
52151    this.originalState = { };
52152    this.saveState();
52153
52154    return this;
52155  }
52156});
52157
52158
52159(function(){
52160
52161  var getPointer = fabric.util.getPointer,
52162      degreesToRadians = fabric.util.degreesToRadians;
52163
52164  fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {
52165
52166    /**
52167     * Determines which one of the four corners has been clicked
52168     * @private
52169     * @param {Event} e Event object
52170     * @param {Object} offset Canvas offset
52171     * @return {String|Boolean} corner code (tl, tr, bl, br, etc.), or false if nothing is found
52172     */
52173    _findTargetCorner: function(e, offset) {
52174      if (!this.hasControls || !this.active) return false;
52175
52176      var pointer = getPointer(e, this.canvas.upperCanvasEl),
52177          ex = pointer.x - offset.left,
52178          ey = pointer.y - offset.top,
52179          xPoints,
52180          lines;
52181
52182      for (var i in this.oCoords) {
52183
52184        if (i === 'mtr' && !this.hasRotatingPoint) {
52185          continue;
52186        }
52187
52188        if (this.get('lockUniScaling') && (i === 'mt' || i === 'mr' || i === 'mb' || i === 'ml')) {
52189          continue;
52190        }
52191
52192        lines = this._getImageLines(this.oCoords[i].corner);
52193
52194        // debugging
52195
52196        // canvas.contextTop.fillRect(lines.bottomline.d.x, lines.bottomline.d.y, 2, 2);
52197        // canvas.contextTop.fillRect(lines.bottomline.o.x, lines.bottomline.o.y, 2, 2);
52198
52199        // canvas.contextTop.fillRect(lines.leftline.d.x, lines.leftline.d.y, 2, 2);
52200        // canvas.contextTop.fillRect(lines.leftline.o.x, lines.leftline.o.y, 2, 2);
52201
52202        // canvas.contextTop.fillRect(lines.topline.d.x, lines.topline.d.y, 2, 2);
52203        // canvas.contextTop.fillRect(lines.topline.o.x, lines.topline.o.y, 2, 2);
52204
52205        // canvas.contextTop.fillRect(lines.rightline.d.x, lines.rightline.d.y, 2, 2);
52206        // canvas.contextTop.fillRect(lines.rightline.o.x, lines.rightline.o.y, 2, 2);
52207
52208        xPoints = this._findCrossPoints({x: ex, y: ey}, lines);
52209        if (xPoints !== 0 && xPoints % 2 === 1) {
52210          this.__corner = i;
52211          return i;
52212        }
52213      }
52214      return false;
52215    },
52216
52217    /**
52218     * Sets the coordinates of the draggable boxes in the corners of
52219     * the image used to scale/rotate it.
52220     * @private
52221     */
52222    _setCornerCoords: function() {
52223      var coords = this.oCoords,
52224          theta = degreesToRadians(this.angle),
52225          newTheta = degreesToRadians(45 - this.angle),
52226          cornerHypotenuse = Math.sqrt(2 * Math.pow(this.cornerSize, 2)) / 2,
52227          cosHalfOffset = cornerHypotenuse * Math.cos(newTheta),
52228          sinHalfOffset = cornerHypotenuse * Math.sin(newTheta),
52229          sinTh = Math.sin(theta),
52230          cosTh = Math.cos(theta);
52231
52232      coords.tl.corner = {
52233        tl: {
52234          x: coords.tl.x - sinHalfOffset,
52235          y: coords.tl.y - cosHalfOffset
52236        },
52237        tr: {
52238          x: coords.tl.x + cosHalfOffset,
52239          y: coords.tl.y - sinHalfOffset
52240        },
52241        bl: {
52242          x: coords.tl.x - cosHalfOffset,
52243          y: coords.tl.y + sinHalfOffset
52244        },
52245        br: {
52246          x: coords.tl.x + sinHalfOffset,
52247          y: coords.tl.y + cosHalfOffset
52248        }
52249      };
52250
52251      coords.tr.corner = {
52252        tl: {
52253          x: coords.tr.x - sinHalfOffset,
52254          y: coords.tr.y - cosHalfOffset
52255        },
52256        tr: {
52257          x: coords.tr.x + cosHalfOffset,
52258          y: coords.tr.y - sinHalfOffset
52259        },
52260        br: {
52261          x: coords.tr.x + sinHalfOffset,
52262          y: coords.tr.y + cosHalfOffset
52263        },
52264        bl: {
52265          x: coords.tr.x - cosHalfOffset,
52266          y: coords.tr.y + sinHalfOffset
52267        }
52268      };
52269
52270      coords.bl.corner = {
52271        tl: {
52272          x: coords.bl.x - sinHalfOffset,
52273          y: coords.bl.y - cosHalfOffset
52274        },
52275        bl: {
52276          x: coords.bl.x - cosHalfOffset,
52277          y: coords.bl.y + sinHalfOffset
52278        },
52279        br: {
52280          x: coords.bl.x + sinHalfOffset,
52281          y: coords.bl.y + cosHalfOffset
52282        },
52283        tr: {
52284          x: coords.bl.x + cosHalfOffset,
52285          y: coords.bl.y - sinHalfOffset
52286        }
52287      };
52288
52289      coords.br.corner = {
52290        tr: {
52291          x: coords.br.x + cosHalfOffset,
52292          y: coords.br.y - sinHalfOffset
52293        },
52294        bl: {
52295          x: coords.br.x - cosHalfOffset,
52296          y: coords.br.y + sinHalfOffset
52297        },
52298        br: {
52299          x: coords.br.x + sinHalfOffset,
52300          y: coords.br.y + cosHalfOffset
52301        },
52302        tl: {
52303          x: coords.br.x - sinHalfOffset,
52304          y: coords.br.y - cosHalfOffset
52305        }
52306      };
52307
52308      coords.ml.corner = {
52309        tl: {
52310          x: coords.ml.x - sinHalfOffset,
52311          y: coords.ml.y - cosHalfOffset
52312        },
52313        tr: {
52314          x: coords.ml.x + cosHalfOffset,
52315          y: coords.ml.y - sinHalfOffset
52316        },
52317        bl: {
52318          x: coords.ml.x - cosHalfOffset,
52319          y: coords.ml.y + sinHalfOffset
52320        },
52321        br: {
52322          x: coords.ml.x + sinHalfOffset,
52323          y: coords.ml.y + cosHalfOffset
52324        }
52325      };
52326
52327      coords.mt.corner = {
52328        tl: {
52329          x: coords.mt.x - sinHalfOffset,
52330          y: coords.mt.y - cosHalfOffset
52331        },
52332        tr: {
52333          x: coords.mt.x + cosHalfOffset,
52334          y: coords.mt.y - sinHalfOffset
52335        },
52336        bl: {
52337          x: coords.mt.x - cosHalfOffset,
52338          y: coords.mt.y + sinHalfOffset
52339        },
52340        br: {
52341          x: coords.mt.x + sinHalfOffset,
52342          y: coords.mt.y + cosHalfOffset
52343        }
52344      };
52345
52346      coords.mr.corner = {
52347        tl: {
52348          x: coords.mr.x - sinHalfOffset,
52349          y: coords.mr.y - cosHalfOffset
52350        },
52351        tr: {
52352          x: coords.mr.x + cosHalfOffset,
52353          y: coords.mr.y - sinHalfOffset
52354        },
52355        bl: {
52356          x: coords.mr.x - cosHalfOffset,
52357          y: coords.mr.y + sinHalfOffset
52358        },
52359        br: {
52360          x: coords.mr.x + sinHalfOffset,
52361          y: coords.mr.y + cosHalfOffset
52362        }
52363      };
52364
52365      coords.mb.corner = {
52366        tl: {
52367          x: coords.mb.x - sinHalfOffset,
52368          y: coords.mb.y - cosHalfOffset
52369        },
52370        tr: {
52371          x: coords.mb.x + cosHalfOffset,
52372          y: coords.mb.y - sinHalfOffset
52373        },
52374        bl: {
52375          x: coords.mb.x - cosHalfOffset,
52376          y: coords.mb.y + sinHalfOffset
52377        },
52378        br: {
52379          x: coords.mb.x + sinHalfOffset,
52380          y: coords.mb.y + cosHalfOffset
52381        }
52382      };
52383
52384      coords.mtr.corner = {
52385        tl: {
52386          x: coords.mtr.x - sinHalfOffset + (sinTh * this.rotatingPointOffset),
52387          y: coords.mtr.y - cosHalfOffset - (cosTh * this.rotatingPointOffset)
52388        },
52389        tr: {
52390          x: coords.mtr.x + cosHalfOffset + (sinTh * this.rotatingPointOffset),
52391          y: coords.mtr.y - sinHalfOffset - (cosTh * this.rotatingPointOffset)
52392        },
52393        bl: {
52394          x: coords.mtr.x - cosHalfOffset + (sinTh * this.rotatingPointOffset),
52395          y: coords.mtr.y + sinHalfOffset - (cosTh * this.rotatingPointOffset)
52396        },
52397        br: {
52398          x: coords.mtr.x + sinHalfOffset + (sinTh * this.rotatingPointOffset),
52399          y: coords.mtr.y + cosHalfOffset - (cosTh * this.rotatingPointOffset)
52400        }
52401      };
52402    },
52403    /**
52404     * Draws borders of an object's bounding box.
52405     * Requires public properties: width, height
52406     * Requires public options: padding, borderColor
52407     * @param {CanvasRenderingContext2D} ctx Context to draw on
52408     * @return {fabric.Object} thisArg
52409     * @chainable
52410     */
52411    drawBorders: function(ctx) {
52412      if (!this.hasBorders) return this;
52413
52414      var padding = this.padding,
52415          padding2 = padding * 2,
52416          strokeWidth = ~~(this.strokeWidth / 2) * 2; // Round down to even number
52417
52418      ctx.save();
52419
52420      ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1;
52421      ctx.strokeStyle = this.borderColor;
52422
52423      var scaleX = 1 / this._constrainScale(this.scaleX),
52424          scaleY = 1 / this._constrainScale(this.scaleY);
52425
52426      ctx.lineWidth = 1 / this.borderScaleFactor;
52427
52428      ctx.scale(scaleX, scaleY);
52429
52430      var w = this.getWidth(),
52431          h = this.getHeight();
52432
52433      ctx.strokeRect(
52434        ~~(-(w / 2) - padding - strokeWidth / 2 * this.scaleX) - 0.5, // offset needed to make lines look sharper
52435        ~~(-(h / 2) - padding - strokeWidth / 2 * this.scaleY) - 0.5,
52436        ~~(w + padding2 + strokeWidth * this.scaleX) + 1, // double offset needed to make lines look sharper
52437        ~~(h + padding2 + strokeWidth * this.scaleY) + 1
52438      );
52439
52440      if (this.hasRotatingPoint && !this.get('lockRotation') && this.hasControls) {
52441
52442        var rotateHeight = (
52443          this.flipY
52444            ? h + (strokeWidth * this.scaleY) + (padding * 2)
52445            : -h - (strokeWidth * this.scaleY) - (padding * 2)
52446        ) / 2;
52447
52448        ctx.beginPath();
52449        ctx.moveTo(0, rotateHeight);
52450        ctx.lineTo(0, rotateHeight + (this.flipY ? this.rotatingPointOffset : -this.rotatingPointOffset));
52451        ctx.closePath();
52452        ctx.stroke();
52453      }
52454
52455      ctx.restore();
52456      return this;
52457    },
52458
52459    /**
52460     * Draws corners of an object's bounding box.
52461     * Requires public properties: width, height, scaleX, scaleY
52462     * Requires public options: cornerSize, padding
52463     * @param {CanvasRenderingContext2D} ctx Context to draw on
52464     * @return {fabric.Object} thisArg
52465     * @chainable
52466     */
52467    drawControls: function(ctx) {
52468      if (!this.hasControls) return this;
52469
52470      var size = this.cornerSize,
52471          size2 = size / 2,
52472          strokeWidth2 = ~~(this.strokeWidth / 2), // half strokeWidth rounded down
52473          left = -(this.width / 2),
52474          top = -(this.height / 2),
52475          _left,
52476          _top,
52477          sizeX = size / this.scaleX,
52478          sizeY = size / this.scaleY,
52479          paddingX = this.padding / this.scaleX,
52480          paddingY = this.padding / this.scaleY,
52481          scaleOffsetY = size2 / this.scaleY,
52482          scaleOffsetX = size2 / this.scaleX,
52483          scaleOffsetSizeX = (size2 - size) / this.scaleX,
52484          scaleOffsetSizeY = (size2 - size) / this.scaleY,
52485          height = this.height,
52486          width = this.width,
52487          methodName = this.transparentCorners ? 'strokeRect' : 'fillRect',
52488          transparent = this.transparentCorners,
52489          isVML = typeof G_vmlCanvasManager !== 'undefined';
52490
52491      ctx.save();
52492
52493      ctx.lineWidth = 1 / Math.max(this.scaleX, this.scaleY);
52494
52495      ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1;
52496      ctx.strokeStyle = ctx.fillStyle = this.cornerColor;
52497
52498      // top-left
52499      _left = left - scaleOffsetX - strokeWidth2 - paddingX;
52500      _top = top - scaleOffsetY - strokeWidth2 - paddingY;
52501
52502      isVML || transparent || ctx.clearRect(_left, _top, sizeX, sizeY);
52503      ctx[methodName](_left, _top, sizeX, sizeY);
52504
52505      // top-right
52506      _left = left + width - scaleOffsetX + strokeWidth2 + paddingX;
52507      _top = top - scaleOffsetY - strokeWidth2 - paddingY;
52508
52509      isVML || transparent || ctx.clearRect(_left, _top, sizeX, sizeY);
52510      ctx[methodName](_left, _top, sizeX, sizeY);
52511
52512      // bottom-left
52513      _left = left - scaleOffsetX - strokeWidth2 - paddingX;
52514      _top = top + height + scaleOffsetSizeY + strokeWidth2 + paddingY;
52515
52516      isVML || transparent || ctx.clearRect(_left, _top, sizeX, sizeY);
52517      ctx[methodName](_left, _top, sizeX, sizeY);
52518
52519      // bottom-right
52520      _left = left + width + scaleOffsetSizeX + strokeWidth2 + paddingX;
52521      _top = top + height + scaleOffsetSizeY + strokeWidth2 + paddingY;
52522
52523      isVML || transparent || ctx.clearRect(_left, _top, sizeX, sizeY);
52524      ctx[methodName](_left, _top, sizeX, sizeY);
52525
52526      if (!this.get('lockUniScaling')) {
52527        // middle-top
52528        _left = left + width/2 - scaleOffsetX;
52529        _top = top - scaleOffsetY - strokeWidth2 - paddingY;
52530
52531        isVML || transparent || ctx.clearRect(_left, _top, sizeX, sizeY);
52532        ctx[methodName](_left, _top, sizeX, sizeY);
52533
52534        // middle-bottom
52535        _left = left + width/2 - scaleOffsetX;
52536        _top = top + height + scaleOffsetSizeY + strokeWidth2 + paddingY;
52537
52538        isVML || transparent || ctx.clearRect(_left, _top, sizeX, sizeY);
52539        ctx[methodName](_left, _top, sizeX, sizeY);
52540
52541        // middle-right
52542        _left = left + width + scaleOffsetSizeX + strokeWidth2 + paddingX;
52543        _top = top + height/2 - scaleOffsetY;
52544
52545        isVML || transparent || ctx.clearRect(_left, _top, sizeX, sizeY);
52546        ctx[methodName](_left, _top, sizeX, sizeY);
52547
52548        // middle-left
52549        _left = left - scaleOffsetX - strokeWidth2 - paddingX;
52550        _top = top + height/2 - scaleOffsetY;
52551
52552        isVML || transparent || ctx.clearRect(_left, _top, sizeX, sizeY);
52553        ctx[methodName](_left, _top, sizeX, sizeY);
52554      }
52555
52556      // middle-top-rotate
52557      if (this.hasRotatingPoint) {
52558
52559        _left = left + width/2 - scaleOffsetX;
52560        _top = this.flipY ?
52561          (top + height + (this.rotatingPointOffset / this.scaleY) - sizeY/2 + strokeWidth2 + paddingY)
52562          : (top - (this.rotatingPointOffset / this.scaleY) - sizeY/2 - strokeWidth2 - paddingY);
52563
52564        isVML || transparent || ctx.clearRect(_left, _top, sizeX, sizeY);
52565        ctx[methodName](_left, _top, sizeX, sizeY);
52566      }
52567
vendor: 6,900 bytes, lines 52568-52822
52568      ctx.restore();
52569
52570      return this;
52571    }
52572  });
52573})();
52574
52575
52576fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ {
52577
52578  /**
52579   * Animation duration (in ms) for fx* methods
52580   * @type Number
52581   * @default
52582   */
52583  FX_DURATION: 500,
52584
52585  /**
52586   * Centers object horizontally with animation.
52587   * @param {fabric.Object} object Object to center
52588   * @param {Object} [callbacks] Callbacks object with optional "onComplete" and/or "onChange" properties
52589   * @param {Function} [callbacks.onComplete] Invoked on completion
52590   * @param {Function} [callbacks.onChange] Invoked on every step of animation
52591   * @return {fabric.Canvas} thisArg
52592   * @chainable
52593   */
52594  fxCenterObjectH: function (object, callbacks) {
52595    callbacks = callbacks || { };
52596
52597    var empty = function() { },
52598        onComplete = callbacks.onComplete || empty,
52599        onChange = callbacks.onChange || empty,
52600        _this = this;
52601
52602    fabric.util.animate({
52603      startValue: object.get('left'),
52604      endValue: this.getCenter().left,
52605      duration: this.FX_DURATION,
52606      onChange: function(value) {
52607        object.set('left', value);
52608        _this.renderAll();
52609        onChange();
52610      },
52611      onComplete: function() {
52612        object.setCoords();
52613        onComplete();
52614      }
52615    });
52616
52617    return this;
52618  },
52619
52620  /**
52621   * Centers object vertically with animation.
52622   * @param {fabric.Object} object Object to center
52623   * @param {Object} [callbacks] Callbacks object with optional "onComplete" and/or "onChange" properties
52624   * @param {Function} [callbacks.onComplete] Invoked on completion
52625   * @param {Function} [callbacks.onChange] Invoked on every step of animation
52626   * @return {fabric.Canvas} thisArg
52627   * @chainable
52628   */
52629  fxCenterObjectV: function (object, callbacks) {
52630    callbacks = callbacks || { };
52631
52632    var empty = function() { },
52633        onComplete = callbacks.onComplete || empty,
52634        onChange = callbacks.onChange || empty,
52635        _this = this;
52636
52637    fabric.util.animate({
52638      startValue: object.get('top'),
52639      endValue: this.getCenter().top,
52640      duration: this.FX_DURATION,
52641      onChange: function(value) {
52642        object.set('top', value);
52643        _this.renderAll();
52644        onChange();
52645      },
52646      onComplete: function() {
52647        object.setCoords();
52648        onComplete();
52649      }
52650    });
52651
52652    return this;
52653  },
52654
52655  /**
52656   * Same as `fabric.Canvas#remove` but animated
52657   * @param {fabric.Object} object Object to remove
52658   * @param {Object} [callbacks] Callbacks object with optional "onComplete" and/or "onChange" properties
52659   * @param {Function} [callbacks.onComplete] Invoked on completion
52660   * @param {Function} [callbacks.onChange] Invoked on every step of animation
52661   * @return {fabric.Canvas} thisArg
52662   * @chainable
52663   */
52664  fxRemove: function (object, callbacks) {
52665    callbacks = callbacks || { };
52666
52667    var empty = function() { },
52668        onComplete = callbacks.onComplete || empty,
52669        onChange = callbacks.onChange || empty,
52670        _this = this;
52671
52672    fabric.util.animate({
52673      startValue: object.get('opacity'),
52674      endValue: 0,
52675      duration: this.FX_DURATION,
52676      onStart: function() {
52677        object.set('active', false);
52678      },
52679      onChange: function(value) {
52680        object.set('opacity', value);
52681        _this.renderAll();
52682        onChange();
52683      },
52684      onComplete: function () {
52685        _this.remove(object);
52686        onComplete();
52687      }
52688    });
52689
52690    return this;
52691  }
52692});
52693
52694fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {
52695  /**
52696   * Animates object's properties
52697   * @param {String|Object} property to animate (if string) or properties to animate (if object)
52698   * @param {Number|Object} value to animate property to (if string was given first) or options object
52699   * @return {fabric.Object} thisArg
52700   * @tutorial {@link http://fabricjs.com/fabric-intro-part-2/#animation}
52701   * @chainable
52702   *
52703   * As object — multiple properties
52704   *
52705   * object.animate({ left: ..., top: ... });
52706   * object.animate({ left: ..., top: ... }, { duration: ... });
52707   *
52708   * As string — one property
52709   *
52710   * object.animate('left', ...);
52711   * object.animate('left', { duration: ... });
52712   *
52713   */
52714  animate: function() {
52715    if (arguments[0] && typeof arguments[0] === 'object') {
52716      var propsToAnimate = [ ], prop, skipCallbacks;
52717      for (prop in arguments[0]) {
52718        propsToAnimate.push(prop);
52719      }
52720      for (var i = 0, len = propsToAnimate.length; i<len; i++) {
52721        prop = propsToAnimate[i];
52722        skipCallbacks = i !== len - 1;
52723        this._animate(prop, arguments[0][prop], arguments[1], skipCallbacks);
52724      }
52725    }
52726    else {
52727      this._animate.apply(this, arguments);
52728    }
52729    return this;
52730  },
52731
52732  /**
52733   * @private
52734   * @param {String} property Property to animate
52735   * @param {String} to Value to animate to
52736   * @param {Object} [options] Options object
52737   * @param {Boolean} [skipCallbacks] When true, callbacks like onchange and oncomplete are not invoked
52738   */
52739  _animate: function(property, to, options, skipCallbacks) {
52740    var obj = this, propPair;
52741
52742    to = to.toString();
52743
52744    if (!options) {
52745      options = { };
52746    }
52747    else {
52748      options = fabric.util.object.clone(options);
52749    }
52750
52751    if (~property.indexOf('.')) {
52752      propPair = property.split('.');
52753    }
52754
52755    var currentValue = propPair
52756      ? this.get(propPair[0])[propPair[1]]
52757      : this.get(property);
52758
52759    if (!('from' in options)) {
52760      options.from = currentValue;
52761    }
52762
52763    if (~to.indexOf('=')) {
52764      to = currentValue + parseFloat(to.replace('=', ''));
52765    }
52766    else {
52767      to = parseFloat(to);
52768    }
52769
52770    fabric.util.animate({
52771      startValue: options.from,
52772      endValue: to,
52773      byValue: options.by,
52774      easing: options.easing,
52775      duration: options.duration,
52776      abort: options.abort && function() {
52777        return options.abort.call(obj);
52778      },
52779      onChange: function(value) {
52780        if (propPair) {
52781          obj[propPair[0]][propPair[1]] = value;
52782        }
52783        else {
52784          obj.set(property, value);
52785        }
52786        if (skipCallbacks) return;
52787        options.onChange && options.onChange();
52788      },
52789      onComplete: function() {
52790        if (skipCallbacks) return;
52791
52792        obj.setCoords();
52793        options.onComplete && options.onComplete();
52794      }
52795    });
52796  }
52797});
52798
52799
52800(function(global) {
52801
52802  "use strict";
52803
52804  var fabric = global.fabric || (global.fabric = { }),
52805      extend = fabric.util.object.extend,
52806      coordProps = { 'x1': 1, 'x2': 1, 'y1': 1, 'y2': 1 },
52807      supportsLineDash = fabric.StaticCanvas.supports('setLineDash');
52808
52809  if (fabric.Line) {
52810    fabric.warn('fabric.Line is already defined');
52811    return;
52812  }
52813
52814  /**
52815   * Line class
52816   * @class fabric.Line
52817   * @extends fabric.Object
52818   */
52819  fabric.Line = fabric.util.createClass(fabric.Object, /** @lends fabric.Line.prototype */ {
52820
52821    /**
52822     * Type of an object
52823     * @type String
52824     * @default
52825     */
52826    type: 'line',
52827
52828    /**
52829     * Constructor
52830     * @param {Array} [points] Array of points
52831     * @param {Object} [options] Options object
52832     * @return {fabric.Line} thisArg
52833     */
52834    initialize: function(points, options) {
52835      options = options || { };
52836
52837      if (!points) {
52838        points = [0, 0, 0, 0];
52839      }
52840
52841      this.callSuper('initialize', options);
52842
52843      this.set('x1', points[0]);
52844      this.set('y1', points[1]);
52845      this.set('x2', points[2]);
52846      this.set('y2', points[3]);
52847
52848      this._setWidthHeight(options);
52849    },
52850
52851    /**
52852     * @private
52853     * @param {Object} [options] Options
52854     */
52855    _setWidthHeight: function(options) {
52856      options || (options = { });
52857
52858      this.set('width', Math.abs(this.x2 - this.x1) || 1);
52859      this.set('height', Math.abs(this.y2 - this.y1) || 1);
52860
52861      this.set('left', 'left' in options ? options.left : (Math.min(this.x1, this.x2) + this.width / 2));
52862      this.set('top', 'top' in options ? options.top : (Math.min(this.y1, this.y2) + this.height / 2));
52863    },
52864
52865    /**
52866     * @private
52867     * @param {String} key
52868     * @param {Any} value
52869     */
52870    _set: function(key, value) {
52871      this[key] = value;
52872      if (key in coordProps) {
52873        this._setWidthHeight();
52874      }
52875      return this;
52876    },
52877
52878    /**
52879     * @private
52880     * @param {CanvasRenderingContext2D} ctx Context to render on
52881     */
52882    _render: function(ctx) {
52883      ctx.beginPath();
52884
52885      var isInPathGroup = this.group && this.group.type !== 'group';
52886      if (isInPathGroup && !this.transformMatrix) {
52887        ctx.translate(-this.group.width/2 + this.left, -this.group.height / 2 + this.top);
52888      }
52889
52890      if (!this.strokeDashArray || this.strokeDashArray && supportsLineDash) {
52891
52892        // move from center (of virtual box) to its left/top corner
52893        // we can't assume x1, y1 is top left and x2, y2 is bottom right
52894        var xMult = this.x1 <= this.x2 ? -1 : 1;
52895        var yMult = this.y1 <= this.y2 ? -1 : 1;
52896
52897        ctx.moveTo(
52898          this.width === 1 ? 0 : (xMult * this.width / 2),
52899          this.height === 1 ? 0 : (yMult * this.height / 2));
52900
52901        ctx.lineTo(
52902          this.width === 1 ? 0 : (xMult * -1 * this.width / 2),
52903          this.height === 1 ? 0 : (yMult * -1 * this.height / 2));
52904      }
52905
52906      ctx.lineWidth = this.strokeWidth;
52907
52908      // TODO: test this
52909      // make sure setting "fill" changes color of a line
52910      // (by copying fillStyle to strokeStyle, since line is stroked, not filled)
52911      var origStrokeStyle = ctx.strokeStyle;
52912      ctx.strokeStyle = this.stroke || ctx.fillStyle;
52913      this._renderStroke(ctx);
52914      ctx.strokeStyle = origStrokeStyle;
52915    },
52916
52917    /**
52918     * @private
52919     * @param {CanvasRenderingContext2D} ctx Context to render on
52920     */
52921    _renderDashedStroke: function(ctx) {
52922      var
52923        xMult = this.x1 <= this.x2 ? -1 : 1,
52924        yMult = this.y1 <= this.y2 ? -1 : 1,
52925        x = this.width === 1 ? 0 : xMult * this.width / 2,
52926        y = this.height === 1 ? 0 : yMult * this.height / 2;
52927
52928      ctx.beginPath();
52929      fabric.util.drawDashedLine(ctx, x, y, -x, -y, this.strokeDashArray);
52930      ctx.closePath();
52931    },
52932
52933    /**
52934     * Returns object representation of an instance
52935     * @methd toObject
52936     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output
52937     * @return {Object} object representation of an instance
52938     */
52939    toObject: function(propertiesToInclude) {
52940      return extend(this.callSuper('toObject', propertiesToInclude), {
52941        x1: this.get('x1'),
52942        y1: this.get('y1'),
52943        x2: this.get('x2'),
52944        y2: this.get('y2')
52945      });
52946    },
52947
52948    /* _TO_SVG_START_ */
52949    /**
52950     * Returns SVG representation of an instance
52951     * @param {Function} [reviver] Method for further parsing of svg representation.
52952     * @return {String} svg representation of an instance
52953     */
52954    toSVG: function(reviver) {
52955      var markup = this._createBaseSVGMarkup();
52956
52957      markup.push(
52958        '<line ',
52959          'x1="', this.get('x1'),
52960          '" y1="', this.get('y1'),
52961          '" x2="', this.get('x2'),
52962          '" y2="', this.get('y2'),
52963          '" style="', this.getSvgStyles(),
52964        '"/>'
52965      );
52966
52967      return reviver ? reviver(markup.join('')) : markup.join('');
52968    },
52969    /* _TO_SVG_END_ */
52970
52971    /**
52972     * Returns complexity of an instance
52973     * @return {Number} complexity
52974     */
52975    complexity: function() {
52976      return 1;
52977    }
52978  });
52979
52980  /* _FROM_SVG_START_ */
52981  /**
52982   * List of attribute names to account for when parsing SVG element (used by {@link fabric.Line.fromElement})
52983   * @static
52984   * @memberOf fabric.Line
52985   * @see http://www.w3.org/TR/SVG/shapes.html#LineElement
52986   */
52987  fabric.Line.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('x1 y1 x2 y2'.split(' '));
52988
52989  /**
52990   * Returns fabric.Line instance from an SVG element
52991   * @static
52992   * @memberOf fabric.Line
52993   * @param {SVGElement} element Element to parse
52994   * @param {Object} [options] Options object
52995   * @return {fabric.Line} instance of fabric.Line
52996   */
52997  fabric.Line.fromElement = function(element, options) {
52998    var parsedAttributes = fabric.parseAttributes(element, fabric.Line.ATTRIBUTE_NAMES);
52999    var points = [
53000      parsedAttributes.x1 || 0,
53001      parsedAttributes.y1 || 0,
53002      parsedAttributes.x2 || 0,
53003      parsedAttributes.y2 || 0
53004    ];
53005    return new fabric.Line(points, extend(parsedAttributes, options));
53006  };
53007  /* _FROM_SVG_END_ */
53008
53009  /**
53010   * Returns fabric.Line instance from an object representation
53011   * @static
53012   * @memberOf fabric.Line
53013   * @param {Object} object Object to create an instance from
53014   * @return {fabric.Line} instance of fabric.Line
53015   */
53016  fabric.Line.fromObject = function(object) {
53017    var points = [object.x1, object.y1, object.x2, object.y2];
53018    return new fabric.Line(points, object);
53019  };
53020
53021})(typeof exports !== 'undefined' ? exports : this);
53022
53023
53024(function(global) {
53025
53026  "use strict";
53027
53028  var fabric  = global.fabric || (global.fabric = { }),
53029      piBy2   = Math.PI * 2,
53030      extend = fabric.util.object.extend;
53031
53032  if (fabric.Circle) {
53033    fabric.warn('fabric.Circle is already defined.');
53034    return;
53035  }
53036
53037  /**
53038   * Circle class
53039   * @class fabric.Circle
53040   * @extends fabric.Object
53041   */
53042  fabric.Circle = fabric.util.createClass(fabric.Object, /** @lends fabric.Circle.prototype */ {
53043
53044    /**
53045     * Type of an object
53046     * @type String
53047     * @default
53048     */
53049    type: 'circle',
53050
53051    /**
53052     * Constructor
53053     * @param {Object} [options] Options object
53054     * @return {fabric.Circle} thisArg
53055     */
53056    initialize: function(options) {
53057      options = options || { };
53058
53059      this.set('radius', options.radius || 0);
53060      this.callSuper('initialize', options);
53061    },
53062
53063    /**
53064     * @private
53065     * @param {String} key
53066     * @param {Any} value
53067     * @return {fabric.Circle} thisArg
53068     */
53069    _set: function(key, value) {
53070      this.callSuper('_set', key, value);
53071
53072      if (key === 'radius') {
53073        this.setRadius(value);
53074      }
53075
53076      return this;
53077    },
53078
53079    /**
53080     * Returns object representation of an instance
53081     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output
53082     * @return {Object} object representation of an instance
53083     */
53084    toObject: function(propertiesToInclude) {
53085      return extend(this.callSuper('toObject', propertiesToInclude), {
53086        radius: this.get('radius')
53087      });
53088    },
53089
53090    /* _TO_SVG_START_ */
53091    /**
53092     * Returns svg representation of an instance
53093     * @param {Function} [reviver] Method for further parsing of svg representation.
53094     * @return {String} svg representation of an instance
53095     */
53096    toSVG: function(reviver) {
53097      var markup = this._createBaseSVGMarkup();
53098
53099      markup.push(
53100        '<circle ',
53101          'cx="0" cy="0" ',
53102          'r="', this.radius,
53103          '" style="', this.getSvgStyles(),
53104          '" transform="', this.getSvgTransform(),
53105        '"/>'
53106      );
53107
53108      return reviver ? reviver(markup.join('')) : markup.join('');
53109    },
53110    /* _TO_SVG_END_ */
53111
53112    /**
53113     * @private
53114     * @param ctx {CanvasRenderingContext2D} context to render on
53115     */
53116    _render: function(ctx, noTransform) {
53117      ctx.beginPath();
53118      // multiply by currently set alpha (the one that was set by path group where this object is contained, for example)
53119      ctx.globalAlpha = this.group ? (ctx.globalAlpha * this.opacity) : this.opacity;
53120      ctx.arc(noTransform ? this.left : 0, noTransform ? this.top : 0, this.radius, 0, piBy2, false);
53121      ctx.closePath();
53122
53123      this._renderFill(ctx);
53124      this._renderStroke(ctx);
53125    },
53126
53127    /**
53128     * Returns horizontal radius of an object (according to how an object is scaled)
53129     * @return {Number}
53130     */
53131    getRadiusX: function() {
53132      return this.get('radius') * this.get('scaleX');
53133    },
53134
53135    /**
53136     * Returns vertical radius of an object (according to how an object is scaled)
53137     * @return {Number}
53138     */
53139    getRadiusY: function() {
53140      return this.get('radius') * this.get('scaleY');
53141    },
53142
53143    /**
53144     * Sets radius of an object (and updates width accordingly)
53145     * @return {Number}
53146     */
53147    setRadius: function(value) {
53148      this.radius = value;
53149      this.set('width', value * 2).set('height', value * 2);
53150    },
53151
53152    /**
53153     * Returns complexity of an instance
53154     * @return {Number} complexity of this instance
53155     */
53156    complexity: function() {
53157      return 1;
53158    }
53159  });
53160
53161  /* _FROM_SVG_START_ */
53162  /**
53163   * List of attribute names to account for when parsing SVG element (used by {@link fabric.Circle.fromElement})
53164   * @static
53165   * @memberOf fabric.Circle
53166   * @see: http://www.w3.org/TR/SVG/shapes.html#CircleElement
53167   */
53168  fabric.Circle.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('cx cy r'.split(' '));
53169
53170  /**
53171   * Returns {@link fabric.Circle} instance from an SVG element
53172   * @static
53173   * @memberOf fabric.Circle
53174   * @param {SVGElement} element Element to parse
53175   * @param {Object} [options] Options object
53176   * @throws {Error} If value of `r` attribute is missing or invalid
53177   * @return {fabric.Circle} Instance of fabric.Circle
53178   */
53179  fabric.Circle.fromElement = function(element, options) {
53180    options || (options = { });
53181    var parsedAttributes = fabric.parseAttributes(element, fabric.Circle.ATTRIBUTE_NAMES);
53182    if (!isValidRadius(parsedAttributes)) {
53183      throw new Error('value of `r` attribute is required and can not be negative');
53184    }
53185    if ('left' in parsedAttributes) {
53186      parsedAttributes.left -= (options.width / 2) || 0;
53187    }
53188    if ('top' in parsedAttributes) {
53189      parsedAttributes.top -= (options.height / 2) || 0;
53190    }
53191    var obj = new fabric.Circle(extend(parsedAttributes, options));
53192
53193    obj.cx = parseFloat(element.getAttribute('cx')) || 0;
53194    obj.cy = parseFloat(element.getAttribute('cy')) || 0;
53195
53196    return obj;
53197  };
53198
53199  /**
53200   * @private
53201   */
53202  function isValidRadius(attributes) {
53203    return (('radius' in attributes) && (attributes.radius > 0));
53204  }
53205  /* _FROM_SVG_END_ */
53206
53207  /**
53208   * Returns {@link fabric.Circle} instance from an object representation
53209   * @static
53210   * @memberOf fabric.Circle
53211   * @param {Object} object Object to create an instance from
53212   * @return {Object} Instance of fabric.Circle
53213   */
53214  fabric.Circle.fromObject = function(object) {
53215    return new fabric.Circle(object);
53216  };
53217
53218})(typeof exports !== 'undefined' ? exports : this);
53219
53220
53221(function(global) {
53222
53223  "use strict";
53224
53225  var fabric = global.fabric || (global.fabric = { });
53226
53227  if (fabric.Triangle) {
53228    fabric.warn('fabric.Triangle is already defined');
53229    return;
53230  }
53231
53232  /**
53233   * Triangle class
53234   * @class fabric.Triangle
53235   * @extends fabric.Object
53236   * @return {fabric.Triangle} thisArg
53237   */
53238  fabric.Triangle = fabric.util.createClass(fabric.Object, /** @lends fabric.Triangle.prototype */ {
53239
53240    /**
53241     * Type of an object
53242     * @type String
53243     * @default
53244     */
53245    type: 'triangle',
53246
53247    /**
53248     * Constructor
53249     * @param {Object} [options] Options object
53250     * @return {Object} thisArg
53251     */
53252    initialize: function(options) {
53253      options = options || { };
53254
53255      this.callSuper('initialize', options);
53256
53257      this.set('width', options.width || 100)
53258          .set('height', options.height || 100);
53259    },
53260
53261    /**
53262     * @private
53263     * @param ctx {CanvasRenderingContext2D} Context to render on
53264     */
53265    _render: function(ctx) {
53266      var widthBy2 = this.width / 2,
53267          heightBy2 = this.height / 2;
53268
53269      ctx.beginPath();
53270      ctx.moveTo(-widthBy2, heightBy2);
53271      ctx.lineTo(0, -heightBy2);
53272      ctx.lineTo(widthBy2, heightBy2);
53273      ctx.closePath();
53274
53275      this._renderFill(ctx);
53276      this._renderStroke(ctx);
53277    },
53278
53279    /**
53280     * @private
53281     * @param ctx {CanvasRenderingContext2D} Context to render on
53282     */
53283    _renderDashedStroke: function(ctx) {
53284      var widthBy2 = this.width / 2,
53285          heightBy2 = this.height / 2;
53286
53287      ctx.beginPath();
53288      fabric.util.drawDashedLine(ctx, -widthBy2, heightBy2, 0, -heightBy2, this.strokeDashArray);
53289      fabric.util.drawDashedLine(ctx, 0, -heightBy2, widthBy2, heightBy2, this.strokeDashArray);
53290      fabric.util.drawDashedLine(ctx, widthBy2, heightBy2, -widthBy2, heightBy2, this.strokeDashArray);
53291      ctx.closePath();
53292    },
53293
53294    /* _TO_SVG_START_ */
53295    /**
53296     * Returns SVG representation of an instance
53297     * @param {Function} [reviver] Method for further parsing of svg representation.
53298     * @return {String} svg representation of an instance
53299     */
53300    toSVG: function(reviver) {
53301      var markup = this._createBaseSVGMarkup(),
53302          widthBy2 = this.width / 2,
53303          heightBy2 = this.height / 2;
53304
53305      var points = [
53306        -widthBy2 + " " + heightBy2,
53307        "0 " + -heightBy2,
53308        widthBy2 + " " + heightBy2
53309      ].join(",");
53310
53311      markup.push(
53312        '<polygon ',
53313          'points="', points,
53314          '" style="', this.getSvgStyles(),
53315          '" transform="', this.getSvgTransform(),
53316        '"/>'
53317      );
53318
53319      return reviver ? reviver(markup.join('')) : markup.join('');
53320    },
53321    /* _TO_SVG_END_ */
53322
53323    /**
53324     * Returns complexity of an instance
53325     * @return {Number} complexity of this instance
53326     */
53327    complexity: function() {
53328      return 1;
53329    }
53330  });
53331
53332  /**
53333   * Returns fabric.Triangle instance from an object representation
53334   * @static
53335   * @memberOf fabric.Triangle
53336   * @param object {Object} object to create an instance from
53337   * @return {Object} instance of Canvas.Triangle
53338   */
53339  fabric.Triangle.fromObject = function(object) {
53340    return new fabric.Triangle(object);
53341  };
53342
53343})(typeof exports !== 'undefined' ? exports : this);
53344
53345
53346(function(global){
53347
53348  "use strict";
53349
53350  var fabric = global.fabric || (global.fabric = { }),
53351      piBy2   = Math.PI * 2,
53352      extend = fabric.util.object.extend;
53353
53354  if (fabric.Ellipse) {
53355    fabric.warn('fabric.Ellipse is already defined.');
53356    return;
53357  }
53358
53359  /**
53360   * Ellipse class
53361   * @class fabric.Ellipse
53362   * @extends fabric.Object
53363   * @return {fabric.Ellipse} thisArg
53364   */
53365  fabric.Ellipse = fabric.util.createClass(fabric.Object, /** @lends fabric.Ellipse.prototype */ {
53366
53367    /**
53368     * Type of an object
53369     * @type String
53370     * @default
53371     */
53372    type: 'ellipse',
53373
53374    /**
53375     * Horizontal radius
53376     * @type Number
53377     * @default
53378     */
53379    rx:   0,
53380
53381    /**
53382     * Vertical radius
53383     * @type Number
53384     * @default
53385     */
53386    ry:   0,
53387
53388    /**
53389     * Constructor
53390     * @param {Object} [options] Options object
53391     * @return {fabric.Ellipse} thisArg
53392     */
53393    initialize: function(options) {
53394      options = options || { };
53395
53396      this.callSuper('initialize', options);
53397
53398      this.set('rx', options.rx || 0);
53399      this.set('ry', options.ry || 0);
53400
53401      this.set('width', this.get('rx') * 2);
53402      this.set('height', this.get('ry') * 2);
53403    },
53404
53405    /**
53406     * Returns object representation of an instance
53407     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output
53408     * @return {Object} object representation of an instance
53409     */
53410    toObject: function(propertiesToInclude) {
53411      return extend(this.callSuper('toObject', propertiesToInclude), {
53412        rx: this.get('rx'),
53413        ry: this.get('ry')
53414      });
53415    },
53416
53417    /* _TO_SVG_START_ */
53418    /**
53419     * Returns svg representation of an instance
53420     * @param {Function} [reviver] Method for further parsing of svg representation.
53421     * @return {String} svg representation of an instance
53422     */
53423    toSVG: function(reviver) {
53424      var markup = this._createBaseSVGMarkup();
53425
53426      markup.push(
53427        '<ellipse ',
53428          'rx="', this.get('rx'),
53429          '" ry="', this.get('ry'),
53430          '" style="', this.getSvgStyles(),
53431          '" transform="', this.getSvgTransform(),
53432        '"/>'
53433      );
53434
53435      return reviver ? reviver(markup.join('')) : markup.join('');
53436    },
53437    /* _TO_SVG_END_ */
53438
53439    /**
53440     * Renders this instance on a given context
53441     * @param ctx {CanvasRenderingContext2D} context to render on
53442     * @param noTransform {Boolean} context is not transformed when set to true
53443     */
53444    render: function(ctx, noTransform) {
53445      // do not use `get` for perf. reasons
53446      if (this.rx === 0 || this.ry === 0) return;
53447      return this.callSuper('render', ctx, noTransform);
53448    },
53449
53450    /**
53451     * @private
53452     * @param ctx {CanvasRenderingContext2D} context to render on
53453     */
53454    _render: function(ctx, noTransform) {
53455      ctx.beginPath();
53456      ctx.save();
53457      ctx.globalAlpha = this.group ? (ctx.globalAlpha * this.opacity) : this.opacity;
53458      if (this.transformMatrix && this.group) {
53459        ctx.translate(this.cx, this.cy);
53460      }
53461      ctx.transform(1, 0, 0, this.ry/this.rx, 0, 0);
53462      ctx.arc(noTransform ? this.left : 0, noTransform ? this.top : 0, this.rx, 0, piBy2, false);
53463
53464      this._renderFill(ctx);
53465      this._renderStroke(ctx);
53466      ctx.restore();
53467    },
53468
53469    /**
53470     * Returns complexity of an instance
53471     * @return {Number} complexity
53472     */
53473    complexity: function() {
53474      return 1;
53475    }
53476  });
53477
53478  /* _FROM_SVG_START_ */
53479  /**
53480   * List of attribute names to account for when parsing SVG element (used by {@link fabric.Ellipse.fromElement})
53481   * @static
53482   * @memberOf fabric.Ellipse
53483   * @see http://www.w3.org/TR/SVG/shapes.html#EllipseElement
53484   */
53485  fabric.Ellipse.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('cx cy rx ry'.split(' '));
53486
53487  /**
53488   * Returns {@link fabric.Ellipse} instance from an SVG element
53489   * @static
53490   * @memberOf fabric.Ellipse
53491   * @param {SVGElement} element Element to parse
53492   * @param {Object} [options] Options object
53493   * @return {fabric.Ellipse}
53494   */
53495  fabric.Ellipse.fromElement = function(element, options) {
53496    options || (options = { });
53497
53498    var parsedAttributes = fabric.parseAttributes(element, fabric.Ellipse.ATTRIBUTE_NAMES);
53499    var cx = parsedAttributes.left;
53500    var cy = parsedAttributes.top;
53501
53502    if ('left' in parsedAttributes) {
53503      parsedAttributes.left -= (options.width / 2) || 0;
53504    }
53505    if ('top' in parsedAttributes) {
53506      parsedAttributes.top -= (options.height / 2) || 0;
53507    }
53508
53509    var ellipse = new fabric.Ellipse(extend(parsedAttributes, options));
53510
53511    ellipse.cx = cx || 0;
53512    ellipse.cy = cy || 0;
53513
53514    return ellipse;
53515  };
53516  /* _FROM_SVG_END_ */
53517
53518  /**
53519   * Returns {@link fabric.Ellipse} instance from an object representation
53520   * @static
53521   * @memberOf fabric.Ellipse
53522   * @param {Object} object Object to create an instance from
53523   * @return {fabric.Ellipse}
53524   */
53525  fabric.Ellipse.fromObject = function(object) {
53526    return new fabric.Ellipse(object);
53527  };
53528
53529})(typeof exports !== 'undefined' ? exports : this);
53530
53531
53532(function(global) {
53533
53534  "use strict";
53535
53536  var fabric = global.fabric || (global.fabric = { }),
53537      extend = fabric.util.object.extend;
53538
53539  if (fabric.Rect) {
53540    console.warn('fabric.Rect is already defined');
53541    return;
53542  }
53543
53544  var stateProperties = fabric.Object.prototype.stateProperties.concat();
53545  stateProperties.push('rx', 'ry', 'x', 'y');
53546
53547  /**
53548   * Rectangle class
53549   * @class fabric.Rect
53550   * @extends fabric.Object
53551   * @return {fabric.Rect} thisArg
53552   */
53553  fabric.Rect = fabric.util.createClass(fabric.Object, /** @lends fabric.Rect.prototype */ {
53554
53555    /**
53556     * List of properties to consider when checking if state of an object is changed ({@link fabric.Object#hasStateChanged})
53557     * as well as for history (undo/redo) purposes
53558     * @type Array
53559     */
53560    stateProperties: stateProperties,
53561
53562    /**
53563     * Type of an object
53564     * @type String
53565     * @default
53566     */
53567    type: 'rect',
53568
53569    /**
53570     * Horizontal border radius
53571     * @type Number
53572     * @default
53573     */
53574    rx:   0,
53575
53576    /**
53577     * Vertical border radius
53578     * @type Number
53579     * @default
53580     */
53581    ry:   0,
53582
53583    /**
53584     * @type Number
53585     * @default
53586     */
53587    x: 0,
53588
53589    /**
53590     * @type Number
53591     * @default
53592     */
53593    y: 0,
53594
53595    /**
53596     * Used to specify dash pattern for stroke on this object
53597     * @type Array
53598     */
53599    strokeDashArray: null,
53600
53601    /**
53602     * Constructor
53603     * @param {Object} [options] Options object
53604     * @return {Object} thisArg
53605     */
53606    initialize: function(options) {
53607      options = options || { };
53608
53609      this.callSuper('initialize', options);
53610      this._initRxRy();
53611
53612      this.x = options.x || 0;
53613      this.y = options.y || 0;
53614    },
53615
53616    /**
53617     * Initializes rx/ry attributes
53618     * @private
53619     */
53620    _initRxRy: function() {
53621      if (this.rx && !this.ry) {
53622        this.ry = this.rx;
53623      }
53624      else if (this.ry && !this.rx) {
53625        this.rx = this.ry;
53626      }
53627    },
53628
53629    /**
53630     * @private
53631     * @param ctx {CanvasRenderingContext2D} context to render on
53632     */
53633    _render: function(ctx) {
53634      var rx = this.rx || 0,
53635          ry = this.ry || 0,
53636          x = -this.width / 2,
53637          y = -this.height / 2,
53638          w = this.width,
53639          h = this.height,
53640          isInPathGroup = this.group && this.group.type !== 'group';
53641
53642      ctx.beginPath();
53643      ctx.globalAlpha = isInPathGroup ? (ctx.globalAlpha * this.opacity) : this.opacity;
53644
53645      if (this.transformMatrix && isInPathGroup) {
53646        ctx.translate(
53647          this.width / 2 + this.x,
53648          this.height / 2 + this.y);
53649      }
53650      if (!this.transformMatrix && isInPathGroup) {
53651        ctx.translate(
53652          -this.group.width / 2 + this.width / 2 + this.x,
53653          -this.group.height / 2 + this.height / 2 + this.y);
53654      }
53655
53656      var isRounded = rx !== 0 || ry !== 0;
53657
53658      ctx.moveTo(x+rx, y);
53659      ctx.lineTo(x+w-rx, y);
53660      isRounded && ctx.quadraticCurveTo(x+w, y, x+w, y+ry, x+w, y+ry);
53661      ctx.lineTo(x+w, y+h-ry);
53662      isRounded && ctx.quadraticCurveTo(x+w,y+h,x+w-rx,y+h,x+w-rx,y+h);
53663      ctx.lineTo(x+rx,y+h);
53664      isRounded && ctx.quadraticCurveTo(x,y+h,x,y+h-ry,x,y+h-ry);
53665      ctx.lineTo(x,y+ry);
53666      isRounded && ctx.quadraticCurveTo(x,y,x+rx,y,x+rx,y);
53667      ctx.closePath();
53668
53669      this._renderFill(ctx);
53670      this._renderStroke(ctx);
53671    },
53672
53673    /**
53674     * @private
53675     * @param ctx {CanvasRenderingContext2D} context to render on
53676     */
53677    _renderDashedStroke: function(ctx) {
53678     var x = -this.width/2,
53679         y = -this.height/2,
53680         w = this.width,
53681         h = this.height;
53682
53683      ctx.beginPath();
53684      fabric.util.drawDashedLine(ctx, x, y, x+w, y, this.strokeDashArray);
53685      fabric.util.drawDashedLine(ctx, x+w, y, x+w, y+h, this.strokeDashArray);
53686      fabric.util.drawDashedLine(ctx, x+w, y+h, x, y+h, this.strokeDashArray);
53687      fabric.util.drawDashedLine(ctx, x, y+h, x, y, this.strokeDashArray);
53688      ctx.closePath();
53689    },
53690
53691    /**
53692     * Since coordinate system differs from that of SVG
53693     * @private
53694     */
53695    _normalizeLeftTopProperties: function(parsedAttributes) {
53696      if ('left' in parsedAttributes) {
53697        this.set('left', parsedAttributes.left + this.getWidth() / 2);
53698      }
53699      this.set('x', parsedAttributes.left || 0);
53700      if ('top' in parsedAttributes) {
53701        this.set('top', parsedAttributes.top + this.getHeight() / 2);
53702      }
53703      this.set('y', parsedAttributes.top || 0);
53704      return this;
53705    },
53706
53707    /**
53708     * Returns object representation of an instance
53709     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output
53710     * @return {Object} object representation of an instance
53711     */
53712    toObject: function(propertiesToInclude) {
53713      var object = extend(this.callSuper('toObject', propertiesToInclude), {
53714        rx: this.get('rx') || 0,
53715        ry: this.get('ry') || 0,
53716        x: this.get('x'),
53717        y: this.get('y')
53718      });
53719      if (!this.includeDefaultValues) {
53720        this._removeDefaultValues(object);
53721      }
53722      return object;
53723    },
53724
53725    /* _TO_SVG_START_ */
53726    /**
53727     * Returns svg representation of an instance
53728     * @param {Function} [reviver] Method for further parsing of svg representation.
53729     * @return {String} svg representation of an instance
53730     */
53731    toSVG: function(reviver) {
53732      var markup = this._createBaseSVGMarkup();
53733
53734      markup.push(
53735        '<rect ',
53736          'x="', (-1 * this.width / 2), '" y="', (-1 * this.height / 2),
53737          '" rx="', this.get('rx'), '" ry="', this.get('ry'),
53738          '" width="', this.width, '" height="', this.height,
53739          '" style="', this.getSvgStyles(),
53740          '" transform="', this.getSvgTransform(),
53741        '"/>'
53742      );
53743
53744      return reviver ? reviver(markup.join('')) : markup.join('');
53745    },
53746    /* _TO_SVG_END_ */
53747
53748    /**
53749     * Returns complexity of an instance
53750     * @return {Number} complexity
53751     */
53752    complexity: function() {
53753      return 1;
53754    }
53755  });
53756
53757  /* _FROM_SVG_START_ */
53758  /**
53759   * List of attribute names to account for when parsing SVG element (used by `fabric.Rect.fromElement`)
53760   * @static
53761   * @memberOf fabric.Rect
53762   * @see: http://www.w3.org/TR/SVG/shapes.html#RectElement
53763   */
53764  fabric.Rect.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('x y rx ry width height'.split(' '));
53765
53766  /**
53767   * @private
53768   */
53769  function _setDefaultLeftTopValues(attributes) {
53770    attributes.left = attributes.left || 0;
53771    attributes.top  = attributes.top  || 0;
53772    return attributes;
53773  }
53774
53775  /**
53776   * Returns {@link fabric.Rect} instance from an SVG element
53777   * @static
53778   * @memberOf fabric.Rect
53779   * @param {SVGElement} element Element to parse
53780   * @param {Object} [options] Options object
53781   * @return {fabric.Rect} Instance of fabric.Rect
53782   */
53783  fabric.Rect.fromElement = function(element, options) {
53784    if (!element) {
53785      return null;
53786    }
53787
53788    var parsedAttributes = fabric.parseAttributes(element, fabric.Rect.ATTRIBUTE_NAMES);
53789    parsedAttributes = _setDefaultLeftTopValues(parsedAttributes);
53790
53791    var rect = new fabric.Rect(extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes));
53792    rect._normalizeLeftTopProperties(parsedAttributes);
53793
53794    return rect;
53795  };
53796  /* _FROM_SVG_END_ */
53797
53798  /**
53799   * Returns {@link fabric.Rect} instance from an object representation
53800   * @static
53801   * @memberOf fabric.Rect
53802   * @param object {Object} object to create an instance from
53803   * @return {Object} instance of fabric.Rect
53804   */
53805  fabric.Rect.fromObject = function(object) {
53806    return new fabric.Rect(object);
53807  };
53808
53809})(typeof exports !== 'undefined' ? exports : this);
53810
53811
53812(function(global) {
53813
53814  "use strict";
53815
53816  var fabric = global.fabric || (global.fabric = { }),
53817      toFixed = fabric.util.toFixed,
53818      min = fabric.util.array.min;
53819
53820  if (fabric.Polyline) {
53821    fabric.warn('fabric.Polyline is already defined');
53822    return;
53823  }
53824
53825  /**
53826   * Polyline class
53827   * @class fabric.Polyline
53828   * @extends fabric.Object
53829   */
53830  fabric.Polyline = fabric.util.createClass(fabric.Object, /** @lends fabric.Polyline.prototype */ {
53831
53832    /**
53833     * Type of an object
53834     * @type String
53835     * @default
53836     */
53837    type: 'polyline',
53838
53839    /**
53840     * Constructor
53841     * @param {Array} points Array of points
53842     * @param {Object} [options] Options object
53843     * @param {Boolean} [skipOffset] Whether points offsetting should be skipped
53844     * @return {fabric.Polyline} thisArg
53845     */
53846    initialize: function(points, options, skipOffset) {
53847      options = options || { };
53848      this.set('points', points);
53849      this.callSuper('initialize', options);
53850      this._calcDimensions(skipOffset);
53851    },
53852
53853    /**
53854     * @private
53855     * @param {Boolean} [skipOffset] Whether points offsetting should be skipped
53856     */
53857    _calcDimensions: function(skipOffset) {
53858      return fabric.Polygon.prototype._calcDimensions.call(this, skipOffset);
53859    },
53860
53861    /**
53862     * Returns object representation of an instance
53863     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output
53864     * @return {Object} Object representation of an instance
53865     */
53866    toObject: function(propertiesToInclude) {
53867      return fabric.Polygon.prototype.toObject.call(this, propertiesToInclude);
53868    },
53869
53870    /* _TO_SVG_START_ */
53871    /**
53872     * Returns SVG representation of an instance
53873     * @param {Function} [reviver] Method for further parsing of svg representation.
53874     * @return {String} svg representation of an instance
53875     */
53876    toSVG: function(reviver) {
53877      var points = [],
53878          markup = this._createBaseSVGMarkup();
53879
53880      for (var i = 0, len = this.points.length; i < len; i++) {
53881        points.push(toFixed(this.points[i].x, 2), ',', toFixed(this.points[i].y, 2), ' ');
53882      }
53883
53884      markup.push(
53885        '<polyline ',
53886          'points="', points.join(''),
53887          '" style="', this.getSvgStyles(),
53888          '" transform="', this.getSvgTransform(),
53889        '"/>'
53890      );
53891
53892      return reviver ? reviver(markup.join('')) : markup.join('');
53893    },
53894    /* _TO_SVG_END_ */
53895
53896    /**
53897     * @private
53898     * @param {CanvasRenderingContext2D} ctx Context to render on
53899     */
53900    _render: function(ctx) {
53901      var point;
53902      ctx.beginPath();
53903      ctx.moveTo(this.points[0].x, this.points[0].y);
53904      for (var i = 0, len = this.points.length; i < len; i++) {
53905        point = this.points[i];
53906        ctx.lineTo(point.x, point.y);
53907      }
53908
53909      this._renderFill(ctx);
53910      this._renderStroke(ctx);
53911    },
53912
53913    /**
53914     * @private
53915     * @param {CanvasRenderingContext2D} ctx Context to render on
53916     */
53917    _renderDashedStroke: function(ctx) {
53918      var p1, p2;
53919
53920      ctx.beginPath();
53921      for (var i = 0, len = this.points.length; i < len; i++) {
53922        p1 = this.points[i];
53923        p2 = this.points[i+1] || p1;
53924        fabric.util.drawDashedLine(ctx, p1.x, p1.y, p2.x, p2.y, this.strokeDashArray);
53925      }
53926    },
53927
53928    /**
53929     * Returns complexity of an instance
53930     * @return {Number} complexity of this instance
53931     */
53932    complexity: function() {
53933      return this.get('points').length;
53934    }
53935  });
53936
53937  /* _FROM_SVG_START_ */
53938  /**
53939   * List of attribute names to account for when parsing SVG element (used by {@link fabric.Polyline.fromElement})
53940   * @static
53941   * @memberOf fabric.Polyline
53942   * @see: http://www.w3.org/TR/SVG/shapes.html#PolylineElement
53943   */
53944  fabric.Polyline.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat();
53945
53946  /**
53947   * Returns fabric.Polyline instance from an SVG element
53948   * @static
53949   * @memberOf fabric.Polyline
53950   * @param {SVGElement} element Element to parse
53951   * @param {Object} [options] Options object
53952   * @return {fabric.Polyline} Instance of fabric.Polyline
53953   */
53954  fabric.Polyline.fromElement = function(element, options) {
53955    if (!element) {
53956      return null;
53957    }
53958    options || (options = { });
53959
53960    var points = fabric.parsePointsAttribute(element.getAttribute('points')),
53961        parsedAttributes = fabric.parseAttributes(element, fabric.Polyline.ATTRIBUTE_NAMES),
53962        minX = min(points, 'x'),
53963        minY = min(points, 'y');
53964
53965    minX = minX < 0 ? minX : 0;
53966    minY = minX < 0 ? minY : 0;
53967
53968    for (var i = 0, len = points.length; i < len; i++) {
53969      // normalize coordinates, according to containing box (dimensions of which are passed via `options`)
53970      points[i].x -= (options.width / 2 + minX) || 0;
53971      points[i].y -= (options.height / 2 + minY) || 0;
53972    }
53973
53974    return new fabric.Polyline(points, fabric.util.object.extend(parsedAttributes, options), true);
53975  };
53976  /* _FROM_SVG_END_ */
53977
53978  /**
53979   * Returns fabric.Polyline instance from an object representation
53980   * @static
53981   * @memberOf fabric.Polyline
53982   * @param object {Object} object Object to create an instance from
53983   * @return {fabric.Polyline} Instance of fabric.Polyline
53984   */
53985  fabric.Polyline.fromObject = function(object) {
53986    var points = object.points;
53987    return new fabric.Polyline(points, object, true);
53988  };
53989
53990})(typeof exports !== 'undefined' ? exports : this);
53991
53992
53993(function(global) {
53994
53995  "use strict";
53996
53997  var fabric = global.fabric || (global.fabric = { }),
53998      extend = fabric.util.object.extend,
53999      min = fabric.util.array.min,
54000      max = fabric.util.array.max,
54001      toFixed = fabric.util.toFixed;
54002
54003  if (fabric.Polygon) {
54004    fabric.warn('fabric.Polygon is already defined');
54005    return;
54006  }
54007
54008  /**
54009   * Polygon class
54010   * @class fabric.Polygon
54011   * @extends fabric.Object
54012   */
54013  fabric.Polygon = fabric.util.createClass(fabric.Object, /** @lends fabric.Polygon.prototype */ {
54014
54015    /**
54016     * Type of an object
54017     * @type String
54018     * @default
54019     */
54020    type: 'polygon',
54021
54022    /**
54023     * Constructor
54024     * @param {Array} points Array of points
54025     * @param {Object} [options] Options object
54026     * @param {Boolean} [skipOffset] Whether points offsetting should be skipped
54027     * @return {fabric.Polygon} thisArg
54028     */
54029    initialize: function(points, options, skipOffset) {
54030      options = options || { };
54031      this.points = points;
54032      this.callSuper('initialize', options);
54033      this._calcDimensions(skipOffset);
54034    },
54035
54036    /**
54037     * @private
54038     * @param {Boolean} [skipOffset] Whether points offsetting should be skipped
54039     */
54040    _calcDimensions: function(skipOffset) {
54041
54042      var points = this.points,
54043          minX = min(points, 'x'),
54044          minY = min(points, 'y'),
54045          maxX = max(points, 'x'),
54046          maxY = max(points, 'y');
54047
54048      this.width = (maxX - minX) || 1;
54049      this.height = (maxY - minY) || 1;
54050
54051      this.minX = minX;
54052      this.minY = minY;
54053
54054      if (skipOffset) return;
54055
54056      var halfWidth = this.width / 2 + this.minX,
54057          halfHeight = this.height / 2 + this.minY;
54058
54059      // change points to offset polygon into a bounding box
54060      this.points.forEach(function(p) {
54061        p.x -= halfWidth;
54062        p.y -= halfHeight;
54063      }, this);
54064    },
54065
54066    /**
54067     * Returns object representation of an instance
54068     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output
54069     * @return {Object} Object representation of an instance
54070     */
54071    toObject: function(propertiesToInclude) {
54072      return extend(this.callSuper('toObject', propertiesToInclude), {
54073        points: this.points.concat()
54074      });
54075    },
54076
54077    /* _TO_SVG_START_ */
54078    /**
54079     * Returns svg representation of an instance
54080     * @param {Function} [reviver] Method for further parsing of svg representation.
54081     * @return {String} svg representation of an instance
54082     */
54083    toSVG: function(reviver) {
54084      var points = [],
54085          markup = this._createBaseSVGMarkup();
54086
54087      for (var i = 0, len = this.points.length; i < len; i++) {
54088        points.push(toFixed(this.points[i].x, 2), ',', toFixed(this.points[i].y, 2), ' ');
54089      }
54090
54091      markup.push(
54092        '<polygon ',
54093          'points="', points.join(''),
54094          '" style="', this.getSvgStyles(),
54095          '" transform="', this.getSvgTransform(),
54096        '"/>'
54097      );
54098
54099      return reviver ? reviver(markup.join('')) : markup.join('');
54100    },
54101    /* _TO_SVG_END_ */
54102
54103    /**
54104     * @private
54105     * @param {CanvasRenderingContext2D} ctx Context to render on
54106     */
54107    _render: function(ctx) {
54108      var point;
54109      ctx.beginPath();
54110      ctx.moveTo(this.points[0].x, this.points[0].y);
54111      for (var i = 0, len = this.points.length; i < len; i++) {
54112        point = this.points[i];
54113        ctx.lineTo(point.x, point.y);
54114      }
54115      this._renderFill(ctx);
54116      if (this.stroke || this.strokeDashArray) {
54117        ctx.closePath();
54118        this._renderStroke(ctx);
54119      }
54120    },
54121
54122    /**
54123     * @private
54124     * @param {CanvasRenderingContext2D} ctx Context to render on
54125     */
54126    _renderDashedStroke: function(ctx) {
54127      var p1, p2;
54128
54129      ctx.beginPath();
54130      for (var i = 0, len = this.points.length; i < len; i++) {
54131        p1 = this.points[i];
54132        p2 = this.points[i+1] || this.points[0];
54133        fabric.util.drawDashedLine(ctx, p1.x, p1.y, p2.x, p2.y, this.strokeDashArray);
54134      }
54135      ctx.closePath();
54136    },
54137
54138    /**
54139     * Returns complexity of an instance
54140     * @return {Number} complexity of this instance
54141     */
54142    complexity: function() {
54143      return this.points.length;
54144    }
54145  });
54146
54147  /* _FROM_SVG_START_ */
54148  /**
54149   * List of attribute names to account for when parsing SVG element (used by `fabric.Polygon.fromElement`)
54150   * @static
54151   * @memberOf fabric.Polygon
54152   * @see: http://www.w3.org/TR/SVG/shapes.html#PolygonElement
54153   */
54154  fabric.Polygon.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat();
54155
54156  /**
54157   * Returns {@link fabric.Polygon} instance from an SVG element
54158   * @static
54159   * @memberOf fabric.Polygon
54160   * @param {SVGElement} element Element to parse
54161   * @param {Object} [options] Options object
54162   * @return {fabric.Polygon} Instance of fabric.Polygon
54163   */
54164  fabric.Polygon.fromElement = function(element, options) {
54165    if (!element) {
54166      return null;
54167    }
54168    options || (options = { });
54169
54170    var points = fabric.parsePointsAttribute(element.getAttribute('points')),
54171        parsedAttributes = fabric.parseAttributes(element, fabric.Polygon.ATTRIBUTE_NAMES),
54172        minX = min(points, 'x'),
54173        minY = min(points, 'y');
54174
54175    minX = minX < 0 ? minX : 0;
54176    minY = minX < 0 ? minY : 0;
54177
54178    for (var i = 0, len = points.length; i < len; i++) {
54179      // normalize coordinates, according to containing box (dimensions of which are passed via `options`)
54180      points[i].x -= (options.width / 2 + minX) || 0;
54181      points[i].y -= (options.height / 2 + minY) || 0;
54182    }
54183
54184    return new fabric.Polygon(points, extend(parsedAttributes, options), true);
54185  };
54186  /* _FROM_SVG_END_ */
54187
54188  /**
54189   * Returns fabric.Polygon instance from an object representation
54190   * @static
54191   * @memberOf fabric.Polygon
54192   * @param object {Object} object Object to create an instance from
54193   * @return {fabric.Polygon} Instance of fabric.Polygon
54194   */
54195  fabric.Polygon.fromObject = function(object) {
54196    return new fabric.Polygon(object.points, object, true);
54197  };
54198
54199})(typeof exports !== 'undefined' ? exports : this);
54200
54201
54202(function(global) {
54203
54204  var commandLengths = {
54205    m: 2,
54206    l: 2,
54207    h: 1,
54208    v: 1,
54209    c: 6,
54210    s: 4,
54211    q: 4,
54212    t: 2,
54213    a: 7
54214  };
54215
54216  "use strict";
54217
54218  var fabric = global.fabric || (global.fabric = { }),
54219      min = fabric.util.array.min,
54220      max = fabric.util.array.max,
54221      extend = fabric.util.object.extend,
54222      _toString = Object.prototype.toString,
54223      drawArc = fabric.util.drawArc;
54224
54225  if (fabric.Path) {
54226    fabric.warn('fabric.Path is already defined');
54227    return;
54228  }
54229
54230  /**
54231   * @private
54232   */
54233  function getX(item) {
54234    if (item[0] === 'H') {
54235      return item[1];
54236    }
54237    return item[item.length - 2];
54238  }
54239
54240  /**
54241   * @private
54242   */
54243  function getY(item) {
54244    if (item[0] === 'V') {
54245      return item[1];
54246    }
54247    return item[item.length - 1];
54248  }
54249
54250  /**
54251   * Path class
54252   * @class fabric.Path
54253   * @extends fabric.Object
54254   * @tutorial {@link http://fabricjs.com/fabric-intro-part-1/#path_and_pathgroup}
54255   */
54256  fabric.Path = fabric.util.createClass(fabric.Object, /** @lends fabric.Path.prototype */ {
54257
54258    /**
54259     * Type of an object
54260     * @type String
54261     * @default
54262     */
54263    type: 'path',
54264
54265    /**
54266     * Constructor
54267     * @param {Array|String} path Path data (sequence of coordinates and corresponding "command" tokens)
54268     * @param {Object} [options] Options object
54269     * @return {fabric.Path} thisArg
54270     */
54271    initialize: function(path, options) {
54272      options = options || { };
54273
54274      this.setOptions(options);
54275
54276      if (!path) {
54277        throw new Error('`path` argument is required');
54278      }
54279
54280      var fromArray = _toString.call(path) === '[object Array]';
54281
54282      this.path = fromArray
54283        ? path
54284        // one of commands (m,M,l,L,q,Q,c,C,etc.) followed by non-command characters (i.e. command values)
54285        : path.match && path.match(/[mzlhvcsqta][^mzlhvcsqta]*/gi);
54286
54287      if (!this.path) return;
54288
54289      if (!fromArray) {
54290        this.path = this._parsePath();
54291      }
54292      this._initializePath(options);
54293
54294      if (options.sourcePath) {
54295        this.setSourcePath(options.sourcePath);
54296      }
54297    },
54298
54299    /**
54300     * @private
54301     * @param {Object} [options] Options object
54302     */
54303    _initializePath: function (options) {
54304      var isWidthSet = 'width' in options && options.width != null,
54305          isHeightSet = 'height' in options && options.width != null,
54306          isLeftSet = 'left' in options,
54307          isTopSet = 'top' in options,
54308          origLeft = isLeftSet ? this.left : 0,
54309          origTop = isTopSet ? this.top : 0;
54310
54311      if (!isWidthSet || !isHeightSet) {
54312        extend(this, this._parseDimensions());
54313        if (isWidthSet) {
54314          this.width = options.width;
54315        }
54316        if (isHeightSet) {
54317          this.height = options.height;
54318        }
54319      }
54320      else { //Set center location relative to given height/width if not specified
54321        if (!isTopSet) {
54322          this.top = this.height / 2;
54323        }
54324        if (!isLeftSet) {
54325          this.left = this.width / 2;
54326        }
54327      }
54328      this.pathOffset = this.pathOffset || this._calculatePathOffset(origLeft, origTop); //Save top-left coords as offset
54329    },
54330
54331    /**
54332     * @private
54333     * @param {Boolean} positionSet When false, path offset is returned otherwise 0
54334     */
54335    _calculatePathOffset: function (origLeft, origTop) {
54336      return {
54337        x: this.left - origLeft - (this.width / 2),
54338        y: this.top - origTop - (this.height / 2)
54339      };
54340    },
54341
54342    /**
54343     * @private
54344     * @param {CanvasRenderingContext2D} ctx context to render path on
54345     */
54346    _render: function(ctx) {
54347      var current, // current instruction
54348          previous = null,
54349          x = 0, // current x
54350          y = 0, // current y
54351          controlX = 0, // current control point x
54352          controlY = 0, // current control point y
54353          tempX,
54354          tempY,
54355          tempControlX,
54356          tempControlY,
54357          l = -((this.width / 2) + this.pathOffset.x),
54358          t = -((this.height / 2) + this.pathOffset.y);
54359
54360      for (var i = 0, len = this.path.length; i < len; ++i) {
54361
54362        current = this.path[i];
54363
54364        switch (current[0]) { // first letter
54365
54366          case 'l': // lineto, relative
54367            x += current[1];
54368            y += current[2];
54369            ctx.lineTo(x + l, y + t);
54370            break;
54371
54372          case 'L': // lineto, absolute
54373            x = current[1];
54374            y = current[2];
54375            ctx.lineTo(x + l, y + t);
54376            break;
54377
54378          case 'h': // horizontal lineto, relative
54379            x += current[1];
54380            ctx.lineTo(x + l, y + t);
54381            break;
54382
54383          case 'H': // horizontal lineto, absolute
54384            x = current[1];
54385            ctx.lineTo(x + l, y + t);
54386            break;
54387
54388          case 'v': // vertical lineto, relative
54389            y += current[1];
54390            ctx.lineTo(x + l, y + t);
54391            break;
54392
54393          case 'V': // verical lineto, absolute
54394            y = current[1];
54395            ctx.lineTo(x + l, y + t);
54396            break;
54397
54398          case 'm': // moveTo, relative
54399            x += current[1];
54400            y += current[2];
54401            // draw a line if previous command was moveTo as well (otherwise, it will have no effect)
54402            ctx[(previous && (previous[0] === 'm' || previous[0] === 'M')) ? 'lineTo' : 'moveTo'](x + l, y + t);
54403            break;
54404
54405          case 'M': // moveTo, absolute
54406            x = current[1];
54407            y = current[2];
54408            // draw a line if previous command was moveTo as well (otherwise, it will have no effect)
54409            ctx[(previous && (previous[0] === 'm' || previous[0] === 'M')) ? 'lineTo' : 'moveTo'](x + l, y + t);
54410            break;
54411
54412          case 'c': // bezierCurveTo, relative
54413            tempX = x + current[5];
54414            tempY = y + current[6];
54415            controlX = x + current[3];
54416            controlY = y + current[4];
54417            ctx.bezierCurveTo(
54418              x + current[1] + l, // x1
54419              y + current[2] + t, // y1
54420              controlX + l, // x2
54421              controlY + t, // y2
54422              tempX + l,
54423              tempY + t
54424            );
54425            x = tempX;
54426            y = tempY;
54427            break;
54428
54429          case 'C': // bezierCurveTo, absolute
54430            x = current[5];
54431            y = current[6];
54432            controlX = current[3];
54433            controlY = current[4];
54434            ctx.bezierCurveTo(
54435              current[1] + l,
54436              current[2] + t,
54437              controlX + l,
54438              controlY + t,
54439              x + l,
54440              y + t
54441            );
54442            break;
54443
54444          case 's': // shorthand cubic bezierCurveTo, relative
54445
54446            // transform to absolute x,y
54447            tempX = x + current[3];
54448            tempY = y + current[4];
54449
54450            // calculate reflection of previous control points
54451            controlX = controlX ? (2 * x - controlX) : x;
54452            controlY = controlY ? (2 * y - controlY) : y;
54453
54454            ctx.bezierCurveTo(
54455              controlX + l,
54456              controlY + t,
54457              x + current[1] + l,
54458              y + current[2] + t,
54459              tempX + l,
54460              tempY + t
54461            );
54462            // set control point to 2nd one of this command
54463            // "... the first control point is assumed to be the reflection of the second control point on the previous command relative to the current point."
54464            controlX = x + current[1];
54465            controlY = y + current[2];
54466
54467            x = tempX;
54468            y = tempY;
54469            break;
54470
54471          case 'S': // shorthand cubic bezierCurveTo, absolute
54472            tempX = current[3];
54473            tempY = current[4];
54474            // calculate reflection of previous control points
54475            controlX = 2*x - controlX;
54476            controlY = 2*y - controlY;
54477            ctx.bezierCurveTo(
54478              controlX + l,
54479              controlY + t,
54480              current[1] + l,
54481              current[2] + t,
54482              tempX + l,
54483              tempY + t
54484            );
54485            x = tempX;
54486            y = tempY;
54487
54488            // set control point to 2nd one of this command
54489            // "... the first control point is assumed to be the reflection of the second control point on the previous command relative to the current point."
54490            controlX = current[1];
54491            controlY = current[2];
54492
54493            break;
54494
54495          case 'q': // quadraticCurveTo, relative
54496            // transform to absolute x,y
54497            tempX = x + current[3];
54498            tempY = y + current[4];
54499
54500            controlX = x + current[1];
54501            controlY = y + current[2];
54502
54503            ctx.quadraticCurveTo(
54504              controlX + l,
54505              controlY + t,
54506              tempX + l,
54507              tempY + t
54508            );
54509            x = tempX;
54510            y = tempY;
54511            break;
54512
54513          case 'Q': // quadraticCurveTo, absolute
54514            tempX = current[3];
54515            tempY = current[4];
54516
54517            ctx.quadraticCurveTo(
54518              current[1] + l,
54519              current[2] + t,
54520              tempX + l,
54521              tempY + t
54522            );
54523            x = tempX;
54524            y = tempY;
54525            controlX = current[1];
54526            controlY = current[2];
54527            break;
54528
54529          case 't': // shorthand quadraticCurveTo, relative
54530
54531            // transform to absolute x,y
54532            tempX = x + current[1];
54533            tempY = y + current[2];
54534
54535
54536            if (previous[0].match(/[QqTt]/) === null) {
54537              // If there is no previous command or if the previous command was not a Q, q, T or t,
54538              // assume the control point is coincident with the current point
54539              controlX = x;
54540              controlY = y;
54541            }
54542            else if (previous[0] === 't') {
54543              // calculate reflection of previous control points for t
54544              controlX = 2 * x - tempControlX;
54545              controlY = 2 * y - tempControlY;
54546            }
54547            else if (previous[0] === 'q') {
54548              // calculate reflection of previous control points for q
54549              controlX = 2 * x - controlX;
54550              controlY = 2 * y - controlY;
54551            }
54552
54553            tempControlX = controlX;
54554            tempControlY = controlY;
54555
54556            ctx.quadraticCurveTo(
54557              controlX + l,
54558              controlY + t,
54559              tempX + l,
54560              tempY + t
54561            );
54562            x = tempX;
54563            y = tempY;
54564            controlX = x + current[1];
54565            controlY = y + current[2];
54566            break;
54567
54568          case 'T':
54569            tempX = current[1];
54570            tempY = current[2];
54571
54572            // calculate reflection of previous control points
54573            controlX = 2 * x - controlX;
54574            controlY = 2 * y - controlY;
54575            ctx.quadraticCurveTo(
54576              controlX + l,
54577              controlY + t,
54578              tempX + l,
54579              tempY + t
54580            );
54581            x = tempX;
54582            y = tempY;
54583            break;
54584
54585          case 'a':
54586            // TODO: optimize this
54587            drawArc(ctx, x + l, y + t, [
54588              current[1],
54589              current[2],
54590              current[3],
54591              current[4],
54592              current[5],
54593              current[6] + x + l,
54594              current[7] + y + t
54595            ]);
54596            x += current[6];
54597            y += current[7];
54598            break;
54599
54600          case 'A':
54601            // TODO: optimize this
54602            drawArc(ctx, x + l, y + t, [
54603              current[1],
54604              current[2],
54605              current[3],
54606              current[4],
54607              current[5],
54608              current[6] + l,
54609              current[7] + t
54610            ]);
54611            x = current[6];
54612            y = current[7];
54613            break;
54614
54615          case 'z':
54616          case 'Z':
54617            ctx.closePath();
54618            break;
54619        }
54620        previous = current;
54621      }
54622    },
54623
54624    /**
54625     * Renders path on a specified context
54626     * @param {CanvasRenderingContext2D} ctx context to render path on
54627     * @param {Boolean} [noTransform] When true, context is not transformed
54628     */
54629    render: function(ctx, noTransform) {
54630      // do not render if object is not visible
54631      if (!this.visible) return;
54632
54633      ctx.save();
54634      var m = this.transformMatrix;
54635      if (m) {
54636        ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]);
54637      }
54638      if (!noTransform) {
54639        this.transform(ctx);
54640      }
54641      // ctx.globalCompositeOperation = this.fillRule;
54642
54643      if (this.fill) {
54644        ctx.fillStyle = this.fill.toLive
54645          ? this.fill.toLive(ctx)
54646          : this.fill;
54647      }
54648
54649      if (this.stroke) {
54650        ctx.lineWidth = this.strokeWidth;
54651        ctx.lineCap = this.strokeLineCap;
54652        ctx.lineJoin = this.strokeLineJoin;
54653        ctx.miterLimit = this.strokeMiterLimit;
54654        ctx.strokeStyle = this.stroke.toLive
54655          ? this.stroke.toLive(ctx)
54656          : this.stroke;
54657      }
54658
54659      this._setShadow(ctx);
54660      this.clipTo && fabric.util.clipContext(this, ctx);
54661      ctx.beginPath();
54662
54663      this._render(ctx);
54664      this._renderFill(ctx);
54665      this._renderStroke(ctx);
54666      this.clipTo && ctx.restore();
54667      this._removeShadow(ctx);
54668
54669      if (!noTransform && this.active) {
54670        this.drawBorders(ctx);
54671        this.drawControls(ctx);
54672      }
54673      ctx.restore();
54674    },
54675
54676    /**
54677     * Returns string representation of an instance
54678     * @return {String} string representation of an instance
54679     */
54680    toString: function() {
54681      return '#<fabric.Path (' + this.complexity() +
54682        '): { "top": ' + this.top + ', "left": ' + this.left + ' }>';
54683    },
54684
54685    /**
54686     * Returns object representation of an instance
54687     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output
54688     * @return {Object} object representation of an instance
54689     */
54690    toObject: function(propertiesToInclude) {
54691      var o = extend(this.callSuper('toObject', propertiesToInclude), {
54692        path: this.path,
54693        pathOffset: this.pathOffset
54694      });
54695      if (this.sourcePath) {
54696        o.sourcePath = this.sourcePath;
54697      }
54698      if (this.transformMatrix) {
54699        o.transformMatrix = this.transformMatrix;
54700      }
54701      return o;
54702    },
54703
54704    /**
54705     * Returns dataless object representation of an instance
54706     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output
54707     * @return {Object} object representation of an instance
54708     */
54709    toDatalessObject: function(propertiesToInclude) {
54710      var o = this.toObject(propertiesToInclude);
54711      if (this.sourcePath) {
54712        o.path = this.sourcePath;
54713      }
54714      delete o.sourcePath;
54715      return o;
54716    },
54717
54718    /* _TO_SVG_START_ */
54719    /**
54720     * Returns svg representation of an instance
54721     * @param {Function} [reviver] Method for further parsing of svg representation.
54722     * @return {String} svg representation of an instance
54723     */
54724    toSVG: function(reviver) {
54725      var chunks = [],
54726          markup = this._createBaseSVGMarkup();
54727
54728      for (var i = 0, len = this.path.length; i < len; i++) {
54729        chunks.push(this.path[i].join(' '));
54730      }
54731      var path = chunks.join(' ');
54732
54733      markup.push(
54734        '<g transform="', (this.group ? '' : this.getSvgTransform()), '">',
54735          '<path ',
54736            'd="', path,
54737            '" style="', this.getSvgStyles(),
54738            '" transform="translate(', (-this.width / 2), ' ', (-this.height/2), ')',
54739            '" stroke-linecap="round" ',
54740          '/>',
54741        '</g>'
54742      );
54743
54744      return reviver ? reviver(markup.join('')) : markup.join('');
54745    },
54746    /* _TO_SVG_END_ */
54747
54748    /**
54749     * Returns number representation of an instance complexity
54750     * @return {Number} complexity of this instance
54751     */
54752    complexity: function() {
54753      return this.path.length;
54754    },
54755
54756    /**
54757     * @private
54758     */
54759    _parsePath: function() {
54760      var result = [ ],
54761          coords = [ ],
54762          currentPath,
54763          parsed,
54764          re = /(-?\.\d+)|(-?\d+(\.\d+)?)/g,
54765          match,
54766          coordsStr;
54767
54768      for (var i = 0, coordsParsed, len = this.path.length; i < len; i++) {
54769        currentPath = this.path[i];
54770
54771        coordsStr = currentPath.slice(1).trim();
54772        coords.length = 0;
54773
54774        while ((match = re.exec(coordsStr))) {
54775          coords.push(match[0]);
54776        }
54777
54778        coordsParsed = [ currentPath.charAt(0) ];
54779
54780        for (var j = 0, jlen = coords.length; j < jlen; j++) {
54781          parsed = parseFloat(coords[j]);
54782          if (!isNaN(parsed)) {
54783            coordsParsed.push(parsed);
54784          }
54785        }
54786
54787        var command = coordsParsed[0].toLowerCase(),
54788            commandLength = commandLengths[command];
54789
54790        if (coordsParsed.length - 1 > commandLength) {
54791          for (var k = 1, klen = coordsParsed.length; k < klen; k += commandLength) {
54792            result.push([ coordsParsed[0] ].concat(coordsParsed.slice(k, k + commandLength)));
54793          }
54794        }
54795        else {
54796          result.push(coordsParsed);
54797        }
54798      }
54799
54800      return result;
54801    },
54802
54803    /**
54804     * @private
54805     */
54806    _parseDimensions: function() {
54807      var aX = [],
54808          aY = [],
54809          previousX,
54810          previousY,
54811          isLowerCase = false,
54812          x,
54813          y;
54814
54815      this.path.forEach(function(item, i) {
54816        if (item[0] !== 'H') {
54817          previousX = (i === 0) ? getX(item) : getX(this.path[i-1]);
54818        }
54819        if (item[0] !== 'V') {
54820          previousY = (i === 0) ? getY(item) : getY(this.path[i-1]);
54821        }
54822
54823        // lowercased letter denotes relative position;
54824        // transform to absolute
54825        if (item[0] === item[0].toLowerCase()) {
54826          isLowerCase = true;
54827        }
54828
54829        // last 2 items in an array of coordinates are the actualy x/y (except H/V);
54830        // collect them
54831
54832        // TODO (kangax): support relative h/v commands
54833
54834        x = isLowerCase
54835          ? previousX + getX(item)
54836          : item[0] === 'V'
54837            ? previousX
54838            : getX(item);
54839
54840        y = isLowerCase
54841          ? previousY + getY(item)
54842          : item[0] === 'H'
54843            ? previousY
54844            : getY(item);
54845
54846        var val = parseInt(x, 10);
54847        if (!isNaN(val)) aX.push(val);
54848
54849        val = parseInt(y, 10);
54850        if (!isNaN(val)) aY.push(val);
54851
54852      }, this);
54853
54854      var minX = min(aX),
54855          minY = min(aY),
54856          maxX = max(aX),
54857          maxY = max(aY),
54858          deltaX = maxX - minX,
54859          deltaY = maxY - minY;
54860
54861      var o = {
54862        left: this.left + (minX + deltaX / 2),
54863        top: this.top + (minY + deltaY / 2),
54864        width: deltaX,
54865        height: deltaY
54866      };
54867
54868      return o;
54869    }
54870  });
54871
54872  /**
54873   * Creates an instance of fabric.Path from an object
54874   * @static
54875   * @memberOf fabric.Path
54876   * @param {Object} object
54877   * @param {Function} callback Callback to invoke when an fabric.Path instance is created
54878   */
54879  fabric.Path.fromObject = function(object, callback) {
54880    if (typeof object.path === 'string') {
54881      fabric.loadSVGFromURL(object.path, function (elements) {
54882        var path = elements[0];
54883
54884        var pathUrl = object.path;
54885        delete object.path;
54886
54887        fabric.util.object.extend(path, object);
54888        path.setSourcePath(pathUrl);
54889
54890        callback(path);
54891      });
54892    }
54893    else {
54894      callback(new fabric.Path(object.path, object));
54895    }
54896  };
54897
54898  /* _FROM_SVG_START_ */
54899  /**
54900   * List of attribute names to account for when parsing SVG element (used by `fabric.Path.fromElement`)
54901   * @static
54902   * @memberOf fabric.Path
54903   * @see http://www.w3.org/TR/SVG/paths.html#PathElement
54904   */
54905  fabric.Path.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat(['d']);
54906
54907  /**
54908   * Creates an instance of fabric.Path from an SVG <path> element
54909   * @static
54910   * @memberOf fabric.Path
54911   * @param {SVGElement} element to parse
54912   * @param {Function} callback Callback to invoke when an fabric.Path instance is created
54913   * @param {Object} [options] Options object
54914   */
54915  fabric.Path.fromElement = function(element, callback, options) {
54916    var parsedAttributes = fabric.parseAttributes(element, fabric.Path.ATTRIBUTE_NAMES);
54917    callback && callback(new fabric.Path(parsedAttributes.d, extend(parsedAttributes, options)));
54918  };
54919  /* _FROM_SVG_END_ */
54920
54921  /**
54922   * Indicates that instances of this type are async
54923   * @static
54924   * @memberOf fabric.Path
54925   * @type Boolean
54926   * @default
54927   */
54928  fabric.Path.async = true;
54929
54930})(typeof exports !== 'undefined' ? exports : this);
54931
54932
54933(function(global) {
54934
54935  "use strict";
54936
54937  var fabric = global.fabric || (global.fabric = { }),
54938      extend = fabric.util.object.extend,
54939      invoke = fabric.util.array.invoke,
54940      parentToObject = fabric.Object.prototype.toObject;
54941
54942  if (fabric.PathGroup) {
54943    fabric.warn('fabric.PathGroup is already defined');
54944    return;
54945  }
54946
54947  /**
54948   * Path group class
54949   * @class fabric.PathGroup
54950   * @extends fabric.Path
54951   * @tutorial {@link http://fabricjs.com/fabric-intro-part-1/#path_and_pathgroup}
54952   */
54953  fabric.PathGroup = fabric.util.createClass(fabric.Path, /** @lends fabric.PathGroup.prototype */ {
54954
54955    /**
54956     * Type of an object
54957     * @type String
54958     * @default
54959     */
54960    type: 'path-group',
54961
54962    /**
54963     * Fill value
54964     * @type String
54965     * @default
54966     */
54967    fill: '',
54968
54969    /**
54970     * Constructor
54971     * @param {Array} paths
54972     * @param {Object} [options] Options object
54973     * @return {fabric.PathGroup} thisArg
54974     */
54975    initialize: function(paths, options) {
54976
54977      options = options || { };
54978      this.paths = paths || [ ];
54979
54980      for (var i = this.paths.length; i--; ) {
54981        this.paths[i].group = this;
54982      }
54983
54984      this.setOptions(options);
54985      this.setCoords();
54986
54987      if (options.sourcePath) {
54988        this.setSourcePath(options.sourcePath);
54989      }
54990    },
54991
54992    /**
54993     * Renders this group on a specified context
54994     * @param {CanvasRenderingContext2D} ctx Context to render this instance on
54995     */
54996    render: function(ctx) {
54997      // do not render if object is not visible
54998      if (!this.visible) return;
54999
55000      ctx.save();
55001
55002      var m = this.transformMatrix;
55003      if (m) {
55004        ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]);
55005      }
55006
55007      this.transform(ctx);
55008
55009      this._setShadow(ctx);
55010      this.clipTo && fabric.util.clipContext(this, ctx);
55011      for (var i = 0, l = this.paths.length; i < l; ++i) {
55012        this.paths[i].render(ctx, true);
55013      }
55014      this.clipTo && ctx.restore();
55015      this._removeShadow(ctx);
55016
55017      if (this.active) {
55018        this.drawBorders(ctx);
55019        this.drawControls(ctx);
55020      }
55021      ctx.restore();
55022    },
55023
55024    /**
55025     * Sets certain property to a certain value
55026     * @param {String} prop
55027     * @param {Any} value
55028     * @return {fabric.PathGroup} thisArg
55029     */
55030    _set: function(prop, value) {
55031
55032      if (prop === 'fill' && value && this.isSameColor()) {
55033        var i = this.paths.length;
55034        while (i--) {
55035          this.paths[i]._set(prop, value);
55036        }
55037      }
55038
55039      return this.callSuper('_set', prop, value);
55040    },
55041
55042    /**
55043     * Returns object representation of this path group
55044     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output
55045     * @return {Object} object representation of an instance
55046     */
55047    toObject: function(propertiesToInclude) {
55048      var o = extend(parentToObject.call(this, propertiesToInclude), {
55049        paths: invoke(this.getObjects(), 'toObject', propertiesToInclude)
55050      });
55051      if (this.sourcePath) {
55052        o.sourcePath = this.sourcePath;
55053      }
55054      return o;
55055    },
55056
55057    /**
55058     * Returns dataless object representation of this path group
55059     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output
55060     * @return {Object} dataless object representation of an instance
55061     */
55062    toDatalessObject: function(propertiesToInclude) {
55063      var o = this.toObject(propertiesToInclude);
55064      if (this.sourcePath) {
55065        o.paths = this.sourcePath;
55066      }
55067      return o;
55068    },
55069
55070    /* _TO_SVG_START_ */
55071    /**
55072     * Returns svg representation of an instance
55073     * @param {Function} [reviver] Method for further parsing of svg representation.
55074     * @return {String} svg representation of an instance
55075     */
55076    toSVG: function(reviver) {
55077      var objects = this.getObjects();
55078      var markup = [
55079        '<g ',
55080          'style="', this.getSvgStyles(), '" ',
55081          'transform="', this.getSvgTransform(), '" ',
55082        '>'
55083      ];
55084
55085      for (var i = 0, len = objects.length; i < len; i++) {
55086        markup.push(objects[i].toSVG(reviver));
55087      }
55088      markup.push('</g>');
55089
55090      return reviver ? reviver(markup.join('')) : markup.join('');
55091    },
55092    /* _TO_SVG_END_ */
55093
55094    /**
55095     * Returns a string representation of this path group
55096     * @return {String} string representation of an object
55097     */
55098    toString: function() {
55099      return '#<fabric.PathGroup (' + this.complexity() +
55100        '): { top: ' + this.top + ', left: ' + this.left + ' }>';
55101    },
55102
55103    /**
55104     * Returns true if all paths in this group are of same color
55105     * @return {Boolean} true if all paths are of the same color (`fill`)
55106     */
55107    isSameColor: function() {
55108      var firstPathFill = this.getObjects()[0].get('fill');
55109      return this.getObjects().every(function(path) {
55110        return path.get('fill') === firstPathFill;
55111      });
55112    },
55113
55114    /**
55115     * Returns number representation of object's complexity
55116     * @return {Number} complexity
55117     */
55118    complexity: function() {
55119      return this.paths.reduce(function(total, path) {
55120        return total + ((path && path.complexity) ? path.complexity() : 0);
55121      }, 0);
55122    },
55123
55124    /**
55125     * Returns all paths in this path group
55126     * @return {Array} array of path objects included in this path group
55127     */
55128    getObjects: function() {
55129      return this.paths;
55130    }
55131  });
55132
55133  /**
55134   * Creates fabric.PathGroup instance from an object representation
55135   * @static
55136   * @memberOf fabric.PathGroup
55137   * @param {Object} object Object to create an instance from
55138   * @param {Function} callback Callback to invoke when an fabric.PathGroup instance is created
55139   */
55140  fabric.PathGroup.fromObject = function(object, callback) {
55141    if (typeof object.paths === 'string') {
55142      fabric.loadSVGFromURL(object.paths, function (elements) {
55143
55144        var pathUrl = object.paths;
55145        delete object.paths;
55146
55147        var pathGroup = fabric.util.groupSVGElements(elements, object, pathUrl);
55148
55149        callback(pathGroup);
55150      });
55151    }
55152    else {
55153      fabric.util.enlivenObjects(object.paths, function(enlivenedObjects) {
55154        delete object.paths;
55155        callback(new fabric.PathGroup(enlivenedObjects, object));
55156      });
55157    }
55158  };
55159
55160  /**
55161   * Indicates that instances of this type are async
55162   * @static
55163   * @memberOf fabric.PathGroup
55164   * @type Boolean
55165   * @default
55166   */
55167  fabric.PathGroup.async = true;
55168
55169})(typeof exports !== 'undefined' ? exports : this);
55170
55171
55172(function(global){
55173
55174  "use strict";
55175
55176  var fabric = global.fabric || (global.fabric = { }),
55177      extend = fabric.util.object.extend,
55178      min = fabric.util.array.min,
55179      max = fabric.util.array.max,
55180      invoke = fabric.util.array.invoke;
55181
55182  if (fabric.Group) {
55183    return;
55184  }
55185
55186  // lock-related properties, for use in fabric.Group#get
55187  // to enable locking behavior on group
55188  // when one of its objects has lock-related properties set
55189  var _lockProperties = {
55190    lockMovementX:  true,
55191    lockMovementY:  true,
55192    lockRotation:   true,
55193    lockScalingX:   true,
55194    lockScalingY:   true,
55195    lockUniScaling: true
55196  };
55197
55198  /**
55199   * Group class
55200   * @class fabric.Group
55201   * @extends fabric.Object
55202   * @mixes fabric.Collection
55203   * @tutorial {@link http://fabricjs.com/fabric-intro-part-3/#groups}
55204   */
55205  fabric.Group = fabric.util.createClass(fabric.Object, fabric.Collection, /** @lends fabric.Group.prototype */ {
55206
55207    /**
55208     * Type of an object
55209     * @type String
55210     * @default
55211     */
55212    type: 'group',
55213
55214    /**
55215     * Constructor
55216     * @param {Object} objects Group objects
55217     * @param {Object} [options] Options object
55218     * @return {Object} thisArg
55219     */
55220    initialize: function(objects, options) {
55221      options = options || { };
55222
55223      this._objects = objects || [];
55224      for (var i = this._objects.length; i--; ) {
55225        this._objects[i].group = this;
55226      }
55227
55228      this.originalState = { };
55229      this.callSuper('initialize');
55230
55231      this._calcBounds();
55232      this._updateObjectsCoords();
55233
55234      if (options) {
55235        extend(this, options);
55236      }
55237      this._setOpacityIfSame();
55238
55239      this.setCoords(true);
55240      this.saveCoords();
55241    },
55242
55243    /**
55244     * @private
55245     */
55246    _updateObjectsCoords: function() {
55247      var groupDeltaX = this.left,
55248          groupDeltaY = this.top;
55249
55250      this.forEachObject(function(object) {
55251
55252        var objectLeft = object.get('left'),
55253            objectTop = object.get('top');
55254
55255        object.set('originalLeft', objectLeft);
55256        object.set('originalTop', objectTop);
55257
55258        object.set('left', objectLeft - groupDeltaX);
55259        object.set('top', objectTop - groupDeltaY);
55260
55261        object.setCoords();
55262
55263        // do not display corners of objects enclosed in a group
55264        object.__origHasControls = object.hasControls;
55265        object.hasControls = false;
55266      }, this);
55267    },
55268
55269    /**
55270     * Returns string represenation of a group
55271     * @return {String}
55272     */
55273    toString: function() {
55274      return '#<fabric.Group: (' + this.complexity() + ')>';
55275    },
55276
55277    /**
55278     * Returns an array of all objects in this group
55279     * @return {Array} group objects
55280     */
55281    getObjects: function() {
55282      return this._objects;
55283    },
55284
55285    /**
55286     * Adds an object to a group; Then recalculates group's dimension, position.
55287     * @param {Object} object
55288     * @return {fabric.Group} thisArg
55289     * @chainable
55290     */
55291    addWithUpdate: function(object) {
55292      this._restoreObjectsState();
55293      this._objects.push(object);
55294      object.group = this;
55295      // since _restoreObjectsState set objects inactive
55296      this.forEachObject(function(o){ o.set('active', true); o.group = this; }, this);
55297      this._calcBounds();
55298      this._updateObjectsCoords();
55299      return this;
55300    },
55301
55302    /**
55303     * Removes an object from a group; Then recalculates group's dimension, position.
55304     * @param {Object} object
55305     * @return {fabric.Group} thisArg
55306     * @chainable
55307     */
55308    removeWithUpdate: function(object) {
55309      this._moveFlippedObject(object);
55310      this._restoreObjectsState();
55311      // since _restoreObjectsState set objects inactive
55312      this.forEachObject(function(o){ o.set('active', true); o.group = this; }, this);
55313
55314      this.remove(object);
55315      this._calcBounds();
55316      this._updateObjectsCoords();
55317      return this;
55318    },
55319
55320    /**
55321     * @private
55322     */
55323    _onObjectAdded: function(object) {
55324      object.group = this;
55325    },
55326
55327    /**
55328     * @private
55329     */
55330    _onObjectRemoved: function(object) {
55331      delete object.group;
55332      object.set('active', false);
55333    },
55334
55335    /**
55336     * Properties that are delegated to group objects when reading/writing
55337     * @param {Object} delegatedProperties
55338     */
55339    delegatedProperties: {
55340      fill:             true,
55341      opacity:          true,
55342      fontFamily:       true,
55343      fontWeight:       true,
55344      fontSize:         true,
55345      fontStyle:        true,
55346      lineHeight:       true,
55347      textDecoration:   true,
55348      textAlign:        true,
55349      backgroundColor:  true
55350    },
55351
55352    /**
55353     * @private
55354     */
55355    _set: function(key, value) {
55356      if (key in this.delegatedProperties) {
55357        var i = this._objects.length;
55358        this[key] = value;
55359        while (i--) {
55360          this._objects[i].set(key, value);
55361        }
55362      }
55363      else {
55364        this[key] = value;
55365      }
55366    },
55367
55368    /**
55369     * Returns object representation of an instance
55370     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output
55371     * @return {Object} object representation of an instance
55372     */
55373    toObject: function(propertiesToInclude) {
55374      return extend(this.callSuper('toObject', propertiesToInclude), {
55375        objects: invoke(this._objects, 'toObject', propertiesToInclude)
55376      });
55377    },
55378
55379    /**
55380     * Renders instance on a given context
55381     * @param {CanvasRenderingContext2D} ctx context to render instance on
55382     * @param {Boolean} [noTransform] When true, context is not transformed
55383     */
55384    render: function(ctx, noTransform) {
55385      // do not render if object is not visible
55386      if (!this.visible) return;
55387
55388      ctx.save();
55389      this.transform(ctx);
55390
55391      var groupScaleFactor = Math.max(this.scaleX, this.scaleY);
55392
55393      this.clipTo && fabric.util.clipContext(this, ctx);
55394
55395      //The array is now sorted in order of highest first, so start from end.
55396      for (var i = 0, len = this._objects.length; i < len; i++) {
55397
55398        var object = this._objects[i],
55399            originalScaleFactor = object.borderScaleFactor,
55400            originalHasRotatingPoint = object.hasRotatingPoint;
55401
55402        // do not render if object is not visible
55403        if (!object.visible) continue;
55404
55405        object.borderScaleFactor = groupScaleFactor;
55406        object.hasRotatingPoint = false;
55407
55408        object.render(ctx);
55409
55410        object.borderScaleFactor = originalScaleFactor;
55411        object.hasRotatingPoint = originalHasRotatingPoint;
55412      }
55413      this.clipTo && ctx.restore();
55414
55415      if (!noTransform && this.active) {
55416        this.drawBorders(ctx);
55417        this.drawControls(ctx);
55418      }
55419      ctx.restore();
55420      this.setCoords();
55421    },
55422
55423    /**
55424     * Retores original state of each of group objects (original state is that which was before group was created).
55425     * @private
55426     * @return {fabric.Group} thisArg
55427     * @chainable
55428     */
55429    _restoreObjectsState: function() {
55430      this._objects.forEach(this._restoreObjectState, this);
55431      return this;
55432    },
55433
55434    /**
55435     * Moves a flipped object to the position where it's displayed
55436     * @private
55437     * @param {fabric.Object} object
55438     * @return {fabric.Group} thisArg
55439     */
55440    _moveFlippedObject: function(object) {
55441      var oldOriginX = object.get('originX');
55442      var oldOriginY = object.get('originY');
55443      var center = object.getCenterPoint();
55444      object.set({
55445        originX: 'center',
55446        originY: 'center',
55447        left: center.x,
55448        top: center.y
55449      });
55450
55451      if (this.flipX) {
55452        object.toggle('flipX');
55453        object.set('left', -object.get('left'));
55454        object.setAngle(-object.getAngle());
55455      }
55456      if (this.flipY) {
55457        object.toggle('flipY');
55458        object.set('top', -object.get('top'));
55459        object.setAngle(-object.getAngle());
55460      }
55461
55462      var newOrigin = object.getPointByOrigin(oldOriginX, oldOriginY);
55463      object.set({
55464        originX: oldOriginX,
55465        originY: oldOriginY,
55466        left: newOrigin.x,
55467        top: newOrigin.y
55468      });
55469      return this;
55470    },
55471
55472    /**
55473     * Restores original state of a specified object in group
55474     * @private
55475     * @param {fabric.Object} object
55476     * @return {fabric.Group} thisArg
55477     */
55478    _restoreObjectState: function(object) {
55479      var groupLeft = this.get('left'),
55480          groupTop = this.get('top'),
55481          groupAngle = this.getAngle() * (Math.PI / 180),
55482          rotatedTop = Math.cos(groupAngle) * object.get('top') * this.get('scaleY') + Math.sin(groupAngle) * object.get('left') * this.get('scaleX'),
55483          rotatedLeft = -Math.sin(groupAngle) * object.get('top') * this.get('scaleY') + Math.cos(groupAngle) * object.get('left') * this.get('scaleX');
55484
55485      object.setAngle(object.getAngle() + this.getAngle());
55486
55487      object.set('left', groupLeft + rotatedLeft);
55488      object.set('top', groupTop + rotatedTop);
55489
55490      object.set('scaleX', object.get('scaleX') * this.get('scaleX'));
55491      object.set('scaleY', object.get('scaleY') * this.get('scaleY'));
55492
55493      object.setCoords();
55494      object.hasControls = object.__origHasControls;
55495      delete object.__origHasControls;
55496      object.set('active', false);
55497      object.setCoords();
55498      delete object.group;
55499
55500      return this;
55501    },
55502
55503    /**
55504     * Destroys a group (restoring state of its objects)
55505     * @return {fabric.Group} thisArg
55506     * @chainable
55507     */
55508    destroy: function() {
55509      this._objects.forEach(this._moveFlippedObject, this);
55510      return this._restoreObjectsState();
55511    },
55512
55513    /**
55514     * Saves coordinates of this instance (to be used together with `hasMoved`)
55515     * @saveCoords
55516     * @return {fabric.Group} thisArg
55517     * @chainable
55518     */
55519    saveCoords: function() {
55520      this._originalLeft = this.get('left');
55521      this._originalTop = this.get('top');
55522      return this;
55523    },
55524
55525    /**
55526     * Checks whether this group was moved (since `saveCoords` was called last)
55527     * @return {Boolean} true if an object was moved (since fabric.Group#saveCoords was called)
55528     */
55529    hasMoved: function() {
55530      return this._originalLeft !== this.get('left') ||
55531             this._originalTop !== this.get('top');
55532    },
55533
55534    /**
55535     * Sets coordinates of all group objects
55536     * @return {fabric.Group} thisArg
55537     * @chainable
55538     */
55539    setObjectsCoords: function() {
55540      this.forEachObject(function(object) {
55541        object.setCoords();
55542      });
55543      return this;
55544    },
55545
55546    /**
55547     * @private
55548     */
55549    _setOpacityIfSame: function() {
55550      var objects = this.getObjects(),
55551          firstValue = objects[0] ? objects[0].get('opacity') : 1;
55552
55553      var isSameOpacity = objects.every(function(o) {
55554        return o.get('opacity') === firstValue;
55555      });
55556
55557      if (isSameOpacity) {
55558        this.opacity = firstValue;
55559      }
55560    },
55561
55562    /**
55563     * @private
55564     */
55565    _calcBounds: function() {
55566      var aX = [],
55567          aY = [],
55568          minX, minY, maxX, maxY, o, width, height,
55569          i = 0,
55570          len = this._objects.length;
55571
55572      for (; i < len; ++i) {
55573        o = this._objects[i];
55574        o.setCoords();
55575        for (var prop in o.oCoords) {
55576          aX.push(o.oCoords[prop].x);
55577          aY.push(o.oCoords[prop].y);
55578        }
55579      }
55580
55581      minX = min(aX);
55582      maxX = max(aX);
55583      minY = min(aY);
55584      maxY = max(aY);
55585
55586      width = (maxX - minX) || 0;
55587      height = (maxY - minY) || 0;
55588
55589      this.width = width;
55590      this.height = height;
55591
55592      this.left = (minX + width / 2) || 0;
55593      this.top = (minY + height / 2) || 0;
55594    },
55595
55596    /* _TO_SVG_START_ */
55597    /**
55598     * Returns svg representation of an instance
55599     * @param {Function} [reviver] Method for further parsing of svg representation.
55600     * @return {String} svg representation of an instance
55601     */
55602    toSVG: function(reviver) {
55603      var markup = [
55604        '<g ',
55605          'transform="', this.getSvgTransform(),
55606        '">'
55607      ];
55608
55609      for (var i = 0, len = this._objects.length; i < len; i++) {
55610        markup.push(this._objects[i].toSVG(reviver));
55611      }
55612
55613      markup.push('</g>');
55614
55615      return reviver ? reviver(markup.join('')) : markup.join('');
55616    },
55617    /* _TO_SVG_END_ */
55618
55619    /**
55620     * Returns requested property
55621     * @param {String} prop Property to get
55622     * @return {Any}
55623     */
55624    get: function(prop) {
55625      if (prop in _lockProperties) {
55626        if (this[prop]) {
55627          return this[prop];
55628        }
55629        else {
55630          for (var i = 0, len = this._objects.length; i < len; i++) {
55631            if (this._objects[i][prop]) {
55632              return true;
55633            }
55634          }
55635          return false;
55636        }
55637      }
55638      else {
55639        if (prop in this.delegatedProperties) {
55640          return this._objects[0] && this._objects[0].get(prop);
55641        }
55642        return this[prop];
55643      }
55644    }
55645  });
55646
55647  /**
55648   * Returns {@link fabric.Group} instance from an object representation
55649   * @static
55650   * @memberOf fabric.Group
55651   * @param {Object} object Object to create a group from
55652   * @param {Object} [options] Options object
55653   * @return {fabric.Group} An instance of fabric.Group
55654   */
55655  fabric.Group.fromObject = function(object, callback) {
55656    fabric.util.enlivenObjects(object.objects, function(enlivenedObjects) {
55657      delete object.objects;
55658      callback && callback(new fabric.Group(enlivenedObjects, object));
55659    });
55660  };
55661
55662  /**
55663   * Indicates that instances of this type are async
55664   * @static
55665   * @memberOf fabric.Group
55666   * @type Boolean
55667   * @default
55668   */
55669  fabric.Group.async = true;
55670
55671})(typeof exports !== 'undefined' ? exports : this);
55672
55673
55674(function(global) {
55675
55676  "use strict";
55677
55678  var extend = fabric.util.object.extend;
55679
55680  if (!global.fabric) {
55681    global.fabric = { };
55682  }
55683
55684  if (global.fabric.Image) {
55685    fabric.warn('fabric.Image is already defined.');
55686    return;
55687  }
55688
55689  /**
55690   * Image class
55691   * @class fabric.Image
55692   * @extends fabric.Object
55693   * @tutorial {@link http://fabricjs.com/fabric-intro-part-1/#images}
55694   */
55695  fabric.Image = fabric.util.createClass(fabric.Object, /** @lends fabric.Image.prototype */ {
55696
55697    /**
55698     * Type of an object
55699     * @type String
55700     * @default
55701     */
55702    type: 'image',
55703
55704    /**
55705     * Constructor
55706     * @param {HTMLImageElement | String} element Image element
55707     * @param {Object} [options] Options object
55708     * @return {fabric.Image} thisArg
55709     */
55710    initialize: function(element, options) {
55711      options || (options = { });
55712
55713      this.filters = [ ];
55714
55715      this.callSuper('initialize', options);
55716      this._initElement(element);
55717      this._initConfig(options);
55718
55719      if (options.filters) {
55720        this.filters = options.filters;
55721        this.applyFilters();
55722      }
55723    },
55724
55725    /**
55726     * Returns image element which this instance if based on
55727     * @return {HTMLImageElement} Image element
55728     */
55729    getElement: function() {
55730      return this._element;
55731    },
55732
55733    /**
55734     * Sets image element for this instance to a specified one.
55735     * If filters defined they are applied to new image.
55736     * You might need to call `canvas.renderAll` and `object.setCoords` after replacing, to render new image and update controls area.
55737     * @param {HTMLImageElement} element
55738     * @param {Function} [callback] Callback is invoked when all filters have been applied and new image is generated
55739     * @return {fabric.Image} thisArg
55740     * @chainable
55741     */
55742    setElement: function(element, callback) {
55743      this._element = element;
55744      this._originalElement = element;
55745      this._initConfig();
55746
55747      if (this.filters.length !== 0) {
55748        this.applyFilters(callback);
55749      }
55750
55751      return this;
55752    },
55753
55754    /**
55755     * Returns original size of an image
55756     * @return {Object} Object with "width" and "height" properties
55757     */
55758    getOriginalSize: function() {
55759      var element = this.getElement();
55760      return {
55761        width: element.width,
55762        height: element.height
55763      };
55764    },
55765
55766    /**
55767     * Renders image on a specified context
55768     * @param {CanvasRenderingContext2D} ctx Context to render on
55769     * @param {Boolean} [noTransform] When true, context is not transformed
55770     */
55771    render: function(ctx, noTransform) {
55772      // do not render if object is not visible
55773      if (!this.visible) return;
55774
55775      ctx.save();
55776      var m = this.transformMatrix;
55777      var isInPathGroup = this.group && this.group.type !== 'group';
55778
55779      // this._resetWidthHeight();
55780      if (isInPathGroup) {
55781        ctx.translate(-this.group.width/2 + this.width/2, -this.group.height/2 + this.height/2);
55782      }
55783      if (m) {
55784        ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]);
55785      }
55786      if (!noTransform) {
55787        this.transform(ctx);
55788      }
55789
55790      ctx.save();
55791      this._setShadow(ctx);
55792      this.clipTo && fabric.util.clipContext(this, ctx);
55793      this._render(ctx);
55794      if (this.shadow && !this.shadow.affectStroke) {
55795        this._removeShadow(ctx);
55796      }
55797      this._renderStroke(ctx);
55798      this.clipTo && ctx.restore();
55799      ctx.restore();
55800
55801      if (this.active && !noTransform) {
55802        this.drawBorders(ctx);
55803        this.drawControls(ctx);
55804      }
55805      ctx.restore();
55806    },
55807
55808    /**
55809     * @private
55810     * @param {CanvasRenderingContext2D} ctx Context to render on
55811     */
55812    _stroke: function(ctx) {
55813      ctx.save();
55814      ctx.lineWidth = this.strokeWidth;
55815      ctx.lineCap = this.strokeLineCap;
55816      ctx.lineJoin = this.strokeLineJoin;
55817      ctx.miterLimit = this.strokeMiterLimit;
55818      ctx.strokeStyle = this.stroke.toLive
55819        ? this.stroke.toLive(ctx)
55820        : this.stroke;
55821
55822      ctx.beginPath();
55823      ctx.strokeRect(-this.width / 2, -this.height / 2, this.width, this.height);
55824      ctx.closePath();
55825      ctx.restore();
55826    },
55827
55828    /**
55829     * @private
55830     * @param {CanvasRenderingContext2D} ctx Context to render on
55831     */
55832    _renderDashedStroke: function(ctx) {
55833     var x = -this.width/2,
55834         y = -this.height/2,
55835         w = this.width,
55836         h = this.height;
55837
55838      ctx.save();
55839      ctx.lineWidth = this.strokeWidth;
55840      ctx.lineCap = this.strokeLineCap;
55841      ctx.lineJoin = this.strokeLineJoin;
55842      ctx.miterLimit = this.strokeMiterLimit;
55843      ctx.strokeStyle = this.stroke.toLive
55844        ? this.stroke.toLive(ctx)
55845        : this.stroke;
55846
55847      ctx.beginPath();
55848      fabric.util.drawDashedLine(ctx, x, y, x+w, y, this.strokeDashArray);
55849      fabric.util.drawDashedLine(ctx, x+w, y, x+w, y+h, this.strokeDashArray);
55850      fabric.util.drawDashedLine(ctx, x+w, y+h, x, y+h, this.strokeDashArray);
55851      fabric.util.drawDashedLine(ctx, x, y+h, x, y, this.strokeDashArray);
55852      ctx.closePath();
55853      ctx.restore();
55854    },
55855
55856    /**
55857     * Returns object representation of an instance
55858     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output
55859     * @return {Object} Object representation of an instance
55860     */
55861    toObject: function(propertiesToInclude) {
55862      return extend(this.callSuper('toObject', propertiesToInclude), {
55863        src: this._originalElement.src || this._originalElement._src,
55864        filters: this.filters.map(function(filterObj) {
55865          return filterObj && filterObj.toObject();
55866        })
55867      });
55868    },
55869
55870    /* _TO_SVG_START_ */
55871    /**
55872     * Returns SVG representation of an instance
55873     * @param {Function} [reviver] Method for further parsing of svg representation.
55874     * @return {String} svg representation of an instance
55875     */
55876    toSVG: function(reviver) {
55877      var markup = [];
55878
55879      markup.push(
55880        '<g transform="', this.getSvgTransform(), '">',
55881          '<image xlink:href="', this.getSvgSrc(),
55882            '" style="', this.getSvgStyles(),
55883            // we're essentially moving origin of transformation from top/left corner to the center of the shape
55884            // by wrapping it in container <g> element with actual transformation, then offsetting object to the top/left
55885            // so that object's center aligns with container's left/top
55886            '" transform="translate(' + (-this.width/2) + ' ' + (-this.height/2) + ')',
55887            '" width="', this.width,
55888            '" height="', this.height,
55889          '"></image>'
55890      );
55891
55892      if (this.stroke || this.strokeDashArray) {
55893        var origFill = this.fill;
55894        this.fill = null;
55895        markup.push(
55896          '<rect ',
55897            'x="', (-1 * this.width / 2), '" y="', (-1 * this.height / 2),
55898            '" width="', this.width, '" height="', this.height,
55899            '" style="', this.getSvgStyles(),
55900          '"/>'
55901        );
55902        this.fill = origFill;
55903      }
55904
55905      markup.push('</g>');
55906
55907      return reviver ? reviver(markup.join('')) : markup.join('');
55908    },
55909    /* _TO_SVG_END_ */
55910
55911    /**
55912     * Returns source of an image
55913     * @return {String} Source of an image
55914     */
55915    getSrc: function() {
55916      return this.getElement().src || this.getElement()._src;
55917    },
55918
55919    /**
55920     * Returns string representation of an instance
55921     * @return {String} String representation of an instance
55922     */
55923    toString: function() {
55924      return '#<fabric.Image: { src: "' + this.getSrc() + '" }>';
55925    },
55926
55927    /**
55928     * Returns a clone of an instance
55929     * @param {Function} callback Callback is invoked with a clone as a first argument
55930     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output
55931     */
55932    clone: function(callback, propertiesToInclude) {
55933      this.constructor.fromObject(this.toObject(propertiesToInclude), callback);
55934    },
55935
55936    /**
55937     * Applies filters assigned to this image (from "filters" array)
55938     * @mthod applyFilters
55939     * @param {Function} callback Callback is invoked when all filters have been applied and new image is generated
55940     * @return {fabric.Image} thisArg
55941     * @chainable
55942     */
55943    applyFilters: function(callback) {
55944
55945      if (this.filters.length === 0) {
55946        this._element = this._originalElement;
55947        callback && callback();
55948        return;
55949      }
55950
55951      var imgEl = this._originalElement,
55952          canvasEl = fabric.util.createCanvasElement(),
55953          replacement = fabric.util.createImage(),
55954          _this = this;
55955
55956      canvasEl.width = imgEl.width;
55957      canvasEl.height = imgEl.height;
55958
55959      canvasEl.getContext('2d').drawImage(imgEl, 0, 0, imgEl.width, imgEl.height);
55960
55961      this.filters.forEach(function(filter) {
55962        filter && filter.applyTo(canvasEl);
55963      });
55964
55965       /** @ignore */
55966
55967      replacement.width = imgEl.width;
55968      replacement.height = imgEl.height;
55969
55970      if (fabric.isLikelyNode) {
55971        replacement.src = canvasEl.toBuffer(undefined, fabric.Image.pngCompression);
55972
55973        // onload doesn't fire in some node versions, so we invoke callback manually
55974        _this._element = replacement;
55975        callback && callback();
55976      }
55977      else {
55978        replacement.onload = function() {
55979          _this._element = replacement;
55980          callback && callback();
55981          replacement.onload = canvasEl = imgEl = null;
55982        };
55983        replacement.src = canvasEl.toDataURL('image/png');
55984      }
55985
55986      return this;
55987    },
55988
55989    /**
55990     * @private
55991     * @param {CanvasRenderingContext2D} ctx Context to render on
55992     */
55993    _render: function(ctx) {
55994      ctx.drawImage(
55995        this._element,
55996        -this.width / 2,
55997        -this.height / 2,
55998        this.width,
55999        this.height
56000      );
56001    },
56002
56003    /**
56004     * @private
56005     */
56006    _resetWidthHeight: function() {
56007      var element = this.getElement();
56008
56009      this.set('width', element.width);
56010      this.set('height', element.height);
56011    },
56012
56013    /**
56014     * The Image class's initialization method. This method is automatically
56015     * called by the constructor.
56016     * @private
56017     * @param {HTMLImageElement|String} element The element representing the image
56018     */
56019    _initElement: function(element) {
56020      this.setElement(fabric.util.getById(element));
56021      fabric.util.addClass(this.getElement(), fabric.Image.CSS_CANVAS);
56022    },
56023
56024    /**
56025     * @private
56026     * @param {Object} [options] Options object
56027     */
56028    _initConfig: function(options) {
56029      options || (options = { });
56030      this.setOptions(options);
56031      this._setWidthHeight(options);
56032    },
56033
56034    /**
56035     * @private
56036     * @param {Object} object Object with filters property
56037     * @param {Function} callback Callback to invoke when all fabric.Image.filters instances are created
56038     */
56039    _initFilters: function(object, callback) {
56040      if (object.filters && object.filters.length) {
56041        fabric.util.enlivenObjects(object.filters, function(enlivenedObjects) {
56042          callback && callback(enlivenedObjects);
56043        }, 'fabric.Image.filters');
56044      }
56045      else {
56046        callback && callback();
56047      }
56048    },
56049
56050    /**
56051     * @private
56052     * @param {Object} [options] Object with width/height properties
56053     */
56054    _setWidthHeight: function(options) {
56055      this.width = 'width' in options
56056        ? options.width
56057        : (this.getElement().width || 0);
56058
56059      this.height = 'height' in options
56060        ? options.height
56061        : (this.getElement().height || 0);
56062    },
56063
56064    /**
56065     * Returns complexity of an instance
56066     * @return {Number} complexity of this instance
56067     */
56068    complexity: function() {
56069      return 1;
56070    }
56071  });
56072
56073  /**
56074   * Default CSS class name for canvas
56075   * @static
56076   * @type String
56077   * @default
56078   */
56079  fabric.Image.CSS_CANVAS = "canvas-img";
56080
56081  /**
56082   * Alias for getSrc
56083   * @static
56084   */
56085  fabric.Image.prototype.getSvgSrc = fabric.Image.prototype.getSrc;
56086
56087  /**
56088   * Creates an instance of fabric.Image from its object representation
56089   * @static
56090   * @param {Object} object Object to create an instance from
56091   * @param {Function} [callback] Callback to invoke when an image instance is created
56092   */
56093  fabric.Image.fromObject = function(object, callback) {
56094    var img = fabric.document.createElement('img'),
56095        src = object.src;
56096
56097    /** @ignore */
56098    img.onload = function() {
56099      fabric.Image.prototype._initFilters.call(object, object, function(filters) {
56100        object.filters = filters || [ ];
56101
56102        var instance = new fabric.Image(img, object);
56103        callback && callback(instance);
56104        img = img.onload = img.onerror = null;
56105      });
56106    };
56107
56108    /** @ignore */
56109    img.onerror = function() {
56110      fabric.log('Error loading ' + img.src);
56111      callback && callback(null, true);
56112      img = img.onload = img.onerror = null;
56113    };
56114
56115    img.src = src;
56116  };
56117
56118  /**
56119   * Creates an instance of fabric.Image from an URL string
56120   * @static
56121   * @param {String} url URL to create an image from
56122   * @param {Function} [callback] Callback to invoke when image is created (newly created image is passed as a first argument)
56123   * @param {Object} [imgOptions] Options object
56124   */
56125  fabric.Image.fromURL = function(url, callback, imgOptions) {
56126    fabric.util.loadImage(url, function(img) {
56127      callback(new fabric.Image(img, imgOptions));
56128    });
56129  };
56130
56131  /* _FROM_SVG_START_ */
56132  /**
56133   * List of attribute names to account for when parsing SVG element (used by {@link fabric.Image.fromElement})
56134   * @static
56135   * @see {@link http://www.w3.org/TR/SVG/struct.html#ImageElement}
56136   */
56137  fabric.Image.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('x y width height xlink:href'.split(' '));
56138
56139  /**
56140   * Returns {@link fabric.Image} instance from an SVG element
56141   * @static
56142   * @param {SVGElement} element Element to parse
56143   * @param {Function} callback Callback to execute when fabric.Image object is created
56144   * @param {Object} [options] Options object
56145   * @return {fabric.Image} Instance of fabric.Image
56146   */
56147  fabric.Image.fromElement = function(element, callback, options) {
56148    var parsedAttributes = fabric.parseAttributes(element, fabric.Image.ATTRIBUTE_NAMES);
56149
56150    fabric.Image.fromURL(parsedAttributes['xlink:href'], callback,
56151      extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes));
56152  };
56153  /* _FROM_SVG_END_ */
56154
56155  /**
56156   * Indicates that instances of this type are async
56157   * @static
56158   * @type Boolean
56159   * @default
56160   */
56161  fabric.Image.async = true;
56162
56163  /**
56164   * Indicates compression level used when generating PNG under Node (in applyFilters). Any of 0-9
56165   * @static
56166   * @type Number
56167   * @default
56168   */
56169  fabric.Image.pngCompression = 1;
56170
56171})(typeof exports !== 'undefined' ? exports : this);
56172
56173
56174fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {
56175
56176  /**
56177   * @private
56178   * @return {Number} angle value
56179   */
56180  _getAngleValueForStraighten: function() {
56181    var angle = this.getAngle() % 360;
56182    if (angle > 0) {
56183      return Math.round((angle-1)/90) * 90;
56184    }
56185    return Math.round(angle/90) * 90;
56186  },
56187
56188  /**
56189   * Straightens an object (rotating it from current angle to one of 0, 90, 180, 270, etc. depending on which is closer)
56190   * @return {fabric.Object} thisArg
56191   * @chainable
56192   */
56193  straighten: function() {
56194    this.setAngle(this._getAngleValueForStraighten());
56195    return this;
56196  },
56197
56198  /**
56199   * Same as {@link fabric.Object.prototype.straighten} but with animation
56200   * @param {Object} callbacks Object with callback functions
56201   * @param {Function} [callbacks.onComplete] Invoked on completion
56202   * @param {Function} [callbacks.onChange] Invoked on every step of animation
56203   * @return {fabric.Object} thisArg
56204   * @chainable
56205   */
56206  fxStraighten: function(callbacks) {
56207    callbacks = callbacks || { };
56208
56209    var empty = function() { },
56210        onComplete = callbacks.onComplete || empty,
56211        onChange = callbacks.onChange || empty,
56212        _this = this;
56213
56214    fabric.util.animate({
56215      startValue: this.get('angle'),
56216      endValue: this._getAngleValueForStraighten(),
56217      duration: this.FX_DURATION,
56218      onChange: function(value) {
56219        _this.setAngle(value);
56220        onChange();
56221      },
56222      onComplete: function() {
56223        _this.setCoords();
56224        onComplete();
56225      },
56226      onStart: function() {
56227        _this.set('active', false);
56228      }
56229    });
56230
56231    return this;
56232  }
56233});
56234
56235fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ {
56236
56237  /**
56238   * Straightens object, then rerenders canvas
56239   * @param {fabric.Object} object Object to straighten
56240   * @return {fabric.Canvas} thisArg
56241   * @chainable
56242   */
56243  straightenObject: function (object) {
56244    object.straighten();
56245    this.renderAll();
56246    return this;
56247  },
56248
56249  /**
56250   * Same as {@link fabric.Canvas.prototype.straightenObject}, but animated
56251   * @param {fabric.Object} object Object to straighten
56252   * @return {fabric.Canvas} thisArg
56253   * @chainable
56254   */
56255  fxStraightenObject: function (object) {
56256    object.fxStraighten({
56257      onChange: this.renderAll.bind(this)
56258    });
56259    return this;
56260  }
56261});
56262
56263
56264/**
56265 * @namespace fabric.Image.filters
56266 * @memberOf fabric.Image
56267 * @tutorial {@link http://fabricjs.com/fabric-intro-part-2/#image_filters}
56268 * @see {@link http://fabricjs.com/image-filters/|ImageFilters demo}
56269 */
56270fabric.Image.filters = fabric.Image.filters || { };
56271
56272
56273/**
56274 * Root filter class from which all filter classes inherit from
56275 * @class fabric.Image.filters.BaseFilter
56276 * @memberOf fabric.Image.filters
56277 */
56278fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Image.filters.BaseFilter.prototype */ {
56279
56280  /**
56281   * Filter type
56282   * @param {String} type
56283   * @default
56284   */
56285  type: 'BaseFilter',
56286
56287  /**
56288   * Returns object representation of an instance
56289   * @return {Object} Object representation of an instance
56290   */
56291  toObject: function() {
56292    return { type: this.type };
56293  },
56294
56295  /**
56296   * Returns a JSON representation of an instance
56297   * @return {Object} JSON
56298   */
56299  toJSON: function() {
56300    // delegate, not alias
56301    return this.toObject();
56302  }
56303});
56304
56305
56306(function(global) {
56307
56308  "use strict";
56309
56310  var fabric  = global.fabric || (global.fabric = { }),
56311      extend = fabric.util.object.extend;
56312
56313  /**
56314   * Brightness filter class
56315   * @class fabric.Image.filters.Brightness
56316   * @memberOf fabric.Image.filters
56317   * @extends fabric.Image.filters.BaseFilter
56318   */
56319  fabric.Image.filters.Brightness = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Brightness.prototype */ {
56320
56321    /**
56322     * Filter type
56323     * @param {String} type
56324     * @default
56325     */
56326    type: 'Brightness',
56327
56328    /**
56329     * Constructor
56330     * @memberOf fabric.Image.filters.Brightness.prototype
56331     * @param {Object} [options] Options object
56332     * @param {Number} [options.brightness=100] Value to brighten the image up (0..255)
56333     */
56334    initialize: function(options) {
56335      options = options || { };
56336      this.brightness = options.brightness || 100;
56337    },
56338
56339    /**
56340     * Applies filter to canvas element
56341     * @param {Object} canvasEl Canvas element to apply filter to
56342     */
56343    applyTo: function(canvasEl) {
56344      var context = canvasEl.getContext('2d'),
56345          imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),
56346          data = imageData.data,
56347          brightness = this.brightness;
56348
56349      for (var i = 0, len = data.length; i < len; i += 4) {
56350        data[i] += brightness;
56351        data[i + 1] += brightness;
56352        data[i + 2] += brightness;
56353      }
56354
56355      context.putImageData(imageData, 0, 0);
56356    },
56357
56358    /**
56359     * Returns object representation of an instance
56360     * @return {Object} Object representation of an instance
56361     */
56362    toObject: function() {
56363      return extend(this.callSuper('toObject'), {
56364        brightness: this.brightness
56365      });
56366    }
56367  });
56368
56369  /**
56370   * Returns filter instance from an object representation
56371   * @static
56372   * @param {Object} object Object to create an instance from
56373   * @return {fabric.Image.filters.Brightness} Instance of fabric.Image.filters.Brightness
56374   */
56375  fabric.Image.filters.Brightness.fromObject = function(object) {
56376    return new fabric.Image.filters.Brightness(object);
56377  };
56378
56379})(typeof exports !== 'undefined' ? exports : this);
56380
56381
56382(function(global) {
56383
56384  "use strict";
56385
56386  var fabric  = global.fabric || (global.fabric = { }),
56387      extend = fabric.util.object.extend;
56388
56389  /**
56390   * Adapted from <a href="http://www.html5rocks.com/en/tutorials/canvas/imagefilters/">html5rocks article</a>
56391   * @class fabric.Image.filters.Convolute
56392   * @memberOf fabric.Image.filters
56393   * @extends fabric.Image.filters.BaseFilter
56394   */
56395  fabric.Image.filters.Convolute = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Convolute.prototype */ {
56396
56397    /**
56398     * Filter type
56399     * @param {String} type
56400     * @default
56401     */
56402    type: 'Convolute',
56403
56404    /**
56405     * Constructor
56406     * @memberOf fabric.Image.filters.Convolute.prototype
56407     * @param {Object} [options] Options object
56408     * @param {Boolean} [options.opaque=false] Opaque value (true/false)
56409     * @param {Array} [options.matrix] Filter matrix
56410     */
56411    initialize: function(options) {
56412      options = options || { };
56413
56414      this.opaque = options.opaque;
56415      this.matrix = options.matrix || [ 0, 0, 0,
56416        0, 1, 0,
56417        0, 0, 0 ];
56418
56419      var canvasEl = fabric.util.createCanvasElement();
56420      this.tmpCtx = canvasEl.getContext('2d');
56421    },
56422
56423    /**
56424     * @private
56425     */
56426    _createImageData: function(w, h) {
56427      return this.tmpCtx.createImageData(w, h);
56428    },
56429
56430    /**
56431     * Applies filter to canvas element
56432     * @param {Object} canvasEl Canvas element to apply filter to
56433     */
56434    applyTo: function(canvasEl) {
56435      var weights = this.matrix;
56436      var context = canvasEl.getContext('2d');
56437      var pixels = context.getImageData(0, 0, canvasEl.width, canvasEl.height);
56438
56439      var side = Math.round(Math.sqrt(weights.length));
56440      var halfSide = Math.floor(side/2);
56441      var src = pixels.data;
56442      var sw = pixels.width;
56443      var sh = pixels.height;
56444
56445      // pad output by the convolution matrix
56446      var w = sw;
56447      var h = sh;
56448      var output = this._createImageData(w, h);
56449
56450      var dst = output.data;
56451
56452      // go through the destination image pixels
56453      var alphaFac = this.opaque ? 1 : 0;
56454      for (var y=0; y<h; y++) {
56455        for (var x=0; x<w; x++) {
56456          var sy = y;
56457          var sx = x;
56458          var dstOff = (y*w+x)*4;
56459          // calculate the weighed sum of the source image pixels that
56460          // fall under the convolution matrix
56461          var r=0, g=0, b=0, a=0;
56462          for (var cy=0; cy<side; cy++) {
56463            for (var cx=0; cx<side; cx++) {
56464              var scy = sy + cy - halfSide;
56465              var scx = sx + cx - halfSide;
56466              if (scy >= 0 && scy < sh && scx >= 0 && scx < sw) {
56467                var srcOff = (scy*sw+scx)*4;
56468                var wt = weights[cy*side+cx];
56469                r += src[srcOff] * wt;
56470                g += src[srcOff+1] * wt;
56471                b += src[srcOff+2] * wt;
56472                a += src[srcOff+3] * wt;
56473              }
56474            }
56475          }
56476          dst[dstOff] = r;
56477          dst[dstOff+1] = g;
56478          dst[dstOff+2] = b;
56479          dst[dstOff+3] = a + alphaFac*(255-a);
56480        }
56481      }
56482
56483      context.putImageData(output, 0, 0);
56484    },
56485
56486    /**
56487     * Returns object representation of an instance
56488     * @return {Object} Object representation of an instance
56489     */
56490    toObject: function() {
56491      return extend(this.callSuper('toObject'), {
56492        opaque: this.opaque,
56493        matrix: this.matrix
56494      });
56495    }
56496  });
56497
56498  /**
56499   * Returns filter instance from an object representation
56500   * @static
56501   * @param {Object} object Object to create an instance from
56502   * @return {fabric.Image.filters.Convolute} Instance of fabric.Image.filters.Convolute
56503   */
56504  fabric.Image.filters.Convolute.fromObject = function(object) {
56505      return new fabric.Image.filters.Convolute(object);
56506  };
56507
56508})(typeof exports !== 'undefined' ? exports : this);
56509
56510
56511(function(global) {
56512
56513  "use strict";
56514
56515  var fabric  = global.fabric || (global.fabric = { }),
56516      extend = fabric.util.object.extend;
56517
56518  /**
56519   * GradientTransparency filter class
56520   * @class fabric.Image.filters.GradientTransparency
56521   * @memberOf fabric.Image.filters
56522   * @extends fabric.Image.filters.BaseFilter
56523   */
56524  fabric.Image.filters.GradientTransparency = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.GradientTransparency.prototype */ {
56525
56526    /**
56527     * Filter type
56528     * @param {String} type
56529     * @default
56530     */
56531    type: 'GradientTransparency',
56532
56533    /**
56534     * Constructor
56535     * @memberOf fabric.Image.filters.GradientTransparency
56536     * @param {Object} [options] Options object
56537     * @param {Number} [options.threshold=100] Threshold value
56538     */
56539    initialize: function(options) {
56540      options = options || { };
56541      this.threshold = options.threshold || 100;
56542    },
56543
56544    /**
56545     * Applies filter to canvas element
56546     * @param {Object} canvasEl Canvas element to apply filter to
56547     */
56548    applyTo: function(canvasEl) {
56549      var context = canvasEl.getContext('2d'),
56550          imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),
56551          data = imageData.data,
56552          threshold = this.threshold,
56553          total = data.length;
56554
56555      for (var i = 0, len = data.length; i < len; i += 4) {
56556        data[i + 3] = threshold + 255 * (total - i) / total;
56557      }
56558
56559      context.putImageData(imageData, 0, 0);
56560    },
56561
56562    /**
56563     * Returns object representation of an instance
56564     * @return {Object} Object representation of an instance
56565     */
56566    toObject: function() {
56567      return extend(this.callSuper('toObject'), {
56568        threshold: this.threshold
56569      });
56570    }
56571  });
56572
56573  /**
56574   * Returns filter instance from an object representation
56575   * @static
56576   * @param {Object} object Object to create an instance from
56577   * @return {fabric.Image.filters.GradientTransparency} Instance of fabric.Image.filters.GradientTransparency
56578   */
56579  fabric.Image.filters.GradientTransparency.fromObject = function(object) {
56580    return new fabric.Image.filters.GradientTransparency(object);
56581  };
56582
56583})(typeof exports !== 'undefined' ? exports : this);
56584
56585
56586(function(global) {
56587
56588  "use strict";
56589
56590  var fabric  = global.fabric || (global.fabric = { });
56591
56592  /**
56593   * Grayscale image filter class
56594   * @class fabric.Image.filters.Grayscale
56595   * @memberOf fabric.Image.filters
56596   * @extends fabric.Image.filters.BaseFilter
56597   */
56598  fabric.Image.filters.Grayscale = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Grayscale.prototype */ {
56599
56600    /**
56601     * Filter type
56602     * @param {String} type
56603     * @default
56604     */
56605    type: 'Grayscale',
56606
56607    /**
56608     * Applies filter to canvas element
56609     * @memberOf fabric.Image.filters.Grayscale.prototype
56610     * @param {Object} canvasEl Canvas element to apply filter to
56611     */
56612    applyTo: function(canvasEl) {
56613      var context = canvasEl.getContext('2d'),
56614          imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),
56615          data = imageData.data,
56616          len = imageData.width * imageData.height * 4,
56617          index = 0,
56618          average;
56619
56620      while (index < len) {
56621        average = (data[index] + data[index + 1] + data[index + 2]) / 3;
56622        data[index]     = average;
56623        data[index + 1] = average;
56624        data[index + 2] = average;
56625        index += 4;
56626      }
56627
56628      context.putImageData(imageData, 0, 0);
56629    }
56630  });
56631
56632  /**
56633   * Returns filter instance from an object representation
56634   * @static
56635   * @return {fabric.Image.filters.Grayscale} Instance of fabric.Image.filters.Grayscale
56636   */
56637  fabric.Image.filters.Grayscale.fromObject = function() {
56638    return new fabric.Image.filters.Grayscale();
56639  };
56640
56641})(typeof exports !== 'undefined' ? exports : this);
56642
56643
56644(function(global) {
56645
56646  "use strict";
56647
56648  var fabric  = global.fabric || (global.fabric = { });
56649
56650  /**
56651   * Invert filter class
56652   * @class fabric.Image.filters.Invert
56653   * @memberOf fabric.Image.filters
56654   * @extends fabric.Image.filters.BaseFilter
56655   */
56656  fabric.Image.filters.Invert = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Invert.prototype */ {
56657
56658    /**
56659     * Filter type
56660     * @param {String} type
56661     * @default
56662     */
56663    type: 'Invert',
56664
56665    /**
56666     * Applies filter to canvas element
56667     * @memberOf fabric.Image.filters.Invert.prototype
56668     * @param {Object} canvasEl Canvas element to apply filter to
56669     */
56670    applyTo: function(canvasEl) {
56671      var context = canvasEl.getContext('2d'),
56672          imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),
56673          data = imageData.data,
56674          iLen = data.length, i;
56675
56676      for (i = 0; i < iLen; i+=4) {
56677        data[i] = 255 - data[i];
56678        data[i + 1] = 255 - data[i + 1];
56679        data[i + 2] = 255 - data[i + 2];
56680      }
56681
56682      context.putImageData(imageData, 0, 0);
56683    }
56684  });
56685
56686  /**
56687   * Returns filter instance from an object representation
56688   * @static
56689   * @return {fabric.Image.filters.Invert} Instance of fabric.Image.filters.Invert
56690   */
56691  fabric.Image.filters.Invert.fromObject = function() {
56692    return new fabric.Image.filters.Invert();
56693  };
56694
56695})(typeof exports !== 'undefined' ? exports : this);
56696
56697
56698(function(global) {
56699
56700  "use strict";
56701
56702  var fabric  = global.fabric || (global.fabric = { }),
56703      extend = fabric.util.object.extend;
56704
56705  /**
56706   * Mask filter class
56707   * See http://resources.aleph-1.com/mask/
56708   * @class fabric.Image.filters.Mask
56709   * @memberOf fabric.Image.filters
56710   * @extends fabric.Image.filters.BaseFilter
56711   */
56712  fabric.Image.filters.Mask = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Mask.prototype */ {
56713
56714    /**
56715     * Filter type
56716     * @param {String} type
56717     * @default
56718     */
56719    type: 'Mask',
56720
56721    /**
56722     * Constructor
56723     * @memberOf fabric.Image.filters.Mask.prototype
56724     * @param {Object} [options] Options object
56725     * @param {fabric.Image} [options.mask] Mask image object
56726     * @param {Number} [options.channel=0] Rgb channel (0, 1, 2 or 3)
56727     */
56728    initialize: function(options) {
56729      options = options || { };
56730
56731      this.mask = options.mask;
56732      this.channel = [ 0, 1, 2, 3 ].indexOf(options.channel) > -1 ? options.channel : 0;
56733    },
56734
56735    /**
56736     * Applies filter to canvas element
56737     * @param {Object} canvasEl Canvas element to apply filter to
56738     */
56739    applyTo: function(canvasEl) {
56740      if (!this.mask) return;
56741
56742      var context = canvasEl.getContext('2d'),
56743          imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),
56744          data = imageData.data,
56745          maskEl = this.mask.getElement(),
56746          maskCanvasEl = fabric.util.createCanvasElement(),
56747          channel = this.channel,
56748          i,
56749          iLen = imageData.width * imageData.height * 4;
56750
56751      maskCanvasEl.width = maskEl.width;
56752      maskCanvasEl.height = maskEl.height;
56753
56754      maskCanvasEl.getContext('2d').drawImage(maskEl, 0, 0, maskEl.width, maskEl.height);
56755
56756      var maskImageData = maskCanvasEl.getContext('2d').getImageData(0, 0, maskEl.width, maskEl.height),
56757          maskData = maskImageData.data;
56758
56759      for (i = 0; i < iLen; i += 4) {
56760        data[i + 3] = maskData[i + channel];
56761      }
56762
56763      context.putImageData(imageData, 0, 0);
56764    },
56765
56766    /**
56767     * Returns object representation of an instance
56768     * @return {Object} Object representation of an instance
56769     */
56770    toObject: function() {
56771      return extend(this.callSuper('toObject'), {
56772        mask: this.mask.toObject(),
56773        channel: this.channel
56774      });
56775    }
56776  });
56777
56778  /**
56779   * Returns filter instance from an object representation
56780   * @static
56781   * @param {Object} object Object to create an instance from
56782   * @param {Function} [callback] Callback to invoke when a mask filter instance is created
56783   */
56784  fabric.Image.filters.Mask.fromObject = function(object, callback) {
56785    var img = fabric.document.createElement('img'),
56786        src = object.mask.src;
56787
56788    /** @ignore */
56789    img.onload = function() {
56790      object.mask = new fabric.Image(img, object.mask);
56791
56792      callback && callback(new fabric.Image.filters.Mask(object));
56793      img = img.onload = img.onerror = null;
56794    };
56795
56796    /** @ignore */
56797    img.onerror = function() {
56798      fabric.log('Error loading ' + img.src);
56799      callback && callback(null, true);
56800      img = img.onload = img.onerror = null;
56801    };
56802
56803    img.src = src;
56804  };
56805
56806  /**
56807   * Indicates that instances of this type are async
56808   * @static
56809   * @type Boolean
56810   * @default
56811   */
56812  fabric.Image.filters.Mask.async = true;
56813
56814})(typeof exports !== 'undefined' ? exports : this);
56815
56816
56817(function(global) {
56818
56819  "use strict";
56820
56821  var fabric  = global.fabric || (global.fabric = { }),
56822      extend = fabric.util.object.extend;
56823
56824  /**
56825   * Noise filter class
56826   * @class fabric.Image.filters.Noise
56827   * @memberOf fabric.Image.filters
56828   * @extends fabric.Image.filters.BaseFilter
56829   */
56830  fabric.Image.filters.Noise = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Noise.prototype */ {
56831
56832    /**
56833     * Filter type
56834     * @param {String} type
56835     * @default
56836     */
56837    type: 'Noise',
56838
56839    /**
56840     * Constructor
56841     * @memberOf fabric.Image.filters.Noise.prototype
56842     * @param {Object} [options] Options object
56843     * @param {Number} [options.noise=100] Noise value
56844     */
56845    initialize: function(options) {
56846      options = options || { };
56847      this.noise = options.noise || 100;
56848    },
56849
56850    /**
56851     * Applies filter to canvas element
56852     * @param {Object} canvasEl Canvas element to apply filter to
56853     */
56854    applyTo: function(canvasEl) {
56855      var context = canvasEl.getContext('2d'),
56856          imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),
56857          data = imageData.data,
56858          noise = this.noise, rand;
56859
56860      for (var i = 0, len = data.length; i < len; i += 4) {
56861
56862        rand = (0.5 - Math.random()) * noise;
56863
56864        data[i] += rand;
56865        data[i + 1] += rand;
56866        data[i + 2] += rand;
56867      }
56868
56869      context.putImageData(imageData, 0, 0);
56870    },
56871
56872    /**
56873     * Returns object representation of an instance
56874     * @return {Object} Object representation of an instance
56875     */
56876    toObject: function() {
56877      return extend(this.callSuper('toObject'), {
56878        noise: this.noise
56879      });
56880    }
56881  });
56882
56883  /**
56884   * Returns filter instance from an object representation
56885   * @static
56886   * @param {Object} object Object to create an instance from
56887   * @return {fabric.Image.filters.Noise} Instance of fabric.Image.filters.Noise
56888   */
56889  fabric.Image.filters.Noise.fromObject = function(object) {
56890    return new fabric.Image.filters.Noise(object);
56891  };
56892
56893})(typeof exports !== 'undefined' ? exports : this);
56894
56895
56896(function(global) {
56897
56898  "use strict";
56899
56900  var fabric  = global.fabric || (global.fabric = { }),
56901      extend = fabric.util.object.extend;
56902
56903  /**
56904   * Pixelate filter class
56905   * @class fabric.Image.filters.Pixelate
56906   * @memberOf fabric.Image.filters
56907   * @extends fabric.Image.filters.BaseFilter
56908   */
56909  fabric.Image.filters.Pixelate = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Pixelate.prototype */ {
56910
56911    /**
56912     * Filter type
56913     * @param {String} type
56914     * @default
56915     */
56916    type: 'Pixelate',
56917
56918    /**
56919     * Constructor
56920     * @memberOf fabric.Image.filters.Pixelate.prototype
56921     * @param {Object} [options] Options object
56922     * @param {Number} [options.blocksize=4] Blocksize for pixelate
56923     */
56924    initialize: function(options) {
56925      options = options || { };
56926      this.blocksize = options.blocksize || 4;
56927    },
56928
56929    /**
56930     * Applies filter to canvas element
56931     * @param {Object} canvasEl Canvas element to apply filter to
56932     */
56933    applyTo: function(canvasEl) {
56934      var context = canvasEl.getContext('2d'),
56935          imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),
56936          data = imageData.data,
56937          iLen = imageData.height,
56938          jLen = imageData.width,
56939          index, i, j, r, g, b, a;
56940
56941      for (i = 0; i < iLen; i += this.blocksize) {
56942        for (j = 0; j < jLen; j += this.blocksize) {
56943
56944          index = (i * 4) * jLen + (j * 4);
56945
56946          r = data[index];
56947          g = data[index+1];
56948          b = data[index+2];
56949          a = data[index+3];
56950
56951          /*
56952           blocksize: 4
56953
56954           [1,x,x,x,1]
56955           [x,x,x,x,1]
56956           [x,x,x,x,1]
56957           [x,x,x,x,1]
56958           [1,1,1,1,1]
56959           */
56960
56961          for (var _i = i, _ilen = i + this.blocksize; _i < _ilen; _i++) {
56962            for (var _j = j, _jlen = j + this.blocksize; _j < _jlen; _j++) {
56963              index = (_i * 4) * jLen + (_j * 4);
56964              data[index] = r;
56965              data[index + 1] = g;
56966              data[index + 2] = b;
56967              data[index + 3] = a;
56968            }
56969          }
56970        }
56971      }
56972
56973      context.putImageData(imageData, 0, 0);
56974    },
56975
56976    /**
56977     * Returns object representation of an instance
56978     * @return {Object} Object representation of an instance
56979     */
56980    toObject: function() {
56981      return extend(this.callSuper('toObject'), {
56982        blocksize: this.blocksize
56983      });
56984    }
56985  });
56986
56987  /**
56988   * Returns filter instance from an object representation
56989   * @static
56990   * @param {Object} object Object to create an instance from
56991   * @return {fabric.Image.filters.Pixelate} Instance of fabric.Image.filters.Pixelate
56992   */
56993  fabric.Image.filters.Pixelate.fromObject = function(object) {
56994    return new fabric.Image.filters.Pixelate(object);
56995  };
56996
56997})(typeof exports !== 'undefined' ? exports : this);
56998
56999
57000(function(global) {
57001
57002  "use strict";
57003
57004  var fabric  = global.fabric || (global.fabric = { }),
57005      extend = fabric.util.object.extend;
57006
57007  /**
57008   * Remove white filter class
57009   * @class fabric.Image.filters.RemoveWhite
57010   * @memberOf fabric.Image.filters
57011   * @extends fabric.Image.filters.BaseFilter
57012   */
57013  fabric.Image.filters.RemoveWhite = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.RemoveWhite.prototype */ {
57014
57015    /**
57016     * Filter type
57017     * @param {String} type
57018     * @default
57019     */
57020    type: 'RemoveWhite',
57021
57022    /**
57023     * Constructor
57024     * @memberOf fabric.Image.filters.RemoveWhite.prototype
57025     * @param {Object} [options] Options object
57026     * @param {Number} [options.threshold=30] Threshold value
57027     * @param {Number} [options.distance=20] Distance value
57028     */
57029    initialize: function(options) {
57030      options = options || { };
57031      this.threshold = options.threshold || 30;
57032      this.distance = options.distance || 20;
57033    },
57034
57035    /**
57036     * Applies filter to canvas element
57037     * @param {Object} canvasEl Canvas element to apply filter to
57038     */
57039    applyTo: function(canvasEl) {
57040      var context = canvasEl.getContext('2d'),
57041          imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),
57042          data = imageData.data,
57043          threshold = this.threshold,
57044          distance = this.distance,
57045          limit = 255 - threshold,
57046          abs = Math.abs,
57047          r, g, b;
57048
57049      for (var i = 0, len = data.length; i < len; i += 4) {
57050        r = data[i];
57051        g = data[i+1];
57052        b = data[i+2];
57053
57054        if (r > limit &&
57055            g > limit &&
57056            b > limit &&
57057            abs(r-g) < distance &&
57058            abs(r-b) < distance &&
57059            abs(g-b) < distance
57060        ) {
57061          data[i+3] = 1;
57062        }
57063      }
57064
57065      context.putImageData(imageData, 0, 0);
57066    },
57067
57068    /**
57069     * Returns object representation of an instance
57070     * @return {Object} Object representation of an instance
57071     */
57072    toObject: function() {
57073      return extend(this.callSuper('toObject'), {
57074        threshold: this.threshold,
57075        distance: this.distance
57076      });
57077    }
57078  });
57079
57080  /**
57081   * Returns filter instance from an object representation
57082   * @static
57083   * @param {Object} object Object to create an instance from
57084   * @return {fabric.Image.filters.RemoveWhite} Instance of fabric.Image.filters.RemoveWhite
57085   */
57086  fabric.Image.filters.RemoveWhite.fromObject = function(object) {
57087    return new fabric.Image.filters.RemoveWhite(object);
57088  };
57089
57090})(typeof exports !== 'undefined' ? exports : this);
57091
57092
57093(function(global) {
57094
57095  "use strict";
57096
57097  var fabric  = global.fabric || (global.fabric = { });
57098
57099  /**
57100   * Sepia filter class
57101   * @class fabric.Image.filters.Sepia
57102   * @memberOf fabric.Image.filters
57103   * @extends fabric.Image.filters.BaseFil
57103ter
57104   */
57105  fabric.Image.filters.Sepia = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Sepia.prototype */ {
57106
57107    /**
57108     * Filter type
57109     * @param {String} type
57110     * @default
57111     */
57112    type: 'Sepia',
57113
57114    /**
57115     * Applies filter to canvas element
57116     * @memberOf fabric.Image.filters.Sepia.prototype
57117     * @param {Object} canvasEl Canvas element to apply filter to
57118     */
57119    applyTo: function(canvasEl) {
57120      var context = canvasEl.getContext('2d'),
57121          imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),
57122          data = imageData.data,
57123          iLen = data.length, i, avg;
57124
57125      for (i = 0; i < iLen; i+=4) {
57126        avg = 0.3  * data[i] + 0.59 * data[i + 1] + 0.11 * data[i + 2];
57127        data[i] = avg + 100;
57128        data[i + 1] = avg + 50;
57129        data[i + 2] = avg + 255;
57130      }
57131
57132      context.putImageData(imageData, 0, 0);
57133    }
57134  });
57135
57136  /**
57137   * Returns filter instance from an object representation
57138   * @static
57139   * @return {fabric.Image.filters.Sepia} Instance of fabric.Image.filters.Sepia
57140   */
57141  fabric.Image.filters.Sepia.fromObject = function() {
57142    return new fabric.Image.filters.Sepia();
57143  };
57144
57145})(typeof exports !== 'undefined' ? exports : this);
57146
57147
57148(function(global) {
57149
57150  "use strict";
57151
57152  var fabric  = global.fabric || (global.fabric = { });
57153
57154  /**
57155   * Sepia2 filter class
57156   * @class fabric.Image.filters.Sepia2
57157   * @memberOf fabric.Image.filters
57158   * @extends fabric.Image.filters.BaseFilter
57159   */
57160  fabric.Image.filters.Sepia2 = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Sepia2.prototype */ {
57161
57162    /**
57163     * Filter type
57164     * @param {String} type
57165     * @default
57166     */
57167    type: 'Sepia2',
57168
57169    /**
57170     * Applies filter to canvas element
57171     * @memberOf fabric.Image.filters.Sepia.prototype
57172     * @param {Object} canvasEl Canvas element to apply filter to
57173     */
57174    applyTo: function(canvasEl) {
57175      var context = canvasEl.getContext('2d'),
57176          imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),
57177          data = imageData.data,
57178          iLen = data.length, i, r, g, b;
57179
57180      for (i = 0; i < iLen; i+=4) {
57181        r = data[i];
57182        g = data[i + 1];
57183        b = data[i + 2];
57184
57185        data[i] = (r * 0.393 + g * 0.769 + b * 0.189 ) / 1.351;
57186        data[i + 1] = (r * 0.349 + g * 0.686 + b * 0.168 ) / 1.203;
57187        data[i + 2] = (r * 0.272 + g * 0.534 + b * 0.131 ) / 2.140;
57188      }
57189
57190      context.putImageData(imageData, 0, 0);
57191    }
57192  });
57193
57194  /**
57195   * Returns filter instance from an object representation
57196   * @static
57197   * @return {fabric.Image.filters.Sepia2} Instance of fabric.Image.filters.Sepia2
57198   */
57199  fabric.Image.filters.Sepia2.fromObject = function() {
57200    return new fabric.Image.filters.Sepia2();
57201  };
57202
57203})(typeof exports !== 'undefined' ? exports : this);
57204
57205
57206(function(global) {
57207
57208  "use strict";
57209
57210  var fabric  = global.fabric || (global.fabric = { }),
57211      extend = fabric.util.object.extend;
57212
57213  /**
57214   * Tint filter class
57215   * Adapted from <a href="https://github.com/mezzoblue/PaintbrushJS">https://github.com/mezzoblue/PaintbrushJS</a>
57216   * @class fabric.Image.filters.Tint
57217   * @memberOf fabric.Image.filters
57218   * @extends fabric.Image.filters.BaseFilter
57219   */
57220  fabric.Image.filters.Tint = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Tint.prototype */ {
57221
57222    /**
57223     * Filter type
57224     * @param {String} type
57225     * @default
57226     */
57227    type: 'Tint',
57228
57229    /**
57230     * Constructor
57231     * @memberOf fabric.Image.filters.Tint.prototype
57232     * @param {Object} [options] Options object
57233     * @param {String} [options.color=#000000] Color to tint the image with
57234     * @param {Number} [options.opacity] Opacity value that controls the tint effect's transparency (0..1)
57235     */
57236    initialize: function(options) {
57237      options = options || { };
57238
57239      this.color = options.color || '#000000';
57240      this.opacity = typeof options.opacity !== 'undefined'
57241                      ? options.opacity
57242                      : new fabric.Color(this.color).getAlpha();
57243    },
57244
57245    /**
57246     * Applies filter to canvas element
57247     * @param {Object} canvasEl Canvas element to apply filter to
57248     */
57249    applyTo: function(canvasEl) {
57250      var context = canvasEl.getContext('2d'),
57251          imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),
57252          data = imageData.data,
57253          iLen = data.length, i,
57254          tintR, tintG, tintB,
57255          r, g, b, alpha1,
57256          source;
57257
57258      source = new fabric.Color(this.color).getSource();
57259
57260      tintR = source[0] * this.opacity;
57261      tintG = source[1] * this.opacity;
57262      tintB = source[2] * this.opacity;
57263
57264      alpha1 = 1 - this.opacity;
57265
57266      for (i = 0; i < iLen; i+=4) {
57267        r = data[i];
57268        g = data[i + 1];
57269        b = data[i + 2];
57270
57271        // alpha compositing
57272        data[i] = tintR + r * alpha1;
57273        data[i + 1] = tintG + g * alpha1;
57274        data[i + 2] = tintB + b * alpha1;
57275      }
57276
57277      context.putImageData(imageData, 0, 0);
57278    },
57279
57280    /**
57281     * Returns object representation of an instance
57282     * @return {Object} Object representation of an instance
57283     */
57284    toObject: function() {
57285      return extend(this.callSuper('toObject'), {
57286        color: this.color,
57287        opacity: this.opacity
57288      });
57289    }
57290  });
57291
57292  /**
57293   * Returns filter instance from an object representation
57294   * @static
57295   * @param {Object} object Object to create an instance from
57296   * @return {fabric.Image.filters.Tint} Instance of fabric.Image.filters.Tint
57297   */
57298  fabric.Image.filters.Tint.fromObject = function(object) {
57299    return new fabric.Image.filters.Tint(object);
57300  };
57301
57302})(typeof exports !== 'undefined' ? exports : this);
57303
57304
57305(function(global) {
57306
57307  "use strict";
57308
57309  var fabric = global.fabric || (global.fabric = { }),
57310      extend = fabric.util.object.extend,
57311      clone = fabric.util.object.clone,
57312      toFixed = fabric.util.toFixed,
57313      supportsLineDash = fabric.StaticCanvas.supports('setLineDash');
57314
57315  if (fabric.Text) {
57316    fabric.warn('fabric.Text is already defined');
57317    return;
57318  }
57319
57320  var stateProperties = fabric.Object.prototype.stateProperties.concat();
57321  stateProperties.push(
57322    'fontFamily',
57323    'fontWeight',
57324    'fontSize',
57325    'text',
57326    'textDecoration',
57327    'textAlign',
57328    'fontStyle',
57329    'lineHeight',
57330    'textBackgroundColor',
57331    'useNative',
57332    'path'
57333  );
57334
57335  /**
57336   * Text class
57337   * @class fabric.Text
57338   * @extends fabric.Object
57339   * @return {fabric.Text} thisArg
57340   * @tutorial {@link http://fabricjs.com/fabric-intro-part-2/#text}
57341   */
57342  fabric.Text = fabric.util.createClass(fabric.Object, /** @lends fabric.Text.prototype */ {
57343
57344    /**
57345     * Properties which when set cause object to change dimensions
57346     * @type Object
57347     * @private
57348     */
57349    _dimensionAffectingProps: {
57350      fontSize: true,
57351      fontWeight: true,
57352      fontFamily: true,
57353      textDecoration: true,
57354      fontStyle: true,
57355      lineHeight: true,
57356      stroke: true,
57357      strokeWidth: true,
57358      text: true
57359    },
57360
57361    /**
57362     * Retrieves object's fontSize
57363     * @method getFontSize
57364     * @memberOf fabric.Text.prototype
57365     * @return {String} Font size (in pixels)
57366     */
57367
57368    /**
57369     * Sets object's fontSize
57370     * @method setFontSize
57371     * @memberOf fabric.Text.prototype
57372     * @param {Number} fontSize Font size (in pixels)
57373     * @return {fabric.Text}
57374     * @chainable
57375     */
57376
57377    /**
57378     * Retrieves object's fontWeight
57379     * @method getFontWeight
57380     * @memberOf fabric.Text.prototype
57381     * @return {(String|Number)} Font weight
57382     */
57383
57384    /**
57385     * Sets object's fontWeight
57386     * @method setFontWeight
57387     * @memberOf fabric.Text.prototype
57388     * @param {(Number|String)} fontWeight Font weight
57389     * @return {fabric.Text}
57390     * @chainable
57391     */
57392
57393    /**
57394     * Retrieves object's fontFamily
57395     * @method getFontFamily
57396     * @memberOf fabric.Text.prototype
57397     * @return {String} Font family
57398     */
57399
57400    /**
57401     * Sets object's fontFamily
57402     * @method setFontFamily
57403     * @memberOf fabric.Text.prototype
57404     * @param {String} fontFamily Font family
57405     * @return {fabric.Text}
57406     * @chainable
57407     */
57408
57409    /**
57410     * Retrieves object's text
57411     * @method getText
57412     * @memberOf fabric.Text.prototype
57413     * @return {String} text
57414     */
57415
57416    /**
57417     * Sets object's text
57418     * @method setText
57419     * @memberOf fabric.Text.prototype
57420     * @param {String} text Text
57421     * @return {fabric.Text}
57422     * @chainable
57423     */
57424
57425    /**
57426     * Retrieves object's textDecoration
57427     * @method getTextDecoration
57428     * @memberOf fabric.Text.prototype
57429     * @return {String} Text decoration
57430     */
57431
57432    /**
57433     * Sets object's textDecoration
57434     * @method setTextDecoration
57435     * @memberOf fabric.Text.prototype
57436     * @param {String} textDecoration Text decoration
57437     * @return {fabric.Text}
57438     * @chainable
57439     */
57440
57441    /**
57442     * Retrieves object's fontStyle
57443     * @method getFontStyle
57444     * @memberOf fabric.Text.prototype
57445     * @return {String} Font style
57446     */
57447
57448    /**
57449     * Sets object's fontStyle
57450     * @method setFontStyle
57451     * @memberOf fabric.Text.prototype
57452     * @param {String} fontStyle Font style
57453     * @return {fabric.Text}
57454     * @chainable
57455     */
57456
57457    /**
57458     * Retrieves object's lineHeight
57459     * @method getLineHeight
57460     * @memberOf fabric.Text.prototype
57461     * @return {Number} Line height
57462     */
57463
57464    /**
57465     * Sets object's lineHeight
57466     * @method setLineHeight
57467     * @memberOf fabric.Text.prototype
57468     * @param {Number} lineHeight Line height
57469     * @return {fabric.Text}
57470     * @chainable
57471     */
57472
57473    /**
57474     * Retrieves object's textAlign
57475     * @method getTextAlign
57476     * @memberOf fabric.Text.prototype
57477     * @return {String} Text alignment
57478     */
57479
57480    /**
57481     * Sets object's textAlign
57482     * @method setTextAlign
57483     * @memberOf fabric.Text.prototype
57484     * @param {String} textAlign Text alignment
57485     * @return {fabric.Text}
57486     * @chainable
57487     */
57488
57489    /**
57490     * Retrieves object's textBackgroundColor
57491     * @method getTextBackgroundColor
57492     * @memberOf fabric.Text.prototype
57493     * @return {String} Text background color
57494     */
57495
57496    /**
57497     * Sets object's textBackgroundColor
57498     * @method setTextBackgroundColor
57499     * @memberOf fabric.Text.prototype
57500     * @param {String} textBackgroundColor Text background color
57501     * @return {fabric.Text}
57502     * @chainable
57503     */
57504
57505    /**
57506     * Type of an object
57507     * @type String
57508     * @default
57509     */
57510    type:                 'text',
57511
57512    /**
57513     * Font size (in pixels)
57514     * @type Number
57515     * @default
57516     */
57517    fontSize:             40,
57518
57519    /**
57520     * Font weight (e.g. bold, normal, 400, 600, 800)
57521     * @type {(Number|String)}
57522     * @default
57523     */
57524    fontWeight:           'normal',
57525
57526    /**
57527     * Font family
57528     * @type String
57529     * @default
57530     */
57531    fontFamily:           'Times New Roman',
57532
57533    /**
57534     * Text decoration Possible values: "", "underline", "overline" or "line-through".
57535     * @type String
57536     * @default
57537     */
57538    textDecoration:       '',
57539
57540    /**
57541     * Text alignment. Possible values: "left", "center", or "right".
57542     * @type String
57543     * @default
57544     */
57545    textAlign:            'left',
57546
57547    /**
57548     * Font style . Possible values: "", "normal", "italic" or "oblique".
57549     * @type String
57550     * @default
57551     */
57552    fontStyle:            '',
57553
57554    /**
57555     * Line height
57556     * @type Number
57557     * @default
57558     */
57559    lineHeight:           1.3,
57560
57561    /**
57562     * Background color of text lines
57563     * @type String
57564     * @default
57565     */
57566    textBackgroundColor:  '',
57567
57568    /**
57569     * URL of a font file, when using Cufon
57570     * @type String | null
57571     * @default
57572     */
57573    path:                 null,
57574
57575    /**
57576     * Indicates whether canvas native text methods should be used to render text (otherwise, Cufon is used)
57577     * @type Boolean
57578     * @default
57579     */
57580    useNative:            true,
57581
57582    /**
57583     * List of properties to consider when checking if state of an object is changed ({@link fabric.Object#hasStateChanged})
57584     * as well as for history (undo/redo) purposes
57585     * @type Array
57586     */
57587    stateProperties:      stateProperties,
57588
57589    /**
57590     * When defined, an object is rendered via stroke and this property specifies its color.
57591     * <b>Backwards incompatibility note:</b> This property was named "strokeStyle" until v1.1.6
57592     * @type String
57593     * @default
57594     */
57595    stroke:               null,
57596
57597    /**
57598     * Shadow object representing shadow of this shape.
57599     * <b>Backwards incompatibility note:</b> This property was named "textShadow" (String) until v1.2.11
57600     * @type fabric.Shadow
57601     * @default
57602     */
57603    shadow:               null,
57604
57605    /**
57606     * Constructor
57607     * @param {String} text Text string
57608     * @param {Object} [options] Options object
57609     * @return {fabric.Text} thisArg
57610     */
57611    initialize: function(text, options) {
57612      options = options || { };
57613
57614      this.text = text;
57615      this.__skipDimension = true;
57616      this.setOptions(options);
57617      this.__skipDimension = false;
57618      this._initDimensions();
57619      this.setCoords();
57620    },
57621
57622    /**
57623     * Renders text object on offscreen canvas, so that it would get dimensions
57624     * @private
57625     */
57626    _initDimensions: function() {
57627      if (this.__skipDimension) return;
57628      var canvasEl = fabric.util.createCanvasElement();
57629      this._render(canvasEl.getContext('2d'));
57630    },
57631
57632    /**
57633     * Returns string representation of an instance
57634     * @return {String} String representation of text object
57635     */
57636    toString: function() {
57637      return '#<fabric.Text (' + this.complexity() +
57638        '): { "text": "' + this.text + '", "fontFamily": "' + this.fontFamily + '" }>';
57639    },
57640
57641    /**
57642     * @private
57643     * @param {CanvasRenderingContext2D} ctx Context to render on
57644     */
57645    _render: function(ctx) {
57646
57647      var isInPathGroup = this.group && this.group.type !== 'group';
57648      if (isInPathGroup && !this.transformMatrix) {
57649        ctx.translate(-this.group.width/2 + this.left, -this.group.height / 2 + this.top);
57650      }
57651      else if (isInPathGroup && this.transformMatrix) {
57652        ctx.translate(-this.group.width/2, -this.group.height/2);
57653      }
57654
57655      if (typeof Cufon === 'undefined' || this.useNative === true) {
57656        this._renderViaNative(ctx);
57657      }
57658      else {
57659        this._renderViaCufon(ctx);
57660      }
57661    },
57662
57663    /**
57664     * @private
57665     * @param {CanvasRenderingContext2D} ctx Context to render on
57666     */
57667    _renderViaNative: function(ctx) {
57668
57669      this.transform(ctx, fabric.isLikelyNode);
57670
57671      this._setTextStyles(ctx);
57672
57673      var textLines = this.text.split(/\r?\n/);
57674
57675      this.width = this._getTextWidth(ctx, textLines);
57676      this.height = this._getTextHeight(ctx, textLines);
57677
57678      this.clipTo && fabric.util.clipContext(this, ctx);
57679
57680      this._renderTextBackground(ctx, textLines);
57681
57682      if (this.textAlign !== 'left' && this.textAlign !== 'justify') {
57683        ctx.save();
57684        ctx.translate(this.textAlign === 'center' ? (this.width / 2) : this.width, 0);
57685      }
57686
57687      ctx.save();
57688      this._setShadow(ctx);
57689      this._renderTextFill(ctx, textLines);
57690      this._renderTextStroke(ctx, textLines);
57691      this._removeShadow(ctx);
57692      ctx.restore();
57693
57694      if (this.textAlign !== 'left' && this.textAlign !== 'justify') {
57695        ctx.restore();
57696      }
57697
57698      this._renderTextDecoration(ctx, textLines);
57699      this.clipTo && ctx.restore();
57700
57701      this._setBoundaries(ctx, textLines);
57702      this._totalLineHeight = 0;
57703    },
57704
57705    /**
57706     * @private
57707     * @param {CanvasRenderingContext2D} ctx Context to render on
57708     * @param {Array} textLines Array of all text lines
57709     */
57710    _setBoundaries: function(ctx, textLines) {
57711      this._boundaries = [ ];
57712
57713      for (var i = 0, len = textLines.length; i < len; i++) {
57714
57715        var lineWidth = this._getLineWidth(ctx, textLines[i]);
57716        var lineLeftOffset = this._getLineLeftOffset(lineWidth);
57717
57718        this._boundaries.push({
57719          height: this.fontSize * this.lineHeight,
57720          width: lineWidth,
57721          left: lineLeftOffset
57722        });
57723      }
57724    },
57725
57726    /**
57727     * @private
57728     * @param {CanvasRenderingContext2D} ctx Context to render on
57729     */
57730    _setTextStyles: function(ctx) {
57731      if (this.fill) {
57732        ctx.fillStyle = this.fill.toLive
57733            ? this.fill.toLive(ctx)
57734            : this.fill;
57735      }
57736      if (this.stroke) {
57737        ctx.lineWidth = this.strokeWidth;
57738        ctx.lineCap = this.strokeLineCap;
57739        ctx.lineJoin = this.strokeLineJoin;
57740        ctx.miterLimit = this.strokeMiterLimit;
57741        ctx.strokeStyle = this.stroke.toLive
57742          ? this.stroke.toLive(ctx)
57743          : this.stroke;
57744      }
57745      ctx.textBaseline = 'alphabetic';
57746      ctx.textAlign = this.textAlign;
57747      ctx.font = this._getFontDeclaration();
57748    },
57749
57750    /**
57751     * @private
57752     * @param {CanvasRenderingContext2D} ctx Context to render on
57753     * @param {Array} textLines Array of all text lines
57754     * @return {Number} Height of fabric.Text object
57755     */
57756    _getTextHeight: function(ctx, textLines) {
57757      return this.fontSize * textLines.length * this.lineHeight;
57758    },
57759
57760    /**
57761     * @private
57762     * @param {CanvasRenderingContext2D} ctx Context to render on
57763     * @param {Array} textLines Array of all text lines
57764     * @return {Number} Maximum width of fabric.Text object
57765     */
57766    _getTextWidth: function(ctx, textLines) {
57767      var maxWidth = ctx.measureText(textLines[0]).width;
57768
57769      for (var i = 1, len = textLines.length; i < len; i++) {
57770        var currentLineWidth = ctx.measureText(textLines[i]).width;
57771        if (currentLineWidth > maxWidth) {
57772          maxWidth = currentLineWidth;
57773        }
57774      }
57775      return maxWidth;
57776    },
57777
57778    /**
57779     * @private
57780     * @param {String} method Method name ("fillText" or "strokeText")
57781     * @param {CanvasRenderingContext2D} ctx Context to render on
57782     * @param {String} line Chars to render
57783     * @param {Number} left Left position of text
57784     * @param {Number} top Top position of text
57785     */
57786    _drawChars: function(method, ctx, chars, left, top) {
57787      ctx[method](chars, left, top);
57788    },
57789
57790    /**
57791     * @private
57792     * @param {String} method Method name ("fillText" or "strokeText")
57793     * @param {CanvasRenderingContext2D} ctx Context to render on
57794     * @param {String} line Text to render
57795     * @param {Number} left Left position of text
57796     * @param {Number} top Top position of text
57797     * @param {Number} lineIndex Index of a line in a text
57798     */
57799    _drawTextLine: function(method, ctx, line, left, top, lineIndex) {
57800      // lift the line by quarter of fontSize
57801      top -= this.fontSize / 4;
57802
57803      // short-circuit
57804      if (this.textAlign !== 'justify') {
57805        this._drawChars(method, ctx, line, left, top, lineIndex);
57806        return;
57807      }
57808
57809      var lineWidth = ctx.measureText(line).width;
57810      var totalWidth = this.width;
57811
57812      if (totalWidth > lineWidth) {
57813        // stretch the line
57814        var words = line.split(/\s+/);
57815        var wordsWidth = ctx.measureText(line.replace(/\s+/g, '')).width;
57816        var widthDiff = totalWidth - wordsWidth;
57817        var numSpaces = words.length - 1;
57818        var spaceWidth = widthDiff / numSpaces;
57819
57820        var leftOffset = 0;
57821        for (var i = 0, len = words.length; i < len; i++) {
57822          this._drawChars(method, ctx, words[i], left + leftOffset, top, lineIndex);
57823          leftOffset += ctx.measureText(words[i]).width + spaceWi
57823dth;
57824        }
57825      }
57826      else {
57827        this._drawChars(method, ctx, line, left, top, lineIndex);
57828      }
57829    },
57830
57831    /**
57832     * @private
57833     * @return {Number} Left offset
57834     */
57835    _getLeftOffset: function() {
57836      if (fabric.isLikelyNode) {
57837        return 0;
57838      }
57839      return -this.width / 2;
57840    },
57841
57842    /**
57843     * @private
57844     * @return {Number} Top offset
57845     */
57846    _getTopOffset: function() {
57847      return -this.height / 2;
57848    },
57849
57850    /**
57851     * @private
57852     * @param {CanvasRenderingContext2D} ctx Context to render on
57853     * @param {Array} textLines Array of all text lines
57854     */
57855    _renderTextFill: function(ctx, textLines) {
57856      if (!this.fill && !this.skipFillStrokeCheck) return;
57857
57858      this._boundaries = [ ];
57859      var lineHeights = 0;
57860
57861      for (var i = 0, len = textLines.length; i < len; i++) {
57862        var heightOfLine = this._getHeightOfLine(ctx, i, textLines);
57863        lineHeights += heightOfLine;
57864
57865        this._drawTextLine(
57866          'fillText',
57867          ctx,
57868          textLines[i],
57869          this._getLeftOffset(),
57870          this._getTopOffset() + lineHeights,
57871          i
57872        );
57873      }
57874    },
57875
57876    /**
57877     * @private
57878     * @param {CanvasRenderingContext2D} ctx Context to render on
57879     * @param {Array} textLines Array of all text lines
57880     */
57881    _renderTextStroke: function(ctx, textLines) {
57882      if (!this.stroke && !this.skipFillStrokeCheck) return;
57883
57884      var lineHeights = 0;
57885
57886      ctx.save();
57887      if (this.strokeDashArray) {
57888        // Spec requires the concatenation of two copies the dash list when the number of elements is odd
57889        if (1 & this.strokeDashArray.length) {
57890          this.strokeDashArray.push.apply(this.strokeDashArray, this.strokeDashArray);
57891        }
57892        supportsLineDash && ctx.setLineDash(this.strokeDashArray);
57893      }
57894
57895      ctx.beginPath();
57896      for (var i = 0, len = textLines.length; i < len; i++) {
57897        var heightOfLine = this._getHeightOfLine(ctx, i, textLines);
57898        lineHeights += heightOfLine;
57899
57900        this._drawTextLine(
57901          'strokeText',
57902          ctx,
57903          textLines[i],
57904          this._getLeftOffset(),
57905          this._getTopOffset() + lineHeights,
57906          i
57907        );
57908      }
57909      ctx.closePath();
57910      ctx.restore();
57911    },
57912
57913    _getHeightOfLine: function() {
57914      return this.fontSize * this.lineHeight;
57915    },
57916
57917    /**
57918     * @private
57919     * @param {CanvasRenderingContext2D} ctx Context to render on
57920     * @param {Array} textLines Array of all text lines
57921     */
57922    _renderTextBackground: function(ctx, textLines) {
57923      this._renderTextBoxBackground(ctx);
57924      this._renderTextLinesBackground(ctx, textLines);
57925    },
57926
57927    /**
57928     * @private
57929     * @param {CanvasRenderingContext2D} ctx Context to render on
57930     */
57931    _renderTextBoxBackground: function(ctx) {
57932      if (!this.backgroundColor) return;
57933
57934      ctx.save();
57935      ctx.fillStyle = this.backgroundColor;
57936
57937      ctx.fillRect(
57938        this._getLeftOffset(),
57939        this._getTopOffset(),
57940        this.width,
57941        this.height
57942      );
57943
57944      ctx.restore();
57945    },
57946
57947    /**
57948     * @private
57949     * @param {CanvasRenderingContext2D} ctx Context to render on
57950     * @param {Array} textLines Array of all text lines
57951     */
57952    _renderTextLinesBackground: function(ctx, textLines) {
57953      if (!this.textBackgroundColor) return;
57954
57955      ctx.save();
57956      ctx.fillStyle = this.textBackgroundColor;
57957
57958      for (var i = 0, len = textLines.length; i < len; i++) {
57959
57960        if (textLines[i] !== '') {
57961
57962          var lineWidth = this._getLineWidth(ctx, textLines[i]);
57963          var lineLeftOffset = this._getLineLeftOffset(lineWidth);
57964
57965          ctx.fillRect(
57966            this._getLeftOffset() + lineLeftOffset,
57967            this._getTopOffset() + (i * this.fontSize * this.lineHeight),
57968            lineWidth,
57969            this.fontSize * this.lineHeight
57970          );
57971        }
57972      }
57973      ctx.restore();
57974    },
57975
57976    /**
57977     * @private
57978     * @param {Number} lineWidth Width of text line
57979     * @return {Number} Line left offset
57980     */
57981    _getLineLeftOffset: function(lineWidth) {
57982      if (this.textAlign === 'center') {
57983        return (this.width - lineWidth) / 2;
57984      }
57985      if (this.textAlign === 'right') {
57986        return this.width - lineWidth;
57987      }
57988      return 0;
57989    },
57990
57991    /**
57992     * @private
57993     * @param {CanvasRenderingContext2D} ctx Context to render on
57994     * @param {String} line Text line
57995     * @return {Number} Line width
57996     */
57997    _getLineWidth: function(ctx, line) {
57998      return this.textAlign === 'justify'
57999        ? this.width
58000        : ctx.measureText(line).width;
58001    },
58002
58003    /**
58004     * @private
58005     * @param {CanvasRenderingContext2D} ctx Context to render on
58006     * @param {Array} textLines Array of all text lines
58007     */
58008    _renderTextDecoration: function(ctx, textLines) {
58009      if (!this.textDecoration) return;
58010
58011      // var halfOfVerticalBox = this.originY === 'top' ? 0 : this._getTextHeight(ctx, textLines) / 2;
58012      var halfOfVerticalBox = this._getTextHeight(ctx, textLines) / 2;
58013      var _this = this;
58014
58015      /** @ignore */
58016      function renderLinesAtOffset(offset) {
58017        for (var i = 0, len = textLines.length; i < len; i++) {
58018
58019          var lineWidth = _this._getLineWidth(ctx, textLines[i]);
58020          var lineLeftOffset = _this._getLineLeftOffset(lineWidth);
58021
58022          ctx.fillRect(
58023            _this._getLeftOffset() + lineLeftOffset,
58024            ~~((offset + (i * _this._getHeightOfLine(ctx, i, textLines))) - halfOfVerticalBox),
58025            lineWidth,
58026            1);
58027        }
58028      }
58029
58030      if (this.textDecoration.indexOf('underline') > -1) {
58031        renderLinesAtOffset(this.fontSize * this.lineHeight);
58032      }
58033      if (this.textDecoration.indexOf('line-through') > -1) {
58034        renderLinesAtOffset(this.fontSize * this.lineHeight - this.fontSize / 2);
58035      }
58036      if (this.textDecoration.indexOf('overline') > -1) {
58037        renderLinesAtOffset(this.fontSize * this.lineHeight - this.fontSize);
58038      }
58039    },
58040
58041    /**
58042     * @private
58043     */
58044    _getFontDeclaration: function() {
58045      return [
58046        // node-canvas needs "weight style", while browsers need "style weight"
58047        (fabric.isLikelyNode ? this.fontWeight : this.fontStyle),
58048        (fabric.isLikelyNode ? this.fontStyle : this.fontWeight),
58049        this.fontSize + 'px',
58050        (fabric.isLikelyNode ? ('"' + this.fontFamily + '"') : this.fontFamily)
58051      ].join(' ');
58052    },
58053
58054    /**
58055     * Renders text instance on a specified context
58056     * @param {CanvasRenderingContext2D} ctx Context to render on
58057     * @param {Boolean} [noTransform] When true, context is not transformed
58058     */
58059    render: function(ctx, noTransform) {
58060      // do not render if object is not visible
58061      if (!this.visible) return;
58062
58063      ctx.save();
58064      this._render(ctx);
58065      if (!noTransform && this.active) {
58066        this.drawBorders(ctx);
58067        this.drawControls(ctx);
58068      }
58069      ctx.restore();
58070    },
58071
58072    /**
58073     * Returns object representation of an instance
58074     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output
58075     * @return {Object} Object representation of an instance
58076     */
58077    toObject: function(propertiesToInclude) {
58078      var object = extend(this.callSuper('toObject', propertiesToInclude), {
58079        text:                 this.text,
58080        fontSize:             this.fontSize,
58081        fontWeight:           this.fontWeight,
58082        fontFamily:           this.fontFamily,
58083        fontStyle:            this.fontStyle,
58084        lineHeight:           this.lineHeight,
58085        textDecoration:       this.textDecoration,
58086        textAlign:            this.textAlign,
58087        path:                 this.path,
58088        textBackgroundColor:  this.textBackgroundColor,
58089        useNative:            this.useNative
58090      });
58091      if (!this.includeDefaultValues) {
58092        this._removeDefaultValues(object);
58093      }
58094      return object;
58095    },
58096
58097    /* _TO_SVG_START_ */
58098    /**
58099     * Returns SVG representation of an instance
58100     * @param {Function} [reviver] Method for further parsing of svg representation.
58101     * @return {String} svg representation of an instance
58102     */
58103    toSVG: function(reviver) {
58104      var markup = [ ],
58105          textLines = this.text.split(/\r?\n/),
58106          lineTopOffset = this.useNative
58107            ? this.fontSize * this.lineHeight
58108            : (-this._fontAscent - ((this._fontAscent / 5) * this.lineHeight)),
58109
58110          textLeftOffset = -(this.width/2),
58111          textTopOffset = this.useNative
58112            ? this.fontSize - 1
58113            : (this.height/2) - (textLines.length * this.fontSize) - this._totalLineHeight,
58114
58115          textAndBg = this._getSVGTextAndBg(lineTopOffset, textLeftOffset, textLines),
58116          shadowSpans = this._getSVGShadows(lineTopOffset, textLines);
58117
58118      // move top offset by an ascent
58119      textTopOffset += (this._fontAscent ? ((this._fontAscent / 5) * this.lineHeight) : 0);
58120
58121      markup.push(
58122        '<g transform="', this.getSvgTransform(), '">',
58123          textAndBg.textBgRects.join(''),
58124          '<text ',
58125            (this.fontFamily ? 'font-family="' + this.fontFamily.replace(/"/g,'\'') + '" ': ''),
58126            (this.fontSize ? 'font-size="' + this.fontSize + '" ': ''),
58127            (this.fontStyle ? 'font-style="' + this.fontStyle + '" ': ''),
58128            (this.fontWeight ? 'font-weight="' + this.fontWeight + '" ': ''),
58129            (this.textDecoration ? 'text-decoration="' + this.textDecoration + '" ': ''),
58130            'style="', this.getSvgStyles(), '" ',
58131            /* svg starts from left/bottom corner so we normalize height */
58132            'transform="translate(', toFixed(textLeftOffset, 2), ' ', toFixed(textTopOffset, 2), ')">',
58133            shadowSpans.join(''),
58134            textAndBg.textSpans.join(''),
58135          '</text>',
58136        '</g>'
58137      );
58138
58139      return reviver ? reviver(markup.join('')) : markup.join('');
58140    },
58141
58142    /**
58143     * @private
58144     * @param {Number} lineTopOffset Line top offset
58145     * @param {Array} textLines Array of all text lines
58146     * @return {Array}
58147     */
58148    _getSVGShadows: function(lineTopOffset, textLines) {
58149      var shadowSpans = [],
58150          i, len,
58151          lineTopOffsetMultiplier = 1;
58152
58153      if (!this.shadow || !this._boundaries) {
58154        return shadowSpans;
58155      }
58156
58157      for (i = 0, len = textLines.length; i < len; i++) {
58158        if (textLines[i] !== '') {
58159          var lineLeftOffset = (this._boundaries && this._boundaries[i]) ? this._boundaries[i].left : 0;
58160          shadowSpans.push(
58161            '<tspan x="',
58162            toFixed((lineLeftOffset + lineTopOffsetMultiplier) + this.shadow.offsetX, 2),
58163            ((i === 0 || this.useNative) ? '" y' : '" dy'), '="',
58164            toFixed(this.useNative
58165              ? ((lineTopOffset * i) - this.height / 2 + this.shadow.offsetY)
58166              : (lineTopOffset + (i === 0 ? this.shadow.offsetY : 0)), 2),
58167            '" ',
58168            this._getFillAttributes(this.shadow.color), '>',
58169            fabric.util.string.escapeXml(textLines[i]),
58170          '</tspan>');
58171          lineTopOffsetMultiplier = 1;
58172        } else {
58173          // in some environments (e.g. IE 7 & 8) empty tspans are completely ignored, using a lineTopOffsetMultiplier
58174          // prevents empty tspans
58175          lineTopOffsetMultiplier++;
58176        }
58177      }
58178
58179      return shadowSpans;
58180    },
58181
58182    /**
58183     * @private
58184     * @param {Number} lineTopOffset Line top offset
58185     * @param {Number} textLeftOffset Text left offset
58186     * @param {Array} textLines Array of all text lines
58187     * @return {Object}
58188     */
58189    _getSVGTextAndBg: function(lineTopOffset, textLeftOffset, textLines) {
58190      var textSpans = [ ], textBgRects = [ ], i, lineLeftOffset, len, lineTopOffsetMultiplier = 1;
58191
58192      // bounding-box background
58193      if (this.backgroundColor && this._boundaries) {
58194        textBgRects.push(
58195          '<rect ',
58196            this._getFillAttributes(this.backgroundColor),
58197            ' x="',
58198            toFixed(-this.width / 2, 2),
58199            '" y="',
58200            toFixed(-this.height / 2, 2),
58201            '" width="',
58202            toFixed(this.width, 2),
58203            '" height="',
58204            toFixed(this.height, 2),
58205          '"></rect>');
58206      }
58207
58208      // text and text-background
58209      for (i = 0, len = textLines.length; i < len; i++) {
58210        if (textLines[i] !== '') {
58211          lineLeftOffset = (this._boundaries && this._boundaries[i]) ? toFixed(this._boundaries[i].left, 2) : 0;
58212          textSpans.push(
58213            '<tspan x="',
58214              lineLeftOffset, '" ',
58215              (i === 0 || this.useNative ? 'y' : 'dy'), '="',
58216              toFixed(this.useNative ? ((lineTopOffset * i) - this.height / 2) : (lineTopOffset * lineTopOffsetMultiplier), 2) , '" ',
58217              // doing this on <tspan> elements since setting opacity on containing <text> one doesn't work in Illustrator
58218              this._getFillAttributes(this.fill), '>',
58219              fabric.util.string.escapeXml(textLines[i]),
58220            '</tspan>'
58221          );
58222          lineTopOffsetMultiplier = 1;
58223        }
58224        else {
58225          // in some environments (e.g. IE 7 & 8) empty tspans are completely ignored, using a lineTopOffsetMultiplier
58226          // prevents empty tspans
58227          lineTopOffsetMultiplier++;
58228        }
58229
58230        if (!this.textBackgroundColor || !this._boundaries) continue;
58231
58232        textBgRects.push(
58233          '<rect ',
58234            this._getFillAttributes(this.textBackgroundColor),
58235            ' x="',
58236            toFixed(textLeftOffset + this._boundaries[i].left, 2),
58237            '" y="',
58238            /* an offset that seems to straighten things out */
58239            toFixed((lineTopOffset * i) - this.height / 2, 2),
58240            '" width="',
58241            toFixed(this._boundaries[i].width, 2),
58242            '" height="',
58243            toFixed(this._boundaries[i].height, 2),
58244          '"></rect>');
58245      }
58246      return {
58247        textSpans: textSpans,
58248        textBgRects: textBgRects
58249      };
58250    },
58251
58252    /**
58253     * Adobe Illustrator (at least CS5) is unable to render rgba()-based fill values
58254     * we work around it by "moving" alpha channel into opacity attribute and setting fill's alpha to 1
58255     *
58256     * @private
58257     * @param {Any} value
58258     * @return {String}
58259     */
58260    _getFillAttributes: function(value) {
58261      var fillColor = (value && typeof value === 'string') ? new fabric.Color(value) : '';
58262      if (!fillColor || !fillColor.getSource() || fillColor.getAlpha() === 1) {
58263        return 'fill="' + value + '"';
58264      }
58265      return 'opacity="' + fillColor.getAlpha() + '" fill="' + fillColor.setAlpha(1).toRgb() + '"';
58266    },
58267    /* _TO_SVG_END_ */
58268
58269    /**
58270     * Sets specified property to a specified value
58271     * @param {String} key
58272     * @param {Any} value
58273     * @return {fabric.Text} thisArg
58274     * @chainable
58275     */
58276    _set: function(key, value) {
58277      if (key === 'fontFamily' && this.path) {
58278        this.path = this.path.replace(/(.*?)([^\/]*)(\.font\.js)/, '$1' + value + '$3');
58279      }
58280      this.callSuper('_set', key, value);
58281
58282      if (key in this._dimensionAffectingProps) {
58283        this._initDimensions();
58284        this.setCoords();
58285      }
58286    },
58287
58288    /**
58289     * Returns complexity of an instance
58290     * @return {Number} complexity
58291     */
58292    complexity: function() {
58293      return 1;
58294    }
58295  });
58296
58297  /* _FROM_SVG_START_ */
58298  /**
58299   * List of attribute names to account for when parsing SVG element (used by {@link fabric.Text.fromElement})
58300   * @static
58301   * @memberOf fabric.Text
58302   * @see: http://www.w3.org/TR/SVG/text.html#TextElement
58303   */
58304  fabric.Text.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat(
58305    'x y font-family font-style font-weight font-size text-decoration'.split(' '));
58306
58307  /**
58308   * Returns fabric.Text instance from an SVG element (<b>not yet implemented</b>)
58309   * @static
58310   * @memberOf fabric.Text
58311   * @param {SVGElement} element Element to parse
58312   * @param {Object} [options] Options object
58313   * @return {fabric.Text} Instance of fabric.Text
58314   */
58315  fabric.Text.fromElement = function(element, options) {
58316    if (!element) {
58317      return null;
58318    }
58319
58320    var parsedAttributes = fabric.parseAttributes(element, fabric.Text.ATTRIBUTE_NAMES);
58321    options = fabric.util.object.extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes);
58322
58323    var text = new fabric.Text(element.textContent, options);
58324
58325    /*
58326      Adjust positioning:
58327        x/y attributes in SVG correspond to the bottom-left corner of text bounding box
58328        top/left properties in Fabric correspond to center point of text bounding box
58329    */
58330
58331    text.set({
58332      left: text.getLeft() + text.getWidth() / 2,
58333      top: text.getTop() - text.getHeight() / 2
58334    });
58335
58336    return text;
58337  };
58338  /* _FROM_SVG_END_ */
58339
58340  /**
58341   * Returns fabric.Text instance from an object representation
58342   * @static
58343   * @memberOf fabric.Text
58344   * @param object {Object} object Object to create an instance from
58345   * @return {fabric.Text} Instance of fabric.Text
58346   */
58347  fabric.Text.fromObject = function(object) {
58348    return new fabric.Text(object.text, clone(object));
58349  };
58350
58351  fabric.util.createAccessors(fabric.Text);
58352
58353})(typeof exports !== 'undefined' ? exports : this);
58354
58355
58356/**
58357 * @private
58358 * @param {CanvasRenderingContext2D} ctx Context to render on
58359 */
58360fabric.util.object.extend(fabric.Text.prototype, {
58361  _renderViaCufon: function(ctx) {
58362
58363    var o = Cufon.textOptions || (Cufon.textOptions = { });
58364
58365    // export options to be used by cufon.js
58366    o.left = this.left;
58367    o.top = this.top;
58368    o.context = ctx;
58369    o.color = this.fill;
58370
58371    var el = this._initDummyElementForCufon();
58372
58373    // set "cursor" to top/left corner
58374    this.transform(ctx);
58375
58376    // draw text
58377    Cufon.replaceElement(el, {
58378      engine: 'canvas',
58379      separate: 'none',
58380      fontFamily: this.fontFamily,
58381      fontWeight: this.fontWeight,
58382      textDecoration: this.textDecoration,
58383      textShadow: this.shadow && this.shadow.toString(),
58384      textAlign: this.textAlign,
58385      fontStyle: this.fontStyle,
58386      lineHeight: this.lineHeight,
58387      stroke: this.stroke,
58388      strokeWidth: this.strokeWidth,
58389      backgroundColor: this.backgroundColor,
58390      textBackgroundColor: this.textBackgroundColor
58391    });
58392
58393    // update width, height
58394    this.width = o.width;
58395    this.height = o.height;
58396
58397    this._totalLineHeight = o.totalLineHeight;
58398    this._fontAscent = o.fontAscent;
58399    this._boundaries = o.boundaries;
58400
58401    el = null;
58402
58403    // need to set coords _after_ the width/height was retreived from Cufon
58404    this.setCoords();
58405  },
58406
58407  /**
58408   * @private
58409   */
58410  _initDummyElementForCufon: function() {
58411    var el = fabric.document.createElement('pre'),
58412        container = fabric.document.createElement('div');
58413
58414    // Cufon doesn't play nice with textDecoration=underline if element doesn't have a parent
58415    container.appendChild(el);
58416
58417    if (typeof G_vmlCanvasManager === 'undefined') {
58418      el.innerHTML = this.text;
58419    }
58420    else {
58421      // IE 7 & 8 drop newlines and white space on text nodes
58422      // see: http://web.student.tuwien.ac.at/~e0226430/innerHtmlQuirk.html
58423      // see: http://www.w3schools.com/dom/dom_mozilla_vs_ie.asp
58424      el.innerText =  this.text.replace(/\r?\n/gi, '\r');
58425    }
58426
58427    el.style.fontSize = this.fontSize + 'px';
58428    el.style.letterSpacing = 'normal';
58429
58430    return el;
58431  }
58432});
58433
58434
58435(function() {
58436
58437  if (typeof document !== 'undefined' && typeof window !== 'undefined') {
58438    return;
58439  }
58440
58441  var DOMParser = new require('xmldom').DOMParser,
58442      URL = require('url'),
58443      HTTP = require('http'),
58444      HTTPS = require('https'),
58445
58446      Canvas = require('canvas'),
58447      Image = require('canvas').Image;
58448
58449  /** @private */
58450  function request(url, encoding, callback) {
58451    var oURL = URL.parse(url);
58452
58453    // detect if http or https is used
58454    if ( !oURL.port ) {
58455      oURL.port = ( oURL.protocol.indexOf('https:') === 0 ) ? 443 : 80;
58456    }
58457
58458    // assign request handler based on protocol
58459    var reqHandler = ( oURL.port === 443 ) ? HTTPS : HTTP;
58460
58461    var req = reqHandler.request({
58462      hostname: oURL.hostname,
58463      port: oURL.port,
58464      path: oURL.path,
58465      method: 'GET'
58466    }, function(response){
58467      var body = "";
58468      if (encoding) {
58469        response.setEncoding(encoding);
58470      }
58471      response.on('end', function () {
58472        callback(body);
58473      });
58474      response.on('data', function (chunk) {
58475        if (response.statusCode === 200) {
58476          body += chunk;
58477        }
58478      });
58479    });
58480
58481    req.on('error', function(err) {
58482      if (err.errno === process.ECONNREFUSED) {
58483        fabric.log('ECONNREFUSED: connection refused to ' + oURL.hostname + ':' + oURL.port);
58484      }
58485      else {
58486        fabric.log(err.message);
58487      }
58488    });
58489
58490    req.end();
58491  }
58492
58493  /** @private */
58494  function request_fs(path, callback){
58495    var fs = require('fs');
58496    fs.readFile(path, function (err, data) {
58497      if (err) {
58498        fabric.log(err);
58499        throw err;
58500      } else {
58501        callback(data);
58502      }
58503    });
58504  }
58505
58506  fabric.util.loadImage = function(url, callback, context) {
58507    var createImageAndCallBack = function(data){
58508      img.src = new Buffer(data, 'binary');
58509      // preserving original url, which seems to be lost in node-canvas
58510      img._src = url;
58511      callback && callback.call(context, img);
58512    };
58513    var img = new Image();
58514    if (url && (url instanceof Buffer || url.indexOf('data') === 0)) {
58515      img.src = img._src = url;
58516      callback && callback.call(context, img);
58517    }
58518    else if (url && url.indexOf('http') !== 0) {
58519      request_fs(url, createImageAndCallBack);
58520    }
58521    else if (url) {
58522      request(url, 'binary', createImageAndCallBack);
58523    }
58524  };
58525
58526  fabric.loadSVGFromURL = function(url, callback, reviver) {
58527    url = url.replace(/^\n\s*/, '').replace(/\?.*$/, '').trim();
58528    if (url.indexOf('http') !== 0) {
58529      request_fs(url, function(body) {
58530        fabric.loadSVGFromString(body, callback, reviver);
58531      });
58532    }
58533    else {
58534      request(url, '', function(body) {
58535        fabric.loadSVGFromString(body, callback, reviver);
58536      });
58537    }
58538  };
58539
58540  fabric.loadSVGFromString = function(string, callback, reviver) {
58541    var doc = new DOMParser().parseFromString(string);
58542    fabric.parseSVGDocument(doc.documentElement, function(results, options) {
58543      callback && callback(results, options);
58544    }, reviver);
58545  };
58546
58547  fabric.util.getScript = function(url, callback) {
58548    request(url, '', function(body) {
58549      eval(body);
58550      callback && callback();
58551    });
58552  };
58553
58554  fabric.Image.fromObject = function(object, callback) {
58555    fabric.util.loadImage(object.src, function(img) {
58556      var oImg = new fabric.Image(img);
58557
58558      oImg._initConfig(object);
58559      oImg._initFilters(object, function(filters) {
58560        oImg.filters = filters || [ ];
58561        callback && callback(oImg);
58562      });
58563    });
58564  };
58565
58566  /**
58567   * Only available when running fabric on node.js
58568   * @param width Canvas width
58569   * @param height Canvas height
58570   * @return {Object} wrapped canvas instance
58571   */
58572  fabric.createCanvasForNode = function(width, height) {
58573
58574    var canvasEl = fabric.document.createElement('canvas'),
58575        nodeCanvas = new Canvas(width || 600, height || 600);
58576
58577    // jsdom doesn't create style on canvas element, so here be temp. workaround
58578    canvasEl.style = { };
58579
58580    canvasEl.width = nodeCanvas.width;
58581    canvasEl.height = nodeCanvas.height;
58582
58583    var FabricCanvas = fabric.Canvas || fabric.StaticCanvas;
58584    var fabricCanvas = new FabricCanvas(canvasEl);
58585    fabricCanvas.contextContainer = nodeCanvas.getContext('2d');
58586    fabricCanvas.nodeCanvas = nodeCanvas;
58587    fabricCanvas.Font = Canvas.Font;
58588
58589    return fabricCanvas;
58590  };
58591
58592  /** @ignore */
58593  fabric.StaticCanvas.prototype.createPNGStream = function() {
58594    return this.nodeCanvas.createPNGStream();
58595  };
58596
58597  fabric.StaticCanvas.prototype.createJPEGStream = function(opts) {
58598    return this.nodeCanvas.createJPEGStream(opts);
58599  };
58600
58601  var origSetWidth = fabric.StaticCanvas.prototype.setWidth;
58602  fabric.StaticCanvas.prototype.setWidth = function(width) {
58603    origSetWidth.call(this, width);
58604    this.nodeCanvas.width = width;
58605    return this;
58606  };
58607  if (fabric.Canvas) {
58608    fabric.Canvas.prototype.setWidth = fabric.StaticCanvas.prototype.setWidth;
58609  }
58610
58611  var origSetHeight = fabric.StaticCanvas.prototype.setHeight;
58612  fabric.StaticCanvas.prototype.setHeight = function(height) {
58613    origSetHeight.call(this, height);
58614    this.nodeCanvas.height = height;
58615    return this;
58616  };
58617  if (fabric.Canvas) {
58618    fabric.Canvas.prototype.setHeight = fabric.StaticCanvas.prototype.setHeight;
58619  }
58620
58621})();
58622
58623
58624define("fabric", function(){});
58625
58626/*!!
58627 * Hasher <http://github.com/millermedeiros/hasher>
58628 * @author Miller Medeiros
58629 * @version 1.2.0 (2013/11/11 03:18 PM)
58630 * Released under the MIT License
58631 */
58632
58633;(function () {
58634var factory = function(signals){
58635
58636/*jshint white:false*/
58637/*global signals:false, window:false*/
58638
58639/**
58640 * Hasher
58641 * @namespace History Manager for rich-media applications.
58642 * @name hasher
58643 */
58644var hasher = (function(window){
58645
58646    //--------------------------------------------------------------------------------------
58647    // Private Vars
58648    //--------------------------------------------------------------------------------------
58649
58650    var
58651
58652        // frequency that it will check hash value on IE 6-7 since it doesn't
58653        // support the hashchange event
58654        POOL_INTERVAL = 25,
58655
58656        // local storage for brevity and better compression --------------------------------
58657
58658        document = window.document,
58659        history = window.history,
58660        Signal = signals.Signal,
58661
58662        // local vars ----------------------------------------------------------------------
58663
58664        hasher,
58665        _hash,
58666        _checkInterval,
58667        _isActive,
58668        _frame, //iframe used for legacy IE (6-7)
58669        _checkHistory,
58670        _hashValRegexp = /#(.*)$/,
58671        _baseUrlRegexp = /(\?.*)|(\#.*)/,
58672        _hashRegexp = /^\#/,
58673
58674        // sniffing/feature detection -------------------------------------------------------
58675
58676        //hack based on this: http://webreflection.blogspot.com/2009/01/32-bytes-to-know-if-your-browser-is-ie.html
58677        _isIE = (!+"\v1"),
58678        // hashchange is supported by FF3.6+, IE8+, Chrome 5+, Safari 5+ but
58679        // feature detection fails on IE compatibility mode, so we need to
58680        // check documentMode
58681        _isHashChangeSupported = ('onhashchange' in window) && document.documentMode !== 7,
58682        //check if is IE6-7 since hash change is only supported on IE8+ and
58683        //changing hash value on IE6-7 doesn't generate history record.
58684        _isLegacyIE = _isIE && !_isHashChangeSupported,
58685        _isLocal = (location.protocol === 'file:');
58686
58687
58688    //--------------------------------------------------------------------------------------
58689    // Private Methods
58690    //--------------------------------------------------------------------------------------
58691
58692    function _escapeRegExp(str){
58693        return String(str || '').replace(/\W/g, "\\$&");
58694    }
58695
58696    function _trimHash(hash){
58697        if (!hash) return '';
58698        var regexp = new RegExp('^' + _escapeRegExp(hasher.prependHash) + '|' + _escapeRegExp(hasher.appendHash) + '$', 'g');
58699        return hash.replace(regexp, '');
58700    }
58701
58702    function _getWindowHash(){
58703        //parsed full URL instead of getting window.location.hash because Firefox decode hash value (and all the other browsers don't)
58704        //also because of IE8 bug with hash query in local file [issue #6]
58705        var result = _hashValRegexp.exec( hasher.getURL() );
58706        var path = (result && result[1]) || '';
58707        try {
58708          return hasher.raw? path : decodeURIComponent(path);
58709        } catch (e) {
58710          // in case user did not set `hasher.raw` and decodeURIComponent
58711          // throws an error (see #57)
58712          return path;
58713        }
58714    }
58715
58716    function _getFrameHash(){
58717        return (_frame)? _frame.contentWindow.frameHash : null;
58718    }
58719
58720    function _createFrame(){
58721        _frame = document.createElement('iframe');
58722        _frame.src = 'about:blank';
58723        _frame.style.display = 'none';
58724        document.body.appendChild(_frame);
58725    }
58726
58727    function _updateFrame(){
58728        if(_frame && _hash !== _getFrameHash()){
58729            var frameDoc = _frame.contentWindow.document;
58730            frameDoc.open();
58731            //update iframe content to force new history record.
58732            //based on Really Simple History, SWFAddress and YUI.history.
58733            frameDoc.write('<html><head><title>' + document.title + '</title><script type="text/javascript">var frameHash="' + _hash + '";</script></head><body>&nbsp;</body></html>');
58734            frameDoc.close();
58735        }
58736    }
58737
58738    function _registerChange(newHash, isReplace){
58739        if(_hash !== newHash){
58740            var oldHash = _hash;
58741            _hash = newHash; //should come before event dispatch to make sure user can get proper value inside event handler
58742            if(_isLegacyIE){
58743                if(!isReplace){
58744                    _updateFrame();
58745                } else {
58746                    _frame.contentWindow.frameHash = newHash;
58747                }
58748            }
58749            hasher.changed.dispatch(_trimHash(newHash), _trimHash(oldHash));
58750        }
58751    }
58752
58753    if (_isLegacyIE) {
58754        /**
58755         * @private
58756         */
58757        _checkHistory = function(){
58758            var windowHash = _getWindowHash(),
58759                frameHash = _getFrameHash();
58760            if(frameHash !== _hash && frameHash !== windowHash){
58761                //detect changes made pressing browser history buttons.
58762                //Workaround since history.back() and history.forward() doesn't
58763                //update hash value on IE6/7 but updates content of the iframe.
58764                //needs to trim hash since value stored already have
58765                //prependHash + appendHash for fast check.
58766                hasher.setHash(_trimHash(frameHash));
58767            } else if (windowHash !== _hash){
58768                //detect if hash changed (manually or using setHash)
58769                _registerChange(windowHash);
58770            }
58771        };
58772    } else {
58773        /**
58774         * @private
58775         */
58776        _checkHistory = function(){
58777            var windowHash = _getWindowHash();
58778            if(windowHash !== _hash){
58779                _registerChange(windowHash);
58780            }
58781        };
58782    }
58783
58784    function _addListener(elm, eType, fn){
58785        if(elm.addEventListener){
58786            elm.addEventListener(eType, fn, false);
58787        } else if (elm.attachEvent){
58788            elm.attachEvent('on' + eType, fn);
58789        }
58790    }
58791
58792    function _removeListener(elm, eType, fn){
58793        if(elm.removeEventListener){
58794            elm.removeEventListener(eType, fn, false);
58795        } else if (elm.detachEvent){
58796            elm.detachEvent('on' + eType, fn);
58797        }
58798    }
58799
58800    function _makePath(paths){
58801        paths = Array.prototype.slice.call(arguments);
58802
58803        var path = paths.join(hasher.separator);
58804        path = path? hasher.prependHash + path.replace(_hashRegexp, '') + hasher.appendHash : path;
58805        return path;
58806    }
58807
58808    function _encodePath(path){
58809        //used encodeURI instead of encodeURIComponent to preserve '?', '/',
58810        //'#'. Fixes Safari bug [issue #8]
58811        path = encodeURI(path);
58812        if(_isIE && _isLocal){
58813            //fix IE8 local file bug [issue #6]
58814            path = path.replace(/\?/, '%3F');
58815        }
58816        return path;
58817    }
58818
58819    //--------------------------------------------------------------------------------------
58820    // Public (API)
58821    //--------------------------------------------------------------------------------------
58822
58823    hasher = /** @lends hasher */ {
58824
58825        /**
58826         * hasher Version Number
58827         * @type string
58828         * @constant
58829         */
58830        VERSION : '1.2.0',
58831
58832        /**
58833         * Boolean deciding if hasher encodes/decodes the hash or not.
58834         * <ul>
58835         * <li>default value: false;</li>
58836         * </ul>
58837         * @type boolean
58838         */
58839        raw : false,
58840
58841        /**
58842         * String that should always be added to the end of Hash value.
58843         * <ul>
58844         * <li>default value: '';</li>
58845         * <li>will be automatically removed from `hasher.getHash()`</li>
58846         * <li>avoid conflicts with elements that contain ID equal to hash value;</li>
58847         * </ul>
58848         * @type string
58849         */
58850        appendHash : '',
58851
58852        /**
58853         * String that should always be added to the beginning of Hash value.
58854         * <ul>
58855         * <li>default value: '/';</li>
58856         * <li>will be automatically removed from `hasher.getHash()`</li>
58857         * <li>avoid conflicts with elements that contain ID equal to hash value;</li>
58858         * </ul>
58859         * @type string
58860         */
58861        prependHash : '/',
58862
58863        /**
58864         * String used to split hash paths; used by `hasher.getHashAsArray()` to split paths.
58865         * <ul>
58866         * <li>default value: '/';</li>
58867         * </ul>
58868         * @type string
58869         */
58870        separator : '/',
58871
58872        /**
58873         * Signal dispatched when hash value changes.
58874         * - pass current hash as 1st parameter to listeners and previous hash value as 2nd parameter.
58875         * @type signals.Signal
58876         */
58877        changed : new Signal(),
58878
58879        /**
58880         * Signal dispatched when hasher is stopped.
58881         * -  pass current hash as first parameter to listeners
58882         * @type signals.Signal
58883         */
58884        stopped : new Signal(),
58885
58886        /**
58887         * Signal dispatched when hasher is initialized.
58888         * - pass current hash as first parameter to listeners.
58889         * @type signals.Signal
58890         */
58891        initialized : new Signal(),
58892
58893        /**
58894         * Start listening/dispatching changes in the hash/history.
58895         * <ul>
58896         *   <li>hasher won't dispatch CHANGE events by manually typing a new value or pressing the back/forward buttons before calling this method.</li>
58897         * </ul>
58898         */
58899        init : function(){
58900            if(_isActive) return;
58901
58902            _hash = _getWindowHash();
58903
58904            //thought about branching/overloading hasher.init() to avoid checking multiple times but
58905            //don't think worth doing it since it probably won't be called multiple times.
58906            if(_isHashChangeSupported){
58907                _addListener(window, 'hashchange', _checkHistory);
58908            }else {
58909                if(_isLegacyIE){
58910                    if(! _frame){
58911                        _createFrame();
58912                    }
58913                    _updateFrame();
58914                }
58915                _checkInterval = setInterval(_checkHistory, POOL_INTERVAL);
58916            }
58917
58918            _isActive = true;
58919            hasher.initialized.dispatch(_trimHash(_hash));
58920        },
58921
58922        /**
58923         * Stop listening/dispatching changes in the hash/history.
58924         * <ul>
58925         *   <li>hasher won't dispatch CHANGE events by manually typing a new value or pressing the back/forward buttons after calling this method, unless you call hasher.init() again.</li>
58926         *   <li>hasher will still dispatch changes made programatically by calling hasher.setHash();</li>
58927         * </ul>
58928         */
58929        stop : function(){
58930            if(! _isActive) return;
58931
58932            if(_isHashChangeSupported){
58933                _removeListener(window, 'hashchange', _checkHistory);
58934            }else{
58935                clearInterval(_checkInterval);
58936                _checkInterval = null;
58937            }
58938
58939            _isActive = false;
58940            hasher.stopped.dispatch(_trimHash(_hash));
58941        },
58942
58943        /**
58944         * @return {boolean}    If hasher is listening to changes on the browser history and/or hash value.
58945         */
58946        isActive : function(){
58947            return _isActive;
58948        },
58949
58950        /**
58951         * @return {string} Full URL.
58952         */
58953        getURL : function(){
58954            return window.location.href;
58955        },
58956
58957        /**
58958         * @return {string} Retrieve URL without query string and hash.
58959         */
58960        getBaseURL : function(){
58961            return hasher.getURL().replace(_baseUrlRegexp, ''); //removes everything after '?' and/or '#'
58962        },
58963
58964        /**
58965         * Set Hash value, generating a new history record.
58966         * @param {...string} path    Hash value without '#'. Hasher will join
58967         * path segments using `hasher.separator` and prepend/append hash value
58968         * with `hasher.appendHash` and `hasher.prependHash`
58969         * @example hasher.setHash('lorem', 'ipsum', 'dolor') -> '#/lorem/ipsum/dolor'
58970         */
58971        setHash : function(path){
58972            path = _makePath.apply(null, arguments);
58973            if(path !== _hash){
58974                // we should store raw value
58975                _registerChange(path);
58976                if (path === _hash) {
58977                    // we check if path is still === _hash to avoid error in
58978                    // case of multiple consecutive redirects [issue #39]
58979                    if (! hasher.raw) {
58980                        path = _encodePath(path);
58981                    }
58982                    window.location.hash = '#' + path;
58983                }
58984            }
58985        },
58986
58987        /**
58988         * Set Hash value without keeping previous hash on the history record.
58989         * Similar to calling `window.location.replace("#/hash")` but will also work on IE6-7.
58990         * @param {...string} path    Hash value without '#'. Hasher will join
58991         * path segments using `hasher.separator` and prepend/append hash value
58992         * with `hasher.appendHash` and `hasher.prependHash`
58993         * @example hasher.replaceHash('lorem', 'ipsum', 'dolor') -> '#/lorem/ipsum/dolor'
58994         */
58995        replaceHash : function(path){
58996            path = _makePath.apply(null, arguments);
58997            if(path !== _hash){
58998                // we should store raw value
58999                _registerChange(path, true);
59000                if (path === _hash) {
59001                    // we check if path is still === _hash to avoid error in
59002                    // case of multiple consecutive redirects [issue #39]
59003                    if (! hasher.raw) {
59004                        path = _encodePath(path);
59005                    }
59006                    window.location.replace('#' + path);
59007                }
59008            }
59009        },
59010
59011        /**
59012         * @return {string} Hash value without '#', `hasher.appendHash` and `hasher.prependHash`.
59013         */
59014        getHash : function(){
59015            //didn't used actual value of the `window.location.hash` to avoid breaking the application in case `window.location.hash` isn't available and also because value should always be synched.
59016            return _trimHash(_hash);
59017        },
59018
59019        /**
59020         * @return {Array.<string>} Hash value split into an Array.
59021         */
59022        getHashAsArray : function(){
59023            return hasher.getHash().split(hasher.separator);
59024        },
59025
59026        /**
59027         * Removes all event listeners, stops hasher and destroy hasher object.
59028         * - IMPORTANT: hasher won't work after calling this method, hasher Object will be deleted.
59029         */
59030        dispose : function(){
59031            hasher.stop();
59032            hasher.initialized.dispose();
59033            hasher.stopped.dispose();
59034            hasher.changed.dispose();
59035            _frame = hasher = window.hasher = null;
59036        },
59037
59038        /**
59039         * @return {string} A string representation of the object.
59040         */
59041        toString : function(){
59042            return '[hasher version="'+ hasher.VERSION +'" hash="'+ hasher.getHash() +'"]';
59043        }
59044
59045    };
59046
59047    hasher.initialized.memorize = true; //see #33
59048
59049    return hasher;
59050
59051}(window));
59052
59053
59054    return hasher;
59055};
59056
59057if (typeof define === 'function' && define.amd) {
59058    define('hasher',['signals'], factory);
59059} else if (typeof exports === 'object') {
59060    module.exports = factory(require('signals'));
59061} else {
59062    /*jshint sub:true */
59063    window['hasher'] = factory(window['signals']);
59064}
59065
59066}());
59067
59068/*!
59069 * iCheck v1.0.3, http://git.io/arlzeA
59070 * ===================================
59071 * Powerful jQuery and Zepto plugin for checkboxes and radio buttons customization
59072 *
59073 * (c) 2013 Damir Sultanov, http://fronteed.com
59074 * MIT Licensed
59075 */
59076
59077(function($) {
59078
59079  // Cached vars
59080  var _iCheck = 'iCheck',
59081    _iCheckHelper = _iCheck + '-helper',
59082    _checkbox = 'checkbox',
59083    _radio = 'radio',
59084    _checked = 'checked',
59085    _unchecked = 'un' + _checked,
59086    _disabled = 'disabled',
59087    _determinate = 'determinate',
vendor: 15,628 bytes, lines 59088-59609
59088    _indeterminate = 'in' + _determinate,
59089    _update = 'update',
59090    _type = 'type',
59091    _click = 'click',
59092    _touch = 'touchbegin.i touchend.i',
59093    _add = 'addClass',
59094    _remove = 'removeClass',
59095    _callback = 'trigger',
59096    _label = 'label',
59097    _cursor = 'cursor',
59098    _mobile = /ip(hone|od|ad)|android|blackberry|windows phone|opera mini|silk/i.test(navigator.userAgent) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1);
59099
59100  // Plugin init
59101  $.fn[_iCheck] = function(options, fire) {
59102
59103    // Walker
59104    var handle = 'input[type="' + _checkbox + '"], input[type="' + _radio + '"]',
59105      stack = $(),
59106      walker = function(object) {
59107        object.each(function() {
59108          var self = $(this);
59109
59110          if (self.is(handle)) {
59111            stack = stack.add(self);
59112          } else {
59113            stack = stack.add(self.find(handle));
59114          }
59115        });
59116      };
59117
59118    // Check if we should operate with some method
59119    if (/^(check|uncheck|toggle|indeterminate|determinate|disable|enable|update|destroy)$/i.test(options)) {
59120
59121      // Normalize method's name
59122      options = options.toLowerCase();
59123
59124      // Find checkboxes and radio buttons
59125      walker(this);
59126
59127      return stack.each(function() {
59128        var self = $(this);
59129
59130        if (options == 'destroy') {
59131          tidy(self, 'ifDestroyed');
59132        } else {
59133          operate(self, true, options);
59134        }
59135
59136        // Fire method's callback
59137        if ($.isFunction(fire)) {
59138          fire();
59139        }
59140      });
59141
59142    // Customization
59143    } else if (typeof options == 'object' || !options) {
59144
59145      // Check if any options were passed
59146      var settings = $.extend({
59147          checkedClass: _checked,
59148          disabledClass: _disabled,
59149          indeterminateClass: _indeterminate,
59150          labelHover: true
59151        }, options),
59152
59153        selector = settings.handle,
59154        hoverClass = settings.hoverClass || 'hover',
59155        focusClass = settings.focusClass || 'focus',
59156        activeClass = settings.activeClass || 'active',
59157        labelHover = !!settings.labelHover,
59158        labelHoverClass = settings.labelHoverClass || 'hover',
59159
59160        // Setup clickable area
59161        area = ('' + settings.increaseArea).replace('%', '') | 0;
59162
59163      // Selector limit
59164      if (selector == _checkbox || selector == _radio) {
59165        handle = 'input[type="' + selector + '"]';
59166      }
59167
59168      // Clickable area limit
59169      if (area < -50) {
59170        area = -50;
59171      }
59172
59173      // Walk around the selector
59174      walker(this);
59175
59176      return stack.each(function() {
59177        var self = $(this);
59178
59179        // If already customized
59180        tidy(self);
59181
59182        var node = this,
59183          id = node.id,
59184
59185          // Layer styles
59186          offset = -area + '%',
59187          size = 100 + (area * 2) + '%',
59188          layer = {
59189            position: 'absolute',
59190            top: offset,
59191            left: offset,
59192            display: 'block',
59193            width: size,
59194            height: size,
59195            margin: 0,
59196            padding: 0,
59197            background: '#fff',
59198            border: 0,
59199            opacity: 0
59200          },
59201
59202          // Choose how to hide input
59203          hide = _mobile ? {
59204            position: 'absolute',
59205            visibility: 'hidden'
59206          } : area ? layer : {
59207            position: 'absolute',
59208            opacity: 0
59209          },
59210
59211          // Get proper class
59212          className = node[_type] == _checkbox ? settings.checkboxClass || 'i' + _checkbox : settings.radioClass || 'i' + _radio,
59213
59214          // Find assigned labels
59215          label = $(_label + '[for="' + id + '"]').add(self.closest(_label)),
59216
59217          // Check ARIA option
59218          aria = !!settings.aria,
59219
59220          // Set ARIA placeholder
59221          ariaID = _iCheck + '-' + Math.random().toString(36).substr(2,6),
59222
59223          // Parent & helper
59224          parent = '<div class="' + className + '" ' + (aria ? 'role="' + node[_type] + '" ' : ''),
59225          helper;
59226
59227        // Set ARIA "labelledby"
59228        if (aria) {
59229          label.each(function() {
59230            parent += 'aria-labelledby="';
59231
59232            if (this.id) {
59233              parent += this.id;
59234            } else {
59235              this.id = ariaID;
59236              parent += ariaID;
59237            }
59238
59239            parent += '"';
59240          });
59241        }
59242
59243        // Wrap input
59244        parent = self.wrap(parent + '/>')[_callback]('ifCreated').parent().append(settings.insert);
59245
59246        // Layer addition
59247        helper = $('<ins class="' + _iCheckHelper + '"/>').css(layer).appendTo(parent);
59248
59249        // Finalize customization
59250        self.data(_iCheck, {o: settings, s: self.attr('style')}).css(hide);
59251        !!settings.inheritClass && parent[_add](node.className || '');
59252        !!settings.inheritID && id && parent.attr('id', _iCheck + '-' + id);
59253        parent.css('position') == 'static' && parent.css('position', 'relative');
59254        operate(self, true, _update);
59255
59256        // Label events
59257        if (label.length) {
59258          label.on(_click + '.i mouseover.i mouseout.i ' + _touch, function(event) {
59259            var type = event[_type],
59260              item = $(this);
59261
59262            // Do nothing if input is disabled
59263            if (!node[_disabled]) {
59264
59265              // Click
59266              if (type == _click) {
59267                if ($(event.target).is('a')) {
59268                  return;
59269                }
59270                operate(self, false, true);
59271
59272              // Hover state
59273              } else if (labelHover) {
59274
59275                // mouseout|touchend
59276                if (/ut|nd/.test(type)) {
59277                  parent[_remove](hoverClass);
59278                  item[_remove](labelHoverClass);
59279                } else {
59280                  parent[_add](hoverClass);
59281                  item[_add](labelHoverClass);
59282                }
59283              }
59284
59285              if (_mobile) {
59286                event.stopPropagation();
59287              } else {
59288                return false;
59289              }
59290            }
59291          });
59292        }
59293
59294        // Input events
59295        self.on(_click + '.i focus.i blur.i keyup.i keydown.i keypress.i', function(event) {
59296          var type = event[_type],
59297            key = event.keyCode;
59298
59299          // Click
59300          if (type == _click) {
59301            return false;
59302
59303          // Keydown
59304          } else if (type == 'keydown' && key == 32) {
59305            if (!(node[_type] == _radio && node[_checked])) {
59306              if (node[_checked]) {
59307                off(self, _checked);
59308              } else {
59309                on(self, _checked);
59310              }
59311            }
59312
59313            return false;
59314
59315          // Keyup
59316          } else if (type == 'keyup' && node[_type] == _radio) {
59317            !node[_checked] && on(self, _checked);
59318
59319          // Focus/blur
59320          } else if (/us|ur/.test(type)) {
59321            parent[type == 'blur' ? _remove : _add](focusClass);
59322          }
59323        });
59324
59325        // Helper events
59326        helper.on(_click + ' mousedown mouseup mouseover mouseout ' + _touch, function(event) {
59327          var type = event[_type],
59328
59329            // mousedown|mouseup
59330            toggle = /wn|up/.test(type) ? activeClass : hoverClass;
59331
59332          // Do nothing if input is disabled
59333          if (!node[_disabled]) {
59334
59335            // Click
59336            if (type == _click) {
59337              operate(self, false, true);
59338
59339            // Active and hover states
59340            } else {
59341
59342              // State is on
59343              if (/wn|er|in/.test(type)) {
59344
59345                // mousedown|mouseover|touchbegin
59346                parent[_add](toggle);
59347
59348              // State is off
59349              } else {
59350                parent[_remove](toggle + ' ' + activeClass);
59351              }
59352
59353              // Label hover
59354              if (label.length && labelHover && toggle == hoverClass) {
59355
59356                // mouseout|touchend
59357                label[/ut|nd/.test(type) ? _remove : _add](labelHoverClass);
59358              }
59359            }
59360
59361            if (_mobile) {
59362              event.stopPropagation();
59363            } else {
59364              return false;
59365            }
59366          }
59367        });
59368      });
59369    } else {
59370      return this;
59371    }
59372  };
59373
59374  // Do something with inputs
59375  function operate(input, direct, method) {
59376    var node = input[0],
59377      state = /er/.test(method) ? _indeterminate : /bl/.test(method) ? _disabled : _checked,
59378      active = method == _update ? {
59379        checked: node[_checked],
59380        disabled: node[_disabled],
59381        indeterminate: input.attr(_indeterminate) == 'true' || input.attr(_determinate) == 'false'
59382      } : node[state];
59383
59384    // Check, disable or indeterminate
59385    if (/^(ch|di|in)/.test(method) && !active) {
59386      on(input, state);
59387
59388    // Uncheck, enable or determinate
59389    } else if (/^(un|en|de)/.test(method) && active) {
59390      off(input, state);
59391
59392    // Update
59393    } else if (method == _update) {
59394
59395      // Handle states
59396      for (var each in active) {
59397        if (active[each]) {
59398          on(input, each, true);
59399        } else {
59400          off(input, each, true);
59401        }
59402      }
59403
59404    } else if (!direct || method == 'toggle') {
59405
59406      // Helper or label was clicked
59407      if (!direct) {
59408        input[_callback]('ifClicked');
59409      }
59410
59411      // Toggle checked state
59412      if (active) {
59413        if (node[_type] !== _radio) {
59414          off(input, state);
59415        }
59416      } else {
59417        on(input, state);
59418      }
59419    }
59420  }
59421
59422  // Add checked, disabled or indeterminate state
59423  function on(input, state, keep) {
59424    var node = input[0],
59425      parent = input.parent(),
59426      checked = state == _checked,
59427      indeterminate = state == _indeterminate,
59428      disabled = state == _disabled,
59429      callback = indeterminate ? _determinate : checked ? _unchecked : 'enabled',
59430      regular = option(input, callback + capitalize(node[_type])),
59431      specific = option(input, state + capitalize(node[_type]));
59432
59433    // Prevent unnecessary actions
59434    if (node[state] !== true) {
59435
59436      // Toggle assigned radio buttons
59437      if (!keep && state == _checked && node[_type] == _radio && node.name) {
59438        var form = input.closest('form'),
59439          inputs = 'input[name="' + node.name + '"]';
59440
59441        inputs = form.length ? form.find(inputs) : $(inputs);
59442
59443        inputs.each(function() {
59444          if (this !== node && $(this).data(_iCheck)) {
59445            off($(this), state);
59446          }
59447        });
59448      }
59449
59450      // Indeterminate state
59451      if (indeterminate) {
59452
59453        // Add indeterminate state
59454        node[state] = true;
59455
59456        // Remove checked state
59457        if (node[_checked]) {
59458          off(input, _checked, 'force');
59459        }
59460
59461      // Checked or disabled state
59462      } else {
59463
59464        // Add checked or disabled state
59465        if (!keep) {
59466          node[state] = true;
59467        }
59468
59469        // Remove indeterminate state
59470        if (checked && node[_indeterminate]) {
59471          off(input, _indeterminate, false);
59472        }
59473      }
59474
59475      // Trigger callbacks
59476      callbacks(input, checked, state, keep);
59477    }
59478
59479    // Add proper cursor
59480    if (node[_disabled] && !!option(input, _cursor, true)) {
59481      parent.find('.' + _iCheckHelper).css(_cursor, 'default');
59482    }
59483
59484    // Add state class
59485    parent[_add](specific || option(input, state) || '');
59486
59487    // Set ARIA attribute
59488    if (!!parent.attr('role') && !indeterminate) {
59489      parent.attr('aria-' + (disabled ? _disabled : _checked), 'true');
59490    }
59491
59492    // Remove regular state class
59493    parent[_remove](regular || option(input, callback) || '');
59494  }
59495
59496  // Remove checked, disabled or indeterminate state
59497  function off(input, state, keep) {
59498    var node = input[0],
59499      parent = input.parent(),
59500      checked = state == _checked,
59501      indeterminate = state == _indeterminate,
59502      disabled = state == _disabled,
59503      callback = indeterminate ? _determinate : checked ? _unchecked : 'enabled',
59504      regular = option(input, callback + capitalize(node[_type])),
59505      specific = option(input, state + capitalize(node[_type]));
59506
59507    // Prevent unnecessary actions
59508    if (node[state] !== false) {
59509
59510      // Toggle state
59511      if (indeterminate || !keep || keep == 'force') {
59512        node[state] = false;
59513      }
59514
59515      // Trigger callbacks
59516      callbacks(input, checked, callback, keep);
59517    }
59518
59519    // Add proper cursor
59520    if (!node[_disabled] && !!option(input, _cursor, true)) {
59521      parent.find('.' + _iCheckHelper).css(_cursor, 'pointer');
59522    }
59523
59524    // Remove state class
59525    parent[_remove](specific || option(input, state) || '');
59526
59527    // Set ARIA attribute
59528    if (!!parent.attr('role') && !indeterminate) {
59529      parent.attr('aria-' + (disabled ? _disabled : _checked), 'false');
59530    }
59531
59532    // Add regular state class
59533    parent[_add](regular || option(input, callback) || '');
59534  }
59535
59536  // Remove all traces
59537  function tidy(input, callback) {
59538    if (input.data(_iCheck)) {
59539
59540      // Remove everything except input
59541      input.parent().html(input.attr('style', input.data(_iCheck).s || ''));
59542
59543      // Callback
59544      if (callback) {
59545        input[_callback](callback);
59546      }
59547
59548      // Unbind events
59549      input.off('.i').unwrap();
59550      $(_label + '[for="' + input[0].id + '"]').add(input.closest(_label)).off('.i');
59551    }
59552  }
59553
59554  // Get some option
59555  function option(input, state, regular) {
59556    if (input.data(_iCheck)) {
59557      return input.data(_iCheck).o[state + (regular ? '' : 'Class')];
59558    }
59559  }
59560
59561  // Capitalize some string
59562  function capitalize(string) {
59563    return string.charAt(0).toUpperCase() + string.slice(1);
59564  }
59565
59566  // Executable handlers
59567  function callbacks(input, checked, callback, keep) {
59568    if (!keep) {
59569      if (checked) {
59570        input[_callback]('ifToggled');
59571      }
59572
59573      input[_callback]('change')[_callback]('ifChanged')[_callback]('if' + capitalize(callback));
59574    }
59575  }
59576})(window.jQuery || window.Zepto);
59577
59578define("icheck", function(){});
59579
59580/**
59581 * isMobile.js v0.4.1
59582 *
59583 * A simple library to detect Apple phones and tablets,
59584 * Android phones and tablets, other mobile devices (like blackberry, mini-opera and windows phone),
59585 * and any kind of seven inch device, via user agent sniffing.
59586 *
59587 * @author: Kai Mallea ([email protected])
59588 *
59589 * @license: http://creativecommons.org/publicdomain/zero/1.0/
59590 */
59591(function (global) {
59592
59593    var apple_phone         = /iPhone/i,
59594        apple_ipod          = /iPod/i,
59595        apple_tablet        = /iPad/i,
59596        android_phone       = /(?=.*\bAndroid\b)(?=.*\bMobile\b)/i, // Match 'Android' AND 'Mobile'
59597        android_tablet      = /Android/i,
59598        amazon_phone        = /(?=.*\bAndroid\b)(?=.*\bSD4930UR\b)/i,
59599        amazon_tablet       = /(?=.*\bAndroid\b)(?=.*\b(?:KFOT|KFTT|KFJWI|KFJWA|KFSOWI|KFTHWI|KFTHWA|KFAPWI|KFAPWA|KFARWI|KFASWI|KFSAWI|KFSAWA)\b)/i,
59600        windows_phone       = /Windows Phone/i,
59601        windows_tablet      = /(?=.*\bWindows\b)(?=.*\bARM\b)/i, // Match 'Windows' AND 'ARM'
59602        other_blackberry    = /BlackBerry/i,
59603        other_blackberry_10 = /BB10/i,
59604        other_opera         = /Opera Mini/i,
59605        other_chrome        = /(CriOS|Chrome)(?=.*\bMobile\b)/i,
59606        other_firefox       = /(?=.*\bFirefox\b)(?=.*\bMobile\b)/i, // Match 'Firefox' AND 'Mobile'
59607        seven_inch = new RegExp(
59608            '(?:' +         // Non-capturing group
59609
59610            'Nexus 7' +     // Nexus 7
59611
59612            '|' +           // OR
59613
59614            'BNTV250' +     // B&N Nook Tablet 7 inch
59615
59616            '|' +           // OR
59617
59618            'Kindle Fire' + // Kindle Fire
59619
59620            '|' +           // OR
59621
59622            'Silk' +        // Kindle Fire, Silk Accelerated
59623
59624            '|' +           // OR
59625
59626            'GT-P1000' +    // Galaxy Tab 7 inch
59627
59628            ')',            // End non-capturing group
59629
59630            'i');           // Case-insensitive matching
59631
59632    var match = function(regex, userAgent) {
59633        return regex.test(userAgent);
59634    };
59635
59636    var IsMobileClass = function(userAgent) {
59637        var ua = userAgent || navigator.userAgent;
59638
59639        // Facebook mobile app's integrated browser adds a bunch of strings that
59640        // match everything. Strip it out if it exists.
59641        var tmp = ua.split('[FBAN');
59642        if (typeof tmp[1] !== 'undefined') {
59643            ua = tmp[0];
59644        }
59645
59646        // Twitter mobile app's integrated browser on iPad adds a "Twitter for
59647        // iPhone" string. Same probable happens on other tablet platforms.
59648        // This will confuse detection so strip it out if it exists.
59649        tmp = ua.split('Twitter');
59650        if (typeof tmp[1] !== 'undefined') {
59651            ua = tmp[0];
59652        }
59653
59654        this.apple = {
59655            phone:  match(apple_phone, ua),
59656            ipod:   match(apple_ipod, ua),
59657            tablet: !match(apple_phone, ua) && match(apple_tablet, ua),
59658            device: match(apple_phone, ua) || match(apple_ipod, ua) || match(apple_tablet, ua)
59659        };
59660        this.amazon = {
59661            phone:  match(amazon_phone, ua),
59662            tablet: !match(amazon_phone, ua) && match(amazon_tablet, ua),
59663            device: match(amazon_phone, ua) || match(amazon_tablet, ua)
59664        };
59665        this.android = {
59666            phone:  match(amazon_phone, ua) || match(android_phone, ua),
59667            tablet: !match(amazon_phone, ua) && !match(android_phone, ua) && (match(amazon_tablet, ua) || match(android_tablet, ua)),
59668            device: match(amazon_phone, ua) || match(amazon_tablet, ua) || match(android_phone, ua) || match(android_tablet, ua)
59669        };
59670        this.windows = {
59671            phone:  match(windows_phone, ua),
59672            tablet: match(windows_tablet, ua),
59673            device: match(windows_phone, ua) || match(windows_tablet, ua)
59674        };
59675        this.other = {
59676            blackberry:   match(other_blackberry, ua),
59677            blackberry10: match(other_blackberry_10, ua),
59678            opera:        match(other_opera, ua),
59679            firefox:      match(other_firefox, ua),
59680            chrome:       match(other_chrome, ua),
59681            device:       match(other_blackberry, ua) || match(other_blackberry_10, ua) || match(other_opera, ua) || match(other_firefox, ua) || match(other_chrome, ua)
59682        };
59683        this.seven_inch = match(seven_inch, ua);
59684        this.any = this.apple.device || this.android.device || this.windows.device || this.other.device || this.seven_inch;
59685
59686        // excludes 'other' devices and ipods, targeting touchscreen phones
59687        this.phone = this.apple.phone || this.android.phone || this.windows.phone;
59688
59689        // excludes 7 inch devices, classifying as phone or tablet is left to the user
59690        this.tablet = this.apple.tablet || this.android.tablet || this.windows.tablet;
59691
59692        if (typeof window === 'undefined') {
59693            return this;
59694        }
59695    };
59696
59697    var instantiate = function() {
59698        var IM = new IsMobileClass();
59699        IM.Class = IsMobileClass;
59700        return IM;
59701    };
59702
59703    if (typeof module !== 'undefined' && module.exports && typeof window === 'undefined') {
59704        //node
59705        module.exports = IsMobileClass;
59706    } else if (typeof module !== 'undefined' && module.exports && typeof window !== 'undefined') {
59707        //browserify
59708        module.exports = instantiate();
59709    } else if (typeof define === 'function' && define.amd) {
59710        //AMD
59711        define('isMobile', [], global.isMobile = instantiate());
59712    } else {
59713        global.isMobile = instantiate();
59714    }
59715
59716})(this);
59717
59718/*!
59719	Autosize v1.17.8 - 2013-09-07
59720	Automatically adjust textarea height based on user input.
59721	(c) 2013 Jack Moore - http://www.jacklmoore.com/autosize
59722	license: http://www.opensource.org/licenses/mit-license.php
59723*/
59724(function (factory) {
59725	if (typeof define === 'function' && define.amd) {
59726		// AMD. Register as an anonymous module.
59727		define('jqueryAutosize',['jquery'], factory);
59728	} else {
59729		// Browser globals: jQuery or jQuery-like library, such as Zepto
59730		factory(window.jQuery || window.$);
59731	}
59732}(function ($) {
59733	var
59734	defaults = {
59735		className: 'autosizejs',
59736		append: '',
59737		callback: false,
59738		resizeDelay: 10
59739	},
59740
59741	// border:0 is unnecessary, but avoids a bug in FireFox on OSX
59742	copy = '<textarea tabindex="-1" style="position:absolute; top:-999px; left:0; right:auto; bottom:auto; border:0; padding: 0; -moz-box-sizing:content-box; -webkit-box-sizing:content-box; box-sizing:content-box; word-wrap:break-word; height:0 !important; min-height:0 !important; overflow:hidden; transition:none; -webkit-transition:none; -moz-transition:none;"/>',
59743
59744	// line-height is conditionally included because IE7/IE8/old Opera do not return the correct value.
59745	typographyStyles = [
59746		'fontFamily',
59747		'fontSize',
59748		'fontWeight',
59749		'fontStyle',
59750		'letterSpacing',
59751		'textTransform',
59752		'wordSpacing',
59753		'textIndent'
59754	],
59755
59756	// to keep track which textarea is being mirrored when adjust() is called.
59757	mirrored,
59758
59759	// the mirror element, which is used to calculate what size the mirrored element should be.
59760	mirror = $(copy).data('autosize', true)[0];
59761
59762	// test that line-height can be accurately copied.
59763	mirror.style.lineHeight = '99px';
59764	if ($(mirror).css('lineHeight') === '99px') {
59765		typographyStyles.push('lineHeight');
59766	}
59767	mirror.style.lineHeight = '';
59768
59769	$.fn.autosize = function (options) {
59770		if (!this.length) {
59771			return this;
59772		}
59773
59774		options = $.extend({}, defaults, options || {});
59775
59776		if (mirror.parentNode !== document.body) {
59777			$(document.body).append(mirror);
59778		}
59779
59780		return this.each(function () {
59781			var
59782			ta = this,
59783			$ta = $(ta),
59784			maxHeight,
59785			minHeight,
59786			boxOffset = 0,
59787			callback = $.isFunction(options.callback),
59788			originalStyles = {
59789				height: ta.style.height,
59790				overflow: ta.style.overflow,
59791				overflowY: ta.style.overflowY,
59792				wordWrap: ta.style.wordWrap,
59793				resize: ta.style.resize
59794			},
59795			timeout,
59796			width = $ta.width();
59797
59798			if ($ta.data('autosize')) {
59799				// exit if autosize has already been applied, or if the textarea is the mirror element.
59800				return;
59801			}
59802			$ta.data('autosize', true);
59803
59804			if ($ta.css('box-sizing') === 'border-box' || $ta.css('-moz-box-sizing') === 'border-box' || $ta.css('-webkit-box-sizing') === 'border-box'){
59805				boxOffset = $ta.outerHeight() - $ta.height();
59806			}
59807
59808			// IE8 and lower return 'auto', which parses to NaN, if no min-height is set.
59809			minHeight = Math.max(parseInt($ta.css('minHeight'), 10) - boxOffset || 0, $ta.height());
59810
59811			$ta.css({
59812				overflow: 'hidden',
59813				overflowY: 'hidden',
59814				wordWrap: 'break-word', // horizontal overflow is hidden, so break-word is necessary for handling words longer than the textarea width
59815				resize: ($ta.css('resize') === 'none' || $ta.css('resize') === 'vertical') ? 'none' : 'horizontal'
59816			});
59817
59818			// The mirror width must exactly match the textarea width, so using getBoundingClientRect because it doesn't round the sub-pixel value.
59819			function setWidth() {
59820				var style, width;
59821				
59822				if ('getComputedStyle' in window) {
59823					style = window.getComputedStyle(ta);
59824					width = ta.getBoundingClientRect().width;
59825
59826					$.each(['paddingLeft', 'paddingRight', 'borderLeftWidth', 'borderRightWidth'], function(i,val){
59827						width -= parseInt(style[val],10);
59828					});
59829
59830					mirror.style.width = width + 'px';
59831				}
59832				else {
59833					// window.getComputedStyle, getBoundingClientRect returning a width are unsupported and unneeded in IE8 and lower.
59834					mirror.style.width = Math.max($ta.width(), 0) + 'px';
59835				}
59836			}
59837
59838			function initMirror() {
59839				var styles = {};
59840
59841				mirrored = ta;
59842				mirror.className = options.className;
59843				maxHeight = parseInt($ta.css('maxHeight'), 10);
59844
59845				// mirror is a duplicate textarea located off-screen that
59846				// is automatically updated to contain the same text as the
59847				// original textarea.  mirror always has a height of 0.
59848				// This gives a cross-browser supported way getting the actual
59849				// height of the text, through the scrollTop property.
59850				$.each(typographyStyles, function(i,val){
59851					styles[val] = $ta.css(val);
59852				});
59853				$(mirror).css(styles);
59854
59855				setWidth();
59856
59857				// Chrome-specific fix:
59858				// When the textarea y-overflow is hidden, Chrome doesn't reflow the text to account for the space
59859				// made available by removing the scrollbar. This workaround triggers the reflow for Chrome.
59860				if (window.chrome) {
59861					var width = ta.style.width;
59862					ta.style.width = '0px';
59863					var ignore = ta.offsetWidth;
59864					ta.style.width = width;
59865				}
59866			}
59867
59868			// Using mainly bare JS in this function because it is going
59869			// to fire very often while typing, and needs to very efficient.
59870			function adjust() {
59871				var height, original;
59872
59873				if (mirrored !== ta) {
59874					initMirror();
59875				} else {
59876					setWidth();
59877				}
59878
59879				mirror.value = ta.value + options.append;
59880				mirror.style.overflowY = ta.style.overflowY;
59881				original = parseInt(ta.style.height,10);
59882
59883				// Setting scrollTop to zero is needed in IE8 and lower for the next step to be accurately applied
59884				mirror.scrollTop = 0;
59885
59886				mirror.scrollTop = 9e4;
59887
59888				// Using scrollTop rather than scrollHeight because scrollHeight is non-standard and includes padding.
59889				height = mirror.scrollTop;
59890
59891				if (maxHeight && height > maxHeight) {
59892					ta.style.overflowY = 'scroll';
59893					height = maxHeight;
59894				} else {
59895					ta.style.overflowY = 'hidden';
59896					if (height < minHeight) {
59897						height = minHeight;
59898					}
59899				}
59900
59901				height += boxOffset;
59902
59903				if (original !== height) {
59904					ta.style.height = height + 'px';
59905					if (callback) {
59906						options.callback.call(ta,ta);
59907					}
59908				}
59909			}
59910
59911			function resize () {
59912				clearTimeout(timeout);
59913				timeout = setTimeout(function(){
59914					var newWidth = $ta.width();
59915
59916					if (newWidth !== width) {
59917						width = newWidth;
59918						adjust();
59919					}
59920				}, parseInt(options.resizeDelay,10));
59921			}
59922
59923			if ('onpropertychange' in ta) {
59924				if ('oninput' in ta) {
59925					// Detects IE9.  IE9 does not fire onpropertychange or oninput for deleti
59925ons,
59926					// so binding to onkeyup to catch most of those occasions.  There is no way that I
59927					// know of to detect something like 'cut' in IE9.
59928					$ta.on('input.autosize keyup.autosize', adjust);
59929				} else {
59930					// IE7 / IE8
59931					$ta.on('propertychange.autosize', function(){
59932						if(event.propertyName === 'value'){
59933							adjust();
59934						}
59935					});
59936				}
59937			} else {
59938				// Modern Browsers
59939				$ta.on('input.autosize', adjust);
59940			}
59941
59942			// Set options.resizeDelay to false if using fixed-width textarea elements.
59943			// Uses a timeout and width check to reduce the amount of times adjust needs to be called after window resize.
59944
59945			if (options.resizeDelay !== false) {
59946				$(window).on('resize.autosize', resize);
59947			}
59948
59949			// Event for manual triggering if needed.
59950			// Should only be needed when the value of the textarea is changed through JavaScript rather than user input.
59951			$ta.on('autosize.resize', adjust);
59952
59953			// Event for manual triggering that also forces the styles to update as well.
59954			// Should only be needed if one of typography styles of the textarea change, and the textarea is already the target of the adjust method.
59955			$ta.on('autosize.resizeIncludeStyle', function() {
59956				mirrored = null;
59957				adjust();
59958			});
59959
59960			$ta.on('autosize.destroy', function(){
59961				mirrored = null;
59962				clearTimeout(timeout);
59963				$(window).off('resize', resize);
59964				$ta
59965					.off('autosize')
59966					.off('.autosize')
59967					.css(originalStyles)
59968					.removeData('autosize');
59969			});
59970
59971			// Call adjust in case the textarea already contains text.
59972			adjust();
59973		});
59974	};
59975}));
59976
59977(function() {
59978  var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
59979    __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; };
59980
59981  (function($) {
59982    /*
59983    $(".my-pagination").pagination();
59984    
59985    $(".my-pagination").pagination({total_pages: 3, current_page: 1});
59986    
59987    $(".my-pagination").pagination({
59988      total_pages: 3,
59989      current_page: 1,
59990      callback: function(event, page) {
59991        alert("Clicked: " + page);
59992      }
59993    });
59994    */
59995
59996    var PaginationView;
59997
59998    $.fn.pagination = function(options) {
59999      return this.each(function() {
60000        return new PaginationView($(this), options).render();
60001      });
60002    };
60003    return PaginationView = (function() {
60004      function PaginationView(el, options) {
60005        var defaults;
60006
60007        this.el = el;
60008        this.change = __bind(this.change, this);
60009        this.clicked = __bind(this.clicked, this);
60010        this.isValidPage = __bind(this.isValidPage, this);
60011        this.render = __bind(this.render, this);
60012        this.pages = __bind(this.pages, this);
60013        this.buildLink = __bind(this.buildLink, this);
60014        this.buildLi = __bind(this.buildLi, this);
60015        this.buildLinks = __bind(this.buildLinks, this);
60016        defaults = {
60017          current_page: 1,
60018          total_pages: 1,
60019          next: "<svg height=\"14px\" width=\"14px\" xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" x=\"0\" y=\"0\" viewBox=\"0 0 60 60\" enable-background=\"new 0 0 36 36\" xml:space=\"preserve\"><polygon points=\"15.3 60 13.8 58.2 43 30 13.8 1.7 15.3 0 46.3 30 \"/></svg>",
60020          prev: "<svg height=\"14px\" width=\"14px\" xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" x=\"0\" y=\"0\" viewBox=\"0 0 60 60\" enable-background=\"new 0 0 36 36\" xml:space=\"preserve\"><polygon points=\"13.8 30 44.8 0 46.3 1.7 17 30 46.3 58.3 44.8 60 \"/></svg>",
60021          first: false,
60022          last: false,
60023          display_max: 2,
60024          ignore_single_page: true,
60025          no_turbolink: false
60026        };
60027        this.settings = $.extend(defaults, options);
60028        if ($(document).on) {
60029          $(this.el).on("click", "a", this.clicked);
60030        } else {
60031          $("a", this.el).live("click", this.clicked);
60032        }
60033        this.el.data("paginationView", this);
60034      }
60035
60036      PaginationView.prototype.buildLinks = function() {
60037        var current_page, links, page, _i, _len, _ref;
60038
60039        current_page = this.settings.current_page;
60040        links = [];
60041        if (this.settings.first) {
60042          links.push(this.buildLi(1, this.settings.first));
60043        }
60044        if (this.settings.prev) {
60045          links.push(this.buildLi(current_page - 1, this.settings.prev));
60046        }
60047        _ref = this.pages();
60048        for (_i = 0, _len = _ref.length; _i < _len; _i++) {
60049          page = _ref[_i];
60050          links.push(this.buildLi(page, page));
60051        }
60052        if (this.settings.next) {
60053          links.push(this.buildLi(current_page + 1, this.settings.next));
60054        }
60055        if (this.settings.last) {
60056          links.push(this.buildLi(this.settings.total_pages, this.settings.last));
60057        }
60058        return links;
60059      };
60060
60061      PaginationView.prototype.buildLi = function(page, text) {
60062        if (text == null) {
60063          text = page;
60064        }
60065        return "<li>" + (this.buildLink(page, text)) + "</li>";
60066      };
60067
60068      PaginationView.prototype.buildLink = function(page, text) {
60069        var data_attr;
60070
60071        if (text == null) {
60072          text = page;
60073        }
60074        if (this.settings.no_turbolink) {
60075          data_attr = " data-no-turbolink='1'";
60076        } else {
60077          data_attr = "";
60078        }
60079        return "<a href='#' data-page='" + page + "'" + data_attr + ">" + text + "</a>";
60080      };
60081
60082      PaginationView.prototype.pages = function() {
60083        var buf, current_page, max, page, pages, total_pages, _i, _j, _k, _l, _m, _ref, _ref1, _ref2, _ref3;
60084
60085        total_pages = this.settings.total_pages;
60086        current_page = this.settings.current_page;
60087        pages = [];
60088        max = this.settings.display_max;
60089        if (total_pages > 10) {
60090          pages.push(1);
60091          if (current_page > max - 1) {
60092            pages.push("..");
60093          }
60094          if (current_page === total_pages) {
60095            for (page = _i = _ref = total_pages - max; _ref <= total_pages ? _i <= total_pages : _i >= total_pages; page = _ref <= total_pages ? ++_i : --_i) {
60096              pages.push(page);
60097            }
60098          }
60099          if (total_pages - current_page < max - 1) {
60100            for (page = _j = _ref1 = total_pages - max; _ref1 <= total_pages ? _j <= total_pages : _j >= total_pages; page = _ref1 <= total_pages ? ++_j : --_j) {
60101              pages.push(page);
60102            }
60103          } else if (current_page > max - 1) {
60104            buf = max / 2;
60105            for (page = _k = _ref2 = current_page - buf, _ref3 = current_page + buf; _ref2 <= _ref3 ? _k <= _ref3 : _k >= _ref3; page = _ref2 <= _ref3 ? ++_k : --_k) {
60106              pages.push(page);
60107            }
60108          } else if (current_page <= max - 1) {
60109            for (page = _l = 2; 2 <= max ? _l <= max : _l >= max; page = 2 <= max ? ++_l : --_l) {
60110              pages.push(page);
60111            }
60112          }
60113          pages = $.grep(pages, function(v, k) {
60114            return $.inArray(v, pages) === k;
60115          });
60116          if (__indexOf.call(pages, total_pages) < 0) {
60117            if (!((total_pages - current_page) < max - 1)) {
60118              pages.push("..");
60119            }
60120            pages.push(total_pages);
60121          }
60122        } else {
60123          for (page = _m = 1; 1 <= total_pages ? _m <= total_pages : _m >= total_pages; page = 1 <= total_pages ? ++_m : --_m) {
60124            pages.push(page);
60125          }
60126        }
60127        return pages;
60128      };
60129
60130      PaginationView.prototype.render = function() {
60131        var html, link, _i, _len, _ref;
60132
60133        this.el.html("");
60134        if (this.settings.total_pages === 1 && this.settings.ignore_single_page) {
60135          return;
60136        }
60137        html = ["<div class='jquery-bootstrap-pagination'>"];
60138        html.push("<ul class='pagination'>");
60139        _ref = this.buildLinks();
60140        for (_i = 0, _len = _ref.length; _i < _len; _i++) {
60141          link = _ref[_i];
60142          html.push(link);
60143        }
60144        html.push("</ul>");
60145        html.push("</div>");
60146        this.el.html(html.join("\n"));
60147        $("[data-page=" + this.settings.current_page + "]", this.el).closest("li").addClass("active");
60148        $("[data-page='..']", this.el).closest("li").addClass("disabled");
60149        $("[data-page='0']", this.el).closest("li").addClass("disabled");
60150        $("[data-page='" + (this.settings.total_pages + 1) + "']", this.el).closest("li").addClass("disabled");
60151        if (this.settings.current_page === 1 && this.settings.first) {
60152          $("li:first", this.el).removeClass("active").addClass("disabled");
60153        }
60154        if (this.settings.current_page === this.settings.total_pages && this.settings.last) {
60155          return $("li:last", this.el).removeClass("active").addClass("disabled");
60156        }
60157      };
60158
60159      PaginationView.prototype.isValidPage = function(page) {
60160        return page > 0 && page !== this.settings.current_page && page <= this.settings.total_pages;
60161      };
60162
60163      PaginationView.prototype.clicked = function(event) {
60164        var page;
60165
60166        page = parseInt($(event.target).attr("data-page"));
60167        if (!this.isValidPage(page)) {
60168          return;
60169        }
60170        if (this.settings.callback != null) {
60171          this.settings.callback(event, page);
60172        }
60173        return this.change(page);
60174      };
60175
60176      PaginationView.prototype.change = function(page) {
60177        page = parseInt(page);
60178        if (!this.isValidPage(page)) {
60179          return;
60180        }
60181        this.settings.current_page = page;
60182        return this.render();
60183      };
60184
60185      return PaginationView;
60186
60187    })();
60188  })(jQuery);
60189
60190}).call(this);
60191
60192define("jqueryBootstrapPagination", ["jquery"], function(){});
60193
60194/*! jQuery UI - v1.11.4+CommonJS - 2015-08-28
60195* http://jqueryui.com
60196* Includes: widget.js
60197* Copyright 2015 jQuery Foundation and other contributors; Licensed MIT */
60198
60199(function( factory ) {
60200	if ( typeof define === "function" && define.amd ) {
60201
60202		// AMD. Register as an anonymous module.
60203		define('jquery.ui.widget',[ "jquery" ], factory );
60204
60205	} else if ( typeof exports === "object" ) {
60206
60207		// Node/CommonJS
60208		factory( require( "jquery" ) );
60209
60210	} else {
60211
60212		// Browser globals
60213		factory( jQuery );
60214	}
60215}(function( $ ) {
vendor: 15,589 bytes, lines 60215-60763
60215
60216/*!
60217 * jQuery UI Widget 1.11.4
60218 * http://jqueryui.com
60219 *
60220 * Copyright jQuery Foundation and other contributors
60221 * Released under the MIT license.
60222 * http://jquery.org/license
60223 *
60224 * http://api.jqueryui.com/jQuery.widget/
60225 */
60226
60227
60228var widget_uuid = 0,
60229	widget_slice = Array.prototype.slice;
60230
60231$.cleanData = (function( orig ) {
60232	return function( elems ) {
60233		var events, elem, i;
60234		for ( i = 0; (elem = elems[i]) != null; i++ ) {
60235			try {
60236
60237				// Only trigger remove when necessary to save time
60238				events = $._data( elem, "events" );
60239				if ( events && events.remove ) {
60240					$( elem ).triggerHandler( "remove" );
60241				}
60242
60243			// http://bugs.jquery.com/ticket/8235
60244			} catch ( e ) {}
60245		}
60246		orig( elems );
60247	};
60248})( $.cleanData );
60249
60250$.widget = function( name, base, prototype ) {
60251	var fullName, existingConstructor, constructor, basePrototype,
60252		// proxiedPrototype allows the provided prototype to remain unmodified
60253		// so that it can be used as a mixin for multiple widgets (#8876)
60254		proxiedPrototype = {},
60255		namespace = name.split( "." )[ 0 ];
60256
60257	name = name.split( "." )[ 1 ];
60258	fullName = namespace + "-" + name;
60259
60260	if ( !prototype ) {
60261		prototype = base;
60262		base = $.Widget;
60263	}
60264
60265	// create selector for plugin
60266	$.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
60267		return !!$.data( elem, fullName );
60268	};
60269
60270	$[ namespace ] = $[ namespace ] || {};
60271	existingConstructor = $[ namespace ][ name ];
60272	constructor = $[ namespace ][ name ] = function( options, element ) {
60273		// allow instantiation without "new" keyword
60274		if ( !this._createWidget ) {
60275			return new constructor( options, element );
60276		}
60277
60278		// allow instantiation without initializing for simple inheritance
60279		// must use "new" keyword (the code above always passes args)
60280		if ( arguments.length ) {
60281			this._createWidget( options, element );
60282		}
60283	};
60284	// extend with the existing constructor to carry over any static properties
60285	$.extend( constructor, existingConstructor, {
60286		version: prototype.version,
60287		// copy the object used to create the prototype in case we need to
60288		// redefine the widget later
60289		_proto: $.extend( {}, prototype ),
60290		// track widgets that inherit from this widget in case this widget is
60291		// redefined after a widget inherits from it
60292		_childConstructors: []
60293	});
60294
60295	basePrototype = new base();
60296	// we need to make the options hash a property directly on the new instance
60297	// otherwise we'll modify the options hash on the prototype that we're
60298	// inheriting from
60299	basePrototype.options = $.widget.extend( {}, basePrototype.options );
60300	$.each( prototype, function( prop, value ) {
60301		if ( !$.isFunction( value ) ) {
60302			proxiedPrototype[ prop ] = value;
60303			return;
60304		}
60305		proxiedPrototype[ prop ] = (function() {
60306			var _super = function() {
60307					return base.prototype[ prop ].apply( this, arguments );
60308				},
60309				_superApply = function( args ) {
60310					return base.prototype[ prop ].apply( this, args );
60311				};
60312			return function() {
60313				var __super = this._super,
60314					__superApply = this._superApply,
60315					returnValue;
60316
60317				this._super = _super;
60318				this._superApply = _superApply;
60319
60320				returnValue = value.apply( this, arguments );
60321
60322				this._super = __super;
60323				this._superApply = __superApply;
60324
60325				return returnValue;
60326			};
60327		})();
60328	});
60329	constructor.prototype = $.widget.extend( basePrototype, {
60330		// TODO: remove support for widgetEventPrefix
60331		// always use the name + a colon as the prefix, e.g., draggable:start
60332		// don't prefix for widgets that aren't DOM-based
60333		widgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name
60334	}, proxiedPrototype, {
60335		constructor: constructor,
60336		namespace: namespace,
60337		widgetName: name,
60338		widgetFullName: fullName
60339	});
60340
60341	// If this widget is being redefined then we need to find all widgets that
60342	// are inheriting from it and redefine all of them so that they inherit from
60343	// the new version of this widget. We're essentially trying to replace one
60344	// level in the prototype chain.
60345	if ( existingConstructor ) {
60346		$.each( existingConstructor._childConstructors, function( i, child ) {
60347			var childPrototype = child.prototype;
60348
60349			// redefine the child widget using the same prototype that was
60350			// originally used, but inherit from the new version of the base
60351			$.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );
60352		});
60353		// remove the list of existing child constructors from the old constructor
60354		// so the old child constructors can be garbage collected
60355		delete existingConstructor._childConstructors;
60356	} else {
60357		base._childConstructors.push( constructor );
60358	}
60359
60360	$.widget.bridge( name, constructor );
60361
60362	return constructor;
60363};
60364
60365$.widget.extend = function( target ) {
60366	var input = widget_slice.call( arguments, 1 ),
60367		inputIndex = 0,
60368		inputLength = input.length,
60369		key,
60370		value;
60371	for ( ; inputIndex < inputLength; inputIndex++ ) {
60372		for ( key in input[ inputIndex ] ) {
60373			value = input[ inputIndex ][ key ];
60374			if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
60375				// Clone objects
60376				if ( $.isPlainObject( value ) ) {
60377					target[ key ] = $.isPlainObject( target[ key ] ) ?
60378						$.widget.extend( {}, target[ key ], value ) :
60379						// Don't extend strings, arrays, etc. with objects
60380						$.widget.extend( {}, value );
60381				// Copy everything else by reference
60382				} else {
60383					target[ key ] = value;
60384				}
60385			}
60386		}
60387	}
60388	return target;
60389};
60390
60391$.widget.bridge = function( name, object ) {
60392	var fullName = object.prototype.widgetFullName || name;
60393	$.fn[ name ] = function( options ) {
60394		var isMethodCall = typeof options === "string",
60395			args = widget_slice.call( arguments, 1 ),
60396			returnValue = this;
60397
60398		if ( isMethodCall ) {
60399			this.each(function() {
60400				var methodValue,
60401					instance = $.data( this, fullName );
60402				if ( options === "instance" ) {
60403					returnValue = instance;
60404					return false;
60405				}
60406				if ( !instance ) {
60407					return $.error( "cannot call methods on " + name + " prior to initialization; " +
60408						"attempted to call method '" + options + "'" );
60409				}
60410				if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {
60411					return $.error( "no such method '" + options + "' for " + name + " widget instance" );
60412				}
60413				methodValue = instance[ options ].apply( instance, args );
60414				if ( methodValue !== instance && methodValue !== undefined ) {
60415					returnValue = methodValue && methodValue.jquery ?
60416						returnValue.pushStack( methodValue.get() ) :
60417						methodValue;
60418					return false;
60419				}
60420			});
60421		} else {
60422
60423			// Allow multiple hashes to be passed on init
60424			if ( args.length ) {
60425				options = $.widget.extend.apply( null, [ options ].concat(args) );
60426			}
60427
60428			this.each(function() {
60429				var instance = $.data( this, fullName );
60430				if ( instance ) {
60431					instance.option( options || {} );
60432					if ( instance._init ) {
60433						instance._init();
60434					}
60435				} else {
60436					$.data( this, fullName, new object( options, this ) );
60437				}
60438			});
60439		}
60440
60441		return returnValue;
60442	};
60443};
60444
60445$.Widget = function( /* options, element */ ) {};
60446$.Widget._childConstructors = [];
60447
60448$.Widget.prototype = {
60449	widgetName: "widget",
60450	widgetEventPrefix: "",
60451	defaultElement: "<div>",
60452	options: {
60453		disabled: false,
60454
60455		// callbacks
60456		create: null
60457	},
60458	_createWidget: function( options, element ) {
60459		element = $( element || this.defaultElement || this )[ 0 ];
60460		this.element = $( element );
60461		this.uuid = widget_uuid++;
60462		this.eventNamespace = "." + this.widgetName + this.uuid;
60463
60464		this.bindings = $();
60465		this.hoverable = $();
60466		this.focusable = $();
60467
60468		if ( element !== this ) {
60469			$.data( element, this.widgetFullName, this );
60470			this._on( true, this.element, {
60471				remove: function( event ) {
60472					if ( event.target === element ) {
60473						this.destroy();
60474					}
60475				}
60476			});
60477			this.document = $( element.style ?
60478				// element within the document
60479				element.ownerDocument :
60480				// element is window or document
60481				element.document || element );
60482			this.window = $( this.document[0].defaultView || this.document[0].parentWindow );
60483		}
60484
60485		this.options = $.widget.extend( {},
60486			this.options,
60487			this._getCreateOptions(),
60488			options );
60489
60490		this._create();
60491		this._trigger( "create", null, this._getCreateEventData() );
60492		this._init();
60493	},
60494	_getCreateOptions: $.noop,
60495	_getCreateEventData: $.noop,
60496	_create: $.noop,
60497	_init: $.noop,
60498
60499	destroy: function() {
60500		this._destroy();
60501		// we can probably remove the unbind calls in 2.0
60502		// all event bindings should go through this._on()
60503		this.element
60504			.unbind( this.eventNamespace )
60505			.removeData( this.widgetFullName )
60506			// support: jquery <1.6.3
60507			// http://bugs.jquery.com/ticket/9413
60508			.removeData( $.camelCase( this.widgetFullName ) );
60509		this.widget()
60510			.unbind( this.eventNamespace )
60511			.removeAttr( "aria-disabled" )
60512			.removeClass(
60513				this.widgetFullName + "-disabled " +
60514				"ui-state-disabled" );
60515
60516		// clean up events and states
60517		this.bindings.unbind( this.eventNamespace );
60518		this.hoverable.removeClass( "ui-state-hover" );
60519		this.focusable.removeClass( "ui-state-focus" );
60520	},
60521	_destroy: $.noop,
60522
60523	widget: function() {
60524		return this.element;
60525	},
60526
60527	option: function( key, value ) {
60528		var options = key,
60529			parts,
60530			curOption,
60531			i;
60532
60533		if ( arguments.length === 0 ) {
60534			// don't return a reference to the internal hash
60535			return $.widget.extend( {}, this.options );
60536		}
60537
60538		if ( typeof key === "string" ) {
60539			// handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
60540			options = {};
60541			parts = key.split( "." );
60542			key = parts.shift();
60543			if ( parts.length ) {
60544				curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
60545				for ( i = 0; i < parts.length - 1; i++ ) {
60546					curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
60547					curOption = curOption[ parts[ i ] ];
60548				}
60549				key = parts.pop();
60550				if ( arguments.length === 1 ) {
60551					return curOption[ key ] === undefined ? null : curOption[ key ];
60552				}
60553				curOption[ key ] = value;
60554			} else {
60555				if ( arguments.length === 1 ) {
60556					return this.options[ key ] === undefined ? null : this.options[ key ];
60557				}
60558				options[ key ] = value;
60559			}
60560		}
60561
60562		this._setOptions( options );
60563
60564		return this;
60565	},
60566	_setOptions: function( options ) {
60567		var key;
60568
60569		for ( key in options ) {
60570			this._setOption( key, options[ key ] );
60571		}
60572
60573		return this;
60574	},
60575	_setOption: function( key, value ) {
60576		this.options[ key ] = value;
60577
60578		if ( key === "disabled" ) {
60579			this.widget()
60580				.toggleClass( this.widgetFullName + "-disabled", !!value );
60581
60582			// If the widget is becoming disabled, then nothing is interactive
60583			if ( value ) {
60584				this.hoverable.removeClass( "ui-state-hover" );
60585				this.focusable.removeClass( "ui-state-focus" );
60586			}
60587		}
60588
60589		return this;
60590	},
60591
60592	enable: function() {
60593		return this._setOptions({ disabled: false });
60594	},
60595	disable: function() {
60596		return this._setOptions({ disabled: true });
60597	},
60598
60599	_on: function( suppressDisabledCheck, element, handlers ) {
60600		var delegateElement,
60601			instance = this;
60602
60603		// no suppressDisabledCheck flag, shuffle arguments
60604		if ( typeof suppressDisabledCheck !== "boolean" ) {
60605			handlers = element;
60606			element = suppressDisabledCheck;
60607			suppressDisabledCheck = false;
60608		}
60609
60610		// no element argument, shuffle and use this.element
60611		if ( !handlers ) {
60612			handlers = element;
60613			element = this.element;
60614			delegateElement = this.widget();
60615		} else {
60616			element = delegateElement = $( element );
60617			this.bindings = this.bindings.add( element );
60618		}
60619
60620		$.each( handlers, function( event, handler ) {
60621			function handlerProxy() {
60622				// allow widgets to customize the disabled handling
60623				// - disabled as an array instead of boolean
60624				// - disabled class as method for disabling individual parts
60625				if ( !suppressDisabledCheck &&
60626						( instance.options.disabled === true ||
60627							$( this ).hasClass( "ui-state-disabled" ) ) ) {
60628					return;
60629				}
60630				return ( typeof handler === "string" ? instance[ handler ] : handler )
60631					.apply( instance, arguments );
60632			}
60633
60634			// copy the guid so direct unbinding works
60635			if ( typeof handler !== "string" ) {
60636				handlerProxy.guid = handler.guid =
60637					handler.guid || handlerProxy.guid || $.guid++;
60638			}
60639
60640			var match = event.match( /^([\w:-]*)\s*(.*)$/ ),
60641				eventName = match[1] + instance.eventNamespace,
60642				selector = match[2];
60643			if ( selector ) {
60644				delegateElement.delegate( selector, eventName, handlerProxy );
60645			} else {
60646				element.bind( eventName, handlerProxy );
60647			}
60648		});
60649	},
60650
60651	_off: function( element, eventName ) {
60652		eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) +
60653			this.eventNamespace;
60654		element.unbind( eventName ).undelegate( eventName );
60655
60656		// Clear the stack to avoid memory leaks (#10056)
60657		this.bindings = $( this.bindings.not( element ).get() );
60658		this.focusable = $( this.focusable.not( element ).get() );
60659		this.hoverable = $( this.hoverable.not( element ).get() );
60660	},
60661
60662	_delay: function( handler, delay ) {
60663		function handlerProxy() {
60664			return ( typeof handler === "string" ? instance[ handler ] : handler )
60665				.apply( instance, arguments );
60666		}
60667		var instance = this;
60668		return setTimeout( handlerProxy, delay || 0 );
60669	},
60670
60671	_hoverable: function( element ) {
60672		this.hoverable = this.hoverable.add( element );
60673		this._on( element, {
60674			mouseenter: function( event ) {
60675				$( event.currentTarget ).addClass( "ui-state-hover" );
60676			},
60677			mouseleave: function( event ) {
60678				$( event.currentTarget ).removeClass( "ui-state-hover" );
60679			}
60680		});
60681	},
60682
60683	_focusable: function( element ) {
60684		this.focusable = this.focusable.add( element );
60685		this._on( element, {
60686			focusin: function( event ) {
60687				$( event.currentTarget ).addClass( "ui-state-focus" );
60688			},
60689			focusout: function( event ) {
60690				$( event.currentTarget ).removeClass( "ui-state-focus" );
60691			}
60692		});
60693	},
60694
60695	_trigger: function( type, event, data ) {
60696		var prop, orig,
60697			callback = this.options[ type ];
60698
60699		data = data || {};
60700		event = $.Event( event );
60701		event.type = ( type === this.widgetEventPrefix ?
60702			type :
60703			this.widgetEventPrefix + type ).toLowerCase();
60704		// the original event may come from any element
60705		// so we need to reset the target on the new event
60706		event.target = this.element[ 0 ];
60707
60708		// copy original event properties over to the new event
60709		orig = event.originalEvent;
60710		if ( orig ) {
60711			for ( prop in orig ) {
60712				if ( !( prop in event ) ) {
60713					event[ prop ] = orig[ prop ];
60714				}
60715			}
60716		}
60717
60718		this.element.trigger( event, data );
60719		return !( $.isFunction( callback ) &&
60720			callback.apply( this.element[0], [ event ].concat( data ) ) === false ||
60721			event.isDefaultPrevented() );
60722	}
60723};
60724
60725$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
60726	$.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
60727		if ( typeof options === "string" ) {
60728			options = { effect: options };
60729		}
60730		var hasOptions,
60731			effectName = !options ?
60732				method :
60733				options === true || typeof options === "number" ?
60734					defaultEffect :
60735					options.effect || defaultEffect;
60736		options = options || {};
60737		if ( typeof options === "number" ) {
60738			options = { duration: options };
60739		}
60740		hasOptions = !$.isEmptyObject( options );
60741		options.complete = callback;
60742		if ( options.delay ) {
60743			element.delay( options.delay );
60744		}
60745		if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
60746			element[ method ]( options );
60747		} else if ( effectName !== method && element[ effectName ] ) {
60748			element[ effectName ]( options.duration, options.easing, callback );
60749		} else {
60750			element.queue(function( next ) {
60751				$( this )[ method ]();
60752				if ( callback ) {
60753					callback.call( element[ 0 ] );
60754				}
60755				next();
60756			});
60757		}
60758	};
60759});
60760
60761var widget = $.widget;
60762
60763
60764
60765}));
60766
60767/*
60768 * jQuery File Upload Plugin
60769 * https://github.com/blueimp/jQuery-File-Upload
60770 *
60771 * Copyright 2010, Sebastian Tschan
60772 * https://blueimp.net
60773 *
60774 * Licensed under the MIT license:
60775 * http://www.opensource.org/licenses/MIT
60776 */
60777
60778/* jshint nomen:false */
60779/* global define, require, window, document, location, Blob, FormData */
60780
60781;(function (factory) {
60782    'use strict';
60783    if (typeof define === 'function' && define.amd) {
60784        // Register as an anonymous AMD module:
60785        define('jquery.fileupload',[
60786            'jquery',
60787            'jquery-ui/widget'
60788        ], factory);
60789    } else if (typeof exports === 'object') {
60790        // Node/CommonJS:
60791        factory(
60792            require('jquery'),
60793            require('./vendor/jquery.ui.widget')
60794        );
60795    } else {
60796        // Browser globals:
60797        factory(window.jQuery);
60798    }
60799}(function ($) {
60800    'use strict';
60801
60802    // Detect file input support, based on
60803    // http://viljamis.com/blog/2012/file-upload-support-on-mobile/
60804    $.support.fileInput = !(new RegExp(
60805        // Handle devices which give false positives for the feature detection:
60806        '(Android (1\\.[0156]|2\\.[01]))' +
60807            '|(Windows Phone (OS 7|8\\.0))|(XBLWP)|(ZuneWP)|(WPDesktop)' +
60808            '|(w(eb)?OSBrowser)|(webOS)' +
60809            '|(Kindle/(1\\.0|2\\.[05]|3\\.0))'
60810    ).test(window.navigator.userAgent) ||
60811        // Feature detection for all other devices:
60812        $('<input type="file">').prop('disabled'));
60813
60814    // The FileReader API is not actually used, but works as feature detection,
60815    // as some Safari versions (5?) support XHR file uploads via the FormData API,
60816    // but not non-multipart XHR file uploads.
60817    // window.XMLHttpRequestUpload is not available on IE10, so we check for
60818    // window.ProgressEvent instead to detect XHR2 file upload capability:
60819    $.support.xhrFileUpload = !!(window.ProgressEvent && window.FileReader);
60820    $.support.xhrFormDataFileUpload = !!window.FormData;
60821
60822    // Detect support for Blob slicing (required for chunked uploads):
60823    $.support.blobSlice = window.Blob && (Blob.prototype.slice ||
60824        Blob.prototype.webkitSlice || Blob.prototype.mozSlice);
60825
60826    // Helper function to create drag handlers for dragover/dragenter/dragleave:
60827    function getDragHandler(type) {
60828        var isDragOver = type === 'dragover';
60829        return function (e) {
60830            e.dataTransfer = e.originalEvent && e.originalEvent.dataTransfer;
60831            var dataTransfer = e.dataTransfer;
60832            if (dataTransfer && $.inArray('Files', dataTransfer.types) !== -1 &&
60833                    this._trigger(
60834                        type,
60835                        $.Event(type, {delegatedEvent: e})
60836                    ) !== false) {
60837                e.preventDefault();
60838                if (isDragOver) {
60839                    dataTransfer.dropEffect = 'copy';
60840                }
60841            }
60842        };
60843    }
60844
60845    // The fileupload widget listens for change events on file input fields defined
60846    // via fileInput setting and paste or drop events of the given dropZone.
60847    // In addition to the default jQuery Widget methods, the fileupload widget
60848    // exposes the "add" and "send" methods, to add or directly send files using
60849    // the fileupload API.
60850    // By default, files added via file input selection, paste, drag & drop or
60851    // "add" method are uploaded immediately, but it is possible to override
60852    // the "add" callback option to queue file uploads.
60853    $.widget('blueimp.fileupload', {
60854
60855        options: {
60856            // The drop target element(s), by the default the complete document.
60857            // Set to null to disable drag & drop support:
60858            dropZone: $(document),
60859            // The paste target element(s), by the default undefined.
60860            // Set to a DOM node or jQuery object to enable file pasting:
60861            pasteZone: undefined,
60862            // The file input field(s), that are listened to for change events.
60863            // If undefined, it is set to the file input fields inside
60864            // of the widget element on plugin initialization.
60865            // Set to null to disable the change listener.
60866            fileInput: undefined,
60867            // By default, the file input field is replaced with a clone after
60868            // each input field change event. This is required for iframe transport
60869            // queues and allows change events to be fired for the same file
60870            // selection, but can be disabled by setting the following option to fal
60870se:
60871            replaceFileInput: true,
60872            // The parameter name for the file form data (the request argument name).
60873            // If undefined or empty, the name property of the file input field is
60874            // used, or "files[]" if the file input name property is also empty,
60875            // can be a string or an array of strings:
60876            paramName: undefined,
60877            // By default, each file of a selection is uploaded using an individual
60878            // request for XHR type uploads. Set to false to upload file
60879            // selections in one request each:
60880            singleFileUploads: true,
60881            // To limit the number of files uploaded with one XHR request,
60882            // set the following option to an integer greater than 0:
60883            limitMultiFileUploads: undefined,
60884            // The following option limits the number of files uploaded with one
60885            // XHR request to keep the request size under or equal to the defined
60886            // limit in bytes:
60887            limitMultiFileUploadSize: undefined,
60888            // Multipart file uploads add a number of bytes to each uploaded file,
60889            // therefore the following option adds an overhead for each file used
60890            // in the limitMultiFileUploadSize configuration:
60891            limitMultiFileUploadSizeOverhead: 512,
60892            // Set the following option to true to issue all file upload requests
60893            // in a sequential order:
60894            sequentialUploads: false,
60895            // To limit the number of concurrent uploads,
60896            // set the following option to an integer greater than 0:
60897            limitConcurrentUploads: undefined,
60898            // Set the following option to true to force iframe transport uploads:
60899            forceIframeTransport: false,
60900            // Set the following option to the location of a redirect url on the
60901            // origin server, for cross-domain iframe transport uploads:
60902            redirect: undefined,
60903            // The parameter name for the redirect url, sent as part of the form
60904            // data and set to 'redirect' if this option is empty:
60905            redirectParamName: undefined,
60906            // Set the following option to the location of a postMessage window,
60907            // to enable postMessage transport uploads:
60908            postMessage: undefined,
60909            // By default, XHR file uploads are sent as multipart/form-data.
60910            // The iframe transport is always using multipart/form-data.
60911            // Set to false to enable non-multipart XHR uploads:
60912            multipart: true,
60913            // To upload large files in smaller chunks, set the following option
60914            // to a preferred maximum chunk size. If set to 0, null or undefined,
60915            // or the browser does not support the required Blob API, files will
60916            // be uploaded as a whole.
60917            maxChunkSize: undefined,
60918            // When a non-multipart upload or a chunked multipart upload has been
60919            // aborted, this option can be used to resume the upload by setting
60920            // it to the size of the already uploaded bytes. This option is most
60921            // useful when modifying the options object inside of the "add" or
60922            // "send" callbacks, as the options are cloned for each file upload.
60923            uploadedBytes: undefined,
60924            // By default, failed (abort or error) file uploads are removed from the
60925            // global progress calculation. Set the following option to false to
60926            // prevent recalculating the global progress data:
60927            recalculateProgress: true,
60928            // Interval in milliseconds to calculate and trigger progress events:
60929            progressInterval: 100,
60930            // Interval in milliseconds to calculate progress bitrate:
60931            bitrateInterval: 500,
60932            // By default, uploads are started automatically when adding files:
60933            autoUpload: true,
60934
60935            // Error and info messages:
60936            messages: {
60937                uploadedBytes: 'Uploaded bytes exceed file size'
60938            },
60939
60940            // Translation function, gets the message key to be translated
60941            // and an object with context specific data as arguments:
60942            i18n: function (message, context) {
60943                message = this.messages[message] || message.toString();
60944                if (context) {
60945                    $.each(context, function (key, value) {
60946                        message = message.replace('{' + key + '}', value);
60947                    });
60948                }
60949                return message;
60950            },
60951
60952            // Additional form data to be sent along with the file uploads can be set
60953            // using this option, which accepts an array of objects with name and
60954            // value properties, a function returning such an array, a FormData
60955            // object (for XHR file uploads), or a simple object.
60956            // The form of the first fileInput is given as parameter to the function:
60957            formData: function (form) {
60958                return form.serializeArray();
60959            },
60960
60961            // The add callback is invoked as soon as files are added to the fileupload
60962            // widget (via file input selection, drag & drop, paste or add API call).
60963            // If the singleFileUploads option is enabled, this callback will be
60964            // called once for each file in the selection for XHR file uploads, else
60965            // once for each file selection.
60966            //
60967            // The upload starts when the submit method is invoked on the data parameter.
60968            // The data object contains a files property holding the added files
60969            // and allows you to override plugin options as well as define ajax settings.
60970            //
60971            // Listeners for this callback can also be bound the following way:
60972            // .bind('fileuploadadd', func);
60973            //
60974            // data.submit() returns a Promise object and allows to attach additional
60975            // handlers using jQuery's Deferred callbacks:
60976            // data.submit().done(func).fail(func).always(func);
60977            add: function (e, data) {
60978                if (e.isDefaultPrevented()) {
60979                    return false;
60980                }
60981                if (data.autoUpload || (data.autoUpload !== false &&
60982                        $(this).fileupload('option', 'autoUpload'))) {
60983                    data.process().done(function () {
60984                        data.submit();
60985                    });
60986                }
60987            },
60988
60989            // Other callbacks:
60990
60991            // Callback for the submit event of each file upload:
60992            // submit: function (e, data) {}, // .bind('fileuploadsubmit', func);
60993
60994            // Callback for the start of each file upload request:
60995            // send: function (e, data) {}, // .bind('fileuploadsend', func);
60996
60997            // Callback for successful uploads:
60998            // done: function (e, data) {}, // .bind('fileuploaddone', func);
60999
61000            // Callback for failed (abort or error) uploads:
61001            // fail: function (e, data) {}, // .bind('fileuploadfail', func);
61002
61003            // Callback for completed (success, abort or error) requests:
61004            // always: function (e, data) {}, // .bind('fileuploadalways', func);
61005
61006            // Callback for upload progress events:
61007            // progress: function (e, data) {}, // .bind('fileuploadprogress', func);
61008
61009            // Callback for global upload progress events:
61010            // progressall: function (e, data) {}, // .bind('fileuploadprogressall', func);
61011
61012            // Callback for uploads start, equivalent to the global ajaxStart event:
61013            // start: function (e) {}, // .bind('fileuploadstart', func);
61014
61015            // Callback for uploads stop, equivalent to the global ajaxStop event:
61016            // stop: function (e) {}, // .bind('fileuploadstop', func);
61017
61018            // Callback for change events of the fileInput(s):
61019            // change: function (e, data) {}, // .bind('fileuploadchange', func);
61020
61021            // Callback for paste events to the pasteZone(s):
61022            // paste: function (e, data) {}, // .bind('fileuploadpaste', func);
61023
61024            // Callback for drop events of the dropZone(s):
61025            // drop: function (e, data) {}, // .bind('fileuploaddrop', func);
61026
61027            // Callback for dragover events of the dropZone(s):
61028            // dragover: function (e) {}, // .bind('fileuploaddragover', func);
61029
61030            // Callback for the start of each chunk upload request:
61031            // chunksend: function (e, data) {}, // .bind('fileuploadchunksend', func);
61032
61033            // Callback for successful chunk uploads:
61034            // chunkdone: function (e, data) {}, // .bind('fileuploadchunkdone', func);
61035
61036            // Callback for failed (abort or error) chunk uploads:
61037            // chunkfail: function (e, data) {}, // .bind('fileuploadchunkfail', func);
61038
61039            // Callback for completed (success, abort or error) chunk upload requests:
61040            // chunkalways: function (e, data) {}, // .bind('fileuploadchunkalways', func);
61041
61042            // The plugin options are used as settings object for the ajax calls.
61043            // The following are jQuery ajax settings required for the file uploads:
61044            processData: false,
61045            contentType: false,
61046            cache: false,
61047            timeout: 0
61048        },
61049
61050        // A list of options that require reinitializing event listeners and/or
61051        // special initialization code:
61052        _specialOptions: [
61053            'fileInput',
61054            'dropZone',
61055            'pasteZone',
61056            'multipart',
61057            'forceIframeTransport'
61058        ],
61059
61060        _blobSlice: $.support.blobSlice && function () {
61061            var slice = this.slice || this.webkitSlice || this.mozSlice;
61062            return slice.apply(this, arguments);
61063        },
61064
61065        _BitrateTimer: function () {
61066            this.timestamp = ((Date.now) ? Date.now() : (new Date()).getTime());
61067            this.loaded = 0;
61068            this.bitrate = 0;
61069            this.getBitrate = function (now, loaded, interval) {
61070                var timeDiff = now - this.timestamp;
61071                if (!this.bitrate || !interval || timeDiff > interval) {
61072                    this.bitrate = (loaded - this.loaded) * (1000 / timeDiff) * 8;
61073                    this.loaded = loaded;
61074                    this.timestamp = now;
61075                }
61076                return this.bitrate;
61077            };
61078        },
61079
61080        _isXHRUpload: function (options) {
61081            return !options.forceIframeTransport &&
61082                ((!options.multipart && $.support.xhrFileUpload) ||
61083                $.support.xhrFormDataFileUpload);
61084        },
61085
61086        _getFormData: function (options) {
61087            var formData;
61088            if ($.type(options.formData) === 'function') {
61089                return options.formData(options.form);
61090            }
61091            if ($.isArray(options.formData)) {
61092                return options.formData;
61093            }
61094            if ($.type(options.formData) === 'object') {
61095                formData = [];
61096                $.each(options.formData, function (name, value) {
61097                    formData.push({name: name, value: value});
61098                });
61099                return formData;
61100            }
61101            return [];
61102        },
61103
61104        _getTotal: function (files) {
61105            var total = 0;
61106            $.each(files, function (index, file) {
61107                total += file.size || 1;
61108            });
61109            return total;
61110        },
61111
61112        _initProgressObject: function (obj) {
61113            var progress = {
61114                loaded: 0,
61115                total: 0,
61116                bitrate: 0
61117            };
61118            if (obj._progress) {
61119                $.extend(obj._progress, progress);
61120            } else {
61121                obj._progress = progress;
61122            }
61123        },
61124
61125        _initResponseObject: function (obj) {
61126            var prop;
61127            if (obj._response) {
61128                for (prop in obj._response) {
61129                    if (obj._response.hasOwnProperty(prop)) {
61130                        delete obj._response[prop];
61131                    }
61132                }
61133            } else {
61134                obj._response = {};
61135            }
61136        },
61137
61138        _onProgress: function (e, data) {
61139            if (e.lengthComputable) {
61140                var now = ((Date.now) ? Date.now() : (new Date()).getTime()),
61141                    loaded;
61142                if (data._time && data.progressInterval &&
61143                        (now - data._time < data.progressInterval) &&
61144                        e.loaded !== e.total) {
61145                    return;
61146                }
61147                data._time = now;
61148                loaded = Math.floor(
61149                    e.loaded / e.total * (data.chunkSize || data._progress.total)
61150                ) + (data.uploadedBytes || 0);
61151                // Add the difference from the previously loaded state
61152                // to the global loaded counter:
61153                this._progress.loaded += (loaded - data._progress.loaded);
61154                this._progress.bitrate = this._bitrateTimer.getBitrate(
61155                    now,
61156                    this._progress.loaded,
61157                    data.bitrateInterval
61158                );
61159                data._progress.loaded = data.loaded = loaded;
61160                data._progress.bitrate = data.bitrate = data._bitrateTimer.getBitrate(
61161                    now,
61162                    loaded,
61163                    data.bitrateInterval
61164                );
61165                // Trigger a custom progress event with a total data property set
61166                // to the file size(s) of the current upload and a loaded data
61167                // property calculated accordingly:
61168                this._trigger(
61169                    'progress',
61170                    $.Event('progress', {delegatedEvent: e}),
61171                    data
61172                );
61173                // Trigger a global progress event for all current file uploads,
61174                // including ajax calls queued for sequential file uploads:
61175                this._trigger(
61176                    'progressall',
61177                    $.Event('progressall', {delegatedEvent: e}),
61178                    this._progress
61179                );
61180            }
61181        },
61182
61183        _initProgressListener: function (options) {
61184            var that = this,
61185                xhr = options.xhr ? options.xhr() : $.ajaxSettings.xhr();
61186            // Accesss to the native XHR object is required to add event listeners
61187            // for the upload progress event:
61188            if (xhr.upload) {
61189                $(xhr.upload).bind('progress', function (e) {
61190                    var oe = e.originalEvent;
61191                    // Make sure the progress event properties get copied over:
61192                    e.lengthComputable = oe.lengthComputable;
61193                    e.loaded = oe.loaded;
61194                    e.total = oe.total;
61195                    that._onProgress(e, options);
61196                });
61197                options.xhr = function () {
61198                    return xhr;
61199                };
61200            }
61201        },
61202
61203        _isInstanceOf: function (type, obj) {
61204            // Cross-frame instanceof check
61205            return Object.prototype.toString.call(obj) === '[object ' + type + ']';
61206        },
61207
61208        _initXHRData: function (options) {
61209            var that = this,
61210                formData,
61211                file = options.files[0],
61212                // Ignore non-multipart setting if not supported:
61213                multipart = options.multipart || !$.support.xhrFileUpload,
61214                paramName = $.type(options.paramName) === 'array' ?
61215                    options.paramName[0] : options.paramName;
61216            options.headers = $.extend({}, options.headers);
61217            if (options.contentRange) {
61218                options.headers['Content-Range'] = options.contentRange;
61219            }
61220            if (!multipart || options.blob || !this._isInstanceOf('File', file)) {
61221                options.headers['Content-Disposition'] = 'attachment; filename="' +
61222                    encodeURI(file.name) + '"';
61223            }
61224            if (!multipart) {
61225                options.contentType = file.type || 'application/octet-stream';
61226                options.data = options.blob || file;
61227            } else if ($.support.xhrFormDataFileUpload) {
61228                if (options.postMessage) {
61229                    // window.postMessage does not allow sending FormData
61230                    // objects, so we just add the File/Blob objects to
61231                    // the formData array and let the postMessage window
61232                    // create the FormData object out of this array:
61233                    formData = this._getFormData(options);
61234                    if (options.blob) {
61235                        formData.push({
61236                            name: paramName,
61237                            value: options.blob
61238                        });
61239                    } else {
61240                        $.each(options.files, function (index, file) {
61241                            formData.push({
61242                                name: ($.type(options.paramName) === 'array' &&
61243                                    options.paramName[index]) || paramName,
61244                                value: file
61245                            });
61246                        });
61247                    }
61248                } else {
61249                    if (that._isInstanceOf('FormData', options.formData)) {
61250                        formData = options.formData;
61251                    } else {
61252                        formData = new FormData();
61253                        $.each(this._getFormData(options), function (index, field) {
61254                            formData.append(field.name, field.value);
61255                        });
61256                    }
61257                    if (options.blob) {
61258                        formData.append(paramName, options.blob, file.name);
61259                    } else {
61260                        $.each(options.files, function (index, file) {
61261                            // This check allows the tests to run with
61262                            // dummy objects:
61263                            if (that._isInstanceOf('File', file) ||
61264                                    that._isInstanceOf('Blob', file)) {
61265                                formData.append(
61266                                    ($.type(options.paramName) === 'array' &&
61267                                        options.paramName[index]) || paramName,
61268                                    file,
61269                                    file.uploadName || file.name
61270                                );
61271                            }
61272                        });
61273                    }
61274                }
61275                options.data = formData;
61276            }
61277            // Blob reference is not needed anymore, free memory:
61278            options.blob = null;
61279        },
61280
61281        _initIframeSettings: function (options) {
61282            var targetHost = $('<a></a>').prop('href', options.url).prop('host');
61283            // Setting the dataType to iframe enables the iframe transport:
61284            options.dataType = 'iframe ' + (options.dataType || '');
61285            // The iframe transport accepts a serialized array as form data:
61286            options.formData = this._getFormData(options);
61287            // Add redirect url to form data on cross-domain uploads:
61288            if (options.redirect && targetHost && targetHost !== location.host) {
61289                options.formData.push({
61290                    name: options.redirectParamName || 'redirect',
61291                    value: options.redirect
61292                });
61293            }
61294        },
61295
61296        _initDataSettings: function (options) {
61297            if (this._isXHRUpload(options)) {
61298                if (!this._chunkedUpload(options, true)) {
61299                    if (!options.data) {
61300                        this._initXHRData(options);
61301                    }
61302                    this._initProgressListener(options);
61303                }
61304                if (options.postMessage) {
61305                    // Setting the dataType to postmessage enables the
61306                    // postMessage transport:
61307                    options.dataType = 'postmessage ' + (options.dataType || '');
61308                }
61309            } else {
61310                this._initIframeSettings(options);
61311            }
61312        },
61313
61314        _getParamName: function (options) {
61315            var fileInput = $(options.fileInput),
61316                paramName = options.paramName;
61317            if (!paramName) {
61318                paramName = [];
61319                fileInput.each(function () {
61320                    var input = $(this),
61321                        name = input.prop('name') || 'files[]',
61322                        i = (input.prop('files') || [1]).length;
61323                    while (i) {
61324                        paramName.push(name);
61325                        i -= 1;
61326                    }
61327                });
61328                if (!paramName.length) {
61329                    paramName = [fileInput.prop('name') || 'files[]'];
61330                }
61331            } else if (!$.isArray(paramName)) {
61332                paramName = [paramName];
61333            }
61334            return paramName;
61335        },
61336
61337        _initFormSettings: function (options) {
61338            // Retrieve missing options from the input field and the
61339            // associated form, if available:
61340            if (!options.form || !options.form.length) {
61341                options.form = $(options.fileInput.prop('form'));
61342                // If the given file input doesn't have an associated form,
61343                // use the default widget file input's form:
61344                if (!options.form.length) {
61345                    options.form = $(this.options.fileInput.prop('form'));
61346                }
61347            }
61348            options.paramName = this._getParamName(options);
61349            if (!options.url) {
61350                options.url = options.form.prop('action') || location.href;
61351            }
61352            // The HTTP request method must be "POST" or "PUT":
61353            options.type = (options.type ||
61354                ($.type(options.form.prop('method')) === 'string' &&
61355                    options.form.prop('method')) || ''
61356                ).toUpperCase();
61357            if (options.type !== 'POST' && options.type !== 'PUT' &&
61358                    options.type !== 'PATCH') {
61359                options.type = 'POST';
61360            }
61361            if (!options.formAcceptCharset) {
61362                options.formAcceptCharset = options.form.attr('accept-charset');
61363            }
61364        },
61365
61366        _getAJAXSettings: function (data) {
61367            var options = $.extend({}, this.options, data);
61368            this._initFormSettings(options);
61369            this._initDataSettings(options);
61370            return options;
61371        },
61372
61373        // jQuery 1.6 doesn't provide .state(),
61374        // while jQuery 1.8+ removed .isRejected() and .isResolved():
61375        _getDeferredState: function (deferred) {
61376            if (deferred.state) {
61377                return deferred.state();
61378            }
61379            if (deferred.isResolved()) {
61380                return 'resolved';
61381            }
61382            if (deferred.isRejected()) {
61383                return 'rejected';
61384            }
61385            return 'pending';
61386        },
61387
61388        // Maps jqXHR callbacks to the equivalent
61389        // methods of the given Promise object:
61390        _enhancePromise: function (promise) {
61391            promise.success = promise.done;
61392            promise.error = promise.fail;
61393            promise.complete = promise.always;
61394            return promise;
61395        },
61396
61397        // Creates and returns a Promise object enhanced with
61398        // the jqXHR methods abort, success, error and complete:
61399        _getXHRPromise: function (resolveOrReject, context, args
61399) {
61400            var dfd = $.Deferred(),
61401                promise = dfd.promise();
61402            context = context || this.options.context || promise;
61403            if (resolveOrReject === true) {
61404                dfd.resolveWith(context, args);
61405            } else if (resolveOrReject === false) {
61406                dfd.rejectWith(context, args);
61407            }
61408            promise.abort = dfd.promise;
61409            return this._enhancePromise(promise);
61410        },
61411
61412        // Adds convenience methods to the data callback argument:
61413        _addConvenienceMethods: function (e, data) {
61414            var that = this,
61415                getPromise = function (args) {
61416                    return $.Deferred().resolveWith(that, args).promise();
61417                };
61418            data.process = function (resolveFunc, rejectFunc) {
61419                if (resolveFunc || rejectFunc) {
61420                    data._processQueue = this._processQueue =
61421                        (this._processQueue || getPromise([this])).then(
61422                            function () {
61423                                if (data.errorThrown) {
61424                                    return $.Deferred()
61425                                        .rejectWith(that, [data]).promise();
61426                                }
61427                                return getPromise(arguments);
61428                            }
61429                        ).then(resolveFunc, rejectFunc);
61430                }
61431                return this._processQueue || getPromise([this]);
61432            };
61433            data.submit = function () {
61434                if (this.state() !== 'pending') {
61435                    data.jqXHR = this.jqXHR =
61436                        (that._trigger(
61437                            'submit',
61438                            $.Event('submit', {delegatedEvent: e}),
61439                            this
61440                        ) !== false) && that._onSend(e, this);
61441                }
61442                return this.jqXHR || that._getXHRPromise();
61443            };
61444            data.abort = function () {
61445                if (this.jqXHR) {
61446                    return this.jqXHR.abort();
61447                }
61448                this.errorThrown = 'abort';
61449                that._trigger('fail', null, this);
61450                return that._getXHRPromise(false);
61451            };
61452            data.state = function () {
61453                if (this.jqXHR) {
61454                    return that._getDeferredState(this.jqXHR);
61455                }
61456                if (this._processQueue) {
61457                    return that._getDeferredState(this._processQueue);
61458                }
61459            };
61460            data.processing = function () {
61461                return !this.jqXHR && this._processQueue && that
61462                    ._getDeferredState(this._processQueue) === 'pending';
61463            };
61464            data.progress = function () {
61465                return this._progress;
61466            };
61467            data.response = function () {
61468                return this._response;
61469            };
61470        },
61471
61472        // Parses the Range header from the server response
61473        // and returns the uploaded bytes:
61474        _getUploadedBytes: function (jqXHR) {
61475            var range = jqXHR.getResponseHeader('Range'),
61476                parts = range && range.split('-'),
61477                upperBytesPos = parts && parts.length > 1 &&
61478                    parseInt(parts[1], 10);
61479            return upperBytesPos && upperBytesPos + 1;
61480        },
61481
61482        // Uploads a file in multiple, sequential requests
61483        // by splitting the file up in multiple blob chunks.
61484        // If the second parameter is true, only tests if the file
61485        // should be uploaded in chunks, but does not invoke any
61486        // upload requests:
61487        _chunkedUpload: function (options, testOnly) {
61488            options.uploadedBytes = options.uploadedBytes || 0;
61489            var that = this,
61490                file = options.files[0],
61491                fs = file.size,
61492                ub = options.uploadedBytes,
61493                mcs = options.maxChunkSize || fs,
61494                slice = this._blobSlice,
61495                dfd = $.Deferred(),
61496                promise = dfd.promise(),
61497                jqXHR,
61498                upload;
61499            if (!(this._isXHRUpload(options) && slice && (ub || mcs < fs)) ||
61500                    options.data) {
61501                return false;
61502            }
61503            if (testOnly) {
61504                return true;
61505            }
61506            if (ub >= fs) {
61507                file.error = options.i18n('uploadedBytes');
61508                return this._getXHRPromise(
61509                    false,
61510                    options.context,
61511                    [null, 'error', file.error]
61512                );
61513            }
61514            // The chunk upload method:
61515            upload = function () {
61516                // Clone the options object for each chunk upload:
61517                var o = $.extend({}, options),
61518                    currentLoaded = o._progress.loaded;
61519                o.blob = slice.call(
61520                    file,
61521                    ub,
61522                    ub + mcs,
61523                    file.type
61524                );
61525                // Store the current chunk size, as the blob itself
61526                // will be dereferenced after data processing:
61527                o.chunkSize = o.blob.size;
61528                // Expose the chunk bytes position range:
61529                o.contentRange = 'bytes ' + ub + '-' +
61530                    (ub + o.chunkSize - 1) + '/' + fs;
61531                // Process the upload data (the blob and potential form data):
61532                that._initXHRData(o);
61533                // Add progress listeners for this chunk upload:
61534                that._initProgressListener(o);
61535                jqXHR = ((that._trigger('chunksend', null, o) !== false && $.ajax(o)) ||
61536                        that._getXHRPromise(false, o.context))
61537                    .done(function (result, textStatus, jqXHR) {
61538                        ub = that._getUploadedBytes(jqXHR) ||
61539                            (ub + o.chunkSize);
61540                        // Create a progress event if no final progress event
61541                        // with loaded equaling total has been triggered
61542                        // for this chunk:
61543                        if (currentLoaded + o.chunkSize - o._progress.loaded) {
61544                            that._onProgress($.Event('progress', {
61545                                lengthComputable: true,
61546                                loaded: ub - o.uploadedBytes,
61547                                total: ub - o.uploadedBytes
61548                            }), o);
61549                        }
61550                        options.uploadedBytes = o.uploadedBytes = ub;
61551                        o.result = result;
61552                        o.textStatus = textStatus;
61553                        o.jqXHR = jqXHR;
61554                        that._trigger('chunkdone', null, o);
61555                        that._trigger('chunkalways', null, o);
61556                        if (ub < fs) {
61557                            // File upload not yet complete,
61558                            // continue with the next chunk:
61559                            upload();
61560                        } else {
61561                            dfd.resolveWith(
61562                                o.context,
61563                                [result, textStatus, jqXHR]
61564                            );
61565                        }
61566                    })
61567                    .fail(function (jqXHR, textStatus, errorThrown) {
61568                        o.jqXHR = jqXHR;
61569                        o.textStatus = textStatus;
61570                        o.errorThrown = errorThrown;
61571                        that._trigger('chunkfail', null, o);
61572                        that._trigger('chunkalways', null, o);
61573                        dfd.rejectWith(
61574                            o.context,
61575                            [jqXHR, textStatus, errorThrown]
61576                        );
61577                    });
61578            };
61579            this._enhancePromise(promise);
61580            promise.abort = function () {
61581                return jqXHR.abort();
61582            };
61583            upload();
61584            return promise;
61585        },
61586
61587        _beforeSend: function (e, data) {
61588            if (this._active === 0) {
61589                // the start callback is triggered when an upload starts
61590                // and no other uploads are currently running,
61591                // equivalent to the global ajaxStart event:
61592                this._trigger('start');
61593                // Set timer for global bitrate progress calculation:
61594                this._bitrateTimer = new this._BitrateTimer();
61595                // Reset the global progress values:
61596                this._progress.loaded = this._progress.total = 0;
61597                this._progress.bitrate = 0;
61598            }
61599            // Make sure the container objects for the .response() and
61600            // .progress() methods on the data object are available
61601            // and reset to their initial state:
61602            this._initResponseObject(data);
61603            this._initProgressObject(data);
61604            data._progress.loaded = data.loaded = data.uploadedBytes || 0;
61605            data._progress.total = data.total = this._getTotal(data.files) || 1;
61606            data._progress.bitrate = data.bitrate = 0;
61607            this._active += 1;
61608            // Initialize the global progress values:
61609            this._progress.loaded += data.loaded;
61610            this._progress.total += data.total;
61611        },
61612
61613        _onDone: function (result, textStatus, jqXHR, options) {
61614            var total = options._progress.total,
61615                response = options._response;
61616            if (options._progress.loaded < total) {
61617                // Create a progress event if no final progress event
61618                // with loaded equaling total has been triggered:
61619                this._onProgress($.Event('progress', {
61620                    lengthComputable: true,
61621                    loaded: total,
61622                    total: total
61623                }), options);
61624            }
61625            response.result = options.result = result;
61626            response.textStatus = options.textStatus = textStatus;
61627            response.jqXHR = options.jqXHR = jqXHR;
61628            this._trigger('done', null, options);
61629        },
61630
61631        _onFail: function (jqXHR, textStatus, errorThrown, options) {
61632            var response = options._response;
61633            if (options.recalculateProgress) {
61634                // Remove the failed (error or abort) file upload from
61635                // the global progress calculation:
61636                this._progress.loaded -= options._progress.loaded;
61637                this._progress.total -= options._progress.total;
61638            }
61639            response.jqXHR = options.jqXHR = jqXHR;
61640            response.textStatus = options.textStatus = textStatus;
61641            response.errorThrown = options.errorThrown = errorThrown;
61642            this._trigger('fail', null, options);
61643        },
61644
61645        _onAlways: function (jqXHRorResult, textStatus, jqXHRorError, options) {
61646            // jqXHRorResult, textStatus and jqXHRorError are added to the
61647            // options object via done and fail callbacks
61648            this._trigger('always', null, options);
61649        },
61650
61651        _onSend: function (e, data) {
61652            if (!data.submit) {
61653                this._addConvenienceMethods(e, data);
61654            }
61655            var that = this,
61656                jqXHR,
61657                aborted,
61658                slot,
61659                pipe,
61660                options = that._getAJAXSettings(data),
61661                send = function () {
61662                    that._sending += 1;
61663                    // Set timer for bitrate progress calculation:
61664                    options._bitrateTimer = new that._BitrateTimer();
61665                    jqXHR = jqXHR || (
61666                        ((aborted || that._trigger(
61667                            'send',
61668                            $.Event('send', {delegatedEvent: e}),
61669                            options
61670                        ) === false) &&
61671                        that._getXHRPromise(false, options.context, aborted)) ||
61672                        that._chunkedUpload(options) || $.ajax(options)
61673                    ).done(function (result, textStatus, jqXHR) {
61674                        that._onDone(result, textStatus, jqXHR, options);
61675                    }).fail(function (jqXHR, textStatus, errorThrown) {
61676                        that._onFail(jqXHR, textStatus, errorThrown, options);
61677                    }).always(function (jqXHRorResult, textStatus, jqXHRorError) {
61678                        that._onAlways(
61679                            jqXHRorResult,
61680                            textStatus,
61681                            jqXHRorError,
61682                            options
61683                        );
61684                        that._sending -= 1;
61685                        that._active -= 1;
61686                        if (options.limitConcurrentUploads &&
61687                                options.limitConcurrentUploads > that._sending) {
61688                            // Start the next queued upload,
61689                            // that has not been aborted:
61690                            var nextSlot = that._slots.shift();
61691                            while (nextSlot) {
61692                                if (that._getDeferredState(nextSlot) === 'pending') {
61693                                    nextSlot.resolve();
61694                                    break;
61695                                }
61696                                nextSlot = that._slots.shift();
61697                            }
61698                        }
61699                        if (that._active === 0) {
61700                            // The stop callback is triggered when all uploads have
61701                            // been completed, equivalent to the global ajaxStop event:
61702                            that._trigger('stop');
61703                        }
61704                    });
61705                    return jqXHR;
61706                };
61707            this._beforeSend(e, options);
61708            if (this.options.sequentialUploads ||
61709                    (this.options.limitConcurrentUploads &&
61710                    this.options.limitConcurrentUploads <= this._sending)) {
61711                if (this.options.limitConcurrentUploads > 1) {
61712                    slot = $.Deferred();
61713                    this._slots.push(slot);
61714                    pipe = slot.then(send);
61715                } else {
61716                    this._sequence = this._sequence.then(send, send);
61717                    pipe = this._sequence;
61718                }
61719                // Return the piped Promise object, enhanced with an abort method,
61720                // which is delegated to the jqXHR object of the current upload,
61721                // and jqXHR callbacks mapped to the equivalent Promise methods:
61722                pipe.abort = function () {
61723                    aborted = [undefined, 'abort', 'abort'];
61724                    if (!jqXHR) {
61725                        if (slot) {
61726                            slot.rejectWith(options.context, aborted);
61727                        }
61728                        return send();
61729                    }
61730                    return jqXHR.abort();
61731                };
61732                return this._enhancePromise(pipe);
61733            }
61734            return send();
61735        },
61736
61737        _onAdd: function (e, data) {
61738            var that = this,
61739                result = true,
61740                options = $.extend({}, this.options, data),
61741                files = data.files,
61742                filesLength = files.length,
61743                limit = options.limitMultiFileUploads,
61744                limitSize = options.limitMultiFileUploadSize,
61745                overhead = options.limitMultiFileUploadSizeOverhead,
61746                batchSize = 0,
61747                paramName = this._getParamName(options),
61748                paramNameSet,
61749                paramNameSlice,
61750                fileSet,
61751                i,
61752                j = 0;
61753            if (!filesLength) {
61754                return false;
61755            }
61756            if (limitSize && files[0].size === undefined) {
61757                limitSize = undefined;
61758            }
61759            if (!(options.singleFileUploads || limit || limitSize) ||
61760                    !this._isXHRUpload(options)) {
61761                fileSet = [files];
61762                paramNameSet = [paramName];
61763            } else if (!(options.singleFileUploads || limitSize) && limit) {
61764                fileSet = [];
61765                paramNameSet = [];
61766                for (i = 0; i < filesLength; i += limit) {
61767                    fileSet.push(files.slice(i, i + limit));
61768                    paramNameSlice = paramName.slice(i, i + limit);
61769                    if (!paramNameSlice.length) {
61770                        paramNameSlice = paramName;
61771                    }
61772                    paramNameSet.push(paramNameSlice);
61773                }
61774            } else if (!options.singleFileUploads && limitSize) {
61775                fileSet = [];
61776                paramNameSet = [];
61777                for (i = 0; i < filesLength; i = i + 1) {
61778                    batchSize += files[i].size + overhead;
61779                    if (i + 1 === filesLength ||
61780                            ((batchSize + files[i + 1].size + overhead) > limitSize) ||
61781                            (limit && i + 1 - j >= limit)) {
61782                        fileSet.push(files.slice(j, i + 1));
61783                        paramNameSlice = paramName.slice(j, i + 1);
61784                        if (!paramNameSlice.length) {
61785                            paramNameSlice = paramName;
61786                        }
61787                        paramNameSet.push(paramNameSlice);
61788                        j = i + 1;
61789                        batchSize = 0;
61790                    }
61791                }
61792            } else {
61793                paramNameSet = paramName;
61794            }
61795            data.originalFiles = files;
61796            $.each(fileSet || files, function (index, element) {
61797                var newData = $.extend({}, data);
61798                newData.files = fileSet ? element : [element];
61799                newData.paramName = paramNameSet[index];
61800                that._initResponseObject(newData);
61801                that._initProgressObject(newData);
61802                that._addConvenienceMethods(e, newData);
61803                result = that._trigger(
61804                    'add',
61805                    $.Event('add', {delegatedEvent: e}),
61806                    newData
61807                );
61808                return result;
61809            });
61810            return result;
61811        },
61812
61813        _replaceFileInput: function (data) {
61814            var input = data.fileInput,
61815                inputClone = input.clone(true),
61816                restoreFocus = input.is(document.activeElement);
61817            // Add a reference for the new cloned file input to the data argument:
61818            data.fileInputClone = inputClone;
61819            $('<form></form>').append(inputClone)[0].reset();
61820            // Detaching allows to insert the fileInput on another form
61821            // without loosing the file input value:
61822            input.after(inputClone).detach();
61823            // If the fileInput had focus before it was detached,
61824            // restore focus to the inputClone.
61825            if (restoreFocus) {
61826                inputClone.focus();
61827            }
61828            // Avoid memory leaks with the detached file input:
61829            $.cleanData(input.unbind('remove'));
61830            // Replace the original file input element in the fileInput
61831            // elements set with the clone, which has been copied including
61832            // event handlers:
61833            this.options.fileInput = this.options.fileInput.map(function (i, el) {
61834                if (el === input[0]) {
61835                    return inputClone[0];
61836                }
61837                return el;
61838            });
61839            // If the widget has been initialized on the file input itself,
61840            // override this.element with the file input clone:
61841            if (input[0] === this.element[0]) {
61842                this.element = inputClone;
61843            }
61844        },
61845
61846        _handleFileTreeEntry: function (entry, path) {
61847            var that = this,
61848                dfd = $.Deferred(),
61849                entries = [],
61850                dirReader,
61851                errorHandler = function (e) {
61852                    if (e && !e.entry) {
61853                        e.entry = entry;
61854                    }
61855                    // Since $.when returns immediately if one
61856                    // Deferred is rejected, we use resolve instead.
61857                    // This allows valid files and invalid items
61858                    // to be returned together in one set:
61859                    dfd.resolve([e]);
61860                },
61861                successHandler = function (entries) {
61862                    that._handleFileTreeEntries(
61863                        entries,
61864                        path + entry.name + '/'
61865                    ).done(function (files) {
61866                        dfd.resolve(files);
61867                    }).fail(errorHandler);
61868                },
61869                readEntries = function () {
61870                    dirReader.readEntries(function (results) {
61871                        if (!results.length) {
61872                            successHandler(entries);
61873                        } else {
61874                            entries = entries.concat(results);
61875                            readEntries();
61876                        }
61877                    }, errorHandler);
61878                };
61879            path = path || '';
61880            if (entry.isFile) {
61881                if (entry._file) {
61882                    // Workaround for Chrome bug #149735
61883                    entry._file.relativePath = path;
61884                    dfd.resolve(entry._file);
61885                } else {
61886                    entry.file(function (file) {
61887                        file.relativePath = path;
61888                        dfd.resolve(file);
61889                    }, errorHandler);
61890                }
61891            } else if (entry.isDirectory) {
61892                dirReader = entry.createReader();
61893                readEntries();
61894            } else {
61895                // Return an empy list for file system items
61896                // other than files or directories:
61897                dfd.resolve([]);
61898            }
61899            return dfd.promise();
61900        },
61901
61902        _handleFileTreeEntries: function (entries, path) {
61903            var that = this;
61904            return $.when.apply(
61905                $,
61906                $.map(entries, function (entry) {
61907                    return that._handleFileTreeEntry(entry, path);
61908                })
61909            ).then(function () {
61910                return Array.prototype.concat.apply(
61911                    [],
61912                    arguments
61913                );
61914            });
61915        },
61916
61917        _getDroppedFiles: function (dataTransfer) {
61918            dataTransfer = dataTransfer || {};
61919            var items = dataTransfer.items;
61920            if (items && items.length && (items[0].webkitGetAsEntry ||
61921                    items[0].getAsEntry)) {
61922                return this._handleFileTreeEntries(
61923                    $.map(items, function (item) {
61924                        var entry;
61925                        if (item.webkitGetAsEntry) {
61926                            entry = item.webkitGetAsEntry();
61927                            if (entry) {
61928                                // Workaround for Chrome bug #149735:
61929                                entry._file = item.getAsFile();
61930                            }
61931                            return entry;
61932                        }
61933                        return item.getAsEntry();
61934                    })
61935                );
61936            }
61937            return $.Deferred().resolve(
61938                $.makeArray(dataTransfer.files)
61939            ).promise();
61940        },
61941
61942        _getSingleFileInputFiles: function (fileInput) {
61943            fileInput = $(fileInput);
61944            var entries = fileInput.prop('webkitEntries') ||
61945                    fileInput.prop('entries'),
61946                files,
61947                value;
61948            if (entries && entries.length) {
61949                return this._handleFileTreeEntries(entries);
61950            }
61951            files = $.makeArray(fileInput.prop('files'));
61952            if (!files.length) {
61953                value = fileInput.prop('value');
61954                if (!value) {
61955                    return $.Deferred().resolve([]).promise();
61956                }
61957                // If the files property is not available, the browser does not
61958                // support the File API and we add a pseudo File object with
61959                // the input value as name with path information removed:
61960                files = [{name: value.replace(/^.*\\/, '')}];
61961            } else if (files[0].name === undefined && files[0].fileName) {
61962                // File normalization for Safari 4 and Firefox 3:
61963                $.each(files, function (index, file) {
61964                    file.name = file.fileName;
61965                    file.size = file.fileSize;
61966                });
61967            }
61968            return $.Deferred().resolve(files).promise();
61969        },
61970
61971        _getFileInputFiles: function (fileInput) {
61972            if (!(fileInput instanceof $) || fileInput.length === 1) {
61973                return this._getSingleFileInputFiles(fileInput);
61974            }
61975            return $.when.apply(
61976                $,
61977                $.map(fileInput, this._getSingleFileInputFiles)
61978            ).then(function () {
61979                return Array.prototype.concat.apply(
61980                    [],
61981                    arguments
61982                );
61983            });
61984        },
61985
61986        _onChange: function (e) {
61987            var that = this,
61988                data = {
61989                    fileInput: $(e.target),
61990                    form: $(e.target.form)
61991                };
61992            this._getFileInputFiles(data.fileInput).always(function (files) {
61993                data.files = files;
61994                if (that.options.replaceFileInput) {
61995                    that._replaceFileInput(data);
61996                }
61997                if (that._trigger(
61998                        'change',
61999                        $.Event('change', {delegatedEvent: e}),
62000                        data
62001                    ) !== false) {
62002                    that._onAdd(e, data);
62003                }
62004            });
62005        },
62006
62007        _onPaste: function (e) {
62008            var items = e.originalEvent && e.originalEvent.clipboardData &&
62009                    e.originalEvent.clipboardData.items,
62010                data = {files: []};
62011            if (items && items.length) {
62012                $.each(items, function (index, item) {
62013                    var file = item.getAsFile && item.getAsFile();
62014                    if (file) {
62015                        data.files.push(file);
62016                    }
62017                });
62018                if (this._trigger(
62019                        'paste',
62020                        $.Event('paste', {delegatedEvent: e}),
62021                        data
62022                    ) !== false) {
62023                    this._onAdd(e, data);
62024                }
62025            }
62026        },
62027
62028        _onDrop: function (e) {
62029            e.dataTransfer = e.originalEvent && e.originalEvent.dataTransfer;
62030            var that = this,
62031                dataTransfer = e.dataTransfer,
62032                data = {};
62033            if (dataTransfer && dataTransfer.files && dataTransfer.files.length) {
62034                e.preventDefault();
62035                this._getDroppedFiles(dataTransfer).always(function (files) {
62036                    data.files = files;
62037                    if (that._trigger(
62038                            'drop',
62039                            $.Event('drop', {delegatedEvent: e}),
62040                            data
62041                        ) !== false) {
62042                        that._onAdd(e, data);
62043                    }
62044                });
62045            }
62046        },
62047
62048        _onDragOver: getDragHandler('dragover'),
62049
62050        _onDragEnter: getDragHandler('dragenter'),
62051
62052        _onDragLeave: getDragHandler('dragleave'),
62053
62054        _initEventHandlers: function () {
62055            if (this._isXHRUpload(this.options)) {
62056                this._on(this.options.dropZone, {
62057                    dragover: this._onDragOver,
62058                    drop: this._onDrop,
62059                    // event.preventDefault() on dragenter is required for IE10+:
62060                    dragenter: this._onDragEnter,
62061                    // dragleave is not required, but added for c
62061ompleteness:
62062                    dragleave: this._onDragLeave
62063                });
62064                this._on(this.options.pasteZone, {
62065                    paste: this._onPaste
62066                });
62067            }
62068            if ($.support.fileInput) {
62069                this._on(this.options.fileInput, {
62070                    change: this._onChange
62071                });
62072            }
62073        },
62074
62075        _destroyEventHandlers: function () {
62076            this._off(this.options.dropZone, 'dragenter dragleave dragover drop');
62077            this._off(this.options.pasteZone, 'paste');
62078            this._off(this.options.fileInput, 'change');
62079        },
62080
62081        _destroy: function () {
62082            this._destroyEventHandlers();
62083        },
62084
62085        _setOption: function (key, value) {
62086            var reinit = $.inArray(key, this._specialOptions) !== -1;
62087            if (reinit) {
62088                this._destroyEventHandlers();
62089            }
62090            this._super(key, value);
62091            if (reinit) {
62092                this._initSpecialOptions();
62093                this._initEventHandlers();
62094            }
62095        },
62096
62097        _initSpecialOptions: function () {
62098            var options = this.options;
62099            if (options.fileInput === undefined) {
62100                options.fileInput = this.element.is('input[type="file"]') ?
62101                        this.element : this.element.find('input[type="file"]');
62102            } else if (!(options.fileInput instanceof $)) {
62103                options.fileInput = $(options.fileInput);
62104            }
62105            if (!(options.dropZone instanceof $)) {
62106                options.dropZone = $(options.dropZone);
62107            }
62108            if (!(options.pasteZone instanceof $)) {
62109                options.pasteZone = $(options.pasteZone);
62110            }
62111        },
62112
62113        _getRegExp: function (str) {
62114            var parts = str.split('/'),
62115                modifiers = parts.pop();
62116            parts.shift();
62117            return new RegExp(parts.join('/'), modifiers);
62118        },
62119
62120        _isRegExpOption: function (key, value) {
62121            return key !== 'url' && $.type(value) === 'string' &&
62122                /^\/.*\/[igm]{0,3}$/.test(value);
62123        },
62124
62125        _initDataAttributes: function () {
62126            var that = this,
62127                options = this.options,
62128                data = this.element.data();
62129            // Initialize options set via HTML5 data-attributes:
62130            $.each(
62131                this.element[0].attributes,
62132                function (index, attr) {
62133                    var key = attr.name.toLowerCase(),
62134                        value;
62135                    if (/^data-/.test(key)) {
62136                        // Convert hyphen-ated key to camelCase:
62137                        key = key.slice(5).replace(/-[a-z]/g, function (str) {
62138                            return str.charAt(1).toUpperCase();
62139                        });
62140                        value = data[key];
62141                        if (that._isRegExpOption(key, value)) {
62142                            value = that._getRegExp(value);
62143                        }
62144                        options[key] = value;
62145                    }
62146                }
62147            );
62148        },
62149
62150        _create: function () {
62151            this._initDataAttributes();
62152            this._initSpecialOptions();
62153            this._slots = [];
62154            this._sequence = this._getXHRPromise(true);
62155            this._sending = this._active = 0;
62156            this._initProgressObject(this);
62157            this._initEventHandlers();
62158        },
62159
62160        // This method is exposed to the widget API and allows to query
62161        // the number of active uploads:
62162        active: function () {
62163            return this._active;
62164        },
62165
62166        // This method is exposed to the widget API and allows to query
62167        // the widget upload progress.
62168        // It returns an object with loaded, total and bitrate properties
62169        // for the running uploads:
62170        progress: function () {
62171            return this._progress;
62172        },
62173
62174        // This method is exposed to the widget API and allows adding files
62175        // using the fileupload API. The data parameter accepts an object which
62176        // must have a files property and can contain additional options:
62177        // .fileupload('add', {files: filesList});
62178        add: function (data) {
62179            var that = this;
62180            if (!data || this.options.disabled) {
62181                return;
62182            }
62183            if (data.fileInput && !data.files) {
62184                this._getFileInputFiles(data.fileInput).always(function (files) {
62185                    data.files = files;
62186                    that._onAdd(null, data);
62187                });
62188            } else {
62189                data.files = $.makeArray(data.files);
62190                this._onAdd(null, data);
62191            }
62192        },
62193
62194        // This method is exposed to the widget API and allows sending files
62195        // using the fileupload API. The data parameter accepts an object which
62196        // must have a files or fileInput property and can contain additional options:
62197        // .fileupload('send', {files: filesList});
62198        // The method returns a Promise object for the file upload call.
62199        send: function (data) {
62200            if (data && !this.options.disabled) {
62201                if (data.fileInput && !data.files) {
62202                    var that = this,
62203                        dfd = $.Deferred(),
62204                        promise = dfd.promise(),
62205                        jqXHR,
62206                        aborted;
62207                    promise.abort = function () {
62208                        aborted = true;
62209                        if (jqXHR) {
62210                            return jqXHR.abort();
62211                        }
62212                        dfd.reject(null, 'abort', 'abort');
62213                        return promise;
62214                    };
62215                    this._getFileInputFiles(data.fileInput).always(
62216                        function (files) {
62217                            if (aborted) {
62218                                return;
62219                            }
62220                            if (!files.length) {
62221                                dfd.reject();
62222                                return;
62223                            }
62224                            data.files = files;
62225                            jqXHR = that._onSend(null, data);
62226                            jqXHR.then(
62227                                function (result, textStatus, jqXHR) {
62228                                    dfd.resolve(result, textStatus, jqXHR);
62229                                },
62230                                function (jqXHR, textStatus, errorThrown) {
62231                                    dfd.reject(jqXHR, textStatus, errorThrown);
62232                                }
62233                            );
62234                        }
62235                    );
62236                    return this._enhancePromise(promise);
62237                }
62238                data.files = $.makeArray(data.files);
62239                if (data.files.length) {
62240                    return this._onSend(null, data);
62241                }
62242            }
62243            return this._getXHRPromise(false, data && data.context);
62244        }
62245
62246    });
62247
62248}));
62249
62250/*
62251 * jQuery File Upload Processing Plugin
62252 * https://github.com/blueimp/jQuery-File-Upload
62253 *
62254 * Copyright 2012, Sebastian Tschan
62255 * https://blueimp.net
62256 *
62257 * Licensed under the MIT license:
62258 * http://www.opensource.org/licenses/MIT
62259 */
62260
62261/* jshint nomen:false */
62262/* global define, require, window */
62263
62264;(function (factory) {
62265    'use strict';
62266    if (typeof define === 'function' && define.amd) {
62267        // Register as an anonymous AMD module:
62268        define('jquery.fileupload-process',[
62269            'jquery',
62270            './jquery.fileupload'
62271        ], factory);
62272    } else if (typeof exports === 'object') {
62273        // Node/CommonJS:
62274        factory(require('jquery'));
62275    } else {
62276        // Browser globals:
62277        factory(
62278            window.jQuery
62279        );
62280    }
62281}(function ($) {
62282    'use strict';
62283
62284    var originalAdd = $.blueimp.fileupload.prototype.options.add;
62285
62286    // The File Upload Processing plugin extends the fileupload widget
62287    // with file processing functionality:
62288    $.widget('blueimp.fileupload', $.blueimp.fileupload, {
62289
62290        options: {
62291            // The list of processing actions:
62292            processQueue: [
62293                /*
62294                {
62295                    action: 'log',
62296                    type: 'debug'
62297                }
62298                */
62299            ],
62300            add: function (e, data) {
62301                var $this = $(this);
62302                data.process(function () {
62303                    return $this.fileupload('process', data);
62304                });
62305                originalAdd.call(this, e, data);
62306            }
62307        },
62308
62309        processActions: {
62310            /*
62311            log: function (data, options) {
62312                console[options.type](
62313                    'Processing "' + data.files[data.index].name + '"'
62314                );
62315            }
62316            */
62317        },
62318
62319        _processFile: function (data, originalData) {
62320            var that = this,
62321                dfd = $.Deferred().resolveWith(that, [data]),
62322                chain = dfd.promise();
62323            this._trigger('process', null, data);
62324            $.each(data.processQueue, function (i, settings) {
62325                var func = function (data) {
62326                    if (originalData.errorThrown) {
62327                        return $.Deferred()
62328                                .rejectWith(that, [originalData]).promise();
62329                    }
62330                    return that.processActions[settings.action].call(
62331                        that,
62332                        data,
62333                        settings
62334                    );
62335                };
62336                chain = chain.then(func, settings.always && func);
62337            });
62338            chain
62339                .done(function () {
62340                    that._trigger('processdone', null, data);
62341                    that._trigger('processalways', null, data);
62342                })
62343                .fail(function () {
62344                    that._trigger('processfail', null, data);
62345                    that._trigger('processalways', null, data);
62346                });
62347            return chain;
62348        },
62349
62350        // Replaces the settings of each processQueue item that
62351        // are strings starting with an "@", using the remaining
62352        // substring as key for the option map,
62353        // e.g. "@autoUpload" is replaced with options.autoUpload:
62354        _transformProcessQueue: function (options) {
62355            var processQueue = [];
62356            $.each(options.processQueue, function () {
62357                var settings = {},
62358                    action = this.action,
62359                    prefix = this.prefix === true ? action : this.prefix;
62360                $.each(this, function (key, value) {
62361                    if ($.type(value) === 'string' &&
62362                            value.charAt(0) === '@') {
62363                        settings[key] = options[
62364                            value.slice(1) || (prefix ? prefix +
62365                                key.charAt(0).toUpperCase() + key.slice(1) : key)
62366                        ];
62367                    } else {
62368                        settings[key] = value;
62369                    }
62370
62371                });
62372                processQueue.push(settings);
62373            });
62374            options.processQueue = processQueue;
62375        },
62376
62377        // Returns the number of files currently in the processsing queue:
62378        processing: function () {
62379            return this._processing;
62380        },
62381
62382        // Processes the files given as files property of the data parameter,
62383        // returns a Promise object that allows to bind callbacks:
62384        process: function (data) {
62385            var that = this,
62386                options = $.extend({}, this.options, data);
62387            if (options.processQueue && options.processQueue.length) {
62388                this._transformProcessQueue(options);
62389                if (this._processing === 0) {
62390                    this._trigger('processstart');
62391                }
62392                $.each(data.files, function (index) {
62393                    var opts = index ? $.extend({}, options) : options,
62394                        func = function () {
62395                            if (data.errorThrown) {
62396                                return $.Deferred()
62397                                        .rejectWith(that, [data]).promise();
62398                            }
62399                            return that._processFile(opts, data);
62400                        };
62401                    opts.index = index;
62402                    that._processing += 1;
62403                    that._processingQueue = that._processingQueue.then(func, func)
62404                        .always(function () {
62405                            that._processing -= 1;
62406                            if (that._processing === 0) {
62407                                that._trigger('processstop');
62408                            }
62409                        });
62410                });
62411            }
62412            return this._processingQueue;
62413        },
62414
62415        _create: function () {
62416            this._super();
62417            this._processing = 0;
62418            this._processingQueue = $.Deferred().resolveWith(this)
62419                .promise();
62420        }
62421
62422    });
62423
62424}));
62425
62426/*
62427 * JavaScript Load Image
62428 * https://github.com/blueimp/JavaScript-Load-Image
62429 *
62430 * Copyright 2011, Sebastian Tschan
62431 * https://blueimp.net
62432 *
62433 * Licensed under the MIT license:
62434 * http://www.opensource.org/licenses/MIT
62435 */
62436
62437/*global define, module, window, document, URL, webkitURL, FileReader */
62438
62439;(function ($) {
62440  'use strict'
62441
62442  // Loads an image for a given File object.
62443  // Invokes the callback with an img or optional canvas
62444  // element (if supported by the browser) as parameter:
62445  var loadImage = function (file, callback, options) {
62446    var img = document.createElement('img')
62447    var url
62448    var oUrl
62449    img.onerror = callback
62450    img.onload = function () {
62451      if (oUrl && !(options && options.noRevoke)) {
62452        loadImage.revokeObjectURL(oUrl)
62453      }
62454      if (callback) {
62455        callback(loadImage.scale(img, options))
62456      }
62457    }
62458    if (loadImage.isInstanceOf('Blob', file) ||
62459      // Files are also Blob instances, but some browsers
62460      // (Firefox 3.6) support the File API but not Blobs:
62461      loadImage.isInstanceOf('File', file)) {
62462      url = oUrl = loadImage.createObjectURL(file)
62463      // Store the file type for resize processing:
62464      img._type = file.type
62465    } else if (typeof file === 'string') {
62466      url = file
62467      if (options && options.crossOrigin) {
62468        img.crossOrigin = options.crossOrigin
62469      }
62470    } else {
62471      return false
62472    }
62473    if (url) {
62474      img.src = url
62475      return img
62476    }
62477    return loadImage.readFile(file, function (e) {
62478      var target = e.target
62479      if (target && target.result) {
62480        img.src = target.result
62481      } else {
62482        if (callback) {
62483          callback(e)
62484        }
62485      }
62486    })
62487  }
62488  // The check for URL.revokeObjectURL fixes an issue with Opera 12,
62489  // which provides URL.createObjectURL but doesn't properly implement it:
62490  var urlAPI = (window.createObjectURL && window) ||
62491                (window.URL && URL.revokeObjectURL && URL) ||
62492                (window.webkitURL && webkitURL)
62493
62494  loadImage.isInstanceOf = function (type, obj) {
62495    // Cross-frame instanceof check
62496    return Object.prototype.toString.call(obj) === '[object ' + type + ']'
62497  }
62498
62499  // Transform image coordinates, allows to override e.g.
62500  // the canvas orientation based on the orientation option,
62501  // gets canvas, options passed as arguments:
62502  loadImage.transformCoordinates = function () {
62503    return
62504  }
62505
62506  // Returns transformed options, allows to override e.g.
62507  // maxWidth, maxHeight and crop options based on the aspectRatio.
62508  // gets img, options passed as arguments:
62509  loadImage.getTransformedOptions = function (img, options) {
62510    var aspectRatio = options.aspectRatio
62511    var newOptions
62512    var i
62513    var width
62514    var height
62515    if (!aspectRatio) {
62516      return options
62517    }
62518    newOptions = {}
62519    for (i in options) {
62520      if (options.hasOwnProperty(i)) {
62521        newOptions[i] = options[i]
62522      }
62523    }
62524    newOptions.crop = true
62525    width = img.naturalWidth || img.width
62526    height = img.naturalHeight || img.height
62527    if (width / height > aspectRatio) {
62528      newOptions.maxWidth = height * aspectRatio
62529      newOptions.maxHeight = height
62530    } else {
62531      newOptions.maxWidth = width
62532      newOptions.maxHeight = width / aspectRatio
62533    }
62534    return newOptions
62535  }
62536
62537  // Canvas render method, allows to implement a different rendering algorithm:
62538  loadImage.renderImageToCanvas = function (
62539    canvas,
62540    img,
62541    sourceX,
62542    sourceY,
62543    sourceWidth,
62544    sourceHeight,
62545    destX,
62546    destY,
62547    destWidth,
62548    destHeight
62549  ) {
62550    canvas.getContext('2d').drawImage(
62551      img,
62552      sourceX,
62553      sourceY,
62554      sourceWidth,
62555      sourceHeight,
62556      destX,
62557      destY,
62558      destWidth,
62559      destHeight
62560    )
62561    return canvas
62562  }
62563
62564  // This method is used to determine if the target image
62565  // should be a canvas element:
62566  loadImage.hasCanvasOption = function (options) {
62567    return options.canvas || options.crop || !!options.aspectRatio
62568  }
62569
62570  // Scales and/or crops the given image (img or canvas HTML element)
62571  // using the given options.
62572  // Returns a canvas object if the browser supports canvas
62573  // and the hasCanvasOption method returns true or a canvas
62574  // object is passed as image, else the scaled image:
62575  loadImage.scale = function (img, options) {
62576    options = options || {}
62577    var canvas = document.createElement('canvas')
62578    var useCanvas = img.getContext ||
62579                    (loadImage.hasCanvasOption(options) && canvas.getContext)
62580    var width = img.naturalWidth || img.width
62581    var height = img.naturalHeight || img.height
62582    var destWidth = width
62583    var destHeight = height
62584    var maxWidth
62585    var maxHeight
62586    var minWidth
62587    var minHeight
62588    var sourceWidth
62589    var sourceHeight
62590    var sourceX
62591    var sourceY
62592    var pixelRatio
62593    var downsamplingRatio
62594    var tmp
62595    function scaleUp () {
62596      var scale = Math.max(
62597        (minWidth || destWidth) / destWidth,
62598        (minHeight || destHeight) / destHeight
62599      )
62600      if (scale > 1) {
62601        destWidth *= scale
62602        destHeight *= scale
62603      }
62604    }
62605    function scaleDown () {
62606      var scale = Math.min(
62607        (maxWidth || destWidth) / destWidth,
62608        (maxHeight || destHeight) / destHeight
62609      )
62610      if (scale < 1) {
62611        destWidth *= scale
62612        destHeight *= scale
62613      }
62614    }
62615    if (useCanvas) {
62616      options = loadImage.getTransformedOptions(img, options)
62617      sourceX = options.left || 0
62618      sourceY = options.top || 0
62619      if (options.sourceWidth) {
62620        sourceWidth = options.sourceWidth
62621        if (options.right !== undefined && options.left === undefined) {
62622          sourceX = width - sourceWidth - options.right
62623        }
62624      } else {
62625        sourceWidth = width - sourceX - (options.right || 0)
62626      }
62627      if (options.sourceHeight) {
62628        sourceHeight = options.sourceHeight
62629        if (options.bottom !== undefined && options.top === undefined) {
62630          sourceY = height - sourceHeight - options.bottom
62631        }
62632      } else {
62633        sourceHeight = height - sourceY - (options.bottom || 0)
62634      }
62635      destWidth = sourceWidth
62636      destHeight = sourceHeight
62637    }
62638    maxWidth = options.maxWidth
62639    maxHeight = options.maxHeight
62640    minWidth = options.minWidth
62641    minHeight = options.minHeight
62642    if (useCanvas && maxWidth && maxHeight && options.crop) {
62643      destWidth = maxWidth
62644      destHeight = maxHeight
62645      tmp = sourceWidth / sourceHeight - maxWidth / maxHeight
62646      if (tmp < 0) {
62647        sourceHeight = maxHeight * sourceWidth / maxWidth
62648        if (options.top === undefined && options.bottom === undefined) {
62649          sourceY = (height - sourceHeight) / 2
62650        }
62651      } else if (tmp > 0) {
62652        sourceWidth = maxWidth * sourceHeight / maxHeight
62653        if (options.left === undefined && options.right === undefined) {
62654          sourceX = (width - sourceWidth) / 2
62655        }
62656      }
62657    } else {
62658      if (options.contain || options.cover) {
62659        minWidth = maxWidth = maxWidth || minWidth
62660        minHeight = maxHeight = maxHeight || minHeight
62661      }
62662      if (options.cover) {
62663        scaleDown()
62664        scaleUp()
62665      } else {
62666        scaleUp()
62667        scaleDown()
62668      }
62669    }
62670    if (useCanvas) {
62671      pixelRatio = options.pixelRatio
62672      if (pixelRatio > 1) {
62673        canvas.style.width = destWidth + 'px'
62674        canvas.style.height = destHeight + 'px'
62675        destWidth *= pixelRatio
62676        destHeight *= pixelRatio
62677        canvas.getContext('2d').scale(pixelRatio, pixelRatio)
62678      }
62679      downsamplingRatio = options.downsamplingRatio
62680      if (downsamplingRatio > 0 && downsamplingRatio < 1 &&
62681            destWidth < sourceWidth && destHeight < sourceHeight) {
62682        while (sourceWidth * downsamplingRatio > destWidth) {
62683          canvas.width = sourceWidth * downsamplingRatio
62684          canvas.height = sourceHeight * downsamplingRatio
62685          loadImage.renderImageToCanvas(
62686            canvas,
62687            img,
62688            sourceX,
62689            sourceY,
62690            sourceWidth,
62691            sourceHeight,
62692            0,
62693            0,
62694            canvas.width,
62695            canvas.height
62696          )
62697          sourceWidth = canvas.width
62698          sourceHeight = canvas.height
62699          img = document.createElement('canvas')
62700          img.width = sourceWidth
62701          img.height = sourceHeight
62702          loadImage.renderImageToCanvas(
62703            img,
62704            canvas,
62705            0,
62706            0,
62707            sourceWidth,
62708            sourceHeight,
62709            0,
62710            0,
62711            sourceWidth,
62712            sourceHeight
62713          )
62714        }
62715      }
62716      canvas.width = destWidth
62717      canvas.height = destHeight
62718      loadImage.transformCoordinates(
62719        canvas,
62720        options
62721      )
62722      return loadImage.renderImageToCanvas(
62723        canvas,
62724        img,
62725        sourceX,
62726        sourceY,
62727        sourceWidth,
62728        sourceHeight,
62729        0,
62730        0,
62731        destWidth,
62732        destHeight
62733      )
62734    }
62735    img.width = destWidth
62736    img.height = destHeight
62737    return img
62738  }
62739
62740  loadImage.createObjectURL = function (file) {
62741    return urlAPI ? urlAPI.createObjectURL(file) : false
62742  }
62743
62744  loadImage.revokeObjectURL = function (url) {
62745    return urlAPI ? urlAPI.revokeObjectURL(url) : false
62746  }
62747
62748  // Loads a given File object via FileReader interface,
62749  // invokes the callback with the event object (load or error).
62750  // The result can be read via event.target.result:
62751  loadImage.readFile = function (file, callback, method) {
62752    if (window.FileReader) {
62753      var fileReader = new FileReader()
62754      fileReader.onload = fileReader.onerror = callback
62755      method = method || 'readAsDataURL'
62756      if (fileReader[method]) {
62757        fileReader[method](file)
62758        return fileReader
62759      }
62760    }
62761    return false
62762  }
62763
62764  if (typeof define === 'function' && define.amd) {
62765    define('load-image',[],function () {
62766      return loadImage
62767    })
62768  } else if (typeof module === 'object' && module.exports) {
62769    module.exports = loadImage
62770  } else {
62771    $.loadImage = loadImage
62772  }
62773}(window))
62774;
62775/*
62776 * JavaScript Load Image Meta
62777 * https://github.com/blueimp/JavaScript-Load-Image
62778 *
62779 * Copyright 2013, Sebastian Tschan
62780 * https://blueimp.net
62781 *
62782 * Image meta data handling implementation
62783 * based on the help and contribution of
62784 * Achim Stöhr.
62785 *
62786 * Licensed under the MIT license:
62787 * http://www.opensource.org/licenses/MIT
62788 */
62789
62790/*global define, module, require, window, DataView, Blob, Uint8Array, console */
62791
62792;(function (factory) {
62793  'use strict'
62794  if (typeof define === 'function' && define.amd) {
62795    // Register as an anonymous AMD module:
62796    define('load-image-meta',['./load-image'], factory)
62797  } else if (typeof module === 'object' && module.exports) {
62798    factory(require('./load-image'))
62799  } else {
62800    // Browser globals:
62801    factory(window.loadImage)
62802  }
62803}(function (loadImage) {
62804  'use strict'
62805
62806  var hasblobSlice = window.Blob && (Blob.prototype.slice ||
62807  Blob.prototype.webkitSlice || Blob.prototype.mozSlice)
62808
62809  loadImage.blobSlice = hasblobSlice && function () {
62810    var slice = this.slice || this.webkitSlice || this.mozSlice
62811    return slice.apply(this, arguments)
62812  }
62813
62814  loadImage.metaDataParsers = {
62815    jpeg: {
62816      0xffe1: [] // APP1 marker
62817    }
62818  }
62819
62820  // Parses image meta data and calls the callback with an object argument
62821  // with the following properties:
62822  // * imageHead: The complete image head as ArrayBuffer (Uint8Array for IE10)
62823  // The options arguments accepts an object and supports the following properties:
62824  // * maxMetaDataSize: Defines the maximum number of bytes to parse.
62825  // * disableImageHead: Disables creating the imageHead property.
62826  loadImage.parseMetaData = function (file, callback, options) {
62827    options = options || {}
62828    var that = this
62829    // 256 KiB should contain all EXIF/ICC/IPTC segments:
62830    var maxMetaDataSize = options.maxMetaDataSize || 262144
62831    var data = {}
62832    var noMetaData = !(window.DataView && file && file.size >= 12 &&
62833                      file.type === 'image/jpeg' && loadImage.blobSlice)
62834    if (noMetaData || !loadImage.readFile(
62835        loadImage.blobSlice.call(file, 0, maxMetaDataSize),
62836        function (e) {
62837          if (e.target.error) {
62838            // FileReader error
62839            console.log(e.target.error)
62840            callback(data)
62841            return
62842          }
62843          // Note on endianness:
62844          // Since the marker and length bytes in JPEG files are always
62845          // stored in big endian order, we can leave the endian parameter
62846          // of the DataView methods undefined, defaulting to big endian.
62847          var buffer = e.target.result
62848          var dataView = new DataView(buffer)
62849          var offset = 2
62850          var maxOffset = dataView.byteLength - 4
62851          var headLength = offset
62852          var markerBytes
62853          var markerLength
62854          var parsers
62855          var i
62856          // Check for the JPEG marker (0xffd8):
62857          if (dataView.getUint16(0) === 0xffd8) {
62858            while (offset < maxOffset) {
62859              markerBytes = dataView.getUint16(offset)
62860              // Search for APPn (0xffeN) and COM (0xfffe) markers,
62861              // which contain application-specific meta-data like
62862              // Exif, ICC and IPTC data and text comments:
62863              if ((markerBytes >= 0xffe0 && markerBytes <= 0xffef) ||
62864                markerBytes === 0xfffe) {
62865                // The marker bytes (2) are always followed by
62866                // the length bytes (2), indicating the length of the
62867                // marker segment, which includes the length bytes,
62868                // but not the marker bytes, so we add 2:
62869                markerLength = dataView.getUint16(offset + 2) + 2
62870                if (offset + markerLength > dataView.byteLength) {
62871                  console.log('Invalid meta data: Invalid segment size.')
62872                  break
62873                }
62874                parsers = loadImage.metaDataParsers.jpeg[markerBytes]
62875                if (parsers) {
62876                  for (i = 0; i < parsers.length; i += 1) {
62877                    parsers[i].call(
62878                      that,
62879                      dataView,
62880                      offset,
62881                      markerLength,
62882                      data,
62883                      options
62884                    )
62885                  }
62886                }
62887                offset += markerLength
62888                headLength = offset
62889              } else {
62890                // Not an APPn or COM marker, probably safe to
62891                // assume that this is the end of the meta data
62892                break
62893              }
62894            }
62895            // Meta length must be longer than JPEG marker (2)
62896            // plus APPn marker (2), followed by length bytes (2):
62897            if (!options.disableImageHead && headLength > 6) {
62898              if (buffer.slice) {
62899                data.imageHead = buffer.slice(0, headLength)
62900              } else {
62901                // Workaround for IE10, which does not yet
62902                // support ArrayBuffer.slice:
62903                data.imageHead = new Uint8Array(buffer)
62904                  .subarray(0, headLength)
62905              }
62906            }
62907          } else {
62908            console.log('Invalid JPEG file: Missing JPEG marker.')
62909          }
62910          callback(data)
62911        },
62912        'readAsArrayBuffer'
62913      )) {
62914      callback(data)
62915    }
62916  }
62917}))
62918;
62919/*
62920 * JavaScript Load Image Exif Parser
62921 * https://github.com/blueimp/JavaScript-Load-Image
62922 *
62923 * Copyright 2013, Sebastian Tschan
62924 * https://blueimp.net
62925 *
62926 * Licensed under the MIT license:
62927 * http://www.opensource.org/licenses/MIT
62928 */
62929
62930/*global define, module, require, window, console */
62931
62932;(function (factory) {
62933  'use strict'
62934  if (typeof define === 'function' && define.amd) {
62935    // Register as an anonymous AMD module:
62936    define('load-image-exif',['./load-image', './load-image-meta'], factory)
62937  } else if (typeof module === 'object' && module.exports) {
62938    factory(require('./load-image'), require('./load-image-meta'))
62939  } else {
62940    // Browser globals:
62941    factory(window.loadImage)
62942  }
62943}(function (loadImage) {
62944  'use strict'
62945
62946  loadImage.ExifMap = function () {
62947    return this
62948  }
62949
62950  loadImage.ExifMap.prototype.map = {
62951    'Orientation': 0x0112
62952  }
62953
62954  loadImage.ExifMap.prototype.get = function (id) {
62955    return this[id] || this[this.map[id]]
62956  }
62957
62958  loadImage.getExifThumbnail = function (dataView, offset, length) {
62959    var hexData,
62960      i,
62961      b
62962    if (!length || offset + length > dataView.byteLength) {
62963      console.log('Invalid Exif data: Invalid thumbnail data.')
62964      return
62965    }
62966    hexData = []
62967    for (i = 0; i < length; i += 1) {
62968      b = dataView.getUint8(offset + i)
62969      hexData.push((b < 16 ? '0' : '') + b.toString(16))
62970    }
62971    return 'data:image/jpeg,%' + hexData.join('%')
62972  }
62973
62974  loadImage.exifTagTypes = {
62975    // byte, 8-bit unsigned int:
62976    1: {
62977      getValue: function (dataView, dataOffset) {
62978        return dataView.getUint8(dataOffset)
62979      },
62980      size: 1
62981    },
62982    // ascii, 8-bit byte:
62983    2: {
62984      getValue: function (dataView, dataOffset) {
62985        return String.fromCharCode(dataView.getUint8(dataOffset))
62986      },
62987      size: 1,
62988      ascii: true
62989    },
62990    // short, 16 bit int:
62991    3: {
62992      getValue: function (dataView, dataOffset, littleEndian) {
62993        return dataView.getUint16(dataOffset, littleEndian)
62994      },
62995      size: 2
62996    },
62997    // long, 32 bit int:
62998    4: {
62999      getValue: function (dataView, dataOffset, littleEndian) {
63000        return dataView.getUint32(dataOffset, littleEndian)
63001      },
63002      size: 4
63003    },
63004    // rational = two long values, first is numerator, second is denominator:
63005    5: {
63006      getValue: function (dataView, dataOffset, littleEndian) {
63007        return dataView.getUint32(dataOffset, littleEndian) /
63008        dataView.getUint32(dataOffset + 4, littleEndian)
63009      },
63010      size: 8
63011    },
63012    // slong, 32 bit signed int:
63013    9: {
63014      getValue: function (dataView, dataOffset, littleEndian) {
63015        return dataView.getInt32(dataOffset, littleEndian)
63016      },
63017      size: 4
63018    },
63019    // srational, two slongs, first is numerator, second is denominator:
63020    10: {
63021      getValue: function (dataView, dataOffset, littleEndian) {
63022        return dataView.getInt32(dataOffset, littleEndian) /
63023        dataView.getInt32(dataOffset + 4, littleEndian)
63024      },
63025      size: 8
63026    }
63027  }
63028  // undefined, 8-bit byte, value depending on field:
63029  loadImage.exifTagTypes[7] = loadImage.exifTagTypes[1]
63030
63031  loadImage.getExifValue = function (dataView, tiffOffset, offset, type, length, littleEndian) {
63032    var tagType = loadImage.exifTagTypes[type]
63033    var tagSize
63034    var dataOffset
63035    var values
63036    var i
63037    var str
63038    var c
63039    if (!tagType) {
63040      console.log('Invalid Exif data: Invalid tag type.')
63041      return
63042    }
63043    tagSize = tagType.size * length
63044    // Determine if the value is contained in the dataOffset bytes,
63045    // or if the value at the dataOffset is a pointer to the actual data:
63046    dataOffset = tagSize > 4
63047      ? tiffOffset + dataView.getUint32(offset + 8, littleEndian)
63048      : (offset + 8)
63049    if (dataOffset + tagSize > dataView.byteLength) {
63050      console.log('Invalid Exif data: Invalid data offset.')
63051      return
63052    }
63053    if (length === 1) {
63054      return tagType.getValue(dataView, dataOffset, littleEndian)
63055    }
63056    values = []
63057    for (i = 0; i < length; i += 1) {
63058      values[i] = tagType.getValue(dataView, dataOffset + i * tagType.size, littleEndian)
63059    }
63060    if (tagType.ascii) {
63061      str = ''
63062      // Concatenate the chars:
63063      for (i = 0; i < values.length; i += 1) {
63064        c = values[i]
63065        // Ignore the terminating NULL byte(s):
63066        if (c === '\u0000') {
63067          break
63068        }
63069        str += c
63070      }
63071      return str
63072    }
63073    return values
63074  }
63075
63076  loadImage.parseExifTag = function (dataView, tiffOffset, offset, littleEndian, data) {
63077    var tag = dataView.getUint16(offset, littleEndian)
63078    data.exif[tag] = loadImage.getExifValue(
63079      dataView,
63080      tiffOffset,
63081      offset,
63082      dataView.getUint16(offset + 2, littleEndian), // tag type
63083      dataView.getUint32(offset + 4, littleEndian), // tag length
63084      littleEndian
63085    )
63086  }
63087
63088  loadImage.parseExifTags = function (dataView, tiffOffset, dirOffset, littleEndian, data) {
63089    var tagsNumber,
63090      dirEndOffset,
63091      i
63092    if (dirOffset + 6 > dataView.byteLength) {
63093      console.log('Invalid Exif data: Invalid directory offset.')
63094      return
63095    }
63096    tagsNumber = dataView.getUint16(dirOffset, littleEndian)
63097    dirEndOffset = dirOffset + 2 + 12 * tagsNumber
63098    if (dirEndOffset + 4 > dataView.byteLength) {
63099      console.log('Invalid Exif data: Invalid directory size.')
63100      return
63101    }
63102    for (i = 0; i < tagsNumber; i += 1) {
63103      this.parseExifTag(
63104        dataView,
63105        tiffOffset,
63106        dirOffset + 2 + 12 * i, // tag offset
63107        littleEndian,
63108        data
63109      )
63110    }
63111    // Return the offset to the next directory:
63112    return dataView.getUint32(dirEndOffset, littleEndian)
63113  }
63114
63115  loadImage.parseExifData = function (dataView, offset, length, data, options) {
63116    if (options.disableExif) {
63117      return
63118    }
63119    var tiffOffset = offset + 10
63120    var littleEndian
63121    var dirOffset
63122    var thumbnailData
63123    // Check for the ASCII code for "Exif" (0x45786966):
63124    if (dataView.getUint32(offset + 4) !== 0x45786966) {
63125      // No Exif data, might be XMP data instead
63126      return
63127    }
63128    if (tiffOffset + 8 > dataView.byteLength) {
63129      console.log('Invalid Exif data: Invalid segment size.')
63130      return
63131    }
63132    // Check for the two null bytes:
63133    if (dataView.getUint16(offset + 8) !== 0x0000) {
63134      console.log('Invalid Exif data: Missing byte alignment offset.')
63135      return
63136    }
63137    // Check the byte alignment:
63138    switch (dataView.getUint16(tiffOffset)) {
63139      case 0x4949:
63140        littleEndian = true
63141        break
63142      case 0x4D4D:
63143        littleEndian = false
63144        break
63145      default:
63146        console.log('Invalid Exif data: Invalid byte alignment marker.')
63147        return
63148    }
63149    // Check for the TIFF tag marker (0x002A):
63150    if (dataView.getUint16(tiffOffset + 2, littleEndian) !== 0x002A) {
63151      console.log('Invalid Exif data: Missing TIFF marker.')
63152      return
63153    }
63154    // Retrieve the directory offset bytes, usually 0x00000008 or 8 decimal:
63155    dirOffset = dataView.getUint32(tiffOffset + 4, littleEndian)
63156    // Create the exif object to store the tags:
63157    data.exif = new loadImage.ExifMap()
63158    // Parse the tags of the main image directory and retrieve the
63159    // offset to the next directory, usually the thumbnail directory:
63160    dirOffset = loadImage.parseExifTags(
63161      dataView,
63162      tiffOffset,
63163      tiffOffset + dirOffset,
63164      littleEndian,
63165      data
63166    )
63167    if (dirOffset && !options.disableExifThumbnail) {
63168      thumbnailData = {exif: {}}
63169      dirOffset = loadImage.parseExifTags(
63170        dataView,
63171        tiffOffset,
63172        tiffOffset + dirOffset,
63173        littleEndian,
63174        thumbnailData
63175      )
63176      // Check for JPEG Thumbnail offset:
63177      if (thumbnailData.exif[0x0201]) {
63178        data.exif.Thumbnail = loadImage.getExifThumbnail(
63179          dataView,
63180          tiffOffset + thumbnailData.exif[0x0201],
63181          thumbnailData.exif[0x0202] // Thumbnail data length
63182        )
63183      }
63184    }
63185    // Check for Exif Sub IFD Pointer:
63186    if (data.exif[0x8769] && !options.disableExifSub) {
63187      loadImage.parseExifTags(
63188        dataView,
63189        tiffOffset,
63190        tiffOffset + data.exif[0x8769], // directory offset
63191        littleEndian,
63192        data
63193      )
63194    }
63195    // Check for GPS Info IFD Pointer:
63196    if (data.exif[0x8825] && !options.disableExifGps) {
63197      loadImage.parseExifTags(
63198        dataView,
63199        tiffOffset,
63200        tiffOffset + data.exif[0x8825], // directory offset
63201        littleEndian,
63202        data
63203      )
63204    }
63205  }
63206
63207  // Registers the Exif parser for the APP1 JPEG meta data segment:
63208  loadImage.metaDataParsers.jpeg[0xffe1].push(loadImage.parseExifData)
63209
63210  // Adds the following properties to the parseMetaData callback data:
63211  // * exif: The exif tags, parsed by the parseExifData method
63212
63213  // Adds the following options to the parseMetaData method:
63214  // * disableExif: Disables Exif parsing.
63215  // * disableExifThumbnail: Disables parsing of the Exif Thumbnail.
63216  // * disableExifSub: Disables parsing of the Exif Sub IFD.
63217  // * disableExifGps: Disables parsing of the Exif GPS Info IFD.
63218}))
63219;
63220/*
63221 * jQuery File Upload Image Preview & Resize Plugin
63222 * https://github.com/blueimp/jQuery-File-Upload
63223 *
63224 * Copyright 2013, Sebastian Tschan
63225 * https://blueimp.net
63226 *
63227 * Licensed under the MIT license:
63228 * http://www.opensource.org/licenses/MIT
63229 */
63230
63231/* jshint nomen:false */
63232/* global define, require, window, Blob */
63233
63234;(function (factory) {
63235    'use strict';
63236    if (typeof define === 'function' && define.amd) {
63237        // Register as an anonymous AMD module:
63238        define('jquery.fileupload-image',[
63239            'jquery',
63240            'load-image',
63241            'load-image-meta',
63242            'load-image-exif',
63243            'canvas-to-blob',
63244            './jquery.fileupload-process'
63245        ], factory);
63246    } else if (typeof exports === 'object') {
63247        // Node/CommonJS:
63248        factory(
63249            require('jquery'),
63250            require('blueimp-load-image/js/load-image'),
63251            require('blueimp-load-image/js/load-image-meta'),
63252            require('blueimp-load-image/js/load-image-exif'),
63253            require('blueimp-canvas-to-blob'),
63254            require('./jquery.fileupload-process')
63255        );
63256    } else {
63257        // Browser globals:
63258        factory(
63259            window.jQuery,
63260            window.loadImage
63261        );
63262    }
63263}(function ($, loadImage) {
63264    'use strict';
63265
63266    // Prepend to the default processQueue:
63267    $.blueimp.fileupload.prototype.options.processQueue.unshift(
63268        {
63269            action: 'loadImageMetaData',
63270            disableImageHead: '@',
63271            disableExif: '@',
63272            disableExifThumbnail: '@',
63273            disableExifSub: '@',
63274            disableExifGps: '@',
63275            disabled: '@disableImageMetaDataLoad'
63276        },
63277        {
63278            action: 'loadImage',
63279            // Use the action as prefix for the "@" options:
63280            prefix: true,
63281            fileTypes: '@',
63282            maxFileSize: '@',
63283            noRevoke: '@',
63284            disabled: '@disableImageLoad'
63285        },
63286        {
63287            action: 'resizeImage',
63288            // Use "image" as prefix for the "@" options:
63289            prefix: 'image',
63290            maxWidth: '@',
63291            maxHeight: '@',
63292            minWidth: '@',
63293            minHeight: '@',
63294            crop: '@',
63295            orientation: '@',
63296            forceResize: '@',
63297            disabled: '@disableImageResize'
63298        },
63299        {
63300            action: 'saveImage',
63301            quality: '@imageQuality',
63302            type: '@imageType',
63303            disabled: '@disableImageResize'
63304        },
63305        {
63306            action: 'saveImageMetaData',
63307            disabled: '@disableImageMetaDataSave'
63308        },
63309        {
63310            action: 'resizeImage',
63311            // Use "preview" as prefix for the "@" options:
63312            prefix: 'preview',
63313            maxWidth: '@',
63314            maxHeight: '@',
63315            minWidth: '@',
63316            minHeight: '@',
63317            crop: '@',
63318            orientation: '@',
63319            thumbnail: '@',
63320            canvas: '@',
63321            disabled: '@disableImagePreview'
63322        },
63323        {
63324            action: 'setImage',
63325            name: '@imagePreviewName',
63326            disabled: '@disableImagePreview'
63327        },
63328        {
63329            action: 'deleteImageReferences',
63330            disabled: '@disableImageReferencesDeletion'
63331        }
63332    );
63333
63334    // The File Upload Resize plugin extends the fileupload widget
63335    // with image resize functionality:
63336    $.widget('blueimp.fileupload', $.blueimp.fileupload, {
63337
63338        options: {
63339            // The regular expression for the types of images to load:
63340            // matched against the file type:
63341            loadImageFileTypes: /^image\/(gif|jpeg|png|svg\+xml)$/,
63342            // The maximum file size of images to load:
63343            loadImageMaxFileSize: 10000000, // 10MB
63344            // The maximum width of resized images:
63345            imageMaxWidth: 1920,
63346            // The maximum height of resized images:
63347            imageMaxHeight: 1080,
63348            // Defines the image orientation (1-8) or takes the orientation
63349            // value from Exif data if set to true:
63350            imageOrientation: false,
63351            // Define if resized images should be cropped or only scaled:
63352            imageCrop: false,
63353            // Disable the resize image functionality by default:
63354            disableImageResize: true,
63355            // The maximum width of the preview images:
63356            previewMaxWidth: 80,
63357            // The maximum height of the preview images:
63358            previewMaxHeight: 80,
63359            // Defines the preview orientation (1-8) or takes the orientation
63360            // value from Exif data if set to true:
63361            previewOrientation: true,
63362            // Create the preview using the Exif data thumbnail:
63363            previewThumbnail: true,
63364            // Define if preview images should be cropped or only scaled:
63365            previewCrop: false,
63366            // Define if preview images should be resized as canvas elements:
63367            previewCanvas: true
63368        },
63369
63370        processActions: {
63371
63372            // Loads the image given via data.files and data.index
63373            // as img element, if the browser supports the File API.
63374            // Accepts the options fileTypes (regular expression)
63375            // and maxFileSize (integer) to limit the files to load:
63376            loadImage: function (data, options) {
63377                if (options.disabled) {
63378                    return data;
63379                }
63380                var that = this,
63381                    file = data.files[data.index],
63382                    dfd = $.Deferred();
63383                if (($.type(options.maxFileSize) === 'number' &&
63384                            file.size > options.maxFileSize) ||
63385                        (options.fileTypes &&
63386                            !options.fileTypes.test(file.type)) ||
63387                        !loadImage(
63388                            file,
63389                            function (img) {
63390                                if (img.src) {
63391                                    data.img = img;
63392                                }
63393                                dfd.resolveWith(that, [data]);
63394                            },
63395                            options
63396                        )) {
63397                    return data;
63398                }
63399                return dfd.promise();
63400            },
63401
63402            // Resizes the image given as data.canvas or data.img
63403            // and updates data.canvas or data.img with the resized image.
63404            // Also stores the resized image as preview property.
63405            // Accepts the options maxWidth, maxHeight, minWidth,
63406            // minHeight, canvas and crop:
63407            resizeImage: function (data, options) {
63408                if (options.disabled || !(data.canvas || data.img)) {
63409                    return data;
63410                }
63411                options = $.extend({canvas: true}, options);
63412                var that = this,
63413                    dfd = $.Deferred(),
63414                    img = (options.canvas && data.canvas) || data.img,
63415                    resolve = function (newImg) {
63416                        if (newImg && (newImg.width !== img.width ||
63417                                newImg.height !== img.height ||
63418                                options.forceResize)) {
63419                            data[newImg.getContext ? 'canvas' : 'img'] = newImg;
63420                        }
63421                        data.preview = newImg;
63422                        dfd.resolveWith(that, [data]);
63423                    },
63424                    thumbnail;
63425                if (data.exif) {
63426                    if (options.orientation === true) {
63427                        options.orientation = data.exif.get('Orientation');
63428                    }
63429                    if (options.thumbnail) {
63430                        thumbnail = data.exif.get('Thumbnail');
63431                        if (thumbnail) {
63432                            loadImage(thumbnail, resolve, options);
63433                            return dfd.promise();
63434                        }
63435                    }
63436                    // Prevent orienting the same image twice:
63437                    if (data.orientation) {
63438                        delete options.orientation;
63439                    } else {
63440                        data.orientation = options.orientation;
63441                    }
63442                }
63443                if (img) {
63444                    resolve(loadImage.scale(img, options));
63445                    return dfd.promise();
63446                }
63447                return data;
63448            },
63449
63450            // Saves the processed image given as data.canvas
63451            // inplace at data.index of data.files:
63452            saveImage: function (data, options) {
63453                if (!data.canvas || options.disabled) {
63454                    return data;
63455                }
63456                var that = this,
63457                    file = data.files[data.index],
63458                    dfd = $.Deferred();
63459                if (data.canvas.toBlob) {
63460                    data.canvas.toBlob(
63461                        function (blob) {
63462                            if (!blob.name) {
63463                                if (file.type === blob.type) {
63464                                    blob.name = file.name;
63465                                } else if (file.name) {
63466                                    blob.name = file.name.replace(
63467                                        /\.\w+$/,
63468                                        '.' + blob.type.substr(6)
63469                                    );
63470                                }
63471                            }
63472                            // Don't restore invalid meta data:
63473                            if (file.type !== blob.type) {
63474                                delete data.imageHead;
63475                            }
63476                            // Store the created blob at the position
63477                            // of the original file in the files list:
63478                            data.files[data.index] = blob;
63479                            dfd.resolveWith(that, [data]);
63480                        },
63481                        options.type || file.type,
63482                        options.quality
63483                    );
63484                } else {
63485                    return data;
63486                }
63487                return dfd.promise();
63488            },
63489
63490            loadImageMetaData: function (data, options) {
63491                if (options.disabled) {
63492                    return data;
63493                }
63494                var that = this,
63495                    dfd = $.Deferred();
63496                loadImage.parseMetaData(data.files[data.index], function (result) {
63497                    $.extend(data, result);
63498                    dfd.resolveWith(that, [data]);
63499                }, options);
63500                return dfd.promise();
63501            },
63502
63503            saveImageMetaData: function (data, options) {
63504                if (!(data.imageHead && data.canvas &&
63505                        data.canvas.toBlob && !options.disabled)) {
63506                    return data;
63507                }
63508                var file = data.files[data.index],
63509                    blob = new Blob([
63510                        data.imageHead,
63511                        // Resized images always have a head size of 20 bytes,
63512                        // including the JPEG marker and a minimal JFIF header:
63513                        this._blobSlice.call(file, 20)
63514                    ], {type: file.type});
63515                blob.name = file.name;
63516                data.files[data.index] = blob;
63517                return data;
63518            },
63519
63520            // Sets the resized version of the image as a property of the
63521            // file object, must be called after "saveImage":
63522            setImage: function (data, options) {
63523                if (data.preview && !options.disabled) {
63524                    data.files[data.index][options.name || 'preview'] = data.preview;
63525                }
63526                return data;
63527            },
63528
63529            deleteImageReferences: function (data, options) {
63530                if (!options.disabled) {
63531                    delete data.img;
63532                    delete data.canvas;
63533                    delete data.preview;
63534                    delete data.imageHead;
63535                }
63536                return data;
63537            }
63538
63539        }
63540
63541    });
63542
63543}));
63544
63545/*
63546 * jQuery Iframe Transport Plugin
63547 * https://github.com/blueimp/jQuery-File-Upload
63548 *
63549 * Copyright 2011, Sebastian Tschan
63550 * https://blueimp.net
63551 *
63552 * Licensed under the MIT license:
63553 * http://www.opensource.org/licenses/MIT
63554 */
63555
63556/* global define, require, window, document */
63557
63558;(function (factory) {
63559    'use strict';
63560    if (typeof define === 'function' && define.amd) {
63561        // Register as an anonymous AMD module:
63562        define('jqueryIFrameTransport',['jquery'], factory);
63563    } else if (typeof exports === 'object') {
63564        // Node/CommonJS:
63565        factory(require('jquery'));
63566    } else {
63567        // Browser globals:
63568        factory(window.jQuery);
63569    }
63570}(function ($) {
63571    'use strict';
63572
63573    // Helper variable to create unique names for the transport iframes:
63574    var counter = 0;
63575
63576    // The iframe transport accepts four additional options:
63577    // options.fileInput: a jQuery collection of file input fields
63578    // options.paramName: the parameter name for the file form data,
63579    //  overrides the name property of the file input field(s),
63580    //  can be a string or an array of strings.
63581    // options.formData: an array of objects with name and value properties,
63582    //  equivalent to the return data of .serializeArray(), e.g.:
63583    //  [{name: 'a', value: 1}, {name: 'b', value: 2}]
63584    // options.initialIframeSrc: the URL of the initial iframe src,
63585    //  by default set to "javascript:false;"
63586    $.ajaxTransport('iframe', function (options) {
63587        if (options.async) {
63588            // javascript:false as initial iframe src
63589            // prevents warning popups on HTTPS in IE6:
63590            /*jshint scripturl: true */
63591            var initialIframeSrc = options.initialIframeSrc || 'javascript:false;',
63592            /*jshint scripturl: false */
63593                form,
63594                iframe,
63595                addParamChar;
63596            return {
63597                send: function (_, completeCallback) {
63598                    form = $('<form style="display:none;"></form>');
63599                    form.attr('accept-charset', options.formAcceptCharset);
63600                    addParamChar = /\?/.test(options.url) ? '&' : '?';
63601                    // XDomainRequest only supports GET and POST:
63602                    if (options.type === 'DELETE') {
63603                        options.url = options.url + addParamChar + '_method=DELETE';
63604                        options.type = 'POST';
63605                    } else if (options.type === 'PUT') {
63606                        options.url = options.url + addParamChar + '_method=PUT';
63607                        options.type = 'POST';
63608                    } else if (options.type === 'PATCH') {
63609                        options.url = options.url + addParamChar + '_method=PATCH';
63610                        options.type = 'POST';
63611                    }
63612                    // IE versions below IE8 cannot set the name property of
63613                    // elements that have already been added to the DOM,
63614                    // so we set the name along with the iframe HTML markup:
63615                    counter += 1;
63616                    iframe = $(
63617                        '<iframe src="' + initialIframeSrc +
63618                            '" name="iframe-transport-' + counter + '"></iframe>'
63619                    ).bind('load', function () {
63620                        var fileInputClones,
63621                            paramNames = $.isArray(options.paramName) ?
63622                                    options.paramName : [options.paramName];
63623                        iframe
63624                            .unbind('load')
63625                            .bind('load', function () {
63626                                var response;
63627                                // Wrap in a try/catch block to catch exceptions thrown
63628                                // when trying to access cross-domain iframe contents:
63629                                try {
63630                                    response = iframe.contents();
63631                                    // Google Chrome and Firefox do not throw an
63632                                    // exception when calling iframe.contents() on
63633                                    // cross-domain requests, so we unify the response:
63634                                    if (!response.length || !response[0].firstChild) {
63635                                        throw new Error();
63636                                    }
63637                                } catch (e) {
63638                                    response = undefined;
63639                                }
63640                                // The complete callback returns the
63641                                // iframe content document as response object:
63642                                completeCallback(
63643                                    200,
63644                                    'success',
63645                                    {'iframe': response}
63646                                );
63647                                // Fix for IE endless progress bar activity bug
63648                                // (happens on form submits to iframe targets):
63649                                $('<iframe src="' + initialIframeSrc + '"></iframe>')
63650                                    .appendTo(form);
63651                                window.setTimeout(function () {
63652                                    // Removing the form in a setTimeout call
63653                                    // allows Chrome's developer tools to display
63654                                    // the response result
63655                                    form.remove();
63656                                }, 0);
63657                            });
63658                        form
63659                            .prop('target', iframe.prop('name'))
63660                            .prop('action', options.url)
63661                            .prop('method', options.type);
63662                        if (options.formData) {
63663                            $.each(options.formData, function (index, field) {
63664                                $('<input type="hidden"/>')
63665                                    .prop('name', field.name)
63666                                    .val(field.value)
63667                                    .appendTo(form);
63668                            });
63669                        }
63670                        if (options.fileInput && options.fileInput.length &&
63671                                options.type === 'POST') {
63672                            fileInputClones = options.fileInput.clone();
63673                            // Insert a clone for each file input field:
63674                            options.fileInput.after(function (index) {
63675                                return fileInputClones[index];
63676                            });
63677                            if (options.paramName) {
63678                                options.fileInput.each(function (index) {
63679                                    $(this).prop(
63680                                        'name',
63681                                        paramNames[index] || options.paramName
63682                                    );
63683                                });
63684                            }
63685                            // Appending the file input fields to the hidden form
63686                            // removes them from their original location:
63687                            form
63688                                .append(options.fileInput)
63689                                .prop('enctype', 'multipart/form-data')
63690                                // enctype must be set as encoding for IE:
63691                                .prop('encoding', 'multipart/form-data');
63692                            // Remove the HTML5 form attribute from the input(s):
63693                            options.fileInput.removeAttr('form');
63694                        }
63695                        form.submit();
63696                        // Insert the file input fields at their original location
63697                        // by replacing the clones with the originals:
63698                        if (fileInputClones && fileInputClones.length) {
63699                            options.fileInput.each(function (index, input) {
63700                                var clone = $(fileInputClones[index]);
63701                                // Restore the original name and form properties:
63702                                $(input)
63703                                    .prop('name', clone.prop('name'))
63704                                    .attr('form', clone.attr('form'));
63705                                clone.replaceWith(input);
63706                            });
63707                        }
63708                    });
63709                    form.append(iframe).appendTo(document.body);
63710                },
63711                abort: function () {
63712                    if (iframe) {
63713                        // javascript:false as iframe src aborts the request
63714                        // and prevents warning popups on HTTPS in IE6.
63715                        // concat is used to avoid the "Script URL" JSLint error:
63716                        iframe
63717                            .unbind('load')
63718                            .prop('src', initialIframeSrc);
63719                    }
63720                    if (form) {
63721                        form.remove();
63722                    }
63723                }
63724            };
63725        }
63726    });
63727
63728    // The iframe transport returns the iframe content document as response.
63729    // The following adds converters from iframe to text, json, html, xml
63730    // and script.
63731    // Please note that the Content-Type for JSON responses has to be text/plain
63732    // or text/html, if the browser doesn't include application/json in the
63733    // Accept header, else IE will show a download dialog.
63734    // The Content-Type for XML responses on the other hand has to be al
63734ways
63735    // application/xml or text/xml, so IE properly parses the XML response.
63736    // See also
63737    // https://github.com/blueimp/jQuery-File-Upload/wiki/Setup#content-type-negotiation
63738    $.ajaxSetup({
63739        converters: {
63740            'iframe text': function (iframe) {
63741                return iframe && $(iframe[0].body).text();
63742            },
63743            'iframe json': function (iframe) {
63744                return iframe && $.parseJSON($(iframe[0].body).text());
63745            },
63746            'iframe html': function (iframe) {
63747                return iframe && $(iframe[0].body).html();
63748            },
63749            'iframe xml': function (iframe) {
63750                var xmlDoc = iframe && iframe[0];
63751                return xmlDoc && $.isXMLDoc(xmlDoc) ? xmlDoc :
63752                        $.parseXML((xmlDoc.XMLDocument && xmlDoc.XMLDocument.xml) ||
63753                            $(xmlDoc.body).html());
63754            },
63755            'iframe script': function (iframe) {
63756                return iframe && $.globalEval($(iframe[0].body).text());
63757            }
63758        }
63759    });
63760
63761}));
63762
63763
63764
63765(function($){
63766
63767$.fn.sendkeys = function (x){
63768	return this.each( function(){
63769		bililiteRange(this).bounds('selection').sendkeys(x).select();
63770		this.focus();
63771	});
63772}; // sendkeys
63773
63774// add a default handler for keydowns so that we can send keystrokes, even though code-generated events 
63775// are untrusted (http://www.w3.org/TR/DOM-Level-3-Events/#trusted-events)
63776// documentation of special event handlers is at http://learn.jquery.com/events/event-extensions/
63777$.event.special.keydown = $.event.special.keydown || {};
63778$.event.special.keydown._default = function (evt){
63779	if (evt.isTrusted) return false;
63780	if (evt.key == null) return false; // nothing to print. Use the keymap plugin to set this 
63781	if (evt.ctrlKey || evt.altKey || evt.metaKey) return false; // only deal with printable characters.
63782	var target = evt.target;
63783	if (target.isContentEditable || target.nodeName == 'INPUT' || target.nodeName == 'TEXTAREA') {
63784		// only insert into editable elements
63785		var key = evt.key;
63786		if (key.length > 1 && key.charAt(0) != '{') key = '{'+key+'}'; // sendkeys notation
63787		$(target).sendkeys(key);
63788		return true;
63789	}
63790	return false;
63791}
63792})(jQuery);
63793define("jquerySendkeys", ["jquery","bililiteRange"], function(){});
63794
63795/**
63796 * Timeago is a jQuery plugin that makes it easy to support automatically
63797 * updating fuzzy timestamps (e.g. "4 minutes ago" or "about 1 day ago").
63798 *
63799 * @name timeago
63800 * @version 1.3.2
63801 * @requires jQuery v1.2.3+
63802 * @author Ryan McGeary
63803 * @license MIT License - http://www.opensource.org/licenses/mit-license.php
63804 *
63805 * For usage and examples, visit:
63806 * http://timeago.yarp.com/
63807 *
63808 * Copyright (c) 2008-2013, Ryan McGeary (ryan -[at]- mcgeary [*dot*] org)
63809 */
63810
63811(function (factory) {
63812  if (typeof define === 'function' && define.amd) {
63813    // AMD. Register as an anonymous module.
63814    define('jquery-timeago',['jquery'], factory);
63815  } else {
63816    // Browser globals
63817    factory(jQuery);
63818  }
63819}(function ($) {
63820  $.timeago = function(timestamp) {
63821    if (timestamp instanceof Date) {
63822      return inWords(timestamp);
63823    } else if (typeof timestamp === "string") {
63824      return inWords($.timeago.parse(timestamp));
63825    } else if (typeof timestamp === "number") {
63826      return inWords(new Date(timestamp));
63827    } else {
63828      return inWords($.timeago.datetime(timestamp));
63829    }
63830  };
63831  var $t = $.timeago;
63832
63833  $.extend($.timeago, {
63834    settings: {
63835      refreshMillis: 60000,
63836      allowFuture: false,
63837      localeTitle: false,
63838      cutoff: 0,
63839      strings: {
63840        prefixAgo: null,
63841        prefixFromNow: null,
63842        suffixAgo: "ago",
63843        suffixFromNow: "from now",
63844        seconds: "less than a minute",
63845        minute: "about a minute",
63846        minutes: "%d minutes",
63847        hour: "about an hour",
63848        hours: "about %d hours",
63849        day: "a day",
63850        days: "%d days",
63851        month: "about a month",
63852        months: "%d months",
63853        year: "about a year",
63854        years: "%d years",
63855        wordSeparator: " ",
63856        numbers: []
63857      }
63858    },
63859    inWords: function(distanceMillis) {
63860      var $l = this.settings.strings;
63861      var prefix = $l.prefixAgo;
63862      var suffix = $l.suffixAgo;
63863      if (this.settings.allowFuture) {
63864        if (distanceMillis < 0) {
63865          prefix = $l.prefixFromNow;
63866          suffix = $l.suffixFromNow;
63867        }
63868      }
63869
63870      var seconds = Math.abs(distanceMillis) / 1000;
63871      var minutes = seconds / 60;
63872      var hours = minutes / 60;
63873      var days = hours / 24;
63874      var years = days / 365;
63875
63876      function substitute(stringOrFunction, number) {
63877        var string = $.isFunction(stringOrFunction) ? stringOrFunction(number, distanceMillis) : stringOrFunction;
63878        var value = ($l.numbers && $l.numbers[number]) || number;
63879        return string.replace(/%d/i, value);
63880      }
63881
63882      var words = seconds < 45 && substitute($l.seconds, Math.round(seconds)) ||
63883        seconds < 90 && substitute($l.minute, 1) ||
63884        minutes < 45 && substitute($l.minutes, Math.round(minutes)) ||
63885        minutes < 90 && substitute($l.hour, 1) ||
63886        hours < 24 && substitute($l.hours, Math.round(hours)) ||
63887        hours < 42 && substitute($l.day, 1) ||
63888        days < 30 && substitute($l.days, Math.round(days)) ||
63889        days < 45 && substitute($l.month, 1) ||
63890        days < 365 && substitute($l.months, Math.round(days / 30)) ||
63891        years < 1.5 && substitute($l.year, 1) ||
63892        substitute($l.years, Math.round(years));
63893
63894      var separator = $l.wordSeparator || "";
63895      if ($l.wordSeparator === undefined) { separator = " "; }
63896      return $.trim([prefix, words, suffix].join(separator));
63897    },
63898    parse: function(iso8601) {
63899      var s = $.trim(iso8601);
63900      s = s.replace(/\.\d+/,""); // remove milliseconds
63901      s = s.replace(/-/,"/").replace(/-/,"/");
63902      s = s.replace(/T/," ").replace(/Z/," UTC");
63903      s = s.replace(/([\+\-]\d\d)\:?(\d\d)/," $1$2"); // -04:00 -> -0400
63904      s = s.replace(/([\+\-]\d\d)$/," $100"); // +09 -> +0900
63905      return new Date(s);
63906    },
63907    datetime: function(elem) {
63908      var iso8601 = $t.isTime(elem) ? $(elem).attr("datetime") : $(elem).attr("title");
63909      return $t.parse(iso8601);
63910    },
63911    isTime: function(elem) {
63912      // jQuery's `is()` doesn't play well with HTML5 in IE
63913      return $(elem).get(0).tagName.toLowerCase() === "time"; // $(elem).is("time");
63914    }
63915  });
63916
63917  // functions that can be called via $(el).timeago('action')
63918  // init is default when no action is given
63919  // functions are called with context of a single element
63920  var functions = {
63921    init: function(){
63922      var refresh_el = $.proxy(refresh, this);
63923      refresh_el();
63924      var $s = $t.settings;
63925      if ($s.refreshMillis > 0) {
63926        this._timeagoInterval = setInterval(refresh_el, $s.refreshMillis);
63927      }
63928    },
63929    update: function(time){
63930      var parsedTime = $t.parse(time);
63931      $(this).data('timeago', { datetime: parsedTime });
63932      if($t.settings.localeTitle) $(this).attr("title", parsedTime.toLocaleStr
63932ing());
63933      refresh.apply(this);
63934    },
63935    updateFromDOM: function(){
63936      $(this).data('timeago', { datetime: $t.parse( $t.isTime(this) ? $(this).attr("datetime") : $(this).attr("title") ) });
63937      refresh.apply(this);
63938    },
63939    dispose: function () {
63940      if (this._timeagoInterval) {
63941        window.clearInterval(this._timeagoInterval);
63942        this._timeagoInterval = null;
63943      }
63944    }
63945  };
63946
63947  $.fn.timeago = function(action, options) {
63948    var fn = action ? functions[action] : functions.init;
63949    if(!fn){
63950      throw new Error("Unknown function name '"+ action +"' for timeago");
63951    }
63952    // each over objects here and call the requested function
63953    this.each(function(){
63954      fn.call(this, options);
63955    });
63956    return this;
63957  };
63958
63959  function refresh() {
63960    var data = prepareData(this);
63961    var $s = $t.settings;
63962
63963    if (!isNaN(data.datetime)) {
63964      if ( $s.cutoff == 0 || distance(data.datetime) < $s.cutoff) {
63965        $(this).text(inWords(data.datetime));
63966      }
63967    }
63968    return this;
63969  }
63970
63971  function prepareData(element) {
63972    element = $(element);
63973    if (!element.data("timeago")) {
63974      element.data("timeago", { datetime: $t.datetime(element) });
63975      var text = $.trim(element.text());
63976      if ($t.settings.localeTitle) {
63977        element.attr("title", element.data('timeago').datetime.toLocaleString());
63978      } else if (text.length > 0 && !($t.isTime(element) && element.attr("title"))) {
63979        element.attr("title", text);
63980      }
63981    }
63982    return element.data("timeago");
63983  }
63984
63985  function inWords(date) {
63986    return $t.inWords(distance(date));
63987  }
63988
63989  function distance(date) {
63990    return (new Date().getTime() - date.getTime());
63991  }
63992
63993  // fix for IE6 suckage
63994  document.createElement("abbr");
63995  document.createElement("time");
63996}));
63997
63998/* NUGET: BEGIN LICENSE TEXT
63999 *
64000 * Microsoft grants you the right to use these script files for the sole
64001 * purpose of either: (i) interacting through your browser with the Microsoft
64002 * website or online service, subject to the applicable licensing or use
64003 * terms; or (ii) using the files as included with a Microsoft product subject
64004 * to that product's license terms. Microsoft reserves all other rights to the
64005 * files not expressly granted by Microsoft, whether by implication, estoppel
64006 * or otherwise. Insofar as a script file is dual licensed under GPL,
64007 * Microsoft neither took the code under GPL nor distributes it thereunder but
64008 * under the terms set out in this paragraph. All notices and licenses
64009 * below are for informational purposes only.
64010 *
64011 * NUGET: END LICENSE TEXT */
64012/*!
64013** Unobtrusive Ajax support library for jQuery
64014** Copyright (C) Microsoft Corporation. All rights reserved.
64015*/
64016
64017/*jslint white: true, browser: true, onevar: true, undef: true, nomen: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, newcap: true, immed: true, strict: false */
64018/*global window: false, jQuery: false */
64019
64020(function ($) {
64021    var data_click = "unobtrusiveAjaxClick",
64022        data_target = "unobtrusiveAjaxClickTarget"
64023        data_validation = "unobtrusiveValidation";
64024
64025    function getFunction(code, argNames) {
64026        var fn = window, parts = (code || "").split(".");
64027        while (fn && parts.length) {
64028            fn = fn[parts.shift()];
64029        }
64030        if (typeof (fn) === "function") {
64031            return fn;
64032        }
64033        argNames.push(code);
64034        return Function.constructor.apply(null, argNames);
64035    }
64036
64037    function isMethodProxySafe(method) {
64038        return method === "GET" || method === "POST";
64039    }
64040
64041    function asyncOnBeforeSend(xhr, method) {
64042        if (!isMethodProxySafe(method)) {
64043            xhr.setRequestHeader("X-HTTP-Method-Override", method);
64044        }
64045    }
64046
64047    function asyncOnSuccess(element, data, contentType) {
64048        var mode;
64049
64050        if (contentType.indexOf("application/x-javascript") !== -1) {  // jQuery already executes JavaScript for us
64051            return;
64052        }
64053
64054        mode = (element.getAttribute("data-ajax-mode") || "").toUpperCase();
64055        $(element.getAttribute("data-ajax-update")).each(function (i, update) {
64056            var top;
64057
64058            switch (mode) {
64059            case "BEFORE":
64060                top = update.firstChild;
64061                $("<div />").html(data).contents().each(function () {
64062                    update.insertBefore(this, top);
64063                });
64064                break;
64065            case "AFTER":
64066                $("<div />").html(data).contents().each(function () {
64067                    update.appendChild(this);
64068                });
64069                break;
64070            default:
64071                $(update).html(data);
64072                break;
64073            }
64074        });
64075    }
64076
64077    function asyncRequest(element, options) {
64078        var confirm, loading, method, duration;
64079
64080        confirm = element.getAttribute("data-ajax-confirm");
64081        if (confirm && !window.confirm(confirm)) {
64082            return;
64083        }
64084
64085        loading = $(element.getAttribute("data-ajax-loading"));
64086        duration = parseInt(element.getAttribute("data-ajax-loading-duration"), 10) || 0;
64087
64088        $.extend(options, {
64089            context: element,
64090            type: element.getAttribute("data-ajax-method") || undefined,
64091            url: element.getAttribute("data-ajax-url") || undefined,
64092            beforeSend: function (xhr) {
64093                var result;
64094                asyncOnBeforeSend(xhr, method);
64095                result = getFunction(element.getAttribute("data-ajax-begin"), ["xhr"]).apply(this, arguments);
64096                if (result !== false) {
64097                    loading.show(duration);
64098                }
64099                return result;
64100            },
64101            complete: function () {
64102                loading.hide(duration);
64103                getFunction(element.getAttribute("data-ajax-complete"), ["xhr", "status"]).apply(this, arguments);
64104            },
64105            success: function (data, status, xhr) {
64106                asyncOnSuccess(element, data, xhr.getResponseHeader("Content-Type") || "text/html");
64107                getFunction(element.getAttribute("data-ajax-success"), ["data", "status", "xhr"]).apply(this, arguments);
64108            },
64109            error: getFunction(element.getAttribute("data-ajax-failure"), ["xhr", "status", "error"])
64110        });
64111
64112        options.data.push({ name: "X-Requested-With", value: "XMLHttpRequest" });
64113
64114        method = options.type.toUpperCase();
64115        if (!isMethodProxySafe(method)) {
64116            options.type = "POST";
64117            options.data.push({ name: "X-HTTP-Method-Override", value: method });
64118        }
64119
64120        $.ajax(options);
64121    }
64122
64123    function validate(form) {
64124        var validationInfo = $(form).data(data_validation);
64125        return !validationInfo || !validationInfo.validate || validationInfo.validate();
64126    }
64127
64128    $(document).on("click", "a[data-ajax=true]", function (evt) {
64129        evt.preventDefault();
64130        asyncRequest(this, {
64131            url: this.href,
64132            type: "GET",
64133            data: []
64134        });
64135    });
64136
64137    $(document).on("click", "form[data-ajax=true] input[type=image]", function (evt) {
64138        var name = evt.target.name,
64139            target = $(evt.target),
64140            form = $(target.parents("form")[0]),
64141            offset = target.offset();
64142
64143        form.data(data_click, [
64144            { name: name + ".x", value: Math.round(evt.pageX - offset.left) },
64145            { name: name + ".y", value: Math.round(evt.pageY - offset.top) }
64146        ]);
64147
64148        setTimeout(function () {
64149            form.removeData(data_click);
64150        }, 0);
64151    });
64152
64153    $(document).on("click", "form[data-ajax=true] :submit", function (evt) {
64154        var name = evt.currentTarget.name,
64155            target = $(evt.target),
64156            form = $(target.parents("form")[0]);
64157
64158        form.data(data_click, name ? [{ name: name, value: evt.currentTarget.value }] : []);
64159        form.data(data_target, target);
64160
64161        setTimeout(function () {
64162            form.removeData(data_click);
64163            form.removeData(data_target);
64164        }, 0);
64165    });
64166
64167    $(document).on("submit", "form[data-ajax=true]", function (evt) {
64168        var clickInfo = $(this).data(data_click) || [],
64169            clickTarget = $(this).data(data_target),
64170            isCancel = clickTarget && clickTarget.hasClass("cancel");
64171        evt.preventDefault();
64172        if (!isCancel && !validate(this)) {
64173            return;
64174        }
64175        asyncRequest(this, {
64176            url: this.action,
64177            type: this.method || "GET",
64178            data: clickInfo.concat($(this).serializeArray())
64179        });
64180    });
64181}(jQuery));
64182define("jqueryUnobstrusive", ["jquery"], (function (global) {
64183    return function () {
64184        var ret, fn;
64185        return ret || global.$;
64186    };
64187}(this)));
64188
64189/*!
64190 * jQuery Validation Plugin v1.12.0
64191 *
64192 * http://jqueryvalidation.org/
64193 *
64194 * Copyright (c) 2014 Jörn Zaefferer
64195 * Released under the MIT license
64196 */
64197(function($) {
64198
64199$.extend($.fn, {
64200	// http://jqueryvalidation.org/validate/
64201	validate: function( options ) {
64202
64203		// if nothing is selected, return nothing; can't chain anyway
64204		if ( !this.length ) {
64205			if ( options && options.debug && window.console ) {
64206				console.warn( "Nothing selected, can't validate, returning nothing." );
64207			}
64208			return;
64209		}
64210
64211		// check if a validator for this form was already created
64212		var validator = $.data( this[0], "validator" );
64213		if ( validator ) {
64214			return validator;
64215		}
64216
64217		// Add novalidate tag if HTML5.
64218		this.attr( "novalidate", "novalidate" );
64219
64220		validator = new $.validator( options, this[0] );
64221		$.data( this[0], "validator", validator );
64222
64223		if ( validator.settings.onsubmit ) {
64224
64225			this.validateDelegate( ":submit", "click", function( event ) {
64226				if ( validator.settings.submitHandler ) {
64227					validator.submitButton = event.target;
64228				}
64229				// allow suppressing validation by adding a cancel class to the submit button
64230				if ( $(event.target).hasClass("cancel") ) {
64231					validator.cancelSubmit = true;
64232				}
64233
64234				// allow suppressing validation by adding the html5 formnovalidate attribute to the submit button
64235				if ( $(event.target).attr("formnovalidate") !== undefined ) {
64236					validator.cancelSubmit = true;
64237				}
64238			});
64239
64240			// validate the form on submit
64241			this.submit( function( event ) {
64242				if ( validator.settings.debug ) {
64243					// prevent form submit to be able to see console output
64244					event.preventDefault();
64245				}
64246				function handle() {
64247					var hidden;
64248					if ( validator.settings.submitHandler ) {
64249						if ( validator.submitButton ) {
64250							// insert a hidden input as a replacement for the missing submit button
64251							hidden = $("<input type='hidden'/>").attr("name", validator.submitButton.name).val( $(validator.submitButton).val() ).appendTo(validator.currentForm);
64252						}
64253						validator.settings.submitHandler.call( validator, validator.currentForm, event );
64254						if ( validator.submitButton ) {
64255							// and clean up afterwards; thanks to no-block-scope, hidden can be referenced
64256							hidden.remove();
64257						}
64258						return false;
64259					}
64260					return true;
64261				}
64262
64263				// prevent submit for invalid forms or custom submit handlers
64264				if ( validator.cancelSubmit ) {
64265					validator.cancelSubmit = false;
64266					return handle();
64267				}
64268				if ( validator.form() ) {
vendor: 4,582 bytes, lines 64269-64433
64269					if ( validator.pendingRequest ) {
64270						validator.formSubmitted = true;
64271						return false;
64272					}
64273					return handle();
64274				} else {
64275					validator.focusInvalid();
64276					return false;
64277				}
64278			});
64279		}
64280
64281		return validator;
64282	},
64283	// http://jqueryvalidation.org/valid/
64284	valid: function() {
64285		var valid, validator;
64286
64287		if ( $(this[0]).is("form")) {
64288			valid = this.validate().form();
64289		} else {
64290			valid = true;
64291			validator = $(this[0].form).validate();
64292			this.each(function() {
64293				valid = validator.element(this) && valid;
64294			});
64295		}
64296		return valid;
64297	},
64298	// attributes: space separated list of attributes to retrieve and remove
64299	removeAttrs: function( attributes ) {
64300		var result = {},
64301			$element = this;
64302		$.each(attributes.split(/\s/), function( index, value ) {
64303			result[value] = $element.attr(value);
64304			$element.removeAttr(value);
64305		});
64306		return result;
64307	},
64308	// http://jqueryvalidation.org/rules/
64309	rules: function( command, argument ) {
64310		var element = this[0],
64311			settings, staticRules, existingRules, data, param, filtered;
64312
64313		if ( command ) {
64314			settings = $.data(element.form, "validator").settings;
64315			staticRules = settings.rules;
64316			existingRules = $.validator.staticRules(element);
64317			switch (command) {
64318			case "add":
64319				$.extend(existingRules, $.validator.normalizeRule(argument));
64320				// remove messages from rules, but allow them to be set separately
64321				delete existingRules.messages;
64322				staticRules[element.name] = existingRules;
64323				if ( argument.messages ) {
64324					settings.messages[element.name] = $.extend( settings.messages[element.name], argument.messages );
64325				}
64326				break;
64327			case "remove":
64328				if ( !argument ) {
64329					delete staticRules[element.name];
64330					return existingRules;
64331				}
64332				filtered = {};
64333				$.each(argument.split(/\s/), function( index, method ) {
64334					filtered[method] = existingRules[method];
64335					delete existingRules[method];
64336					if ( method === "required" ) {
64337						$(element).removeAttr("aria-required");
64338					}
64339				});
64340				return filtered;
64341			}
64342		}
64343
64344		data = $.validator.normalizeRules(
64345		$.extend(
64346			{},
64347			$.validator.classRules(element),
64348			$.validator.attributeRules(element),
64349			$.validator.dataRules(element),
64350			$.validator.staticRules(element)
64351		), element);
64352
64353		// make sure required is at front
64354		if ( data.required ) {
64355			param = data.required;
64356			delete data.required;
64357			data = $.extend({ required: param }, data );
64358			$(element).attr( "aria-required", "true" );
64359		}
64360
64361		// make sure remote is at back
64362		if ( data.remote ) {
64363			param = data.remote;
64364			delete data.remote;
64365			data = $.extend( data, { remote: param });
64366		}
64367
64368		return data;
64369	}
64370});
64371
64372// Custom selectors
64373$.extend($.expr[":"], {
64374	// http://jqueryvalidation.org/blank-selector/
64375	blank: function( a ) { return !$.trim("" + $(a).val()); },
64376	// http://jqueryvalidation.org/filled-selector/
64377	filled: function( a ) { return !!$.trim("" + $(a).val()); },
64378	// http://jqueryvalidation.org/unchecked-selector/
64379	unchecked: function( a ) { return !$(a).prop("checked"); }
64380});
64381
64382// constructor for validator
64383$.validator = function( options, form ) {
64384	this.settings = $.extend( true, {}, $.validator.defaults, options );
64385	this.currentForm = form;
64386	this.init();
64387};
64388
64389// http://jqueryvalidation.org/jQuery.validator.format/
64390$.validator.format = function( source, params ) {
64391	if ( arguments.length === 1 ) {
64392		return function() {
64393			var args = $.makeArray(arguments);
64394			args.unshift(source);
64395			return $.validator.format.apply( this, args );
64396		};
64397	}
64398	if ( arguments.length > 2 && params.constructor !== Array  ) {
64399		params = $.makeArray(arguments).slice(1);
64400	}
64401	if ( params.constructor !== Array ) {
64402		params = [ params ];
64403	}
64404	$.each(params, function( i, n ) {
64405		source = source.replace( new RegExp("\\{" + i + "\\}", "g"), function() {
64406			return n;
64407		});
64408	});
64409	return source;
64410};
64411
64412$.extend($.validator, {
64413
64414	defaults: {
64415		messages: {},
64416		groups: {},
64417		rules: {},
64418		errorClass: "error",
64419		validClass: "valid",
64420		errorElement: "label",
64421		focusInvalid: true,
64422		errorContainer: $([]),
64423		errorLabelContainer: $([]),
64424		onsubmit: true,
64425		ignore: ":hidden",
64426		ignoreTitle: false,
64427		onfocusin: function( element ) {
64428			this.lastActive = element;
64429
64430			// hide error label and remove error class on focus if enabled
64431			if ( this.settings.focusCleanup && !this.blockFocusCleanup ) {
64432				if ( this.settings.unhighlight ) {
64433					this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.val
64433idClass );
64434				}
64435				this.addWrapper(this.errorsFor(element)).hide();
64436			}
64437		},
64438		onfocusout: function( element ) {
64439			if ( !this.checkable(element) && (element.name in this.submitted || !this.optional(element)) ) {
64440				this.element(element);
64441			}
64442		},
64443		onkeyup: function( element, event ) {
64444			if ( event.which === 9 && this.elementValue(element) === "" ) {
64445				return;
64446			} else if ( element.name in this.submitted || element === this.lastElement ) {
64447				this.element(element);
64448			}
64449		},
64450		onclick: function( element ) {
64451			// click on selects, radiobuttons and checkboxes
64452			if ( element.name in this.submitted ) {
64453				this.element(element);
64454
64455			// or option elements, check parent select in that case
64456			} else if ( element.parentNode.name in this.submitted ) {
64457				this.element(element.parentNode);
64458			}
64459		},
64460		highlight: function( element, errorClass, validClass ) {
64461			if ( element.type === "radio" ) {
64462				this.findByName(element.name).addClass(errorClass).removeClass(validClass);
64463			} else {
64464				$(element).addClass(errorClass).removeClass(validClass);
64465			}
64466		},
64467		unhighlight: function( element, errorClass, validClass ) {
64468			if ( element.type === "radio" ) {
64469				this.findByName(element.name).removeClass(errorClass).addClass(validClass);
64470			} else {
64471				$(element).removeClass(errorClass).addClass(validClass);
64472			}
64473		}
64474	},
64475
64476	// http://jqueryvalidation.org/jQuery.validator.setDefaults/
64477	setDefaults: function( settings ) {
64478		$.extend( $.validator.defaults, settings );
64479	},
64480
64481	messages: {
64482		required: "This field is required.",
64483		remote: "Please fix this field.",
64484		email: "Please enter a valid email address.",
64485		url: "Please enter a valid URL.",
64486		date: "Please enter a valid date.",
64487		dateISO: "Please enter a valid date (ISO).",
64488		number: "Please enter a valid number.",
64489		digits: "Please enter only digits.",
64490		creditcard: "Please enter a valid credit card number.",
64491		equalTo: "Please enter the same value again.",
64492		maxlength: $.validator.format("Please enter no more than {0} characters."),
64493		minlength: $.validator.format("Please enter at least {0} characters."),
64494		rangelength: $.validator.format("Please enter a value between {0} and {1} characters long."),
64495		range: $.validator.format("Please enter a value between {0} and {1}."),
64496		max: $.validator.format("Please enter a value less than or equal to {0}."),
64497		min: $.validator.format("Please enter a value greater than or equal to {0}.")
64498	},
64499
64500	autoCreateRanges: false,
64501
64502	prototype: {
64503
64504		init: function() {
64505			this.labelContainer = $(this.settings.errorLabelContainer);
64506			this.errorContext = this.labelContainer.length && this.labelContainer || $(this.currentForm);
64507			this.containers = $(this.settings.errorContainer).add( this.settings.errorLabelContainer );
64508			this.submitted = {};
64509			this.valueCache = {};
64510			this.pendingRequest = 0;
64511			this.pending = {};
64512			this.invalid = {};
64513			this.reset();
64514
64515			var groups = (this.groups = {}),
64516				rules;
64517			$.each(this.settings.groups, function( key, value ) {
64518				if ( typeof value === "string" ) {
64519					value = value.split(/\s/);
64520				}
64521				$.each(value, function( index, name ) {
64522					groups[name] = key;
64523				});
64524			});
64525			rules = this.settings.rules;
64526			$.each(rules, function( key, value ) {
64527				rules[key] = $.validator.normalizeRule(value);
64528			});
64529
64530			function delegate(event) {
64531				var validator = $.data(this[0].form, "validator"),
64532					eventType = "on" + event.type.replace(/^validate/, ""),
64533					settings = validator.settings;
64534				if ( settings[eventType] && !this.is( settings.ignore ) ) {
64535					settings[eventType].call(validator, this[0], event);
64536				}
64537			}
64538			$(this.currentForm)
64539				.validateDelegate(":text, [type='password'], [type='file'], select, textarea, " +
64540					"[type='number'], [type='search'] ,[type='tel'], [type='url'], " +
64541					"[type='email'], [type='datetime'], [type='date'], [type='month'], " +
64542					"[type='week'], [type='time'], [type='datetime-local'], " +
64543					"[type='range'], [type='color'] ",
64544					"focusin focusout keyup", delegate)
64545				.validateDelegate("[type='radio'], [type='checkbox'], select, option", "click", delegate);
64546
64547			if ( this.settings.invalidHandler ) {
64548				$(this.currentForm).bind("invalid-form.validate", this.settings.invalidHandler);
64549			}
64550
64551			// Add aria-required to any Static/Data/Class required fields before first validation
64552			// Screen readers require this attribute to be present before the initial submission http://www.w3.org/TR/WCAG-TECHS/ARIA2.html
64553			$(this.currentForm).find("[required], [data-rule-required], .required").attr("aria-required", "true");
64554		},
64555
64556		// http://jqueryvalidation.org/Validator.form/
64557		form: function() {
64558			this.checkForm();
64559			$.extend(this.submitted, this.errorMap);
64560			this.invalid = $.extend({}, this.errorMap);
64561			if ( !this.valid() ) {
64562				$(this.currentForm).triggerHandler("invalid-form", [ this ]);
64563			}
64564			this.showErrors();
64565			return this.valid();
64566		},
64567
64568		checkForm: function() {
64569			this.prepareForm();
64570			for ( var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++ ) {
64571				this.check( elements[i] );
64572			}
64573			return this.valid();
64574		},
64575
64576		// http://jqueryvalidation.org/Validator.element/
64577		element: function( element ) {
64578			var cleanElement = this.clean( element ),
64579				checkElement = this.validationTargetFor( cleanElement ),
64580				result = true;
64581
64582			this.lastElement = checkElement;
64583
64584			if ( checkElement === undefined ) {
64585				delete this.invalid[ cleanElement.name ];
64586			} else {
64587				this.prepareElement( checkElement );
64588				this.currentElements = $( checkElement );
64589
64590				result = this.check( checkElement ) !== false;
64591				if (result) {
64592					delete this.invalid[checkElement.name];
64593				} else {
64594					this.invalid[checkElement.name] = true;
64595				}
64596			}
64597			// Add aria-invalid status for screen readers
64598			$( element ).attr( "aria-invalid", !result );
64599
64600			if ( !this.numberOfInvalids() ) {
64601				// Hide error containers on last error
64602				this.toHide = this.toHide.add( this.containers );
64603			}
64604			this.showErrors();
64605			return result;
64606		},
64607
64608		// http://jqueryvalidation.org/Validator.showErrors/
64609		showErrors: function( errors ) {
64610			if ( errors ) {
64611				// add items to error list and map
64612				$.extend( this.errorMap, errors );
64613				this.errorList = [];
64614				for ( var name in errors ) {
64615					this.errorList.push({
64616						message: errors[name],
64617						element: this.findByName(name)[0]
64618					});
vendor: 4,846 bytes, lines 64619-64798
64619				}
64620				// remove items from success list
64621				this.successList = $.grep( this.successList, function( element ) {
64622					return !(element.name in errors);
64623				});
64624			}
64625			if ( this.settings.showErrors ) {
64626				this.settings.showErrors.call( this, this.errorMap, this.errorList );
64627			} else {
64628				this.defaultShowErrors();
64629			}
64630		},
64631
64632		// http://jqueryvalidation.org/Validator.resetForm/
64633		resetForm: function() {
64634			if ( $.fn.resetForm ) {
64635				$(this.currentForm).resetForm();
64636			}
64637			this.submitted = {};
64638			this.lastElement = null;
64639			this.prepareForm();
64640			this.hideErrors();
64641			this.elements()
64642					.removeClass( this.settings.errorClass )
64643					.removeData( "previousValue" )
64644					.removeAttr( "aria-invalid" );
64645		},
64646
64647		numberOfInvalids: function() {
64648			return this.objectLength(this.invalid);
64649		},
64650
64651		objectLength: function( obj ) {
64652			/* jshint unused: false */
64653			var count = 0,
64654				i;
64655			for ( i in obj ) {
64656				count++;
64657			}
64658			return count;
64659		},
64660
64661		hideErrors: function() {
64662			this.addWrapper( this.toHide ).hide();
64663		},
64664
64665		valid: function() {
64666			return this.size() === 0;
64667		},
64668
64669		size: function() {
64670			return this.errorList.length;
64671		},
64672
64673		focusInvalid: function() {
64674			if ( this.settings.focusInvalid ) {
64675				try {
64676					$(this.findLastActive() || this.errorList.length && this.errorList[0].element || [])
64677					.filter(":visible")
64678					.focus()
64679					// manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find
64680					.trigger("focusin");
64681				} catch(e) {
64682					// ignore IE throwing errors when focusing hidden elements
64683				}
64684			}
64685		},
64686
64687		findLastActive: function() {
64688			var lastActive = this.lastActive;
64689			return lastActive && $.grep(this.errorList, function( n ) {
64690				return n.element.name === lastActive.name;
64691			}).length === 1 && lastActive;
64692		},
64693
64694		elements: function() {
64695			var validator = this,
64696				rulesCache = {};
64697
64698			// select all valid inputs inside the form (no submit or reset buttons)
64699			return $(this.currentForm)
64700			.find("input, select, textarea")
64701			.not(":submit, :reset, :image, [disabled]")
64702			.not( this.settings.ignore )
64703			.filter(function() {
64704				if ( !this.name && validator.settings.debug && window.console ) {
64705					console.error( "%o has no name assigned", this);
64706				}
64707
64708				// select only the first element for each name, and only those with rules specified
64709				if ( this.name in rulesCache || !validator.objectLength($(this).rules()) ) {
64710					return false;
64711				}
64712
64713				rulesCache[this.name] = true;
64714				return true;
64715			});
64716		},
64717
64718		clean: function( selector ) {
64719			return $(selector)[0];
64720		},
64721
64722		errors: function() {
64723			var errorClass = this.settings.errorClass.split(" ").join(".");
64724			return $(this.settings.errorElement + "." + errorClass, this.errorContext);
64725		},
64726
64727		reset: function() {
64728			this.successList = [];
64729			this.errorList = [];
64730			this.errorMap = {};
64731			this.toShow = $([]);
64732			this.toHide = $([]);
64733			this.currentElements = $([]);
64734		},
64735
64736		prepareForm: function() {
64737			this.reset();
64738			this.toHide = this.errors().add( this.containers );
64739		},
64740
64741		prepareElement: function( element ) {
64742			this.reset();
64743			this.toHide = this.errorsFor(element);
64744		},
64745
64746		elementValue: function( element ) {
64747			var val,
64748				$element = $(element),
64749				type = $element.attr("type");
64750
64751			if ( type === "radio" || type === "checkbox" ) {
64752				return $("input[name='" + $element.attr("name") + "']:checked").val();
64753			}
64754
64755			val = $element.val();
64756			if ( typeof val === "string" ) {
64757				return val.replace(/\r/g, "");
64758			}
64759			return val;
64760		},
64761
64762		check: function( element ) {
64763			element = this.validationTargetFor( this.clean( element ) );
64764
64765			var rules = $(element).rules(),
64766				rulesCount = $.map( rules, function(n, i) {
64767					return i;
64768				}).length,
64769				dependencyMismatch = false,
64770				val = this.elementValue(element),
64771				result, method, rule;
64772
64773			for (method in rules ) {
64774				rule = { method: method, parameters: rules[method] };
64775				try {
64776
64777					result = $.validator.methods[method].call( this, val, element, rule.parameters );
64778
64779					// if a method indicates that the field is optional and therefore valid,
64780					// don't mark it as valid when there are no other rules
64781					if ( result === "dependency-mismatch" && rulesCount === 1 ) {
64782						dependencyMismatch = true;
64783						continue;
64784					}
64785					dependencyMismatch = false;
64786
64787					if ( result === "pending" ) {
64788						this.toHide = this.toHide.not( this.errorsFor(element) );
64789						return;
64790					}
64791
64792					if ( !result ) {
64793						this.formatAndAdd( element, rule );
64794						return false;
64795					}
64796				} catch(e) {
64797					if ( this.settings.debug && window.console ) {
64798						console.log( "Exception occurred when checking element " + element.i
64798d + ", check the '" + rule.method + "' method.", e );
64799					}
64800					throw e;
64801				}
64802			}
64803			if ( dependencyMismatch ) {
64804				return;
64805			}
64806			if ( this.objectLength(rules) ) {
64807				this.successList.push(element);
64808			}
64809			return true;
64810		},
64811
64812		// return the custom message for the given element and validation method
64813		// specified in the element's HTML5 data attribute
64814		// return the generic message if present and no method specific message is present
64815		customDataMessage: function( element, method ) {
64816			return $( element ).data( "msg" + method[ 0 ].toUpperCase() +
64817				method.substring( 1 ).toLowerCase() ) || $( element ).data("msg");
64818		},
64819
64820		// return the custom message for the given element name and validation method
64821		customMessage: function( name, method ) {
64822			var m = this.settings.messages[name];
64823			return m && (m.constructor === String ? m : m[method]);
64824		},
64825
64826		// return the first defined argument, allowing empty strings
64827		findDefined: function() {
64828			for (var i = 0; i < arguments.length; i++) {
64829				if ( arguments[i] !== undefined ) {
64830					return arguments[i];
64831				}
64832			}
64833			return undefined;
64834		},
64835
64836		defaultMessage: function( element, method ) {
64837			return this.findDefined(
64838				this.customMessage( element.name, method ),
64839				this.customDataMessage( element, method ),
64840				// title is never undefined, so handle empty string as undefined
64841				!this.settings.ignoreTitle && element.title || undefined,
64842				$.validator.messages[method],
64843				"<strong>Warning: No message defined for " + element.name + "</strong>"
64844			);
64845		},
64846
64847		formatAndAdd: function( element, rule ) {
64848			var message = this.defaultMessage( element, rule.method ),
64849				theregex = /\$?\{(\d+)\}/g;
64850			if ( typeof message === "function" ) {
64851				message = message.call(this, rule.parameters, element);
64852			} else if (theregex.test(message)) {
64853				message = $.validator.format(message.replace(theregex, "{$1}"), rule.parameters);
64854			}
64855			this.errorList.push({
64856				message: message,
64857				element: element,
64858				method: rule.method
64859			});
64860
64861			this.errorMap[element.name] = message;
64862			this.submitted[element.name] = message;
64863		},
64864
64865		addWrapper: function( toToggle ) {
64866			if ( this.settings.wrapper ) {
64867				toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) );
64868			}
64869			return toToggle;
64870		},
64871
64872		defaultShowErrors: function() {
64873			var i, elements, error;
64874			for ( i = 0; this.errorList[i]; i++ ) {
64875				error = this.errorList[i];
64876				if ( this.settings.highlight ) {
64877					this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass );
64878				}
64879				this.showLabel( error.element, error.message );
64880			}
64881			if ( this.errorList.length ) {
64882				this.toShow = this.toShow.add( this.containers );
64883			}
64884			if ( this.settings.success ) {
64885				for ( i = 0; this.successList[i]; i++ ) {
64886					this.showLabel( this.successList[i] );
64887				}
64888			}
64889			if ( this.settings.unhighlight ) {
64890				for ( i = 0, elements = this.validElements(); elements[i]; i++ ) {
64891					this.settings.unhighlight.call( this, elements[i], this.settings.errorClass, this.settings.validClass );
64892				}
64893			}
64894			this.toHide = this.toHide.not( this.toShow );
64895			this.hideErrors();
64896			this.addWrapper( this.toShow ).show();
64897		},
64898
64899		validElements: function() {
64900			return this.currentElements.not(this.invalidElements());
64901		},
64902
64903		invalidElements: function() {
64904			return $(this.errorList).map(function() {
64905				return this.element;
64906			});
64907		},
64908
64909		showLabel: function( element, message ) {
64910			var label = this.errorsFor( element );
64911			if ( label.length ) {
64912				// refresh error/success class
64913				label.removeClass( this.settings.validClass ).addClass( this.settings.errorClass );
64914				// replace message on existing label
64915				label.html(message);
64916			} else {
64917				// create label
64918				label = $("<" + this.settings.errorElement + ">")
64919					.attr("for", this.idOrName(element))
64920					.addClass(this.settings.errorClass)
64921					.html(message || "");
64922				if ( this.settings.wrapper ) {
64923					// make sure the element is visible, even in IE
64924					// actually showing the wrapped element is handled elsewhere
64925					label = label.hide().show().wrap("<" + this.settings.wrapper + "/>").parent();
64926				}
64927				if ( !this.labelContainer.append(label).length ) {
64928					if ( this.settings.errorPlacement ) {
64929						this.settings.errorPlacement(label, $(element) );
64930					} else {
64931						label.insertAfter(element);
64932					}
64933				}
64934			}
64935			if ( !message && this.settings.success ) {
64936				label.text("");
64937				if ( typeof this.settings.success === "string" ) {
64938					label.addClass( this.settings.success );
64939				} else {
64940					this.settings.success( label, element );
64941				}
64942			}
64943			this.toShow = this.toShow.add(label);
64944		},
64945
64946		errorsFor: function( element ) {
64947			var name = this.idOrName(element);
64948			return this.errors().filter(function() {
64949				return $(this).attr("for") === name;
64950			});
64951		},
64952
64953		idOrName: function( element ) {
64954			return this.groups[element.name] || (this.checkable(element) ? element.name : element.i
vendor: 7,023 bytes, lines 64954-65204
64954d || element.name);
64955		},
64956
64957		validationTargetFor: function( element ) {
64958			// if radio/checkbox, validate first element in group instead
64959			if ( this.checkable(element) ) {
64960				element = this.findByName( element.name ).not(this.settings.ignore)[0];
64961			}
64962			return element;
64963		},
64964
64965		checkable: function( element ) {
64966			return (/radio|checkbox/i).test(element.type);
64967		},
64968
64969		findByName: function( name ) {
64970			return $(this.currentForm).find("[name='" + name + "']");
64971		},
64972
64973		getLength: function( value, element ) {
64974			switch ( element.nodeName.toLowerCase() ) {
64975			case "select":
64976				return $("option:selected", element).length;
64977			case "input":
64978				if ( this.checkable( element) ) {
64979					return this.findByName(element.name).filter(":checked").length;
64980				}
64981			}
64982			return value.length;
64983		},
64984
64985		depend: function( param, element ) {
64986			return this.dependTypes[typeof param] ? this.dependTypes[typeof param](param, element) : true;
64987		},
64988
64989		dependTypes: {
64990			"boolean": function( param ) {
64991				return param;
64992			},
64993			"string": function( param, element ) {
64994				return !!$(param, element.form).length;
64995			},
64996			"function": function( param, element ) {
64997				return param(element);
64998			}
64999		},
65000
65001		optional: function( element ) {
65002			var val = this.elementValue(element);
65003			return !$.validator.methods.required.call(this, val, element) && "dependency-mismatch";
65004		},
65005
65006		startRequest: function( element ) {
65007			if ( !this.pending[element.name] ) {
65008				this.pendingRequest++;
65009				this.pending[element.name] = true;
65010			}
65011		},
65012
65013		stopRequest: function( element, valid ) {
65014			this.pendingRequest--;
65015			// sometimes synchronization fails, make sure pendingRequest is never < 0
65016			if ( this.pendingRequest < 0 ) {
65017				this.pendingRequest = 0;
65018			}
65019			delete this.pending[element.name];
65020			if ( valid && this.pendingRequest === 0 && this.formSubmitted && this.form() ) {
65021				$(this.currentForm).submit();
65022				this.formSubmitted = false;
65023			} else if (!valid && this.pendingRequest === 0 && this.formSubmitted) {
65024				$(this.currentForm).triggerHandler("invalid-form", [ this ]);
65025				this.formSubmitted = false;
65026			}
65027		},
65028
65029		previousValue: function( element ) {
65030			return $.data(element, "previousValue") || $.data(element, "previousValue", {
65031				old: null,
65032				valid: true,
65033				message: this.defaultMessage( element, "remote" )
65034			});
65035		}
65036
65037	},
65038
65039	classRuleSettings: {
65040		required: { required: true },
65041		email: { email: true },
65042		url: { url: true },
65043		date: { date: true },
65044		dateISO: { dateISO: true },
65045		number: { number: true },
65046		digits: { digits: true },
65047		creditcard: { creditcard: true }
65048	},
65049
65050	addClassRules: function( className, rules ) {
65051		if ( className.constructor === String ) {
65052			this.classRuleSettings[className] = rules;
65053		} else {
65054			$.extend(this.classRuleSettings, className);
65055		}
65056	},
65057
65058	classRules: function( element ) {
65059		var rules = {},
65060			classes = $(element).attr("class");
65061
65062		if ( classes ) {
65063			$.each(classes.split(" "), function() {
65064				if ( this in $.validator.classRuleSettings ) {
65065					$.extend(rules, $.validator.classRuleSettings[this]);
65066				}
65067			});
65068		}
65069		return rules;
65070	},
65071
65072	attributeRules: function( element ) {
65073		var rules = {},
65074			$element = $(element),
65075			type = element.getAttribute("type"),
65076			method, value;
65077
65078		for (method in $.validator.methods) {
65079
65080			// support for <input required> in both html5 and older browsers
65081			if ( method === "required" ) {
65082				value = element.getAttribute(method);
65083				// Some browsers return an empty string for the required attribute
65084				// and non-HTML5 browsers might have required="" markup
65085				if ( value === "" ) {
65086					value = true;
65087				}
65088				// force non-HTML5 browsers to return bool
65089				value = !!value;
65090			} else {
65091				value = $element.attr(method);
65092			}
65093
65094			// convert the value to a number for number inputs, and for text for backwards compability
65095			// allows type="date" and others to be compared as strings
65096			if ( /min|max/.test( method ) && ( type === null || /number|range|text/.test( type ) ) ) {
65097				value = Number(value);
65098			}
65099
65100			if ( value || value === 0 ) {
65101				rules[method] = value;
65102			} else if ( type === method && type !== "range" ) {
65103				// exception: the jquery validate 'range' method
65104				// does not test for the html5 'range' type
65105				rules[method] = true;
65106			}
65107		}
65108
65109		// maxlength may be returned as -1, 2147483647 (IE) and 524288 (safari) for text inputs
65110		if ( rules.maxlength && /-1|2147483647|524288/.test(rules.maxlength) ) {
65111			delete rules.maxlength;
65112		}
65113
65114		return rules;
65115	},
65116
65117	dataRules: function( element ) {
65118		var method, value,
65119			rules = {}, $element = $( element );
65120		for ( method in $.validator.methods ) {
65121			value = $element.data( "rule" + method[ 0 ].toUpperCase() + method.substring( 1 ).toLowerCase() );
65122			if ( value !== undefined ) {
65123				rules[ method ] = value;
65124			}
65125		}
65126		return rules;
65127	},
65128
65129	staticRules: function( element ) {
65130		var rules = {},
65131			validator = $.data(element.form, "validator");
65132
65133		if ( validator.settings.rules ) {
65134			rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {};
65135		}
65136		return rules;
65137	},
65138
65139	normalizeRules: function( rules, element ) {
65140		// handle dependency check
65141		$.each(rules, function( prop, val ) {
65142			// ignore rule when param is explicitly false, eg. required:false
65143			if ( val === false ) {
65144				delete rules[prop];
65145				return;
65146			}
65147			if ( val.param || val.depends ) {
65148				var keepRule = true;
65149				switch (typeof val.depends) {
65150				case "string":
65151					keepRule = !!$(val.depends, element.form).length;
65152					break;
65153				case "function":
65154					keepRule = val.depends.call(element, element);
65155					break;
65156				}
65157				if ( keepRule ) {
65158					rules[prop] = val.param !== undefined ? val.param : true;
65159				} else {
65160					delete rules[prop];
65161				}
65162			}
65163		});
65164
65165		// evaluate parameters
65166		$.each(rules, function( rule, parameter ) {
65167			rules[rule] = $.isFunction(parameter) ? parameter(element) : parameter;
65168		});
65169
65170		// clean number parameters
65171		$.each([ "minlength", "maxlength" ], function() {
65172			if ( rules[this] ) {
65173				rules[this] = Number(rules[this]);
65174			}
65175		});
65176		$.each([ "rangelength", "range" ], function() {
65177			var parts;
65178			if ( rules[this] ) {
65179				if ( $.isArray(rules[this]) ) {
65180					rules[this] = [ Number(rules[this][0]), Number(rules[this][1]) ];
65181				} else if ( typeof rules[this] === "string" ) {
65182					parts = rules[this].split(/[\s,]+/);
65183					rules[this] = [ Number(parts[0]), Number(parts[1]) ];
65184				}
65185			}
65186		});
65187
65188		if ( $.validator.autoCreateRanges ) {
65189			// auto-create ranges
65190			if ( rules.min && rules.max ) {
65191				rules.range = [ rules.min, rules.max ];
65192				delete rules.min;
65193				delete rules.max;
65194			}
65195			if ( rules.minlength && rules.maxlength ) {
65196				rules.rangelength = [ rules.minlength, rules.maxlength ];
65197				delete rules.minlength;
65198				delete rules.maxlength;
65199			}
65200		}
65201
65202		return rules;
65203	},
65204
65205	// Converts a simple string to a {string: true} rule, e.g., "required" to {required:true}
65206	normalizeRule: function( data ) {
65207		if ( typeof data === "string" ) {
65208			var transformed = {};
65209			$.each(data.split(/\s/), function() {
65210				transformed[this] = true;
65211			});
65212			data = transformed;
65213		}
65214		return data;
65215	},
65216
65217	// http://jqueryvalidation.org/jQuery.validator.addMethod/
65218	addMethod: function( name, method, message ) {
65219		$.validator.methods[name] = method;
65220		$.validator.messages[name] = message !== undefined ? message : $.validator.messages[name];
65221		if ( method.length < 3 ) {
65222			$.validator.addClassRules(name, $.validator.normalizeRule(name));
65223		}
65224	},
65225
65226	methods: {
65227
65228		// http://jqueryvalidation.org/required-method/
65229		required: function( value, element, param ) {
65230			// check if dependency is met
65231			if ( !this.depend(param, element) ) {
65232				return "dependency-mismatch";
65233			}
65234			if ( element.nodeName.toLowerCase() === "select" ) {
65235				// could be an array for select-multiple or a string, both are fine this way
65236				var val = $(element).val();
65237				return val && val.length > 0;
65238			}
65239			if ( this.checkable(element) ) {
65240				return this.getLength(value, element) > 0;
65241			}
65242			return $.trim(value).length > 0;
65243		},
65244
65245		// http://jqueryvalidation.org/email-method/
65246		email: function( value, element ) {
65247			// From http://www.whatwg.org/specs/web-apps/current-work/multipage/states-of-the-type-attribute.html#e-mail-state-%28type=email%29
65248			// Retrieved 2014-01-14
65249			// If you have a problem with this implementation, report a bug against the above spec
65250			// Or use custom methods to implement your own email validation
65251			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);
65252		},
65253
65254		// http://jqueryvalidation.org/url-method/
65255		url: function( value, element ) {
65256			// contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/
65257			return this.optional(element) || /^(https?|s?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);
65258		},
65259
65260		// http://jqueryvalidation.org/date-method/
65261		date: function( value, element ) {
65262			return this.optional(element) || !/Invalid|NaN/.test(new Date(value).toString());
65263		},
65264
65265		// http://jqueryvalidation.org/dateISO-method/
65266		dateISO: function( value, element ) {
65267			return this.optional(element) || /^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/.test(value);
65268		},
65269
65270		// http://jqueryvalidation.org/number-method/
65271		number: function( value, element ) {
65272			return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(value);
65273		},
65274
65275		// http://jqueryvalidation.org/digits-method/
65276		digits: function( value, element ) {
65277			return this.optional(element) || /^\d+$/.test(value);
65278		},
65279
65280		// http://jqueryvalidation.org/creditcard-method/
65281		// based on http://en.wikipedia.org/wiki/Luhn/
65282		creditcard: function( value, element ) {
65283			if ( this.optional(element) ) {
65284				return "dependency-mismatch";
65285			}
65286			// accept only spaces, digits and dashes
65287			if ( /[^0-9 \-]+/.test(value) ) {
65288				return false;
65289			}
65290			var nCheck = 0,
65291				nDigit = 0,
65292				bEven = false,
65293				n, cDigit;
65294
65295			value = value.replace(/\D/g, "");
65296
65297			// Basing min and max length on
65298			// http://developer.ean.com/general_info/Valid_Credit_Card_Types
65299			if ( value.length < 13 || value.length > 19 ) {
65300				return false;
65301			}
65302
65303			for ( n = value.length - 1; n >= 0; n--) {
65304				cDigit = value.charAt(n);
65305				nDigit = parseInt(cDigit, 10);
65306				if ( bEven ) {
65307					if ( (nDigit *= 2) > 9 ) {
65308						nDigit -= 9;
65309					}
65310				}
65311				nCheck += nDigit;
65312				bEven = !bEven;
65313			}
65314
65315			return (nCheck % 10) === 0;
65316		},
65317
65318		// http://jqueryvalidation.org/minlength-method/
65319		minlength: function( value, element, param ) {
65320			var length = $.isArray( value ) ? value.length : this.getLength($.trim(value), element);
65321			return this.optional(element) || length >= param;
65322		},
65323
65324		// http://jqueryvalidation.org/maxlength-method/
65325		maxlength: function( value, element, param ) {
65326			var length = $.isArray( value ) ? value.length : this.getLength($.trim(value), element);
65327			return this.optional(element) || length <= param;
65328		},
65329
65330		// http://jqueryvalidation.org/rangelength-method/
65331		rangelength: function( value, element, param ) {
65332			var length = $.isArray( value ) ? value.length : this.getLength($.trim(value), element);
65333			return this.optional(element) || ( length >= param[0] && length <= param[1] );
65334		},
65335
65336		// http://jqueryvalidation.org/min-method/
65337		min: function( value, element, param ) {
65338			return this.optional(element) || value >= param;
65339		},
65340
65341		// http://jqueryvalidation.org/max-method/
65342		max: function( value, element, param ) {
65343			return this.optional(element) || value <= param;
65344		},
65345
65346		// http://jqueryvalidation.org/range-method/
65347		range: function( value, element, param ) {
65348			return this.optional(element) || ( value >= param[0] && value <= param[1] );
65349		},
65350
65351		// http://jqueryvalidation.org/equalTo-method/
65352		equalTo: function( value, element, param ) {
65353			// bind to the blur event of the target in order to revalidate whenever the target field is updated
65354			// TODO find a way to bind the event just once, avoiding the unbind-rebind overhead
65355			var target = $(param);
65356			if ( this.settings.onfocusout ) {
65357				target.unbind(".validate-equalTo").bind("blur.validate-equalTo", function() {
65358					$(element).valid();
65359				});
65360			}
65361			return value === target.val();
65362		},
65363
65364		// http://jqueryvalidation.org/remote-method/
65365		remote: function( value, element, param ) {
65366			if ( this.optional(element) ) {
65367				return "dependency-mismatch";
65368			}
65369
65370			var previous = this.previousValue(element),
65371				validator, data;
65372
65373			if (!this.settings.messages[element.name] ) {
65374				this.settings.messages[element.name] = {};
65375			}
65376			previous.originalMessage = this.settings.messages[element.name].remote;
65377			this.settings.messages[element.name].remote = previous.message;
65378
65379			param = typeof param === "string" && { url: param } || param;
65380
65381			if ( previous.old === value ) {
65382				return previous.valid;
65383			}
65384
65385			previous.old = value;
65386			validator = this;
65387			this.startRequest(element);
65388			data = {};
65389			data[element.name] = value;
65390			$.ajax($.extend(true, {
65391				url: param,
65392				mode: "abort",
65393				port: "validate" + element.name,
65394				dataType: "json",
65395				data: data,
65396				context: validator.currentForm,
65397				success: function( response ) {
65398					var valid = response === true || response === "true",
65399						errors, message, submitted;
65400
65401					validator.settings.messages[element.name].remote = previous.originalMessage;
65402					if ( valid ) {
65403						submitted = validator.formSubmitted;
65404						validator.prepareElement(element);
65405						validator.formSubmitted = submitted;
65406						validator.successList.push(element);
65407						delete validator.invalid[element.name];
65408						validator.showErrors();
65409					} else {
65410						errors = {};
65411						message = response || validator.defaultMessage( element, "remote" );
65412						errors[element.name] = previous.message = $.isFunction(message) ? message(value) : message;
65413						validator.invalid[element.name] = true;
65414						validator.showErrors(errors);
65415					}
65416					previous.valid = valid;
65417					validator.stopRequest(element, valid);
65418				}
65419			}, param));
65420			return "pending";
65421		}
65422
65423	}
65424
65425});
65426
65427$.format = function deprecated() {
65428	throw "$.format has been deprecated. Please use $.validator.format instead.";
65429};
65430
65431}(jQuery));
65432
65433// ajax mode: abort
65434// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]});
65435// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort()
65436(function($) {
65437	var pendingRequests = {},
65438		ajax;
65439	// Use a prefilter if available (1.5+)
65440	if ( $.ajaxPrefilter ) {
65441		$.ajaxPrefilter(function( settings, _, xhr ) {
65442			var port = settings.port;
65443			if ( settings.mode === "abort" ) {
65444				if ( pendingRequests[port] ) {
65445					pendingRequests[port].abort();
65446				}
65447				pendingRequests[port] = xhr;
65448			}
65449		});
65450	} else {
65451		// Proxy ajax
65452		ajax = $.ajax;
65453		$.ajax = function( settings ) {
65454			var mode = ( "mode" in settings ? settings : $.ajaxSettings ).mode,
65455				port = ( "port" in settings ? settings : $.ajaxSettings ).port;
65456			if ( mode === "abort" ) {
65457				if ( pendingRequests[port] ) {
65458					pendingRequests[port].abort();
65459				}
65460				pendingRequests[port] = ajax.apply(this, arguments);
65461				return pendingRequests[port];
65462			}
65463			return ajax.apply(this, arguments);
65464		};
65465	}
65466}(jQuery));
65467
65468// provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation
65469// handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target
65470(function($) {
65471	$.extend($.fn, {
65472		validateDelegate: function( delegate, type, handler ) {
65473			return this.bind(type, function( event ) {
65474				var target = $(event.target);
65475				if ( target.is(delegate) ) {
65476					return handler.apply(target, arguments);
65477				}
65478			});
65479		}
65480	});
65481}(jQuery));
65482
65483define("jqueryValidate", ["jquery"], (function (global) {
65484    return function () {
65485        var ret, fn;
65486        return ret || global.$;
65487    };
65488}(this)));
65489
65490/*!
65491 * JavaScript Cookie v2.1.4
65492 * https://github.com/js-cookie/js-cookie
65493 *
65494 * Copyright 2006, 2015 Klaus Hartl & Fagner Brack
65495 * Released under the MIT license
65496 */
65497;(function (factory) {
65498	var registeredInModuleLoader = false;
65499	if (typeof define === 'function' && define.amd) {
65500		define('jscookie',factory);
65501		registeredInModuleLoader = true;
65502	}
65503	if (typeof exports === 'object') {
65504		module.exports = factory();
65505		registeredInModuleLoader = true;
65506	}
65507	if (!registeredInModuleLoader) {
65508		var OldCookies = window.Cookies;
65509		var api = window.Cookies = factory();
65510		api.noConflict = function () {
65511			window.Cookies = OldCookies;
65512			return api;
65513		};
65514	}
65515}(function () {
65516	function extend () {
65517		var i = 0;
65518		var result = {};
65519		for (; i < arguments.length; i++) {
65520			var attributes = arguments[ i ];
65521			for (var key in attributes) {
65522				result[key] = attributes[key];
65523			}
65524		}
65525		return result;
65526	}
65527
65528	function init (converter) {
65529		function api (key, value, attributes) {
65530			var result;
65531			if (typeof document === 'undefined') {
65532				return;
65533			}
65534
65535			// Write
65536
65537			if (arguments.length > 1) {
65538				attributes = extend({
65539					path: '/'
65540				}, api.defaults, attributes);
65541
65542				if (typeof attributes.expires === 'number') {
65543					var expires = new Date();
65544					expires.setMilliseconds(expires.getMilliseconds() + attributes.expires * 864e+5);
65545					attributes.expires = expires;
65546				}
65547
65548				// We're using "expires" because "max-age" is not supported by IE
65549				attributes.expires = attributes.expires ? attributes.expires.toUTCString() : '';
65550
65551				try {
65552					result = JSON.stringify(value);
65553					if (/^[\{\[]/.test(result)) {
65554						value = result;
65555					}
65556				} catch (e) {}
65557
65558				if (!converter.write) {
65559					value = encodeURIComponent(String(value))
65560						.replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent);
65561				} else {
65562					value = converter.write(value, key);
65563				}
65564
65565				key = encodeURIComponent(String(key));
65566				key = key.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent);
65567				key = key.replace(/[\(\)]/g, escape);
65568
65569				var stringifiedAttributes = '';
65570
65571				for (var attributeName in attributes) {
65572					if (!attributes[attributeName]) {
65573						continue;
65574					}
65575					stringifiedAttributes += '; ' + attributeName;
65576					if (attributes[attributeName] === true) {
65577						continue;
65578					}
65579					stringifiedAttributes += '=' + attributes[attributeName];
65580				}
65581				return (document.cookie = key + '=' + value + stringifiedAttributes);
65582			}
65583
65584			// Read
65585
65586			if (!key) {
65587				result = {};
65588			}
65589
65590			// To prevent the for loop in the first place assign an empty array
65591			// in case there are no cookies at all. Also prevents odd result when
65592			// calling "get()"
65593			var cookies = document.cookie ? document.cookie.split('; ') : [];
65594			var rdecode = /(%[0-9A-Z]{2})+/g;
65595			var i = 0;
65596
65597			for (; i < cookies.length; i++) {
65598				var parts = cookies[i].split('=');
65599				var cookie = parts.slice(1).join('=');
65600
65601				if (cookie.charAt(0) === '"') {
65602					cookie = cookie.slice(1, -1);
65603				}
65604
65605				try {
65606					var name = parts[0].replace(rdecode, decodeURIComponent);
65607					cookie = converter.read ?
65608						converter.read(cookie, name) : converter(cookie, name) ||
65609						cookie.replace(rdecode, decodeURIComponent);
65610
65611					if (this.json) {
65612						try {
65613							cookie = JSON.parse(cookie);
65614						} catch (e) {}
65615					}
65616
65617					if (key === name) {
65618						result = cookie;
65619						break;
65620					}
65621
65622					if (!key) {
65623						result[name] = cookie;
65624					}
65625				} catch (e) {}
65626			}
65627
65628			return result;
65629		}
65630
65631		api.set = api;
65632		api.get = function (key) {
65633			return api.call(api, key);
65634		};
65635		api.getJSON = function () {
65636			return api.apply({
65637				json: true
65638			}, [].slice.call(arguments));
65639		};
65640		api.defaults = {};
65641
65642		api.remove = function (key, attributes) {
65643			api(key, '', extend(attributes, {
65644				expires: -1
65645			}));
65646		};
65647
65648		api.withConverter = init;
65649
65650		return api;
65651	}
65652
65653	return init(function () {});
65654}));
65655
65656/*!
65657 * Knockout JavaScript library v3.2.0
65658 * (c) Steven Sanderson - http://knockoutjs.com/
65659 * License: MIT (http://www.opensource.org/licenses/mit-license.php)
65660 */
65661
65662(function() {(function(p){var s=this||(0,eval)("this"),v=s.document,L=s.navigator,w=s.jQuery,D=s.JSON;(function(p){"function"===typeof require&&"object"===typeof exports&&"object"===typeof module?p(module.exports||exports,require):"function"===typeof define&&define.amd?define('knockout',["exports","require"],p):p(s.ko={})})(function(M,N){function H(a,d){return null===a||typeof a in R?a===d:!1}function S(a,d){var c;return function(){c||(c=setTimeout(function(){c=p;a()},d))}}function T(a,d){var c;return function(){clearTimeout(c);
65663c=setTimeout(a,d)}}function I(b,d,c,e){a.d[b]={init:function(b,h,k,f,m){var l,q;a.s(function(){var f=a.a.c(h()),k=!c!==!f,z=!q;if(z||d||k!==l)z&&a.Y.la()&&(q=a.a.ia(a.f.childNodes(b),!0)),k?(z||a.f.T(b,a.a.ia(q)),a.Ca(e?e(m,f):m,b)):a.f.j
vendor: 4,243 bytes, lines 65663-65671
65663a(b),l=k},null,{o:b});return{controlsDescendantBindings:!0}}};a.h.ha[b]=!1;a.f.Q[b]=!0}var a="undefined"!==typeof M?M:{};a.b=function(b,d){for(var c=b.split("."),e=a,g=0;g<c.length-1;g++)e=e[c[g]];e[c[c.length-1]]=d};a.A=function(a,d,c){a[d]=c};a.version="3.2.0";
65664a.b("version",a.version);a.a=function(){function b(a,b){for(var c in a)a.hasOwnProperty(c)&&b(c,a[c])}function d(a,b){if(b)for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c]);return a}function c(a,b){a.__proto__=b;return a}var e={__proto__:[]}instanceof Array,g={},h={};g[L&&/Firefox\/2/i.test(L.userAgent)?"KeyboardEvent":"UIEvents"]=["keyup","keydown","keypress"];g.MouseEvents="click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave".split(" ");b(g,function(a,b){if(b.length)for(var c=
656650,d=b.length;c<d;c++)h[b[c]]=a});var k={propertychange:!0},f=v&&function(){for(var a=3,b=v.createElement("div"),c=b.getElementsByTagName("i");b.innerHTML="\x3c!--[if gt IE "+ ++a+"]><i></i><![endif]--\x3e",c[0];);return 4<a?a:p}();return{vb:["authenticity_token",/^__RequestVerificationToken(_.*)?$/],u:function(a,b){for(var c=0,d=a.length;c<d;c++)b(a[c],c)},m:function(a,b){if("function"==typeof Array.prototype.indexOf)return Array.prototype.indexOf.call(a,b);for(var c=0,d=a.length;c<d;c++)if(a[c]===
65666b)return c;return-1},qb:function(a,b,c){for(var d=0,f=a.length;d<f;d++)if(b.call(c,a[d],d))return a[d];return null},ua:function(m,b){var c=a.a.m(m,b);0<c?m.splice(c,1):0===c&&m.shift()},rb:function(m){m=m||[];for(var b=[],c=0,d=m.length;c<d;c++)0>a.a.m(b,m[c])&&b.push(m[c]);return b},Da:function(a,b){a=a||[];for(var c=[],d=0,f=a.length;d<f;d++)c.push(b(a[d],d));return c},ta:function(a,b){a=a||[];for(var c=[],d=0,f=a.length;d<f;d++)b(a[d],d)&&c.push(a[d]);return c},ga:function(a,b){if(b instanceof
65667Array)a.push.apply(a,b);else for(var c=0,d=b.length;c<d;c++)a.push(b[c]);return a},ea:function(b,c,d){var f=a.a.m(a.a.Xa(b),c);0>f?d&&b.push(c):d||b.splice(f,1)},xa:e,extend:d,za:c,Aa:e?c:d,G:b,na:function(a,b){if(!a)return a;var c={},d;for(d in a)a.hasOwnProperty(d)&&(c[d]=b(a[d],d,a));return c},Ka:function(b){for(;b.firstChild;)a.removeNode(b.firstChild)},oc:function(b){b=a.a.S(b);for(var c=v.createElement("div"),d=0,f=b.length;d<f;d++)c.appendChild(a.R(b[d]));return c},ia:function(b,c){for(var d=
656680,f=b.length,e=[];d<f;d++){var k=b[d].cloneNode(!0);e.push(c?a.R(k):k)}return e},T:function(b,c){a.a.Ka(b);if(c)for(var d=0,f=c.length;d<f;d++)b.appendChild(c[d])},Lb:function(b,c){var d=b.nodeType?[b]:b;if(0<d.length){for(var f=d[0],e=f.parentNode,k=0,g=c.length;k<g;k++)e.insertBefore(c[k],f);k=0;for(g=d.length;k<g;k++)a.removeNode(d[k])}},ka:function(a,b){if(a.length){for(b=8===b.nodeType&&b.parentNode||b;a.length&&a[0].parentNode!==b;)a.shift();if(1<a.length){var c=a[0],d=a[a.length-1];for(a.length=
656690;c!==d;)if(a.push(c),c=c.nextSibling,!c)return;a.push(d)}}return a},Nb:function(a,b){7>f?a.setAttribute("selected",b):a.selected=b},cb:function(a){return null===a||a===p?"":a.trim?a.trim():a.toString().replace(/^[\s\xa0]+|[\s\xa0]+$/g,"")},vc:function(a,b){a=a||"";return b.length>a.length?!1:a.substring(0,b.length)===b},cc:function(a,b){if(a===b)return!0;if(11===a.nodeType)return!1;if(b.contains)return b.contains(3===a.nodeType?a.parentNode:a);if(b.compareDocumentPosition)return 16==(b.compareDocumentPosition(a)&
6567016);for(;a&&a!=b;)a=a.parentNode;return!!a},Ja:function(b){return a.a.cc(b,b.ownerDocument.documentElement)},ob:function(b){return!!a.a.qb(b,a.a.Ja)},t:function(a){return a&&a.tagName&&a.tagName.toLowerCase()},n:function(b,c,d){var e=f&&k[c];if(!e&&w)w(b).bind(c,d);else if(e||"function"!=typeof b.addEventListener)if("undefined"!=typeof b.attachEvent){var g=function(a){d.call(b,a)},h="on"+c;b.attachEvent(h,g);a.a.w.da(b,function(){b.detachEvent(h,g)})}else throw Error("Browser doesn't support addEventListener or attachEvent");
65671else b.addEventListener(c,d,!1)},oa:function(b,c){if(!b||!b.nodeType)throw Error("element must be a DOM node when calling triggerEvent");var d;"input"===a.a.t(b)&&b.type&&"click"==c.toLowerCase()?(d=b.type,d="checkbox"==d||"radio"==d):d=!1;if(w&&!d)w(b).trigger(c);else if("function"==typeof v.createEvent)if("function"==typeof b.dispatchEvent)d=v.createEvent(h[c]||"HTMLEvents"),d.initEvent(c,
vendor: 4,454 bytes, lines 65671-65680
65671!0,!0,s,0,0,0,0,0,!1,!1,!1,!1,0,b),b.dispatchEvent(d);else throw Error("The supplied element doesn't support dispatchEvent");
65672else if(d&&b.click)b.click();else if("undefined"!=typeof b.fireEvent)b.fireEvent("on"+c);else throw Error("Browser doesn't support triggering events");},c:function(b){return a.C(b)?b():b},Xa:function(b){return a.C(b)?b.v():b},Ba:function(b,c,d){if(c){var f=/\S+/g,e=b.className.match(f)||[];a.a.u(c.match(f),function(b){a.a.ea(e,b,d)});b.className=e.join(" ")}},bb:function(b,c){var d=a.a.c(c);if(null===d||d===p)d="";var f=a.f.firstChild(b);!f||3!=f.nodeType||a.f.nextSibling(f)?a.f.T(b,[b.ownerDocument.createTextNode(d)]):
65673f.data=d;a.a.fc(b)},Mb:function(a,b){a.name=b;if(7>=f)try{a.mergeAttributes(v.createElement("<input name='"+a.name+"'/>"),!1)}catch(c){}},fc:function(a){9<=f&&(a=1==a.nodeType?a:a.parentNode,a.style&&(a.style.zoom=a.style.zoom))},dc:function(a){if(f){var b=a.style.width;a.style.width=0;a.style.width=b}},sc:function(b,c){b=a.a.c(b);c=a.a.c(c);for(var d=[],f=b;f<=c;f++)d.push(f);return d},S:function(a){for(var b=[],c=0,d=a.length;c<d;c++)b.push(a[c]);return b},yc:6===f,zc:7===f,L:f,xb:function(b,c){for(var d=
65674a.a.S(b.getElementsByTagName("input")).concat(a.a.S(b.getElementsByTagName("textarea"))),f="string"==typeof c?function(a){return a.name===c}:function(a){return c.test(a.name)},e=[],k=d.length-1;0<=k;k--)f(d[k])&&e.push(d[k]);return e},pc:function(b){return"string"==typeof b&&(b=a.a.cb(b))?D&&D.parse?D.parse(b):(new Function("return "+b))():null},eb:function(b,c,d){if(!D||!D.stringify)throw Error("Cannot find JSON.stringify(). Some browsers (e.g., IE < 8) don't support it natively, but you can overcome this by adding a script reference to json2.js, downloadable from http://www.json.org/json2.js");
65675return D.stringify(a.a.c(b),c,d)},qc:function(c,d,f){f=f||{};var e=f.params||{},k=f.includeFields||this.vb,g=c;if("object"==typeof c&&"form"===a.a.t(c))for(var g=c.action,h=k.length-1;0<=h;h--)for(var r=a.a.xb(c,k[h]),E=r.length-1;0<=E;E--)e[r[E].name]=r[E].value;d=a.a.c(d);var y=v.createElement("form");y.style.display="none";y.action=g;y.method="post";for(var p in d)c=v.createElement("input"),c.type="hidden",c.name=p,c.value=a.a.eb(a.a.c(d[p])),y.appendChild(c);b(e,function(a,b){var c=v.createElement("input");
65676c.type="hidden";c.name=a;c.value=b;y.appendChild(c)});v.body.appendChild(y);f.submitter?f.submitter(y):y.submit();setTimeout(function(){y.parentNode.removeChild(y)},0)}}}();a.b("utils",a.a);a.b("utils.arrayForEach",a.a.u);a.b("utils.arrayFirst",a.a.qb);a.b("utils.arrayFilter",a.a.ta);a.b("utils.arrayGetDistinctValues",a.a.rb);a.b("utils.arrayIndexOf",a.a.m);a.b("utils.arrayMap",a.a.Da);a.b("utils.arrayPushAll",a.a.ga);a.b("utils.arrayRemoveItem",a.a.ua);a.b("utils.extend",a.a.extend);a.b("utils.fieldsIncludedWithJsonPost",
65677a.a.vb);a.b("utils.getFormFields",a.a.xb);a.b("utils.peekObservable",a.a.Xa);a.b("utils.postJson",a.a.qc);a.b("utils.parseJson",a.a.pc);a.b("utils.registerEventHandler",a.a.n);a.b("utils.stringifyJson",a.a.eb);a.b("utils.range",a.a.sc);a.b("utils.toggleDomNodeCssClass",a.a.Ba);a.b("utils.triggerEvent",a.a.oa);a.b("utils.unwrapObservable",a.a.c);a.b("utils.objectForEach",a.a.G);a.b("utils.addOrRemoveItem",a.a.ea);a.b("unwrap",a.a.c);Function.prototype.bind||(Function.prototype.bind=function(a){var d=
65678this,c=Array.prototype.slice.call(arguments);a=c.shift();return function(){return d.apply(a,c.concat(Array.prototype.slice.call(arguments)))}});a.a.e=new function(){function a(b,h){var k=b[c];if(!k||"null"===k||!e[k]){if(!h)return p;k=b[c]="ko"+d++;e[k]={}}return e[k]}var d=0,c="__ko__"+(new Date).getTime(),e={};return{get:function(c,d){var e=a(c,!1);return e===p?p:e[d]},set:function(c,d,e){if(e!==p||a(c,!1)!==p)a(c,!0)[d]=e},clear:function(a){var b=a[c];return b?(delete e[b],a[c]=null,!0):!1},F:function(){return d++ +
65679c}}};a.b("utils.domData",a.a.e);a.b("utils.domData.clear",a.a.e.clear);a.a.w=new function(){function b(b,d){var f=a.a.e.get(b,c);f===p&&d&&(f=[],a.a.e.set(b,c,f));return f}function d(c){var e=b(c,!1);if(e)for(var e=e.slice(0),f=0;f<e.length;f++)e[f](c);a.a.e.clear(c);a.a.w.cleanExternalData(c);if(g[c.nodeType])for(e=c.firstChild;c=e;)e=c.nextSibling,8===c.nodeType&&d(c)}var c=a.a.e.F(),e={1:!0,8:!0,9:!0},g={1:!0,9:!0};return{da:function(a,c){if("function"!=typeof c)throw Error("Callback must be a function");
65680b(a,!0).push(c)},Kb:function(d,e){var f=b(d,!1);f&&(a.a.ua(f,e),0==f.length&&a.a.e.set(d,c,p))}
65680,R:function(b){if(e[b.nodeType]&&(d(b),g[b.nodeType])){var c=[];a.a.ga(c,b.getElementsByTagName("*"));for(var f=0,m=c.length;f<m;f++)d(c[f])}return b},removeNode:function(b){a.R(b);b.parentNode&&b.parentNode.removeChild(b)},cleanExternalData:function(a){w&&"function"==typeof w.cleanData&&w.cleanData([a])}}};a.R=a.a.w.R;a.removeNode=a.a.w.removeNode;a.b("cleanNode",a.R);a.b("removeNode",a.removeNode);a.b("utils.domNodeDisposal",
65681a.a.w);a.b("utils.domNodeDisposal.addDisposeCallback",a.a.w.da);a.b("utils.domNodeDisposal.removeDisposeCallback",a.a.w.Kb);(function(){a.a.ba=function(b){var d;if(w)if(w.parseHTML)d=w.parseHTML(b)||[];else{if((d=w.clean([b]))&&d[0]){for(b=d[0];b.parentNode&&11!==b.parentNode.nodeType;)b=b.parentNode;b.parentNode&&b.parentNode.removeChild(b)}}else{var c=a.a.cb(b).toLowerCase();d=v.createElement("div");c=c.match(/^<(thead|tbody|tfoot)/)&&[1,"<table>","</table>"]||!c.indexOf("<tr")&&[2,"<table><tbody>",
65682"</tbody></table>"]||(!c.indexOf("<td")||!c.indexOf("<th"))&&[3,"<table><tbody><tr>","</tr></tbody></table>"]||[0,"",""];b="ignored<div>"+c[1]+b+c[2]+"</div>";for("function"==typeof s.innerShiv?d.appendChild(s.innerShiv(b)):d.innerHTML=b;c[0]--;)d=d.lastChild;d=a.a.S(d.lastChild.childNodes)}return d};a.a.$a=function(b,d){a.a.Ka(b);d=a.a.c(d);if(null!==d&&d!==p)if("string"!=typeof d&&(d=d.toString()),w)w(b).html(d);else for(var c=a.a.ba(d),e=0;e<c.length;e++)b.appendChild(c[e])}})();a.b("utils.parseHtmlFragment",
65683a.a.ba);a.b("utils.setHtml",a.a.$a);a.D=function(){function b(c,d){if(c)if(8==c.nodeType){var g=a.D.Gb(c.nodeValue);null!=g&&d.push({bc:c,mc:g})}else if(1==c.nodeType)for(var g=0,h=c.childNodes,k=h.length;g<k;g++)b(h[g],d)}var d={};return{Ua:function(a){if("function"!=typeof a)throw Error("You can only pass a function to ko.memoization.memoize()");var b=(4294967296*(1+Math.random())|0).toString(16).substring(1)+(4294967296*(1+Math.random())|0).toString(16).substring(1);d[b]=a;return"\x3c!--[ko_memo:"+
65684b+"]--\x3e"},Rb:function(a,b){var g=d[a];if(g===p)throw Error("Couldn't find any memo with ID "+a+". Perhaps it's already been unmemoized.");try{return g.apply(null,b||[]),!0}finally{delete d[a]}},Sb:function(c,d){var g=[];b(c,g);for(var h=0,k=g.length;h<k;h++){var f=g[h].bc,m=[f];d&&a.a.ga(m,d);a.D.Rb(g[h].mc,m);f.nodeValue="";f.parentNode&&f.parentNode.removeChild(f)}},Gb:function(a){return(a=a.match(/^\[ko_memo\:(.*?)\]$/))?a[1]:null}}}();a.b("memoization",a.D);a.b("memoization.memoize",a.D.Ua);
65685a.b("memoization.unmemoize",a.D.Rb);a.b("memoization.parseMemoText",a.D.Gb);a.b("memoization.unmemoizeDomNodeAndDescendants",a.D.Sb);a.La={throttle:function(b,d){b.throttleEvaluation=d;var c=null;return a.j({read:b,write:function(a){clearTimeout(c);c=setTimeout(function(){b(a)},d)}})},rateLimit:function(a,d){var c,e,g;"number"==typeof d?c=d:(c=d.timeout,e=d.method);g="notifyWhenChangesStop"==e?T:S;a.Ta(function(a){return g(a,c)})},notify:function(a,d){a.equalityComparer="always"==d?null:H}};var R=
65686{undefined:1,"boolean":1,number:1,string:1};a.b("extenders",a.La);a.Pb=function(b,d,c){this.target=b;this.wa=d;this.ac=c;this.Cb=!1;a.A(this,"dispose",this.K)};a.Pb.prototype.K=function(){this.Cb=!0;this.ac()};a.P=function(){a.a.Aa(this,a.P.fn);this.M={}};var G="change",A={U:function(b,d,c){var e=this;c=c||G;var g=new a.Pb(e,d?b.bind(d):b,function(){a.a.ua(e.M[c],g);e.nb&&e.nb()});e.va&&e.va(c);e.M[c]||(e.M[c]=[]);e.M[c].push(g);return g},notifySubscribers:function(b,d){d=d||G;if(this.Ab(d))try{a.k.Ea();
65687for(var c=this.M[d].slice(0),e=0,g;g=c[e];++e)g.Cb||g.wa(b)}finally{a.k.end()}},Ta:function(b){var d=this,c=a.C(d),e,g,h;d.qa||(d.qa=d.notifySubscribers,d.notifySubscribers=function(a,b){b&&b!==G?"beforeChange"===b?d.kb(a):d.qa(a,b):d.lb(a)});var k=b(function(){c&&h===d&&(h=d());e=!1;d.Pa(g,h)&&d.qa(g=h)});d.lb=function(a){e=!0;h=a;k()};d.kb=function(a){e||(g=a,d.qa(a,"beforeChange"))}},Ab:function(a){return this.M[a]&&this.M[a].length},yb:function(){var b=0;a.a.G(this.M,function(a,c){b+=c.length});
65688return b},Pa:function(a,d){return!this.equalityComparer||!this.equalityComparer(a,d)},extend:function(b){var d=this;b&&a.a.G(b,function(b,e){var g=a.La[b];"function"==typeof g&&(d=g(d,e)||d)});return d}};a.A(A,"subscribe",A.U);a.A(A,"extend",A.extend);a.A(A,"getSubscriptionsCount",A.yb);a.a.xa&&a.a.za(A,Function.prototype);a.P.fn=A;a.Db=function(a){return null!=a&&"function"==typeof a.U&&"function"==typeof a.notifySubscribers};a.b("subscribable",a.P);a.b("isSubscribable",a.Db);a.Y=a.k=function(){function b(a){c.push(e);
65689e=a}function d(){e=c.pop()}var c=[],e,g=0;return{Ea:b,end:d,Jb:function(b){if(e){if(!a.Db(b))throw Error("Only subscribable things can act as dependencies");e.wa(b,b.Vb||(b.Vb=++g))}},B:function(a,c,f){try{return b(),a.apply(c,f||[])}finally{d()}},la:function(){if(e)return e.s.la()},ma:function(){if(e)return e.ma}}}();a.b("computedContext",a.Y);a.b("computedContext.getDependenciesCount",a.Y.la);a.b("computedContext.isInitial",a.Y.ma);a.b("computedContext.isSleeping",a.Y.Ac);a.p=function(b){function d(){if(0<
65690arguments.length)return d.Pa(c,arguments[0])&&(d.X(),c=arguments[0],d.W()),this;a.k.Jb(d);return c}var c=b;a.P.call(d);a.a.Aa(d,a.p.fn);d.v=function(){return c};d.W=function(){d.notifySubscribers(c)};d.X=function(){d.notifySubscribers(c,"beforeChange")};a.A(d,"peek",d.v);a.A(d,"valueHasMutated",d.W);a.A(d,"valueWillMutate",d.X);return d};a.p.fn={equalityComparer:H};var F=a.p.rc="__ko_proto__";a.p.fn[F]=a.p;a.a.xa&&a.a.za(a.p.fn,a.P.fn);a.Ma=function(b,d){return null===b||b===p||b[F]===p?!1:b[F]===
65691d?!0:a.Ma(b[F],d)};a.C=function(b){return a.Ma(b,a.p)};a.Ra=function(b){return"function"==typeof b&&b[F]===a.p||"function"==typeof b&&b[F]===a.j&&b.hc?!0:!1};a.b("observable",a.p);a.b("isObservable",a.C);a.b("isWriteableObservable",a.Ra);a.b("isWritableObservable",a.Ra);a.aa=function(b){b=b||[];if("object"!=typeof b||!("length"in b))throw Error("The argument passed when initializing an observable array must be an array, or null, or undefined.");b=a.p(b);a.a.Aa(b,a.aa.fn);return b.extend({trackArrayChanges:!0})};
65692a.aa.fn={remove:function(b){for(var d=this.v(),c=[],e="function"!=typeof b||a.C(b)?function(a){return a===b}:b,g=0;g<d.length;g++){var h=d[g];e(h)&&(0===c.length&&this.X(),c.push(h),d.splice(g,1),g--)}c.length&&this.W();return c},removeAll:function(b){if(b===p){var d=this.v(),c=d.slice(0);this.X();d.splice(0,d.length);this.W();return c}return b?this.remove(function(c){return 0<=a.a.m(b,c)}):[]},destroy:function(b){var d=this.v(),c="function"!=typeof b||a.C(b)?function(a){return a===b}:b;this.X();
65693for(var e=d.length-1;0<=e;e--)c(d[e])&&(d[e]._destroy=!0);this.W()},destroyAll:function(b){return b===p?this.destroy(function(){return!0}):b?this.destroy(function(d){return 0<=a.a.m(b,d)}):[]},indexOf:function(b){var d=this();return a.a.m(d,b)},replace:function(a,d){var c=this.indexOf(a);0<=c&&(this.X(),this.v()[c]=d,this.W())}};a.a.u("pop push reverse shift sort splice unshift".split(" "),function(b){a.aa.fn[b]=function(){var a=this.v();this.X();this.sb(a,b,arguments);a=a[b].apply(a,arguments);this.W();
65694return a}});a.a.u(["slice"],function(b){a.aa.fn[b]=function(){var a=this();return a[b].apply(a,arguments)}});a.a.xa&&a.a.za(a.aa.fn,a.p.fn);a.b("observableArray",a.aa);var J="arrayChange";a.La.trackArrayChanges=function(b){function d(){if(!c){c=!0;var d=b.notifySubscribers;b.notifySubscribers=function(a,b){b&&b!==G||++g;return d.apply(this,arguments)};var f=[].concat(b.v()||[]);e=null;b.U(function(c){c=[].concat(c||[]);if(b.Ab(J)){var d;if(!e||1<g)e=a.a.Fa(f,c,{sparse:!0});d=e;d.length&&b.notifySubscribers(d,
65695J)}f=c;e=null;g=0})}}if(!b.sb){var c=!1,e=null,g=0,h=b.U;b.U=b.subscribe=function(a,b,c){c===J&&d();return h.apply(this,arguments)};b.sb=function(b,d,m){function l(a,b,c){return q[q.length]={status:a,value:b,index:c}}if(c&&!g){var q=[],h=b.length,t=m.length,z=0;switch(d){case "push":z=h;case "unshift":for(d=0;d<t;d++)l("added",m[d],z+d);break;case "pop":z=h-1;case "shift":h&&l("deleted",b[z],z);break;case "splice":d=Math.min(Math.max(0,0>m[0]?h+m[0]:m[0]),h);for(var h=1===t?h:Math.min(d+(m[1]||0),
65696h),t=d+t-2,z=Math.max(h,t),u=[],r=[],E=2;d<z;++d,++E)d<h&&r.push(l("deleted",b[d],d)),d<t&&u.push(l("added",m[E],d));a.a.wb(r,u);break;default:return}e=q}}}};a.s=a.j=function(b,d,c){function e(){a.a.G(v,function(a,b){b.K()});v={}}function g(){e();C=0;u=!0;n=!1}function h(){var a=f.throttleEvaluation;a&&0<=a?(clearTimeout(P),P=setTimeout(k,a)):f.ib?f.ib():k()}function k(b){if(t){if(E)throw Error("A 'pure' computed must not be called recursively");}else if(!u){if(w&&w()){if(!z){s();return}}else z=!1;
65697t=!0;if(y)try{var c={};a.k.Ea({wa:function(a,b){c[b]||(c[b]=1,++C)},s:f,ma:p});C=0;q=r.call(d)}finally{a.k.end(),t=!1}else try{var e=v,m=C;a.k.Ea({wa:function(a,b){u||(m&&e[b]?(v[b]=e[b],++C,delete e[b],--m):v[b]||(v[b]=a.U(h),++C))},s:f,ma:E?p:!C});v={};C=0;try{var l=d?r.call(d):r()}finally{a.k.end(),m&&a.a.G(e,function(a,b){b.K()}),n=!1}f.Pa(q,l)&&(f.notifySubscribers(q,"beforeChange"),q=l,!0!==b&&f.notifySubscribers(q))}finally{t=!1}C||s()}}function f(){if(0<arguments.length){if("function"===typeof O)O.apply(d,
65698arguments);else throw Error("Cannot write a value to a ko.computed unless you specify a 'write' option. If you wish to read the current value, don't pass any parameters.");return this}a.k.Jb(f);n&&k(!0);return q}function m(){n&&!C&&k(!0);return q}function l(){return n||0<C}var q,n=!0,t=!1,z=!1,u=!1,r=b,E=!1,y=!1;r&&"object"==typeof r?(c=r,r=c.read):(c=c||{},r||(r=c.read));if("function"!=typeof r)throw Error("Pass a function that returns the value of the ko.computed");var O=c.write,x=c.disposeWhenNodeIsRemoved||
65699c.o||null,B=c.disposeWhen||c.Ia,w=B,s=g,v={},C=0,P=null;d||(d=c.owner);a.P.call(f);a.a.Aa(f,a.j.fn);f.v=m;f.la=function(){return C};f.hc="function"===typeof c.write;f.K=function(){s()};f.Z=l;var A=f.Ta;f.Ta=function(a){A.call(f,a);f.ib=function(){f.kb(q);n=!0;f.lb(f)}};c.pure?(y=E=!0,f.va=function(){y&&(y=!1,k(!0))},f.nb=function(){f.yb()||(e(),y=n=!0)}):c.deferEvaluation&&(f.va=function(){m();delete f.va});a.A(f,"peek",f.v);a.A(f,"dispose",f.K);a.A(f,"isActive",f.Z);a.A(f,"getDependenciesCount",
65700f.la);x&&(z=!0,x.nodeType&&(w=function(){return!a.a.Ja(x)||B&&B()}));y||c.deferEvaluation||k();x&&l()&&x.nodeType&&(s=function(){a.a.w.Kb(x,s);g()},a.a.w.da(x,s));return f};a.jc=function(b){return a.Ma(b,a.j)};A=a.p.rc;a.j[A]=a.p;a.j.fn={equalityComparer:H};a.j.fn[A]=a.j;a.a.xa&&a.a.za(a.j.fn,a.P.fn);a.b("dependentObservable",a.j);a.b("computed",a.j);a.b("isComputed",a.jc);a.Ib=function(b,d){if("function"===typeof b)return a.s(b,d,{pure:!0});b=a.a.extend({},b);b.pure=!0;return a.s(b,d)};a.b("pureComputed",
65701a.Ib);(function(){function b(a,g,h){h=h||new c;a=g(a);if("object"!=typeof a||null===a||a===p||a instanceof Date||a instanceof String||a instanceof Number||a instanceof Boolean)return a;var k=a instanceof Array?[]:{};h.save(a,k);d(a,function(c){var d=g(a[c]);switch(typeof d){case "boolean":case "number":case "string":case "function":k[c]=d;break;case "object":case "undefined":var l=h.get(d);k[c]=l!==p?l:b(d,g,h)}});return k}function d(a,b){if(a instanceof Array){for(var c=0;c<a.length;c++)b(c);"function"==
65702typeof a.toJSON&&b("toJSON")}else for(c in a)b(c)}function c(){this.keys=[];this.hb=[]}a.Qb=function(c){if(0==arguments.length)throw Error("When calling ko.toJS, pass the object you want to convert.");return b(c,function(b){for(var c=0;a.C(b)&&10>c;c++)b=b();return b})};a.toJSON=function(b,c,d){b=a.Qb(b);return a.a.eb(b,c,d)};c.prototype={save:function(b,c){var d=a.a.m(this.keys,b);0<=d?this.hb[d]=c:(this.keys.push(b),this.hb.push(c))},get:function(b){b=a.a.m(this.keys,b);return 0<=b?this.hb[b]:p}}})();
65703a.b("toJS",a.Qb);a.b("toJSON",a.toJSON);(function(){a.i={q:function(b){switch(a.a.t(b)){case "option":return!0===b.__ko__hasDomDataOptionValue__?a.a.e.get(b,a.d.options.Va):7>=a.a.L?b.getAttributeNode("value")&&b.getAttributeNode("value").specified?b.value:b.text:b.value;case "select":return 0<=b.selectedIndex?a.i.q(b.options[b.selectedIndex]):p;default:return b.value}}
vendor: 6,520 bytes, lines 65703-65716
65703,ca:function(b,d,c){switch(a.a.t(b)){case "option":switch(typeof d){case "string":a.a.e.set(b,a.d.options.Va,p);"__ko__hasDomDataOptionValue__"in
65704b&&delete b.__ko__hasDomDataOptionValue__;b.value=d;break;default:a.a.e.set(b,a.d.options.Va,d),b.__ko__hasDomDataOptionValue__=!0,b.value="number"===typeof d?d:""}break;case "select":if(""===d||null===d)d=p;for(var e=-1,g=0,h=b.options.length,k;g<h;++g)if(k=a.i.q(b.options[g]),k==d||""==k&&d===p){e=g;break}if(c||0<=e||d===p&&1<b.size)b.selectedIndex=e;break;default:if(null===d||d===p)d="";b.value=d}}}})();a.b("selectExtensions",a.i);a.b("selectExtensions.readValue",a.i.q);a.b("selectExtensions.writeValue",
65705a.i.ca);a.h=function(){function b(b){b=a.a.cb(b);123===b.charCodeAt(0)&&(b=b.slice(1,-1));var c=[],d=b.match(e),k,n,t=0;if(d){d.push(",");for(var z=0,u;u=d[z];++z){var r=u.charCodeAt(0);if(44===r){if(0>=t){k&&c.push(n?{key:k,value:n.join("")}:{unknown:k});k=n=t=0;continue}}else if(58===r){if(!n)continue}else if(47===r&&z&&1<u.length)(r=d[z-1].match(g))&&!h[r[0]]&&(b=b.substr(b.indexOf(u)+1),d=b.match(e),d.push(","),z=-1,u="/");else if(40===r||123===r||91===r)++t;else if(41===r||125===r||93===r)--t;
65706else if(!k&&!n){k=34===r||39===r?u.slice(1,-1):u;continue}n?n.push(u):n=[u]}}return c}var d=["true","false","null","undefined"],c=/^(?:[$_a-z][$\w]*|(.+)(\.\s*[$_a-z][$\w]*|\[.+\]))$/i,e=RegExp("\"(?:[^\"\\\\]|\\\\.)*\"|'(?:[^'\\\\]|\\\\.)*'|/(?:[^/\\\\]|\\\\.)*/w*|[^\\s:,/][^,\"'{}()/:[\\]]*[^\\s,\"'{}()/:[\\]]|[^\\s]","g"),g=/[\])"'A-Za-z0-9_$]+$/,h={"in":1,"return":1,"typeof":1},k={};return{ha:[],V:k,Wa:b,ya:function(f,m){function e(b,m){var f;if(!z){var u=a.getBindingHandler(b);if(u&&u.preprocess&&
65707!(m=u.preprocess(m,b,e)))return;if(u=k[b])f=m,0<=a.a.m(d,f)?f=!1:(u=f.match(c),f=null===u?!1:u[1]?"Object("+u[1]+")"+u[2]:f),u=f;u&&h.push("'"+b+"':function(_z){"+f+"=_z}")}t&&(m="function(){return "+m+" }");g.push("'"+b+"':"+m)}m=m||{};var g=[],h=[],t=m.valueAccessors,z=m.bindingParams,u="string"===typeof f?b(f):f;a.a.u(u,function(a){e(a.key||a.unknown,a.value)});h.length&&e("_ko_property_writers","{"+h.join(",")+" }");return g.join(",")},lc:function(a,b){for(var c=0;c<a.length;c++)if(a[c].key==
65708b)return!0;return!1},pa:function(b,c,d,e,k){if(b&&a.C(b))!a.Ra(b)||k&&b.v()===e||b(e);else if((b=c.get("_ko_property_writers"))&&b[d])b[d](e)}}}();a.b("expressionRewriting",a.h);a.b("expressionRewriting.bindingRewriteValidators",a.h.ha);a.b("expressionRewriting.parseObjectLiteral",a.h.Wa);a.b("expressionRewriting.preProcessBindings",a.h.ya);a.b("expressionRewriting._twoWayBindings",a.h.V);a.b("jsonExpressionRewriting",a.h);a.b("jsonExpressionRewriting.insertPropertyAccessorsIntoJson",a.h.ya);(function(){function b(a){return 8==
65709a.nodeType&&h.test(g?a.text:a.nodeValue)}function d(a){return 8==a.nodeType&&k.test(g?a.text:a.nodeValue)}function c(a,c){for(var f=a,e=1,k=[];f=f.nextSibling;){if(d(f)&&(e--,0===e))return k;k.push(f);b(f)&&e++}if(!c)throw Error("Cannot find closing comment tag to match: "+a.nodeValue);return null}function e(a,b){var d=c(a,b);return d?0<d.length?d[d.length-1].nextSibling:a.nextSibling:null}var g=v&&"\x3c!--test--\x3e"===v.createComment("test").text,h=g?/^\x3c!--\s*ko(?:\s+([\s\S]+))?\s*--\x3e$/:/^\s*ko(?:\s+([\s\S]+))?\s*$/,
65710k=g?/^\x3c!--\s*\/ko\s*--\x3e$/:/^\s*\/ko\s*$/,f={ul:!0,ol:!0};a.f={Q:{},childNodes:function(a){return b(a)?c(a):a.childNodes},ja:function(c){if(b(c)){c=a.f.childNodes(c);for(var d=0,f=c.length;d<f;d++)a.removeNode(c[d])}else a.a.Ka(c)},T:function(c,d){if(b(c)){a.f.ja(c);for(var f=c.nextSibling,e=0,k=d.length;e<k;e++)f.parentNode.insertBefore(d[e],f)}else a.a.T(c,d)},Hb:function(a,c){b(a)?a.parentNode.insertBefore(c,a.nextSibling):a.firstChild?a.insertBefore(c,a.firstChild):a.appendChild(c)},Bb:function(c,
65711d,f){f?b(c)?c.parentNode.insertBefore(d,f.nextSibling):f.nextSibling?c.insertBefore(d,f.nextSibling):c.appendChild(d):a.f.Hb(c,d)},firstChild:function(a){return b(a)?!a.nextSibling||d(a.nextSibling)?null:a.nextSibling:a.firstChild},nextSibling:function(a){b(a)&&(a=e(a));return a.nextSibling&&d(a.nextSibling)?null:a.nextSibling},gc:b,xc:function(a){return(a=(g?a.text:a.nodeValue).match(h))?a[1]:null},Fb:function(c){if(f[a.a.t(c)]){var k=c.firstChild;if(k){do if(1===k.nodeType){var g;g=k.firstChild;
65712var h=null;if(g){do if(h)h.push(g);else if(b(g)){var t=e(g,!0);t?g=t:h=[g]}else d(g)&&(h=[g]);while(g=g.nextSibling)}if(g=h)for(h=k.nextSibling,t=0;t<g.length;t++)h?c.insertBefore(g[t],h):c.appendChild(g[t])}while(k=k.nextSibling)}}}}})();a.b("virtualElements",a.f);a.b("virtualElements.allowedBindings",a.f.Q);a.b("virtualElements.emptyNode",a.f.ja);a.b("virtualElements.insertAfter",a.f.Bb);a.b("virtualElements.prepend",a.f.Hb);a.b("virtualElements.setDomNodeChildren",a.f.T);(function(){a.J=function(){this.Yb=
65713{}};a.a.extend(a.J.prototype,{nodeHasBindings:function(b){switch(b.nodeType){case 1:return null!=b.getAttribute("data-bind")||a.g.getComponentNameForNode(b);case 8:return a.f.gc(b);default:return!1}},getBindings:function(b,d){var c=this.getBindingsString(b,d),c=c?this.parseBindingsString(c,d,b):null;return a.g.mb(c,b,d,!1)},getBindingAccessors:function(b,d){var c=this.getBindingsString(b,d),c=c?this.parseBindingsString(c,d,b,{valueAccessors:!0}):null;return a.g.mb(c,b,d,!0)},getBindingsString:function(b){switch(b.nodeType){case 1:return b.getAttribute("data-bind");
65714case 8:return a.f.xc(b);default:return null}},parseBindingsString:function(b,d,c,e){try{var g=this.Yb,h=b+(e&&e.valueAccessors||""),k;if(!(k=g[h])){var f,m="with($context){with($data||{}){return{"+a.h.ya(b,e)+"}}}";f=new Function("$context","$element",m);k=g[h]=f}return k(d,c)}catch(l){throw l.message="Unable to parse bindings.\nBindings value: "+b+"\nMessage: "+l.message,l;}}});a.J.instance=new a.J})();a.b("bindingProvider",a.J);(function(){function b(a){return function(){return a}}function d(a){return a()}
65715function c(b){return a.a.na(a.k.B(b),function(a,c){return function(){return b()[c]}})}function e(a,b){return c(this.getBindings.bind(this,a,b))}function g(b,c,d){var f,e=a.f.firstChild(c),k=a.J.instance,g=k.preprocessNode;if(g){for(;f=e;)e=a.f.nextSibling(f),g.call(k,f);e=a.f.firstChild(c)}for(;f=e;)e=a.f.nextSibling(f),h(b,f,d)}function h(b,c,d){var e=!0,k=1===c.nodeType;k&&a.f.Fb(c);if(k&&d||a.J.instance.nodeHasBindings(c))e=f(c,null,b,d).shouldBindDescendants;e&&!l[a.a.t(c)]&&g(b,c,!k)}function k(b){var c=
65716[],d={},f=[];a.a.G(b,function y(e){if(!d[e]){var k=a.getBindingHandler(e);k&&(k.after&&(f.push(e),a.a.u(k.after,function(c){if(b[c]){if(-1!==a.a.m(f,c)
65716)throw Error("Cannot combine the following bindings, because they have a cyclic dependency: "+f.join(", "));y(c)}}),f.length--),c.push({key:e,zb:k}));d[e]=!0}});return c}function f(b,c,f,g){var m=a.a.e.get(b,q);if(!c){if(m)throw Error("You cannot apply bindings multiple times to the same element.");a.a.e.set(b,q,!0)}!m&&g&&a.Ob(b,f);var l;if(c&&"function"!==
65717typeof c)l=c;else{var h=a.J.instance,n=h.getBindingAccessors||e,s=a.j(function(){(l=c?c(f,b):n.call(h,b,f))&&f.I&&f.I();return l},null,{o:b});l&&s.Z()||(s=null)}var v;if(l){var w=s?function(a){return function(){return d(s()[a])}}:function(a){return l[a]},A=function(){return a.a.na(s?s():l,d)};A.get=function(a){return l[a]&&d(w(a))};A.has=function(a){return a in l};g=k(l);a.a.u(g,function(c){var d=c.zb.init,e=c.zb.update,k=c.key;if(8===b.nodeType&&!a.f.Q[k])throw Error("The binding '"+k+"' cannot be used with virtual elements");
65718try{"function"==typeof d&&a.k.B(function(){var a=d(b,w(k),A,f.$data,f);if(a&&a.controlsDescendantBindings){if(v!==p)throw Error("Multiple bindings ("+v+" and "+k+") are trying to control descendant bindings of the same element. You cannot use these bindings together on the same element.");v=k}}),"function"==typeof e&&a.j(function(){e(b,w(k),A,f.$data,f)},null,{o:b})}catch(g){throw g.message='Unable to process binding "'+k+": "+l[k]+'"\nMessage: '+g.message,g;}})}return{shouldBindDescendants:v===p}}
65719function m(b){return b&&b instanceof a.N?b:new a.N(b)}a.d={};var l={script:!0};a.getBindingHandler=function(b){return a.d[b]};a.N=function(b,c,d,f){var e=this,k="function"==typeof b&&!a.C(b),g,m=a.j(function(){var g=k?b():b,l=a.a.c(g);c?(c.I&&c.I(),a.a.extend(e,c),m&&(e.I=m)):(e.$parents=[],e.$root=l,e.ko=a);e.$rawData=g;e.$data=l;d&&(e[d]=l);f&&f(e,c,l);return e.$data},null,{Ia:function(){return g&&!a.a.ob(g)},o:!0});m.Z()&&(e.I=m,m.equalityComparer=null,g=[],m.Tb=function(b){g.push(b);a.a.w.da(b,
65720function(b){a.a.ua(g,b);g.length||(m.K(),e.I=m=p)})})};a.N.prototype.createChildContext=function(b,c,d){return new a.N(b,this,c,function(a,b){a.$parentContext=b;a.$parent=b.$data;a.$parents=(b.$parents||[]).slice(0);a.$parents.unshift(a.$parent);d&&d(a)})};a.N.prototype.extend=function(b){return new a.N(this.I||this.$data,this,null,function(c,d){c.$rawData=d.$rawData;a.a.extend(c,"function"==typeof b?b():b)})};var q=a.a.e.F(),n=a.a.e.F();a.Ob=function(b,c){if(2==arguments.length)a.a.e.set(b,n,c),
65721c.I&&c.I.Tb(b);else return a.a.e.get(b,n)};a.ra=function(b,c,d){1===b.nodeType&&a.f.Fb(b);return f(b,c,m(d),!0)};a.Wb=function(d,f,e){e=m(e);return a.ra(d,"function"===typeof f?c(f.bind(null,e,d)):a.a.na(f,b),e)};a.Ca=function(a,b){1!==b.nodeType&&8!==b.nodeType||g(m(a),b,!0)};a.pb=function(a,b){!w&&s.jQuery&&(w=s.jQuery);if(b&&1!==b.nodeType&&8!==b.nodeType)throw Error("ko.applyBindings: first parameter should be your view model; second parameter should be a DOM node");b=b||s.document.body;h(m(a),
65722b,!0)};a.Ha=function(b){switch(b.nodeType){case 1:case 8:var c=a.Ob(b);if(c)return c;if(b.parentNode)return a.Ha(b.parentNode)}return p};a.$b=function(b){return(b=a.Ha(b))?b.$data:p};a.b("bindingHandlers",a.d);a.b("applyBindings",a.pb);a.b("applyBindingsToDescendants",a.Ca);a.b("applyBindingAccessorsToNode",a.ra);a.b("applyBindingsToNode",a.Wb);a.b("contextFor",a.Ha);a.b("dataFor",a.$b)})();(function(b){function d(d,f){var e=g.hasOwnProperty(d)?g[d]:b,l;e||(e=g[d]=new a.P,c(d,function(a){h[d]=a;delete g[d];
65723l?e.notifySubscribers(a):setTimeout(function(){e.notifySubscribers(a)},0)}),l=!0);e.U(f)}function c(a,b){e("getConfig",[a],function(c){c?e("loadComponent",[a,c],function(a){b(a)}):b(null)})}function e(c,d,g,l){l||(l=a.g.loaders.slice(0));var h=l.shift();if(h){var n=h[c];if(n){var t=!1;if(n.apply(h,d.concat(function(a){t?g(null):null!==a?g(a):e(c,d,g,l)}))!==b&&(t=!0,!h.suppressLoaderExceptions))throw Error("Component loaders must supply values by invoking the callback, not by returning values synchronously.");
65724}else e(c,d,g,l)}else g(null)}var g={},h={};a.g={get:function(a,c){var e=h.hasOwnProperty(a)?h[a]:b;e?setTimeout(function(){c(e)},0):d(a,c)},tb:function(a){delete h[a]},jb:e};a.g.loaders=[];a.b("components",a.g);a.b("components.get",a.g.get);a.b("components.clearCachedDefinition",a.g.tb)})();(function(){function b(b,c,d,e){function k(){0===--u&&e(h)}var h={},u=2,r=d.template;d=d.viewModel;r?g(c,r,function(c){a.g.jb("loadTemplate",[b,c],function(a){h.template=a;k()})}):k();d?g(c,d,function(c){a.g.jb("loadViewModel",
65725[b,c],function(a){h[f]=a;k()})}):k()}function d(a,b,c){if("function"===typeof b)c(function(a){return new b(a)});else if("function"===typeof b[f])c(b[f]);else if("instance"in b){var e=b.instance;c(function(){return e})}else"viewModel"in b?d(a,b.viewModel,c):a("Unknown viewModel value: "+b)}function c(b){switch(a.a.t(b)){case "script":return a.a.ba(b.text);case "textarea":return a.a.ba(b.value);case "template":if(e(b.content))return a.a.ia(b.content.childNodes)}return a.a.ia(b.childNodes)}function e(a){return s.DocumentFragment?
65726a instanceof DocumentFragment:a&&11===a.nodeType}function g(a,b,c){"string"===typeof b.require?N||s.require?(N||s.require)([b.require],c):a("Uses require, but no AMD loader is present"):c(b)}function h(a){return function(b){throw Error("Component '"+a+"': "+b);}}var k={};a.g.tc=function(b,c){if(!c)throw Error("Invalid configuration for "+b);if(a.g.Qa(b))throw Error("Component "+b+" is already registered");k[b]=c};a.g.Qa=function(a){return a in k};a.g.wc=function(b){delete k[b];a.g.tb(b)};a.g.ub={getConfig:function(a,
65727b){b(k.hasOwnProperty(a)?k[a]:null)},loadComponent:function(a,c,d){var e=h(a);g(e,c,function(c){b(a,e,c,d)})},loadTemplate:function(b,d,f){b=h(b);if("string"===typeof d)f(a.a.ba(d));else if(d instanceof Array)f(d);
65727else if(e(d))f(a.a.S(d.childNodes));else if(d.element)if(d=d.element,s.HTMLElement?d instanceof HTMLElement:d&&d.tagName&&1===d.nodeType)f(c(d));else if("string"===typeof d){var k=v.getElementById(d);k?f(c(k)):b("Cannot find element with ID "+d)}else b("Unknown element type: "+d);else b("Unknown template value: "+
65728d)},loadViewModel:function(a,b,c){d(h(a),b,c)}};var f="createViewModel";a.b("components.register",a.g.tc);a.b("components.isRegistered",a.g.Qa);a.b("components.unregister",a.g.wc);a.b("components.defaultLoader",a.g.ub);a.g.loaders.push(a.g.ub);a.g.Ub=k})();(function(){function b(b,e){var g=b.getAttribute("params");if(g){var g=d.parseBindingsString(g,e,b,{valueAccessors:!0,bindingParams:!0}),g=a.a.na(g,function(d){return a.s(d,null,{o:b})}),h=a.a.na(g,function(d){return d.Z()?a.s(function(){return a.a.c(d())},
65729null,{o:b}):d.v()});h.hasOwnProperty("$raw")||(h.$raw=g);return h}return{$raw:{}}}a.g.getComponentNameForNode=function(b){b=a.a.t(b);return a.g.Qa(b)&&b};a.g.mb=function(c,d,g,h){if(1===d.nodeType){var k=a.g.getComponentNameForNode(d);if(k){c=c||{};if(c.component)throw Error('Cannot use the "component" binding on a custom element matching a component');var f={name:k,params:b(d,g)};c.component=h?function(){return f}:f}}return c};var d=new a.J;9>a.a.L&&(a.g.register=function(a){return function(b){v.createElement(b);
65730return a.apply(this,arguments)}}(a.g.register),v.createDocumentFragment=function(b){return function(){var d=b(),g=a.g.Ub,h;for(h in g)g.hasOwnProperty(h)&&d.createElement(h);return d}}(v.createDocumentFragment))})();(function(){var b=0;a.d.component={init:function(d,c,e,g,h){function k(){var a=f&&f.dispose;"function"===typeof a&&a.call(f);m=null}var f,m;a.a.w.da(d,k);a.s(function(){var e=a.a.c(c()),g,n;"string"===typeof e?g=e:(g=a.a.c(e.name),n=a.a.c(e.params));if(!g)throw Error("No component name specified");
65731var t=m=++b;a.g.get(g,function(b){if(m===t){k();if(!b)throw Error("Unknown component '"+g+"'");var c=b.template;if(!c)throw Error("Component '"+g+"' has no template");c=a.a.ia(c);a.f.T(d,c);var c=n,e=b.createViewModel;b=e?e.call(b,c,{element:d}):c;c=h.createChildContext(b);f=b;a.Ca(c,d)}})},null,{o:d});return{controlsDescendantBindings:!0}}};a.f.Q.component=!0})();var Q={"class":"className","for":"htmlFor"};a.d.attr={update:function(b,d){var c=a.a.c(d())||{};a.a.G(c,function(c,d){d=a.a.c(d);var h=
65732!1===d||null===d||d===p;h&&b.removeAttribute(c);8>=a.a.L&&c in Q?(c=Q[c],h?b.removeAttribute(c):b[c]=d):h||b.setAttribute(c,d.toString());"name"===c&&a.a.Mb(b,h?"":d.toString())})}};(function(){a.d.checked={after:["value","attr"],init:function(b,d,c){function e(){var e=b.checked,k=q?h():e;if(!a.Y.ma()&&(!f||e)){var g=a.k.B(d);m?l!==k?(e&&(a.a.ea(g,k,!0),a.a.ea(g,l,!1)),l=k):a.a.ea(g,k,e):a.h.pa(g,c,"checked",k,!0)}}function g(){var c=a.a.c(d());b.checked=m?0<=a.a.m(c,h()):k?c:h()===c}var h=a.Ib(function(){return c.has("checkedValue")?
65733a.a.c(c.get("checkedValue")):c.has("value")?a.a.c(c.get("value")):b.value}),k="checkbox"==b.type,f="radio"==b.type;if(k||f){var m=k&&a.a.c(d())instanceof Array,l=m?h():p,q=f||m;f&&!b.name&&a.d.uniqueName.init(b,function(){return!0});a.s(e,null,{o:b});a.a.n(b,"click",e);a.s(g,null,{o:b})}}};a.h.V.checked=!0;a.d.checkedValue={update:function(b,d){b.value=a.a.c(d())}}})();a.d.css={update:function(b,d){var c=a.a.c(d());"object"==typeof c?a.a.G(c,function(c,d){d=a.a.c(d);a.a.Ba(b,c,d)}):(c=String(c||""),
65734a.a.Ba(b,b.__ko__cssValue,!1),b.__ko__cssValue=c,a.a.Ba(b,c,!0))}};a.d.enable={update:function(b,d){var c=a.a.c(d());c&&b.disabled?b.removeAttribute("disabled"):c||b.disabled||(b.disabled=!0)}};a.d.disable={update:function(b,d){a.d.enable.update(b,function(){return!a.a.c(d())})}};a.d.event={init:function(b,d,c,e,g){var h=d()||{};a.a.G(h,function(k){"string"==typeof k&&a.a.n(b,k,function(b){var h,l=d()[k];if(l){try{var q=a.a.S(arguments);e=g.$data;q.unshift(e);h=l.apply(e,q)}finally{!0!==h&&(b.preventDefault?
65735b.preventDefault():b.returnValue=!1)}!1===c.get(k+"Bubble")&&(b.cancelBubble=!0,b.stopPropagation&&b.stopPropagation())}})})}};a.d.foreach={Eb:function(b){return function(){var d=b(),c=a.a.Xa(d);if(!c||"number"==typeof c.length)return{foreach:d,templateEngine:a.O.Oa};a.a.c(d);return{foreach:c.data,as:c.as,includeDestroyed:c.includeDestroyed,afterAdd:c.afterAdd,beforeRemove:c.beforeRemove,afterRe
vendor: 13,701 bytes, lines 65735-65762
65735nder:c.afterRender,beforeMove:c.beforeMove,afterMove:c.afterMove,templateEngine:a.O.Oa}}},init:function(b,
65736d){return a.d.template.init(b,a.d.foreach.Eb(d))},update:function(b,d,c,e,g){return a.d.template.update(b,a.d.foreach.Eb(d),c,e,g)}};a.h.ha.foreach=!1;a.f.Q.foreach=!0;a.d.hasfocus={init:function(b,d,c){function e(e){b.__ko_hasfocusUpdating=!0;var f=b.ownerDocument;if("activeElement"in f){var g;try{g=f.activeElement}catch(h){g=f.body}e=g===b}f=d();a.h.pa(f,c,"hasfocus",e,!0);b.__ko_hasfocusLastValue=e;b.__ko_hasfocusUpdating=!1}var g=e.bind(null,!0),h=e.bind(null,!1);a.a.n(b,"focus",g);a.a.n(b,"focusin",
65737g);a.a.n(b,"blur",h);a.a.n(b,"focusout",h)},update:function(b,d){var c=!!a.a.c(d());b.__ko_hasfocusUpdating||b.__ko_hasfocusLastValue===c||(c?b.focus():b.blur(),a.k.B(a.a.oa,null,[b,c?"focusin":"focusout"]))}};a.h.V.hasfocus=!0;a.d.hasFocus=a.d.hasfocus;a.h.V.hasFocus=!0;a.d.html={init:function(){return{controlsDescendantBindings:!0}},update:function(b,d){a.a.$a(b,d())}};I("if");I("ifnot",!1,!0);I("with",!0,!1,function(a,d){return a.createChildContext(d)});var K={};a.d.options={init:function(b){if("select"!==
65738a.a.t(b))throw Error("options binding applies only to SELECT elements");for(;0<b.length;)b.remove(0);return{controlsDescendantBindings:!0}},update:function(b,d,c){function e(){return a.a.ta(b.options,function(a){return a.selected})}function g(a,b,c){var d=typeof b;return"function"==d?b(a):"string"==d?a[b]:c}function h(c,d){if(q.length){var e=0<=a.a.m(q,a.i.q(d[0]));a.a.Nb(d[0],e);n&&!e&&a.k.B(a.a.oa,null,[b,"change"])}}var k=0!=b.length&&b.multiple?b.scrollTop:null,f=a.a.c(d()),m=c.get("optionsIncludeDestroyed");
65739d={};var l,q;q=b.multiple?a.a.Da(e(),a.i.q):0<=b.selectedIndex?[a.i.q(b.options[b.selectedIndex])]:[];f&&("undefined"==typeof f.length&&(f=[f]),l=a.a.ta(f,function(b){return m||b===p||null===b||!a.a.c(b._destroy)}),c.has("optionsCaption")&&(f=a.a.c(c.get("optionsCaption")),null!==f&&f!==p&&l.unshift(K)));var n=!1;d.beforeRemove=function(a){b.removeChild(a)};f=h;c.has("optionsAfterRender")&&(f=function(b,d){h(0,d);a.k.B(c.get("optionsAfterRender"),null,[d[0],b!==K?b:p])});a.a.Za(b,l,function(d,e,f){f.length&&
65740(q=f[0].selected?[a.i.q(f[0])]:[],n=!0);e=b.ownerDocument.createElement("option");d===K?(a.a.bb(e,c.get("optionsCaption")),a.i.ca(e,p)):(f=g(d,c.get("optionsValue"),d),a.i.ca(e,a.a.c(f)),d=g(d,c.get("optionsText"),f),a.a.bb(e,d));return[e]},d,f);a.k.B(function(){c.get("valueAllowUnset")&&c.has("value")?a.i.ca(b,a.a.c(c.get("value")),!0):(b.multiple?q.length&&e().length<q.length:q.length&&0<=b.selectedIndex?a.i.q(b.options[b.selectedIndex])!==q[0]:q.length||0<=b.selectedIndex)&&a.a.oa(b,"change")});
65741a.a.dc(b);k&&20<Math.abs(k-b.scrollTop)&&(b.scrollTop=k)}};a.d.options.Va=a.a.e.F();a.d.selectedOptions={after:["options","foreach"],init:function(b,d,c){a.a.n(b,"change",function(){var e=d(),g=[];a.a.u(b.getElementsByTagName("option"),function(b){b.selected&&g.push(a.i.q(b))});a.h.pa(e,c,"selectedOptions",g)})},update:function(b,d){if("select"!=a.a.t(b))throw Error("values binding applies only to SELECT elements");var c=a.a.c(d());c&&"number"==typeof c.length&&a.a.u(b.getElementsByTagName("option"),
65742function(b){var d=0<=a.a.m(c,a.i.q(b));a.a.Nb(b,d)})}};a.h.V.selectedOptions=!0;a.d.style={update:function(b,d){var c=a.a.c(d()||{});a.a.G(c,function(c,d){d=a.a.c(d);if(null===d||d===p||!1===d)d="";b.style[c]=d})}};a.d.submit={init:function(b,d,c,e,g){if("function"!=typeof d())throw Error("The value for a submit binding must be a function");a.a.n(b,"submit",function(a){var c,e=d();try{c=e.call(g.$data,b)}finally{!0!==c&&(a.preventDefault?a.preventDefault():a.returnValue=!1)}})}};a.d.text={init:function(){return{controlsDescendantBindings:!0}},
65743update:function(b,d){a.a.bb(b,d())}};a.f.Q.text=!0;(function(){if(s&&s.navigator)var b=function(a){if(a)return parseFloat(a[1])},d=s.opera&&s.opera.version&&parseInt(s.opera.version()),c=s.navigator.userAgent,e=b(c.match(/^(?:(?!chrome).)*version\/([^ ]*) safari/i)),g=b(c.match(/Firefox\/([^ ]*)/));if(10>a.a.L)var h=a.a.e.F(),k=a.a.e.F(),f=function(b){var c=this.activeElement;(c=c&&a.a.e.get(c,k))&&c(b)},m=function(b,c){var d=b.ownerDocument;a.a.e.get(d,h)||(a.a.e.set(d,h,!0),a.a.n(d,"selectionchange",
65744f));a.a.e.set(b,k,c)};a.d.textInput={init:function(b,c,f){function k(c,d){a.a.n(b,c,d)}function h(){var d=a.a.c(c());if(null===d||d===p)d="";v!==p&&d===v?setTimeout(h,4):b.value!==d&&(s=d,b.value=d)}function u(){y||(v=b.value,y=setTimeout(r,4))}function r(){clearTimeout(y);v=y=p;var d=b.value;s!==d&&(s=d,a.h.pa(c(),f,"textInput",d))}var s=b.value,y,v;10>a.a.L?(k("propertychange",function(a){"value"===a.propertyName&&r()}),8==a.a.L&&(k("keyup",r),k("keydown",r)),8<=a.a.L&&(m(b,r),k("dragend",u))):
65745(k("input",r),5>e&&"textarea"===a.a.t(b)?(k("keydown",u),k("paste",u),k("cut",u)):11>d?k("keydown",u):4>g&&(k("DOMAutoComplete",r),k("dragdrop",r),k("drop",r)));k("change",r);a.s(h,null,{o:b})}};a.h.V.textInput=!0;a.d.textinput={preprocess:function(a,b,c){c("textInput",a)}}})();a.d.uniqueName={init:function(b,d){if(d()){var c="ko_unique_"+ ++a.d.uniqueName.Zb;a.a.Mb(b,c)}}};a.d.uniqueName.Zb=0;a.d.value={after:["options","foreach"],init:function(b,d,c){if("input"!=b.tagName.toLowerCase()||"checkbox"!=
65746b.type&&"radio"!=b.type){var e=["change"],g=c.get("valueUpdate"),h=!1,k=null;g&&("string"==typeof g&&(g=[g]),a.a.ga(e,g),e=a.a.rb(e));var f=function(){k=null;h=!1;var e=d(),f=a.i.q(b);a.h.pa(e,c,"value",f)};!a.a.L||"input"!=b.tagName.toLowerCase()||"text"!=b.type||"off"==b.autocomplete||b.form&&"off"==b.form.autocomplete||-1!=a.a.m(e,"propertychange")||(a.a.n(b,"propertychange",function(){h=!0}),a.a.n(b,"focus",function(){h=!1}),a.a.n(b,"blur",function(){h&&f()}));a.a.u(e,function(c){var d=f;a.a.vc(c,
65747"after")&&(d=function(){k=a.i.q(b);setTimeout(f,0)},c=c.substring(5));a.a.n(b,c,d)});var m=function(){var e=a.a.c(d()),f=a.i.q(b);if(null!==k&&e===k)setTimeout(m,0);else if(e!==f)if("select"===a.a.t(b)){var g=c.get("valueAllowUnset"),f=function(){a.i.ca(b,e,g)};f();g||e===a.i.q(b)?setTimeout(f,0):a.k.B(a.a.oa,null,[b,"change"])}else a.i.ca(b,e)};a.s(m,null,{o:b})}else a.ra(b,{checkedValue:d})},update:function(){}};a.h.V.value=!0;a.d.visible={update:function(b,d){var c=a.a.c(d()),e="none"!=b.style.display;
65748c&&!e?b.style.display="":!c&&e&&(b.style.display="none")}};(function(b){a.d[b]={init:function(d,c,e,g,h){return a.d.event.init.call(this,d,function(){var a={};a[b]=c();return a},e,g,h)}}})("click");a.H=function(){};a.H.prototype.renderTemplateSource=function(){throw Error("Override renderTemplateSource");};a.H.prototype.createJavaScriptEvaluatorBlock=function(){throw Error("Override createJavaScriptEvaluatorBlock");};a.H.prototype.makeTemplateSource=function(b,d){if("string"==typeof b){d=d||v;var c=
65749d.getElementById(b);if(!c)throw Error("Cannot find template with ID "+b);return new a.r.l(c)}if(1==b.nodeType||8==b.nodeType)return new a.r.fa(b);throw Error("Unknown template type: "+b);};a.H.prototype.renderTemplate=function(a,d,c,e){a=this.makeTemplateSource(a,e);return this.renderTemplateSource(a,d,c)};a.H.prototype.isTemplateRewritten=function(a,d){return!1===this.allowTemplateRewriting?!0:this.makeTemplateSource(a,d).data("isRewritten")};a.H.prototype.rewriteTemplate=function(a,d,c){a=this.makeTemplateSource(a,
65750c);d=d(a.text());a.text(d);a.data("isRewritten",!0)};a.b("templateEngine",a.H);a.fb=function(){function b(b,c,d,k){b=a.h.Wa(b);for(var f=a.h.ha,m=0;m<b.length;m++){var l=b[m].key;if(f.hasOwnProperty(l)){var q=f[l];if("function"===typeof q){if(l=q(b[m].value))throw Error(l);}else if(!q)throw Error("This template engine does not support the '"+l+"' binding within its templates");}}d="ko.__tr_ambtns(function($context,$element){return(function(){return{ "+a.h.ya(b,{valueAccessors:!0})+" } })()},'"+d.toLowerCase()+
65751"')";return k.createJavaScriptEvaluatorBlock(d)+c}var d=/(<([a-z]+\d*)(?:\s+(?!data-bind\s*=\s*)[a-z0-9\-]+(?:=(?:\"[^\"]*\"|\'[^\']*\'))?)*\s+)data-bind\s*=\s*(["'])([\s\S]*?)\3/gi,c=/\x3c!--\s*ko\b\s*([\s\S]*?)\s*--\x3e/g;return{ec:function(b,c,d){c.isTemplateRewritten(b,d)||c.rewriteTemplate(b,function(b){return a.fb.nc(b,c)},d)},nc:function(a,g){return a.replace(d,function(a,c,d,e,l){return b(l,c,d,g)}).replace(c,function(a,c){return b(c,"\x3c!-- ko --\x3e","#comment",g)})},Xb:function(b,c){return a.D.Ua(function(d,
65752k){var f=d.nextSibling;f&&f.nodeName.toLowerCase()===c&&a.ra(f,b,k)})}}}();a.b("__tr_ambtns",a.fb.Xb);(function(){a.r={};a.r.l=function(a){this.l=a};a.r.l.prototype.text=function(){var b=a.a.t(this.l),b="script"===b?"text":"textarea"===b?"value":"innerHTML";if(0==arguments.length)return this.l[b];var d=arguments[0];"innerHTML"===b?a.a.$a(this.l,d):this.l[b]=d};var b=a.a.e.F()+"_";a.r.l.prototype.data=function(c){if(1===arguments.length)return a.a.e.get(this.l,b+c);a.a.e.set(this.l,b+c,arguments[1])};
65753var d=a.a.e.F();a.r.fa=function(a){this.l=a};a.r.fa.prototype=new a.r.l;a.r.fa.prototype.text=function(){if(0==arguments.length){var b=a.a.e.get(this.l,d)||{};b.gb===p&&b.Ga&&(b.gb=b.Ga.innerHTML);return b.gb}a.a.e.set(this.l,d,{gb:arguments[0]})};a.r.l.prototype.nodes=function(){if(0==arguments.length)return(a.a.e.get(this.l,d)||{}).Ga;a.a.e.set(this.l,d,{Ga:arguments[0]})};a.b("templateSources",a.r);a.b("templateSources.domElement",a.r.l);a.b("templateSources.anonymousTemplate",a.r.fa)})();(function(){function b(b,
65754c,d){var e;for(c=a.f.nextSibling(c);b&&(e=b)!==c;)b=a.f.nextSibling(e),d(e,b)}function d(c,d){if(c.length){var e=c[0],g=c[c.length-1],h=e.parentNode,n=a.J.instance,t=n.preprocessNode;if(t){b(e,g,function(a,b){var c=a.previousSibling,d=t.call(n,a);d&&(a===e&&(e=d[0]||b),a===g&&(g=d[d.length-1]||c))});c.length=0;if(!e)return;e===g?c.push(e):(c.push(e,g),a.a.ka(c,h))}b(e,g,function(b){1!==b.nodeType&&8!==b.nodeType||a.pb(d,b)});b(e,g,function(b){1!==b.nodeType&&8!==b.nodeType||a.D.Sb(b,[d])});a.a.ka(c,
65755h)}}function c(a){return a.nodeType?a:0<a.length?a[0]:null}function e(b,e,h,l,q){q=q||{};var n=b&&c(b),n=n&&n.ownerDocument,t=q.templateEngine||g;a.fb.ec(h,t,n);h=t.renderTemplate(h,l,q,n);if("number"!=typeof h.length||0<h.length&&"number"!=typeof h[0].nodeType)throw Error("Template engine must return an array of DOM nodes");n=!1;switch(e){case "replaceChildren":a.f.T(b,h);n=!0;break;case "replaceNode":a.a.Lb(b,h);n=!0;break;case "ignoreTargetNode":break;default:throw Error("Unknown renderMode: "+
65756e);}n&&(d(h,l),q.afterRender&&a.k.B(q.afterRender,null,[h,l.$data]));return h}var g;a.ab=function(b){if(b!=p&&!(b instanceof a.H))throw Error("templateEngine must inherit from ko.templateEngine");g=b};a.Ya=function(b,d,h,l,q){h=h||{};if((h.templateEngine||g)==p)throw Error("Set a template engine before calling renderTemplate");q=q||"replaceChildren";if(l){var n=c(l);return a.j(function(){var g=d&&d instanceof a.N?d:new a.N(a.a.c(d)),p=a.C(b)?b():"function"===typeof b?b(g.$data,g):b,g=e(l,q,p,g,h);
65757"replaceNode"==q&&(l=g,n=c(l))},null,{Ia:function(){return!n||!a.a.Ja(n)},o:n&&"replaceNode"==q?n.parentNode:n})}return a.D.Ua(function(c){a.Ya(b,d,h,c,"replaceNode")})};a.uc=function(b,c,g,h,q){function n(a,b){d(b,s);g.afterRender&&g.afterRender(b,a)}function t(c,d){s=q.createChildContext(c,g.as,function(a){a.$index=d});var f=a.C(b)?b():"function"===typeof b?b(c,s):b;return e(null,"ignoreTargetNode",f,s,g)}var s;return a.j(function(){var b=a.a.c(c)||[];"undefined"==typeof b.length&&(b=[b]);b=a.a.ta(b,
65758function(b){return g.includeDestroyed||b===p||null===b||!a.a.c(b._destroy)});a.k.B(a.a.Za,null,[h,b,t,g,n])},null,{o:h})};var h=a.a.e.F();a.d.template={init:function(b,c){var d=a.a.c(c());"string"==typeof d||d.name?a.f.ja(b):(d=a.f.childNodes(b),d=a.a.oc(d),(new a.r.fa(b)).nodes(d));return{controlsDescendantBindings:!0}},update:function(b,c,d,e,g){var n=c(),t;c=a.a.c(n);d=!0;e=null;"string"==typeof c?c={}:(n=c.name,"if"in c&&(d=a.a.c(c["if"])),d&&"ifnot"in c&&(d=!a.a.c(c.ifnot)),t=a.a.c(c.data));
65759"foreach"in c?e=a.uc(n||b,d&&c.foreach||[],c,b,g):d?(g="data"in c?g.createChildContext(t,c.as):g,e=a.Ya(n||b,g,c,b)):a.f.ja(b);g=e;(t=a.a.e.get(b,h))&&"function"==typeof t.K&&t.K();a.a.e.set(b,h,g&&g.Z()?g:p)}};a.h.ha.template=function(b){b=a.h.Wa(b);return 1==b.length&&b[0].unknown||a.h.lc(b,"name")?null:"This template engine does not support anonymous templates nested within its templates"};a.f.Q.template=!0})();a.b("setTemplateEngine",a.ab);a.b("renderTemplate",a.Ya);a.a.wb=function(a,d,c){if(a.length&&
65760d.length){var e,g,h,k,f;for(e=g=0;(!c||e<c)&&(k=a[g]);++g){for(h=0;f=d[h];++h)if(k.value===f.value){k.moved=f.index;f.moved=k.index;d.splice(h,1);e=h=0;break}e+=h}}};a.a.Fa=function(){function b(b,c,e,g,h){var k=Math.min,f=Math.max,m=[],l,q=b.length,n,p=c.length,s=p-q||1,u=q+p+1,r,v,w;for(l=0;l<=q;l++)for(v=r,m.push(r=[]),w=k(p,l+s),n=f(0,l-1);n<=w;n++)r[n]=n?l?b[l-1]===c[n-1]?v[n-1]:k(v[n]||u,r[n-1]||u)+1:n+1:l+1;k=[];f=[];s=[];l=q;for(n=p;l||n;)p=m[l][n]-1,n&&p===m[l][n-1]?f.push(k[k.length]={status:e,
65761value:c[--n],index:n}):l&&p===m[l-1][n]?s.push(k[k.length]={status:g,value:b[--l],index:l}):(--n,--l,h.sparse||k.push({status:"retained",value:c[n]}));a.a.wb(f,s,10*q);return k.reverse()}return function(a,c,e){e="boolean"===typeof e?{dontLimitMoves:e}:e||{};a=a||[];c=c||[];return a.length<=c.length?b(a,c,"added","deleted",e):b(c,a,"deleted","added",e)}}();a.b("utils.compareArrays",a.a.Fa);(function(){function b(b,d,g,h,k){var f=[],m=a.j(function(){var l=d(g,k,a.a.ka(f,b))||[];0<f.length&&(a.a.Lb(f,
65762l),h&&a.k.B(h,null,[g,l,k]));f.length=0;a.a.ga(f,l)},null,{o:b,Ia:function(){return!a.a.ob(f)}});return{$:f,j:m.Z()?m:p}}var d=a.a.e.F();a.a.Za=function(c,e,g,h,k){function f(b,d){x=q[d];r!==d&&(A[b]=x);x.Na(r++);a.a.ka(x.$,c);s.push(x);w.push(x)}function m(b,c){if(b)for(var d=0,e=c.length;d<e;
vendor: 2,888 bytes, lines 65762-65785
65762d++)c[d]&&a.a.u(c[d].$,function(a){b(a,d,c[d].sa)})}e=e||[];h=h||{};var l=a.a.e.get(c,d)===p,q=a.a.e.get(c,d)||[],n=a.a.Da(q,function(a){return a.sa}),t=a.a.Fa(n,e,h.dontLimitMoves),s=[],u=0,r=0,v=[],w=[];e=
65763[];for(var A=[],n=[],x,B=0,D,F;D=t[B];B++)switch(F=D.moved,D.status){case "deleted":F===p&&(x=q[u],x.j&&x.j.K(),v.push.apply(v,a.a.ka(x.$,c)),h.beforeRemove&&(e[B]=x,w.push(x)));u++;break;case "retained":f(B,u++);break;case "added":F!==p?f(B,F):(x={sa:D.value,Na:a.p(r++)},s.push(x),w.push(x),l||(n[B]=x))}m(h.beforeMove,A);a.a.u(v,h.beforeRemove?a.R:a.removeNode);for(var B=0,l=a.f.firstChild(c),G;x=w[B];B++){x.$||a.a.extend(x,b(c,g,x.sa,k,x.Na));for(u=0;t=x.$[u];l=t.nextSibling,G=t,u++)t!==l&&a.f.Bb(c,
65764t,G);!x.ic&&k&&(k(x.sa,x.$,x.Na),x.ic=!0)}m(h.beforeRemove,e);m(h.afterMove,A);m(h.afterAdd,n);a.a.e.set(c,d,s)}})();a.b("utils.setDomNodeChildrenFromArrayMapping",a.a.Za);a.O=function(){this.allowTemplateRewriting=!1};a.O.prototype=new a.H;a.O.prototype.renderTemplateSource=function(b){var d=(9>a.a.L?0:b.nodes)?b.nodes():null;if(d)return a.a.S(d.cloneNode(!0).childNodes);b=b.text();return a.a.ba(b)};a.O.Oa=new a.O;a.ab(a.O.Oa);a.b("nativeTemplateEngine",a.O);(function(){a.Sa=function(){var a=this.kc=
65765function(){if(!w||!w.tmpl)return 0;try{if(0<=w.tmpl.tag.tmpl.open.toString().indexOf("__"))return 2}catch(a){}return 1}();this.renderTemplateSource=function(b,e,g){g=g||{};if(2>a)throw Error("Your version of jQuery.tmpl is too old. Please upgrade to jQuery.tmpl 1.0.0pre or later.");var h=b.data("precompiled");h||(h=b.text()||"",h=w.template(null,"{{ko_with $item.koBindingContext}}"+h+"{{/ko_with}}"),b.data("precompiled",h));b=[e.$data];e=w.extend({koBindingContext:e},g.templateOptions);e=w.tmpl(h,
65766b,e);e.appendTo(v.createElement("div"));w.fragments={};return e};this.createJavaScriptEvaluatorBlock=function(a){return"{{ko_code ((function() { return "+a+" })()) }}"};this.addTemplate=function(a,b){v.write("<script type='text/html' id='"+a+"'>"+b+"\x3c/script>")};0<a&&(w.tmpl.tag.ko_code={open:"__.push($1 || '');"},w.tmpl.tag.ko_with={open:"with($1) {",close:"} "})};a.Sa.prototype=new a.H;var b=new a.Sa;0<b.kc&&a.ab(b);a.b("jqueryTmplTemplateEngine",a.Sa)})()})})();})();
65767
65768/*!
65769 * Knockout Mapping plugin v2.6.0
65770 * (c) 2013 Steven Sanderson, Roy Jacobs - http://knockoutjs.com/
65771 * License: MIT (http://www.opensource.org/licenses/mit-license.php)
65772 */
65773(function(factory) {
65774    'use strict';
65775
65776    /*jshint sub:true,curly:false*/
65777    /*global ko,require,exports,define,module*/
65778
65779    if (typeof require === "function" && typeof exports === "object" && typeof module === "object") {
65780        // CommonJS or Node: hard-coded dependency on "knockout"
65781        factory(require("knockout"), exports);
65782    }
65783    else if (typeof define === "function" && define["amd"]) {
65784        // AMD anonymous module with hard-coded dependency on "knockout"
65785        define('komapping',
vendor: 34,206 bytes, lines 65785-66641
65785["knockout", "exports"], factory);
65786    }
65787    else {
65788        // <script> tag: use the global `ko` object, attaching a `mapping` property
65789        if (typeof ko === 'undefined') {
65790            throw new Error('Knockout is required, please ensure it is loaded before loading this mapping plug-in');
65791        }
65792        factory(ko, ko.mapping = {});
65793    }
65794}(function(ko, exports) {
65795    /*jshint sub:true,curly:false*/
65796    'use strict';
65797
65798    ko.mapping = exports;
65799
65800    var DEBUG=true;
65801    var mappingProperty = "__ko_mapping__";
65802    var realKoDependentObservable = ko.dependentObservable;
65803    var mappingNesting = 0;
65804    var dependentObservables;
65805    var visitedObjects;
65806    var recognizedRootProperties = ["create", "update", "key", "arrayChanged"];
65807    var emptyReturn = {};
65808
65809    var _defaultOptions = {
65810        include: ["_destroy"],
65811        ignore: [],
65812        copy: [],
65813        observe: []
65814    };
65815    var defaultOptions = _defaultOptions;
65816
65817    function unionArrays() {
65818        var args = arguments,
65819            l = args.length,
65820            obj = {},
65821            res = [],
65822            i, j, k;
65823
65824        while (l--) {
65825            k = args[l];
65826            i = k.length;
65827
65828            while (i--) {
65829                j = k[i];
65830                if (!obj[j]) {
65831                    obj[j] = 1;
65832                    res.push(j);
65833                }
65834            }
65835        }
65836
65837        return res;
65838    }
65839
65840    function extendObject(destination, source) {
65841        var destType;
65842
65843        for (var key in source) {
65844            if (source.hasOwnProperty(key) && source[key]) {
65845                destType = exports.getType(destination[key]);
65846                if (key && destination[key] && destType !== "array" && destType !== "string") {
65847                    extendObject(destination[key], source[key]);
65848                }
65849                else {
65850                    var bothArrays = exports.getType(destination[key]) === "array" && exports.getType(source[key]) === "array";
65851                    if (bothArrays) {
65852                        destination[key] = unionArrays(destination[key], source[key]);
65853                    }
65854                    else {
65855                        destination[key] = source[key];
65856                    }
65857                }
65858            }
65859        }
65860    }
65861
65862    function merge(obj1, obj2) {
65863        var merged = {};
65864        extendObject(merged, obj1);
65865        extendObject(merged, obj2);
65866
65867        return merged;
65868    }
65869
65870    exports.isMapped = function(viewModel) {
65871        var unwrapped = ko.utils.unwrapObservable(viewModel);
65872        return unwrapped && unwrapped[mappingProperty];
65873    };
65874
65875    exports.fromJS = function(jsObject /*, inputOptions, target*/) {
65876        if (arguments.length === 0) {
65877            throw new Error("When calling ko.fromJS, pass the object you want to convert.");
65878        }
65879        try {
65880            if (!mappingNesting) {
65881                dependentObservables = [];
65882                visitedObjects = new ObjectLookup();
65883            }
65884            mappingNesting++;
65885
65886            var options;
65887            var target;
65888
65889            if (arguments.length === 2) {
65890                if (arguments[1][mappingProperty]) {
65891                    target = arguments[1];
65892                }
65893                else {
65894                    options = arguments[1];
65895                }
65896            }
65897            if (arguments.length === 3) {
65898                options = arguments[1];
65899                target = arguments[2];
65900            }
65901
65902            if (target) {
65903                options = merge(options, target[mappingProperty]);
65904            }
65905            options = fillOptions(options);
65906
65907            var result = updateViewModel(target, jsObject, options);
65908            if (target) {
65909                result = target;
65910            }
65911
65912            // Evaluate any dependent observables that were proxied.
65913            // Do this after the model's observables have been created
65914            if (!--mappingNesting) {
65915                while (dependentObservables.length) {
65916                    var DO = dependentObservables.pop();
65917                    if (DO) {
65918                        DO();
65919                        // Move this magic property to the underlying dependent observable
65920                        DO.__DO["throttleEvaluation"] = DO["throttleEvaluation"];
65921                    }
65922                }
65923            }
65924
65925            // Save any new mapping options in the view model, so that updateFromJS can use them later.
65926            result[mappingProperty] = merge(result[mappingProperty], options);
65927
65928            return result;
65929        }
65930        catch (e) {
65931            mappingNesting = 0;
65932            throw e;
65933        }
65934    };
65935
65936    exports.fromJSON = function(jsonString /*, options, target*/) {
65937        var args = Array.prototype.slice.call(arguments, 0);
65938        args[0] = ko.utils.parseJson(jsonString);
65939        return exports.fromJS.apply(this, args);
65940    };
65941
65942    exports.toJS = function(rootObject, options) {
65943        if (!defaultOptions) exports.resetDefaultOptions();
65944
65945        if (arguments.length === 0) throw new Error("When calling ko.mapping.toJS, pass the object you want to convert.");
65946        if (exports.getType(defaultOptions.ignore) !== "array") throw new Error("ko.mapping.defaultOptions().ignore should be an array.");
65947        if (exports.getType(defaultOptions.include) !== "array") throw new Error("ko.mapping.defaultOptions().include should be an array.");
65948        if (exports.getType(defaultOptions.copy) !== "array") throw new Error("ko.mapping.defaultOptions().copy should be an array.");
65949
65950        // Merge in the options used in fromJS
65951        options = fillOptions(options, rootObject[mappingProperty]);
65952
65953        // We just unwrap everything at every level in the object graph
65954        return exports.visitModel(rootObject, function(x) {
65955            return ko.utils.unwrapObservable(x);
65956        }, options);
65957    };
65958
65959    exports.toJSON = function(rootObject, options, replacer, space) {
65960        var plainJavaScriptObject = exports.toJS(rootObject, options);
65961        return ko.utils.stringifyJson(plainJavaScriptObject, replacer, space);
65962    };
65963
65964    exports.defaultOptions = function() {
65965        if (arguments.length > 0) {
65966            defaultOptions = arguments[0];
65967        }
65968        else {
65969            return defaultOptions;
65970        }
65971    };
65972
65973    exports.resetDefaultOptions = function() {
65974        defaultOptions = {
65975            include: _defaultOptions.include.slice(0),
65976            ignore: _defaultOptions.ignore.slice(0),
65977            copy: _defaultOptions.copy.slice(0),
65978            observe: _defaultOptions.observe.slice(0)
65979        };
65980    };
65981
65982    exports.getType = function(x) {
65983        if ((x) && (typeof (x) === "object")) {
65984            if (x.constructor === Date) return "date";
65985            if (x.constructor === Array) return "array";
65986        }
65987        return typeof x;
65988    };
65989
65990    function fillOptions(rawOptions, otherOptions) {
65991        var options = merge({}, rawOptions);
65992
65993        // Move recognized root-level properties into a root namespace
65994        for (var i = recognizedRootProperties.length - 1; i >= 0; i--) {
65995            var property = recognizedRootProperties[i];
65996
65997            // Carry on, unless this property is present
65998            if (!options[property]) continue;
65999
66000            // Move the property into the root namespace
66001            if (!(options[""] instanceof Object)) options[""] = {};
66002            options[""][property] = options[property];
66003            delete options[property];
66004        }
66005
66006        if (otherOptions) {
66007            options.ignore = mergeArrays(otherOptions.ignore, options.ignore);
66008            options.include = mergeArrays(otherOptions.include, options.include);
66009            options.copy = mergeArrays(otherOptions.copy, options.copy);
66010            options.observe = mergeArrays(otherOptions.observe, options.observe);
66011        }
66012        options.ignore = mergeArrays(options.ignore, defaultOptions.ignore);
66013        options.include = mergeArrays(options.include, defaultOptions.include);
66014        options.copy = mergeArrays(options.copy, defaultOptions.copy);
66015        options.observe = mergeArrays(options.observe, defaultOptions.observe);
66016
66017        options.mappedProperties = options.mappedProperties || {};
66018        options.copiedProperties = options.copiedProperties || {};
66019        return options;
66020    }
66021
66022    function mergeArrays(a, b) {
66023        if (a === undefined) {
66024            a = [];
66025        }
66026        else if (exports.getType(a) !== "array") {
66027            a = [a];
66028        }
66029
66030        if (b === undefined) {
66031            b = [];
66032        }
66033        else if (exports.getType(b) !== "array") {
66034            b = [b];
66035        }
66036
66037        return ko.utils.arrayGetDistinctValues(a.concat(b));
66038    }
66039
66040    // When using a 'create' callback, we proxy the dependent observable so that it doesn't immediately evaluate on creation.
66041    // The reason is that the dependent observables in the user-specified callback may contain references to properties that have not been mapped yet.
66042    function withProxyDependentObservable(dependentObservables, callback) {
66043        var localDO = ko.dependentObservable;
66044        ko.dependentObservable = function(read, owner, options) {
66045            options = options || {};
66046
66047            if (read && typeof read === "object") { // mirrors condition in knockout implementation of DO's
66048                options = read;
66049            }
66050
66051            var realDeferEvaluation = options.deferEvaluation;
66052            var realIsPure = options.pure;
66053
66054            var isRemoved = false;
66055
66056            // We wrap the original dependent observable so that we can remove it from the 'dependentObservables' list we need to evaluate after mapping has
66057            // completed if the user already evaluated the DO themselves in the meantime.
66058            var wrap = function(DO) {
66059                // Temporarily revert ko.dependentObservable, since it is used in ko.isWriteableObservable
66060                var tmp = ko.dependentObservable;
66061                ko.dependentObservable = realKoDependentObservable;
66062                var isWriteable = ko.isWriteableObservable(DO);
66063                ko.dependentObservable = tmp;
66064
66065                var wrapped = realKoDependentObservable({
66066                    read: function() {
66067                        if (!isRemoved) {
66068                            ko.utils.arrayRemoveItem(dependentObservables, DO);
66069                            isRemoved = true;
66070                        }
66071                        return DO.apply(DO, arguments);
66072                    },
66073                    write: isWriteable && function(val) {
66074                        return DO(val);
66075                    },
66076                    deferEvaluation: true
66077                });
66078                if (DEBUG) wrapped._wrapper = true;
66079                wrapped.__DO = DO;
66080                return wrapped;
66081            };
66082
66083            options.deferEvaluation = true; // will either set for just options, or both read/options.
66084            var realDependentObservable = realKoDependentObservable(read, owner, options);
66085
66086            if (!realDeferEvaluation && !realIsPure) {
66087                realDependentObservable = wrap(realDependentObservable);
66088                dependentObservables.push(realDependentObservable);
66089            }
66090
66091            return realDependentObservable;
66092        };
66093        ko.dependentObservable.fn = realKoDependentObservable.fn;
66094        ko.computed = ko.dependentObservable;
66095        var result = callback();
66096        ko.dependentObservable = localDO;
66097        ko.computed = ko.dependentObservable;
66098        return result;
66099    }
66100
66101    function updateViewModel(mappedRootObject, rootObject, options, parentName, parent, parentPropertyName, mappedParent) {
66102        var isArray = exports.getType(ko.utils.unwrapObservable(rootObject)) === "array";
66103
66104        parentPropertyName = parentPropertyName || "";
66105
66106        // If this object was already mapped previously, take the options from there and merge them with our existing ones.
66107        if (exports.isMapped(mappedRootObject)) {
66108            var previousMapping = ko.utils.unwrapObservable(mappedRootObject)[mappingProperty];
66109            options = merge(previousMapping, options);
66110        }
66111
66112        var callbackParams = {
66113            data: rootObject,
66114            parent: mappedParent || parent
66115        };
66116
66117        var hasCreateCallback = function() {
66118            return options[parentName] && options[parentName].create instanceof Function;
66119        };
66120
66121        var createCallback = function(data) {
66122            return withProxyDependentObservable(dependentObservables, function() {
66123
66124                if (ko.utils.unwrapObservable(parent) instanceof Array) {
66125                    return options[parentName].create({
66126                        data: data || callbackParams.data,
66127                        parent: callbackParams.parent,
66128                        skip: emptyReturn
66129                    });
66130                }
66131                else {
66132                    return options[parentName].create({
66133                        data: data || callbackParams.data,
66134                        parent: callbackParams.parent
66135                    });
66136                }
66137            });
66138        };
66139
66140        var hasUpdateCallback = function() {
66141            return options[parentName] && options[parentName].update instanceof Function;
66142        };
66143
66144        var updateCallback = function(obj, data) {
66145            var params = {
66146                data: data || callbackParams.data,
66147                parent: callbackParams.parent,
66148                target: ko.utils.unwrapObservable(obj)
66149            };
66150
66151            if (ko.isWriteableObservable(obj)) {
66152                params.observable = obj;
66153            }
66154
66155            return options[parentName].update(params);
66156        };
66157
66158        var alreadyMapped = visitedObjects.get(rootObject);
66159        if (alreadyMapped) {
66160            return alreadyMapped;
66161        }
66162
66163        parentName = parentName || "";
66164
66165        if (!isArray) {
66166            // For atomic types, do a direct update on the observable
66167            if (!canHaveProperties(rootObject)) {
66168                switch (exports.getType(rootObject)) {
66169                    case "function":
66170                        if (hasUpdateCallback()) {
66171                            if (ko.isWriteableObservable(rootObject)) {
66172                                rootObject(updateCallback(rootObject));
66173                                mappedRootObject = rootObject;
66174                            }
66175                            else {
66176                                mappedRootObject = updateCallback(rootObject);
66177                            }
66178                        }
66179                        else {
66180                            mappedRootObject = rootObject;
66181                        }
66182                        break;
66183                    default:
66184                        if (ko.isWriteableObservable(mappedRootObject)) {
66185                            var valueToWrite;
66186                            if (hasUpdateCallback()) {
66187                                valueToWrite = updateCallback(mappedRootObject);
66188                                mappedRootObject(valueToWrite);
66189                                return valueToWrite;
66190                            }
66191                            else {
66192                                valueToWrite = ko.utils.unwrapObservable(rootObject);
66193                                mappedRootObject(valueToWrite);
66194                                return valueToWrite;
66195                            }
66196                        }
66197                        else {
66198                            var hasCreateOrUpdateCallback = hasCreateCallback() || hasUpdateCallback();
66199
66200                            if (hasCreateCallback()) {
66201                                mappedRootObject = createCallback();
66202                            }
66203                            else {
66204                                mappedRootObject = ko.observable(ko.utils.unwrapObservable(rootObject));
66205                            }
66206
66207                            if (hasUpdateCallback()) {
66208                                mappedRootObject(updateCallback(mappedRootObject));
66209                            }
66210
66211                            if (hasCreateOrUpdateCallback) return mappedRootObject;
66212                        }
66213                }
66214
66215            }
66216            else {
66217                mappedRootObject = ko.utils.unwrapObservable(mappedRootObject);
66218                if (!mappedRootObject) {
66219                    if (hasCreateCallback()) {
66220                        var result = createCallback();
66221
66222                        if (hasUpdateCallback()) {
66223                            result = updateCallback(result);
66224                        }
66225                        return result;
66226                    }
66227                    else {
66228                        if (hasUpdateCallback()) {
66229                            //Removed ambiguous parameter result
66230                            return updateCallback();
66231                        }
66232                        mappedRootObject = {};
66233                    }
66234                }
66235
66236                if (hasUpdateCallback()) {
66237                    mappedRootObject = updateCallback(mappedRootObject);
66238                }
66239
66240                visitedObjects.save(rootObject, mappedRootObject);
66241                if (hasUpdateCallback()) return mappedRootObject;
66242
66243                // For non-atomic types, visit all properties and update recursively
66244                visitPropertiesOrArrayEntries(rootObject, function(indexer) {
66245                    var fullPropertyName = parentPropertyName.length ? parentPropertyName + "." + escapePropertyNameComponent(indexer) : escapePropertyNameComponent(indexer);
66246
66247                    if (ko.utils.arrayIndexOf(options.ignore, fullPropertyName) !== -1) {
66248                        return;
66249                    }
66250
66251                    if (ko.utils.arrayIndexOf(options.copy, fullPropertyName) !== -1) {
66252                        mappedRootObject[indexer] = rootObject[indexer];
66253                        return;
66254                    }
66255
66256                    if (typeof rootObject[indexer] !== "object" && exports.getType(rootObject[indexer]) !== "array" && options.observe.length > 0 && ko.utils.arrayIndexOf(options.observe, fullPropertyName) === -1) {
66257                        mappedRootObject[indexer] = rootObject[indexer];
66258                        options.copiedProperties[fullPropertyName] = true;
66259                        return;
66260                    }
66261
66262                    // In case we are adding an already mapped property, fill it with the previously mapped property value to prevent recursion.
66263                    // If this is a property that was generated by fromJS, we should use the options specified there
66264                    var prevMappedProperty = visitedObjects.get(rootObject[indexer]);
66265                    var retval = updateViewModel(mappedRootObject[indexer], rootObject[indexer], options, indexer, mappedRootObject, fullPropertyName, mappedRootObject);
66266                    var value = prevMappedProperty || retval;
66267
66268                    if (options.observe.length > 0 && ko.utils.arrayIndexOf(options.observe, fullPropertyName) === -1) {
66269                        mappedRootObject[indexer] = ko.utils.unwrapObservable(value);
66270                        options.copiedProperties[fullPropertyName] = true;
66271                        return;
66272                    }
66273
66274                    if (ko.isWriteableObservable(mappedRootObject[indexer])) {
66275                        value = ko.utils.unwrapObservable(value);
66276                        if (mappedRootObject[indexer]() !== value) {
66277                            mappedRootObject[indexer](value);
66278                        }
66279                    }
66280                    else {
66281                        value = mappedRootObject[indexer] === undefined ? value : ko.utils.unwrapObservable(value);
66282                        mappedRootObject[indexer] = value;
66283                    }
66284
66285                    options.mappedProperties[fullPropertyName] = true;
66286                });
66287            }
66288        }
66289        else { //mappedRootObject is an array
66290            var changes = [];
66291
66292            var hasKeyCallback = false;
66293            var keyCallback = function(x) {
66294                return x;
66295            };
66296            if (options[parentName] && options[parentName].key) {
66297                keyCallback = options[parentName].key;
66298                hasKeyCallback = true;
66299            }
66300
66301            if (!ko.isObservable(mappedRootObject)) {
66302                // When creating the new observable array, also add a bunch of utility functions that take the 'key' of the array items into account.
66303                mappedRootObject = ko.observableArray([]);
66304
66305                mappedRootObject.mappedRemove = function(valueOrPredicate) {
66306                    var predicate = typeof valueOrPredicate === "function" ? valueOrPredicate : function(value) {
66307                        return value === keyCallback(valueOrPredicate);
66308                    };
66309                    return mappedRootObject.remove(function(item) {
66310                        return predicate(keyCallback(item));
66311                    });
66312                };
66313
66314                mappedRootObject.mappedRemoveAll = function(arrayOfValues) {
66315                    var arrayOfKeys = filterArrayByKey(arrayOfValues, keyCallback);
66316                    return mappedRootObject.remove(function(item) {
66317                        return ko.utils.arrayIndexOf(arrayOfKeys, keyCallback(item)) !== -1;
66318                    });
66319                };
66320
66321                mappedRootObject.mappedDestroy = function(valueOrPredicate) {
66322                    var predicate = typeof valueOrPredicate === "function" ? valueOrPredicate : function(value) {
66323                        return value === keyCallback(valueOrPredicate);
66324                    };
66325                    return mappedRootObject.destroy(function(item) {
66326                        return predicate(keyCallback(item));
66327                    });
66328                };
66329
66330                mappedRootObject.mappedDestroyAll = function(arrayOfValues) {
66331                    var arrayOfKeys = filterArrayByKey(arrayOfValues, keyCallback);
66332                    return mappedRootObject.destroy(function(item) {
66333                        return ko.utils.arrayIndexOf(arrayOfKeys, keyCallback(item)) !== -1;
66334                    });
66335                };
66336
66337                mappedRootObject.mappedIndexOf = function(item) {
66338                    var keys = filterArrayByKey(mappedRootObject(), keyCallback);
66339                    var key = keyCallback(item);
66340                    return ko.utils.arrayIndexOf(keys, key);
66341                };
66342
66343                mappedRootObject.mappedGet = function(item) {
66344                    return mappedRootObject()[mappedRootObject.mappedIndexOf(item)];
66345                };
66346
66347                mappedRootObject.mappedCreate = function(value) {
66348                    if (mappedRootObject.mappedIndexOf(value) !== -1) {
66349                        throw new Error("There already is an object with the key that you specified.");
66350                    }
66351                    var item = hasCreateCallback() ? createCallback(value) : value;
66352                    if (hasUpdateCallback()) {
66353                        var newValue = updateCallback(item, value);
66354                        if (ko.isWriteableObservable(item)) {
66355                            item(newValue);
66356                        }
66357                        else {
66358                            item = newValue;
66359                        }
66360                    }
66361                    mappedRootObject.push(item);
66362                    return item;
66363                };
66364            }
66365
66366            var currentArrayKeys = filterArrayByKey(ko.utils.unwrapObservable(mappedRootObject), keyCallback).sort();
66367            var newArrayKeys = filterArrayByKey(rootObject, keyCallback);
66368            if (hasKeyCallback) newArrayKeys.sort();
66369            var editScript = ko.utils.compareArrays(currentArrayKeys, newArrayKeys);
66370
66371            var ignoreIndexOf = {};
66372
66373            var i, j, key;
66374
66375            var unwrappedRootObject = ko.utils.unwrapObservable(rootObject);
66376            var itemsByKey = {};
66377            var optimizedKeys = true;
66378            for (i = 0, j = unwrappedRootObject.length; i < j; i++) {
66379                key = keyCallback(unwrappedRootObject[i]);
66380                if (key === undefined || key instanceof Object) {
66381                    optimizedKeys = false;
66382                    break;
66383                }
66384                itemsByKey[key] = unwrappedRootObject[i];
66385            }
66386
66387            var newContents = [];
66388            var passedOver = 0;
66389            var item, index;
66390
66391            for (i = 0, j = editScript.length; i < j; i++) {
66392                key = editScript[i];
66393                var mappedItem;
66394                var fullPropertyName = parentPropertyName + "[" + escapePropertyNameComponent(i) + "]";
66395
66396                switch (key.status) {
66397                    case "added":
66398                        item = optimizedKeys ? itemsByKey[key.value] : getItemByKey(ko.utils.unwrapObservable(rootObject), key.value, keyCallback);
66399                        mappedItem = updateViewModel(undefined, item, options, parentName, mappedRootObject, fullPropertyName, parent);
66400                        if (!hasCreateCallback()) {
66401                            mappedItem = ko.utils.unwrapObservable(mappedItem);
66402                        }
66403
66404                        index = ignorableIndexOf(ko.utils.unwrapObservable(rootObject), item, ignoreIndexOf);
66405
66406                        if (mappedItem === emptyReturn) {
66407                            passedOver++;
66408                        }
66409                        else {
66410                            newContents[index - passedOver] = mappedItem;
66411                        }
66412
66413                        ignoreIndexOf[index] = true;
66414                        break;
66415                    case "retained":
66416                        item = optimizedKeys ? itemsByKey[key.value] : getItemByKey(ko.utils.unwrapObservable(rootObject), key.value, keyCallback);
66417                        mappedItem = getItemByKey(mappedRootObject, key.value, keyCallback);
66418                        updateViewModel(mappedItem, item, options, parentName, mappedRootObject, fullPropertyName, parent);
66419
66420                        index = ignorableIndexOf(ko.utils.unwrapObservable(rootObject), item, ignoreIndexOf);
66421                        newContents[index] = mappedItem;
66422                        ignoreIndexOf[index] = true;
66423                        break;
66424                    case "deleted":
66425                        mappedItem = getItemByKey(mappedRootObject, key.value, keyCallback);
66426                        break;
66427                }
66428
66429                changes.push({
66430                    event: key.status,
66431                    item: mappedItem
66432                });
66433            }
66434
66435            mappedRootObject(newContents);
66436
66437            if (options[parentName] && options[parentName].arrayChanged) {
66438                ko.utils.arrayForEach(changes, function(change) {
66439                    options[parentName].arrayChanged(change.event, change.item);
66440                });
66441            }
66442        }
66443
66444        return mappedRootObject;
66445    }
66446
66447    function ignorableIndexOf(array, item, ignoreIndices) {
66448        for (var i = 0, j = array.length; i < j; i++) {
66449            if (ignoreIndices[i] === true) continue;
66450            if (array[i] === item) return i;
66451        }
66452        return null;
66453    }
66454
66455    function mapKey(item, callback) {
66456        var mappedItem;
66457        if (callback) mappedItem = callback(item);
66458        if (exports.getType(mappedItem) === "undefined") mappedItem = item;
66459
66460        return ko.utils.unwrapObservable(mappedItem);
66461    }
66462
66463    function getItemByKey(array, key, callback) {
66464        array = ko.utils.unwrapObservable(array);
66465        for (var i = 0, j = array.length; i < j; i++) {
66466            var item = array[i];
66467            if (mapKey(item, callback) === key) return item;
66468        }
66469
66470        throw new Error("When calling ko.update*, the key '" + key + "' was not found!");
66471    }
66472
66473    function filterArrayByKey(array, callback) {
66474        return ko.utils.arrayMap(ko.utils.unwrapObservable(array), function(item) {
66475            if (callback) {
66476                return mapKey(item, callback);
66477            }
66478            else {
66479                return item;
66480            }
66481        });
66482    }
66483
66484    function visitPropertiesOrArrayEntries(rootObject, visitorCallback) {
66485        if (exports.getType(rootObject) === "array") {
66486            for (var i = 0; i < rootObject.length; i++)
66487                visitorCallback(i);
66488        }
66489        else {
66490            for (var propertyName in rootObject) {
66491                if (rootObject.hasOwnProperty(propertyName)) {
66492                    visitorCallback(propertyName);
66493                }
66494            }
66495        }
66496    }
66497
66498    function canHaveProperties(object) {
66499        if (object === null) {
66500            return false;
66501        }
66502        var type = exports.getType(object);
66503        return (type === "object") || (type === "array");
66504    }
66505
66506    // Based on the parentName, this creates a fully classified name of a property
66507
66508    function getPropertyName(parentName, parent, indexer) {
66509        var propertyName = parentName || "";
66510        if (exports.getType(parent) === "array") {
66511            if (parentName) {
66512                propertyName += "[" + escapePropertyNameComponent(indexer) + "]";
66513            }
66514        }
66515        else {
66516            if (parentName) {
66517                propertyName += ".";
66518            }
66519            propertyName += escapePropertyNameComponent(indexer);
66520        }
66521        return propertyName;
66522    }
66523
66524    function escapePropertyNameComponent(indexer) {
66525        var escapedIndexer  = (''+indexer)
66526            .replace(/~/g, '~~')
66527            .replace(/\[/g, '~[')
66528            .replace(/]/g, '~]')
66529            .replace(/\./g, '~.');
66530        return escapedIndexer;
66531    }
66532
66533
66534    exports.visitModel = function(rootObject, callback, options) {
66535        options = options || {};
66536        options.visitedObjects = options.visitedObjects || new ObjectLookup();
66537
66538        var mappedRootObject;
66539        var unwrappedRootObject = ko.utils.unwrapObservable(rootObject);
66540
66541        if (!canHaveProperties(unwrappedRootObject)) {
66542            return callback(rootObject, options.parentName);
66543        }
66544        else {
66545            options = fillOptions(options, unwrappedRootObject[mappingProperty]);
66546
66547            // Only do a callback, but ignore the results
66548            callback(rootObject, options.parentName);
66549            mappedRootObject = exports.getType(unwrappedRootObject) === "array" ? [] : {};
66550        }
66551
66552        options.visitedObjects.save(rootObject, mappedRootObject);
66553
66554        var parentName = options.parentName;
66555        visitPropertiesOrArrayEntries(unwrappedRootObject, function(indexer) {
66556            var escapedIndexer = escapePropertyNameComponent(indexer);
66557            if (options.ignore && ko.utils.arrayIndexOf(options.ignore, escapedIndexer) !== -1) return;
66558
66559            var propertyValue = unwrappedRootObject[indexer];
66560            options.parentName = getPropertyName(parentName, unwrappedRootObject, indexer);
66561
66562            // If we don't want to explicitly copy the unmapped property...
66563            if (ko.utils.arrayIndexOf(options.copy, escapedIndexer) === -1) {
66564                // ...find out if it's a property we want to explicitly include
66565                if (ko.utils.arrayIndexOf(options.include, escapedIndexer) === -1) {
66566                    // The mapped properties object contains all the properties that were part of the original object.
66567                    // If a property does not exist, and it is not because it is part of an array (e.g. "myProp[3]"), then it should not be unmapped.
66568                    var unwrappedRootMappingProperty = unwrappedRootObject[mappingProperty];
66569                    if (unwrappedRootMappingProperty) {
66570                        var mappedProperties = unwrappedRootMappingProperty.mappedProperties;
66571                        if (mappedProperties && !mappedProperties[escapedIndexer]) {
66572                            var copiedProperties = unwrappedRootMappingProperty.copiedProperties;
66573                            if (copiedProperties && !copiedProperties[escapedIndexer] && (exports.getType(unwrappedRootObject) !== "array")) {
66574                                return;
66575                            }
66576                        }
66577                    }
66578                }
66579            }
66580
66581            switch (exports.getType(ko.utils.unwrapObservable(propertyValue))) {
66582                case "object":
66583                case "array":
66584                case "undefined":
66585                    var previouslyMappedValue = options.visitedObjects.get(propertyValue);
66586                    mappedRootObject[indexer] = (exports.getType(previouslyMappedValue) !== "undefined") ? previouslyMappedValue : exports.visitModel(propertyValue, callback, options);
66587                    break;
66588                default:
66589                    mappedRootObject[indexer] = callback(propertyValue, options.parentName);
66590            }
66591        });
66592
66593        return mappedRootObject;
66594    };
66595
66596    function SimpleObjectLookup() {
66597        var keys = [];
66598        var values = [];
66599        this.save = function(key, value) {
66600            var existingIndex = ko.utils.arrayIndexOf(keys, key);
66601            if (existingIndex >= 0) values[existingIndex] = value;
66602            else {
66603                keys.push(key);
66604                values.push(value);
66605            }
66606        };
66607        this.get = function(key) {
66608            var existingIndex = ko.utils.arrayIndexOf(keys, key);
66609            var value = (existingIndex >= 0) ? values[existingIndex] : undefined;
66610            return value;
66611        };
66612    }
66613
66614    function ObjectLookup() {
66615        var buckets = {};
66616
66617        var findBucket = function(key) {
66618            var bucketKey;
66619            try {
66620                bucketKey = key;//JSON.stringify(key);
66621            }
66622            catch (e) {
66623                bucketKey = "$$$";
66624            }
66625
66626            var bucket = buckets[bucketKey];
66627            if (!buckets.hasOwnProperty(bucketKey)) {
66628                bucket = new SimpleObjectLookup();
66629                buckets[bucketKey] = bucket;
66630            }
66631            return bucket;
66632        };
66633
66634        this.save = function(key, value) {
66635            findBucket(key).save(key, value);
66636        };
66637        this.get = function(key) {
66638            return findBucket(key).get(key);
66639        };
66640    }
66641}));
66642
66643/*=============================================================================
66644	Author:			Eric M. Barnard - @ericmbarnard								
66645	License:		MIT (http://opensource.org/licenses/mit-license.php)		
66646																				
66647	Description:	Validation Library for KnockoutJS							
66648	Version:		2.0.0-pre.3											
66649===============================================================================
66650*/
66651/*globals require: false, exports: false, define: false, ko: false */
66652
66653(function (factory) {
66654    // Module systems magic dance.
66655
66656    if (typeof require === "function" && typeof exports === "object" && typeof module === "object") {
66657        // CommonJS or Node: hard-coded dependency on "knockout"
vendor: 15,685 bytes, lines 66658-67162
66658        factory(require("knockout"), exports);
66659    } else if (typeof define === "function" && define["amd"]) {
66660        // AMD anonymous module with hard-coded dependency on "knockout"
66661        define('knockoutValidation',["knockout", "exports"], factory);
66662    } else {
66663        // <script> tag: use the global `ko` object, attaching a `mapping` property
66664        factory(ko, ko.validation = {});
66665    }
66666}(function ( ko, exports ) {
66667
66668    if (typeof (ko) === 'undefined') { throw 'Knockout is required, please ensure it is loaded before loading this validation plug-in'; }
66669
66670    // create our namespace object
66671    ko.validation = exports;
66672
66673    var kv = ko.validation,
66674		koUtils = ko.utils,
66675		unwrap = koUtils.unwrapObservable,
66676		forEach = koUtils.arrayForEach,
66677		extend = koUtils.extend;
66678;/*global ko: false*/
66679
66680var defaults = {
66681	registerExtenders: true,
66682	messagesOnModified: true,
66683	errorsAsTitle: true,            // enables/disables showing of errors as title attribute of the target element.
66684	errorsAsTitleOnModified: false, // shows the error when hovering the input field (decorateElement must be true)
66685	messageTemplate: null,
66686	insertMessages: true,           // automatically inserts validation messages as <span></span>
66687	parseInputAttributes: false,    // parses the HTML5 validation attribute from a form element and adds that to the object
66688	writeInputAttributes: false,    // adds HTML5 input validation attributes to form elements that ko observable's are bound to
66689	decorateInputElement: false,         // false to keep backward compatibility
66690	decorateElementOnModified: true,// true to keep backward compatibility
66691	errorClass: null,               // single class for error message and element
66692	errorElementClass: 'validationElement',  // class to decorate error element
66693	errorMessageClass: 'validationMessage',  // class to decorate error message
66694	allowHtmlMessages: false,		// allows HTML in validation messages
66695	grouping: {
66696		deep: false,        //by default grouping is shallow
66697		observable: true,   //and using observables
66698		live: false		    //react to changes to observableArrays if observable === true
66699	},
66700	validate: {
66701		// throttle: 10
66702	}
66703};
66704
66705// make a copy  so we can use 'reset' later
66706var configuration = extend({}, defaults);
66707
66708configuration.html5Attributes = ['required', 'pattern', 'min', 'max', 'step'];
66709configuration.html5InputTypes = ['email', 'number', 'date'];
66710
66711configuration.reset = function () {
66712	extend(configuration, defaults);
66713};
66714
66715kv.configuration = configuration;
66716;kv.utils = (function () {
66717	var seedId = new Date().getTime();
66718
66719	var domData = {}; //hash of data objects that we reference from dom elements
66720	var domDataKey = '__ko_validation__';
66721
66722	return {
66723		isArray: function (o) {
66724			return o.isArray || Object.prototype.toString.call(o) === '[object Array]';
66725		},
66726		isObject: function (o) {
66727			return o !== null && typeof o === 'object';
66728		},
66729		isNumber: function(o) {
66730			return !isNaN(o);	
66731		},
66732		isObservableArray: function(instance) {
66733			return !!instance &&
66734					typeof instance["remove"] === "function" &&
66735					typeof instance["removeAll"] === "function" &&
66736					typeof instance["destroy"] === "function" &&
66737					typeof instance["destroyAll"] === "function" &&
66738					typeof instance["indexOf"] === "function" &&
66739					typeof instance["replace"] === "function";
66740		},
66741		values: function (o) {
66742			var r = [];
66743			for (var i in o) {
66744				if (o.hasOwnProperty(i)) {
66745					r.push(o[i]);
66746				}
66747			}
66748			return r;
66749		},
66750		getValue: function (o) {
66751			return (typeof o === 'function' ? o() : o);
66752		},
66753		hasAttribute: function (node, attr) {
66754			return node.getAttribute(attr) !== null;
66755		},
66756		getAttribute: function (element, attr) {
66757			return element.getAttribute(attr);
66758		},
66759		setAttribute: function (element, attr, value) {
66760			return element.setAttribute(attr, value);
66761		},
66762		isValidatable: function (o) {
66763			return !!(o && o.rules && o.isValid && o.isModified);
66764		},
66765		insertAfter: function (node, newNode) {
66766			node.parentNode.insertBefore(newNode, node.nextSibling);
66767		},
66768		newId: function () {
66769			return seedId += 1;
66770		},
66771		getConfigOptions: function (element) {
66772			var options = kv.utils.contextFor(element);
66773
66774			return options || kv.configuration;
66775		},
66776		setDomData: function (node, data) {
66777			var key = node[domDataKey];
66778
66779			if (!key) {
66780				node[domDataKey] = key = kv.utils.newId();
66781			}
66782
66783			domData[key] = data;
66784		},
66785		getDomData: function (node) {
66786			var key = node[domDataKey];
66787
66788			if (!key) {
66789				return undefined;
66790			}
66791
66792			return domData[key];
66793		},
66794		contextFor: function (node) {
66795			switch (node.nodeType) {
66796				case 1:
66797				case 8:
66798					var context = kv.utils.getDomData(node);
66799					if (context) { return context; }
66800					if (node.parentNode) { return kv.utils.contextFor(node.parentNode); }
66801					break;
66802			}
66803			return undefined;
66804		},
66805		isEmptyVal: function (val) {
66806			if (val === undefined) {
66807				return true;
66808			}
66809			if (val === null) {
66810				return true;
66811			}
66812			if (val === "") {
66813				return true;
66814			}
66815		},
66816		getOriginalElementTitle: function (element) {
66817			var savedOriginalTitle = kv.utils.getAttribute(element, 'data-orig-title'),
66818				currentTitle = element.title,
66819				hasSavedOriginalTitle = kv.utils.hasAttribute(element, 'data-orig-title');
66820
66821			return hasSavedOriginalTitle ?
66822				savedOriginalTitle : currentTitle;
66823		},
66824		async: function (expr) {
66825			if (window.setImmediate) { window.setImmediate(expr); }
66826			else { window.setTimeout(expr, 0); }
66827		},
66828		forEach: function (object, callback) {
66829			if (kv.utils.isArray(object)) {
66830				return forEach(object, callback);
66831			}
66832			for (var prop in object) {
66833				if (object.hasOwnProperty(prop)) {
66834					callback(object[prop], prop);
66835				}
66836			}
66837		}
66838	};
66839}());;var api = (function () {
66840
66841	var isInitialized = 0,
66842		configuration = kv.configuration,
66843		utils = kv.utils;
66844
66845	function cleanUpSubscriptions(context) {
66846		forEach(context.subscriptions, function (subscription) {
66847			subscription.dispose();
66848		});
66849		context.subscriptions = [];
66850	}
66851
66852	function dispose(context) {
66853		if (context.options.deep) {
66854			forEach(context.flagged, function (obj) {
66855				delete obj.__kv_traversed;
66856			});
66857			context.flagged.length = 0;
66858		}
66859
66860		if (!context.options.live) {
66861			cleanUpSubscriptions(context);
66862		}
66863	}
66864
66865	function runTraversal(obj, context) {
66866		context.validatables = [];
66867		cleanUpSubscriptions(context);
66868		traverseGraph(obj, context);
66869		dispose(context);
66870	}
66871
66872	function traverseGraph(obj, context, level) {
66873		var objValues = [],
66874			val = obj.peek ? obj.peek() : obj;
66875
66876		if (obj.__kv_traversed === true) {
66877			return;
66878		}
66879
66880		if (context.options.deep) {
66881			obj.__kv_traversed = true;
66882			context.flagged.push(obj);
66883		}
66884
66885		//default level value depends on deep option.
66886		level = (level !== undefined ? level : context.options.deep ? 1 : -1);
66887
66888		// if object is observable then add it to the list
66889		if (ko.isObservable(obj)) {
66890			// ensure it's validatable but don't extend validatedObservable because it
66891			// would overwrite isValid property.
66892			if (!obj.errors && !utils.isValidatable(obj)) {
66893				obj.extend({ validatable: true });
66894			}
66895			context.validatables.push(obj);
66896
66897			if (context.options.live && utils.isObservableArray(obj)) {
66898				context.subscriptions.push(obj.subscribe(function () {
66899					context.graphMonitor.valueHasMutated();
66900				}));
66901			}
66902		}
66903
66904		//get list of values either from array or object but ignore non-objects
66905		// and destroyed objects
66906		if (val && !val._destroy) {
66907			if (utils.isArray(val)) {
66908				objValues = val;
66909			}
66910			else if (utils.isObject(val)) {
66911				objValues = utils.values(val);
66912			}
66913		}
66914
66915		//process recursively if it is deep grouping
66916		if (level !== 0) {
66917			utils.forEach(objValues, function (observable) {
66918				//but not falsy things and not HTML Elements
66919				if (observable && !observable.nodeType && (!ko.isComputed(observable) || observable.rules)) {
66920					traverseGraph(observable, context, level + 1);
66921				}
66922			});
66923		}
66924	}
66925
66926	function collectErrors(array) {
66927		var errors = [];
66928		forEach(array, function (observable) {
66929			// Do not collect validatedObservable errors
66930			if (utils.isValidatable(observable) && !observable.isValid()) {
66931				// Use peek because we don't want a dependency for 'error' property because it
66932				// changes before 'isValid' does. (Issue #99)
66933				errors.push(observable.error.peek());
66934			}
66935		});
66936		return errors;
66937	}
66938
66939	return {
66940		//Call this on startup
66941		//any config can be overridden with the passed in options
66942		init: function (options, force) {
66943			//done run this multiple times if we don't really want to
66944			if (isInitialized > 0 && !force) {
66945				return;
66946			}
66947
66948			//because we will be accessing options properties it has to be an object at least
66949			options = options || {};
66950			//if specific error classes are not provided then apply generic errorClass
66951			//it has to be done on option so that options.errorClass can override default
66952			//errorElementClass and errorMessage class but not those provided in options
66953			options.errorElementClass = options.errorElementClass || options.errorClass || configuration.errorElementClass;
66954			options.errorMessageClass = options.errorMessageClass || options.errorClass || configuration.errorMessageClass;
66955
66956			extend(configuration, options);
66957
66958			if (configuration.registerExtenders) {
66959				kv.registerExtenders();
66960			}
66961
66962			isInitialized = 1;
66963		},
66964		// backwards compatibility
66965		configure: function (options) { kv.init(options); },
66966
66967		// resets the config back to its original state
66968		reset: kv.configuration.reset,
66969
66970		// recursively walks a viewModel and creates an object that
66971		// provides validation information for the entire viewModel
66972		// obj -> the viewModel to walk
66973		// options -> {
66974		//	  deep: false, // if true, will walk past the first level of viewModel properties
66975		//	  observable: false // if true, returns a computed observable indicating if the viewModel is valid
66976		// }
66977		group: function group(obj, options) { // array of observables or viewModel
66978			options = extend(extend({}, configuration.grouping), options);
66979
66980			var context = {
66981				options: options,
66982				graphMonitor: ko.observable(),
66983				flagged: [],
66984				subscriptions: [],
66985				validatables: []
66986			};
66987
66988			var result = null;
66989
66990			//if using observables then traverse structure once and add observables
66991			if (options.observable) {
66992				result = ko.computed(function () {
66993					context.graphMonitor(); //register dependency
66994					runTraversal(obj, context);
66995					return collectErrors(context.validatables);
66996				});
66997			}
66998			else { //if not using observables then every call to error() should traverse the structure
66999				result = function () {
67000					runTraversal(obj, context);
67001					return collectErrors(context.validatables);
67002				};
67003			}
67004
67005			result.showAllMessages = function (show) { // thanks @heliosPortal
67006				if (show === undefined) {//default to true
67007					show = true;
67008				}
67009
67010				result.forEach(function (observable) {
67011					if (utils.isValidatable(observable)) {
67012						observable.isModified(show);
67013					}
67014				});
67015			};
67016
67017			result.isAnyMessageShown = function () {
67018				var invalidAndModifiedPresent;
67019
67020				invalidAndModifiedPresent = !!result.find(function (observable) {
67021					return utils.isValidatable(observable) && !observable.isValid() && observable.isModified();
67022				});
67023				return invalidAndModifiedPresent;
67024			};
67025
67026			result.filter = function(predicate) {
67027				predicate = predicate || function () { return true; };
67028				// ensure we have latest changes
67029				result();
67030
67031				return koUtils.arrayFilter(context.validatables, predicate);
67032			};
67033
67034			result.find = function(predicate) {
67035				predicate = predicate || function () { return true; };
67036				// ensure we have latest changes
67037				result();
67038
67039				return koUtils.arrayFirst(context.validatables, predicate);
67040			};
67041
67042			result.forEach = function(callback) {
67043				callback = callback || function () { };
67044				// ensure we have latest changes
67045				result();
67046
67047				forEach(context.validatables, callback);
67048			};
67049
67050			result.map = function(mapping) {
67051				mapping = mapping || function (item) { return item; };
67052				// ensure we have latest changes
67053				result();
67054
67055				return koUtils.arrayMap(context.validatables, mapping);
67056			};
67057
67058			/**
67059			 * @private You should not rely on this method being here.
67060			 * It's a private method and it may change in the future.
67061			 *
67062			 * @description Updates the validated object and collects errors from it.
67063			 */
67064			result._updateState = function(newValue) {
67065				if (!utils.isObject(newValue)) {
67066					throw new Error('An object is required.');
67067				}
67068				obj = newValue;
67069				if (options.observable) {
67070					context.graphMonitor.valueHasMutated();
67071				}
67072				else {
67073					runTraversal(newValue, context);
67074					return collectErrors(context.validatables);
67075				}
67076			};
67077			return result;
67078		},
67079
67080		formatMessage: function (message, params, observable) {
67081			if (utils.isObject(params) && params.typeAttr) {
67082				params = params.value;
67083			}
67084			if (typeof (message) === 'function') {
67085				return message(params, observable);
67086			}
67087			var replacements = unwrap(params) || [];
67088			if (!utils.isArray(replacements)) {
67089				replacements = [replacements];
67090			}
67091			return message.replace(/{(\d+)}/gi, function(match, index) {
67092				if (typeof replacements[index] !== 'undefined') {
67093					return replacements[index];
67094				}
67095				return match;
67096			});
67097		},
67098
67099		// addRule:
67100		// This takes in a ko.observable and a Rule Context - which is just a rule name and params to supply to the validator
67101		// ie: kv.addRule(myObservable, {
67102		//		  rule: 'required',
67103		//		  params: true
67104		//	  });
67105		//
67106		addRule: function (observable, rule) {
67107			observable.extend({ validatable: true });
67108
67109			var hasRule = !!koUtils.arrayFirst(observable.rules(), function(item) {
67110				return item.rule && item.rule === rule.rule;
67111			});
67112
67113			if (!hasRule) {
67114				//push a Rule Context to the observables local array of Rule Contexts
67115				observable.rules.push(rule);
67116			}
67117			return observable;
67118		},
67119
67120		// addAnonymousRule:
67121		// Anonymous Rules essentially have all the properties of a Rule, but are only specific for a certain property
67122		// and developers typically are wanting to add them on the fly or not register a rule with the 'kv.rules' object
67123		//
67124		// Example:
67125		// var test = ko.observable('something').extend{(
67126		//	  validation: {
67127		//		  validator: function(val, someOtherVal){
67128		//			  return true;
67129		//		  },
67130		//		  message: "Something must be really wrong!',
67131		//		  params: true
67132		//	  }
67133		//  )};
67134		addAnonymousRule: function (observable, ruleObj) {
67135			if (ruleObj['message'] === undefined) {
67136				ruleObj['message'] = 'Error';
67137			}
67138
67139			//make sure onlyIf is honoured
67140			if (ruleObj.onlyIf) {
67141				ruleObj.condition = ruleObj.onlyIf;
67142			}
67143
67144			//add the anonymous rule to the observable
67145			kv.addRule(observable, ruleObj);
67146		},
67147
67148		addExtender: function (ruleName) {
67149			ko.extenders[ruleName] = function (observable, params) {
67150				//params can come in a few flavors
67151				// 1. Just the params to be passed to the validator
67152				// 2. An object containing the Message to be used and the Params to pass to the validator
67153				// 3. A condition when the validation rule to be applied
67154				//
67155				// Example:
67156				// var test = ko.observable(3).extend({
67157				//	  max: {
67158				//		  message: 'This special field has a Max of {0}',
67159				//		  params: 2,
67160				//		  onlyIf: function() {
67161				//					  return specialField.IsVisible();
67162				//		
vendor: 7,170 bytes, lines 67162-67397
67162		  }
67163				//	  }
67164				//  )};
67165				//
67166				if (params && (params.message || params.onlyIf)) { //if it has a message or condition object, then its an object literal to use
67167					return kv.addRule(observable, {
67168						rule: ruleName,
67169						message: params.message,
67170						params: utils.isEmptyVal(params.params) ? true : params.params,
67171						condition: params.onlyIf
67172					});
67173				} else {
67174					return kv.addRule(observable, {
67175						rule: ruleName,
67176						params: params
67177					});
67178				}
67179			};
67180		},
67181
67182		// loops through all kv.rules and adds them as extenders to
67183		// ko.extenders
67184		registerExtenders: function () { // root extenders optional, use 'validation' extender if would cause conflicts
67185			if (configuration.registerExtenders) {
67186				for (var ruleName in kv.rules) {
67187					if (kv.rules.hasOwnProperty(ruleName)) {
67188						if (!ko.extenders[ruleName]) {
67189							kv.addExtender(ruleName);
67190						}
67191					}
67192				}
67193			}
67194		},
67195
67196		//creates a span next to the @element with the specified error class
67197		insertValidationMessage: function (element) {
67198			var span = document.createElement('SPAN');
67199			span.className = utils.getConfigOptions(element).errorMessageClass;
67200			utils.insertAfter(element, span);
67201			return span;
67202		},
67203
67204		// if html-5 validation attributes have been specified, this parses
67205		// the attributes on @element
67206		parseInputValidationAttributes: function (element, valueAccessor) {
67207			forEach(kv.configuration.html5Attributes, function (attr) {
67208				if (utils.hasAttribute(element, attr)) {
67209
67210					var params = element.getAttribute(attr) || true;
67211
67212					if (attr === 'min' || attr === 'max')
67213					{
67214						// If we're validating based on the min and max attributes, we'll
67215						// need to know what the 'type' attribute is set to
67216						var typeAttr = element.getAttribute('type');
67217						if (typeof typeAttr === "undefined" || !typeAttr)
67218						{
67219							// From http://www.w3.org/TR/html-markup/input:
67220							//   An input element with no type attribute specified represents the
67221							//   same thing as an input element with its type attribute set to "text".
67222							typeAttr = "text";
67223						}
67224						params = {typeAttr: typeAttr, value: params};
67225					}
67226
67227					kv.addRule(valueAccessor(), {
67228						rule: attr,
67229						params: params
67230					});
67231				}
67232			});
67233
67234			var currentType = element.getAttribute('type');
67235			forEach(kv.configuration.html5InputTypes, function (type) {
67236				if (type === currentType) {
67237					kv.addRule(valueAccessor(), {
67238						rule: (type === 'date') ? 'dateISO' : type,
67239						params: true
67240					});
67241				}
67242			});
67243		},
67244
67245		// writes html5 validation attributes on the element passed in
67246		writeInputValidationAttributes: function (element, valueAccessor) {
67247			var observable = valueAccessor();
67248
67249			if (!observable || !observable.rules) {
67250				return;
67251			}
67252
67253			var contexts = observable.rules(); // observable array
67254
67255			// loop through the attributes and add the information needed
67256			forEach(kv.configuration.html5Attributes, function (attr) {
67257				var ctx = koUtils.arrayFirst(contexts, function (ctx) {
67258					return ctx.rule && ctx.rule.toLowerCase() === attr.toLowerCase();
67259				});
67260
67261				if (!ctx) {
67262					return;
67263				}
67264
67265				// we have a rule matching a validation attribute at this point
67266				// so lets add it to the element along with the params
67267				ko.computed({
67268					read: function() {
67269						var params = ko.unwrap(ctx.params);
67270
67271						// we have to do some special things for the pattern validation
67272						if (ctx.rule === "pattern" && params instanceof RegExp) {
67273							// we need the pure string representation of the RegExpr without the //gi stuff
67274							params = params.source;
67275						}
67276
67277						element.setAttribute(attr, params);
67278					},
67279					disposeWhenNodeIsRemoved: element
67280				});
67281			});
67282
67283			contexts = null;
67284		},
67285
67286		//take an existing binding handler and make it cause automatic validations
67287		makeBindingHandlerValidatable: function (handlerName) {
67288			var init = ko.bindingHandlers[handlerName].init;
67289
67290			ko.bindingHandlers[handlerName].init = function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
67291
67292				init(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext);
67293
67294				return ko.bindingHandlers['validationCore'].init(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext);
67295			};
67296		},
67297
67298		// visit an objects properties and apply validation rules from a definition
67299		setRules: function (target, definition) {
67300			var setRules = function (target, definition) {
67301				if (!target || !definition) { return; }
67302
67303				for (var prop in definition) {
67304					if (!definition.hasOwnProperty(prop)) { continue; }
67305					var ruleDefinitions = definition[prop];
67306
67307					//check the target property exists and has a value
67308					if (!target[prop]) { continue; }
67309					var targetValue = target[prop],
67310						unwrappedTargetValue = unwrap(targetValue),
67311						rules = {},
67312						nonRules = {};
67313
67314					for (var rule in ruleDefinitions) {
67315						if (!ruleDefinitions.hasOwnProperty(rule)) { continue; }
67316						if (kv.rules[rule]) {
67317							rules[rule] = ruleDefinitions[rule];
67318						} else {
67319							nonRules[rule] = ruleDefinitions[rule];
67320						}
67321					}
67322
67323					//apply rules
67324					if (ko.isObservable(targetValue)) {
67325						targetValue.extend(rules);
67326					}
67327
67328					//then apply child rules
67329					//if it's an array, apply rules to all children
67330					if (unwrappedTargetValue && utils.isArray(unwrappedTargetValue)) {
67331						for (var i = 0; i < unwrappedTargetValue.length; i++) {
67332							setRules(unwrappedTargetValue[i], nonRules);
67333						}
67334						//otherwise, just apply to this property
67335					} else {
67336						setRules(unwrappedTargetValue, nonRules);
67337					}
67338				}
67339			};
67340			setRules(target, definition);
67341		}
67342	};
67343
67344}());
67345
67346// expose api publicly
67347extend(ko.validation, api);
67348;//Validation Rules:
67349// You can view and override messages or rules via:
67350// kv.rules[ruleName]
67351//
67352// To implement a custom Rule, simply use this template:
67353// kv.rules['<custom rule name>'] = {
67354//      validator: function (val, param) {
67355//          <custom logic>
67356//          return <true or false>;
67357//      },
67358//      message: '<custom validation message>' //optionally you can also use a '{0}' to denote a placeholder that will be replaced with your 'param'
67359// };
67360//
67361// Example:
67362// kv.rules['mustEqual'] = {
67363//      validator: function( val, mustEqualVal ){
67364//          return val === mustEqualVal;
67365//      },
67366//      message: 'This field must equal {0}'
67367// };
67368//
67369kv.rules = {};
67370kv.rules['required'] = {
67371	validator: function (val, required) {
67372		var testVal;
67373
67374		if (val === undefined || val === null) {
67375			return !required;
67376		}
67377
67378		testVal = val;
67379		if (typeof (val) === 'string') {
67380			if (String.prototype.trim) {
67381				testVal = val.trim();
67382			}
67383			else {
67384				testVal = val.replace(/^\s+|\s+$/g, '');
67385			}
67386		}
67387
67388		if (!required) {// if they passed: { required: false }, then don't require this
67389			return true;
67390		}
67391
67392		return ((testVal + '').length > 0);
67393	},
67394	message: 'This field is required.'
67395};
67396
67397function minMaxValidatorFactory(validatorName) {
vendor: 21,121 bytes, lines 67398-67968
67398    var isMaxValidation = validatorName === "max";
67399
67400    return function (val, options) {
67401        if (kv.utils.isEmptyVal(val)) {
67402            return true;
67403        }
67404
67405        var comparisonValue, type;
67406        if (options.typeAttr === undefined) {
67407            // This validator is being called from javascript rather than
67408            // being bound from markup
67409            type = "text";
67410            comparisonValue = options;
67411        } else {
67412            type = options.typeAttr;
67413            comparisonValue = options.value;
67414        }
67415
67416        // From http://www.w3.org/TR/2012/WD-html5-20121025/common-input-element-attributes.html#attr-input-min,
67417        // if the value is parseable to a number, then the minimum should be numeric
67418        if (!isNaN(comparisonValue) && !(comparisonValue instanceof Date)) {
67419            type = "number";
67420        }
67421
67422        var regex, valMatches, comparisonValueMatches;
67423        switch (type.toLowerCase()) {
67424            case "week":
67425                regex = /^(\d{4})-W(\d{2})$/;
67426                valMatches = val.match(regex);
67427                if (valMatches === null) {
67428                    throw "Invalid value for " + validatorName + " attribute for week input.  Should look like " +
67429                        "'2000-W33' http://www.w3.org/TR/html-markup/input.week.html#input.week.attrs.min";
67430                }
67431                comparisonValueMatches = comparisonValue.match(regex);
67432                // If no regex matches were found, validation fails
67433                if (!comparisonValueMatches) {
67434                    return false;
67435                }
67436
67437                if (isMaxValidation) {
67438                    return (valMatches[1] < comparisonValueMatches[1]) || // older year
67439                        // same year, older week
67440                        ((valMatches[1] === comparisonValueMatches[1]) && (valMatches[2] <= comparisonValueMatches[2]));
67441                } else {
67442                    return (valMatches[1] > comparisonValueMatches[1]) || // newer year
67443                        // same year, newer week
67444                        ((valMatches[1] === comparisonValueMatches[1]) && (valMatches[2] >= comparisonValueMatches[2]));
67445                }
67446                break;
67447
67448            case "month":
67449                regex = /^(\d{4})-(\d{2})$/;
67450                valMatches = val.match(regex);
67451                if (valMatches === null) {
67452                    throw "Invalid value for " + validatorName + " attribute for month input.  Should look like " +
67453                        "'2000-03' http://www.w3.org/TR/html-markup/input.month.html#input.month.attrs.min";
67454                }
67455                comparisonValueMatches = comparisonValue.match(regex);
67456                // If no regex matches were found, validation fails
67457                if (!comparisonValueMatches) {
67458                    return false;
67459                }
67460
67461                if (isMaxValidation) {
67462                    return ((valMatches[1] < comparisonValueMatches[1]) || // older year
67463                        // same year, older month
67464                        ((valMatches[1] === comparisonValueMatches[1]) && (valMatches[2] <= comparisonValueMatches[2])));
67465                } else {
67466                    return (valMatches[1] > comparisonValueMatches[1]) || // newer year
67467                        // same year, newer month
67468                        ((valMatches[1] === comparisonValueMatches[1]) && (valMatches[2] >= comparisonValueMatches[2]));
67469                }
67470                break;
67471
67472            case "number":
67473            case "range":
67474                if (isMaxValidation) {
67475                    return (!isNaN(val) && parseFloat(val) <= parseFloat(comparisonValue));
67476                } else {
67477                    return (!isNaN(val) && parseFloat(val) >= parseFloat(comparisonValue));
67478                }
67479                break;
67480
67481            default:
67482                if (isMaxValidation) {
67483                    return val <= comparisonValue;
67484                } else {
67485                    return val >= comparisonValue;
67486                }
67487        }
67488    };
67489}
67490
67491kv.rules['min'] = {
67492	validator: minMaxValidatorFactory("min"),
67493	message: 'Please enter a value greater than or equal to {0}.'
67494};
67495
67496kv.rules['max'] = {
67497	validator: minMaxValidatorFactory("max"),
67498	message: 'Please enter a value less than or equal to {0}.'
67499};
67500
67501kv.rules['minLength'] = {
67502	validator: function (val, minLength) {
67503		if(kv.utils.isEmptyVal(val)) { return true; }
67504		var normalizedVal = kv.utils.isNumber(val) ? ('' + val) : val;
67505		return normalizedVal.length >= minLength;
67506	},
67507	message: 'Please enter at least {0} characters.'
67508};
67509
67510kv.rules['maxLength'] = {
67511	validator: function (val, maxLength) {
67512		if(kv.utils.isEmptyVal(val)) { return true; }
67513		var normalizedVal = kv.utils.isNumber(val) ? ('' + val) : val;
67514		return normalizedVal.length <= maxLength;
67515	},
67516	message: 'Please enter no more than {0} characters.'
67517};
67518
67519kv.rules['pattern'] = {
67520	validator: function (val, regex) {
67521		return kv.utils.isEmptyVal(val) || val.toString().match(regex) !== null;
67522	},
67523	message: 'Please check this value.'
67524};
67525
67526kv.rules['step'] = {
67527	validator: function (val, step) {
67528
67529		// in order to handle steps of .1 & .01 etc.. Modulus won't work
67530		// if the value is a decimal, so we have to correct for that
67531		if (kv.utils.isEmptyVal(val) || step === 'any') { return true; }
67532		var dif = (val * 100) % (step * 100);
67533		return Math.abs(dif) < 0.00001 || Math.abs(1 - dif) < 0.00001;
67534	},
67535	message: 'The value must increment by {0}.'
67536};
67537
67538kv.rules['email'] = {
67539	validator: function (val, validate) {
67540		if (!validate) { return true; }
67541
67542		//I think an empty email address is also a valid entry
67543		//if one want's to enforce entry it should be done with 'required: true'
67544		return kv.utils.isEmptyVal(val) || (
67545			// jquery validate regex - thanks Scott Gonzalez
67546			validate && /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([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])))$/i.test(val)
67547		);
67548	},
67549	message: 'Please enter a proper email address.'
67550};
67551
67552kv.rules['date'] = {
67553	validator: function (value, validate) {
67554		if (!validate) { return true; }
67555		return kv.utils.isEmptyVal(value) || (validate && !/Invalid|NaN/.test(new Date(value)));
67556	},
67557	message: 'Please enter a proper date.'
67558};
67559
67560kv.rules['dateISO'] = {
67561	validator: function (value, validate) {
67562		if (!validate) { return true; }
67563		return kv.utils.isEmptyVal(value) || (validate && /^\d{4}[-/](?:0?[1-9]|1[012])[-/](?:0?[1-9]|[12][0-9]|3[01])$/.test(value));
67564	},
67565	message: 'Please enter a proper date.'
67566};
67567
67568kv.rules['number'] = {
67569	validator: function (value, validate) {
67570		if (!validate) { return true; }
67571		return kv.utils.isEmptyVal(value) || (validate && /^-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(value));
67572	},
67573	message: 'Please enter a number.'
67574};
67575
67576kv.rules['digit'] = {
67577	validator: function (value, validate) {
67578		if (!validate) { return true; }
67579		return kv.utils.isEmptyVal(value) || (validate && /^\d+$/.test(value));
67580	},
67581	message: 'Please enter a digit.'
67582};
67583
67584kv.rules['phoneUS'] = {
67585	validator: function (phoneNumber, validate) {
67586		if (!validate) { return true; }
67587		if (kv.utils.isEmptyVal(phoneNumber)) { return true; } // makes it optional, use 'required' rule if it should be required
67588		if (typeof (phoneNumber) !== 'string') { return false; }
67589		phoneNumber = phoneNumber.replace(/\s+/g, "");
67590		return validate && phoneNumber.length > 9 && phoneNumber.match(/^(1-?)?(\([2-9]\d{2}\)|[2-9]\d{2})-?[2-9]\d{2}-?\d{4}$/);
67591	},
67592	message: 'Please specify a valid phone number.'
67593};
67594
67595kv.rules['equal'] = {
67596	validator: function (val, params) {
67597		var otherValue = params;
67598		return val === kv.utils.getValue(otherValue);
67599	},
67600	message: 'Values must equal.'
67601};
67602
67603kv.rules['notEqual'] = {
67604	validator: function (val, params) {
67605		var otherValue = params;
67606		return val !== kv.utils.getValue(otherValue);
67607	},
67608	message: 'Please choose another value.'
67609};
67610
67611//unique in collection
67612// options are:
67613//    collection: array or function returning (observable) array
67614//              in which the value has to be unique
67615//    valueAccessor: function that returns value from an object stored in collection
67616//              if it is null the value is compared directly
67617//    external: set to true when object you are validating is automatically updating collection
67618kv.rules['unique'] = {
67619	validator: function (val, options) {
67620		var c = kv.utils.getValue(options.collection),
67621			external = kv.utils.getValue(options.externalValue),
67622			counter = 0;
67623
67624		if (!val || !c) { return true; }
67625
67626		koUtils.arrayFilter(c, function (item) {
67627			if (val === (options.valueAccessor ? options.valueAccessor(item) : item)) { counter++; }
67628		});
67629		// if value is external even 1 same value in collection means the value is not unique
67630		return counter < (!!external ? 1 : 2);
67631	},
67632	message: 'Please make sure the value is unique.'
67633};
67634
67635
67636//now register all of these!
67637(function () {
67638	kv.registerExtenders();
67639}());
67640;// The core binding handler
67641// this allows us to setup any value binding that internally always
67642// performs the same functionality
67643ko.bindingHandlers['validationCore'] = (function () {
67644
67645	return {
67646		init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
67647			var config = kv.utils.getConfigOptions(element);
67648			var observable = valueAccessor();
67649
67650			// parse html5 input validation attributes, optional feature
67651			if (config.parseInputAttributes) {
67652				kv.utils.async(function () { kv.parseInputValidationAttributes(element, valueAccessor); });
67653			}
67654
67655			// if requested insert message element and apply bindings
67656			if (config.insertMessages && kv.utils.isValidatable(observable)) {
67657
67658				// insert the <span></span>
67659				var validationMessageElement = kv.insertValidationMessage(element);
67660
67661				// if we're told to use a template, make sure that gets rendered
67662				if (config.messageTemplate) {
67663					ko.renderTemplate(config.messageTemplate, { field: observable }, null, validationMessageElement, 'replaceNode');
67664				} else {
67665					ko.applyBindingsToNode(validationMessageElement, { validationMessage: observable });
67666				}
67667			}
67668
67669			// write the html5 attributes if indicated by the config
67670			if (config.writeInputAttributes && kv.utils.isValidatable(observable)) {
67671
67672				kv.writeInputValidationAttributes(element, valueAccessor);
67673			}
67674
67675			// if requested, add binding to decorate element
67676			if (config.decorateInputElement && kv.utils.isValidatable(observable)) {
67677				ko.applyBindingsToNode(element, { validationElement: observable });
67678			}
67679		}
67680	};
67681
67682}());
67683
67684// override for KO's default 'value', 'checked', 'textInput' and selectedOptions bindings
67685kv.makeBindingHandlerValidatable("value");
67686kv.makeBindingHandlerValidatable("checked");
67687if (ko.bindingHandlers.textInput) {
67688	kv.makeBindingHandlerValidatable("textInput");
67689}
67690kv.makeBindingHandlerValidatable("selectedOptions");
67691
67692
67693ko.bindingHandlers['validationMessage'] = { // individual error message, if modified or post binding
67694	update: function (element, valueAccessor) {
67695		var obsv = valueAccessor(),
67696			config = kv.utils.getConfigOptions(element),
67697			val = unwrap(obsv),
67698			msg = null,
67699			isModified = false,
67700			isValid = false;
67701
67702		if (obsv === null || typeof obsv === 'undefined') {
67703			throw new Error('Cannot bind validationMessage to undefined value. data-bind expression: ' +
67704				element.getAttribute('data-bind'));
67705		}
67706
67707		if (!obsv.isValid || !obsv.isModified) {
67708			throw new Error("Observable is not validatable");
67709		}
67710
67711		isModified = obsv.isModified();
67712		isValid = obsv.isValid();
67713
67714		var error = null;
67715		if (!config.messagesOnModified || isModified) {
67716			error = isValid ? null : obsv.error;
67717		}
67718
67719		var isVisible = !config.messagesOnModified || isModified ? !isValid : false;
67720		var isCurrentlyVisible = element.style.display !== "none";
67721
67722		if (config.allowHtmlMessages) {
67723			koUtils.setHtml(element, error);
67724		} else {
67725			ko.bindingHandlers.text.update(element, function () { return error; });
67726		}
67727
67728		if (isCurrentlyVisible && !isVisible) {
67729			element.style.display = 'none';
67730		} else if (!isCurrentlyVisible && isVisible) {
67731			element.style.display = '';
67732		}
67733	}
67734};
67735
67736ko.bindingHandlers['validationElement'] = {
67737	update: function (element, valueAccessor, allBindingsAccessor) {
67738		var obsv = valueAccessor(),
67739			config = kv.utils.getConfigOptions(element),
67740			val = unwrap(obsv),
67741			msg = null,
67742			isModified = false,
67743			isValid = false;
67744
67745		if (obsv === null || typeof obsv === 'undefined') {
67746			throw new Error('Cannot bind validationElement to undefined value. data-bind expression: ' +
67747				element.getAttribute('data-bind'));
67748		}
67749
67750		if (!obsv.isValid || !obsv.isModified) {
67751			throw new Error("Observable is not validatable");
67752		}
67753
67754		isModified = obsv.isModified();
67755		isValid = obsv.isValid();
67756
67757		// create an evaluator function that will return something like:
67758		// css: { validationElement: true }
67759		var cssSettingsAccessor = function () {
67760			var css = {};
67761
67762			var shouldShow = ((!config.decorateElementOnModified || isModified) ? !isValid : false);
67763
67764			// css: { validationElement: false }
67765			css[config.errorElementClass] = shouldShow;
67766
67767			return css;
67768		};
67769
67770		//add or remove class on the element;
67771		ko.bindingHandlers.css.update(element, cssSettingsAccessor, allBindingsAccessor);
67772		if (!config.errorsAsTitle) { return; }
67773
67774		ko.bindingHandlers.attr.update(element, function () {
67775			var
67776				hasModification = !config.errorsAsTitleOnModified || isModified,
67777				title = kv.utils.getOriginalElementTitle(element);
67778
67779			if (hasModification && !isValid) {
67780				return { title: obsv.error, 'data-orig-title': title };
67781			} else if (!hasModification || isValid) {
67782				return { title: title, 'data-orig-title': null };
67783			}
67784		});
67785	}
67786};
67787
67788// ValidationOptions:
67789// This binding handler allows you to override the initial config by setting any of the options for a specific element or context of elements
67790//
67791// Example:
67792// <div data-bind="validationOptions: { insertMessages: true, messageTemplate: 'customTemplate', errorMessageClass: 'mySpecialClass'}">
67793//      <input type="text" data-bind="value: someValue"/>
67794//      <input type="text" data-bind="value: someValue2"/>
67795// </div>
67796ko.bindingHandlers['validationOptions'] = (function () {
67797	return {
67798		init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
67799			var options = unwrap(valueAccessor());
67800			if (options) {
67801				var newConfig = extend({}, kv.configuration);
67802				extend(newConfig, options);
67803
67804				//store the validation options on the node so we can retrieve it later
67805				kv.utils.setDomData(element, newConfig);
67806			}
67807		}
67808	};
67809}());
67810;// Validation Extender:
67811// This is for creating custom validation logic on the fly
67812// Example:
67813// var test = ko.observable('something').extend{(
67814//      validation: {
67815//          validator: function(val, someOtherVal){
67816//              return true;
67817//          },
67818//          message: "Something must be really wrong!',
67819//          params: true
67820//      }
67821//  )};
67822ko.extenders['validation'] = function (observable, rules) { // allow single rule or array
67823	forEach(kv.utils.isArray(rules) ? rules : [rules], function (rule) {
67824		// the 'rule' being passed in here has no name to identify a core Rule,
67825		// so we add it as an anonymous rule
67826		// If the developer is wanting to use a core Rule, but use a different message see the 'addExtender' logic for examples
67827		kv.addAnonymousRule(observable, rule);
67828	});
67829	return observable;
67830};
67831
67832//This is the extender that makes a Knockout Observable also 'Validatable'
67833//examples include:
67834// 1. var test = ko.observable('something').extend({validatable: true});
67835// this will ensure that the Observable object is setup properly to respond to rules
67836//
67837// 2. test.extend({validatable: false});
67838// this will remove the validation properties from the Observable object should you need to do that.
67839ko.extenders['validatable'] = function (observable, options) {
67840	if (!kv.utils.isObject(options)) {
67841		options = { enable: options };
67842	}
67843
67844	if (!('enable' in options)) {
67845		options.enable = true;
67846	}
67847
67848	if (options.enable && !kv.utils.isValidatable(observable)) {
67849		var config = kv.configuration.validate || {};
67850		var validationOptions = {
67851			throttleEvaluation : options.throttle || config.throttle
67852		};
67853
67854		observable.error = ko.observable(null); // holds the error message, we only need one since we stop processing validators when one is invalid
67855
67856		// observable.rules:
67857		// ObservableArray of Rule Contexts, where a Rule Context is simply the name of a rule and the params to supply to it
67858		//
67859		// Rule Context = { rule: '<rule name>', params: '<passed in params>', message: '<Override of default Message>' }
67860		observable.rules = ko.observableArray(); //holds the rule Contexts to use as part of validation
67861
67862		//in case async validation is occurring
67863		observable.isValidating = ko.observable(false);
67864
67865		//the true holder of whether the observable is valid or not
67866		observable.__valid__ = ko.observable(true);
67867
67868		observable.isModified = ko.observable(false);
67869
67870		// a semi-protected observable
67871		observable.isValid = ko.computed(observable.__valid__);
67872
67873		//manually set error state
67874		observable.setError = function (error) {
67875			var previousError = observable.error.peek();
67876			var previousIsValid = observable.__valid__.peek();
67877
67878			observable.error(error);
67879			observable.__valid__(false);
67880
67881			if (previousError !== error && !previousIsValid) {
67882				// if the observable was not valid before then isValid will not mutate,
67883				// hence causing any grouping to not display the latest error.
67884				observable.isValid.notifySubscribers();
67885			}
67886		};
67887
67888		//manually clear error state
67889		observable.clearError = function () {
67890			observable.error(null);
67891			observable.__valid__(true);
67892			return observable;
67893		};
67894
67895		//subscribe to changes in the observable
67896		var h_change = observable.subscribe(function () {
67897			observable.isModified(true);
67898		});
67899
67900		// we use a computed here to ensure that anytime a dependency changes, the
67901		// validation logic evaluates
67902		var h_obsValidationTrigger = ko.computed(extend({
67903			read: function () {
67904				var obs = observable(),
67905					ruleContexts = observable.rules();
67906
67907				kv.validateObservable(observable);
67908
67909				return true;
67910			}
67911		}, validationOptions));
67912
67913		extend(h_obsValidationTrigger, validationOptions);
67914
67915		observable._disposeValidation = function () {
67916			//first dispose of the subscriptions
67917			observable.isValid.dispose();
67918			observable.rules.removeAll();
67919			if (observable.isModified.getSubscriptionsCount() > 0) {
67920				observable.isModified._subscriptions['change'] = [];
67921			}
67922			if (observable.isValidating.getSubscriptionsCount() > 0) {
67923				observable.isValidating._subscriptions['change'] = [];
67924			}
67925			if (observable.__valid__.getSubscriptionsCount() > 0) {
67926				observable.__valid__._subscriptions['change'] = [];
67927			}
67928			h_change.dispose();
67929			h_obsValidationTrigger.dispose();
67930
67931			delete observable['rules'];
67932			delete observable['error'];
67933			delete observable['isValid'];
67934			delete observable['isValidating'];
67935			delete observable['__valid__'];
67936			delete observable['isModified'];
67937		};
67938	} else if (options.enable === false && observable._disposeValidation) {
67939		observable._disposeValidation();
67940	}
67941	return observable;
67942};
67943
67944function validateSync(observable, rule, ctx) {
67945	//Execute the validator and see if its valid
67946	if (!rule.validator(observable(), (ctx.params === undefined ? true : unwrap(ctx.params)))) { // default param is true, eg. required = true
67947
67948		//not valid, so format the error message and stick it in the 'error' variable
67949		observable.setError(kv.formatMessage(
67950					ctx.message || rule.message,
67951					unwrap(ctx.params),
67952					observable));
67953		return false;
67954	} else {
67955		return true;
67956	}
67957}
67958
67959function validateAsync(observable, rule, ctx) {
67960	observable.isValidating(true);
67961
67962	var callBack = function (valObj) {
67963		var isValid = false,
67964			msg = '';
67965
67966		if (!observable.__valid__()) {
67967
67968			// since we're returning early, make sure we turn this off
67969			observable.isValidating(false);
67970
67971			return; //if its already NOT valid, don't add to that
67972		}
67973
67974		//we were handed back a complex object
67975		if (valObj['message']) {
67976			isValid = valObj.isValid;
67977			msg = valObj.message;
67978		} else {
67979			isValid = valObj;
67980		}
67981
67982		if (!isValid) {
67983			//not valid, so format the error message and stick it in the 'error' variable
67984			observable.error(kv.formatMessage(
67985				msg || ctx.message || rule.message,
67986				unwrap(ctx.params),
67987				observable));
67988			observable.__valid__(isValid);
67989		}
67990
67991		// tell it that we're done
67992		observable.isValidating(false);
67993	};
67994
67995	//fire the validator and hand it the callback
67996	rule.validator(observable(), unwrap(ctx.params || true), callBack);
67997}
67998
67999kv.validateObservable = function (observable) {
68000	var i = 0,
68001		rule, // the rule validator to execute
68002		ctx, // the current Rule Context for the loop
68003		ruleContexts = observable.rules(), //cache for iterator
68004		len = ruleContexts.length; //cache for iterator
68005
68006	for (; i < len; i++) {
68007
68008		//get the Rule Context info to give to the core Rule
68009		ctx = ruleContexts[i];
68010
68011		// checks an 'onlyIf' condition
68012		if (ctx.condition && !ctx.condition()) {
68013			continue;
68014		}
68015
68016		//get the core Rule to use for validation
68017		rule = ctx.rule ? kv.rules[ctx.rule] : ctx;
68018
68019		if (rule['async'] || ctx['async']) {
68020			//run async validation
68021			validateAsync(observable, rule, ctx);
68022
68023		} else {
68024			//run normal sync validation
68025			if (!validateSync(observable, rule, ctx)) {
68026				return false; //break out of the loop
68027			}
68028		}
68029	}
68030	//finally if we got this far, make the observable valid again!
68031	observable.clearError();
68032	return true;
68033};
68034;
68035//quick function to override rule messages
68036kv.localize = function (msgTranslations) {
68037
68038	var msg, rule;
68039
68040	//loop the properties in the object and assign the msg to the rule
68041	for (rule in msgTranslations) {
68042		if (kv.rules.hasOwnProperty(rule)) {
68043			kv.rules[rule].message = msgTranslations[rule];
68044		}
68045	}
68046};;/**
68047 * Possible invocations:
68048 * 		applyBindingsWithValidation(viewModel)
68049 * 		applyBindingsWithValidation(viewModel, options)
68050 * 		applyBindingsWithValidation(viewModel, rootNode)
68051 *		applyBindingsWithValidation(viewModel, rootNode, options)
68052 */
68053ko.applyBindingsWithValidation = function (viewModel, rootNode, options) {
68054	var node = document.body,
68055		config;
68056
68057	if (rootNode && rootNode.nodeType) {
68058		node = rootNode;
68059		config = options;
68060	}
68061	else {
68062		config = rootNode;
68063	}
68064
68065	kv.init();
68066
68067	if (config) {
68068		config = extend(extend({}, kv.configuration), config);
68069		kv.utils.setDomData(node, config);
68070	}
68071
68072	ko.applyBindings(viewModel, node);
68073};
68074
68075//override the original applyBindings so that we can ensure all new rules and what not are correctly registered
68076var origApplyBindings = ko.applyBindings;
68077ko.applyBindings = function (viewModel, rootNode) {
68078
68079	kv.init();
68080
68081	origApplyBindings(viewModel, rootNode);
68082};
68083
68084ko.validatedObservable = function (initialValue, options) {
68085	if (!options && !kv.utils.isObject(initialValue)) {
68086		return ko.observable(initialValue).extend({ validatable: true });
68087	}
68088
68089	var obsv = ko.observable(initialValue);
68090	obsv.errors = kv.group(kv.utils.isObject(initialValue) ? initialValue : {}, options);
68091	obsv.isValid = ko.observable(obsv.errors().length === 0);
68092
68093	if (ko.isObservable(obsv.errors)) {
68094		obsv.errors.subscribe(function(errors) {
68095			obsv.isValid(errors.length === 0);
68096		});
68097	}
68098	else {
68099		ko.computed(obsv.errors).subscribe(function (errors) {
68100			obsv.isValid(errors.length === 0);
68101		});
68102	}
68103
68104	obsv.subscribe(function(newValue) {
68105		if (!kv.utils.isObject(newValue)) {
68106			/*
68107			 * The validation group works on objects.
68108			 * Since the new value is a primitive (scalar, null or undefined) we need
68109			 * to create an empty object to pass along.
68110			 */
68111			newValue = {};
68112		}
68113		// Force the group to refresh
68114		obsv.errors._updateState(newValue);
68115		obsv.isValid(obsv.errors().length === 0);
68116	});
68117
68118	return obsv;
68119};
68120;}));
68121(function(window, factory) {
68122	var lazySizes = factory(window, window.document);
68123	window.lazySizes = lazySizes;
68124	if(typeof module == 'object' && module.exports){
68125		module.exports = lazySizes;
68126	} else if (typeof define == 'function' && define.amd) {
68127		define('lazysizes',lazySizes);
68128	}
68129}(window, function(window, document) {
68130	'use strict';
68131	/*jshint eqnull:true */
68132	if(!document.getElementsByClassName){return;}
68133
68134	var lazySizesConfig;
68135
68136	var docElem = document.documentElement;
68137
68138	var addEventListener = window.addEventListener;
68139
68140	var regPicture = /^picture$/i;
68141
68142	var loadEvents = ['load', 'error', 'lazyincluded', '_lazyloaded'];
68143
68144	var hasClass = function(ele, cls) {
68145		var reg = new RegExp('(\\s|^)'+cls+'(\\s|$)');
68146		return ele.className.match(reg) && reg;
68147	};
68148
68149	var addClass = function(ele, cls) {
68150		if (!hasClass(ele, cls)){
68151			ele.className += ' '+cls;
68152		}
68153	};
68154
68155	var removeClass = function(ele, cls) {
68156		var reg;
68157		if ((reg = hasClass(ele,cls))) {
68158			ele.className = ele.className.replace(reg, ' ');
68159		}
68160	};
68161
68162	var addRemoveLoadEvents = function(dom, fn, add){
68163		var action = add ? 'addEventListener' : 'removeEventListener';
68164		if(add){
68165			addRemoveLoadEvents(dom, fn);
68166		}
68167		loadEvents.forEach(function(evt){
68168			dom[action](evt, fn);
68169		});
68170	};
68171
68172	var triggerEvent = function(elem, name, details, noBubbles, noCanceable){
68173		var event = document.createEvent('Event');
68174
68175		event.initEvent(name, !noBubbles, !noCanceable);
68176
68177		event.details = details || {};
68178
68179		elem.dispatchEvent(event);
68180		return event;
68181	};
68182
68183	var updatePolyfill = function (el, full){
68184		var polyfill;
68185		if(!window.HTMLPictureElement){
68186			if( ( polyfill = (window.picturefill || window.respimage || lazySizesConfig.pf) ) ){
68187				polyfill({reevaluate: true, reparse: true, elements: [el]});
68188			} else if(full && full.src){
68189				el.src = full.src;
68190			}
68191		}
68192	};
68193
68194	var getCSS = function (elem, style){
68195		return getComputedStyle(elem, null)[style];
68196	};
68197
68198	var getWidth = function(elem, parent){
68199		var width = elem.offsetWidth;
68200
68201		while(width < lazySizesConfig.minSize && parent && !elem._lazysizesWidth){
68202			width =  parent.offsetWidth;
68203			parent = parent.parentNode;
68204		}
68205
68206		return width;
68207	};
68208
68209	var throttle = function(fn){
68210		var run, timer;
68211		var main = function(){
68212			if(run){
68213				run = false;
68214				fn();
68215			}
68216		};
68217		var handleVisibility = function(){
68218			clearInterval(timer);
68219			if(!document.hidden){
68220				main();
68221				timer = setInterval(main, 51);
68222			}
68223		};
68224
68225		document.addEventListener('visibilitychange', handleVisibility);
68226		handleVisibility();
68227
68228		return function(force){
68229			run = true;
68230			if(force === true){
68231				main();
68232			}
68233		};
68234	};
68235
68236	var loader = (function(){
68237		var lazyloadElems, preloadElems, isCompleted, resetPreloadingTimer, loadMode;
68238
68239		var eLvW, elvH, eLtop, eLleft, eLright, eLbottom;
68240
68241		var defaultExpand, preloadExpand;
68242
68243		var regImg = /^img$/i;
68244		var regIframe = /^iframe$/i;
68245
68246		var supportScroll = ('onscroll' in window) && !(/glebot/.test(navigator.userAgent));
68247
68248		var shrinkExpand = 0;
68249		var currentExpand = 0;
68250		var lowRuns = 0;
68251
68252		var isLoading = 0;
68253
68254		var checkElementsIndex = 0;
68255
68256		var resetPreloading = function(e){
68257			isLoading--;
68258			if(e && e.target){
68259				addRemoveLoadEvents(e.target, resetPreloading);
68260			}
68261
68262			if(!e || isLoading < 0 || !e.target){
68263				isLoading = 0;
68264			}
68265		};
68266
68267		var isNestedVisible = function(elem, elemExpand){
68268			var outerRect;
68269			var parent = elem;
68270			var visible = getCSS(elem, 'visibility') != 'hidden';
68271
68272			eLtop -= elemExpand;
68273			eLbottom += elemExpand;
68274			eLleft -= elemExpand;
68275			eLright += elemExpand;
68276
68277			while(visible && (parent = parent.offsetParent)){
68278				visible = (isCompleted && isLoading < 2) || ((getCSS(parent, 'opacity') || 1) > 0);
68279
68280				if(visible && getCSS(parent, 'overflow') != 'visible'){
68281					outerRect = parent.getBoundingClientRect();
68282					visible = eLright > outerRect.left &&
68283					eLleft < outerRect.right &&
68284					eLbottom > outerRect.top - 1 &&
68285					eLtop < outerRect.bottom + 1
68286					;
68287				}
68288			}
68289			return visible;
68290		};
68291
68292		var checkElements = function() {
68293			var i, start, rect, autoLoadElem, loadedSomething, elemExpand, elemNegativeExpand, elemExpandVal, beforeExpandVal;
68294
68295			var eLlen = lazyloadElems.length;
68296
68297			if(eLlen && (loadMode = lazySizesConfig.loadMode)){
68298				start = Date.now();
68299
68300				i = checkElementsIndex;
68301
68302				lowRuns++;
68303
68304				if(currentExpand < preloadExpand && isLoading < 1 && lowRuns > 5 && loadMode > 2){
68305					currentExpand = preloadExpand;
68306					lowRuns = 0;
68307				} else if(currentExpand != defaultExpand && loadMode > 1 && lowRuns > 4){
68308					currentExpand = defaultExpand;
68309				} else {
68310					currentExpand = shrinkExpand;
68311				}
68312
68313				for(; i < eLlen; i++, checkElementsIndex++){
68314
68315					if(!lazyloadElems[i] || lazyloadElems[i]._lazyRace){continue;}
68316
68317					if(!supportScroll){unveilElement(lazyloadElems[i]);continue;}
68318
68319					if(!(elemExpandVal = lazyloadElems[i].getAttribute('data-expand')) || !(elemExpand = elemExpandVal * 1)){
68320						elemExpand = currentExpand;
68321					}
68322
68323					if(isLoading > 6 && (!elemExpandVal || ('src' in lazyloadElems[i]))){continue;}
68324
68325					if(elemExpand > shrinkExpand && (loadMode < 2 || isLoading > 3)){
68326						elemExpand = shrinkExpand;
68327					}
68328
68329					if(beforeExpandVal !== elemExpand){
68330						eLvW = innerWidth + elemExpand;
68331						elvH = innerHeight + elemExpand;
68332						elemNegativeExpand = elemExpand * -1;
68333						beforeExpandVal = elemExpand;
68334					}
68335
68336					rect = lazyloadElems[i].getBoundingClientRect();
68337
68338					if ((eLbottom = rect.bottom) >= elemNegativeExpand &&
68339						(eLtop = rect.top) <= elvH &&
68340						(eLright = rect.right) >= elemNegativeExpand &&
68341						(eLleft = rect.left) <= eLvW &&
68342						(eLbottom || eLright || eLleft || eLtop) &&
68343						((isCompleted && currentExpand < preloadExpand && isLoading < 3 && lowRuns < 4 && !elemExpandVal && loadMode > 2) || isNestedVisible(lazyloadElems[i], elemExpand))){
68344						checkElementsIndex--;
68345						start += 2;
68346						unveilElement(lazyloadElems[i]);
68347						loadedSomething = true;
68348					} else  {
68349						if(Date.now() - start > 3){
68350							checkElementsIndex++;
68351							throttledCheckElements();
68352							return;
68353						}
68354
68355						if(!loadedSomething && isCompleted && !autoLoadElem &&
68356							isLoading < 3 && lowRuns < 4 && loadMode > 2 &&
68357							(preloadElems[0] || lazySizesConfig.preloadAfterLoad) &&
68358							(preloadElems[0] || (!elemExpandVal && ((eLbottom || eLright || eLleft || eLtop) || lazyloadElems[i].getAttribute(lazySizesConfig.sizesAttr) != 'auto')))){
68359							autoLoadElem = preloadElems[0] || lazyloadElems[i];
68360						}
68361					}
68362				}
68363
68364				checkElementsIndex = 0;
68365
68366				if(autoLoadElem && !loadedSomething){
68367					unveilElement(autoLoadElem);
68368				}
68369			}
68370		};
68371
68372		var throttledCheckElements = throttle(checkElements);
68373
68374		var switchLoadingClass = function(e){
68375			addClass(e.target, lazySizesConfig.loadedClass);
68376			removeClass(e.target, lazySizesConfig.loadingClass);
68377			addRemoveLoadEvents(e.target, switchLoadingClass);
68378		};
68379
68380		var changeIframeSrc = function(elem, src){
68381			try {
68382				elem.contentWindow.location.replace(src);
68383			} catch(e){
68384				elem.setAttribute('src', src);
68385			}
68386		};
68387
68388		var unveilElement = function (elem, force){
68389			var sources, i, len, sourceSrcset, src, srcset, parent, isPicture, event, firesLoad, customMedia;
68390
68391			var curSrc = elem.currentSrc || elem.src;
68392			var isImg = regImg.test(elem.nodeName);
68393
68394			//allow using sizes="auto", but don't use. it's invalid. Use data-sizes="auto" or a valid value for sizes instead (i.e.: sizes="80vw")
68395			var sizes = elem.getAttribute(lazySizesConfig.sizesAttr) || elem.getAttribute('sizes');
68396			var isAuto = sizes == 'auto';
68397
68398			if( (isAuto || !isCompleted) && isImg && curSrc && !elem.complete && !hasClass(elem, lazySizesConfig.errorClass)){return;}
68399
68400			elem._lazyRace = true;
68401
68402			if(!(event = triggerEvent(elem, 'lazybeforeunveil', {force: !!force})).defaultPrevented){
68403
68404				if(sizes){
68405					if(isAuto){
68406						autoSizer.updateElem(elem, true);
68407					} else {
68408						elem.setAttribute('sizes', sizes);
68409					}
68410				}
68411
68412				srcset = elem.getAttribute(lazySizesConfig.srcsetAttr);
68413				src = elem.getAttribute(lazySizesConfig.srcAttr);
68414
68415				if(isImg) {
68416					parent = elem.parentNode;
68417					isPicture = regPicture.test(parent.nodeName || '');
68418				}
68419
68420				firesLoad = event.details.firesLoad || (('src' in elem) && (srcset || src || isPicture));
68421
68422				if(firesLoad){
68423					isLoading++;
68424					addRemoveLoadEvents(elem, resetPreloading, true);
68425					clearTimeout(resetPreloadingTimer);
68426					resetPreloadingTimer = setTimeout(resetPreloading, 3000);
68427				}
68428
68429				if(isPicture){
68430					sources = parent.getElementsByTagName('source');
68431					for(i = 0, len = sources.length; i < len; i++){
68432						if( (customMedia = lazySizesConfig.customMedia[sources[i].getAttribute('data-media') || sources[i].getAttribute('media')]) ){
68433							sources[i].setAttribute('media', customMedia);
68434						}
68435						sourceSrcset = sources[i].getAttribute(lazySizesConfig.srcsetAttr);
68436						if(sourceSrcset){
68437							sources[i].setAttribute('srcset', sourceSrcset);
68438						}
68439					}
68440				}
68441
68442				if(srcset){
68443					elem.setAttribute('srcset', srcset);
68444				} else if(src){
68445					if(regIframe.test(elem.nodeName)){
68446						changeIframeSrc(elem, src);
68447					} else {
68448						elem.setAttribute('src', src);
68449					}
68450				}
68451
68452				addClass(elem, lazySizesConfig.loadingClass);
68453				addRemoveLoadEvents(elem, switchLoadingClass, true);
68454			}
68455
68456			setTimeout(function(){
68457				if(elem._lazyRace){
68458					delete elem._lazyRace;
68459				}
68460
68461				if(sizes == 'auto'){
68462					addClass(elem, lazySizesConfig.autosizesClass);
68463				}
68464
68465				if(srcset || isPicture){
68466					updatePolyfill(elem, {src: src});
68467				}
68468
68469				removeClass(elem, lazySizesConfig.lazyClass);
68470
68471				//remove curSrc == (elem.currentSrc || elem.src) it's a workaround for FF. see: https://bugzilla.mozilla.org/show_bug.cgi?id=608261
68472				if( !firesLoad || (elem.complete && curSrc == (elem.currentSrc || elem.src)) ){
68473					if(firesLoad){
68474						resetPreloading(event);
68475					}
68476					switchLoadingClass(event);
68477				}
68478				elem = null;
68479			});
68480		};
68481
68482		var onload = function(){
68483			var scrollTimer;
68484			var afterScroll = function(){
68485				lazySizesConfig.loadMode = 3;
68486				throttledCheckElements();
68487			};
68488
68489			isCompleted = true;
68490			lowRuns += 8;
68491
68492			lazySizesConfig.loadMode = 3;
68493			throttledCheckElements(true);
68494
68495			addEventListener('scroll', function(){
68496				if(lazySizesConfig.loadMode == 3){
68497					lazySizesConfig.loadMode = 2;
68498				}
68499				clearTimeout(scrollTimer);
68500				scrollTimer = setTimeout(afterScroll, 66);
68501			}, true);
68502		};
68503
68504		return {
68505			_: function(){
68506
68507				lazyloadElems = document.getElementsByClassName(lazySizesConfig.lazyClass);
68508				preloadElems = document.getElementsByClassName(lazySizesConfig.lazyClass + ' ' + lazySizesConfig.preloadClass);
68509
68510				defaultExpand = lazySizesConfig.expand;
68511				preloadExpand = defaultExpand * lazySizesConfig.expFactor;
68512
68513				addEventListener('scroll', throttledCheckElements, true);
68514
68515				addEventListener('resize', throttledCheckElements, true);
68516
68517				if(window.MutationObserver){
68518					new MutationObserver( throttledCheckElements ).observe( docElem, {childList: true, subtree: true, attributes: true} );
68519				} else {
68520					docElem.addEventListener('DOMNodeInserted', throttledCheckElements, true);
68521					docElem.addEventListener('DOMAttrModified', throttledCheckElements, true);
68522					setInterval(throttledCheckElements, 3000);
68523				}
68524
68525				addEventListener('hashchange', throttledCheckElements, true);
68526
68527				['transitionstart', 'transitionend', 'load', 'focus', 'mouseover', 'animationend', 'click'].forEach(function(name){
68528					document.addEventListener(name, throttledCheckElements, true);
68529				});
68530
68531				if(!(isCompleted = /d$|^c/.test(document.readyState))){
68532					addEventListener('load', onload);
68533					document.addEventListener('DOMContentLoaded', throttledCheckElements);
68534				} else {
68535					onload();
68536				}
68537
68538				throttledCheckElements(lazyloadElems.length > 0);
68539			},
68540			checkElems: throttledCheckElements,
68541			unveil: unveilElement
68542		};
68543	})();
68544
68545
68546	var autoSizer = (function(){
68547		var autosizesElems;
68548
68549		var sizeElement = function (elem, dataAttr){
68550			var width, sources, i, len, event;
68551			var parent = elem.parentNode;
68552
68553			if(parent){
68554				width = getWidth(elem, parent);
68555				event = triggerEvent(elem, 'lazybeforesizes', {width: width, dataAttr: !!dataAttr});
68556
68557				if(!event.defaultPrevented){
68558					width = event.details.width;
68559
68560					if(width && width !== elem._lazysizesWidth){
68561						elem._lazysizesWidth = width;
68562						width += 'px';
68563						elem.setAttribute('sizes', width);
68564
68565						if(regPicture.test(parent.nodeName || '')){
68566							sources = parent.getElementsByTagName('source');
68567							for(i = 0, len = sources.length; i < len; i++){
68568								sources[i].setAttribute('sizes', width);
68569							}
68570						}
68571
68572						if(!event.details.dataAttr){
68573							updatePolyfill(elem, event.details);
68574						}
68575					}
68576				}
68577			}
68578		};
68579
68580		var updateElementsSizes = function(){
68581			var i;
68582			var len = autosizesElems.length;
68583			if(len){
68584				i = 0;
68585
68586				for(; i < len; i++){
68587					sizeElement(autosizesElems[i]);
68588				}
68589			}
68590		};
68591
68592		var throttledUpdateElementsSizes = throttle(updateElementsSizes);
68593
68594		return {
68595			_: function(){
68596				autosizesElems = document.getElementsByClassName(lazySizesConfig.autosizesClass);
68597				addEventListener('resize', throttledUpdateElementsSizes);
68598			},
68599			checkElems: throttledUpdateElementsSizes,
68600			updateElem: sizeElement
68601		};
68602	})();
68603
68604	var init = function(){
68605		if(!init.i){
68606			init.i = true;
68607			autoSizer._();
68608			loader._();
68609		}
68610	};
68611
68612	(function(){
68613		var prop;
68614		var lazySizesDefaults = {
68615			lazyClass: 'lazyload',
68616			loadedClass: 'lazyloaded',
68617			loadingClass: 'lazyloading',
68618			preloadClass: 'lazypreload',
68619			errorClass: 'lazyerror',
68620			autosizesClass: 'lazyautosizes',
68621			srcAttr: 'data-src',
68622			srcsetAttr: 'data-srcset',
68623			sizesAttr: 'data-sizes',
68624			//preloadAfterLoad: false,
68625			minSize: 50,
68626			customMedia: {},
68627			init: true,
68628			expFactor: 2,
68629			expand: 300,
68630			loadMode: 2
68631		};
68632
68633		lazySizesConfig = window.lazySizesConfig || {};
68634
68635		for(prop in lazySizesDefaults){
68636			if(!(prop in lazySizesConfig)){
68637				lazySizesConfig[prop] = lazySizesDefaults[prop];
68638			}
68639		}
68640
68641		window.lazySizesConfig = lazySizesConfig;
68642
68643		setTimeout(function(){
68644			if(lazySizesConfig.init){
68645				init();
68646			}
68647		});
68648	})();
68649
68650	return {
68651		cfg: lazySizesConfig,
68652		autoSizer: autoSizer,
68653		loader: loader,
68654		init: init,
68655		uP: updatePolyfill,
68656		aC: addClass,
68657		rC: removeClass,
68658		hC: hasClass,
68659		fire: triggerEvent,
68660		gW: getWidth
68661	};
68662}));
68663
68664/*!
68665 * Modernizr v2.7.2
68666 * www.modernizr.com
68667 *
68668 * Copyright (c) Faruk Ates, Paul Irish, Alex Sexton
68669 * Available under the BSD and MIT licenses: www.modernizr.com/license/
68670 */
68671
68672/*
68673 * Modernizr tests which native CSS3 and HTML5 features are available in
68674 * the current UA and makes the results available to you in two ways:
68675 * as properties on a global Modernizr object, and as classes on the
68676 * <html> element. This information allows you to progressively enhance
68677 * your pages with a granular level of control over the experience.
68678 *
68679 * Modernizr has an optional (not included) conditional resource loader
68680 * called Modernizr.load(), based on Yepnope.js (yepnopejs.com).
68681 * To get a build that includes Modernizr.load(), as well as choosing
68682 * which tests to include, go to www.modernizr.com/download/
68683 *
68684 * Authors        Faruk Ates, Paul Irish, Alex Sexton
68685 * Contributors   Ryan Seddon, Ben Alman
68686 */
68687
68688window.Modernizr = (function( window, document, undefined ) {
68689
68690    var version = '2.7.2',
68691
68692    Modernizr = {},
68693
68694    /*>>cssclasses*/
68695    // option for enabling the HTML classes to be added
68696    enableClasses = true,
68697    /*>>cssclasses*/
68698
68699    docElement = document.documentElement,
68700
68701    /**
68702     * Create our "modernizr" element that we do most feature tests on.
68703     */
68704    mod = 'modernizr',
68705    modElem = document.createElement(mod),
68706    mStyle = modElem.style,
68707
68708    /**
68709     * Create the input element for various Web Forms feature tests.
68710     */
68711    inputElem /*>>inputelem*/ = document.createElement('input') /*>>inputelem*/ ,
68712
68713    /*>>smile*/
68714    smile = ':)',
68715    /*>>smile*/
68716
68717    toString = {}.toString,
68718
68719    // TODO :: make the prefixes more granular
68720    /*>>prefixes*/
68721    // List of property values to set for css tests. See ticket #21
68722    prefixes = ' -webkit- -moz- -o- -ms- '.split(' '),
68723    /*>>prefixes*/
68724
68725    /*>>domprefixes*/
68726    // Following spec is to expose vendor-specific style properties as:
68727    //   elem.style.WebkitBorderRadius
68728    // and the following would be incorrect:
68729    //   elem.style.webkitBorderRadius
68730
68731    // Webkit ghosts their properties in lowercase but Opera & Moz do not.
68732    // Microsoft uses a lowercase `ms` instead of the correct `Ms` in IE8+
68733    //   erik.eae.net/archives/2008/03/10/21.48.10/
68734
68735    // More here: github.com/Modernizr/Modernizr/issues/issue/21
68736    omPrefixes = 'Webkit Moz O ms',
68737
68738    cssomPrefixes = omPrefixes.split(' '),
68739
68740    domPrefixes = omPrefixes.toLowerCase().split(' '),
68741    /*>>domprefixes*/
68742
68743    /*>>ns*/
68744    ns = {'svg': 'http://www.w3.org/2000/svg'},
68745    /*>>ns*/
68746
68747    tests = {},
68748    inputs = {},
68749    attrs = {},
68750
68751    classes = [],
68752
68753    slice = classes.slice,
68754
68755    featureName, // used in testing loop
68756
68757
68758    /*>>
vendor: 21,732 bytes, lines 68758-69367
68758teststyles*/
68759    // Inject element with style element and some CSS rules
68760    injectElementWithStyles = function( rule, callback, nodes, testnames ) {
68761
68762      var style, ret, node, docOverflow,
68763          div = document.createElement('div'),
68764          // After page load injecting a fake body doesn't work so check if body exists
68765          body = document.body,
68766          // IE6 and 7 won't return offsetWidth or offsetHeight unless it's in the body element, so we fake it.
68767          fakeBody = body || document.createElement('body');
68768
68769      if ( parseInt(nodes, 10) ) {
68770          // In order not to give false positives we create a node for each test
68771          // This also allows the method to scale for unspecified uses
68772          while ( nodes-- ) {
68773              node = document.createElement('div');
68774              node.id = testnames ? testnames[nodes] : mod + (nodes + 1);
68775              div.appendChild(node);
68776          }
68777      }
68778
68779      // <style> elements in IE6-9 are considered 'NoScope' elements and therefore will be removed
68780      // when injected with innerHTML. To get around this you need to prepend the 'NoScope' element
68781      // with a 'scoped' element, in our case the soft-hyphen entity as it won't mess with our measurements.
68782      // msdn.microsoft.com/en-us/library/ms533897%28VS.85%29.aspx
68783      // Documents served as xml will throw if using &shy; so use xml friendly encoded version. See issue #277
68784      style = ['&#173;','<style id="s', mod, '">', rule, '</style>'].join('');
68785      div.id = mod;
68786      // IE6 will false positive on some tests due to the style element inside the test div somehow interfering offsetHeight, so insert it into body or fakebody.
68787      // Opera will act all quirky when injecting elements in documentElement when page is served as xml, needs fakebody too. #270
68788      (body ? div : fakeBody).innerHTML += style;
68789      fakeBody.appendChild(div);
68790      if ( !body ) {
68791          //avoid crashing IE8, if background image is used
68792          fakeBody.style.background = '';
68793          //Safari 5.13/5.1.4 OSX stops loading if ::-webkit-scrollbar is used and scrollbars are visible
68794          fakeBody.style.overflow = 'hidden';
68795          docOverflow = docElement.style.overflow;
68796          docElement.style.overflow = 'hidden';
68797          docElement.appendChild(fakeBody);
68798      }
68799
68800      ret = callback(div, rule);
68801      // If this is done after page load we don't want to remove the body so check if body exists
68802      if ( !body ) {
68803          fakeBody.parentNode.removeChild(fakeBody);
68804          docElement.style.overflow = docOverflow;
68805      } else {
68806          div.parentNode.removeChild(div);
68807      }
68808
68809      return !!ret;
68810
68811    },
68812    /*>>teststyles*/
68813
68814    /*>>mq*/
68815    // adapted from matchMedia polyfill
68816    // by Scott Jehl and Paul Irish
68817    // gist.github.com/786768
68818    testMediaQuery = function( mq ) {
68819
68820      var matchMedia = window.matchMedia || window.msMatchMedia;
68821      if ( matchMedia ) {
68822        return matchMedia(mq).matches;
68823      }
68824
68825      var bool;
68826
68827      injectElementWithStyles('@media ' + mq + ' { #' + mod + ' { position: absolute; } }', function( node ) {
68828        bool = (window.getComputedStyle ?
68829                  getComputedStyle(node, null) :
68830                  node.currentStyle)['position'] == 'absolute';
68831      });
68832
68833      return bool;
68834
68835     },
68836     /*>>mq*/
68837
68838
68839    /*>>hasevent*/
68840    //
68841    // isEventSupported determines if a given element supports the given event
68842    // kangax.github.com/iseventsupported/
68843    //
68844    // The following results are known incorrects:
68845    //   Modernizr.hasEvent("webkitTransitionEnd", elem) // false negative
68846    //   Modernizr.hasEvent("textInput") // in Webkit. github.com/Modernizr/Modernizr/issues/333
68847    //   ...
68848    isEventSupported = (function() {
68849
68850      var TAGNAMES = {
68851        'select': 'input', 'change': 'input',
68852        'submit': 'form', 'reset': 'form',
68853        'error': 'img', 'load': 'img', 'abort': 'img'
68854      };
68855
68856      function isEventSupported( eventName, element ) {
68857
68858        element = element || document.createElement(TAGNAMES[eventName] || 'div');
68859        eventName = 'on' + eventName;
68860
68861        // When using `setAttribute`, IE skips "unload", WebKit skips "unload" and "resize", whereas `in` "catches" those
68862        var isSupported = eventName in element;
68863
68864        if ( !isSupported ) {
68865          // If it has no `setAttribute` (i.e. doesn't implement Node interface), try generic element
68866          if ( !element.setAttribute ) {
68867            element = document.createElement('div');
68868          }
68869          if ( element.setAttribute && element.removeAttribute ) {
68870            element.setAttribute(eventName, '');
68871            isSupported = is(element[eventName], 'function');
68872
68873            // If property was created, "remove it" (by setting value to `undefined`)
68874            if ( !is(element[eventName], 'undefined') ) {
68875              element[eventName] = undefined;
68876            }
68877            element.removeAttribute(eventName);
68878          }
68879        }
68880
68881        element = null;
68882        return isSupported;
68883      }
68884      return isEventSupported;
68885    })(),
68886    /*>>hasevent*/
68887
68888    // TODO :: Add flag for hasownprop ? didn't last time
68889
68890    // hasOwnProperty shim by kangax needed for Safari 2.0 support
68891    _hasOwnProperty = ({}).hasOwnProperty, hasOwnProp;
68892
68893    if ( !is(_hasOwnProperty, 'undefined') && !is(_hasOwnProperty.call, 'undefined') ) {
68894      hasOwnProp = function (object, property) {
68895        return _hasOwnProperty.call(object, property);
68896      };
68897    }
68898    else {
68899      hasOwnProp = function (object, property) { /* yes, this can give false positives/negatives, but most of the time we don't care about those */
68900        return ((property in object) && is(object.constructor.prototype[property], 'undefined'));
68901      };
68902    }
68903
68904    // Adapted from ES5-shim https://github.com/kriskowal/es5-shim/blob/master/es5-shim.js
68905    // es5.github.com/#x15.3.4.5
68906
68907    if (!Function.prototype.bind) {
68908      Function.prototype.bind = function bind(that) {
68909
68910        var target = this;
68911
68912        if (typeof target != "function") {
68913            throw new TypeError();
68914        }
68915
68916        var args = slice.call(arguments, 1),
68917            bound = function () {
68918
68919            if (this instanceof bound) {
68920
68921              var F = function(){};
68922              F.prototype = target.prototype;
68923              var self = new F();
68924
68925              var result = target.apply(
68926                  self,
68927                  args.concat(slice.call(arguments))
68928              );
68929              if (Object(result) === result) {
68930                  return result;
68931              }
68932              return self;
68933
68934            } else {
68935
68936              return target.apply(
68937                  that,
68938                  args.concat(slice.call(arguments))
68939              );
68940
68941            }
68942
68943        };
68944
68945        return bound;
68946      };
68947    }
68948
68949    /**
68950     * setCss applies given styles to the Modernizr DOM node.
68951     */
68952    function setCss( str ) {
68953        mStyle.cssText = str;
68954    }
68955
68956    /**
68957     * setCssAll extrapolates all vendor-specific css strings.
68958     */
68959    function setCssAll( str1, str2 ) {
68960        return setCss(prefixes.join(str1 + ';') + ( str2 || '' ));
68961    }
68962
68963    /**
68964     * is returns a boolean for if typeof obj is exactly type.
68965     */
68966    function is( obj, type ) {
68967        return typeof obj === type;
68968    }
68969
68970    /**
68971     * contains returns a boolean for if substr is found within str.
68972     */
68973    function contains( str, substr ) {
68974        return !!~('' + str).indexOf(substr);
68975    }
68976
68977    /*>>testprop*/
68978
68979    // testProps is a generic CSS / DOM property test.
68980
68981    // In testing support for a given CSS property, it's legit to test:
68982    //    `elem.style[styleName] !== undefined`
68983    // If the property is supported it will return an empty string,
68984    // if unsupported it will return undefined.
68985
68986    // We'll take advantage of this quick test and skip setting a style
68987    // on our modernizr element, but instead just testing undefined vs
68988    // empty string.
68989
68990    // Because the testing of the CSS property names (with "-", as
68991    // opposed to the camelCase DOM properties) is non-portable and
68992    // non-standard but works in WebKit and IE (but not Gecko or Opera),
68993    // we explicitly reject properties with dashes so that authors
68994    // developing in WebKit or IE first don't end up with
68995    // browser-specific content by accident.
68996
68997    function testProps( props, prefixed ) {
68998        for ( var i in props ) {
68999            var prop = props[i];
69000            if ( !contains(prop, "-") && mStyle[prop] !== undefined ) {
69001                return prefixed == 'pfx' ? prop : true;
69002            }
69003        }
69004        return false;
69005    }
69006    /*>>testprop*/
69007
69008    // TODO :: add testDOMProps
69009    /**
69010     * testDOMProps is a generic DOM property test; if a browser supports
69011     *   a certain property, it won't return undefined for it.
69012     */
69013    function testDOMProps( props, obj, elem ) {
69014        for ( var i in props ) {
69015            var item = obj[props[i]];
69016            if ( item !== undefined) {
69017
69018                // return the property name as a string
69019                if (elem === false) return props[i];
69020
69021                // let's bind a function
69022                if (is(item, 'function')){
69023                  // default to autobind unless override
69024                  return item.bind(elem || obj);
69025                }
69026
69027                // return the unbound function or obj or value
69028                return item;
69029            }
69030        }
69031        return false;
69032    }
69033
69034    /*>>testallprops*/
69035    /**
69036     * testPropsAll tests a list of DOM properties we want to check against.
69037     *   We specify literally ALL possible (known and/or likely) properties on
69038     *   the element including the non-vendor prefixed one, for forward-
69039     *   compatibility.
69040     */
69041    function testPropsAll( prop, prefixed, elem ) {
69042
69043        var ucProp  = prop.charAt(0).toUpperCase() + prop.slice(1),
69044            props   = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' ');
69045
69046        // did they call .prefixed('boxSizing') or are we just testing a prop?
69047        if(is(prefixed, "string") || is(prefixed, "undefined")) {
69048          return testProps(props, prefixed);
69049
69050        // otherwise, they called .prefixed('requestAnimationFrame', window[, elem])
69051        } else {
69052          props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' ');
69053          return testDOMProps(props, prefixed, elem);
69054        }
69055    }
69056    /*>>testallprops*/
69057
69058
69059    /**
69060     * Tests
69061     * -----
69062     */
69063
69064    // The *new* flexbox
69065    // dev.w3.org/csswg/css3-flexbox
69066
69067    tests['flexbox'] = function() {
69068      return testPropsAll('flexWrap');
69069    };
69070
69071    // The *old* flexbox
69072    // www.w3.org/TR/2009/WD-css3-flexbox-20090723/
69073
69074    tests['flexboxlegacy'] = function() {
69075        return testPropsAll('boxDirection');
69076    };
69077
69078    // On the S60 and BB Storm, getContext exists, but always returns undefined
69079    // so we actually have to call getContext() to verify
69080    // github.com/Modernizr/Modernizr/issues/issue/97/
69081
69082    tests['canvas'] = function() {
69083        var elem = document.createElement('canvas');
69084        return !!(elem.getContext && elem.getContext('2d'));
69085    };
69086
69087    tests['canvastext'] = function() {
69088        return !!(Modernizr['canvas'] && is(document.createElement('canvas').getContext('2d').fillText, 'function'));
69089    };
69090
69091    // webk.it/70117 is tracking a legit WebGL feature detect proposal
69092
69093    // We do a soft detect which may false positive in order to avoid
69094    // an expensive context creation: bugzil.la/732441
69095
69096    tests['webgl'] = function() {
69097        return !!window.WebGLRenderingContext;
69098    };
69099
69100    /*
69101     * The Modernizr.touch test only indicates if the browser supports
69102     *    touch events, which does not necessarily reflect a touchscreen
69103     *    device, as evidenced by tablets running Windows 7 or, alas,
69104     *    the Palm Pre / WebOS (touch) phones.
69105     *
69106     * Additionally, Chrome (desktop) used to lie about its support on this,
69107     *    but that has since been rectified: crbug.com/36415
69108     *
69109     * We also test for Firefox 4 Multitouch Support.
69110     *
69111     * For more info, see: modernizr.github.com/Modernizr/touch.html
69112     */
69113
69114    tests['touch'] = function() {
69115        var bool;
69116
69117        if(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) {
69118          bool = true;
69119        } else {
69120          injectElementWithStyles(['@media (',prefixes.join('touch-enabled),('),mod,')','{#modernizr{top:9px;position:absolute}}'].join(''), function( node ) {
69121            bool = node.offsetTop === 9;
69122          });
69123        }
69124
69125        return bool;
69126    };
69127
69128
69129    // geolocation is often considered a trivial feature detect...
69130    // Turns out, it's quite tricky to get right:
69131    //
69132    // Using !!navigator.geolocation does two things we don't want. It:
69133    //   1. Leaks memory in IE9: github.com/Modernizr/Modernizr/issues/513
69134    //   2. Disables page caching in WebKit: webk.it/43956
69135    //
69136    // Meanwhile, in Firefox < 8, an about:config setting could expose
69137    // a false positive that would throw an exception: bugzil.la/688158
69138
69139    tests['geolocation'] = function() {
69140        return 'geolocation' in navigator;
69141    };
69142
69143
69144    tests['postmessage'] = function() {
69145      return !!window.postMessage;
69146    };
69147
69148
69149    // Chrome incognito mode used to throw an exception when using openDatabase
69150    // It doesn't anymore.
69151    tests['websqldatabase'] = function() {
69152      return !!window.openDatabase;
69153    };
69154
69155    // Vendors had inconsistent prefixing with the experimental Indexed DB:
69156    // - Webkit's implementation is accessible through webkitIndexedDB
69157    // - Firefox shipped moz_indexedDB before FF4b9, but since then has been mozIndexedDB
69158    // For speed, we don't test the legacy (and beta-only) indexedDB
69159    tests['indexedDB'] = function() {
69160      return !!testPropsAll("indexedDB", window);
69161    };
69162
69163    // documentMode logic from YUI to filter out IE8 Compat Mode
69164    //   which false positives.
69165    tests['hashchange'] = function() {
69166      return isEventSupported('hashchange', window) && (document.documentMode === undefined || document.documentMode > 7);
69167    };
69168
69169    // Per 1.6:
69170    // This used to be Modernizr.historymanagement but the longer
69171    // name has been deprecated in favor of a shorter and property-matching one.
69172    // The old API is still available in 1.6, but as of 2.0 will throw a warning,
69173    // and in the first release thereafter disappear entirely.
69174    tests['history'] = function() {
69175      return !!(window.history && history.pushState);
69176    };
69177
69178    tests['draganddrop'] = function() {
69179        var div = document.createElement('div');
69180        return ('draggable' in div) || ('ondragstart' in div && 'ondrop' in div);
69181    };
69182
69183    // FF3.6 was EOL'ed on 4/24/12, but the ESR version of FF10
69184    // will be supported until FF19 (2/12/13), at which time, ESR becomes FF17.
69185    // FF10 still uses prefixes, so check for it until then.
69186    // for more ESR info, see: mozilla.org/en-US/firefox/organizations/faq/
69187    tests['websockets'] = function() {
69188        return 'WebSocket' in window || 'MozWebSocket' in window;
69189    };
69190
69191
69192    // css-tricks.com/rgba-browser-support/
69193    tests['rgba'] = function() {
69194        // Set an rgba() color and check the returned value
69195
69196        setCss('background-color:rgba(150,255,150,.5)');
69197
69198        return contains(mStyle.backgroundColor, 'rgba');
69199    };
69200
69201    tests['hsla'] = function() {
69202        // Same as rgba(), in fact, browsers re-map hsla() to rgba() internally,
69203        //   except IE9 who retains it as hsla
69204
69205        setCss('background-color:hsla(120,40%,100%,.5)');
69206
69207        return contains(mStyle.backgroundColor, 'rgba') || contains(mStyle.backgroundColor, 'hsla');
69208    };
69209
69210    tests['multiplebgs'] = function() {
69211        // Setting multiple images AND a color on the background shorthand property
69212        //  and then querying the style.background property value for the number of
69213        //  occurrences of "url(" is a reliable method for detecting ACTUAL support for this!
69214
69215        setCss('background:url(https://),url(https://),red url(https://)');
69216
69217        // If the UA supports multiple backgrounds, there should be three occurrences
69218        //   of the string "url(" in the return value for elemStyle.background
69219
69220        return (/(url\s*\(.*?){3}/).test(mStyle.background);
69221    };
69222
69223
69224
69225    // this will false positive in Opera Mini
69226    //   github.com/Modernizr/Modernizr/issues/396
69227
69228    tests['backgroundsize'] = function() {
69229        return testPropsAll('backgroundSize');
69230    };
69231
69232    tests['borderimage'] = function() {
69233        return testPropsAll('borderImage');
69234    };
69235
69236
69237    // Super comprehensive table about all the unique implementations of
69238    // border-radius: muddledramblings.com/table-of-css3-border-radius-compliance
69239
69240    tests['borderradius'] = function() {
69241        return testPropsAll('borderRadius');
69242    };
69243
69244    // WebOS unfortunately false positives on this test.
69245    tests['boxshadow'] = function() {
69246        return testPropsAll('boxShadow');
69247    };
69248
69249    // FF3.0 will false positive on this test
69250    tests['textshadow'] = function() {
69251        return document.createElement('div').style.textShadow === '';
69252    };
69253
69254
69255    tests['opacity'] = function() {
69256        // Browsers that actually have CSS Opacity implemented have done so
69257        //  according to spec, which means their return values are within the
69258        //  range of [0.0,1.0] - including the leading zero.
69259
69260        setCssAll('opacity:.55');
69261
69262        // The non-literal . in this regex is intentional:
69263        //   German Chrome returns this value as 0,55
69264        // github.com/Modernizr/Modernizr/issues/#issue/59/comment/516632
69265        return (/^0.55$/).test(mStyle.opacity);
69266    };
69267
69268
69269    // Note, Android < 4 will pass this test, but can only animate
69270    //   a single property at a time
69271    //   goo.gl/v3V4Gp
69272    tests['cssanimations'] = function() {
69273        return testPropsAll('animationName');
69274    };
69275
69276
69277    tests['csscolumns'] = function() {
69278        return testPropsAll('columnCount');
69279    };
69280
69281
69282    tests['cssgradients'] = function() {
69283        /**
69284         * For CSS Gradients syntax, please see:
69285         * webkit.org/blog/175/introducing-css-gradients/
69286         * developer.mozilla.org/en/CSS/-moz-linear-gradient
69287         * developer.mozilla.org/en/CSS/-moz-radial-gradient
69288         * dev.w3.org/csswg/css3-images/#gradients-
69289         */
69290
69291        var str1 = 'background-image:',
69292            str2 = 'gradient(linear,left top,right bottom,from(#9f9),to(white));',
69293            str3 = 'linear-gradient(left top,#9f9, white);';
69294
69295        setCss(
69296             // legacy webkit syntax (FIXME: remove when syntax not in use anymore)
69297              (str1 + '-webkit- '.split(' ').join(str2 + str1) +
69298             // standard syntax             // trailing 'background-image:'
69299              prefixes.join(str3 + str1)).slice(0, -str1.length)
69300        );
69301
69302        return contains(mStyle.backgroundImage, 'gradient');
69303    };
69304
69305
69306    tests['cssreflections'] = function() {
69307        return testPropsAll('boxReflect');
69308    };
69309
69310
69311    tests['csstransforms'] = function() {
69312        return !!testPropsAll('transform');
69313    };
69314
69315
69316    tests['csstransforms3d'] = function() {
69317
69318        var ret = !!testPropsAll('perspective');
69319
69320        // Webkit's 3D transforms are passed off to the browser's own graphics renderer.
69321        //   It works fine in Safari on Leopard and Snow Leopard, but not in Chrome in
69322        //   some conditions. As a result, Webkit typically recognizes the syntax but
69323        //   will sometimes throw a false positive, thus we must do a more thorough check:
69324        if ( ret && 'webkitPerspective' in docElement.style ) {
69325
69326          // Webkit allows this media query to succeed only if the feature is enabled.
69327          // `@media (transform-3d),(-webkit-transform-3d){ ... }`
69328          injectElementWithStyles('@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}', function( node, rule ) {
69329            ret = node.offsetLeft === 9 && node.offsetHeight === 3;
69330          });
69331        }
69332        return ret;
69333    };
69334
69335
69336    tests['csstransitions'] = function() {
69337        return testPropsAll('transition');
69338    };
69339
69340
69341    /*>>fontface*/
69342    // @font-face detection routine by Diego Perini
69343    // javascript.nwbox.com/CSSSupport/
69344
69345    // false positives:
69346    //   WebOS github.com/Modernizr/Modernizr/issues/342
69347    //   WP7   github.com/Modernizr/Modernizr/issues/538
69348    tests['fontface'] = function() {
69349        var bool;
69350
69351        injectElementWithStyles('@font-face {font-family:"font";src:url("https://")}', function( node, rule ) {
69352          var style = document.getElementById('smodernizr'),
69353              sheet = style.sheet || style.styleSheet,
69354              cssText = sheet ? (sheet.cssRules && sheet.cssRules[0] ? sheet.cssRules[0].cssText : sheet.cssText || '') : '';
69355
69356          bool = /src/i.test(cssText) && cssText.indexOf(rule.split(' ')[0]) === 0;
69357        });
69358
69359        return bool;
69360    };
69361    /*>>fontface*/
69362
69363    // CSS generated content detection
69364    tests['generatedcontent'] = function() {
69365        var bool;
69366
69367        injectElementWithStyles(['#',mod,'{font:0/0 a}
69367#',mod,':after{content:"',smile,'";visibility:hidden;font:3px/1 a}'].join(''), function( node ) {
69368          bool = node.offsetHeight >= 3;
69369        });
69370
69371        return bool;
69372    };
69373
69374
69375
69376    // These tests evaluate support of the video/audio elements, as well as
69377    // testing what types of content they support.
69378    //
69379    // We're using the Boolean constructor here, so that we can extend the value
69380    // e.g.  Modernizr.video     // true
69381    //       Modernizr.video.ogg // 'probably'
69382    //
69383    // Codec values from : github.com/NielsLeenheer/html5test/blob/9106a8/index.html#L845
69384    //                     thx to NielsLeenheer and zcorpan
69385
69386    // Note: in some older browsers, "no" was a return value instead of empty string.
69387    //   It was live in FF3.5.0 and 3.5.1, but fixed in 3.5.2
69388    //   It was also live in Safari 4.0.0 - 4.0.4, but fixed in 4.0.5
69389
69390    tests['video'] = function() {
69391        var elem = document.createElement('video'),
69392            bool = false;
69393
69394        // IE9 Running on Windows Server SKU can cause an exception to be thrown, bug #224
69395        try {
69396            if ( bool = !!elem.canPlayType ) {
69397                bool      = new Boolean(bool);
69398                bool.ogg  = elem.canPlayType('video/ogg; codecs="theora"')      .replace(/^no$/,'');
69399
vendor: 14,978 bytes, lines 69400-69774
69400                // Without QuickTime, this value will be `undefined`. github.com/Modernizr/Modernizr/issues/546
69401                bool.h264 = elem.canPlayType('video/mp4; codecs="avc1.42E01E"') .replace(/^no$/,'');
69402
69403                bool.webm = elem.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,'');
69404            }
69405
69406        } catch(e) { }
69407
69408        return bool;
69409    };
69410
69411    tests['audio'] = function() {
69412        var elem = document.createElement('audio'),
69413            bool = false;
69414
69415        try {
69416            if ( bool = !!elem.canPlayType ) {
69417                bool      = new Boolean(bool);
69418                bool.ogg  = elem.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,'');
69419                bool.mp3  = elem.canPlayType('audio/mpeg;')               .replace(/^no$/,'');
69420
69421                // Mimetypes accepted:
69422                //   developer.mozilla.org/En/Media_formats_supported_by_the_audio_and_video_elements
69423                //   bit.ly/iphoneoscodecs
69424                bool.wav  = elem.canPlayType('audio/wav; codecs="1"')     .replace(/^no$/,'');
69425                bool.m4a  = ( elem.canPlayType('audio/x-m4a;')            ||
69426                              elem.canPlayType('audio/aac;'))             .replace(/^no$/,'');
69427            }
69428        } catch(e) { }
69429
69430        return bool;
69431    };
69432
69433
69434    // In FF4, if disabled, window.localStorage should === null.
69435
69436    // Normally, we could not test that directly and need to do a
69437    //   `('localStorage' in window) && ` test first because otherwise Firefox will
69438    //   throw bugzil.la/365772 if cookies are disabled
69439
69440    // Also in iOS5 Private Browsing mode, attempting to use localStorage.setItem
69441    // will throw the exception:
69442    //   QUOTA_EXCEEDED_ERRROR DOM Exception 22.
69443    // Peculiarly, getItem and removeItem calls do not throw.
69444
69445    // Because we are forced to try/catch this, we'll go aggressive.
69446
69447    // Just FWIW: IE8 Compat mode supports these features completely:
69448    //   www.quirksmode.org/dom/html5.html
69449    // But IE8 doesn't support either with local files
69450
69451    tests['localstorage'] = function() {
69452        try {
69453            localStorage.setItem(mod, mod);
69454            localStorage.removeItem(mod);
69455            return true;
69456        } catch(e) {
69457            return false;
69458        }
69459    };
69460
69461    tests['sessionstorage'] = function() {
69462        try {
69463            sessionStorage.setItem(mod, mod);
69464            sessionStorage.removeItem(mod);
69465            return true;
69466        } catch(e) {
69467            return false;
69468        }
69469    };
69470
69471
69472    tests['webworkers'] = function() {
69473        return !!window.Worker;
69474    };
69475
69476
69477    tests['applicationcache'] = function() {
69478        return !!window.applicationCache;
69479    };
69480
69481
69482    // Thanks to Erik Dahlstrom
69483    tests['svg'] = function() {
69484        return !!document.createElementNS && !!document.createElementNS(ns.svg, 'svg').createSVGRect;
69485    };
69486
69487    // specifically for SVG inline in HTML, not within XHTML
69488    // test page: paulirish.com/demo/inline-svg
69489    tests['inlinesvg'] = function() {
69490      var div = document.createElement('div');
69491      div.innerHTML = '<svg/>';
69492      return (div.firstChild && div.firstChild.namespaceURI) == ns.svg;
69493    };
69494
69495    // SVG SMIL animation
69496    tests['smil'] = function() {
69497        return !!document.createElementNS && /SVGAnimate/.test(toString.call(document.createElementNS(ns.svg, 'animate')));
69498    };
69499
69500    // This test is only for clip paths in SVG proper, not clip paths on HTML content
69501    // demo: srufaculty.sru.edu/david.dailey/svg/newstuff/clipPath4.svg
69502
69503    // However read the comments to dig into applying SVG clippaths to HTML content here:
69504    //   github.com/Modernizr/Modernizr/issues/213#issuecomment-1149491
69505    tests['svgclippaths'] = function() {
69506        return !!document.createElementNS && /SVGClipPath/.test(toString.call(document.createElementNS(ns.svg, 'clipPath')));
69507    };
69508
69509    /*>>webforms*/
69510    // input features and input types go directly onto the ret object, bypassing the tests loop.
69511    // Hold this guy to execute in a moment.
69512    function webforms() {
69513        /*>>input*/
69514        // Run through HTML5's new input attributes to see if the UA understands any.
69515        // We're using f which is the <input> element created early on
69516        // Mike Taylr has created a comprehensive resource for testing these attributes
69517        //   when applied to all input types:
69518        //   miketaylr.com/code/input-type-attr.html
69519        // spec: www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary
69520
69521        // Only input placeholder is tested while textarea's placeholder is not.
69522        // Currently Safari 4 and Opera 11 have support only for the input placeholder
69523        // Both tests are available in feature-detects/forms-placeholder.js
69524        Modernizr['input'] = (function( props ) {
69525            for ( var i = 0, len = props.length; i < len; i++ ) {
69526                attrs[ props[i] ] = !!(props[i] in inputElem);
69527            }
69528            if (attrs.list){
69529              // safari false positive's on datalist: webk.it/74252
69530              // see also github.com/Modernizr/Modernizr/issues/146
69531              attrs.list = !!(document.createElement('datalist') && window.HTMLDataListElement);
69532            }
69533            return attrs;
69534        })('autocomplete autofocus list placeholder max min multiple pattern required step'.split(' '));
69535        /*>>input*/
69536
69537        /*>>inputtypes*/
69538        // Run through HTML5's new input types to see if the UA understands any.
69539        //   This is put behind the tests runloop because it doesn't return a
69540        //   true/false like all the other tests; instead, it returns an object
69541        //   containing each input type with its corresponding true/false value
69542
69543        // Big thanks to @miketaylr for the html5 forms expertise. miketaylr.com/
69544        Modernizr['inputtypes'] = (function(props) {
69545
69546            for ( var i = 0, bool, inputElemType, defaultView, len = props.length; i < len; i++ ) {
69547
69548                inputElem.setAttribute('type', inputElemType = props[i]);
69549                bool = inputElem.type !== 'text';
69550
69551                // We first check to see if the type we give it sticks..
69552                // If the type does, we feed it a textual value, which shouldn't be valid.
69553                // If the value doesn't stick, we know there's input sanitization which infers a custom UI
69554                if ( bool ) {
69555
69556                    inputElem.value         = smile;
69557                    inputElem.style.cssText = 'position:absolute;visibility:hidden;';
69558
69559                    if ( /^range$/.test(inputElemType) && inputElem.style.WebkitAppearance !== undefined ) {
69560
69561                      docElement.appendChild(inputElem);
69562                      defaultView = document.defaultView;
69563
69564                      // Safari 2-4 allows the smiley as a value, despite making a slider
69565                      bool =  defaultView.getComputedStyle &&
69566                              defaultView.getComputedStyle(inputElem, null).WebkitAppearance !== 'textfield' &&
69567                              // Mobile android web browser has false positive, so must
69568                              // check the height to see if the widget is actually there.
69569                              (inputElem.offsetHeight !== 0);
69570
69571                      docElement.removeChild(inputElem);
69572
69573                    } else if ( /^(search|tel)$/.test(inputElemType) ){
69574                      // Spec doesn't define any special parsing or detectable UI
69575                      //   behaviors so we pass these through as true
69576
69577                      // Interestingly, opera fails the earlier test, so it doesn't
69578                      //  even make it here.
69579
69580                    } else if ( /^(url|email)$/.test(inputElemType) ) {
69581                      // Real url and email support comes with prebaked validation.
69582                      bool = inputElem.checkValidity && inputElem.checkValidity() === false;
69583
69584                    } else {
69585                      // If the upgraded input compontent rejects the :) text, we got a winner
69586                      bool = inputElem.value != smile;
69587                    }
69588                }
69589
69590                inputs[ props[i] ] = !!bool;
69591            }
69592            return inputs;
69593        })('search tel url email datetime date month week time datetime-local number range color'.split(' '));
69594        /*>>inputtypes*/
69595    }
69596    /*>>webforms*/
69597
69598
69599    // End of test definitions
69600    // -----------------------
69601
69602
69603
69604    // Run through all tests and detect their support in the current UA.
69605    // todo: hypothetically we could be doing an array of tests and use a basic loop here.
69606    for ( var feature in tests ) {
69607        if ( hasOwnProp(tests, feature) ) {
69608            // run the test, throw the return value into the Modernizr,
69609            //   then based on that boolean, define an appropriate className
69610            //   and push it into an array of classes we'll join later.
69611            featureName  = feature.toLowerCase();
69612            Modernizr[featureName] = tests[feature]();
69613
69614            classes.push((Modernizr[featureName] ? '' : 'no-') + featureName);
69615        }
69616    }
69617
69618    /*>>webforms*/
69619    // input tests need to run.
69620    Modernizr.input || webforms();
69621    /*>>webforms*/
69622
69623
69624    /**
69625     * addTest allows the user to define their own feature tests
69626     * the result will be added onto the Modernizr object,
69627     * as well as an appropriate className set on the html element
69628     *
69629     * @param feature - String naming the feature
69630     * @param test - Function returning true if feature is supported, false if not
69631     */
69632     Modernizr.addTest = function ( feature, test ) {
69633       if ( typeof feature == 'object' ) {
69634         for ( var key in feature ) {
69635           if ( hasOwnProp( feature, key ) ) {
69636             Modernizr.addTest( key, feature[ key ] );
69637           }
69638         }
69639       } else {
69640
69641         feature = feature.toLowerCase();
69642
69643         if ( Modernizr[feature] !== undefined ) {
69644           // we're going to quit if you're trying to overwrite an existing test
69645           // if we were to allow it, we'd do this:
69646           //   var re = new RegExp("\\b(no-)?" + feature + "\\b");
69647           //   docElement.className = docElement.className.replace( re, '' );
69648           // but, no rly, stuff 'em.
69649           return Modernizr;
69650         }
69651
69652         test = typeof test == 'function' ? test() : test;
69653
69654         if (typeof enableClasses !== "undefined" && enableClasses) {
69655           docElement.className += ' ' + (test ? '' : 'no-') + feature;
69656         }
69657         Modernizr[feature] = test;
69658
69659       }
69660
69661       return Modernizr; // allow chaining.
69662     };
69663
69664
69665    // Reset modElem.cssText to nothing to reduce memory footprint.
69666    setCss('');
69667    modElem = inputElem = null;
69668
69669    /*>>shiv*/
69670    /**
69671     * @preserve HTML5 Shiv prev3.7.1 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
69672     */
69673    ;(function(window, document) {
69674        /*jshint evil:true */
69675        /** version */
69676        var version = '3.7.0';
69677
69678        /** Preset options */
69679        var options = window.html5 || {};
69680
69681        /** Used to skip problem elements */
69682        var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i;
69683
69684        /** Not all elements can be cloned in IE **/
69685        var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i;
69686
69687        /** Detect whether the browser supports default html5 styles */
69688        var supportsHtml5Styles;
69689
69690        /** Name of the expando, to work with multiple documents or to re-shiv one document */
69691        var expando = '_html5shiv';
69692
69693        /** The id for the the documents expando */
69694        var expanID = 0;
69695
69696        /** Cached data for each document */
69697        var expandoData = {};
69698
69699        /** Detect whether the browser supports unknown elements */
69700        var supportsUnknownElements;
69701
69702        (function() {
69703          try {
69704            var a = document.createElement('a');
69705            a.innerHTML = '<xyz></xyz>';
69706            //if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles
69707            supportsHtml5Styles = ('hidden' in a);
69708
69709            supportsUnknownElements = a.childNodes.length == 1 || (function() {
69710              // assign a false positive if unable to shiv
69711              (document.createElement)('a');
69712              var frag = document.createDocumentFragment();
69713              return (
69714                typeof frag.cloneNode == 'undefined' ||
69715                typeof frag.createDocumentFragment == 'undefined' ||
69716                typeof frag.createElement == 'undefined'
69717              );
69718            }());
69719          } catch(e) {
69720            // assign a false positive if detection fails => unable to shiv
69721            supportsHtml5Styles = true;
69722            supportsUnknownElements = true;
69723          }
69724
69725        }());
69726
69727        /*--------------------------------------------------------------------------*/
69728
69729        /**
69730         * Creates a style sheet with the given CSS text and adds it to the document.
69731         * @private
69732         * @param {Document} ownerDocument The document.
69733         * @param {String} cssText The CSS text.
69734         * @returns {StyleSheet} The style element.
69735         */
69736        function addStyleSheet(ownerDocument, cssText) {
69737          var p = ownerDocument.createElement('p'),
69738          parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement;
69739
69740          p.innerHTML = 'x<style>' + cssText + '</style>';
69741          return parent.insertBefore(p.lastChild, parent.firstChild);
69742        }
69743
69744        /**
69745         * Returns the value of `html5.elements` as an array.
69746         * @private
69747         * @returns {Array} An array of shived element node names.
69748         */
69749        function getElements() {
69750          var elements = html5.elements;
69751          return typeof elements == 'string' ? elements.split(' ') : elements;
69752        }
69753
69754        /**
69755         * Returns the data associated to the given document
69756         * @private
69757         * @param {Document} ownerDocument The document.
69758         * @returns {Object} An object of data.
69759         */
69760        function getExpandoData(ownerDocument) {
69761          var data = expandoData[ownerDocument[expando]];
69762          if (!data) {
69763            data = {};
69764            expanID++;
69765            ownerDocument[expando] = expanID;
69766            expandoData[expanID] = data;
69767          }
69768          return data;
69769        }
69770
69771        /**
69772         * returns a shived element for the given nodeName and document
69773         * @memberOf html5
69774         * @param {String}
vendor: 4,707 bytes, lines 69774-69885
69774 nodeName name of the element
69775         * @param {Document} ownerDocument The context document.
69776         * @returns {Object} The shived element.
69777         */
69778        function createElement(nodeName, ownerDocument, data){
69779          if (!ownerDocument) {
69780            ownerDocument = document;
69781          }
69782          if(supportsUnknownElements){
69783            return ownerDocument.createElement(nodeName);
69784          }
69785          if (!data) {
69786            data = getExpandoData(ownerDocument);
69787          }
69788          var node;
69789
69790          if (data.cache[nodeName]) {
69791            node = data.cache[nodeName].cloneNode();
69792          } else if (saveClones.test(nodeName)) {
69793            node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode();
69794          } else {
69795            node = data.createElem(nodeName);
69796          }
69797
69798          // Avoid adding some elements to fragments in IE < 9 because
69799          // * Attributes like `name` or `type` cannot be set/changed once an element
69800          //   is inserted into a document/fragment
69801          // * Link elements with `src` attributes that are inaccessible, as with
69802          //   a 403 response, will cause the tab/window to crash
69803          // * Script elements appended to fragments will execute when their `src`
69804          //   or `text` property is set
69805          return node.canHaveChildren && !reSkip.test(nodeName) && !node.tagUrn ? data.frag.appendChild(node) : node;
69806        }
69807
69808        /**
69809         * returns a shived DocumentFragment for the given document
69810         * @memberOf html5
69811         * @param {Document} ownerDocument The context document.
69812         * @returns {Object} The shived DocumentFragment.
69813         */
69814        function createDocumentFragment(ownerDocument, data){
69815          if (!ownerDocument) {
69816            ownerDocument = document;
69817          }
69818          if(supportsUnknownElements){
69819            return ownerDocument.createDocumentFragment();
69820          }
69821          data = data || getExpandoData(ownerDocument);
69822          var clone = data.frag.cloneNode(),
69823          i = 0,
69824          elems = getElements(),
69825          l = elems.length;
69826          for(;i<l;i++){
69827            clone.createElement(elems[i]);
69828          }
69829          return clone;
69830        }
69831
69832        /**
69833         * Shivs the `createElement` and `createDocumentFragment` methods of the document.
69834         * @private
69835         * @param {Document|DocumentFragment} ownerDocument The document.
69836         * @param {Object} data of the document.
69837         */
69838        function shivMethods(ownerDocument, data) {
69839          if (!data.cache) {
69840            data.cache = {};
69841            data.createElem = ownerDocument.createElement;
69842            data.createFrag = ownerDocument.createDocumentFragment;
69843            data.frag = data.createFrag();
69844          }
69845
69846
69847          ownerDocument.createElement = function(nodeName) {
69848            //abort shiv
69849            if (!html5.shivMethods) {
69850              return data.createElem(nodeName);
69851            }
69852            return createElement(nodeName, ownerDocument, data);
69853          };
69854
69855          ownerDocument.createDocumentFragment = Function('h,f', 'return function(){' +
69856                                                          'var n=f.cloneNode(),c=n.createElement;' +
69857                                                          'h.shivMethods&&(' +
69858                                                          // unroll the `createElement` calls
69859                                                          getElements().join().replace(/[\w\-]+/g, function(nodeName) {
69860            data.createElem(nodeName);
69861            data.frag.createElement(nodeName);
69862            return 'c("' + nodeName + '")';
69863          }) +
69864            ');return n}'
69865                                                         )(html5, data.frag);
69866        }
69867
69868        /*--------------------------------------------------------------------------*/
69869
69870        /**
69871         * Shivs the given document.
69872         * @memberOf html5
69873         * @param {Document} ownerDocument The document to shiv.
69874         * @returns {Document} The shived document.
69875         */
69876        function shivDocument(ownerDocument) {
69877          if (!ownerDocument) {
69878            ownerDocument = document;
69879          }
69880          var data = getExpandoData(ownerDocument);
69881
69882          if (html5.shivCSS && !supportsHtml5Styles && !data.hasCSS) {
69883            data.hasCSS = !!addStyleSheet(ownerDocument,
69884                                          // corrects block display not defined in IE6/7/8/9
69885                                          'article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{dis
69885play:block}' +
69886                                            // adds styling not present in IE6/7/8/9
69887                                            'mark{background:#FF0;color:#000}' +
69888                                            // hides non-rendered elements
69889                                            'template{display:none}'
69890                                         );
69891          }
69892          if (!supportsUnknownElements) {
69893            shivMethods(ownerDocument, data);
69894          }
69895          return ownerDocument;
69896        }
69897
69898        /*--------------------------------------------------------------------------*/
69899
69900        /**
69901         * The `html5` object is exposed so that more elements can be shived and
69902         * existing shiving can be detected on iframes.
69903         * @type Object
69904         * @example
69905         *
69906         * // options can be changed before the script is included
69907         * html5 = { 'elements': 'mark section', 'shivCSS': false, 'shivMethods': false };
69908         */
69909        var html5 = {
69910
69911          /**
69912           * An array or space separated string of node names of the elements to shiv.
69913           * @memberOf html5
69914           * @type Array|String
69915           */
69916          'elements': options.elements || 'abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video',
69917
69918          /**
69919           * current version of html5shiv
69920           */
69921          'version': version,
69922
69923          /**
69924           * A flag to indicate that the HTML5 style sheet should be inserted.
69925           * @memberOf html5
69926           * @type Boolean
69927           */
69928          'shivCSS': (options.shivCSS !== false),
69929
69930          /**
69931           * Is equal to true if a browser supports creating unknown/HTML5 elements
69932           * @memberOf html5
69933           * @type boolean
69934           */
69935          'supportsUnknownElements': supportsUnknownElements,
69936
69937          /**
69938           * A flag to indicate that the document's `createElement` and `createDocumentFragment`
69939           * methods should be overwritten.
69940           * @memberOf html5
69941           * @type Boolean
69942           */
69943          'shivMethods': (options.shivMethods !== false),
69944
69945          /**
69946           * A string to describe the type of `html5` object ("default" or "default print").
69947           * @memberOf html5
69948           * @type String
69949           */
69950          'type': 'default',
69951
69952          // shivs the document according to the specified `html5` object options
69953          'shivDocument': shivDocument,
69954
69955          //creates a shived element
69956          createElement: createElement,
69957
69958          //creates a shived documentFragment
69959          createDocumentFragment: createDocumentFragment
69960        };
69961
69962        /*--------------------------------------------------------------------------*/
69963
69964        // expose html5
69965        window.html5 = html5;
69966
69967        // shiv the document
69968        shivDocument(document);
69969
69970    }(this, document));
69971    /*>>shiv*/
69972
69973    // Assign private properties to the return object with prefix
69974    Modernizr._version      = version;
69975
69976    // expose these for the plugin API. Look in the source for how to join() them against your input
69977    /*>>prefixes*/
69978    Modernizr._prefixes     = prefixes;
69979    /*>>prefixes*/
69980    /*>>domprefixes*/
69981    Modernizr._domPrefixes  = domPrefixes;
69982    Modernizr._cssomPrefixes  = cssomPrefixes;
69983    /*>>domprefixes*/
69984
69985    /*>>mq*/
69986    // Modernizr.mq tests a given media query, live against the current state of the window
69987    // A few important notes:
69988    //   * If a browser does not support media queries at all (eg. oldIE) the mq() will always return false
69989    //   * A max-width or orientation query will be evaluated against the current state, which may change later.
69990    //   * You must specify values. Eg. If you are testing support for the min-width media query use:
69991    //       Modernizr.mq('(min-width:0)')
69992    // usage:
69993    // Modernizr.mq('only screen and (max-width:768)')
69994    Modernizr.mq            = testMediaQuery;
69995    /*>>mq*/
69996
69997    /*>>hasevent*/
69998    // Modernizr.hasEvent() detects support for a given event, with an optional element to test on
69999    // Modernizr.hasEvent('gesturestart', elem)
70000    Modernizr.hasEvent      = isEventSupported;
70001    /*>>hasevent*/
70002
70003    /*>>testprop*/
70004    // Modernizr.testProp() investigates whether a given style property is recognized
70005    // Note that the property names must be provided in the camelCase variant.
70006    // Modernizr.testProp('pointerEvents')
70007    Modernizr.testProp      = function(prop){
70008        return testProps([prop]);
70009    };
70010    /*>>testprop*/
70011
70012    /*>>testallprops*/
70013    // Modernizr.testAllProps() investigates whether a given style property,
70014    //   or any of its vendor-prefixed variants, is recognized
70015    // Note that the property names must be provided in the camelCase variant.
70016    // Modernizr.testAllProps('boxSizing')
70017    Modernizr.testAllProps  = testPropsAll;
70018    /*>>testallprops*/
70019
70020
70021    /*>>teststyles*/
70022    // Modernizr.testStyles() allows you to add custom styles to the document and test an element afterwards
70023    // Modernizr.testStyles('#modernizr { position:absolute }', function(elem, rule){ ... })
70024    Modernizr.testStyles    = injectElementWithStyles;
70025    /*>>teststyles*/
70026
70027
70028    /*>>prefixed*/
70029    // Modernizr.prefixed() returns the prefixed or nonprefixed property name variant of your input
70030    // Modernizr.prefixed('boxSizing') // 'MozBoxSizing'
70031
70032    // Properties must be passed as dom-style camelcase, rather than `box-sizing` hypentated style.
70033    // Return values will also be the camelCase variant, if you need to translate that to hypenated style use:
70034    //
70035    //     str.replace(/([A-Z])/g, function(str,m1){ return '-' + m1.toLowerCase(); }).replace(/^ms-/,'-ms-');
70036
70037    // If you're trying to ascertain which transition end event to bind to, you might do something like...
70038    //
70039    //     var transEndEventNames = {
70040    //       'WebkitTransition' : 'webkitTransitionEnd',
70041    //       'MozTransition'    : 'transitionend',
70042    //       'OTransition'      : 'oTransitionEnd',
70043    //       'msTransition'     : 'MSTransitionEnd',
70044    //       'transition'       : 'transitionend'
70045    //     },
70046    //     transEndEventName = transEndEventNames[ Modernizr.prefixed('transition') ];
70047
70048    Modernizr.prefixed      = function(prop, obj, elem){
70049      if(!obj) {
70050        return testPropsAll(prop, 'pfx');
70051      } else {
70052        // Testing DOM property e.g. Modernizr.prefixed('requestAnimationFrame', window) // 'mozRequestAnimationFrame'
70053        return testPropsAll(prop, obj, elem);
70054      }
70055    };
70056    /*>>prefixed*/
70057
70058
70059    /*>>cssclasses*/
70060    // Remove "no-js" class from <html> element, if it exists:
70061    docElement.className = docElement.className.replace(/(^|\s)no-js(\s|$)/, '$1$2') +
70062
70063                            // Add the new classes to the <html> element.
70064                            (enableClasses ? ' js ' + classes.join(' ') : '');
70065    /*>>cssclasses*/
70066
70067    return Modernizr;
70068
70069})(this, this.document);
70070
70071define("modernizr", function(){});
70072
70073/*global define:false */
70074/**
70075 * Copyright 2013 Craig Campbell
70076 *
70077 * Licensed under the Apache License, Version 2.0 (the "License");
70078 * you may not use this file except in compliance with the License.
70079 * You may obtain a copy of the License at
70080 *
70081 * http://www.apache.org/licenses/LICENSE-2.0
70082 *
70083 * Unless required by applicable law or agreed to in writing, software
70084 * distributed under the License is distributed on an "AS IS" BASIS,
70085 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
70086 * See the License for the specific language governing permissions and
70087 * limitations under the License.
70088 *
70089 * Mousetrap is a simple keyboard shortcut library for Javascript with
70090 * no external dependencies
70091 *
70092 * @version 1.4.6
70093 * @url craig.is/killing/mice
70094 */
70095(function(window, document, undefined) {
70096
70097    /**
70098     * mapping of special keycodes to their corresponding keys
70099     *
70100     * everything in this dictionary cannot use keypress events
70101     * so it has to be here to map to the correct keycodes for
70102     * keyup/keydown events
70103     *
70104     * @type {Object}
70105     */
70106    var _MAP = {
70107            8: 'backspace',
70108            9: 'tab',
70109            13: 'enter',
70110            16: 'shift',
70111            17: 'ctrl',
70112            18: 'alt',
70113            20: 'capslock',
70114            27: 'esc',
70115            32: 'space',
70116            33: 'pageup',
70117            34: 'pagedown',
70118            35: 'end',
70119            36: 'home',
70120            37: 'left',
70121            38: 'up',
70122            39: 'right',
70123            40: 'down',
70124            45: 'ins',
70125            46: 'del',
70126            91: 'meta',
70127            93: 'meta',
70128            224: 'meta'
70129        },
70130
70131        /**
70132         * mapping for special characters so they can support
70133         *
70134         * this dictionary is only used incase you want to bind a
70135         * keyup or keydown event to one of these keys
70136         *
70137         * @type {Object}
70138         */
70139        _KEYCODE_MAP = {
70140            106: '*',
70141            107: '+',
70142            109: '-',
70143            110: '.',
70144            111 : '/',
70145            186: ';',
70146            187: '=',
70147            188: ',',
70148            189: '-',
70149            190: '.',
70150            191: '/',
70151            192: '`',
70152            219: '[',
70153            220: '\\',
70154            221: ']',
70155            222: '\''
70156        },
70157
70158        /**
70159         * this is a mapping of keys that require shift on a US keypad
70160         * back to the non shift equivelents
70161         *
70162         * this is so you can use keyup events with these keys
70163         *
70164         * note that this will only work reliably on US keyboards
70165         *
70166         * @type {Object}
70167         */
70168        _SHIFT_MAP = {
70169            '~': '`',
70170            '!': '1',
70171            '@': '2',
70172            '#': '3',
70173            '$': '4',
70174            '%': '5',
70175            '^': '6',
70176            '&': '7',
70177            '*': '8',
70178            '(': '9',
70179            ')': '0',
70180            '_': '-',
70181            '+': '=',
70182            ':': ';',
70183            '\"': '\'',
70184            '<': ',',
70185            '>': '.',
70186            '?': '/',
70187            '|': '\\'
70188        },
70189
70190        /**
70191         * this is a list of special strings you can use to map
70192         * to modifier keys when you specify your keyboard shortcuts
70193         *
70194         * @type {Object}
70195         */
70196        _SPECIAL_ALIASES = {
70197            'option': 'alt',
70198            'command': 'meta',
70199            'return': 'enter',
70200            'escape': 'esc',
70201            'mod': /Mac|iPod|iPhone|iPad/.test(navigator.platform) ? 'meta' : 'ctrl'
70202        },
70203
70204        /**
70205         * variable to store the flipped version of _MAP from above
70206         * needed to check if we should use keypress or not when no action
70207         * is specified
70208         *
70209         * @type {Object|undefined}
70210         */
70211        _REVERSE_MAP,
70212
70213        /**
70214         * a list of all the callbacks setup via Mousetrap.bind()
70215         *
70216         * @type {Object}
70217         */
70218        _callbacks = {},
70219
70220        /**
70221         * direct map of string combinations to callbacks used for trigger()
70222         *
70223         * @type {Object}
70224         */
70225        _directMap = {},
70226
70227        /**
70228         * keeps track of what level each sequence is at since multiple
70229         * sequences can start out with the same sequence
70230         *
70231         * @type {Object}
70232         */
70233        _sequenceLevels = {},
70234
70235        /**
70236         * variable to store the setTimeout call
70237         *
70238         * @type {null|number}
70239         */
70240        _resetTimer,
70241
70242        /**
70243         * temporary state where we will ignore the next keyup
70244         *
70245         * @type {boolean|string}
70246         */
70247        _ignoreNextKeyup = false,
70248
70249        /**
70250         * temporary state where we will ignore the next keypress
70251         *
70252         * @type {boolean}
70253         */
70254        _ignoreNextKeypress = false,
70255
70256        /**
70257         * are we currently inside of a sequence?
70258         * type of action ("keyup" or "keydown" or "keypress") or false
70259         *
70260         * @type {boolean|string}
70261         */
70262        _nextExpectedAction = false;
vendor: 5,466 bytes, lines 70263-70432
70263
70264    /**
70265     * loop through the f keys, f1 to f19 and add them to the map
70266     * programatically
70267     */
70268    for (var i = 1; i < 20; ++i) {
70269        _MAP[111 + i] = 'f' + i;
70270    }
70271
70272    /**
70273     * loop through to map numbers on the numeric keypad
70274     */
70275    for (i = 0; i <= 9; ++i) {
70276        _MAP[i + 96] = i;
70277    }
70278
70279    /**
70280     * cross browser add event method
70281     *
70282     * @param {Element|HTMLDocument} object
70283     * @param {string} type
70284     * @param {Function} callback
70285     * @returns void
70286     */
70287    function _addEvent(object, type, callback) {
70288        if (object.addEventListener) {
70289            object.addEventListener(type, callback, false);
70290            return;
70291        }
70292
70293        object.attachEvent('on' + type, callback);
70294    }
70295
70296    /**
70297     * takes the event and returns the key character
70298     *
70299     * @param {Event} e
70300     * @return {string}
70301     */
70302    function _characterFromEvent(e) {
70303
70304        // for keypress events we should return the character as is
70305        if (e.type == 'keypress') {
70306            var character = String.fromCharCode(e.which);
70307
70308            // if the shift key is not pressed then it is safe to assume
70309            // that we want the character to be lowercase.  this means if
70310            // you accidentally have caps lock on then your key bindings
70311            // will continue to work
70312            //
70313            // the only side effect that might not be desired is if you
70314            // bind something like 'A' cause you want to trigger an
70315            // event when capital A is pressed caps lock will no longer
70316            // trigger the event.  shift+a will though.
70317            if (!e.shiftKey) {
70318                character = character.toLowerCase();
70319            }
70320
70321            return character;
70322        }
70323
70324        // for non keypress events the special maps are needed
70325        if (_MAP[e.which]) {
70326            return _MAP[e.which];
70327        }
70328
70329        if (_KEYCODE_MAP[e.which]) {
70330            return _KEYCODE_MAP[e.which];
70331        }
70332
70333        // if it is not in the special map
70334
70335        // with keydown and keyup events the character seems to always
70336        // come in as an uppercase character whether you are pressing shift
70337        // or not.  we should make sure it is always lowercase for comparisons
70338        return String.fromCharCode(e.which).toLowerCase();
70339    }
70340
70341    /**
70342     * checks if two arrays are equal
70343     *
70344     * @param {Array} modifiers1
70345     * @param {Array} modifiers2
70346     * @returns {boolean}
70347     */
70348    function _modifiersMatch(modifiers1, modifiers2) {
70349        return modifiers1.sort().join(',') === modifiers2.sort().join(',');
70350    }
70351
70352    /**
70353     * resets all sequence counters except for the ones passed in
70354     *
70355     * @param {Object} doNotReset
70356     * @returns void
70357     */
70358    function _resetSequences(doNotReset) {
70359        doNotReset = doNotReset || {};
70360
70361        var activeSequences = false,
70362            key;
70363
70364        for (key in _sequenceLevels) {
70365            if (doNotReset[key]) {
70366                activeSequences = true;
70367                continue;
70368            }
70369            _sequenceLevels[key] = 0;
70370        }
70371
70372        if (!activeSequences) {
70373            _nextExpectedAction = false;
70374        }
70375    }
70376
70377    /**
70378     * finds all callbacks that match based on the keycode, modifiers,
70379     * and action
70380     *
70381     * @param {string} character
70382     * @param {Array} modifiers
70383     * @param {Event|Object} e
70384     * @param {string=} sequenceName - name of the sequence we are looking for
70385     * @param {string=} combination
70386     * @param {number=} level
70387     * @returns {Array}
70388     */
70389    function _getMatches(character, modifiers, e, sequenceName, combination, level) {
70390        var i,
70391            callback,
70392            matches = [],
70393            action = e.type;
70394
70395        // if there are no events related to this keycode
70396        if (!_callbacks[character]) {
70397            return [];
70398        }
70399
70400        // if a modifier key is coming up on its own we should allow it
70401        if (action == 'keyup' && _isModifier(character)) {
70402            modifiers = [character];
70403        }
70404
70405        // loop through all callbacks for the key that was pressed
70406        // and see if any of them match
70407        for (i = 0; i < _callbacks[character].length; ++i) {
70408            callback = _callbacks[character][i];
70409
70410            // if a sequence name is not specified, but this is a sequence at
70411            // the wrong level then move onto the next match
70412            if (!sequenceName && callback.seq && _sequenceLevels[callback.seq] != callback.level) {
70413                continue;
70414            }
70415
70416            // if the action we are looking for doesn't match the action we got
70417            // then we should keep going
70418            if (action != callback.action) {
70419                continue;
70420            }
70421
70422            // if this is a keypress event and the meta key and control key
70423            // are not pressed that means that we need to only look at the
70424            // character, otherwise check the modifiers as well
70425            //
70426            // chrome will not fire a keypress if meta or control is down
70427            // safari will fire a keypress if meta or meta+shift is down
70428            // firefox will fire a keypress if meta or control is down
70429            if ((action == 'keypress' && !e.metaKey && !e.ctrlKey) || _modifiersMatch(modifiers, callback.modifiers)) {
70430
70431                // when you bind a combination or sequence a second time it
70432                // should overwrite the first one.  if a sequenceName or
vendor: 13,975 bytes, lines 70433-70869
70433                // combination is specified in this call it does just that
70434                //
70435                // @todo make deleting its own method?
70436                var deleteCombo = !sequenceName && callback.combo == combination;
70437                var deleteSequence = sequenceName && callback.seq == sequenceName && callback.level == level;
70438                if (deleteCombo || deleteSequence) {
70439                    _callbacks[character].splice(i, 1);
70440                }
70441
70442                matches.push(callback);
70443            }
70444        }
70445
70446        return matches;
70447    }
70448
70449    /**
70450     * takes a key event and figures out what the modifiers are
70451     *
70452     * @param {Event} e
70453     * @returns {Array}
70454     */
70455    function _eventModifiers(e) {
70456        var modifiers = [];
70457
70458        if (e.shiftKey) {
70459            modifiers.push('shift');
70460        }
70461
70462        if (e.altKey) {
70463            modifiers.push('alt');
70464        }
70465
70466        if (e.ctrlKey) {
70467            modifiers.push('ctrl');
70468        }
70469
70470        if (e.metaKey) {
70471            modifiers.push('meta');
70472        }
70473
70474        return modifiers;
70475    }
70476
70477    /**
70478     * prevents default for this event
70479     *
70480     * @param {Event} e
70481     * @returns void
70482     */
70483    function _preventDefault(e) {
70484        if (e.preventDefault) {
70485            e.preventDefault();
70486            return;
70487        }
70488
70489        e.returnValue = false;
70490    }
70491
70492    /**
70493     * stops propogation for this event
70494     *
70495     * @param {Event} e
70496     * @returns void
70497     */
70498    function _stopPropagation(e) {
70499        if (e.stopPropagation) {
70500            e.stopPropagation();
70501            return;
70502        }
70503
70504        e.cancelBubble = true;
70505    }
70506
70507    /**
70508     * actually calls the callback function
70509     *
70510     * if your callback function returns false this will use the jquery
70511     * convention - prevent default and stop propogation on the event
70512     *
70513     * @param {Function} callback
70514     * @param {Event} e
70515     * @returns void
70516     */
70517    function _fireCallback(callback, e, combo, sequence) {
70518
70519        // if this event should not happen stop here
70520        if (Mousetrap.stopCallback(e, e.target || e.srcElement, combo, sequence)) {
70521            return;
70522        }
70523
70524        if (callback(e, combo) === false) {
70525            _preventDefault(e);
70526            _stopPropagation(e);
70527        }
70528    }
70529
70530    /**
70531     * handles a character key event
70532     *
70533     * @param {string} character
70534     * @param {Array} modifiers
70535     * @param {Event} e
70536     * @returns void
70537     */
70538    function _handleKey(character, modifiers, e) {
70539        var callbacks = _getMatches(character, modifiers, e),
70540            i,
70541            doNotReset = {},
70542            maxLevel = 0,
70543            processedSequenceCallback = false;
70544
70545        // Calculate the maxLevel for sequences so we can only execute the longest callback sequence
70546        for (i = 0; i < callbacks.length; ++i) {
70547            if (callbacks[i].seq) {
70548                maxLevel = Math.max(maxLevel, callbacks[i].level);
70549            }
70550        }
70551
70552        // loop through matching callbacks for this key event
70553        for (i = 0; i < callbacks.length; ++i) {
70554
70555            // fire for all sequence callbacks
70556            // this is because if for example you have multiple sequences
70557            // bound such as "g i" and "g t" they both need to fire the
70558            // callback for matching g cause otherwise you can only ever
70559            // match the first one
70560            if (callbacks[i].seq) {
70561
70562                // only fire callbacks for the maxLevel to prevent
70563                // subsequences from also firing
70564                //
70565                // for example 'a option b' should not cause 'option b' to fire
70566                // even though 'option b' is part of the other sequence
70567                //
70568                // any sequences that do not match here will be discarded
70569                // below by the _resetSequences call
70570                if (callbacks[i].level != maxLevel) {
70571                    continue;
70572                }
70573
70574                processedSequenceCallback = true;
70575
70576                // keep a list of which sequences were matches for later
70577                doNotReset[callbacks[i].seq] = 1;
70578                _fireCallback(callbacks[i].callback, e, callbacks[i].combo, callbacks[i].seq);
70579                continue;
70580            }
70581
70582            // if there were no sequence matches but we are still here
70583            // that means this is a regular match so we should fire that
70584            if (!processedSequenceCallback) {
70585                _fireCallback(callbacks[i].callback, e, callbacks[i].combo);
70586            }
70587        }
70588
70589        // if the key you pressed matches the type of sequence without
70590        // being a modifier (ie "keyup" or "keypress") then we should
70591        // reset all sequences that were not matched by this event
70592        //
70593        // this is so, for example, if you have the sequence "h a t" and you
70594        // type "h e a r t" it does not match.  in this case the "e" will
70595        // cause the sequence to reset
70596        //
70597        // modifier keys are ignored because you can have a sequence
70598        // that contains modifiers such as "enter ctrl+space" and in most
70599        // cases the modifier key will be pressed before the next key
70600        //
70601        // also if you have a sequence such as "ctrl+b a" then pressing the
70602        // "b" key will trigger a "keypress" and a "keydown"
70603        //
70604        // the "keydown" is expected when there is a modifier, but the
70605        // "keypress" ends up matching the _nextExpectedAction since it occurs
70606        // after and that causes the sequence to reset
70607        //
70608        // we ignore keypresses in a sequence that directly follow a keydown
70609        // for the same character
70610        var ignoreThisKeypress = e.type == 'keypress' && _ignoreNextKeypress;
70611        if (e.type == _nextExpectedAction && !_isModifier(character) && !ignoreThisKeypress) {
70612            _resetSequences(doNotReset);
70613        }
70614
70615        _ignoreNextKeypress = processedSequenceCallback && e.type == 'keydown';
70616    }
70617
70618    /**
70619     * handles a keydown event
70620     *
70621     * @param {Event} e
70622     * @returns void
70623     */
70624    function _handleKeyEvent(e) {
70625
70626        // normalize e.which for key events
70627        // @see http://stackoverflow.com/questions/4285627/javascript-keycode-vs-charcode-utter-confusion
70628        if (typeof e.which !== 'number') {
70629            e.which = e.keyCode;
70630        }
70631
70632        var character = _characterFromEvent(e);
70633
70634        // no character found then stop
70635        if (!character) {
70636            return;
70637        }
70638
70639        // need to use === for the character check because the character can be 0
70640        if (e.type == 'keyup' && _ignoreNextKeyup === character) {
70641            _ignoreNextKeyup = false;
70642            return;
70643        }
70644
70645        Mousetrap.handleKey(character, _eventModifiers(e), e);
70646    }
70647
70648    /**
70649     * determines if the keycode specified is a modifier key or not
70650     *
70651     * @param {string} key
70652     * @returns {boolean}
70653     */
70654    function _isModifier(key) {
70655        return key == 'shift' || key == 'ctrl' || key == 'alt' || key == 'meta';
70656    }
70657
70658    /**
70659     * called to set a 1 second timeout on the specified sequence
70660     *
70661     * this is so after each key press in the sequence you have 1 second
70662     * to press the next key before you have to start over
70663     *
70664     * @returns void
70665     */
70666    function _resetSequenceTimer() {
70667        clearTimeout(_resetTimer);
70668        _resetTimer = setTimeout(_resetSequences, 1000);
70669    }
70670
70671    /**
70672     * reverses the map lookup so that we can look for specific keys
70673     * to see what can and can't use keypress
70674     *
70675     * @return {Object}
70676     */
70677    function _getReverseMap() {
70678        if (!_REVERSE_MAP) {
70679            _REVERSE_MAP = {};
70680            for (var key in _MAP) {
70681
70682                // pull out the numeric keypad from here cause keypress should
70683                // be able to detect the keys from the character
70684                if (key > 95 && key < 112) {
70685                    continue;
70686                }
70687
70688                if (_MAP.hasOwnProperty(key)) {
70689                    _REVERSE_MAP[_MAP[key]] = key;
70690                }
70691            }
70692        }
70693        return _REVERSE_MAP;
70694    }
70695
70696    /**
70697     * picks the best action based on the key combination
70698     *
70699     * @param {string} key - character for key
70700     * @param {Array} modifiers
70701     * @param {string=} action passed in
70702     */
70703    function _pickBestAction(key, modifiers, action) {
70704
70705        // if no action was picked in we should try to pick the one
70706        // that we think would work best for this key
70707        if (!action) {
70708            action = _getReverseMap()[key] ? 'keydown' : 'keypress';
70709        }
70710
70711        // modifier keys don't work as expected with keypress,
70712        // switch to keydown
70713        if (action == 'keypress' && modifiers.length) {
70714            action = 'keydown';
70715        }
70716
70717        return action;
70718    }
70719
70720    /**
70721     * binds a key sequence to an event
70722     *
70723     * @param {string} combo - combo specified in bind call
70724     * @param {Array} keys
70725     * @param {Function} callback
70726     * @param {string=} action
70727     * @returns void
70728     */
70729    function _bindSequence(combo, keys, callback, action) {
70730
70731        // start off by adding a sequence level record for this combination
70732        // and setting the level to 0
70733        _sequenceLevels[combo] = 0;
70734
70735        /**
70736         * callback to increase the sequence level for this sequence and reset
70737         * all other sequences that were active
70738         *
70739         * @param {string} nextAction
70740         * @returns {Function}
70741         */
70742        function _increaseSequence(nextAction) {
70743            return function() {
70744                _nextExpectedAction = nextAction;
70745                ++_sequenceLevels[combo];
70746                _resetSequenceTimer();
70747            };
70748        }
70749
70750        /**
70751         * wraps the specified callback inside of another function in order
70752         * to reset all sequence counters as soon as this sequence is done
70753         *
70754         * @param {Event} e
70755         * @returns void
70756         */
70757        function _callbackAndReset(e) {
70758            _fireCallback(callback, e, combo);
70759
70760            // we should ignore the next key up if the action is key down
70761            // or keypress.  this is so if you finish a sequence and
70762            // release the key the final key will not trigger a keyup
70763            if (action !== 'keyup') {
70764                _ignoreNextKeyup = _characterFromEvent(e);
70765            }
70766
70767            // weird race condition if a sequence ends with the key
70768            // another sequence begins with
70769            setTimeout(_resetSequences, 10);
70770        }
70771
70772        // loop through keys one at a time and bind the appropriate callback
70773        // function.  for any key leading up to the final one it should
70774        // increase the sequence. after the final, it should reset all sequences
70775        //
70776        // if an action is specified in the original bind call then that will
70777        // be used throughout.  otherwise we will pass the action that the
70778        // next key in the sequence should match.  this allows a sequence
70779        // to mix and match keypress and keydown events depending on which
70780        // ones are better suited to the key provided
70781        for (var i = 0; i < keys.length; ++i) {
70782            var isFinal = i + 1 === keys.length;
70783            var wrappedCallback = isFinal ? _callbackAndReset : _increaseSequence(action || _getKeyInfo(keys[i + 1]).action);
70784            _bindSingle(keys[i], wrappedCallback, action, combo, i);
70785        }
70786    }
70787
70788    /**
70789     * Converts from a string key combination to an array
70790     *
70791     * @param  {string} combination like "command+shift+l"
70792     * @return {Array}
70793     */
70794    function _keysFromString(combination) {
70795        if (combination === '+') {
70796            return ['+'];
70797        }
70798
70799        return combination.split('+');
70800    }
70801
70802    /**
70803     * Gets info for a specific key combination
70804     *
70805     * @param  {string} combination key combination ("command+s" or "a" or "*")
70806     * @param  {string=} action
70807     * @returns {Object}
70808     */
70809    function _getKeyInfo(combination, action) {
70810        var keys,
70811            key,
70812            i,
70813            modifiers = [];
70814
70815        // take the keys from this pattern and figure out what the actual
70816        // pattern is all about
70817        keys = _keysFromString(combination);
70818
70819        for (i = 0; i < keys.length; ++i) {
70820            key = keys[i];
70821
70822            // normalize key names
70823            if (_SPECIAL_ALIASES[key]) {
70824                key = _SPECIAL_ALIASES[key];
70825            }
70826
70827            // if this is not a keypress event then we should
70828            // be smart about using shift keys
70829            // this will only work for US keyboards however
70830            if (action && action != 'keypress' && _SHIFT_MAP[key]) {
70831                key = _SHIFT_MAP[key];
70832                modifiers.push('shift');
70833            }
70834
70835            // if this key is a modifier then add it to the list of modifiers
70836            if (_isModifier(key)) {
70837                modifiers.push(key);
70838            }
70839        }
70840
70841        // depending on what the key combination is
70842        // we will try to pick the best event for it
70843        action = _pickBestAction(key, modifiers, action);
70844
70845        return {
70846            key: key,
70847            modifiers: modifiers,
70848            action: action
70849        };
70850    }
70851
70852    /**
70853     * binds a single keyboard combination
70854     *
70855     * @param {string} combination
70856     * @param {Function} callback
70857     * @param {string=} action
70858     * @param {string=} sequenceName - name of sequence if part of sequence
70859     * @param {number=} level - what part of the sequence the command is
70860     * @returns void
70861     */
70862    function _bindSingle(combination, callback, action, sequenceName, level) {
70863
70864        // store a direct mapped reference for use with Mousetrap.trigger
70865        _directMap[combination + ':' + action] = callback;
70866
70867        // make sure multiple spaces in a row become a single space
70868        combination = combination.replace(/\s+/g, ' ');
70869
70870        var sequence = combination.split(' '),
70871            info;
70872
70873        // if this pattern is a sequence of keys then run through this method
70874        // to reprocess each pattern one key at a time
70875        if (sequence.length > 1) {
70876            _bindSequence(combination, sequence, callback, action);
70877            return;
70878        }
70879
70880        info = _getKeyInfo(combination, action);
70881
70882        // make sure to initialize array if this is the first time
70883        // a callback is added for this key
70884        _callbacks[info.key] = _callbacks[info.key] || [];
70885
70886        // remove an existing match if there is one
70887        _getMatches(info.key, info.modifiers, {type: info.action}, sequenceName, combination, level);
70888
70889        // add this call back to the array
70890        // if it is a sequence put it at the beginning
70891        // if not put it at the end
70892        //
70893        // this is important because the way these are processed expects
70894        // the sequence ones to come first
70895        _callbacks[info.key][sequenceName ? 'unshift' : 'push']({
70896            callback: callback,
70897            modifiers: info.modifiers,
70898            action: info.action,
70899            seq: sequenceName,
70900            level: level,
70901            combo: combination
70902        });
70903    }
70904
70905    /**
70906     * binds multiple combinations to the same callback
70907     *
70908     * @param {Array} combinations
70909     * @param {Function} callback
70910     * @param {string|undefined} action
70911     * @returns void
70912     */
70913    function _bindMultiple(combinations, callback, action) {
70914        for (var i = 0;
70914 i < combinations.length; ++i) {
70915            _bindSingle(combinations[i], callback, action);
70916        }
70917    }
70918
70919    // start!
70920    _addEvent(document, 'keypress', _handleKeyEvent);
70921    _addEvent(document, 'keydown', _handleKeyEvent);
70922    _addEvent(document, 'keyup', _handleKeyEvent);
70923
70924    var Mousetrap = {
70925
70926        /**
70927         * binds an event to mousetrap
70928         *
70929         * can be a single key, a combination of keys separated with +,
70930         * an array of keys, or a sequence of keys separated by spaces
70931         *
70932         * be sure to list the modifier keys first to make sure that the
70933         * correct key ends up getting bound (the last key in the pattern)
70934         *
70935         * @param {string|Array} keys
70936         * @param {Function} callback
70937         * @param {string=} action - 'keypress', 'keydown', or 'keyup'
70938         * @returns void
70939         */
70940        bind: function(keys, callback, action) {
70941            keys = keys instanceof Array ? keys : [keys];
70942            _bindMultiple(keys, callback, action);
70943            return this;
70944        },
70945
70946        /**
70947         * unbinds an event to mousetrap
70948         *
70949         * the unbinding sets the callback function of the specified key combo
70950         * to an empty function and deletes the corresponding key in the
70951         * _directMap dict.
70952         *
70953         * TODO: actually remove this from the _callbacks dictionary instead
70954         * of binding an empty function
70955         *
70956         * the keycombo+action has to be exactly the same as
70957         * it was defined in the bind method
70958         *
70959         * @param {string|Array} keys
70960         * @param {string} action
70961         * @returns void
70962         */
70963        unbind: function(keys, action) {
70964            return Mousetrap.bind(keys, function() {}, action);
70965        },
70966
70967        /**
70968         * triggers an event that has already been bound
70969         *
70970         * @param {string} keys
70971         * @param {string=} action
70972         * @returns void
70973         */
70974        trigger: function(keys, action) {
70975            if (_directMap[keys + ':' + action]) {
70976                _directMap[keys + ':' + action]({}, keys);
70977            }
70978            return this;
70979        },
70980
70981        /**
70982         * resets the library back to its initial state.  this is useful
70983         * if you want to clear out the current keyboard shortcuts and bind
70984         * new ones - for example if you switch to another page
70985         *
70986         * @returns void
70987         */
70988        reset: function() {
70989            _callbacks = {};
70990            _directMap = {};
70991            return this;
70992        },
70993
70994       /**
70995        * should we stop this event before firing off callbacks
70996        *
70997        * @param {Event} e
70998        * @param {Element} element
70999        * @return {boolean}
71000        */
71001        stopCallback: function(e, element) {
71002
71003            // if the element has the class "mousetrap" then no need to stop
71004            if ((' ' + element.className + ' ').indexOf(' mousetrap ') > -1) {
71005                return false;
71006            }
71007
71008            // stop for input, select, and textarea
71009            return element.tagName == 'INPUT' || element.tagName == 'SELECT' || element.tagName == 'TEXTAREA' || element.isContentEditable;
71010        },
71011
71012        /**
71013         * exposes _handleKey publicly so it can be overwritten by extensions
71014         */
71015        handleKey: _handleKey
71016    };
71017
71018    // expose mousetrap to the global object
71019    window.Mousetrap = Mousetrap;
71020
71021    // expose mousetrap as an AMD module
71022    if (typeof define === 'function' && define.amd) {
71023        define('mousetrap',Mousetrap);
71024    }
71025}) (window, document);
71026
71027/* -----------------------------------------------
71028/* Author : Vincent Garreau  - vincentgarreau.com
71029/* MIT license: http://opensource.org/licenses/MIT
71030/* Demo / Generator : vincentgarreau.com/particles.js
71031/* GitHub : github.com/VincentGarreau/particles.js
71032/* How to use? : Check the GitHub README
71033/* v2.0.0
71034/* ----------------------------------------------- */
71035
71036var pJS = function(tag_id, params){
71037
71038  var canvas_el = document.querySelector('#'+tag_id+' > .particles-js-canvas-el');
71039
71040  /* particles.js variables with default values */
71041  this.pJS = {
71042    canvas: {
71043      el: canvas_el,
71044      w: canvas_el.offsetWidth,
71045      h: canvas_el.offsetHeight
71046    },
71047    particles: {
71048      number: {
71049        value: 400,
71050        density: {
71051          enable: true,
71052          value_area: 800
71053        }
71054      },
71055      color: {
71056        value: '#fff'
71057      },
71058      shape: {
71059        type: 'circle',
71060        stroke: {
71061          width: 0,
71062          color: '#ff0000'
71063        },
71064        polygon: {
71065          nb_sides: 5
71066        },
71067        image: {
71068          src: '',
71069          src_list: [],
71070          width: 100,
71071          height: 100
71072        }
71073      },
71074      opacity: {
71075        value: 1,
71076        random: false,
71077        anim: {
71078          enable: false,
71079          speed: 2,
71080          opacity_min: 0,
71081          sync: false
71082        }
71083      },
71084      size: {
71085        value: 20,
71086        random: false,
71087        anim: {
71088          enable: false,
71089          speed: 20,
71090          size_min: 0,
71091          sync: false
71092        }
71093      },
71094      line_linked: {
71095        enable: true,
71096        distance: 100,
71097        color: '#fff',
71098        opacity: 1,
71099        width: 1
71100      },
71101      move: {
71102        enable: true,
71103        speed: 2,
71104        direction: 'none',
71105        random: false,
71106        straight: false,
71107        out_mode: 'out',
71108        bounce: false,
71109        attract: {
71110          enable: false,
71111          rotateX: 3000,
71112          rotateY: 3000
71113        }
71114      },
71115      array: []
71116    },
71117    interactivity: {
71118      detect_on: 'canvas',
71119      events: {
71120        onhover: {
71121          enable: true,
71122          mode: 'grab'
71123        },
71124        onclick: {
71125          enable: true,
71126          mode: 'push'
71127        },
71128        resize: true
71129      },
71130      modes: {
71131        grab:{
71132          distance: 100,
71133          line_linked:{
71134            opacity: 1
71135          }
71136        },
71137        bubble:{
71138          distance: 200,
71139          size: 80,
71140          duration: 0.4
71141        },
71142        repulse:{
71143          distance: 200,
71144          duration: 0.4
71145        },
71146        push:{
71147          particles_nb: 4
71148        },
71149        remove:{
71150          particles_nb: 2
71151        }
71152      },
71153      mouse:{}
71154    },
71155    retina_detect: false,
71156    fn: {
71157      interact: {},
71158      modes: {},
71159      vendors:{}
71160    },
71161    tmp: {}
71162  };
71163
71164  var pJS = this.pJS;
71165
71166  /* params settings */
71167  if(params){
vendor: 33,566 bytes, lines 71168-72262
71168    Object.deepExtend(pJS, params);
71169  }
71170
71171  pJS.tmp.obj = {
71172    size_value: pJS.particles.size.value,
71173    size_anim_speed: pJS.particles.size.anim.speed,
71174    move_speed: pJS.particles.move.speed,
71175    line_linked_distance: pJS.particles.line_linked.distance,
71176    line_linked_width: pJS.particles.line_linked.width,
71177    mode_grab_distance: pJS.interactivity.modes.grab.distance,
71178    mode_bubble_distance: pJS.interactivity.modes.bubble.distance,
71179    mode_bubble_size: pJS.interactivity.modes.bubble.size,
71180    mode_repulse_distance: pJS.interactivity.modes.repulse.distance
71181  };
71182
71183  pJS.tmp.source_svg_list = []
71184  pJS.tmp.count_svg = 0
71185
71186  pJS.fn.retinaInit = function(){
71187
71188    if(pJS.retina_detect && window.devicePixelRatio > 1){
71189      pJS.canvas.pxratio = window.devicePixelRatio; 
71190      pJS.tmp.retina = true;
71191    } 
71192    else{
71193      pJS.canvas.pxratio = 1;
71194      pJS.tmp.retina = false;
71195    }
71196
71197    pJS.canvas.w = pJS.canvas.el.offsetWidth * pJS.canvas.pxratio;
71198    pJS.canvas.h = pJS.canvas.el.offsetHeight * pJS.canvas.pxratio;
71199
71200    pJS.particles.size.value = pJS.tmp.obj.size_value * pJS.canvas.pxratio;
71201    pJS.particles.size.anim.speed = pJS.tmp.obj.size_anim_speed * pJS.canvas.pxratio;
71202    pJS.particles.move.speed = pJS.tmp.obj.move_speed * pJS.canvas.pxratio;
71203    pJS.particles.line_linked.distance = pJS.tmp.obj.line_linked_distance * pJS.canvas.pxratio;
71204    pJS.interactivity.modes.grab.distance = pJS.tmp.obj.mode_grab_distance * pJS.canvas.pxratio;
71205    pJS.interactivity.modes.bubble.distance = pJS.tmp.obj.mode_bubble_distance * pJS.canvas.pxratio;
71206    pJS.particles.line_linked.width = pJS.tmp.obj.line_linked_width * pJS.canvas.pxratio;
71207    pJS.interactivity.modes.bubble.size = pJS.tmp.obj.mode_bubble_size * pJS.canvas.pxratio;
71208    pJS.interactivity.modes.repulse.distance = pJS.tmp.obj.mode_repulse_distance * pJS.canvas.pxratio;
71209
71210  };
71211
71212
71213
71214  /* ---------- pJS functions - canvas ------------ */
71215
71216  pJS.fn.canvasInit = function(){
71217    pJS.canvas.ctx = pJS.canvas.el.getContext('2d');
71218  };
71219
71220  pJS.fn.canvasSize = function(){
71221
71222    pJS.canvas.el.width = pJS.canvas.w;
71223    pJS.canvas.el.height = pJS.canvas.h;
71224
71225    if(pJS && pJS.interactivity.events.resize){
71226
71227      window.addEventListener('resize', function(){
71228
71229          pJS.canvas.w = pJS.canvas.el.offsetWidth;
71230          pJS.canvas.h = pJS.canvas.el.offsetHeight;
71231
71232          /* resize canvas */
71233          if(pJS.tmp.retina){
71234            pJS.canvas.w *= pJS.canvas.pxratio;
71235            pJS.canvas.h *= pJS.canvas.pxratio;
71236          }
71237
71238          pJS.canvas.el.width = pJS.canvas.w;
71239          pJS.canvas.el.height = pJS.canvas.h;
71240
71241          /* repaint canvas on anim disabled */
71242          if(!pJS.particles.move.enable){
71243            pJS.fn.particlesEmpty();
71244            pJS.fn.particlesCreate();
71245            pJS.fn.particlesDraw();
71246            pJS.fn.vendors.densityAutoParticles();
71247          }
71248
71249        /* density particles enabled */
71250        pJS.fn.vendors.densityAutoParticles();
71251
71252      });
71253
71254    }
71255
71256  };
71257
71258
71259  pJS.fn.canvasPaint = function(){
71260    pJS.canvas.ctx.fillRect(0, 0, pJS.canvas.w, pJS.canvas.h);
71261  };
71262
71263  pJS.fn.canvasClear = function(){
71264    pJS.canvas.ctx.clearRect(0, 0, pJS.canvas.w, pJS.canvas.h);
71265  };
71266
71267
71268  /* --------- pJS functions - particles ----------- */
71269
71270  pJS.fn.particle = function(color, opacity, position){
71271
71272    /* size */
71273    this.radius = (pJS.particles.size.random ? Math.random() : 1) * pJS.particles.size.value;
71274    if(pJS.particles.size.anim.enable){
71275      this.size_status = false;
71276      this.vs = pJS.particles.size.anim.speed / 100;
71277      if(!pJS.particles.size.anim.sync){
71278        this.vs = this.vs * Math.random();
71279      }
71280    }
71281
71282    /* position */
71283    this.x = position ? position.x : Math.random() * pJS.canvas.w;
71284    this.y = position ? position.y : Math.random() * pJS.canvas.h;
71285
71286    /* check position  - into the canvas */
71287    if(this.x > pJS.canvas.w - this.radius*2) this.x = this.x - this.radius;
71288    else if(this.x < this.radius*2) this.x = this.x + this.radius;
71289    if(this.y > pJS.canvas.h - this.radius*2) this.y = this.y - this.radius;
71290    else if(this.y < this.radius*2) this.y = this.y + this.radius;
71291
71292    /* check position - avoid overlap */
71293    if(pJS.particles.move.bounce){
71294      pJS.fn.vendors.checkOverlap(this, position);
71295    }
71296
71297    /* color */
71298    this.color = {};
71299    if(typeof(color.value) == 'object'){
71300
71301      if(color.value instanceof Array){
71302        var color_selected = color.value[Math.floor(Math.random() * pJS.particles.color.value.length)];
71303        this.color.rgb = hexToRgb(color_selected);
71304      }else{
71305        if(color.value.r != undefined && color.value.g != undefined && color.value.b != undefined){
71306          this.color.rgb = {
71307            r: color.value.r,
71308            g: color.value.g,
71309            b: color.value.b
71310          }
71311        }
71312        if(color.value.h != undefined && color.value.s != undefined && color.value.l != undefined){
71313          this.color.hsl = {
71314            h: color.value.h,
71315            s: color.value.s,
71316            l: color.value.l
71317          }
71318        }
71319      }
71320
71321    }
71322    else if(color.value == 'random'){
71323      this.color.rgb = {
71324        r: (Math.floor(Math.random() * (255 - 0 + 1)) + 0),
71325        g: (Math.floor(Math.random() * (255 - 0 + 1)) + 0),
71326        b: (Math.floor(Math.random() * (255 - 0 + 1)) + 0)
71327      }
71328    }
71329    else if(typeof(color.value) == 'string'){
71330      this.color = color;
71331      this.color.rgb = hexToRgb(this.color.value);
71332    }
71333
71334    /* opacity */
71335    this.opacity = (pJS.particles.opacity.random ? Math.random() : 1) * pJS.particles.opacity.value;
71336    if(pJS.particles.opacity.anim.enable){
71337      this.opacity_status = false;
71338      this.vo = pJS.particles.opacity.anim.speed / 100;
71339      if(!pJS.particles.opacity.anim.sync){
71340        this.vo = this.vo * Math.random();
71341      }
71342    }
71343
71344    /* animation - velocity for speed */
71345    var velbase = {}
71346    switch(pJS.particles.move.direction){
71347      case 'top':
71348        velbase = { x:0, y:-1 };
71349      break;
71350      case 'top-right':
71351        velbase = { x:0.5, y:-0.5 };
71352      break;
71353      case 'right':
71354        velbase = { x:1, y:-0 };
71355      break;
71356      case 'bottom-right':
71357        velbase = { x:0.5, y:0.5 };
71358      break;
71359      case 'bottom':
71360        velbase = { x:0, y:1 };
71361      break;
71362      case 'bottom-left':
71363        velbase = { x:-0.5, y:1 };
71364      break;
71365      case 'left':
71366        velbase = { x:-1, y:0 };
71367      break;
71368      case 'top-left':
71369        velbase = { x:-0.5, y:-0.5 };
71370      break;
71371      default:
71372        velbase = { x:0, y:0 };
71373      break;
71374    }
71375
71376    if(pJS.particles.move.straight){
71377      this.vx = velbase.x;
71378      this.vy = velbase.y;
71379      if(pJS.particles.move.random){
71380        this.vx = this.vx * (Math.random());
71381        this.vy = this.vy * (Math.random());
71382      }
71383    }else{
71384      this.vx = velbase.x + Math.random()-0.5;
71385      this.vy = velbase.y + Math.random()-0.5;
71386    }
71387
71388    // var theta = 2.0 * Math.PI * Math.random();
71389    // this.vx = Math.cos(theta);
71390    // this.vy = Math.sin(theta);
71391
71392    this.vx_i = this.vx;
71393    this.vy_i = this.vy;
71394
71395    
71396
71397    /* if shape is image */
71398
71399    var shape_type = pJS.particles.shape.type;
71400    if(typeof(shape_type) == 'object'){
71401      if(shape_type instanceof Array){
71402        var shape_selected = shape_type[Math.floor(Math.random() * shape_type.length)];
71403        this.shape = shape_selected;
71404      }
71405    }else{
71406      this.shape = shape_type;
71407    }
71408
71409    if(this.shape == 'image'){
71410      var sh = pJS.particles.shape;
71411      this.img = {
71412        src: sh.image.src,
71413        ratio: sh.image.width / sh.image.height
71414      }
71415      if(!this.img.ratio) this.img.ratio = 1;
71416      if(pJS.tmp.source_svg_list.length){
71417          var random = Math.floor(Math.random() * pJS.tmp.source_svg_list.length)
71418          this.img.src = sh.image.src_list[random]
71419          pJS.fn.vendors.createSvgImg(this, pJS.tmp.source_svg_list[random]);
71420          if(pJS.tmp.pushing){
71421            this.img.loaded = false;
71422          }
71423
71424      } else if(pJS.tmp.img_type == 'svg' && pJS.tmp.source_svg != undefined){
71425        pJS.fn.vendors.createSvgImg(this, pJS.tmp.source_svg);
71426        if(pJS.tmp.pushing){
71427          this.img.loaded = false;
71428        }
71429      }
71430    }
71431  };
71432
71433
71434  pJS.fn.particle.prototype.draw = function() {
71435    var p = this;
71436
71437    if(p.radius_bubble != undefined){
71438      var radius = p.radius_bubble; 
71439    }else{
71440      var radius = p.radius;
71441    }
71442
71443    if(p.opacity_bubble != undefined){
71444      var opacity = p.opacity_bubble;
71445    }else{
71446      var opacity = p.opacity;
71447    }
71448
71449    if(p.color.rgb){
71450      var color_value = 'rgba('+p.color.rgb.r+','+p.color.rgb.g+','+p.color.rgb.b+','+opacity+')';
71451    }else{
71452      var color_value = 'hsla('+p.color.hsl.h+','+p.color.hsl.s+'%,'+p.color.hsl.l+'%,'+opacity+')';
71453    }
71454
71455    pJS.canvas.ctx.fillStyle = color_value;
71456    pJS.canvas.ctx.beginPath();
71457
71458    switch(p.shape){
71459
71460      case 'circle':
71461        pJS.canvas.ctx.arc(p.x, p.y, radius, 0, Math.PI * 2, false);
71462      break;
71463
71464      case 'edge':
71465        pJS.canvas.ctx.rect(p.x-radius, p.y-radius, radius*2, radius*2);
71466      break;
71467
71468      case 'triangle':
71469        pJS.fn.vendors.drawShape(pJS.canvas.ctx, p.x-radius, p.y+radius / 1.66, radius*2, 3, 2);
71470      break;
71471
71472      case 'polygon':
71473        pJS.fn.vendors.drawShape(
71474          pJS.canvas.ctx,
71475          p.x - radius / (pJS.particles.shape.polygon.nb_sides/3.5), // startX
71476          p.y - radius / (2.66/3.5), // startY
71477          radius*2.66 / (pJS.particles.shape.polygon.nb_sides/3), // sideLength
71478          pJS.particles.shape.polygon.nb_sides, // sideCountNumerator
71479          1 // sideCountDenominator
71480        );
71481      break;
71482
71483      case 'star':
71484        pJS.fn.vendors.drawShape(
71485          pJS.canvas.ctx,
71486          p.x - radius*2 / (pJS.particles.shape.polygon.nb_sides/4), // startX
71487          p.y - radius / (2*2.66/3.5), // startY
71488          radius*2*2.66 / (pJS.particles.shape.polygon.nb_sides/3), // sideLength
71489          pJS.particles.shape.polygon.nb_sides, // sideCountNumerator
71490          2 // sideCountDenominator
71491        );
71492      break;
71493
71494      case 'image':
71495
71496        function draw(){
71497          pJS.canvas.ctx.drawImage(
71498            img_obj,
71499            p.x-radius,
71500            p.y-radius,
71501            radius*2,
71502            radius*2 / p.img.ratio
71503          );
71504        }
71505
71506        if(pJS.tmp.img_type == 'svg'){
71507          var img_obj = p.img.obj;
71508        }else{
71509          var img_obj = pJS.tmp.img_obj;
71510        }
71511
71512        if(img_obj){
71513          draw();
71514        }
71515
71516      break;
71517
71518    }
71519
71520    pJS.canvas.ctx.closePath();
71521
71522    if(pJS.particles.shape.stroke.width > 0){
71523      pJS.canvas.ctx.strokeStyle = pJS.particles.shape.stroke.color;
71524      pJS.canvas.ctx.lineWidth = pJS.particles.shape.stroke.width;
71525      pJS.canvas.ctx.stroke();
71526    }
71527    
71528    pJS.canvas.ctx.fill();
71529    
71530  };
71531
71532
71533  pJS.fn.particlesCreate = function(){
71534    for(var i = 0; i < pJS.particles.number.value; i++) {
71535      pJS.particles.array.push(new pJS.fn.particle(pJS.particles.color, pJS.particles.opacity.value));
71536    }
71537  };
71538
71539  pJS.fn.particlesUpdate = function(){
71540
71541    for(var i = 0; i < pJS.particles.array.length; i++){
71542
71543      /* the particle */
71544      var p = pJS.particles.array[i];
71545
71546      // var d = ( dx = pJS.interactivity.mouse.click_pos_x - p.x ) * dx + ( dy = pJS.interactivity.mouse.click_pos_y - p.y ) * dy;
71547      // var f = -BANG_SIZE / d;
71548      // if ( d < BANG_SIZE ) {
71549      //     var t = Math.atan2( dy, dx );
71550      //     p.vx = f * Math.cos(t);
71551      //     p.vy = f * Math.sin(t);
71552      // }
71553
71554      /* move the particle */
71555      if(pJS.particles.move.enable){
71556        var ms = pJS.particles.move.speed/2;
71557        p.x += p.vx * ms;
71558        p.y += p.vy * ms;
71559      }
71560
71561      /* change opacity status */
71562      if(pJS.particles.opacity.anim.enable) {
71563        if(p.opacity_status == true) {
71564          if(p.opacity >= pJS.particles.opacity.value) p.opacity_status = false;
71565          p.opacity += p.vo;
71566        }else {
71567          if(p.opacity <= pJS.particles.opacity.anim.opacity_min) p.opacity_status = true;
71568          p.opacity -= p.vo;
71569        }
71570        if(p.opacity < 0) p.opacity = 0;
71571      }
71572
71573      /* change size */
71574      if(pJS.particles.size.anim.enable){
71575        if(p.size_status == true){
71576          if(p.radius >= pJS.particles.size.value) p.size_status = false;
71577          p.radius += p.vs;
71578        }else{
71579          if(p.radius <= pJS.particles.size.anim.size_min) p.size_status = true;
71580          p.radius -= p.vs;
71581        }
71582        if(p.radius < 0) p.radius = 0;
71583      }
71584
71585      /* change particle position if it is out of canvas */
71586      if(pJS.particles.move.out_mode == 'bounce'){
71587        var new_pos = {
71588          x_left: p.radius,
71589          x_right:  pJS.canvas.w,
71590          y_top: p.radius,
71591          y_bottom: pJS.canvas.h
71592        }
71593      }else{
71594        var new_pos = {
71595          x_left: -p.radius,
71596          x_right: pJS.canvas.w + p.radius,
71597          y_top: -p.radius,
71598          y_bottom: pJS.canvas.h + p.radius
71599        }
71600      }
71601
71602      if(p.x - p.radius > pJS.canvas.w){
71603        p.x = new_pos.x_left;
71604        p.y = Math.random() * pJS.canvas.h;
71605      }
71606      else if(p.x + p.radius < 0){
71607        p.x = new_pos.x_right;
71608        p.y = Math.random() * pJS.canvas.h;
71609      }
71610      if(p.y - p.radius > pJS.canvas.h){
71611        p.y = new_pos.y_top;
71612        p.x = Math.random() * pJS.canvas.w;
71613      }
71614      else if(p.y + p.radius < 0){
71615        p.y = new_pos.y_bottom;
71616        p.x = Math.random() * pJS.canvas.w;
71617      }
71618
71619      /* out of canvas modes */
71620      switch(pJS.particles.move.out_mode){
71621        case 'bounce':
71622          if (p.x + p.radius > pJS.canvas.w) p.vx = -p.vx;
71623          else if (p.x - p.radius < 0) p.vx = -p.vx;
71624          if (p.y + p.radius > pJS.canvas.h) p.vy = -p.vy;
71625          else if (p.y - p.radius < 0) p.vy = -p.vy;
71626        break;
71627      }
71628
71629      /* events */
71630      if(isInArray('grab', pJS.interactivity.events.onhover.mode)){
71631        pJS.fn.modes.grabParticle(p);
71632      }
71633
71634      if(isInArray('bubble', pJS.interactivity.events.onhover.mode) || isInArray('bubble', pJS.interactivity.events.onclick.mode)){
71635        pJS.fn.modes.bubbleParticle(p);
71636      }
71637
71638      if(isInArray('repulse', pJS.interactivity.events.onhover.mode) || isInArray('repulse', pJS.interactivity.events.onclick.mode)){
71639        pJS.fn.modes.repulseParticle(p);
71640      }
71641
71642      /* interaction auto between particles */
71643      if(pJS.particles.line_linked.enable || pJS.particles.move.attract.enable){
71644        for(var j = i + 1; j < pJS.particles.array.length; j++){
71645          var p2 = pJS.particles.array[j];
71646
71647          /* link particles */
71648          if(pJS.particles.line_linked.enable){
71649            pJS.fn.interact.linkParticles(p,p2);
71650          }
71651
71652          /* attract particles */
71653          if(pJS.particles.move.attract.enable){
71654            pJS.fn.interact.attractParticles(p,p2);
71655          }
71656
71657          /* bounce particles */
71658          if(pJS.particles.move.bounce){
71659            pJS.fn.interact.bounceParticles(p,p2);
71660          }
71661
71662        }
71663      }
71664
71665
71666    }
71667
71668  };
71669
71670  pJS.fn.particlesDraw = function(){
71671
71672    /* clear canvas */
71673    pJS.canvas.ctx.clearRect(0, 0, pJS.canvas.w, pJS.canvas.h);
71674
71675    /* update each particles param */
71676    pJS.fn.particlesUpdate();
71677
71678    /* draw each particle */
71679    for(var i = 0; i < pJS.particles.array.length; i++){
71680      var p = pJS.particles.array[i];
71681      p.draw();
71682    }
71683
71684  };
71685
71686  pJS.fn.particlesEmpty = function(){
71687    pJS.particles.array = [];
71688  };
71689
71690  pJS.fn.particlesRefresh = function(){
71691
71692    /* init all */
71693    cancelRequestAnimFrame(pJS.fn.checkAnimFrame);
71694    cancelRequestAnimFrame(pJS.fn.drawAnimFrame);
71695    pJS.tmp.source_svg = undefined;
71696    pJS.tmp.source_svg_list = [];
71697    pJS.tmp.img_obj = undefined;
71698    pJS.tmp.count_svg = 0;
71699    pJS.fn.particlesEmpty();
71700    pJS.fn.canvasClear();
71701    
71702    /* restart */
71703    pJS.fn.vendors.start();
71704
71705  };
71706
71707
71708  /* ---------- pJS functions - particles interaction ------------ */
71709
71710  pJS.fn.interact.linkParticles = function(p1, p2){
71711
71712    var dx = p1.x - p2.x,
71713        dy = p1.y - p2.y,
71714        dist = Math.sqrt(dx*dx + dy*dy);
71715
71716    /* draw a line between p1 and p2 if the distance between them is under the config distance */
71717    if(dist <= pJS.particles.line_linked.distance){
71718
71719      var opacity_line = pJS.particles.line_linked.opacity - (dist / (1/pJS.particles.line_linked.opacity)) / pJS.particles.line_linked.distance;
71720
71721      if(opacity_line > 0){        
71722        
71723        /* style */
71724        var color_line = pJS.particles.line_linked.color_rgb_line;
71725        pJS.canvas.ctx.strokeStyle = 'rgba('+color_line.r+','+color_line.g+','+color_line.b+','+opacity_line+')';
71726        pJS.canvas.ctx.lineWidth = pJS.particles.line_linked.width;
71727        //pJS.canvas.ctx.lineCap = 'round'; /* performance issue */
71728        
71729        /* path */
71730        pJS.canvas.ctx.beginPath();
71731        pJS.canvas.ctx.moveTo(p1.x, p1.y);
71732        pJS.canvas.ctx.lineTo(p2.x, p2.y);
71733        pJS.canvas.ctx.stroke();
71734        pJS.canvas.ctx.closePath();
71735
71736      }
71737
71738    }
71739
71740  };
71741
71742
71743  pJS.fn.interact.attractParticles  = function(p1, p2){
71744
71745    /* condensed particles */
71746    var dx = p1.x - p2.x,
71747        dy = p1.y - p2.y,
71748        dist = Math.sqrt(dx*dx + dy*dy);
71749
71750    if(dist <= pJS.particles.line_linked.distance){
71751
71752      var ax = dx/(pJS.particles.move.attract.rotateX*1000),
71753          ay = dy/(pJS.particles.move.attract.rotateY*1000);
71754
71755      p1.vx -= ax;
71756      p1.vy -= ay;
71757
71758      p2.vx += ax;
71759      p2.vy += ay;
71760
71761    }
71762    
71763
71764  }
71765
71766
71767  pJS.fn.interact.bounceParticles = function(p1, p2){
71768
71769    var dx = p1.x - p2.x,
71770        dy = p1.y - p2.y,
71771        dist = Math.sqrt(dx*dx + dy*dy),
71772        dist_p = p1.radius+p2.radius;
71773
71774    if(dist <= dist_p){
71775      p1.vx = -p1.vx;
71776      p1.vy = -p1.vy;
71777
71778      p2.vx = -p2.vx;
71779      p2.vy = -p2.vy;
71780    }
71781
71782  }
71783
71784
71785  /* ---------- pJS functions - modes events ------------ */
71786
71787  pJS.fn.modes.pushParticles = function(nb, pos){
71788
71789    pJS.tmp.pushing = true;
71790
71791    for(var i = 0; i < nb; i++){
71792      pJS.particles.array.push(
71793        new pJS.fn.particle(
71794          pJS.particles.color,
71795          pJS.particles.opacity.value,
71796          {
71797            'x': pos ? pos.pos_x : Math.random() * pJS.canvas.w,
71798            'y': pos ? pos.pos_y : Math.random() * pJS.canvas.h
71799          }
71800        )
71801      )
71802      if(i == nb-1){
71803        if(!pJS.particles.move.enable){
71804          pJS.fn.particlesDraw();
71805        }
71806        pJS.tmp.pushing = false;
71807      }
71808    }
71809
71810  };
71811
71812
71813  pJS.fn.modes.removeParticles = function(nb){
71814
71815    pJS.particles.array.splice(0, nb);
71816    if(!pJS.particles.move.enable){
71817      pJS.fn.particlesDraw();
71818    }
71819
71820  };
71821
71822
71823  pJS.fn.modes.bubbleParticle = function(p){
71824
71825    /* on hover event */
71826    if(pJS.interactivity.events.onhover.enable && isInArray('bubble', pJS.interactivity.events.onhover.mode)){
71827
71828      var dx_mouse = p.x - pJS.interactivity.mouse.pos_x,
71829          dy_mouse = p.y - pJS.interactivity.mouse.pos_y,
71830          dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse),
71831          ratio = 1 - dist_mouse / pJS.interactivity.modes.bubble.distance;
71832
71833      function init(){
71834        p.opacity_bubble = p.opacity;
71835        p.radius_bubble = p.radius;
71836      }
71837
71838      /* mousemove - check ratio */
71839      if(dist_mouse <= pJS.interactivity.modes.bubble.distance){
71840
71841        if(ratio >= 0 && pJS.interactivity.status == 'mousemove'){
71842          
71843          /* size */
71844          if(pJS.interactivity.modes.bubble.size != pJS.particles.size.value){
71845
71846            if(pJS.interactivity.modes.bubble.size > pJS.particles.size.value){
71847              var size = p.radius + (pJS.interactivity.modes.bubble.size*ratio);
71848              if(size >= 0){
71849                p.radius_bubble = size;
71850              }
71851            }else{
71852              var dif = p.radius - pJS.interactivity.modes.bubble.size,
71853                  size = p.radius - (dif*ratio);
71854              if(size > 0){
71855                p.radius_bubble = size;
71856              }else{
71857                p.radius_bubble = 0;
71858              }
71859            }
71860
71861          }
71862
71863          /* opacity */
71864          if(pJS.interactivity.modes.bubble.opacity != pJS.particles.opacity.value){
71865
71866            if(pJS.interactivity.modes.bubble.opacity > pJS.particles.opacity.value){
71867              var opacity = pJS.interactivity.modes.bubble.opacity*ratio;
71868              if(opacity > p.opacity && opacity <= pJS.interactivity.modes.bubble.opacity){
71869                p.opacity_bubble = opacity;
71870              }
71871            }else{
71872              var opacity = p.opacity - (pJS.particles.opacity.value-pJS.interactivity.modes.bubble.opacity)*ratio;
71873              if(opacity < p.opacity && opacity >= pJS.interactivity.modes.bubble.opacity){
71874                p.opacity_bubble = opacity;
71875              }
71876            }
71877
71878          }
71879
71880        }
71881
71882      }else{
71883        init();
71884      }
71885
71886
71887      /* mouseleave */
71888      if(pJS.interactivity.status == 'mouseleave'){
71889        init();
71890      }
71891    
71892    }
71893
71894    /* on click event */
71895    else if(pJS.interactivity.events.onclick.enable && isInArray('bubble', pJS.interactivity.events.onclick.mode)){
71896
71897
71898      if(pJS.tmp.bubble_clicking){
71899        var dx_mouse = p.x - pJS.interactivity.mouse.click_pos_x,
71900            dy_mouse = p.y - pJS.interactivity.mouse.click_pos_y,
71901            dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse),
71902            time_spent = (new Date().getTime() - pJS.interactivity.mouse.click_time)/1000;
71903
71904        if(time_spent > pJS.interactivity.modes.bubble.duration){
71905          pJS.tmp.bubble_duration_end = true;
71906        }
71907
71908        if(time_spent > pJS.interactivity.modes.bubble.duration*2){
71909          pJS.tmp.bubble_clicking = false;
71910          pJS.tmp.bubble_duration_end = false;
71911        }
71912      }
71913
71914
71915      function process(bubble_param, particles_param, p_obj_bubble, p_obj, id){
71916
71917        if(bubble_param != particles_param){
71918
71919          if(!pJS.tmp.bubble_duration_end){
71920            if(dist_mouse <= pJS.interactivity.modes.bubble.distance){
71921              if(p_obj_bubble != undefined) var obj = p_obj_bubble;
71922              else var obj = p_obj;
71923              if(obj != bubble_param){
71924                var value = p_obj - (time_spent * (p_obj - bubble_param) / pJS.interactivity.modes.bubble.duration);
71925                if(id == 'size') p.radius_bubble = value;
71926                if(id == 'opacity') p.opacity_bubble = value;
71927              }
71928            }else{
71929              if(id == 'size') p.radius_bubble = undefined;
71930              if(id == 'opacity') p.opacity_bubble = undefined;
71931            }
71932          }else{
71933            if(p_obj_bubble != undefined){
71934              var value_tmp = p_obj - (time_spent * (p_obj - bubble_param) / pJS.interactivity.modes.bubble.duration),
71935                  dif = bubble_param - value_tmp;
71936                  value = bubble_param + dif;
71937              if(id == 'size') p.radius_bubble = value;
71938              if(id == 'opacity') p.opacity_bubble = value;
71939            }
71940          }
71941
71942        }
71943
71944      }
71945
71946      if(pJS.tmp.bubble_clicking){
71947        /* size */
71948        process(pJS.interactivity.modes.bubble.size, pJS.particles.size.value, p.radius_bubble, p.radius, 'size');
71949        /* opacity */
71950        process(pJS.interactivity.modes.bubble.opacity, pJS.particles.opacity.value, p.opacity_bubble, p.opacity, 'opacity');
71951      }
71952
71953    }
71954
71955  };
71956
71957
71958  pJS.fn.modes.repulseParticle = function(p){
71959
71960    if(pJS.interactivity.events.onhover.enable && isInArray('repulse', pJS.interactivity.events.onhover.mode) && pJS.interactivity.status == 'mousemove') {
71961
71962      var dx_mouse = p.x - pJS.interactivity.mouse.pos_x,
71963          dy_mouse = p.y - pJS.interactivity.mouse.pos_y,
71964          dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse);
71965
71966      var normVec = {x: dx_mouse/dist_mouse, y: dy_mouse/dist_mouse},
71967          repulseRadius = pJS.interactivity.modes.repulse.distance,
71968          velocity = 100,
71969          repulseFactor = clamp((1/repulseRadius)*(-1*Math.pow(dist_mouse/repulseRadius,2)+1)*repulseRadius*velocity, 0, 50);
71970      
71971      var pos = {
71972        x: p.x + normVec.x * repulseFactor,
71973        y: p.y + normVec.y * repulseFactor
71974      }
71975
71976      if(pJS.particles.move.out_mode == 'bounce'){
71977        if(pos.x - p.radius > 0 && pos.x + p.radius < pJS.canvas.w) p.x = pos.x;
71978        if(pos.y - p.radius > 0 && pos.y + p.radius < pJS.canvas.h) p.y = pos.y;
71979      }else{
71980        p.x = pos.x;
71981        p.y = pos.y;
71982      }
71983    
71984    }
71985
71986
71987    else if(pJS.interactivity.events.onclick.enable && isInArray('repulse', pJS.interactivity.events.onclick.mode)) {
71988
71989      if(!pJS.tmp.repulse_finish){
71990        pJS.tmp.repulse_count++;
71991        if(pJS.tmp.repulse_count == pJS.particles.array.length){
71992          pJS.tmp.repulse_finish = true;
71993        }
71994      }
71995
71996      if(pJS.tmp.repulse_clicking){
71997
71998        var repulseRadius = Math.pow(pJS.interactivity.modes.repulse.distance/6, 3);
71999
72000        var dx = pJS.interactivity.mouse.click_pos_x - p.x,
72001            dy = pJS.interactivity.mouse.click_pos_y - p.y,
72002            d = dx*dx + dy*dy;
72003
72004        var force = -repulseRadius / d * 1;
72005
72006        function process(){
72007
72008          var f = Math.atan2(dy,dx);
72009          p.vx = force * Math.cos(f);
72010          p.vy = force * Math.sin(f);
72011
72012          if(pJS.particles.move.out_mode == 'bounce'){
72013            var pos = {
72014              x: p.x + p.vx,
72015              y: p.y + p.vy
72016            }
72017            if (pos.x + p.radius > pJS.canvas.w) p.vx = -p.vx;
72018            else if (pos.x - p.radius < 0) p.vx = -p.vx;
72019            if (pos.y + p.radius > pJS.canvas.h) p.vy = -p.vy;
72020            else if (pos.y - p.radius < 0) p.vy = -p.vy;
72021          }
72022
72023        }
72024
72025        // default
72026        if(d <= repulseRadius){
72027          process();
72028        }
72029
72030        // bang - slow motion mode
72031        // if(!pJS.tmp.repulse_finish){
72032        //   if(d <= repulseRadius){
72033        //     process();
72034        //   }
72035        // }else{
72036        //   process();
72037        // }
72038        
72039
72040      }else{
72041
72042        if(pJS.tmp.repulse_clicking == false){
72043
72044          p.vx = p.vx_i;
72045          p.vy = p.vy_i;
72046        
72047        }
72048
72049      }
72050
72051    }
72052
72053  }
72054
72055
72056  pJS.fn.modes.grabParticle = function(p){
72057
72058    if(pJS.interactivity.events.onhover.enable && pJS.interactivity.status == 'mousemove'){
72059
72060      var dx_mouse = p.x - pJS.interactivity.mouse.pos_x,
72061          dy_mouse = p.y - pJS.interactivity.mouse.pos_y,
72062          dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse);
72063
72064      /* draw a line between the cursor and the particle if the distance between them is under the config distance */
72065      if(dist_mouse <= pJS.interactivity.modes.grab.distance){
72066
72067        var opacity_line = pJS.interactivity.modes.grab.line_linked.opacity - (dist_mouse / (1/pJS.interactivity.modes.grab.line_linked.opacity)) / pJS.interactivity.modes.grab.distance;
72068
72069        if(opacity_line > 0){
72070
72071          /* style */
72072          var color_line = pJS.particles.line_linked.color_rgb_line;
72073          pJS.canvas.ctx.strokeStyle = 'rgba('+color_line.r+','+color_line.g+','+color_line.b+','+opacity_line+')';
72074          pJS.canvas.ctx.lineWidth = pJS.particles.line_linked.width;
72075          //pJS.canvas.ctx.lineCap = 'round'; /* performance issue */
72076          
72077          /* path */
72078          pJS.canvas.ctx.beginPath();
72079          pJS.canvas.ctx.moveTo(p.x, p.y);
72080          pJS.canvas.ctx.lineTo(pJS.interactivity.mouse.pos_x, pJS.interactivity.mouse.pos_y);
72081          pJS.canvas.ctx.stroke();
72082          pJS.canvas.ctx.closePath();
72083
72084        }
72085
72086      }
72087
72088    }
72089
72090  };
72091
72092
72093
72094  /* ---------- pJS functions - vendors ------------ */
72095
72096  pJS.fn.vendors.eventsListeners = function(){
72097
72098    /* events target element */
72099    if(pJS.interactivity.detect_on == 'window'){
72100      pJS.interactivity.el = window;
72101    }else{
72102      pJS.interactivity.el = pJS.canvas.el;
72103    }
72104
72105
72106    /* detect mouse pos - on hover / click event */
72107    if(pJS.interactivity.events.onhover.enable || pJS.interactivity.events.onclick.enable){
72108
72109      /* el on mousemove */
72110      pJS.interactivity.el.addEventListener('mousemove', function(e){
72111
72112        if(pJS.interactivity.el == window){
72113          var pos_x = e.clientX,
72114              pos_y = e.clientY;
72115        }
72116        else{
72117          var pos_x = e.offsetX || e.clientX,
72118              pos_y = e.offsetY || e.clientY;
72119        }
72120
72121        pJS.interactivity.mouse.pos_x = pos_x;
72122        pJS.interactivity.mouse.pos_y = pos_y;
72123
72124        if(pJS.tmp.retina){
72125          pJS.interactivity.mouse.pos_x *= pJS.canvas.pxratio;
72126          pJS.interactivity.mouse.pos_y *= pJS.canvas.pxratio;
72127        }
72128
72129        pJS.interactivity.status = 'mousemove';
72130
72131      });
72132
72133      /* el on onmouseleave */
72134      pJS.interactivity.el.addEventListener('mouseleave', function(e){
72135
72136        pJS.interactivity.mouse.pos_x = null;
72137        pJS.interactivity.mouse.pos_y = null;
72138        pJS.interactivity.status = 'mouseleave';
72139
72140      });
72141
72142    }
72143
72144    /* on click event */
72145    if(pJS.interactivity.events.onclick.enable){
72146
72147      pJS.interactivity.el.addEventListener('click', function(){
72148
72149        pJS.interactivity.mouse.click_pos_x = pJS.interactivity.mouse.pos_x;
72150        pJS.interactivity.mouse.click_pos_y = pJS.interactivity.mouse.pos_y;
72151        pJS.interactivity.mouse.click_time = new Date().getTime();
72152
72153        if(pJS.interactivity.events.onclick.enable){
72154
72155          switch(pJS.interactivity.events.onclick.mode){
72156
72157            case 'push':
72158              if(pJS.particles.move.enable){
72159                pJS.fn.modes.pushParticles(pJS.interactivity.modes.push.particles_nb, pJS.interactivity.mouse);
72160              }else{
72161                if(pJS.interactivity.modes.push.particles_nb == 1){
72162                  pJS.fn.modes.pushParticles(pJS.interactivity.modes.push.particles_nb, pJS.interactivity.mouse);
72163                }
72164                else if(pJS.interactivity.modes.push.particles_nb > 1){
72165                  pJS.fn.modes.pushParticles(pJS.interactivity.modes.push.particles_nb);
72166                }
72167              }
72168            break;
72169
72170            case 'remove':
72171              pJS.fn.modes.removeParticles(pJS.interactivity.modes.remove.particles_nb);
72172            break;
72173
72174            case 'bubble':
72175              pJS.tmp.bubble_clicking = true;
72176            break;
72177
72178            case 'repulse':
72179              pJS.tmp.repulse_clicking = true;
72180              pJS.tmp.repulse_count = 0;
72181              pJS.tmp.repulse_finish = false;
72182              setTimeout(function(){
72183                pJS.tmp.repulse_clicking = false;
72184              }, pJS.interactivity.modes.repulse.duration*1000)
72185            break;
72186
72187          }
72188
72189        }
72190
72191      });
72192        
72193    }
72194
72195
72196  };
72197
72198  pJS.fn.vendors.densityAutoParticles = function(){
72199
72200    if(pJS.particles.number.density.enable){
72201
72202      /* calc area */
72203      var area = pJS.canvas.el.width * pJS.canvas.el.height / 1000;
72204      if(pJS.tmp.retina){
72205        area = area/(pJS.canvas.pxratio*2);
72206      }
72207
72208      /* calc number of particles based on density area */
72209      var nb_particles = area * pJS.particles.number.value / pJS.particles.number.density.value_area;
72210
72211      /* add or remove X particles */
72212      var missing_particles = pJS.particles.array.length - nb_particles;
72213      if(missing_particles < 0) pJS.fn.modes.pushParticles(Math.abs(missing_particles));
72214      else pJS.fn.modes.removeParticles(missing_particles);
72215
72216    }
72217
72218  };
72219
72220
72221  pJS.fn.vendors.checkOverlap = function(p1, position){
72222    for(var i = 0; i < pJS.particles.array.length; i++){
72223      var p2 = pJS.particles.array[i];
72224
72225      var dx = p1.x - p2.x,
72226          dy = p1.y - p2.y,
72227          dist = Math.sqrt(dx*dx + dy*dy);
72228
72229      if(dist <= p1.radius + p2.radius){
72230        p1.x = position ? position.x : Math.random() * pJS.canvas.w;
72231        p1.y = position ? position.y : Math.random() * pJS.canvas.h;
72232        pJS.fn.vendors.checkOverlap(p1);
72233      }
72234    }
72235  };
72236
72237
72238  pJS.fn.vendors.createSvgImg = function(p, source_svg){
72239    /* set color to svg element */
72240    var svgXml =  source_svg,
72241        rgbHex = /#([0-9A-F]{3,6})/gi,
72242        coloredSvgXml = svgXml.replace(rgbHex, function (m, r, g, b) {
72243          if(p.color.rgb){
72244            var color_value = 'rgba('+p.color.rgb.r+','+p.color.rgb.g+','+p.color.rgb.b+','+p.opacity+')';
72245          }else{
72246            var color_value = 'hsla('+p.color.hsl.h+','+p.color.hsl.s+'%,'+p.color.hsl.l+'%,'+p.opacity+')';
72247          }
72248          return color_value;
72249        });
72250
72251    /* prepare to create img with colored svg */
72252    var svg = new Blob([coloredSvgXml], {type: 'image/svg+xml;charset=utf-8'}),
72253        DOMURL = window.URL || window.webkitURL || window,
72254        url = DOMURL.createObjectURL(svg);
72255    /* create particle img obj */
72256    var img = new Image();
72257    img.addEventListener('load', function(){
72258        p.img.obj = img;
72259        p.img.loaded = true;
72260        DOMURL.revokeObjectURL(url);
72261        pJS.tmp.count_svg++;
72262    });
72263    img.src = url;
72264  };
72265
72266
72267  pJS.fn.vendors.destroypJS = function(){
72268    cancelAnimationFrame(pJS.fn.drawAnimFrame);
72269    canvas_el.remove();
72270    pJSDom = null;
72271  };
72272
72273
72274  pJS.fn.vendors.drawShape = function(c, startX, startY, sideLength, sideCountNumerator, sideCountDenominator){
72275
72276    // By Programming Thomas - https://programmingthomas.wordpress.com/2013/04/03/n-sided-shapes/
72277    var sideCount = sideCountNumerator * sideCountDenominator;
72278    var decimalSides = sideCountNumerator / sideCountDenominator;
72279    var interiorAngleDegrees = (180 * (decimalSides - 2)) / decimalSides;
72280    var interiorAngle = Math.PI - Math.PI * interiorAngleDegrees / 180; // convert to radians
72281    c.save();
72282    c.beginPath();
72283    c.translate(startX, startY);
72284    c.moveTo(0,0);
72285    for (var i = 0; i < sideCount; i++) {
72286      c.lineTo(sideLength,0);
72287      c.translate(sideLength,0);
72288      c.rotate(interiorAngle);
72289    }
72290    //c.stroke();
72291    c.fill();
72292    c.restore();
72293
72294  };
72295
72296  pJS.fn.vendors.exportImg = function(){
72297    window.open(pJS.canvas.el.toDataURL('image/png'), '_blank');
72298  };
72299
72300
72301  pJS.fn.vendors.loadImg = function(type){
72302
72303    pJS.tmp.img_error = undefined;
72304    if(pJS.particles.shape.image.src_list && pJS.particles.shape.image.src_list.length >= 2){
72305      // type svg support only
72306      var xhrList = []
72307      for(var i in pJS.particles.shape.image.src_list){
72308          (function(index){
72309              xhrList[index] = new XMLHttpRequest();
72310              xhrList[index].open('GET', pJS.particles.shape.image.src_list[index]);
72311              xhrList[index].onreadystatechange = function(data){
72312                if(xhrList[index].readyState == 4 && xhrList[index].status == 200){
72313
72314                   pJS.tmp.source_svg_list[index] = data.currentTarget.response
72315
72316                    // Check whether all the images are loaded. You cannot 
72317                    // rely on the index
72318                   var isLoaded = true;
72319
72320                   for (var j in pJS.particles.shape.image.src_list){
72321                       if (pJS.tmp.source_svg_list[j] === undefined) {
72322                           isLoaded = false;
72323                       }
72324                   }
72325
72326                   if (isLoaded) {
72327                        pJS.fn.vendors.checkBeforeDraw();
72328                   }
72329                }
72330              }
72331              xhrList[index].send()
72332          })(i)
72333      }
72334      return   
72335    }
72336
72337    if(pJS.particles.shape.image.src != ''){
72338      if(type == 'svg'){
72339        var xhr = new XMLHttpRequest();
72340        xhr.open('GET', pJS.particles.shape.image.src);
72341        xhr.onreadystatechange = function (data) {
72342          if(xhr.readyState == 4){
72343            if(xhr.status == 200){
72344              pJS.tmp.source_svg = data.currentTarget.response;
72345              pJS.fn.vendors.checkBeforeDraw();
72346            }else{
72347              console.log('Error pJS - Image not found');
72348              pJS.tmp.img_error = true;
72349            }
72350          }
72351        }
72352        xhr.send();
72353      }else{
72354        var img = new Image();
72355        img.addEventListener('load', function(){
72356          pJS.tmp.img_obj = img;
72357          pJS.fn.vendors.checkBeforeDraw();
72358        });
72359        img.src = pJS.particles.shape.image.src;
72360      }
72361    }
72362    else{
72363      if( ! pJS.particles.shape.image.src_list || pJS.particles.shape.image.src_list.length < 2){
72364          console.log('Error pJS - No image.src');
72365          pJS.tmp.img_error = true;
72366      }
72367    }
72368
72369  };
72370
72371
72372  pJS.fn.vendors.draw = function(){
72373    if(pJS.particles.shape.type == 'image'){
72374      if(pJS.tmp.img_type == 'svg'){
72375        if(pJS.tmp.count_svg >= pJS.particles.number.value){
72376          pJS.fn.particlesDraw();
72377          if(!pJS.particles.move.enable) cancelRequestAnimFrame(pJS.fn.drawAnimFrame);
72378          else pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw);
72379        }else{
72380          //console.log('still loading...');
72381          if(!pJS.tmp.img_error) pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw);
72382        }
72383      }else{
72384        if(pJS.tmp.img_obj != undefined){
72385          pJS.fn.particlesDraw();
vendor: 5,769 bytes, lines 72386-72592
72386          if(!pJS.particles.move.enable) cancelRequestAnimFrame(pJS.fn.drawAnimFrame);
72387          else pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw);
72388        }else{
72389          if(!pJS.tmp.img_error) pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw);
72390        }
72391      }
72392    }else{
72393      pJS.fn.particlesDraw();
72394      if(!pJS.particles.move.enable) cancelRequestAnimFrame(pJS.fn.drawAnimFrame);
72395      else pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw);
72396    }
72397
72398  };
72399
72400
72401  pJS.fn.vendors.checkBeforeDraw = function(){
72402
72403    // if shape is image
72404    if(pJS.tmp.source_svg_list.length){
72405        pJS.fn.vendors.init();
72406        pJS.fn.vendors.draw();
72407        return 
72408    }
72409    if(pJS.particles.shape.type == 'image'){
72410      if(pJS.tmp.img_type == 'svg' && pJS.tmp.source_svg == undefined){
72411        pJS.tmp.checkAnimFrame = requestAnimFrame(check);
72412      }else{
72413        //console.log('images loaded! cancel check');
72414        cancelRequestAnimFrame(pJS.tmp.checkAnimFrame);
72415        if(!pJS.tmp.img_error){
72416          pJS.fn.vendors.init();
72417          pJS.fn.vendors.draw();
72418        }
72419        
72420      }
72421
72422    }else{    
72423      pJS.fn.vendors.init();
72424      pJS.fn.vendors.draw();
72425    }
72426
72427  };
72428
72429
72430  pJS.fn.vendors.init = function(){
72431
72432    /* init canvas + particles */
72433    pJS.fn.retinaInit();
72434    pJS.fn.canvasInit();
72435    pJS.fn.canvasSize();
72436    pJS.fn.canvasPaint();
72437    pJS.fn.particlesCreate();
72438    pJS.fn.vendors.densityAutoParticles();
72439
72440    /* particles.line_linked - convert hex colors to rgb */
72441    pJS.particles.line_linked.color_rgb_line = hexToRgb(pJS.particles.line_linked.color);
72442
72443  };
72444
72445
72446  pJS.fn.vendors.start = function(){
72447
72448    if(isInArray('image', pJS.particles.shape.type)){
72449      var src_split = pJS.particles.shape.image.src.split(".");
72450      var type = src_split[ src_split.length - 1 >= 0 ? src_split.length - 1 : '' ]
72451      pJS.tmp.img_type = type ? type.toLowerCase() : 'svg';
72452      pJS.fn.vendors.loadImg(pJS.tmp.img_type);
72453    }else{
72454      pJS.fn.vendors.checkBeforeDraw();
72455    }
72456
72457  };
72458
72459
72460
72461
72462  /* ---------- pJS - start ------------ */
72463
72464
72465  pJS.fn.vendors.eventsListeners();
72466
72467  pJS.fn.vendors.start();
72468  
72469
72470
72471};
72472
72473/* ---------- global functions - vendors ------------ */
72474
72475Object.deepExtend = function(destination, source) {
72476  for (var property in source) {
72477    if (source[property] && source[property].constructor &&
72478     source[property].constructor === Object) {
72479      destination[property] = destination[property] || {};
72480      arguments.callee(destination[property], source[property]);
72481    } else {
72482      destination[property] = source[property];
72483    }
72484  }
72485  return destination;
72486};
72487
72488window.requestAnimFrame = (function(){
72489  return  window.requestAnimationFrame ||
72490    window.webkitRequestAnimationFrame ||
72491    window.mozRequestAnimationFrame    ||
72492    window.oRequestAnimationFrame      ||
72493    window.msRequestAnimationFrame     ||
72494    function(callback){
72495      window.setTimeout(callback, 1000 / 60);
72496    };
72497})();
72498
72499window.cancelRequestAnimFrame = ( function() {
72500  return window.cancelAnimationFrame         ||
72501    window.webkitCancelRequestAnimationFrame ||
72502    window.mozCancelRequestAnimationFrame    ||
72503    window.oCancelRequestAnimationFrame      ||
72504    window.msCancelRequestAnimationFrame     ||
72505    clearTimeout
72506} )();
72507
72508function hexToRgb(hex){
72509  // By Tim Down - http://stackoverflow.com/a/5624139/3493650
72510  // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
72511  var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
72512  hex = hex.replace(shorthandRegex, function(m, r, g, b) {
72513     return r + r + g + g + b + b;
72514  });
72515  var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
72516  return result ? {
72517      r: parseInt(result[1], 16),
72518      g: parseInt(result[2], 16),
72519      b: parseInt(result[3], 16)
72520  } : null;
72521};
72522
72523function clamp(number, min, max) {
72524  return Math.min(Math.max(number, min), max);
72525};
72526
72527function isInArray(value, array) {
72528  return array.indexOf(value) > -1;
72529}
72530
72531
72532/* ---------- particles.js functions - start ------------ */
72533
72534window.pJSDom = [];
72535
72536window.particlesJS = function(tag_id, params){
72537
72538  //console.log(params);
72539
72540  /* no string id? so it's object params, and set the id with default id */
72541  if(typeof(tag_id) != 'string'){
72542    params = tag_id;
72543    tag_id = 'particles-js';
72544  }
72545
72546  /* no id? set the id to default id */
72547  if(!tag_id){
72548    tag_id = 'particles-js';
72549  }
72550
72551  /* pJS elements */
72552  var pJS_tag = document.getElementById(tag_id),
72553      pJS_canvas_class = 'particles-js-canvas-el',
72554      exist_canvas = pJS_tag.getElementsByClassName(pJS_canvas_class);
72555
72556  /* remove canvas if exists into the pJS target tag */
72557  if(exist_canvas.length){
72558    while(exist_canvas.length > 0){
72559      pJS_tag.removeChild(exist_canvas[0]);
72560    }
72561  }
72562
72563  /* create canvas element */
72564  var canvas_el = document.createElement('canvas');
72565  canvas_el.className = pJS_canvas_class;
72566
72567  /* set size canvas */
72568  canvas_el.style.width = "100%";
72569  canvas_el.style.height = "100%";
72570
72571  /* append canvas */
72572  var canvas = document.getElementById(tag_id).appendChild(canvas_el);
72573
72574  /* launch particle.js */
72575  if(canvas != null){
72576    pJSDom.push(new pJS(tag_id, params));
72577  }
72578
72579};
72580
72581window.particlesJS.load = function(tag_id, path_config_json, callback){
72582
72583  /* load json config */
72584  var xhr = new XMLHttpRequest();
72585  xhr.open('GET', path_config_json);
72586  xhr.onreadystatechange = function (data) {
72587    if(xhr.readyState == 4){
72588      if(xhr.status == 200){
72589        var params = JSON.parse(data.currentTarget.response);
72590        window.particlesJS(tag_id, params);
72591        if(callback) callback();
72592      }else{
72593        console.log('Error pJS - XMLHttpRequest status: '+xhr.status);
72594        console.log('Error pJS - File config not found');
72595      }
72596    }
72597  };
72598  xhr.send();
72599
72600};
72601define("particles", function(){});
72602
72603/*global ActiveXObject, window, console, define, module, jQuery */
72604//jshint unused:false, strict: false
72605
72606/**
72607 *  PDFObject v2.1.1
72608 *  https://github.com/pipwerks/PDFObject
72609 *  @license
72610 *  Copyright (c) 2008-2018 Philip Hutchison
72611 *  MIT-style license: http://pipwerks.mit-license.org/
72612 *  UMD module pattern from https://github.com/umdjs/umd/blob/master/templates/returnExports.js
72613 */
72614
72615(function (root, factory) {
72616    if (typeof define === 'function' && define.amd) {
72617        // AMD. Register as an anonymous module.
72618        define('pdfobject',[], factory);
72619    } else if (typeof module === 'object' && module.exports) {
72620        // Node. Does not work with strict CommonJS, but
72621        // only CommonJS-like environments that support module.exports,
72622        // like Node.
72623        module.exports = factory();
72624    } else {
72625        // Browser globals (root is window)
72626        root.PDFObject = factory();
72627  }
72628}(this, function () {
72629
72630    "use strict";
72631    //jshint unused:true
72632
72633    //PDFObject is designed for client-side (browsers), not server-side (node)
72634    //Will choke on undefined navigator and window vars when run on server
72635    //Return boolean false and exit function when running server-side
72636
72637    if(typeof window === "undefined" || typeof navigator === "undefined"){ return false; }
72638
72639    var pdfobjectversion = "2.1.1",
72640        ua = window.navigator.userAgent,
72641
72642        //declare booleans
72643        supportsPDFs,
72644        isIE,
72645        supportsPdfMimeType = (typeof navigator.mimeTypes !== "undefined" && typeof navigator.mimeTypes['application/pdf'] !== "undefined"),
72646        supportsPdfActiveX,
72647        isModernBrowser = (function (){ return (typeof window.Promise !== "undefined"); })(),
72648        isFirefox = (function (){ return (ua.indexOf("irefox") !== -1); } )(),
72649        isFirefoxWithPDFJS = (function (){
72650            //Firefox started shipping PDF.js in Firefox 19.
72651            //If this is Firefox 19 or greater, assume PDF.js is available
72652            if(!isFirefox){ return false; }
72653            //parse userAgent string to get release version ("rv")
72654            //ex: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:57.0) Gecko/20100101 Firefox/57.0
72655            return (parseInt(ua.split("rv:")[1].split(".")[0], 10) > 18);
72656        })(),
72657        isIOS = (function (){ return (/iphone|ipad|ipod/i.test(ua.toLowerCase())); })(),
72658
72659        //declare functions
72660        createAXO,
72661        buildFragmentString,
72662        log,
72663        embedError,
72664        embed,
72665        getTargetElement,
72666        generatePDFJSiframe,
72667        generateEmbedElement;
72668
72669
72670    /* ----------------------------------------------------
72671       Supporting functions
72672       ---------------------------------------------------- */
72673
72674    createAXO = function (type){
72675        var ax;
72676        try {
72677            ax = new ActiveXObject(type);
72678        } catch (e) {
72679            ax = null; //ensure ax remains null
72680        }
72681        return ax;
72682    };
72683
72684    //IE11 still uses ActiveX for Adobe Reader, but IE 11 doesn't expose
72685    //window.ActiveXObject the same way previous versions of IE did
72686    //window.ActiveXObject will evaluate to false in IE 11, but "ActiveXObject" in window evaluates to true
72687    //so check the first one for older IE, and the second for IE11
72688    //FWIW, MS Edge (replacing IE11) does not support ActiveX at all, both will evaluate false
72689    //Constructed as a method (not a prop) to avoid unneccesarry overhead -- will only be evaluated if needed
72690    isIE = function (){ return !!(window.ActiveXObject || "ActiveXObject" in window); };
72691
72692    //If either ActiveX support for "AcroPDF.PDF" or "PDF.PdfCtrl" are found, return true
72693    //Constructed as a method (not a prop) to avoid unneccesarry overhead -- will only be evaluated if needed
72694    supportsPdfActiveX = function (){ return !!(createAXO("AcroPDF.PDF") || createAXO("PDF.PdfCtrl")); };
72695
72696    //Determines whether PDF support is available
72697    supportsPDFs = (
72698        //as of iOS 12, inline PDF rendering is still not supported in Safari or native webview
72699        //3rd-party browsers (eg Chrome, Firefox) use Apple's webview for rendering, and thus the same result as Safari
72700        //Therefore if iOS, we shall assume that PDF support is not available
72701        !isIOS && (
72702            //Modern versions of Firefox come bundled with PDFJS
72703            isFirefoxWithPDFJS ||
72704            //Browsers that still support the original MIME type check
72705            supportsPdfMimeType || (
72706                //Pity the poor souls still using IE
72707                isIE() && supportsPdfActiveX()
72708            )
72709        )
72710    );
72711
72712    //Create a fragment identifier for using PDF Open parameters when embedding PDF
72713    buildFragmentString = function(pdfParams){
72714
72715        var string = "",
72716            prop;
72717
72718        if(pdfParams){
72719
72720            for (prop in pdfParams) {
72721                if (pdfParams.hasOwnProperty(prop)) {
72722                    string += encodeURIComponent(prop) + "=" + encodeURIComponent(pdfParams[prop]) + "&";
72723                }
72724            }
72725
72726            //The string will be empty if no PDF Params found
72727            if(string){
72728
72729                string = "#" + string;
72730
72731                //Remove last ampersand
72732                string = string.slice(0, string.length - 1);
72733
72734            }
72735
72736        }
72737
72738        return string;
72739
72740    };
72741
72742    log = function (msg){
72743        if(typeof console !== "undefined" && console.log){
72744            console.log("[PDFObject] " + msg);
72745        }
72746    };
72747
72748    embedError = function (msg){
72749        log(msg);
72750        return false;
72751    };
72752
72753    getTargetElement = function (targetSelector){
72754
72755        //Default to body for full-browser PDF
72756        var targetNode = document.body;
72757
72758        //If a targetSelector is specified, check to see whether
72759        //it's passing a selector, jQuery object, or an HTML element
72760
72761        if(typeof targetSelector === "string"){
72762
72763            //Is CSS selector
72764            targetNode = document.querySelector(targetSelector);
72765
72766        } else if (typeof jQuery !== "undefined" && targetSelector instanceof jQuery && targetSelector.length) {
72767
72768            //Is jQuery element. Extract HTML node
72769            targetNode = targetSelector.get(0);
72770
72771        } else if (typeof targetSelector.nodeType !== "undefined" && targetSelector.nodeType === 1){
72772
72773            //Is HTML element
72774            targetNode = targetSelector;
72775
72776        }
72777
72778        return targetNode;
72779
72780    };
72781
72782    generatePDFJSiframe = function (targetNode, url, pdfOpenFragment, PDFJS_URL, id){
72783
72784        var fullURL = PDFJS_URL + "?file=" + encodeURIComponent(url) + pdfOpenFragment;
72785        var scrollfix = (isIOS) ? "-webkit-overflow-scrolling: touch; overflow-y: scroll; " : "overflow: hidden; ";
72786        var iframe = "<div style='" + scrollfix + "position: absolute; top: 0; right: 0; bottom: 0; left: 0;'><iframe  " + id + " src='" + fullURL + "' style='border: none; width: 100%; height: 100%;' frameborder='0'></iframe></div>";
72787        targetNode.className += " pdfobject-container";
72788        targetNode.style.position = "relative";
72789        targetNode.style.overflow = "auto";
72790        targetNode.innerHTML = iframe;
72791        return targetNode.getElementsByTagName("iframe")[0];
72792
72793    };
72794
72795    generateEmbedElement = function (targetNode, targetSelector, url, pdfOpenFragment, width, height, id){
72796
72797        var style = "";
72798
72799        if(targetSelector && targetSelector !== document.body){
72800            style = "width: " + width + "; height: " + height + ";";
72801        } else {
72802            style = "position: absolute; top: 0; right: 0; bottom: 0; left: 0; width: 100%; height: 100%;";
72803        }
72804
72805        targetNode.className += " pdfobject-container";
72806        targetNode.innerHTML = "<embed " + id + " class='pdfobject' src='" + url + pdfOpenFragment + "' type='application/pdf' style='overflow: auto; " + style + "'/>";
72807
72808        return targetNode.getElementsByTagName("embed")[0];
72809
72810    };
72811
72812    embed = function(url, targetSelector, options){
72813
72814        //Ensure URL is available. If not, exit now.
72815        if(typeof url !== "string"){ return embedError("URL is not valid"); }
72816
72817        //If targetSelector is not defined, convert to boolean
72818        targetSelector = (typeof targetSelector !== "undefined") ? targetSelector : false;
72819
72820        //Ensure options object is not undefined -- enables easier error checking below
72821        options = (typeof options !== "undefined") ? options : {};
72822
72823        //Get passed options, or set reasonable defaults
72824        var id = (options.id && typeof options.id === "string") ? "id='" + options.id + "'" : "",
72825            page = (options.page) ? options.page : false,
72826            pdfOpenParams = (options.pdfOpenParams) ? options.pdfOpenParams : {},
72827            fallbackLink = (typeof options.fallbackLink !== "undefined") ? options.fallbackLink : true,
72828            width = (options.width) ? options.width : "100%",
72829            height = (options.height) ? options.height : "100%",
72830            assumptionMode = (typeof options.assumptionMode === "boolean") ? options.assumptionMode : true,
72831            forcePDFJS = (typeof options.forcePDFJS === "boolean") ? options.forcePDFJS : false,
72832            PDFJS_URL = (options.PDFJS_URL) ? options.PDFJS_URL : false,
72833            targetNode = getTargetElement(targetSelector),
72834            fallbackHTML = "",
72835            pdfOpenFragment = "",
72836            fallbackHTML_default = "<p>This browser does not support inline PDFs. Please download the PDF to view it: <a href='[url]'>Download PDF</a></p>";
72837
72838        //If target element is specified but is not valid, exit without doing anything
72839        if(!targetNode){ return embedError("Target element cannot be determined"); }
72840
72841
72842        //page option overrides pdfOpenParams, if found
72843        if(page){
72844            pdfOpenParams.page = page;
72845        }
72846
72847        //Stringify optional Adobe params for opening document (as fragment identifier)
72848        pdfOpenFragment = buildFragmentString(pdfOpenParams);
72849
72850        //Do the dance
72851
72852        //If the forcePDFJS option is invoked, skip everything else and embed as directed
72853        if(forcePDFJS && PDFJS_URL){
72854
72855            return generatePDFJSiframe(targetNode, url, pdfOpenFragment, PDFJS_URL, id);
72856
72857        //If traditional support is provided, or if this is a modern browser and not iOS (see comment for supportsPDFs declaration)
72858        } else if(supportsPDFs || (assumptionMode && isModernBrowser && !isIOS)){
72859
72860            return generateEmbedElement(targetNode, targetSelector, url, pdfOpenFragment, width, height, id);
72861
72862        //If everything else has failed and a PDFJS fallback is provided, try to use it
72863        } else if(PDFJS_URL){
72864
72865            return generatePDFJSiframe(targetNode, url, pdfOpenFragment, PDFJS_URL, id);
72866
72867        } else {
72868
72869            //Display the fallback link if available
72870            if(fallbackLink){
72871
72872                fallbackHTML = (typeof fallbackLink === "string") ? fallbackLink : fallbackHTML_default;
72873                targetNode.innerHTML = fallbackHTML.replace(/\[url\]/g, url);
72874
72875            }
72876
72877            return embedError("This browser does not support embedded PDFs");
72878
72879        }
72880
72881    };
72882
72883    return {
72884        embed: function (a,b,c){ return embed(a,b,c); },
72885        pdfobjectversion: (function () { return pdfobjectversion; })(),
72886        supportsPDFs: (function (){ return supportsPDFs; })()
72887    };
72888
72889}));
72890/* perfect-scrollbar v0.6.14 */
72891(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
72892'use strict';
72893
72894var ps = require('../main');
72895var psInstances = require('../plugin/instances');
72896
72897function mountJQuery(jQuery) {
72898  jQuery.fn.perfectScrollbar = function (settingOrCommand) {
72899    return this.each(function () {
72900      if (typeof settingOrCommand === 'object' ||
72901          typeof settingOrCommand === 'undefined') {
72902        // If it's an object or none, initialize.
72903        var settings = settingOrCommand;
72904
72905        if (!psInstances.get(this)) {
72906          ps.initialize(this, settings);
72907        }
72908      } else {
72909        // Unless, it may be a command.
72910        var command = settingOrCommand;
72911
72912        if (command === 'update') {
72913          ps.update(this);
72914        } else if (command === 'destroy') {
72915          ps.destroy(this);
72916        }
72917      }
72918    });
72919  };
72920}
72921
72922if (typeof define === 'function' && define.amd) {
72923  // AMD. Register as an anonymous module.
72924  define('perfectScrollbarJquery',['jquery'], mountJQuery);
72925} else {
72926  var jq = window.jQuery ? window.jQuery : window.$;
72927  if (typeof jq !== 'undefined') {
72928    mountJQuery(jq);
72929  }
72930}
72931
72932module.exports = mountJQuery;
72933
72934},{"../main":7,"../plugin/instances":18}],2:[function(require,module,exports){
72935'use strict';
72936
72937function oldAdd(element, className) {
72938  var classes = element.className.split(' ');
72939  if (classes.indexOf(className) < 0) {
72940    classes.push(className);
72941  }
72942  element.className = classes.join(' ');
72943}
72944
72945function oldRemove(element, className) {
72946  var classes = element.className.split(' ');
72947  var idx = classes.indexOf(className);
72948  if (idx >= 0) {
72949    classes.splice(idx, 1);
72950  }
72951  element.className = classes.join(' ');
72952}
72953
72954exports.add = function (element, className) {
72955  if (element.classList) {
72956    element.classList.add(className);
72957  } else {
72958    oldAdd(element, className);
72959  }
72960};
72961
72962exports.remove = function (element, className) {
72963  if (element.classList) {
72964    element.classList.remove(className);
72965  } else {
72966    oldRemove(element, className);
72967  }
72968};
72969
72970exports.list = function (element) {
72971  if (element.classList) {
72972    return Array.prototype.slice.apply(element.classList);
72973  } else {
72974    return element.className.split(' ');
72975  }
72976};
72977
72978},{}],3:[function(require,module,exports){
72979'use strict';
72980
72981var DOM = {};
72982
72983DOM.e = function (tagName, className) {
72984  var element = document.createElement(tagName);
72985  element.className = className;
72986  return element;
72987};
72988
72989DOM.appendTo = function (child, parent) {
72990  parent.appendChild(child);
72991  return child;
72992};
72993
72994function cssGet(element, styleName) {
72995  return window.getComputedStyle(element)[styleName];
72996}
72997
72998function cssSet(element, styleName, styleValue) {
72999  if (typeof styleValue === 'number') {
73000    styleValue = styleValue.toString() + 'px';
73001  }
73002  element.style[styleName] = styleValue;
73003  return element;
73004}
73005
73006function cssMultiSet(element, obj) {
73007  for (var key in obj) {
73008    var val = obj[key];
73009    if (typeof val === 'number') {
73010      val = val.toString() + 'px';
73011    }
73012    element.style[key] = val;
73013  }
73014  return element;
73015}
73016
73017DOM.css = function (element, styleNameOrObject, styleValue) {
73018  if (typeof styleNameOrObject === 'object') {
73019    // multiple set with object
73020    return cssMultiSet(element, styleNameOrObject);
73021  } else {
73022    if (typeof styleValue === 'undefined') {
73023      return cssGet(element, styleNameOrObject);
73024    } else {
73025      return cssSet(element, styleNameOrObject, styleValue);
73026    }
73027  }
73028};
73029
73030DOM.matches = function (element, query) {
73031  if (typeof element.matches !== 'undefined') {
73032    return element.matches(query);
73033  } else {
73034    if (typeof element.matchesSelector !== 'undefined') {
73035      return element.matchesSelector(query);
73036    } else if (typeof element.webkitMatchesSelector !== 'undefined') {
73037      return element.webkitMatchesSelector(query);
73038    } else if (typeof element.mozMatchesSelector !== 'undefined') {
73039      return element.mozMatchesSelector(query);
73040    } else if (typeof element.msMatchesSelector !== 'undefined') {
73041      return element.msMatchesSelector(query);
73042    }
73043  }
73044};
73045
73046DOM.remove = function (element) {
73047  if (typeof element.remove !== 'undefined') {
73048    element.remove();
73049  } else {
73050    if (element.parentNode) {
73051      element.parentNode.removeChild(element);
73052    }
73053  }
73054};
73055
73056DOM.queryChildren = function (element, selector) {
73057  return Array.prototype.filter.call(element.childNodes, function (child) {
73058    return DOM.matches(child, selector);
73059  });
73060};
73061
73062module.exports = DOM;
73063
73064},{}],4:[function(require,module,exports){
73065'use strict';
73066
73067var EventElement = function (element) {
73068  this.element = element;
73069  this.events = {};
73070};
73071
73072EventElement.prototype.bind = function (eventName, handler) {
73073  if (typeof this.events[eventName] === 'undefined') {
73074    this.events[eventName] = [];
73075  }
73076  this.events[eventName].push(handler);
73077  this.element.addEventListener(eventName, handler, false);
73078};
73079
73080EventElement.prototype.unbind = function (eventName, handler) {
73081  var isHandlerProvided = (typeof handler !== 'undefined');
73082  this.events[eventName] = this.events[eventName].filter(function (hdlr) {
73083    if (isHandlerProvided && hdlr !== handler) {
73084      return true;
73085    }
73086    this.element.removeEventListener(eventName, hdlr, false);
73087    return false;
73088  }, this);
73089};
73090
73091EventElement.prototype.unbindAll = function () {
73092  for (var name in this.events) {
73093    this.unbind(name);
73094  }
73095};
73096
73097var EventManager = function () {
73098  this.eventElements = [];
73099};
73100
73101EventManager.prototype.eventElement = function (element) {
73102  var ee = this.eventElements.filter(function (eventElement) {
73103    return eventElement.element === element;
73104  })[0];
73105  if (typeof ee === 'undefined') {
73106    ee = new EventElement(element);
73107    this.eventElements.push(ee);
73108  }
73109  return ee;
73110};
73111
73112EventManager.prototype.bind = function (element, eventName, handler) {
73113  this.eventElement(element).bind(eventName, handler);
73114};
73115
73116EventManager.prototype.unbind = function (element, eventName, handler) {
73117  this.eventElement(element).unbind(eventName, handler);
73118};
73119
73120EventManager.prototype.unbindAll = function () {
73121  for (var i = 0; i < this.eventElements.length; i++) {
73122    this.eventElements[i].unbindAll();
73123  }
73124};
73125
73126EventManager.prototype.once = function (element, eventName, handler) {
73127  var ee = this.eventElement(element);
73128  var onceHandler = function (e) {
73129    ee.unbind(eventName, onceHandler);
73130    handler(e);
73131  };
73132  ee.bind(eventName, onceHandler);
73133};
73134
73135module.exports = EventManager;
73136
73137},{}],5:[function(require,module,exports){
73138'use strict';
73139
73140module.exports = (function () {
73141  function s4() {
73142    return Math.floor((1 + Math.random()) * 0x10000)
73143               .toString(16)
73144               .substring(1);
73145  }
73146  return function () {
73147    return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
73148           s4() + '-' + s4() + s4() + s4();
73149  };
73150})();
73151
73152},{}],6:[function(require,module,exports){
73153'use strict';
73154
73155var cls = require('./class');
73156var dom = require('./dom');
73157
73158var toInt = exports.toInt = function (x) {
73159  return parseInt(x, 10) || 0;
73160};
73161
73162var clone = exports.clone = function (obj) {
73163  if (!obj) {
73164    return null;
73165  } else if (obj.constructor === Array) {
73166    return obj.map(clone);
73167  } else if (typeof obj === 'object') {
73168    var result = {};
73169    for (var key in obj) {
73170      result[key] = clone(obj[key]);
73171    }
73172    return result;
73173  } else {
73174    return obj;
73175  }
73176};
73177
73178exports.extend = function (original, source) {
73179  var result = clone(original);
73180  for (var key in source) {
73181    result[key] = clone(source[key]);
73182  }
73183  return result;
73184};
73185
73186exports.isEditable = function (el) {
73187  return dom.matches(el, "input,[contenteditable]") ||
73188         dom.matches(el, "select,[contenteditable]") ||
73189         dom.matches(el, "textarea,[contenteditable]") ||
73190         dom.matches(el, "button,[contenteditable]");
73191};
73192
73193exports.removePsClasses = function (element) {
73194  var clsList = cls.list(element);
73195  for (var i = 0; i < clsList.length; i++) {
73196    var className = clsList[i];
73197    if (className.indexOf('ps-') === 0) {
73198      cls.remove(element, className);
73199    }
73200  }
73201};
73202
73203exports.outerWidth = function (element) {
73204  return toInt(dom.css(element, 'width')) +
73205         toInt(dom.css(element, 'paddingLeft')) +
73206         toInt(dom.css(element, 'paddingRight')) +
73207         toInt(dom.css(element, 'borderLeftWidth')) +
73208         toInt(dom.css(element, 'borderRightWidth'));
73209};
73210
73211exports.startScrolling = function (element, axis) {
73212  cls.add(element, 'ps-in-scrolling');
73213  if (typeof axis !== 'undefined') {
73214    cls.add(element, 'ps-' + axis);
73215  } else {
73216    cls.add(element, 'ps-x');
73217    cls.add(element, 'ps-y');
73218  }
73219};
73220
73221exports.stopScrolling = function (element, axis) {
73222  cls.remove(element, 'ps-in-scrolling');
73223  if (typeof axis !== 'undefined') {
73224    cls.remove(element, 'ps-' + axis);
73225  } else {
73226    cls.remove(element, 'ps-x');
73227    cls.remove(element, 'ps-y');
73228  }
73229};
73230
73231exports.env = {
73232  isWebKit: 'WebkitAppearance' in document.documentElement.style,
73233  supportsTouch: (('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch),
73234  supportsIePointer: window.navigator.msMaxTouchPoints !== null
73235};
73236
73237},{"./class":2,"./dom":3}],7:[function(require,module,exports){
73238'use strict';
73239
73240var destroy = require('./plugin/destroy');
73241var initialize = require('./plugin/initialize');
73242var update = require('./plugin/update');
73243
73244module.exports = {
73245  initialize: initialize,
73246  update: update,
73247  destroy: destroy
73248};
73249
73250},{"./plugin/destroy":9,"./plugin/initialize":17,"./plugin/update":2
732501}],8:[function(require,module,exports){
73251'use strict';
73252
73253module.exports = {
73254  handlers: ['click-rail', 'drag-scrollbar', 'keyboard', 'wheel', 'touch'],
73255  maxScrollbarLength: null,
73256  minScrollbarLength: null,
73257  scrollXMarginOffset: 0,
73258  scrollYMarginOffset: 0,
73259  suppressScrollX: false,
73260  suppressScrollY: false,
73261  swipePropagation: true,
73262  useBothWheelAxes: false,
73263  wheelPropagation: false,
73264  wheelSpeed: 1,
73265  theme: 'default'
73266};
73267
73268},{}],9:[function(require,module,exports){
73269'use strict';
73270
73271var _ = require('../lib/helper');
73272var dom = require('../lib/dom');
73273var instances = require('./instances');
73274
73275module.exports = function (element) {
73276  var i = instances.get(element);
73277
73278  if (!i) {
73279    return;
73280  }
73281
73282  i.event.unbindAll();
73283  dom.remove(i.scrollbarX);
73284  dom.remove(i.scrollbarY);
73285  dom.remove(i.scrollbarXRail);
73286  dom.remove(i.scrollbarYRail);
73287  _.removePsClasses(element);
73288
73289  instances.remove(element);
73290};
73291
73292},{"../lib/dom":3,"../lib/helper":6,"./instances":18}],10:[function(require,module,exports){
73293'use strict';
73294
73295var instances = require('../instances');
73296var updateGeometry = require('../update-geometry');
73297var updateScroll = require('../update-scroll');
73298
73299function bindClickRailHandler(element, i) {
73300  function pageOffset(el) {
73301    return el.getBoundingClientRect();
73302  }
73303  var stopPropagation = function (e) { e.stopPropagation(); };
73304
73305  i.event.bind(i.scrollbarY, 'click', stopPropagation);
73306  i.event.bind(i.scrollbarYRail, 'click', function (e) {
73307    var positionTop = e.pageY - window.pageYOffset - pageOffset(i.scrollbarYRail).top;
73308    var direction = positionTop > i.scrollbarYTop ? 1 : -1;
73309
73310    updateScroll(element, 'top', element.scrollTop + direction * i.containerHeight);
73311    updateGeometry(element);
73312
73313    e.stopPropagation();
73314  });
73315
73316  i.event.bind(i.scrollbarX, 'click', stopPropagation);
73317  i.event.bind(i.scrollbarXRail, 'click', function (e) {
73318    var positionLeft = e.pageX - window.pageXOffset - pageOffset(i.scrollbarXRail).left;
73319    var direction = positionLeft > i.scrollbarXLeft ? 1 : -1;
73320
73321    updateScroll(element, 'left', element.scrollLeft + direction * i.containerWidth);
73322    updateGeometry(element);
73323
73324    e.stopPropagation();
73325  });
73326}
73327
73328module.exports = function (element) {
73329  var i = instances.get(element);
73330  bindClickRailHandler(element, i);
73331};
73332
73333},{"../instances":18,"../update-geometry":19,"../update-scroll":20}],11:[function(require,module,exports){
73334'use strict';
73335
73336var _ = require('../../lib/helper');
73337var dom = require('../../lib/dom');
73338var instances = require('../instances');
73339var updateGeometry = require('../update-geometry');
73340var updateScroll = require('../update-scroll');
73341
73342function bindMouseScrollXHandler(element, i) {
73343  var currentLeft = null;
73344  var currentPageX = null;
73345
73346  function updateScrollLeft(deltaX) {
73347    var newLeft = currentLeft + (deltaX * i.railXRatio);
73348    var maxLeft = Math.max(0, i.scrollbarXRail.getBoundingClientRect().left) + (i.railXRatio * (i.railXWidth - i.scrollbarXWidth));
73349
73350    if (newLeft < 0) {
73351      i.scrollbarXLeft = 0;
73352    } else if (newLeft > maxLeft) {
73353      i.scrollbarXLeft = maxLeft;
73354    } else {
73355      i.scrollbarXLeft = newLeft;
73356    }
73357
73358    var scrollLeft = _.toInt(i.scrollbarXLeft * (i.contentWidth - i.containerWidth) / (i.containerWidth - (i.railXRatio * i.scrollbarXWidth))) - i.negativeScrollAdjustment;
73359    updateScroll(element, 'left', scrollLeft);
73360  }
73361
73362  var mouseMoveHandler = function (e) {
73363    updateScrollLeft(e.pageX - currentPageX);
73364    updateGeometry(element);
73365    e.stopPropagation();
73366    e.preventDefault();
73367  };
73368
73369  var mouseUpHandler = function () {
73370    _.stopScrolling(element, 'x');
73371    i.event.unbind(i.ownerDocument, 'mousemove', mouseMoveHandler);
73372  };
73373
73374  i.event.bind(i.scrollbarX, 'mousedown', function (e) {
73375    currentPageX = e.pageX;
73376    currentLeft = _.toInt(dom.css(i.scrollbarX, 'left')) * i.railXRatio;
73377    _.startScrolling(element, 'x');
73378
73379    i.event.bind(i.ownerDocument, 'mousemove', mouseMoveHandler);
73380    i.event.once(i.ownerDocument, 'mouseup', mouseUpHandler);
73381
73382    e.stopPropagation();
73383    e.preventDefault();
73384  });
73385}
73386
73387function bindMouseScrollYHandler(element, i) {
73388  var currentTop = null;
73389  var currentPageY = null;
73390
73391  function updateScrollTop(deltaY) {
73392    var newTop = currentTop + (deltaY * i.railYRatio);
73393    var maxTop = Math.max(0, i.scrollbarYRail.getBoundingClientRect().top) + (i.railYRatio * (i.railYHeight - i.scrollbarYHeight));
73394
73395    if (newTop < 0) {
73396      i.scrollbarYTop = 0;
73397    } else if (newTop > maxTop) {
73398      i.scrollbarYTop = maxTop;
73399    } else {
73400      i.scrollbarYTop = newTop;
73401    }
73402
73403    var scrollTop = _.toInt(i.scrollbarYTop * (i.contentHeight - i.containerHeight) / (i.containerHeight - (i.railYRatio * i.scrollbarYHeight)));
73404    updateScroll(element, 'top', scrollTop);
73405  }
73406
73407  var mouseMoveHandler = function (e) {
73408    updateScrollTop(e.pageY - currentPageY);
73409    updateGeometry(element);
73410    e.stopPropagation();
73411    e.preventDefault();
73412  };
73413
73414  var mouseUpHandler = function () {
73415    _.stopScrolling(element, 'y');
73416    i.event.unbind(i.ownerDocument, 'mousemove', mouseMoveHandler);
73417  };
73418
73419  i.event.bind(i.scrollbarY, 'mousedown', function (e) {
73420    currentPageY = e.pageY;
73421    currentTop = _.toInt(dom.css(i.scrollbarY, 'top')) * i.railYRatio;
73422    _.startScrolling(element, 'y');
73423
73424    i.event.bind(i.ownerDocument, 'mousemove', mouseMoveHandler);
73425    i.event.once(i.ownerDocument, 'mouseup', mouseUpHandler);
73426
73427    e.stopPropagation();
73428    e.preventDefault();
73429  });
73430}
73431
73432module.exports = function (element) {
73433  var i = instances.get(element);
73434  bindMouseScrollXHandler(element, i);
73435  bindMouseScrollYHandler(element, i);
73436};
73437
73438},{"../../lib/dom":3,"../../lib/helper":6,"../instances":18,"../update-geometry":19,"../update-scroll":20}],12:[function(require,module,exports){
73439'use strict';
73440
73441var _ = require('../../lib/helper');
73442var dom = require('../../lib/dom');
73443var instances = require('../instances');
73444var updateGeometry = require('../update-geometry');
73445var updateScroll = require('../update-scroll');
73446
73447function bindKeyboardHandler(element, i) {
73448  var hovered = false;
73449  i.event.bind(element, 'mouseenter', function () {
73450    hovered = true;
73451  });
73452  i.event.bind(element, 'mouseleave', function () {
73453    hovered = false;
73454  });
73455
73456  var shouldPrevent = false;
73457  function shouldPreventDefault(deltaX, deltaY) {
73458    var scrollTop = element.scrollTop;
73459    if (deltaX === 0) {
73460      if (!i.scrollbarYActive) {
73461        return false;
73462      }
73463      if ((scrollTop === 0 && deltaY > 0) || (scrollTop >= i.contentHeight - i.containerHeight && deltaY < 0)) {
73464        return !i.settings.wheelPropagation;
73465      }
73466    }
73467
73468    var scrollLeft = element.scrollLeft;
73469    if (deltaY === 0) {
73470      if (!i.scrollbarXActive) {
73471        return false;
73472      }
73473      if ((scrollLeft === 0 && deltaX < 0) || (scrollLeft >= i.contentWidth - i.containerWidth && deltaX > 0)) {
73474        return !i.settings.wheelPropagation;
73475      }
73476    }
73477    return true;
73478  }
73479
73480  i.event.bind(i.ownerDocument, 'keydown', function (e) {
73481    if ((e.isDefaultPrevented && e.isDefaultPrevented()) || e.defaultPrevented) {
73482      return;
73483    }
73484
73485    var focused = dom.matches(i.scrollbarX, ':focus') ||
73486                  dom.matches(i.scrollbarY, ':focus');
73487
73488    if (!hovered && !focused) {
73489      return;
73490    }
73491
73492    var activeElement = document.activeElement ? document.activeElement : i.ownerDocument.activeElement;
73493    if (activeElement) {
73494      if (activeElement.tagName === 'IFRAME') {
73495        activeElement = activeElement.contentDocument.activeElement;
73496      } else {
73497        // go deeper if element is a webcomponent
73498        while (activeElement.shadowRoot) {
73499          activeElement = activeElement.shadowRoot.activeElement;
73500        }
73501      }
73502      if (_.isEditable(activeElement)) {
73503        return;
73504      }
73505    }
73506
73507    var deltaX = 0;
73508    var deltaY = 0;
73509
73510    switch (e.which) {
73511    case 37: // left
73512      if (e.metaKey) {
73513        deltaX = -i.contentWidth;
73514      } else if (e.altKey) {
73515        deltaX = -i.containerWidth;
73516      } else {
73517        deltaX = -30;
73518      }
73519      break;
73520    case 38: // up
73521      if (e.metaKey) {
73522        deltaY = i.contentHeight;
73523      } else if (e.altKey) {
73524        deltaY = i.containerHeight;
73525      } else {
73526        deltaY = 30;
73527      }
73528      break;
73529    case 39: // right
73530      if (e.metaKey) {
73531        deltaX = i.contentWidth;
73532      } else if (e.altKey) {
73533        deltaX = i.containerWidth;
73534      } else {
73535        deltaX = 30;
73536      }
73537      break;
73538    case 40: // down
73539      if (e.metaKey) {
73540        deltaY = -i.contentHeight;
73541      } else if (e.altKey) {
73542        deltaY = -i.containerHeight;
73543      } else {
73544        deltaY = -30;
73545      }
73546      break;
73547    case 33: // page up
73548      deltaY = 90;
73549      break;
73550    case 32: // space bar
73551      if (e.shiftKey) {
73552        deltaY = 90;
73553      } else {
73554        deltaY = -90;
73555      }
73556      break;
73557    case 34: // page down
73558      deltaY = -90;
73559      break;
73560    case 35: // end
73561      if (e.ctrlKey) {
73562        deltaY = -i.contentHeight;
73563      } else {
73564        deltaY = -i.containerHeight;
73565      }
73566      break;
73567    case 36: // home
73568      if (e.ctrlKey) {
73569        deltaY = element.scrollTop;
73570      } else {
73571        deltaY = i.containerHeight;
73572      }
73573      break;
73574    default:
73575      return;
73576    }
73577
73578    updateScroll(element, 'top', element.scrollTop - deltaY);
73579    updateScroll(element, 'left', element.scrollLeft + deltaX);
73580    updateGeometry(element);
73581
73582    shouldPrevent = shouldPreventDefault(deltaX, deltaY);
73583    if (shouldPrevent) {
73584      e.preventDefault();
73585    }
73586  });
73587}
73588
73589module.exports = function (element) {
73590  var i = instances.get(element);
73591  bindKeyboardHandler(element, i);
73592};
73593
73594},{"../../lib/dom":3,"../../lib/helper":6,"../instances":18,"../update-geometry":19,"../update-scroll":20}],13:[function(require,module,exports){
73595'use strict';
73596
73597var instances = require('../instances');
73598var updateGeometry = require('../update-geometry');
73599var updateScroll = require('../update-scroll');
73600
73601function bindMouseWheelHandler(element, i) {
73602  var shouldPrevent = false;
73603
73604  function shouldPreventDefault(deltaX, deltaY) {
73605    var scrollTop = element.scrollTop;
73606    if (deltaX === 0) {
73607      if (!i.scrollbarYActive) {
73608        return false;
73609      }
73610      if ((scrollTop === 0 && deltaY > 0) || (scrollTop >= i.contentHeight - i.containerHeight && deltaY < 0)) {
73611        return !i.settings.wheelPropagation;
73612      }
73613    }
73614
73615    var scrollLeft = element.scrollLeft;
73616    if (deltaY === 0) {
73617      if (!i.scrollbarXActive) {
73618        return false;
73619      }
73620      if ((scrollLeft === 0 && deltaX < 0) || (scrollLeft >= i.contentWidth - i.containerWidth && deltaX > 0)) {
73621        return !i.settings.wheelPropagation;
73622      }
73623    }
73624    return true;
73625  }
73626
73627  function getDeltaFromEvent(e) {
73628    var deltaX = e.deltaX;
73629    var deltaY = -1 * e.deltaY;
73630
73631    if (typeof deltaX === "undefined" || typeof deltaY === "undefined") {
73632      // OS X Safari
73633      deltaX = -1 * e.wheelDeltaX / 6;
73634      deltaY = e.wheelDeltaY / 6;
73635    }
73636
73637    if (e.deltaMode && e.deltaMode === 1) {
73638      // Firefox in deltaMode 1: Line scrolling
73639      deltaX *= 10;
73640      deltaY *= 10;
73641    }
73642
73643    if (deltaX !== deltaX && deltaY !== deltaY/* NaN checks */) {
73644      // IE in some mouse drivers
73645      deltaX = 0;
73646      deltaY = e.wheelDelta;
73647    }
73648
73649    if (e.shiftKey) {
73650      // reverse axis with shift key
73651      return [-deltaY, -deltaX];
73652    }
73653    return [deltaX, deltaY];
73654  }
73655
73656  function shouldBeConsumedByChild(deltaX, deltaY) {
73657    var child = element.querySelector('textarea:hover, select[multiple]:hover, .ps-child:hover');
73658    if (child) {
73659      if (!window.getComputedStyle(child).overflow.match(/(scroll|auto)/)) {
73660        // if not scrollable
73661        return false;
73662      }
73663
73664      var maxScrollTop = child.scrollHeight - child.clientHeight;
73665      if (maxScrollTop > 0) {
73666        if (!(child.scrollTop === 0 && deltaY > 0) && !(child.scrollTop === maxScrollTop && deltaY < 0)) {
73667          return true;
73668        }
73669      }
73670      var maxScrollLeft = child.scrollLeft - child.clientWidth;
73671      if (maxScrollLeft > 0) {
73672        if (!(child.scrollLeft === 0 && deltaX < 0) && !(child.scrollLeft === maxScrollLeft && deltaX > 0)) {
73673          return true;
73674        }
73675      }
73676    }
73677    return false;
73678  }
73679
73680  function mousewheelHandler(e) {
73681    var delta = getDeltaFromEvent(e);
73682
73683    var deltaX = delta[0];
73684    var deltaY = delta[1];
73685
73686    if (shouldBeConsumedByChild(deltaX, deltaY)) {
73687      return;
73688    }
73689
73690    shouldPrevent = false;
73691    if (!i.settings.useBothWheelAxes) {
73692      // deltaX will only be used for horizontal scrolling and deltaY will
73693      // only be used for vertical scrolling - this is the default
73694      updateScroll(element, 'top', element.scrollTop - (deltaY * i.settings.wheelSpeed));
73695      updateScroll(element, 'left', element.scrollLeft + (deltaX * i.settings.wheelSpeed));
73696    } else if (i.scrollbarYActive && !i.scrollbarXActive) {
73697      // only vertical scrollbar is active and useBothWheelAxes option is
73698      // active, so let's scroll vertical bar using both mouse wheel axes
73699      if (deltaY) {
73700        updateScroll(element, 'top', element.scrollTop - (deltaY * i.settings.wheelSpeed));
73701      } else {
73702        updateScroll(element, 'top', element.scrollTop + (deltaX * i.settings.wheelSpeed));
73703      }
73704      shouldPrevent = true;
73705    } else if (i.scrollbarXActive && !i.scrollbarYActive) {
73706      // useBothWheelAxes and only horizontal bar is active, so use both
73707      // wheel axes for horizontal bar
73708      if (deltaX) {
73709        updateScroll(element, 'left', element.scrollLeft + (deltaX * i.settings.wheelSpeed));
73710      } else {
73711        updateScroll(element, 'left', element.scrollLeft - (deltaY * i.settings.wheelSpeed));
73712      }
73713      shouldPrevent = true;
73714    }
73715
73716    updateGeometry(element);
73717
73718    shouldPrevent = (shouldPrevent || shouldPreventDefault(deltaX, deltaY));
73719    if (shouldPrevent) {
73720      e.stopPropagation();
73721      e.preventDefault();
73722    }
73723  }
73724
73725  if (typeof window.onwheel !== "undefined") {
73726    i.event.bind(element, 'wheel', mousewheelHandler);
73727  } else if (typeof window.onmousewheel !== "undefined") {
73728    i.event.bind(element, 'mousewheel', mousewheelHandler);
73729  }
73730}
73731
73732module.exports = function (element) {
73733  var i = instances.get(element);
73734  bindMouseWheelHandler(element, i);
73735};
73736
73737},{"../instances":18,"../update-geometry":19,"../update-scroll":20}],14:[function(require,module,exports){
73738'use strict';
73739
73740var instances = require('../instances');
73741var updateGeometry = require('../update-geometry');
73742
73743function bindNativeScrollHandler(element, i) {
73744  i.event.bind(element, 'scroll', function () {
73745    updateGeometry(element);
73746  });
73747}
73748
73749module.exports = function (element) {
73750  var i = instances.get(element);
73751  bindNativeScrollHandler(element, i);
73752};
73753
73754},{"../instances":18,"../update-geometry":19}],15:[function(require,module,exports){
73755'use strict';
73756
73757var _ = require('../../lib/helper');
73758var instances = require('../instances');
73759var updateGeometry = require('../update-geometry');
73760var updateScroll = require('../update-scroll');
73761
73762function bindSelectionHandler(element, i) {
73763  function getRangeNode() {
73764    var selection = window.getSelection ? window.getSelection() :
73765                    document.getSelection ? document.getSelection() : '';
73766    if (selection.toString().length === 0) {
73767      return null;
73768    } else {
73769      return selection.getRangeAt(0).commonAncestorContainer;
73770    }
73771  }
73772
73773  var scrollingLoop = null;
73774  var scrollDiff = {top: 0, left: 0};
73775  function startScrolling() {
73776    if (!scrollingLoop) {
73777      scrollingLoop = setInterval(function () {
73778        if (!instances.get(element)) {
73779          clearInterval(scrollingLoop);
73780          return;
73781        }
73782
73783        updateScroll(element, 'top', element.scrollTop + scrollDiff.top);
73784        updateScroll(element, 'left', element.scrollLeft + scrollDiff.left);
73785        updateGeometry(element);
73786      }, 50); // every .1 sec
73787    }
73788  }
73789  function stopScrolling() {
73790    if (scrollingLoop) {
73791      clearInterval(scrollingLoop);
73792      scrollingLoop = null;
73793    }
73794    _.stopScrolling(element);
73795  }
73796
73797  var isSelected = false;
73798  i.event.bind(i.ownerDocument, 'selectionchange', function () {
73799    if (element.contains(getRangeNode())) {
73800      isSelected = true;
73801    } else {
73802      isSelected = false;
73803      stopScrolling();
73804    }
73805  });
73806  i.event.bind(window, 'mouseup', function () {
73807    if (isSelected) {
73808      isSelected = false;
73809      stopScrolling();
73810    }
73811  });
73812  i.event.bind(window, 'keyup', function () {
73813    if (isSelected) {
73814      isSelected = false;
73815      stopScrolling();
73816    }
73817  });
73818
73819  i.event.bind(window, 'mousemove', function (e) {
73820    if (isSelected) {
73821      var mousePosition = {x: e.pageX, y: e.pageY};
73822      var containerGeometry = {
73823        left: element.offsetLeft,
73824        right: element.offsetLeft + element.offsetWidth,
73825        top: element.offsetTop,
73826        bottom: element.offsetTop + element.offsetHeight
73827      };
73828
73829      if (mousePosition.x < containerGeometry.left + 3) {
73830        scrollDiff.left = -5;
73831        _.startScrolling(element, 'x');
73832      } else if (mousePosition.x > containerGeometry.right - 3) {
73833        scrollDiff.left = 5;
73834        _.startScrolling(element, 'x');
73835      } else {
73836        scrollDiff.left = 0;
73837      }
73838
73839      if (mousePosition.y < containerGeometry.top + 3) {
73840        if (containerGeometry.top + 3 - mousePosition.y < 5) {
73841          scrollDiff.top = -5;
73842        } else {
73843          scrollDiff.top = -20;
73844        }
73845        _.startScrolling(element, 'y');
73846      } else if (mousePosition.y > containerGeometry.bottom - 3) {
73847        if (mousePosition.y - containerGeometry.bottom + 3 < 5) {
73848          scrollDiff.top = 5;
73849        } else {
73850          scrollDiff.top = 20;
73851        }
73852        _.startScrolling(element, 'y');
73853      } else {
73854        scrollDiff.top = 0;
73855      }
73856
73857      if (scrollDiff.top === 0 && scrollDiff.left === 0) {
73858        stopScrolling();
73859      } else {
73860        startScrolling();
73861      }
73862    }
73863  });
73864}
73865
73866module.exports = function (element) {
73867  var i = instances.get(element);
73868  bindSelectionHandler(element, i);
73869};
73870
73871},{"../../lib/helper":6,"../instances":18,"../update-geometry":19,"../update-scroll":20}],16:[function(require,module,exports){
73872'use strict';
73873
73874var _ = require('../../lib/helper');
73875var instances = require('../instances');
73876var updateGeometry = require('../update-geometry');
73877var updateScroll = require('../update-scroll');
73878
73879function bindTouchHandler(element, i, supportsTouch, supportsIePointer) {
73880  function shouldPreventDefault(deltaX, deltaY) {
73881    var scrollTop = element.scrollTop;
73882    var scrollLeft = element.scrollLeft;
73883    var magnitudeX = Math.abs(deltaX);
73884    var magnitudeY = Math.abs(deltaY);
73885
73886    if (magnitudeY > magnitudeX) {
73887      // user is perhaps trying to swipe up/down the page
73888
73889      if (((deltaY < 0) && (scrollTop === i.contentHeight - i.containerHeight)) ||
73890          ((deltaY > 0) && (scrollTop === 0))) {
73891        return !i.settings.swipePropagation;
73892      }
73893    } else if (magnitudeX > magnitudeY) {
73894      // user is perhaps trying to swipe left/right across the page
73895
73896      if (((deltaX < 0) && (scrollLeft === i.contentWidth - i.containerWidth)) ||
73897          ((deltaX > 0) && (scrollLeft === 0))) {
73898        return !i.settings.swipePropagation;
73899      }
73900    }
73901
73902    return true;
73903  }
73904
73905  function applyTouchMove(differenceX, differenceY) {
73906    updateScroll(element, 'top', element.scrollTop - differenceY);
73907    updateScroll(element, 'left', element.scrollLeft - differenceX);
73908
73909    updateGeometry(element);
73910  }
73911
73912  var startOffset = {};
73913  var startTime = 0;
73914  var speed = {};
73915  var easingLoop = null;
73916  var inGlobalTouch = false;
73917  var inLocalTouch = false;
73918
73919  function globalTouchStart() {
73920    inGlobalTouch = true;
73921  }
73922  function globalTouchEnd() {
73923    inGlobalTouch = false;
73924  }
73925
73926  function getTouch(e) {
73927    if (e.targetTouches) {
73928      return e.targetTouches[0];
73929    } else {
73930      // Maybe IE pointer
73931      return e;
73932    }
73933  }
73934  function shouldHandle(e) {
73935    if (e.targetTouches && e.targetTouches.length === 1) {
73936      return true;
73937    }
73938    if (e.pointerType && e.pointerType !== 'mouse' && e.pointerType !== e.MSPOINTER_TYPE_MOUSE) {
73939      return true;
73940    }
73941    return false;
73942  }
73943  function touchStart(e) {
73944    if (shouldHandle(e)) {
73945      inLocalTouch = true;
73946
73947      var touch = getTouch(e);
73948
73949      startOffset.pageX = touch.pageX;
73950      startOffset.pageY = touch.pageY;
73951
73952      startTime = (new Date()).getTime();
73953
73954      if (easingLoop !== null) {
73955        clearInterval(easingLoop);
73956      }
73957
73958      e.stopPropagation();
73959    }
73960  }
73961  function touchMove(e) {
73962    if (!inLocalTouch && i.settings.swipePropagation) {
73963      touchStart(e);
73964    }
73965    if (!inGlobalTouch && inLocalTouch && shouldHandle(e)) {
73966      var touch = getTouch(e);
73967
73968      var currentOffset = {pageX: touch.pageX, pageY: touch.pageY};
73969
73970      var differenceX = currentOffset.pageX - startOffset.pageX;
73971      var differenceY = currentOffset.pageY - startOffset.pageY;
73972
73973      applyTouchMove(differenceX, differenceY);
73974      startOffset = currentOffset;
73975
73976      var currentTime = (new Date()).getTime();
73977
73978      var timeGap = currentTime - startTime;
73979      if (timeGap > 0) {
73980        speed.x = differenceX / timeGap;
73981        speed.y = differenceY / timeGap;
73982        startTime = currentTime;
73983      }
73984
73985      if (shouldPreventDefault(differenceX, differenceY)) {
73986        e.stopPropagation();
73987        e.preventDefault();
73988      }
73989    }
73990  }
73991  function touchEnd() {
73992    if (!inGlobalTouch && inLocalTouch) {
73993      inLocalTouch = false;
73994
73995      clearInterval(easingLoop);
73996      easingLoop = setInterval(function () {
73997        if (!instances.get(element)) {
73998          clearInterval(easingLoop);
73999          return;
74000        }
74001
74002        if (!speed.x && !speed.y) {
74003          clearInterval(easingLoop);
74004          return;
74005        }
74006
74007        if (Math.abs(speed.x) < 0.01 && Math.abs(speed.y) < 0.01) {
74008          clearInterval(easingLoop);
74009          return;
74010        }
74011
74012        applyTouchMove(speed.x * 30, speed.y * 30);
74013
74014        speed.x *= 0.8;
74015        speed.y *= 0.8;
74016      }, 10);
74017    }
74018  }
74019
74020  if (supportsTouch) {
74021    i.event.bind(window, 'touchstart', globalTouchStart);
74022    i.event.bind(window, 'touchend', globalTouchEnd);
74023    i.event.bind(element, 'touchstart', touchStart);
74024    i.event.bind(element, 'touchmove', touchMove);
74025    i.event.bind(element, 'touchend', touchEnd);
74026  }
74027
74028  if (supportsIePointer) {
74029    if (window.PointerEvent) {
74030      i.event.bind(window, 'pointerdown', globalTouchStart);
74031      i.event.bind(window, 'pointerup', globalTouchEnd);
74032      i.event.bind(element, 'pointerdown', touchStart);
74033      i.event.bind(element, 'pointermove', touchMove);
74034      i.event.bind(element, 'pointerup', touchEnd);
74035    } else if (window.MSPointerEvent) {
74036      i.event.bind(window, 'MSPointerDown', globalTouchStart);
74037      i.event.bind(window, 'MSPointerUp', globalTouchEnd);
74038      i.event.bind(element, 'MSPointerDown', touchStart);
74039      i.event.bind(element, 'MSPointerMove', touchMove);
74040      i.event.bind(element, 'MSPointerUp', touchEnd);
74041    }
74042  }
74043}
74044
74045module.exports = function (element) {
74046  if (!_.env.supportsTouch && !_.env.supportsIePointer) {
74047    return;
74048  }
74049
74050  var i = instances.get(element);
74051  bindTouchHandler(element, i, _.env.supportsTouch, _.env.supportsIePointer);
74052};
74053
74054},{"../../lib/helper":6,"../instances":18,"../update-geometry":19,"../update-scroll":20}],17:[function(require,module,exports){
74055'use strict';
74056
74057var _ = require('../lib/helper');
74058var cls = require('../lib/class');
74059var instances = require('./instances');
74060var updateGeometry = require('./update-geometry');
74061
74062// Handlers
74063var handlers = {
74064  'click-rail': require('./handler/click-rail'),
74065  'drag-scrollbar': require('./handler/drag-scrollbar'),
74066  'keyboard': require('./handler/keyboard'),
74067  'wheel': require('./handler/mouse-wheel'),
74068  'touch': require('./handler/touch'),
74069  'selection': require('./handler/selection')
74070};
74071var nativeScrollHandler = require('./handler/native-scroll');
74072
74073module.exports = function (element, userSettings) {
74074  userSettings = typeof userSettings === 'object' ? userSettings : {};
74075
74076  cls.add(element, 'ps-container');
74077
74078  // Create a plugin instance.
74079  var i = instances.add(element);
74080
74081  i.settings = _.extend(i.settings, userSettings);
74082  cls.add(element, 'ps-theme-' + i.settings.theme);
74083
74084  i.settings.handlers.forEach(function (handlerName) {
74085    handlers[handlerName](element);
74086  });
74087
74088  nativeScrollHandler(element);
74089
74090  updateGeometry(element);
74091};
74092
74093},{"../lib/class":2,"../lib/helper":6,"./handler/click-rail":10,"./handler/drag-scrollbar":11,"./handler/keyboard":12,"./handler/mouse-wheel":13,"./handler/native-scroll":14,"./handler/selection":15,"./handler/touch":16,"./instances":18,"./update-geometry":19}],18:[function(require,module,exports){
74094'use strict';
74095
74096var _ = require('../lib/helper');
74097var cls = require('../lib/class');
74098var defaultSettings = require('./default-setting');
74099var dom = require('../lib/dom');
74100var EventManager = require('../lib/event-manager');
74101var guid = require('../lib/guid');
74102
74103var instances = {};
74104
74105function Instance(element) {
74106  var i = this;
74107
74108  i.settings = _.clone(defaultSettings);
74109  i.containerWidth = null;
74110  i.containerHeight = null;
74111  i.contentWidth = null;
74112  i.contentHeight = null;
74113
74114  i.isRtl = dom.css(element, 'direction') === "rtl";
74115  i.isNegativeScroll = (function () {
74116    var originalScrollLeft = element.scrollLeft;
74117    var result = null;
74118    element.scrollLeft = -1;
74119    result = element.scrollLeft < 0;
74120    element.scrollLeft = originalScrollLeft;
74121    return result;
74122  })();
74123  i.negativeScrollAdjustment = i.isNegativeScroll ? element.scrollWidth - element.clientWidth : 0;
74124  i.event = new EventManager();
74125  i.ownerDocument = element.ownerDocument || document;
74126
74127  function focus() {
74128    cls.add(element, 'ps-focus');
74129  }
74130
74131  function blur() {
74132    cls.remove(element, 'ps-focus');
74133  }
74134
74135  i.scrollbarXRail = dom.appendTo(dom.e('div', 'ps-scrollbar-x-rail'), element);
74136  i.scrollbarX = dom.appendTo(dom.e('div', 'ps-scrollbar-x'), i.scrollbarXRail);
74137  i.scrollbarX.setAttribute('tabindex', 0);
74138  i.event.bind(i.scrollbarX, 'focus', focus);
74139  i.event.bind(i.scrollbarX, 'blur', blur);
74140  i.scrollbarXActive = null;
74141  i.scrollbarXWidth = null;
74142  i.scrollbarXLeft = null;
74143  i.scrollbarXBottom = _.toInt(dom.css(i.scrollbarXRail, 'bottom'));
74144  i.isScrollbarXUsingBottom = i.scrollbarXBottom === i.scrollbarXBottom; // !isNaN
74145  i.scrollbarXTop = i.isScrollbarXUsingBottom ? null : _.toInt(dom.css(i.scrollbarXRail, 'top'));
74146  i.railBorderXWidth = _.toInt(dom.css(i.scrollbarXRail, 'borderLeftWidth')) + _.toInt(dom.css(i.scrollbarXRail, 'borderRightWidth'));
74147  // Set rail to display:block to calculate margins
74148  dom.css(i.scrollbarXRail, 'display', 'block');
74149  i.railXMarginWidth = _.toInt(dom.css(i.scrollbarXRail, 'marginLeft')) + _.toInt(dom.css(i.scrollbarXRail, 'marginRight'));
74150  dom.css(i.scrollbarXRail, 'display', '');
74151  i.railXWidth = null;
74152  i.railXRatio = null;
74153
74154  i.scrollbarYRail = dom.appendTo(dom.e('div', 'ps-scrollbar-y-rail'), element);
74155  i.scrollbarY = dom.appendTo(dom.e('div', 'ps-scrollbar-y'), i.scrollbarYRail);
74156  i.scrollbarY.setAttribute('tabindex', 0);
74157  i.event.bind(i.scrollbarY, 'focus', focus);
74158  i.event.bind(i.scrollbarY, 'blur', blur);
74159  i.scrollbarYActive = null;
74160  i.scrollbarYHeight = null;
74161  i.scrollbarYTop = null;
74162  i.scrollbarYRight = _.toInt(dom.css(i.scrollbarYRail, 'right'));
74163  i.isScrollbarYUsingRight = i.scrollbarYRight === i.scrollbarYRight; // !isNaN
74164  i.scrollbarYLeft = i.isScrollbarYUsingRight ? null : _.toInt(dom.css(i.scrollbarYRail, 'left'));
74165  i.scrollbarYOuterWidth = i.isRtl ? _.outerWidth(i.scrollbarY) : null;
74166  i.railBorderYWidth = _.toInt(dom.css(i.scrollbarYRail, 'borderTopWidth')) + _.toInt(dom.css(i.scrollbarYRail, 'borderBottomWidth'));
74167  dom.css(i.scrollbarYRail, 'display', 'block');
74168  i.railYMarginHeight = _.toInt(dom.css(i.scrollbarYRail, 'marginTop')) + _.toInt(dom.css(i.scrollbarYRail, 'marginBottom'));
74169  dom.css(i.scrollbarYRail, 'display', '');
74170  i.railYHeight = null;
74171  i.railYRatio = null;
74172}
74173
74174function getId(element) {
74175  return element.getAttribute('data-ps-id');
74176}
74177
74178function setId(element, id) {
74179  element.setAttribute('data-ps-id', id);
74180}
74181
74182function removeId(element) {
74183  element.removeAttribute('data-ps-id');
74184}
74185
74186exports.add = function (element) {
74187  var newId = guid();
74188  setId(element, newId);
74189  instances[newId] = new Instance(element);
74190  return instances[newId];
74191};
74192
74193exports.remove = function (element) {
74194  delete instances[getId(element)];
74195  removeId(element);
74196};
74197
74198exports.get = function (element) {
74199  return instances[getId(element)];
74200};
74201
74202},{"../lib/class":2,"../lib/dom":3,"../lib/event-manager":4,"../lib/guid":5,"../lib/helper":6,"./default-setting":8}],19:[function(require,module,exports){
74203'use strict';
74204
74205var _ = require('../lib/helper');
74206var cls = require('../lib/class');
74207var dom = require('../lib/dom');
74208var instances = require('./instances');
74209var updateScroll = require('./update-scroll');
74210
74211function getThumbSize(i, thumbSize) {
74212  if (i.settings.minScrollbarLength) {
74213    thumbSize = Math.max(thumbSize, i.settings.minScrollbarLength);
74214  }
74215  if (i.settings.maxScrollbarLength) {
74216    thumbSize = Math.min(thumbSize, i.settings.maxScrollbarLength);
74217  }
74218  return thumbSize;
74219}
74220
74221function updateCss(element, i) {
74222  var xRailOffset = {width: i.railXWidth};
74223  if (i.isRtl) {
74224    xRailOffset.left = i.negativeScrollAdjustment + element.scrollLeft + i.containerWidth - i.contentWidth;
74225  } else {
74226    xRailOffset.left = element.scrollLeft;
74227  }
74228  if (i.isScrollbarXUsingBottom) {
74229    xRailOffset.bottom = i.scrollbarXBottom - element.scrollTop;
74230  } else {
74231    xRailOffset.top = i.scrollbarXTop + element.scrollTop;
74232  }
74233  dom.css(i.scrollbarXRail, xRailOffset);
74234
74235  var yRailOffset = {top: element.scrollTop, height: i.railYHeight};
74236  if (i.isScrollbarYUsingRight) {
74237    if (i.isRtl) {
74238      yRailOffset.right = i.contentWidth - (i.negativeScrollAdjustment + element.scrollLeft) - i.scrollbarYRight - i.scrollbarYOuterWidth;
74239    } else {
74240      yRailOffset.right = i.scrollbarYRight - element.scrollLeft;
74241    }
74242  } else {
74243    if (i.isRtl) {
74244      yRailOffset.left = i.negativeScrollAdjustment + element.scrollLeft + i.containerWidth * 2 - i.contentWidth - i.scrollbarYLeft - i.scrollbarYOuterWidth;
74245    } else {
74246      yRailOffset.left = i.scrollbarYLeft + element.scrollLeft;
74247    }
74248  }
74249  dom.css(i.scrollbarYRail, yRailOffset);
74250
74251  dom.css(i.scrollbarX, {left: i.scrollbarXLeft, width: i.scrollbarXWidth - i.railBorderXWidth});
74252  dom.css(i.scrollbarY, {top: i.scrollbarYTop, height: i.scrollbarYHeight - i.railBorderYWidth});
74253}
74254
74255module.exports = function (element) {
74256  var i = instances.get(element);
74257
74258  i.containerWidth = element.clientWidth;
74259  i.containerHeight = element.clientHeight;
74260  i.contentWidth = element.scrollWidth;
74261  i.contentHeight = element.scrollHeight;
74262
74263  var existingRails;
74264  if (!element.contains(i.scrollbarXRail)) {
74265    existingRails = dom.queryChildren(element, '.ps-scrollbar-x-rail');
74266    if (existingRails.length > 0) {
74267      existingRails.forEach(function (rail) {
74268        dom.remove(rail);
74269      });
74270    }
74271    dom.appendTo(i.scrollbarXRail, element);
74272  }
74273  if (!element.contains(i.scrollbarYRail)) {
74274    existingRails = dom.queryChildren(element, '.ps-scrollbar-y-rail');
74275    if (existingRails.length > 0) {
74276      existingRails.forEach(function (rail) {
74277        dom.remove(rail);
74278      });
74279    }
74280    dom.appendTo(i.scrollbarYRail, element);
74281  }
74282
74283  if (!i.settings.suppressScrollX && i.containerWidth + i.settings.scrollXMarginOffset < i.contentWidth) {
74284    i.scrollbarXActive = true;
74285    i.railXWidth = i.containerWidth - i.railXMarginWidth;
74286    i.railXRatio = i.containerWidth / i.railXWidth;
74287    i.scrollbarXWidth = getThumbSize(i, _.toInt(i.railXWidth * i.containerWidth / i.contentWidth));
74288    i.scrollbarXLeft = _.toInt((i.negativeScrollAdjustment + element.scrollLeft) * (i.railXWidth - i.scrollbarXWidth) / (i.contentWidth - i.containerWidth));
74289  } else {
74290    i.scrollbarXActive = false;
74291  }
74292
74293  if (!i.settings.suppressScrollY && i.containerHeight + i.settings.scrollYMarginOffset < i.contentHeight) {
74294    i.scrollbarYActive = true;
74295    i.railYHeight = i.containerHeight - i.railYMarginHeight;
74296    i.railYRatio = i.containerHeight / i.railYHeight;
74297    i.scrollbarYHeight = getThumbSize(i, _.toInt(i.railYHeight * i.containerHeight / i.contentHeight));
74298    i.scrollbarYTop = _.toInt(element.scrollTop * (i.railYHeight - i.scrollbarYHeight) / (i.contentHeight - i.containerHeight));
74299  } else {
74300    i.scrollbarYActive = false;
74301  }
74302
74303  if (i.scrollbarXLeft >= i.railXWidth - i.scrollbarXWidth) {
74304    i.scrollbarXLeft = i.railXWidth - i.scrollbarXWidth;
74305  }
74306  if (i.scrollbarYTop >= i.railYHeight - i.scrollbarYHeight) {
74307    i.scrollbarYTop = i.railYHeight - i.scrollbarYHeight;
74308  }
74309
74310  updateCss(element, i);
74311
74312  if (i.scrollbarXActive) {
74313    cls.add(element, 'ps-active-x');
74314  } else {
74315    cls.remove(element, 'ps-active-x');
74316    i.scrollbarXWidth = 0;
74317    i.scrollbarXLeft = 0;
74318    updateScroll(element, 'left', 0);
74319  }
74320  if (i.scrollbarYActive) {
74321    cls.add(element, 'ps-active-y');
74322  } else {
74323    cls.remove(element, 'ps-active-y');
74324    i.scrollbarYHeight = 0;
74325    i.scrollbarYTop = 0;
74326    updateScroll(element, 'top', 0);
74327  }
74328};
74329
74330},{"../lib/class":2,"../lib/dom":3,"../lib/helper":6,"./instances":18,"./update-scroll":20}],20:[function(require,module,exports){
74331'use strict';
74332
74333var instances = require('./instances');
74334
74335var lastTop;
74336var lastLeft;
74337
74338var createDOMEvent = function (name) {
74339  var event = document.createEvent("Event");
74340  event.initEvent(name, true, true);
74341  return event;
74342};
74343
74344module.exports = function (element, axis, value) {
74345  if (typeof element === 'undefined') {
74346    throw 'You must provide an element to the update-scroll function';
74347  }
74348
74349  if (typeof axis === 'undefined') {
74350    throw 'You must provide an axis to the update-scroll function';
74351  }
74352
74353  if (typeof value === 'undefined') {
74354    throw 'You must provide a value to the update-scroll function';
74355  }
74356
74357  if (axis === 'top' && value <= 0) {
74358    element.scrollTop = value = 0; // don't allow negative scroll
74359    element.dispatchEvent(createDOMEvent('ps-y-reach-start'));
74360  }
74361
74362  if (axis === 'left' && value <= 0) {
74363    element.scrollLeft = value = 0; // don't allow negative scroll
74364    element.dispatchEvent(createDOMEvent('ps-x-reach-start'));
74365  }
74366
74367  var i = instances.get(element);
74368
74369  if (axis === 'top' && value >= i.contentHeight - i.containerHeight) {
74370    // don't allow scroll past container
74371    value = i.contentHeight - i.containerHeight;
74372    if (value - element.scrollTop <= 1) {
74373      // mitigates rounding errors on non-subpixel scroll values
74374      value = element.scrollTop;
74375    } else {
74376      element.scrollTop = value;
74377    }
74378    element.dispatchEvent(createDOMEvent('ps-y-reach-end'));
74379  }
74380
74381  if (axis === 'left' && value >= i.contentWidth - i.containerWidth) {
74382    // don't allow scroll past container
74383    value = i.contentWidth - i.containerWidth;
74384    if (value - element.scrollLeft <= 1) {
74385      // mitigates rounding errors on non-subpixel scroll values
74386      value = element.scrollLeft;
74387    } else {
74388      element.scrollLeft = value;
74389    }
74390    element.dispatchEvent(createDOMEvent('ps-x-reach-end'));
74391  }
74392
74393  if (!lastTop) {
74394    lastTop = element.scrollTop;
74395  }
74396
74397  if (!lastLeft) {
74398    lastLeft = element.scrollLeft;
74399  }
74400
74401  if (axis === 'top' && value < lastTop) {
74402    element.dispatchEvent(createDOMEvent('ps-scroll-up'));
74403  }
74404
74405  if (axis === 'top' && value > lastTop) {
74406    element.dispatchEvent(createDOMEvent('ps-scroll-down'));
74407  }
74408
74409  if (axis === 'left' && value < lastLeft) {
74410    element.dispatchEvent(createDOMEvent('ps-scroll-left'));
74411  }
74412
74413  if (axis === 'left' && value > lastLeft) {
74414    element.dispatchEvent(createDOMEvent('ps-scroll-right'));
74415  }
74416
74417  if (axis === 'top') {
74418    element.scrollTop = lastTop = value;
74419    element.dispatchEvent(createDOMEvent('ps-scroll-y'));
74420  }
74421
74422  if (axis === 'left') {
74423    element.scrollLeft = lastLeft = value;
74424    element.dispatchEvent(createDOMEvent('ps-scroll-x'));
74425  }
74426
74427};
74428
74429},{"./instances":18}],21:[function(require,module,exports){
74430'use strict';
74431
74432var _ = require('../lib/helper');
74433var dom = require('../lib/dom');
74434var instances = require('./instances');
74435var updateGeometry = require('./update-geometry');
74436var updateScroll = require('./update-scroll');
74437
74438module.exports = function (element) {
74439  var i = instances.get(element);
74440
74441  if (!i) {
74442    return;
74443  }
74444
74445  // Recalcuate negative scrollLeft adjustment
74446  i.negativeScrollAdjustment = i.isNegativeScroll ? element.scrollWidth - element.clientWidth : 0;
74447
74448  // Recalculate rail margins
74449  dom.css(i.scrollbarXRail, 'display', 'block');
74450  dom.css(i.scrollbarYRail, 'display', 'block');
74451  i.railXMarginWidth = _.toInt(dom.css(i.scrollbarXRail, 'marginLeft')) + _.toInt(dom.css(i.scrollbarXRail, 'marginRight'));
74452  i.railYMarginHeight = _.toInt(dom.css(i.scrollbarYRail, 'marginTop')) + _.toInt(dom.css(i.scrollbarYRail, 'marginBottom'));
74453
74454  // Hide scrollbars not to affect scrollWidth and scrollHeight
74455  dom.css(i.scrollbarXRail, 'display', 'none');
74456  dom.css(i.scrollbarYRail, 'display', 'none');
74457
74458  updateGeometry(element);
74459
74460  // Update top/left scroll to trigger events
74461  updateScroll(element, 'top', element.scrollTop);
74462  updateScroll(element, 'left', element.scrollLeft);
74463
74464  dom.css(i.scrollbarXRail, 'display', '');
74465  dom.css(i.scrollbarYRail, 'display', '');
74466};
74467
74468},{"../lib/dom":3,"../lib/helper":6,"./instances":18,"./update-geometry":19,"./update-scroll":20}]},{},[1]);
74469
74470 /**
74471  * React v15.0.2
74472  */
74473(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define('react',[],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.React = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
74474/**
74475 * Copyright 2013-present, Facebook, Inc.
74476 * All rights reserved.
74477 *
74478 * This source code is licensed under the BSD-style license found in the
74479 * LICENSE file in the root directory of this source tree. An additional grant
74480 * of patent rights can be found in the PATENTS file in the same directory.
74481 *
74482 * @providesModule AutoFocusUtils
74483 */
74484
74485
74486
74487var ReactDOMComponentTree = _dereq_(40);
74488
74489var focusNode = _dereq_(152);
74490
74491var AutoFocusUtils = {
74492  focusDOMComponent: function () {
74493    focusNode(ReactDOMComponentTree.getNodeFromInstance(this));
74494  }
74495};
74496
74497module.exports = AutoFocusUtils;
74498},{"152":152,"40":40}],2:[function(_dereq_,module,exports){
74499/**
74500 * Copyright 2013-present Facebook, Inc.
74501 * All rights reserved.
74502 *
74503 * This source code is licensed under the BSD-style license found in the
74504 * LICENSE file in the root directory of this source tree. An additional grant
74505 * of patent rights can be found in the PATENTS file in the same directory.
74506 *
74507 * @providesModule BeforeInputEventPlugin
74508 */
74509
74510
74511
74512var EventConstants = _dereq_(16);
74513var EventPropagators = _dereq_(20);
74514var ExecutionEnvironment = _dereq_(144);
74515var FallbackCompositionState = _dereq_(21);
74516var SyntheticCompositionEvent = _dereq_(101);
74517var SyntheticInputEvent = _dereq_(105);
74518
74519var keyOf = _dereq_(162);
74520
74521var END_KEYCODES = [9, 13, 27, 32]; // Tab, Return, Esc, Space
74522var START_KEYCODE = 229;
74523
74524var canUseCompositionEvent = ExecutionEnvironment.canUseDOM && 'CompositionEvent' in window;
74525
74526var documentMode = null;
74527if (ExecutionEnvironment.canUseDOM && 'documentMode' in document) {
74528  documentMode = document.documentMode;
74529}
74530
74531// Webkit offers a very useful `textInput` event that can be used to
74532// directly represent `beforeInput`. The IE `textinput` event is not as
74533// useful, so we don't use it.
74534var canUseTextInputEvent = ExecutionEnvironment.canUseDOM && 'TextEvent' in window && !documentMode && !isPresto();
74535
74536// In IE9+, we have access to composition events, but the data supplied
74537// by the native compositionend event may be incorrect. Japanese ideographic
74538// spaces, for instance (\u3000) are not recorded correctly.
74539var useFallbackCompositionData = ExecutionEnvironment.canUseDOM && (!canUseCompositionEvent || documentMode && documentMode > 8 && documentMode <= 11);
74540
74541/**
74542 * Opera <= 12 includes TextEvent in window, but does not fire
74543 * text input events. Rely on keypress instead.
74544 */
74545function isPresto() {
74546  var opera = window.opera;
74547  return typeof opera === 'object' && typeof opera.version === 'function' && parseInt(opera.version(), 10) <= 12;
74548}
74549
74550var SPACEBAR_CODE = 32;
74551var SPACEBAR_CHAR = String.fromCharCode(SPACEBAR_CODE);
74552
74553var topLevelTypes = EventConstants.topLevelTypes;
74554
74555// Events and their corresponding property names.
74556var eventTypes = {
74557  beforeInput: {
74558    phasedRegistrationNames: {
74559      bubbled: keyOf({ onBeforeInput: null }),
74560      captured: keyOf({ onBeforeInputCapture: null })
74561    },
74562    dependencies: [topLevelTypes.topCompositionEnd, topLevelTypes.topKeyPress, topLevelTypes.topTextInput, topLevelTypes.topPaste]
74563  },
74564  compositionEnd: {
74565    phasedRegistrationNames: {
74566      bubbled: keyOf({ onCompositionEnd: null }),
74567      captured: keyOf({ onCompositionEndCapture: null })
74568    },
74569    dependencies: [topLevelTypes.topBlur, topLevelTypes.topCompositionEnd, topLevelTypes.topKeyDown, topLevelTypes.topKeyPress, topLevelTypes.topKeyUp, topLevelTypes.topMouseDown]
74570  },
74571  compositionStart: {
74572    phasedRegistrationNames: {
74573      bubbled: keyOf({ onCompositionStart: null }),
74574      captured: keyOf({ onCompositionStartCapture: null })
74575    },
74576    dependencies: [topLevelTypes.topBlur, topLevelTypes.topCompositionStart, topLevelTypes.topKeyDown, topLevelTypes.topKeyPress, topLevelTypes.topKeyUp, topLevelTypes.topMouseDown]
74577  },
74578  compositionUpdate: {
74579    phasedRegistrationNames: {
74580      bubbled: keyOf({ onCompositionUpdate: null }),
74581      captured: keyOf({ onCompositionUpdateCapture: null })
74582    },
74583    dependencies: [topLevelTypes.topBlur, topLevelTypes.topCompositionUpdate, topLevelTypes.topKeyDown, topLevelTypes.topKeyPress, topLevelTypes.topKeyUp, topLevelTypes.topMouseDown]
74584  }
74585};
74586
74587// Track whether we've ever handled a keypress on the space key.
74588var hasSpaceKeypress = false;
74589
74590/**
74591 * Return whether a native keypress event is assumed to be a command.
74592 * This is required because Firefox fires `keypress` events for key commands
74593 * (cut, copy, select-all, etc.) even though no character is inserted.
74594 */
74595function isKeypressCommand(nativeEvent) {
74596  return (nativeEvent.ctrlKey || nativeEvent.altKey || nativeEvent.metaKey) &&
74597  // ctrlKey && altKey is equivalent to AltGr, and is not a command.
74598  !(nativeEvent.ctrlKey && nativeEvent.altKey);
74599}
74600
74601/**
74602 * Translate native top level events into event types.
74603 *
74604 * @param {string} topLevelType
74605 * @return {object}
74606 */
74607function getCompositionEventType(topLevelType) {
74608  switch (topLevelType) {
74609    case topLevelTypes.topCompositionStart:
74610      return eventTypes.compositionStart;
74611    case topLevelTypes.topCompositionEnd:
74612      return eventTypes.compositionEnd;
74613    case topLevelTypes.topCompositionUpdate:
74614      return eventTypes.compositionUpdate;
74615  }
74616}
74617
74618/**
74619 * Does our fallback best-guess model think this event signifies that
74620 * composition has begun?
74621 *
74622 * @param {string} topLevelType
74623 * @param {object} nativeEvent
74624 * @return {boolean}
74625 */
74626function isFallbackCompositionStart(topLevelType, nativeEvent) {
74627  return topLevelType === topLevelTypes.topKeyDown && nativeEvent.keyCode === START_KEYCODE;
74628}
74629
74630/**
74631 * Does our fallback mode think that this event is the end of composition?
74632 *
74633 * @param {string} topLevelType
74634 * @param {object} nativeEvent
74635 * @return {boolean}
74636 */
74637function isFallbackCompositionEnd(topLevelType, nativeEvent) {
74638  switch (topLevelType) {
74639    case topLevelTypes.topKeyUp:
74640      // Command keys insert or clear IME input.
74641      return END_KEYCODES.indexOf(nativeEvent.keyCode) !== -1;
74642    case topLevelTypes.topKeyDown:
74643      // Expect IME keyCode on each keydown. If we get any other
74644      // code we must have exited earlier.
74645      return nativeEvent.keyCode !== START_KEYCODE;
74646    case topLevelTypes.topKeyPress:
74647    case topLevelTypes.topMouseDown:
74648    case topLevelTypes.topBlur:
74649      // Events are not possible without cancelling IME.
74650      return true;
74651    default:
74652      return false;
74653  }
74654}
74655
74656/**
74657 * Google Input Tools provides composition data via a CustomEvent,
74658 * with the `data` property populated in the `detail` object. If this
74659 * is available on the event object, use it. If not, this is a plain
74660 * composition event and we have nothing special to extract.
74661 *
74662 * @param {object} nativeEvent
74663 * @return {?string}
74664 */
74665function getDataFromCustomEvent(nativeEvent) {
74666  var detail = nativeEvent.detail;
74667  if (typeof detail === 'object' && 'data' in detail) {
74668    return detail.data;
74669  }
74670  return null;
74671}
74672
74673// Track the current IME composition fallback object, if any.
74674var currentComposition = null;
74675
74676/**
74677 * @return {?object} A SyntheticCompositionEvent.
74678 */
74679function extractCompositionEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget) {
74680  var eventType;
74681  var fallbackData;
74682
74683  if (canUseCompositionEvent) {
74684    eventType = getCompositionEventType(topLevelType);
74685  } else if (!currentComposition) {
74686    if (isFallbackCompositionStart(topLevelType, nativeEvent)) {
74687      eventType = eventTypes.compositionStart;
74688    }
74689  } else if (isFallbackCompositionEnd(topLevelType, nativeEvent)) {
74690    eventType = eventTypes.compositionEnd;
74691  }
74692
74693  if (!eventType) {
74694    return null;
74695  }
74696
74697  if (useFallbackCompositionData) {
74698    // The current composition is stored statically and must not be
74699    // overwritten while composition continues.
74700    if (!currentComposition && eventType === eventTypes.compositionStart) {
74701      currentComposition = FallbackCompositionState.getPooled(nativeEventTarget);
74702    } else if (eventType === eventTypes.compositionEnd) {
74703      if (currentComposition) {
74704        fallbackData = currentComposition.getData();
74705      }
74706    }
74707  }
74708
74709  var event = SyntheticCompositionEvent.getPooled(eventType, targetInst, nativeEvent, nativeEventTarget);
74710
74711  if (fallbackData) {
74712    // Inject data generated from fallback path into the synthetic event.
74713    // This matches the property of native CompositionEventInterface.
74714    event.data = fallbackData;
74715  } else {
74716    var customData = getDataFromCustomEvent(nativeEvent);
74717    if (customData !== null) {
74718      event.data = customData;
74719    }
74720  }
74721
74722  EventPropagators.accumulateTwoPhaseDispatches(event);
74723  return event;
74724}
74725
74726/**
74727 * @param {string} topLevelType Record from `EventConstants`.
74728 * @param {object} nativeEvent Native browser event.
74729 * @return {?string} The string corresponding to this `beforeInput` event.
74730 */
74731function getNativeBeforeInputChars(topLevelType, nativeEvent) {
74732  switch (topLevelType) {
74733    case topLevelTypes.topCompositionEnd:
74734      return getDataFromCustomEvent(nativeEvent);
74735    case topLevelTypes.topKeyPress:
74736      /**
74737       * If native `textInput` events are available, our goal is to make
74738       * use of them. However, there is a special case: the spacebar key.
74739       * In Webkit, preventing default on a spacebar `textInput` event
74740       * cancels character insertion, but it *also* causes the browser
74741       * to fall back to its default spacebar behavior of scrolling the
74742       * page.
74743       *
74744       * Tracking at:
74745       * https://code.google.com/p/chromium/issues/detail?id=355103
74746       *
74747       * To avoid this issue, use the keypress event as if no `textInput`
74748       * event is available.
74749       */
74750      var which = nativeEvent.which;
74751      if (which !== SPACEBAR_CODE) {
74752        return null;
74753      }
74754
74755      hasSpaceKeypress = true;
74756      return SPACEBAR_CHAR;
74757
74758    case topLevelTypes.topTextInput:
74759      // Record the characters to be added to the DOM.
74760      var chars = nativeEvent.data;
74761
74762      // If it's a spacebar character, assume that we have already handled
74763      // it at the keypress level and bail immediately. Android Chrome
74764      // doesn't give us keycodes, so we need to blacklist it.
74765      if (chars === SPACEBAR_CHAR && hasSpaceKeypress) {
74766        return null;
74767      }
74768
74769      return chars;
74770
74771    default:
74772      // For other native event types, do nothing.
74773      return null;
74774  }
74775}
74776
74777/**
74778 * For browsers that do not provide the `textInput` event, extract the
74779 * appropriate string to use for SyntheticInputEvent.
74780 *
74781 * @param {string} topLevelType Record from `EventConstants`.
74782 * @param {object} nativeEvent Native browser event.
74783 * @return {?string} The fallback string for this `beforeInput` event.
74784 */
74785function getFallbackBeforeInputChars(topLevelType, nativeEvent) {
74786  // If we are currently composing (IME) and using a fallback to do so,
74787  // try to extract the composed characters from the fallback object.
74788  if (currentComposition) {
74789    if (topLevelType === topLevelTypes.topCompositionEnd || isFallbackCompositionEnd(topLevelType, nativeEvent)) {
74790      var chars = currentComposition.getData();
74791      FallbackCompositionState.release(currentComposition);
74792      currentComposition = null;
74793      return chars;
74794    }
74795    return null;
74796  }
74797
74798  switch (topLevelType) {
74799    case topLevelTypes.topPaste:
74800      // If a paste event occurs after a keypress, throw out the input
74801      // chars. Paste events should not lead to BeforeInput events.
74802      return null;
74803    case topLevelTypes.topKeyPress:
74804      /**
74805       * As of v27, Firefox may fire keypress events even when no character
74806       * will be inserted. A few possibilities:
74807       *
74808       * - `which` is `0`. Arrow keys, Esc key, etc.
74809       *
74810       * - `which` is the pressed key code, but no char is available.
74811       *   Ex: 'AltGr + d` in Polish. There is no modified character for
74812       *   this key combination and no character is inserted into the
74813       *   document, but FF fires the keypress for char code `100` anyway.
74814       *   No `input` event will occur.
74815       *
74816       * - `which` is the pressed key code, but a command combination is
74817       *   being used. Ex: `Cmd+C`. No character is inserted, and no
74818       *   `input` event will occur.
74819       */
74820      if (nativeEvent.which && !isKeypressCommand(nativeEvent)) {
74821        return String.fromCharCode(nativeEvent.which);
74822      }
74823      return null;
74824    case topLevelTypes.topCompositionEnd:
74825      return useFallbackCompositionData ? null : nativeEvent.data;
74826    default:
74827      return null;
74828  }
74829}
74830
74831/**
74832 * Extract a SyntheticInputEvent for `beforeInput`, based on either native
74833 * `textInput` or fallback behavior.
74834 *
74835 * @return {?object} A SyntheticInputEvent.
74836 */
74837function extractBeforeInputEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget) {
74838  var chars;
74839
74840  if (canUseTextInputEvent) {
74841    chars = getNativeBeforeInputChars(topLevelType, nativeEvent);
74842  } else {
74843    chars = getFallbackBeforeInputChars(topLevelType, nativeEvent);
74844  }
74845
74846  // If no characters are being inserted, no BeforeInput event should
74847  // be fired.
74848  if (!chars) {
74849    return null;
74850  }
74851
74852  var event = SyntheticInputEvent.getPooled(eventTypes.beforeInput, targetInst, nativeEvent, nativeEventTarget);
74853
74854  event.data = chars;
74855  EventPropagators.accumulateTwoPhaseDispatches(event);
74856  return event;
74857}
74858
74859/**
74860 * Create an `onBeforeInput` event to match
74861 * http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105/#events-inputevents.
74862 *
74863 * This event plugin is based on the native `textInput` event
74864 * available in Chrome, Safari, Opera, and IE. This event fires after
74865 * `onKeyPress` and `onCompositionEnd`, but before `onInput`.
74866 *
74867 * `beforeInput` is spec'd but not implemented in any browsers, and
74868 * the `input` event does not provide any useful information about what has
74869 * actually been added, contrary to the spec. Thus, `textInput` is the best
74870 * available event to identify the characters that have actually been inserted
74871 * into the target node.
74872 *
74873 * This plugin is also responsible for emitting `composition` events, thus
74874 * allowing us to share composition fallback code for both `beforeInput` and
74875 * `composition` event types.
74876 */
74877var BeforeInputEventPlugin = {
74878
74879  eventTypes: eventTypes,
74880
74881  extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
74882    return [extractCompositionEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget), extractBeforeInputEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget)];
74883  }
74884};
74885
74886module.exports = BeforeInputEventPlugin;
74887},{"101":101,"105":105,"144":144,"16":16,"162":162,"20":20,"21":21}],3:[function(_dereq_,module,exports){
74888/**
74889 * Copyright 2013-present, Facebook, Inc.
74890 * All rights reserved.
74891 *
74892 * This source code is licensed under the BSD-style license found in the
74893 * LICENSE file in the root directory of this source tree. An additional grant
74894 * of patent rights can be found in the PATENTS file in the same directory.
74895 *
74896 * @providesModule CSSProperty
74897 */
74898
74899
74900
74901/**
74902 * CSS properties which accept numbers but are not in units of "px".
74903 */
74904
74905var isUnitlessNumber = {
74906  animationIterationCount: true,
74907  borderImageOutset: true,
74908  borderImageSlice: true,
74909  borderImageWidth: true,
74910  boxFlex: true,
74911  boxFlexGroup: true,
74912  boxOrdinalGroup: true,
74913  columnCount: true,
74914  flex: true,
74915  flexGrow: true,
74916  flexPositive: true,
74917  flexShrink: true,
74918  flexNegative: true,
74919  flexOrder: true,
74920  gridRow: true,
74921  gridColumn: true,
74922  fontWeight: true,
74923  lineClamp: true,
74924  lineHeight: true,
74925  opacity: true,
74926  order: true,
74927  orphans: true,
74928  tabSize: true,
74929  widows: true,
74930  zIndex: true,
74931  zoom: true,
74932
74933  // SVG-related properties
74934  fillOpacity: true,
74935  floodOpacity: true,
74936  stopOpacity: true,
74937  strokeDasharray: true,
74938  strokeDashoffset: true,
74939  strokeMiterlimit: true,
74940  strokeOpacity: true,
74941  strokeWidth: true
74942};
74943
74944/**
74945 * @param {string} prefix vendor-specific prefix, eg: Webkit
74946 * @param {string} key style name, eg: transitionDuration
74947 * @return {string} style name prefixed with `prefix`, properly camelCased, eg:
74948 * WebkitTransitionDuration
74949 */
74950function prefixKey(prefix, key) {
74951  return prefix + key.charAt(0).toUpperCase() + key.substring(1);
74952}
74953
74954/**
74955 * Support style names that may come passed in prefixed by adding permutations
74956 * of vendor prefixes.
74957 */
74958var prefixes = ['Webkit', 'ms', 'Moz', 'O'];
74959
74960// Using Object.keys here, or else the vanilla for-in loop makes IE8 go into an
74961// infinite loop, because it iterates over the newly added props too.
74962Object.keys(isUnitlessNumber).forEach(function (prop) {
74963  prefixes.forEach(function (prefix) {
74964    isUnitlessNumber[prefixKey(prefix, prop)] = isUnitlessNumber[prop];
74965  });
74966});
74967
74968/**
74969 * Most style properties can be unset by doing .style[prop] = '' but IE8
74970 * doesn't like doing that with shorthand properties so for the properties that
74971 * IE8 breaks on, which are listed here, we instead unset each of the
74972 * individual properties. See http://bugs.jquery.com/ticket/12385.
74973 * The 4-value 'clock' properties like margin, padding, border-width seem to
74974 * behave without any problems. Curiously, list-style works too without any
74975 * special prodding.
74976 */
74977var shorthandPropertyExpansions = {
74978  background: {
74979    backgroundAttachment: true,
74980    backgroundColor: true,
74981    backgroundImage: true,
74982    backgroundPositionX: true,
74983    backgroundPositionY: true,
74984    backgroundRepeat: true
74985  },
74986  backgroundPosition: {
74987    backgroundPositionX: true,
74988    backgroundPositionY: true
74989  },
74990  border: {
74991    borderWidth: true,
74992    borderStyle: true,
74993    borderColor: true
74994  },
74995  borderBottom: {
74996    borderBottomWidth: true,
74997    borderBottomStyle: true,
74998    borderBottomColor: true
74999  },
75000  borderLeft: {
75001    borderLeftWidth: true,
75002    borderLeftStyle: true,
75003    borderLeftColor: true
75004  },
75005  borderRight: {
75006    borderRightWidth: true,
75007    borderRightStyle: true,
75008    borderRightColor: true
75009  },
75010  borderTop: {
75011    borderTopWidth: true,
75012    borderTopStyle: true,
75013    borderTopColor: true
75014  },
75015  font: {
75016    fontStyle: true,
75017    fontVariant: true,
75018    fontWeight: true,
75019    fontSize: true,
75020    lineHeight: true,
75021    fontFamily: true
75022  },
75023  outline: {
75024    outlineWidth: true,
75025    outlineStyle: true,
75026    outlineColor: true
75027  }
75028};
75029
75030var CSSProperty = {
75031  isUnitlessNumber: isUnitlessNumber,
75032  shorthandPropertyExpansions: shorthandPropertyExpansions
75033};
75034
75035module.exports = CSSProperty;
75036},{}],4:[function(_dereq_,module,exports){
75037/**
75038 * Copyright 2013-present, Facebook, Inc.
75039 * All rights reserved.
75040 *
75041 * This source code is licensed under the BSD-style license found in the
75042 * LICENSE file in the root directory of this source tree. An additional grant
75043 * of patent rights can be found in the PATENTS file in the same directory.
75044 *
75045 * @providesModule CSSPropertyOperations
75046 */
75047
75048
75049
75050var CSSProperty = _dereq_(3);
75051var ExecutionEnvironment = _dereq_(144);
75052var ReactPerf = _dereq_(82);
75053
75054var camelizeStyleName = _dereq_(146);
75055var dangerousStyleValue = _dereq_(118);
75056var hyphenateStyleName = _dereq_(157);
75057var memoizeStringOnly = _dereq_(164);
75058var warning = _dereq_(168);
75059
75060var processStyleName = memoizeStringOnly(function (styleName) {
75061  return hyphenateStyleName(styleName);
75062});
75063
75064var hasShorthandPropertyBug = false;
75065var styleFloatAccessor = 'cssFloat';
75066if (ExecutionEnvironment.canUseDOM) {
75067  var tempStyle = document.createElement('div').style;
75068  try {
75069    // IE8 throws "Invalid argument." if resetting shorthand style properties.
75070    tempStyle.font = '';
75071  } catch (e) {
75072    hasShorthandPropertyBug = true;
75073  }
75074  // IE8 only supports accessing cssFloat (standard) as styleFloat
75075  if (document.documentElement.style.cssFloat === undefined) {
75076    styleFloatAccessor = 'styleFloat';
75077  }
75078}
75079
75080if ("development" !== 'production') {
75081  // 'msTransform' is correct, but the other prefixes should be capitalized
75082  var badVendoredStyleNamePattern = /^(?:webkit|moz|o)[A-Z]/;
75083
75084  // style values shouldn't contain a semicolon
75085  var badStyleValueWithSemicolonPattern = /;\s*$/;
75086
75087  var warnedStyleNames = {};
75088  var warnedStyleValues = {};
75089  var warnedForNaNValue = false;
75090
75091  var warnHyphenatedStyleName = function (name, owner) {
75092    if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {
75093      return;
75094    }
75095
75096    warnedStyleNames[name] = true;
75097    "development" !== 'production' ? warning(false, 'Unsupported style property %s. Did you mean %s?%s', name, camelizeStyleName(name), checkRenderMessage(owner)) : void 0;
75098  };
75099
75100  var warnBadVendoredStyleName = function (name, owner) {
75101    if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {
75102      return;
75103    }
75104
75105    warnedStyleNames[name] = true;
75106    "development" !== 'production' ? warning(false, 'Unsupported vendor-prefixed style property %s. Did you mean %s?%s', name, name.charAt(0).toUpperCase() + name.slice(1), checkRenderMessage(owner)) : void 0;
75107  };
75108
75109  var warnStyleValueWithSemicolon = function (name, value, owner) {
75110    if (warnedStyleValues.hasOwnProperty(value) && warnedStyleValues[value]) {
75111      return;
75112    }
75113
75114    warnedStyleValues[value] = true;
75115    "development" !== 'production' ? warning(false, 'Style property values shouldn\'t contain a semicolon.%s ' + 'Try "%s: %s" instead.', checkRenderMessage(owner), name, value.replace(badStyleValueWithSemicolonPattern, '')) : void 0;
75116  };
75117
75118  var warnStyleValueIsNaN = function (name, value, owner) {
75119    if (warnedForNaNValue) {
75120      return;
75121    }
75122
75123    warnedForNaNValue = true;
75124    "development" !== 'production' ? warning(false, '`NaN` is an invalid value for the `%s` css style property.%s', name, checkRenderMessage(owner)) : void 0;
75125  };
75126
75127  var checkRenderMessage = function (owner) {
75128    if (owner) {
75129      var name = owner.getName();
75130      if (name) {
75131        return ' Check the render method of `' + name + '`.';
75132      }
75133    }
75134    return '';
75135  };
75136
75137  /**
75138   * @param {string} name
75139   * @param {*} value
75140   * @param {ReactDOMComponent} component
75141   */
75142  var warnValidStyle = function (name, value, component) {
75143    var owner;
75144    if (component) {
75145      owner = component._currentElement._owner;
75146    }
75147    if (name.indexOf('-') > -1) {
75148      warnHyphenatedStyleName(name, owner);
75149    } else if (badVendoredStyleNamePattern.test(name)) {
75150      warnBadVendoredStyleName(name, owner);
75151    } else if (badStyleValueWithSemicolonPattern.test(value)) {
75152      warnStyleValueWithSemicolon(name, value, owner);
75153    }
75154
75155    if (typeof value === 'number' && isNaN(value)) {
75156      warnStyleValueIsNaN(name, value, owner);
75157    }
75158  };
75159}
75160
75161/**
75162 * Operations for dealing with CSS properties.
75163 */
75164var CSSPropertyOperations = {
75165
75166  /**
75167   * Serializes a mapping of style properties for use as inline styles:
75168   *
75169   *   > createMarkupForStyles({width: '200px', height: 0})
75170   *   "width:200px;height:0;"
75171   *
75172   * Undefined values are ignored so that declarative programming is easier.
75173   * The result should be HTML-escaped before insertion into the DOM.
75174   *
75175   * @param {object} styles
75176   * @param {ReactDOMComponent} component
75177   * @return {?string}
75178   */
75179  createMarkupForStyles: function (styles, component) {
75180    var serialized = '';
75181    for (var styleName in styles) {
75182      if (!styles.hasOwnProperty(styleName)) {
75183        continue;
75184      }
75185      var styleValue = styles[styleName];
75186      if ("development" !== 'production') {
75187        warnValidStyle(styleName, styleValue, component);
75188      }
75189      if (styleValue != null) {
75190        serialized += processStyleName(styleName) + ':';
75191        serialized += dangerousStyleValue(styleName, styleValue, component) + ';';
75192      }
75193    }
75194    return serialized || null;
75195  },
75196
75197  /**
75198   * Sets the value for multiple styles on a node.  If a value is specified as
75199   * '' (empty string), the corresponding style property will be unset.
75200   *
75201   * @param {DOMElement} node
75202   * @param {object} styles
75203   * @param {ReactDOMComponent} component
75204   */
75205  setValueForStyles: function (node, styles, component) {
75206    var style = node.style;
75207    for (var styleName in styles) {
75208      if (!styles.hasOwnProperty(styleName)) {
75209        continue;
75210      }
75211      if ("development" !== 'production') {
75212        warnValidStyle(styleName, styles[styleName], component);
75213      }
75214      var styleValue = dangerousStyleValue(styleName, styles[styleName], component);
75215      if (styleName === 'float' || styleName === 'cssFloat') {
75216        styleName = styleFloatAccessor;
75217      }
75218      if (styleValue) {
75219        style[styleName] = styleValue;
75220      } else {
75221        var expansion = hasShorthandPropertyBug && CSSProperty.shorthandPropertyExpansions[styleName];
75222        if (expansion) {
75223          // Shorthand property that IE8 won't like unsetting, so unset each
75224          // component to placate it
75225          for (var individualStyleName in expansion) {
75226            style[individualStyleName] = '';
75227          }
75228        } else {
75229          style[styleName] = '';
75230        }
75231      }
75232    }
75233  }
75234
75235};
75236
75237ReactPerf.measureMethods(CSSPropertyOperations, 'CSSPropertyOperations', {
75238  setValueForStyles: 'setValueForStyles'
75239});
75240
75241module.exports = CSSPropertyOperations;
75242},{"118":118,"144":144,"146":146,"157":157,"164":164,"168":168,"3":3,"82":82}],5:[function(_dereq_,module,exports){
75243/**
75244 * Copyright 2013-present, Facebook, Inc.
75245 * All rights reserved.
75246 *
75247 * This source code is licensed under the BSD-style license found in the
75248 * LICENSE file in the root directory of this source tree. An additional grant
75249 * of patent rights can be found in the PATENTS file in the same directory.
75250 *
75251 * @providesModule CallbackQueue
75252 */
75253
75254
75255
75256var _assign = _dereq_(169);
75257
75258var PooledClass = _dereq_(25);
75259
75260var invariant = _dereq_(158);
75261
75262/**
75263 * A specialized pseudo-event module to help keep track of components waiting to
75264 * be notified when their DOM representations are available for use.
75265 *
75266 * This implements `PooledClass`, so you should never need to instantiate this.
75267 * Instead, use `CallbackQueue.getPooled()`.
75268 *
75269 * @class ReactMountReady
75270 * @implements PooledClass
75271 * @internal
75272 */
75273function CallbackQueue() {
75274  this._callbacks = null;
75275  this._contexts = null;
75276}
75277
75278_assign(CallbackQueue.prototype, {
75279
75280  /**
75281   * Enqueues a callback to be invoked when `notifyAll` is invoked.
75282   *
75283   * @param {function} callback Invoked when `notifyAll` is invoked.
75284   * @param {?object} context Context to call `callback` with.
75285   * @internal
75286   */
75287  enqueue: function (callback, context) {
75288    this._callbacks = this._callbacks || [];
75289    this._contexts = this._contexts || [];
75290    this._callbacks.push(callback);
75291    this._contexts.push(context);
75292  },
75293
75294  /**
75295   * Invokes all enqueued callbacks and clears the queue. This is invoked after
75296   * the DOM representation of a component has been created or updated.
75297   *
75298   * @internal
75299   */
75300  notifyAll: function () {
75301    var callbacks = this._callbacks;
75302    var contexts = this._contexts;
75303    if (callbacks) {
75304      !(callbacks.length === contexts.length) ? "development" !== 'production' ? invariant(false, 'Mismatched list of contexts in callback queue') : invariant(false) : void 0;
75305      this._callbacks = null;
75306      this._contexts = null;
75307      for (var i = 0; i < callbacks.length; i++) {
75308        callbacks[i].call(contexts[i]);
75309      }
75310      callbacks.length = 0;
75311      contexts.length = 0;
75312    }
75313  },
75314
75315  checkpoint: function () {
75316    return this._callbacks ? this._callbacks.length : 0;
75317  },
75318
75319  rollback: function (len) {
75320    if (this._callbacks) {
75321      this._callbacks.length = len;
75322      this._contexts.length = len;
75323    }
75324  },
75325
75326  /**
75327   * Resets the internal queue.
75328   *
75329   * @internal
75330   */
75331  reset: function () {
75332    this._callbacks = null;
75333    this._contexts = null;
75334  },
75335
75336  /**
75337   * `PooledClass` looks for this.
75338   */
75339  destructor: function () {
75340    this.reset();
75341  }
75342
75343});
75344
75345PooledClass.addPoolingTo(CallbackQueue);
75346
75347module.exports = CallbackQueue;
75348},{"158":158,"169":169,"25":25}],6:[function(_dereq_,module,exports){
75349/**
75350 * Copyright 2013-present, Facebook, Inc.
75351 * All rights reserved.
75352 *
75353 * This source code is licensed under the BSD-style license found in the
75354 * LICENSE file in the root directory of this source tree. An additional grant
75355 * of patent rights can be found in the PATENTS file in the same directory.
75356 *
75357 * @providesModule ChangeEventPlugin
75358 */
75359
75360
75361
75362var EventConstants = _dereq_(16);
75363var EventPluginHub = _dereq_(17);
75364var EventPropagators = _dereq_(20);
75365var ExecutionEnvironment = _dereq_(144);
75366var ReactDOMComponentTree = _dereq_(40);
75367var ReactUpdates = _dereq_(94);
75368var SyntheticEvent = _dereq_(103);
75369
75370var getEventTarget = _dereq_(126);
75371var isEventSupported = _dereq_(133);
75372var isTextInputElement = _dereq_(134);
75373var keyOf = _dereq_(162);
75374
75375var topLevelTypes = EventConstants.topLevelTypes;
75376
75377var eventTypes = {
75378  change: {
75379    phasedRegistrationNames: {
75380      bubbled: keyOf({ onChange: null }),
75381      captured: keyOf({ onChangeCapture: null })
75382    },
75383    dependencies: [topLevelTypes.topBlur, topLevelTypes.topChange, topLevelTypes.topClick, topLevelTypes.topFocus, topLevelTypes.topInput, topLevelTypes.topKeyDown, topLevelTypes.topKeyUp, topLevelTypes.topSelectionChange]
75384  }
75385};
75386
75387/**
75388 * For IE shims
75389 */
75390var activeElement = null;
75391var activeElementInst = null;
75392var activeElementValue = null;
75393var activeElementValueProp = null;
75394
75395/**
75396 * SECTION: handle `change` event
75397 */
75398function shouldUseChangeEvent(elem) {
75399  var nodeName = elem.nodeName && elem.nodeName.toLowerCase();
75400  return nodeName === 'select' || nodeName === 'input' && elem.type === 'file';
75401}
75402
75403var doesChangeEventBubble = false;
75404if (ExecutionEnvironment.canUseDOM) {
75405  // See `handleChange` comment below
75406  doesChangeEventBubble = isEventSupported('change') && (!('documentMode' in document) || document.documentMode > 8);
75407}
75408
75409function manualDispatchChangeEvent(nativeEvent) {
75410  var event = SyntheticEvent.getPooled(eventTypes.change, activeElementInst, nativeEvent, getEventTarget(nativeEvent));
75411  EventPropagators.accumulateTwoPhaseDispatches(event);
75412
75413  // If change and propertychange bubbled, we'd just bind to it like all the
75414  // other events and have it go through ReactBrowserEventEmitter. Since it
75415  // doesn't, we manually listen for the events and so we have to enqueue and
75416  // process the abstract event manually.
75417  //
75418  // Batching is necessary here in order to ensure that all event handlers run
75419  // before the next rerender (including event handlers attached to ancestor
75420  // elements instead of directly on the input). Without this, controlled
75421  // components don't work properly in conjunction with event bubbling because
75422  // the component is rerendered and the value reverted before all the event
75423  // handlers can run. See https://github.com/facebook/react/issues/708.
75424  ReactUpdates.batchedUpdates(runEventInBatch, event);
75425}
75426
75427function runEventInBatch(event) {
75428  EventPluginHub.enqueueEvents(event);
75429  EventPluginHub.processEventQueue(false);
75430}
75431
75432function startWatchingForChangeEventIE8(target, targetInst) {
75433  activeElement = target;
75434  activeElementInst = targetInst;
75435  activeElement.attachEvent('onchange', manualDispatchChangeEvent);
75436}
75437
75438function stopWatchingForChangeEventIE8() {
75439  if (!activeElement) {
75440    return;
75441  }
75442  activeElement.detachEvent('onchange', manualDispatchChangeEvent);
75443  activeElement = null;
75444  activeElementInst = null;
75445}
75446
75447function getTargetInstForChangeEvent(topLevelType, targetInst) {
75448  if (topLevelType === topLevelTypes.topChange) {
75449    return targetInst;
75450  }
75451}
75452function handleEventsForChangeEventIE8(topLevelType, target, targetInst) {
75453  if (topLevelType === topLevelTypes.topFocus) {
75454    // stopWatching() should be a noop here but we call it just in case we
75455    // missed a blur event somehow.
75456    stopWatchingForChangeEventIE8();
75457    startWatchingForChangeEventIE8(target, targetInst);
75458  } else if (topLevelType === topLevelTypes.topBlur) {
75459    stopWatchingForChangeEventIE8();
75460  }
75461}
75462
75463/**
75464 * SECTION: handle `input` event
75465 */
75466var isInputEventSupported = false;
75467if (ExecutionEnvironment.canUseDOM) {
75468  // IE9 claims to support the input event but fails to trigger it when
75469  // deleting text, so we ignore its input events.
75470  // IE10+ fire input events to often, such when a placeholder
75471  // changes or when an input with a placeholder is focused.
75472  isInputEventSupported = isEventSupported('input') && (!('documentMode' in document) || document.documentMode > 11);
75473}
75474
75475/**
75476 * (For IE <=11) Replacement getter/setter for the `value` property that gets
75477 * set on the active element.
75478 */
75479var newValueProp = {
75480  get: function () {
75481    return activeElementValueProp.get.call(this);
75482  },
75483  set: function (val) {
75484    // Cast to a string so we can do equality checks.
75485    activeElementValue = '' + val;
75486    activeElementValueProp.set.call(this, val);
75487  }
75488};
75489
75490/**
75491 * (For IE <=11) Starts tracking propertychange events on the passed-in element
75492 * and override the value property so that we can distinguish user events from
75493 * value changes in JS.
75494 */
75495function startWatchingForValueChange(target, targetInst) {
75496  activeElement = target;
75497  activeElementInst = targetInst;
75498  activeElementValue = target.value;
75499  activeElementValueProp = Object.getOwnPropertyDescriptor(target.constructor.prototype, 'value');
75500
75501  // Not guarded in a canDefineProperty check: IE8 supports defineProperty only
75502  // on DOM elements
75503  Object.defineProperty(activeElement, 'value', newValueProp);
75504  if (activeElement.attachEvent) {
75505    activeElement.attachEvent('onpropertychange', handlePropertyChange);
75506  } else {
75507    activeElement.addEventListener('propertychange', handlePropertyChange, false);
75508  }
75509}
75510
75511/**
75512 * (For IE <=11) Removes the event listeners from the currently-tracked element,
75513 * if any exists.
75514 */
75515function stopWatchingForValueChange() {
75516  if (!activeElement) {
75517    return;
75518  }
75519
75520  // delete restores the original property definition
75521  delete activeElement.value;
75522
75523  if (activeElement.detachEvent) {
75524    activeElement.detachEvent('onpropertychange', handlePropertyChange);
75525  } else {
75526    activeElement.removeEventListener('propertychange', handlePropertyChange, false);
75527  }
75528
75529  activeElement = null;
75530  activeElementInst = null;
75531  activeElementValue = null;
75532  activeElementValueProp = null;
75533}
75534
75535/**
75536 * (For IE <=11) Handles a propertychange event, sending a `change` event if
75537 * the value of the active element has changed.
75538 */
75539function handlePropertyChange(nativeEvent) {
75540  if (nativeEvent.propertyName !== 'value') {
75541    return;
75542  }
75543  var value = nativeEvent.srcElement.value;
75544  if (value === activeElementValue) {
75545    return;
75546  }
75547  activeElementValue = value;
75548
75549  manualDispatchChangeEvent(nativeEvent);
75550}
75551
75552/**
75553 * If a `change` event should be fired, returns the target's ID.
75554 */
75555function getTargetInstForInputEvent(topLevelType, targetInst) {
75556  if (topLevelType === topLevelTypes.topInput) {
75557    // In modern browsers (i.e., not IE8 or IE9), the input event is exactly
75558    // what we want so fall through here and trigger an abstract event
75559    return targetInst;
75560  }
75561}
75562
75563function handleEventsForInputEventIE(topLevelType, target, targetInst) {
75564  if (topLevelType === topLevelTypes.topFocus) {
75565    // In IE8, we can capture almost all .value changes by adding a
75566    // propertychange handler and looking for events with propertyName
75567    // equal to 'value'
75568    // In IE9-11, propertychange fires for most input events but is buggy and
75569    // doesn't fire when text is deleted, but conveniently, selectionchange
75570    // appears to fire in all of the remaining cases so we catch those and
75571    // forward the event if the value has changed
75572    // In either case, we don't want to call the event handler if the value
75573    // is changed from JS so we redefine a setter for `.value` that updates
75574    // our activeElementValue variable, allowing us to ignore those changes
75575    //
75576    // stopWatching() should be a noop here but we call it just in case we
75577    // missed a blur event somehow.
75578    stopWatchingForValueChange();
75579    startWatchingForValueChange(target, targetInst);
75580  } else if (topLevelType === topLevelTypes.topBlur) {
75581    stopWatchingForValueChange();
75582  }
75583}
75584
75585// For IE8 and IE9.
75586function getTargetInstForInputEventIE(topLevelType, targetInst) {
75587  if (topLevelType === topLevelTypes.topSelectionChange || topLevelType === topLevelTypes.topKeyUp || topLevelType === topLevelTypes.topKeyDown) {
75588    // On the selectionchange event, the target is just document which isn't
75589    // helpful for us so just check activeElement instead.
75590    //
75591    // 99% of the time, keydown and keyup aren't necessary. IE8 fails to fire
75592    // propertychange on the first input event after setting `value` from a
75593    // script and fires only keydown, keypress, keyup. Catching keyup usually
75594    // gets it and catching keydown lets us fire an event for the first
75595    // keystroke if user does a key repeat (it'll be a little delayed: right
75596    // before the second keystroke). Other input methods (e.g., paste) seem to
75597    // fire selectionchange normally.
75598    if (activeElement && activeElement.value !== activeElementValue) {
75599      activeElementValue = activeElement.value;
75600      return activeElementInst;
75601    }
75602  }
75603}
75604
75605/**
75606 * SECTION: handle `click` event
75607 */
75608function shouldUseClickEvent(elem) {
75609  // Use the `click` event to detect changes to checkbox and radio inputs.
75610  // This approach works across all browsers, whereas `change` does not fire
75611  // until `blur` in IE8.
75612  return elem.nodeName && elem.nodeName.toLowerCase() === 'input' && (elem.type === 'checkbox' || elem.type === 'radio');
75613}
75614
75615function getTargetInstForClickEvent(topLevelType, targetInst) {
75616  if (topLevelType === topLevelTypes.topClick) {
75617    return targetInst;
75618  }
75619}
75620
75621/**
75622 * This plugin creates an `onChange` event that normalizes change events
75623 * across form elements. This event fires at a time when it's possible to
75624 * change the element's value without seeing a flicker.
75625 *
75626 * Supported elements are:
75627 * - input (see `isTextInputElement`)
75628 * - textarea
75629 * - select
75630 */
75631var ChangeEventPlugin = {
75632
75633  eventTypes: eventTypes,
75634
75635  extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
75636    var targetNode = targetInst ? ReactDOMComponentTree.getNodeFromInstance(targetInst) : window;
75637
75638    var getTargetInstFunc, handleEventFunc;
75639    if (shouldUseChangeEvent(targetNode)) {
75640      if (doesChangeEventBubble) {
75641        getTargetInstFunc = getTargetInstForChangeEvent;
75642      } else {
75643        handleEventFunc = handleEventsForChangeEventIE8;
75644      }
75645    } else if (isTextInputElement(targetNode)) {
75646      if (isInputEventSupported) {
75647        getTargetInstFunc = getTargetInstForInputEvent;
75648      } else {
75649        getTargetInstFunc = getTargetInstForInputEventIE;
75650        handleEventFunc = handleEventsForInputEventIE;
75651      }
75652    } else if (shouldUseClickEvent(targetNode)) {
75653      getTargetInstFunc = getTargetInstForClickEvent;
75654    }
75655
75656    if (getTargetInstFunc) {
75657      var inst = getTargetInstFunc(topLevelType, targetInst);
75658      if (inst) {
75659        var event = SyntheticEvent.getPooled(eventTypes.change, inst, nativeEvent, nativeEventTarget);
75660        event.type = 'change';
75661        EventPropagators.accumulateTwoPhaseDispatches(event);
75662        return event;
75663      }
75664    }
75665
75666    if (handleEventFunc) {
75667      handleEventFunc(topLevelType, targetNode, targetInst);
75668    }
75669  }
75670
75671};
75672
75673module.exports = ChangeEventPlugin;
75674},{"103":103,"126":126,"133":133,"134":134,"144":144,"16":16,"162":162,"17":17,"20":20,"40":40,"94":94}],7:[function(_dereq_,module,exports){
75675/**
75676 * Copyright 2013-present, Facebook, Inc.
75677 * All rights reserved.
75678 *
75679 * This source code is licensed under the BSD-style license found in the
75680 * LICENSE file in the root directory of this source tree. An additional grant
75681 * of patent rights can be found in the PATENTS file in the same directory.
75682 *
75683 * @providesModule DOMChildrenOperations
75684 */
75685
75686
75687
75688var DOMLazyTree = _dereq_(8);
75689var Danger = _dereq_(12);
75690var ReactMultiChildUpdateTypes = _dereq_(77);
75691var ReactPerf = _dereq_(82);
75692
75693var createMicrosoftUnsafeLocalFunction = _dereq_(117);
75694var setInnerHTML = _dereq_(138);
75695var setTextContent = _dereq_(139);
75696
75697function getNodeAfter(parentNode, node) {
75698  // Special case for text components, which return [open, close] comments
75699  // from getNativeNode.
75700  if (Array.isArray(node)) {
75701    node = node[1];
75702  }
75703  return node ? node.nextSibling : parentNode.firstChild;
75704}
75705
75706/**
75707 * Inserts `childNode` as a child of `parentNode` at the `index`.
75708 *
75709 * @param {DOMElement} parentNode Parent node in which to insert.
75710 * @param {DOMElement} childNode Child node to insert.
75711 * @param {number} index Index at which to insert the child.
75712 * @internal
75713 */
75714var insertChildAt = createMicrosoftUnsafeLocalFunction(function (parentNode, childNode, referenceNode) {
75715  // We rely exclusively on `insertBefore(node, null)` instead of also using
75716  // `appendChild(node)`. (Using `undefined` is not allowed by all browsers so
75717  // we are careful to use `null`.)
75718  parentNode.insertBefore(childNode, referenceNode);
75719});
75720
75721function insertLazyTreeChildAt(parentNode, childTree, referenceNode) {
75722  DOMLazyTree.insertTreeBefore(parentNode, childTree, referenceNode);
75723}
75724
75725function moveChild(parentNode, childNode, referenceNode) {
75726  if (Array.isArray(childNode)) {
75727    moveDelimitedText(parentNode, childNode[0], childNode[1], referenceNode);
75728  } else {
75729    insertChildAt(parentNode, childNode, referenceNode);
75730  }
75731}
75732
75733function removeChild(parentNode, childNode) {
75734  if (Array.isArray(childNode)) {
75735    var closingComment = childNode[1];
75736    childNode = childNode[0];
75737    removeDelimitedText(parentNode, childNode, closingComment);
75738    parentNode.removeChild(closingComment);
75739  }
75740  parentNode.removeChild(childNode);
75741}
75742
75743function moveDelimitedText(parentNode, openingComment, closingComment, referenceNode) {
75744  var node = openingComment;
75745  while (true) {
75746    var nextNode = node.nextSibling;
75747    insertChildAt(parentNode, node, referenceNode);
75748    if (node === closingComment) {
75749      break;
75750    }
75751    node = nextNode;
75752  }
75753}
75754
75755function removeDelimitedText(parentNode, startNode, closingComment) {
75756  while (true) {
75757    var node = startNode.nextSibling;
75758    if (node === closingComment) {
75759      // The closing comment is removed by ReactMultiChild.
75760      break;
75761    } else {
75762      parentNode.removeChild(node);
75763    }
75764  }
75765}
75766
75767function replaceDelimitedText(openingComment, closingComment, stringText) {
75768  var parentNode = openingComment.parentNode;
75769  var nodeAfterComment = openingComment.nextSibling;
75770  if (nodeAfterComment === closingComment) {
75771    // There are no text nodes between the opening and closing comments; insert
75772    // a new one if stringText isn't empty.
75773    if (stringText) {
75774      insertChildAt(parentNode, document.createTextNode(stringText), nodeAfterComment);
75775    }
75776  } else {
75777    if (stringText) {
75778      // Set the text content of the first node after the opening comment, and
75779      // remove all following nodes up until the closing comment.
75780      setTextContent(nodeAfterComment, stringText);
75781      removeDelimitedText(parentNode, nodeAfterComment, closingComment);
75782    } else {
75783      removeDelimitedText(parentNode, openingComment, closingComment);
75784    }
75785  }
75786}
75787
75788/**
75789 * Operations for updating with DOM children.
75790 */
75791var DOMChildrenOperations = {
75792
75793  dangerouslyReplaceNodeWithMarkup: Danger.dangerouslyReplaceNodeWithMarkup,
75794
75795  replaceDelimitedText: replaceDelimitedText,
75796
75797  /**
75798   * Updates a component's children by processing a series of updates. The
75799   * update configurations are each expected to have a `parentNode` property.
75800   *
75801   * @param {array<object>} updates List of update configurations.
75802   * @internal
75803   */
75804  processUpdates: function (parentNode, updates) {
75805    for (var k = 0; k < updates.length; k++) {
75806      var update = updates[k];
75807      switch (update.type) {
75808        case ReactMultiChildUpdateTypes.INSERT_MARKUP:
75809          insertLazyTreeChildAt(parentNode, update.content, getNodeAfter(parentNode, update.afterNode));
75810          break;
75811        case ReactMultiChildUpdateTypes.MOVE_EXISTING:
75812          moveChild(parentNode, update.fromNode, getNodeAfter(parentNode, update.afterNode));
75813          break;
75814        case ReactMultiChildUpdateTypes.SET_MARKUP:
75815          setInnerHTML(parentNode, update.content);
75816          break;
75817        case ReactMultiChildUpdateTypes.TEXT_CONTENT:
75818          setTextContent(parentNode, update.content);
75819          break;
75820        case ReactMultiChildUpdateTypes.REMOVE_NODE:
75821          removeChild(parentNode, update.fromNode);
75822          break;
75823      }
75824    }
75825  }
75826
75827};
75828
75829ReactPerf.measureMethods(DOMChildrenOperations, 'DOMChildrenOperations', {
75830  replaceDelimitedText: 'replaceDelimitedText'
75831});
75832
75833module.exports = DOMChildrenOperations;
75834},{"117":117,"12":12,"138":138,"139":139,"77":77,"8":8,"82":82}],8:[function(_dereq_,module,exports){
75835/**
75836 * Copyright 2015-present, Facebook, Inc.
75837 * All rights reserved.
75838 *
75839 * This source code is licensed under the BSD-style license found in the
75840 * LICENSE file in the root directory of this source tree. An additional grant
75841 * of patent rights can be found in the PATENTS file in the same directory.
75842 *
75843 * @providesModule DOMLazyTree
75844 */
75845
75846
75847
75848var createMicrosoftUnsafeLocalFunction = _dereq_(117);
75849var setTextContent = _dereq_(139);
75850
75851/**
75852 * In IE (8-11) and Edge, appending nodes with no children is dramatically
75853 * faster than appending a full subtree, so we essentially queue up the
75854 * .appendChild calls here and apply them so each node is added to its parent
75855 * before any children are added.
75856 *
75857 * In other browsers, doing so is slower or neutral compared to the other order
75858 * (in Firefox, twice as slow) so we only do this inversion in IE.
75859 *
75860 * See https://github.com/spicyj/innerhtml-vs-createelement-vs-clonenode.
75861 */
75862var enableLazy = typeof document !== 'undefined' && typeof document.documentMode === 'number' || typeof navigator !== 'undefined' && typeof navigator.userAgent === 'string' && /\bEdge\/\d/.test(navigator.userAgent);
75863
75864function insertTreeChildren(tree) {
75865  if (!enableLazy) {
75866    return;
75867  }
75868  var node = tree.node;
75869  var children = tree.children;
75870  if (children.length) {
75871    for (var i = 0; i < children.length; i++) {
75872      insertTreeBefore(node, children[i], null);
75873    }
75874  } else if (tree.html != null) {
75875    node.innerHTML = tree.html;
75876  } else if (tree.text != null) {
75877    setTextContent(node, tree.text);
75878  }
75879}
75880
75881var insertTreeBefore = createMicrosoftUnsafeLocalFunction(function (parentNode, tree, referenceNode) {
75882  // DocumentFragments aren't actually part of the DOM after insertion so
75883  // appending children won't update the DOM. We need to ensure the fragment
75884  // is properly populated first, breaking out of our lazy approach for just
75885  // this level.
75886  if (tree.node.nodeType === 11) {
75887    insertTreeChildren(tree);
75888    parentNode.insertBefore(tree.node, referenceNode);
75889  } else {
75890    parentNode.insertBefore(tree.node, referenceNode);
75891    insertTreeChildren(tree);
75892  }
75893});
75894
75895function replaceChildWithTree(oldNode, newTree) {
75896  oldNode.parentNode.replaceChild(newTree.node, oldNode);
75897  insertTreeChildren(newTree);
75898}
75899
75900function queueChild(parentTree, childTree) {
75901  if (enableLazy) {
75902    parentTree.children.push(childTree);
75903  } else {
75904    parentTree.node.appendChild(childTree.node);
75905  }
75906}
75907
75908function queueHTML(tree, html) {
75909  if (enableLazy) {
75910    tree.html = html;
75911  } else {
75912    tree.node.innerHTML = html;
75913  }
75914}
75915
75916function queueText(tree, text) {
75917  if (enableLazy) {
75918    tree.text = text;
75919  } else {
75920    setTextContent(tree.node, text);
75921  }
75922}
75923
75924function DOMLazyTree(node) {
75925  return {
75926    node: node,
75927    children: [],
75928    html: null,
75929    text: null
75930  };
75931}
75932
75933DOMLazyTree.insertTreeBefore = insertTreeBefore;
75934DOMLazyTree.replaceChildWithTree = replaceChildWithTree;
75935DOMLazyTree.queueChild = queueChild;
75936DOMLazyTree.queueHTML = queueHTML;
75937DOMLazyTree.queueText = queueText;
75938
75939module.exports = DOMLazyTree;
75940},{"117":117,"139":139}],9:[function(_dereq_,module,exports){
75941/**
75942 * Copyright 2013-present, Facebook, Inc.
75943 * All rights reserved.
75944 *
75945 * This source code is licensed under the BSD-style license found in the
75946 * LICENSE file in the root directory of this source tree. An additional grant
75947 * of patent rights can be found in the PATENTS file in the same directory.
75948 *
75949 * @providesModule DOMNamespaces
75950 */
75951
75952
75953
75954var DOMNamespaces = {
75955  html: 'http://www.w3.org/1999/xhtml',
75956  mathml: 'http://www.w3.org/1998/Math/MathML',
75957  svg: 'http://www.w3.org/2000/svg'
75958};
75959
75960module.exports = DOMNamespaces;
75961},{}],10:[function(_dereq_,module,exports){
75962/**
75963 * Copyright 2013-present, Facebook, Inc.
75964 * All rights reserved.
75965 *
75966 * This source code is licensed under the BSD-style license found in the
75967 * LICENSE file in the root directory of this source tree. An additional grant
75968 * of patent rights can be found in the PATENTS file in the same directory.
75969 *
75970 * @providesModule DOMProperty
75971 */
75972
75973
75974
75975var invariant = _dereq_(158);
75976
75977function checkMask(value, bitmask) {
75978  return (value & bitmask) === bitmask;
75979}
75980
75981var DOMPropertyInjection = {
75982  /**
75983   * Mapping from normalized, camelcased property names to a configuration that
75984   * specifies how the associated DOM property should be accessed or rendered.
75985   */
75986  MUST_USE_PROPERTY: 0x1,
75987  HAS_SIDE_EFFECTS: 0x2,
75988  HAS_BOOLEAN_VALUE: 0x4,
75989  HAS_NUMERIC_VALUE: 0x8,
75990  HAS_POSITIVE_NUMERIC_VALUE: 0x10 | 0x8,
75991  HAS_OVERLOADED_BOOLEAN_VALUE: 0x20,
75992
75993  /**
75994   * Inject some specialized knowledge about the DOM. This takes a config object
75995   * with the following properties:
75996   *
75997   * isCustomAttribute: function that given an attribute name will return true
75998   * if it can be inserted into the DOM verbatim. Useful for data-* or aria-*
75999   * attributes where it's impossible to enumerate all of the possible
76000   * attribute names,
76001   *
76002   * Properties: object mapping DOM property name to one of the
76003   * DOMPropertyInjection constants or null. If your attribute isn't in here,
76004   * it won't get written to the DOM.
76005   *
76006   * DOMAttributeNames: object mapping React attribute name to the DOM
76007   * attribute name. Attribute names not specified use the **lowercase**
76008   * normalized name.
76009   *
76010   * DOMAttributeNamespaces: object mapping React attribute name to the DOM
76011   * attribute namespace URL. (Attribute names not specified use no namespace.)
76012   *
76013   * DOMPropertyNames: similar to DOMAttributeNames but for DOM properties.
76014   * Property names not specified use the normalized name.
76015   *
76016   * DOMMutationMethods: Properties that require special mutation methods. If
76017   * `value` is undefined, the mutation method should unset the property.
76018   *
76019   * @param {object} domPropertyConfig the config as described above.
76020   */
76021  injectDOMPropertyConfig: function (domPropertyConfig) {
76022    var Injection = DOMPropertyInjection;
76023    var Properties = domPropertyConfig.Properties || {};
76024    var DOMAttributeNamespaces = domPropertyConfig.DOMAttributeNamespaces || {};
76025    var DOMAttributeNames = domPropertyConfig.DOMAttributeNames || {};
76026    var DOMPropertyNames = domPropertyConfig.DOMPropertyNames || {};
76027    var DOMMutationMethods = domPropertyConfig.DOMMutationMethods || {};
76028
76029    if (domPropertyConfig.isCustomAttribute) {
76030      DOMProperty._isCustomAttributeFunctions.push(domPropertyConfig.isCustomAttribute);
76031    }
76032
76033    for (var propName in Properties) {
76034      !!DOMProperty.properties.hasOwnProperty(propName) ? "development" !== 'production' ? invariant(false, 'injectDOMPropertyConfig(...): You\'re trying to inject DOM property ' + '\'%s\' which has already been injected. You may be accidentally ' + 'injecting the same DOM property config twice, or you may be ' + 'injecting two configs that have conflicting property names.', propName) : invariant(false) : void 0;
76035
76036      var lowerCased = propName.toLowerCase();
76037      var propConfig = Properties[propName];
76038
76039      var propertyInfo = {
76040        attributeName: lowerCased,
76041        attributeNamespace: null,
76042        propertyName: propName,
76043        mutationMethod: null,
76044
76045        mustUseProperty: checkMask(propConfig, Injection.MUST_USE_PROPERTY),
76046        hasSideEffects: checkMask(propConfig, Injection.HAS_SIDE_EFFECTS),
76047        hasBooleanValue: checkMask(propConfig, Injection.HAS_BOOLEAN_VALUE),
76048        hasNumericValue: checkMask(propConfig, Injection.HAS_NUMERIC_VALUE),
76049        hasPositiveNumericValue: checkMask(propConfig, Injection.HAS_POSITIVE_NUMERIC_VALUE),
76050        hasOverloadedBooleanValue: checkMask(propConfig, Injection.HAS_OVERLOADED_BOOLEAN_VALUE)
76051      };
76052
76053      !(propertyInfo.mustUseProperty || !propertyInfo.hasSideEffects) ? "development" !== 'production' ? invariant(false, 'DOMProperty: Properties that have side effects must use property: %s', propName) : invariant(false) : void 0;
76054      !(propertyInfo.hasBooleanValue + propertyInfo.hasNumericValue + propertyInfo.hasOverloadedBooleanValue <= 1) ? "development" !== 'production' ? invariant(false, 'DOMProperty: Value can be one of boolean, overloaded boolean, or ' + 'numeric value, but not a combination: %s', propName) : invariant(false) : void 0;
76055
76056      if ("development" !== 'production') {
76057        DOMProperty.getPossibleStandardName[lowerCased] = propName;
76058      }
76059
76060      if (DOMAttributeNames.hasOwnProperty(propName)) {
76061        var attributeName = DOMAttributeNames[propName];
76062        propertyInfo.attributeName = attributeName;
76063        if ("development" !== 'production') {
76064          DOMProperty.getPossibleStandardName[attributeName] = propName;
76065        }
76066      }
76067
76068      if (DOMAttributeNamespaces.hasOwnProperty(propName)) {
76069        propertyInfo.attributeNamespace = DOMAttributeNamespaces[propName];
76070      }
76071
76072      if (DOMPropertyNames.hasOwnProperty(propName)) {
76073        propertyInfo.propertyName = DOMPropertyNames[propName];
76074      }
76075
76076      if (DOMMutationMethods.hasOwnProperty(propName)) {
76077        propertyInfo.mutationMethod = DOMMutationMethods[propName];
76078      }
76079
76080      DOMProperty.properties[propName] = propertyInfo;
76081    }
76082  }
76083};
76084
76085/* eslint-disable max-len */
76086var ATTRIBUTE_NAME_START_CHAR = ':A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u
76086037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD';
76087/* eslint-enable max-len */
76088
76089/**
76090 * DOMProperty exports lookup objects that can be used like functions:
76091 *
76092 *   > DOMProperty.isValid['id']
76093 *   true
76094 *   > DOMProperty.isValid['foobar']
76095 *   undefined
76096 *
76097 * Although this may be confusing, it performs better in general.
76098 *
76099 * @see http://jsperf.com/key-exists
76100 * @see http://jsperf.com/key-missing
76101 */
76102var DOMProperty = {
76103
76104  ID_ATTRIBUTE_NAME: 'data-reactid',
76105  ROOT_ATTRIBUTE_NAME: 'data-reactroot',
76106
76107  ATTRIBUTE_NAME_START_CHAR: ATTRIBUTE_NAME_START_CHAR,
76108  ATTRIBUTE_NAME_CHAR: ATTRIBUTE_NAME_START_CHAR + '\\-.0-9\\uB7\\u0300-\\u036F\\u203F-\\u2040',
76109
76110  /**
76111   * Map from property "standard name" to an object with info about how to set
76112   * the property in the DOM. Each object contains:
76113   *
76114   * attributeName:
76115   *   Used when rendering markup or with `*Attribute()`.
76116   * attributeNamespace
76117   * propertyName:
76118   *   Used on DOM node instances. (This includes properties that mutate due to
76119   *   external factors.)
76120   * mutationMethod:
76121   *   If non-null, used instead of the property or `setAttribute()` after
76122   *   initial render.
76123   * mustUseProperty:
76124   *   Whether the property must be accessed and mutated as an object property.
76125   * hasSideEffects:
76126   *   Whether or not setting a value causes side effects such as triggering
76127   *   resources to be loaded or text selection changes. If true, we read from
76128   *   the DOM before updating to ensure that the value is only set if it has
76129   *   changed.
76130   * hasBooleanValue:
76131   *   Whether the property should be removed when set to a falsey value.
76132   * hasNumericValue:
76133   *   Whether the property must be numeric or parse as a numeric and should be
76134   *   removed when set to a falsey value.
76135   * hasPositiveNumericValue:
76136   *   Whether the property must be positive numeric or parse as a positive
76137   *   numeric and should be removed when set to a falsey value.
76138   * hasOverloadedBooleanValue:
76139   *   Whether the property can be used as a flag as well as with a value.
76140   *   Removed when strictly equal to false; present without a value when
76141   *   strictly equal to true; present with a value otherwise.
76142   */
76143  properties: {},
76144
76145  /**
76146   * Mapping from lowercase property names to the properly cased version, used
76147   * to warn in the case of missing properties. Available only in __DEV__.
76148   * @type {Object}
76149   */
76150  getPossibleStandardName: "development" !== 'production' ? {} : null,
76151
76152  /**
76153   * All of the isCustomAttribute() functions that have been injected.
76154   */
76155  _isCustomAttributeFunctions: [],
76156
76157  /**
76158   * Checks whether a property name is a custom attribute.
76159   * @method
76160   */
76161  isCustomAttribute: function (attributeName) {
76162    for (var i = 0; i < DOMProperty._isCustomAttributeFunctions.length; i++) {
76163      var isCustomAttributeFn = DOMProperty._isCustomAttributeFunctions[i];
76164      if (isCustomAttributeFn(attributeName)) {
76165        return true;
76166      }
76167    }
76168    return false;
76169  },
76170
76171  injection: DOMPropertyInjection
76172};
76173
76174module.exports = DOMProperty;
76175},{"158":158}],11:[function(_dereq_,module,exports){
76176/**
76177 * Copyright 2013-present, Facebook, Inc.
76178 * All rights reserved.
76179 *
76180 * This source code is licensed under the BSD-style license found in the
76181 * LICENSE file in the root directory of this source tree. An additional grant
76182 * of patent rights can be found in the PATENTS file in the same directory.
76183 *
76184 * @providesModule DOMPropertyOperations
76185 */
76186
76187
76188
76189var DOMProperty = _dereq_(10);
76190var ReactDOMInstrumentation = _dereq_(48);
76191var ReactPerf = _dereq_(82);
76192
76193var quoteAttributeValueForBrowser = _dereq_(136);
76194var warning = _dereq_(168);
76195
76196var VALID_ATTRIBUTE_NAME_REGEX = new RegExp('^[' + DOMProperty.ATTRIBUTE_NAME_START_CHAR + '][' + DOMProperty.ATTRIBUTE_NAME_CHAR + ']*$');
76197var illegalAttributeNameCache = {};
76198var validatedAttributeNameCache = {};
76199
76200function isAttributeNameSafe(attributeName) {
76201  if (validatedAttributeNameCache.hasOwnProperty(attributeName)) {
76202    return true;
76203  }
76204  if (illegalAttributeNameCache.hasOwnProperty(attributeName)) {
76205    return false;
76206  }
76207  if (VALID_ATTRIBUTE_NAME_REGEX.test(attributeName)) {
76208    validatedAttributeNameCache[attributeName] = true;
76209    return true;
76210  }
76211  illegalAttributeNameCache[attributeName] = true;
76212  "development" !== 'production' ? warning(false, 'Invalid attribute name: `%s`', attributeName) : void 0;
76213  return false;
76214}
76215
76216function shouldIgnoreValue(propertyInfo, value) {
76217  return value == null || propertyInfo.hasBooleanValue && !value || propertyInfo.hasNumericValue && isNaN(value) || propertyInfo.hasPositiveNumericValue && value < 1 || propertyInfo.hasOverloadedBooleanValue && value === false;
76218}
76219
76220/**
76221 * Operations for dealing with DOM properties.
76222 */
76223var DOMPropertyOperations = {
76224
76225  /**
76226   * Creates markup for the ID property.
76227   *
76228   * @param {string} id Unescaped ID.
76229   * @return {string} Markup string.
76230   */
76231  createMarkupForID: function (id) {
76232    return DOMProperty.ID_ATTRIBUTE_NAME + '=' + quoteAttributeValueForBrowser(id);
76233  },
76234
76235  setAttributeForID: function (node, id) {
76236    node.setAttribute(DOMProperty.ID_ATTRIBUTE_NAME, id);
76237  },
76238
76239  createMarkupForRoot: function () {
76240    return DOMProperty.ROOT_ATTRIBUTE_NAME + '=""';
76241  },
76242
76243  setAttributeForRoot: function (node) {
76244    node.setAttribute(DOMProperty.ROOT_ATTRIBUTE_NAME, '');
76245  },
76246
76247  /**
76248   * Creates markup for a property.
76249   *
76250   * @param {string} name
76251   * @param {*} value
76252   * @return {?string} Markup string, or null if the property was invalid.
76253   */
76254  createMarkupForProperty: function (name, value) {
76255    if ("development" !== 'production') {
76256      ReactDOMInstrumentation.debugTool.onCreateMarkupForProperty(name, value);
76257    }
76258    var propertyInfo = DOMProperty.properties.hasOwnProperty(name) ? DOMProperty.properties[name] : null;
76259    if (propertyInfo) {
76260      if (shouldIgnoreValue(propertyInfo, value)) {
76261        return '';
76262      }
76263      var attributeName = propertyInfo.attributeName;
76264      if (propertyInfo.hasBooleanValue || propertyInfo.hasOverloadedBooleanValue && value === true) {
76265        return attributeName + '=""';
76266      }
76267      return attributeName + '=' + quoteAttributeValueForBrowser(value);
76268    } else if (DOMProperty.isCustomAttribute(name)) {
76269      if (value == null) {
76270        return '';
76271      }
76272      return name + '=' + quoteAttributeValueForBrowser(value);
76273    }
76274    return null;
76275  },
76276
76277  /**
76278   * Creates markup for a custom property.
76279   *
76280   * @param {string} name
76281   * @param {*} value
76282   * @return {string} Markup string, or empty string if the property was invalid.
76283   */
76284  createMarkupForCustomAttribute: function (name, value) {
76285    if (!isAttributeNameSafe(name) || value == null) {
76286      return '';
76287    }
76288    return name + '=' + quoteAttributeValueForBrowser(value);
76289  },
76290
76291  /**
76292   * Sets the value for a property on a node.
76293   *
76294   * @param {DOMElement} node
76295   * @param {string} name
76296   * @param {*} value
76297   */
76298  setValueForProperty: function (node, name, value) {
76299    if ("development" !== 'production') {
76300      ReactDOMInstrumentation.debugTool.onSetValueForProperty(node, name, value);
76301    }
76302    var propertyInfo = DOMProperty.properties.hasOwnProperty(name) ? DOMProperty.properties[name] : null;
76303    if (propertyInfo) {
76304      var mutationMethod = propertyInfo.mutationMethod;
76305      if (mutationMethod) {
76306        mutationMethod(node, value);
76307      } else if (shouldIgnoreValue(propertyInfo, value)) {
76308        this.deleteValueForProperty(node, name);
76309      } else if (propertyInfo.mustUseProperty) {
76310        var propName = propertyInfo.propertyName;
76311        // Must explicitly cast values for HAS_SIDE_EFFECTS-properties to the
76312        // property type before comparing; only `value` does and is string.
76313        if (!propertyInfo.hasSideEffects || '' + node[propName] !== '' + value) {
76314          // Contrary to `setAttribute`, object properties are properly
76315          // `toString`ed by IE8/9.
76316          node[propName] = value;
76317        }
76318      } else {
76319        var attributeName = propertyInfo.attributeName;
76320        var namespace = propertyInfo.attributeNamespace;
76321        // `setAttribute` with objects becomes only `[object]` in IE8/9,
76322        // ('' + value) makes it output the correct toString()-value.
76323        if (namespace) {
76324          node.setAttributeNS(namespace, attributeName, '' + value);
76325        } else if (propertyInfo.hasBooleanValue || propertyInfo.hasOverloadedBooleanValue && value === true) {
76326          node.setAttribute(attributeName, '');
76327        } else {
76328          node.setAttribute(attributeName, '' + value);
76329        }
76330      }
76331    } else if (DOMProperty.isCustomAttribute(name)) {
76332      DOMPropertyOperations.setValueForAttribute(node, name, value);
76333    }
76334  },
76335
76336  setValueForAttribute: function (node, name, value) {
76337    if (!isAttributeNameSafe(name)) {
76338      return;
76339    }
76340    if (value == null) {
76341      node.removeAttribute(name);
76342    } else {
76343      node.setAttribute(name, '' + value);
76344    }
76345  },
76346
76347  /**
76348   * Deletes the value for a property on a node.
76349   *
76350   * @param {DOMElement} node
76351   * @param {string} name
76352   */
76353  deleteValueForProperty: function (node, name) {
76354    if ("development" !== 'production') {
76355      ReactDOMInstrumentation.debugTool.onDeleteValueForProperty(node, name);
76356    }
76357    var propertyInfo = DOMProperty.properties.hasOwnProperty(name) ? DOMProperty.properties[name] : null;
76358    if (propertyInfo) {
76359      var mutationMethod = propertyInfo.mutationMethod;
76360      if (mutationMethod) {
76361        mutationMethod(node, undefined);
76362      } else if (propertyInfo.mustUseProperty) {
76363        var propName = propertyInfo.propertyName;
76364        if (propertyInfo.hasBooleanValue) {
76365          // No HAS_SIDE_EFFECTS logic here, only `value` has it and is string.
76366          node[propName] = false;
76367        } else {
76368          if (!propertyInfo.hasSideEffects || '' + node[propName] !== '') {
76369            node[propName] = '';
76370          }
76371        }
76372      } else {
76373        node.removeAttribute(propertyInfo.attributeName);
76374      }
76375    } else if (DOMProperty.isCustomAttribute(name)) {
76376      node.removeAttribute(name);
76377    }
76378  }
76379
76380};
76381
76382ReactPerf.measureMethods(DOMPropertyOperations, 'DOMPropertyOperations', {
76383  setValueForProperty: 'setValueForProperty',
76384  setValueForAttribute: 'setValueForAttribute',
76385  deleteValueForProperty: 'deleteValueForProperty'
76386});
76387
76388module.exports = DOMPropertyOperations;
76389},{"10":10,"136":136,"168":168,"48":48,"82":82}],12:[function(_dereq_,module,exports){
76390/**
76391 * Copyright 2013-present, Facebook, Inc.
76392 * All rights reserved.
76393 *
76394 * This source code is licensed under the BSD-style license found in the
76395 * LICENSE file in the root directory of this source tree. An additional grant
76396 * of patent rights can be found in the PATENTS file in the same directory.
76397 *
76398 * @providesModule Danger
76399 */
76400
76401
76402
76403var DOMLazyTree = _dereq_(8);
76404var ExecutionEnvironment = _dereq_(144);
76405
76406var createNodesFromMarkup = _dereq_(149);
76407var emptyFunction = _dereq_(150);
76408var getMarkupWrap = _dereq_(154);
76409var invariant = _dereq_(158);
76410
76411var OPEN_TAG_NAME_EXP = /^(<[^ \/>]+)/;
76412var RESULT_INDEX_ATTR = 'data-danger-index';
76413
76414/**
76415 * Extracts the `nodeName` from a string of markup.
76416 *
76417 * NOTE: Extracting the `nodeName` does not require a regular expression match
76418 * because we make assumptions about React-generated markup (i.e. there are no
76419 * spaces surrounding the opening tag and there is at least one attribute).
76420 *
76421 * @param {string} markup String of markup.
76422 * @return {string} Node name of the supplied markup.
76423 * @see http://jsperf.com/extract-nodename
76424 */
76425function getNodeName(markup) {
76426  return markup.substring(1, markup.indexOf(' '));
76427}
76428
76429var Danger = {
76430
76431  /**
76432   * Renders markup into an array of nodes. The markup is expected to render
76433   * into a list of root nodes. Also, the length of `resultList` and
76434   * `markupList` should be the same.
76435   *
76436   * @param {array<string>} markupList List of markup strings to render.
76437   * @return {array<DOMElement>} List of rendered nodes.
76438   * @internal
76439   */
76440  dangerouslyRenderMarkup: function (markupList) {
76441    !ExecutionEnvironment.canUseDOM ? "development" !== 'production' ? invariant(false, 'dangerouslyRenderMarkup(...): Cannot render markup in a worker ' + 'thread. Make sure `window` and `document` are available globally ' + 'before requiring React when unit testing or use ' + 'ReactDOMServer.renderToString for server rendering.') : invariant(false) : void 0;
76442    var nodeName;
76443    var markupByNodeName = {};
76444    // Group markup by `nodeName` if a wrap is necessary, else by '*'.
76445    for (var i = 0; i < markupList.length; i++) {
76446      !markupList[i] ? "development" !== 'production' ? invariant(false, 'dangerouslyRenderMarkup(...): Missing markup.') : invariant(false) : void 0;
76447      nodeName = getNodeName(markupList[i]);
76448      nodeName = getMarkupWrap(nodeName) ? nodeName : '*';
76449      markupByNodeName[nodeName] = markupByNodeName[nodeName] || [];
76450      markupByNodeName[nodeName][i] = markupList[i];
76451    }
76452    var resultList = [];
76453    var resultListAssignmentCount = 0;
76454    for (nodeName in markupByNodeName) {
76455      if (!markupByNodeName.hasOwnProperty(nodeName)) {
76456        continue;
76457      }
76458      var markupListByNodeName = markupByNodeName[nodeName];
76459
76460      // This for-in loop skips the holes of the sparse array. The order of
76461      // iteration should follow the order of assignment, which happens to match
76462      // numerical index order, but we don't rely on that.
76463      var resultIndex;
76464      for (resultIndex in markupListByNodeName) {
76465        if (markupListByNodeName.hasOwnProperty(resultIndex)) {
76466          var markup = markupListByNodeName[resultIndex];
76467
76468          // Push the requested markup with an additional RESULT_INDEX_ATTR
76469          // attribute.  If the markup does not start with a < character, it
76470          // will be discarded below (with an appropriate console.error).
76471          markupListByNodeName[resultIndex] = markup.replace(OPEN_TAG_NAME_EXP,
76472          // This index will be parsed back out below.
76473          '$1 ' + RESULT_INDEX_ATTR + '="' + resultIndex + '" ');
76474        }
76475      }
76476
76477      // Render each group of markup with similar wrapping `nodeName`.
76478      var renderNodes = createNodesFromMarkup(markupListByNodeName.join(''), emptyFunction // Do nothing special with <script> tags.
76479      );
76480
76481      for (var j = 0; j < renderNodes.length; ++j) {
76482        var renderNode = renderNodes[j];
76483        if (renderNode.hasAttribute && renderNode.hasAttribute(RESULT_INDEX_ATTR)) {
76484
76485          resultIndex = +renderNode.getAttribute(RESULT_INDEX_ATTR);
76486          renderNode.removeAttribute(RESULT_INDEX_ATTR);
76487
76488          !!resultList.hasOwnProperty(resultIndex) ? "development" !== 'production' ? invariant(false, 'Danger: Assigning to an already-occupied result index.') : invariant(false) : void 0;
76489
76490          resultList[resultIndex] = renderNode;
76491
76492          // This should match resultList.length and markupList.length when
76493          // we're done.
76494          resultListAssignmentCount += 1;
76495        } else if ("development" !== 'production') {
76496          console.error('Danger: Discarding unexpected node:', renderNode);
76497        }
76498      }
76499    }
76500
76501    // Although resultList was populated out of order, it should now be a dense
76502    // array.
76503    !(resultListAssignmentCount === resultList.length) ? "development" !== 'production' ? invariant(false, 'Danger: Did not assign to every index of resultList.') : invariant(false) : void 0;
76504
76505    !(resultList.length === markupList.length) ? "development" !== 'production' ? invariant(false, 'Danger: Expected markup to render %s nodes, but rendered %s.', markupList.length, resultList.length) : invariant(false) : void 0;
76506
76507    return resultList;
76508  },
76509
76510  /**
76511   * Replaces a node with a string of markup at its current position within its
76512   * parent. The markup must render into a single root node.
76513   *
76514   * @param {DOMElement} oldChild Child node to replace.
76515   * @param {string} markup Markup to render in place of the child node.
76516   * @internal
76517   */
76518  dangerouslyReplaceNodeWithMarkup: function (oldChild, markup) {
76519    !ExecutionEnvironment.canUseDOM ? "development" !== 'production' ? invariant(false, 'dangerouslyReplaceNodeWithMarkup(...): Cannot render markup in a ' + 'worker thread. Make sure `window` and `document` are available ' + 'globally before requiring React when unit testing or use ' + 'ReactDOMServer.renderToString() for server rendering.') : invariant(false) : void 0;
76520    !markup ? "development" !== 'production' ? invariant(false, 'dangerouslyReplaceNodeWithMarkup(...): Missing markup.') : invariant(false) : void 0;
76521    !(oldChild.nodeName !== 'HTML') ? "development" !== 'production' ? invariant(false, 'dangerouslyReplaceNodeWithMarkup(...): Cannot replace markup of the ' + '<html> node. This is because browser quirks make this unreliable ' + 'and/or slow. If you want to render to the root you must use ' + 'server rendering. See ReactDOMServer.renderToString().') : invariant(false) : void 0;
76522
76523    if (typeof markup === 'string') {
76524      var newChild = createNodesFromMarkup(markup, emptyFunction)[0];
76525      oldChild.parentNode.replaceChild(newChild, oldChild);
76526    } else {
76527      DOMLazyTree.replaceChildWithTree(oldChild, markup);
76528    }
76529  }
76530
76531};
76532
76533module.exports = Danger;
76534},{"144":144,"149":149,"150":150,"154":154,"158":158,"8":8}],13:[function(_dereq_,module,exports){
76535/**
76536 * Copyright 2013-present, Facebook, Inc.
76537 * All rights reserved.
76538 *
76539 * This source code is licensed under the BSD-style license found in the
76540 * LICENSE file in the root directory of this source tree. An additional grant
76541 * of patent rights can be found in the PATENTS file in the same directory.
76542 *
76543 * @providesModule DefaultEventPluginOrder
76544 */
76545
76546
76547
76548var keyOf = _dereq_(162);
76549
76550/**
76551 * Module that is injectable into `EventPluginHub`, that specifies a
76552 * deterministic ordering of `EventPlugin`s. A convenient way to reason about
76553 * plugins, without having to package every one of them. This is better than
76554 * having plugins be ordered in the same order that they are injected because
76555 * that ordering would be influenced by the packaging order.
76556 * `ResponderEventPlugin` must occur before `SimpleEventPlugin` so that
76557 * preventing default on events is convenient in `SimpleEventPlugin` handlers.
76558 */
76559var DefaultEventPluginOrder = [keyOf({ ResponderEventPlugin: null }), keyOf({ SimpleEventPlugin: null }), keyOf({ TapEventPlugin: null }), keyOf({ EnterLeaveEventPlugin: null }), keyOf({ ChangeEventPlugin: null }), keyOf({ SelectEventPlugin: null }), keyOf({ BeforeInputEventPlugin: null })];
76560
76561module.exports = DefaultEventPluginOrder;
76562},{"162":162}],14:[function(_dereq_,module,exports){
76563/**
76564 * Copyright 2013-present, Facebook, Inc.
76565 * All rights reserved.
76566 *
76567 * This source code is licensed under the BSD-style license found in the
76568 * LICENSE file in the root directory of this source tree. An additional grant
76569 * of patent rights can be found in the PATENTS file in the same directory.
76570 *
76571 * @providesModule DisabledInputUtils
76572 */
76573
76574
76575
76576var disableableMouseListenerNames = {
76577  onClick: true,
76578  onDoubleClick: true,
76579  onMouseDown: true,
76580  onMouseMove: true,
76581  onMouseUp: true,
76582
76583  onClickCapture: true,
76584  onDoubleClickCapture: true,
76585  onMouseDownCapture: true,
76586  onMouseMoveCapture: true,
76587  onMouseUpCapture: true
76588};
76589
76590/**
76591 * Implements a native component that does not receive mouse events
76592 * when `disabled` is set.
76593 */
76594var DisabledInputUtils = {
76595  getNativeProps: function (inst, props) {
76596    if (!props.disabled) {
76597      return props;
76598    }
76599
76600    // Copy the props, except the mouse listeners
76601    var nativeProps = {};
76602    for (var key in props) {
76603      if (!disableableMouseListenerNames[key] && props.hasOwnProperty(key)) {
76604        nativeProps[key] = props[key];
76605      }
76606    }
76607
76608    return nativeProps;
76609  }
76610};
76611
76612module.exports = DisabledInputUtils;
76613},{}],15:[function(_dereq_,module,exports){
76614/**
76615 * Copyright 2013-present, Facebook, Inc.
76616 * All rights reserved.
76617 *
76618 * This source code is licensed under the BSD-style license found in the
76619 * LICENSE file in the root directory of this source tree. An additional grant
76620 * of patent rights can be found in the PATENTS file in the same directory.
76621 *
76622 * @providesModule EnterLeaveEventPlugin
76623 */
76624
76625
76626
76627var EventConstants = _dereq_(16);
76628var EventPropagators = _dereq_(20);
76629var ReactDOMComponentTree = _dereq_(40);
76630var SyntheticMouseEvent = _dereq_(107);
76631
76632var keyOf = _dereq_(162);
76633
76634var topLevelTypes = EventConstants.topLevelTypes;
76635
76636var eventTypes = {
76637  mouseEnter: {
76638    registrationName: keyOf({ onMouseEnter: null }),
76639    dependencies: [topLevelTypes.topMouseOut, topLevelTypes.topMouseOver]
76640  },
76641  mouseLeave: {
76642    registrationName: keyOf({ onMouseLeave: null }),
76643    dependencies: [topLevelTypes.topMouseOut, topLevelTypes.topMouseOver]
76644  }
76645};
76646
76647var EnterLeaveEventPlugin = {
76648
76649  eventTypes: eventTypes,
76650
76651  /**
76652   * For almost every interaction we care about, there will be both a top-level
76653   * `mouseover` and `mouseout` event that occurs. Only use `mouseout` so that
76654   * we do not extract duplicate events. However, moving the mouse into the
76655   * browser from outside will not fire a `mouseout` event. In this case, we use
76656   * the `mouseover` top-level event.
76657   */
76658  extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
76659    if (topLevelType === topLevelTypes.topMouseOver && (nativeEvent.relatedTarget || nativeEvent.fromElement)) {
76660      return null;
76661    }
76662    if (topLevelType !== topLevelTypes.topMouseOut && topLevelType !== topLevelTypes.topMouseOver) {
76663      // Must not be a mouse in or mouse out - ignoring.
76664      return null;
76665    }
76666
76667    var win;
76668    if (nativeEventTarget.window === nativeEventTarget) {
76669      // `nativeEventTarget` is probably a window object.
76670      win = nativeEventTarget;
76671    } else {
76672      // TODO: Figure out why `ownerDocument` is sometimes undefined in IE8.
76673      var doc = nativeEventTarget.ownerDocument;
76674      if (doc) {
76675        win = doc.defaultView || doc.parentWindow;
76676      } else {
76677        win = window;
76678      }
76679    }
76680
76681    var from;
76682    var to;
76683    if (topLevelType === topLevelTypes.topMouseOut) {
76684      from = targetInst;
76685      var related = nativeEvent.relatedTarget || nativeEvent.toElement;
76686      to = related ? ReactDOMComponentTree.getClosestInstanceFromNode(related) : null;
76687    } else {
76688      // Moving to a node from outside the window.
76689      from = null;
76690      to = targetInst;
76691    }
76692
76693    if (from === to) {
76694      // Nothing pertains to our managed components.
76695      return null;
76696    }
76697
76698    var fromNode = from == null ? win : ReactDOMComponentTree.getNodeFromInstance(from);
76699    var toNode = to == null ? win : ReactDOMComponentTree.getNodeFromInstance(to);
76700
76701    var leave = SyntheticMouseEvent.getPooled(eventTypes.mouseLeave, from, nativeEvent, nativeEventTarget);
76702    leave.type = 'mouseleave';
76703    leave.target = fromNode;
76704    leave.relatedTarget = toNode;
76705
76706    var enter = SyntheticMouseEvent.getPooled(eventTypes.mouseEnter, to, nativeEvent, nativeEventTarget);
76707    enter.type = 'mouseenter';
76708    enter.target = toNode;
76709    enter.relatedTarget = fromNode;
76710
76711    EventPropagators.accumulateEnterLeaveDispatches(leave, enter, from, to);
76712
76713    return [leave, enter];
76714  }
76715
76716};
76717
76718module.exports = EnterLeaveEventPlugin;
76719},{"107":107,"16":16,"162":162,"20":20,"40":40}],16:[function(_dereq_,module,exports){
76720/**
76721 * Copyright 2013-present, Facebook, Inc.
76722 * All rights reserved.
76723 *
76724 * This source code is licensed under the BSD-style license found in the
76725 * LICENSE file in the root directory of this source tree. An additional grant
76726 * of patent rights can be found in the PATENTS file in the same directory.
76727 *
76728 * @providesModule EventConstants
76729 */
76730
76731
76732
76733var keyMirror = _dereq_(161);
76734
76735var PropagationPhases = keyMirror({ bubbled: null, captured: null });
76736
76737/**
76738 * Types of raw signals from the browser caught at the top level.
76739 */
76740var topLevelTypes = keyMirror({
76741  topAbort: null,
76742  topAnimationEnd: null,
76743  topAnimationIteration: null,
76744  topAnimationStart: null,
76745  topBlur: null,
76746  topCanPlay: null,
76747  topCanPlayThrough: null,
76748  topChange: null,
76749  topClick: null,
76750  topCompositionEnd: null,
76751  topCompositionStart: null,
76752  topCompositionUpdate: null,
76753  topContextMenu: null,
76754  topCopy: null,
76755  topCut: null,
76756  topDoubleClick: null,
76757  topDrag: null,
76758  topDragEnd: null,
76759  topDragEnter: null,
76760  topDragExit: null,
76761  topDragLeave: null,
76762  topDragOver: null,
76763  topDragStart: null,
76764  topDrop: null,
76765  topDurationChange: null,
76766  topEmptied: null,
76767  topEncrypted: null,
76768  topEnded: null,
76769  topError: null,
76770  topFocus: null,
76771  topInput: null,
76772  topInvalid: null,
76773  topKeyDown: null,
76774  topKeyPress: null,
76775  topKeyUp: null,
76776  topLoad: null,
76777  topLoadedData: null,
76778  topLoadedMetadata: null,
76779  topLoadStart: null,
76780  topMouseDown: null,
76781  topMouseMove: null,
76782  topMouseOut: null,
76783  topMouseOver: null,
76784  topMouseUp: null,
76785  topPaste: null,
76786  topPause: null,
76787  topPlay: null,
76788  topPlaying: null,
76789  topProgress: null,
76790  topRateChange: null,
76791  topReset: null,
76792  topScroll: null,
76793  topSeeked: null,
76794  topSeeking: null,
76795  topSelectionChange: null,
76796  topStalled: null,
76797  topSubmit: null,
76798  topSuspend: null,
76799  topTextInput: null,
76800  topTimeUpdate: null,
76801  topTouchCancel: null,
76802  topTouchEnd: null,
76803  topTouchMove: null,
76804  topTouchStart: null,
76805  topTransitionEnd: null,
76806  topVolumeChange: null,
76807  topWaiting: null,
76808  topWheel: null
76809});
76810
76811var EventConstants = {
76812  topLevelTypes: topLevelTypes,
76813  PropagationPhases: PropagationPhases
76814};
76815
76816module.exports = EventConstants;
76817},{"161":161}],17:[function(_dereq_,module,exports){
76818/**
76819 * Copyright 2013-present, Facebook, Inc.
76820 * All rights reserved.
76821 *
76822 * This source code is licensed under the BSD-style license found in the
76823 * LICENSE file in the root directory of this source tree. An additional grant
76824 * of patent rights can be found in the PATENTS file in the same directory.
76825 *
76826 * @providesModule EventPluginHub
76827 */
76828
76829
76830
76831var EventPluginRegistry = _dereq_(18);
76832var EventPluginUtils = _dereq_(19);
76833var ReactErrorUtils = _dereq_(65);
76834
76835var accumulateInto = _dereq_(114);
76836var forEachAccumulated = _dereq_(122);
76837var invariant = _dereq_(158);
76838
76839/**
76840 * Internal store for event listeners
76841 */
76842var listenerBank = {};
76843
76844/**
76845 * Internal queue of events that have accumulated their dispatches and are
76846 * waiting to have their dispatches executed.
76847 */
76848var eventQueue = null;
76849
76850/**
76851 * Dispatches an event and releases it back into the pool, unless persistent.
76852 *
76853 * @param {?object} event Synthetic event to be dispatched.
76854 * @param {boolean} simulated If the event is simulated (changes exn behavior)
76855 * @private
76856 */
76857var executeDispatchesAndRelease = function (event, simulated) {
76858  if (event) {
76859    EventPluginUtils.executeDispatchesInOrder(event, simulated);
76860
76861    if (!event.isPersistent()) {
76862      event.constructor.release(event);
76863    }
76864  }
76865};
76866var executeDispatchesAndReleaseSimulated = function (e) {
76867  return executeDispatchesAndRelease(e, true);
76868};
76869var executeDispatchesAndReleaseTopLevel = function (e) {
76870  return executeDispatchesAndRelease(e, false);
76871};
76872
76873/**
76874 * This is a unified interface for event plugins to be installed and configured.
76875 *
76876 * Event plugins can implement the following properties:
76877 *
76878 *   `extractEvents` {function(string, DOMEventTarget, string, object): *}
76879 *     Required. When a top-level event is fired, this method is expected to
76880 *     extract synthetic events that will in turn be queued and dispatched.
76881 *
76882 *   `eventTypes` {object}
76883 *     Optional, plugins that fire events must publish a mapping of registration
76884 *     names that are used to register listeners. Values of this mapping must
76885 *     be objects that contain `registrationName` or `phasedRegistrationNames`.
76886 *
76887 *   `executeDispatch` {function(object, function, string)}
76888 *     Optional, allows plugins to override how an event gets dispatched. By
76889 *     default, the listener is simply invoked.
76890 *
76891 * Each plugin that is injected into `EventsPluginHub` is immediately operable.
76892 *
76893 * @public
76894 */
76895var EventPluginHub = {
76896
76897  /**
76898   * Methods for injecting dependencies.
76899   */
76900  injection: {
76901
76902    /**
76903     * @param {array} InjectedEventPluginOrder
76904     * @public
76905     */
76906    injectEventPluginOrder: EventPluginRegistry.injectEventPluginOrder,
76907
76908    /**
76909     * @param {object} injectedNamesToPlugins Map from names to plugin modules.
76910     */
76911    injectEventPluginsByName: EventPluginRegistry.injectEventPluginsByName
76912
76913  },
76914
76915  /**
76916   * Stores `listener` at `listenerBank[registrationName][id]`. Is idempotent.
76917   *
76918   * @param {object} inst The instance, which is the source of events.
76919   * @param {string} registrationName Name of listener (e.g. `onClick`).
76920   * @param {function} listener The callback to store.
76921   */
76922  putListener: function (inst, registrationName, listener) {
76923    !(typeof listener === 'function') ? "development" !== 'production' ? invariant(false, 'Expected %s listener to be a function, instead got type %s', registrationName, typeof listener) : invariant(false) : void 0;
76924
76925    var bankForRegistrationName = listenerBank[registrationName] || (listenerBank[registrationName] = {});
76926    bankForRegistrationName[inst._rootNodeID] = listener;
76927
76928    var PluginModule = EventPluginRegistry.registrationNameModules[registrationName];
76929    if (PluginModule && PluginModule.didPutListener) {
76930      PluginModule.didPutListener(inst, registrationName, listener);
76931    }
76932  },
76933
76934  /**
76935   * @param {object} inst The instance, which is the source of events.
76936   * @param {string} registrationName Name of listener (e.g. `onClick`).
76937   * @return {?function} The stored callback.
76938   */
76939  getListener: function (inst, registrationName) {
76940    var bankForRegistrationName = listenerBank[registrationName];
76941    return bankForRegistrationName && bankForRegistrationName[inst._rootNodeID];
76942  },
76943
76944  /**
76945   * Deletes a listener from the registration bank.
76946   *
76947   * @param {object} inst The instance, which is the source of events.
76948   * @param {string} registrationName Name of listener (e.g. `onClick`).
76949   */
76950  deleteListener: function (inst, registrationName) {
76951    var PluginModule = EventPluginRegistry.registrationNameModules[registrationName];
76952    if (PluginModule && PluginModule.willDeleteListener) {
76953      PluginModule.willDeleteListener(inst, registrationName);
76954    }
76955
76956    var bankForRegistrationName = listenerBank[registrationName];
76957    // TODO: This should never be null -- when is it?
76958    if (bankForRegistrationName) {
76959      delete bankForRegistrationName[inst._rootNodeID];
76960    }
76961  },
76962
76963  /**
76964   * Deletes all listeners for the DOM element with the supplied ID.
76965   *
76966   * @param {object} inst The instance, which is the source of events.
76967   */
76968  deleteAllListeners: function (inst) {
76969    for (var registrationName in listenerBank) {
76970      if (!listenerBank[registrationName][inst._rootNodeID]) {
76971        continue;
76972      }
76973
76974      var PluginModule = EventPluginRegistry.registrationNameModules[registrationName];
76975      if (PluginModule && PluginModule.willDeleteListener) {
76976        PluginModule.willDeleteListener(inst, registrationName);
76977      }
76978
76979      delete listenerBank[registrationName][inst._rootNodeID];
76980    }
76981  },
76982
76983  /**
76984   * Allows registered plugins an opportunity to extract events from top-level
76985   * native browser events.
76986   *
76987   * @return {*} An accumulation of synthetic events.
76988   * @internal
76989   */
76990  extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
76991    var events;
76992    var plugins = EventPluginRegistry.plugins;
76993    for (var i = 0; i < plugins.length; i++) {
76994      // Not every plugin in the ordering may be loaded at runtime.
76995      var possiblePlugin = plugins[i];
76996      if (possiblePlugin) {
76997        var extractedEvents = possiblePlugin.extractEvents(topLevelType, targetInst, nativeEvent, nativeEventTarget);
76998        if (extractedEvents) {
76999          events = accumulateInto(events, extractedEvents);
77000        }
77001      }
77002    }
77003    return events;
77004  },
77005
77006  /**
77007   * Enqueues a synthetic event that should be dispatched when
77008   * `processEventQueue` is invoked.
77009   *
77010   * @param {*} events An accumulation of synthetic events.
77011   * @internal
77012   */
77013  enqueueEvents: function (events) {
77014    if (events) {
77015      eventQueue = accumulateInto(eventQueue, events);
77016    }
77017  },
77018
77019  /**
77020   * Dispatches all synthetic events on the event queue.
77021   *
77022   * @internal
77023   */
77024  processEventQueue: function (simulated) {
77025    // Set `eventQueue` to null before processing it so that we can tell if more
77026    // events get enqueued while processing.
77027    var processingEventQueue = eventQueue;
77028    eventQueue = null;
77029    if (simulated) {
77030      forEachAccumulated(processingEventQueue, executeDispatchesAndReleaseSimulated);
77031    } else {
77032      forEachAccumulated(processingEventQueue, executeDispatchesAndReleaseTopLevel);
77033    }
77034    !!eventQueue ? "development" !== 'production' ? invariant(false, 'processEventQueue(): Additional events were enqueued while processing ' + 'an event queue. Support for this has not yet been implemented.') : invariant(false) : void 0;
77035    // This would be a good time to rethrow if any of the event handlers threw.
77036    ReactErrorUtils.rethrowCaughtError();
77037  },
77038
77039  /**
77040   * These are needed for tests only. Do not use!
77041   */
77042  __purge: function () {
77043    listenerBank = {};
77044  },
77045
77046  __getListenerBank: function () {
77047    return listenerBank;
77048  }
77049
77050};
77051
77052module.exports = EventPluginHub;
77053},{"114":114,"122":122,"158":158,"18":18,"19":19,"65":65}],18:[function(_dereq_,module,exports){
77054/**
77055 * Copyright 2013-present, Facebook, Inc.
77056 * All rights reserved.
77057 *
77058 * This source code is licensed under the BSD-style license found in the
77059 * LICENSE file in the root directory of this source tree. An additional grant
77060 * of patent rights can be found in the PATENTS file in the same directory.
77061 *
77062 * @providesModule EventPluginRegistry
77063 */
77064
77065
77066
77067var invariant = _dereq_(158);
77068
77069/**
77070 * Injectable ordering of event plugins.
77071 */
77072var EventPluginOrder = null;
77073
77074/**
77075 * Injectable mapping from names to event plugin modules.
77076 */
77077var namesToPlugins = {};
77078
77079/**
77080 * Recomputes the plugin list using the injected plugins and plugin ordering.
77081 *
77082 * @private
77083 */
77084function recomputePluginOrdering() {
77085  if (!EventPluginOrder) {
77086    // Wait until an `EventPluginOrder` is injected.
77087    return;
77088  }
77089  for (var pluginName in namesToPlugins) {
77090    var PluginModule = namesToPlugins[pluginName];
77091    var pluginIndex = EventPluginOrder.indexOf(pluginName);
77092    !(pluginIndex > -1) ? "development" !== 'production' ? invariant(false, 'EventPluginRegistry: Cannot inject event plugins that do not exist in ' + 'the plugin ordering, `%s`.', pluginName) : invariant(false) : void 0;
77093    if (EventPluginRegistry.plugins[pluginIndex]) {
77094      continue;
77095    }
77096    !PluginModule.extractEvents ? "development" !== 'production' ? invariant(false, 'EventPluginRegistry: Event plugins must implement an `extractEvents` ' + 'method, but `%s` does not.', pluginName) : invariant(false) : void 0;
77097    EventPluginRegistry.plugins[pluginIndex] = PluginModule;
77098    var publishedEvents = PluginModule.eventTypes;
77099    for (var eventName in publishedEvents) {
77100      !publishEventForPlugin(publishedEvents[eventName], PluginModule, eventName) ? "development" !== 'production' ? invariant(false, 'EventPluginRegistry: Failed to publish event `%s` for plugin `%s`.', eventName, pluginName) : invariant(false) : void 0;
77101    }
77102  }
77103}
77104
77105/**
77106 * Publishes an event so that it can be dispatched by the supplied plugin.
77107 *
77108 * @param {object} dispatchConfig Dispatch configuration for the event.
77109 * @param {object} PluginModule Plugin publishing the event.
77110 * @return {boolean} True if the event was successfully published.
77111 * @private
77112 */
77113function publishEventForPlugin(dispatchConfig, PluginModule, eventName) {
77114  !!EventPluginRegistry.eventNameDispatchConfigs.hasOwnProperty(eventName) ? "development" !== 'production' ? invariant(false, 'EventPluginHub: More than one plugin attempted to publish the same ' + 'event name, `%s`.', eventName) : invariant(false) : void 0;
77115  EventPluginRegistry.eventNameDispatchConfigs[eventName] = dispatchConfig;
77116
77117  var phasedRegistrationNames = dispatchConfig.phasedRegistrationNames;
77118  if (phasedRegistrationNames) {
77119    for (var phaseName in phasedRegistrationNames) {
77120      if (phasedRegistrationNames.hasOwnProperty(phaseName)) {
77121        var phasedRegistrationName = phasedRegistrationNames[phaseName];
77122        publishRegistrationName(phasedRegistrationName, PluginModule, eventName);
77123      }
77124    }
77125    return true;
77126  } else if (dispatchConfig.registrationName) {
77127    publishRegistrationName(dispatchConfig.registrationName, PluginModule, eventName);
77128    return true;
77129  }
77130  return false;
77131}
77132
77133/**
77134 * Publishes a registration name that is used to identify dispatched events and
77135 * can be used with `EventPluginHub.putListener` to register listeners.
77136 *
77137 * @param {string} registrationName Registration name to add.
77138 * @param {object} PluginModule Plugin publishing the event.
77139 * @private
77140 */
77141function publishRegistrationName(registrationName, PluginModule, eventName) {
77142  !!EventPluginRegistry.registrationNameModules[registrationName] ? "development" !== 'production' ? invariant(false, 'EventPluginHub: More than one plugin attempted to publish the same ' + 'registration name, `%s`.', registrationName) : invariant(false) : void 0;
77143  EventPluginRegistry.registrationNameModules[registrationName] = PluginModule;
77144  EventPluginRegistry.registrationNameDependencies[registrationName] = PluginModule.eventTypes[eventName].dependencies;
77145
77146  if ("development" !== 'production') {
77147    var lowerCasedName = registrationName.toLowerCase();
77148    EventPluginRegistry.possibleRegistrationNames[lowerCasedName] = registrationName;
77149  }
77150}
77151
77152/**
77153 * Registers plugins so that they can extract and dispatch events.
77154 *
77155 * @see {EventPluginHub}
77156 */
77157var EventPluginRegistry = {
77158
77159  /**
77160   * Ordered list of injected plugins.
77161   */
77162  plugins: [],
77163
77164  /**
77165   * Mapping from event name to dispatch config
77166   */
77167  eventNameDispatchConfigs: {},
77168
77169  /**
77170   * Mapping from registration name to plugin module
77171   */
77172  registrationNameModules: {},
77173
77174  /**
77175   * Mapping from registration name to event name
77176   */
77177  registrationNameDependencies: {},
77178
77179  /**
77180   * Mapping from lowercase registration names to the properly cased version,
77181   * used to warn in the case of missing event handlers. Available
77182   * only in __DEV__.
77183   * @type {Object}
77184   */
77185  possibleRegistrationNames: "development" !== 'production' ? {} : null,
77186
77187  /**
77188   * Injects an ordering of plugins (by plugin name). This allows the ordering
77189   * to be decoupled from injection of the actual plugins so that ordering is
77190   * always deterministic regardless of packaging, on-the-fly injection, etc.
77191   *
77192   * @param {array} InjectedEventPluginOrder
77193   * @internal
77194   * @see {EventPluginHub.injection.injectEventPluginOrder}
77195   */
77196  injectEventPluginOrder: function (InjectedEventPluginOrder) {
77197    !!EventPluginOrder ? "development" !== 'production' ? invariant(false, 'EventPluginRegistry: Cannot inject event plugin ordering more than ' + 'once. You are likely trying to load more than one copy of React.') : invariant(false) : void 0;
77198    // Clone the ordering so it cannot be dynamically mutated.
77199    EventPluginOrder = Array.prototype.slice.call(InjectedEventPluginOrder);
77200    recomputePluginOrdering();
77201  },
77202
77203  /**
77204   * Injects plugins to be used by `EventPluginHub`. The plugin names must be
77205   * in the ordering injected by `injectEventPluginOrder`.
77206   *
77207   * Plugins can be injected as part of page initialization or on-the-fly.
77208   *
77209   * @param {object} injectedNamesToPlugins Map from names to plugin modules.
77210   * @internal
77211   * @see {EventPluginHub.injection.injectEventPluginsByName}
77212   */
77213  injectEventPluginsByName: function (injectedNamesToPlugins) {
77214    var isOrderingDirty = false;
77215    for (var pluginName in injectedNamesToPlugins) {
77216      if (!injectedNamesToPlugins.hasOwnProperty(pluginName)) {
77217        continue;
77218      }
77219      var PluginModule = injectedNamesToPlugins[pluginName];
77220      if (!namesToPlugins.hasOwnProperty(pluginName) || namesToPlugins[pluginName] !== PluginModule) {
77221        !!namesToPlugins[pluginName] ? "development" !== 'production' ? invariant(false, 'EventPluginRegistry: Cannot inject two different event plugins ' + 'using the same name, `%s`.', pluginName) : invariant(false) : void 0;
77222        namesToPlugins[pluginName] = PluginModule;
77223        isOrderingDirty = true;
77224      }
77225    }
77226    if (isOrderingDirty) {
77227      recomputePluginOrdering();
77228    }
77229  },
77230
77231  /**
77232   * Looks up the plugin for the supplied event.
77233   *
77234   * @param {object} event A synthetic event.
77235   * @return {?object} The plugin that created the supplied event.
77236   * @internal
77237   */
77238  getPluginModuleForEvent: function (event) {
77239    var dispatchConfig = event.dispatchConfig;
77240    if (dispatchConfig.registrationName) {
77241      return EventPluginRegistry.registrationNameModules[dispatchConfig.registrationName] || null;
77242    }
77243    for (var phase in dispatchConfig.phasedRegistrationNames) {
77244      if (!dispatchConfig.phasedRegistrationNames.hasOwnProperty(phase)) {
77245        continue;
77246      }
77247      var PluginModule = EventPluginRegistry.registrationNameModules[dispatchConfig.phasedRegistrationNames[phase]];
77248      if (PluginModule) {
77249        return PluginModule;
77250      }
77251    }
77252    return null;
77253  },
77254
77255  /**
77256   * Exposed for unit testing.
77257   * @private
77258   */
77259  _resetEventPlugins: function () {
77260    EventPluginOrder = null;
77261    for (var pluginName in namesToPlugins) {
77262      if (namesToPlugins.hasOwnProperty(pluginName)) {
77263        delete namesToPlugins[pluginName];
77264      }
77265    }
77266    EventPluginRegistry.plugins.length = 0;
77267
77268    var eventNameDispatchConfigs = EventPluginRegistry.eventNameDispatchConfigs;
77269    for (var eventName in eventNameDispatchConfigs) {
77270      if (eventNameDispatchConfigs.hasOwnProperty(eventName)) {
77271        delete eventNameDispatchConfigs[eventName];
77272      }
77273    }
77274
77275    var registrationNameModules = EventPluginRegistry.registrationNameModules;
77276    for (var registrationName in registrationNameModules) {
77277      if (registrationNameModules.hasOwnProperty(registrationName)) {
77278        delete registrationNameModules[registrationName];
77279      }
77280    }
77281
77282    if ("development" !== 'production') {
77283      var possibleRegistrationNames = EventPluginRegistry.possibleRegistrationNames;
77284      for (var lowerCasedName in possibleRegistrationNames) {
77285        if (possibleRegistrationNames.hasOwnProperty(lowerCasedName)) {
77286          delete possibleRegistrationNames[lowerCasedName];
77287        }
77288      }
77289    }
77290  }
77291
77292};
77293
77294module.exports = EventPluginRegistry;
77295},{"158":158}],19:[function(_dereq_,module,exports){
77296/**
77297 * Copyright 2013-present, Facebook, Inc.
77298 * All rights reserved.
77299 *
77300 * This source code is licensed under the BSD-style license found in the
77301 * LICENSE file in the root directory of this source tree. An additional grant
77302 * of patent rights can be found in the PATENTS file in the same directory.
77303 *
77304 * @providesModule EventPluginUtils
77305 */
77306
77307
77308
77309var EventConstants = _dereq_(16);
77310var ReactErrorUtils = _dereq_(65);
77311
77312var invariant = _dereq_(158);
77313var warning = _dereq_(168);
77314
77315/**
77316 * Injected dependencies:
77317 */
77318
77319/**
77320 * - `ComponentTree`: [required] Module that can convert between React instances
77321 *   and actual node references.
77322 */
77323var ComponentTree;
77324var TreeTraversal;
77325var injection = {
77326  injectComponentTree: function (Injected) {
77327    ComponentTree = Injected;
77328    if ("development" !== 'production') {
77329      "development" !== 'production' ? warning(Injected && Injected.getNodeFromInstance && Injected.getInstanceFromNode, 'EventPluginUtils.injection.injectComponentTree(...): Injected ' + 'module is missing getNodeFromInstance or getInstanceFromNode.') : void 0;
77330    }
77331  },
77332  injectTreeTraversal: function (Injected) {
77333    TreeTraversal = Injected;
77334    if ("development" !== 'production') {
77335      "development" !== 'production' ? warning(Injected && Injected.isAncestor && Injected.getLowestCommonAncestor, 'EventPluginUtils.injection.injectTreeTraversal(...): Injected ' + 'module is missing isAncestor or getLowestCommonAncestor.') : void 0;
77336    }
77337  }
77338};
77339
77340var topLevelTypes = EventConstants.topLevelTypes;
77341
77342function isEndish(topLevelType) {
77343  return topLevelType === topLevelTypes.topMouseUp || topLevelType === topLevelTypes.topTouchEnd || topLevelType === topLevelTypes.topTouchCancel;
77344}
77345
77346function isMoveish(topLevelType) {
77347  return topLevelType === topLevelTypes.topMouseMove || topLevelType === topLevelTypes.topTouchMove;
77348}
77349function isStartish(topLevelType) {
77350  return topLevelType === topLevelTypes.topMouseDown || topLevelType === topLevelTypes.topTouchStart;
77351}
77352
77353var validateEventDispatches;
77354if ("development" !== 'production') {
77355  validateEventDispatches = function (event) {
77356    var dispatchListeners = event._dispatchListeners;
77357    var dispatchInstances = event._dispatchInstances;
77358
77359    var listenersIsArr = Array.isArray(dispatchListeners);
77360    var listenersLen = listenersIsArr ? dispatchListeners.length : dis
77360patchListeners ? 1 : 0;
77361
77362    var instancesIsArr = Array.isArray(dispatchInstances);
77363    var instancesLen = instancesIsArr ? dispatchInstances.length : dispatchInstances ? 1 : 0;
77364
77365    "development" !== 'production' ? warning(instancesIsArr === listenersIsArr && instancesLen === listenersLen, 'EventPluginUtils: Invalid `event`.') : void 0;
77366  };
77367}
77368
77369/**
77370 * Dispatch the event to the listener.
77371 * @param {SyntheticEvent} event SyntheticEvent to handle
77372 * @param {boolean} simulated If the event is simulated (changes exn behavior)
77373 * @param {function} listener Application-level callback
77374 * @param {*} inst Internal component instance
77375 */
77376function executeDispatch(event, simulated, listener, inst) {
77377  var type = event.type || 'unknown-event';
77378  event.currentTarget = EventPluginUtils.getNodeFromInstance(inst);
77379  if (simulated) {
77380    ReactErrorUtils.invokeGuardedCallbackWithCatch(type, listener, event);
77381  } else {
77382    ReactErrorUtils.invokeGuardedCallback(type, listener, event);
77383  }
77384  event.currentTarget = null;
77385}
77386
77387/**
77388 * Standard/simple iteration through an event's collected dispatches.
77389 */
77390function executeDispatchesInOrder(event, simulated) {
77391  var dispatchListeners = event._dispatchListeners;
77392  var dispatchInstances = event._dispatchInstances;
77393  if ("development" !== 'production') {
77394    validateEventDispatches(event);
77395  }
77396  if (Array.isArray(dispatchListeners)) {
77397    for (var i = 0; i < dispatchListeners.length; i++) {
77398      if (event.isPropagationStopped()) {
77399        break;
77400      }
77401      // Listeners and Instances are two parallel arrays that are always in sync.
77402      executeDispatch(event, simulated, dispatchListeners[i], dispatchInstances[i]);
77403    }
77404  } else if (dispatchListeners) {
77405    executeDispatch(event, simulated, dispatchListeners, dispatchInstances);
77406  }
77407  event._dispatchListeners = null;
77408  event._dispatchInstances = null;
77409}
77410
77411/**
77412 * Standard/simple iteration through an event's collected dispatches, but stops
77413 * at the first dispatch execution returning true, and returns that id.
77414 *
77415 * @return {?string} id of the first dispatch execution who's listener returns
77416 * true, or null if no listener returned true.
77417 */
77418function executeDispatchesInOrderStopAtTrueImpl(event) {
77419  var dispatchListeners = event._dispatchListeners;
77420  var dispatchInstances = event._dispatchInstances;
77421  if ("development" !== 'production') {
77422    validateEventDispatches(event);
77423  }
77424  if (Array.isArray(dispatchListeners)) {
77425    for (var i = 0; i < dispatchListeners.length; i++) {
77426      if (event.isPropagationStopped()) {
77427        break;
77428      }
77429      // Listeners and Instances are two parallel arrays that are always in sync.
77430      if (dispatchListeners[i](event, dispatchInstances[i])) {
77431        return dispatchInstances[i];
77432      }
77433    }
77434  } else if (dispatchListeners) {
77435    if (dispatchListeners(event, dispatchInstances)) {
77436      return dispatchInstances;
77437    }
77438  }
77439  return null;
77440}
77441
77442/**
77443 * @see executeDispatchesInOrderStopAtTrueImpl
77444 */
77445function executeDispatchesInOrderStopAtTrue(event) {
77446  var ret = executeDispatchesInOrderStopAtTrueImpl(event);
77447  event._dispatchInstances = null;
77448  event._dispatchListeners = null;
77449  return ret;
77450}
77451
77452/**
77453 * Execution of a "direct" dispatch - there must be at most one dispatch
77454 * accumulated on the event or it is considered an error. It doesn't really make
77455 * sense for an event with multiple dispatches (bubbled) to keep track of the
77456 * return values at each dispatch execution, but it does tend to make sense when
77457 * dealing with "direct" dispatches.
77458 *
77459 * @return {*} The return value of executing the single dispatch.
77460 */
77461function executeDirectDispatch(event) {
77462  if ("development" !== 'production') {
77463    validateEventDispatches(event);
77464  }
77465  var dispatchListener = event._dispatchListeners;
77466  var dispatchInstance = event._dispatchInstances;
77467  !!Array.isArray(dispatchListener) ? "development" !== 'production' ? invariant(false, 'executeDirectDispatch(...): Invalid `event`.') : invariant(false) : void 0;
77468  event.currentTarget = dispatchListener ? EventPluginUtils.getNodeFromInstance(dispatchInstance) : null;
77469  var res = dispatchListener ? dispatchListener(event) : null;
77470  event.currentTarget = null;
77471  event._dispatchListeners = null;
77472  event._dispatchInstances = null;
77473  return res;
77474}
77475
77476/**
77477 * @param {SyntheticEvent} event
77478 * @return {boolean} True iff number of dispatches accumulated is greater than 0.
77479 */
77480function hasDispatches(event) {
77481  return !!event._dispatchListeners;
77482}
77483
77484/**
77485 * General utilities that are useful in creating custom Event Plugins.
77486 */
77487var EventPluginUtils = {
77488  isEndish: isEndish,
77489  isMoveish: isMoveish,
77490  isStartish: isStartish,
77491
77492  executeDirectDispatch: executeDirectDispatch,
77493  executeDispatchesInOrder: executeDispatchesInOrder,
77494  executeDispatchesInOrderStopAtTrue: executeDispatchesInOrderStopAtTrue,
77495  hasDispatches: hasDispatches,
77496
77497  getInstanceFromNode: function (node) {
77498    return ComponentTree.getInstanceFromNode(node);
77499  },
77500  getNodeFromInstance: function (node) {
77501    return ComponentTree.getNodeFromInstance(node);
77502  },
77503  isAncestor: function (a, b) {
77504    return TreeTraversal.isAncestor(a, b);
77505  },
77506  getLowestCommonAncestor: function (a, b) {
77507    return TreeTraversal.getLowestCommonAncestor(a, b);
77508  },
77509  getParentInstance: function (inst) {
77510    return TreeTraversal.getParentInstance(inst);
77511  },
77512  traverseTwoPhase: function (target, fn, arg) {
77513    return TreeTraversal.traverseTwoPhase(target, fn, arg);
77514  },
77515  traverseEnterLeave: function (from, to, fn, argFrom, argTo) {
77516    return TreeTraversal.traverseEnterLeave(from, to, fn, argFrom, argTo);
77517  },
77518
77519  injection: injection
77520};
77521
77522module.exports = EventPluginUtils;
77523},{"158":158,"16":16,"168":168,"65":65}],20:[function(_dereq_,module,exports){
77524/**
77525 * Copyright 2013-present, Facebook, Inc.
77526 * All rights reserved.
77527 *
77528 * This source code is licensed under the BSD-style license found in the
77529 * LICENSE file in the root directory of this source tree. An additional grant
77530 * of patent rights can be found in the PATENTS file in the same directory.
77531 *
77532 * @providesModule EventPropagators
77533 */
77534
77535
77536
77537var EventConstants = _dereq_(16);
77538var EventPluginHub = _dereq_(17);
77539var EventPluginUtils = _dereq_(19);
77540
77541var accumulateInto = _dereq_(114);
77542var forEachAccumulated = _dereq_(122);
77543var warning = _dereq_(168);
77544
77545var PropagationPhases = EventConstants.PropagationPhases;
77546var getListener = EventPluginHub.getListener;
77547
77548/**
77549 * Some event types have a notion of different registration names for different
77550 * "phases" of propagation. This finds listeners by a given phase.
77551 */
77552function listenerAtPhase(inst, event, propagationPhase) {
77553  var registrationName = event.dispatchConfig.phasedRegistrationNames[propagationPhase];
77554  return getListener(inst, registrationName);
77555}
77556
77557/**
77558 * Tags a `SyntheticEvent` with dispatched listeners. Creating this function
77559 * here, allows us to not have to bind or create functions for each event.
77560 * Mutating the event's members allows us to not have to create a wrapping
77561 * "dispatch" object that pairs the event with the listener.
77562 */
77563function accumulateDirectionalDispatches(inst, upwards, event) {
77564  if ("development" !== 'production') {
77565    "development" !== 'production' ? warning(inst, 'Dispatching inst must not be null') : void 0;
77566  }
77567  var phase = upwards ? PropagationPhases.bubbled : PropagationPhases.captured;
77568  var listener = listenerAtPhase(inst, event, phase);
77569  if (listener) {
77570    event._dispatchListeners = accumulateInto(event._dispatchListeners, listener);
77571    event._dispatchInstances = accumulateInto(event._dispatchInstances, inst);
77572  }
77573}
77574
77575/**
77576 * Collect dispatches (must be entirely collected before dispatching - see unit
77577 * tests). Lazily allocate the array to conserve memory.  We must loop through
77578 * each event and perform the traversal for each one. We cannot perform a
77579 * single traversal for the entire collection of events because each event may
77580 * have a different target.
77581 */
77582function accumulateTwoPhaseDispatchesSingle(event) {
77583  if (event && event.dispatchConfig.phasedRegistrationNames) {
77584    EventPluginUtils.traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event);
77585  }
77586}
77587
77588/**
77589 * Same as `accumulateTwoPhaseDispatchesSingle`, but skips over the targetID.
77590 */
77591function accumulateTwoPhaseDispatchesSingleSkipTarget(event) {
77592  if (event && event.dispatchConfig.phasedRegistrationNames) {
77593    var targetInst = event._targetInst;
77594    var parentInst = targetInst ? EventPluginUtils.getParentInstance(targetInst) : null;
77595    EventPluginUtils.traverseTwoPhase(parentInst, accumulateDirectionalDispatches, event);
77596  }
77597}
77598
77599/**
77600 * Accumulates without regard to direction, does not look for phased
77601 * registration names. Same as `accumulateDirectDispatchesSingle` but without
77602 * requiring that the `dispatchMarker` be the same as the dispatched ID.
77603 */
77604function accumulateDispatches(inst, ignoredDirection, event) {
77605  if (event && event.dispatchConfig.registrationName) {
77606    var registrationName = event.dispatchConfig.registrationName;
77607    var listener = getListener(inst, registrationName);
77608    if (listener) {
77609      event._dispatchListeners = accumulateInto(event._dispatchListeners, listener);
77610      event._dispatchInstances = accumulateInto(event._dispatchInstances, inst);
77611    }
77612  }
77613}
77614
77615/**
77616 * Accumulates dispatches on an `SyntheticEvent`, but only for the
77617 * `dispatchMarker`.
77618 * @param {SyntheticEvent} event
77619 */
77620function accumulateDirectDispatchesSingle(event) {
77621  if (event && event.dispatchConfig.registrationName) {
77622    accumulateDispatches(event._targetInst, null, event);
77623  }
77624}
77625
77626function accumulateTwoPhaseDispatches(events) {
77627  forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle);
77628}
77629
77630function accumulateTwoPhaseDispatchesSkipTarget(events) {
77631  forEachAccumulated(events, accumulateTwoPhaseDispatchesSingleSkipTarget);
77632}
77633
77634function accumulateEnterLeaveDispatches(leave, enter, from, to) {
77635  EventPluginUtils.traverseEnterLeave(from, to, accumulateDispatches, leave, enter);
77636}
77637
77638function accumulateDirectDispatches(events) {
77639  forEachAccumulated(events, accumulateDirectDispatchesSingle);
77640}
77641
77642/**
77643 * A small set of propagation patterns, each of which will accept a small amount
77644 * of information, and generate a set of "dispatch ready event objects" - which
77645 * are sets of events that have already been annotated with a set of dispatched
77646 * listener functions/ids. The API is designed this way to discourage these
77647 * propagation strategies from actually executing the dispatches, since we
77648 * always want to collect the entire set of dispatches before executing event a
77649 * single one.
77650 *
77651 * @constructor EventPropagators
77652 */
77653var EventPropagators = {
77654  accumulateTwoPhaseDispatches: accumulateTwoPhaseDispatches,
77655  accumulateTwoPhaseDispatchesSkipTarget: accumulateTwoPhaseDispatchesSkipTarget,
77656  accumulateDirectDispatches: accumulateDirectDispatches,
77657  accumulateEnterLeaveDispatches: accumulateEnterLeaveDispatches
77658};
77659
77660module.exports = EventPropagators;
77661},{"114":114,"122":122,"16":16,"168":168,"17":17,"19":19}],21:[function(_dereq_,module,exports){
77662/**
77663 * Copyright 2013-present, Facebook, Inc.
77664 * All rights reserved.
77665 *
77666 * This source code is licensed under the BSD-style license found in the
77667 * LICENSE file in the root directory of this source tree. An additional grant
77668 * of patent rights can be found in the PATENTS file in the same directory.
77669 *
77670 * @providesModule FallbackCompositionState
77671 */
77672
77673
77674
77675var _assign = _dereq_(169);
77676
77677var PooledClass = _dereq_(25);
77678
77679var getTextContentAccessor = _dereq_(130);
77680
77681/**
77682 * This helper class stores information about text content of a target node,
77683 * allowing comparison of content before and after a given event.
77684 *
77685 * Identify the node where selection currently begins, then observe
77686 * both its text content and its current position in the DOM. Since the
77687 * browser may natively replace the target node during composition, we can
77688 * use its position to find its replacement.
77689 *
77690 * @param {DOMEventTarget} root
77691 */
77692function FallbackCompositionState(root) {
77693  this._root = root;
77694  this._startText = this.getText();
77695  this._fallbackText = null;
77696}
77697
77698_assign(FallbackCompositionState.prototype, {
77699  destructor: function () {
77700    this._root = null;
77701    this._startText = null;
77702    this._fallbackText = null;
77703  },
77704
77705  /**
77706   * Get current text of input.
77707   *
77708   * @return {string}
77709   */
77710  getText: function () {
77711    if ('value' in this._root) {
77712      return this._root.value;
77713    }
77714    return this._root[getTextContentAccessor()];
77715  },
77716
77717  /**
77718   * Determine the differing substring between the initially stored
77719   * text content and the current content.
77720   *
77721   * @return {string}
77722   */
77723  getData: function () {
77724    if (this._fallbackText) {
77725      return this._fallbackText;
77726    }
77727
77728    var start;
77729    var startValue = this._startText;
77730    var startLength = startValue.length;
77731    var end;
77732    var endValue = this.getText();
77733    var endLength = endValue.length;
77734
77735    for (start = 0; start < startLength; start++) {
77736      if (startValue[start] !== endValue[start]) {
77737        break;
77738      }
77739    }
77740
77741    var minEnd = startLength - start;
77742    for (end = 1; end <= minEnd; end++) {
77743      if (startValue[startLength - end] !== endValue[endLength - end]) {
77744        break;
77745      }
77746    }
77747
77748    var sliceTail = end > 1 ? 1 - end : undefined;
77749    this._fallbackText = endValue.slice(start, sliceTail);
77750    return this._fallbackText;
77751  }
77752});
77753
77754PooledClass.addPoolingTo(FallbackCompositionState);
77755
77756module.exports = FallbackCompositionState;
77757},{"130":130,"169":169,"25":25}],22:[function(_dereq_,module,exports){
77758/**
77759 * Copyright 2013-present, Facebook, Inc.
77760 * All rights reserved.
77761 *
77762 * This source code is licensed under the BSD-style license found in the
77763 * LICENSE file in the root directory of this source tree. An additional grant
77764 * of patent rights can be found in the PATENTS file in the same directory.
77765 *
77766 * @providesModule HTMLDOMPropertyConfig
77767 */
77768
77769
77770
77771var DOMProperty = _dereq_(10);
77772
77773var MUST_USE_PROPERTY = DOMProperty.injection.MUST_USE_PROPERTY;
77774var HAS_BOOLEAN_VALUE = DOMProperty.injection.HAS_BOOLEAN_VALUE;
77775var HAS_SIDE_EFFECTS = DOMProperty.injection.HAS_SIDE_EFFECTS;
77776var HAS_NUMERIC_VALUE = DOMProperty.injection.HAS_NUMERIC_VALUE;
77777var HAS_POSITIVE_NUMERIC_VALUE = DOMProperty.injection.HAS_POSITIVE_NUMERIC_VALUE;
77778var HAS_OVERLOADED_BOOLEAN_VALUE = DOMProperty.injection.HAS_OVERLOADED_BOOLEAN_VALUE;
77779
77780var HTMLDOMPropertyConfig = {
77781  isCustomAttribute: RegExp.prototype.test.bind(new RegExp('^(data|aria)-[' + DOMProperty.ATTRIBUTE_NAME_CHAR + ']*$')),
77782  Properties: {
77783    /**
77784     * Standard Properties
77785     */
77786    accept: 0,
77787    acceptCharset: 0,
77788    accessKey: 0,
77789    action: 0,
77790    allowFullScreen: HAS_BOOLEAN_VALUE,
77791    allowTransparency: 0,
77792    alt: 0,
77793    async: HAS_BOOLEAN_VALUE,
77794    autoComplete: 0,
77795    // autoFocus is polyfilled/normalized by AutoFocusUtils
77796    // autoFocus: HAS_BOOLEAN_VALUE,
77797    autoPlay: HAS_BOOLEAN_VALUE,
77798    capture: HAS_BOOLEAN_VALUE,
77799    cellPadding: 0,
77800    cellSpacing: 0,
77801    charSet: 0,
77802    challenge: 0,
77803    checked: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
77804    cite: 0,
77805    classID: 0,
77806    className: 0,
77807    cols: HAS_POSITIVE_NUMERIC_VALUE,
77808    colSpan: 0,
77809    content: 0,
77810    contentEditable: 0,
77811    contextMenu: 0,
77812    controls: HAS_BOOLEAN_VALUE,
77813    coords: 0,
77814    crossOrigin: 0,
77815    data: 0, // For `<object />` acts as `src`.
77816    dateTime: 0,
77817    'default': HAS_BOOLEAN_VALUE,
77818    defer: HAS_BOOLEAN_VALUE,
77819    dir: 0,
77820    disabled: HAS_BOOLEAN_VALUE,
77821    download: HAS_OVERLOADED_BOOLEAN_VALUE,
77822    draggable: 0,
77823    encType: 0,
77824    form: 0,
77825    formAction: 0,
77826    formEncType: 0,
77827    formMethod: 0,
77828    formNoValidate: HAS_BOOLEAN_VALUE,
77829    formTarget: 0,
77830    frameBorder: 0,
77831    headers: 0,
77832    height: 0,
77833    hidden: HAS_BOOLEAN_VALUE,
77834    high: 0,
77835    href: 0,
77836    hrefLang: 0,
77837    htmlFor: 0,
77838    httpEquiv: 0,
77839    icon: 0,
77840    id: 0,
77841    inputMode: 0,
77842    integrity: 0,
77843    is: 0,
77844    keyParams: 0,
77845    keyType: 0,
77846    kind: 0,
77847    label: 0,
77848    lang: 0,
77849    list: 0,
77850    loop: HAS_BOOLEAN_VALUE,
77851    low: 0,
77852    manifest: 0,
77853    marginHeight: 0,
77854    marginWidth: 0,
77855    max: 0,
77856    maxLength: 0,
77857    media: 0,
77858    mediaGroup: 0,
77859    method: 0,
77860    min: 0,
77861    minLength: 0,
77862    // Caution; `option.selected` is not updated if `select.multiple` is
77863    // disabled with `removeAttribute`.
77864    multiple: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
77865    muted: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
77866    name: 0,
77867    nonce: 0,
77868    noValidate: HAS_BOOLEAN_VALUE,
77869    open: HAS_BOOLEAN_VALUE,
77870    optimum: 0,
77871    pattern: 0,
77872    placeholder: 0,
77873    poster: 0,
77874    preload: 0,
77875    profile: 0,
77876    radioGroup: 0,
77877    readOnly: HAS_BOOLEAN_VALUE,
77878    rel: 0,
77879    required: HAS_BOOLEAN_VALUE,
77880    reversed: HAS_BOOLEAN_VALUE,
77881    role: 0,
77882    rows: HAS_POSITIVE_NUMERIC_VALUE,
77883    rowSpan: HAS_NUMERIC_VALUE,
77884    sandbox: 0,
77885    scope: 0,
77886    scoped: HAS_BOOLEAN_VALUE,
77887    scrolling: 0,
77888    seamless: HAS_BOOLEAN_VALUE,
77889    selected: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
77890    shape: 0,
77891    size: HAS_POSITIVE_NUMERIC_VALUE,
77892    sizes: 0,
77893    span: HAS_POSITIVE_NUMERIC_VALUE,
77894    spellCheck: 0,
77895    src: 0,
77896    srcDoc: 0,
77897    srcLang: 0,
77898    srcSet: 0,
77899    start: HAS_NUMERIC_VALUE,
77900    step: 0,
77901    style: 0,
77902    summary: 0,
77903    tabIndex: 0,
77904    target: 0,
77905    title: 0,
77906    // Setting .type throws on non-<input> tags
77907    type: 0,
77908    useMap: 0,
77909    value: MUST_USE_PROPERTY | HAS_SIDE_EFFECTS,
77910    width: 0,
77911    wmode: 0,
77912    wrap: 0,
77913
77914    /**
77915     * RDFa Properties
77916     */
77917    about: 0,
77918    datatype: 0,
77919    inlist: 0,
77920    prefix: 0,
77921    // property is also supported for OpenGraph in meta tags.
77922    property: 0,
77923    resource: 0,
77924    'typeof': 0,
77925    vocab: 0,
77926
77927    /**
77928     * Non-standard Properties
77929     */
77930    // autoCapitalize and autoCorrect are supported in Mobile Safari for
77931    // keyboard hints.
77932    autoCapitalize: 0,
77933    autoCorrect: 0,
77934    // autoSave allows WebKit/Blink to persist values of input fields on page reloads
77935    autoSave: 0,
77936    // color is for Safari mask-icon link
77937    color: 0,
77938    // itemProp, itemScope, itemType are for
77939    // Microdata support. See http://schema.org/docs/gs.html
77940    itemProp: 0,
77941    itemScope: HAS_BOOLEAN_VALUE,
77942    itemType: 0,
77943    // itemID and itemRef are for Microdata support as well but
77944    // only specified in the WHATWG spec document. See
77945    // https://html.spec.whatwg.org/multipage/microdata.html#microdata-dom-api
77946    itemID: 0,
77947    itemRef: 0,
77948    // results show looking glass icon and recent searches on input
77949    // search fields in WebKit/Blink
77950    results: 0,
77951    // IE-only attribute that specifies security restrictions on an iframe
77952    // as an alternative to the sandbox attribute on IE<10
77953    security: 0,
77954    // IE-only attribute that controls focus behavior
77955    unselectable: 0
77956  },
77957  DOMAttributeNames: {
77958    acceptCharset: 'accept-charset',
77959    className: 'class',
77960    htmlFor: 'for',
77961    httpEquiv: 'http-equiv'
77962  },
77963  DOMPropertyNames: {}
77964};
77965
77966module.exports = HTMLDOMPropertyConfig;
77967},{"10":10}],23:[function(_dereq_,module,exports){
77968/**
77969 * Copyright 2013-present, Facebook, Inc.
77970 * All rights reserved.
77971 *
77972 * This source code is licensed under the BSD-style license found in the
77973 * LICENSE file in the root directory of this source tree. An additional grant
77974 * of patent rights can be found in the PATENTS file in the same directory.
77975 *
77976 * @providesModule KeyEscapeUtils
77977 */
77978
77979
77980
77981/**
77982 * Escape and wrap key so it is safe to use as a reactid
77983 *
77984 * @param {*} key to be escaped.
77985 * @return {string} the escaped key.
77986 */
77987
77988function escape(key) {
77989  var escapeRegex = /[=:]/g;
77990  var escaperLookup = {
77991    '=': '=0',
77992    ':': '=2'
77993  };
77994  var escapedString = ('' + key).replace(escapeRegex, function (match) {
77995    return escaperLookup[match];
77996  });
77997
77998  return '$' + escapedString;
77999}
78000
78001/**
78002 * Unescape and unwrap key for human-readable display
78003 *
78004 * @param {string} key to unescape.
78005 * @return {string} the unescaped key.
78006 */
78007function unescape(key) {
78008  var unescapeRegex = /(=0|=2)/g;
78009  var unescaperLookup = {
78010    '=0': '=',
78011    '=2': ':'
78012  };
78013  var keySubstring = key[0] === '.' && key[1] === '$' ? key.substring(2) : key.substring(1);
78014
78015  return ('' + keySubstring).replace(unescapeRegex, function (match) {
78016    return unescaperLookup[match];
78017  });
78018}
78019
78020var KeyEscapeUtils = {
78021  escape: escape,
78022  unescape: unescape
78023};
78024
78025module.exports = KeyEscapeUtils;
78026},{}],24:[function(_dereq_,module,exports){
78027/**
78028 * Copyright 2013-present, Facebook, Inc.
78029 * All rights reserved.
78030 *
78031 * This source code is licensed under the BSD-style license found in the
78032 * LICENSE file in the root directory of this source tree. An additional grant
78033 * of patent rights can be found in the PATENTS file in the same directory.
78034 *
78035 * @providesModule LinkedValueUtils
78036 */
78037
78038
78039
78040var ReactPropTypes = _dereq_(85);
78041var ReactPropTypeLocations = _dereq_(84);
78042
78043var invariant = _dereq_(158);
78044var warning = _dereq_(168);
78045
78046var hasReadOnlyValue = {
78047  'button': true,
78048  'checkbox': true,
78049  'image': true,
78050  'hidden': true,
78051  'radio': true,
78052  'reset': true,
78053  'submit': true
78054};
78055
78056function _assertSingleLink(inputProps) {
78057  !(inputProps.checkedLink == null || inputProps.valueLink == null) ? "development" !== 'production' ? invariant(false, 'Cannot provide a checkedLink and a valueLink. If you want to use ' + 'checkedLink, you probably don\'t want to use valueLink and vice versa.') : invariant(false) : void 0;
78058}
78059function _assertValueLink(inputProps) {
78060  _assertSingleLink(inputProps);
78061  !(inputProps.value == null && inputProps.onChange == null) ? "development" !== 'production' ? invariant(false, 'Cannot provide a valueLink and a value or onChange event. If you want ' + 'to use value or onChange, you probably don\'t want to use valueLink.') : invariant(false) : void 0;
78062}
78063
78064function _assertCheckedLink(inputProps) {
78065  _assertSingleLink(inputProps);
78066  !(inputProps.checked == null && inputProps.onChange == null) ? "development" !== 'production' ? invariant(false, 'Cannot provide a checkedLink and a checked property or onChange event. ' + 'If you want to use checked or onChange, you probably don\'t want to ' + 'use checkedLink') : invariant(false) : void 0;
78067}
78068
78069var propTypes = {
78070  value: function (props, propName, componentName) {
78071    if (!props[propName] || hasReadOnlyValue[props.type] || props.onChange || props.readOnly || props.disabled) {
78072      return null;
78073    }
78074    return new Error('You provided a `value` prop to a form field without an ' + '`onChange` handler. This will render a read-only field. If ' + 'the field should be mutable use `defaultValue`. Otherwise, ' + 'set either `onChange` or `readOnly`.');
78075  },
78076  checked: function (props, propName, componentName) {
78077    if (!props[propName] || props.onChange || props.readOnly || props.disabled) {
78078      return null;
78079    }
78080    return new Error('You provided a `checked` prop to a form field without an ' + '`onChange` handler. This will render a read-only field. If ' + 'the field should be mutable use `defaultChecked`. Otherwise, ' + 'set either `onChange` or `readOnly`.');
78081  },
78082  onChange: ReactPropTypes.func
78083};
78084
78085var loggedTypeFailures = {};
78086function getDeclarationErrorAddendum(owner) {
78087  if (owner) {
78088    var name = owner.getName();
78089    if (name) {
78090      return ' Check the render method of `' + name + '`.';
78091    }
78092  }
78093  return '';
78094}
78095
78096/**
78097 * Provide a linked `value` attribute for controlled forms. You should not use
78098 * this outside of the ReactDOM controlled form components.
78099 */
78100var LinkedValueUtils = {
78101  checkPropTypes: function (tagName, props, owner) {
78102    for (var propName in propTypes) {
78103      if (propTypes.hasOwnProperty(propName)) {
78104        var error = propTypes[propName](props, propName, tagName, ReactPropTypeLocations.prop);
78105      }
78106      if (error instanceof Error && !(error.message in loggedTypeFailures)) {
78107        // Only monitor this failure once because there tends to be a lot of the
78108        // same error.
78109        loggedTypeFailures[error.message] = true;
78110
78111        var addendum = getDeclarationErrorAddendum(owner);
78112        "development" !== 'production' ? warning(false, 'Failed form propType: %s%s', error.message, addendum) : void 0;
78113      }
78114    }
78115  },
78116
78117  /**
78118   * @param {object} inputProps Props for form component
78119   * @return {*} current value of the input either from value prop or link.
78120   */
78121  getValue: function (inputProps) {
78122    if (inputProps.valueLink) {
78123      _assertValueLink(inputProps);
78124      return inputProps.valueLink.value;
78125    }
78126    return inputProps.value;
78127  },
78128
78129  /**
78130   * @param {object} inputProps Props for form component
78131   * @return {*} current checked status of the input either from checked prop
78132   *             or link.
78133   */
78134  getChecked: function (inputProps) {
78135    if (inputProps.checkedLink) {
78136      _assertCheckedLink(inputProps);
78137      return inputProps.checkedLink.value;
78138    }
78139    return inputProps.checked;
78140  },
78141
78142  /**
78143   * @param {object} inputProps Props for form component
78144   * @param {SyntheticEvent} event change event to handle
78145   */
78146  executeOnChange: function (inputProps, event) {
78147    if (inputProps.valueLink) {
78148      _assertValueLink(inputProps);
78149      return inputProps.valueLink.requestChange(event.target.value);
78150    } else if (inputProps.checkedLink) {
78151      _assertCheckedLink(inputProps);
78152      return inputProps.checkedLink.requestChange(event.target.checked);
78153    } else if (inputProps.onChange) {
78154      return inputProps.onChange.call(undefined, event);
78155    }
78156  }
78157};
78158
78159module.exports = LinkedValueUtils;
78160},{"158":158,"168":168,"84":84,"85":85}],25:[function(_dereq_,module,exports){
78161/**
78162 * Copyright 2013-present, Facebook, Inc.
78163 * All rights reserved.
78164 *
78165 * This source code is licensed under the BSD-style license found in the
78166 * LICENSE file in the root directory of this source tree. An additional grant
78167 * of patent rights can be found in the PATENTS file in the same directory.
78168 *
78169 * @providesModule PooledClass
78170 */
78171
78172
78173
78174var invariant = _dereq_(158);
78175
78176/**
78177 * Static poolers. Several custom versions for each potential number of
78178 * arguments. A completely generic pooler is easy to implement, but would
78179 * require accessing the `arguments` object. In each of these, `this` refers to
78180 * the Class itself, not an instance. If any others are needed, simply add them
78181 * here, or in their own files.
78182 */
78183var oneArgumentPooler = function (copyFieldsFrom) {
78184  var Klass = this;
78185  if (Klass.instancePool.length) {
78186    var instance = Klass.instancePool.pop();
78187    Klass.call(instance, copyFieldsFrom);
78188    return instance;
78189  } else {
78190    return new Klass(copyFieldsFrom);
78191  }
78192};
78193
78194var twoArgumentPooler = function (a1, a2) {
78195  var Klass = this;
78196  if (Klass.instancePool.length) {
78197    var instance = Klass.instancePool.pop();
78198    Klass.call(instance, a1, a2);
78199    return instance;
78200  } else {
78201    return new Klass(a1, a2);
78202  }
78203};
78204
78205var threeArgumentPooler = function (a1, a2, a3) {
78206  var Klass = this;
78207  if (Klass.instancePool.length) {
78208    var instance = Klass.instancePool.pop();
78209    Klass.call(instance, a1, a2, a3);
78210    return instance;
78211  } else {
78212    return new Klass(a1, a2, a3);
78213  }
78214};
78215
78216var fourArgumentPooler = function (a1, a2, a3, a4) {
78217  var Klass = this;
78218  if (Klass.instancePool.length) {
78219    var instance = Klass.instancePool.pop();
78220    Klass.call(instance, a1, a2, a3, a4);
78221    return instance;
78222  } else {
78223    return new Klass(a1, a2, a3, a4);
78224  }
78225};
78226
78227var fiveArgumentPooler = function (a1, a2, a3, a4, a5) {
78228  var Klass = this;
78229  if (Klass.instancePool.length) {
78230    var instance = Klass.instancePool.pop();
78231    Klass.call(instance, a1, a2, a3, a4, a5);
78232    return instance;
78233  } else {
78234    return new Klass(a1, a2, a3, a4, a5);
78235  }
78236};
78237
78238var standardReleaser = function (instance) {
78239  var Klass = this;
78240  !(instance instanceof Klass) ? "development" !== 'production' ? invariant(false, 'Trying to release an instance into a pool of a different type.') : invariant(false) : void 0;
78241  instance.destructor();
78242  if (Klass.instancePool.length < Klass.poolSize) {
78243    Klass.instancePool.push(instance);
78244  }
78245};
78246
78247var DEFAULT_POOL_SIZE = 10;
78248var DEFAULT_POOLER = oneArgumentPooler;
78249
78250/**
78251 * Augments `CopyConstructor` to be a poolable class, augmenting only the class
78252 * itself (statically) not adding any prototypical fields. Any CopyConstructor
78253 * you give this may have a `poolSize` property, and will look for a
78254 * prototypical `destructor` on instances (optional).
78255 *
78256 * @param {Function} CopyConstructor Constructor that can be used to reset.
78257 * @param {Function} pooler Customizable pooler.
78258 */
78259var addPoolingTo = function (CopyConstructor, pooler) {
78260  var NewKlass = CopyConstructor;
78261  NewKlass.instancePool = [];
78262  NewKlass.getPooled = pooler || DEFAULT_POOLER;
78263  if (!NewKlass.poolSize) {
78264    NewKlass.poolSize = DEFAULT_POOL_SIZE;
78265  }
78266  NewKlass.release = standardReleaser;
78267  return NewKlass;
78268};
78269
78270var PooledClass = {
78271  addPoolingTo: addPoolingTo,
78272  oneArgumentPooler: oneArgumentPooler,
78273  twoArgumentPooler: twoArgumentPooler,
78274  threeArgumentPooler: threeArgumentPooler,
78275  fourArgumentPooler: fourArgumentPooler,
78276  fiveArgumentPooler: fiveArgumentPooler
78277};
78278
78279module.exports = PooledClass;
78280},{"158":158}],26:[function(_dereq_,module,exports){
78281/**
78282 * Copyright 2013-present, Facebook, Inc.
78283 * All rights reserved.
78284 *
78285 * This source code is licensed under the BSD-style license found in the
78286 * LICENSE file in the root directory of this source tree. An additional grant
78287 * of patent rights can be found in the PATENTS file in the same directory.
78288 *
78289 * @providesModule React
78290 */
78291
78292
78293
78294var _assign = _dereq_(169);
78295
78296var ReactChildren = _dereq_(29);
78297var ReactComponent = _dereq_(31);
78298var ReactClass = _dereq_(30);
78299var ReactDOMFactories = _dereq_(44);
78300var ReactElement = _dereq_(62);
78301var ReactElementValidator = _dereq_(63);
78302var ReactPropTypes = _dereq_(85);
78303var ReactVersion = _dereq_(95);
78304
78305var onlyChild = _dereq_(135);
78306var warning = _dereq_(168);
78307
78308var createElement = ReactElement.createElement;
78309var createFactory = ReactElement.createFactory;
78310var cloneElement = ReactElement.cloneElement;
78311
78312if ("development" !== 'production') {
78313  createElement = ReactElementValidator.createElement;
78314  createFactory = ReactElementValidator.createFactory;
78315  cloneElement = ReactElementValidator.cloneElement;
78316}
78317
78318var __spread = _assign;
78319
78320if ("development" !== 'production') {
78321  var warned = false;
78322  __spread = function () {
78323    "development" !== 'production' ? warning(warned, 'React.__spread is deprecated and should not be used. Use ' + 'Object.assign directly or another helper function with similar ' + 'semantics. You may be seeing this warning due to your compiler. ' + 'See https://fb.me/react-spread-deprecation for more details.') : void 0;
78324    warned = true;
78325    return _assign.apply(null, arguments);
78326  };
78327}
78328
78329var React = {
78330
78331  // Modern
78332
78333  Children: {
78334    map: ReactChildren.map,
78335    forEach: ReactChildren.forEach,
78336    count: ReactChildren.count,
78337    toArray: ReactChildren.toArray,
78338    only: onlyChild
78339  },
78340
78341  Component: ReactComponent,
78342
78343  createElement: createElement,
78344  cloneElement: cloneElement,
78345  isValidElement: ReactElement.isValidElement,
78346
78347  // Classic
78348
78349  PropTypes: ReactPropTypes,
78350  createClass: ReactClass.createClass,
78351  createFactory: createFactory,
78352  createMixin: function (mixin) {
78353    // Currently a noop. Will be used to validate and trace mixins.
78354    return mixin;
78355  },
78356
78357  // This looks DOM specific but these are actually isomorphic helpers
78358  // since they are just generating DOM strings.
78359  DOM: ReactDOMFactories,
78360
78361  version: ReactVersion,
78362
78363  // Deprecated hook for JSX spread, don't use this for anything.
78364  __spread: __spread
78365};
78366
78367module.exports = React;
78368},{"135":135,"168":168,"169":169,"29":29,"30":30,"31":31,"44":44,"62":62,"63":63,"85":85,"95":95}],27:[function(_dereq_,module,exports){
78369/**
78370 * Copyright 2013-present, Facebook, Inc.
78371 * All rights reserved.
78372 *
78373 * This source code is licensed under the BSD-style license found in the
78374 * LICENSE file in the root directory of this source tree. An additional grant
78375 * of patent rights can be found in the PATENTS file in the same directory.
78376 *
78377 * @providesModule ReactBrowserEventEmitter
78378 */
78379
78380
78381
78382var _assign = _dereq_(169);
78383
78384var EventConstants = _dereq_(16);
78385var EventPluginRegistry = _dereq_(18);
78386var ReactEventEmitterMixin = _dereq_(66);
78387var ViewportMetrics = _dereq_(113);
78388
78389var getVendorPrefixedEventName = _dereq_(131);
78390var isEventSupported = _dereq_(133);
78391
78392/**
78393 * Summary of `ReactBrowserEventEmitter` event handling:
78394 *
78395 *  - Top-level delegation is used to trap most native browser events. This
78396 *    may only occur in the main thread and is the responsibility of
78397 *    ReactEventListener, which is injected and can therefore support pluggable
78398 *    event sources. This is the only work that occurs in the main thread.
78399 *
78400 *  - We normalize and de-duplicate events to account for browser quirks. This
78401 *    may be done in the worker thread.
78402 *
78403 *  - Forward these native events (with the associated top-level type used to
78404 *    trap it) to `EventPluginHub`, which in turn will ask plugins if they want
78405 *    to extract any synthetic events.
78406 *
78407 *  - The `EventPluginHub` will then process each event by annotating them with
78408 *    "dispatches", a sequence of listeners and IDs that care about that event.
78409 *
78410 *  - The `EventPluginHub` then dispatches the events.
78411 *
78412 * Overview of React and the event system:
78413 *
78414 * +------------+    .
78415 * |    DOM     |    .
78416 * +------------+    .
78417 *       |           .
78418 *       v           .
78419 * +------------+    .
78420 * | ReactEvent |    .
78421 * |  Listener  |    .
78422 * +------------+    .                         +-----------+
78423 *       |           .               +--------+|SimpleEvent|
78424 *       |           .               |         |Plugin     |
78425 * +-----|------+    .               v         +-----------+
78426 * |     |      |    .    +--------------+                    +------------+
78427 * |     +-----------.--->|EventPluginHub|                    |    Event   |
78428 * |            |    .    |              |     +-----------+  | Propagators|
78429 * | ReactEvent |    .    |              |     |TapEvent   |  |------------|
78430 * |  Emitter   |    .    |              |<---+|Plugin     |  |other plugin|
78431 * |            |    .    |              |     +-----------+  |  utilities |
78432 * |     +-----------.--->|              |                    +------------+
78433 * |     |      |    .    +--------------+
78434 * +-----|------+    .                ^        +-----------+
78435 *       |           .                |        |Enter/Leave|
78436 *       +           .                +-------+|Plugin     |
78437 * +-------------+   .                         +-----------+
78438 * | application |   .
78439 * |-------------|   .
78440 * |             |   .
78441 * |             |   .
78442 * +-------------+   .
78443 *                   .
78444 *    React Core     .  General Purpose Event Plugin System
78445 */
78446
78447var hasEventPageXY;
78448var alreadyListeningTo = {};
78449var isMonitoringScrollValue = false;
78450var reactTopListenersCounter = 0;
78451
78452// For events like 'submit' which don't consistently bubble (which we trap at a
78453// lower node than `document`), binding at `document` would cause duplicate
78454// events so we don't include them here
78455var topEventMapping = {
78456  topAbort: 'abort',
78457  topAnimationEnd: getVendorPrefixedEventName('animationend') || 'animationend',
78458  topAnimationIteration: getVendorPrefixedEventName('animationiteration') || 'animationiteration',
78459  topAnimationStart: getVendorPrefixedEventName('animationstart') || 'animationstart',
78460  topBlur: 'blur',
78461  topCanPlay: 'canplay',
78462  topCanPlayThrough: 'canplaythrough',
78463  topChange: 'change',
78464  topClick: 'click',
78465  topCompositionEnd: 'compositionend',
78466  topCompositionStart: 'compositionstart',
78467  topCompositionUpdate: 'compositionupdate',
78468  topContextMenu: 'contextmenu',
78469  topCopy: 'copy',
78470  topCut: 'cut',
78471  topDoubleClick: 'dblclick',
78472  topDrag: 'drag',
78473  topDragEnd: 'dragend',
78474  topDragEnter: 'dragenter',
78475  topDragExit: 'dragexit',
78476  topDragLeave: 'dragleave',
78477  topDragOver: 'dragover',
78478  topDragStart: 'dragstart',
78479  topDrop: 'drop',
78480  topDurationChange: 'durationchange',
78481  topEmptied: 'emptied',
78482  topEncrypted: 'encrypted',
78483  topEnded: 'ended',
78484  topError: 'error',
78485  topFocus: 'focus',
78486  topInput: 'input',
78487  topKeyDown: 'keydown',
78488  topKeyPress: 'keypress',
78489  topKeyUp: 'keyup',
78490  topLoadedData: 'loadeddata',
78491  topLoadedMetadata: 'loadedmetadata',
78492  topLoadStart: 'loadstart',
78493  topMouseDown: 'mousedown',
78494  topMouseMove: 'mousemove',
78495  topMouseOut: 'mouseout',
78496  topMouseOver: 'mouseover',
78497  topMouseUp: 'mouseup',
78498  topPaste: 'paste',
78499  topPause: 'pause',
78500  topPlay: 'play',
78501  topPlaying: 'playing',
78502  topProgress: 'progress',
78503  topRateChange: 'ratechange',
78504  topScroll: 'scroll',
78505  topSeeked: 'seeked',
78506  topSeeking: 'seeking',
78507  topSelectionChange: 'selectionchange',
78508  topStalled: 'stalled',
78509  topSuspend: 'suspend',
78510  topTextInput: 'textInput',
78511  topTimeUpdate: 'timeupdate',
78512  topTouchCancel: 'touchcancel',
78513  topTouchEnd: 'touchend',
78514  topTouchMove: 'touchmove',
78515  topTouchStart: 'touchstart',
78516  topTransitionEnd: getVendorPrefixedEventName('transitionend') || 'transitionend',
78517  topVolumeChange: 'volumechange',
78518  topWaiting: 'waiting',
78519  topWheel: 'wheel'
78520};
78521
78522/**
78523 * To ensure no conflicts with other potential React instances on the page
78524 */
78525var topListenersIDKey = '_reactListenersID' + String(Math.random()).slice(2);
78526
78527function getListeningForDocument(mountAt) {
78528  // In IE8, `mountAt` is a host object and doesn't have `hasOwnProperty`
78529  // directly.
78530  if (!Object.prototype.hasOwnProperty.call(mountAt, topListenersIDKey)) {
78531    mountAt[topListenersIDKey] = reactTopListenersCounter++;
78532    alreadyListeningTo[mountAt[topListenersIDKey]] = {};
78533  }
78534  return alreadyListeningTo[mountAt[topListenersIDKey]];
78535}
78536
78537/**
78538 * `ReactBrowserEventEmitter` is used to attach top-level event listeners. For
78539 * example:
78540 *
78541 *   EventPluginHub.putListener('myID', 'onClick', myFunction);
78542 *
78543 * This would allocate a "registration" of `('onClick', myFunction)` on 'myID'.
78544 *
78545 * @internal
78546 */
78547var ReactBrowserEventEmitter = _assign({}, ReactEventEmitterMixin, {
78548
78549  /**
78550   * Injectable event backend
78551   */
78552  ReactEventListener: null,
78553
78554  injection: {
78555    /**
78556     * @param {object} ReactEventListener
78557     */
78558    injectReactEventListener: function (ReactEventListener) {
78559      ReactEventListener.setHandleTopLevel(ReactBrowserEventEmitter.handleTopLevel);
78560      ReactBrowserEventEmitter.ReactEventListener = ReactEventListener;
78561    }
78562  },
78563
78564  /**
78565   * Sets whether or not any created callbacks should be enabled.
78566   *
78567   * @param {boolean} enabled True if callbacks should be enabled.
78568   */
78569  setEnabled: function (enabled) {
78570    if (ReactBrowserEventEmitter.ReactEventListener) {
78571      ReactBrowserEventEmitter.ReactEventListener.setEnabled(enabled);
78572    }
78573  },
78574
78575  /**
78576   * @return {boolean} True if callbacks are enabled.
78577   */
78578  isEnabled: function () {
78579    return !!(ReactBrowserEventEmitter.ReactEventListener && ReactBrowserEventEmitter.ReactEventListener.isEnabled());
78580  },
78581
78582  /**
78583   * We listen for bubbled touch events on the document object.
78584   *
78585   * Firefox v8.01 (and possibly others) exhibited strange behavior when
78586   * mounting `onmousemove` events at some node that was not the document
78587   * element. The symptoms were that if your mouse is not moving over something
78588   * contained within that mount point (for example on the background) the
78589   * top-level listeners for `onmousemove` won't be called. However, if you
78590   * register the `mousemove` on the document object, then it will of course
78591   * catch all `mousemove`s. This along with iOS quirks, justifies restricting
78592   * top-level listeners to the document object only, at least for these
78593   * movement types of events and possibly all events.
78594   *
78595   * @see http://www.quirksmode.org/blog/archives/2010/09/click_event_del.html
78596   *
78597   * Also, `keyup`/`keypress`/`keydown` do not bubble to the window on IE, but
78598   * they bubble to document.
78599   *
78600   * @param {string} registrationName Name of listener (e.g. `onClick`).
78601   * @param {object} contentDocumentHandle Document which owns the container
78602   */
78603  listenTo: function (registrationName, contentDocumentHandle) {
78604    var mountAt = contentDocumentHandle;
78605    var isListening = getListeningForDocument(mountAt);
78606    var dependencies = EventPluginRegistry.registrationNameDependencies[registrationName];
78607
78608    var topLevelTypes = EventConstants.topLevelTypes;
78609    for (var i = 0; i < dependencies.length; i++) {
78610      var dependency = dependencies[i];
78611      if (!(isListening.hasOwnProperty(dependency) && isListening[dependency])) {
78612        if (dependency === topLevelTypes.topWheel) {
78613          if (isEventSupported('wheel')) {
78614            ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topWheel, 'wheel', mountAt);
78615          } else if (isEventSupported('mousewheel')) {
78616            ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topWheel, 'mousewheel', mountAt);
78617          } else {
78618            // Firefox needs to capture a different mouse scroll event.
78619            // @see http://www.quirksmode.org/dom/events/tests/scroll.html
78620            ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topWheel, 'DOMMouseScroll', mountAt);
78621          }
78622        } else if (dependency === topLevelTypes.topScroll) {
78623
78624          if (isEventSupported('scroll', true)) {
78625            ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(topLevelTypes.topScroll, 'scroll', mountAt);
78626          } else {
78627            ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topScroll, 'scroll', ReactBrowserEventEmitter.ReactEventListener.WINDOW_HANDLE);
78628          }
78629        } else if (dependency === topLevelTypes.topFocus || dependency === topLevelTypes.topBlur) {
78630
78631          if (isEventSupported('focus', true)) {
78632            ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(topLevelTypes.topFocus, 'focus', mountAt);
78633            ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(topLevelTypes.topBlur, 'blur', mountAt);
78634          } else if (isEventSupported('focusin')) {
78635            // IE has `focusin` and `focusout` events which bubble.
78636            // @see http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html
78637            ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topFocus, 'focusin', mountAt);
78638            ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topBlur, 'focusout', mountAt);
78639          }
78640
78641          // to make sure blur and focus event listeners are only attached once
78642          isListening[topLevelTypes.topBlur] = true;
78643          isListening[topLevelTypes.topFocus] = true;
78644        } else if (topEventMapping.hasOwnProperty(dependency)) {
78645          ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(dependency, topEventMapping[dependency], mountAt);
78646        }
78647
78648        isListening[dependency] = true;
78649      }
78650    }
78651  },
78652
78653  trapBubbledEvent: function (topLevelType, handlerBaseName, handle) {
78654    return ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelType, handlerBaseName, handle);
78655  },
78656
78657  trapCapturedEvent: function (topLevelType, handlerBaseName, handle) {
78658    return ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(topLevelType, handlerBaseName, handle);
78659  },
78660
78661  /**
78662   * Listens to window scroll and resize events. We cache scroll values so that
78663   * application code can access them without triggering reflows.
78664   *
78665   * ViewportMetrics is only used by SyntheticMouse/TouchEvent and only when
78666   * pageX/pageY isn't supported (legacy browsers).
78667   *
78668   * NOTE: Scroll events do not bubble.
78669   *
78670   * @see http://www.quirksmode.org/dom/events/scroll.html
78671   */
78672  ensureScrollValueMonitoring: function () {
78673    if (hasEventPageXY === undefined) {
78674      hasEventPageXY = document.createEvent && 'pageX' in document.createEvent('MouseEvent');
78675    }
78676    if (!hasEventPageXY && !isMonitoringScrollValue) {
78677      var refresh = ViewportMetrics.refreshScrollValues;
78678      ReactBrowserEventEmitter.ReactEventListener.monitorScrollValue(refresh);
78679      isMonitoringScrollValue = true;
78680    }
78681  }
78682
78683});
78684
78685module.exports = ReactBrowserEventEmitter;
78686},{"113":113,"131":131,"133":133,"16":16,"169":169,"18":18,"66":66}],28:[function(_dereq_,module,exports){
78687/**
78688 * Copyright 2014-present, Facebook, Inc.
78689 * All rights reserved.
78690 *
78691 * This source code is licensed under the BSD-style license found in the
78692 * LICENSE file in the root directory of this source tree. An additional grant
78693 * of patent rights can be found in the PATENTS file in the same directory.
78694 *
78695 * @providesModule ReactChildReconciler
78696 */
78697
78698
78699
78700var ReactReconciler = _dereq_(87);
78701
78702var instantiateReactComponent = _dereq_(132);
78703var KeyEscapeUtils = _dereq_(23);
78704var shouldUpdateReactComponent = _dereq_(140);
78705var traverseAllChildren = _dereq_(141);
78706var warning = _dereq_(168);
78707
78708function instantiateChild(childInstances, child, name) {
78709  // We found a component instance.
78710  var keyUnique = childInstances[name] === undefined;
78711  if ("development" !== 'production') {
78712    "development" !== 'production' ? warning(keyUnique, 'flattenChildren(...): Encountered two children with the same key, ' + '`%s`. Child keys must be unique; when two children share a key, only ' + 'the first child will be used.', KeyEscapeUtils.unescape(name)) : void 0;
78713  }
78714  if (child != null && keyUnique) {
78715    childInstances[name] = instantiateReactComponent(child);
78716  }
78717}
78718
78719/**
78720 * ReactChildReconciler provides helpers for initializing or updating a set of
78721 * children. Its output is suitable for passing it onto ReactMultiChild which
78722 * does diffed reordering and insertion.
78723 */
78724var ReactChildReconciler = {
78725  /**
78726   * Generates a "mount image" for each of the supplied children. In the case
78727   * of `ReactDOMComponent`, a mount image is a string of markup.
78728   *
78729   * @param {?object} nestedChildNodes Nested child maps.
78730   * @return {?object} A set of child instances.
78731   * @internal
78732   */
78733  instantiateChildren: function (nestedChildNodes, transaction, context) {
78734    if (nestedChildNodes == null) {
78735      return null;
78736    }
78737    var childInstances = {};
78738    traverseAllChildren(nestedChildNodes, instantiateChild, childInstances);
78739    return childInstances;
78740  },
78741
78742  /**
78743   * Updates the rendered children and returns a new set of children.
78744   *
78745   * @param {?object} prevChildren Previously initialized set of children.
78746   * @param {?object} nextChildren Flat child element maps.
78747   * @param {ReactReconcileTransaction} transaction
78748   * @param {object} context
78749   * @return {?object} A new set of child instances.
78750   * @internal
78751   */
78752  updateChildren: function (prevChildren, nextChildren, removedNodes, transaction, context) {
78753    // We currently don't have a way to track moves here but if we use iterators
78754    // instead of for..in we can zip the iterators and check if an item has
78755    // moved.
78756    // TODO: If nothing has changed, return the prevChildren object so that we
78757    // can quickly bailout if nothing has changed.
78758    if (!nextChildren && !prevChildren) {
78759      return;
78760    }
78761    var name;
78762    var prevChild;
78763    for (name in nextChildren) {
78764      if (!nextChildren.hasOwnProperty(name)) {
78765        continue;
78766      }
78767      prevChild = prevChildren && prevChildren[name];
78768      var prevElement = prevChild && prevChild._currentElement;
78769      var nextElement = nextChildren[name];
78770      if (prevChild != null && shouldUpdateReactComponent(prevElement, nextElement)) {
78771        ReactReconciler.receiveComponent(prevChild, nextElement, transaction, context);
78772        nextChildren[name] = prevChild;
78773      } else {
78774        if (prevChild) {
78775          removedNodes[name] = ReactReconciler.getNativeNode(prevChild);
78776          ReactReconciler.unmountComponent(prevChild, false);
78777        }
78778        // The child must be instantiated before it's mounted.
78779        var nextChildInstance = instantiateReactComponent(nextElement);
78780        nextChildren[name] = nextChildInstance;
78781      }
78782    }
78783    // Unmount children that are no longer present.
78784    for (name in prevChildren) {
78785      if (prevChildren.hasOwnProperty(name) && !(nextChildren && nextChildren.hasOwnProperty(name))) {
78786        prevChild = prevChildren[name];
78787        removedNodes[name] = ReactReconciler.getNativeNode(prevChild);
78788        ReactReconciler.unmountComponent(prevChild, false);
78789      }
78790    }
78791  },
78792
78793  /**
78794   * Unmounts all rendered children. This should be used to clean up children
78795   * when this component is unmounted.
78796   *
78797   * @param {?object} renderedChildren Previously initialized set of children.
78798   * @internal
78799   */
78800  unmountChildren: function (renderedChildren, safely) {
78801    for (var name in renderedChildren) {
78802      if (renderedChildren.hasOwnProperty(name)) {
78803        var renderedChild = renderedChildren[name];
78804        ReactReconciler.unmountComponent(renderedChild, safely);
78805      }
78806    }
78807  }
78808
78809};
78810
78811module.exports = ReactChildReconciler;
78812},{"132":132,"140":140,"141":141,"168":168,"23":23,"87":87}],29:[function(_dereq_,module,exports){
78813/**
78814 * Copyright 2013-present, Facebook, Inc.
78815 * All rights reserved.
78816 *
78817 * This source code is licensed under the BSD-style license found in the
78818 * LICENSE file in the root directory of this source tree. An additional grant
78819 * of patent rights can be found in the PATENTS file in the same directory.
78820 *
78821 * @providesModule ReactChildren
78822 */
78823
78824
78825
78826var PooledClass = _dereq_(25);
78827var ReactElement = _dereq_(62);
78828
78829var emptyFunction = _dereq_(150);
78830var traverseAllChildren = _dereq_(141);
78831
78832var twoArgumentPooler = PooledClass.twoArgumentPooler;
78833var fourArgumentPooler = PooledClass.fourArgumentPooler;
78834
78835var userProvidedKeyEscapeRegex = /\/+/g;
78836function escapeUserProvidedKey(text) {
78837  return ('' + text).replace(userProvidedKeyEscapeRegex, '$&/');
78838}
78839
78840/**
78841 * PooledClass representing the bookkeeping associated with performing a child
78842 * traversal. Allows avoiding binding callbacks.
78843 *
78844 * @constructor ForEachBookKeeping
78845 * @param {!function} forEachFunction Function to perform traversal with.
78846 * @param {?*} forEachContext Context to perform context with.
78847 */
78848function ForEachBookKeeping(forEachFunction, forEachContext) {
78849  this.func = forEachFunction;
78850  this.context = forEachContext;
78851  this.count = 0;
78852}
78853ForEachBookKeeping.prototype.destructor = function () {
78854  this.func = null;
78855  this.context = null;
78856  this.count = 0;
78857};
78858PooledClass.addPoolingTo(ForEachBookKeeping, twoArgumentPooler);
78859
78860function forEachSingleChild(bookKeeping, child, name) {
78861  var func = bookKeeping.func;
78862  var context = bookKeeping.context;
78863
78864  func.call(context, child, bookKeeping.count++);
78865}
78866
78867/**
78868 * Iterates through children that are typically specified as `props.children`.
78869 *
78870 * The provided forEachFunc(child, index) will be called for each
78871 * leaf child.
78872 *
78873 * @param {?*} children Children tree container.
78874 * @param {function(*, int)} forEachFunc
78875 * @param {*} forEachContext Context for forEachContext.
78876 */
78877function forEachChildren(children, forEachFunc, forEachContext) {
78878  if (children == null) {
78879    return children;
78880  }
78881  var traverseContext = ForEachBookKeeping.getPooled(forEachFunc, forEachContext);
78882  traverseAllChildren(children, forEachSingleChild, traverseContext);
78883  ForEachBookKeeping.release(traverseContext);
78884}
78885
78886/**
78887 * PooledClass representing the bookkeeping associated with performing a child
78888 * mapping. Allows avoiding binding callbacks.
78889 *
78890 * @constructor MapBookKeeping
78891 * @param {!*} mapResult Object containing the ordered map of results.
78892 * @param {!function} mapFunction Function to perform mapping with.
78893 * @param {?*} mapContext Context to perform mapping with.
78894 */
78895function MapBookKeeping(mapResult, keyPrefix, mapFunction, mapContext) {
78896  this.result = mapResult;
78897  this.keyPrefix = keyPrefix;
78898  this.func = mapFunction;
78899  this.context = mapContext;
78900  this.count = 0;
78901}
78902MapBookKeeping.prototype.destructor = function () {
78903  this.result = null;
78904  this.keyPrefix = null;
78905  this.func = null;
78906  this.context = null;
78907  this.count = 0;
78908};
78909PooledClass.addPoolingTo(MapBookKeeping, fourArgumentPooler);
78910
78911function mapSingleChildIntoContext(bookKeeping, child, childKey) {
78912  var result = bookKeeping.result;
78913  var keyPrefix = bookKeeping.keyPrefix;
78914  var func = bookKeeping.func;
78915  var context = bookKeeping.context;
78916
78917
78918  var mappedChild = func.call(context, child, bookKeeping.count++);
78919  if (Array.isArray(mappedChild)) {
78920    mapIntoWithKeyPrefixInternal(mappedChild, result, childKey, emptyFunction.thatReturnsArgument);
78921  } else if (mappedChild != null) {
78922    if (ReactElement.isValidElement(mappedChild)) {
78923      mappedChild = ReactElement.cloneAndReplaceKey(mappedChild,
78924      // Keep both the (mapped) and old keys if they differ, just as
78925      // traverseAllChildren used to do for objects as children
78926      keyPrefix + (mappedChild.key && (!child || child.key !== mappedChild.key) ? escapeUserProvidedKey(mappedChild.key) + '/' : '') + childKey);
78927    }
78928    result.push(mappedChild);
78929  }
78930}
78931
78932function mapIntoWithKeyPrefixInternal(children, array, prefix, func, context) {
78933  var escapedPrefix = '';
78934  if (prefix != null) {
78935    escapedPrefix = escapeUserProvidedKey(prefix) + '/';
78936  }
78937  var traverseContext = MapBookKeeping.getPooled(array, escapedPrefix, func, context);
78938  traverseAllChildren(children, mapSingleChildIntoContext, traverseContext);
78939  MapBookKeeping.release(traverseContext);
78940}
78941
78942/**
78943 * Maps children that are typically specified as `props.children`.
78944 *
78945 * The provided mapFunction(child, index) will be called for each
78946 * leaf child.
78947 *
78948 * @param {?*} children Children tree container.
78949 * @param {function(*, int)} func The map function.
78950 * @param {*} context Context for mapFunction.
78951 * @return {object} Object containing the ordered map of results.
78952 */
78953function mapChildren(children, func, context) {
78954  if (children == null) {
78955    return children;
78956  }
78957  var result = [];
78958  mapIntoWithKeyPrefixInternal(children, result, null, func, context);
78959  return result;
78960}
78961
78962function forEachSingleChildDummy(traverseContext, child, name) {
78963  return null;
78964}
78965
78966/**
78967 * Count the number of children that are typically specified as
78968 * `props.children`.
78969 *
78970 * @param {?*} children Children tree container.
78971 * @return {number} The number of children.
78972 */
78973function countChildren(children, context) {
78974  return traverseAllChildren(children, forEachSingleChildDummy, null);
78975}
78976
78977/**
78978 * Flatten a children object (typically specified as `props.children`) and
78979 * return an array with appropriately re-keyed children.
78980 */
78981function toArray(children) {
78982  var result = [];
78983  mapIntoWithKeyPrefixInternal(children, result, null, emptyFunction.thatReturnsArgument);
78984  return result;
78985}
78986
78987var ReactChildren = {
78988  forEach: forEachChildren,
78989  map: mapChildren,
78990  mapIntoWithKeyPrefixInternal: mapIntoWithKeyPrefixInternal,
78991  count: countChildren,
78992  toArray: toArray
78993};
78994
78995module.exports = ReactChildren;
78996},{"141":141,"150":150,"25":25,"62":62}],30:[function(_dereq_,module,exports){
78997/**
78998 * Copyright 2013-present, Facebook, Inc.
78999 * All rights reserved.
79000 *
79001 * This source code is licensed under the BSD-style license found in the
79002 * LICENSE file in the root directory of this source tree. An additional grant
79003 * of patent rights can be found in the PATENTS file in the same directory.
79004 *
79005 * @providesModule ReactClass
79006 */
79007
79008
79009
79010var _assign = _dereq_(169);
79011
79012var ReactComponent = _dereq_(31);
79013var ReactElement = _dereq_(62);
79014var ReactPropTypeLocations = _dereq_(84);
79015var ReactPropTypeLocationNames = _dereq_(83);
79016var ReactNoopUpdateQueue = _dereq_(80);
79017
79018var emptyObject = _dereq_(151);
79019var invariant = _dereq_(158);
79020var keyMirror = _dereq_(161);
79021var keyOf = _dereq_(162);
79022var warning = _dereq_(168);
79023
79024var MIXINS_KEY = keyOf({ mixins: null });
79025
79026/**
79027 * Policies that describe methods in `ReactClassInterface`.
79028 */
79029var SpecPolicy = keyMirror({
79030  /**
79031   * These methods may be defined only once by the class specification or mixin.
79032   */
79033  DEFINE_ONCE: null,
79034  /**
79035   * These methods may be defined by both the class specification and mixins.
79036   * Subsequent definitions will be chained. These methods must return void.
79037   */
79038  DEFINE_MANY: null,
79039  /**
79040   * These methods are overriding the base class.
79041   */
79042  OVERRIDE_BASE: null,
79043  /**
79044   * These methods are similar to DEFINE_MANY, except we assume they return
79045   * objects. We try to merge the keys of the return values of all the mixed in
79046   * functions. If there is a key conflict we throw.
79047   */
79048  DEFINE_MANY_MERGED: null
79049});
79050
79051var injectedMixins = [];
79052
79053/**
79054 * Composite components are higher-level components that compose other composite
79055 * or native components.
79056 *
79057 * To create a new type of `ReactClass`, pass a specification of
79058 * your new class to `React.createClass`. The only requirement of your class
79059 * specification is that you implement a `render` method.
79060 *
79061 *   var MyComponent = React.createClass({
79062 *     render: function() {
79063 *       return <div>Hello World</div>;
79064 *     }
79065 *   });
79066 *
79067 * The class specification supports a specific protocol of methods that have
79068 * special meaning (e.g. `render`). See `ReactClassInterface` for
79069 * more the comprehensive protocol. Any other properties and methods in the
79070 * class specification will be available on the prototype.
79071 *
79072 * @interface ReactClassInterface
79073 * @internal
79074 */
79075var ReactClassInterface = {
79076
79077  /**
79078   * An array of Mixin objects to include when defining your component.
79079   *
79080   * @type {array}
79081   * @optional
79082   */
79083  mixins: SpecPolicy.DEFINE_MANY,
79084
79085  /**
79086   * An object containing properties and methods that should be defined on
79087   * the component's constructor instead of its prototype (static methods).
79088   *
79089   * @type {object}
79090   * @optional
79091   */
79092  statics: SpecPolicy.DEFINE_MANY,
79093
79094  /**
79095   * Definition of prop types for this component.
79096   *
79097   * @type {object}
79098   * @optional
79099   */
79100  propTypes: SpecPolicy.DEFINE_MANY,
79101
79102  /**
79103   * Definition of context types for this component.
79104   *
79105   * @type {object}
79106   * @optional
79107   */
79108  contextTypes: SpecPolicy.DEFINE_MANY,
79109
79110  /**
79111   * Definition of context types this component sets for its children.
79112   *
79113   * @type {object}
79114   * @optional
79115   */
79116  childContextTypes: SpecPolicy.DEFINE_MANY,
79117
79118  // ==== Definition methods ====
79119
79120  /**
79121   * Invoked when the component is mounted. Values in the mapping will be set on
79122   * `this.props` if that prop is not specified (i.e. using an `in` check).
79123   *
79124   * This method is invoked before `getInitialState` and therefore cannot rely
79125   * on `this.state` or use `this.setState`.
79126   *
79127   * @return {object}
79128   * @optional
79129   */
79130  getDefaultProps: SpecPolicy.DEFINE_MANY_MERGED,
79131
79132  /**
79133   * Invoked once before the component is mounted. The return value will be used
79134   * as the initial value of `this.state`.
79135   *
79136   *   getInitialState: function() {
79137   *     return {
79138   *       isOn: false,
79139   *       fooBaz: new BazFoo()
79140   *     }
79141   *   }
79142   *
79143   * @return {object}
79144   * @optional
79145   */
79146  getInitialState: SpecPolicy.DEFINE_MANY_MERGED,
79147
79148  /**
79149   * @return {object}
79150   * @optional
79151   */
79152  getChildContext: SpecPolicy.DEFINE_MANY_MERGED,
79153
79154  /**
79155   * Uses props from `this.props` and state from `this.state` to render the
79156   * structure of the component.
79157   *
79158   * No guarantees are made about when or how often this method is invoked, so
79159   * it must not have side effects.
79160   *
79161   *   render: function() {
79162   *     var name = this.props.name;
79163   *     return <div>Hello, {name}!</div>;
79164   *   }
79165   *
79166   * @return {ReactComponent}
79167   * @nosideeffects
79168   * @required
79169   */
79170  render: SpecPolicy.DEFINE_ONCE,
79171
79172  // ==== Delegate methods ====
79173
79174  /**
79175   * Invoked when the component is initially created and about to be mou
79175nted.
79176   * This may have side effects, but any external subscriptions or data created
79177   * by this method must be cleaned up in `componentWillUnmount`.
79178   *
79179   * @optional
79180   */
79181  componentWillMount: SpecPolicy.DEFINE_MANY,
79182
79183  /**
79184   * Invoked when the component has been mounted and has a DOM representation.
79185   * However, there is no guarantee that the DOM node is in the document.
79186   *
79187   * Use this as an opportunity to operate on the DOM when the component has
79188   * been mounted (initialized and rendered) for the first time.
79189   *
79190   * @param {DOMElement} rootNode DOM element representing the component.
79191   * @optional
79192   */
79193  componentDidMount: SpecPolicy.DEFINE_MANY,
79194
79195  /**
79196   * Invoked before the component receives new props.
79197   *
79198   * Use this as an opportunity to react to a prop transition by updating the
79199   * state using `this.setState`. Current props are accessed via `this.props`.
79200   *
79201   *   componentWillReceiveProps: function(nextProps, nextContext) {
79202   *     this.setState({
79203   *       likesIncreasing: nextProps.likeCount > this.props.likeCount
79204   *     });
79205   *   }
79206   *
79207   * NOTE: There is no equivalent `componentWillReceiveState`. An incoming prop
79208   * transition may cause a state change, but the opposite is not true. If you
79209   * need it, you are probably looking for `componentWillUpdate`.
79210   *
79211   * @param {object} nextProps
79212   * @optional
79213   */
79214  componentWillReceiveProps: SpecPolicy.DEFINE_MANY,
79215
79216  /**
79217   * Invoked while deciding if the component should be updated as a result of
79218   * receiving new props, state and/or context.
79219   *
79220   * Use this as an opportunity to `return false` when you're certain that the
79221   * transition to the new props/state/context will not require a component
79222   * update.
79223   *
79224   *   shouldComponentUpdate: function(nextProps, nextState, nextContext) {
79225   *     return !equal(nextProps, this.props) ||
79226   *       !equal(nextState, this.state) ||
79227   *       !equal(nextContext, this.context);
79228   *   }
79229   *
79230   * @param {object} nextProps
79231   * @param {?object} nextState
79232   * @param {?object} nextContext
79233   * @return {boolean} True if the component should update.
79234   * @optional
79235   */
79236  shouldComponentUpdate: SpecPolicy.DEFINE_ONCE,
79237
79238  /**
79239   * Invoked when the component is about to update due to a transition from
79240   * `this.props`, `this.state` and `this.context` to `nextProps`, `nextState`
79241   * and `nextContext`.
79242   *
79243   * Use this as an opportunity to perform preparation before an update occurs.
79244   *
79245   * NOTE: You **cannot** use `this.setState()` in this method.
79246   *
79247   * @param {object} nextProps
79248   * @param {?object} nextState
79249   * @param {?object} nextContext
79250   * @param {ReactReconcileTransaction} transaction
79251   * @optional
79252   */
79253  componentWillUpdate: SpecPolicy.DEFINE_MANY,
79254
79255  /**
79256   * Invoked when the component's DOM representation has been updated.
79257   *
79258   * Use this as an opportunity to operate on the DOM when the component has
79259   * been updated.
79260   *
79261   * @param {object} prevProps
79262   * @param {?object} prevState
79263   * @param {?object} prevContext
79264   * @param {DOMElement} rootNode DOM element representing the component.
79265   * @optional
79266   */
79267  componentDidUpdate: SpecPolicy.DEFINE_MANY,
79268
79269  /**
79270   * Invoked when the component is about to be removed from its parent and have
79271   * its DOM representation destroyed.
79272   *
79273   * Use this as an opportunity to deallocate any external resources.
79274   *
79275   * NOTE: There is no `componentDidUnmount` since your component will have been
79276   * destroyed by that point.
79277   *
79278   * @optional
79279   */
79280  componentWillUnmount: SpecPolicy.DEFINE_MANY,
79281
79282  // ==== Advanced methods ====
79283
79284  /**
79285   * Updates the component's currently mounted DOM representation.
79286   *
79287   * By default, this implements React's rendering and reconciliation algorithm.
79288   * Sophisticated clients may wish to override this.
79289   *
79290   * @param {ReactReconcileTransaction} transaction
79291   * @internal
79292   * @overridable
79293   */
79294  updateComponent: SpecPolicy.OVERRIDE_BASE
79295
79296};
79297
79298/**
79299 * Mapping from class specification keys to special processing functions.
79300 *
79301 * Although these are declared like instance properties in the specification
79302 * when defining classes using `React.createClass`, they are actually static
79303 * and are accessible on the constructor instead of the prototype. Despite
79304 * being static, they must be defined outside of the "statics" key under
79305 * which all other static methods are defined.
79306 */
79307var RESERVED_SPEC_KEYS = {
79308  displayName: function (Constructor, displayName) {
79309    Constructor.displayName = displayName;
79310  },
79311  mixins: function (Constructor, mixins) {
79312    if (mixins) {
79313      for (var i = 0; i < mixins.length; i++) {
79314        mixSpecIntoComponent(Constructor, mixins[i]);
79315      }
79316    }
79317  },
79318  childContextTypes: function (Constructor, childContextTypes) {
79319    if ("development" !== 'production') {
79320      validateTypeDef(Constructor, childContextTypes, ReactPropTypeLocations.childContext);
79321    }
79322    Constructor.childContextTypes = _assign({}, Constructor.childContextTypes, childContextTypes);
79323  },
79324  contextTypes: function (Constructor, contextTypes) {
79325    if ("development" !== 'production') {
79326      validateTypeDef(Constructor, contextTypes, ReactPropTypeLocations.context);
79327    }
79328    Constructor.contextTypes = _assign({}, Constructor.contextTypes, contextTypes);
79329  },
79330  /**
79331   * Special case getDefaultProps which should move into statics but requires
79332   * automatic merging.
79333   */
79334  getDefaultProps: function (Constructor, getDefaultProps) {
79335    if (Constructor.getDefaultProps) {
79336      Constructor.getDefaultProps = createMergedResultFunction(Constructor.getDefaultProps, getDefaultProps);
79337    } else {
79338      Constructor.getDefaultProps = getDefaultProps;
79339    }
79340  },
79341  propTypes: function (Constructor, propTypes) {
79342    if ("development" !== 'production') {
79343      validateTypeDef(Constructor, propTypes, ReactPropTypeLocations.prop);
79344    }
79345    Constructor.propTypes = _assign({}, Constructor.propTypes, propTypes);
79346  },
79347  statics: function (Constructor, statics) {
79348    mixStaticSpecIntoComponent(Constructor, statics);
79349  },
79350  autobind: function () {} };
79351
79352// noop
79353function validateTypeDef(Constructor, typeDef, location) {
79354  for (var propName in typeDef) {
79355    if (typeDef.hasOwnProperty(propName)) {
79356      // use a warning instead of an invariant so components
79357      // don't show up in prod but only in __DEV__
79358      "development" !== 'production' ? warning(typeof typeDef[propName] === 'function', '%s: %s type `%s` is invali
79358d; it must be a function, usually from ' + 'React.PropTypes.', Constructor.displayName || 'ReactClass', ReactPropTypeLocationNames[location], propName) : void 0;
79359    }
79360  }
79361}
79362
79363function validateMethodOverride(isAlreadyDefined, name) {
79364  var specPolicy = ReactClassInterface.hasOwnProperty(name) ? ReactClassInterface[name] : null;
79365
79366  // Disallow overriding of base class methods unless explicitly allowed.
79367  if (ReactClassMixin.hasOwnProperty(name)) {
79368    !(specPolicy === SpecPolicy.OVERRIDE_BASE) ? "development" !== 'production' ? invariant(false, 'ReactClassInterface: You are attempting to override ' + '`%s` from your class specification. Ensure that your method names ' + 'do not overlap with React methods.', name) : invariant(false) : void 0;
79369  }
79370
79371  // Disallow defining methods more than once unless explicitly allowed.
79372  if (isAlreadyDefined) {
79373    !(specPolicy === SpecPolicy.DEFINE_MANY || specPolicy === SpecPolicy.DEFINE_MANY_MERGED) ? "development" !== 'production' ? invariant(false, 'ReactClassInterface: You are attempting to define ' + '`%s` on your component more than once. This conflict may be due ' + 'to a mixin.', name) : invariant(false) : void 0;
79374  }
79375}
79376
79377/**
79378 * Mixin helper which handles policy validation and reserved
79379 * specification keys when building React classes.
79380 */
79381function mixSpecIntoComponent(Constructor, spec) {
79382  if (!spec) {
79383    return;
79384  }
79385
79386  !(typeof spec !== 'function') ? "development" !== 'production' ? invariant(false, 'ReactClass: You\'re attempting to ' + 'use a component class or function as a mixin. Instead, just use a ' + 'regular object.') : invariant(false) : void 0;
79387  !!ReactElement.isValidElement(spec) ? "development" !== 'production' ? invariant(false, 'ReactClass: You\'re attempting to ' + 'use a component as a mixin. Instead, just use a regular object.') : invariant(false) : void 0;
79388
79389  var proto = Constructor.prototype;
79390  var autoBindPairs = proto.__reactAutoBindPairs;
79391
79392  // By handling mixins before any other properties, we ensure the same
79393  // chaining order is applied to methods with DEFINE_MANY policy, whether
79394  // mixins are listed before or after these methods in the spec.
79395  if (spec.hasOwnProperty(MIXINS_KEY)) {
79396    RESERVED_SPEC_KEYS.mixins(Constructor, spec.mixins);
79397  }
79398
79399  for (var name in spec) {
79400    if (!spec.hasOwnProperty(name)) {
79401      continue;
79402    }
79403
79404    if (name === MIXINS_KEY) {
79405      // We have already handled mixins in a special case above.
79406      continue;
79407    }
79408
79409    var property = spec[name];
79410    var isAlreadyDefined = proto.hasOwnProperty(name);
79411    validateMethodOverride(isAlreadyDefined, name);
79412
79413    if (RESERVED_SPEC_KEYS.hasOwnProperty(name)) {
79414      RESERVED_SPEC_KEYS[name](Constructor, property);
79415    } else {
79416      // Setup methods on prototype:
79417      // The following member methods should not be automatically bound:
79418      // 1. Expected ReactClass methods (in the "interface").
79419      // 2. Overridden methods (that were mixed in).
79420      var isReactClassMethod = ReactClassInterface.hasOwnProperty(name);
79421      var isFunction = typeof property === 'function';
79422      var shouldAutoBind = isFunction && !isReactClassMethod && !isAlreadyDefined && spec.autobind !== false;
79423
79424      if (shouldAutoBind) {
79425        autoBindPairs.push(name, property);
79426        proto[name] = property;
79427      } else {
79428        if (isAlreadyDefined) {
79429          var specPolicy = ReactClassInterface[name];
79430
79431          // These cases should already be caught by validateMethodOverride.
79432          !(isReactClassMethod && (specPolicy === SpecPolicy.DEFINE_MANY_MERGED || specPolicy === SpecPolicy.DEFINE_MANY)) ? "development" !== 'production' ? invariant(false, 'ReactClass: Unexpected spec policy %s for key %s ' + 'when mixing in component specs.', specPolicy, name) : invariant(false) : void 0;
79433
79434          // For methods which are defined more than once, call the existing
79435          // methods before calling the new property, merging if appropriate.
79436          if (specPolicy === SpecPolicy.DEFINE_MANY_MERGED) {
79437            proto[name] = createMergedResultFunction(proto[name], property);
79438          } else if (specPolicy === SpecPolicy.DEFINE_MANY) {
79439            proto[name] = createChainedFunction(proto[name], property);
79440          }
79441        } else {
79442          proto[name] = property;
79443          if ("development" !== 'production') {
79444            // Add verbose displayName to the function, which helps when looking
79445            // at profiling tools.
79446            if (typeof property === 'function' && spec.displayName) {
79447              proto[name].displayName = spec.displayName + '_' + name;
79448            }
79449          }
79450        }
79451      }
79452    }
79453  }
79454}
79455
79456function mixStaticSpecIntoComponent(Constructor, statics) {
79457  if (!statics) {
79458    return;
79459  }
79460  for (var name in statics) {
79461    var property = statics[name];
79462    if (!statics.hasOwnProperty(name)) {
79463      continue;
79464    }
79465
79466    var isReserved = name in RESERVED_SPEC_KEYS;
79467    !!isReserved ? "development" !== 'production' ? invariant(false, 'ReactClass: You are attempting to define a reserved ' + 'property, `%s`, that shouldn\'t be on the "statics" key. Define it ' + 'as an instance property instead; it will still be accessible on the ' + 'constructor.', name) : invariant(false) : void 0;
79468
79469    var isInherited = name in Constructor;
79470    !!isInherited ? "development" !== 'production' ? invariant(false, 'ReactClass: You are attempting to define ' + '`%s` on your component more than once. This conflict may be ' + 'due to a mixin.', name) : invariant(false) : void 0;
79471    Constructor[name] = property;
79472  }
79473}
79474
79475/**
79476 * Merge two objects, but throw if both contain the same key.
79477 *
79478 * @param {object} one The first object, which is mutated.
79479 * @param {object} two The second object
79480 * @return {object} one after it has been mutated to contain everything in two.
79481 */
79482function mergeIntoWithNoDuplicateKeys(one, two) {
79483  !(one && two && typeof one === 'object' && typeof two === 'object') ? "development" !== 'production' ? invariant(false, 'mergeIntoWithNoDuplicateKeys(): Cannot merge non-objects.') : invariant(false) : void 0;
79484
79485  for (var key in two) {
79486    if (two.hasOwnProperty(key)) {
79487      !(one[key] === undefined) ? "development" !== 'production' ? invariant(false, 'mergeIntoWithNoDuplicateKeys(): ' + 'Tried to merge two objects with the same key: `%s`. This conflict ' + 'may be due to a mixin; in particular, this may be caused by two ' + 'getInitialState() or getDefaultProps() methods returning objects ' + 'with clashing keys.', key) : invariant(false) : void 0;
79488      one[key] = two[key];
79489    }
79490  }
79491  return one;
79492}
79493
79494/**
79495 * Creates a function that invokes two functions and merges their return values.
79496 *
79497 * @param {function} one Function to invoke first.
79498 * @param {function} two Function to invoke second.
79499 * @return {function} Function that invokes the two argument functions.
79500 * @private
79501 */
79502function createMergedResultFunction(one, two) {
79503  return function mergedResult() {
79504    var a = one.apply(this, arguments);
79505    var b = two.apply(this, arguments);
79506    if (a == null) {
79507      return b;
79508    } else if (b == null) {
79509      return a;
79510    }
79511    var c = {};
79512    mergeIntoWithNoDuplicateKeys(c, a);
79513    mergeIntoWithNoDuplicateKeys(c, b);
79514    return c;
79515  };
79516}
79517
79518/**
79519 * Creates a function that invokes two functions and ignores their return vales.
79520 *
79521 * @param {function} one Function to invoke first.
79522 * @param {function} two Function to invoke second.
79523 * @return {function} Function that invokes the two argument functions.
79524 * @private
79525 */
79526function createChainedFunction(one, two) {
79527  return function chainedFunction() {
79528    one.apply(this, arguments);
79529    two.apply(this, arguments);
79530  };
79531}
79532
79533/**
79534 * Binds a method to the component.
79535 *
79536 * @param {object} component Component whose method is going to be bound.
79537 * @param {function} method Method to be bound.
79538 * @return {function} The bound method.
79539 */
79540function bindAutoBindMethod(component, method) {
79541  var boundMethod = method.bind(component);
79542  if ("development" !== 'production') {
79543    boundMethod.__reactBoundContext = component;
79544    boundMethod.__reactBoundMethod = method;
79545    boundMethod.__reactBoundArguments = null;
79546    var componentName = component.constructor.displayName;
79547    var _bind = boundMethod.bind;
79548    boundMethod.bind = function (newThis) {
79549      for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
79550        args[_key - 1] = arguments[_key];
79551      }
79552
79553      // User is trying to bind() an autobound method; we effectively will
79554      // ignore the value of "this" that the user is trying to use, so
79555      // let's warn.
79556      if (newThis !== component && newThis !== null) {
79557        "development" !== 'production' ? warning(false, 'bind(): React component methods may only be bound to the ' + 'component instance. See %s', componentName) : void 0;
79558      } else if (!args.length) {
79559        "development" !== 'production' ? warning(false, 'bind(): You are binding a component method to the component. ' + 'React does this for you automatically in a high-performance ' + 'way, so you can safely remove this call. See %s', componentName) : void 0;
79560        return boundMethod;
79561      }
79562      var reboundMethod = _bind.apply(boundMethod, arguments);
79563      reboundMethod.__reactBoundContext = component;
79564      reboundMethod.__reactBoundMethod = method;
79565      reboundMethod.__reactBoundArguments = args;
79566      return reboundMethod;
79567    };
79568  }
79569  return boundMethod;
79570}
79571
79572/**
79573 * Binds all auto-bound methods in a component.
79574 *
79575 * @param {object} component Component whose method is going to be bound.
79576 */
79577function bindAutoBindMethods(component) {
79578  var pairs = component.__reactAutoBindPairs;
79579  for (var i = 0; i < pairs.length; i += 2) {
79580    var autoBindKey = pairs[i];
79581    var method = pairs[i + 1];
79582    component[autoBindKey] = bindAutoBindMethod(component, method);
79583  }
79584}
79585
79586/**
79587 * Add more to the ReactClass base class. These are all legacy features and
79588 * therefore not already part of the modern ReactComponent.
79589 */
79590var ReactClassMixin = {
79591
79592  /**
79593   * TODO: This will be deprecated because state should always keep a consistent
79594   * type signature and the only use case for this, is to avoid that.
79595   */
79596  replaceState: function (newState, callback) {
79597    this.updater.enqueueReplaceState(this, newState);
79598    if (callback) {
79599      this.updater.enqueueCallback(this, callback, 'replaceState');
79600    }
79601  },
79602
79603  /**
79604   * Checks whether or not this composite component is mounted.
79605   * @return {boolean} True if mounted, false otherwise.
79606   * @protected
79607   * @final
79608   */
79609  isMounted: function () {
79610    return this.updater.isMounted(this);
79611  }
79612};
79613
79614var ReactClassComponent = function () {};
79615_assign(ReactClassComponent.prototype, ReactComponent.prototype, ReactClassMixin);
79616
79617/**
79618 * Module for creating composite components.
79619 *
79620 * @class ReactClass
79621 */
79622var ReactClass = {
79623
79624  /**
79625   * Creates a composite component class given a class specification.
79626   *
79627   * @param {object} spec Class specification (which must define `render`).
79628   * @return {function} Component constructor function.
79629   * @public
79630   */
79631  createClass: function (spec) {
79632    var Constructor = function (props, context, updater) {
79633      // This constructor gets overridden by mocks. The argument is used
79634      // by mocks to assert on what gets mounted.
79635
79636      if ("development" !== 'production') {
79637        "development" !== 'production' ? warning(this instanceof Constructor, 'Something is calling a React component directly. Use a factory or ' + 'JSX instead. See: https://fb.me/react-legacyfactory') : void 0;
79638      }
79639
79640      // Wire up auto-binding
79641      if (this.__reactAutoBindPairs.length) {
79642        bindAutoBindMethods(this);
79643      }
79644
79645      this.props = props;
79646      this.context = context;
79647      this.refs = emptyObject;
79648      this.updater = updater || ReactNoopUpdateQueue;
79649
79650      this.state = null;
79651
79652      // ReactClasses doesn't have constructors. Instead, they use the
79653      // getInitialState and componentWillMount methods for initialization.
79654
79655      var initialState = this.getInitialState ? this.getInitialState() : null;
79656      if ("development" !== 'production') {
79657        // We allow auto-mocks to proceed as if they're returning null.
79658        if (initialState === undefined && this.getInitialState._isMockFunction) {
79659          // This is probably bad practice. Consider warning here and
79660          // deprecating this convenience.
79661          initialState = null;
79662        }
79663      }
79664      !(typeof initialState === 'object' && !Array.isArray(initialState)) ? "development" !== 'production' ? invariant(false, '%s.getInitialState(): must return an object or null', Constructor.displayName || 'ReactCompositeComponent') : invariant(false) : void 0;
79665
79666      this.state = initialState;
79667    };
79668    Constructor.prototype = new ReactClassComponent();
79669    Constructor.prototype.constructor = Constructor;
79670    Constructor.prototype.__reactAutoBindPairs = [];
79671
79672    injectedMixins.forEach(mixSpecIntoComponent.bind(null, Constructor));
79673
79674    mixSpecIntoComponent(Constructor, spec);
79675
79676    // Initialize the defaultProps property after all mixins have been merged.
79677    if (Constructor.getDefaultProps) {
79678      Constructor.defaultProps = Constructor.getDefaultProps();
79679    }
79680
79681    if ("development" !== 'production') {
79682      // This is a tag to indicate that the use of these method names is ok,
79683      // since it's used with createClass. If it's not, then it's likely a
79684      // mistake so we'll warn you to use the static property, property
79685      // initializer or constructor respectively.
79686      if (Constructor.getDefaultProps) {
79687        Constructor.getDefaultProps.isReactClassApproved = {};
79688      }
79689      if (Constructor.prototype.getInitialState) {
79690        Constructor.prototype.getInitialState.isReactClassApproved = {};
79691      }
79692    }
79693
79694    !Constructor.prototype.render ? "development" !== 'production' ? invariant(false, 'createClass(...): Class specification must implement a `render` method.') : invariant(false) : void 0;
79695
79696    if ("development" !== 'production') {
79697      "development" !== 'production' ? warning(!Constructor.prototype.componentShouldUpdate, '%s has a method called ' + 'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' + 'The name is phrased as a question because the function is ' + 'expected to return a value.', spec.displayName || 'A component') : void 0;
79698      "development" !== 'production' ? warning(!Constructor.prototype.componentWillRecieveProps, '%s has a method called ' + 'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?', spec.displayName || 'A component') : void 0;
79699    }
79700
79701    // Reduce time spent doing lookups by setting these on the prototype.
79702    for (var methodName in ReactClassInterface) {
79703      if (!Constructor.prototype[methodName]) {
79704        Constructor.prototype[methodName] = null;
79705      }
79706    }
79707
79708    return Constructor;
79709  },
79710
79711  injection: {
79712    injectMixin: function (mixin) {
79713      injectedMixins.push(mixin);
79714    }
79715  }
79716
79717};
79718
79719module.exports = ReactClass;
79720},{"151":151,"158":158,"161":161,"162":162,"168":168,"169":169,"31":31,"62":62,"80":80,"83":83,"84":84}],31:[function(_dereq_,module,exports){
79721/**
79722 * Copyright 2013-present, Facebook, Inc.
79723 * All rights reserved.
79724 *
79725 * This source code is licensed under the BSD-style license found in the
79726 * LICENSE file in the root directory of this source tree. An additional grant
79727 * of patent rights can be found in the PATENTS file in the same directory.
79728 *
79729 * @providesModule ReactComponent
79730 */
79731
79732
79733
79734var ReactNoopUpdateQueue = _dereq_(80);
79735var ReactInstrumentation = _dereq_(72);
79736
79737var canDefineProperty = _dereq_(116);
79738var emptyObject = _dereq_(151);
79739var invariant = _dereq_(158);
79740var warning = _dereq_(168);
79741
79742/**
79743 * Base class helpers for the updating state of a component.
79744 */
79745function ReactComponent(props, context, updater) {
79746  this.props = props;
79747  this.context = context;
79748  this.refs = emptyObject;
79749  // We initialize the default updater but the real one gets injected by the
79750  // renderer.
79751  this.updater = updater || ReactNoopUpdateQueue;
79752}
79753
79754ReactComponent.prototype.isReactComponent = {};
79755
79756/**
79757 * Sets a subset of the state. Always use this to mutate
79758 * state. You should treat `this.state` as immutable.
79759 *
79760 * There is no guarantee that `this.state` will be immediately updated, so
79761 * accessing `this.state` after calling this method may return the old value.
79762 *
79763 * There is no guarantee that calls to `setState` will run synchronously,
79764 * as they may eventually be batched together.  You can provide an optional
79765 * callback that will be executed when the call to setState is actually
79766 * completed.
79767 *
79768 * When a function is provided to setState, it will be called at some point in
79769 * the future (not synchronously). It will be called with the up to date
79770 * component arguments (state, props, context). These values can be different
79771 * from this.* because your function may be called after receiveProps but before
79772 * shouldComponentUpdate, and this new state, props, and context will not yet be
79773 * assigned to this.
79774 *
79775 * @param {object|function} partialState Next partial state or function to
79776 *        produce next partial state to be merged with current state.
79777 * @param {?function} callback Called after state is updated.
79778 * @final
79779 * @protected
79780 */
79781ReactComponent.prototype.setState = function (partialState, callback) {
79782  !(typeof partialState === 'object' || typeof partialState === 'function' || partialState == null) ? "development" !== 'production' ? invariant(false, 'setState(...): takes an object of state variables to update or a ' + 'function which returns an object of state variables.') : invariant(false) : void 0;
79783  if ("development" !== 'production') {
79784    ReactInstrumentation.debugTool.onSetState();
79785    "development" !== 'production' ? warning(partialState != null, 'setState(...): You passed an undefined or null state object; ' + 'instead, use forceUpdate().') : void 0;
79786  }
79787  this.updater.enqueueSetState(this, partialState);
79788  if (callback) {
79789    this.updater.enqueueCallback(this, callback, 'setState');
79790  }
79791};
79792
79793/**
79794 * Forces an update. This should only be invoked when it is known with
79795 * certainty that we are **not** in a DOM transaction.
79796 *
79797 * You may want to call this when you know that some deeper aspect of the
79798 * component's state has changed but `setState` was not called.
79799 *
79800 * This will not invoke `shouldComponentUpdate`, but it will invoke
79801 * `componentWillUpdate` and `componentDidUpdate`.
79802 *
79803 * @param {?function} callback Called after update is complete.
79804 * @final
79805 * @protected
79806 */
79807ReactComponent.prototype.forceUpdate = function (callback) {
79808  this.updater.enqueueForceUpdate(this);
79809  if (callback) {
79810    this.updater.enqueueCallback(this, callback, 'forceUpdate');
79811  }
79812};
79813
79814/**
79815 * Deprecated APIs. These APIs used to exist on classic React classes but since
79816 * we would like to deprecate them, we're not going to move them over to this
79817 * modern base class. Instead, we define a getter that warns if it's accessed.
79818 */
79819if ("development" !== 'production') {
79820  var deprecatedAPIs = {
79821    isMounted: ['isMounted', 'Instead, make sure to clean up subscriptions and pending requests in ' + 'componentWillUnmount to prevent memory leaks.'],
79822    replaceState: ['replaceState', 'Refactor your code to use setState instead (see ' + 'https://github.com/facebook/react/issues/3236).']
79823  };
79824  var defineDeprecationWarning = function (methodName, info) {
79825    if (canDefineProperty) {
79826      Object.defineProperty(ReactComponent.prototype, methodName, {
79827        get: function () {
79828          "development" !== 'production' ? warning(false, '%s(...) is deprecated in plain JavaScript React classes. %s', info[0], info[1]) : void 0;
79829          return undefined;
79830        }
79831      });
79832    }
79833  };
79834  for (var fnName in deprecatedAPIs) {
79835    if (deprecatedAPIs.hasOwnProperty(fnName)) {
79836      defineDeprecationWarning(fnName, deprecatedAPIs[fnName]);
79837    }
79838  }
79839}
79840
79841module.exports = ReactComponent;
79842},{"116":116,"151":151,"158":158,"168":168,"72":72,"80":80}],32:[function(_dereq_,module,exports){
79843/**
79844 * Copyright 2013-present, Facebook, Inc.
79845 * All rights reserved.
79846 *
79847 * This source code is licensed under the BSD-style license found in the
79848 * LICENSE file in the root directory of this source tree. An additional grant
79849 * of patent rights can be found in the PATENTS file in the same directory.
79850 *
79851 * @providesModule ReactComponentBrowserEnvironment
79852 */
79853
79854
79855
79856var DOMChildrenOperations = _dereq_(7);
79857var ReactDOMIDOperations = _dereq_(46);
79858var ReactPerf = _dereq_(82);
79859
79860/**
79861 * Abstracts away all functionality of the reconciler that requires knowledge of
79862 * the browser context. TODO: These callers should be refactored to avoid the
79863 * need for this injection.
79864 */
79865var ReactComponentBrowserEnvironment = {
79866
79867  processChildrenUpdates: ReactDOMIDOperations.dangerouslyProcessChildrenUpdates,
79868
79869  replaceNodeWithMarkup: DOMChildrenOperations.dangerouslyReplaceNodeWithMarkup,
79870
79871  /**
79872   * If a particular environment requires that some resources be cleaned up,
79873   * specify this in the injected Mixin. In the DOM, we would likely want to
79874   * purge any cached node ID lookups.
79875   *
79876   * @private
79877   */
79878  unmountIDFromEnvironment: function (rootNodeID) {}
79879
79880};
79881
79882ReactPerf.measureMethods(ReactComponentBrowserEnvironment, 'ReactComponentBrowserEnvironment', {
79883  replaceNodeWithMarkup: 'replaceNodeWithMarkup'
79884});
79885
79886module.exports = ReactComponentBrowserEnvironment;
79887},{"46":46,"7":7,"82":82}],33:[function(_dereq_,module,exports){
79888/**
79889 * Copyright 2014-present, Facebook, Inc.
79890 * All rights reserved.
79891 *
79892 * This source code is licensed under the BSD-style license found in the
79893 * LICENSE file in the root directory of this source tree. An additional grant
79894 * of patent rights can be found in the PATENTS file in the same directory.
79895 *
79896 * @providesModule ReactComponentEnvironment
79897 */
79898
79899
79900
79901var invariant = _dereq_(158);
79902
79903var injected = false;
79904
79905var ReactComponentEnvironment = {
79906
79907  /**
79908   * Optionally injectable environment dependent cleanup hook. (server vs.
79909   * browser etc). Example: A browser system caches DOM nodes based on component
79910   * ID and must remove that cache entry when this instance is unmounted.
79911   */
79912  unmountIDFromEnvironment: null,
79913
79914  /**
79915   * Optionally injectable hook for swapping out mount images in the middle of
79916   * the tree.
79917   */
79918  replaceNodeWithMarkup: null,
79919
79920  /**
79921   * Optionally injectable hook for processing a queue of child updates. Will
79922   * later move into MultiChildComponents.
79923   */
79924  processChildrenUpdates: null,
79925
79926  injection: {
79927    injectEnvironment: function (environment) {
79928      !!injected ? "development" !== 'production' ? invariant(false, 'ReactCompositeComponent: injectEnvironment() can only be called once.') : invariant(false) : void 0;
79929      ReactComponentEnvironment.unmountIDFromEnvironment = environment.unmountIDFromEnvironment;
79930      ReactComponentEnvironment.replaceNodeWithMarkup = environment.replaceNodeWithMarkup;
79931      ReactComponentEnvironment.processChildrenUpdates = environment.processChildrenUpdates;
79932      injected = true;
79933    }
79934  }
79935
79936};
79937
79938module.exports = ReactComponentEnvironment;
79939},{"158":158}],34:[function(_dereq_,module,exports){
79940/**
79941 * Copyright 2013-present, Facebook, Inc.
79942 * All rights reserved.
79943 *
79944 * This source code is licensed under the BSD-style license found in the
79945 * LICENSE file in the root directory of this source tree. An additional grant
79946 * of patent rights can be found in the PATENTS file in the same directory.
79947 *
79948 * @providesModule ReactCompositeComponent
79949 */
79950
79951
79952
79953var _assign = _dereq_(169);
79954
79955var ReactComponentEnvironment = _dereq_(33);
79956var ReactCurrentOwner = _dereq_(35);
79957var ReactElement = _dereq_(62);
79958var ReactErrorUtils = _dereq_(65);
79959var ReactInstanceMap = _dereq_(71);
79960var ReactInstrumentation = _dereq_(72);
79961var ReactNodeTypes = _dereq_(79);
79962var ReactPerf = _dereq_(82);
79963var ReactPropTypeLocations = _dereq_(84);
79964var ReactPropTypeLocationNames = _dereq_(83);
79965var ReactReconciler = _dereq_(87);
79966var ReactUpdateQueue = _dereq_(93);
79967
79968var emptyObject = _dereq_(151);
79969var invariant = _dereq_(158);
79970var shouldUpdateReactComponent = _dereq_(140);
79971var warning = _dereq_(168);
79972
79973function getDeclarationErrorAddendum(component) {
79974  var owner = component._currentElement._owner || null;
79975  if (owner) {
79976    var name = owner.getName();
79977    if (name) {
79978      return ' Check the render method of `' + name + '`.';
79979    }
79980  }
79981  return '';
79982}
79983
79984function StatelessComponent(Component) {}
79985StatelessComponent.prototype.render = function () {
79986  var Component = ReactInstanceMap.get(this)._currentElement.type;
79987  var element = Component(this.props, this.context, this.updater);
79988  warnIfInvalidElement(Component, element);
79989  return element;
79990};
79991
79992function warnIfInvalidElement(Component, element) {
79993  if ("development" !== 'production') {
79994    "development" !== 'production' ? warning(element === null || element === false || ReactElement.isValidElement(element), '%s(...): A val
79994id React element (or null) must be returned. You may have ' + 'returned undefined, an array or some other invalid object.', Component.displayName || Component.name || 'Component') : void 0;
79995  }
79996}
79997
79998function shouldConstruct(Component) {
79999  return Component.prototype && Component.prototype.isReactComponent;
80000}
80001
80002/**
80003 * ------------------ The Life-Cycle of a Composite Component ------------------
80004 *
80005 * - constructor: Initialization of state. The instance is now retained.
80006 *   - componentWillMount
80007 *   - render
80008 *   - [children's constructors]
80009 *     - [children's componentWillMount and render]
80010 *     - [children's componentDidMount]
80011 *     - componentDidMount
80012 *
80013 *       Update Phases:
80014 *       - componentWillReceiveProps (only called if parent updated)
80015 *       - shouldComponentUpdate
80016 *         - componentWillUpdate
80017 *           - render
80018 *           - [children's constructors or receive props phases]
80019 *         - componentDidUpdate
80020 *
80021 *     - componentWillUnmount
80022 *     - [children's componentWillUnmount]
80023 *   - [children destroyed]
80024 * - (destroyed): The instance is now blank, released by React and ready for GC.
80025 *
80026 * -----------------------------------------------------------------------------
80027 */
80028
80029/**
80030 * An incrementing ID assigned to each component when it is mounted. This is
80031 * used to enforce the order in which `ReactUpdates` updates dirty components.
80032 *
80033 * @private
80034 */
80035var nextMountID = 1;
80036
80037/**
80038 * @lends {ReactCompositeComponent.prototype}
80039 */
80040var ReactCompositeComponentMixin = {
80041
80042  /**
80043   * Base constructor for all composite component.
80044   *
80045   * @param {ReactElement} element
80046   * @final
80047   * @internal
80048   */
80049  construct: function (element) {
80050    this._currentElement = element;
80051    this._rootNodeID = null;
80052    this._instance = null;
80053    this._nativeParent = null;
80054    this._nativeContainerInfo = null;
80055
80056    // See ReactUpdateQueue
80057    this._pendingElement = null;
80058    this._pendingStateQueue = null;
80059    this._pendingReplaceState = false;
80060    this._pendingForceUpdate = false;
80061
80062    this._renderedNodeType = null;
80063    this._renderedComponent = null;
80064    this._context = null;
80065    this._mountOrder = 0;
80066    this._topLevelWrapper = null;
80067
80068    // See ReactUpdates and ReactUpdateQueue.
80069    this._pendingCallbacks = null;
80070
80071    // ComponentWillUnmount shall only be called once
80072    this._calledComponentWillUnmount = false;
80073  },
80074
80075  /**
80076   * Initializes the component, renders markup, and registers event listeners.
80077   *
80078   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
80079   * @param {?object} nativeParent
80080   * @param {?object} nativeContainerInfo
80081   * @param {?object} context
80082   * @return {?string} Rendered markup to be inserted into the DOM.
80083   * @final
80084   * @internal
80085   */
80086  mountComponent: function (transaction, nativeParent, nativeContainerInfo, context) {
80087    this._context = context;
80088    this._mountOrder = nextMountID++;
80089    this._nativeParent = nativeParent;
80090    this._nativeContainerInfo = nativeContainerInfo;
80091
80092    var publicProps = this._processProps(this._currentElement.props);
80093    var publicContext = this._processContext(context);
80094
80095    var Component = this._currentElement.type;
80096
80097    // Initialize the public class
80098    var inst = this._constructComponent(publicProps, publicContext);
80099    var renderedElement;
80100
80101    // Support functional components
80102    if (!shouldConstruct(Component) && (inst == null || inst.render == null)) {
80103      renderedElement = inst;
80104      warnIfInvalidElement(Component, renderedElement);
80105      !(inst === null || inst === false || ReactElement.isValidElement(inst)) ? "development" !== 'production' ? invariant(false, '%s(...): A val
80105id React element (or null) must be returned. You may have ' + 'returned undefined, an array or some other invalid object.', Component.displayName || Component.name || 'Component') : invariant(false) : void 0;
80106      inst = new StatelessComponent(Component);
80107    }
80108
80109    if ("development" !== 'production') {
80110      // This will throw later in _renderValidatedComponent, but add an early
80111      // warning now to help debugging
80112      if (inst.render == null) {
80113        "development" !== 'production' ? warning(false, '%s(...): No `render` method found on the returned component ' + 'instance: you may have forgotten to define `render`.', Component.displayName || Component.name || 'Component') : void 0;
80114      }
80115
80116      var propsMutated = inst.props !== publicProps;
80117      var componentName = Component.displayName || Component.name || 'Component';
80118
80119      "development" !== 'production' ? warning(inst.props === undefined || !propsMutated, '%s(...): When calling super() in `%s`, make sure to pass ' + 'up the same props that your component\'s constructor was passed.', componentName, componentName) : void 0;
80120    }
80121
80122    // These should be set up in the constructor, but as a convenience for
80123    // simpler class abstractions, we set them up after the fact.
80124    inst.props = publicProps;
80125    inst.context = publicContext;
80126    inst.refs = emptyObject;
80127    inst.updater = ReactUpdateQueue;
80128
80129    this._instance = inst;
80130
80131    // Store a reference from the instance back to the internal representation
80132    ReactInstanceMap.set(inst, this);
80133
80134    if ("development" !== 'production') {
80135      // Since plain JS classes are defined without any special initialization
80136      // logic, we can not catch common errors early. Therefore, we have to
80137      // catch them here, at initialization time, instead.
80138      "development" !== 'production' ? warning(!inst.getInitialState || inst.getInitialState.isReactClassApproved, 'getInitialState was defined on %s, a plain JavaScript class. ' + 'This is only supported for classes created using React.createClass. ' + 'Did you mean to define a state property instead?', this.getName() || 'a component') : void 0;
80139      "development" !== 'production' ? warning(!inst.getDefaultProps || inst.getDefaultProps.isReactClassApproved, 'getDefaultProps was defined on %s, a plain JavaScript class. ' + 'This is only supported for classes created using React.createClass. ' + 'Use a static property to define defaultProps instead.', this.getName() || 'a component') : void 0;
80140      "development" !== 'production' ? warning(!inst.propTypes, 'propTypes was defined as an instance property on %s. Use a static ' + 'property to define propTypes instead.', this.getName() || 'a component') : void 0;
80141      "development" !== 'production' ? warning(!inst.contextTypes, 'contextTypes was defined as an instance property on %s. Use a ' + 'static property to define contextTypes instead.', this.getName() || 'a component') : void 0;
80142      "development" !== 'production' ? warning(typeof inst.componentShouldUpdate !== 'function', '%s has a method called ' + 'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' + 'The name is phrased as a question because the function is ' + 'expected to return a value.', this.getName() || 'A c
80142omponent') : void 0;
80143      "development" !== 'production' ? warning(typeof inst.componentDidUnmount !== 'function', '%s has a method called ' + 'componentDidUnmount(). But there is no such lifecycle method. ' + 'Did you mean componentWillUnmount()?', this.getName() || 'A component') : void 0;
80144      "development" !== 'production' ? warning(typeof inst.componentWillRecieveProps !== 'function', '%s has a method called ' + 'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?', this.getName() || 'A component') : void 0;
80145    }
80146
80147    var initialState = inst.state;
80148    if (initialState === undefined) {
80149      inst.state = initialState = null;
80150    }
80151    !(typeof initialState === 'object' && !Array.isArray(initialState)) ? "development" !== 'production' ? invariant(false, '%s.state: must be set to an object or null', this.getName() || 'ReactCompositeComponent') : invariant(false) : void 0;
80152
80153    this._pendingStateQueue = null;
80154    this._pendingReplaceState = false;
80155    this._pendingForceUpdate = false;
80156
80157    var markup;
80158    if (inst.unstable_handleError) {
80159      markup = this.performInitialMountWithErrorHandling(renderedElement, nativeParent, nativeContainerInfo, transaction, context);
80160    } else {
80161      markup = this.performInitialMount(renderedElement, nativeParent, nativeContainerInfo, transaction, context);
80162    }
80163
80164    if (inst.componentDidMount) {
80165      transaction.getReactMountReady().enqueue(inst.componentDidMount, inst);
80166    }
80167
80168    return markup;
80169  },
80170
80171  _constructComponent: function (publicProps, publicContext) {
80172    if ("development" !== 'production') {
80173      ReactCurrentOwner.current = this;
80174      try {
80175        return this._constructComponentWithoutOwner(publicProps, publicContext);
80176      } finally {
80177        ReactCurrentOwner.current = null;
80178      }
80179    } else {
80180      return this._constructComponentWithoutOwner(publicProps, publicContext);
80181    }
80182  },
80183
80184  _constructComponentWithoutOwner: function (publicProps, publicContext) {
80185    var Component = this._currentElement.type;
80186    if (shouldConstruct(Component)) {
80187      return new Component(publicProps, publicContext, ReactUpdateQueue);
80188    } else {
80189      return Component(publicProps, publicContext, ReactUpdateQueue);
80190    }
80191  },
80192
80193  performInitialMountWithErrorHandling: function (renderedElement, nativeParent, nativeContainerInfo, transaction, context) {
80194    var markup;
80195    var checkpoint = transaction.checkpoint();
80196    try {
80197      markup = this.performInitialMount(renderedElement, nativeParent, nativeContainerInfo, transaction, context);
80198    } catch (e) {
80199      // Roll back to checkpoint, handle error (which may add items to the transaction), and take a new checkpoint
80200      transaction.rollback(checkpoint);
80201      this._instance.unstable_handleError(e);
80202      if (this._pendingStateQueue) {
80203        this._instance.state = this._processPendingState(this._instance.props, this._instance.context);
80204      }
80205      checkpoint = transaction.checkpoint();
80206
80207      this._renderedComponent.unmountComponent(true);
80208      transaction.rollback(checkpoint);
80209
80210      // Try again - we've informed the component about the error, so they can render an error message this time.
80211      // If this throws again, the error will bubble up (and can be caught by a higher error boundary).
80212      markup = this.performInitialMount(renderedElement, nativeParent, nativeContainerInfo, transaction, context);
80213    }
80214    return markup;
80215  },
80216
80217  performInitialMount: function (renderedElement, nativeParent, nativeContainerInfo, transaction, context) {
80218    var inst = this._instance;
80219    if (inst.componentWillMount) {
80220      inst.componentWillMount();
80221      // When mounting, calls to `setState` by `componentWillMount` will set
80222      // `this._pendingStateQueue` without triggering a re-render.
80223      if (this._pendingStateQueue) {
80224        inst.state = this._processPendingState(inst.props, inst.context);
80225      }
80226    }
80227
80228    // If not a stateless component, we now render
80229    if (renderedElement === undefined) {
80230      renderedElement = this._renderValidatedComponent();
80231    }
80232
80233    this._renderedNodeType = ReactNodeTypes.getType(renderedElement);
80234    this._renderedComponent = this._instantiateReactComponent(renderedElement);
80235
80236    var markup = ReactReconciler.mountComponent(this._renderedComponent, transaction, nativeParent, nativeContainerInfo, this._processChildContext(context));
80237
80238    return markup;
80239  },
80240
80241  getNativeNode: function () {
80242    return ReactReconciler.getNativeNode(this._renderedComponent);
80243  },
80244
80245  /**
80246   * Releases any resources allocated by `mountComponent`.
80247   *
80248   * @final
80249   * @internal
80250   */
80251  unmountComponent: function (safely) {
80252    if (!this._renderedComponent) {
80253      return;
80254    }
80255    var inst = this._instance;
80256
80257    if (inst.componentWillUnmount && !inst._calledComponentWillUnmount) {
80258      inst._calledComponentWillUnmount = true;
80259      if (safely) {
80260        var name = this.getName() + '.componentWillUnmount()';
80261        ReactErrorUtils.invokeGuardedCallback(name, inst.componentWillUnmount.bind(inst));
80262      } else {
80263        inst.componentWillUnmount();
80264      }
80265    }
80266
80267    if (this._renderedComponent) {
80268      ReactReconciler.unmountComponent(this._renderedComponent, safely);
80269      this._renderedNodeType = null;
80270      this._renderedComponent = null;
80271      this._instance = null;
80272    }
80273
80274    // Reset pending fields
80275    // Even if this component is scheduled for another update in ReactUpdates,
80276    // it would still be ignored because these fields are reset.
80277    this._pendingStateQueue = null;
80278    this._pendingReplaceState = false;
80279    this._pendingForceUpdate = false;
80280    this._pendingCallbacks = null;
80281    this._pendingElement = null;
80282
80283    // These fields do not really need to be reset since this object is no
80284    // longer accessible.
80285    this._context = null;
80286    this._rootNodeID = null;
80287    this._topLevelWrapper = null;
80288
80289    // Delete the reference from the instance to this internal representation
80290    // which allow the internals to be properly cleaned up even if the user
80291    // leaks a reference to the public instance.
80292    ReactInstanceMap.remove(inst);
80293
80294    // Some existing components rely on inst.props even after they've been
80295    // destroyed (in event handlers).
80296    // TODO: inst.props = null;
80297    // TODO: inst.state = null;
80298    // TODO: inst.context = null;
80299  },
80300
80301  /**
80302   * Filters the context object to only contain keys specified in
80303   * `contextTypes`
80304   *
80305   * @param {object} context
80306   * @return {?object}
80307   * @private
80308   */
80309  _maskContext: function (context) {
80310    var Component = this._currentElement.type;
80311    var contextTypes = Component.contextTypes;
80312    if (!contextTypes) {
80313      return emptyObject;
80314    }
80315    var maskedContext = {};
80316    for (var contextName in contextTypes) {
80317      maskedContext[contextName] = context[contextName];
80318    }
80319    return maskedContext;
80320  },
80321
80322  /**
80323   * Filters the context object to only contain keys specified in
80324   * `contextTypes`, and asserts that they are valid.
80325   *
80326   * @param {object} context
80327   * @return {?object}
80328   * @private
80329   */
80330  _processContext: function (context) {
80331    var maskedContext = this._maskContext(context);
80332    if ("development" !== 'production') {
80333      var Component = this._currentElement.type;
80334      if (Component.contextTypes) {
80335        this._checkPropTypes(Component.contextTypes, maskedContext, ReactPropTypeLocations.context);
80336      }
80337    }
80338    return maskedContext;
80339  },
80340
80341  /**
80342   * @param {object} currentContext
80343   * @return {object}
80344   * @private
80345   */
80346  _processChildContext: function (currentContext) {
80347    var Component = this._currentElement.type;
80348    var inst = this._instance;
80349    if ("development" !== 'production') {
80350      ReactInstrumentation.debugTool.onBeginProcessingChildContext();
80351    }
80352    var childContext = inst.getChildContext && inst.getChildContext();
80353    if ("development" !== 'production') {
80354      ReactInstrumentation.debugTool.onEndProcessingChildContext();
80355    }
80356    if (childContext) {
80357      !(typeof Component.childContextTypes === 'object') ? "development" !== 'production' ? invariant(false, '%s.getChildContext(): childContextTypes must be defined in order to ' + 'use getChildContext().', this.getName() || 'ReactCompositeComponent') : invariant(false) : void 0;
80358      if ("development" !== 'production') {
80359        this._checkPropTypes(Component.childContextTypes, childContext, ReactPropTypeLocations.childContext);
80360      }
80361      for (var name in childContext) {
80362        !(name in Component.childContextTypes) ? "development" !== 'production' ? invariant(false, '%s.getChildContext(): key "%s" is not defined in childContextTypes.', this.getName() || 'ReactCompositeComponent', name) : invariant(false) : void 0;
80363      }
80364      return _assign({}, currentContext, childContext);
80365    }
80366    return currentContext;
80367  },
80368
80369  /**
80370   * Processes props by setting default values for unspecified props and
80371   * asserting that the props are valid. Does not mutate its argument; returns
80372   * a new props object with defaults merged in.
80373   *
80374   * @param {object} newProps
80375   * @return {object}
80376   * @private
80377   */
80378  _processProps: function (newProps) {
80379    if ("development" !== 'production') {
80380      var Component = this._currentElement.type;
80381      if (Component.propTypes) {
80382        this._checkPropTypes(Component.propTypes, newProps, ReactPropTypeLocations.prop);
80383      }
80384    }
80385    return newProps;
80386  },
80387
80388  /**
80389   * Assert that the props are valid
80390   *
80391   * @param {object} propTypes Map of prop name to a ReactPropType
80392   * @param {object} props
80393   * @param {string} location e.g. "prop", "context", "child context"
80394   * @private
80395   */
80396  _checkPropTypes: function (propTypes, props, location) {
80397    // TODO: Stop validating prop types here and only use the element
80398    // validation.
80399    var componentName = this.getName();
80400    for (var propName in propTypes) {
80401      if (propTypes.hasOwnProperty(propName)) {
80402        var error;
80403        try {
80404          // This is intentionally an invariant that gets caught. It's the same
80405          // behavior as without this statement except with a better message.
80406          !(typeof propTypes[propName] === 'function') ? "development" !== 'production' ? invariant(false, '%s: %s type `%s` is invali
80406d; it must be a function, usually ' + 'from React.PropTypes.', componentName || 'React class', ReactPropTypeLocationNames[location], propName) : invariant(false) : void 0;
80407          error = propTypes[propName](props, propName, componentName, location);
80408        } catch (ex) {
80409          error = ex;
80410        }
80411        if (error instanceof Error) {
80412          // We may want to extend this logic for similar errors in
80413          // top-level render calls, so I'm abstracting it away into
80414          // a function to minimize refactoring in the future
80415          var addendum = getDeclarationErrorAddendum(this);
80416
80417          if (location === ReactPropTypeLocations.prop) {
80418            // Preface gives us something to blacklist in warning module
80419            "development" !== 'production' ? warning(false, 'Failed Composite propType: %s%s', error.message, addendum) : void 0;
80420          } else {
80421            "development" !== 'production' ? warning(false, 'Failed Context Types: %s%s', error.message, addendum) : void 0;
80422          }
80423        }
80424      }
80425    }
80426  },
80427
80428  receiveComponent: function (nextElement, transaction, nextContext) {
80429    var prevElement = this._currentElement;
80430    var prevContext = this._context;
80431
80432    this._pendingElement = null;
80433
80434    this.updateComponent(transaction, prevElement, nextElement, prevContext, nextContext);
80435  },
80436
80437  /**
80438   * If any of `_pendingElement`, `_pendingStateQueue`, or `_pendingForceUpdate`
80439   * is set, update the component.
80440   *
80441   * @param {ReactReconcileTransaction} transaction
80442   * @internal
80443   */
80444  performUpdateIfNecessary: function (transaction) {
80445    if (this._pendingElement != null) {
80446      ReactReconciler.receiveComponent(this, this._pendingElement, transaction, this._context);
80447    }
80448
80449    if (this._pendingStateQueue !== null || this._pendingForceUpdate) {
80450      this.updateComponent(transaction, this._currentElement, this._currentElement, this._context, this._context);
80451    }
80452  },
80453
80454  /**
80455   * Perform an update to a mounted component. The componentWillReceiveProps and
80456   * shouldComponentUpdate methods are called, then (assuming the update isn't
80457   * skipped) the remaining update lifecycle methods are called and the DOM
80458   * representation is updated.
80459   *
80460   * By default, this implements React's rendering and reconciliation algorithm.
80461   * Sophisticated clients may wish to override this.
80462   *
80463   * @param {ReactReconcileTransaction} transaction
80464   * @param {ReactElement} prevParentElement
80465   * @param {ReactElement} nextParentElement
80466   * @internal
80467   * @overridable
80468   */
80469  updateComponent: function (transaction, prevParentElement, nextParentElement, prevUnmaskedContext, nextUnmaskedContext) {
80470    var inst = this._instance;
80471    var willReceive = false;
80472    var nextContext;
80473    var nextProps;
80474
80475    // Determine if the context has changed or not
80476    if (this._context === nextUnmaskedContext) {
80477      nextContext = inst.context;
80478    } else {
80479      nextContext = this._processContext(nextUnmaskedContext);
80480      willReceive = true;
80481    }
80482
80483    // Distinguish between a props update versus a simple state update
80484    if (prevParentElement === nextParentElement) {
80485      // Skip checking prop types again -- we don't read inst.props to avoid
80486      // warning for DOM component props in this upgrade
80487      nextProps = nextParentElement.props;
80488    } else {
80489      nextProps = this._processProps(nextParentElement.props);
80490      willReceive = true;
80491    }
80492
80493    // An update here will schedule an update but immediately set
80494    // _pendingStateQueue which will ensure that any state updates gets
80495    // immediately reconciled instead of waiting for the next batch.
80496    if (willReceive && inst.componentWillReceiveProps) {
80497      inst.componentWillReceiveProps(nextProps, nextContext);
80498    }
80499
80500    var nextState = this._processPendingState(nextProps, nextContext);
80501
80502    var shouldUpdate = this._pendingForceUpdate || !inst.shouldComponentUpdate || inst.shouldComponentUpdate(nextProps, nextState, nextContext);
80503
80504    if ("development" !== 'production') {
80505      "development" !== 'production' ? warning(shouldUpdate !== undefined, '%s.shouldComponentUpdate(): Returned undefined instead of a ' + 'boolean value. Make sure to return true or false.', this.getName() || 'ReactCompositeComponent') : void 0;
80506    }
80507
80508    if (shouldUpdate) {
80509      this._pendingForceUpdate = false;
80510      // Will set `this.props`, `this.state` and `this.context`.
80511      this._performComponentUpdate(nextParentElement, nextProps, nextState, nextContext, transaction, nextUnmaskedContext);
80512    } else {
80513      // If it's determined that a component should not update, we still want
80514      // to set props and state but we shortcut the rest of the update.
80515      this._currentElement = nextParentElement;
80516      this._context = nextUnmaskedContext;
80517      inst.props = nextProps;
80518      inst.state = nextState;
80519      inst.context = nextContext;
80520    }
80521  },
80522
80523  _processPendingState: function (props, context) {
80524    var inst = this._instance;
80525    var queue = this._pendingStateQueue;
80526    var replace = this._pendingReplaceState;
80527    this._pendingReplaceState = false;
80528    this._pendingStateQueue = null;
80529
80530    if (!queue) {
80531      return inst.state;
80532    }
80533
80534    if (replace && queue.length === 1) {
80535      return queue[0];
80536    }
80537
80538    var nextState = _assign({}, replace ? queue[0] : inst.state);
80539    for (var i = replace ? 1 : 0; i < queue.length; i++) {
80540      var partial = queue[i];
80541      _assign(nextState, typeof partial === 'function' ? partial.call(inst, nextState, props, context) : partial);
80542    }
80543
80544    return nextState;
80545  },
80546
80547  /**
80548   * Merges new props and state, notifies delegate methods of update and
80549   * performs update.
80550   *
80551   * @param {ReactElement} nextElement Next element
80552   * @param {object} nextProps Next public object to set as properties.
80553   * @param {?object} nextState Next object to set as state.
80554   * @param {?object} nextContext Next public object to set as context.
80555   * @param {ReactReconcileTransaction} transaction
80556   * @param {?object} unmaskedContext
80557   * @private
80558   */
80559  _performComponentUpdate: function (nextElement, nextProps, nextState, nextContext, transaction, unmaskedContext) {
80560    var inst = this._instance;
80561
80562    var hasComponentDidUpdate = Boolean(inst.componentDidUpdate);
80563    var prevProps;
80564    var prevState;
80565    var prevContext;
80566    if (hasComponentDidUpdate) {
80567      prevProps = inst.props;
80568      prevState = inst.state;
80569      prevContext = inst.context;
80570    }
80571
80572    if (inst.componentWillUpdate) {
80573      inst.componentWillUpdate(nextProps, nextState, nextContext);
80574    }
80575
80576    this._currentElement = nextElement;
80577    this._context = unmaskedContext;
80578    inst.props = nextProps;
80579    inst.state = nextState;
80580    inst.context = nextContext;
80581
80582    this._updateRenderedComponent(transaction, unmaskedContext);
80583
80584    if (hasComponentDidUpdate) {
80585      transaction.getReactMountReady().enqueue(inst.componentDidUpdate.bind(inst, prevProps, prevState, prevContext), inst);
80586    }
80587  },
80588
80589  /**
80590   * Call the component's `render` method and update the DOM accordingly.
80591   *
80592   * @param {ReactReconcileTransaction} transaction
80593   * @internal
80594   */
80595  _updateRenderedComponent: function (transaction, context) {
80596    var prevComponentInstance = this._renderedComponent;
80597    var prevRenderedElement = prevComponentInstance._currentElement;
80598    var nextRenderedElement = this._renderValidatedComponent();
80599    if (shouldUpdateReactComponent(prevRenderedElement, nextRenderedElement)) {
80600      ReactReconciler.receiveComponent(prevComponentInstance, nextRenderedElement, transaction, this._processChildContext(context));
80601    } else {
80602      var oldNativeNode = ReactReconciler.getNativeNode(prevComponentInstance);
80603      ReactReconciler.unmountComponent(prevComponentInstance, false);
80604
80605      this._renderedNodeType = ReactNodeTypes.getType(nextRenderedElement);
80606      this._renderedComponent = this._instantiateReactComponent(nextRenderedElement);
80607      var nextMarkup = ReactReconciler.mountComponent(this._renderedComponent, transaction, this._nativeParent, this._nativeContainerInfo, this._processChildContext(context));
80608      this._replaceNodeWithMarkup(oldNativeNode, nextMarkup);
80609    }
80610  },
80611
80612  /**
80613   * Overridden in shallow rendering.
80614   *
80615   * @protected
80616   */
80617  _replaceNodeWithMarkup: function (oldNativeNode, nextMarkup) {
80618    ReactComponentEnvironment.replaceNodeWithMarkup(oldNativeNode, nextMarkup);
80619  },
80620
80621  /**
80622   * @protected
80623   */
80624  _renderValidatedComponentWithoutOwnerOrContext: function () {
80625    var inst = this._instance;
80626    var renderedComponent = inst.render();
80627    if ("development" !== 'production') {
80628      // We allow auto-mocks to proceed as if they're returning null.
80629      if (renderedComponent === undefined && inst.render._isMockFunction) {
80630        // This is probably bad practice. Consider warning here and
80631        // deprecating this convenience.
80632        renderedComponent = null;
80633      }
80634    }
80635
80636    return renderedComponent;
80637  },
80638
80639  /**
80640   * @private
80641   */
80642  _renderValidatedComponent: function () {
80643    var renderedComponent;
80644    ReactCurrentOwner.current = this;
80645    try {
80646      renderedComponent = this._renderValidatedComponentWithoutOwnerOrContext();
80647    } finally {
80648      ReactCurrentOwner.current = null;
80649    }
80650    !(
80651    // TODO: An `isValidNode` function would probably be more appropriate
80652    renderedComponent === null || renderedComponent === false || ReactElement.isValidElement(renderedComponent)) ? "development" !== 'production' ? invariant(false, '%s.render(): A valid React element (or null) must be returned. You may have ' + 'returned undefined, an array or some other invalid object.', this.getName() || 'ReactCompositeComponent') : invariant(false) : void 0;
80653    return renderedComponent;
80654  },
80655
80656  /**
80657   * Lazily allocates the refs object and stores `component` as `ref`.
80658   *
80659   * @param {string} ref Reference name.
80660   * @param {component} component Component to store as `ref`.
80661   * @final
80662   * @private
80663   */
80664  attachRef: function (ref, component) {
80665    var inst = this.getPublicInstance();
80666    !(inst != null) ? "development" !== 'production' ? invariant(false, 'Stateless function components cannot have refs.') : invariant(false) : void 0;
80667    var publicComponentInstance = component.getPublicInstance();
80668    if ("development" !== 'production') {
80669      var componentName = component && component.getName ? component.getName() : 'a component';
80670      "development" !== 'production' ? warning(publicComponentInstance != null, 'Stateless function components cannot be given refs ' + '(See ref "%s" in %s created by %s). ' + 'Attempts to access this ref will fail.', ref, componentName, this.getName()) : void 0;
80671    }
80672    var refs = inst.refs === emptyObject ? inst.refs = {} : inst.refs;
80673    refs[ref] = publicComponentInstance;
80674  },
80675
80676  /**
80677   * Detaches a reference name.
80678   *
80679   * @param {string} ref Name to dereference.
80680   * @final
80681   * @private
80682   */
80683  detachRef: function (ref) {
80684    var refs = this.getPublicInstance().refs;
80685    delete refs[ref];
80686  },
80687
80688  /**
80689   * Get a text description of the component that can be used to identify it
80690   * in error messages.
80691   * @return {string} The name or null.
80692   * @internal
80693   */
80694  getName: function () {
80695    var type = this._currentElement.type;
80696    var constructor = this._instance && this._instance.constructor;
80697    return type.displayName || constructor && constructor.displayName || type.name || constructor && constructor.name || null;
80698  },
80699
80700  /**
80701   * Get the publicly accessible representation of this component - i.e. what
80702   * is exposed by refs and returned by render. Can be null for stateless
80703   * components.
80704   *
80705   * @return {ReactComponent} the public component instance.
80706   * @internal
80707   */
80708  getPublicInstance: function () {
80709    var inst = this._instance;
80710    if (inst instanceof StatelessComponent) {
80711      return null;
80712    }
80713    return inst;
80714  },
80715
80716  // Stub
80717  _instantiateReactComponent: null
80718
80719};
80720
80721ReactPerf.measureMethods(ReactCompositeComponentMixin, 'ReactCompositeComponent', {
80722  mountComponent: 'mountComponent',
80723  updateComponent: 'updateComponent',
80724  _renderValidatedComponent: '_renderValidatedComponent'
80725});
80726
80727var ReactCompositeComponent = {
80728
80729  Mixin: ReactCompositeComponentMixin
80730
80731};
80732
80733module.exports = ReactCompositeComponent;
80734},{"140":140,"151":151,"158":158,"168":168,"169":169,"33":33,"35":35,"62":62,"65":65,"71":71,"72":72,"79":79,"82":82,"83":83,"84":84,"87":87,"93":93}],35:[function(_dereq_,module,exports){
80735/**
80736 * Copyright 2013-present, Facebook, Inc.
80737 * All rights reserved.
80738 *
80739 * This source code is licensed under the BSD-style license found in the
80740 * LICENSE file in the root directory of this source tree. An additional grant
80741 * of patent rights can be found in the PATENTS file in the same directory.
80742 *
80743 * @providesModule ReactCurrentOwner
80744 */
80745
80746
80747
80748/**
80749 * Keeps track of the current owner.
80750 *
80751 * The current owner is the component who should own any components that are
80752 * currently being constructed.
80753 */
80754
80755var ReactCurrentOwner = {
80756
80757  /**
80758   * @internal
80759   * @type {ReactComponent}
80760   */
80761  current: null
80762
80763};
80764
80765module.exports = ReactCurrentOwner;
80766},{}],36:[function(_dereq_,module,exports){
80767/**
80768 * Copyright 2013-present, Facebook, Inc.
80769 * All rights reserved.
80770 *
80771 * This source code is licensed under the BSD-style license found in the
80772 * LICENSE file in the root directory of this source tree. An additional grant
80773 * of patent rights can be found in the PATENTS file in the same directory.
80774 *
80775 * @providesModule ReactDOM
80776 */
80777
80778/* globals __REACT_DEVTOOLS_GLOBAL_HOOK__*/
80779
80780
80781
80782var ReactDOMComponentTree = _dereq_(40);
80783var ReactDefaultInjection = _dereq_(59);
80784var ReactMount = _dereq_(75);
80785var ReactPerf = _dereq_(82);
80786var ReactReconciler = _dereq_(87);
80787var ReactUpdates = _dereq_(94);
80788var ReactVersion = _dereq_(95);
80789
80790var findDOMNode = _dereq_(120);
80791var getNativeComponentFromComposite = _dereq_(128);
80792var renderSubtreeIntoContainer = _dereq_(137);
80793var warning = _dereq_(168);
80794
80795ReactDefaultInjection.inject();
80796
80797var render = ReactPerf.measure('React', 'render', ReactMount.render);
80798
80799var React = {
80800  findDOMNode: findDOMNode,
80801  render: render,
80802  unmountComponentAtNode: ReactMount.unmountComponentAtNode,
80803  version: ReactVersion,
80804
80805  /* eslint-disable camelcase */
80806  unstable_batchedUpdates: ReactUpdates.batchedUpdates,
80807  unstable_renderSubtreeIntoContainer: renderSubtreeIntoContainer
80808};
80809
80810// Inject the runtime into a devtools global hook regardless of browser.
80811// Allows for debugging when the hook is injected on the page.
80812/* eslint-enable camelcase */
80813if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' && typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.inject === 'function') {
80814  __REACT_DEVTOOLS_GLOBAL_HOOK__.inject({
80815    ComponentTree: {
80816      getClosestInstanceFromNode: ReactDOMComponentTree.getClosestInstanceFromNode,
80817      getNodeFromInstance: function (inst) {
80818        // inst is an internal instance (but could be a composite)
80819        if (inst._renderedComponent) {
80820          inst = getNativeComponentFromComposite(inst);
80821        }
80822        if (inst) {
80823          return ReactDOMComponentTree.getNodeFromInstance(inst);
80824        } else {
80825          return null;
80826        }
80827      }
80828    },
80829    Mount: ReactMount,
80830    Reconciler: ReactReconciler
80831  });
80832}
80833
80834if ("development" !== 'production') {
80835  var ExecutionEnvironment = _dereq_(144);
80836  if (ExecutionEnvironment.canUseDOM && window.top === window.self) {
80837
80838    // First check if devtools is not installed
80839    if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined') {
80840      // If we're in Chrome or Firefox, provide a download link if not installed.
80841      if (navigator.userAgent.indexOf('Chrome') > -1 && navigator.userAgent.indexOf('Edge') === -1 || navigator.userAgent.indexOf('Firefox') > -1) {
80842        // Firefox does not have the issue with devtools loaded over file://
80843        var showFileUrlMessage = window.location.protocol.indexOf('http') === -1 && navigator.userAgent.indexOf('Firefox') === -1;
80844        console.debug('Download the React DevTools ' + (showFileUrlMessage ? 'and use an HTTP server (instead of a file: URL) ' : '') + 'for a better development experience: ' + 'https://fb.me/react-devtools');
80845      }
80846    }
80847
80848    var testFunc = function testFn() {};
80849    "development" !== 'production' ? warning((testFunc.name || testFunc.toString()).indexOf('testFn') !== -1, 'It looks like you\'re using a minified copy of the development build ' + 'of React. When deploying React apps to production, make sure to use ' + 'the production build which skips development warnings and is faster. ' + 'See https://fb.me/react-minification for more details.') : void 0;
80850
80851    // If we're in IE8, check to see if we are in compatibility mode and provide
80852    // information on preventing compatibility mode
80853    var ieCompatibilityMode = document.documentMode && document.documentMode < 8;
80854
80855    "development" !== 'production' ? warning(!ieCompatibilityMode, 'Internet Explorer is running in compatibility mode; please add the ' + 'following tag to your HTML to prevent this from happening: ' + '<meta http-equiv="X-UA-Compatible" content="IE=edge" />') : void 0;
80856
80857    var expectedFeatures = [
80858    // shims
80859    Array.isArray, Array.prototype.every, Array.prototype.forEach, Array.prototype.indexOf, Array.prototype.map, Date.now, Function.prototype.bind, Object.keys, String.prototype.split, String.prototype.trim];
80860
80861    for (var i = 0; i < expectedFeatures.length; i++) {
80862      if (!expectedFeatures[i]) {
80863        "development" !== 'production' ? warning(false, 'One or more ES5 shims expected by React are not available: ' + 'https://fb.me/react-warning-polyfills') : void 0;
80864        break;
80865      }
80866    }
80867  }
80868}
80869
80870module.exports = React;
80871},{"120":120,"128":128,"137":137,"144":144,"168":168,"40":40,"59":59,"75":75,"82":82,"87":87,"94":94,"95":95}],37:[function(_dereq_,module,exports){
80872/**
80873 * Copyright 2013-present, Facebook, Inc.
80874 * All rights reserved.
80875 *
80876 * This source code is licensed under the BSD-style license found in the
80877 * LICENSE file in the root directory of this source tree. An additional grant
80878 * of patent rights can be found in the PATENTS file in the same directory.
80879 *
80880 * @providesModule ReactDOMButton
80881 */
80882
80883
80884
80885var DisabledInputUtils = _dereq_(14);
80886
80887/**
80888 * Implements a <button> native component that does not receive mouse events
80889 * when `disabled` is set.
80890 */
80891var ReactDOMButton = {
80892  getNativeProps: DisabledInputUtils.getNativeProps
80893};
80894
80895module.exports = ReactDOMButton;
80896},{"14":14}],38:[function(_dereq_,module,exports){
80897/**
80898 * Copyright 2013-present, Facebook, Inc.
80899 * All rights reserved.
80900 *
80901 * This source code is licensed under the BSD-style license found in the
80902 * LICENSE file in the root directory of this source tree. An additional grant
80903 * of patent rights can be found in the PATENTS file in the same directory.
80904 *
80905 * @providesModule ReactDOMComponent
80906 */
80907
80908/* global hasOwnProperty:true */
80909
80910
80911
80912var _assign = _dereq_(169);
80913
80914var AutoFocusUtils = _dereq_(1);
80915var CSSPropertyOperations = _dereq_(4);
80916var DOMLazyTree = _dereq_(8);
80917var DOMNamespaces = _dereq_(9);
80918var DOMProperty = _dereq_(10);
80919var DOMPropertyOperations = _dereq_(11);
80920var EventConstants = _dereq_(16);
80921var EventPluginHub = _dereq_(17);
80922var EventPluginRegistry = _dereq_(18);
80923var ReactBrowserEventEmitter = _dereq_(27);
80924var ReactComponentBrowserEnvironment = _dereq_(32);
80925var ReactDOMButton = _dereq_(37);
80926var ReactDOMComponentFlags = _dereq_(39);
80927var ReactDOMComponentTree = _dereq_(40);
80928var ReactDOMInput = _dereq_(47);
80929var ReactDOMOption = _dereq_(49);
80930var ReactDOMSelect = _dereq_(50);
80931var ReactDOMTextarea = _dereq_(54);
80932var ReactMultiChild = _dereq_(76);
80933var ReactPerf = _dereq_(82);
80934
80935var escapeTextContentForBrowser = _dereq_(119);
80936var invariant = _dereq_(158);
80937var isEventSupported = _dereq_(133);
80938var keyOf = _dereq_(162);
80939var shallowEqual = _dereq_(167);
80940var validateDOMNesting = _dereq_(142);
80941var warning = _dereq_(168);
80942
80943var Flags = ReactDOMComponentFlags;
80944var deleteListener = EventPluginHub.deleteListener;
80945var getNode = ReactDOMComponentTree.getNodeFromInstance;
80946var listenTo = ReactBrowserEventEmitter.listenTo;
80947var registrationNameModules = EventPluginRegistry.registrationNameModules;
80948
80949// For quickly matching children type, to test if can be treated as content.
80950var CONTENT_TYPES = { 'string': true, 'number': true };
80951
80952var STYLE = keyOf({ style: null });
80953var HTML = keyOf({ __html: null });
80954var RESERVED_PROPS = {
80955  children: null,
80956  dangerouslySetInnerHTML: null,
80957  suppressContentEditableWarning: null
80958};
80959
80960// Node type for document fragments (Node.DOCUMENT_FRAGMENT_NODE).
80961var DOC_FRAGMENT_TYPE = 11;
80962
80963function getDeclarationErrorAddendum(internalInstance) {
80964  if (internalInstance) {
80965    var owner = internalInstance._currentElement._owner || null;
80966    if (owner) {
80967      var name = owner.getName();
80968      if (name) {
80969        return ' This DOM node was rendered by `' + name + '`.';
80970      }
80971    }
80972  }
80973  return '';
80974}
80975
80976function friendlyStringify(obj) {
80977  if (typeof obj === 'object') {
80978    if (Array.isArray(obj)) {
80979      return '[' + obj.map(friendlyStringify).join(', ') + ']';
80980    } else {
80981      var pairs = [];
80982      for (var key in obj) {
80983        if (Object.prototype.hasOwnProperty.call(obj, key)) {
80984          var keyEscaped = /^[a-z$_][\w$_]*$/i.test(key) ? key : JSON.stringify(key);
80985          pairs.push(keyEscaped + ': ' + friendlyStringify(obj[key]));
80986        }
80987      }
80988      return '{' + pairs.join(', ') + '}';
80989    }
80990  } else if (typeof obj === 'string') {
80991    return JSON.stringify(obj);
80992  } else if (typeof obj === 'function') {
80993    return '[function object]';
80994  }
80995  // Differs from JSON.stringify in that undefined because undefined and that
80996  // inf and nan don't become null
80997  return String(obj);
80998}
80999
81000var styleMutationWarning = {};
81001
81002function checkAndWarnForMutatedStyle(style1, style2, component) {
81003  if (style1 == null || style2 == null) {
81004    return;
81005  }
81006  if (shallowEqual(style1, style2)) {
81007    return;
81008  }
81009
81010  var componentName = component._tag;
81011  var owner = component._currentElement._owner;
81012  var ownerName;
81013  if (owner) {
81014    ownerName = owner.getName();
81015  }
81016
81017  var hash = ownerName + '|' + componentName;
81018
81019  if (styleMutationWarning.hasOwnProperty(hash)) {
81020    return;
81021  }
81022
81023  styleMutationWarning[hash] = true;
81024
81025  "development" !== 'production' ? warning(false, '`%s` was passed a style object that has previously been mutated. ' + 'Mutating `style` is deprecated. Consider cloning it beforehand. Check ' + 'the `render` %s. Previous style: %s. Mutated style: %s.', componentName, owner ? 'of `' + ownerName + '`' : 'using <' + componentName + '>', friendlyStringify(style1), friendlyStringify(style2)) : void 0;
81026}
81027
81028/**
81029 * @param {object} component
81030 * @param {?object} props
81031 */
81032function assertValidProps(component, props) {
81033  if (!props) {
81034    return;
81035  }
81036  // Note the use of `==` which checks for null or undefined.
81037  if (voidElementTags[component._tag]) {
81038    !(props.children == null && props.dangerouslySetInnerHTML == null) ? "development" !== 'production' ? invariant(false, '%s is a void element tag and must not have `children` or ' + 'use `props.dangerouslySetInnerHTML`.%s', component._tag, component._currentElement._owner ? ' Check the render method of ' + component._currentElement._owner.getName() + '.' : '') : invariant(false) : void 0;
81039  }
81040  if (props.dangerouslySetInnerHTML != null) {
81041    !(props.children == null) ? "development" !== 'production' ? invariant(false, 'Can only set one of `children` or `props.dangerouslySetInnerHTML`.') : invariant(false) : void 0;
81042    !(typeof props.dangerouslySetInnerHTML === 'object' && HTML in props.dangerouslySetInnerHTML) ? "development" !== 'production' ? invariant(false, '`props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. ' + 'Please visit https://fb.me/react-invariant-dangerously-set-inner-html ' + 'for more information.') : invariant(false) : void 0;
81043  }
81044  if ("development" !== 'production') {
81045    "development" !== 'production' ? warning(props.innerHTML == null, 'Directly setting property `innerHTML` is not permitted. ' + 'For more information, lookup documentation on `dangerouslySetInnerHTML`.') : void 0;
81046    "development" !== 'production' ? warning(props.suppressContentEditableWarning || !props.contentEditable || props.children == null, 'A component is `contentEditable` and contains `children` managed by ' + 'React. It is now your responsibility to guarantee that none of ' + 'those nodes are unexpectedly modified or duplicated. This is ' + 'probably not intentional.') : void 0;
81047    "development" !== 'production' ? warning(props.onFocusIn == null && props.onFocusOut == null, 'React uses onFocus and onBlur instead of onFocusIn and onFocusOut. ' + 'All React events are normalized to bubble, so onFocusIn and onFocusOut ' + 'are not needed/supported by React.') : void 0;
81048  }
81049  !(props.style == null || typeof props.style === 'object') ? "development" !== 'production' ? invariant(false, 'The `style` prop expects a mapping from style properties to values, ' + 'not a string. For example, style={{marginRight: spacing + \'em\'}} when ' + 'using JSX.%s', getDeclarationErrorAddendum(component)) : invariant(false) : void 0;
81050}
81051
81052function enqueuePutListener(inst, registrationName, listener, transaction) {
81053  if ("development" !== 'production') {
81054    // IE8 has no API for event capturing and the `onScroll` event doesn't
81055    // bubble.
81056    "development" !== 'production' ? warning(registrationName !== 'onScroll' || isEventSupported('scroll', true), 'This browser doesn\'t support the `onScroll` event') : void 0;
81057  }
81058  var containerInfo = inst._nativeContainerInfo;
81059  var isDocumentFragment = containerInfo._node && containerInfo._node.nodeType === DOC_FRAGMENT_TYPE;
81060  var doc = isDocumentFragment ? containerInfo._node : containerInfo._ownerDocument;
81061  if (!doc) {
81062    // Server rendering.
81063    return;
81064  }
81065  listenTo(registrationName, doc);
81066  transaction.getReactMountReady().enqueue(putListener, {
81067    inst: inst,
81068    registrationName: registrationName,
81069    listener: listener
81070  });
81071}
81072
81073function putListener() {
81074  var listenerToPut = this;
81075  EventPluginHub.putListener(listenerToPut.inst, listenerToPut.registrationName, listenerToPut.listener);
81076}
81077
81078function optionPostMount() {
81079  var inst = this;
81080  ReactDOMOption.postMountWrapper(inst);
81081}
81082
81083// There are so many media events, it makes sense to just
81084// maintain a list rather than create a `trapBubbledEvent` for each
81085var mediaEvents = {
81086  topAbort: 'abort',
81087  topCanPlay: 'canplay',
81088  topCanPlayThrough: 'canplaythrough',
81089  topDurationChange: 'durationchange',
81090  topEmptied: 'emptied',
81091  topEncrypted: 'encrypted',
81092  topEnded: 'ended',
81093  topError: 'error',
81094  topLoadedData: 'loadeddata',
81095  topLoadedMetadata: 'loadedmetadata',
81096  topLoadStart: 'loadstart',
81097  topPause: 'pause',
81098  topPlay: 'play',
81099  topPlaying: 'playing',
81100  topProgress: 'progress',
81101  topRateChange: 'ratechange',
81102  topSeeked: 'seeked',
81103  topSeeking: 'seeking',
81104  topStalled: 'stalled',
81105  topSuspend: 'suspend',
81106  topTimeUpdate: 'timeupdate',
81107  topVolumeChange: 'volumechange',
81108  topWaiting: 'waiting'
81109};
81110
81111function trapBubbledEventsLocal() {
81112  var inst = this;
81113  // If a component renders to null or if another component fatals and causes
81114  // the state of the tree to be corrupted, `node` here can be null.
81115  !inst._rootNodeID ? "development" !== 'production' ? invariant(false, 'Must be mounted to trap events') : invariant(false) : void 0;
81116  var node = getNode(inst);
81117  !node ? "development" !== 'production' ? invariant(false, 'trapBubbledEvent(...): Requires node to be rendered.') : invariant(false) : void 0;
81118
81119  switch (inst._tag) {
81120    case 'iframe':
81121    case 'object':
81122      inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topLoad, 'load', node)];
81123      break;
81124    case 'video':
81125    case 'audio':
81126
81127      inst._wrapperState.listeners = [];
81128      // Create listener for each media event
81129      for (var event in mediaEvents) {
81130        if (mediaEvents.hasOwnProperty(event)) {
81131          inst._wrapperState.listeners.push(ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes[event], mediaEvents[event], node));
81132        }
81133      }
81134
81135      break;
81136    case 'img':
81137      inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topError, 'error', node), ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topLoad, 'load', node)];
81138      break;
81139    case 'form':
81140      inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topReset, 'reset', node), ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topSubmit, 'submit', node)];
81141      break;
81142    case 'input':
81143    case 'select':
81144    case 'textarea':
81145      inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topInvalid, 'invalid', node)];
81146      break;
81147  }
81148}
81149
81150function postUpdateSelectWrapper() {
81151  ReactDOMSelect.postUpdateWrapper(this);
81152}
81153
81154// For HTML, certain tags should omit their close tag. We keep a whitelist for
81155// those special-case tags.
81156
81157var omittedCloseTags = {
81158  'area': true,
81159  'base': true,
81160  'br': true,
81161  'col': true,
81162  'embed': true,
81163  'hr': true,
81164  'img': true,
81165  'input': true,
81166  'keygen': true,
81167  'link': true,
81168  'meta': true,
81169  'param': true,
81170  'source': true,
81171  'track': true,
81172  'wbr': true
81173};
81174
81175// NOTE: menuitem's close tag should be omitted, but that causes problems.
81176var newlineEatingTags = {
81177  'listing': true,
81178  'pre': true,
81179  'textarea': true
81180};
81181
81182// For HTML, certain tags cannot have children. This has the same purpose as
81183// `omittedCloseTags` except that `menuitem` should still have its closing tag.
81184
81185var voidElementTags = _assign({
81186  'menuitem': true
81187}, omittedCloseTags);
81188
81189// We accept any tag to be rendered but since this gets injected into arbitrary
81190// HTML, we want to make sure that it's a safe tag.
81191// http://www.w3.org/TR/REC-xml/#NT-Name
81192
81193var VALID_TAG_REGEX = /^[a-zA-Z][a-zA-Z:_\.\-\d]*$/; // Simplified subset
81194var validatedTagCache = {};
81195var hasOwnProperty = {}.hasOwnProperty;
81196
81197function validateDangerousTag(tag) {
81198  if (!hasOwnProperty.call(validatedTagCache, tag)) {
81199    !VALID_TAG_REGEX.test(tag) ? "development" !== 'production' ? invariant(false, 'Invalid tag: %s', tag) : invariant(false) : void 0;
81200    validatedTagCache[tag] = true;
81201  }
81202}
81203
81204function isCustomComponent(tagName, props) {
81205  return tagName.indexOf('-') >= 0 || props.is != null;
81206}
81207
81208var globalIdCounter = 1;
81209
81210/**
81211 * Creates a new React class that is idempotent and capable of containing other
81212 * React components. It accepts event listeners and DOM properties that are
81213 * valid according to `DOMProperty`.
81214 *
81215 *  - Event listeners: `onClick`, `onMouseDown`, etc.
81216 *  - DOM properties: `className`, `name`, `title`, etc.
81217 *
81218 * The `style` property functions differently from the DOM API. It accepts an
81219 * object mapping of style properties to values.
81220 *
81221 * @constructor ReactDOMComponent
81222 * @extends ReactMultiChild
81223 */
81224function ReactDOMComponent(element) {
81225  var tag = element.type;
81226  validateDangerousTag(tag);
81227  this._currentElement = element;
81228  this._tag = tag.toLowerCase();
81229  this._namespaceURI = null;
81230  this._renderedChildren = null;
81231  this._previousStyle = null;
81232  this._previousStyleCopy = null;
81233  this._nativeNode = null;
81234  this._nativeParent = null;
81235  this._rootNodeID = null;
81236  this._domID = null;
81237  this._nativeContainerInfo = null;
81238  this._wrapperState = null;
81239  this._topLevelWrapper = null;
81240  this._flags = 0;
81241  if ("development" !== 'production') {
81242    this._ancestorInfo = null;
81243  }
81244}
81245
81246ReactDOMComponent.displayName = 'ReactDOMComponent';
81247
81248ReactDOMComponent.Mixin = {
81249
81250  /**
81251   * Generates root tag markup then recurses. This method has side effects and
81252   * is not idempotent.
81253   *
81254   * @internal
81255   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
81256   * @param {?ReactDOMComponent} the containing DOM component instance
81257   * @param {?object} info about the native container
81258   * @param {object} context
81259   * @return {string} The computed markup.
81260   */
81261  mountComponent: function (transaction, nativeParent, nativeContainerInfo, context) {
81262    this._rootNodeID = globalIdCounter++;
81263    this._domID = nativeContainerInfo._idCounter++;
81264    this._nativeParent = nativeParent;
81265    this._nativeContainerInfo = nativeContainerInfo;
81266
81267    var props = this._currentElement.props;
81268
81269    switch (this._tag) {
81270      case 'iframe':
81271      case 'object':
81272      case 'img':
81273      case 'form':
81274      case 'video':
81275      case 'audio':
81276        this._wrapperState = {
81277          listeners: null
81278        };
81279        transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this);
81280        break;
81281      case 'button':
81282        props = ReactDOMButton.getNativeProps(this, props, nativeParent);
81283        break;
81284      case 'input':
81285        ReactDOMInput.mountWrapper(this, props, nativeParent);
81286        props = ReactDOMInput.getNativeProps(this, props);
81287        transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this);
81288        break;
81289      case 'option':
81290        ReactDOMOption.mountWrapper(this, props, nativeParent);
81291        props = ReactDOMOption.getNativeProps(this, props);
81292        break;
81293      case 'select':
81294        ReactDOMSelect.mountWrapper(this, props, nativeParent);
81295        props = ReactDOMSelect.getNativeProps(this, props);
81296        transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this);
81297        break;
81298      case 'textarea':
81299        ReactDOMTextarea.mountWrapper(this, props, nativeParent);
81300        props = ReactDOMTextarea.getNativeProps(this, props);
81301        transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this);
81302        break;
81303    }
81304
81305    assertValidProps(this, props);
81306
81307    // We create tags in the namespace of their parent container, except HTML
81308    // tags get no namespace.
81309    var namespaceURI;
81310    var parentTag;
81311    if (nativeParent != null) {
81312      namespaceURI = nativeParent._namespaceURI;
81313      parentTag = nativeParent._tag;
81314    } else if (nativeContainerInfo._tag) {
81315      namespaceURI = nativeContainerInfo._namespaceURI;
81316      parentTag = nativeContainerInfo._tag;
81317    }
81318    if (namespaceURI == null || namespaceURI === DOMNamespaces.svg && parentTag === 'foreignobject') {
81319      namespaceURI = DOMNamespaces.html;
81320    }
81321    if (namespaceURI === DOMNamespaces.html) {
81322      if (this._tag === 'svg') {
81323        namespaceURI = DOMNamespaces.svg;
81324      } else if (this._tag === 'math') {
81325        namespaceURI = DOMNamespaces.mathml;
81326      }
81327    }
81328    this._namespaceURI = namespaceURI;
81329
81330    if ("development" !== 'production') {
81331      var parentInfo;
81332      if (nativeParent != null) {
81333        parentInfo = nativeParent._ancestorInfo;
81334      } else if (nativeContainerInfo._tag) {
81335        parentInfo = nativeContainerInfo._ancestorInfo;
81336      }
81337      if (parentInfo) {
81338        // parentInfo should always be present except for the top-level
81339        // component when server rendering
81340        validateDOMNesting(this._tag, this, parentInfo);
81341      }
81342      this._ancestorInfo = validateDOMNesting.updatedAncestorInfo(p
81342arentInfo, this._tag, this);
81343    }
81344
81345    var mountImage;
81346    if (transaction.useCreateElement) {
81347      var ownerDocument = nativeContainerInfo._ownerDocument;
81348      var el;
81349      if (namespaceURI === DOMNamespaces.html) {
81350        if (this._tag === 'script') {
81351          // Create the script via .innerHTML so its "parser-inserted" flag is
81352          // set to true and it does not execute
81353          var div = ownerDocument.createElement('div');
81354          var type = this._currentElement.type;
81355          div.innerHTML = '<' + type + '></' + type + '>';
81356          el = div.removeChild(div.firstChild);
81357        } else {
81358          el = ownerDocument.createElement(this._currentElement.type);
81359        }
81360      } else {
81361        el = ownerDocument.createElementNS(namespaceURI, this._currentElement.type);
81362      }
81363      ReactDOMComponentTree.precacheNode(this, el);
81364      this._flags |= Flags.hasCachedChildNodes;
81365      if (!this._nativeParent) {
81366        DOMPropertyOperations.setAttributeForRoot(el);
81367      }
81368      this._updateDOMProperties(null, props, transaction);
81369      var lazyTree = DOMLazyTree(el);
81370      this._createInitialChildren(transaction, props, context, lazyTree);
81371      mountImage = lazyTree;
81372    } else {
81373      var tagOpen = this._createOpenTagMarkupAndPutListeners(transaction, props);
81374      var tagContent = this._createContentMarkup(transaction, props, context);
81375      if (!tagContent && omittedCloseTags[this._tag]) {
81376        mountImage = tagOpen + '/>';
81377      } else {
81378        mountImage = tagOpen + '>' + tagContent + '</' + this._currentElement.type + '>';
81379      }
81380    }
81381
81382    switch (this._tag) {
81383      case 'button':
81384      case 'input':
81385      case 'select':
81386      case 'textarea':
81387        if (props.autoFocus) {
81388          transaction.getReactMountReady().enqueue(AutoFocusUtils.focusDOMComponent, this);
81389        }
81390        break;
81391      case 'option':
81392        transaction.getReactMountReady().enqueue(optionPostMount, this);
81393    }
81394
81395    return mountImage;
81396  },
81397
81398  /**
81399   * Creates markup for the open tag and all attributes.
81400   *
81401   * This method has side effects because events get registered.
81402   *
81403   * Iterating over object properties is faster than iterating over arrays.
81404   * @see http://jsperf.com/obj-vs-arr-iteration
81405   *
81406   * @private
81407   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
81408   * @param {object} props
81409   * @return {string} Markup of opening tag.
81410   */
81411  _createOpenTagMarkupAndPutListeners: function (transaction, props) {
81412    var ret = '<' + this._currentElement.type;
81413
81414    for (var propKey in props) {
81415      if (!props.hasOwnProperty(propKey)) {
81416        continue;
81417      }
81418      var propValue = props[propKey];
81419      if (propValue == null) {
81420        continue;
81421      }
81422      if (registrationNameModules.hasOwnProperty(propKey)) {
81423        if (propValue) {
81424          enqueuePutListener(this, propKey, propValue, transaction);
81425        }
81426      } else {
81427        if (propKey === STYLE) {
81428          if (propValue) {
81429            if ("development" !== 'production') {
81430              // See `_updateDOMProperties`. style block
81431              this._previousStyle = propValue;
81432            }
81433            propValue = this._previousStyleCopy = _assign({}, props.style);
81434          }
81435          propValue = CSSPropertyOperations.createMarkupForStyles(propValue, this);
81436        }
81437        var markup = null;
81438        if (this._tag != null && isCustomComponent(this._tag, props)) {
81439          if (!RESERVED_PROPS.hasOwnProperty(propKey)) {
81440            markup = DOMPropertyOperations.createMarkupForCustomAttribute(propKey, propValue);
81441          }
81442        } else {
81443          markup = DOMPropertyOperations.createMarkupForProperty(propKey, propValue);
81444        }
81445        if (markup) {
81446          ret += ' ' + markup;
81447        }
81448      }
81449    }
81450
81451    // For static pages, no need to put React ID and checksum. Saves lots of
81452    // bytes.
81453    if (transaction.renderToStaticMarkup) {
81454      return ret;
81455    }
81456
81457    if (!this._nativeParent) {
81458      ret += ' ' + DOMPropertyOperations.createMarkupForRoot();
81459    }
81460    ret += ' ' + DOMPropertyOperations.createMarkupForID(this._domID);
81461    return ret;
81462  },
81463
81464  /**
81465   * Creates markup for the content between the tags.
81466   *
81467   * @private
81468   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
81469   * @param {object} props
81470   * @param {object} context
81471   * @return {string} Content markup.
81472   */
81473  _createContentMarkup: function (transaction, props, context) {
81474    var ret = '';
81475
81476    // Intentional use of != to avoid catching zero/false.
81477    var innerHTML = props.dangerouslySetInnerHTML;
81478    if (innerHTML != null) {
81479      if (innerHTML.__html != null) {
81480        ret = innerHTML.__html;
81481      }
81482    } else {
81483      var contentToUse = CONTENT_TYPES[typeof props.children] ? props.children : null;
81484      var childrenToUse = contentToUse != null ? null : props.children;
81485      if (contentToUse != null) {
81486        // TODO: Validate that text is allowed as a child of this node
81487        ret = escapeTextContentForBrowser(contentToUse);
81488      } else if (childrenToUse != null) {
81489        var mountImages = this.mountChildren(childrenToUse, transaction, context);
81490        ret = mountImages.join('');
81491      }
81492    }
81493    if (newlineEatingTags[this._tag] && ret.charAt(0) === '\n') {
81494      // text/html ignores the first character in these tags if it's a newline
81495      // Prefer to break application/xml over text/html (for now) by adding
81496      // a newline specifically to get eaten by the parser. (Alternately for
81497      // textareas, replacing "^\n" with "\r\n" doesn't get eaten, and the first
81498      // \r is normalized out by HTMLTextAreaElement#value.)
81499      // See: <http://www.w3.org/TR/html-polyglot/#newlines-in-textarea-and-pre>
81500      // See: <http://www.w3.org/TR/html5/syntax.html#element-restr
81500ictions>
81501      // See: <http://www.w3.org/TR/html5/syntax.html#newlines>
81502      // See: Parsing of "textarea" "listing" and "pre" elements
81503      //  from <http://www.w3.org/TR/html5/syntax.html#parsing-main-inbody>
81504      return '\n' + ret;
81505    } else {
81506      return ret;
81507    }
81508  },
81509
81510  _createInitialChildren: function (transaction, props, context, lazyTree) {
81511    // Intentional use of != to avoid catching zero/false.
81512    var innerHTML = props.dangerouslySetInnerHTML;
81513    if (innerHTML != null) {
81514      if (innerHTML.__html != null) {
81515        DOMLazyTree.queueHTML(lazyTree, innerHTML.__html);
81516      }
81517    } else {
81518      var contentToUse = CONTENT_TYPES[typeof props.children] ? props.children : null;
81519      var childrenToUse = contentToUse != null ? null : props.children;
81520      if (contentToUse != null) {
81521        // TODO: Validate that text is allowed as a child of this node
81522        DOMLazyTree.queueText(lazyTree, contentToUse);
81523      } else if (childrenToUse != null) {
81524        var mountImages = this.mountChildren(childrenToUse, transaction, context);
81525        for (var i = 0; i < mountImages.length; i++) {
81526          DOMLazyTree.queueChild(lazyTree, mountImages[i]);
81527        }
81528      }
81529    }
81530  },
81531
81532  /**
81533   * Receives a next element and updates the component.
81534   *
81535   * @internal
81536   * @param {ReactElement} nextElement
81537   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
81538   * @param {object} context
81539   */
81540  receiveComponent: function (nextElement, transaction, context) {
81541    var prevElement = this._currentElement;
81542    this._currentElement = nextElement;
81543    this.updateComponent(transaction, prevElement, nextElement, context);
81544  },
81545
81546  /**
81547   * Updates a native DOM component after it has already been allocated and
81548   * attached to the DOM. Reconciles the root DOM node, then recurses.
81549   *
81550   * @param {ReactReconcileTransaction} transaction
81551   * @param {ReactElement} prevElement
81552   * @param {ReactElement} nextElement
81553   * @internal
81554   * @overridable
81555   */
81556  updateComponent: function (transaction, prevElement, nextElement, context) {
81557    var lastProps = prevElement.props;
81558    var nextProps = this._currentElement.props;
81559
81560    switch (this._tag) {
81561      case 'button':
81562        lastProps = ReactDOMButton.getNativeProps(this, lastProps);
81563        nextProps = ReactDOMButton.getNativeProps(this, nextProps);
81564        break;
81565      case 'input':
81566        ReactDOMInput.updateWrapper(this);
81567        lastProps = ReactDOMInput.getNativeProps(this, lastProps);
81568        nextProps = ReactDOMInput.getNativeProps(this, nextProps);
81569        break;
81570      case 'option':
81571        lastProps = ReactDOMOption.getNativeProps(this, lastProps);
81572        nextProps = ReactDOMOption.getNativeProps(this, nextProps);
81573        break;
81574      case 'select':
81575        lastProps = ReactDOMSelect.getNativeProps(this, lastProps);
81576        nextProps = ReactDOMSelect.getNativeProps(this, nextProps);
81577        break;
81578      case 'textarea':
81579        ReactDOMTextarea.updateWrapper(this);
81580        lastProps = ReactDOMTextarea.getNativeProps(this, lastProps);
81581        nextProps = ReactDOMTextarea.getNativeProps(this, nextProps);
81582        break;
81583    }
81584
81585    assertValidProps(this, nextProps);
81586    this._updateDOMProperties(lastProps, nextProps, transaction);
81587    this._updateDOMChildren(lastProps, nextProps, transaction, context);
81588
81589    if (this._tag === 'select') {
81590      // <select> value update needs to occur after <option> children
81591      // reconciliation
81592      transaction.getReactMountReady().enqueue(postUpdateSelectWrapper, this);
81593    }
81594  },
81595
81596  /**
81597   * Reconciles the properties by detecting differences in property values and
81598   * updating the DOM as necessary. This function is probably the single most
81599   * critical path for performance optimization.
81600   *
81601   * TODO: Benchmark whether checking for changed values in memory actually
81602   *       improves performance (especially statically positioned elements).
81603   * TODO: Benchmark the effects of putting this at the top since 99% of props
81604   *       do not change for a given reconciliation.
81605   * TODO: Benchmark areas that can be improved with caching.
81606   *
81607   * @private
81608   * @param {object} lastProps
81609   * @param {object} nextProps
81610   * @param {?DOMElement} node
81611   */
81612  _updateDOMProperties: function (lastProps, nextProps, transaction) {
81613    var propKey;
81614    var styleName;
81615    var styleUpdates;
81616    for (propKey in lastProps) {
81617      if (nextProps.hasOwnProperty(propKey) || !lastProps.hasOwnProperty(propKey) || lastProps[propKey] == null) {
81618        continue;
81619      }
81620      if (propKey === STYLE) {
81621        var lastStyle = this._previousStyleCopy;
81622        for (styleName in lastStyle) {
81623          if (lastStyle.hasOwnProperty(styleName)) {
81624            styleUpdates = styleUpdates || {};
81625            styleUpdates[styleName] = '';
81626          }
81627        }
81628        this._previousStyleCopy = null;
81629      } else if (registrationNameModules.hasOwnProperty(propKey)) {
81630        if (lastProps[propKey]) {
81631          // Only call deleteListener if there was a listener previously or
81632          // else willDeleteListener gets called when there wasn't actually a
81633          // listener (e.g., onClick={null})
81634          deleteListener(this, propKey);
81635        }
81636      } else if (DOMProperty.properties[propKey] || DOMProperty.isCustomAttribute(propKey)) {
81637        DOMPropertyOperations.deleteValueForProperty(getNode(this), propKey);
81638      }
81639    }
81640    for (propKey in nextProps) {
81641      var nextProp = nextProps[propKey];
81642      var lastProp = propKey === STYLE ? this._previousStyleCopy : lastProps != null ? lastProps[propKey] : undefined;
81643      if (!nextProps.hasOwnProperty(propKey) || nextProp === lastProp || nextProp == null && lastProp == null) {
81644        continue;
81645      }
81646      if (propKey === STYLE) {
81647        if (nextProp) {
81648          if ("development" !== 'production') {
81649            checkAndWarnForMutatedStyle(this._previousStyleCopy, this._previousStyle, this);
81650            this._previousStyle = nextProp;
81651          }
81652          nextProp = this._previousStyleCopy = _assign({}, nextProp);
81653        } else {
81654          this._previousStyleCopy = null;
81655        }
81656        if (lastProp) {
81657          // Unset styles on `lastProp` but not on `nextProp`.
81658          for (styleName in lastProp) {
81659            if (lastProp.hasOwnProperty(styleName) && (!nextProp || !nextProp.hasOwnProperty(styleName))) {
81660              styleUpdates = styleUpdates || {};
81661              styleUpdates[styleName] = '';
81662            }
81663          }
81664          // Update styles that changed since `lastProp`.
81665          for (styleName in nextProp) {
81666            if (nextProp.hasOwnProperty(styleName) && lastProp[styleName] !== nextProp[styleName]) {
81667              styleUpdates = styleUpdates || {};
81668              styleUpdates[styleName] = nextProp[styleName];
81669            }
81670          }
81671        } else {
81672          // Relies on `updateStylesByID` not mutating `styleUpdates`.
81673          styleUpdates = nextProp;
81674        }
81675      } else if (registrationNameModules.hasOwnProperty(propKey)) {
81676        if (nextProp) {
81677          enqueuePutListener(this, propKey, nextProp, transaction);
81678        } else if (lastProp) {
81679          deleteListener(this, propKey);
81680        }
81681      } else if (isCustomComponent(this._tag, nextProps)) {
81682        if (!RESERVED_PROPS.hasOwnProperty(propKey)) {
81683          DOMPropertyOperations.setValueForAttribute(getNode(this), propKey, nextProp);
81684        }
81685      } else if (DOMProperty.properties[propKey] || DOMProperty.isCustomAttribute(propKey)) {
81686        var node = getNode(this);
81687        // If we're updating to null or undefined, we should remove the property
81688        // from the DOM node instead of inadvertently setting to a string. This
81689        // brings us in line with the same behavior we have on initial render.
81690        if (nextProp != null) {
81691          DOMPropertyOperations.setValueForProperty(node, propKey, nextProp);
81692        } else {
81693          DOMPropertyOperations.deleteValueForProperty(node, propKey);
81694        }
81695      }
81696    }
81697    if (styleUpdates) {
81698      CSSPropertyOperations.setValueForStyles(getNode(this), styleUpdates, this);
81699    }
81700  },
81701
81702  /**
81703   * Reconciles the children with the various properties that affect the
81704   * children content.
81705   *
81706   * @param {object} lastProps
81707   * @param {object} nextProps
81708   * @param {ReactReconcileTransaction} transaction
81709   * @param {object} context
81710   */
81711  _updateDOMChildren: function (lastProps, nextProps, transaction, context) {
81712    var lastContent = CONTENT_TYPES[typeof lastProps.children] ? lastProps.children : null;
81713    var nextContent = CONTENT_TYPES[typeof nextProps.children] ? nextProps.children : null;
81714
81715    var lastHtml = lastProps.dangerouslySetInnerHTML && lastProps.dangerouslySetInnerHTML.__html;
81716    var nextHtml = nextProps.dangerouslySetInnerHTML && nextProps.dangerouslySetInnerHTML.__html;
81717
81718    // Note the use of `!=` which checks for null or undefined.
81719    var lastChildren = lastContent != null ? null : lastProps.children;
81720    var nextChildren = nextContent != null ? null : nextProps.children;
81721
81722    // If we're switching from children to content/html or vice versa, remove
81723    // the old content
81724    var lastHasContentOrHtml = lastContent != null || lastHtml != null;
81725    var nextHasContentOrHtml = nextContent != null || nextHtml != null;
81726    if (lastChildren != null && nextChildren == null) {
81727      this.updateChildren(null, transaction, context);
81728    } else if (lastHasContentOrHtml && !nextHasContentOrHtml) {
81729      this.updateTextContent('');
81730    }
81731
81732    if (nextContent != null) {
81733      if (lastContent !== nextContent) {
81734        this.updateTextContent('' + nextContent);
81735      }
81736    } else if (nextHtml != null) {
81737      if (lastHtml !== nextHtml) {
81738        this.updateMarkup('' + nextHtml);
81739      }
81740    } else if (nextChildren != null) {
81741      this.updateChildren(nextChildren, transaction, context);
81742    }
81743  },
81744
81745  getNativeNode: function () {
81746    return getNode(this);
81747  },
81748
81749  /**
81750   * Destroys all event registrations for this instance. Does not remove from
81751   * the DOM. That must be done by the parent.
81752   *
81753   * @internal
81754   */
81755  unmountComponent: function (safely) {
81756    switch (this._tag) {
81757      case 'iframe':
81758      case 'object':
81759      case 'img':
81760      case 'form':
81761      case 'video':
81762      case 'audio':
81763        var listeners = this._wrapperState.listeners;
81764        if (listeners) {
81765          for (var i = 0; i < listeners.length; i++) {
81766            listeners[i].remove();
81767          }
81768        }
81769        break;
81770      case 'html':
81771      case 'head':
81772      case 'body':
81773        /**
81774         * Components like <html> <head> and <body> can't be removed or added
81775         * easily in a cross-browser way, however it's valuable to be able to
81776         * take advantage of React's reconciliation for styling and <title>
81777         * management. So we just document it and throw in dangerous cases.
81778         */
81779        !false ? "development" !== 'production' ? invariant(false, '<%s> tried to unmount. Because of cross-browser quirks it is ' + 'impossible to unmount some top-level components (eg <html>, ' + '<head>, and <body>) reliably and efficiently. To fix this, have a ' + 'single top-level component that never unmounts render these ' + 'elements.', this._tag) : invariant(false) : void 0;
81780        break;
81781    }
81782
81783    this.unmountChildren(safely);
81784    ReactDOMComponentTree.uncacheNode(this);
81785    EventPluginHub.deleteAllListeners(this);
81786    ReactComponentBrowserEnvironment.unmountIDFromEnvironment(this._rootNodeID);
81787    this._rootNodeID = null;
81788    this._domID = null;
81789    this._wrapperState = null;
81790  },
81791
81792  getPublicInstance: function () {
81793    return getNode(this);
81794  }
81795
81796};
81797
81798ReactPerf.measureMethods(ReactDOMComponent.Mixin, 'ReactDOMComponent', {
81799  mountComponent: 'mountComponent',
81800  receiveComponent: 'receiveComponent'
81801});
81802
81803_assign(ReactDOMComponent.prototype, ReactDOMComponent.Mixin, ReactMultiChild.Mixin);
81804
81805module.exports = ReactDOMComponent;
81806},{"1":1,"10":10,"11":11,"119":119,"133":133,"142":142,"158":158,"16":16,"162":162,"167":167,"168":168,"169":169,"17":17,"18":18,"27":27,"32":32,"37":37,"39":39,"4":4,"40":40,"47":47,"49":49,"50":50,"54":54,"76":76,"8":8,"82":82,"9":9}],39:[function(_dereq_,module,exports){
81807/**
81808 * Copyright 2015-present, Facebook, Inc.
81809 * All rights reserved.
81810 *
81811 * This source code is licensed under the BSD-style license found in the
81812 * LICENSE file in the root directory of this source tree. An additional grant
81813 * of patent rights can be found in the PATENTS file in the same directory.
81814 *
81815 * @providesModule ReactDOMComponentFlags
81816 */
81817
81818
81819
81820var ReactDOMComponentFlags = {
81821  hasCachedChildNodes: 1 << 0
81822};
81823
81824module.exports = ReactDOMComponentFlags;
81825},{}],40:[function(_dereq_,module,exports){
81826/**
81827 * Copyright 2013-present, Facebook, Inc.
81828 * All rights reserved.
81829 *
81830 * This source code is licensed under the BSD-style license found in the
81831 * LICENSE file in the root directory of this source tree. An additional grant
81832 * of patent rights can be found in the PATENTS file in the same directory.
81833 *
81834 * @providesModule ReactDOMComponentTree
81835 */
81836
81837
81838
81839var DOMProperty = _dereq_(10);
81840var ReactDOMComponentFlags = _dereq_(39);
81841
81842var invariant = _dereq_(158);
81843
81844var ATTR_NAME = DOMProperty.ID_ATTRIBUTE_NAME;
81845var Flags = ReactDOMComponentFlags;
81846
81847var internalInstanceKey = '__reactInternalInstance$' + Math.random().toString(36).slice(2);
81848
81849/**
81850 * Drill down (through composites and empty components) until we get a native or
81851 * native text component.
81852 *
81853 * This is pretty polymorphic but unavoidable with the current structure we have
81854 * for `_renderedChildren`.
81855 */
81856function getRenderedNativeOrTextFromComponent(component) {
81857  var rendered;
81858  while (rendered = component._renderedComponent) {
81859    component = rendered;
81860  }
81861  return component;
81862}
81863
81864/**
81865 * Populate `_nativeNode` on the rendered native/text component with the given
81866 * DOM node. The passed `inst` can be a composite.
81867 */
81868function precacheNode(inst, node) {
81869  var nativeInst = getRenderedNativeOrTextFromComponent(inst);
81870  nativeInst._nativeNode = node;
81871  node[internalInstanceKey] = nativeInst;
81872}
81873
81874function uncacheNode(inst) {
81875  var node = inst._nativeNode;
81876  if (node) {
81877    delete node[internalInstanceKey];
81878    inst._nativeNode = null;
81879  }
81880}
81881
81882/**
81883 * Populate `_nativeNode` on each child of `inst`, assuming that the children
81884 * match up with the DOM (element) children of `node`.
81885 *
81886 * We cache entire levels at once to avoid an n^2 problem where we access the
81887 * children of a node sequentially and have to walk from the start to our target
81888 * node every time.
81889 *
81890 * Since we update `_renderedChildren` and the actual DOM at (slightly)
81891 * different times, we could race here and see a newer `_renderedChildren` than
81892 * the DOM nodes we see. To avoid this, ReactMultiChild calls
81893 * `prepareToManageChildren` before we change `_renderedChildren`, at which
81894 * time the container's child nodes are always cached (until it unmounts).
81895 */
81896function precacheChildNodes(inst, node) {
81897  if (inst._flags & Flags.hasCachedChildNodes) {
81898    return;
81899  }
81900  var children = inst._renderedChildren;
81901  var childNode = node.firstChild;
81902  outer: for (var name in children) {
81903    if (!children.hasOwnProperty(name)) {
81904      continue;
81905    }
81906    var childInst = children[name];
81907    var childID = getRenderedNativeOrTextFromComponent(childInst)._domID;
81908    if (childID == null) {
81909      // We're currently unmounting this child in ReactMultiChild; skip it.
81910      continue;
81911    }
81912    // We assume the child nodes are in the same order as the child instances.
81913    for (; childNode !== null; childNode = childNode.nextSibling) {
81914      if (childNode.nodeType === 1 && childNode.getAttribute(ATTR_NAME) === String(childID) || childNode.nodeType === 8 && childNode.nodeValue === ' react-text: ' + childID + ' ' || childNode.nodeType === 8 && childNode.nodeValue === ' react-empty: ' + childID + ' ') {
81915        precacheNode(childInst, childNode);
81916        continue outer;
81917      }
81918    }
81919    // We reached the end of the DOM children without finding an ID match.
81920    !false ? "development" !== 'production' ? invariant(false, 'Unable to find element with ID %s.', childID) : invariant(false) : void 0;
81921  }
81922  inst._flags |= Flags.hasCachedChildNodes;
81923}
81924
81925/**
81926 * Given a DOM node, return the closest ReactDOMComponent or
81927 * ReactDOMTextComponent instance ancestor.
81928 */
81929function getClosestInstanceFromNode(node) {
81930  if (node[internalInstanceKey]) {
81931    return node[internalInstanceKey];
81932  }
81933
81934  // Walk up the tree until we find an ancestor whose instance we have cached.
81935  var parents = [];
81936  while (!node[internalInstanceKey]) {
81937    parents.push(node);
81938    if (node.parentNode) {
81939      node = node.parentNode;
81940    } else {
81941      // Top of the tree. This node must not be part of a React tree (or is
81942      // unmounted, potentially).
81943      return null;
81944    }
81945  }
81946
81947  var closest;
81948  var inst;
81949  for (; node && (inst = node[internalInstanceKey]); node = parents.pop()) {
81950    closest = inst;
81951    if (parents.length) {
81952      precacheChildNodes(inst, node);
81953    }
81954  }
81955
81956  return closest;
81957}
81958
81959/**
81960 * Given a DOM node, return the ReactDOMComponent or ReactDOMTextComponent
81961 * instance, or null if the node was not rendered by this React.
81962 */
81963function getInstanceFromNode(node) {
81964  var inst = getClosestInstanceFromNode(node);
81965  if (inst != null && inst._nativeNode === node) {
81966    return inst;
81967  } else {
81968    return null;
81969  }
81970}
81971
81972/**
81973 * Given a ReactDOMComponent or ReactDOMTextComponent, return the corresponding
81974 * DOM node.
81975 */
81976function getNodeFromInstance(inst) {
81977  // Without this first invariant, passing a non-DOM-component triggers the next
81978  // invariant for a missing parent, which is super confusing.
81979  !(inst._nativeNode !== undefined) ? "development" !== 'production' ? invariant(false, 'getNodeFromInstance: Invalid argument.') : invariant(false) : void 0;
81980
81981  if (inst._nativeNode) {
81982    return inst._nativeNode;
81983  }
81984
81985  // Walk up the tree until we find an ancestor whose DOM node we have cached.
81986  var parents = [];
81987  while (!inst._nativeNode) {
81988    parents.push(inst);
81989    !inst._nativeParent ? "development" !== 'production' ? invariant(false, 'React DOM tree root should always have a node reference.') 
81989: invariant(false) : void 0;
81990    inst = inst._nativeParent;
81991  }
81992
81993  // Now parents contains each ancestor that does *not* have a cached native
81994  // node, and `inst` is the deepest ancestor that does.
81995  for (; parents.length; inst = parents.pop()) {
81996    precacheChildNodes(inst, inst._nativeNode);
81997  }
81998
81999  return inst._nativeNode;
82000}
82001
82002var ReactDOMComponentTree = {
82003  getClosestInstanceFromNode: getClosestInstanceFromNode,
82004  getInstanceFromNode: getInstanceFromNode,
82005  getNodeFromInstance: getNodeFromInstance,
82006  precacheChildNodes: precacheChildNodes,
82007  precacheNode: precacheNode,
82008  uncacheNode: uncacheNode
82009};
82010
82011module.exports = ReactDOMComponentTree;
82012},{"10":10,"158":158,"39":39}],41:[function(_dereq_,module,exports){
82013/**
82014 * Copyright 2013-present, Facebook, Inc.
82015 * All rights reserved.
82016 *
82017 * This source code is licensed under the BSD-style license found in the
82018 * LICENSE file in the root directory of this source tree. An additional grant
82019 * of patent rights can be found in the PATENTS file in the same directory.
82020 *
82021 * @providesModule ReactDOMContainerInfo
82022 */
82023
82024
82025
82026var validateDOMNesting = _dereq_(142);
82027
82028var DOC_NODE_TYPE = 9;
82029
82030function ReactDOMContainerInfo(topLevelWrapper, node) {
82031  var info = {
82032    _topLevelWrapper: topLevelWrapper,
82033    _idCounter: 1,
82034    _ownerDocument: node ? node.nodeType === DOC_NODE_TYPE ? node : node.ownerDocument : null,
82035    _node: node,
82036    _tag: node ? node.nodeName.toLowerCase() : null,
82037    _namespaceURI: node ? node.namespaceURI : null
82038  };
82039  if ("development" !== 'production') {
82040    info._ancestorInfo = node ? validateDOMNesting.updatedAncestorInfo(null, info._tag, null) : null;
82041  }
82042  return info;
82043}
82044
82045module.exports = ReactDOMContainerInfo;
82046},{"142":142}],42:[function(_dereq_,module,exports){
82047/**
82048 * Copyright 2013-present, Facebook, Inc.
82049 * All rights reserved.
82050 *
82051 * This source code is licensed under the BSD-style license found in the
82052 * LICENSE file in the root directory of this source tree. An additional grant
82053 * of patent rights can be found in the PATENTS file in the same directory.
82054 *
82055 * @providesModule ReactDOMDebugTool
82056 */
82057
82058
82059
82060var ReactDOMUnknownPropertyDevtool = _dereq_(56);
82061
82062var warning = _dereq_(168);
82063
82064var eventHandlers = [];
82065var handlerDoesThrowForEvent = {};
82066
82067function emitEvent(handlerFunctionName, arg1, arg2, arg3, arg4, arg5) {
82068  if ("development" !== 'production') {
82069    eventHandlers.forEach(function (handler) {
82070      try {
82071        if (handler[handlerFunctionName]) {
82072          handler[handlerFunctionName](arg1, arg2, arg3, arg4, arg5);
82073        }
82074      } catch (e) {
82075        "development" !== 'production' ? warning(!handlerDoesThrowForEvent[handlerFunctionName], 'exception thrown by devtool while handling %s: %s', handlerFunctionName, e.message) : void 0;
82076        handlerDoesThrowForEvent[handlerFunctionName] = true;
82077      }
82078    });
82079  }
82080}
82081
82082var ReactDOMDebugTool = {
82083  addDevtool: function (devtool) {
82084    eventHandlers.push(devtool);
82085  },
82086  removeDevtool: function (devtool) {
82087    for (var i = 0; i < eventHandlers.length; i++) {
82088      if (eventHandlers[i] === devtool) {
82089        eventHandlers.splice(i, 1);
82090        i--;
82091      }
82092    }
82093  },
82094  onCreateMarkupForProperty: function (name, value) {
82095    emitEvent('onCreateMarkupForProperty', name, value);
82096  },
82097  onSetValueForProperty: function (node, name, value) {
82098    emitEvent('onSetValueForProperty', node, name, value);
82099  },
82100  onDeleteValueForProperty: function (node, name) {
82101    emitEvent('onDeleteValueForProperty', node, name);
82102  }
82103};
82104
82105ReactDOMDebugTool.addDevtool(ReactDOMUnknownPropertyDevtool);
82106
82107module.exports = ReactDOMDebugTool;
82108},{"168":168,"56":56}],43:[function(_dereq_,module,exports){
82109/**
82110 * Copyright 2014-present, Facebook, Inc.
82111 * All rights reserved.
82112 *
82113 * This source code is licensed under the BSD-style license found in the
82114 * LICENSE file in the root directory of this source tree. An additional grant
82115 * of patent rights can be found in the PATENTS file in the same directory.
82116 *
82117 * @providesModule ReactDOMEmptyComponent
82118 */
82119
82120
82121
82122var _assign = _dereq_(169);
82123
82124var DOMLazyTree = _dereq_(8);
82125var ReactDOMComponentTree = _dereq_(40);
82126
82127var ReactDOMEmptyComponent = function (instantiate) {
82128  // ReactCompositeComponent uses this:
82129  this._currentElement = null;
82130  // ReactDOMComponentTree uses these:
82131  this._nativeNode = null;
82132  this._nativeParent = null;
82133  this._nativeContainerInfo = null;
82134  this._domID = null;
82135};
82136_assign(ReactDOMEmptyComponent.prototype, {
82137  mountComponent: function (transaction, nativeParent, nativeContainerInfo, context) {
82138    var domID = nativeContainerInfo._idCounter++;
82139    this._domID = domID;
82140    this._nativeParent = nativeParent;
82141    this._nativeContainerInfo = nativeContainerInfo;
82142
82143    var nodeValue = ' react-empty: ' + this._domID + ' ';
82144    if (transaction.useCreateElement) {
82145      var ownerDocument = nativeContainerInfo._ownerDocument;
82146      var node = ownerDocument.createComment(nodeValue);
82147      ReactDOMComponentTree.precacheNode(this, node);
82148      return DOMLazyTree(node);
82149    } else {
82150      if (transaction.renderToStaticMarkup) {
82151        // Normally we'd insert a comment node, but since this is a situation
82152        // where React won't take over (static pages), we can simply return
82153        // nothing.
82154        return '';
82155      }
82156      return '<!--' + nodeValue + '-->';
82157    }
82158  },
82159  receiveComponent: function () {},
82160  getNativeNode: function () {
82161    return ReactDOMComponentTree.getNodeFromInstance(this);
82162  },
82163  unmountComponent: function () {
82164    ReactDOMComponentTree.uncacheNode(this);
82165  }
82166});
82167
82168module.exports = ReactDOMEmptyComponent;
82169},{"169":169,"40":40,"8":8}],44:[function(_dereq_,module,exports){
82170/**
82171 * Copyright 2013-present, Facebook, Inc.
82172 * All rights reserved.
82173 *
82174 * This source code is licensed under the BSD-style license found in the
82175 * LICENSE file in the root directory of this source tree. An additional grant
82176 * of patent rights can be found in the PATENTS file in the same directory.
82177 *
82178 * @providesModule ReactDOMFactories
82179 */
82180
82181
82182
82183var ReactElement = _dereq_(62);
82184var ReactElementValidator = _dereq_(63);
82185
82186var mapObject = _dereq_(163);
82187
82188/**
82189 * Create a factory that creates HTML tag elements.
82190 *
82191 * @param {string} tag Tag name (e.g. `div`).
82192 * @private
82193 */
82194function createDOMFactory(tag) {
82195  if ("development" !== 'production') {
82196    return ReactElementValidator.createFactory(tag);
82197  }
82198  return ReactElement.createFactory(tag);
82199}
82200
82201/**
82202 * Creates a mapping from supported HTML tags to `ReactDOMComponent` classes.
82203 * This is also accessible via `React.DOM`.
82204 *
82205 * @public
82206 */
82207var ReactDOMFactories = mapObject({
82208  a: 'a',
82209  abbr: 'abbr',
82210  address: 'address',
82211  area: 'area',
82212  article: 'article',
82213  aside: 'aside',
82214  audio: 'audio',
82215  b: 'b',
82216  base: 'base',
82217  bdi: 'bdi',
82218  bdo: 'bdo',
82219  big: 'big',
82220  blockquote: 'blockquote',
82221  body: 'body',
82222  br: 'br',
82223  button: 'button',
82224  canvas: 'canvas',
82225  caption: 'caption',
82226  cite: 'cite',
82227  code: 'code',
82228  col: 'col',
82229  colgroup: 'colgroup',
82230  data: 'data',
82231  datalist: 'datalist',
82232  dd: 'dd',
82233  del: 'del',
82234  details: 'details',
82235  dfn: 'dfn',
82236  dialog: 'dialog',
82237  div: 'div',
82238  dl: 'dl',
82239  dt: 'dt',
82240  em: 'em',
82241  embed: 'embed',
82242  fieldset: 'fieldset',
82243  figcaption: 'figcaption',
82244  figure: 'figure',
82245  footer: 'footer',
82246  form: 'form',
82247  h1: 'h1',
82248  h2: 'h2',
82249  h3: 'h3',
82250  h4: 'h4',
82251  h5: 'h5',
82252  h6: 'h6',
82253  head: 'head',
82254  header: 'header',
82255  hgroup: 'hgroup',
82256  hr: 'hr',
82257  html: 'html',
82258  i: 'i',
82259  iframe: 'iframe',
82260  img: 'img',
82261  input: 'input',
82262  ins: 'ins',
82263  kbd: 'kbd',
82264  keygen: 'keygen',
82265  label: 'label',
82266  legend: 'legend',
82267  li: 'li',
82268  link: 'link',
82269  main: 'main',
82270  map: 'map',
82271  mark: 'mark',
82272  menu: 'menu',
82273  menuitem: 'menuitem',
82274  meta: 'meta',
82275  meter: 'meter',
82276  nav: 'nav',
82277  noscript: 'noscript',
82278  object: 'object',
82279  ol: 'ol',
82280  optgroup: 'optgroup',
82281  option: 'option',
82282  output: 'output',
82283  p: 'p',
82284  param: 'param',
82285  picture: 'picture',
82286  pre: 'pre',
82287  progress: 'progress',
82288  q: 'q',
82289  rp: 'rp',
82290  rt: 'rt',
82291  ruby: 'ruby',
82292  s: 's',
82293  samp: 'samp',
82294  script: 'script',
82295  section: 'section',
82296  select: 'select',
82297  small: 'small',
82298  source: 'source',
82299  span: 'span',
82300  strong: 'strong',
82301  style: 'style',
82302  sub: 'sub',
82303  summary: 'summary',
82304  sup: 'sup',
82305  table: 'table',
82306  tbody: 'tbody',
82307  td: 'td',
82308  textarea: 'textarea',
82309  tfoot: 'tfoot',
82310  th: 'th',
82311  thead: 'thead',
82312  time: 'time',
82313  title: 'title',
82314  tr: 'tr',
82315  track: 'track',
82316  u: 'u',
82317  ul: 'ul',
82318  'var': 'var',
82319  video: 'video',
82320  wbr: 'wbr',
82321
82322  // SVG
82323  circle: 'circle',
82324  clipPath: 'clipPath',
82325  defs: 'defs',
82326  ellipse: 'ellipse',
82327  g: 'g',
82328  image: 'image',
82329  line: 'line',
82330  linearGradient: 'linearGradient',
82331  mask: 'mask',
82332  path: 'path',
82333  pattern: 'pattern',
82334  polygon: 'polygon',
82335  polyline: 'polyline',
82336  radialGradient: 'radialGradient',
82337  rect: 'rect',
82338  stop: 'stop',
82339  svg: 'svg',
82340  text: 'text',
82341  tspan: 'tspan'
82342
82343}, createDOMFactory);
82344
82345module.exports = ReactDOMFactories;
82346},{"163":163,"62":62,"63":63}],45:[function(_dereq_,module,exports){
82347/**
82348 * Copyright 2013-present, Facebook, Inc.
82349 * All rights reserved.
82350 *
82351 * This source code is licensed under the BSD-style license found in the
82352 * LICENSE file in the root directory of this source tree. An additional grant
82353 * of patent rights can be found in the PATENTS file in the same directory.
82354 *
82355 * @providesModule ReactDOMFeatureFlags
82356 */
82357
82358
82359
82360var ReactDOMFeatureFlags = {
82361  useCreateElement: true
82362};
82363
82364module.exports = ReactDOMFeatureFlags;
82365},{}],46:[function(_dereq_,module,exports){
82366/**
82367 * Copyright 2013-present, Facebook, Inc.
82368 * All rights reserved.
82369 *
82370 * This source code is licensed under the BSD-style license found in the
82371 * LICENSE file in the root directory of this source tree. An additional grant
82372 * of patent rights can be found in the PATENTS file in the same directory.
82373 *
82374 * @providesModule ReactDOMIDOperations
82375 */
82376
82377
82378
82379var DOMChildrenOperations = _dereq_(7);
82380var ReactDOMComponentTree = _dereq_(40);
82381var ReactPerf = _dereq_(82);
82382
82383/**
82384 * Operations used to process updates to DOM nodes.
82385 */
82386var ReactDOMIDOperations = {
82387
82388  /**
82389   * Updates a component's children by processing a series of updates.
82390   *
82391   * @param {array<object>} updates List of update configurations.
82392   * @internal
82393   */
82394  dangerouslyProcessChildrenUpdates: function (parentInst, updates) {
82395    var node = ReactDOMComponentTree.getNodeFromInstance(parentInst);
82396    DOMChildrenOperations.processUpdates(node, updates);
82397  }
82398};
82399
82400ReactPerf.measureMethods(ReactDOMIDOperations, 'ReactDOMIDOperations', {
82401  dangerouslyProcessChildrenUpdates: 'dangerouslyProcessChildrenUpdates'
82402});
82403
82404module.exports = ReactDOMIDOperations;
82405},{"40":40,"7":7,"82":82}],47:[function(_dereq_,module,exports){
82406/**
82407 * Copyright 2013-present, Facebook, Inc.
82408 * All rights reserved.
82409 *
82410 * This source code is licensed under the BSD-style license found in the
82411 * LICENSE file in the root directory of this source tree. An additional grant
82412 * of patent rights can be found in the PATENTS file in the same directory.
82413 *
82414 * @providesModule ReactDOMInput
82415 */
82416
82417
82418
82419var _assign = _dereq_(169);
82420
82421var DisabledInputUtils = _dereq_(14);
82422var DOMPropertyOperations = _dereq_(11);
82423var LinkedValueUtils = _dereq_(24);
82424var ReactDOMComponentTree = _dereq_(40);
82425var ReactUpdates = _dereq_(94);
82426
82427var invariant = _dereq_(158);
82428var warning = _dereq_(168);
82429
82430var didWarnValueLink = false;
82431var didWarnCheckedLink = false;
82432var didWarnValueNull = false;
82433var didWarnValueDefaultValue = false;
82434var didWarnCheckedDefaultChecked = false;
82435var didWarnControlledToUncontrolled = false;
82436var didWarnUncontrolledToControlled = false;
82437
82438function forceUpdateIfMounted() {
82439  if (this._rootNodeID) {
82440    // DOM component is still mounted; update
82441    ReactDOMInput.updateWrapper(this);
82442  }
82443}
82444
82445function warnIfValueIsNull(props) {
82446  if (props != null && props.value === null && !didWarnValueNull) {
82447    "development" !== 'production' ? warning(false, '`value` prop on `input` should not be null. ' + 'Consider using the empty string to clear the component or `undefined` ' + 'for uncontrolled components.') : void 0;
82448
82449    didWarnValueNull = true;
82450  }
82451}
82452
82453/**
82454 * Implements an <input> native component that allows setting these optional
82455 * props: `checked`, `value`, `defaultChecked`, and `defaultValue`.
82456 *
82457 * If `checked` or `value` are not supplied (or null/undefined), user actions
82458 * that affect the checked state or value will trigger updates to the element.
82459 *
82460 * If they are supplied (and not null/undefined), the rendered element will not
82461 * trigger updates to the element. Instead, the props must change in order for
82462 * the rendered element to be updated.
82463 *
82464 * The rendered element will be initialized as unchecked (or `defaultChecked`)
82465 * with an empty value (or `defaultValue`).
82466 *
82467 * @see http://www.w3.org/TR/2012/WD-html5-20121025/the-input-element.html
82468 */
82469var ReactDOMInput = {
82470  getNativeProps: function (inst, props) {
82471    var value = LinkedValueUtils.getValue(props);
82472    var checked = LinkedValueUtils.getChecked(props);
82473
82474    var nativeProps = _assign({
82475      // Make sure we set .type before any other properties (setting .value
82476      // before .type means .value is lost in IE11 and below)
82477      type: undefined
82478    }, DisabledInputUtils.getNativeProps(inst, props), {
82479      defaultChecked: undefined,
82480      defaultValue: undefined,
82481      value: value != null ? value : inst._wrapperState.initialValue,
82482      checked: checked != null ? checked : inst._wrapperState.initialChecked,
82483      onChange: inst._wrapperState.onChange
82484    });
82485
82486    return nativeProps;
82487  },
82488
82489  mountWrapper: function (inst, props) {
82490    if ("development" !== 'production') {
82491      LinkedValueUtils.checkPropTypes('input', props, inst._currentElement._owner);
82492
82493      if (props.valueLink !== undefined && !didWarnValueLink) {
82494        "development" !== 'production' ? warning(false, '`valueLink` prop on `input` is deprecated; set `value` and `onChange` instead.') : void 0;
82495        didWarnValueLink = true;
82496      }
82497      if (props.checkedLink !== undefined && !didWarnCheckedLink) {
82498        "development" !== 'production' ? warning(false, '`checkedLink` prop on `input` is deprecated; set `value` and `onChange` instead.') : void 0;
82499        didWarnCheckedLink = true;
82500      }
82501      if (props.checked !== undefined && props.defaultChecked !== undefined && !didWarnCheckedDefaultChecked) {
82502        "development" !== 'production' ? warning(false, 'Input elements must be either controlled or uncontrolled ' + '(specify either the checked prop, or the defaultChecked prop, but not ' + 'both). Decide between using a controlled or uncontrolled input ' + 'element and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components') : void 0;
82503        didWarnCheckedDefaultChecked = true;
82504      }
82505      if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValueDefaultValue) {
82506        "development" !== 'production' ? warning(false, 'Input elements must be either controlled or uncontrolled ' + '(specify either the value prop, or the defaultValue prop, but not ' + 'both). Decide between using a controlled or uncontrolled input ' + 'element and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components') : void 0;
82507        didWarnValueDefaultValue = true;
82508      }
82509      warnIfValueIsNull(props);
82510    }
82511
82512    var defaultValue = props.defaultValue;
82513    inst._wrapperState = {
82514      initialChecked: props.defaultChecked || false,
82515      initialValue: defaultValue != null ? defaultValue : null,
82516      listeners: null,
82517      onChange: _handleChange.bind(inst)
82518    };
82519
82520    if ("development" !== 'production') {
82521      inst._wrapperState.controlled = props.checked !== undefined || props.value !== undefined;
82522    }
82523  },
82524
82525  updateWrapper: function (inst) {
82526    var props = inst._currentElement.props;
82527
82528    if ("development" !== 'production') {
82529      warnIfValueIsNull(props);
82530
82531      var initialValue = inst._wrapperState.initialChecked || inst._wrapperState.initialValue;
82532      var defaultValue = props.defaultChecked || props.defaultValue;
82533      var controlled = props.checked !== undefined || props.value !== undefined;
82534      var owner = inst._currentElement._owner;
82535
82536      if ((initialValue || !inst._wrapperState.controlled) && controlled && !didWarnUncontrolledToControlled) {
82537        "development" !== 'production' ? warning(false, '%s is changing a uncontrolled input of type %s to be controlled. ' + 'Input elements should not switch from uncontrolled to controlled (or vice versa). ' + 'Decide between using a controlled or uncontrolled input ' + 'element for the lifetime of the component. More info: https://fb.me/react-controlled-components', owner && owner.getName() || 'A c
82537omponent', props.type) : void 0;
82538        didWarnUncontrolledToControlled = true;
82539      }
82540      if (inst._wrapperState.controlled && (defaultValue || !controlled) && !didWarnControlledToUncontrolled) {
82541        "development" !== 'production' ? warning(false, '%s is changing a controlled input of type %s to be uncontrolled. ' + 'Input elements should not switch from controlled to uncontrolled (or vice versa). ' + 'Decide between using a controlled or uncontrolled input ' + 'element for the lifetime of the component. More info: https://fb.me/react-controlled-components', owner && owner.getName() || 'A component', props.type) : void 0;
82542        didWarnControlledToUncontrolled = true;
82543      }
82544    }
82545
82546    // TODO: Shouldn't this be getChecked(props)?
82547    var checked = props.checked;
82548    if (checked != null) {
82549      DOMPropertyOperations.setValueForProperty(ReactDOMComponentTree.getNodeFromInstance(inst), 'checked', checked || false);
82550    }
82551
82552    var value = LinkedValueUtils.getValue(props);
82553    if (value != null) {
82554      // Cast `value` to a string to ensure the value is set correctly. While
82555      // browsers typically do this as necessary, jsdom doesn't.
82556      DOMPropertyOperations.setValueForProperty(ReactDOMComponentTree.getNodeFromInstance(inst), 'value', '' + value);
82557    }
82558  }
82559};
82560
82561function _handleChange(event) {
82562  var props = this._currentElement.props;
82563
82564  var returnValue = LinkedValueUtils.executeOnChange(props, event);
82565
82566  // Here we use asap to wait until all updates have propagated, which
82567  // is important when using controlled components within layers:
82568  // https://github.com/facebook/react/issues/1698
82569  ReactUpdates.asap(forceUpdateIfMounted, this);
82570
82571  var name = props.name;
82572  if (props.type === 'radio' && name != null) {
82573    var rootNode = ReactDOMComponentTree.getNodeFromInstance(this);
82574    var queryRoot = rootNode;
82575
82576    while (queryRoot.parentNode) {
82577      queryRoot = queryRoot.parentNode;
82578    }
82579
82580    // If `rootNode.form` was non-null, then we could try `form.elements`,
82581    // but that sometimes behaves strangely in IE8. We could also try using
82582    // `form.getElementsByName`, but that will only return direct children
82583    // and won't include inputs that use the HTML5 `form=` attribute. Since
82584    // the input might not even be in a form, let's just use the global
82585    // `querySelectorAll` to ensure we don't miss anything.
82586    var group = queryRoot.querySelectorAll('input[name=' + JSON.stringify('' + name) + '][type="radio"]');
82587
82588    for (var i = 0; i < group.length; i++) {
82589      var otherNode = group[i];
82590      if (otherNode === rootNode || otherNode.form !== rootNode.form) {
82591        continue;
82592      }
82593      // This will throw if radio buttons rendered by different copies of React
82594      // and the same name are rendered into the same form (same as #1939).
82595      // That's probably okay; we don't support it just as we don't support
82596      // mixing React radio buttons with non-React ones.
82597      var otherInstance = ReactDOMComponentTree.getInstanceFromNode(otherNode);
82598      !otherInstance ? "development" !== 'production' ? invariant(false, 'ReactDOMInput: Mixing React and non-React radio inputs with the ' + 'same `name` is not supported.') : invariant(false) : void 0;
82599      // If this is a controlled radio button group, forcing the input that
82600      // was previously checked to update will cause it to be come re-checked
82601      // as appropriate.
82602      ReactUpdates.asap(forceUpdateIfMounted, otherInstance);
82603    }
82604  }
82605
82606  return returnValue;
82607}
82608
82609module.exports = ReactDOMInput;
82610},{"11":11,"14":14,"158":158,"168":168,"169":169,"24":24,"40":40,"94":94}],48:[function(_dereq_,module,exports){
82611/**
82612 * Copyright 2013-present, Facebook, Inc.
82613 * All rights reserved.
82614 *
82615 * This source code is licensed under the BSD-style license found in the
82616 * LICENSE file in the root directory of this source tree. An additional grant
82617 * of patent rights can be found in the PATENTS file in the same directory.
82618 *
82619 * @providesModule ReactDOMInstrumentation
82620 */
82621
82622
82623
82624var ReactDOMDebugTool = _dereq_(42);
82625
82626module.exports = { debugTool: ReactDOMDebugTool };
82627},{"42":42}],49:[function(_dereq_,module,exports){
82628/**
82629 * Copyright 2013-present, Facebook, Inc.
82630 * All rights reserved.
82631 *
82632 * This source code is licensed under the BSD-style license found in the
82633 * LICENSE file in the root directory of this source tree. An additional grant
82634 * of patent rights can be found in the PATENTS file in the same directory.
82635 *
82636 * @providesModule ReactDOMOption
82637 */
82638
82639
82640
82641var _assign = _dereq_(169);
82642
82643var ReactChildren = _dereq_(29);
82644var ReactDOMComponentTree = _dereq_(40);
82645var ReactDOMSelect = _dereq_(50);
82646
82647var warning = _dereq_(168);
82648
82649/**
82650 * Implements an <option>
82650 native component that warns when `selected` is set.
82651 */
82652var ReactDOMOption = {
82653  mountWrapper: function (inst, props, nativeParent) {
82654    // TODO (yungsters): Remove support for `selected` in <option>.
82655    if ("development" !== 'production') {
82656      "development" !== 'production' ? warning(props.selected == null, 'Use the `defaultValue` or `value` props on <select> instead of ' + 'setting `selected` on <option>.') : void 0;
82657    }
82658
82659    // Look up whether this option is 'selected'
82660    var selectValue = null;
82661    if (nativeParent != null) {
82662      var selectParent = nativeParent;
82663
82664      if (selectParent._tag === 'optgroup') {
82665        selectParent = selectParent._nativeParent;
82666      }
82667
82668      if (selectParent != null && selectParent._tag === 'select') {
82669        selectValue = ReactDOMSelect.getSelectValueContext(selectParent);
82670      }
82671    }
82672
82673    // If the value is null (e.g., no specified value or after initial mount)
82674    // or missing (e.g., for <datalist>), we don't change props.selected
82675    var selected = null;
82676    if (selectValue != null) {
82677      selected = false;
82678      if (Array.isArray(selectValue)) {
82679        // multiple
82680        for (var i = 0; i < selectValue.length; i++) {
82681          if ('' + selectValue[i] === '' + props.value) {
82682            selected = true;
82683            break;
82684          }
82685        }
82686      } else {
82687        selected = '' + selectValue === '' + props.value;
82688      }
82689    }
82690
82691    inst._wrapperState = { selected: selected };
82692  },
82693
82694  postMountWrapper: function (inst) {
82695    // value="" should make a value attribute (#6219)
82696    var props = inst._currentElement.props;
82697    if (props.value != null) {
82698      var node = ReactDOMComponentTree.getNodeFromInstance(inst);
82699      node.setAttribute('value', props.value);
82700    }
82701  },
82702
82703  getNativeProps: function (inst, props) {
82704    var nativeProps = _assign({ selected: undefined, children: undefined }, props);
82705
82706    // Read state only from initial mount because <select> updates value
82707    // manually; we need the initial state only for server rendering
82708    if (inst._wrapperState.selected != null) {
82709      nativeProps.selected = inst._wrapperState.selected;
82710    }
82711
82712    var content = '';
82713
82714    // Flatten children and warn if they aren't strings or numbers;
82715    // invalid types are ignored.
82716    ReactChildren.forEach(props.children, function (child) {
82717      if (child == null) {
82718        return;
82719      }
82720      if (typeof child === 'string' || typeof child === 'number') {
82721        content += child;
82722      } else {
82723        "development" !== 'production' ? warning(false, 'Only strings and numbers are supported as <option> children.') : void 0;
82724      }
82725    });
82726
82727    if (content) {
82728      nativeProps.children = content;
82729    }
82730
82731    return nativeProps;
82732  }
82733
82734};
82735
82736module.exports = ReactDOMOption;
82737},{"168":168,"169":169,"29":29,"40":40,"50":50}],50:[function(_dereq_,module,exports){
82738/**
82739 * Copyright 2013-present, Facebook, Inc.
82740 * All rights reserved.
82741 *
82742 * This source code is licensed under the BSD-style license found in the
82743 * LICENSE file in the root directory of this source tree. An additional grant
82744 * of patent rights can be found in the PATENTS file in the same directory.
82745 *
82746 * @providesModule ReactDOMSelect
82747 */
82748
82749
82750
82751var _assign = _dereq_(169);
82752
82753var DisabledInputUtils = _dereq_(14);
82754var LinkedValueUtils = _dereq_(24);
82755var ReactDOMComponentTree = _dereq_(40);
82756var ReactUpdates = _dereq_(94);
82757
82758var warning = _dereq_(168);
82759
82760var didWarnValueLink = false;
82761var didWarnValueNull = false;
82762var didWarnValueDefaultValue = false;
82763
82764function updateOptionsIfPendingUpdateAndMounted() {
82765  if (this._rootNodeID && this._wrapperState.pendingUpdate) {
82766    this._wrapperState.pendingUpdate = false;
82767
82768    var props = this._currentElement.props;
82769    var value = LinkedValueUtils.getValue(props);
82770
82771    if (value != null) {
82772      updateOptions(this, Boolean(props.multiple), value);
82773    }
82774  }
82775}
82776
82777function getDeclarationErrorAddendum(owner) {
82778  if (owner) {
82779    var name = owner.getName();
82780    if (name) {
82781      return ' Check the render method of `' + name + '`.';
82782    }
82783  }
82784  return '';
82785}
82786
82787function warnIfValueIsNull(props) {
82788  if (props != null && props.value === null && !didWarnValueNull) {
82789    "development" !== 'production' ? warning(false, '`value` prop on `select` should not be null. ' + 'Consider using the empty string to clear the component or `undefined` ' + 'for uncontrolled components.') : void 0;
82790
82791    didWarnValueNull = true;
82792  }
82793}
82794
82795var valuePropNames = ['value', 'defaultValue'];
82796
82797/**
82798 * Validation function for `value` and `defaultValue`.
82799 * @private
82800 */
82801function checkSelectPropTypes(inst, props) {
82802  var owner = inst._currentElement._owner;
82803  LinkedValueUtils.checkPropTypes('select', props, owner);
82804
82805  if (props.valueLink !== undefined && !didWarnValueLink) {
82806    "development" !== 'production' ? warning(false, '`valueLink` prop on `select` is deprecated; set `value` and `onChange` instead.') : void 0;
82807    didWarnValueLink = true;
82808  }
82809
82810  for (var i = 0; i < valuePropNames.length; i++) {
82811    var propName = valuePropNames[i];
82812    if (props[propName] == null) {
82813      continue;
82814    }
82815    if (props.multiple) {
82816      "development" !== 'production' ? warning(Array.isArray(props[propName]), 'The `%s` prop supplied to <select> must be an array if ' + '`multiple` is true.%s', propName, getDeclarationErrorAddendum(owner)) : void 0;
82817    } else {
82818      "development" !== 'production' ? warning(!Array.isArray(props[propName]), 'The `%s` prop supplied to <select> must be a scalar ' + 'value if `multiple` is false.%s', propName, getDeclarationErrorAddendum(owner)) : void 0;
82819    }
82820  }
82821}
82822
82823/**
82824 * @param {ReactDOMComponent} inst
82825 * @param {boolean} multiple
82826 * @param {*} propValue A stringable (with `multiple`, a list of stringables).
82827 * @private
82828 */
82829function updateOptions(inst, multiple, propValue) {
82830  var selectedValue, i;
82831  var options = ReactDOMComponentTree.getNodeFromInstance(inst).options;
82832
82833  if (multiple) {
82834    selectedValue = {};
82835    for (i = 0; i < propValue.length; i++) {
82836      selectedValue['' + propValue[i]] = true;
82837    }
82838    for (i = 0; i < options.length; i++) {
82839      var selected = selectedValue.hasOwnProperty(options[i].value);
82840      if (options[i].selected !== selected) {
82841        options[i].selected = selected;
82842      }
82843    }
82844  } else {
82845    // Do not set `select.value` as exact behavior isn't consistent across all
82846    // browsers for all cases.
82847    selectedValue = '' + propValue;
82848    for (i = 0; i < options.length; i++) {
82849      if (options[i].value === selectedValue) {
82850        options[i].selected = true;
82851        return;
82852      }
82853    }
82854    if (options.length) {
82855      options[0].selected = true;
82856    }
82857  }
82858}
82859
82860/**
82861 * Implements a <select> native component that allows optionally setting the
82862 * props `value` and `defaultValue`. If `multiple` is false, the prop must be a
82863 * stringable. If `multiple` is true, the prop must be an array of stringables.
82864 *
82865 * If `value` is not supplied (or null/undefined), user actions that change the
82866 * selected option will trigger updates to the rendered options.
82867 *
82868 * If it is supplied (and not null/undefined), the rendered options will not
82869 * update in response to user actions. Instead, the `value` prop must change in
82870 * order for the rendered options to update.
82871 *
82872 * If `defaultValue` is provided, any options with the supplied values will be
82873 * selected.
82874 */
82875var ReactDOMSelect = {
82876  getNativeProps: function (inst, props) {
82877    return _assign({}, DisabledInputUtils.getNativeProps(inst, props), {
82878      onChange: inst._wrapperState.onChange,
82879      value: undefined
82880    });
82881  },
82882
82883  mountWrapper: function (inst, props) {
82884    if ("development" !== 'production') {
82885      checkSelectPropTypes(inst, props);
82886      warnIfValueIsNull(props);
82887    }
82888
82889    var value = LinkedValueUtils.getValue(props);
82890    inst._wrapperState = {
82891      pendingUpdate: false,
82892      initialValue: value != null ? value : props.defaultValue,
82893      listeners: null,
82894      onChange: _handleChange.bind(inst),
82895      wasMultiple: Boolean(props.multiple)
82896    };
82897
82898    if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValueDefaultValue) {
82899      "development" !== 'production' ? warning(false, 'Select elements must be either controlled or uncontrolled ' + '(specify either the value prop, or the defaultValue prop, but not ' + 'both). Decide between using a controlled or uncontrolled select ' + 'element and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components') : void 0;
82900      didWarnValueDefaultValue = true;
82901    }
82902  },
82903
82904  getSelectValueContext: function (inst) {
82905    // ReactDOMOption looks at this initial value so the initial generated
82906    // markup has correct `selected` attributes
82907    return inst._wrapperState.initialValue;
82908  },
82909
82910  postUpdateWrapper: function (inst) {
82911    var props = inst._currentElement.props;
82912    if ("development" !== 'production') {
82913      warnIfValueIsNull(props);
82914    }
82915
82916    // After the initial mount, we control selected-ness manually so don't pass
82917    // this value down
82918    inst._wrapperState.initialValue = undefined;
82919
82920    var wasMultiple = inst._wrapperState.wasMultiple;
82921    inst._wrapperState.wasMultiple = Boolean(props.multiple);
82922
82923    var value = LinkedValueUtils.getValue(props);
82924    if (value != null) {
82925      inst._wrapperState.pendingUpdate = false;
82926      updateOptions(inst, Boolean(props.multiple), value);
82927    } else if (wasMultiple !== Boolean(props.multiple)) {
82928      // For simplicity, reapply `defaultValue` if `multiple` is toggled.
82929      if (props.defaultValue != null) {
82930        updateOptions(inst, Boolean(props.multiple), props.defaultValue);
82931      } else {
82932        // Revert the select back to its default unselected state.
82933        updateOptions(inst, Boolean(props.multiple), props.multiple ? [] : '');
82934      }
82935    }
82936  }
82937};
82938
82939function _handleChange(event) {
82940  var props = this._currentElement.props;
82941  var returnValue = LinkedValueUtils.executeOnChange(props, event);
82942
82943  if (this._rootNodeID) {
82944    this._wrapperState.pendingUpdate = true;
82945  }
82946  ReactUpdates.asap(updateOptionsIfPendingUpdateAndMounted, this);
82947  return returnValue;
82948}
82949
82950module.exports = ReactDOMSelect;
82951},{"14":14,"168":168,"169":169,"24":24,"40":40,"94":94}],51:[function(_dereq_,module,exports){
82952/**
82953 * Copyright 2013-present, Facebook, Inc.
82954 * All rights reserved.
82955 *
82956 * This source code is licensed under the BSD-style license found in the
82957 * LICENSE file in the root directory of this source tree. An additional grant
82958 * of patent rights can be found in the PATENTS file in the same directory.
82959 *
82960 * @providesModule ReactDOMSelection
82961 */
82962
82963
82964
82965var ExecutionEnvironment = _dereq_(144);
82966
82967var getNodeForCharacterOffset = _dereq_(129);
82968var getTextContentAccessor = _dereq_(130);
82969
82970/**
82971 * While `isCollapsed` is available on the Selection object and `collapsed`
82972 * is available on the Range object, IE11 sometimes gets them wrong.
82973 * If the anchor/focus nodes and offsets are the same, the range is collapsed.
82974 */
82975function isCollapsed(anchorNode, anchorOffset, focusNode, focusOffset) {
82976  return anchorNode === focusNode && anchorOffset === focusOffset;
82977}
82978
82979/**
82980 * Get the appropriate anchor and focus node/offset pairs for IE.
82981 *
82982 * The catch here is that IE's selection API doesn't provide information
82983 * about whether the selection is forward or backward, so we have to
82984 * behave as though it's always forward.
82985 *
82986 * IE text differs from modern selection in that it behaves as though
82987 * block elements end with a new line. This means character offsets will
82988 * differ between the two APIs.
82989 *
82990 * @param {DOMElement} node
82991 * @return {object}
82992 */
82993function getIEOffsets(node) {
82994  var selection = document.selection;
82995  var selectedRange = selection.createRange();
82996  var selectedLength = selectedRange.text.length;
82997
82998  // Duplicate selection so we can move range without breaking user selection.
82999  var fromStart = selectedRange.duplicate();
83000  fromStart.moveToElementText(node);
83001  fromStart.setEndPoint('EndToStart', selectedRange);
83002
83003  var startOffset = fromStart.text.length;
83004  var endOffset = startOffset + selectedLength;
83005
83006  return {
83007    start: startOffset,
83008    end: endOffset
83009  };
83010}
83011
83012/**
83013 * @param {DOMElement} node
83014 * @return {?object}
83015 */
83016function getModernOffsets(node) {
83017  var selection = window.getSelection && window.getSelection();
83018
83019  if (!selection || selection.rangeCount === 0) {
83020    return null;
83021  }
83022
83023  var anchorNode = selection.anchorNode;
83024  var anchorOffset = selection.anchorOffset;
83025  var focusNode = selection.focusNode;
83026  var focusOffset = selection.focusOffset;
83027
83028  var currentRange = selection.getRangeAt(0);
83029
83030  // In Firefox, range.startContainer and range.endContainer can be "anonymous
83031  // divs", e.g. the up/down buttons on an <input type="number">. Anonymous
83032  // divs do not seem to expose properties, triggering a "Permission denied
83033  // error" if any of its properties are accessed. The only seemingly possible
83034  // way to avoid erroring is to access a property that typically works for
83035  // non-anonymous divs and catch any error that may otherwise arise. See
83036  // https://bugzilla.mozilla.org/show_bug.cgi?id=208427
83037  try {
83038    /* eslint-disable no-unused-expressions */
83039    currentRange.startContainer.nodeType;
83040    currentRange.endContainer.nodeType;
83041    /* eslint-enable no-unused-expressions */
83042  } catch (e) {
83043    return null;
83044  }
83045
83046  // If the node and offset values are the same, the selection is collapsed.
83047  // `Selection.isCollapsed` is available natively, but IE sometimes gets
83048  // this value wrong.
83049  var isSelectionCollapsed = isCollapsed(selection.anchorNode, selection.anchorOffset, selection.focusNode, selection.focusOffset);
83050
83051  var rangeLength = isSelectionCollapsed ? 0 : currentRange.toString().length;
83052
83053  var tempRange = currentRange.cloneRange();
83054  tempRange.selectNodeContents(node);
83055  tempRange.setEnd(currentRange.startContainer, currentRange.startOffset);
83056
83057  var isTempRangeCollapsed = isCollapsed(tempRange.startContainer, tempRange.startOffset, tempRange.endContainer, tempRange.endOffset);
83058
83059  var start = isTempRangeCollapsed ? 0 : tempRange.toString().length;
83060  var end = start + rangeLength;
83061
83062  // Detect whether the selection is backward.
83063  var detectionRange = document.createRange();
83064  detectionRange.setStart(anchorNode, anchorOffset);
83065  detectionRange.setEnd(focusNode, focusOffset);
83066  var isBackward = detectionRange.collapsed;
83067
83068  return {
83069    start: isBackward ? end : start,
83070    end: isBackward ? start : end
83071  };
83072}
83073
83074/**
83075 * @param {DOMElement|DOMTextNode} node
83076 * @param {object} offsets
83077 */
83078function setIEOffsets(node, offsets) {
83079  var range = document.selection.createRange().duplicate();
83080  var start, end;
83081
83082  if (offsets.end === undefined) {
83083    start = offsets.start;
83084    end = start;
83085  } else if (offsets.start > offsets.end) {
83086    start = offsets.end;
83087    end = offsets.start;
83088  } else {
83089    start = offsets.start;
83090    end = offsets.end;
83091  }
83092
83093  range.moveToElementText(node);
83094  range.moveStart('character', start);
83095  range.setEndPoint('EndToStart', range);
83096  range.moveEnd('character', end - start);
83097  range.select();
83098}
83099
83100/**
83101 * In modern non-IE browsers, we can support both forward and backward
83102 * selections.
83103 *
83104 * Note: IE10+ supports the Selection object, but it does not support
83105 * the `extend` method, which means that even in modern IE, it's not possible
83106 * to programmatically create a backward selection. Thus, for all IE
83107 * versions, we use the old IE API to create our selections.
83108 *
83109 * @param {DOMElement|DOMTextNode} node
83110 * @param {object} offsets
83111 */
83112function setModernOffsets(node, offsets) {
83113  if (!window.getSelection) {
83114    return;
83115  }
83116
83117  var selection = window.getSelection();
83118  var length = node[getTextContentAccessor()].length;
83119  var start = Math.min(offsets.start, length);
83120  var end = offsets.end === undefined ? start : Math.min(offsets.end, length);
83121
83122  // IE 11 uses modern selection, but doesn't support the extend method.
83123  // Flip backward selections, so we can set with a single range.
83124  if (!selection.extend && start > end) {
83125    var temp = end;
83126    end = start;
83127    start = temp;
83128  }
83129
83130  var startMarker = getNodeForCharacterOffset(node, start);
83131  var endMarker = getNodeForCharacterOffset(node, end);
83132
83133  if (startMarker && endMarker) {
83134    var range = document.createRange();
83135    range.setStart(startMarker.node, startMarker.offset);
83136    selection.removeAllRanges();
83137
83138    if (start > end) {
83139      selection.addRange(range);
83140      selection.extend(endMarker.node, endMarker.offset);
83141    } else {
83142      range.setEnd(endMarker.node, endMarker.offset);
83143      selection.addRange(range);
83144    }
83145  }
83146}
83147
83148var useIEOffsets = ExecutionEnvironment.canUseDOM && 'selection' in document && !('getSelection' in window);
83149
83150var ReactDOMSelection = {
83151  /**
83152   * @param {DOMElement} node
83153   */
83154  getOffsets: useIEOffsets ? getIEOffsets : getModernOffsets,
83155
83156  /**
83157   * @param {DOMElement|DOMTextNode} node
83158   * @param {object} offsets
83159   */
83160  setOffsets: useIEOffsets ? setIEOffsets : setModernOffsets
83161};
83162
83163module.exports = ReactDOMSelection;
83164},{"129":129,"130":130,"144":144}],52:[function(_dereq_,module,exports){
83165/**
83166 * Copyright 2013-present, Facebook, Inc.
83167 * All rights reserved.
83168 *
83169 * This source code is licensed under the BSD-style license found in the
83170 * LICENSE file in the root directory of this source tree. An additional grant
83171 * of patent rights can be found in the PATENTS file in the same directory.
83172 *
83173 * @providesModule ReactDOMServer
83174 */
83175
83176
83177
83178var ReactDefaultInjection = _dereq_(59);
83179var ReactServerRendering = _dereq_(90);
83180var ReactVersion = _dereq_(95);
83181
83182ReactDefaultInjection.inject();
83183
83184var ReactDOMServer = {
83185  renderToString: ReactServerRendering.renderToString,
83186  renderToStaticMarkup: ReactServerRendering.renderToStaticMarkup,
83187  version: ReactVersion
83188};
83189
83190module.exports = ReactDOMServer;
83191},{"59":59,"90":90,"95":95}],53:[function(_dereq_,module,exports){
83192/**
83193 * Copyright 2013-present, Facebook, Inc.
83194 * All rights reserved.
83195 *
83196 * This source code is licensed under the BSD-style license found in the
83197 * LICENSE file in the root directory of this source tree. An additional grant
83198 * of patent rights can be found in the PATENTS file in the same directory.
83199 *
83200 * @providesModule ReactDOMTextComponent
83201 */
83202
83203
83204
83205var _assign = _dereq_(169);
83206
83207var DOMChildrenOperations = _dereq_(7);
83208var DOMLazyTree = _dereq_(8);
83209var ReactDOMComponentTree = _dereq_(40);
83210var ReactPerf = _dereq_(82);
83211
83212var escapeTextContentForBrowser = _dereq_(119);
83213var invariant = _dereq_(158);
83214var validateDOMNesting = _dereq_(142);
83215
83216/**
83217 * Text nodes violate a couple assumptions that React makes about components:
83218 *
83219 *  - When mounting text into the DOM, adjacent text nodes are merged.
83220 *  - Text nodes cannot be assigned a React root ID.
83221 *
83222 * This component is used to wrap strings between comment nodes so that they
83223 * can undergo the same reconciliation that is applied to elements.
83224 *
83225 * TODO: Investigate representing React components in the DOM with text nodes.
83226 *
83227 * @class ReactDOMTextComponent
83228 * @extends ReactComponent
83229 * @internal
83230 */
83231var ReactDOMTextComponent = function (text) {
83232  // TODO: This is really a ReactText (ReactNode), not a ReactElement
83233  this._currentElement = text;
83234  this._stringText = '' + text;
83235  // ReactDOMComponentTree uses these:
83236  this._nativeNode = null;
83237  this._nativeParent = null;
83238
83239  // Properties
83240  this._domID = null;
83241  this._mountIndex = 0;
83242  this._closingComment = null;
83243  this._commentNodes = null;
83244};
83245
83246_assign(ReactDOMTextComponent.prototype, {
83247
83248  /**
83249   * Creates the markup for this text node. This node is not intended to have
83250   * any features besides containing text content.
83251   *
83252   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
83253   * @return {string} Markup for this text node.
83254   * @internal
83255   */
83256  mountComponent: function (transaction, nativeParent, nativeContainerInfo, context) {
83257    if ("development" !== 'production') {
83258      var parentInfo;
83259      if (nativeParent != null) {
83260        parentInfo = nativeParent._ancestorInfo;
83261      } else if (nativeContainerInfo != null) {
83262        parentInfo = nativeContainerInfo._ancestorInfo;
83263      }
83264      if (parentInfo) {
83265        // parentInfo should always be present except for the top-level
83266        // component when server rendering
83267        validateDOMNesting('#text', this, parentInfo);
83268      }
83269    }
83270
83271    var domID = nativeContainerInfo._idCounter++;
83272    var openingValue = ' react-text: ' + domID + ' ';
83273    var closingValue = ' /react-text ';
83274    this._domID = domID;
83275    this._nativeParent = nativeParent;
83276    if (transaction.useCreateElement) {
83277      var ownerDocument = nativeContainerInfo._ownerDocument;
83278      var openingComment = ownerDocument.createComment(openingValue);
83279      var closingComment = ownerDocument.createComment(closingValue);
83280      var lazyTree = DOMLazyTree(ownerDocument.createDocumentFragment());
83281      DOMLazyTree.queueChild(lazyTree, DOMLazyTree(openingComment));
83282      if (this._stringText) {
83283        DOMLazyTree.queueChild(lazyTree, DOMLazyTree(ownerDocument.createTextNode(this._stringText)));
83284      }
83285      DOMLazyTree.queueChild(lazyTree, DOMLazyTree(closingComment));
83286      ReactDOMComponentTree.precacheNode(this, openingComment);
83287      this._closingComment = closingComment;
83288      return lazyTree;
83289    } else {
83290      var escapedText = escapeTextContentForBrowser(this._stringText);
83291
83292      if (transaction.renderToStaticMarkup) {
83293        // Normally we'd wrap this between comment nodes for the reasons stated
83294        // above, but since this is a situation where React won't take over
83295        // (static pages), we can simply return the text as it is.
83296        return escapedText;
83297      }
83298
83299      return '<!--' + openingValue + '-->' + escapedText + '<!--' + closingValue + '-->';
83300    }
83301  },
83302
83303  /**
83304   * Updates this component by updating the text content.
83305   *
83306   * @param {ReactText} nextText The next text content
83307   * @param {ReactReconcileTransaction} transaction
83308   * @internal
83309   */
83310  receiveComponent: function (nextText, transaction) {
83311    if (nextText !== this._currentElement) {
83312      this._currentElement = nextText;
83313      var nextStringText = '' + nextText;
83314      if (nextStringText !== this._stringText) {
83315        // TODO: Save this as pending props and use performUpdateIfNecessary
83316        // and/or updateComponent to do the actual update for consistency with
83317        // other component types?
83318        this._stringText = nextStringText;
83319        var commentNodes = this.getNativeNode();
83320        DOMChildrenOperations.replaceDelimitedText(commentNodes[0], commentNodes[1], nextStringText);
83321      }
83322    }
83323  },
83324
83325  getNativeNode: function () {
83326    var nativeNode = this._commentNodes;
83327    if (nativeNode) {
83328      return nativeNode;
83329    }
83330    if (!this._closingComment) {
83331      var openingComment = ReactDOMComponentTree.getNodeFromInstance(this);
83332      var node = openingComment.nextSibling;
83333      while (true) {
83334        !(node != null) ? "development" !== 'production' ? invariant(false, 'Missing closing comment for text component %s', this._domID) : invariant(false) : void 0;
83335        if (node.nodeType === 8 && node.nodeValue === ' /react-text ') {
83336          this._closingComment = node;
83337          break;
83338        }
83339        node = node.nextSibling;
83340      }
83341    }
83342    nativeNode = [this._nativeNode, this._closingComment];
83343    this._commentNodes = nativeNode;
83344    return nativeNode;
83345  },
83346
83347  unmountComponent: function () {
83348    this._closingComment = null;
83349    this._commentNodes = null;
83350    ReactDOMComponentTree.uncacheNode(this);
83351  }
83352
83353});
83354
83355ReactPerf.measureMethods(ReactDOMTextComponent.prototype, 'ReactDOMTextComponent', {
83356  mountComponent: 'mountComponent',
83357  receiveComponent: 'receiveComponent'
83358});
83359
83360module.exports = ReactDOMTextComponent;
83361},{"119":119,"142":142,"158":158,"169":169,"40":40,"7":7,"8":8,"82":82}],54:[function(_dereq_,module,exports){
83362/**
83363 * Copyright 2013-present, Facebook, Inc.
83364 * All rights reserved.
83365 *
83366 * This source code is licensed under the BSD-style license found in the
83367 * LICENSE file in the root directory of this source tree. An additional grant
83368 * of patent rights can be found in the PATENTS file in the same directory.
83369 *
83370 * @providesModule ReactDOMTextarea
83371 */
83372
83373
83374
83375var _assign = _dereq_(169);
83376
83377var DisabledInputUtils = _dereq_(14);
83378var DOMPropertyOperations = _dereq_(11);
83379var LinkedValueUtils = _dereq_(24);
83380var ReactDOMComponentTree = _dereq_(40);
83381var ReactUpdates = _dereq_(94);
83382
83383var invariant = _dereq_(158);
83384var warning = _dereq_(168);
83385
83386var didWarnValueLink = false;
83387var didWarnValueNull = false;
83388var didWarnValDefaultVal = false;
83389
83390function forceUpdateIfMounted() {
83391  if (this._rootNodeID) {
83392    // DOM component is still mounted; update
83393    ReactDOMTextarea.updateWrapper(this);
83394  }
83395}
83396
83397function warnIfValueIsNull(props) {
83398  if (props != null && props.value === null && !didWarnValueNull) {
83399    "development" !== 'production' ? warning(false, '`value` prop on `textarea` should not be null. ' + 'Consider using the empty string to clear the component or `undefined` ' + 'for uncontrolled components.') : void 0;
83400
83401    didWarnValueNull = true;
83402  }
83403}
83404
83405/**
83406 * Implements a <textarea> native component that allows setting `value`, and
83407 * `defaultValue`. This differs from the traditional DOM API because value is
83408 * usually set as PCDATA children.
83409 *
83410 * If `value` is not supplied (or null/undefined), user actions that affect the
83411 * value will trigger updates to the element.
83412 *
83413 * If `value` is supplied (and not null/undefined), the rendered element will
83414 * not trigger updates to the element. Instead, the `value` prop must change in
83415 * order for the rendered element to be updated.
83416 *
83417 * The rendered element will be initialized with an empty value, the prop
83418 * `defaultValue` if specified, or the children content (deprecated).
83419 */
83420var ReactDOMTextarea = {
83421  getNativeProps: function (inst, props) {
83422    !(props.dangerouslySetInnerHTML == null) ? "development" !== 'production' ? invariant(false, '`dangerouslySetInnerHTML` does not make sense on <textarea>.') : invariant(false) : void 0;
83423
83424    // Always set children to the same thing. In IE9, the selection range will
83425    // get reset if `textContent` is mutated.
83426    var nativeProps = _assign({}, DisabledInputUtils.getNativeProps(inst, props), {
83427      defaultValue: undefined,
83428      value: undefined,
83429      children: inst._wrapperState.initialValue,
83430      onChange: inst._wrapperState.onChange
83431    });
83432
83433    return nativeProps;
83434  },
83435
83436  mountWrapper: function (inst, props) {
83437    if ("development" !== 'production') {
83438      LinkedValueUtils.checkPropTypes('textarea', props, inst._currentElement._owner);
83439      if (props.valueLink !== undefined && !didWarnValueLink) {
83440        "development" !== 'production' ? warning(false, '`valueLink` prop on `textarea` is deprecated; set `value` and `onChange` instead.') : void 0;
83441        didWarnValueLink = true;
83442      }
83443      if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValDefaultVal) {
83444        "development" !== 'production' ? warning(false, 'Textarea elements must be either controlled or uncontrolled ' + '(specify either the value prop, or the defaultValue prop, but not ' + 'both). Decide between using a controlled or uncontrolled textarea ' + 'and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components') : void 0;
83445        didWarnValDefaultVal = true;
83446      }
83447      warnIfValueIsNull(props);
83448    }
83449
83450    var defaultValue = props.defaultValue;
83451    // TODO (yungsters): Remove support for children content in <textarea>.
83452    var children = props.children;
83453    if (children != null) {
83454      if ("development" !== 'production') {
83455        "development" !== 'production' ? warning(false, 'Use the `defaultValue` or `value` props instead of setting ' + 'children on <textarea>.') : void 0;
83456      }
83457      !(defaultValue == null) ? "development" !== 'production' ? invariant(false, 'If you supply `defaultValue` on a <textarea>, do not pass children.') : invariant(false) : void 0;
83458      if (Array.isArray(children)) {
83459        !(children.length <= 1) ? "development" !== 'production' ? invariant(false, '<textarea> can only have at most one child.') : invariant(false) : void 0;
83460        children = children[0];
83461      }
83462
83463      defaultValue = '' + children;
83464    }
83465    if (defaultValue == null) {
83466      defaultValue = '';
83467    }
83468    var value = LinkedValueUtils.getValue(props);
83469    inst._wrapperState = {
83470      // We save the initial value so that `ReactDOMComponent` doesn't update
83471      // `textContent` (unnecessary since we update value).
83472      // The initial value can be a boolean or object so that's why it's
83473      // forced to be a string.
83474      initialValue: '' + (value != null ? value : defaultValue),
83475      listeners: null,
83476      onChange: _handleChange.bind(inst)
83477    };
83478  },
83479
83480  updateWrapper: function (inst) {
83481    var props = inst._currentElement.props;
83482
83483    if ("development" !== 'production') {
83484      warnIfValueIsNull(props);
83485    }
83486
83487    var value = LinkedValueUtils.getValue(props);
83488    if (value != null) {
83489      // Cast `value` to a string to ensure the value is set correctly. While
83490      // browsers typically do this as necessary, jsdom doesn't.
83491      DOMPropertyOperations.setValueForProperty(ReactDOMComponentTree.getNodeFromInstance(inst), 'value', '' + value);
83492    }
83493  }
83494};
83495
83496function _handleChange(event) {
83497  var props = this._currentElement.props;
83498  var returnValue = LinkedValueUtils.executeOnChange(props, event);
83499  ReactUpdates.asap(forceUpdateIfMounted, this);
83500  return returnValue;
83501}
83502
83503module.exports = ReactDOMTextarea;
83504},{"11":11,"14":14,"158":158,"168":168,"169":169,"24":24,"40":40,"94":94}],55:[function(_dereq_,module,exports){
83505/**
83506 * Copyright 2015-present, Facebook, Inc.
83507 * All rights reserved.
83508 *
83509 * This source code is licensed under the BSD-style license found in the
83510 * LICENSE file in the root directory of this source tree. An additional grant
83511 * of patent rights can be found in the PATENTS file in the same directory.
83512 *
83513 * @providesModule ReactDOMTreeTraversal
83514 */
83515
83516
83517
83518var invariant = _dereq_(158);
83519
83520/**
83521 * Return the lowest common ancestor of A and B, or null if they are in
83522 * different trees.
83523 */
83524function getLowestCommonAncestor(instA, instB) {
83525  !('_nativeNode' in instA) ? "development" !== 'production' ? invariant(false, 'getNodeFromInstance: Invalid argument.') : invariant(false) : void 0;
83526  !('_nativeNode' in instB) ? "development" !== 'production' ? invariant(false, 'getNodeFromInstance: Invalid argument.') : invariant(false) : void 0;
83527
83528  var depthA = 0;
83529  for (var tempA = instA; tempA; tempA = tempA._nativeParent) {
83530    depthA++;
83531  }
83532  var depthB = 0;
83533  for (var tempB = instB; tempB; tempB = tempB._nativeParent) {
83534    depthB++;
83535  }
83536
83537  // If A is deeper, crawl up.
83538  while (depthA - depthB > 0) {
83539    instA = instA._nativeParent;
83540    depthA--;
83541  }
83542
83543  // If B is deeper, crawl up.
83544  while (depthB - depthA > 0) {
83545    instB = instB._nativeParent;
83546    depthB--;
83547  }
83548
83549  // Walk in lockstep until we find a match.
83550  var depth = depthA;
83551  while (depth--) {
83552    if (instA === instB) {
83553      return instA;
83554    }
83555    instA = instA._nativeParent;
83556    instB = instB._nativeParent;
83557  }
83558  return null;
83559}
83560
83561/**
83562 * Return if A is an ancestor of B.
83563 */
83564function isAncestor(instA, instB) {
83565  !('_nativeNode' in instA) ? "development" !== 'production' ? invariant(false, 'isAncestor: Invalid argument.') : invariant(false) : void 0;
83566  !('_nativeNode' in instB) ? "development" !== 'production' ? invariant(false, 'isAncestor: Invalid argument.') : invariant(false) : void 0;
83567
83568  while (instB) {
83569    if (instB === instA) {
83570      return true;
83571    }
83572    instB = instB._nativeParent;
83573  }
83574  return false;
83575}
83576
83577/**
83578 * Return the parent instance of the passed-in instance.
83579 */
83580function getParentInstance(inst) {
83581  !('_nativeNode' in inst) ? "development" !== 'production' ? invariant(false, 'getParentInstance: Invalid argument.') : invariant(false) : void 0;
83582
83583  return inst._nativeParent;
83584}
83585
83586/**
83587 * Simulates the traversal of a two-phase, capture/bubble event dispatch.
83588 */
83589function traverseTwoPhase(inst, fn, arg) {
83590  var path = [];
83591  while (inst) {
83592    path.push(inst);
83593    inst = inst._nativeParent;
83594  }
83595  var i;
83596  for (i = path.length; i-- > 0;) {
83597    fn(path[i], false, arg);
83598  }
83599  for (i = 0; i < path.length; i++) {
83600    fn(path[i], true, arg);
83601  }
83602}
83603
83604/**
83605 * Traverses the ID hierarchy and invokes the supplied `cb` on any IDs that
83606 * should would receive a `mouseEnter` or `mouseLeave` event.
83607 *
83608 * Does not invoke the callback on the nearest common ancestor because nothing
83609 * "entered" or "left" that element.
83610 */
83611function traverseEnterLeave(from, to, fn, argFrom, argTo) {
83612  var common = from && to ? getLowestCommonAncestor(from, to) : null;
83613  var pathFrom = [];
83614  while (from && from !== common) {
83615    pathFrom.push(from);
83616    from = from._nativeParent;
83617  }
83618  var pathTo = [];
83619  while (to && to !== common) {
83620    pathTo.push(to);
83621    to = to._nativeParent;
83622  }
83623  var i;
83624  for (i = 0; i < pathFrom.length; i++) {
83625    fn(pathFrom[i], true, argFrom);
83626  }
83627  for (i = pathTo.length; i-- > 0;) {
83628    fn(pathTo[i], false, argTo);
83629  }
83630}
83631
83632module.exports = {
83633  isAncestor: isAncestor,
83634  getLowestCommonAncestor: getLowestCommonAncestor,
83635  getParentInstance: getParentInstance,
83636  traverseTwoPhase: traverseTwoPhase,
83637  traverseEnterLeave: traverseEnterLeave
83638};
83639},{"158":158}],56:[function(_dereq_,module,exports){
83640/**
83641 * Copyright 2013-present, Facebook, Inc.
83642 * All rights reserved.
83643 *
83644 * This source code is licensed under the BSD-style license found in the
83645 * LICENSE file in the root directory of this source tree. An additional grant
83646 * of patent rights can be found in the PATENTS file in the same directory.
83647 *
83648 * @providesModule ReactDOMUnknownPropertyDevtool
83649 */
83650
83651
83652
83653var DOMProperty = _dereq_(10);
83654var EventPluginRegistry = _dereq_(18);
83655
83656var warning = _dereq_(168);
83657
83658if ("development" !== 'production') {
83659  var reactProps = {
83660    children: true,
83661    dangerouslySetInnerHTML: true,
83662    key: true,
83663    ref: true
83664  };
83665  var warnedProperties = {};
83666
83667  var warnUnknownProperty = function (name) {
83668    if (DOMProperty.properties.hasOwnProperty(name) || DOMProperty.isCustomAttribute(name)) {
83669      return;
83670    }
83671    if (reactProps.hasOwnProperty(name) && reactProps[name] || warnedProperties.hasOwnProperty(name) && warnedProperties[name]) {
83672      return;
83673    }
83674
83675    warnedProperties[name] = true;
83676    var lowerCasedName = name.toLowerCase();
83677
83678    // data-* attributes should be lowercase; suggest the lowercase version
83679    var standardName = DOMProperty.isCustomAttribute(lowerCasedName) ? lowerCasedName : DOMProperty.getPossibleStandardName.hasOwnProperty(lowerCasedName) ? DOMProperty.getPossibleStandardName[lowerCasedName] : null;
83680
83681    // For now, only warn when we have a suggested correction. This prevents
83682    // logging too much when using transferPropsTo.
83683    "development" !== 'production' ? warning(standardName == null, 'Unknown DOM property %s. Did you mean %s?', name, standardName) : void 0;
83684
83685    var registrationName = EventPluginRegistry.possibleRegistrationNames.hasOwnProperty(lowerCasedName) ? EventPluginRegistry.possibleRegistrationNames[lowerCasedName] : null;
83686
83687    "development" !== 'production' ? warning(registrationName == null, 'Unknown event handler property %s. Did you mean `%s`?', name, registrationName) : void 0;
83688  };
83689}
83690
83691var ReactDOMUnknownPropertyDevtool = {
83692  onCreateMarkupForProperty: function (name, value) {
83693    warnUnknownProperty(name);
83694  },
83695  onSetValueForProperty: function (node, name, value) {
83696    warnUnknownProperty(name);
83697  },
83698  onDeleteValueForProperty: function (node, name) {
83699    warnUnknownProperty(name);
83700  }
83701};
83702
83703module.exports = ReactDOMUnknownPropertyDevtool;
83704},{"10":10,"168":168,"18":18}],57:[function(_dereq_,module,exports){
83705/**
83706 * Copyright 2016-present, Facebook, Inc.
83707 * All rights reserved.
83708 *
83709 * This source code is licensed under the BSD-style license found in the
83710 * LICENSE file in the root directory of this source tree. An additional grant
83711 * of patent rights can be found in the PATENTS file in the same directory.
83712 *
83713 * @providesModule ReactDebugTool
83714 */
83715
83716
83717
83718var ReactInvalidSetStateWarningDevTool = _dereq_(73);
83719var warning = _dereq_(168);
83720
83721var eventHandlers = [];
83722var handlerDoesThrowForEvent = {};
83723
83724function emitEvent(handlerFunctionName, arg1, arg2, arg3, arg4, arg5) {
83725  if ("development" !== 'production') {
83726    eventHandlers.forEach(function (handler) {
83727      try {
83728        if (handler[handlerFunctionName]) {
83729          handler[handlerFunctionName](arg1, arg2, arg3, arg4, arg5);
83730        }
83731      } catch (e) {
83732        "development" !== 'production' ? warning(!handlerDoesThrowForEvent[handlerFunctionName], 'exception thrown by devtool while handling %s: %s', handlerFunctionName, e.message) : void 0;
83733        handlerDoesThrowForEvent[handlerFunctionName] = true;
83734      }
83735    });
83736  }
83737}
83738
83739var ReactDebugTool = {
83740  addDevtool: function (devtool) {
83741    eventHandlers.push(devtool);
83742  },
83743  removeDevtool: function (devtool) {
83744    for (var i = 0; i < eventHandlers.length; i++) {
83745      if (eventHandlers[i] === devtool) {
83746        eventHandlers.splice(i, 1);
83747        i--;
83748      }
83749    }
83750  },
83751  onBeginProcessingChildContext: function () {
83752    emitEvent('onBeginProcessingChildContext');
83753  },
83754  onEndProcessingChildContext: function () {
83755    emitEvent('onEndProcessingChildContext');
83756  },
83757  onSetState: function () {
83758    emitEvent('onSetState');
83759  },
83760  onMountRootComponent: function (internalInstance) {
83761    emitEvent('onMountRootComponent', internalInstance);
83762  },
83763  onMountComponent: function (internalInstance) {
83764    emitEvent('onMountComponent', internalInstance);
83765  },
83766  onUpdateComponent: function (internalInstance) {
83767    emitEvent('onUpdateComponent', internalInstance);
83768  },
83769  onUnmountComponent: function (internalInstance) {
83770    emitEvent('onUnmountComponent', internalInstance);
83771  }
83772};
83773
83774ReactDebugTool.addDevtool(ReactInvalidSetStateWarningDevTool);
83775
83776module.exports = ReactDebugTool;
83777},{"168":168,"73":73}],58:[function(_dereq_,module,exports){
83778/**
83779 * Copyright 2013-present, Facebook, Inc.
83780 * All rights reserved.
83781 *
83782 * This source code is licensed under the BSD-style license found in the
83783 * LICENSE file in the root directory of this source tree. An additional grant
83784 * of patent rights can be found in the PATENTS file in the same directory.
83785 *
83786 * @providesModule ReactDefaultBatchingStrategy
83787 */
83788
83789
83790
83791var _assign = _dereq_(169);
83792
83793var ReactUpdates = _dereq_(94);
83794var Transaction = _dereq_(112);
83795
83796var emptyFunction = _dereq_(150);
83797
83798var RESET_BATCHED_UPDATES = {
83799  initialize: emptyFunction,
83800  close: function () {
83801    ReactDefaultBatchingStrategy.isBatchingUpdates = false;
83802  }
83803};
83804
83805var FLUSH_BATCHED_UPDATES = {
83806  initialize: emptyFunction,
83807  close: ReactUpdates.flushBatchedUpdates.bind(ReactUpdates)
83808};
83809
83810var TRANSACTION_WRAPPERS = [FLUSH_BATCHED_UPDATES, RESET_BATCHED_UPDATES];
83811
83812function ReactDefaultBatchingStrategyTransaction() {
83813  this.reinitializeTransaction();
83814}
83815
83816_assign(ReactDefaultBatchingStrategyTransaction.prototype, Transaction.Mixin, {
83817  getTransactionWrappers: function () {
83818    return TRANSACTION_WRAPPERS;
83819  }
83820});
83821
83822var transaction = new ReactDefaultBatchingStrategyTransaction();
83823
83824var ReactDefaultBatchingStrategy = {
83825  isBatchingUpdates: false,
83826
83827  /**
83828   * Call the provided function in a context within which calls to `setState`
83829   * and friends are batched such that components aren't updated unnecessarily.
83830   */
83831  batchedUpdates: function (callback, a, b, c, d, e) {
83832    var alreadyBatchingUpdates = ReactDefaultBatchingStrategy.isBatchingUpdates;
83833
83834    ReactDefaultBatchingStrategy.isBatchingUpdates = true;
83835
83836    // The code is written this way to avoid extra allocations
83837    if (alreadyBatchingUpdates) {
83838      callback(a, b, c, d, e);
83839    } else {
83840      transaction.perform(callback, null, a, b, c, d, e);
83841    }
83842  }
83843};
83844
83845module.exports = ReactDefaultBatchingStrategy;
83846},{"112":112,"150":150,"169":169,"94":94}],59:[function(_dereq_,module,exports){
83847/**
83848 * Copyright 2013-present, Facebook, Inc.
83849 * All rights reserved.
83850 *
83851 * This source code is licensed under the BSD-style license found in the
83852 * LICENSE file in the root directory of this source tree. An additional grant
83853 * of patent rights can be found in the PATENTS file in the same directory.
83854 *
83855 * @providesModule ReactDefaultInjection
83856 */
83857
83858
83859
83860var BeforeInputEventPlugin = _dereq_(2);
83861var ChangeEventPlugin = _dereq_(6);
83862var DefaultEventPluginOrder = _dereq_(13);
83863var EnterLeaveEventPlugin = _dereq_(15);
83864var ExecutionEnvironment = _dereq_(144);
83865var HTMLDOMPropertyConfig = _dereq_(22);
83866var ReactComponentBrowserEnvironment = _dereq_(32);
83867var ReactDOMComponent = _dereq_(38);
83868var ReactDOMComponentTree = _dereq_(40);
83869var ReactDOMEmptyComponent = _dereq_(43);
83870var ReactDOMTreeTraversal = _dereq_(55);
83871var ReactDOMTextComponent = _dereq_(53);
83872var ReactDefaultBatchingStrategy = _dereq_(58);
83873var ReactEventListener = _dereq_(67);
83874var ReactInjection = _dereq_(69);
83875var ReactReconcileTransaction = _dereq_(86);
83876var SVGDOMPropertyConfig = _dereq_(96);
83877var SelectEventPlugin = _dereq_(97);
83878var SimpleEventPlugin = _dereq_(98);
83879
83880var alreadyInjected = false;
83881
83882function inject() {
83883  if (alreadyInjected) {
83884    // TODO: This is currently true because these injections are shared between
83885    // the client and the server package. They should be built independently
83886    // and not share any injection state. Then this problem will be solved.
83887    return;
83888  }
83889  alreadyInjected = true;
83890
83891  ReactInjection.EventEmitter.injectReactEventListener(ReactEventListener);
83892
83893  /**
83894   * Inject modules for resolving DOM hierarchy and plugin ordering.
83895   */
83896  ReactInjection.EventPluginHub.injectEventPluginOrder(DefaultEventPluginOrder);
83897  ReactInjection.EventPluginUtils.injectComponentTree(ReactDOMComponentTree);
83898  ReactInjection.EventPluginUtils.injectTreeTraversal(ReactDOMTreeTraversal);
83899
83900  /**
83901   * Some important event plugins included by default (without having to require
83902   * them).
83903   */
83904  ReactInjection.EventPluginHub.injectEventPluginsByName({
83905    SimpleEventPlugin: SimpleEventPlugin,
83906    EnterLeaveEventPlugin: EnterLeaveEventPlugin,
83907    ChangeEventPlugin: ChangeEventPlugin,
83908    SelectEventPlugin: SelectEventPlugin,
83909    BeforeInputEventPlugin: BeforeInputEventPlugin
83910  });
83911
83912  ReactInjection.NativeComponent.injectGenericComponentClass(ReactDOMComponent);
83913
83914  ReactInjection.NativeComponent.injectTextComponentClass(ReactDOMTextComponent);
83915
83916  ReactInjection.DOMProperty.injectDOMPropertyConfig(HTMLDOMPropertyConfig);
83917  ReactInjection.DOMProperty.injectDOMPropertyConfig(SVGDOMPropertyConfig);
83918
83919  ReactInjection.EmptyComponent.injectEmptyComponentFactory(function (instantiate) {
83920    return new ReactDOMEmptyComponent(instantiate);
83921  });
83922
83923  ReactInjection.Updates.injectReconcileTransaction(ReactReconcileTransaction);
83924  ReactInjection.Updates.injectBatchingStrategy(ReactDefaultBatchingStrategy);
83925
83926  ReactInjection.Component.injectEnvironment(ReactComponentBrowserEnvironment);
83927
83928  if ("development" !== 'production') {
83929    var url = ExecutionEnvironment.canUseDOM && window.location.href || '';
83930    if (/[?&]react_perf\b/.test(url)) {
83931      var ReactDefaultPerf = _dereq_(60);
83932      ReactDefaultPerf.start();
83933    }
83934  }
83935}
83936
83937module.exports = {
83938  inject: inject
83939};
83940},{"13":13,"144":144,"15":15,"2":2,"22":22,"32":32,"38":38,"40":40,"43":43,"53":53,"55":55,"58":58,"6":6,"60":60,"67":67,"69":69,"86":86,"96":96,"97":97,"98":98}],60:[function(_dereq_,module,exports){
83941/**
83942 * Copyright 2013-present, Facebook, Inc.
83943 * All rights reserved.
83944 *
83945 * This source code is licensed under the BSD-style license found in the
83946 * LICENSE file in the root directory of this source tree. An additional grant
83947 * of patent rights can be found in the PATENTS file in the same directory.
83948 *
83949 * @providesModule ReactDefaultPerf
83950 */
83951
83952
83953
83954var DOMProperty = _dereq_(10);
83955var ReactDOMComponentTree = _dereq_(40);
83956var ReactDefaultPerfAnalysis = _dereq_(61);
83957var ReactMount = _dereq_(75);
83958var ReactPerf = _dereq_(82);
83959
83960var performanceNow = _dereq_(166);
83961var warning = _dereq_(168);
83962
83963function roundFloat(val) {
83964  return Math.floor(val * 100) / 100;
83965}
83966
83967function addValue(obj, key, val) {
83968  obj[key] = (obj[key] || 0) + val;
83969}
83970
83971// Composite/text components don't have any built-in ID: we have to make our own
83972var compositeIDMap;
83973var compositeIDCounter = 17000;
83974function getIDOfComposite(inst) {
83975  if (!compositeIDMap) {
83976    compositeIDMap = new WeakMap();
83977  }
83978  if (compositeIDMap.has(inst)) {
83979    return compositeIDMap.get(inst);
83980  } else {
83981    var id = compositeIDCounter++;
83982    compositeIDMap.set(inst, id);
83983    return id;
83984  }
83985}
83986
83987function getID(inst) {
83988  if (inst.hasOwnProperty('_rootNodeID')) {
83989    return inst._rootNodeID;
83990  } else {
83991    return getIDOfComposite(inst);
83992  }
83993}
83994
83995function stripComplexValues(key, value) {
83996  if (typeof value !== 'object' || Array.isArray(value) || value == null) {
83997    return value;
83998  }
83999  var prototype = Object.getPrototypeOf(value);
84000  if (!prototype || prototype === Object.prototype) {
84001    return value;
84002  }
84003  return '<not serializable>';
84004}
84005
84006// This implementation of ReactPerf is going away some time mid 15.x.
84007// While we plan to keep most of the API, the actual format of measurements
84008// will change dramatically. To signal this, we wrap them into an opaque-ish
84009// object to discourage reaching into it until the API stabilizes.
84010function wrapLegacyMeasurements(measurements) {
84011  return { __unstable_this_format_will_change: measurements };
84012}
84013function unwrapLegacyMeasurements(measurements) {
84014  return measurements && measurements.__unstable_this_format_will_change || measurements;
84015}
84016
84017var warnedAboutPrintDOM = false;
84018var warnedAboutGetMeasurementsSummaryMap = false;
84019
84020var ReactDefaultPerf = {
84021  _allMeasurements: [], // last item in the list is the current one
84022  _mountStack: [0],
84023  _compositeStack: [],
84024  _injected: false,
84025
84026  start: function () {
84027    if (!ReactDefaultPerf._injected) {
84028      ReactPerf.injection.injectMeasure(ReactDefaultPerf.measure);
84029    }
84030
84031    ReactDefaultPerf._allMeasurements.length = 0;
84032    ReactPerf.enableMeasure = true;
84033  },
84034
84035  stop: function () {
84036    ReactPerf.enableMeasure = false;
84037  },
84038
84039  getLastMeasurements: function () {
84040    return wrapLegacyMeasurements(ReactDefaultPerf._allMeasurements);
84041  },
84042
84043  printExclusive: function (measurements) {
84044    measurements = unwrapLegacyMeasurements(measurements || ReactDefaultPerf._allMeasurements);
84045    var summary = ReactDefaultPerfAnalysis.getExclusiveSummary(measurements);
84046    console.table(summary.map(function (item) {
84047      return {
84048        'Component class name': item.componentName,
84049        'Total inclusive time (ms)': roundFloat(item.inclusive),
84050        'Exclusive mount time (ms)': roundFloat(item.exclusive),
84051        'Exclusive render time (ms)': roundFloat(item.render),
84052        'Mount time per instance (ms)': roundFloat(item.exclusive / item.count),
84053        'Render time per instance (ms)': roundFloat(item.render / item.count),
84054        'Instances': item.count
84055      };
84056    }));
84057    // TODO: ReactDefaultPerfAnalysis.getTotalTime() does not return the correct
84058    // number.
84059  },
84060
84061  printInclusive: function (measurements) {
84062    measurements = unwrapLegacyMeasurements(measurements || ReactDefaultPerf._allMeasurements);
84063    var summary = ReactDefaultPerfAnalysis.getInclusiveSummary(measurements);
84064    console.table(summary.map(function (item) {
84065      return {
84066        'Owner > component': item.componentName,
84067        'Inclusive time (ms)': roundFloat(item.time),
84068        'Instances': item.count
84069      };
84070    }));
84071    console.log('Total time:', ReactDefaultPerfAnalysis.getTotalTime(measurements).toFixed(2) + ' ms');
84072  },
84073
84074  getMeasurementsSummaryMap: function (measurements) {
84075    "development" !== 'production' ? warning(warnedAboutGetMeasurementsSummaryMap, '`ReactPerf.getMeasurementsSummaryMap(...)` is deprecated. Use ' + '`ReactPerf.getWasted(...)` instead.') : void 0;
84076    warnedAboutGetMeasurementsSummaryMap = true;
84077    return ReactDefaultPerf.getWasted(measurements);
84078  },
84079
84080  getWasted: function (measurements) {
84081    measurements = unwrapLegacyMeasurements(measurements);
84082    var summary = ReactDefaultPerfAnalysis.getInclusiveSummary(measurements, true);
84083    return summary.map(function (item) {
84084      return {
84085        'Owner > component': item.componentName,
84086        'Wasted time (ms)': item.time,
84087        'Instances': item.count
84088      };
84089    });
84090  },
84091
84092  printWasted: function (measurements) {
84093    measurements = unwrapLegacyMeasurements(measurements || ReactDefaultPerf._allMeasurements);
84094    console.table(ReactDefaultPerf.getWasted(measurements));
84095    console.log('Total time:', ReactDefaultPerfAnalysis.getTotalTime(measurements).toFixed(2) + ' ms');
84096  },
84097
84098  printDOM: function (measurements) {
84099    "development" !== 'production' ? warning(warnedAboutPrintDOM, '`ReactPerf.printDOM(...)` is deprecated. Use ' + '`ReactPerf.printOperations(...)` instead.') : void 0;
84100    warnedAboutPrintDOM = true;
84101    return ReactDefaultPerf.printOperations(measurements);
84102  },
84103
84104  printOperations: function (measurements) {
84105    measurements = unwrapLegacyMeasurements(measurements || ReactDefaultPerf._allMeasurements);
84106    var summary = ReactDefaultPerfAnalysis.getDOMSummary(measurements);
84107    console.table(summary.map(function (item) {
84108      var result = {};
84109      result[DOMProperty.ID_ATTRIBUTE_NAME] = item.id;
84110      result.type = item.type;
84111      result.args = JSON.stringify(item.args, stripComplexValues);
84112      return result;
84113    }));
84114    console.log('Total time:', ReactDefaultPerfAnalysis.getTotalTime(measurements).toFixed(2) + ' ms');
84115  },
84116
84117  _recordWrite: function (id, fnName, totalTime, args) {
84118    // TODO: totalTime isn't that useful since it doesn't count paints/reflows
84119    var entry = ReactDefaultPerf._allMeasurements[ReactDefaultPerf._allMeasurements.length - 1];
84120    var writes = entry.writes;
84121    writes[id] = writes[id] || [];
84122    writes[id].push({
84123      type: fnName,
84124      time: totalTime,
84125      args: args
84126    });
84127  },
84128
84129  measure: function (moduleName, fnName, func) {
84130    return function () {
84131      for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
84132        args[_key] = arguments[_key];
84133      }
84134
84135      var totalTime;
84136      var rv;
84137      var start;
84138
84139      var entry = ReactDefaultPerf._allMeasurements[ReactDefaultPerf._allMeasurements.length - 1];
84140
84141      if (fnName === '_renderNewRootComponent' || fnName === 'flushBatchedUp
84141dates') {
84142        // A "measurement" is a set of metrics recorded for each flush. We want
84143        // to group the metrics for a given flush together so we can look at the
84144        // components that rendered and the DOM operations that actually
84145        // happened to determine the amount of "wasted work" performed.
84146        ReactDefaultPerf._allMeasurements.push(entry = {
84147          exclusive: {},
84148          inclusive: {},
84149          render: {},
84150          counts: {},
84151          writes: {},
84152          displayNames: {},
84153          hierarchy: {},
84154          totalTime: 0,
84155          created: {}
84156        });
84157        start = performanceNow();
84158        rv = func.apply(this, args);
84159        entry.totalTime = performanceNow() - start;
84160        return rv;
84161      } else if (fnName === '_mountImageIntoNode' || moduleName === 'ReactDOMIDOperations' || moduleName === 'CSSPropertyOperations' || moduleName === 'DOMChildrenOperations' || moduleName === 'DOMPropertyOperations' || moduleName === 'ReactComponentBrowserEnvironment') {
84162        start = performanceNow();
84163        rv = func.apply(this, args);
84164        totalTime = performanceNow() - start;
84165
84166        if (fnName === '_mountImageIntoNode') {
84167          ReactDefaultPerf._recordWrite('', fnName, totalTime, args[0]);
84168        } else if (fnName === 'dangerouslyProcessChildrenUpdates') {
84169          // special format
84170          args[1].forEach(function (update) {
84171            var writeArgs = {};
84172            if (update.fromIndex !== null) {
84173              writeArgs.fromIndex = update.fromIndex;
84174            }
84175            if (update.toIndex !== null) {
84176              writeArgs.toIndex = update.toIndex;
84177            }
84178            if (update.content !== null) {
84179              writeArgs.content = update.content;
84180            }
84181            ReactDefaultPerf._recordWrite(args[0]._rootNodeID, update.type, totalTime, writeArgs);
84182          });
84183        } else {
84184          // basic format
84185          var id = args[0];
84186          if (moduleName === 'EventPluginHub') {
84187            id = id._rootNodeID;
84188          } else if (fnName === 'replaceNodeWithMarkup') {
84189            // Old node is already unmounted; can't get its instance
84190            id = ReactDOMComponentTree.getInstanceFromNode(args[1].node)._rootNodeID;
84191          } else if (fnName === 'replaceDelimitedText') {
84192            id = getID(ReactDOMComponentTree.getInstanceFromNode(args[0]));
84193          } else if (typeof id === 'object') {
84194            id = getID(ReactDOMComponentTree.getInstanceFromNode(args[0]));
84195          }
84196          ReactDefaultPerf._recordWrite(id, fnName, totalTime, Array.prototype.slice.call(args, 1));
84197        }
84198        return rv;
84199      } else if (moduleName === 'ReactCompositeComponent' && (fnName === 'mountComponent' || fnName === 'updateComponent' || // TODO: receiveComponent()?
84200      fnName === '_renderValidatedComponent')) {
84201
84202        if (this._currentElement.type === ReactMount.TopLevelWrapper) {
84203          return func.apply(this, args);
84204        }
84205
84206        var rootNodeID = getIDOfComposite(this);
84207        var isRender = fnName === '_renderValidatedComponent';
84208        var isMount = fnName === 'mountComponent';
84209
84210        var mountStack = ReactDefaultPerf._mountStack;
84211
84212        if (isRender) {
84213          addValue(entry.counts, rootNodeID, 1);
84214        } else if (isMount) {
84215          entry.created[rootNodeID] = true;
84216          mountStack.push(0);
84217        }
84218
84219        ReactDefaultPerf._compositeStack.push(rootNodeID);
84220
84221        start = performanceNow();
84222        rv = func.apply(this, args);
84223        totalTime = performanceNow() - start;
84224
84225        ReactDefaultPerf._compositeStack.pop();
84226
84227        if (isRender) {
84228          addValue(entry.render, rootNodeID, totalTime);
84229        } else if (isMount) {
84230          var subMountTime = mountStack.pop();
84231          mountStack[mountStack.length - 1] += totalTime;
84232          addValue(entry.exclusive, rootNodeID, totalTime - subMountTime);
84233          addValue(entry.inclusive, rootNodeID, totalTime);
84234        } else {
84235          addValue(entry.inclusive, rootNodeID, totalTime);
84236        }
84237
84238        entry.displayNames[rootNodeID] = {
84239          current: this.getName(),
84240          owner: this._currentElement._owner ? this._currentElement._owner.getName() : '<root>'
84241        };
84242
84243        return rv;
84244      } else if ((moduleName === 'ReactDOMComponent' || moduleName === 'ReactDOMTextComponent') && (fnName === 'mountComponent' || fnName === 'receiveComponent')) {
84245
84246        rv = func.apply(this, args);
84247        entry.hierarchy[getID(this)] = ReactDefaultPerf._compositeStack.slice();
84248        return rv;
84249      } else {
84250        return func.apply(this, args);
84251      }
84252    };
84253  }
84254};
84255
84256module.exports = ReactDefaultPerf;
84257},{"10":10,"166":166,"168":168,"40":40,"61":61,"75":75,"82":82}],61:[function(_dereq_,module,exports){
84258/**
84259 * Copyright 2013-present, Facebook, Inc.
84260 * All rights reserved.
84261 *
84262 * This source code is licensed under the BSD-style license found in the
84263 * LICENSE file in the root directory of this source tree. An additional grant
84264 * of patent rights can be found in the PATENTS file in the same directory.
84265 *
84266 * @providesModule ReactDefaultPerfAnalysis
84267 */
84268
84269
84270
84271// Don't try to save users less than 1.2ms (a number I made up)
84272
84273var _assign = _dereq_(169);
84274
84275var DONT_CARE_THRESHOLD = 1.2;
84276var DOM_OPERATION_TYPES = {
84277  '_mountImageIntoNode': 'set innerHTML',
84278  INSERT_MARKUP: 'set innerHTML',
84279  MOVE_EXISTING: 'move',
84280  REMOVE_NODE: 'remove',
84281  SET_MARKUP: 'set innerHTML',
84282  TEXT_CONTENT: 'set textContent',
84283  'setValueForProperty': 'update attribute',
84284  'setValueForAttribute': 'update attribute',
84285  'deleteValueForProperty': 'remove attribute',
84286  'setValueForStyles': 'update styles',
84287  'replaceNodeWithMarkup': 'replace',
84288  'replaceDelimitedText': 'replace'
84289};
84290
84291function getTotalTime(measurements) {
84292  // TODO: return number of DOM ops? could be misleading.
84293  // TODO: measure dropped frames after reconcile?
84294  // TODO: log total time of each reconcile and the top-level component
84295  // class that triggered it.
84296  var totalTime = 0;
84297  for (var i = 0; i < measurements.length; i++) {
84298    var measurement = measurements[i];
84299    totalTime += measurement.totalTime;
84300  }
84301  return totalTime;
84302}
84303
84304function getDOMSummary(measurements) {
84305  var items = [];
84306  measurements.forEach(function (measurement) {
84307    Object.keys(measurement.writes).forEach(function (id) {
84308      measurement.writes[id].forEach(function (write) {
84309        items.push({
84310          id: id,
84311          type: DOM_OPERATION_TYPES[write.type] || write.type,
84312          args: write.args
84313        });
84314      });
84315    });
84316  });
84317  return items;
84318}
84319
84320function getExclusiveSummary(measurements) {
84321  var candidates = {};
84322  var displayName;
84323
84324  for (var i = 0; i < measurements.length; i++) {
84325    var measurement = measurements[i];
84326    var allIDs = _assign({}, measurement.exclusive, measurement.inclusive);
84327
84328    for (var id in allIDs) {
84329      displayName = measurement.displayNames[id].current;
84330
84331      candidates[displayName] = candidates[displayName] || {
84332        componentName: displayName,
84333        inclusive: 0,
84334        exclusive: 0,
84335        render: 0,
84336        count: 0
84337      };
84338      if (measurement.render[id]) {
84339        candidates[displayName].render += measurement.render[id];
84340      }
84341      if (measurement.exclusive[id]) {
84342        candidates[displayName].exclusive += measurement.exclusive[id];
84343      }
84344      if (measurement.inclusive[id]) {
84345        candidates[displayName].inclusive += measurement.inclusive[id];
84346      }
84347      if (measurement.counts[id]) {
84348        candidates[displayName].count += measurement.counts[id];
84349      }
84350    }
84351  }
84352
84353  // Now make a sorted array with the results.
84354  var arr = [];
84355  for (displayName in candidates) {
84356    if (candidates[displayName].exclusive >= DONT_CARE_THRESHOLD) {
84357      arr.push(candidates[displayName]);
84358    }
84359  }
84360
84361  arr.sort(function (a, b) {
84362    return b.exclusive - a.exclusive;
84363  });
84364
84365  return arr;
84366}
84367
84368function getInclusiveSummary(measurements, onlyClean) {
84369  var candidates = {};
84370  var inclusiveKey;
84371
84372  for (var i = 0; i < measurements.length; i++) {
84373    var measurement = measurements[i];
84374    var allIDs = _assign({}, measurement.exclusive, measurement.inclusive);
84375    var cleanComponents;
84376
84377    if (onlyClean) {
84378      cleanComponents = getUnchangedComponents(measurement);
84379    }
84380
84381    for (var id in allIDs) {
84382      if (onlyClean && !cleanComponents[id]) {
84383        continue;
84384      }
84385
84386      var displayName = measurement.displayNames[id];
84387
84388      // Inclusive time is not useful for many components without knowing where
84389      // they are instantiated. So we aggregate inclusive time with both the
84390      // owner and current displayName as the key.
84391      inclusiveKey = displayName.owner + ' > ' + displayName.current;
84392
84393      candidates[inclusiveKey] = candidates[inclusiveKey] || {
84394        componentName: inclusiveKey,
84395        time: 0,
84396        count: 0
84397      };
84398
84399      if (measurement.inclusive[id]) {
84400        candidates[inclusiveKey].time += measurement.inclusive[id];
84401      }
84402      if (measurement.counts[id]) {
84403        candidates[inclusiveKey].count += measurement.counts[id];
84404      }
84405    }
84406  }
84407
84408  // Now make a sorted array with the results.
84409  var arr = [];
84410  for (inclusiveKey in candidates) {
84411    if (candidates[inclusiveKey].time >= DONT_CARE_THRESHOLD) {
84412      arr.push(candidates[inclusiveKey]);
84413    }
84414  }
84415
84416  arr.sort(function (a, b) {
84417    return b.time - a.time;
84418  });
84419
84420  return arr;
84421}
84422
84423function getUnchangedComponents(measurement) {
84424  // For a given reconcile, look at which components did not actually
84425  // render anything to the DOM and return a mapping of their ID to
84426  // the amount of time it took to render the entire subtree.
84427  var cleanComponents = {};
84428  var writes = measurement.writes;
84429  var hierarchy = measurement.hierarchy;
84430  var dirtyComposites = {};
84431  Object.keys(writes).forEach(function (id) {
84432    writes[id].forEach(function (write) {
84433      // Root mounting (innerHTML set) is recorded with an ID of ''
84434      if (id !== '' && hierarchy.hasOwnProperty(id)) {
84435        hierarchy[id].forEach(function (c) {
84436          return dirtyComposites[c] = true;
84437        });
84438      }
84439    });
84440  });
84441  var allIDs = _assign({}, measurement.exclusive, measurement.inclusive);
84442
84443  for (var id in allIDs) {
84444    var isDirty = false;
84445    // See if any of the DOM operations applied to this component's subtree.
84446    if (dirtyComposites[id]) {
84447      isDirty = true;
84448    }
84449    // check if component newly created
84450    if (measurement.created[id]) {
84451      isDirty = true;
84452    }
84453    if (!isDirty && measurement.counts[id] > 0) {
84454      cleanComponents[id] = true;
84455    }
84456  }
84457  return cleanComponents;
84458}
84459
84460var ReactDefaultPerfAnalysis = {
84461  getExclusiveSummary: getExclusiveSummary,
84462  getInclusiveSummary: getInclusiveSummary,
84463  getDOMSummary: getDOMSummary,
84464  getTotalTime: getTotalTime
84465};
84466
84467module.exports = ReactDefaultPerfAnalysis;
84468},{"169":169}],62:[function(_dereq_,module,exports){
84469/**
84470 * Copyright 2014-present, Facebook, Inc.
84471 * All rights reserved.
84472 *
84473 * This source code is licensed under the BSD-style license found in the
84474 * LICENSE file in the root directory of this source tree. An additional grant
84475 * of patent rights can be found in the PATENTS file in the same directory.
84476 *
84477 * @providesModule ReactElement
84478 */
84479
84480
84481
84482var _assign = _dereq_(169);
84483
84484var ReactCurrentOwner = _dereq_(35);
84485
84486var warning = _dereq_(168);
84487var canDefineProperty = _dereq_(116);
84488
84489// The Symbol used to tag the ReactElement type. If there is no native Symbol
84490// nor polyfill, then a plain number is used for performance.
84491var REACT_ELEMENT_TYPE = typeof Symbol === 'function' && Symbol['for'] && Symbol['for']('react.element') || 0xeac7;
84492
84493var RESERVED_PROPS = {
84494  key: true,
84495  ref: true,
84496  __self: true,
84497  __source: true
84498};
84499
84500var specialPropKeyWarningShown, specialPropRefWarningShown;
84501
84502/**
84503 * Factory method to create a new React element. This no longer adheres to
84504 * the class pattern, so do not use new to call it. Also, no instanceof check
84505 * will work. Instead test $$typeof field against Symbol.for('react.element') to check
84506 * if something is a React Element.
84507 *
84508 * @param {*} type
84509 * @param {*} key
84510 * @param {string|object} ref
84511 * @param {*} self A *temporary* helper to detect places where `this` is
84512 * different from the `owner` when React.createElement is called, so that we
84513 * can warn. We want to get rid of owner and replace string `ref`s with arrow
84514 * functions, and as long as `this` and owner are the same, there will be no
84515 * change in behavior.
84516 * @param {*} source An annotation object (added by a transpiler or otherwise)
84517 * indicating filename, line number, and/or other information.
84518 * @param {*} owner
84519 * @param {*} props
84520 * @internal
84521 */
84522var ReactElement = function (type, key, ref, self, source, owner, props) {
84523  var element = {
84524    // This tag allow us to uniquely identify this as a React Element
84525    $$typeof: REACT_ELEMENT_TYPE,
84526
84527    // Built-in properties that belong on the element
84528    type: type,
84529    key: key,
84530    ref: ref,
84531    props: props,
84532
84533    // Record the component responsible for creating this element.
84534    _owner: owner
84535  };
84536
84537  if ("development" !== 'production') {
84538    // The validation flag is currently mutative. We put it on
84539    // an external backing store so that we can freeze the whole object.
84540    // This can be replaced with a WeakMap once they are implemented in
84541    // commonly used development environments.
84542    element._store = {};
84543
84544    // To make comparing ReactElements easier for testing purposes, we make
84545    // the validation flag non-enumerable (where possible, which should
84546    // include every environment we run tests in), so the test framework
84547    // ignores it.
84548    if (canDefineProperty) {
84549      Object.defineProperty(element._store, 'validated', {
84550        configurable: false,
84551        enumerable: false,
84552        writable: true,
84553        value: false
84554      });
84555      // self and source are DEV only properties.
84556      Object.defineProperty(element, '_self', {
84557        configurable: false,
84558        enumerable: false,
84559        writable: false,
84560        value: self
84561      });
84562      // Two elements created in two different places should be considered
84563      // equal for testing purposes and therefore we hide it from enumeration.
84564      Object.defineProperty(element, '_source', {
84565        configurable: false,
84566        enumerable: false,
84567        writable: false,
84568        value: source
84569      });
84570    } else {
84571      element._store.validated = false;
84572      element._self = self;
84573      element._source = source;
84574    }
84575    if (Object.freeze) {
84576      Object.freeze(element.props);
84577      Object.freeze(element);
84578    }
84579  }
84580
84581  return element;
84582};
84583
84584ReactElement.createElement = function (type, config, children) {
84585  var propName;
84586
84587  // Reserved names are extracted
84588  var props = {};
84589
84590  var key = null;
84591  var ref = null;
84592  var self = null;
84593  var source = null;
84594
84595  if (config != null) {
84596    if ("development" !== 'production') {
84597      ref = !config.hasOwnProperty('ref') || Object.getOwnPropertyDescriptor(config, 'ref').get ? null : config.ref;
84598      key = !config.hasOwnProperty('key') || Object.getOwnPropertyDescriptor(config, 'key').get ? null : '' + config.key;
84599    } else {
84600      ref = config.ref === undefined ? null : config.ref;
84601      key = config.key === undefined ? null : '' + config.key;
84602    }
84603    self = config.__self === undefined ? null : config.__self;
84604    source = config.__source === undefined ? null : config.__source;
84605    // Remaining properties are added to a new props object
84606    for (propName in config) {
84607      if (config.hasOwnProperty(propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {
84608        props[propName] = config[propName];
84609      }
84610    }
84611  }
84612
84613  // Children can be more than one argument, and those are transferred onto
84614  // the newly allocated props object.
84615  var childrenLength = arguments.length - 2;
84616  if (childrenLength === 1) {
84617    props.children = children;
84618  } else if (childrenLength > 1) {
84619    var childArray = Array(childrenLength);
84620    for (var i = 0; i < childrenLength; i++) {
84621      childArray[i] = arguments[i + 2];
84622    }
84623    props.children = childArray;
84624  }
84625
84626  // Resolve default props
84627  if (type && type.defaultProps) {
84628    var defaultProps = type.defaultProps;
84629    for (propName in defaultProps) {
84630      if (props[propName] === undefined) {
84631        props[propName] = defaultProps[propName];
84632      }
84633    }
84634  }
84635  if ("development" !== 'production') {
84636    // Create dummy `key` and `ref` property to `props` to warn users
84637    // against its use
84638    if (typeof props.$$typeof === 'undefined' || props.$$typeof !== REACT_ELEMENT_TYPE) {
84639      if (!props.hasOwnProperty('key')) {
84640        Object.defineProperty(props, 'key', {
84641          get: function () {
84642            if (!specialPropKeyWarningShown) {
84643              specialPropKeyWarningShown = true;
84644              "development" !== 'production' ? warning(false, '%s: `key` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://fb.me/react-special-props)', typeof type === 'function' && 'displayName' in type ? type.displayName : 'Element') : void 0;
84645            }
84646            return undefined;
84647          },
84648          configurable: true
84649        });
84650      }
84651      if (!props.hasOwnProperty('ref')) {
84652        Object.defineProperty(props, 'ref', {
84653          get: function () {
84654            if (!specialPropRefWarningShown) {
84655              specialPropRefWarningShown = true;
84656              "development" !== 'production' ? warning(false, '%s: `ref` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://fb.me/react-special-props)', typeof type === 'function' && 'displayName' in type ? type.displayName : 'Element') : void 0;
84657            }
84658            return undefined;
84659          },
84660          configurable: true
84661        });
84662      }
84663    }
84664  }
84665  return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props);
84666};
84667
84668ReactElement.createFactory = function (type) {
84669  var factory = ReactElement.createElement.bind(null, type);
84670  // Expose the type on the factory and the prototype so that it can be
84671  // easily accessed on elements. E.g. `<Foo />.type === Foo`.
84672  // This should not be named `constructor` since this may not be the function
84673  // that created the element, and it may not even be a constructor.
84674  // Legacy hook TODO: Warn if this is accessed
84675  factory.type = type;
84676  return factory;
84677};
84678
84679ReactElement.cloneAndReplaceKey = function (oldElement, newKey) {
84680  var newElement = ReactElement(oldElement.type, newKey, oldElement.ref, oldElement._self, oldElement._source, oldElement._owner, oldElement.props);
84681
84682  return newElement;
84683};
84684
84685ReactElement.cloneElement = function (element, config, children) {
84686  var propName;
84687
84688  // Original props are copied
84689  var props = _assign({}, element.props);
84690
84691  // Reserved names are extracted
84692  var key = element.key;
84693  var ref = element.ref;
84694  // Self is preserved since the owner is preserved.
84695  var self = element._self;
84696  // Source is preserved since cloneElement is unlikely to be targeted by a
84697  // transpiler, and the original source is probably a better indicator of the
84698  // true owner.
84699  var source = element._source;
84700
84701  // Owner will be preserved, unless ref is overridden
84702  var owner = element._owner;
84703
84704  if (config != null) {
84705    if (config.ref !== undefined) {
84706      // Silently steal the ref from the parent.
84707      ref = config.ref;
84708      owner = ReactCurrentOwner.current;
84709    }
84710    if (config.key !== undefined) {
84711      key = '' + config.key;
84712    }
84713    // Remaining properties override existing props
84714    var defaultProps;
84715    if (element.type && element.type.defaultProps) {
84716      defaultProps = element.type.defaultProps;
84717    }
84718    for (propName in config) {
84719      if (config.hasOwnProperty(propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {
84720        if (config[propName] === undefined && defaultProps !== undefined) {
84721          // Resolve default props
84722          props[propName] = defaultProps[propName];
84723        } else {
84724          props[propName] = config[propName];
84725        }
84726      }
84727    }
84728  }
84729
84730  // Children can be more than one argument, and those are transferred onto
84731  // the newly allocated props object.
84732  var childrenLength = arguments.length - 2;
84733  if (childrenLength === 1) {
84734    props.children = children;
84735  } else if (childrenLength > 1) {
84736    var childArray = Array(childrenLength);
84737    for (var i = 0; i < childrenLength; i++) {
84738      childArray[i] = arguments[i + 2];
84739    }
84740    props.children = childArray;
84741  }
84742
84743  return ReactElement(element.type, key, ref, self, source, owner, props);
84744};
84745
84746/**
84747 * @param {?object} object
84748 * @return {boolean} True if `object` is a valid component.
84749 * @final
84750 */
84751ReactElement.isValidElement = function (object) {
84752  return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE;
84753};
84754
84755module.exports = ReactElement;
84756},{"116":116,"168":168,"169":169,"35":35}],63:[function(_dereq_,module,exports){
84757/**
84758 * Copyright 2014-present, Facebook, Inc.
84759 * All rights reserved.
84760 *
84761 * This source code is licensed under the BSD-style license found in the
84762 * LICENSE file in the root directory of this source tree. An additional grant
84763 * of patent rights can be found in the PATENTS file in the same directory.
84764 *
84765 * @providesModule ReactElementValidator
84766 */
84767
84768/**
84769 * ReactElementValidator provides a wrapper around a element factory
84770 * which validates the props passed to the element. This is intended to be
84771 * used only in DEV and could be replaced by a static type checker for languages
84772 * that support it.
84773 */
84774
84775
84776
84777var ReactElement = _dereq_(62);
84778var ReactPropTypeLocations = _dereq_(84);
84779var ReactPropTypeLocationNames = _dereq_(83);
84780var ReactCurrentOwner = _dereq_(35);
84781
84782var canDefineProperty = _dereq_(116);
84783var getIteratorFn = _dereq_(127);
84784var invariant = _dereq_(158);
84785var warning = _dereq_(168);
84786
84787function getDeclarationErrorAddendum() {
84788  if (ReactCurrentOwner.current) {
84789    var name = ReactCurrentOwner.current.getName();
84790    if (name) {
84791      return ' Check the render method of `' + name + '`.';
84792    }
84793  }
84794  return '';
84795}
84796
84797/**
84798 * Warn if there's no key explicitly set on dynamic arrays of children or
84799 * object keys are not valid. This allows us to keep track of children between
84800 * updates.
84801 */
84802var ownerHasKeyUseWarning = {};
84803
84804var loggedTypeFailures = {};
84805
84806/**
84807 * Warn if the element doesn't have an explicit key assigned to it.
84808 * This element is in an array. The array could grow and shrink or be
84809 * reordered. All children that haven't already been validated are required to
84810 * have a "key" property assigned to it.
84811 *
84812 * @internal
84813 * @param {ReactElement} element Element that requires a key.
84814 * @param {*} parentType element's parent's type.
84815 */
84816function validateExplicitKey(element, parentType) {
84817  if (!element._store || element._store.validated || element.key != null) {
84818    return;
84819  }
84820  element._store.validated = true;
84821
84822  var addenda = getAddendaForKeyUse('uniqueKey', element, parentType);
84823  if (addenda === null) {
84824    // we already showed the warning
84825    return;
84826  }
84827  "development" !== 'production' ? warning(false, 'Each child in an array or iterator should have a unique "key" prop.' + '%s%s%s', addenda.parentOrOwner || '', addenda.childOwner || '', addenda.url || '') : void 0;
84828}
84829
84830/**
84831 * Shared warning and monitoring code for the key warnings.
84832 *
84833 * @internal
84834 * @param {string} messageType A key used for de-duping warnings.
84835 * @param {ReactElement} element Component that requires a key.
84836 * @param {*} parentType element's parent's type.
84837 * @returns {?object} A set of addenda to use in the warning message, or null
84838 * if the warning has already been shown before (and shouldn't be shown again).
84839 */
84840function getAddendaForKeyUse(messageType, element, parentType) {
84841  var addendum = getDeclarationErrorAddendum();
84842  if (!addendum) {
84843    var parentName = typeof parentType === 'string' ? parentType : parentType.displayName || parentType.name;
84844    if (parentName) {
84845      addendum = ' Check the top-level render call using <' + parentName + '>.';
84846    }
84847  }
84848
84849  var memoizer = ownerHasKeyUseWarning[messageType] || (ownerHasKeyUseWarning[messageType] = {});
84850  if (memoizer[addendum]) {
84851    return null;
84852  }
84853  memoizer[addendum] = true;
84854
84855  var addenda = {
84856    parentOrOwner: addendum,
84857    url: ' See https://fb.me/react-warning-keys for more information.',
84858    childOwner: null
84859  };
84860
84861  // Usually the current owner is the offender, but if it accepts children as a
84862  // property, it may be the creator of the child that's responsible for
84863  // assigning it a key.
84864  if (element && element._owner && element._owner !== ReactCurrentOwner.current) {
84865    // Give the component that originally created this child.
84866    addenda.childOwner = ' It was passed a child from ' + element._owner.getName() + '.';
84867  }
84868
84869  return addenda;
84870}
84871
84872/**
84873 * Ensure that every element either is passed in a static location, in an
84874 * array with an explicit keys property defined, or in an object literal
84875 * with valid key property.
84876 *
84877 * @internal
84878 * @param {ReactNode} node Statically passed child of any type.
84879 * @param {*} parentType node's parent's type.
84880 */
84881function validateChildKeys(node, parentType) {
84882  if (typeof node !== 'object') {
84883    return;
84884  }
84885  if (Array.isArray(node)) {
84886    for (var i = 0; i < node.length; i++) {
84887      var child = node[i];
84888      if (ReactElement.isValidElement(child)) {
84889        validateExplicitKey(child, parentType);
84890      }
84891    }
84892  } else if (ReactElement.isValidElement(node)) {
84893    // This element was passed in a valid location.
84894    if (node._store) {
84895      node._store.validated = true;
84896    }
84897  } else if (node) {
84898    var iteratorFn = getIteratorFn(node);
84899    // Entry iterators provide implicit keys.
84900    if (iteratorFn) {
84901      if (iteratorFn !== node.entries) {
84902        var iterator = iteratorFn.call(node);
84903        var step;
84904        while (!(step = iterator.next()).done) {
84905          if (ReactElement.isValidElement(step.value)) {
84906            validateExplicitKey(step.value, parentType);
84907          }
84908        }
84909      }
84910    }
84911  }
84912}
84913
84914/**
84915 * Assert that the props are valid
84916 *
84917 * @param {string} componentName Name of the component for error messages.
84918 * @param {object} propTypes Map of prop name to a ReactPropType
84919 * @param {object} props
84920 * @param {string} location e.g. "prop", "context", "child context"
84921 * @private
84922 */
84923function checkPropTypes(componentName, propTypes, props, location) {
84924  for (var propName in propTypes) {
84925    if (propTypes.hasOwnProperty(propName)) {
84926      var error;
84927      // Prop type validation may throw. In case they do, we don't want to
84928      // fail the render phase where it didn't fail before. So we log it.
84929      // After these have been cleaned up, we'll let them throw.
84930      try {
84931        // This is intentionally an invariant that gets caught. It's the same
84932        // behavior as without this statement except with a better message.
84933        !(typeof propTypes[propName] === 'function') ? "development" !== 'production' ? invariant(false, '%s: %s type `%s` is invalid; it must be a function, usually from ' + 'React.PropTypes.', componentName || 'React class', ReactPropTypeLocationNames[location], propName) : invariant(false) : void 0;
84934        error = propTypes[propName](props, propName, componentName, location);
84935      } catch (ex) {
84936        error = ex;
84937      }
84938      "development" !== 'production' ? warning(!error || error instanceof Error, '%s: type specification of %s `%s` is invalid; the type checker ' + 'function must return `null` or an `Error` but returned a %s. ' + 'You may have forgotten to pass an argument to the type checker ' + 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' + 'shape all require an argument).', componentName || 'React class', ReactPropTypeLocationNames[location], propName, typeof error) : void 0;
84939      if (error instanceof Error && !(error.message in loggedTypeFailures)) {
84940        // Only monitor this failure once because there tends to be a lot of the
84941        // same error.
84942        loggedTypeFailures[error.message] = true;
84943
84944        var addendum = getDeclarationErrorAddendum();
84945        "development" !== 'production' ? warning(false, 'Failed propType: %s%s', error.message, addendum) : void 0;
84946      }
84947    }
84948  }
84949}
84950
84951/**
84952 * Given an element, validate that its props follow the propTypes definition,
84953 * provided by the type.
84954 *
84955 * @param {ReactElement} element
84956 */
84957function validatePropTypes(element) {
84958  var componentClass = element.type;
84959  if (typeof componentClass !== 'function') {
84960    return;
84961  }
84962  var name = componentClass.displayName || componentClass.name;
84963  if (componentClass.propTypes) {
84964    checkPropTypes(name, componentClass.propTypes, element.props, ReactPropTypeLocations.prop);
84965  }
84966  if (typeof componentClass.getDefaultProps === 'function') {
84967    "development" !== 'production' ? warning(componentClass.getDefaultProps.isReactClassApproved, 'getDefaultProps is only used on classic React.createClass ' + 'definitions. Use a static property named `defaultProps` instead.') : void 0;
84968  }
84969}
84970
84971var ReactElementValidator = {
84972
84973  createElement: function (type, props, children) {
84974    var validType = typeof type === 'string' || typeof type === 'function';
84975    // We warn in this case but don't throw. We expect the element creation to
84976    // succeed and there will likely be errors in render.
84977    "development" !== 'production' ? warning(validType, 'React.createElement: type should not be null, undefined, boolean, or ' + 'number. It should be a string (for DOM elements) or a ReactClass ' + '(for composite components).%s', getDeclarationErrorAddendum()) : void 0;
84978
84979    var element = ReactElement.createElement.apply(this, arguments);
84980
84981    // The result can be nullish if a mock or a custom function is used.
84982    // TODO: Drop this when these are no longer allowed as the type argument.
84983    if (element == null) {
84984      return element;
84985    }
84986
84987    // Skip key warning if the type isn't valid since our key validation logic
84988    // doesn't expect a non-string/function type and can throw confusing errors.
84989    // We don't want exception behavior to differ between dev and prod.
84990    // (Rendering will throw with a helpful message and as soon as the type is
84991    // fixed, the key warnings will appear.)
84992    if (validType) {
84993      for (var i = 2; i < arguments.length; i++) {
84994        validateChildKeys(arguments[i], type);
84995      }
84996    }
84997
84998    validatePropTypes(element);
84999
85000    return element;
85001  },
85002
85003  createFactory: function (type) {
85004    var validatedFactory = ReactElementValidator.createElement.bind(null, type);
85005    // Legacy hook TODO: Warn if this is accessed
85006    validatedFactory.type = type;
85007
85008    if ("development" !== 'production') {
85009      if (canDefineProperty) {
85010        Object.defineProperty(validatedFactory, 'type', {
85011          enumerable: false,
85012          get: function () {
85013            "development" !== 'production' ? warning(false, 'Factory.type is deprecated. Access the class directly ' + 'before passing it to createFactory.') : void 0;
85014            Object.defineProperty(this, 'type', {
85015              value: type
85016            });
85017            return type;
85018          }
85019        });
85020      }
85021    }
85022
85023    return validatedFactory;
85024  },
85025
85026  cloneElement: function (element, props, children) {
85027    var newElement = ReactElement.cloneElement.apply(this, arguments);
85028    for (var i = 2; i < arguments.length; i++) {
85029      validateChildKeys(arguments[i], newElement.type);
85030    }
85031    validatePropTypes(newElement);
85032    return newElement;
85033  }
85034
85035};
85036
85037module.exports = ReactElementValidator;
85038},{"116":116,"127":127,"158":158,"168":168,"35":35,"62":62,"83":83,"84":84}],64:[function(_dereq_,module,exports){
85039/**
85040 * Copyright 2014-present, Facebook, Inc.
85041 * All rights reserved.
85042 *
85043 * This source code is licensed under the BSD-style license found in the
85044 * LICENSE file in the root directory of this source tree. An additional grant
85045 * of patent rights can be found in the PATENTS file in the same directory.
85046 *
85047 * @providesModule ReactEmptyComponent
85048 */
85049
85050
85051
85052var emptyComponentFactory;
85053
85054var ReactEmptyComponentInjection = {
85055  injectEmptyComponentFactory: function (factory) {
85056    emptyComponentFactory = factory;
85057  }
85058};
85059
85060var ReactEmptyComponent = {
85061  create: function (instantiate) {
85062    return emptyComponentFactory(instantiate);
85063  }
85064};
85065
85066ReactEmptyComponent.injection = ReactEmptyComponentInjection;
85067
85068module.exports = ReactEmptyComponent;
85069},{}],65:[function(_dereq_,module,exports){
85070/**
85071 * Copyright 2013-present, Facebook, Inc.
85072 * All rights reserved.
85073 *
85074 * This source code is licensed under the BSD-style license found in the
85075 * LICENSE file in the root directory of this source tree. An additional grant
85076 * of patent rights can be found in the PATENTS file in the same directory.
85077 *
85078 * @providesModule ReactErrorUtils
85079 */
85080
85081
85082
85083var caughtError = null;
85084
85085/**
85086 * Call a function while guarding against errors that happens within it.
85087 *
85088 * @param {?String} name of the guard to use for logging or debugging
85089 * @param {Function} func The function to invoke
85090 * @param {*} a First argument
85091 * @param {*} b Second argument
85092 */
85093function invokeGuardedCallback(name, func, a, b) {
85094  try {
85095    return func(a, b);
85096  } catch (x) {
85097    if (caughtError === null) {
85098      caughtError = x;
85099    }
85100    return undefined;
85101  }
85102}
85103
85104var ReactErrorUtils = {
85105  invokeGuardedCallback: invokeGuardedCallback,
85106
85107  /**
85108   * Invoked by ReactTestUtils.Simulate so that any errors thrown by the event
85109   * handler are sure to be rethrown by rethrowCaughtError.
85110   */
85111  invokeGuardedCallbackWithCatch: invokeGuardedCallback,
85112
85113  /**
85114   * During execution of guarded functions we will capture the first error which
85115   * we will rethrow to be handled by the top level error handler.
85116   */
85117  rethrowCaughtError: function () {
85118    if (caughtError) {
85119      var error = caughtError;
85120      caughtError = null;
85121      throw error;
85122    }
85123  }
85124};
85125
85126if ("development" !== 'production') {
85127  /**
85128   * To help development we can get better devtools integration by simulating a
85129   * real browser event.
85130   */
85131  if (typeof window !== 'undefined' && typeof window.dispatchEvent === 'function' && typeof document !== 'undefined' && typeof document.createEvent === 'function') {
85132    var fakeNode = document.createElement('react');
85133    ReactErrorUtils.invokeGuardedCallback = function (name, func, a, b) {
85134      var boundFunc = func.bind(null, a, b);
85135      var evtType = 'react-' + name;
85136      fakeNode.addEventListener(evtType, boundFunc, false);
85137      var evt = document.createEvent('Event');
85138      evt.initEvent(evtType, false, false);
85139      fakeNode.dispatchEvent(evt);
85140      fakeNode.removeEventListener(evtType, boundFunc, false);
85141    };
85142  }
85143}
85144
85145module.exports = ReactErrorUtils;
85146},{}],66:[function(_dereq_,module,exports){
85147/**
85148 * Copyright 2013-present, Facebook, Inc.
85149 * All rights reserved.
85150 *
85151 * This source code is licensed under the BSD-style license found in the
85152 * LICENSE file in the root directory of this source tree. An additional grant
85153 * of patent rights can be found in the PATENTS file in the same directory.
85154 *
85155 * @providesModule ReactEventEmitterMixin
85156 */
85157
85158
85159
85160var EventPluginHub = _dereq_(17);
85161
85162function runEventQueueInBatch(events) {
85163  EventPluginHub.enqueueEvents(events);
85164  EventPluginHub.processEventQueue(false);
85165}
85166
85167var ReactEventEmitterMixin = {
85168
85169  /**
85170   * Streams a fired top-level event to `EventPluginHub` where plugins have the
85171   * opportunity to create `ReactEvent`s to be dispatched.
85172   */
85173  handleTopLevel: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
85174    var events = EventPluginHub.extractEvents(topLevelType, targetInst, nativeEvent, nativeEventTarget);
85175    runEventQueueInBatch(events);
85176  }
85177};
85178
85179module.exports = ReactEventEmitterMixin;
85180},{"17":17}],67:[function(_dereq_,module,exports){
85181/**
85182 * Copyright 2013-present, Facebook, Inc.
85183 * All rights reserved.
85184 *
85185 * This source code is licensed under the BSD-style license found in the
85186 * LICENSE file in the root directory of this source tree. An additional grant
85187 * of patent rights can be found in the PATENTS file in the same directory.
85188 *
85189 * @providesModule ReactEventListener
85190 */
85191
85192
85193
85194var _assign = _dereq_(169);
85195
85196var EventListener = _dereq_(143);
85197var ExecutionEnvironment = _dereq_(144);
85198var PooledClass = _dereq_(25);
85199var ReactDOMComponentTree = _dereq_(40);
85200var ReactUpdates = _dereq_(94);
85201
85202var getEventTarget = _dereq_(126);
85203var getUnboundedScrollPosition = _dereq_(155);
85204
85205/**
85206 * Find the deepest React component completely containing the root of the
85207 * passed-in instance (for use when entire React trees are nested within each
85208 * other). If React trees are not nested, returns null.
85209 */
85210function findParent(inst) {
85211  // TODO: It may be a good idea to cache this to prevent unnecessary DOM
85212  // traversal, but caching is difficult to do correctly without using a
85213  // mutation observer to listen for all DOM changes.
85214  while (inst._nativeParent) {
85215    inst = inst._nativeParent;
85216  }
85217  var rootNode = ReactDOMComponentTree.getNodeFromInstance(inst);
85218  var container = rootNode.parentNode;
85219  return ReactDOMComponentTree.getClosestInstanceFromNode(container);
85220}
85221
85222// Used to store ancestor hierarchy in top level callback
85223function TopLevelCallbackBookKeeping(topLevelType, nativeEvent) {
85224  this.topLevelType = topLevelType;
85225  this.nativeEvent = nativeEvent;
85226  this.ancestors = [];
85227}
85228_assign(TopLevelCallbackBookKeeping.prototype, {
85229  destructor: function () {
85230    this.topLevelType = null;
85231    this.nativeEvent = null;
85232    this.ancestors.length = 0;
85233  }
85234});
85235PooledClass.addPoolingTo(TopLevelCallbackBookKeeping, PooledClass.twoArgumentPooler);
85236
85237function handleTopLevelImpl(bookKeeping) {
85238  var nativeEventTarget = getEventTarget(bookKeeping.nativeEvent);
85239  var targetInst = ReactDOMComponentTree.getClosestInstanceFromNode(nativeEventTarget);
85240
85241  // Loop through the hierarchy, in case there's any nested components.
85242  // It's important that we build the array of ancestors before calling any
85243  // event handlers, because event handlers can modify the DOM, leading to
85244  // inconsistencies with ReactMount's node cache. See #1105.
85245  var ancestor = targetInst;
85246  do {
85247    bookKeeping.ancestors.push(ancestor);
85248    ancestor = ancestor && findParent(ancestor);
85249  } while (ancestor);
85250
85251  for (var i = 0; i < bookKeeping.ancestors.length; i++) {
85252    targetInst = bookKeeping.ancestors[i];
85253    ReactEventListener._handleTopLevel(bookKeeping.topLevelType, targetInst, bookKeeping.nativeEvent, getEventTarget(bookKeeping.nativeEvent));
85254  }
85255}
85256
85257function scrollValueMonitor(cb) {
85258  var scrollPosition = getUnboundedScrollPosition(window);
85259  cb(scrollPosition);
85260}
85261
85262var ReactEventListener = {
85263  _enabled: true,
85264  _handleTopLevel: null,
85265
85266  WINDOW_HANDLE: ExecutionEnvironment.canUseDOM ? window : null,
85267
85268  setHandleTopLevel: function (handleTopLevel) {
85269    ReactEventListener._handleTopLevel = handleTopLevel;
85270  },
85271
85272  setEnabled: function (enabled) {
85273    ReactEventListener._enabled = !!enabled;
85274  },
85275
85276  isEnabled: function () {
85277    return ReactEventListener._enabled;
85278  },
85279
85280  /**
85281   * Traps top-level events by using event bubbling.
85282   *
85283   * @param {string} topLevelType Record from `EventConstants`.
85284   * @param {string} handlerBaseName Event name (e.g. "click").
85285   * @param {object} handle Element on which to attach listener.
85286   * @return {?object} An object with a remove function which will forcefully
85287   *                  remove the listener.
85288   * @internal
85289   */
85290  trapBubbledEvent: function (topLevelType, handlerBaseName, handle) {
85291    var element = handle;
85292    if (!element) {
85293      return null;
85294    }
85295    return EventListener.listen(element, handlerBaseName, ReactEventListener.dispatchEvent.bind(null, topLevelType));
85296  },
85297
85298  /**
85299   * Traps a top-level event by using event capturing.
85300   *
85301   * @param {string} topLevelType Record from `EventConstants`.
85302   * @param {string} handlerBaseName Event name (e.g. "click").
85303   * @param {object} handle Element on which to attach listener.
85304   * @return {?object} An object with a remove function which will forcefully
85305   *                  remove the listener.
85306   * @internal
85307   */
85308  trapCapturedEvent: function (topLevelType, handlerBaseName, handle) {
85309    var element = handle;
85310    if (!element) {
85311      return null;
85312    }
85313    return EventListener.capture(element, handlerBaseName, ReactEventListener.dispatchEvent.bind(null, topLevelType));
85314  },
85315
85316  monitorScrollValue: function (refresh) {
85317    var callback = scrollValueMonitor.bind(null, refresh);
85318    EventListener.listen(window, 'scroll', callback);
85319  },
85320
85321  dispatchEvent: function (topLevelType, nativeEvent) {
85322    if (!ReactEventListener._enabled) {
85323      return;
85324    }
85325
85326    var bookKeeping = TopLevelCallbackBookKeeping.getPooled(topLevelType, nativeEvent);
85327    try {
85328      // Event queue being processed in the same cycle allows
85329      // `preventDefault`.
85330      ReactUpdates.batchedUpdates(handleTopLevelImpl, bookKeeping);
85331    } finally {
85332      TopLevelCallbackBookKeeping.release(bookKeeping);
85333    }
85334  }
85335};
85336
85337module.exports = ReactEventListener;
85338},{"126":126,"143":143,"144":144,"155":155,"169":169,"25":25,"40":40,"94":94}],68:[function(_dereq_,module,exports){
85339/**
85340 * Copyright 2013-present, Facebook, Inc.
85341 * All rights reserved.
85342 *
85343 * This source code is licensed under the BSD-style license found in the
85344 * LICENSE file in the root directory of this source tree. An additional grant
85345 * of patent rights can be found in the PATENTS file in the same directory.
85346 *
85347 * @providesModule ReactFeatureFlags
85348 */
85349
85350
85351
85352var ReactFeatureFlags = {
85353  // When true, call console.time() before and .timeEnd() after each top-level
85354  // render (both initial renders and updates). Useful when looking at prod-mode
85355  // timeline profiles in Chrome, for example.
85356  logTopLevelRenders: false
85357};
85358
85359module.exports = ReactFeatureFlags;
85360},{}],69:[function(_dereq_,module,exports){
85361/**
85362 * Copyright 2013-present, Facebook, Inc.
85363 * All rights reserved.
85364 *
85365 * This source code is licensed under the BSD-style license found in the
85366 * LICENSE file in the root directory of this source tree. An additional grant
85367 * of patent rights can be found in the PATENTS file in the same directory.
85368 *
85369 * @providesModule ReactInjection
85370 */
85371
85372
85373
85374var DOMProperty = _dereq_(10);
85375var EventPluginHub = _dereq_(17);
85376var EventPluginUtils = _dereq_(19);
85377var ReactComponentEnvironment = _dereq_(33);
85378var ReactClass = _dereq_(30);
85379var ReactEmptyComponent = _dereq_(64);
85380var ReactBrowserEventEmitter = _dereq_(27);
85381var ReactNativeComponent = _dereq_(78);
85382var ReactPerf = _dereq_(82);
85383var ReactUpdates = _dereq_(94);
85384
85385var ReactInjection = {
85386  Component: ReactComponentEnvironment.injection,
85387  Class: ReactClass.injection,
85388  DOMProperty: DOMProperty.injection,
85389  EmptyComponent: ReactEmptyComponent.injection,
85390  EventPluginHub: EventPluginHub.injection,
85391  EventPluginUtils: EventPluginUtils.injection,
85392  EventEmitter: ReactBrowserEventEmitter.injection,
85393  NativeComponent: ReactNativeComponent.injection,
85394  Perf: ReactPerf.injection,
85395  Updates: ReactUpdates.injection
85396};
85397
85398module.exports = ReactInjection;
85399},{"10":10,"17":17,"19":19,"27":27,"30":30,"33":33,"64":64,"78":78,"82":82,"94":94}],70:[function(_dereq_,module,exports){
85400/**
85401 * Copyright 2013-present, Facebook, Inc.
85402 * All rights reserved.
85403 *
85404 * This source code is licensed under the BSD-style license found in the
85405 * LICENSE file in the root directory of this source tree. An additional grant
85406 * of patent rights can be found in the PATENTS file in the same directory.
85407 *
85408 * @providesModule ReactInputSelection
85409 */
85410
85411
85412
85413var ReactDOMSelection = _dereq_(51);
85414
85415var containsNode = _dereq_(147);
85416var focusNode = _dereq_(152);
85417var getActiveElement = _dereq_(153);
85418
85419function isInDocument(node) {
85420  return containsNode(document.documentElement, node);
85421}
85422
85423/**
85424 * @ReactInputSelection: React input selection module. Based on Selection.js,
85425 * but modified to be suitable for react and has a couple of bug fixes (doesn't
85426 * assume buttons have range selections allowed).
85427 * Input selection module for React.
85428 */
85429var ReactInputSelection = {
85430
85431  hasSelectionCapabilities: function (elem) {
85432    var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase();
85433    return nodeName && (nodeName === 'input' && elem.type === 'text' || nodeName === 'textarea' || elem.contentEditable === 'true');
85434  },
85435
85436  getSelectionInformation: function () {
85437    var focusedElem = getActiveElement();
85438    return {
85439      focusedElem: focusedElem,
85440      selectionRange: ReactInputSelection.hasSelectionCapabilities(focusedElem) ? ReactInputSelection.getSelection(focusedElem) : null
85441    };
85442  },
85443
85444  /**
85445   * @restoreSelection: If any selection information was potentially lost,
85446   * restore it. This is useful when performing operations that could remove dom
85447   * nodes and place them back in, resulting in focus being lost.
85448   */
85449  restoreSelection: function (priorSelectionInformation) {
85450    var curFocusedElem = getActiveElement();
85451    var priorFocusedElem = priorSelectionInformation.focusedElem;
85452    var priorSelectionRange = priorSelectionInformation.selectionRange;
85453    if (curFocusedElem !== priorFocusedElem && isInDocument(priorFocusedElem)) {
85454      if (ReactInputSelection.hasSelectionCapabilities(priorFocusedElem)) {
85455        ReactInputSelection.setSelection(priorFocusedElem, priorSelectionRange);
85456      }
85457      focusNode(priorFocusedElem);
85458    }
85459  },
85460
85461  /**
85462   * @getSelection: Gets the selection bounds of a focused textarea, input or
85463   * contentEditable node.
85464   * -@input: Look up selection bounds of this input
85465   * -@return {start: selectionStart, end: selectionEnd}
85466   */
85467  getSelection: function (input) {
85468    var selection;
85469
85470    if ('selectionStart' in input) {
85471      // Modern browser with input or textarea.
85472      selection = {
85473        start: input.selectionStart,
85474        end: input.selectionEnd
85475      };
85476    } else if (document.selection && input.nodeName && input.nodeName.toLowerCase() === 'input') {
85477      // IE8 input.
85478      var range = document.selection.createRange();
85479      // There can only be one selection per document in IE, so it must
85480      // be in our element.
85481      if (range.parentElement() === input) {
85482        selection = {
85483          start: -range.moveStart('character', -input.value.length),
85484          end: -range.moveEnd('character', -input.value.length)
85485        };
85486      }
85487    } else {
85488      // Content editable or old IE textarea.
85489      selection = ReactDOMSelection.getOffsets(input);
85490    }
85491
85492    return selection || { start: 0, end: 0 };
85493  },
85494
85495  /**
85496   * @setSelection: Sets the selection bounds of a textarea or input and focuses
85497   * the input.
85498   * -@input     Set selection bounds of this input or textarea
85499   * -@offsets   Object of same form that is returned from get*
85500   */
85501  setSelection: function (input, offsets) {
85502    var start = offsets.start;
85503    var end = offsets.end;
85504    if (end === undefined) {
85505      end = start;
85506    }
85507
85508    if ('selectionStart' in input) {
85509      input.selectionStart = start;
85510      input.selectionEnd = Math.min(end, input.value.length);
85511    } else if (document.selection && input.nodeName && input.nodeName.toLowerCase() === 'input') {
85512      var range = input.createTextRange();
85513      range.collapse(true);
85514      range.moveStart('character', start);
85515      range.moveEnd('character', end - start);
85516      range.select();
85517    } else {
85518      ReactDOMSelection.setOffsets(input, offsets);
85519    }
85520  }
85521};
85522
85523module.exports = ReactInputSelection;
85524},{"147":147,"152":152,"153":153,"51":51}],71:[function(_dereq_,module,exports){
85525/**
85526 * Copyright 2013-present, Facebook, Inc.
85527 * All rights reserved.
85528 *
85529 * This source code is licensed under the BSD-style license found in the
85530 * LICENSE file in the root directory of this source tree. An additional grant
85531 * of patent rights can be found in the PATENTS file in the same directory.
85532 *
85533 * @providesModule ReactInstanceMap
85534 */
85535
85536
85537
85538/**
85539 * `ReactInstanceMap` maintains a mapping from a public facing stateful
85540 * instance (key) and the internal representation (value). This allows public
85541 * methods to accept the user facing instance as an argument and map them back
85542 * to internal methods.
85543 */
85544
85545// TODO: Replace this with ES6: var ReactInstanceMap = new Map();
85546
85547var ReactInstanceMap = {
85548
85549  /**
85550   * This API should be called `delete` but we'd have to make sure to always
85551   * transform these to strings for IE support. When this transform is fully
85552   * supported we can rename it.
85553   */
85554  remove: function (key) {
85555    key._reactInternalInstance = undefined;
85556  },
85557
85558  get: function (key) {
85559    return key._reactInternalInstance;
85560  },
85561
85562  has: function (key) {
85563    return key._reactInternalInstance !== undefined;
85564  },
85565
85566  set: function (key, value) {
85567    key._reactInternalInstance = value;
85568  }
85569
85570};
85571
85572module.exports = ReactInstanceMap;
85573},{}],72:[function(_dereq_,module,exports){
85574/**
85575 * Copyright 2016-present, Facebook, Inc.
85576 * All rights reserved.
85577 *
85578 * This source code is licensed under the BSD-style license found in the
85579 * LICENSE file in the root directory of this source tree. An additional grant
85580 * of patent rights can be found in the PATENTS file in the same directory.
85581 *
85582 * @providesModule ReactInstrumentation
85583 */
85584
85585
85586
85587var ReactDebugTool = _dereq_(57);
85588
85589module.exports = { debugTool: ReactDebugTool };
85590},{"57":57}],73:[function(_dereq_,module,exports){
85591/**
85592 * Copyright 2016-present, Facebook, Inc.
85593 * All rights reserved.
85594 *
85595 * This source code is licensed under the BSD-style license found in the
85596 * LICENSE file in the root directory of this source tree. An additional grant
85597 * of patent rights can be found in the PATENTS file in the same directory.
85598 *
85599 * @providesModule ReactInvalidSetStateWarningDevTool
85600 */
85601
85602
85603
85604var warning = _dereq_(168);
85605
85606if ("development" !== 'production') {
85607  var processingChildContext = false;
85608
85609  var warnInvalidSetState = function () {
85610    "development" !== 'production' ? warning(!processingChildContext, 'setState(...): Cannot call setState() inside getChildContext()') : void 0;
85611  };
85612}
85613
85614var ReactInvalidSetStateWarningDevTool = {
85615  onBeginProcessingChildContext: function () {
85616    processingChildContext = true;
85617  },
85618  onEndProcessingChildContext: function () {
85619    processingChildContext = false;
85620  },
85621  onSetState: function () {
85622    warnInvalidSetState();
85623  }
85624};
85625
85626module.exports = ReactInvalidSetStateWarningDevTool;
85627},{"168":168}],74:[function(_dereq_,module,exports){
85628/**
85629 * Copyright 2013-present, Facebook, Inc.
85630 * All rights reserved.
85631 *
85632 * This source code is licensed under the BSD-style license found in the
85633 * LICENSE file in the root directory of this source tree. An additional grant
85634 * of patent rights can be found in the PATENTS file in the same directory.
85635 *
85636 * @providesModule ReactMarkupChecksum
85637 */
85638
85639
85640
85641var adler32 = _dereq_(115);
85642
85643var TAG_END = /\/?>/;
85644var COMMENT_START = /^<\!\-\-/;
85645
85646var ReactMarkupChecksum = {
85647  CHECKSUM_ATTR_NAME: 'data-react-checksum',
85648
85649  /**
85650   * @param {string} markup Markup string
85651   * @return {string} Markup string with checksum attribute attached
85652   */
85653  addChecksumToMarkup: function (markup) {
85654    var checksum = adler32(markup);
85655
85656    // Add checksum (handle both parent tags, comments and self-closing tags)
85657    if (COMMENT_START.test(markup)) {
85658      return markup;
85659    } else {
85660      return markup.replace(TAG_END, ' ' + ReactMarkupChecksum.CHECKSUM_ATTR_NAME + '="' + checksum + '"$&');
85661    }
85662  },
85663
85664  /**
85665   * @param {string} markup to use
85666   * @param {DOMElement} element root React element
85667   * @returns {boolean} whether or not the markup is the same
85668   */
85669  canReuseMarkup: function (markup, element) {
85670    var existingChecksum = element.getAttribute(ReactMarkupChecksum.CHECKSUM_ATTR_NAME);
85671    existingChecksum = existingChecksum && parseInt(existingChecksum, 10);
85672    var markupChecksum = adler32(markup);
85673    return markupChecksum === existingChecksum;
85674  }
85675};
85676
85677module.exports = ReactMarkupChecksum;
85678},{"115":115}],75:[function(_dereq_,module,exports){
85679/**
85680 * Copyright 2013-present, Facebook, Inc.
85681 * All rights reserved.
85682 *
85683 * This source code is licensed under the BSD-style license found in the
85684 * LICENSE file in the root directory of this source tree. An additional grant
85685 * of patent rights can be found in the PATENTS file in the same directory.
85686 *
85687 * @providesModule ReactMount
85688 */
85689
85690
85691
85692var DOMLazyTree = _dereq_(8);
85693var DOMProperty = _dereq_(10);
85694var ReactBrowserEventEmitter = _dereq_(27);
85695var ReactCurrentOwner = _dereq_(35);
85696var ReactDOMComponentTree = _dereq_(40);
85697var ReactDOMContainerInfo = _dereq_(41);
85698var ReactDOMFeatureFlags = _dereq_(45);
85699var ReactElement = _dereq_(62);
85700var ReactFeatureFlags = _dereq_(68);
85701var ReactInstrumentation = _dereq_(72);
85702var ReactMarkupChecksum = _dereq_(74);
85703var ReactPerf = _dereq_(82);
85704var ReactReconciler = _dereq_(87);
85705var ReactUpdateQueue = _dereq_(93);
85706var ReactUpdates = _dereq_(94);
85707
85708var emptyObject = _dereq_(151);
85709var instantiateReactComponent = _dereq_(132);
85710var invariant = _dereq_(158);
85711var setInnerHTML = _dereq_(138);
85712var shouldUpdateReactComponent = _dereq_(140);
85713var warning = _dereq_(168);
85714
85715var ATTR_NAME = DOMProperty.ID_ATTRIBUTE_NAME;
85716var ROOT_ATTR_NAME = DOMProperty.ROOT_ATTRIBUTE_NAME;
85717
85718var ELEMENT_NODE_TYPE = 1;
85719var DOC_NODE_TYPE = 9;
85720var DOCUMENT_FRAGMENT_NODE_TYPE = 11;
85721
85722var instancesByReactRootID = {};
85723
85724/**
85725 * Finds the index of the first character
85726 * that's not common between the two given strings.
85727 *
85728 * @return {number} the index of the character where the strings diverge
85729 */
85730function firstDifferenceIndex(string1, string2) {
85731  var minLen = Math.min(string1.length, string2.length);
85732  for (var i = 0; i < minLen; i++) {
85733    if (string1.charAt(i) !== string2.charAt(i)) {
85734      return i;
85735    }
85736  }
85737  return string1.length === string2.length ? -1 : minLen;
85738}
85739
85740/**
85741 * @param {DOMElement|DOMDocument} container DOM element that may contain
85742 * a React component
85743 * @return {?*} DOM element that may have the reactRoot ID, or null.
85744 */
85745function getReactRootElementInContainer(container) {
85746  if (!container) {
85747    return null;
85748  }
85749
85750  if (container.nodeType === DOC_NODE_TYPE) {
85751    return container.documentElement;
85752  } else {
85753    return container.firstChild;
85754  }
85755}
85756
85757function internalGetID(node) {
85758  // If node is something like a window, document, or text node, none of
85759  // which support attributes or a .getAttribute method, gracefully return
85760  // the empty string, as if the attribute were missing.
85761  return node.getAttribute && node.getAttribute(ATTR_NAME) || '';
85762}
85763
85764/**
85765 * Mounts this component and inserts it into the DOM.
85766 *
85767 * @param {ReactComponent} componentInstance The instance to mount.
85768 * @param {DOMElement} container DOM element to mount into.
85769 * @param {ReactReconcileTransaction} transaction
85770 * @param {boolean} shouldReuseMarkup If true, do not insert markup
85771 */
85772function mountComponentIntoNode(wrapperInstance, container, transaction, shouldReuseMarkup, context) {
85773  var markerName;
85774  if (ReactFeatureFlags.logTopLevelRenders) {
85775    var wrappedElement = wrapperInstance._currentElement.props;
85776    var type = wrappedElement.type;
85777    markerName = 'React mount: ' + (typeof type === 'string' ? type : type.displayName || type.name);
85778    console.time(markerName);
85779  }
85780
85781  var markup = ReactReconciler.mountComponent(wrapperInstance, transaction, null, ReactDOMContainerInfo(wrapperInstance, container), context);
85782
85783  if (markerName) {
85784    console.timeEnd(markerName);
85785  }
85786
85787  wrapperInstance._renderedComponent._topLevelWrapper = wrapperInstance;
85788  ReactMount._mountImageIntoNode(markup, container, wrapperInstance, shouldReuseMarkup, transaction);
85789}
85790
85791/**
85792 * Batched mount.
85793 *
85794 * @param {ReactComponent} componentInstance The instance to mount.
85795 * @param {DOMElement} container DOM element to mount into.
85796 * @param {boolean} shouldReuseMarkup If true, do not insert markup
85797 */
85798function batchedMountComponentIntoNode(componentInstance, container, shouldReuseMarkup, context) {
85799  var transaction = ReactUpdates.ReactReconcileTransaction.getPooled(
85800  /* useCreateElement */
85801  !shouldReuseMarkup && ReactDOMFeatureFlags.useCreateElement);
85802  transaction.perform(mountComponentIntoNode, null, componentInstance, container, transaction, shouldReuseMarkup, context);
85803  ReactUpdates.ReactReconcileTransaction.release(transaction);
85804}
85805
85806/**
85807 * Unmounts a component and removes it from the DOM.
85808 *
85809 * @param {ReactComponent} instance React component instance.
85810 * @param {DOMElement} container DOM element to unmount from.
85811 * @final
85812 * @internal
85813 * @see {ReactMount.unmountComponentAtNode}
85814 */
85815function unmountComponentFromNode(instance, container, safely) {
85816  ReactReconciler.unmountComponent(instance, safely);
85817
85818  if (container.nodeType === DOC_NODE_TYPE) {
85819    container = container.documentElement;
85820  }
85821
85822  // http://jsperf.com/emptying-a-node
85823  while (container.lastChild) {
85824    container.removeChild(container.lastChild);
85825  }
85826}
85827
85828/**
85829 * True if the supplied DOM node has a direct React-rendered child that is
85830 * not a React root element. Useful for warning in `render`,
85831 * `unmountComponentAtNode`, etc.
85832 *
85833 * @param {?DOMElement} node The candidate DOM node.
85834 * @return {boolean} True if the DOM element contains a direct child that was
85835 * rendered by React but is not a root element.
85836 * @internal
85837 */
85838function hasNonRootReactChild(container) {
85839  var rootEl = getReactRootElementInContainer(container);
85840  if (rootEl) {
85841    var inst = ReactDOMComponentTree.getInstanceFromNode(rootEl);
85842    return !!(inst && inst._nativeParent);
85843  }
85844}
85845
85846function getNativeRootInstanceInContainer(container) {
85847  var rootEl = getReactRootElementInContainer(container);
85848  var prevNativeInstance = rootEl && ReactDOMComponentTree.getInstanceFromNode(rootEl);
85849  return prevNativeInstance && !prevNativeInstance._nativeParent ? prevNativeInstance : null;
85850}
85851
85852function getTopLevelWrapperInContainer(container) {
85853  var root = getNativeRootInstanceInContainer(container);
85854  return root ? root._nativeContainerInfo._topLevelWrapper : null;
85855}
85856
85857/**
85858 * Temporary (?) hack so that we can store all top-level pending updates on
85859 * composites instead of having to worry about different types of components
85860 * here.
85861 */
85862var topLevelRootCounter = 1;
85863var TopLevelWrapper = function () {
85864  this.rootID = topLevelRootCounter++;
85865};
85866TopLevelWrapper.prototype.isReactComponent = {};
85867if ("development" !== 'production') {
85868  TopLevelWrapper.displayName = 'TopLevelWrapper';
85869}
85870TopLevelWrapper.prototype.render = function () {
85871  // this.props is actually a ReactElement
85872  return this.props;
85873};
85874
85875/**
85876 * Mounting is the process of initializing a React component by creating its
85877 * representative DOM elements and inserting them into a supplied `container`.
85878 * Any prior content inside `container` is destroyed in the process.
85879 *
85880 *   ReactMount.render(
85881 *     component,
85882 *     document.getElementById('container')
85883 *   );
85884 *
85885 *   <div id="container">                   <-- Supplied `container`.
85886 *     <div data-reactid=".3">              <-- Rendered reactRoot of React
85887 *       // ...                                 component.
85888 *     </div>
85889 *   </div>
85890 *
85891 * Inside of `container`, the first element rendered is the "reactRoot".
85892 */
85893var ReactMount = {
85894
85895  TopLevelWrapper: TopLevelWrapper,
85896
85897  /**
85898   * Used by devtools. The keys are not important.
85899   */
85900  _instancesByReactRootID: instancesByReactRootID,
85901
85902  /**
85903   * This is a hook provided to support rendering React components while
85904   * ensuring that the apparent scroll position of its `container` does not
85905   * change.
85906   *
85907   * @param {DOMElement} container The `container` being rendered into.
85908   * @param {function} renderCallback This must be called once to do the render.
85909   */
85910  scrollMonitor: function (container, renderCallback) {
85911    renderCallback();
85912  },
85913
85914  /**
85915   * Take a component that's already mounted into the DOM and replace its props
85916   * @param {ReactComponent} prevComponent component instance already in the DOM
85917   * @param {ReactElement} nextElement component instance to render
85918   * @param {DOMElement} container container to render into
85919   * @param {?function} callback function triggered on completion
85920   */
85921  _updateRootComponent: function (prevComponent, nextElement, container, callback) {
85922    ReactMount.scrollMonitor(container, function () {
85923      ReactUpdateQueue.enqueueElementInternal(prevComponent, nextElement);
85924      if (callback) {
85925        ReactUpdateQueue.enqueueCallbackInternal(prevComponent, callback);
85926      }
85927    });
85928
85929    return prevComponent;
85930  },
85931
85932  /**
85933   * Render a new component into the DOM. Hooked by devtools!
85934   *
85935   * @param {ReactElement} nextElement element to render
85936   * @param {DOMElement} container container to render into
85937   * @param {boolean} shouldReuseMarkup if we should skip the markup insertion
85938   * @return {ReactComponent} nextComponent
85939   */
85940  _renderNewRootComponent: function (nextElement, container, shouldReuseMarkup, context) {
85941    // Various parts of our code (such as ReactCompositeComponent's
85942    // _renderValidatedComponent) assume that calls to render aren't nested;
85943    // verify that that's the case.
85944    "development" !== 'production' ? warning(ReactCurrentOwner.current == null, '_renderNewRootComponent(): Render methods should be a pure function ' + 'of props and state; triggering nested component updates from ' + 'render is not allowed. If necessary, trigger nested updates in ' + 'componentDidUpdate. Check the render method of %s.', ReactCurrentOwner.current && ReactCurrentOwner.current.getName() || 'ReactCompositeComponent') : void 0;
85945
85946    !(container && (container.nodeType === ELEMENT_NODE_TYPE || container.nodeType === DOC_NODE_TYPE || container.nodeType === DOCUMENT_FRAGMENT_NODE_TYPE)) ? "development" !== 'production' ? invariant(false, '_registerComponent(...): Target container is not a DOM element.') : invariant(false) : void 0;
85947
85948    ReactBrowserEventEmitter.ensureScrollValueMonitoring();
85949    var componentInstance = instantiateReactComponent(nextElement);
85950
85951    // The initial render is synchronous but any updates that happen during
85952    // rendering, in componentWillMount or componentDidMount, will be batched
85953    // according to the current batching strategy.
85954
85955    ReactUpdates.batchedUpdates(batchedMountComponentIntoNode, componentInstance, container, shouldReuseMarkup, context);
85956
85957    var wrapperID = componentInstance._instance.rootID;
85958    instancesByReactRootID[wrapperID] = componentInstance;
85959
85960    if ("development" !== 'production') {
85961      ReactInstrumentation.debugTool.onMountRootComponent(componentInstance);
85962    }
85963
85964    return componentInstance;
85965  },
85966
85967  /**
85968   * Renders a React component into the DOM in the supplied `container`.
85969   *
85970   * If the React component was previously rendered into `container`, this will
85971   * perform an update on it and only mutate the DOM as necessary to reflect the
85972   * latest React component.
85973   *
85974   * @param {ReactComponent} parentComponent The conceptual parent of this render tree.
85975   * @param {ReactElement} nextElement Component element to render.
85976   * @param {DOMElement} container DOM element to render into.
85977   * @param {?function} callback function triggered on completion
85978   * @return {ReactComponent} Component instance rendered in `container`.
85979   */
85980  renderSubtreeIntoContainer: function (parentComponent, nextElement, container, callback) {
85981    !(parentComponent != null && parentComponent._reactInternalInstance != null) ? "development" !== 'production' ? invariant(false, 'parentComponent must be a valid React Component') : invariant(false) : void 0;
85982    return ReactMount._renderSubtreeIntoContainer(parentComponent, nextElement, container, callback);
85983  },
85984
85985  _renderSubtreeIntoContainer: function (parentComponent, nextElement, container, callback) {
85986    ReactUpdateQueue.validateCallback(callback, 'ReactDOM.render');
85987    !ReactElement.isValidElement(nextElement) ? "development" !== 'production' ? invariant(false, 'ReactDOM.render(): Invalid component element.%s', typeof nextElement === 'string' ? ' Instead of passing a string like \'div\', pass ' + 'React.createElement(\'div\') or <div />.' : typeof nextElement === 'function' ? ' Instead of passing a class like Foo, pass ' + 'React.createElement(Foo) or <Foo />.' :
85988    // Check if it quacks like an element
85989    nextElement != null && nextElement.props !== undefined ? ' This may be caused by unintentionally loading two independent ' + 'copies of React.' : '') : invariant(false) : void 0;
85990
85991    "development" !== 'production' ? warning(!container || !container.tagName || container.tagName.toUpperCase() !== 'BODY', 'render(): Rendering components directly into document.body is ' + 'discouraged, since its children are often manipulated by third-party ' + 'scripts and browser extensions. This may lead to subtle ' + 'reconciliation issues. Try rendering into a container element created ' + 'for your app.') : void 0;
85992
85993    var nextWrappedElement = ReactElement(TopLevelWrapper, null, null, null, null, null, nextElement);
85994
85995    var prevComponent = getTopLevelWrapperInContainer(container);
85996
85997    if (prevComponent) {
85998      var prevWrappedElement = prevComponent._currentElement;
85999      var prevElement = prevWrappedElement.props;
86000      if (shouldUpdateReactComponent(prevElement, nextElement)) {
86001        var publicInst = prevComponent._renderedComponent.getPublicInstance();
86002        var updatedCallback = callback && function () {
86003          callback.call(publicInst);
86004        };
86005        ReactMount._updateRootComponent(prevComponent, nextWrappedElement, container, updatedCallback);
86006        return publicInst;
86007      } else {
86008        ReactMount.unmountComponentAtNode(container);
86009      }
86010    }
86011
86012    var reactRootElement = getReactRootElementInContainer(container);
86013    var containerHasReactMarkup = reactRootElement && !!internalGetID(reactRootElement);
86014    var containerHasNonRootReactChild = hasNonRootReactChild(container);
86015
86016    if ("development" !== 'production') {
86017      "development" !== 'production' ? warning(!containerHasNonRootReactChild, 'render(...): Replacing React-rendered children with a new root ' + 'component. If you intended to update the children of this node, ' + 'you should instead have the existing children update their state ' + 'and render the new components instead of calling ReactDOM.render.') : void 0;
86018
86019      if (!containerHasReactMarkup || reactRootElement.nextSibling) {
86020        var rootElementSibling = reactRootElement;
86021        while (rootElementSibling) {
86022          if (internalGetID(rootElementSibling)) {
86023            "development" !== 'production' ? warning(false, 'render(): Target node has markup rendered by React, but there ' + 'are unrelated nodes as well. This is most commonly caused by ' + 'white-space inserted around server-rendered markup.') : void 0;
86024            break;
86025          }
86026          rootElementSibling = rootElementSibling.nextSibling;
86027        }
86028      }
86029    }
86030
86031    var shouldReuseMarkup = containerHasReactMarkup && !prevComponent && !containerHasNonRootReactChild;
86032    var component = ReactMount._renderNewRootComponent(nextWrappedElement, container, shouldReuseMarkup, parentComponent != null ? parentComponent._reactInternalInstance._processChildContext(parentComponent._reactInternalInstance._context) : emptyObject)._renderedComponent.getPublicInstance();
86033    if (callback) {
86034      callback.call(component);
86035    }
86036    return component;
86037  },
86038
86039  /**
86040   * Renders a React component into the DOM in the supplied `container`.
86041   *
86042   * If the React component was previously rendered into `container`, this will
86043   * perform an update on it and only mutate the DOM as necessary to reflect the
86044   * latest React component.
86045   *
86046   * @param {ReactElement} nextElement Component element to render.
86047   * @param {DOMElement} container DOM element to render into.
86048   * @param {?function} callback function triggered on completion
86049   * @return {ReactComponent} Component instance rendered in `container`.
86050   */
86051  render: function (nextElement, container, callback) {
86052    return ReactMount._renderSubtreeIntoContainer(null, nextElement, container, callback);
86053  },
86054
86055  /**
86056   * Unmounts and destroys the React component rendered in the `container`.
86057   *
86058   * @param {DOMElement} container DOM element containing a React component.
86059   * @return {boolean} True if a component was found in and unmounted from
86060   *                   `container`
86061   */
86062  unmountComponentAtNode: function (container) {
86063    // Various parts of our code (such as ReactCompositeComponent's
86064    // _renderValidatedComponent) assume that calls to render aren't nested;
86065    // verify that that's the case. (Strictly speaking, unmounting won't 
86065cause a
86066    // render but we still don't expect to be in a render call here.)
86067    "development" !== 'production' ? warning(ReactCurrentOwner.current == null, 'unmountComponentAtNode(): Render methods should be a pure function ' + 'of props and state; triggering nested component updates from render ' + 'is not allowed. If necessary, trigger nested updates in ' + 'componentDidUpdate. Check the render method of %s.', ReactCurrentOwner.current && ReactCurrentOwner.current.getName() || 'ReactCompositeComponent') : void 0;
86068
86069    !(container && (container.nodeType === ELEMENT_NODE_TYPE || container.nodeType === DOC_NODE_TYPE || container.nodeType === DOCUMENT_FRAGMENT_NODE_TYPE)) ? "development" !== 'production' ? invariant(false, 'unmountComponentAtNode(...): Target container is not a DOM element.') : invariant(false) : void 0;
86070
86071    var prevComponent = getTopLevelWrapperInContainer(container);
86072    if (!prevComponent) {
86073      // Check if the node being unmounted was rendered by React, but isn't a
86074      // root node.
86075      var containerHasNonRootReactChild = hasNonRootReactChild(container);
86076
86077      // Check if the container itself is a React root node.
86078      var isContainerReactRoot = container.nodeType === 1 && container.hasAttribute(ROOT_ATTR_NAME);
86079
86080      if ("development" !== 'production') {
86081        "development" !== 'production' ? warning(!containerHasNonRootReactChild, 'unmountComponentAtNode(): The node you\'re attempting to unmount ' + 'was rendered by React and is not a top-level container. %s', isContainerReactRoot ? 'You may have accidentally passed in a React root node instead ' + 'of its container.' : 'Instead, have the parent component update its state and ' + 'rerender in order to remove this component.') : void 0;
86082      }
86083
86084      return false;
86085    }
86086    delete instancesByReactRootID[prevComponent._instance.rootID];
86087    ReactUpdates.batchedUpdates(unmountComponentFromNode, prevComponent, container, false);
86088    return true;
86089  },
86090
86091  _mountImageIntoNode: function (markup, container, instance, shouldReuseMarkup, transaction) {
86092    !(container && (container.nodeType === ELEMENT_NODE_TYPE || container.nodeType === DOC_NODE_TYPE || container.nodeType === DOCUMENT_FRAGMENT_NODE_TYPE)) ? "development" !== 'production' ? invariant(false, 'mountComponentIntoNode(...): Target container is not valid.') : invariant(false) : void 0;
86093
86094    if (shouldReuseMarkup) {
86095      var rootElement = getReactRootElementInContainer(container);
86096      if (ReactMarkupChecksum.canReuseMarkup(markup, rootElement)) {
86097        ReactDOMComponentTree.precacheNode(instance, rootElement);
86098        return;
86099      } else {
86100        var checksum = rootElement.getAttribute(ReactMarkupChecksum.CHECKSUM_ATTR_NAME);
86101        rootElement.removeAttribute(ReactMarkupChecksum.CHECKSUM_ATTR_NAME);
86102
86103        var rootMarkup = rootElement.outerHTML;
86104        rootElement.setAttribute(ReactMarkupChecksum.CHECKSUM_ATTR_NAME, checksum);
86105
86106        var normalizedMarkup = markup;
86107        if ("development" !== 'production') {
86108          // because rootMarkup is retrieved from the DOM, various normalizations
86109          // will have occurred which will not be present in `markup`. Here,
86110          // insert markup into a <div> or <iframe> depending on the container
86111          // type to perform the same normalizations before comparing.
86112          var normalizer;
86113          if (container.nodeType === ELEMENT_NODE_TYPE) {
86114            normalizer = document.createElement('div');
86115            normalizer.innerHTML = markup;
86116            normalizedMarkup = normalizer.innerHTML;
86117          } else {
86118            normalizer = document.createElement('iframe');
86119            document.body.appendChild(normalizer);
86120            normalizer.contentDocument.write(markup);
86121            normalizedMarkup = normalizer.contentDocument.documentElement.outerHTML;
86122            document.body.removeChild(normalizer);
86123          }
86124        }
86125
86126        var diffIndex = firstDifferenceIndex(normalizedMarkup, rootMarkup);
86127        var difference = ' (client) ' + normalizedMarkup.substring(diffIndex - 20, diffIndex + 20) + '\n (server) ' + rootMarkup.substring(diffIndex - 20, diffIndex + 20);
86128
86129        !(container.nodeType !== DOC_NODE_TYPE) ? "development" !== 'production' ? invariant(false, 'You\'re trying to render a component to the document using ' + '
86129server rendering but the checksum was invalid. This usually ' + 'means you rendered a different component type or props on ' + 'the client from the one on the server, or your render() ' + 'methods are impure. React cannot handle this case due to ' + 'cross-browser quirks by rendering at the document root. You ' + 'should look for environment dependent code in your components ' + 'and ensure the props are the same client and server side:\n%s', difference) : invariant(false) : void 0;
86130
86131        if ("development" !== 'production') {
86132          "development" !== 'production' ? warning(false, 'React attempted to reuse markup in a container but the ' + 'checksum was invalid. This generally means that you are ' + 'using server rendering and the markup generated on the ' + 'server was not what the client was expecting. React injected ' + 'new markup to compensate which works but you have lost many ' + 'of the benefits of server rendering. Instead, figure out ' + 'why the markup being generated is different on the client ' + 'or server:\n%s', difference) : void 0;
86133        }
86134      }
86135    }
86136
86137    !(container.nodeType !== DOC_NODE_TYPE) ? "development" !== 'production' ? invariant(false, 'You\'re trying to render a component to the document but ' + 'you didn\'t use server rendering. We can\'t do this ' + 'without using server rendering due to cross-browser quirks. ' + 'See ReactDOMServer.renderToString() for server rendering.') : invariant(false) : void 0;
86138
86139    if (transaction.useCreateElement) {
86140      while (container.lastChild) {
86141        container.removeChild(container.lastChild);
86142      }
86143      DOMLazyTree.insertTreeBefore(container, markup, null);
86144    } else {
86145      setInnerHTML(container, markup);
86146      ReactDOMComponentTree.precacheNode(instance, container.firstChild);
86147    }
86148  }
86149};
86150
86151ReactPerf.measureMethods(ReactMount, 'ReactMount', {
86152  _renderNewRootComponent: '_renderNewRootComponent',
86153  _mountImageIntoNode: '_mountImageIntoNode'
86154});
86155
86156module.exports = ReactMount;
86157},{"10":10,"132":132,"138":138,"140":140,"151":151,"158":158,"168":168,"27":27,"35":35,"40":40,"41":41,"45":45,"62":62,"68":68,"72":72,"74":74,"8":8,"82":82,"87":87,"93":93,"94":94}],76:[function(_dereq_,module,exports){
86158/**
86159 * Copyright 2013-present, Facebook, Inc.
86160 * All rights reserved.
86161 *
86162 * This source code is licensed under the BSD-style license found in the
86163 * LICENSE file in the root directory of this source tree. An additional grant
86164 * of patent rights can be found in the PATENTS file in the same directory.
86165 *
86166 * @providesModule ReactMultiChild
86167 */
86168
86169
86170
86171var ReactComponentEnvironment = _dereq_(33);
86172var ReactMultiChildUpdateTypes = _dereq_(77);
86173
86174var ReactCurrentOwner = _dereq_(35);
86175var ReactReconciler = _dereq_(87);
86176var ReactChildReconciler = _dereq_(28);
86177
86178var flattenChildren = _dereq_(121);
86179var invariant = _dereq_(158);
86180
86181/**
86182 * Make an update for markup to be rendered and inserted at a supplied index.
86183 *
86184 * @param {string} markup Markup that renders into an element.
86185 * @param {number} toIndex Destination index.
86186 * @private
86187 */
86188function makeInsertMarkup(markup, afterNode, toIndex) {
86189  // NOTE: Null values reduce hidden classes.
86190  return {
86191    type: ReactMultiChildUpdateTypes.INSERT_MARKUP,
86192    content: markup,
86193    fromIndex: null,
86194    fromNode: null,
86195    toIndex: toIndex,
86196    afterNode: afterNode
86197  };
86198}
86199
86200/**
86201 * Make an update for moving an existing element to another index.
86202 *
86203 * @param {number} fromIndex Source index of the existing element.
86204 * @param {number} toIndex Destination index of the element.
86205 * @private
86206 */
86207function makeMove(child, afterNode, toIndex) {
86208  // NOTE: Null values reduce hidden classes.
86209  return {
86210    type: ReactMultiChildUpdateTypes.MOVE_EXISTING,
86211    content: null,
86212    fromIndex: child._mountIndex,
86213    fromNode: ReactReconciler.getNativeNode(child),
86214    toIndex: toIndex,
86215    afterNode: afterNode
86216  };
86217}
86218
86219/**
86220 * Make an update for removing an element at an index.
86221 *
86222 * @param {number} fromIndex Index of the element to remove.
86223 * @private
86224 */
86225function makeRemove(child, node) {
86226  // NOTE: Null values reduce hidden classes.
86227  return {
86228    type: ReactMultiChildUpdateTypes.REMOVE_NODE,
86229    content: null,
86230    fromIndex: child._mountIndex,
86231    fromNode: node,
86232    toIndex: null,
86233    afterNode: null
86234  };
86235}
86236
86237/**
86238 * Make an update for setting the markup of a node.
86239 *
86240 * @param {string} markup Markup that renders into an element.
86241 * @private
86242 */
86243function makeSetMarkup(markup) {
86244  // NOTE: Null values reduce hidden classes.
86245  return {
86246    type: ReactMultiChildUpdateTypes.SET_MARKUP,
86247    content: markup,
86248    fromIndex: null,
86249    fromNode: null,
86250    toIndex: null,
86251    afterNode: null
86252  };
86253}
86254
86255/**
86256 * Make an update for setting the text content.
86257 *
86258 * @param {string} textContent Text content to set.
86259 * @private
86260 */
86261function makeTextContent(textContent) {
86262  // NOTE: Null values reduce hidden classes.
86263  return {
86264    type: ReactMultiChildUpdateTypes.TEXT_CONTENT,
86265    content: textContent,
86266    fromIndex: null,
86267    fromNode: null,
86268    toIndex: null,
86269    afterNode: null
86270  };
86271}
86272
86273/**
86274 * Push an update, if any, onto the queue. Creates a new queue if none is
86275 * passed and always returns the queue. Mutative.
86276 */
86277function enqueue(queue, update) {
86278  if (update) {
86279    queue = queue || [];
86280    queue.push(update);
86281  }
86282  return queue;
86283}
86284
86285/**
86286 * Processes any enqueued updates.
86287 *
86288 * @private
86289 */
86290function processQueue(inst, updateQueue) {
86291  ReactComponentEnvironment.processChildrenUpdates(inst, updateQueue);
86292}
86293
86294/**
86295 * ReactMultiChild are capable of reconciling multiple children.
86296 *
86297 * @class ReactMultiChild
86298 * @internal
86299 */
86300var ReactMultiChild = {
86301
86302  /**
86303   * Provides common functionality for components that must reconcile multiple
86304   * children. This is used by `ReactDOMComponent` to mount, update, and
86305   * unmount child components.
86306   *
86307   * @lends {ReactMultiChild.prototype}
86308   */
86309  Mixin: {
86310
86311    _reconcilerInstantiateChildren: function (nestedChildren, transaction, context) {
86312      if ("development" !== 'production') {
86313        if (this._currentElement) {
86314          try {
86315            ReactCurrentOwner.current = this._currentElement._owner;
86316            return ReactChildReconciler.instantiateChildren(nestedChildren, transaction, context);
86317          } finally {
86318            ReactCurrentOwner.current = null;
86319          }
86320        }
86321      }
86322      return ReactChildReconciler.instantiateChildren(nestedChildren, transaction, context);
86323    },
86324
86325    _reconcilerUpdateChildren: function (prevChildren, nextNestedChildrenElements, removedNodes, transaction, context) {
86326      var nextChildren;
86327      if ("development" !== 'production') {
86328        if (this._currentElement) {
86329          try {
86330            ReactCurrentOwner.current = this._currentElement._owner;
86331            nextChildren = flattenChildren(nextNestedChildrenElements);
86332          } finally {
86333            ReactCurrentOwner.current = null;
86334          }
86335          ReactChildReconciler.updateChildren(prevChildren, nextChildren, removedNodes, transaction, context);
86336          return nextChildren;
86337        }
86338      }
86339      nextChildren = flattenChildren(nextNestedChildrenElements);
86340      ReactChildReconciler.updateChildren(prevChildren, nextChildren, removedNodes, transaction, context);
86341      return nextChildren;
86342    },
86343
86344    /**
86345     * Generates a "mount image" for each of the supplied children. In the case
86346     * of `ReactDOMComponent`, a mount image is a string of markup.
86347     *
86348     * @param {?object} nestedChildren Nested child maps.
86349     * @return {array} An array of mounted representations.
86350     * @internal
86351     */
86352    mountChildren: function (nestedChildren, transaction, context) {
86353      var children = this._reconcilerInstantiateChildren(nestedChildren, transaction, context);
86354      this._renderedChildren = children;
86355      var mountImages = [];
86356      var index = 0;
86357      for (var name in children) {
86358        if (children.hasOwnProperty(name)) {
86359          var child = children[name];
86360          var mountImage = ReactReconciler.mountComponent(child, transaction, this, this._nativeContainerInfo, context);
86361          child._mountIndex = index++;
86362          mountImages.push(mountImage);
86363        }
86364      }
86365      return mountImages;
86366    },
86367
86368    /**
86369     * Replaces any rendered children with a text content string.
86370     *
86371     * @param {string} nextContent String of content.
86372     * @internal
86373     */
86374    updateTextContent: function (nextContent) {
86375      var prevChildren = this._renderedChildren;
86376      // Remove any rendered children.
86377      ReactChildReconciler.unmountChildren(prevChildren, false);
86378      for (var name in prevChildren) {
86379        if (prevChildren.hasOwnProperty(name)) {
86380          !false ? "development" !== 'production' ? invariant(false, 'updateTextContent called on non-empty component.') : invariant(false) : void 0;
86381        }
86382      }
86383      // Set new text content.
86384      var updates = [makeTextContent(nextContent)];
86385      processQueue(this, updates);
86386    },
86387
86388    /**
86389     * Replaces any rendered children with a markup string.
86390     *
86391     * @param {string} nextMarkup String of markup.
86392     * @internal
86393     */
86394    updateMarkup: function (nextMarkup) {
86395      var prevChildren = this._renderedChildren;
86396      // Remove any rendered children.
86397      ReactChildReconciler.unmountChildren(prevChildren, false);
86398      for (var name in prevChildren) {
86399        if (prevChildren.hasOwnProperty(name)) {
86400          !false ? "development" !== 'production' ? invariant(false, 'updateTextContent called on non-empty component.') : invariant(false) : void 0;
86401        }
86402      }
86403      var updates = [makeSetMarkup(nextMarkup)];
86404      processQueue(this, updates);
86405    },
86406
86407    /**
86408     * Updates the rendered children with new children.
86409     *
86410     * @param {?object} nextNestedChildrenElements Nested child element maps.
86411     * @param {ReactReconcileTransaction} transaction
86412     * @internal
86413     */
86414    updateChildren: function (nextNestedChildrenElements, transaction, context) {
86415      // Hook used by React ART
86416      this._updateChildren(nextNestedChildrenElements, transaction, context);
86417    },
86418
86419    /**
86420     * @param {?object} nextNestedChildrenElements Nested child element maps.
86421     * @param {ReactReconcileTransaction} transaction
86422     * @final
86423     * @protected
86424     */
86425    _updateChildren: function (nextNestedChildrenElements, transaction, context) {
86426      var prevChildren = this._renderedChildren;
86427      var removedNodes = {};
86428      var nextChildren = this._reconcilerUpdateChildren(prevChildren, nextNestedChildrenElements, removedNodes, transaction, context);
86429      if (!nextChildren && !prevChildren) {
86430        return;
86431      }
86432      var updates = null;
86433      var name;
86434      // `nextIndex` will increment for each child in `nextChildren`, but
86435      // `lastIndex` will be the last index visited in `prevChildren`.
86436      var lastIndex = 0;
86437      var nextIndex = 0;
86438      var lastPlacedNode = null;
86439      for (name in nextChildren) {
86440        if (!nextChildren.hasOwnProperty(name)) {
86441          continue;
86442        }
86443        var prevChild = prevChildren && prevChildren[name];
86444        var nextChild = nextChildren[name];
86445        if (prevChild === nextChild) {
86446          updates = enqueue(updates, this.moveChild(prevChild, lastPlacedNode, nextIndex, lastIndex));
86447          lastIndex = Math.max(prevChild._mountIndex, lastIndex);
86448          prevChild._mountIndex = nextIndex;
86449        } else {
86450          if (prevChild) {
86451            // Update `lastIndex` before `_mountIndex` gets unset by unmounting.
86452            lastIndex = Math.max(prevChild._mountIndex, lastIndex);
86453            // The `removedNodes` loop below will actually remove the child.
86454          }
86455          // The child must be instantiated before it's mounted.
86456          updates = enqueue(updates, this._mountChildAtIndex(nextChild, lastPlacedNode, nextIndex, transaction, context));
86457        }
86458        nextIndex++;
86459        lastPlacedNode = ReactReconciler.getNativeNode(nextChild);
86460      }
86461      // Remove children that are no longer present.
86462      for (name in removedNodes) {
86463        if (removedNodes.hasOwnProperty(name)) {
86464          updates = enqueue(updates, this._unmountChild(prevChildren[name], removedNodes[name]));
86465        }
86466      }
86467      if (updates) {
86468        processQueue(this, updates);
86469      }
86470      this._renderedChildren = nextChildren;
86471    },
86472
86473    /**
86474     * Unmounts all rendered children. This should be used to clean up children
86475     * when this component is unmounted. It does not actually perform any
86476     * backend operations.
86477     *
86478     * @internal
86479     */
86480    unmountChildren: function (safely) {
86481      var renderedChildren = this._renderedChildren;
86482      ReactChildReconciler.unmountChildren(renderedChildren, safely);
86483      this._renderedChildren = null;
86484    },
86485
86486    /**
86487     * Moves a child component to the supplied index.
86488     *
86489     * @param {ReactComponent} child Component to move.
86490     * @param {number} toIndex Destination index of the element.
86491     * @param {number} lastIndex Last index visited of the siblings of `child`.
86492     * @protected
86493     */
86494    moveChild: function (child, afterNode, toIndex, lastIndex) {
86495      // If the index of `child` is less than `lastIndex`, then it needs to
86496      // be moved. Otherwise, we do not need to move it because a child will be
86497      // inserted or moved before `child`.
86498      if (child._mountIndex < lastIndex) {
86499        return makeMove(child, afterNode, toIndex);
86500      }
86501    },
86502
86503    /**
86504     * Creates a child component.
86505     *
86506     * @param {ReactComponent} child Component to create.
86507     * @param {string} mountImage Markup to insert.
86508     * @protected
86509     */
86510    createChild: function (child, afterNode, mountImage) {
86511      return makeInsertMarkup(mountImage, afterNode, child._mountIndex);
86512    },
86513
86514    /**
86515     * Removes a child component.
86516     *
86517     * @param {ReactComponent} child Child to remove.
86518     * @protected
86519     */
86520    removeChild: function (child, node) {
86521      return makeRemove(child, node);
86522    },
86523
86524    /**
86525     * Mounts a child with the supplied name.
86526     *
86527     * NOTE: This is part of `updateChildren` and is here for readability.
86528     *
86529     * @param {ReactComponent} child Component to mount.
86530     * @param {string} name Name of the child.
86531     * @param {number} index Index at which to insert the child.
86532     * @param {ReactReconcileTransaction} transaction
86533     * @private
86534     */
86535    _mountChildAtIndex: function (child, afterNode, index, transaction, context) {
86536      var mountImage = ReactReconciler.mountComponent(child, transaction, this, this._nativeContainerInfo, context);
86537      child._mountIndex = index;
86538      return this.createChild(child, afterNode, mountImage);
86539    },
86540
86541    /**
86542     * Unmounts a rendered child.
86543     *
86544     * NOTE: This is part of `updateChildren` and is here for readability.
86545     *
86546     * @param {ReactComponent} child Component to unmount.
86547     * @private
86548     */
86549    _unmountChild: function (child, node) {
86550      var update = this.removeChild(child, node);
86551      child._mountIndex = null;
86552      return update;
86553    }
86554
86555  }
86556
86557};
86558
86559module.exports = ReactMultiChild;
86560},{"121":121,"158":158,"28":28,"33":33,"35":35,"77":77,"87":87}],77:[function(_dereq_,module,exports){
86561/**
86562 * Copyright 2013-present, Facebook, Inc.
86563 * All rights reserved.
86564 *
86565 * This source code is licensed under the BSD-style license found in the
86566 * LICENSE file in the root directory of this source tree. An additional grant
86567 * of patent rights can be found in the PATENTS file in the same directory.
86568 *
86569 * @providesModule ReactMultiChildUpdateTypes
86570 */
86571
86572
86573
86574var keyMirror = _dereq_(161);
86575
86576/**
86577 * When a component's children are updated, a series of update configuration
86578 * objects are created in order to batch and serialize the required changes.
86579 *
86580 * Enumerates all the possible types of update configurations.
86581 *
86582 * @internal
86583 */
86584var ReactMultiChildUpdateTypes = keyMirror({
86585  INSERT_MARKUP: null,
86586  MOVE_EXISTING: null,
86587  REMOVE_NODE: null,
86588  SET_MARKUP: null,
86589  TEXT_CONTENT: null
86590});
86591
86592module.exports = ReactMultiChildUpdateTypes;
86593},{"161":161}],78:[function(_dereq_,module,exports){
86594/**
86595 * Copyright 2014-present, Facebook, Inc.
86596 * All rights reserved.
86597 *
86598 * This source code is licensed under the BSD-style license found in the
86599 * LICENSE file in the root directory of this source tree. An additional grant
86600 * of patent rights can be found in the PATENTS file in the same directory.
86601 *
86602 * @providesModule ReactNativeComponent
86603 */
86604
86605
86606
86607var _assign = _dereq_(169);
86608
86609var invariant = _dereq_(158);
86610
86611var autoGenerateWrapperClass = null;
86612var genericComponentClass = null;
86613// This registry keeps track of wrapper classes around native tags.
86614var tagToComponentClass = {};
86615var textComponentClass = null;
86616
86617var ReactNativeComponentInjection = {
86618  // This accepts a class that receives the tag string. This is a catch all
86619  // that can render any kind of tag.
86620  injectGenericComponentClass: function (componentClass) {
86621    genericComponentClass = componentClass;
86622  },
86623  // This accepts a text component class that takes the text str
86623ing to be
86624  // rendered as props.
86625  injectTextComponentClass: function (componentClass) {
86626    textComponentClass = componentClass;
86627  },
86628  // This accepts a keyed object with classes as values. Each key represents a
86629  // tag. That particular tag will use this class instead of the generic one.
86630  injectComponentClasses: function (componentClasses) {
86631    _assign(tagToComponentClass, componentClasses);
86632  }
86633};
86634
86635/**
86636 * Get a composite component wrapper class for a specific tag.
86637 *
86638 * @param {ReactElement} element The tag for which to get the class.
86639 * @return {function} The React class constructor function.
86640 */
86641function getComponentClassForElement(element) {
86642  if (typeof element.type === 'function') {
86643    return element.type;
86644  }
86645  var tag = element.type;
86646  var componentClass = tagToComponentClass[tag];
86647  if (componentClass == null) {
86648    tagToComponentClass[tag] = componentClass = autoGenerateWrapperClass(tag);
86649  }
86650  return componentClass;
86651}
86652
86653/**
86654 * Get a native internal component class for a specific tag.
86655 *
86656 * @param {ReactElement} element The element to create.
86657 * @return {function} The internal class constructor function.
86658 */
86659function createInternalComponent(element) {
86660  !genericComponentClass ? "development" !== 'production' ? invariant(false, 'There is no registered component for the tag %s', element.type) : invariant(false) : void 0;
86661  return new genericComponentClass(element);
86662}
86663
86664/**
86665 * @param {ReactText} text
86666 * @return {ReactComponent}
86667 */
86668function createInstanceForText(text) {
86669  return new textComponentClass(text);
86670}
86671
86672/**
86673 * @param {ReactComponent} component
86674 * @return {boolean}
86675 */
86676function isTextComponent(component) {
86677  return component instanceof textComponentClass;
86678}
86679
86680var ReactNativeComponent = {
86681  getComponentClassForElement: getComponentClassForElement,
86682  createInternalComponent: createInternalComponent,
86683  createInstanceForText: createInstanceForText,
86684  isTextComponent: isTextComponent,
86685  injection: ReactNativeComponentInjection
86686};
86687
86688module.exports = ReactNativeComponent;
86689},{"158":158,"169":169}],79:[function(_dereq_,module,exports){
86690/**
86691 * Copyright 2013-present, Facebook, Inc.
86692 * All rights reserved.
86693 *
86694 * This source code is licensed under the BSD-style license found in the
86695 * LICENSE file in the root directory of this source tree. An additional grant
86696 * of patent rights can be found in the PATENTS file in the same directory.
86697 *
86698 * @providesModule ReactNodeTypes
86699 */
86700
86701
86702
86703var ReactElement = _dereq_(62);
86704
86705var invariant = _dereq_(158);
86706
86707var ReactNodeTypes = {
86708  NATIVE: 0,
86709  COMPOSITE: 1,
86710  EMPTY: 2,
86711
86712  getType: function (node) {
86713    if (node === null || node === false) {
86714      return ReactNodeTypes.EMPTY;
86715    } else if (ReactElement.isValidElement(node)) {
86716      if (typeof node.type === 'function') {
86717        return ReactNodeTypes.COMPOSITE;
86718      } else {
86719        return ReactNodeTypes.NATIVE;
86720      }
86721    }
86722    !false ? "development" !== 'production' ? invariant(false, 'Unexpected node: %s', node) : invariant(false) : void 0;
86723  }
86724};
86725
86726module.exports = ReactNodeTypes;
86727},{"158":158,"62":62}],80:[function(_dereq_,module,exports){
86728/**
86729 * Copyright 2015-present, Facebook, Inc.
86730 * All rights reserved.
86731 *
86732 * This source code is licensed under the BSD-style license found in the
86733 * LICENSE file in the root directory of this source tree. An additional grant
86734 * of patent rights can be found in the PATENTS file in the same directory.
86735 *
86736 * @providesModule ReactNoopUpdateQueue
86737 */
86738
86739
86740
86741var warning = _dereq_(168);
86742
86743function warnTDZ(publicInstance, callerName) {
86744  if ("development" !== 'production') {
86745    "development" !== 'production' ? warning(false, '%s(...): Can only update a mounted or mounting component. ' + 'This usually means you called %s() on an unmounted component. ' + 'This is a no-op. Please check the code for the %s component.', callerName, callerName, publicInstance.constructor && publicInstance.constructor.displayName || '') : void 0;
86746  }
86747}
86748
86749/**
86750 * This is the abstract API for an update queue.
86751 */
86752var ReactNoopUpdateQueue = {
86753
86754  /**
86755   * Checks whether or not this composite component is mounted.
86756   * @param {ReactClass} publicInstance The instance we want to test.
86757   * @return {boolean} True if mounted, false otherwise.
86758   * @protected
86759   * @final
86760   */
86761  isMounted: function (publicInstance) {
86762    return false;
86763  },
86764
86765  /**
86766   * Enqueue a callback that will be executed after all the pending updates
86767   * have processed.
86768   *
86769   * @param {ReactClass} publicInstance The instance to use as `this` context.
86770   * @param {?function} callback Called after state is updated.
86771   * @internal
86772   */
86773  enqueueCallback: function (publicInstance, callback) {},
86774
86775  /**
86776   * Forces an update. This should only be invoked when it is known with
86777   * certainty that we are **not** in a DOM transaction.
86778   *
86779   * You may want to call this when you know that some deeper aspect of the
86780   * component's state has changed but `setState` was not called.
86781   *
86782   * This will not invoke `shouldComponentUpdate`, but it will invoke
86783   * `componentWillUpdate` and `componentDidUpdate`.
86784   *
86785   * @param {ReactClass} publicInstance The instance that should rerender.
86786   * @internal
86787   */
86788  enqueueForceUpdate: function (publicInstance) {
86789    warnTDZ(publicInstance, 'forceUpdate');
86790  },
86791
86792  /**
86793   * Replaces all of the state. Always use this or `setState` to mutate state.
86794   * You should treat `this.state` as immutable.
86795   *
86796   * There is no guarantee that `this.state` will be immediately updated, so
86797   * accessing `this.state` after calling this method may return the old value.
86798   *
86799   * @param {ReactClass} publicInstance The instance that should rerender.
86800   * @param {object} completeState Next state.
86801   * @internal
86802   */
86803  enqueueReplaceState: function (publicInstance, completeState) {
86804    warnTDZ(publicInstance, 'replaceState');
86805  },
86806
86807  /**
86808   * Sets a subset of the state. This only exists because _pendingState is
86809   * internal. This provides a merging strategy that is not available to deep
86810   * properties which is confusing. TODO: Expose pendingState or don't use it
86811   * during the merge.
86812   *
86813   * @param {ReactClass} publicInstance The instance that should rerender.
86814   * @param {object} partialState Next partial state to be merged with state.
86815   * @internal
86816   */
86817  enqueueSetState: function (publicInstance, partialState) {
86818    warnTDZ(publicInstance, 'setState');
86819  }
86820};
86821
86822module.exports = ReactNoopUpdateQueue;
86823},{"168":168}],81:[function(_dereq_,module,exports){
86824/**
86825 * Copyright 2013-present, Facebook, Inc.
86826 * All rights reserved.
86827 *
86828 * This source code is licensed under the BSD-style license found in the
86829 * LICENSE file in the root directory of this source tree. An additional grant
86830 * of patent rights can be found in the PATENTS file in the same directory.
86831 *
86832 * @providesModule ReactOwner
86833 */
86834
86835
86836
86837var invariant = _dereq_(158);
86838
86839/**
86840 * ReactOwners are capable of storing references to owned components.
86841 *
86842 * All components are capable of //being// referenced by owner components, but
86843 * only ReactOwner components are capable of //referencing// owned components.
86844 * The named reference is known as a "ref".
86845 *
86846 * Refs are available when mounted and updated during reconciliation.
86847 *
86848 *   var MyComponent = React.createClass({
86849 *     render: function() {
86850 *       return (
86851 *         <div onClick={this.handleClick}>
86852 *           <CustomComponent ref="custom" />
86853 *         </div>
86854 *       );
86855 *     },
86856 *     handleClick: function() {
86857 *       this.refs.custom.handleClick();
86858 *     },
86859 *     componentDidMount: function() {
86860 *       this.refs.custom.initialize();
86861 *     }
86862 *   });
86863 *
86864 * Refs should rarely be used. When refs are used, they should only be done to
86865 * control data that is not handled by React's data flow.
86866 *
86867 * @class ReactOwner
86868 */
86869var ReactOwner = {
86870
86871  /**
86872   * @param {?object} object
86873   * @return {boolean} True if `object` is a valid owner.
86874   * @final
86875   */
86876  isValidOwner: function (object) {
86877    return !!(object && typeof object.attachRef === 'function' && typeof object.detachRef === 'function');
86878  },
86879
86880  /**
86881   * Adds a component by ref to an owner component.
86882   *
86883   * @param {ReactComponent} component Component to reference.
86884   * @param {string} ref Name by which to refer to the component.
86885   * @param {ReactOwner} owner Component on which to record the ref.
86886   * @final
86887   * @internal
86888   */
86889  addComponentAsRefTo: function (component, ref, owner) {
86890    !ReactOwner.isValidOwner(owner) ? "development" !== 'production' ? invariant(false, 'addComponentAsRefTo(...): Only a ReactOwner can have refs. You might ' + 'be adding a ref to a component that was not created inside a component\'s ' + '`render` method, or you have multiple copies of React loaded ' + '(details: https://fb.me/react-refs-must-have-owner).') : invariant(false) : void 0;
86891    owner.attachRef(ref, component);
86892  },
86893
86894  /**
86895   * Removes a component by ref from an owner component.
86896   *
86897   * @param {ReactComponent} component Component to dereference.
86898   * @param {string} ref Name of the ref to remove.
86899   * @param {ReactOwner} owner Component on which the ref is recorded.
86900   * @final
86901   * @internal
86902   */
86903  removeComponentAsRefFrom: function (component, ref, owner) {
86904    !ReactOwner.isValidOwner(owner) ? "development" !== 'production' ? invariant(false, 'removeComponentAsRefFrom(...): Only a ReactOwner can have refs. You might ' + 'be removing a ref to a component that was not created inside a component\'s ' + '`render` method, or you have multiple copies of React loaded ' + '(details: https://fb.me/react-refs-must-have-owner).') : invariant(false) : void 0;
86905    var ownerPublicInstance = owner.getPublicInstance();
86906    // Check that `component`'s owner is still alive and that `component` is still the current ref
86907    // because we do not want to detach the ref if another component stole it.
86908    if (ownerPublicInstance && ownerPublicInstance.refs[ref] === component.getPublicInstance()) {
86909      owner.detachRef(ref);
86910    }
86911  }
86912
86913};
86914
86915module.exports = ReactOwner;
86916},{"158":158}],82:[function(_dereq_,module,exports){
86917/**
86918 * Copyright 2013-present, Facebook, Inc.
86919 * All rights reserved.
86920 *
86921 * This source code is licensed under the BSD-style license found in the
86922 * LICENSE file in the root directory of this source tree. An additional grant
86923 * of patent rights can be found in the PATENTS file in the same directory.
86924 *
86925 * @providesModule ReactPerf
86926 */
86927
86928
86929
86930/**
86931 * ReactPerf is a general AOP system designed to measure performance. This
86932 * module only has the hooks: see ReactDefaultPerf for the analysis tool.
86933 */
86934
86935var ReactPerf = {
86936  /**
86937   * Boolean to enable/disable measurement. Set to false by default to prevent
86938   * accidental logging and perf loss.
86939   */
86940  enableMeasure: false,
86941
86942  /**
86943   * Holds onto the measure function in use. By default, don't measure
86944   * anything, but we'll override this if we inject a measure function.
86945   */
86946  storedMeasure: _noMeasure,
86947
86948  /**
86949   * @param {object} object
86950   * @param {string} objectName
86951   * @param {object<string>} methodNames
86952   */
86953  measureMethods: function (object, objectName, methodNames) {
86954    if ("development" !== 'production') {
86955      for (var key in methodNames) {
86956        if (!methodNames.hasOwnProperty(key)) {
86957          continue;
86958        }
86959        object[key] = ReactPerf.measure(objectName, methodNames[key], object[key]);
86960      }
86961    }
86962  },
86963
86964  /**
86965   * Use this to wrap methods you want to measure. Zero overhead in production.
86966   *
86967   * @param {string} objName
86968   * @param {string} fnName
86969   * @param {function} func
86970   * @return {function}
86971   */
86972  measure: function (objName, fnName, func) {
86973    if ("development" !== 'production') {
86974      var measuredFunc = null;
86975      var wrapper = function () {
86976        if (ReactPerf.enableMeasure) {
86977          if (!measuredFunc) {
86978            measuredFunc = ReactPerf.storedMeasure(objName, fnName, func);
86979          }
86980          return measuredFunc.apply(this, arguments);
86981        }
86982        return func.apply(this, arguments);
86983      };
86984      wrapper.displayName = objName + '_' + fnName;
86985      return wrapper;
86986    }
86987    return func;
86988  },
86989
86990  injection: {
86991    /**
86992     * @param {function} measure
86993     */
86994    injectMeasure: function (measure) {
86995      ReactPerf.storedMeasure = measure;
86996    }
86997  }
86998};
86999
87000/**
87001 * Simply passes through the measured function, without measuring it.
87002 *
87003 * @param {string} objName
87004 * @param {string} fnName
87005 * @param {function} func
87006 * @return {function}
87007 */
87008function _noMeasure(objName, fnName, func) {
87009  return func;
87010}
87011
87012module.exports = ReactPerf;
87013},{}],83:[function(_dereq_,module,exports){
87014/**
87015 * Copyright 2013-present, Facebook, Inc.
87016 * All rights reserved.
87017 *
87018 * This source code is licensed under the BSD-style license found in the
87019 * LICENSE file in the root directory of this source tree. An additional grant
87020 * of patent rights can be found in the PATENTS file in the same directory.
87021 *
87022 * @providesModule ReactPropTypeLocationNames
87023 */
87024
87025
87026
87027var ReactPropTypeLocationNames = {};
87028
87029if ("development" !== 'production') {
87030  ReactPropTypeLocationNames = {
87031    prop: 'prop',
87032    context: 'context',
87033    childContext: 'child context'
87034  };
87035}
87036
87037module.exports = ReactPropTypeLocationNames;
87038},{}],84:[function(_dereq_,module,exports){
87039/**
87040 * Copyright 2013-present, Facebook, Inc.
87041 * All rights reserved.
87042 *
87043 * This source code is licensed under the BSD-style license found in the
87044 * LICENSE file in the root directory of this source tree. An additional grant
87045 * of patent rights can be found in the PATENTS file in the same directory.
87046 *
87047 * @providesModule ReactPropTypeLocations
87048 */
87049
87050
87051
87052var keyMirror = _dereq_(161);
87053
87054var ReactPropTypeLocations = keyMirror({
87055  prop: null,
87056  context: null,
87057  childContext: null
87058});
87059
87060module.exports = ReactPropTypeLocations;
87061},{"161":161}],85:[function(_dereq_,module,exports){
87062/**
87063 * Copyright 2013-present, Facebook, Inc.
87064 * All rights reserved.
87065 *
87066 * This source code is licensed under the BSD-style license found in the
87067 * LICENSE file in the root directory of this source tree. An additional grant
87068 * of patent rights can be found in the PATENTS file in the same directory.
87069 *
87070 * @providesModule ReactPropTypes
87071 */
87072
87073
87074
87075var ReactElement = _dereq_(62);
87076var ReactPropTypeLocationNames = _dereq_(83);
87077
87078var emptyFunction = _dereq_(150);
87079var getIteratorFn = _dereq_(127);
87080
87081/**
87082 * Collection of methods that allow declaration and validation of props that are
87083 * supplied to React components. Example usage:
87084 *
87085 *   var Props = require('ReactPropTypes');
87086 *   var MyArticle = React.createClass({
87087 *     propTypes: {
87088 *       // An optional string prop named "description".
87089 *       description: Props.string,
87090 *
87091 *       // A required enum prop named "category".
87092 *       category: Props.oneOf(['News','Photos']).isRequired,
87093 *
87094 *       // A prop named "dialog" that requires an instance of Dialog.
87095 *       dialog: Props.instanceOf(Dialog).isRequired
87096 *     },
87097 *     render: function() { ... }
87098 *   });
87099 *
87100 * A more formal specification of how these methods are used:
87101 *
87102 *   type := array|bool|func|object|number|string|oneOf([...])|instanceOf(...)
87103 *   decl := ReactPropTypes.{type}(.isRequired)?
87104 *
87105 * Each and every declaration produces a function with the same signature. This
87106 * allows the creation of custom validation functions. For example:
87107 *
87108 *  var MyLink = React.createClass({
87109 *    propTypes: {
87110 *      // An optional string or URI prop named "href".
87111 *      href: function(props, propName, componentName) {
87112 *        var propValue = props[propName];
87113 *        if (propValue != null && typeof propValue !== 'string' &&
87114 *            !(propValue instanceof URI)) {
87115 *          return new Error(
87116 *            'Expected a string or an URI for ' + propName + ' in ' +
87117 *            componentName
87118 *          );
87119 *        }
87120 *      }
87121 *    },
87122 *    render: function() {...}
87123 *  });
87124 *
87125 * @internal
87126 */
87127
87128var ANONYMOUS = '<<anonymous>>';
87129
87130var ReactPropTypes = {
87131  array: createPrimitiveTypeChecker('array'),
87132  bool: createPrimitiveTypeChecker('boolean'),
87133  func: createPrimitiveTypeChecker('function'),
87134  number: createPrimitiveTypeChecker('number'),
87135  object: createPrimitiveTypeChecker('object'),
87136  string: createPrimitiveTypeChecker('string'),
87137
87138  any: createAnyTypeChecker(),
87139  arrayOf: createArrayOfTypeChecker,
87140  element: createElementTypeChecker(),
87141  instanceOf: createInstanceTypeChecker,
87142  node: createNodeChecker(),
87143  objectOf: createObjectOfTypeChecker,
87144  oneOf: createEnumTypeChecker,
87145  oneOfType: createUnionTypeChecker,
87146  shape: createShapeTypeChecker
87147};
87148
87149/**
87150 * inlined Object.is polyfill to avoid requiring consumers ship their own
87151 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
87152 */
87153/*eslint-disable no-self-compare*/
87154function is(x, y) {
87155  // SameValue algorithm
87156  if (x === y) {
87157    // Steps 1-5, 7-10
87158    // Steps 6.b-6.e: +0 != -0
87159    return x !== 0 || 1 / x === 1 / y;
87160  } else {
87161    // Step 6.a: NaN == NaN
87162    return x !== x && y !== y;
87163  }
87164}
87165/*eslint-enable no-self-compare*/
87166
87167function createChainableTypeChecker(validate) {
87168  function checkType(isRequired, props, propName, componentName, location, propFullName) {
87169    componentName = componentName || ANONYMOUS;
87170    propFullName = propFullName || propName;
87171    if (props[propName] == null) {
87172      var locationName = ReactPropTypeLocationNames[location];
87173      if (isRequired) {
87174        return new Error('Required ' + locationName + ' `' + propFullName + '` was not specified in ' + ('`' + componentName + '`.'));
87175      }
87176      return null;
87177    } else {
87178      return validate(props, propName, componentName, location, propFullName);
87179    }
87180  }
87181
87182  var chainedCheckType = checkType.bind(null, false);
87183  chainedCheckType.isRequired = checkType.bind(null, true);
87184
87185  return chainedCheckType;
87186}
87187
87188function createPrimitiveTypeChecker(expectedType) {
87189  function validate(props, propName, componentName, location, propFullName) {
87190    var propValue = props[propName];
87191    var propType = getPropType(propValue);
87192    if (propType !== expectedType) {
87193      var locationName = ReactPropTypeLocationNames[location];
87194      // `propValue` being instance of, say, date/regexp, pass the 'object'
87195      // check, but we can offer a more precise error message here rather than
87196      // 'of type `object`'.
87197      var preciseType = getPreciseType(propValue);
87198
87199      return new Error('Invalid ' + locationName + ' `' + propFullName + '` of type ' + ('`' + preciseType + '` supplied to `' + componentName + '`, expected ') + ('`' + expectedType + '`.'));
87200    }
87201    return null;
87202  }
87203  return createChainableTypeChecker(validate);
87204}
87205
87206function createAnyTypeChecker() {
87207  return createChainableTypeChecker(emptyFunction.thatReturns(null));
87208}
87209
87210function createArrayOfTypeChecker(typeChecker) {
87211  function validate(props, propName, componentName, location, propFullName) {
87212    if (typeof typeChecker !== 'function') {
87213      return new Error('Property `' + propFullName + '` of component `' + componentName + '` has invali
87213d PropType notation inside arrayOf.');
87214    }
87215    var propValue = props[propName];
87216    if (!Array.isArray(propValue)) {
87217      var locationName = ReactPropTypeLocationNames[location];
87218      var propType = getPropType(propValue);
87219      return new Error('Invalid ' + locationName + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected an array.'));
87220    }
87221    for (var i = 0; i < propValue.length; i++) {
87222      var error = typeChecker(propValue, i, componentName, location, propFullName + '[' + i + ']');
87223      if (error instanceof Error) {
87224        return error;
87225      }
87226    }
87227    return null;
87228  }
87229  return createChainableTypeChecker(validate);
87230}
87231
87232function createElementTypeChecker() {
87233  function validate(props, propName, componentName, location, propFullName) {
87234    if (!ReactElement.isValidElement(props[propName])) {
87235      var locationName = ReactPropTypeLocationNames[location];
87236      return new Error('Invalid ' + locationName + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`, expected a single ReactElement.'));
87237    }
87238    return null;
87239  }
87240  return createChainableTypeChecker(validate);
87241}
87242
87243function createInstanceTypeChecker(expectedClass) {
87244  function validate(props, propName, componentName, location, propFullName) {
87245    if (!(props[propName] instanceof expectedClass)) {
87246      var locationName = ReactPropTypeLocationNames[location];
87247      var expectedClassName = expectedClass.name || ANONYMOUS;
87248      var actualClassName = getClassName(props[propName]);
87249      return new Error('Invalid ' + locationName + ' `' + propFullName + '` of type ' + ('`' + actualClassName + '` supplied to `' + componentName + '`, expected ') + ('instance of `' + expectedClassName + '`.'));
87250    }
87251    return null;
87252  }
87253  return createChainableTypeChecker(validate);
87254}
87255
87256function createEnumTypeChecker(expectedValues) {
87257  if (!Array.isArray(expectedValues)) {
87258    return createChainableTypeChecker(function () {
87259      return new Error('Invalid argument supplied to oneOf, expected an instance of array.');
87260    });
87261  }
87262
87263  function validate(props, propName, componentName, location, propFullName) {
87264    var propValue = props[propName];
87265    for (var i = 0; i < expectedValues.length; i++) {
87266      if (is(propValue, expectedValues[i])) {
87267        return null;
87268      }
87269    }
87270
87271    var locationName = ReactPropTypeLocationNames[location];
87272    var valuesString = JSON.stringify(expectedValues);
87273    return new Error('Invalid ' + locationName + ' `' + propFullName + '` of value `' + propValue + '` ' + ('supplied to `' + componentName + '`, expected one of ' + valuesString + '.'));
87274  }
87275  return createChainableTypeChecker(validate);
87276}
87277
87278function createObjectOfTypeChecker(typeChecker) {
87279  function validate(props, propName, componentName, location, propFullName) {
87280    if (typeof typeChecker !== 'function') {
87281      return new Error('Property `' + propFullName + '` of component `' + componentName + '` has invalid PropType notation inside objectOf.');
87282    }
87283    var propValue = props[propName];
87284    var propType = getPropType(propValue);
87285    if (propType !== 'object') {
87286      var locationName = ReactPropTypeLocationNames[location];
87287      return new Error('Invalid ' + locationName + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected an object.'));
87288    }
87289    for (var key in propValue) {
87290      if (propValue.hasOwnProperty(key)) {
87291        var error = typeChecker(propValue, key, componentName, location, propFullName + '.' + key);
87292        if (error instanceof Error) {
87293          return error;
87294        }
87295      }
87296    }
87297    return null;
87298  }
87299  return createChainableTypeChecker(validate);
87300}
87301
87302function createUnionTypeChecker(arrayOfTypeCheckers) {
87303  if (!Array.isArray(arrayOfTypeCheckers)) {
87304    return createChainableTypeChecker(function () {
87305      return new Error('Invalid argument supplied to oneOfType, expected an instance of array.');
87306    });
87307  }
87308
87309  function validate(props, propName, componentName, location, propFullName) {
87310    for (var i = 0; i < arrayOfTypeCheckers.length; i++) {
87311      var checker = arrayOfTypeCheckers[i];
87312      if (checker(props, propName, componentName, location, propFullName) == null) {
87313        return null;
87314      }
87315    }
87316
87317    var locationName = ReactPropTypeLocationNames[location];
87318    return new Error('Invalid ' + locationName + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`.'));
87319  }
87320  return createChainableTypeChecker(validate);
87321}
87322
87323function createNodeChecker() {
87324  function validate(props, propName, componentName, location, propFullName) {
87325    if (!isNode(props[propName])) {
87326      var locationName = ReactPropTypeLocationNames[location];
87327      return new Error('Invalid ' + locationName + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`, expected a ReactNode.'));
87328    }
87329    return null;
87330  }
87331  return createChainableTypeChecker(validate);
87332}
87333
87334function createShapeTypeChecker(shapeTypes) {
87335  function validate(props, propName, componentName, location, propFullName) {
87336    var propValue = props[propName];
87337    var propType = getPropType(propValue);
87338    if (propType !== 'object') {
87339      var locationName = ReactPropTypeLocationNames[location];
87340      return new Error('Invalid ' + locationName + ' `' + propFullName + '` of type `' + propT
vendor: 6,165 bytes, lines 87340-87553
87340ype + '` ' + ('supplied to `' + componentName + '`, expected `object`.'));
87341    }
87342    for (var key in shapeTypes) {
87343      var checker = shapeTypes[key];
87344      if (!checker) {
87345        continue;
87346      }
87347      var error = checker(propValue, key, componentName, location, propFullName + '.' + key);
87348      if (error) {
87349        return error;
87350      }
87351    }
87352    return null;
87353  }
87354  return createChainableTypeChecker(validate);
87355}
87356
87357function isNode(propValue) {
87358  switch (typeof propValue) {
87359    case 'number':
87360    case 'string':
87361    case 'undefined':
87362      return true;
87363    case 'boolean':
87364      return !propValue;
87365    case 'object':
87366      if (Array.isArray(propValue)) {
87367        return propValue.every(isNode);
87368      }
87369      if (propValue === null || ReactElement.isValidElement(propValue)) {
87370        return true;
87371      }
87372
87373      var iteratorFn = getIteratorFn(propValue);
87374      if (iteratorFn) {
87375        var iterator = iteratorFn.call(propValue);
87376        var step;
87377        if (iteratorFn !== propValue.entries) {
87378          while (!(step = iterator.next()).done) {
87379            if (!isNode(step.value)) {
87380              return false;
87381            }
87382          }
87383        } else {
87384          // Iterator will provide entry [k,v] tuples rather than values.
87385          while (!(step = iterator.next()).done) {
87386            var entry = step.value;
87387            if (entry) {
87388              if (!isNode(entry[1])) {
87389                return false;
87390              }
87391            }
87392          }
87393        }
87394      } else {
87395        return false;
87396      }
87397
87398      return true;
87399    default:
87400      return false;
87401  }
87402}
87403
87404// Equivalent of `typeof` but with special handling for array and regexp.
87405function getPropType(propValue) {
87406  var propType = typeof propValue;
87407  if (Array.isArray(propValue)) {
87408    return 'array';
87409  }
87410  if (propValue instanceof RegExp) {
87411    // Old webkits (at least until Android 4.0) return 'function' rather than
87412    // 'object' for typeof a RegExp. We'll normalize this here so that /bla/
87413    // passes PropTypes.object.
87414    return 'object';
87415  }
87416  return propType;
87417}
87418
87419// This handles more types than `getPropType`. Only used for error messages.
87420// See `createPrimitiveTypeChecker`.
87421function getPreciseType(propValue) {
87422  var propType = getPropType(propValue);
87423  if (propType === 'object') {
87424    if (propValue instanceof Date) {
87425      return 'date';
87426    } else if (propValue instanceof RegExp) {
87427      return 'regexp';
87428    }
87429  }
87430  return propType;
87431}
87432
87433// Returns class name of the object, if any.
87434function getClassName(propValue) {
87435  if (!propValue.constructor || !propValue.constructor.name) {
87436    return ANONYMOUS;
87437  }
87438  return propValue.constructor.name;
87439}
87440
87441module.exports = ReactPropTypes;
87442},{"127":127,"150":150,"62":62,"83":83}],86:[function(_dereq_,module,exports){
87443/**
87444 * Copyright 2013-present, Facebook, Inc.
87445 * All rights reserved.
87446 *
87447 * This source code is licensed under the BSD-style license found in the
87448 * LICENSE file in the root directory of this source tree. An additional grant
87449 * of patent rights can be found in the PATENTS file in the same directory.
87450 *
87451 * @providesModule ReactReconcileTransaction
87452 */
87453
87454
87455
87456var _assign = _dereq_(169);
87457
87458var CallbackQueue = _dereq_(5);
87459var PooledClass = _dereq_(25);
87460var ReactBrowserEventEmitter = _dereq_(27);
87461var ReactInputSelection = _dereq_(70);
87462var Transaction = _dereq_(112);
87463
87464/**
87465 * Ensures that, when possible, the selection range (currently selected text
87466 * input) is not disturbed by performing the transaction.
87467 */
87468var SELECTION_RESTORATION = {
87469  /**
87470   * @return {Selection} Selection information.
87471   */
87472  initialize: ReactInputSelection.getSelectionInformation,
87473  /**
87474   * @param {Selection} sel Selection information returned from `initialize`.
87475   */
87476  close: ReactInputSelection.restoreSelection
87477};
87478
87479/**
87480 * Suppresses events (blur/focus) that could be inadvertently dispatched due to
87481 * high level DOM manipulations (like temporarily removing a text input from the
87482 * DOM).
87483 */
87484var EVENT_SUPPRESSION = {
87485  /**
87486   * @return {boolean} The enabled status of `ReactBrowserEventEmitter` before
87487   * the reconciliation.
87488   */
87489  initialize: function () {
87490    var currentlyEnabled = ReactBrowserEventEmitter.isEnabled();
87491    ReactBrowserEventEmitter.setEnabled(false);
87492    return currentlyEnabled;
87493  },
87494
87495  /**
87496   * @param {boolean} previouslyEnabled Enabled status of
87497   *   `ReactBrowserEventEmitter` before the reconciliation occurred. `close`
87498   *   restores the previous value.
87499   */
87500  close: function (previouslyEnabled) {
87501    ReactBrowserEventEmitter.setEnabled(previouslyEnabled);
87502  }
87503};
87504
87505/**
87506 * Provides a queue for collecting `componentDidMount` and
87507 * `componentDidUpdate` callbacks during the transaction.
87508 */
87509var ON_DOM_READY_QUEUEING = {
87510  /**
87511   * Initializes the internal `onDOMReady` queue.
87512   */
87513  initialize: function () {
87514    this.reactMountReady.reset();
87515  },
87516
87517  /**
87518   * After DOM is flushed, invoke all registered `onDOMReady` callbacks.
87519   */
87520  close: function () {
87521    this.reactMountReady.notifyAll();
87522  }
87523};
87524
87525/**
87526 * Executed within the scope of the `Transaction` instance. Consider these as
87527 * being member methods, but with an implied ordering while being isolated from
87528 * each other.
87529 */
87530var TRANSACTION_WRAPPERS = [SELECTION_RESTORATION, EVENT_SUPPRESSION, ON_DOM_READY_QUEUEING];
87531
87532/**
87533 * Currently:
87534 * - The order that these are listed in the transaction is critical:
87535 * - Suppresses events.
87536 * - Restores selection range.
87537 *
87538 * Future:
87539 * - Restore document/overflow scroll positions that were unintentionally
87540 *   modified via DOM insertions above the top viewport boundary.
87541 * - Implement/integrate with customized constraint based layout system and keep
87542 *   track of which dimensions must be remeasured.
87543 *
87544 * @class ReactReconcileTransaction
87545 */
87546function ReactReconcileTransaction(useCreateElement) {
87547  this.reinitializeTransaction();
87548  // Only server-side rendering really needs this option (see
87549  // `ReactServerRendering`), but server-side uses
87550  // `ReactServerRenderingTransaction` instead. This option is here so that it's
87551  // accessible and defaults to false when `ReactDOMComponent` and
87552  // `ReactTextComponent` checks it in `mountComponent`.`
87553  this.renderToStaticMarkup = false;
87554  this.reactMountReady = CallbackQueue.getPooled(null);
87555  this.useCreateElement = useCreateElement;
87556}
87557
87558var Mixin = {
87559  /**
87560   * @see Transaction
87561   * @abstract
87562   * @final
87563   * @return {array<object>} List of operation wrap procedures.
87564   *   TODO: convert to array<TransactionWrapper>
87565   */
87566  getTransactionWrappers: function () {
87567    return TRANSACTION_WRAPPERS;
87568  },
87569
87570  /**
87571   * @return {object} The queue to collect `onDOMReady` callbacks with.
87572   */
87573  getReactMountReady: function () {
87574    return this.reactMountReady;
87575  },
87576
87577  /**
87578   * Save current transaction state -- if the return value from this method is
87579   * passed to `rollback`, the transaction will be reset to that state.
87580   */
87581  checkpoint: function () {
87582    // reactMountReady is the our only stateful wrapper
87583    return this.reactMountReady.checkpoint();
87584  },
87585
87586  rollback: function (checkpoint) {
87587    this.reactMountReady.rollback(checkpoint);
87588  },
87589
87590  /**
87591   * `PooledClass` looks for this, and will invoke this before allowing this
87592   * instance to be reused.
87593   */
87594  destructor: function () {
87595    CallbackQueue.release(this.reactMountReady);
87596    this.reactMountReady = null;
87597  }
87598};
87599
87600_assign(ReactReconcileTransaction.prototype, Transaction.Mixin, Mixin);
87601
87602PooledClass.addPoolingTo(ReactReconcileTransaction);
87603
87604module.exports = ReactReconcileTransaction;
87605},{"112":112,"169":169,"25":25,"27":27,"5":5,"70":70}],87:[function(_dereq_,module,exports){
87606/**
87607 * Copyright 2013-present, Facebook, Inc.
87608 * All rights reserved.
87609 *
87610 * This source code is licensed under the BSD-style license found in the
87611 * LICENSE file in the root directory of this source tree. An additional grant
87612 * of patent rights can be found in the PATENTS file in the same directory.
87613 *
87614 * @providesModule ReactReconciler
87615 */
87616
87617
87618
87619var ReactRef = _dereq_(88);
87620var ReactInstrumentation = _dereq_(72);
87621
87622/**
87623 * Helper to call ReactRef.attachRefs with this composite component, split out
87624 * to avoid allocations in the transaction mount-ready queue.
87625 */
87626function attachRefs() {
87627  ReactRef.attachRefs(this, this._currentElement);
87628}
87629
87630var ReactReconciler = {
87631
87632  /**
87633   * Initializes the component, renders markup, and registers event listeners.
87634   *
87635   * @param {ReactComponent} internalInstance
87636   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
87637   * @param {?object} the containing native component instance
87638   * @param {?object} info about the native container
87639   * @return {?string} Rendered markup to be inserted into the DOM.
87640   * @final
87641   * @internal
87642   */
87643  mountComponent: function (internalInstance, transaction, nativeParent, nativeContainerInfo, context) {
87644    var markup = internalInstance.mountComponent(transaction, nativeParent, nativeContainerInfo, context);
87645    if (internalInstance._currentElement && internalInstance._currentElement.ref != null) {
87646      transaction.getReactMountReady().enqueue(attachRefs, internalInstance);
87647    }
87648    if ("development" !== 'production') {
87649      ReactInstrumentation.debugTool.onMountComponent(internalInstance);
87650    }
87651    return markup;
87652  },
87653
87654  /**
87655   * Returns a value that can be passed to
87656   * ReactComponentEnvironment.replaceNodeWithMarkup.
87657   */
87658  getNativeNode: function (internalInstance) {
87659    return internalInstance.getNativeNode();
87660  },
87661
87662  /**
87663   * Releases any resources allocated by `mountComponent`.
87664   *
87665   * @final
87666   * @internal
87667   */
87668  unmountComponent: function (internalInstance, safely) {
87669    ReactRef.detachRefs(internalInstance, internalInstance._currentElement);
87670    internalInstance.unmountComponent(safely);
87671    if ("development" !== 'production') {
87672      ReactInstrumentation.debugTool.onUnmountComponent(internalInstance);
87673    }
87674  },
87675
87676  /**
87677   * Update a component using a new element.
87678   *
87679   * @param {ReactComponent} internalInstance
87680   * @param {ReactElement} nextElement
87681   * @param {ReactReconcileTransaction} transaction
87682   * @param {object} context
87683   * @internal
87684   */
87685  receiveComponent: function (internalInstance, nextElement, transaction, context) {
87686    var prevElement = internalInstance._currentElement;
87687
87688    if (nextElement === prevElement && context === internalInstance._context) {
87689      // Since elements are immutable after the owner is rendered,
87690      // we can do a cheap identity compare here to determine if this is a
87691      // superfluous reconcile. It's possible for state to be mutable but such
87692      // change should trigger an update of the owner which would recreate
87693      // the element. We explicitly check for the existence of an owner since
87694      // it's possible for an element created outside a composite to be
87695      // deeply mutated and reused.
87696
87697      // TODO: Bailing out early is just a perf optimization right?
87698      // TODO: Removing the return statement should affect correctness?
87699      return;
87700    }
87701
87702    var refsChanged = ReactRef.shouldUpdateRefs(prevElement, nextElement);
87703
87704    if (refsChanged) {
87705      ReactRef.detachRefs(internalInstance, prevElement);
87706    }
87707
87708    internalInstance.receiveComponent(nextElement, transaction, context);
87709
87710    if (refsChanged && internalInstance._currentElement && internalInstance._currentElement.ref != null) {
87711      transaction.getReactMountReady().enqueue(attachRefs, internalInstance);
87712    }
87713
87714    if ("development" !== 'production') {
87715      ReactInstrumentation.debugTool.onUpdateComponent(internalInstance);
87716    }
87717  },
87718
87719  /**
87720   * Flush any dirty changes in a component.
87721   *
87722   * @param {ReactComponent} internalInstance
87723   * @param {ReactReconcileTransaction} transaction
87724   * @internal
87725   */
87726  performUpdateIfNecessary: function (internalInstance, transaction) {
87727    internalInstance.performUpdateIfNecessary(transaction);
87728    if ("development" !== 'production') {
87729      ReactInstrumentation.debugTool.onUpdateComponent(internalInstance);
87730    }
87731  }
87732
87733};
87734
87735module.exports = ReactReconciler;
87736},{"72":72,"88":88}],88:[function(_dereq_,module,exports){
87737/**
87738 * Copyright 2013-present, Facebook, Inc.
87739 * All rights reserved.
87740 *
87741 * This source code is licensed under the BSD-style license found in the
87742 * LICENSE file in the root directory of this source tree. An additional grant
87743 * of patent rights can be found in the PATENTS file in the same directory.
87744 *
87745 * @providesModule ReactRef
87746 */
87747
87748
87749
87750var ReactOwner = _dereq_(81);
87751
87752var ReactRef = {};
87753
87754function attachRef(ref, component, owner) {
87755  if (typeof ref === 'function') {
87756    ref(component.getPublicInstance());
87757  } else {
87758    // Legacy ref
87759    ReactOwner.addComponentAsRefTo(component, ref, owner);
87760  }
87761}
87762
87763function detachRef(ref, component, owner) {
87764  if (typeof ref === 'function') {
87765    ref(null);
87766  } else {
87767    // Legacy ref
87768    ReactOwner.removeComponentAsRefFrom(component, ref, owner);
87769  }
87770}
87771
87772ReactRef.attachRefs = function (instance, element) {
87773  if (element === null || element === false) {
87774    return;
87775  }
87776  var ref = element.ref;
87777  if (ref != null) {
87778    attachRef(ref, instance, element._owner);
87779  }
87780};
87781
87782ReactRef.shouldUpdateRefs = function (prevElement, nextElement) {
87783  // If either the owner or a `ref` has changed, make sure the newest owner
87784  // has stored a reference to `this`, and the previous owner (if different)
87785  // has forgotten the reference to `this`. We use the element instead
87786  // of the public this.props because the post processing cannot determine
87787  // a ref. The ref conceptually lives on the element.
87788
87789  // TODO: Should this even be possible? The owner cannot change because
87790  // it's forbidden by shouldUpdateReactComponent. The ref can change
87791  // if you swap the keys of but not the refs. Reconsider where this check
87792  // is made. It probably belongs where the key checking and
87793  // instantiateReactComponent is done.
87794
87795  var prevEmpty = prevElement === null || prevElement === false;
87796  var nextEmpty = nextElement === null || nextElement === false;
87797
87798  return(
87799    // This has a few false positives w/r/t empty components.
87800    prevEmpty || nextEmpty || nextElement._owner !== prevElement._owner || nextElement.ref !== prevElement.ref
87801  );
87802};
87803
87804ReactRef.detachRefs = function (instance, element) {
87805  if (element === null || element === false) {
87806    return;
87807  }
87808  var ref = element.ref;
87809  if (ref != null) {
87810    detachRef(ref, instance, element._owner);
87811  }
87812};
87813
87814module.exports = ReactRef;
87815},{"81":81}],89:[function(_dereq_,module,exports){
87816/**
87817 * Copyright 2014-present, Facebook, Inc.
87818 * All rights reserved.
87819 *
87820 * This source code is licensed under the BSD-style license found in the
87821 * LICENSE file in the root directory of this source tree. An additional grant
87822 * of patent rights can be found in the PATENTS file in the same directory.
87823 *
87824 * @providesModule ReactServerBatchingStrategy
87825 */
87826
87827
87828
87829var ReactServerBatchingStrategy = {
87830  isBatchingUpdates: false,
87831  batchedUpdates: function (callback) {
87832    // Don't do anything here. During the server rendering we don't want to
87833    // schedule any updates. We will simply ignore them.
87834  }
87835};
87836
87837module.exports = ReactServerBatchingStrategy;
87838},{}],90:[function(_dereq_,module,exports){
87839/**
87840 * Copyright 2013-present, Facebook, Inc.
87841 * All rights reserved.
87842 *
87843 * This source code is licensed under the BSD-style license found in the
87844 * LICENSE file in the root directory of this source tree. An additional grant
87845 * of patent rights can be found in the PATENTS file in the same directory.
87846 *
87847 * @providesModule ReactServerRendering
87848 */
87849
87850
87851var ReactDOMContainerInfo = _dereq_(41);
87852var ReactDefaultBatchingStrategy = _dereq_(58);
87853var ReactElement = _dereq_(62);
87854var ReactMarkupChecksum = _dereq_(74);
87855var ReactServerBatchingStrategy = _dereq_(89);
87856var ReactServerRenderingTransaction = _dereq_(91);
87857var ReactUpdates = _dereq_(94);
87858
87859var emptyObject = _dereq_(151);
87860var instantiateReactComponent = _dereq_(132);
87861var invariant = _dereq_(158);
87862
87863/**
87864 * @param {ReactElement} element
87865 * @return {string} the HTML markup
87866 */
87867function renderToStringImpl(element, makeStaticMarkup) {
87868  var transaction;
87869  try {
87870    ReactUpdates.injection.injectBatchingStrategy(ReactServerBatchingStrategy);
87871
87872    transaction = ReactServerRenderingTransaction.getPooled(makeStaticMarkup);
87873
87874    return transaction.perform(function () {
87875      var componentInstance = instantiateReactComponent(element);
87876      var markup = componentInstance.mountComponent(transaction, null, ReactDOMContainerInfo(), emptyObject);
87877      if (!makeStaticMarkup) {
87878        markup = ReactMarkupChecksum.addChecksumToMarkup(markup);
87879      }
87880      return markup;
87881    }, null);
87882  } finally {
87883    ReactServerRenderingTransaction.release(transaction);
87884    // Revert to the DOM batching strategy since these two renderers
87885    // currently share these stateful modules.
87886    ReactUpdates.injection.injectBatchingStrategy(ReactDefaultBatchingStrategy);
87887  }
87888}
87889
87890function renderToString(element) {
87891  !ReactElement.isValidElement(element) ? "development" !== 'production' ? invariant(false, 'renderToString(): You must pass a valid ReactElement.') : invariant(false) : void 0;
87892  return renderToStringImpl(element, false);
87893}
87894
87895function renderToStaticMarkup(element) {
87896  !ReactElement.isValidElement(element) ? "development" !== 'production' ? invariant(false, 'renderToStaticMarkup(): You must pass a valid ReactElement.') : invariant(false) : void 0;
87897  return renderToStringImpl(element, true);
87898}
87899
87900module.exports = {
87901  renderToString: renderToString,
87902  renderToStaticMarkup: renderToStaticMarkup
87903};
87904},{"132":132,"151":151,"158":158,"41":41,"58":58,"62":62,"74":74,"89":89,"91":91,"94":94}],91:[function(_dereq_,module,exports){
87905/**
87906 * Copyright 2014-present, Facebook, Inc.
87907 * All rights reserved.
87908 *
87909 * This source code is licensed under the BSD-style license found in the
87910 * LICENSE file in the root directory of this source tree. An additional grant
87911 * of patent rights can be found in the PATENTS file in the same directory.
87912 *
87913 * @providesModule ReactServerRenderingTransaction
87914 */
87915
87916
87917
87918var _assign = _dereq_(169);
87919
87920var PooledClass = _dereq_(25);
87921var Transaction = _dereq_(112);
87922
87923/**
87924 * Executed within the scope of the `Transaction` instance. Consider these as
87925 * being member methods, but with an implied ordering while being isolated from
87926 * each other.
87927 */
87928var TRANSACTION_WRAPPERS = [];
87929
87930var noopCallbackQueue = {
87931  enqueue: function () {}
87932};
87933
87934/**
87935 * @class ReactServerRenderingTransaction
87936 * @param {boolean} renderToStaticMarkup
87937 */
87938function ReactServerRenderingTransaction(renderToStaticMarkup) {
87939  this.reinitializeTransaction();
87940  this.renderToStaticMarkup = renderToStaticMarkup;
87941  this.useCreateElement = false;
87942}
87943
87944var Mixin = {
87945  /**
87946   * @see Transaction
87947   * @abstract
87948   * @final
87949   * @return {array} Empty list of operation wrap procedures.
87950   */
87951  getTransactionWrappers: function () {
87952    return TRANSACTION_WRAPPERS;
87953  },
87954
87955  /**
87956   * @return {object} The queue to collect `onDOMReady` callbacks with.
87957   */
87958  getReactMountReady: function () {
87959    return noopCallbackQueue;
87960  },
87961
87962  /**
87963   * `PooledClass` looks for this, and will invoke this before allowing this
87964   * instance to be reused.
87965   */
87966  destructor: function () {}
87967};
87968
87969_assign(ReactServerRenderingTransaction.prototype, Transaction.Mixin, Mixin);
87970
87971PooledClass.addPoolingTo(ReactServerRenderingTransaction);
87972
87973module.exports = ReactServerRenderingTransaction;
87974},{"112":112,"169":169,"25":25}],92:[function(_dereq_,module,exports){
87975/**
87976 * Copyright 2013-present, Facebook, Inc.
87977 * All rights reserved.
87978 *
87979 * This source code is licensed under the BSD-style license found in the
87980 * LICENSE file in the root directory of this source tree. An additional grant
87981 * of patent rights can be found in the PATENTS file in the same directory.
87982 *
87983 * @providesModule ReactUMDEntry
87984 */
87985
87986
87987
87988var _assign = _dereq_(169);
87989
87990var ReactDOM = _dereq_(36);
87991var ReactDOMServer = _dereq_(52);
87992var React = _dereq_(26);
87993
87994// `version` will be added here by ReactIsomorphic.
87995var ReactUMDEntry = _assign({
87996  __SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: ReactDOM,
87997  __SECRET_DOM_SERVER_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: ReactDOMServer
87998}, React);
87999
88000module.exports = ReactUMDEntry;
88001},{"169":169,"26":26,"36":36,"52":52}],93:[function(_dereq_,module,exports){
88002/**
88003 * Copyright 2015-present, Facebook, Inc.
88004 * All rights reserved.
88005 *
88006 * This source code is licensed under the BSD-style license found in the
88007 * LICENSE file in the root directory of this source tree. An additional grant
88008 * of patent rights can be found in the PATENTS file in the same directory.
88009 *
88010 * @providesModule ReactUpdateQueue
88011 */
88012
88013
88014
88015var ReactCurrentOwner = _dereq_(35);
88016var ReactInstanceMap = _dereq_(71);
88017var ReactUpdates = _dereq_(94);
88018
88019var invariant = _dereq_(158);
88020var warning = _dereq_(168);
88021
88022function enqueueUpdate(internalInstance) {
88023  ReactUpdates.enqueueUpdate(internalInstance);
88024}
88025
88026function formatUnexpectedArgument(arg) {
88027  var type = typeof arg;
88028  if (type !== 'object') {
88029    return type;
88030  }
88031  var displayName = arg.constructor && arg.constructor.name || type;
88032  var keys = Object.keys(arg);
88033  if (keys.length > 0 && keys.length < 20) {
88034    return displayName + ' (keys: ' + keys.join(', ') + ')';
88035  }
88036  return displayName;
88037}
88038
88039function getInternalInstanceReadyForUpdate(publicInstance, callerName) {
88040  var internalInstance = ReactInstanceMap.get(publicInstance);
88041  if (!internalInstance) {
88042    if ("development" !== 'production') {
88043      // Only warn when we have a callerName. Otherwise we should be silent.
88044      // We're probably calling from enqueueCallback. We don't want to warn
88045      // there because we already warned for the corresponding lifecycle method.
88046      "development" !== 'production' ? warning(!callerName, '%s(...): Can only update a mounted or mounting component. ' + 'This usually means you called %s() on an unmounted component. ' + 'This is a no-op. Please check the code for the %s component.', callerName, callerName, publicInstance.constructor.displayName) : void 0;
88047    }
88048    return null;
88049  }
88050
88051  if ("development" !== 'production') {
88052    "development" !== 'production' ? warning(ReactCurrentOwner.current == null, '%s(...): Cannot update during an existing state transition (such as ' + 'within `render` or another component\'s constructor). Render methods ' + 'should be a pure function of props and state; constructor ' + 'side-effects are an anti-pattern, but can be moved to ' + '`componentWillMount`.', callerName) : void 0;
88053  }
88054
88055  return internalInstance;
88056}
88057
88058/**
88059 * ReactUpdateQueue allows for state updates to be scheduled into a later
88060 * reconciliation step.
88061 */
88062var ReactUpdateQueue = {
88063
88064  /**
88065   * Checks whether or not this composite component is mounted.
88066   * @param {ReactClass} publicInstance The instance we want to test.
88067   * @return {boolean} True if mounted, false otherwise.
88068   * @protected
88069   * @final
88070   */
88071  isMounted: function (publicInstance) {
88072    if ("development" !== 'production') {
88073      var owner = ReactCurrentOwner.current;
88074      if (owner !== null) {
88075        "development" !== 'production' ? warning(owner._warnedAboutRefsInRender, '%s is accessing isMounted inside its render() function. ' + 'render() should be a pure function of props and state. It should ' + 'never access something that requires stale data from the previous ' + 'render, such as refs. Move this logic to componentDidMount and ' + 'componentDidUpdate instead.', owner.getName() || 'A c
88075omponent') : void 0;
88076        owner._warnedAboutRefsInRender = true;
88077      }
88078    }
88079    var internalInstance = ReactInstanceMap.get(publicInstance);
88080    if (internalInstance) {
88081      // During componentWillMount and render this will still be null but after
88082      // that will always render to something. At least for now. So we can use
88083      // this hack.
88084      return !!internalInstance._renderedComponent;
88085    } else {
88086      return false;
88087    }
88088  },
88089
88090  /**
88091   * Enqueue a callback that will be executed after all the pending updates
88092   * have processed.
88093   *
88094   * @param {ReactClass} publicInstance The instance to use as `this` context.
88095   * @param {?function} callback Called after state is updated.
88096   * @param {string} callerName Name of the calling function in the public API.
88097   * @internal
88098   */
88099  enqueueCallback: function (publicInstance, callback, callerName) {
88100    ReactUpdateQueue.validateCallback(callback, callerName);
88101    var internalInstance = getInternalInstanceReadyForUpdate(publicInstance);
88102
88103    // Previously we would throw an error if we didn't have an internal
88104    // instance. Since we want to make it a no-op instead, we mirror the same
88105    // behavior we have in other enqueue* methods.
88106    // We also need to ignore callbacks in componentWillMount. See
88107    // enqueueUpdates.
88108    if (!internalInstance) {
88109      return null;
88110    }
88111
88112    if (internalInstance._pendingCallbacks) {
88113      internalInstance._pendingCallbacks.push(callback);
88114    } else {
88115      internalInstance._pendingCallbacks = [callback];
88116    }
88117    // TODO: The callback here is ignored when setState is called from
88118    // componentWillMount. Either fix it or disallow doing so completely in
88119    // favor of getInitialState. Alternatively, we can disallow
88120    // componentWillMount during server-side rendering.
88121    enqueueUpdate(internalInstance);
88122  },
88123
88124  enqueueCallbackInternal: function (internalInstance, callback) {
88125    if (internalInstance._pendingCallbacks) {
88126      internalInstance._pendingCallbacks.push(callback);
88127    } else {
88128      internalInstance._pendingCallbacks = [callback];
88129    }
88130    enqueueUpdate(internalInstance);
88131  },
88132
88133  /**
88134   * Forces an update. This should only be invoked when it is known with
88135   * certainty that we are **not** in a DOM transaction.
88136   *
88137   * You may want to call this when you know that some deeper aspect of the
88138   * component's state has changed but `setState` was not called.
88139   *
88140   * This will not invoke `shouldComponentUpdate`, but it will invoke
88141   * `componentWillUpdate` and `componentDidUpdate`.
88142   *
88143   * @param {ReactClass} publicInstance The instance that should rerender.
88144   * @internal
88145   */
88146  enqueueForceUpdate: function (publicInstance) {
88147    var internalInstance = getInternalInstanceReadyForUpdate(publicInstance, 'forceUpdate');
88148
88149    if (!internalInstance) {
88150      return;
88151    }
88152
88153    internalInstance._pendingForceUpdate = true;
88154
88155    enqueueUpdate(internalInstance);
88156  },
88157
88158  /**
88159   * Replaces all of the state. Always use this or `setState` to mutate state.
88160   * You should treat `this.state` as immutable.
88161   *
88162   * There is no guarantee that `this.state` will be immediately updated, so
88163   * accessing `this.state` after calling this method may return the old value.
88164   *
88165   * @param {ReactClass} publicInstance The instance that should rerender.
88166   * @param {object} completeState Next state.
88167   * @internal
88168   */
88169  enqueueReplaceState: function (publicInstance, completeState) {
88170    var internalInstance = getInternalInstanceReadyForUpdate(publicInstance, 'replaceState');
88171
88172    if (!internalInstance) {
88173      return;
88174    }
88175
88176    internalInstance._pendingStateQueue = [completeState];
88177    internalInstance._pendingReplaceState = true;
88178
88179    enqueueUpdate(internalInstance);
88180  },
88181
88182  /**
88183   * Sets a subset of the state. This only exists because _pendingState is
88184   * internal. This provides a merging strategy that is not available to deep
88185   * properties which is confusing. TODO: Expose pendingState or don't use it
88186   * during the merge.
88187   *
88188   * @param {ReactClass} publicInstance The instance that should rerender.
88189   * @param {object} partialState Next partial state to be merged with state.
88190   * @internal
88191   */
88192  enqueueSetState: function (publicInstance, partialState) {
88193    var internalInstance = getInternalInstanceReadyForUpdate(publicInstance, 'setState');
88194
88195    if (!internalInstance) {
88196      return;
88197    }
88198
88199    var queue = internalInstance._pendingStateQueue || (internalInstance._pendingStateQueue = []);
88200    queue.push(partialState);
88201
88202    enqueueUpdate(internalInstance);
88203  },
88204
88205  enqueueElementInternal: function (internalInstance, newElement) {
88206    internalInstance._pendingElement = newElement;
88207    enqueueUpdate(internalInstance);
88208  },
88209
88210  validateCallback: function (callback, callerName) {
88211    !(!callback || typeof callback === 'function') ? "development" !== 'production' ? invariant(false, '%s(...): Expected the last optional `callback` argument to be a ' + 'function. Instead received: %s.', callerName, formatUnexpectedArgument(callback)) : invariant(false) : void 0;
88212  }
88213
88214};
88215
88216module.exports = ReactUpdateQueue;
88217},{"158":158,"168":168,"35":35,"71":71,"94":94}],94:[function(_dereq_,module,exports){
88218/**
88219 * Copyright 2013-present, Facebook, Inc.
88220 * All rights reserved.
88221 *
88222 * This source code is licensed under the BSD-style license found in the
88223 * LICENSE file in the root directory of this source tree. An additional grant
88224 * of patent rights can be found in the PATENTS file in the same directory.
88225 *
88226 * @providesModule ReactUpdates
88227 */
88228
88229
88230
88231var _assign = _dereq_(169);
88232
88233var CallbackQueue = _dereq_(5);
88234var PooledClass = _dereq_(25);
88235var ReactFeatureFlags = _dereq_(68);
88236var ReactPerf = _dereq_(82);
88237var ReactReconciler = _dereq_(87);
88238var Transaction = _dereq_(112);
88239
88240var invariant = _dereq_(158);
88241
88242var dirtyComponents = [];
88243var asapCallbackQueue = CallbackQueue.getPooled();
88244var asapEnqueued = false;
88245
88246var batchingStrategy = null;
88247
88248function ensureInjected() {
88249  !(ReactUpdates.ReactReconcileTransaction && batchingStrategy) ? "development" !== 'production' ? invariant(false, 'ReactUpdates: must inject a reconcile transaction class and batching ' + 'strategy') : invariant(false) : void 0;
88250}
88251
88252var NESTED_UPDATES = {
88253  initialize: function () {
88254    this.dirtyComponentsLength = dirtyComponents.length;
88255  },
88256  close: function () {
88257    if (this.dirtyComponentsLength !== dirtyComponents.length) {
88258      // Additional updates were enqueued by componentDidUpdate handlers or
88259      // similar; before our own UPDATE_QUEUEING wrapper closes, we want to run
88260      // these new updates so that if A's componentDidUpdate calls setState on
88261      // B, B will update before the callback A's updater provided when calling
88262      // setState.
88263      dirtyComponents.splice(0, this.dirtyComponentsLength);
88264      flushBatchedUpdates();
88265    } else {
88266      dirtyComponents.length = 0;
88267    }
88268  }
88269};
88270
88271var UPDATE_QUEUEING = {
88272  initialize: function () {
88273    this.callbackQueue.reset();
88274  },
88275  close: function () {
88276    this.callbackQueue.notifyAll();
88277  }
88278};
88279
88280var TRANSACTION_WRAPPERS = [NESTED_UPDATES, UPDATE_QUEUEING];
88281
88282function ReactUpdatesFlushTransaction() {
88283  this.reinitializeTransaction();
88284  this.dirtyComponentsLength = null;
88285  this.callbackQueue = CallbackQueue.getPooled();
88286  this.reconcileTransaction = ReactUpdates.ReactReconcileTransaction.getPooled(
88287  /* useCreateElement */true);
88288}
88289
88290_assign(ReactUpdatesFlushTransaction.prototype, Transaction.Mixin, {
88291  getTransactionWrappers: function () {
88292    return TRANSACTION_WRAPPERS;
88293  },
88294
88295  destructor: function () {
88296    this.dirtyComponentsLength = null;
88297    CallbackQueue.release(this.callbackQueue);
88298    this.callbackQueue = null;
88299    ReactUpdates.ReactReconcileTransaction.release(this.reconcileTransaction);
88300    this.reconcileTransaction = null;
88301  },
88302
88303  perform: function (method, scope, a) {
88304    // Essentially calls `this.reconcileTransaction.perform(method, scope, a)`
88305    // with this transaction's wrappers around it.
88306    return Transaction.Mixin.perform.call(this, this.reconcileTransaction.perform, this.reconcileTransaction, method, scope, a);
88307  }
88308});
88309
88310PooledClass.addPoolingTo(ReactUpdatesFlushTransaction);
88311
88312function batchedUpdates(callback, a, b, c, d, e) {
88313  ensureInjected();
88314  batchingStrategy.batchedUpdates(callback, a, b, c, d, e);
88315}
88316
88317/**
88318 * Array comparator for ReactComponents by mount ordering.
88319 *
88320 * @param {ReactComponent} c1 first component you're comparing
88321 * @param {ReactComponent} c2 second component you're comparing
88322 * @return {number} Return value usable by Array.prototype.sort().
88323 */
88324function mountOrderComparator(c1, c2) {
88325  return c1._mountOrder - c2._mountOrder;
88326}
88327
88328function runBatchedUpdates(transaction) {
88329  var len = transaction.dirtyComponentsLength;
88330  !(len === dirtyComponents.length) ? "development" !== 'production' ? invariant(false, 'Expected flush transaction\'s stored dirty-components length (%s) to ' + 'match dirty-components array length (%s).', len, dirtyComponents.length) : invariant(false) : void 0;
88331
88332  // Since reconciling a component higher in the owner hierarchy usually (not
88333  // always -- see shouldComponentUpdate()) will reconcile children, reconcile
88334  // them before their children by sorting the array.
88335  dirtyComponents.sort(mountOrderComparator);
88336
88337  for (var i = 0; i < len; i++) {
88338    // If a component is unmounted before pending changes apply, it will still
88339    // be here, but we assume that it has cleared its _pendingCallbacks and
88340    // that performUpdateIfNecessary is a noop.
88341    var component = dirtyComponents[i];
88342
88343    // If performUpdateIfNecessary happens to enqueue any new updates, we
88344    // shouldn't execute the callbacks until the next render happens, so
88345    // stash the callbacks first
88346    var callbacks = component._pendingCallbacks;
88347    component._pendingCallbacks = null;
88348
88349    var markerName;
88350    if (ReactFeatureFlags.logTopLevelRenders) {
88351      var namedComponent = component;
88352      // Duck type TopLevelWrapper. This is probably always true.
88353      if (component._currentElement.props === component._renderedComponent._currentElement) {
88354        namedComponent = component._renderedComponent;
88355      }
88356      markerName = 'React update: ' + namedComponent.getName();
88357      console.time(markerName);
88358    }
88359
88360    ReactReconciler.performUpdateIfNecessary(component, transaction.reconcileTransaction);
88361
88362    if (markerName) {
88363      console.timeEnd(markerName);
88364    }
88365
88366    if (callbacks) {
88367      for (var j = 0; j < callbacks.length; j++) {
88368        transaction.callbackQueue.enqueue(callbacks[j], component.getPublicInstance());
88369      }
88370    }
88371  }
88372}
88373
88374var flushBatchedUpdates = function () {
88375  // ReactUpdatesFlushTransaction's wrappers will clear the dirtyComponents
88376  // array and perform any updates enqueued by mount-ready handlers (i.e.,
88377  // componentDidUpdate) but we need to check here too in order to catch
88378  // updates enqueued by setState callbacks and asap calls.
88379  while (dirtyComponents.length || asapEnqueued) {
88380    if (dirtyComponents.length) {
88381      var transaction = ReactUpdatesFlushTransaction.getPooled();
88382      transaction.perform(runBatchedUpdates, null, transaction);
88383      ReactUpdatesFlushTransaction.release(transaction);
88384    }
88385
88386    if (asapEnqueued) {
88387      asapEnqueued = false;
88388      var queue = asapCallbackQueue;
88389      asapCallbackQueue = CallbackQueue.getPooled();
88390      queue.notifyAll();
88391      CallbackQueue.release(queue);
88392    }
88393  }
88394};
88395flushBatchedUpdates = ReactPerf.measure('ReactUpdates', 'flushBatchedUpdates', flushBatchedUpdates);
88396
88397/**
88398 * Mark a component as needing a rerender, adding an optional callback to a
88399 * list of functions which will be executed once the rerender occurs.
88400 */
88401function enqueueUpdate(component) {
88402  ensureInjected();
88403
88404  // Various parts of our code (such as ReactCompositeComponent's
88405  // _renderValidatedComponent) assume that calls to render aren't nested;
88406  // verify that that's the case. (This is called by each top-level update
88407  // function, like setProps, setState, forceUpdate, etc.; creation and
88408  // destruction of top-level components is guarded in ReactMount.)
88409
88410  if (!batchingStrategy.isBatchingUpdates) {
88411    batchingStrategy.batchedUpdates(enqueueUpdate, component);
88412    return;
88413  }
88414
88415  dirtyComponents.push(component);
88416}
88417
88418/**
88419 * Enqueue a callback to be run at the end of the current batching cycle. Throws
88420 * if no updates are currently being performed.
88421 */
88422function asap(callback, context) {
88423  !batchingStrategy.isBatchingUpdates ? "development" !== 'production' ? invariant(false, 'ReactUpdates.asap: Can\'t enqueue an asap callback in a context where' + 'updates are not being batched.') : invariant(false) : void 0;
88424  asapCallbackQueue.enqueue(callback, context);
88425  asapEnqueued = true;
88426}
88427
88428var ReactUpdatesInjection = {
88429  injectReconcileTransaction: function (ReconcileTransaction) {
88430    !ReconcileTransaction ? "development" !== 'production' ? invariant(false, 'ReactUpdates: must provide a reconcile transaction class') : invariant(false) : void 0;
88431    ReactUpdates.ReactReconcileTransaction = ReconcileTransaction;
88432  },
88433
88434  injectBatchingStrategy: function (_batchingStrategy) {
88435    !_batchingStrategy ? "development" !== 'production' ? invariant(false, 'ReactUpdates: must provide a batching strategy') : invariant(false) : void 0;
88436    !(typeof _batchingStrategy.batchedUpdates === 'function') ? "development" !== 'production' ? invariant(false, 'ReactUpdates: must provide a batchedUpdates() function') : invariant(false) : void 0;
88437    !(typeof _batchingStrategy.isBatchingUpdates === 'boolean') ? "development" !== 'production' ? invariant(false, 'ReactUpdates: must provide an isBatchingUpdates boolean attribute') : invariant(false) : void 0;
88438    batchingStrategy = _batchingStrategy;
88439  }
88440};
88441
88442var ReactUpdates = {
88443  /**
88444   * React references `ReactReconcileTransaction` using this property in order
88445   * to allow dependency injection.
88446   *
88447   * @internal
88448   */
88449  ReactReconcileTransaction: null,
88450
88451  batchedUpdates: batchedUpdates,
88452  enqueueUpdate: enqueueUpdate,
88453  flushBatchedUpdates: flushBatchedUpdates,
88454  injection: ReactUpdatesInjection,
88455  asap: asap
88456};
88457
88458module.exports = ReactUpdates;
88459},{"112":112,"158":158,"169":169,"25":25,"5":5,"68":68,"82":82,"87":87}],95:[function(_dereq_,module,exports){
88460/**
88461 * Copyright 2013-present, Facebook, Inc.
88462 * All rights reserved.
88463 *
88464 * This source code is licensed under the BSD-style license found in the
88465 * LICENSE file in the root directory of this source tree. An additional grant
88466 * of patent rights can be found in the PATENTS file in the same directory.
88467 *
88468 * @providesModule ReactVersion
88469 */
88470
88471
88472
88473module.exports = '15.0.2';
88474},{}],96:[function(_dereq_,module,exports){
88475/**
88476 * Copyright 2013-present, Facebook, Inc.
88477 * All rights reserved.
88478 *
88479 * This source code is licensed under the BSD-style license found in the
88480 * LICENSE file in the root directory of this source tree. An additional grant
88481 * of patent rights can be found in the PATENTS file in the same directory.
88482 *
88483 * @providesModule SVGDOMPropertyConfig
88484 */
88485
88486
88487
88488var NS = {
88489  xlink: 'http://www.w3.org/1999/xlink',
88490  xml: 'http://www.w3.org/XML/1998/namespace'
88491};
88492
88493// We use attributes for everything SVG so let's avoid some duplication and run
88494// code instead.
88495// The following are all specified in the HTML config already so we exclude here.
88496// - class (as className)
88497// - color
88498// - height
88499// - id
88500// - lang
88501// - max
88502// - media
88503// - method
88504// - min
88505// - name
88506// - style
88507// - target
88508// - type
88509// - width
88510var ATTRS = {
88511  accentHeight: 'accent-height',
88512  accumulate: 0,
88513  additive: 0,
88514  alignmentBaseline: 'alignment-baseline',
88515  allowReorder: 'allowReorder',
88516  alphabetic: 0,
88517  amplitude: 0,
88518  arabicForm: 'arabic-form',
88519  ascent: 0,
88520  attributeName: 'attributeName',
88521  attributeType: 'attributeType',
88522  autoReverse: 'autoReverse',
88523  azimuth: 0,
88524  baseFrequency: 'baseFrequency',
88525  baseProfile: 'baseProfile',
88526  baselineShift: 'baseline-shift',
88527  bbox: 0,
88528  begin: 0,
88529  bias: 0,
88530  by: 0,
88531  calcMode: 'calcMode',
88532  capHeight: 'cap-height',
88533  clip: 0,
88534  clipPath: 'clip-path',
88535  clipRule: 'clip-rule',
88536  clipPathUnits: 'clipPathUnits',
88537  colorInterpolation: 'color-interpolation',
88538  colorInterpolationFilters: 'color-interpolation-filters',
88539  colorProfile: 'color-profile',
88540  colorRendering: 'color-rendering',
88541  contentScriptType: 'contentScriptType',
88542  contentStyleType: 'contentStyleType',
88543  cursor: 0,
88544  cx: 0,
88545  cy: 0,
88546  d: 0,
88547  decelerate: 0,
88548  descent: 0,
88549  diffuseConstant: 'diffuseConstant',
88550  direction: 0,
88551  display: 0,
88552  divisor: 0,
88553  dominantBaseline: 'dominant-baseline',
88554  dur: 0,
88555  dx: 0,
88556  dy: 0,
88557  edgeMode: 'edgeMode',
88558  elevation: 0,
88559  enableBackground: 'enable-background',
88560  end: 0,
88561  exponent: 0,
88562  externalResourcesRequired: 'externalResourcesRequired',
88563  fill: 0,
88564  fillOpacity: 'fill-opacity',
88565  fillRule: 'fill-rule',
88566  filter: 0,
88567  filterRes: 'filterRes',
88568  filterUnits: 'filterUnits',
88569  floodColor: 'flood-color',
88570  floodOpacity: 'flood-opacity',
88571  focusable: 0,
88572  fontFamily: 'font-family',
88573  fontSize: 'font-size',
88574  fontSizeAdjust: 'font-size-adjust',
88575  fontStretch: 'font-stretch',
88576  fontStyle: 'font-style',
88577  fontVariant: 'font-variant',
88578  fontWeight: 'font-weight',
88579  format: 0,
88580  from: 0,
88581  fx: 0,
88582  fy: 0,
88583  g1: 0,
88584  g2: 0,
88585  glyphName: 'glyph-name',
88586  glyphOrientationHorizontal: 'glyph-orientation-horizontal',
88587  glyphOrientationVertical: 'glyph-orientation-vertical',
88588  glyphRef: 'glyphRef',
88589  gradientTransform: 'gradientTransform',
88590  gradientUnits: 'gradientUnits',
88591  hanging: 0,
88592  horizAdvX: 'horiz-adv-x',
88593  horizOriginX: 'horiz-origin-x',
88594  ideographic: 0,
88595  imageRendering: 'image-rendering',
88596  'in': 0,
88597  in2: 0,
88598  intercept: 0,
88599  k: 0,
88600  k1: 0,
88601  k2: 0,
88602  k3: 0,
88603  k4: 0,
88604  kernelMatrix: 'kernelMatrix',
88605  kernelUnitLength: 'kernelUnitLength',
88606  kerning: 0,
88607  keyPoints: 'keyPoints',
88608  keySplines: 'keySplines',
88609  keyTimes: 'keyTimes',
88610  lengthAdjust: 'lengthAdjust',
88611  letterSpacing: 'letter-spacing',
88612  lightingColor: 'lighting-color',
88613  limitingConeAngle: 'limitingConeAngle',
88614  local: 0,
88615  markerEnd: 'marker-end',
88616  markerMid: 'marker-mid',
88617  markerStart: 'marker-start',
88618  markerHeight: 'markerHeight',
88619  markerUnits: 'markerUnits',
88620  markerWidth: 'markerWidth',
88621  mask: 0,
88622  maskContentUnits: 'maskContentUnits',
88623  maskUnits: 'maskUnits',
88624  mathematical: 0,
88625  mode: 0,
88626  numOctaves: 'numOctaves',
88627  offset: 0,
88628  opacity: 0,
88629  operator: 0,
88630  order: 0,
88631  orient: 0,
88632  orientation: 0,
88633  origin: 0,
88634  overflow: 0,
88635  overlinePosition: 'overline-position',
88636  overlineThickness: 'overline-thickness',
88637  paintOrder: 'paint-order',
88638  panose1: 'panose-1',
88639  pathLength: 'pathLength',
88640  patternContentUnits: 'patternContentUnits',
88641  patternTransform: 'patternTransform',
88642  patternUnits: 'patternUnits',
88643  pointerEvents: 'pointer-events',
88644  points: 0,
88645  pointsAtX: 'pointsAtX',
88646  pointsAtY: 'pointsAtY',
88647  pointsAtZ: 'pointsAtZ',
88648  preserveAlpha: 'preserveAlpha',
88649  preserveAspectRatio: 'preserveAspectRatio',
88650  primitiveUnits: 'primitiveUnits',
88651  r: 0,
88652  radius: 0,
88653  refX: 'refX',
88654  refY: 'refY',
88655  renderingIntent: 'rendering-intent',
88656  repeatCount: 'repeatCount',
88657  repeatDur: 'repeatDur',
88658  requiredExtensions: 'requiredExtensions',
88659  requiredFeatures: 'requiredFeatures',
88660  restart: 0,
88661  result: 0,
88662  rotate: 0,
88663  rx: 0,
88664  ry: 0,
88665  scale: 0,
88666  seed: 0,
88667  shapeRendering: 'shape-rendering',
88668  slope: 0,
88669  spacing: 0,
88670  specularConstant: 'specularConstant',
88671  specularExponent: 'specularExponent',
88672  speed: 0,
88673  spreadMethod: 'spreadMethod',
88674  startOffset: 'startOffset',
88675  stdDeviation: 'stdDeviation',
88676  stemh: 0,
88677  stemv: 0,
88678  stitchTiles: 'stitchTiles',
88679  stopColor: 'stop-color',
88680  stopOpacity: 'stop-opacity',
88681  strikethroughPosition: 'strikethrough-position',
88682  strikethroughThickness: 'strikethrough-thickness',
88683  string: 0,
88684  stroke: 0,
88685  strokeDasharray: 'stroke-dasharray',
88686  strokeDashoffset: 'stroke-dashoffset',
88687  strokeLinecap: 'stroke-linecap',
88688  strokeLinejoin: 'stroke-linejoin',
88689  strokeMiterlimit: 'stroke-miterlimit',
88690  strokeOpacity: 'stroke-opacity',
88691  strokeWidth: 'stroke-width',
88692  surfaceScale: 'surfaceScale',
88693  systemLanguage: 'systemLanguage',
88694  tableValues: 'tableValues',
88695  targetX: 'targetX',
88696  targetY: 'targetY',
88697  textAnchor: 'text-anchor',
88698  textDecoration: 'text-decoration',
88699  textRendering: 'text-rendering',
88700  textLength: 'textLength',
88701  to: 0,
88702  transform: 0,
88703  u1: 0,
88704  u2: 0,
88705  underlinePosition: 'underline-position',
88706  underlineThickness: 'underline-thickness',
88707  unicode: 0,
88708  unicodeBidi: 'unicode-bidi',
88709  unicodeRange: 'unicode-range',
88710  unitsPerEm: 'units-per-em',
88711  vAlphabetic: 'v-alphabetic',
88712  vHanging: 'v-hanging',
88713  vIdeographic: 'v-ideographic',
88714  vMathematical: 'v-mathematical',
88715  values: 0,
88716  vectorEffect: 'vector-effect',
88717  version: 0,
88718  vertAdvY: 'vert-adv-y',
88719  vertOriginX: 'vert-origin-x',
88720  vertOriginY: 'vert-origin-y',
88721  viewBox: 'viewBox',
88722  viewTarget: 'viewTarget',
88723  visibility: 0,
88724  widths: 0,
88725  wordSpacing: 'word-spacing',
88726  writingMode: 'writing-mode',
88727  x: 0,
88728  xHeight: 'x-height',
88729  x1: 0,
88730  x2: 0,
88731  xChannelSelector: 'xChannelSelector',
88732  xlinkActuate: 'xlink:actuate',
88733  xlinkArcrole: 'xlink:arcrole',
88734  xlinkHref: 'xlink:href',
88735  xlinkRole: 'xlink:role',
88736  xlinkShow: 'xlink:show',
88737  xlinkTitle: 'xlink:title',
88738  xlinkType: 'xlink:type',
88739  xmlBase: 'xml:base',
88740  xmlLang: 'xml:lang',
88741  xmlSpace: 'xml:space',
88742  y: 0,
88743  y1: 0,
88744  y2: 0,
88745  yChannelSelector: 'yChannelSelector',
88746  z: 0,
88747  zoomAndPan: 'zoomAndPan'
88748};
88749
88750var SVGDOMPropertyConfig = {
88751  Properties: {},
88752  DOMAttributeNamespaces: {
88753    xlinkActuate: NS.xlink,
88754    xlinkArcrole: NS.xlink,
88755    xlinkHref: NS.xlink,
88756    xlinkRole: NS.xlink,
88757    xlinkShow: NS.xlink,
88758    xlinkTitle: NS.xlink,
88759    xlinkType: NS.xlink,
88760    xmlBase: NS.xml,
88761    xmlLang: NS.xml,
88762    xmlSpace: NS.xml
88763  },
88764  DOMAttributeNames: {}
88765};
88766
88767Object.keys(ATTRS).forEach(function (key) {
88768  SVGDOMPropertyConfig.Properties[key] = 0;
88769  if (ATTRS[key]) {
88770    SVGDOMPropertyConfig.DOMAttributeNames[key] = ATTRS[key];
88771  }
88772});
88773
88774module.exports = SVGDOMPropertyConfig;
88775},{}],97:[function(_dereq_,module,exports){
88776/**
88777 * Copyright 2013-present, Facebook, Inc.
88778 * All rights reserved.
88779 *
88780 * This source code is licensed under the BSD-style license found in the
88781 * LICENSE file in the root directory of this source tree. An additional grant
88782 * of patent rights can be found in the PATENTS file in the same directory.
88783 *
88784 * @providesModule SelectEventPlugin
88785 */
88786
88787
88788
88789var EventConstants = _dereq_(16);
88790var EventPropagators = _dereq_(20);
88791var ExecutionEnvironment = _dereq_(144);
88792var ReactDOMComponentTree = _dereq_(40);
88793var ReactInputSelection = _dereq_(70);
88794var SyntheticEvent = _dereq_(103);
88795
88796var getActiveElement = _dereq_(153);
88797var isTextInputElement = _dereq_(134);
88798var keyOf = _dereq_(162);
88799var shallowEqual = _dereq_(167);
88800
88801var topLevelTypes = EventConstants.topLevelTypes;
88802
88803var skipSelectionChangeEvent = ExecutionEnvironment.canUseDOM && 'documentMode' in document && document.documentMode <= 11;
88804
88805var eventTypes = {
88806  select: {
88807    phasedRegistrationNames: {
88808      bubbled: keyOf({ onSelect: null }),
88809      captured: keyOf({ onSelectCapture: null })
88810    },
88811    dependencies: [topLevelTypes.topBlur, topLevelTypes.topContextMenu, topLevelTypes.topFocus, topLevelTypes.topKeyDown, topLevelTypes.topMouseDown, topLevelTypes.topMouseUp, topLevelTypes.topSelectionChange]
88812  }
88813};
88814
88815var activeElement = null;
88816var activeElementInst = null;
88817var lastSelection = null;
88818var mouseDown = false;
88819
88820// Track whether a listener exists for this plugin. If none exist, we do
88821// not extract events. See #3639.
88822var hasListener = false;
88823var ON_SELECT_KEY = keyOf({ onSelect: null });
88824
88825/**
88826 * Get an object which is a unique representation of the current selection.
88827 *
88828 * The return value will not be consistent across nodes or browsers, but
88829 * two identical selections on the same node will return identical objects.
88830 *
88831 * @param {DOMElement} node
88832 * @return {object}
88833 */
88834function getSelection(node) {
88835  if ('selectionStart' in node && ReactInputSelection.hasSelectionCapabilities(node)) {
88836    return {
88837      start: node.selectionStart,
88838      end: node.selectionEnd
88839    };
88840  } else if (window.getSelection) {
88841    var selection = window.getSelection();
88842    return {
88843      anchorNode: selection.anchorNode,
88844      anchorOffset: selection.anchorOffset,
88845      focusNode: selection.focusNode,
88846      focusOffset: selection.focusOffset
88847    };
88848  } else if (document.selection) {
88849    var range = document.selection.createRange();
88850    return {
88851      parentElement: range.parentElement(),
88852      text: range.text,
88853      top: range.boundingTop,
88854      left: range.boundingLeft
88855    };
88856  }
88857}
88858
88859/**
88860 * Poll selection to see whether it's changed.
88861 *
88862 * @param {object} nativeEvent
88863 * @return {?SyntheticEvent}
88864 */
88865function constructSelectEvent(nativeEvent, nativeEventTarget) {
88866  // Ensure we have the right element, and that the user is not dragging a
88867  // selection (this matches native `select` event behavior). In HTML5, select
88868  // fires only on input and textarea thus if there's no focused element we
88869  // won't dispatch.
88870  if (mouseDown || activeElement == null || activeElement !== getActiveElement()) {
88871    return null;
88872  }
88873
88874  // Only fire when selection has actually changed.
88875  var currentSelection = getSelection(activeElement);
88876  if (!lastSelection || !shallowEqual(lastSelection, currentSelection)) {
88877    lastSelection = currentSelection;
88878
88879    var syntheticEvent = SyntheticEvent.getPooled(eventTypes.select, activeElementInst, nativeEvent, nativeEventTarget);
88880
88881    syntheticEvent.type = 'select';
88882    syntheticEvent.target = activeElement;
88883
88884    EventPropagators.accumulateTwoPhaseDispatches(syntheticEvent);
88885
88886    return syntheticEvent;
88887  }
88888
88889  return null;
88890}
88891
88892/**
88893 * This plugin creates an `onSelect` event that normalizes select events
88894 * across form elements.
88895 *
88896 * Supported elements are:
88897 * - input (see `isTextInputElement`)
88898 * - textarea
88899 * - contentEditable
88900 *
88901 * This differs from native browser implementations in the following ways:
88902 * - Fires on contentEditable fields as well as inputs.
88903 * - Fires for collapsed selection.
88904 * - Fires after user input.
88905 */
88906var SelectEventPlugin = {
88907
88908  eventTypes: eventTypes,
88909
88910  extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
88911    if (!hasListener) {
88912      return null;
88913    }
88914
88915    var targetNode = targetInst ? ReactDOMComponentTree.getNodeFromInstance(targetInst) : window;
88916
88917    switch (topLevelType) {
88918      // Track the input node that has focus.
88919      case topLevelTypes.topFocus:
88920        if (isTextInputElement(targetNode) || targetNode.contentEditable === 'true') {
88921          activeElement = targetNode;
88922          activeElementInst = targetInst;
88923          lastSelection = null;
88924        }
88925        break;
88926      case topLevelTypes.topBlur:
88927        activeElement = null;
88928        activeElementInst = null;
88929        lastSelection = null;
88930        break;
88931
88932      // Don't fire the event while the user is dragging. This matches the
88933      // semantics of the native select event.
88934      case topLevelTypes.topMouseDown:
88935        mouseDown = true;
88936        break;
88937      case topLevelTypes.topContextMenu:
88938      case topLevelTypes.topMouseUp:
88939        mouseDown = false;
88940        return constructSelectEvent(nativeEvent, nativeEventTarget);
88941
88942      // Chrome and IE fire non-standard event when selection is changed (and
88943      // sometimes when it hasn't). IE's event fires out of order with respect
88944      // to key and input events on deletion, so we discard it.
88945      //
88946      // Firefox doesn't support selectionchange, so check selection status
88947      // after each key entry. The selection changes after keydown and before
88948      // keyup, but we check on keydown as well in the case of holding down a
88949      // key, when multiple keydown events are fired but only one keyup is.
88950      // This is also our approach for IE handling, for the reason above.
88951      case topLevelTypes.topSelectionChange:
88952        if (skipSelectionChangeEvent) {
88953          break;
88954        }
88955      // falls through
88956      case topLevelTypes.topKeyDown:
88957      case topLevelTypes.topKeyUp:
88958        return constructSelectEvent(nativeEvent, nativeEventTarget);
88959    }
88960
88961    return null;
88962  },
88963
88964  didPutListener: function (inst, registrationName, listener) {
88965    if (registrationName === ON_SELECT_KEY) {
88966      hasListener = true;
88967    }
88968  }
88969};
88970
88971module.exports = SelectEventPlugin;
88972},{"103":103,"134":134,"144":144,"153":153,"16":16,"162":162,"167":167,"20":20,"40":40,"70":70}],98:[function(_dereq_,module,exports){
88973/**
88974 * Copyright 2013-present, Facebook, Inc.
88975 * All rights reserved.
88976 *
88977 * This source code is licensed under the BSD-style license found in the
88978 * LICENSE file in the root directory of this source tree. An additional grant
88979 * of patent rights can be found in the PATENTS file in the same directory.
88980 *
88981 * @providesModule SimpleEventPlugin
88982 */
88983
88984
88985
88986var EventConstants = _dereq_(16);
88987var EventListener = _dereq_(143);
88988var EventPropagators = _dereq_(20);
88989var ReactDOMComponentTree = _dereq_(40);
88990var SyntheticAnimationEvent = _dereq_(99);
88991var SyntheticClipboardEvent = _dereq_(100);
88992var SyntheticEvent = _dereq_(103);
88993var SyntheticFocusEvent = _dereq_(104);
88994var SyntheticKeyboardEvent = _dereq_(106);
88995var SyntheticMouseEvent = _dereq_(107);
88996var SyntheticDragEvent = _dereq_(102);
88997var SyntheticTouchEvent = _dereq_(108);
88998var SyntheticTransitionEvent = _dereq_(109);
88999var SyntheticUIEvent = _dereq_(110);
89000var SyntheticWheelEvent = _dereq_(111);
89001
89002var emptyFunction = _dereq_(150);
89003var getEventCharCode = _dereq_(123);
89004var invariant = _dereq_(158);
89005var keyOf = _dereq_(162);
89006
89007var topLevelTypes = EventConstants.topLevelTypes;
89008
89009var eventTypes = {
89010  abort: {
89011    phasedRegistrationNames: {
89012      bubbled: keyOf({ onAbort: true }),
89013      captured: keyOf({ onAbortCapture: true })
89014    }
89015  },
89016  animationEnd: {
89017    phasedRegistrationNames: {
89018      bubbled: keyOf({ onAnimationEnd: true }),
89019      captured: keyOf({ onAnimationEndCapture: true })
89020    }
89021  },
89022  animationIteration: {
89023    phasedRegistrationNames: {
89024      bubbled: keyOf({ onAnimationIteration: true }),
89025      captured: keyOf({ onAnimationIterationCapture: true })
89026    }
89027  },
89028  animationStart: {
89029    phasedRegistrationNames: {
89030      bubbled: keyOf({ onAnimationStart: true }),
89031      captured: keyOf({ onAnimationStartCapture: true })
89032    }
89033  },
89034  blur: {
89035    phasedRegistrationNames: {
89036      bubbled: keyOf({ onBlur: true }),
89037      captured: keyOf({ onBlurCapture: true })
89038    }
89039  },
89040  canPlay: {
89041    phasedRegistrationNames: {
89042      bubbled: keyOf({ onCanPlay: true }),
89043      captured: keyOf({ onCanPlayCapture: true })
89044    }
89045  },
89046  canPlayThrough: {
89047    phasedRegistrationNames: {
89048      bubbled: keyOf({ onCanPlayThrough: true }),
89049      captured: keyOf({ onCanPlayThroughCapture: true })
89050    }
89051  },
89052  click: {
89053    phasedRegistrationNames: {
89054      bubbled: keyOf({ onClick: true }),
89055      captured: keyOf({ onClickCapture: true })
89056    }
89057  },
89058  contextMenu: {
89059    phasedRegistrationNames: {
89060      bubbled: keyOf({ onContextMenu: true }),
89061      captured: keyOf({ onContextMenuCapture: true })
89062    }
89063  },
89064  copy: {
89065    phasedRegistrationNames: {
89066      bubbled: keyOf({ onCopy: true }),
89067      captured: keyOf({ onCopyCapture: true })
89068    }
89069  },
89070  cut: {
89071    phasedRegistrationNames: {
89072      bubbled: keyOf({ onCut: true }),
89073      captured: keyOf({ onCutCapture: true })
89074    }
89075  },
89076  doubleClick: {
89077    phasedRegistrationNames: {
89078      bubbled: keyOf({ onDoubleClick: true }),
89079      captured: keyOf({ onDoubleClickCapture: true })
89080    }
89081  },
89082  drag: {
89083    phasedRegistrationNames: {
89084      bubbled: keyOf({ onDrag: true }),
89085      captured: keyOf({ onDragCapture: true })
89086    }
89087  },
89088  dragEnd: {
89089    phasedRegistrationNames: {
89090      bubbled: keyOf({ onDragEnd: true }),
89091      captured: keyOf({ onDragEndCapture: true })
89092    }
89093  },
89094  dragEnter: {
89095    phasedRegistrationNames: {
89096      bubbled: keyOf({ onDragEnter: true }),
89097      captured: keyOf({ onDragEnterCapture: true })
89098    }
89099  },
89100  dragExit: {
89101    phasedRegistrationNames: {
89102      bubbled: keyOf({ onDragExit: true }),
89103      captured: keyOf({ onDragExitCapture: true })
89104    }
89105  },
89106  dragLeave: {
89107    phasedRegistrationNames: {
89108      bubbled: keyOf({ onDragLeave: true }),
89109      captured: keyOf({ onDragLeaveCapture: true })
89110    }
89111  },
89112  dragOver: {
89113    phasedRegistrationNames: {
89114      bubbled: keyOf({ onDragOver: true }),
89115      captured: keyOf({ onDragOverCapture: true })
89116    }
89117  },
89118  dragStart: {
89119    phasedRegistrationNames: {
89120      bubbled: keyOf({ onDragStart: true }),
89121      captured: keyOf({ onDragStartCapture: true })
89122    }
89123  },
89124  drop: {
89125    phasedRegistrationNames: {
89126      bubbled: keyOf({ onDrop: true }),
89127      captured: keyOf({ onDropCapture: true })
89128    }
89129  },
89130  durationChange: {
89131    phasedRegistrationNames: {
89132      bubbled: keyOf({ onDurationChange: true }),
89133      captured: keyOf({ onDurationChangeCapture: true })
89134    }
89135  },
89136  emptied: {
89137    phasedRegistrationNames: {
89138      bubbled: keyOf({ onEmptied: true }),
89139      captured: keyOf({ onEmptiedCapture: true })
89140    }
89141  },
89142  encrypted: {
89143    phasedRegistrationNames: {
89144      bubbled: keyOf({ onEncrypted: true }),
89145      captured: keyOf({ onEncryptedCapture: true })
89146    }
89147  },
89148  ended: {
89149    phasedRegistrationNames: {
89150      bubbled: keyOf({ onEnded: true }),
89151      captured: keyOf({ onEndedCapture: true })
89152    }
89153  },
89154  error: {
89155    phasedRegistrationNames: {
89156      bubbled: keyOf({ onError: true }),
89157      captured: keyOf({ onErrorCapture: true })
89158    }
89159  },
89160  focus: {
89161    phasedRegistrationNames: {
89162      bubbled: keyOf({ onFocus: true }),
89163      captured: keyOf({ onFocusCapture: true })
89164    }
89165  },
89166  input: {
89167    phasedRegistrationNames: {
89168      bubbled: keyOf({ onInput: true }),
89169      captured: keyOf({ onInputCapture: true })
89170    }
89171  },
89172  invalid: {
89173    phasedRegistrationNames: {
89174      bubbled: keyOf({ onInvalid: true }),
89175      captured: keyOf({ onInvalidCapture: true })
89176    }
89177  },
89178  keyDown: {
89179    phasedRegistrationNames: {
89180      bubbled: keyOf({ onKeyDown: true }),
89181      captured: keyOf({ onKeyDownCapture: true })
89182    }
89183  },
89184  keyPress: {
89185    phasedRegistrationNames: {
89186      bubbled: keyOf({ onKeyPress: true }),
89187      captured: keyOf({ onKeyPressCapture: true })
89188    }
89189  },
89190  keyUp: {
89191    phasedRegistrationNames: {
89192      bubbled: keyOf({ onKeyUp: true }),
89193      captured: keyOf({ onKeyUpCapture: true })
89194    }
89195  },
89196  load: {
89197    phasedRegistrationNames: {
89198      bubbled: keyOf({ onLoad: true }),
89199      captured: keyOf({ onLoadCapture: true })
89200    }
89201  },
89202  loadedData: {
89203    phasedRegistrationNames: {
89204      bubbled: keyOf({ onLoadedData: true }),
89205      captured: keyOf({ onLoadedDataCapture: true })
89206    }
89207  },
89208  loadedMetadata: {
89209    phasedRegistrationNames: {
89210      bubbled: keyOf({ onLoadedMetadata: true }),
89211      captured: keyOf({ onLoadedMetadataCapture: true })
89212    }
89213  },
89214  loadStart: {
89215    phasedRegistrationNames: {
89216      bubbled: keyOf({ onLoadStart: true }),
89217      captured: keyOf({ onLoadStartCapture: true })
89218    }
89219  },
89220  // Note: We do not allow listening to mouseOver events. Instead, use the
89221  // onMouseEnter/onMouseLeave created by `EnterLeaveEventPlugin`.
89222  mouseDown: {
89223    phasedRegistrationNames: {
89224      bubbled: keyOf({ onMouseDown: true }),
89225      captured: keyOf({ onMouseDownCapture: true })
89226    }
89227  },
89228  mouseMove: {
89229    phasedRegistrationNames: {
89230      bubbled: keyOf({ onMouseMove: true }),
89231      captured: keyOf({ onMouseMoveCapture: true })
89232    }
89233  },
89234  mouseOut: {
89235    phasedRegistrationNames: {
89236      bubbled: keyOf({ onMouseOut: true }),
89237      captured: keyOf({ onMouseOutCapture: true })
89238    }
89239  },
89240  mouseOver: {
89241    phasedRegistrationNames: {
89242      bubbled: keyOf({ onMouseOver: true }),
89243      captured: keyOf({ onMouseOverCapture: true })
89244    }
89245  },
89246  mouseUp: {
89247    phasedRegistrationNames: {
89248      bubbled: keyOf({ onMouseUp: true }),
89249      captured: keyOf({ onMouseUpCapture: true })
89250    }
89251  },
89252  paste: {
89253    phasedRegistrationNames: {
89254      bubbled: keyOf({ onPaste: true }),
89255      captured: keyOf({ onPasteCapture: true })
89256    }
89257  },
89258  pause: {
89259    phasedRegistrationNames: {
89260      bubbled: keyOf({ onPause: true }),
89261      captured: keyOf({ onPauseCapture: true })
89262    }
89263  },
89264  play: {
89265    phasedRegistrationNames: {
89266      bubbled: keyOf({ onPlay: true }),
89267      captured: keyOf({ onPlayCapture: true })
89268    }
89269  },
89270  playing: {
89271    phasedRegistrationNames: {
89272      bubbled: keyOf({ onPlaying: true }),
89273      captured: keyOf({ onPlayingCapture: true })
89274    }
89275  },
89276  progress: {
89277    phasedRegistrationNames: {
89278      bubbled: keyOf({ onProgress: true }),
89279      captured: keyOf({ onProgressCapture: true })
89280    }
89281  },
89282  rateChange: {
89283    phasedRegistrationNames: {
89284      bubbled: keyOf({ onRateChange: true }),
89285      captured: keyOf({ onRateChangeCapture: true })
89286    }
89287  },
89288  reset: {
89289    phasedRegistrationNames: {
89290      bubbled: keyOf({ onReset: true }),
89291      captured: keyOf({ onResetCapture: true })
89292    }
89293  },
89294  scroll: {
89295    phasedRegistrationNames: {
89296      bubbled: keyOf({ onScroll: true }),
89297      captured: keyOf({ onScrollCapture: true })
89298    }
89299  },
89300  seeked: {
89301    phasedRegistrationNames: {
89302      bubbled: keyOf({ onSeeked: true }),
89303      captured: keyOf({ onSeekedCapture: true })
89304    }
89305  },
89306  seeking: {
89307    phasedRegistrationNames: {
89308      bubbled: keyOf({ onSeeking: true }),
89309      captured: keyOf({ onSeekingCapture: true })
89310    }
89311  },
89312  stalled: {
89313    phasedRegistrationNames: {
89314      bubbled: keyOf({ onStalled: true }),
89315      captured: keyOf({ onStalledCapture: true })
89316    }
89317  },
89318  submit: {
89319    phasedRegistrationNames: {
89320      bubbled: keyOf({ onSubmit: true }),
89321      captured: keyOf({ onSubmitCapture: true })
89322    }
89323  },
89324  suspend: {
89325    phasedRegistrationNames: {
89326      bubbled: keyOf({ onSuspend: true }),
89327      captured: keyOf({ onSuspendCapture: true })
89328    }
89329  },
89330  timeUpdate: {
89331    phasedRegistrationNames: {
89332      bubbled: keyOf({ onTimeUpdate: true }),
89333      captured: keyOf({ onTimeUpdateCapture: true })
89334    }
89335  },
89336  touchCancel: {
89337    phasedRegistrationNames: {
89338      bubbled: keyOf({ onTouchCancel: true }),
89339      captured: keyOf({ onTouchCancelCapture: true })
89340    }
89341  },
89342  touchEnd: {
89343    phasedRegistrationNames: {
89344      bubbled: keyOf({ onTouchEnd: true }),
89345      captured: keyOf({ onTouchEndCapture: true })
89346    }
89347  },
89348  touchMove: {
89349    phasedRegistrationNames: {
89350      bubbled: keyOf({ onTouchMove: true }),
89351      captured: keyOf({ onTouchMoveCapture: true })
89352    }
89353  },
89354  touchStart: {
89355    phasedRegistrationNames: {
89356      bubbled: keyOf({ onTouchStart: true }),
89357      captured: keyOf({ onTouchStartCapture: true })
89358    }
89359  },
89360  transitionEnd: {
89361    phasedRegistrationNames: {
89362      bubbled: keyOf({ onTransitionEnd: true }),
89363      captured: keyOf({ onTransitionEndCapture: true })
89364    }
89365  },
89366  volumeChange: {
89367    phasedRegistrationNames: {
89368      bubbled: keyOf({ onVolumeChange: true }),
89369      captured: keyOf({ onVolumeChangeCapture: true })
89370    }
89371  },
89372  waiting: {
89373    phasedRegistrationNames: {
89374      bubbled: keyOf({ onWaiting: true }),
89375      captured: keyOf({ onWaitingCapture: true })
89376    }
89377  },
89378  wheel: {
89379    phasedRegistrationNames: {
89380      bubbled: keyOf({ onWheel: true }),
89381      captured: keyOf({ onWheelCapture: true })
89382    }
89383  }
89384};
89385
89386var topLevelEventsToDispatchConfig = {
89387  topAbort: eventTypes.abort,
89388  topAnimationEnd: eventTypes.animationEnd,
89389  topAnimationIteration: eventTypes.animationIteration,
89390  topAnimationStart: eventTypes.animationStart,
89391  topBlur: eventTypes.blur,
89392  topCanPlay: eventTypes.canPlay,
89393  topCanPlayThrough: eventTypes.canPlayThrough,
89394  topClick: eventTypes.click,
89395  topContextMenu: eventTypes.contextMenu,
89396  topCopy: eventTypes.copy,
89397  topCut: eventTypes.cut,
89398  topDoubleClick: eventTypes.doubleClick,
89399  topDrag: eventTypes.drag,
89400  topDragEnd: eventTypes.dragEnd,
89401  topDragEnter: eventTypes.dragEnter,
89402  topDragExit: eventTypes.dragExit,
89403  topDragLeave: eventTypes.dragLeave,
89404  topDragOver: eventTypes.dragOver,
89405  topDragStart: eventTypes.dragStart,
89406  topDrop: eventTypes.drop,
89407  topDurationChange: eventTypes.durationChange,
89408  topEmptied: eventTypes.emptied,
89409  topEncrypted: eventTypes.encrypted,
89410  topEnded: eventTypes.ended,
89411  topError: eventTypes.error,
89412  topFocus: eventTypes.focus,
89413  topInput: eventTypes.input,
89414  topInvalid: eventTypes.invalid,
89415  topKeyDown: eventTypes.keyDown,
89416  topKeyPress: eventTypes.keyPress,
89417  topKeyUp: eventTypes.keyUp,
89418  topLoad: eventTypes.load,
89419  topLoadedData: eventTypes.loadedData,
89420  topLoadedMetadata: eventTypes.loadedMetadata,
89421  topLoadStart: eventTypes.loadStart,
89422  topMouseDown: eventTypes.mouseDown,
89423  topMouseMove: eventTypes.mouseMove,
89424  topMouseOut: eventTypes.mouseOut,
89425  topMouseOver: eventTypes.mouseOver,
89426  topMouseUp: eventTypes.mouseUp,
89427  topPaste: eventTypes.paste,
89428  topPause: eventTypes.pause,
89429  topPlay: eventTypes.play,
89430  topPlaying: eventTypes.playing,
89431  topProgress: eventTypes.progress,
89432  topRateChange: eventTypes.rateChange,
89433  topReset: eventTypes.reset,
89434  topScroll: eventTypes.scroll,
89435  topSeeked: eventTypes.seeked,
89436  topSeeking: eventTypes.seeking,
89437  topStalled: eventTypes.stalled,
89438  topSubmit: eventTypes.submit,
89439  topSuspend: eventTypes.suspend,
89440  topTimeUpdate: eventTypes.timeUpdate,
89441  topTouchCancel: eventTypes.touchCancel,
89442  topTouchEnd: eventTypes.touchEnd,
89443  topTouchMove: eventTypes.touchMove,
89444  topTouchStart: eventTypes.touchStart,
89445  topTransitionEnd: eventTypes.transitionEnd,
89446  topVolumeChange: eventTypes.volumeChange,
89447  topWaiting: eventTypes.waiting,
89448  topWheel: eventTypes.wheel
89449};
89450
89451for (var type in topLevelEventsToDispatchConfig) {
89452  topLevelEventsToDispatchConfig[type].dependencies = [type];
89453}
89454
89455var ON_CLICK_KEY = keyOf({ onClick: null });
89456var onClickListeners = {};
89457
89458var SimpleEventPlugin = {
89459
89460  eventTypes: eventTypes,
89461
89462  extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
89463    var dispatchConfig = topLevelEventsToDispatchConfig[topLevelType];
89464    if (!dispatchConfig) {
89465      return null;
89466    }
89467    var EventConstructor;
89468    switch (topLevelType) {
89469      case topLevelTypes.topAbort:
89470      case topLevelTypes.topCanPlay:
89471      case topLevelTypes.topCanPlayThrough:
89472      case topLevelTypes.topDurationChange:
89473      case topLevelTypes.topEmptied:
89474      case topLevelTypes.topEncrypted:
89475      case topLevelTypes.topEnded:
89476      case topLevelTypes.topError:
89477      case topLevelTypes.topInput:
89478      case topLevelTypes.topInvalid:
89479      case topLevelTypes.topLoad:
89480      case topLevelTypes.topLoadedData:
89481      case topLevelTypes.topLoadedMetadata:
89482      case topLevelTypes.topLoadStart:
89483      case topLevelTypes.topPause:
89484      case topLevelTypes.topPlay:
89485      case topLevelTypes.topPlaying:
89486      case topLevelTypes.topProgress:
89487      case topLevelTypes.topRateChange:
89488      case topLevelTypes.topReset:
89489      case topLevelTypes.topSeeked:
89490      case topLevelTypes.topSeeking:
89491      case topLevelTypes.topStalled:
89492      case topLevelTypes.topSubmit:
89493      case topLevelTypes.topSuspend:
89494      case topLevelTypes.topTimeUpdate:
89495      case topLevelTypes.topVolumeChange:
89496      case topLevelTypes.topWaiting:
89497        // HTML Events
89498        // @see http://www.w3.org/TR/html5/index.html#events-0
89499        EventConstructor = SyntheticEvent;
89500        break;
89501      case topLevelTypes.topKeyPress:
89502        // Firefox creates a keypress event for function keys too. This removes
89503        // the unwanted keypress events. Enter is however both printable and
89504        // non-printable. One would expect Tab to be as well (but it isn't).
89505        if (getEventCharCode(nativeEvent) === 0) {
89506          return null;
89507        }
89508      /* falls through */
89509      case topLevelTypes.topKeyDown:
89510      case topLevelTypes.topKeyUp:
89511        EventConstructor = SyntheticKeyboardEvent;
89512        break;
89513      case topLevelTypes.topBlur:
89514      case topLevelTypes.topFocus:
89515        EventConstructor = SyntheticFocusEvent;
89516        break;
89517      case topLevelTypes.topClick:
89518        // Firefox creates a click event on right mouse clicks. This removes the
89519        // unwanted click events.
89520        if (nativeEvent.button === 2) {
89521          return null;
89522        }
89523      /* falls through */
89524      case topLevelTypes.topContextMenu:
89525      case topLevelTypes.topDoubleClick:
89526      case topLevelTypes.topMouseDown:
89527      case topLevelTypes.topMouseMove:
89528      case topLevelTypes.topMouseOut:
89529      case topLevelTypes.topMouseOver:
89530      case topLevelTypes.topMouseUp:
89531        EventConstructor = SyntheticMouseEvent;
89532        break;
89533      case topLevelTypes.topDrag:
89534      case topLevelTypes.topDragEnd:
89535      case topLevelTypes.topDragEnter:
89536      case topLevelTypes.topDragExit:
89537      case topLevelTypes.topDragLeave:
89538      case topLevelTypes.topDragOver:
89539      case topLevelTypes.topDragStart:
89540      case topLevelTypes.topDrop:
89541        EventConstructor = SyntheticDragEvent;
89542        break;
89543      case topLevelTypes.topTouchCancel:
89544      case topLevelTypes.topTouchEnd:
89545      case topLevelTypes.topTouchMove:
89546      case topLevelTypes.topTouchStart:
89547        EventConstructor = SyntheticTouchEvent;
89548        break;
89549      case topLevelTypes.topAnimationEnd:
89550      case topLevelTypes.topAnimationIteration:
89551      case topLevelTypes.topAnimationStart:
89552        EventConstructor = SyntheticAnimationEvent;
89553        break;
89554      case topLevelTypes.topTransitionEnd:
89555        EventConstructor = SyntheticTransitionEvent;
89556        break;
89557      case topLevelTypes.topScroll:
89558        EventConstructor = SyntheticUIEvent;
89559        break;
89560      case topLevelTypes.topWheel:
89561        EventConstructor = SyntheticWheelEvent;
89562        break;
89563      case topLevelTypes.topCopy:
89564      case topLevelTypes.topCut:
89565      case topLevelTypes.topPaste:
89566        EventConstructor = SyntheticClipboardEvent;
89567        break;
89568    }
89569    !EventConstructor ? "development" !== 'production' ? invariant(false, 'SimpleEventPlugin: Unhandled event type, `%s`.', topLevelType) : invariant(false) : void 0;
89570    var event = EventConstructor.getPooled(dispatchConfig, targetInst, nativeEvent, nativeEventTarget);
89571    EventPropagators.accumulateTwoPhaseDispatches(event);
89572    return event;
89573  },
89574
89575  didPutListener: function (inst, registrationName, listener) {
89576    // Mobile Safari does not fire properly bubble click events on
89577    // non-interactive elements, which means delegated click listeners do not
89578    // fire. The workaround for this bug involves attaching an empty click
89579    // listener on the target node.
89580    if (registrationName === ON_CLICK_KEY) {
89581      var id = inst._rootNodeID;
89582      var node = ReactDOMComponentTree.getNodeFromInstance(inst);
89583      if (!onClickListeners[id]) {
89584        onClickListeners[id] = EventListener.listen(node, 'click', emptyFunction);
89585      }
89586    }
89587  },
89588
89589  willDeleteListener: function (inst, registrationName) {
89590    if (registrationName === ON_CLICK_KEY) {
89591      var id = inst._rootNodeID;
89592      onClickListeners[id].remove();
89593      delete onClickListeners[id];
89594    }
89595  }
89596
89597};
89598
89599module.exports = SimpleEventPlugin;
89600},{"100":100,"102":102,"103":103,"104":104,"106":106,"107":107,"108":108,"109":109,"110":110,"111":111,"123":123,"143":143,"150":150,"158":158,"16":16,"162":162,"20":20,"40":40,"99":99}],99:[function(_dereq_,module,exports){
89601/**
89602 * Copyright 2013-present, Facebook, Inc.
89603 * All rights reserved.
89604 *
89605 * This source code is licensed under the BSD-style license found in the
89606 * LICENSE file in the root directory of this source tree. An additional grant
89607 * of patent rights can be found in the PATENTS file in the same directory.
89608 *
89609 * @providesModule SyntheticAnimationEvent
89610 */
89611
89612
89613
89614var SyntheticEvent = _dereq_(103);
89615
89616/**
89617 * @interface Event
89618 * @see http://www.w3.org/TR/css3-animations/#AnimationEvent-interface
89619 * @see https://developer.mozilla.org/en-US/docs/Web/API/AnimationEvent
89620 */
89621var AnimationEventInterface = {
89622  animationName: null,
89623  elapsedTime: null,
89624  pseudoElement: null
89625};
89626
89627/**
89628 * @param {object} dispatchConfig Configuration used to dispatch this event.
89629 * @param {string} dispatchMarker Marker identifying the event target.
89630 * @param {object} nativeEvent Native browser event.
89631 * @extends {SyntheticEvent}
89632 */
89633function SyntheticAnimationEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
89634  return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
89635}
89636
89637SyntheticEvent.augmentClass(SyntheticAnimationEvent, AnimationEventInterface);
89638
89639module.exports = SyntheticAnimationEvent;
89640},{"103":103}],100:[function(_dereq_,module,exports){
89641/**
89642 * Copyright 2013-present, Facebook, Inc.
89643 * All rights reserved.
89644 *
89645 * This source code is licensed under the BSD-style license found in the
89646 * LICENSE file in the root directory of this source tree. An additional grant
89647 * of patent rights can be found in the PATENTS file in the same directory.
89648 *
89649 * @providesModule SyntheticClipboardEvent
89650 */
89651
89652
89653
89654var SyntheticEvent = _dereq_(103);
89655
89656/**
89657 * @interface Event
89658 * @see http://www.w3.org/TR/clipboard-apis/
89659 */
89660var ClipboardEventInterface = {
89661  clipboardData: function (event) {
89662    return 'clipboardData' in event ? event.clipboardData : window.clipboardData;
89663  }
89664};
89665
89666/**
89667 * @param {object} dispatchConfig Configuration used to dispatch this event.
89668 * @param {string} dispatchMarker Marker identifying the event target.
89669 * @param {object} nativeEvent Native browser event.
89670 * @extends {SyntheticUIEvent}
89671 */
89672function SyntheticClipboardEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
89673  return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
89674}
89675
89676SyntheticEvent.augmentClass(SyntheticClipboardEvent, ClipboardEventInterface);
89677
89678module.exports = SyntheticClipboardEvent;
89679},{"103":103}],101:[function(_dereq_,module,exports){
89680/**
89681 * Copyright 2013-present, Facebook, Inc.
89682 * All rights reserved.
89683 *
89684 * This source code is licensed under the BSD-style license found in the
89685 * LICENSE file in the root directory of this source tree. An additional grant
89686 * of patent rights can be found in the PATENTS file in the same directory.
89687 *
89688 * @providesModule SyntheticCompositionEvent
89689 */
89690
89691
89692
89693var SyntheticEvent = _dereq_(103);
89694
89695/**
89696 * @interface Event
89697 * @see http://www.w3.org/TR/DOM-Level-3-Events/#events-compositionevents
89698 */
89699var CompositionEventInterface = {
89700  data: null
89701};
89702
89703/**
89704 * @param {object} dispatchConfig Configuration used to dispatch this event.
89705 * @param {string} dispatchMarker Marker identifying the event target.
89706 * @param {object} nativeEvent Native browser event.
89707 * @extends {SyntheticUIEvent}
89708 */
89709function SyntheticCompositionEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
89710  return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
89711}
89712
89713SyntheticEvent.augmentClass(SyntheticCompositionEvent, CompositionEventInterface);
89714
89715module.exports = SyntheticCompositionEvent;
89716},{"103":103}],102:[function(_dereq_,module,exports){
89717/**
89718 * Copyright 2013-present, Facebook, Inc.
89719 * All rights reserved.
89720 *
89721 * This source code is licensed under the BSD-style license found in the
89722 * LICENSE file in the root directory of this source tree. An additional grant
89723 * of patent rights can be found in the PATENTS file in the same directory.
89724 *
89725 * @providesModule SyntheticDragEvent
89726 */
89727
89728
89729
89730var SyntheticMouseEvent = _dereq_(107);
89731
89732/**
89733 * @interface DragEvent
89734 * @see http://www.w3.org/TR/DOM-Level-3-Events/
89735 */
89736var DragEventInterface = {
89737  dataTransfer: null
89738};
89739
89740/**
89741 * @param {object} dispatchConfig Configuration used to dispatch this event.
89742 * @param {string} dispatchMarker Marker identifying the event target.
89743 * @param {object} nativeEvent Native browser event.
89744 * @extends {SyntheticUIEvent}
89745 */
89746function SyntheticDragEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
89747  return SyntheticMouseEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
89748}
89749
89750SyntheticMouseEvent.augmentClass(SyntheticDragEvent, DragEventInterface);
89751
89752module.exports = SyntheticDragEvent;
89753},{"107":107}],103:[function(_dereq_,module,exports){
89754/**
89755 * Copyright 2013-present, Facebook, Inc.
89756 * All rights reserved.
89757 *
89758 * This source code is licensed under the BSD-style license found in the
89759 * LICENSE file in the root directory of this source tree. An additional grant
89760 * of patent rights can be found in the PATENTS file in the same directory.
89761 *
89762 * @providesModule SyntheticEvent
89763 */
89764
89765
89766
89767var _assign = _dereq_(169);
89768
89769var PooledClass = _dereq_(25);
89770
89771var emptyFunction = _dereq_(150);
89772var warning = _dereq_(168);
89773
89774var didWarnForAddedNewProperty = false;
89775var isProxySupported = typeof Proxy === 'function';
89776
89777var shouldBeReleasedProperties = ['dispatchConfig', '_targetInst', 'nativeEvent', 'isDefaultPrevented', 'isPropagationStopped', '_dispatchListeners', '_dispatchInstances'];
89778
89779/**
89780 * @interface Event
89781 * @see http://www.w3.org/TR/DOM-Level-3-Events/
89782 */
89783var EventInterface = {
89784  type: null,
89785  target: null,
89786  // currentTarget is set when dispatching; no use in copying it here
89787  currentTarget: emptyFunction.thatReturnsNull,
89788  eventPhase: null,
89789  bubbles: null,
89790  cancelable: null,
89791  timeStamp: function (event) {
89792    return event.timeStamp || Date.now();
89793  },
89794  defaultPrevented: null,
89795  isTrusted: null
89796};
89797
89798/**
89799 * Synthetic events are dispatched by event plugins, typically in response to a
89800 * top-level event delegation handler.
89801 *
89802 * These systems should generally use pooling to reduce the frequency of garbage
89803 * collection. The system should check `isPersistent` to determine whether the
89804 * event should be released into the pool after being dispatched. Users that
89805 * need a persisted event should invoke `persist`.
89806 *
89807 * Synthetic events (and subclasses) implement the DOM Level 3 Events API by
89808 * normalizing browser quirks. Subclasses do not necessarily have to implement a
89809 * DOM interface; custom application-specific events can also subclass this.
89810 *
89811 * @param {object} dispatchConfig Configuration used to dispatch this event.
89812 * @param {*} targetInst Marker identifying the event target.
89813 * @param {object} nativeEvent Native browser event.
89814 * @param {DOMEventTarget} nativeEventTarget Target node.
89815 */
89816function SyntheticEvent(dispatchConfig, targetInst, nativeEvent, nativeEventTarget) {
89817  if ("development" !== 'production') {
89818    // these have a getter/setter for warnings
89819    delete this.nativeEvent;
89820    delete this.preventDefault;
89821    delete this.stopPropagation;
89822  }
89823
89824  this.dispatchConfig = dispatchConfig;
89825  this._targetInst = targetInst;
89826  this.nativeEvent = nativeEvent;
89827
89828  var Interface = this.constructor.Interface;
89829  for (var propName in Interface) {
89830    if (!Interface.hasOwnProperty(propName)) {
89831      continue;
89832    }
89833    if ("development" !== 'production') {
89834      delete this[propName]; // this has a getter/setter for warnings
89835    }
89836    var normalize = Interface[propName];
89837    if (normalize) {
89838      this[propName] = normalize(nativeEvent);
89839    } else {
89840      if (propName === 'target') {
89841        this.target = nativeEventTarget;
89842      } else {
89843        this[propName] = nativeEvent[propName];
89844      }
89845    }
89846  }
89847
89848  var defaultPrevented = nativeEvent.defaultPrevented != null ? nativeEvent.defaultPrevented : nativeEvent.returnValue === false;
89849  if (defaultPrevented) {
89850    this.isDefaultPrevented = emptyFunction.thatReturnsTrue;
89851  } else {
89852    this.isDefaultPrevented = emptyFunction.thatReturnsFalse;
89853  }
89854  this.isPropagationStopped = emptyFunction.thatReturnsFalse;
89855  return this;
89856}
89857
89858_assign(SyntheticEvent.prototype, {
89859
89860  preventDefault: function () {
89861    this.defaultPrevented = true;
89862    var event = this.nativeEvent;
89863    if (!event) {
89864      return;
89865    }
89866
89867    if (event.preventDefault) {
89868      event.preventDefault();
89869    } else {
89870      event.returnValue = false;
89871    }
89872    this.isDefaultPrevented = emptyFunction.thatReturnsTrue;
89873  },
89874
89875  stopPropagation: function () {
89876    var event = this.nativeEvent;
89877    if (!event) {
89878      return;
89879    }
89880
89881    if (event.stopPropagation) {
89882      event.stopPropagation();
89883    } else {
89884      event.cancelBubble = true;
89885    }
89886    this.isPropagationStopped = emptyFunction.thatReturnsTrue;
89887  },
89888
89889  /**
89890   * We release all dispatched `SyntheticEvent`s after each event loop, adding
89891   * them back into the pool. This allows a way to hold onto a reference that
89892   * won't be added back into the pool.
89893   */
89894  persist: function () {
89895    this.isPersistent = emptyFunction.thatReturnsTrue;
89896  },
89897
89898  /**
89899   * Checks if this event should be released back into the pool.
89900   *
89901   * @return {boolean} True if this should not be released, false otherwise.
89902   */
89903  isPersistent: emptyFunction.thatReturnsFalse,
89904
89905  /**
89906   * `PooledClass` looks for `destructor` on each instance it releases.
89907   */
89908  destructor: function () {
89909    var Interface = this.constructor.Interface;
89910    for (var propName in Interface) {
89911      if ("development" !== 'production') {
89912        Object.defineProperty(this, propName, getPooledWarningPropertyDefinition(propName, Interface[propName]));
89913      } else {
89914        this[propName] = null;
89915      }
89916    }
89917    for (var i = 0; i < shouldBeReleasedProperties.length; i++) {
89918      this[shouldBeReleasedProperties[i]] = null;
89919    }
89920    if ("development" !== 'production') {
89921      var noop = _dereq_(150);
89922      Object.defineProperty(this, 'nativeEvent', getPooledWarningPropertyDefinition('nativeEvent', null));
89923      Object.defineProperty(this, 'preventDefault', getPooledWarningPropertyDefinition('preventDefault', no
89923op));
89924      Object.defineProperty(this, 'stopPropagation', getPooledWarningPropertyDefinition('stopPropagation', noop));
89925    }
89926  }
89927
89928});
89929
89930SyntheticEvent.Interface = EventInterface;
89931
89932if ("development" !== 'production') {
89933  if (isProxySupported) {
89934    /*eslint-disable no-func-assign */
89935    SyntheticEvent = new Proxy(SyntheticEvent, {
89936      construct: function (target, args) {
89937        return this.apply(target, Object.create(target.prototype), args);
89938      },
89939      apply: function (constructor, that, args) {
89940        return new Proxy(constructor.apply(that, args), {
89941          set: function (target, prop, value) {
89942            if (prop !== 'isPersistent' && !target.constructor.Interface.hasOwnProperty(prop) && shouldBeReleasedProperties.indexOf(prop) === -1) {
89943              "development" !== 'production' ? warning(didWarnForAddedNewProperty || target.isPersistent(), 'This synthetic event is reused for performance reasons. If you\'re ' + 'seeing this, you\'re adding a new property in the synthetic event object. ' + 'The property is never released. See ' + 'https://fb.me/react-event-pooling for more information.') : void 0;
89944              didWarnForAddedNewProperty = true;
89945            }
89946            target[prop] = value;
89947            return true;
89948          }
89949        });
89950      }
89951    });
89952    /*eslint-enable no-func-assign */
89953  }
89954}
89955/**
89956 * Helper to reduce boilerplate when creating subclasses.
89957 *
89958 * @param {function} Class
89959 * @param {?object} Interface
89960 */
89961SyntheticEvent.augmentClass = function (Class, Interface) {
89962  var Super = this;
89963
89964  var E = function () {};
89965  E.prototype = Super.prototype;
89966  var prototype = new E();
89967
89968  _assign(prototype, Class.prototype);
89969  Class.prototype = prototype;
89970  Class.prototype.constructor = Class;
89971
89972  Class.Interface = _assign({}, Super.Interface, Interface);
89973  Class.augmentClass = Super.augmentClass;
89974
89975  PooledClass.addPoolingTo(Class, PooledClass.fourArgumentPooler);
89976};
89977
89978PooledClass.addPoolingTo(SyntheticEvent, PooledClass.fourArgumentPooler);
89979
89980module.exports = SyntheticEvent;
89981
89982/**
89983  * Helper to nullify syntheticEvent instance properties when destructing
89984  *
89985  * @param {object} SyntheticEvent
89986  * @param {String} propName
89987  * @return {object} defineProperty object
89988  */
89989function getPooledWarningPropertyDefinition(propName, getVal) {
89990  var isFunction = typeof getVal === 'function';
89991  return {
89992    configurable: true,
89993    set: set,
89994    get: get
89995  };
89996
89997  function set(val) {
89998    var action = isFunction ? 'setting the method' : 'setting the property';
89999    warn(action, 'This is effectively a no-op');
90000    return val;
90001  }
90002
90003  function get() {
90004    var action = isFunction ? 'accessing the method' : 'accessing the property';
90005    var result = isFunction ? 'This is a no-op function' : 'This is set to null';
90006    warn(action, result);
90007    return getVal;
90008  }
90009
90010  function warn(action, result) {
90011    var warningCondition = false;
90012    "development" !== 'production' ? warning(warningCondition, 'This synthetic event is reused for performance reasons. If you\'re seeing this, ' + 'you\'re %s `%s` on a released/nullified synthetic event. %s. ' + 'If you must keep the original synthetic event around, use event.persist(). ' + 'See https://fb.me/react-event-pooling for more information.', action, propName, result) : void 0;
90013  }
90014}
90015},{"150":150,"168":168,"169":169,"25":25}],104:[function(_dereq_,module,exports){
90016/**
90017 * Copyright 2013-present, Facebook, Inc.
90018 * All rights reserved.
90019 *
90020 * This source code is licensed under the BSD-style license found in the
90021 * LICENSE file in the root directory of this source tree. An additional grant
90022 * of patent rights can be found in the PATENTS file in the same directory.
90023 *
90024 * @providesModule SyntheticFocusEvent
90025 */
90026
90027
90028
90029var SyntheticUIEvent = _dereq_(110);
90030
90031/**
90032 * @interface FocusEvent
90033 * @see http://www.w3.org/TR/DOM-Level-3-Events/
90034 */
90035var FocusEventInterface = {
90036  relatedTarget: null
90037};
90038
90039/**
90040 * @param {object} dispatchConfig Configuration used to dispatch this event.
90041 * @param {string} dispatchMarker Marker identifying the event target.
90042 * @param {object} nativeEvent Native browser event.
90043 * @extends {SyntheticUIEvent}
90044 */
90045function SyntheticFocusEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
90046  return SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
90047}
90048
90049SyntheticUIEvent.augmentClass(SyntheticFocusEvent, FocusEventInterface);
90050
90051module.exports = SyntheticFocusEvent;
90052},{"110":110}],105:[function(_dereq_,module,exports){
90053/**
90054 * Copyright 2013-present, Facebook, Inc.
90055 * All rights reserved.
90056 *
90057 * This source code is licensed under the BSD-style license found in the
90058 * LICENSE file in the root directory of this source tree. An additional grant
90059 * of patent rights can be found in the PATENTS file in the same directory.
90060 *
90061 * @providesModule SyntheticInputEvent
90062 */
90063
90064
90065
90066var SyntheticEvent = _dereq_(103);
90067
90068/**
90069 * @interface Event
90070 * @see http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105
90071 *      /#events-inputevents
90072 */
90073var InputEventInterface = {
90074  data: null
90075};
90076
90077/**
90078 * @param {object} dispatchConfig Configuration used to dispatch this event.
90079 * @param {string} dispatchMarker Marker identifying the event target.
90080 * @param {object} nativeEvent Native browser event.
90081 * @extends {SyntheticUIEvent}
90082 */
90083function SyntheticInputEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
90084  return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
90085}
90086
90087SyntheticEvent.augmentClass(SyntheticInputEvent, InputEventInterface);
90088
90089module.exports = SyntheticInputEvent;
90090},{"103":103}],106:[function(_dereq_,module,exports){
90091/**
90092 * Copyright 2013-present, Facebook, Inc.
90093 * All rights reserved.
90094 *
90095 * This source code is licensed under the BSD-style license found in the
90096 * LICENSE file in the root directory of this source tree. An additional grant
90097 * of patent rights can be found in the PATENTS file in the same directory.
90098 *
90099 * @providesModule SyntheticKeyboardEvent
90100 */
90101
90102
90103
90104var SyntheticUIEvent = _dereq_(110);
90105
90106var getEventCharCode = _dereq_(123);
90107var getEventKey = _dereq_(124);
90108var getEventModifierState = _dereq_(125);
90109
90110/**
90111 * @interface KeyboardEvent
90112 * @see http://www.w3.org/TR/DOM-Level-3-Events/
90113 */
90114var KeyboardEventInterface = {
90115  key: getEventKey,
90116  location: null,
90117  ctrlKey: null,
90118  shiftKey: null,
90119  altKey: null,
90120  metaKey: null,
90121  repeat: null,
90122  locale: null,
90123  getModifierState: getEventModifierState,
90124  // Legacy Interface
90125  charCode: function (event) {
90126    // `charCode` is the result of a KeyPress event and represents the value of
90127    // the actual printable character.
90128
90129    // KeyPress is deprecated, but its replacement is not yet final and n
90129ot
90130    // implemented in any major browser. Only KeyPress has charCode.
90131    if (event.type === 'keypress') {
90132      return getEventCharCode(event);
90133    }
90134    return 0;
90135  },
90136  keyCode: function (event) {
90137    // `keyCode` is the result of a KeyDown/Up event and represents the value of
90138    // physical keyboard key.
90139
90140    // The actual meaning of the value depends on the users' keyboard layout
90141    // which cannot be detected. Assuming that it is a US keyboard layout
90142    // provides a surprisingly accurate mapping for US and European users.
90143    // Due to this, it is left to the user to implement at this time.
90144    if (event.type === 'keydown' || event.type === 'keyup') {
90145      return event.keyCode;
90146    }
90147    return 0;
90148  },
90149  which: function (event) {
90150    // `which` is an alias for either `keyCode` or `charCode` depending on the
90151    // type of the event.
90152    if (event.type === 'keypress') {
90153      return getEventCharCode(event);
90154    }
90155    if (event.type === 'keydown' || event.type === 'keyup') {
90156      return event.keyCode;
90157    }
90158    return 0;
90159  }
90160};
90161
90162/**
90163 * @param {object} dispatchConfig Configuration used to dispatch this event.
90164 * @param {string} dispatchMarker Marker identifying the event target.
90165 * @param {object} nativeEvent Native browser event.
90166 * @extends {SyntheticUIEvent}
90167 */
90168function SyntheticKeyboardEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
90169  return SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
90170}
90171
90172SyntheticUIEvent.augmentClass(SyntheticKeyboardEvent, KeyboardEventInterface);
90173
90174module.exports = SyntheticKeyboardEvent;
90175},{"110":110,"123":123,"124":124,"125":125}],107:[function(_dereq_,module,exports){
90176/**
90177 * Copyright 2013-present, Facebook, Inc.
90178 * All rights reserved.
90179 *
90180 * This source code is licensed under the BSD-style license found in the
90181 * LICENSE file in the root directory of this source tree. An additional grant
90182 * of patent rights can be found in the PATENTS file in the same directory.
90183 *
90184 * @providesModule SyntheticMouseEvent
90185 */
90186
90187
90188
90189var SyntheticUIEvent = _dereq_(110);
90190var ViewportMetrics = _dereq_(113);
90191
90192var getEventModifierState = _dereq_(125);
90193
90194/**
90195 * @interface MouseEvent
90196 * @see http://www.w3.org/TR/DOM-Level-3-Events/
90197 */
90198var MouseEventInterface = {
90199  screenX: null,
90200  screenY: null,
90201  clientX: null,
90202  clientY: null,
90203  ctrlKey: null,
90204  shiftKey: null,
90205  altKey: null,
90206  metaKey: null,
90207  getModifierState: getEventModifierState,
90208  button: function (event) {
90209    // Webkit, Firefox, IE9+
90210    // which:  1 2 3
90211    // button: 0 1 2 (standard)
90212    var button = event.button;
90213    if ('which' in event) {
90214      return button;
90215    }
90216    // IE<9
90217    // which:  undefined
90218    // button: 0 0 0
90219    // button: 1 4 2 (onmouseup)
90220    return button === 2 ? 2 : button === 4 ? 1 : 0;
90221  },
90222  buttons: null,
90223  relatedTarget: function (event) {
90224    return event.relatedTarget || (event.fromElement === event.srcElement ? event.toElement : event.fromElement);
90225  },
90226  // "Proprietary" Interface.
90227  pageX: function (event) {
90228    return 'pageX' in event ? event.pageX : event.clientX + ViewportMetrics.currentScrollLeft;
90229  },
90230  pageY: function (event) {
90231    return 'pageY' in event ? event.pageY : event.clientY + ViewportMetrics.currentScrollTop;
90232  }
90233};
90234
90235/**
90236 * @param {object} dispatchConfig Configuration used to dispatch this event.
90237 * @param {string} dispatchMarker Marker identifying the event target.
90238 * @param {object} nativeEvent Native browser event.
90239 * @extends {SyntheticUIEvent}
90240 */
90241function SyntheticMouseEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
90242  return SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
90243}
90244
90245SyntheticUIEvent.augmentClass(SyntheticMouseEvent, MouseEventInterface);
90246
90247module.exports = SyntheticMouseEvent;
90248},{"110":110,"113":113,"125":125}],108:[function(_dereq_,module,exports){
90249/**
90250 * Copyright 2013-present, Facebook, Inc.
90251 * All rights reserved.
90252 *
90253 * This source code is licensed under the BSD-style license found in the
90254 * LICENSE file in the root directory of this source tree. An additional grant
90255 * of patent rights can be found in the PATENTS file in the same directory.
90256 *
90257 * @providesModule SyntheticTouchEvent
90258 */
90259
90260
90261
90262var SyntheticUIEvent = _dereq_(110);
90263
90264var getEventModifierState = _dereq_(125);
90265
90266/**
90267 * @interface TouchEvent
90268 * @see http://www.w3.org/TR/touch-events/
90269 */
90270var TouchEventInterface = {
90271  touches: null,
90272  targetTouches: null,
90273  changedTouches: null,
90274  altKey: null,
90275  metaKey: null,
90276  ctrlKey: null,
90277  shiftKey: null,
90278  getModifierState: getEventModifierState
90279};
90280
90281/**
90282 * @param {object} dispatchConfig Configuration used to dispatch this event.
90283 * @param {string} dispatchMarker Marker identifying the event target.
90284 * @param {object} nativeEvent Native browser event.
90285 * @extends {SyntheticUIEvent}
90286 */
90287function SyntheticTouchEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
90288  return SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
90289}
90290
90291SyntheticUIEvent.augmentClass(SyntheticTouchEvent, TouchEventInterface);
90292
90293module.exports = SyntheticTouchEvent;
90294},{"110":110,"125":125}],109:[function(_dereq_,module,exports){
90295/**
90296 * Copyright 2013-present, Facebook, Inc.
90297 * All rights reserved.
90298 *
90299 * This source code is licensed under the BSD-style license found in the
90300 * LICENSE file in the root directory of this source tree. An additional grant
90301 * of patent rights can be found in the PATENTS file in the same directory.
90302 *
90303 * @providesModule SyntheticTransitionEvent
90304 */
90305
90306
90307
90308var SyntheticEvent = _dereq_(103);
90309
90310/**
90311 * @interface Event
90312 * @see http://www.w3.org/TR/2009/WD-css3-transitions-20090320/#transition-events-
90313 * @see https://developer.mozilla.org/en-US/docs/Web/API/TransitionEvent
90314 */
90315var TransitionEventInterface = {
90316  propertyName: null,
90317  elapsedTime: null,
90318  pseudoElement: null
90319};
90320
90321/**
90322 * @param {object} dispatchConfig Configuration used to dispatch this event.
90323 * @param {string} dispatchMarker Marker identifying the event target.
90324 * @param {object} nativeEvent Native browser event.
90325 * @extends {SyntheticEvent}
90326 */
90327function SyntheticTransitionEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
90328  return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
90329}
90330
90331SyntheticEvent.augmentClass(SyntheticTransitionEvent, TransitionEventInterface);
90332
90333module.exports = SyntheticTransitionEvent;
90334},{"103":103}],110:[function(_dereq_,module,exports){
90335/**
90336 * Copyright 2013-present, Facebook, Inc.
90337 * All rights reserved.
90338 *
90339 * This source code is licensed under the BSD-style license found in the
90340 * LICENSE file in the root directory of this source tree. An additional grant
90341 * of patent rights can be found in the PATENTS file in the same directory.
90342 *
90343 * @providesModule SyntheticUIEvent
90344 */
90345
90346
90347
90348var SyntheticEvent = _dereq_(103);
90349
90350var getEventTarget = _dereq_(126);
90351
90352/**
90353 * @interface UIEvent
90354 * @see http://www.w3.org/TR/DOM-Level-3-Events/
90355 */
90356var UIEventInterface = {
90357  view: function (event) {
90358    if (event.view) {
90359      return event.view;
90360    }
90361
90362    var target = getEventTarget(event);
90363    if (target != null && target.window === target) {
90364      // target is a window object
90365      return target;
90366    }
90367
90368    var doc = target.ownerDocument;
90369    // TODO: Figure out why `ownerDocument` is sometimes undefined in IE8.
90370    if (doc) {
90371      return doc.defaultView || doc.parentWindow;
90372    } else {
90373      return window;
90374    }
90375  },
90376  detail: function (event) {
90377    return event.detail || 0;
90378  }
90379};
90380
90381/**
90382 * @param {object} dispatchConfig Configuration used to dispatch this event.
90383 * @param {string} dispatchMarker Marker identifying the event target.
90384 * @param {object} nativeEvent Native browser event.
90385 * @extends {SyntheticEvent}
90386 */
90387function SyntheticUIEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
90388  return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
90389}
90390
90391SyntheticEvent.augmentClass(SyntheticUIEvent, UIEventInterface);
90392
90393module.exports = SyntheticUIEvent;
90394},{"103":103,"126":126}],111:[function(_dereq_,module,exports){
90395/**
90396 * Copyright 2013-present, Facebook, Inc.
90397 * All rights reserved.
90398 *
90399 * This source code is licensed under the BSD-style license found in the
90400 * LICENSE file in the root directory of this source tree. An additional grant
90401 * of patent rights can be found in the PATENTS file in the same directory.
90402 *
90403 * @providesModule SyntheticWheelEvent
90404 */
90405
90406
90407
90408var SyntheticMouseEvent = _dereq_(107);
90409
90410/**
90411 * @interface WheelEvent
90412 * @see http://www.w3.org/TR/DOM-Level-3-Events/
90413 */
90414var WheelEventInterface = {
90415  deltaX: function (event) {
90416    return 'deltaX' in event ? event.deltaX :
90417    // Fallback to `wheelDeltaX` for Webkit and normalize (right is positive).
90418    'wheelDeltaX' in event ? -event.wheelDeltaX : 0;
90419  },
90420  deltaY: function (event) {
90421    return 'deltaY' in event ? event.deltaY :
90422    // Fallback to `wheelDeltaY` for Webkit and normalize (down is positive).
90423    'wheelDeltaY' in event ? -event.wheelDeltaY :
90424    // Fallback to `wheelDelta` for IE<9 and normalize (down is positive).
90425    'wheelDelta' in event ? -event.wheelDelta : 0;
90426  },
90427  deltaZ: null,
90428
90429  // Browsers without "deltaMode" is reporting in raw wheel delta where one
90430  // notch on the scroll is always +/- 120, roughly equivalent to pixels.
90431  // A good approximation of DOM_DELTA_LINE (1) is 5% of viewport size or
90432  // ~40 pixels, for DOM_DELTA_SCREEN (2) it is 87.5% of viewport size.
90433  deltaMode: null
90434};
90435
90436/**
90437 * @param {object} dispatchConfig Configuration used to dispatch this event.
90438 * @param {string} dispatchMarker Marker identifying the event target.
90439 * @param {object} nativeEvent Native browser event.
90440 * @extends {SyntheticMouseEvent}
90441 */
90442function SyntheticWheelEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
90443  return SyntheticMouseEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
90444}
90445
90446SyntheticMouseEvent.augmentClass(SyntheticWheelEvent, WheelEventInterface);
90447
90448module.exports = SyntheticWheelEvent;
90449},{"107":107}],112:[function(_dereq_,module,exports){
90450/**
90451 * Copyright 2013-present, Facebook, Inc.
90452 * All rights reserved.
90453 *
90454 * This source code is licensed under the BSD-style license found in the
90455 * LICENSE file in the root directory of this source tree. An additional grant
90456 * of patent rights can be found in the PATENTS file in the same directory.
90457 *
90458 * @providesModule Transaction
90459 */
90460
90461
90462
90463var invariant = _dereq_(158);
90464
90465/**
90466 * `Transaction` creates a black box that is able to wrap any method such that
90467 * certain invariants are maintained before and after the method is invoked
90468 * (Even if an exception is thrown while invoking the wrapped method). Whoever
90469 * instantiates a transaction can provide enforcers of the invariants at
90470 * creation time. The `Transaction` class itself will supply one additional
90471 * automatic invariant for you - the invariant that any transaction instance
90472 * should not be run while it is already being run. You would typically create a
90473 * single instance of a `Transaction` for reuse multiple times, that potentially
90474 * is used to wrap several different methods. Wrappers are extremely simple -
90475 * they only require implementing two methods.
90476 *
90477 * <pre>
90478 *                       wrappers (injected at creation time)
90479 *                                      +        +
90480 *                                      |        |
90481 *                    +-----------------|--------|--------------+
90482 *                    |                 v        |              |
90483 *                    |      +---------------+   |              |
90484 *                    |   +--|    wrapper1   |---|----+         |
90485 *                    |   |  +---------------+   v    |         |
90486 *                    |   |          +-------------+  |         |
90487 *                    |   |     +----|   wrapper2  |--------+   |
90488 *                    |   |     |    +-------------+  |     |   |
90489 *                    |   |     |                     |     |   |
90490 *                    |   v     v                     v     v   | wrapper
90491 *                    | +---+ +---+   +---------+   +---+ +---+ | invariants
90492 * perform(anyMethod) | |   | |   |   |         |   |   | |   | | maintained
90493 * +----------------->|-|---|-|---|-->|anyMethod|---|---|-|---|-|-------->
90494 *                    | |   | |   |   |         |   |   | |   | |
90495 *                    | |   | |   |   |         |   |   | |   | |
90496 *                    | |   | |   |   |         |   |   | |   | |
90497 *                    | +---+ +---+   +---------+   +---+ +---+ |
90498 *                    |  initialize                    close    |
90499 *                    +-----------------------------------------+
90500 * </pre>
90501 *
90502 * Use cases:
90503 * - Preserving the input selection ranges before/after reconciliation.
90504 *   Restoring selection even in the event of an unexpected error.
90505 * - Deactivating events while rearranging the DOM, preventing blurs/focuses,
90506 *   while guaranteeing that afterwards, the event system is reactivated.
90507 * - Flushing a queue of collected DOM mutations to the main UI thread after a
90508 *   reconciliation takes place in a worker thread.
90509 * - Invoking any collected `componentDidUpdate` callbacks after rendering new
90510 *   content.
90511 * - (Future use case): Wrapping particular flushes of the `ReactWorker` queue
90512 *   to preserve the `scrollTop` (an automatic scroll aware DOM).
90513 * - (Future use case): Layout calculations before and after DOM updates.
90514 *
90515 * Transactional plugin API:
90516 * - A module that has an `initialize` method that returns any precomputation.
90517 * - and a `close` method that accepts the precomputation. `close` is invoked
90518 *   when the wrapped process is completed, or has failed.
90519 *
90520 * @param {Array<TransactionalWrapper>} transactionWrapper Wrapper modules
90521 * that implement `initialize` and `close`.
90522 * @return {Transaction} Single transaction for reuse in thread.
90523 *
90524 * @class Transaction
90525 */
90526var Mixin = {
90527  /**
90528   * Sets up this instance so that it is prepared for collecting metrics. Does
90529   * so such that this setup method may be used on an instance that is already
90530   * initialized, in a way that does not consume additional memory upon reuse.
90531   * That can be useful if you decide to make your subclass of this mixin a
90532   * "PooledClass".
90533   */
90534  reinitializeTransaction: function () {
90535    this.transactionWrappers = this.getTransactionWrappers();
90536    if (this.wrapperInitData) {
90537      this.wrapperInitData.length = 0;
90538    } else {
90539      this.wrapperInitData = [];
90540    }
90541    this._isInTransaction = false;
90542  },
90543
90544  _isInTransaction: false,
90545
90546  /**
90547   * @abstract
90548   * @return {Array<TransactionWrapper>} Array of transaction wrappers.
90549   */
90550  getTransactionWrappers: null,
90551
90552  isInTransaction: function () {
90553    return !!this._isInTransaction;
90554  },
90555
90556  /**
90557   * Executes the function within a safety window. Use this for the top level
90558   * methods that result in large amounts of computation/mutations that would
90559   * need to be safety checked. The optional arguments helps prevent the need
90560   * to bind in many cases.
90561   *
90562   * @param {function} method Member of scope to call.
90563   * @param {Object} scope Scope to invoke from.
90564   * @param {Object?=} a Argument to pass to the method.
90565   * @param {Object?=} b Argument to pass to the method.
90566   * @param {Object?=} c Argument to pass to the method.
90567   * @param {Object?=} d Argument to pass to the method.
90568   * @param {Object?=} e Argument to pass to the method.
90569   * @param {Object?=} f Argument to pass to the method.
90570   *
90571   * @return {*} Return value from `method`.
90572   */
90573  perform: function (method, scope, a, b, c, d, e, f) {
90574    !!this.isInTransaction() ? "development" !== 'production' ? invariant(false, 'Transaction.perform(...): Cannot initialize a transaction when there ' + 'is already an outstanding transaction.') : invariant(false) : void 0;
90575    var errorThrown;
90576    var ret;
90577    try {
90578      this._isInTransaction = true;
90579      // Catching errors makes debugging more difficult, so we start with
90580      // errorThrown set to true before setting it to false after calling
90581      // close -- if it's still set to true in the finally block, it means
90582      // one of these calls threw.
90583      errorThrown = true;
90584      this.initializeAll(0);
90585      ret = method.call(scope, a, b, c, d, e, f);
90586      errorThrown = false;
90587    } finally {
90588      try {
90589        if (errorThrown) {
90590          // If `method` throws, prefer to show that stack trace over any thrown
90591          // by invoking `closeAll`.
90592          try {
90593            this.closeAll(0);
90594          } catch (err) {}
90595        } else {
90596          // Since `method` didn't throw, we don't want to silence the exception
90597          // here.
90598          this.closeAll(0);
90599        }
90600      } finally {
90601        this._isInTransaction = false;
90602      }
90603    }
90604    return ret;
90605  },
90606
90607  initializeAll: function (startIndex) {
90608    var transactionWrappers = this.transactionWrappers;
90609    for (var i = startIndex; i < transactionWrappers.length; i++) {
90610      var wrapper = transactionWrappers[i];
90611      try {
90612        // Catching errors makes debugging more difficult, so we start with the
90613        // OBSERVED_ERROR state before overwriting it with the real return value
90614        // of initialize -- if it's still set to OBSERVED_ERROR in the finally
90615        // block, it means wrapper.initialize threw.
90616        this.wrapperInitData[i] = Transaction.OBSERVED_ERROR;
90617        this.wrapperInitData[i] = wrapper.initialize ? wrapper.initialize.call(this) : null;
90618      } finally {
90619        if (this.wrapperInitData[i] === Transaction.OBSERVED_ERROR) {
90620          // The initializer for wrapper i threw an error; initialize the
90621          // remaining wrappers but silence any exceptions from them to ensure
90622          // that the first error is the one to bubble up.
90623          try {
90624            this.initializeAll(i + 1);
90625          } catch (err) {}
90626        }
90627      }
90628    }
90629  },
90630
90631  /**
90632   * Invokes each of `this.transactionWrappers.close[i]` functions, passing into
90633   * them the respective return values of `this.transactionWrappers.init[i]`
90634   * (`close`rs that correspond to initializers that failed will not be
90635   * invoked).
90636   */
90637  closeAll: function (startIndex) {
90638    !this.isInTransaction() ? "development" !== 'production' ? invariant(false, 'Transaction.closeAll(): Cannot close transaction when none are open.') : invariant(false) : void 0;
90639    var transactionWrappers = this.transactionWrappers;
90640    for (var i = startIndex; i < transactionWrappers.length; i++) {
90641      var wrapper = transactionWrappers[i];
90642      var initData = this.wrapperInitData[i];
90643      var errorThrown;
90644      try {
90645        // Catching errors makes debugging more difficult, so we start with
90646        // errorThrown set to true before setting it to false after calling
90647        // close -- if it's still set to true in the finally block, it means
90648        // wrapper.close threw.
90649        errorThrown = true;
90650        if (initData !== Transaction.OBSERVED_ERROR && wrapper.close) {
90651          wrapper.close.call(this, initData);
90652        }
90653        errorThrown = false;
90654      } finally {
90655        if (errorThrown) {
90656          // The closer for wrapper i threw an error; close the remaining
90657          // wrappers but silence any exceptions from them to ensure that the
90658          // first error is the one to bubble up.
90659          try {
90660            this.closeAll(i + 1);
90661          } catch (e) {}
90662        }
90663      }
90664    }
90665    this.wrapperInitData.length = 0;
90666  }
90667};
90668
90669var Transaction = {
90670
90671  Mixin: Mixin,
90672
90673  /**
90674   * Token to look for to determine if an error occurred.
90675   */
90676  OBSERVED_ERROR: {}
90677
90678};
90679
90680module.exports = Transaction;
90681},{"158":158}],113:[function(_dereq_,module,exports){
90682/**
90683 * Copyright 2013-present, Facebook, Inc.
90684 * All rights reserved.
90685 *
90686 * This source code is licensed under the BSD-style license found in the
90687 * LICENSE file in the root directory of this source tree. An additional grant
90688 * of patent rights can be found in the PATENTS file in the same directory.
90689 *
90690 * @providesModule ViewportMetrics
90691 */
90692
90693
90694
90695var ViewportMetrics = {
90696
90697  currentScrollLeft: 0,
90698
90699  currentScrollTop: 0,
90700
90701  refreshScrollValues: function (scrollPosition) {
90702    ViewportMetrics.currentScrollLeft = scrollPosition.x;
90703    ViewportMetrics.currentScrollTop = scrollPosition.y;
90704  }
90705
90706};
90707
90708module.exports = ViewportMetrics;
90709},{}],114:[function(_dereq_,module,exports){
90710/**
90711 * Copyright 2014-present, Facebook, Inc.
90712 * All rights reserved.
90713 *
90714 * This source code is licensed under the BSD-style license found in the
90715 * LICENSE file in the root directory of this source tree. An additional grant
90716 * of patent rights can be found in the PATENTS file in the same directory.
90717 *
90718 * @providesModule accumulateInto
90719 */
90720
90721
90722
90723var invariant = _dereq_(158);
90724
90725/**
90726 *
90727 * Accumulates items that must not be null or undefined into the first one. This
90728 * is used to conserve memory by avoiding array allocations, and thus sacrifices
90729 * API cleanness. Since `current` can be null before being passed in and not
90730 * null after this function, make sure to assign it back to `current`:
90731 *
90732 * `a = accumulateInto(a, b);`
90733 *
90734 * This API should be sparingly used. Try `accumulate` for something cleaner.
90735 *
90736 * @return {*|array<*>} An accumulation of items.
90737 */
90738
90739function accumulateInto(current, next) {
90740  !(next != null) ? "development" !== 'production' ? invariant(false, 'accumulateInto(...): Accumulated items must not be null or undefined.') : invariant(false) : void 0;
90741  if (current == null) {
90742    return next;
90743  }
90744
90745  // Both are not empty. Warning: Never call x.concat(y) when you are not
90746  // certain that x is an Array (x could be a string with concat method).
90747  var currentIsArray = Array.isArray(current);
90748  var nextIsArray = Array.isArray(next);
90749
90750  if (currentIsArray && nextIsArray) {
90751    current.push.apply(current, next);
90752    return current;
90753  }
90754
90755  if (currentIsArray) {
90756    current.push(next);
90757    return current;
90758  }
90759
90760  if (nextIsArray) {
90761    // A bit too dangerous to mutate `next`.
90762    return [current].concat(next);
90763  }
90764
90765  return [current, next];
90766}
90767
90768module.exports = accumulateInto;
90769},{"158":158}],115:[function(_dereq_,module,exports){
90770/**
90771 * Copyright 2013-present, Facebook, Inc.
90772 * All rights reserved.
90773 *
90774 * This source code is licensed under the BSD-style license found in the
90775 * LICENSE file in the root directory of this source tree. An additional grant
90776 * of patent rights can be found in the PATENTS file in the same directory.
90777 *
90778 * @providesModule adler32
90779 */
90780
90781
90782
90783var MOD = 65521;
90784
90785// adler32 is not cryptographically strong, and is only used to sanity check that
90786// markup generated on the server matches the markup generated on the client.
90787// This implementation (a modified version of the SheetJS version) has been optimized
90788// for our use case, at the expense of conforming to the adler32 specification
90789// for non-ascii inputs.
90790function adler32(data) {
90791  var a = 1;
90792  var b = 0;
90793  var i = 0;
90794  var l = data.length;
90795  var m = l & ~0x3;
90796  while (i < m) {
90797    var n = Math.min(i + 4096, m);
90798    for (; i < n; i += 4) {
90799      b += (a += data.charCodeAt(i)) + (a += data.charCodeAt(i + 1)) + (a += data.charCodeAt(i + 2)) + (a += data.charCodeAt(i + 3));
90800    }
90801    a %= MOD;
90802    b %= MOD;
90803  }
90804  for (; i < l; i++) {
90805    b += a += data.charCodeAt(i);
90806  }
90807  a %= MOD;
90808  b %= MOD;
90809  return a | b << 16;
90810}
90811
90812module.exports = adler32;
90813},{}],116:[function(_dereq_,module,exports){
90814/**
90815 * Copyright 2013-present, Facebook, Inc.
90816 * All rights reserved.
90817 *
90818 * This source code is licensed under the BSD-style license found in the
90819 * LICENSE file in the root directory of this source tree. An additional grant
90820 * of patent rights can be found in the PATENTS file in the same directory.
90821 *
90822 * @providesModule canDefineProperty
90823 */
90824
90825
90826
90827var canDefineProperty = false;
90828if ("development" !== 'production') {
90829  try {
90830    Object.defineProperty({}, 'x', { get: function () {} });
90831    canDefineProperty = true;
90832  } catch (x) {
90833    // IE will fail on defineProperty
90834  }
90835}
90836
90837module.exports = canDefineProperty;
90838},{}],117:[function(_dereq_,module,exports){
90839/**
90840 * Copyright 2013-present, Facebook, Inc.
90841 * All rights reserved.
90842 *
90843 * This source code is licensed under the BSD-style license found in the
90844 * LICENSE file in the root directory of this source tree. An additional grant
90845 * of patent rights can be found in the PATENTS file in the same directory.
90846 *
90847 * @providesModule createMicrosoftUnsafeLocalFunction
90848 */
90849
90850/* globals MSApp */
90851
90852
90853
90854/**
90855 * Create a function which has 'unsafe' privileges (required by windows8 apps)
90856 */
90857
90858var createMicrosoftUnsafeLocalFunction = function (func) {
90859  if (typeof MSApp !== 'undefined' && MSApp.execUnsafeLocalFunction) {
90860    return function (arg0, arg1, arg2, arg3) {
90861      MSApp.execUnsafeLocalFunction(function () {
90862        return func(arg0, arg1, arg2, arg3);
90863      });
90864    };
90865  } else {
90866    return func;
90867  }
90868};
90869
90870module.exports = createMicrosoftUnsafeLocalFunction;
90871},{}],118:[function(_dereq_,module,exports){
90872/**
90873 * Copyright 2013-present, Facebook, Inc.
90874 * All rights reserved.
90875 *
90876 * This source code is licensed under the BSD-style license found in the
90877 * LICENSE file in the root directory of this source tree. An additional grant
90878 * of patent rights can be found in the PATENTS file in the same directory.
90879 *
90880 * @providesModule dangerousStyleValue
90881 */
90882
90883
90884
90885var CSSProperty = _dereq_(3);
90886var warning = _dereq_(168);
90887
90888var isUnitlessNumber = CSSProperty.isUnitlessNumber;
90889var styleWarnings = {};
90890
90891/**
90892 * Convert a value into the proper css writable value. The style name `name`
90893 * should be logical (no hyphens), as specified
90894 * in `CSSProperty.isUnitlessNumber`.
90895 *
90896 * @param {string} name CSS property name such as `topMargin`.
90897 * @param {*} value CSS property value such as `10px`.
90898 * @param {ReactDOMComponent} component
90899 * @return {string} Normalized style value with dimensions applied.
90900 */
90901function dangerousStyleValue(name, value, component) {
90902  // Note that we've removed escapeTextForBrowser() calls here since the
90903  // whole string will be escaped when the attribute is injected into
90904  // the markup. If you provide unsafe user data here they can inject
90905  // arbitrary CSS which may be problematic (I couldn't repro this):
90906  // https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet
90907  // http://www.thespanner.co.uk/2007/11/26/ultimate-xss-css-injection/
90908  // This is not an XSS hole but instead a potential CSS injection issue
90909  // which has lead to a greater discussion about how we're going to
90910  // trust URLs moving forward. See #2115901
90911
90912  var isEmpty = value == null || typeof value === 'boolean' || value === '';
90913  if (isEmpty) {
90914    return '';
90915  }
90916
90917  var isNonNumeric = isNaN(value);
90918  if (isNonNumeric || value === 0 || isUnitlessNumber.hasOwnProperty(name) && isUnitlessNumber[name]) {
90919    return '' + value; // cast to string
90920  }
90921
90922  if (typeof value === 'string') {
90923    if ("development" !== 'production') {
90924      if (component) {
90925        var owner = component._currentElement._owner;
90926        var ownerName = owner ? owner.getName() : null;
90927        if (ownerName && !styleWarnings[ownerName]) {
90928          styleWarnings[ownerName] = {};
90929        }
90930        var warned = false;
90931        if (ownerName) {
90932          var warnings = styleWarnings[ownerName];
90933          warned = warnings[name];
90934          if (!warned) {
90935            warnings[name] = true;
90936          }
90937        }
90938        if (!warned) {
90939          "development" !== 'production' ? warning(false, 'a `%s` tag (owner: `%s`) was passed a numeric string value ' + 'for CSS property `%s` (value: `%s`) which will be treated ' + 'as a unitless number in a future version of React.', component._currentElement.type, ownerName || 'unknown', name, value) : void 0;
90940        }
90941      }
90942    }
90943    value = value.trim();
90944  }
90945  return value + 'px';
90946}
90947
90948module.exports = dangerousStyleValue;
90949},{"168":168,"3":3}],119:[function(_dereq_,module,exports){
90950/**
90951 * Copyright 2013-present, Facebook, Inc.
90952 * All rights reserved.
90953 *
90954 * This source code is licensed under the BSD-style license found in the
90955 * LICENSE file in the root directory of this source tree. An additional grant
90956 * of patent rights can be found in the PATENTS file in the same directory.
90957 *
90958 * @providesModule escapeTextContentForBrowser
90959 */
90960
90961
90962
90963var ESCAPE_LOOKUP = {
90964  '&': '&amp;',
90965  '>': '&gt;',
90966  '<': '&lt;',
90967  '"': '&quot;',
90968  '\'': '&#x27;'
90969};
90970
90971var ESCAPE_REGEX = /[&><"']/g;
90972
90973function escaper(match) {
90974  return ESCAPE_LOOKUP[match];
90975}
90976
90977/**
90978 * Escapes text to prevent scripting attacks.
90979 *
90980 * @param {*} text Text value to escape.
90981 * @return {string} An escaped string.
90982 */
90983function escapeTextContentForBrowser(text) {
90984  return ('' + text).replace(ESCAPE_REGEX, escaper);
90985}
90986
90987module.exports = escapeTextContentForBrowser;
90988},{}],120:[function(_dereq_,module,exports){
90989/**
90990 * Copyright 2013-present, Facebook, Inc.
90991 * All rights reserved.
90992 *
90993 * This source code is licensed under the BSD-style license found in the
90994 * LICENSE file in the root directory of this source tree. An additional grant
90995 * of patent rights can be found in the PATENTS file in the same directory.
90996 *
90997 * @providesModule findDOMNode
90998 */
90999
91000
91001
91002var ReactCurrentOwner = _dereq_(35);
91003var ReactDOMComponentTree = _dereq_(40);
91004var ReactInstanceMap = _dereq_(71);
91005
91006var getNativeComponentFromComposite = _dereq_(128);
91007var invariant = _dereq_(158);
91008var warning = _dereq_(168);
91009
91010/**
91011 * Returns the DOM node rendered by this element.
91012 *
91013 * @param {ReactComponent|DOMElement} componentOrElement
91014 * @return {?DOMElement} The root node of this element.
91015 */
91016function findDOMNode(componentOrElement) {
91017  if ("development" !== 'production') {
91018    var owner = ReactCurrentOwner.current;
91019    if (owner !== null) {
91020      "development" !== 'production' ? warning(owner._warnedAboutRefsInRender, '%s is accessing findDOMNode inside its render(). ' + 'render() should be a pure function of props and state. It should ' + 'never access something that requires stale data from the previous ' + 'render, such as refs. Move this logic to componentDidMount and ' + 'componentDidUpdate instead.', owner.getName() || 'A c
91020omponent') : void 0;
91021      owner._warnedAboutRefsInRender = true;
91022    }
91023  }
91024  if (componentOrElement == null) {
91025    return null;
91026  }
91027  if (componentOrElement.nodeType === 1) {
91028    return componentOrElement;
91029  }
91030
91031  var inst = ReactInstanceMap.get(componentOrElement);
91032  if (inst) {
91033    inst = getNativeComponentFromComposite(inst);
91034    return inst ? ReactDOMComponentTree.getNodeFromInstance(inst) : null;
91035  }
91036
91037  if (typeof componentOrElement.render === 'function') {
91038    !false ? "development" !== 'production' ? invariant(false, 'findDOMNode was called on an unmounted component.') : invariant(false) : void 0;
91039  } else {
91040    !false ? "development" !== 'production' ? invariant(false, 'Element appears to be neither ReactComponent nor DOMNode (keys: %s)', Object.keys(componentOrElement)) : invariant(false) : void 0;
91041  }
91042}
91043
91044module.exports = findDOMNode;
91045},{"128":128,"158":158,"168":168,"35":35,"40":40,"71":71}],121:[function(_dereq_,module,exports){
91046/**
91047 * Copyright 2013-present, Facebook, Inc.
91048 * All rights reserved.
91049 *
91050 * This source code is licensed under the BSD-style license found in the
91051 * LICENSE file in the root directory of this source tree. An additional grant
91052 * of patent rights can be found in the PATENTS file in the same directory.
91053 *
91054 * @providesModule flattenChildren
91055 */
91056
91057
91058
91059var KeyEscapeUtils = _dereq_(23);
91060var traverseAllChildren = _dereq_(141);
91061var warning = _dereq_(168);
91062
91063/**
91064 * @param {function} traverseContext Context passed through traversal.
91065 * @param {?ReactComponent} child React child component.
91066 * @param {!string} name String name of key path to child.
91067 */
91068function flattenSingleChildIntoContext(traverseContext, child, name) {
91069  // We found a component instance.
91070  var result = traverseContext;
91071  var keyUnique = result[name] === undefined;
91072  if ("development" !== 'production') {
91073    "development" !== 'production' ? warning(keyUnique, 'flattenChildren(...): Encountered two children with the same key, ' + '`%s`. Child keys must be unique; when two children share a key, only ' + 'the first child will be used.', KeyEscapeUtils.unescape(name)) : void 0;
91074  }
91075  if (keyUnique && child != null) {
91076    result[name] = child;
91077  }
91078}
91079
91080/**
91081 * Flattens children that are typically specified as `props.children`. Any null
91082 * children will not be included in the resulting object.
91083 * @return {!object} flattened children keyed by name.
91084 */
91085function flattenChildren(children) {
91086  if (children == null) {
91087    return children;
91088  }
91089  var result = {};
91090  traverseAllChildren(children, flattenSingleChildIntoContext, result);
91091  return result;
91092}
91093
91094module.exports = flattenChildren;
91095},{"141":141,"168":168,"23":23}],122:[function(_dereq_,module,exports){
91096/**
91097 * Copyright 2013-present, Facebook, Inc.
91098 * All rights reserved.
91099 *
91100 * This source code is licensed under the BSD-style license found in the
91101 * LICENSE file in the root directory of this source tree. An additional grant
91102 * of patent rights can be found in the PATENTS file in the same directory.
91103 *
91104 * @providesModule forEachAccumulated
91105 */
91106
91107
91108
91109/**
91110 * @param {array} arr an "accumulation" of items which is either an Array or
91111 * a single item. Useful when paired with the `accumulate` module. This is a
91112 * simple utility that allows us to reason about a collection of items, but
91113 * handling the case when there is exactly one item (and we do not need to
91114 * allocate an array).
91115 */
91116
91117var forEachAccumulated = function (arr, cb, scope) {
91118  if (Array.isArray(arr)) {
91119    arr.forEach(cb, scope);
91120  } else if (arr) {
91121    cb.call(scope, arr);
91122  }
91123};
91124
91125module.exports = forEachAccumulated;
91126},{}],123:[function(_dereq_,module,exports){
91127/**
91128 * Copyright 2013-present, Facebook, Inc.
91129 * All rights reserved.
91130 *
91131 * This source code is licensed under the BSD-style license found in the
91132 * LICENSE file in the root directory of this source tree. An additional grant
91133 * of patent rights can be found in the PATENTS file in the same directory.
91134 *
91135 * @providesModule getEventCharCode
91136 */
91137
91138
91139
91140/**
91141 * `charCode` represents the actual "character code" and is safe to use with
91142 * `String.fromCharCode`. As such, only keys that correspond to printable
91143 * characters produce a valid `charCode`, the only exception to this is Enter.
91144 * The Tab-key is considered non-printable and does not have a `charCode`,
91145 * presumably because it does not produce a tab-character in browsers.
91146 *
91147 * @param {object} nativeEvent Native browser event.
91148 * @return {number} Normalized `charCode` property.
91149 */
91150
91151function getEventCharCode(nativeEvent) {
91152  var charCode;
91153  var keyCode = nativeEvent.keyCode;
91154
91155  if ('charCode' in nativeEvent) {
91156    charCode = nativeEvent.charCode;
91157
91158    // FF does not set `charCode` for the Enter-key, check against `keyCode`.
91159    if (charCode === 0 && keyCode === 13) {
91160      charCode = 13;
91161    }
91162  } else {
91163    // IE8 does not implement `charCode`, but `keyCode` has the correct value.
91164    charCode = keyCode;
91165  }
91166
91167  // Some non-printable keys are reported in `charCode`/`keyCode`, discard them.
91168  // Must not discard the (non-)printable Enter-key.
91169  if (charCode >= 32 || charCode === 13) {
91170    return charCode;
91171  }
91172
91173  return 0;
91174}
91175
91176module.exports = getEventCharCode;
91177},{}],124:[function(_dereq_,module,exports){
91178/**
91179 * Copyright 2013-present, Facebook, Inc.
91180 * All rights reserved.
91181 *
91182 * This source code is licensed under the BSD-style license found in the
91183 * LICENSE file in the root directory of this source tree. An additional grant
91184 * of patent rights can be found in the PATENTS file in the same directory.
91185 *
91186 * @providesModule getEventKey
91187 */
91188
91189
91190
91191var getEventCharCode = _dereq_(123);
91192
91193/**
91194 * Normalization of deprecated HTML5 `key` values
91195 * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names
91196 */
91197var normalizeKey = {
91198  'Esc': 'Escape',
91199  'Spacebar': ' ',
91200  'Left': 'ArrowLeft',
91201  'Up': 'ArrowUp',
91202  'Right': 'ArrowRight',
91203  'Down': 'ArrowDown',
91204  'Del': 'Delete',
91205  'Win': 'OS',
91206  'Menu': 'ContextMenu',
91207  'Apps': 'ContextMenu',
91208  'Scroll': 'ScrollLock',
91209  'MozPrintableKey': 'Unidentified'
91210};
91211
91212/**
91213 * Translation from legacy `keyCode` to HTML5 `key`
91214 * Only special keys supported, all others depend on keyboard layout or browser
91215 * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names
91216 */
91217var translateToKey = {
91218  8: 'Backspace',
91219  9: 'Tab',
91220  12: 'Clear',
91221  13: 'Enter',
91222  16: 'Shift',
91223  17: 'Control',
91224  18: 'Alt',
91225  19: 'Pause',
91226  20: 'CapsLock',
91227  27: 'Escape',
91228  32: ' ',
91229  33: 'PageUp',
91230  34: 'PageDown',
91231  35: 'End',
91232  36: 'Home',
91233  37: 'ArrowLeft',
91234  38: 'ArrowUp',
91235  39: 'ArrowRight',
91236  40: 'ArrowDown',
91237  45: 'Insert',
91238  46: 'Delete',
91239  112: 'F1', 113: 'F2', 114: 'F3', 115: 'F4', 116: 'F5', 117: 'F6',
91240  118: 'F7', 119: 'F8', 120: 'F9', 121: 'F10', 122: 'F11', 123: 'F12',
91241  144: 'NumLock',
91242  145: 'ScrollLock',
91243  224: 'Meta'
91244};
91245
91246/**
91247 * @param {object} nativeEvent Native browser event.
91248 * @return {string} Normalized `key` property.
91249 */
91250function getEventKey(nativeEvent) {
91251  if (nativeEvent.key) {
91252    // Normalize inconsistent values reported by browsers due to
91253    // implementations of a working draft specification.
91254
91255    // FireFox implements `key` but returns `MozPrintableKey` for all
91256    // printable characters (normalized to `Unidentified`), ignore it.
91257    var key = normalizeKey[nativeEvent.key] || nativeEvent.key;
91258    if (key !== 'Unidentified') {
91259      return key;
91260    }
91261  }
91262
91263  // Browser does not implement `key`, polyfill as much of it as we can.
91264  if (nativeEvent.type === 'keypress') {
91265    var charCode = getEventCharCode(nativeEvent);
91266
91267    // The enter-key is technically both printable and non-printable and can
91268    // thus be captured by `keypress`, no other non-printable key should.
91269    return charCode === 13 ? 'Enter' : String.fromCharCode(charCode);
91270  }
91271  if (nativeEvent.type === 'keydown' || nativeEvent.type === 'keyup') {
91272    // While user keyboard layout determines the actual meaning of each
91273    // `keyCode` value, almost all function keys have a universal value.
91274    return translateToKey[nativeEvent.keyCode] || 'Unidentified';
91275  }
91276  return '';
91277}
91278
91279module.exports = getEventKey;
91280},{"123":123}],125:[function(_dereq_,module,exports){
91281/**
91282 * Copyright 2013-present, Facebook, Inc.
91283 * All rights reserved.
91284 *
91285 * This source code is licensed under the BSD-style license found in the
91286 * LICENSE file in the root directory of this source tree. An additional grant
91287 * of patent rights can be found in the PATENTS file in the same directory.
91288 *
91289 * @providesModule getEventModifierState
91290 */
91291
91292
91293
91294/**
91295 * Translation from modifier key to the associated property in the event.
91296 * @see http://www.w3.org/TR/DOM-Level-3-Events/#keys-Modifiers
91297 */
91298
91299var modifierKeyToProp = {
91300  'Alt': 'altKey',
91301  'Control': 'ctrlKey',
91302  'Meta': 'metaKey',
91303  'Shift': 'shiftKey'
91304};
91305
91306// IE8 does not implement getModifierState so we simply map it to the only
91307// modifier keys exposed by the event itself, does not support Lock-keys.
91308// Currently, all major browsers except Chrome seems to support Lock-keys.
91309function modifierStateGetter(keyArg) {
91310  var syntheticEvent = this;
91311  var nativeEvent = syntheticEvent.nativeEvent;
91312  if (nativeEvent.getModifierState) {
91313    return nativeEvent.getModifierState(keyArg);
91314  }
91315  var keyProp = modifierKeyToProp[keyArg];
91316  return keyProp ? !!nativeEvent[keyProp] : false;
91317}
91318
91319function getEventModifierState(nativeEvent) {
91320  return modifierStateGetter;
91321}
91322
91323module.exports = getEventModifierState;
91324},{}],126:[function(_dereq_,module,exports){
91325/**
91326 * Copyright 2013-present, Facebook, Inc.
91327 * All rights reserved.
91328 *
91329 * This source code is licensed under the BSD-style license found in the
91330 * LICENSE file in the root directory of this source tree. An additional grant
91331 * of patent rights can be found in the PATENTS file in the same directory.
91332 *
91333 * @providesModule getEventTarget
91334 */
91335
91336
91337
91338/**
91339 * Gets the target node from a native browser event by accounting for
91340 * inconsistencies in browser DOM APIs.
91341 *
91342 * @param {object} nativeEvent Native browser event.
91343 * @return {DOMEventTarget} Target node.
91344 */
91345
91346function getEventTarget(nativeEvent) {
91347  var target = nativeEvent.target || nativeEvent.srcElement || window;
91348
91349  // Normalize SVG <use> element events #4963
91350  if (target.correspondingUseElement) {
91351    target = target.correspondingUseElement;
91352  }
91353
91354  // Safari may fire events on text nodes (Node.TEXT_NODE is 3).
91355  // @see http://www.quirksmode.org/js/events_properties.html
91356  return target.nodeType === 3 ? target.parentNode : target;
91357}
91358
91359module.exports = getEventTarget;
91360},{}],127:[function(_dereq_,module,exports){
91361/**
91362 * Copyright 2013-present, Facebook, Inc.
91363 * All rights reserved.
91364 *
91365 * This source code is licensed under the BSD-style license found in the
91366 * LICENSE file in the root directory of this source tree. An additional grant
91367 * of patent rights can be found in the PATENTS file in the same directory.
91368 *
91369 * @providesModule getIteratorFn
91370 */
91371
91372
91373
91374/* global Symbol */
91375
91376var ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;
91377var FAUX_ITERATOR_SYMBOL = '@@iterator'; // Before Symbol spec.
91378
91379/**
91380 * Returns the iterator method function contained on the iterable object.
91381 *
91382 * Be sure to invoke the function with the iterable as context:
91383 *
91384 *     var iteratorFn = getIteratorFn(myIterable);
91385 *     if (iteratorFn) {
91386 *       var iterator = iteratorFn.call(myIterable);
91387 *       ...
91388 *     }
91389 *
91390 * @param {?object} maybeIterable
91391 * @return {?function}
91392 */
91393function getIteratorFn(maybeIterable) {
91394  var iteratorFn = maybeIterable && (ITERATOR_SYMBOL && maybeIterable[ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL]);
91395  if (typeof iteratorFn === 'function') {
91396    return iteratorFn;
91397  }
91398}
91399
91400module.exports = getIteratorFn;
91401},{}],128:[function(_dereq_,module,exports){
91402/**
91403 * Copyright 2013-present, Facebook, Inc.
91404 * All rights reserved.
91405 *
91406 * This source code is licensed under the BSD-style license found in the
91407 * LICENSE file in the root directory of this source tree. An additional grant
91408 * of patent rights can be found in the PATENTS file in the same directory.
91409 *
91410 * @providesModule getNativeComponentFromComposite
91411 */
91412
91413
91414
91415var ReactNodeTypes = _dereq_(79);
91416
91417function getNativeComponentFromComposite(inst) {
91418  var type;
91419
91420  while ((type = inst._renderedNodeType) === ReactNodeTypes.COMPOSITE) {
91421    inst = inst._renderedComponent;
91422  }
91423
91424  if (type === ReactNodeTypes.NATIVE) {
91425    return inst._renderedComponent;
91426  } else if (type === ReactNodeTypes.EMPTY) {
91427    return null;
91428  }
91429}
91430
91431module.exports = getNativeComponentFromComposite;
91432},{"79":79}],129:[function(_dereq_,module,exports){
91433/**
91434 * Copyright 2013-present, Facebook, Inc.
91435 * All rights reserved.
91436 *
91437 * This source code is licensed under the BSD-style license found in the
91438 * LICENSE file in the root directory of this source tree. An additional grant
91439 * of patent rights can be found in the PATENTS file in the same directory.
91440 *
91441 * @providesModule getNodeForCharacterOffset
91442 */
91443
91444
91445
91446/**
91447 * Given any node return the first leaf node without children.
91448 *
91449 * @param {DOMElement|DOMTextNode} node
91450 * @return {DOMElement|DOMTextNode}
91451 */
91452
91453function getLeafNode(node) {
91454  while (node && node.firstChild) {
91455    node = node.firstChild;
91456  }
91457  return node;
91458}
91459
91460/**
91461 * Get the next sibling within a container. This will walk up the
91462 * DOM if a node's siblings have been exhausted.
91463 *
91464 * @param {DOMElement|DOMTextNode} node
91465 * @return {?DOMElement|DOMTextNode}
91466 */
91467function getSiblingNode(node) {
91468  while (node) {
91469    if (node.nextSibling) {
91470      return node.nextSibling;
91471    }
91472    node = node.parentNode;
91473  }
91474}
91475
91476/**
91477 * Get object describing the nodes which contain characters at offset.
91478 *
91479 * @param {DOMElement|DOMTextNode} root
91480 * @param {number} offset
91481 * @return {?object}
91482 */
91483function getNodeForCharacterOffset(root, offset) {
91484  var node = getLeafNode(root);
91485  var nodeStart = 0;
91486  var nodeEnd = 0;
91487
91488  while (node) {
91489    if (node.nodeType === 3) {
91490      nodeEnd = nodeStart + node.textContent.length;
91491
91492      if (nodeStart <= offset && nodeEnd >= offset) {
91493        return {
91494          node: node,
91495          offset: offset - nodeStart
91496        };
91497      }
91498
91499      nodeStart = nodeEnd;
91500    }
91501
91502    node = getLeafNode(getSiblingNode(node));
91503  }
91504}
91505
91506module.exports = getNodeForCharacterOffset;
91507},{}],130:[function(_dereq_,module,exports){
91508/**
91509 * Copyright 2013-present, Facebook, Inc.
91510 * All rights reserved.
91511 *
91512 * This source code is licensed under the BSD-style license found in the
91513 * LICENSE file in the root directory of this source tree. An additional grant
91514 * of patent rights can be found in the PATENTS file in the same directory.
91515 *
91516 * @providesModule getTextContentAccessor
91517 */
91518
91519
91520
91521var ExecutionEnvironment = _dereq_(144);
91522
91523var contentKey = null;
91524
91525/**
91526 * Gets the key used to access text content on a DOM node.
91527 *
91528 * @return {?string} Key used to access text content.
91529 * @internal
91530 */
91531function getTextContentAccessor() {
91532  if (!contentKey && ExecutionEnvironment.canUseDOM) {
91533    // Prefer textContent to innerText because many browsers support both but
91534    // SVG <text> elements don't support innerText even when <div> does.
91535    contentKey = 'textContent' in document.documentElement ? 'textContent' : 'innerText';
91536  }
91537  return contentKey;
91538}
91539
91540module.exports = getTextContentAccessor;
91541},{"144":144}],131:[function(_dereq_,module,exports){
91542/**
91543 * Copyright 2013-present, Facebook, Inc.
91544 * All rights reserved.
91545 *
91546 * This source code is licensed under the BSD-style license found in the
91547 * LICENSE file in the root directory of this source tree. An additional grant
91548 * of patent rights can be found in the PATENTS file in the same directory.
91549 *
91550 * @providesModule getVendorPrefixedEventName
91551 */
91552
91553
91554
91555var ExecutionEnvironment = _dereq_(144);
91556
91557/**
91558 * Generate a mapping of standard vendor prefixes using the defined style property and event name.
91559 *
91560 * @param {string} styleProp
91561 * @param {string} eventName
91562 * @returns {object}
91563 */
91564function makePrefixMap(styleProp, eventName) {
91565  var prefixes = {};
91566
91567  prefixes[styleProp.toLowerCase()] = eventName.toLowerCase();
91568  prefixes['Webkit' + styleProp] = 'webkit' + eventName;
91569  prefixes['Moz' + styleProp] = 'moz' + eventName;
91570  prefixes['ms' + styleProp] = 'MS' + eventName;
91571  prefixes['O' + styleProp] = 'o' + eventName.toLowerCase();
91572
91573  return prefixes;
91574}
91575
91576/**
91577 * A list of event names to a configurable list of vendor prefixes.
91578 */
91579var vendorPrefixes = {
91580  animationend: makePrefixMap('Animation', 'AnimationEnd'),
91581  animationiteration: makePrefixMap('Animation', 'AnimationIteration'),
91582  animationstart: makePrefixMap('Animation', 'AnimationStart'),
91583  transitionend: makePrefixMap('Transition', 'TransitionEnd')
91584};
91585
91586/**
91587 * Event names that have already been detected and prefixed (if applicable).
91588 */
91589var prefixedEventNames = {};
91590
91591/**
91592 * Element to check for prefixes on.
91593 */
91594var style = {};
91595
91596/**
91597 * Bootstrap if a DOM exists.
91598 */
91599if (ExecutionEnvironment.canUseDOM) {
91600  style = document.createElement('div').style;
91601
91602  // On some platforms, in particular some releases of Android 4.x,
91603  // the un-prefixed "animation" and "transition" properties are defined on the
91604  // style object but the events that fire will still be prefixed, so we need
91605  // to check if the un-prefixed events are usable, and if not remove them from the map.
91606  if (!('AnimationEvent' in window)) {
91607    delete vendorPrefixes.animationend.animation;
91608    delete vendorPrefixes.animationiteration.animation;
91609    delete vendorPrefixes.animationstart.animation;
91610  }
91611
91612  // Same as above
91613  if (!('TransitionEvent' in window)) {
91614    delete vendorPrefixes.transitionend.transition;
91615  }
91616}
91617
91618/**
91619 * Attempts to determine the correct vendor prefixed event name.
91620 *
91621 * @param {string} eventName
91622 * @returns {string}
91623 */
91624function getVendorPrefixedEventName(eventName) {
91625  if (prefixedEventNames[eventName]) {
91626    return prefixedEventNames[eventName];
91627  } else if (!vendorPrefixes[eventName]) {
91628    return eventName;
91629  }
91630
91631  var prefixMap = vendorPrefixes[eventName];
91632
91633  for (var styleProp in prefixMap) {
91634    if (prefixMap.hasOwnProperty(styleProp) && styleProp in style) {
91635      return prefixedEventNames[eventName] = prefixMap[styleProp];
91636    }
91637  }
91638
91639  return '';
91640}
91641
91642module.exports = getVendorPrefixedEventName;
91643},{"144":144}],132:[function(_dereq_,module,exports){
91644/**
91645 * Copyright 2013-present, Facebook, Inc.
91646 * All rights reserved.
91647 *
91648 * This source code is licensed under the BSD-style license found in the
91649 * LICENSE file in the root directory of this source tree. An additional grant
91650 * of patent rights can be found in the PATENTS file in the same directory.
91651 *
91652 * @providesModule instantiateReactComponent
91653 */
91654
91655
91656
91657var _assign = _dereq_(169);
91658
91659var ReactCompositeComponent = _dereq_(34);
91660var ReactEmptyComponent = _dereq_(64);
91661var ReactNativeComponent = _dereq_(78);
91662
91663var invariant = _dereq_(158);
91664var warning = _dereq_(168);
91665
91666// To avoid a cyclic dependency, we create the final class in this module
91667var ReactCompositeComponentWrapper = function (element) {
91668  this.construct(element);
91669};
91670_assign(ReactCompositeComponentWrapper.prototype, ReactCompositeComponent.Mixin, {
91671  _instantiateReactComponent: instantiateReactComponent
91672});
91673
91674function getDeclarationErrorAddendum(owner) {
91675  if (owner) {
91676    var name = owner.getName();
91677    if (name) {
91678      return ' Check the render method of `' + name + '`.';
91679    }
91680  }
91681  return '';
91682}
91683
91684/**
91685 * Check if the type reference is a known internal type. I.e. not a user
91686 * provided composite type.
91687 *
91688 * @param {function} type
91689 * @return {boolean} Returns true if this is a valid internal type.
91690 */
91691function isInternalComponentType(type) {
91692  return typeof type === 'function' && typeof type.prototype !== 'undefined' && typeof type.prototype.mountComponent === 'function' && typeof type.prototype.receiveComponent === 'function';
91693}
91694
91695/**
91696 * Given a ReactNode, create an instance that will actually be mounted.
91697 *
91698 * @param {ReactNode} node
91699 * @return {object} A new instance of the element's constructor.
91700 * @protected
91701 */
91702function instantiateReactComponent(node) {
91703  var instance;
91704
91705  if (node === null || node === false) {
91706    instance = ReactEmptyComponent.create(instantiateReactComponent);
91707  } else if (typeof node === 'object') {
91708    var element = node;
91709    !(element && (typeof element.type === 'function' || typeof element.type === 'string')) ? "development" !== 'production' ? invariant(false, 'Element type is invali
91709d: expected a string (for built-in components) ' + 'or a class/function (for composite components) but got: %s.%s', element.type == null ? element.type : typeof element.type, getDeclarationErrorAddendum(element._owner)) : invariant(false) : void 0;
91710
91711    // Special case string values
91712    if (typeof element.type === 'string') {
91713      instance = ReactNativeComponent.createInternalComponent(element);
91714    } else if (isInternalComponentType(element.type)) {
91715      // This is temporarily available for custom components that are not string
91716      // representations. I.e. ART. Once those are updated to use the string
91717      // representation, we can drop this code path.
91718      instance = new element.type(element);
91719    } else {
91720      instance = new ReactCompositeComponentWrapper(element);
91721    }
91722  } else if (typeof node === 'string' || typeof node === 'number') {
91723    instance = ReactNativeComponent.createInstanceForText(node);
91724  } else {
91725    !false ? "development" !== 'production' ? invariant(false, 'Encountered invalid React node of type %s', typeof node) : invariant(false) : void 0;
91726  }
91727
91728  if ("development" !== 'production') {
91729    "development" !== 'production' ? warning(typeof instance.mountComponent === 'function' && typeof instance.receiveComponent === 'function' && typeof instance.getNativeNode === 'function' && typeof instance.unmountComponent === 'function', 'Only React Components can be mounted.') : void 0;
91730  }
91731
91732  // These two fields are used by the DOM and ART diffing algorithms
91733  // respectively. Instead of using expandos on components, we should be
91734  // storing the state needed by the diffing algorithms elsewhere.
91735  instance._mountIndex = 0;
91736  instance._mountImage = null;
91737
91738  if ("development" !== 'production') {
91739    instance._isOwnerNecessary = false;
91740    instance._warnedAboutRefsInRender = false;
91741  }
91742
91743  // Internal instances should fully constructed at this point, so they should
91744  // not get any new fields added to them at this point.
91745  if ("development" !== 'production') {
91746    if (Object.preventExtensions) {
91747      Object.preventExtensions(instance);
91748    }
91749  }
91750
91751  return instance;
91752}
91753
91754module.exports = instantiateReactComponent;
91755},{"158":158,"168":168,"169":169,"34":34,"64":64,"78":78}],133:[function(_dereq_,module,exports){
91756/**
91757 * Copyright 2013-present, Facebook, Inc.
91758 * All rights reserved.
91759 *
91760 * This source code is licensed under the BSD-style license found in the
91761 * LICENSE file in the root directory of this source tree. An additional grant
91762 * of patent rights can be found in the PATENTS file in the same directory.
91763 *
91764 * @providesModule isEventSupported
91765 */
91766
91767
91768
91769var ExecutionEnvironment = _dereq_(144);
91770
91771var useHasFeature;
91772if (ExecutionEnvironment.canUseDOM) {
91773  useHasFeature = document.implementation && document.implementation.hasFeature &&
91774  // always returns true in newer browsers as per the standard.
91775  // @see http://dom.spec.whatwg.org/#dom-domimplementation-hasfeature
91776  document.implementation.hasFeature('', '') !== true;
91777}
91778
91779/**
91780 * Checks if an event is supported in the current execution environment.
91781 *
91782 * NOTE: This will not work correctly for non-generic events such as `change`,
91783 * `reset`, `load`, `error`, and `select`.
91784 *
91785 * Borrows from Modernizr.
91786 *
91787 * @param {string} eventNameSuffix Event name, e.g. "click".
91788 * @param {?boolean} capture Check if the capture phase is supported.
91789 * @return {boolean} True if the event is supported.
91790 * @internal
91791 * @license Modernizr 3.0.0pre (Custom Build) | MIT
91792 */
91793function isEventSupported(eventNameSuffix, capture) {
91794  if (!ExecutionEnvironment.canUseDOM || capture && !('addEventListener' in document)) {
91795    return false;
91796  }
91797
91798  var eventName = 'on' + eventNameSuffix;
91799  var isSupported = eventName in document;
91800
91801  if (!isSupported) {
91802    var element = document.createElement('div');
91803    element.setAttribute(eventName, 'return;');
91804    isSupported = typeof element[eventName] === 'function';
91805  }
91806
91807  if (!isSupported && useHasFeature && eventNameSuffix === 'wheel') {
91808    // This is the only way to test support for the `wheel` event in IE9+.
91809    isSupported = document.implementation.hasFeature('Events.wheel', '3.0');
91810  }
91811
91812  return isSupported;
91813}
91814
91815module.exports = isEventSupported;
91816},{"144":144}],134:[function(_dereq_,module,exports){
91817/**
91818 * Copyright 2013-present, Facebook, Inc.
91819 * All rights reserved.
91820 *
91821 * This source code is licensed under the BSD-style license found in the
91822 * LICENSE file in the root directory of this source tree. An additional grant
91823 * of patent rights can be found in the PATENTS file in the same directory.
91824 *
91825 * @providesModule isTextInputElement
91826 */
91827
91828
91829
91830/**
91831 * @see http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary
91832 */
91833
91834var supportedInputTypes = {
91835  'color': true,
91836  'date': true,
91837  'datetime': true,
91838  'datetime-local': true,
91839  'email': true,
91840  'month': true,
91841  'number': true,
91842  'password': true,
91843  'range': true,
91844  'search': true,
91845  'tel': true,
91846  'text': true,
91847  'time': true,
91848  'url': true,
91849  'week': true
91850};
91851
91852function isTextInputElement(elem) {
91853  var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase();
91854  return nodeName && (nodeName === 'input' && supportedInputTypes[elem.type] || nodeName === 'textarea');
91855}
91856
91857module.exports = isTextInputElement;
91858},{}],135:[function(_dereq_,module,exports){
91859/**
91860 * Copyright 2013-present, Facebook, Inc.
91861 * All rights reserved.
91862 *
91863 * This source code is licensed under the BSD-style license found in the
91864 * LICENSE file in the root directory of this source tree. An additional grant
91865 * of patent rights can be found in the PATENTS file in the same directory.
91866 *
91867 * @providesModule onlyChild
91868 */
91869
91870
91871var ReactElement = _dereq_(62);
91872
91873var invariant = _dereq_(158);
91874
91875/**
91876 * Returns the first child in a collection of children and verifies that there
91877 * is only one child in the collection. The current implementation of this
91878 * function assumes that a single child gets passed without a wrapper, but the
91879 * purpose of this helper function is to abstract away the particular structure
91880 * of children.
91881 *
91882 * @param {?object} children Child collection structure.
91883 * @return {ReactElement} The first and only `ReactElement` contained in the
91884 * structure.
91885 */
91886function onlyChild(children) {
91887  !ReactElement.isValidElement(children) ? "development" !== 'production' ? invariant(false, 'onlyChild must be passed a children with exactly one child.') : invariant(false) : void 0;
91888  return children;
91889}
91890
91891module.exports = onlyChild;
91892},{"158":158,"62":62}],136:[function(_dereq_,module,exports){
91893/**
91894 * Copyright 2013-present, Facebook, Inc.
91895 * All rights reserved.
91896 *
91897 * This source code is licensed under the BSD-style license found in the
91898 * LICENSE file in the root directory of this source tree. An additional grant
91899 * of patent rights can be found in the PATENTS file in the same directory.
91900 *
91901 * @providesModule quoteAttributeValueForBrowser
91902 */
91903
91904
91905
91906var escapeTextContentForBrowser = _dereq_(119);
91907
91908/**
91909 * Escapes attribute value to prevent scripting attacks.
91910 *
91911 * @param {*} value Value to escape.
91912 * @return {string} An escaped string.
91913 */
91914function quoteAttributeValueForBrowser(value) {
91915  return '"' + escapeTextContentForBrowser(value) + '"';
91916}
91917
91918module.exports = quoteAttributeValueForBrowser;
91919},{"119":119}],137:[function(_dereq_,module,exports){
91920/**
91921 * Copyright 2013-present, Facebook, Inc.
91922 * All rights reserved.
91923 *
91924 * This source code is licensed under the BSD-style license found in the
91925 * LICENSE file in the root directory of this source tree. An additional grant
91926 * of patent rights can be found in the PATENTS file in the same directory.
91927 *
91928* @providesModule renderSubtreeIntoContainer
91929*/
91930
91931
91932
91933var ReactMount = _dereq_(75);
91934
91935module.exports = ReactMount.renderSubtreeIntoContainer;
91936},{"75":75}],138:[function(_dereq_,module,exports){
91937/**
91938 * Copyright 2013-present, Facebook, Inc.
91939 * All rights reserved.
91940 *
91941 * This source code is licensed under the BSD-style license found in the
91942 * LICENSE file in the root directory of this source tree. An additional grant
91943 * of patent rights can be found in the PATENTS file in the same directory.
91944 *
91945 * @providesModule setInnerHTML
91946 */
91947
91948
91949
91950var ExecutionEnvironment = _dereq_(144);
91951
91952var WHITESPACE_TEST = /^[ \r\n\t\f]/;
91953var NONVISIBLE_TEST = /<(!--|link|noscript|meta|script|style)[ \r\n\t\f\/>]/;
91954
91955var createMicrosoftUnsafeLocalFunction = _dereq_(117);
91956
91957/**
91958 * Set the innerHTML property of a node, ensuring that whitespace is preserved
91959 * even in IE8.
91960 *
91961 * @param {DOMElement} node
91962 * @param {string} html
91963 * @internal
91964 */
91965var setInnerHTML = createMicrosoftUnsafeLocalFunction(function (node, html) {
91966  node.innerHTML = html;
91967});
91968
91969if (ExecutionEnvironment.canUseDOM) {
91970  // IE8: When updating a just created node with innerHTML only leading
91971  // whitespace is removed. When updating an existing node with innerHTML
91972  // whitespace in root TextNodes is also collapsed.
91973  // @see quirksmode.org/bugreports/archives/2004/11/innerhtml_and_t.html
91974
91975  // Feature detection; only IE8 is known to behave improperly like this.
91976  var testElement = document.createElement('div');
91977  testElement.innerHTML = ' ';
91978  if (testElement.innerHTML === '') {
91979    setInnerHTML = function (node, html) {
91980      // Magic theory: IE8 supposedly differentiates between added and updated
91981      // nodes when processing innerHTML, innerHTML on updated nodes suffers
91982      // from worse whitespace behavior. Re-adding a node like this triggers
91983      // the initial and more favorable whitespace behavior.
91984      // TODO: What to do on a detached node?
91985      if (node.parentNode) {
91986        node.parentNode.replaceChild(node, node);
91987      }
91988
91989      // We also implement a workaround for non-visible tags disappearing into
91990      // thin air on IE8, this only happens if there is no visible text
91991      // in-front of the non-visible tags. Piggyback on the whitespace fix
91992      // and simply check if any non-visible tags appear in the source.
91993      if (WHITESPACE_TEST.test(html) || html[0] === '<' && NONVISIBLE_TEST.test(html)) {
91994        // Recover leading whitespace by temporarily prepending any character.
91995        // \uFEFF has the potential advantage of being zero-width/invisible.
91996        // UglifyJS drops U+FEFF chars when parsing, so use String.fromCharCode
91997        // in hopes that this is preserved even if "\uFEFF" is transformed to
91998        // the actual Unicode character (by Babel, for example).
91999        // https://github.com/mishoo/UglifyJS2/blob/v2.4.20/lib/parse.js#L216
92000        node.innerHTML = String.fromCharCode(0xFEFF) + html;
92001
92002        // deleteData leaves an empty `TextNode` which offsets the index of all
92003        // children. Definitely want to avoid this.
92004        var textNode = node.firstChild;
92005        if (textNode.data.length === 1) {
92006          node.removeChild(textNode);
92007        } else {
92008          textNode.deleteData(0, 1);
92009        }
92010      } else {
92011        node.innerHTML = html;
92012      }
92013    };
92014  }
92015  testElement = null;
92016}
92017
92018module.exports = setInnerHTML;
92019},{"117":117,"144":144}],139:[function(_dereq_,module,exports){
92020/**
92021 * Copyright 2013-present, Facebook, Inc.
92022 * All rights reserved.
92023 *
92024 * This source code is licensed under the BSD-style license found in the
92025 * LICENSE file in the root directory of this source tree. An additional grant
92026 * of patent rights can be found in the PATENTS file in the same directory.
92027 *
92028 * @providesModule setTextContent
92029 */
92030
92031
92032
92033var ExecutionEnvironment = _dereq_(144);
92034var escapeTextContentForBrowser = _dereq_(119);
92035var setInnerHTML = _dereq_(138);
92036
92037/**
92038 * Set the textContent property of a node, ensuring that whitespace is preserved
92039 * even in IE8. innerText is a poor substitute for textContent and, among many
92040 * issues, inserts <br> instead of the literal newline chars. innerHTML behaves
92041 * as it should.
92042 *
92043 * @param {DOMElement} node
92044 * @param {string} text
92045 * @internal
92046 */
92047var setTextContent = function (node, text) {
92048  node.textContent = text;
92049};
92050
92051if (ExecutionEnvironment.canUseDOM) {
92052  if (!('textContent' in document.documentElement)) {
92053    setTextContent = function (node, text) {
92054      setInnerHTML(node, escapeTextContentForBrowser(text));
92055    };
92056  }
92057}
92058
92059module.exports = setTextContent;
92060},{"119":119,"138":138,"144":144}],140:[function(_dereq_,module,exports){
92061/**
92062 * Copyright 2013-present, Facebook, Inc.
92063 * All rights reserved.
92064 *
92065 * This source code is licensed under the BSD-style license found in the
92066 * LICENSE file in the root directory of this source tree. An additional grant
92067 * of patent rights can be found in the PATENTS file in the same directory.
92068 *
92069 * @providesModule shouldUpdateReactComponent
92070 */
92071
92072
92073
92074/**
92075 * Given a `prevElement` and `nextElement`, determines if the existing
92076 * instance should be updated as opposed to being destroyed or replaced by a new
92077 * instance. Both arguments are elements. This ensures that this logic can
92078 * operate on stateless trees without any backing instance.
92079 *
92080 * @param {?object} prevElement
92081 * @param {?object} nextElement
92082 * @return {boolean} True if the existing instance should be updated.
92083 * @protected
92084 */
92085
92086function shouldUpdateReactComponent(prevElement, nextElement) {
92087  var prevEmpty = prevElement === null || prevElement === false;
92088  var nextEmpty = nextElement === null || nextElement === false;
92089  if (prevEmpty || nextEmpty) {
92090    return prevEmpty === nextEmpty;
92091  }
92092
92093  var prevType = typeof prevElement;
92094  var nextType = typeof nextElement;
92095  if (prevType === 'string' || prevType === 'number') {
92096    return nextType === 'string' || nextType === 'number';
92097  } else {
92098    return nextType === 'object' && prevElement.type === nextElement.type && prevElement.key === nextElement.key;
92099  }
92100}
92101
92102module.exports = shouldUpdateReactComponent;
92103},{}],141:[function(_dereq_,module,exports){
92104/**
92105 * Copyright 2013-present, Facebook, Inc.
92106 * All rights reserved.
92107 *
92108 * This source code is licensed under the BSD-style license found in the
92109 * LICENSE file in the root directory of this source tree. An additional grant
92110 * of patent rights can be found in the PATENTS file in the same directory.
92111 *
92112 * @providesModule traverseAllChildren
92113 */
92114
92115
92116
92117var ReactCurrentOwner = _dereq_(35);
92118var ReactElement = _dereq_(62);
92119
92120var getIteratorFn = _dereq_(127);
92121var invariant = _dereq_(158);
92122var KeyEscapeUtils = _dereq_(23);
92123var warning = _dereq_(168);
92124
92125var SEPARATOR = '.';
92126var SUBSEPARATOR = ':';
92127
92128/**
92129 * TODO: Test that a single child and an array with one item have the same key
92130 * pattern.
92131 */
92132
92133var didWarnAboutMaps = false;
92134
92135/**
92136 * Generate a key string that identifies a component within a set.
92137 *
92138 * @param {*} component A component that could contain a manual key.
92139 * @param {number} index Index that is used if a manual key is not provided.
92140 * @return {string}
92141 */
92142function getComponentKey(component, index) {
92143  // Do some typechecking here since we call this blindly. We want to ensure
92144  // that we don't block potential future ES APIs.
92145  if (component && typeof component === 'object' && component.key != null) {
92146    // Explicit key
92147    return KeyEscapeUtils.escape(component.key);
92148  }
92149  // Implicit key determined by the index in the set
92150  return index.toString(36);
92151}
92152
92153/**
92154 * @param {?*} children Children tree container.
92155 * @param {!string} nameSoFar Name of the key path so far.
92156 * @param {!function} callback Callback to invoke with each child found.
92157 * @param {?*} traverseContext Used to pass information throughout the traversal
92158 * process.
92159 * @return {!number} The number of children in this subtree.
92160 */
92161function traverseAllChildrenImpl(children, nameSoFar, callback, traverseContext) {
92162  var type = typeof children;
92163
92164  if (type === 'undefined' || type === 'boolean') {
92165    // All of the above are perceived as null.
92166    children = null;
92167  }
92168
92169  if (children === null || type === 'string' || type === 'number' || ReactElement.isValidElement(children)) {
92170    callback(traverseContext, children,
92171    // If it's the only child, treat the name as if it was wrapped in an array
92172    // so that it's consistent if the number of children grows.
92173    nameSoFar === '' ? SEPARATOR + getComponentKey(children, 0) : nameSoFar);
92174    return 1;
92175  }
92176
92177  var child;
92178  var nextName;
92179  var subtreeCount = 0; // Count of children found in the current subtree.
92180  var nextNamePrefix = nameSoFar === '' ? SEPARATOR : nameSoFar + SUBSEPARATOR;
92181
92182  if (Array.isArray(children)) {
92183    for (var i = 0; i < children.length; i++) {
92184      child = children[i];
92185      nextName = nextNamePrefix + getComponentKey(child, i);
92186      subtreeCount += traverseAllChildrenImpl(child, nextName, callback, traverseContext);
92187    }
92188  } else {
92189    var iteratorFn = getIteratorFn(children);
92190    if (iteratorFn) {
92191      var iterator = iteratorFn.call(children);
92192      var step;
92193      if (iteratorFn !== children.entries) {
92194        var ii = 0;
92195        while (!(step = iterator.next()).done) {
92196          child = step.value;
92197          nextName = nextNamePrefix + getComponentKey(child, ii++);
92198          subtreeCount += traverseAllChildrenImpl(child, nextName, callback, traverseContext);
92199        }
92200      } else {
92201        if ("development" !== 'production') {
92202          "development" !== 'production' ? warning(didWarnAboutMaps, 'Using Maps as children is not yet fully supported. It is an ' + 'experimental feature that might be removed. Convert it to a ' + 'sequence / iterable of keyed ReactElements instead.') : void 0;
92203          didWarnAboutMaps = true;
92204        }
92205        // Iterator will provide entry [k,v] tuples rather than values.
92206        while (!(step = iterator.next()).done) {
92207          var entry = step.value;
92208          if (entry) {
92209            child = entry[1];
92210            nextName = nextNamePrefix + KeyEscapeUtils.escape(entry[0]) + SUBSEPARATOR + getComponentKey(child, 0);
92211            subtreeCount += traverseAllChildrenImpl(child, nextName, callback, traverseContext);
92212          }
92213        }
92214      }
92215    } else if (type === 'object') {
92216      var addendum = '';
92217      if ("development" !== 'production') {
92218        addendum = ' If you meant to render a collection of children, use an array ' + 'instead or wrap the object using createFragment(object) from the ' + 'React add-ons.';
92219        if (children._isReactElement) {
92220          addendum = ' It looks like you\'re using an element created by a different ' + 'version of React. Make sure to use only one copy of React.';
92221        }
92222        if (ReactCurrentOwner.current) {
92223          var name = ReactCurrentOwner.current.getName();
92224          if (name) {
92225            addendum += ' Check the render method of `' + name + '`.';
92226          }
92227        }
92228      }
92229      var childrenString = String(children);
92230      !false ? "development" !== 'production' ? invariant(false, 'Objects are not valid as a React child (found: %s).%s', childrenString === '[object Object]' ? 'object with keys {' + Object.keys(children).join(', ') + '}' : childrenString, addendum) : invariant(false) : void 0;
92231    }
92232  }
92233
92234  return subtreeCount;
92235}
92236
92237/**
92238 * Traverses children that are typically specified as `props.children`, but
92239 * might also be specified through attributes:
92240 *
92241 * - `traverseAllChildren(this.props.children, ...)`
92242 * - `traverseAllChildren(this.props.leftPanelChildren, ...)`
92243 *
92244 * The `traverseContext` is an optional argument that is passed through the
92245 * entire traversal. It can be used to store accumulations or anything else that
92246 * the callback might find relevant.
92247 *
92248 * @param {?*} children Children tree object.
92249 * @param {!function} callback To invoke upon traversing each child.
92250 * @param {?*} traverseContext Context for traversal.
92251 * @return {!number} The number of children in this subtree.
92252 */
92253function traverseAllChildren(children, callback, traverseContext) {
92254  if (children == null) {
92255    return 0;
92256  }
92257
92258  return traverseAllChildrenImpl(children, '', callback, traverseContext);
92259}
92260
92261module.exports = traverseAllChildren;
92262},{"127":127,"158":158,"168":168,"23":23,"35":35,"62":62}],142:[function(_dereq_,module,exports){
92263/**
92264 * Copyright 2015-present, Facebook, Inc.
92265 * All rights reserved.
92266 *
92267 * This source code is licensed under the BSD-style license found in the
92268 * LICENSE file in the root directory of this source tree. An additional grant
92269 * of patent rights can be found in the PATENTS file in the same directory.
92270 *
92271 * @providesModule validateDOMNesting
92272 */
92273
92274
92275
92276var _assign = _dereq_(169);
92277
92278var emptyFunction = _dereq_(150);
92279var warning = _dereq_(168);
92280
92281var validateDOMNesting = emptyFunction;
92282
92283if ("development" !== 'production') {
92284  // This validation code was written based on the HTML5 parsing spec:
92285  // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-scope
92286  //
92287  // Note: this does not catch all invalid nesting, nor does it try to (as it's
92288  // not clear what practical benefit doing so provides); instead, we warn only
92289  // for cases where the parser will give a parse tree differing from what React
92290  // intended. For example, <b><div></div></b>
vendor: 6,723 bytes, lines 92290-92452
92290 is invalid but we don't warn
92291  // because it still parses correctly; we do warn for other cases like nested
92292  // <p> tags where the beginning of the second element implicitly closes the
92293  // first, causing a confusing mess.
92294
92295  // https://html.spec.whatwg.org/multipage/syntax.html#special
92296  var specialTags = ['address', 'applet', 'area', 'article', 'aside', 'base', 'basefont', 'bgsound', 'blockquote', 'body', 'br', 'button', 'caption', 'center', 'col', 'colgroup', 'dd', 'details', 'dir', 'div', 'dl', 'dt', 'embed', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'frame', 'frameset', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'iframe', 'img', 'input', 'isindex', 'li', 'link', 'listing', 'main', 'marquee', 'menu', 'menuitem', 'meta', 'nav', 'noembed', 'noframes', 'noscript', 'object', 'ol', 'p', 'param', 'plaintext', 'pre', 'script', 'section', 'select', 'source', 'style', 'summary', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'title', 'tr', 'track', 'ul', 'wbr', 'xmp'];
92297
92298  // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-scope
92299  var inScopeTags = ['applet', 'caption', 'html', 'table', 'td', 'th', 'marquee', 'object', 'template',
92300
92301  // https://html.spec.whatwg.org/multipage/syntax.html#html-integration-point
92302  // TODO: Distinguish by namespace here -- for <title>, including it here
92303  // errs on the side of fewer warnings
92304  'foreignObject', 'desc', 'title'];
92305
92306  // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-button-scope
92307  var buttonScopeTags = inScopeTags.concat(['button']);
92308
92309  // https://html.spec.whatwg.org/multipage/syntax.html#generate-implied-end-tags
92310  var impliedEndTags = ['dd', 'dt', 'li', 'option', 'optgroup', 'p', 'rp', 'rt'];
92311
92312  var emptyAncestorInfo = {
92313    current: null,
92314
92315    formTag: null,
92316    aTagInScope: null,
92317    buttonTagInScope: null,
92318    nobrTagInScope: null,
92319    pTagInButtonScope: null,
92320
92321    listItemTagAutoclosing: null,
92322    dlItemTagAutoclosing: null
92323  };
92324
92325  var updatedAncestorInfo = function (oldInfo, tag, instance) {
92326    var ancestorInfo = _assign({}, oldInfo || emptyAncestorInfo);
92327    var info = { tag: tag, instance: instance };
92328
92329    if (inScopeTags.indexOf(tag) !== -1) {
92330      ancestorInfo.aTagInScope = null;
92331      ancestorInfo.buttonTagInScope = null;
92332      ancestorInfo.nobrTagInScope = null;
92333    }
92334    if (buttonScopeTags.indexOf(tag) !== -1) {
92335      ancestorInfo.pTagInButtonScope = null;
92336    }
92337
92338    // See rules for 'li', 'dd', 'dt' start tags in
92339    // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody
92340    if (specialTags.indexOf(tag) !== -1 && tag !== 'address' && tag !== 'div' && tag !== 'p') {
92341      ancestorInfo.listItemTagAutoclosing = null;
92342      ancestorInfo.dlItemTagAutoclosing = null;
92343    }
92344
92345    ancestorInfo.current = info;
92346
92347    if (tag === 'form') {
92348      ancestorInfo.formTag = info;
92349    }
92350    if (tag === 'a') {
92351      ancestorInfo.aTagInScope = info;
92352    }
92353    if (tag === 'button') {
92354      ancestorInfo.buttonTagInScope = info;
92355    }
92356    if (tag === 'nobr') {
92357      ancestorInfo.nobrTagInScope = info;
92358    }
92359    if (tag === 'p') {
92360      ancestorInfo.pTagInButtonScope = info;
92361    }
92362    if (tag === 'li') {
92363      ancestorInfo.listItemTagAutoclosing = info;
92364    }
92365    if (tag === 'dd' || tag === 'dt') {
92366      ancestorInfo.dlItemTagAutoclosing = info;
92367    }
92368
92369    return ancestorInfo;
92370  };
92371
92372  /**
92373   * Returns whether
92374   */
92375  var isTagValidWithParent = function (tag, parentTag) {
92376    // First, let's check if we're in an unusual parsing mode...
92377    switch (parentTag) {
92378      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inselect
92379      case 'select':
92380        return tag === 'option' || tag === 'optgroup' || tag === '#text';
92381      case 'optgroup':
92382        return tag === 'option' || tag === '#text';
92383      // Strictly speaking, seeing an <option> doesn't mean we're in a <select>
92384      // but
92385      case 'option':
92386        return tag === '#text';
92387
92388      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intd
92389      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incaption
92390      // No special behavior since these rules fall back to "in body" mode for
92391      // all except special table nodes which cause bad parsing behavior anyway.
92392
92393      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intr
92394      case 'tr':
92395        return tag === 'th' || tag === 'td' || tag === 'style' || tag === 'script' || tag === 'template';
92396
92397      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intbody
92398      case 'tbody':
92399      case 'thead':
92400      case 'tfoot':
92401        return tag === 'tr' || tag === 'style' || tag === 'script' || tag === 'template';
92402
92403      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incolgroup
92404      case 'colgroup':
92405        return tag === 'col' || tag === 'template';
92406
92407      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intable
92408      case 'table':
92409        return tag === 'caption' || tag === 'colgroup' || tag === 'tbody' || tag === 'tfoot' || tag === 'thead' || tag === 'style' || tag === 'script' || tag === 'template';
92410
92411      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inhead
92412      case 'head':
92413        return tag === 'base' || tag === 'basefont' || tag === 'bgsound' || tag === 'link' || tag === 'meta' || tag === 'title' || tag === 'noscript' || tag === 'noframes' || tag === 'style' || tag === 'script' || tag === 'template';
92414
92415      // https://html.spec.whatwg.org/multipage/semantics.html#the-html-element
92416      case 'html':
92417        return tag === 'head' || tag === 'body';
92418      case '#document':
92419        return tag === 'html';
92420    }
92421
92422    // Probably in the "in body" parsing mode, so we outlaw only tag combos
92423    // where the parsing rules cause implicit opens or closes to be added.
92424    // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody
92425    switch (tag) {
92426      case 'h1':
92427      case 'h2':
92428      case 'h3':
92429      case 'h4':
92430      case 'h5':
92431      case 'h6':
92432        return parentTag !== 'h1' && parentTag !== 'h2' && parentTag !== 'h3' && parentTag !== 'h4' && parentTag !== 'h5' && parentTag !== 'h6';
92433
92434      case 'rp':
92435      case 'rt':
92436        return impliedEndTags.indexOf(parentTag) === -1;
92437
92438      case 'body':
92439      case 'caption':
92440      case 'col':
92441      case 'colgroup':
92442      case 'frame':
92443      case 'head':
92444      case 'html':
92445      case 'tbody':
92446      case 'td':
92447      case 'tfoot':
92448      case 'th':
92449      case 'thead':
92450      case 'tr':
92451        // These tags are only valid with a few parents that have special child
92452        // parsing rules -- if we're down here, then none of those matched and
92453        // so we allow it only if we don't know what the parent is, as all other
92454        // cases are invalid.
92455        return parentTag == null;
92456    }
92457
92458    return true;
92459  };
92460
92461  /**
92462   * Returns whether
92463   */
92464  var findInvalidAncestorForTag = function (tag, ancestorInfo) {
92465    switch (tag) {
92466      case 'address':
92467      case 'article':
92468      case 'aside':
92469      case 'blockquote':
92470      case 'center':
92471      case 'details':
92472      case 'dialog':
92473      case 'dir':
92474      case 'div':
92475      case 'dl':
92476      case 'fieldset':
92477      case 'figcaption':
92478      case 'figure':
92479      case 'footer':
92480      case 'header':
92481      case 'hgroup':
92482      case 'main':
92483      case 'menu':
92484      case 'nav':
92485      case 'ol':
92486      case 'p':
92487      case 'section':
92488      case 'summary':
92489      case 'ul':
92490
92491      case 'pre':
92492      case 'listing':
92493
92494      case 'table':
92495
92496      case 'hr':
92497
92498      case 'xmp':
92499
92500      case 'h1':
92501      case 'h2':
92502      case 'h3':
92503      case 'h4':
92504      case 'h5':
92505      case 'h6':
92506        return ancestorInfo.pTagInButtonScope;
92507
92508      case 'form':
92509        return ancestorInfo.formTag || ancestorInfo.pTagInButtonScope;
92510
92511      case 'li':
92512        return ancestorInfo.listItemTagAutoclosing;
92513
92514      case 'dd':
92515      case 'dt':
92516        return ancestorInfo.dlItemTagAutoclosing;
92517
92518      case 'button':
92519        return ancestorInfo.buttonTagInScope;
92520
92521      case 'a':
92522        // Spec says something about storing a list of markers, but it sounds
92523        // equivalent to this check.
92524        return ancestorInfo.aTagInScope;
92525
92526      case 'nobr':
92527        return ancestorInfo.nobrTagInScope;
92528    }
92529
92530    return null;
92531  };
92532
92533  /**
92534   * Given a ReactCompositeComponent instance, return a list of its recursive
92535   * owners, starting at the root and ending with the instance itself.
92536   */
92537  var findOwnerStack = function (instance) {
92538    if (!instance) {
92539      return [];
92540    }
92541
92542    var stack = [];
92543    do {
92544      stack.push(instance);
92545    } while (instance = instance._currentElement._owner);
92546    stack.reverse();
92547    return stack;
92548  };
92549
92550  var didWarn = {};
92551
92552  validateDOMNesting = function (childTag, childInstance, ancestorInfo) {
92553    ancestorInfo = ancestorInfo || emptyAncestorInfo;
92554    var parentInfo = ancestorInfo.current;
92555    var parentTag = parentInfo && parentInfo.tag;
92556
92557    var invalidParent = isTagValidWithParent(childTag, parentTag) ? null : parentInfo;
92558    var invalidAncestor = invalidParent ? null : findInvalidAncestorForTag(childTag, ancestorInfo);
92559    var problematic = invalidParent || invalidAncestor;
92560
92561    if (problematic) {
92562      var ancestorTag = problematic.tag;
92563      var ancestorInstance = problematic.instance;
92564
92565      var childOwner = childInstance && childInstance._currentElement._owner;
92566      var ancestorOwner = ancestorInstance && ancestorInstance._currentElement._owner;
92567
92568      var childOwners = findOwnerStack(childOwner);
92569      var ancestorOwners = findOwnerStack(ancestorOwner);
92570
92571      var minStackLen = Math.min(childOwners.length, ancestorOwners.length);
92572      var i;
92573
92574      var deepestCommon = -1;
92575      for (i = 0; i < minStackLen; i++) {
92576        if (childOwners[i] === ancestorOwners[i]) {
92577          deepestCommon = i;
92578        } else {
92579          break;
92580        }
92581      }
92582
92583      var UNKNOWN = '(unknown)';
92584      var childOwnerNames = childOwners.slice(deepestCommon + 1).map(function (inst) {
92585        return inst.getName() || UNKNOWN;
92586      });
92587      var ancestorOwnerNames = ancestorOwners.slice(deepestCommon + 1).map(function (inst) {
92588        return inst.getName() || UNKNOWN;
92589      });
92590      var ownerInfo = [].concat(
92591      // If the parent and child instances have a common owner ancestor, start
92592      // with that -- otherwise we just start with the parent's owners.
92593      deepestCommon !== -1 ? childOwners[deepestCommon].getName() || UNKNOWN : [], ancestorOwnerNames, ancestorTag,
92594      // If we're warning about an invalid (non-parent) ancestry, add '...'
92595      invalidAncestor ? ['...'] : [], childOwnerNames, childTag).join(' > ');
92596
92597      var warnKey = !!invalidParent + '|' + childTag + '|' + ancestorTag + '|' + ownerInfo;
92598      if (didWarn[warnKey]) {
92599        return;
92600      }
92601      didWarn[warnKey] = true;
92602
92603      var tagDisplayName = childTag;
92604      if (childTag !== '#text') {
92605        tagDisplayName = '<' + childTag + '>';
92606      }
92607
92608      if (invalidParent) {
92609        var info = '';
92610        if (ancestorTag === 'table' && childTag === 'tr') {
92611          info += ' Add a <tbody> to your code to match the DOM tree generated by ' + 'the browser.';
92612        }
92613        "development" !== 'production' ? warning(false, 'validateDOMNesting(...): %s cannot appear as a child of <%s>. ' + 'See %s.%s', tagDisplayName, ancestorTag, ownerInfo, info) : void 0;
92614      } else {
92615        "development" !== 'production' ? warning(false, 'validateDOMNesting(...): %s cannot appear as a descendant of ' + '<%s>. See %s.', tagDisplayName, ancestorTag, ownerInfo) : void 0;
92616      }
92617    }
92618  };
92619
92620  validateDOMNesting.updatedAncestorInfo = updatedAncestorInfo;
92621
92622  // For testing
92623  validateDOMNesting.isTagValidInContext = function (tag, ancestorInfo) {
92624    ancestorInfo = ancestorInfo || emptyAncestorInfo;
92625    var parentInfo = ancestorInfo.current;
92626    var parentTag = parentInfo && parentInfo.tag;
92627    return isTagValidWithParent(tag, parentTag) && !findInvalidAncestorForTag(tag, ancestorInfo);
92628  };
92629}
92630
92631module.exports = validateDOMNesting;
92632},{"150":150,"168":168,"169":169}],143:[function(_dereq_,module,exports){
92633'use strict';
92634
92635/**
92636 * Copyright (c) 2013-present, Facebook, Inc.
92637 *
92638 * Licensed under the Apache License, Version 2.0 (the "License");
92639 * you may not use this file except in compliance with the License.
92640 * You may obtain a copy of the License at
92641 *
92642 * http://www.apache.org/licenses/LICENSE-2.0
92643 *
92644 * Unless required by applicable law or agreed to in writing, software
92645 * distributed under the License is distributed on an "AS IS" BASIS,
92646 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
92647 * See the License for the specific language governing permissions and
92648 * limitations under the License.
92649 *
92650 * @typechecks
92651 */
92652
92653var emptyFunction = _dereq_(150);
92654
92655/**
92656 * Upstream version of event listener. Does not take into account specific
92657 * nature of platform.
92658 */
92659var EventListener = {
92660  /**
92661   * Listen to DOM events during the bubble phase.
92662   *
92663   * @param {DOMEventTarget} target DOM element to register listener on.
92664   * @param {string} eventType Event type, e.g. 'click' or 'mouseover'.
92665   * @param {function} callback Callback function.
92666   * @return {object} Object with a `remove` method.
92667   */
92668  listen: function (target, eventType, callback) {
92669    if (target.addEventListener) {
92670      target.addEventListener(eventType, callback, false);
92671      return {
92672        remove: function () {
92673          target.removeEventListener(eventType, callback, false);
92674        }
92675      };
92676    } else if (target.attachEvent) {
92677      target.attachEvent('on' + eventType, callback);
92678      return {
92679        remove: function () {
92680          target.detachEvent('on' + eventType, callback);
92681        }
92682      };
92683    }
92684  },
92685
92686  /**
92687   * Listen to DOM events during the capture phase.
92688   *
92689   * @param {DOMEventTarget} target DOM element to register listener on.
92690   * @param {string} eventType Event type, e.g. 'click' or 'mouseover'.
92691   * @param {function} callback Callback function.
92692   * @return {object} Object with a `remove` method.
92693   */
92694  capture: function (target, eventType, callback) {
92695    if (target.addEventListener) {
92696      target.addEventListener(eventType, callback, true);
92697      return {
92698        remove: function () {
92699          target.removeEventListener(eventType, callback, true);
92700        }
92701      };
92702    } else {
92703      if ("development" !== 'production') {
92704        console.error('Attempted to listen to events during the capture phase on a ' + 'browser that does not support the capture phase. Your application ' + 'will not receive some events.');
92705      }
92706      return {
92707        remove: emptyFunction
92708      };
92709    }
92710  },
92711
92712  registerDefault: function () {}
92713};
92714
92715module.exports = EventListener;
92716},{"150":150}],144:[function(_dereq_,module,exports){
92717/**
92718 * Copyright (c) 2013-present, Facebook, Inc.
92719 * All rights reserved.
92720 *
92721 * This source code is licensed under the BSD-style license found in the
92722 * LICENSE file in the root directory of this source tree. An additional grant
92723 * of patent rights can be found in the PATENTS file in the same directory.
92724 *
92725 */
92726
92727
92728
92729var canUseDOM = !!(typeof window !== 'undefined' && window.document && window.document.createElement);
92730
92731/**
92732 * Simple, lightweight module assisting with the detection and context of
92733 * Worker. Helps avoid circular dependencies and allows code to reason about
92734 * whether or not they are in a Worker, even if they never include the main
92735 * `ReactWorker` dependency.
92736 */
92737var ExecutionEnvironment = {
92738
92739  canUseDOM: canUseDOM,
92740
92741  canUseWorkers: typeof Worker !== 'undefined',
92742
92743  canUseEventListeners: canUseDOM && !!(window.addEventListener || window.attachEvent),
92744
92745  canUseViewport: canUseDOM && !!window.screen,
92746
92747  isInWorker: !canUseDOM // For now, this is true - might change in the future.
92748
92749};
92750
92751module.exports = ExecutionEnvironment;
92752},{}],145:[function(_dereq_,module,exports){
92753"use strict";
92754
92755/**
92756 * Copyright (c) 2013-present, Facebook, Inc.
92757 * All rights reserved.
92758 *
92759 * This source code is licensed under the BSD-style license found in the
92760 * LICENSE file in the root directory of this source tree. An additional grant
92761 * of patent rights can be found in the PATENTS file in the same directory.
92762 *
92763 * @typechecks
92764 */
92765
92766var _hyphenPattern = /-(.)/g;
92767
92768/**
92769 * Camelcases a hyphenated string, for example:
92770 *
92771 *   > camelize('background-color')
92772 *   < "backgroundColor"
92773 *
92774 * @param {string} string
92775 * @return {string}
92776 */
92777function camelize(string) {
92778  return string.replace(_hyphenPattern, function (_, character) {
92779    return character.toUpperCase();
92780  });
92781}
92782
92783module.exports = camelize;
92784},{}],146:[function(_dereq_,module,exports){
92785/**
92786 * Copyright (c) 2013-present, Facebook, Inc.
92787 * All rights reserved.
92788 *
92789 * This source code is licensed under the BSD-style license found in the
92790 * LICENSE file in the root directory of this source tree. An additional grant
92791 * of patent rights can be found in the PATENTS file in the same directory.
92792 *
92793 * @typechecks
92794 */
92795
92796
92797
92798var camelize = _dereq_(145);
92799
92800var msPattern = /^-ms-/;
92801
92802/**
92803 * Camelcases a hyphenated CSS property name, for example:
92804 *
92805 *   > camelizeStyleName('background-color')
92806 *   < "backgroundColor"
92807 *   > camelizeStyleName('-moz-transition')
92808 *   < "MozTransition"
92809 *   > camelizeStyleName('-ms-transition')
92810 *   < "msTransition"
92811 *
92812 * As Andi Smith suggests
92813 * (http://www.andismith.com/blog/2012/02/modernizr-prefixed/), an `-ms` prefix
92814 * is converted to lowercase `ms`.
92815 *
92816 * @param {string} string
92817 * @return {string}
92818 */
92819function camelizeStyleName(string) {
92820  return camelize(string.replace(msPattern, 'ms-'));
92821}
92822
92823module.exports = camelizeStyleName;
92824},{"145":145}],147:[function(_dereq_,module,exports){
92825'use strict';
92826
92827/**
92828 * Copyright (c) 2013-present, Facebook, Inc.
92829 * All rights reserved.
92830 *
92831 * This source code is licensed under the BSD-style license found in the
92832 * LICENSE file in the root directory of this source tree. An additional grant
92833 * of patent rights can be found in the PATENTS file in the same directory.
92834 *
92835 * @typechecks
92836 */
92837
92838var isTextNode = _dereq_(160);
92839
92840/*eslint-disable no-bitwise */
92841
92842/**
92843 * Checks if a given DOM node contains or is another DOM node.
92844 *
92845 * @param {?DOMNode} outerNode Outer DOM node.
92846 * @param {?DOMNode} innerNode Inner DOM node.
92847 * @return {boolean} True if `outerNode` contains or is `innerNode`.
92848 */
92849function containsNode(outerNode, innerNode) {
92850  if (!outerNode || !innerNode) {
92851    return false;
92852  } else if (outerNode === innerNode) {
92853    return true;
92854  } else if (isTextNode(outerNode)) {
92855    return false;
92856  } else if (isTextNode(innerNode)) {
92857    return containsNode(outerNode, innerNode.parentNode);
92858  } else if (outerNode.contains) {
92859    return outerNode.contains(innerNode);
92860  } else if (outerNode.compareDocumentPosition) {
92861    return !!(outerNode.compareDocumentPosition(innerNode) & 16);
92862  } else {
92863    return false;
92864  }
92865}
92866
92867module.exports = containsNode;
92868},{"160":160}],148:[function(_dereq_,module,exports){
92869'use strict';
92870
92871/**
92872 * Copyright (c) 2013-present, Facebook, Inc.
92873 * All rights reserved.
92874 *
92875 * This source code is licensed under the BSD-style license found in the
92876 * LICENSE file in the root directory of this source tree. An additional grant
92877 * of patent rights can be found in the PATENTS file in the same directory.
92878 *
92879 * @typechecks
92880 */
92881
92882var invariant = _dereq_(158);
92883
92884/**
92885 * Convert array-like objects to arrays.
92886 *
92887 * This API assumes the caller knows the contents of the data type. For less
92888 * well defined inputs use createArrayFromMixed.
92889 *
92890 * @param {object|function|filelist} obj
92891 * @return {array}
92892 */
92893function toArray(obj) {
92894  var length = obj.length;
92895
92896  // Some browsers builtin objects can report typeof 'function' (e.g. NodeList
92897  // in old versions of Safari).
92898  !(!Array.isArray(obj) && (typeof obj === 'object' || typeof obj === 'function')) ? "development" !== 'production' ? invariant(false, 'toArray: Array-like object expected') : invariant(false) : void 0;
92899
92900  !(typeof length === 'number') ? "development" !== 'production' ? invariant(false, 'toArray: Object needs a length property') : invariant(false) : void 0;
92901
92902  !(length === 0 || length - 1 in obj) ? "development" !== 'production' ? invariant(false, 'toArray: Object should have keys for indices') : invariant(false) : void 0;
92903
92904  !(typeof obj.callee !== 'function') ? "development" !== 'production' ? invariant(false, 'toArray: Object can\'t be `arguments`. Use rest params ' + '(function(...args) {}) or Array.from() instead.') : invariant(false) : void 0;
92905
92906  // Old IE doesn't give collections access to hasOwnProperty. Assume inputs
92907  // without method will throw during the slice call and skip straight to the
92908  // fallback.
92909  if (obj.hasOwnProperty) {
92910    try {
92911      return Array.prototype.slice.call(obj);
92912    } catch (e) {
92913      // IE < 9 does not support Array#slice on collections objects
92914    }
92915  }
92916
92917  // Fall back to copying key by key. This assumes all keys have a value,
92918  // so will not preserve sparsely populated inputs.
92919  var ret = Array(length);
92920  for (var ii = 0; ii < length; ii++) {
92921    ret[ii] = obj[ii];
92922  }
92923  return ret;
92924}
92925
92926/**
92927 * Perform a heuristic test to determine if an object is "array-like".
92928 *
92929 *   A monk asked Joshu, a Zen master, "Has a dog Buddha nature?"
92930 *   Joshu replied: "Mu."
92931 *
92932 * This function determines if its argument has "array nature": it returns
92933 * true if the argument is an actual array, an `arguments' object, or an
92934 * HTMLCollection (e.g. node.childNodes or node.getElementsByTagName()).
92935 *
92936 * It will return false for other array-like objects like Filelist.
92937 *
92938 * @param {*} obj
92939 * @return {boolean}
92940 */
92941function hasArrayNature(obj) {
92942  return(
92943    // not null/false
92944    !!obj && (
92945    // arrays are objects, NodeLists are functions in Safari
92946    typeof obj == 'object' || typeof obj == 'function') &&
92947    // quacks like an array
92948    'length' in obj &&
92949    // not window
92950    !('setInterval' in obj) &&
92951    // no DOM node should be considered an array-like
92952    // a 'select' element has 'length' and 'item' properties on IE8
92953    typeof obj.nodeType != 'number' && (
92954    // a real array
92955    Array.isArray(obj) ||
92956    // arguments
92957    'callee' in obj ||
92958    // HTMLCollection/NodeList
92959    'item' in obj)
92960  );
92961}
92962
92963/**
92964 * Ensure that the argument is an array by wrapping it in an array if it is not.
92965 * Creates a copy of the argument if it is already an array.
92966 *
92967 * This is mostly useful idiomatically:
92968 *
92969 *   var createArrayFromMixed = require('createArrayFromMixed');
92970 *
92971 *   function takesOneOrMoreThings(things) {
92972 *     things = createArrayFromMixed(things);
92973 *     ...
92974 *   }
92975 *
92976 * This allows you to treat `things' as an array, but accept scalars in the API.
92977 *
92978 * If you need to convert an array-like object, like `arguments`, into an array
92979 * use toArray instead.
92980 *
92981 * @param {*} obj
92982 * @return {array}
92983 */
92984function createArrayFromMixed(obj) {
92985  if (!hasArrayNature(obj)) {
92986    return [obj];
92987  } else if (Array.isArray(obj)) {
92988    return obj.slice();
92989  } else {
92990    return toArray(obj);
92991  }
92992}
92993
92994module.exports = createArrayFromMixed;
92995},{"158":158}],149:[function(_dereq_,module,exports){
92996'use strict';
92997
92998/**
92999 * Copyright (c) 2013-present, Facebook, Inc.
93000 * All rights reserved.
93001 *
93002 * This source code is licensed under the BSD-style license found in the
93003 * LICENSE file in the root directory of this source tree. An additional grant
93004 * of patent rights can be found in the PATENTS file in the same directory.
93005 *
93006 * @typechecks
93007 */
93008
93009/*eslint-disable fb-www/unsafe-html*/
93010
93011var ExecutionEnvironment = _dereq_(144);
93012
93013var createArrayFromMixed = _dereq_(148);
93014var getMarkupWrap = _dereq_(154);
93015var invariant = _dereq_(158);
93016
93017/**
93018 * Dummy container used to render all markup.
93019 */
93020var dummyNode = ExecutionEnvironment.canUseDOM ? document.createElement('div') : null;
93021
93022/**
93023 * Pattern used by `getNodeName`.
93024 */
93025var nodeNamePattern = /^\s*<(\w+)/;
93026
93027/**
93028 * Extracts the `nodeName` of the first element in a string of markup.
93029 *
93030 * @param {string} markup String of markup.
93031 * @return {?string} Node name of the supplied markup.
93032 */
93033function getNodeName(markup) {
93034  var nodeNameMatch = markup.match(nodeNamePattern);
93035  return nodeNameMatch && nodeNameMatch[1].toLowerCase();
93036}
93037
93038/**
93039 * Creates an array containing the nodes rendered from the supplied markup. The
93040 * optionally supplied `handleScript` function will be invoked once for each
93041 * <script> element that is rendered. If no `handleScript` function is supplied,
93042 * an exception is thrown if any <script> elements are rendered.
93043 *
93044 * @param {string} markup A string of valid HTML markup.
93045 * @param {?function} handleScript Invoked once for each rendered <script>.
93046 * @return {array<DOMElement|DOMTextNode>} An array of rendered nodes.
93047 */
93048function createNodesFromMarkup(markup, handleScript) {
93049  var node = dummyNode;
93050  !!!dummyNode ? "development" !== 'production' ? invariant(false, 'createNodesFromMarkup dummy not initialized') : invariant(false) : void 0;
93051  var nodeName = getNodeName(markup);
93052
93053  var wrap = nodeName && getMarkupWrap(nodeName);
93054  if (wrap) {
93055    node.innerHTML = wrap[1] + markup + wrap[2];
93056
93057    var wrapDepth = wrap[0];
93058    while (wrapDepth--) {
93059      node = node.lastChild;
93060    }
93061  } else {
93062    node.innerHTML = markup;
93063  }
93064
93065  var scripts = node.getElementsByTagName('script');
93066  if (scripts.length) {
93067    !handleScript ? "development" !== 'production' ? invariant(false, 'createNodesFromMarkup(...): Unexpected <script> element rendered.') : invariant(false) : void 0;
93068    createArrayFromMixed(scripts).forEach(handleScript);
93069  }
93070
93071  var nodes = Array.from(node.childNodes);
93072  while (node.lastChild) {
93073    node.removeChild(node.lastChild);
93074  }
93075  return nodes;
93076}
93077
93078module.exports = createNodesFromMarkup;
93079},{"144":144,"148":148,"154":154,"158":158}],150:[function(_dereq_,module,exports){
93080"use strict";
93081
93082/**
93083 * Copyright (c) 2013-present, Facebook, Inc.
93084 * All rights reserved.
93085 *
93086 * This source code is licensed under the BSD-style license found in the
93087 * LICENSE file in the root directory of this source tree. An additional grant
93088 * of patent rights can be found in the PATENTS file in the same directory.
93089 *
93090 */
93091
93092function makeEmptyFunction(arg) {
93093  return function () {
93094    return arg;
93095  };
93096}
93097
93098/**
93099 * This function accepts and discards inputs; it has no side effects. This is
93100 * primarily useful idiomatically for overridable function endpoints which
93101 * always need to be callable, since JS lacks a null-call idiom ala Cocoa.
93102 */
93103function emptyFunction() {}
93104
93105emptyFunction.thatReturns = makeEmptyFunction;
93106emptyFunction.thatReturnsFalse = makeEmptyFunction(false);
93107emptyFunction.thatReturnsTrue = makeEmptyFunction(true);
93108emptyFunction.thatReturnsNull = makeEmptyFunction(null);
93109emptyFunction.thatReturnsThis = function () {
93110  return this;
93111};
93112emptyFunction.thatReturnsArgument = function (arg) {
93113  return arg;
93114};
93115
93116module.exports = emptyFunction;
93117},{}],151:[function(_dereq_,module,exports){
93118/**
93119 * Copyright (c) 2013-present, Facebook, Inc.
93120 * All rights reserved.
93121 *
93122 * This source code is licensed under the BSD-style license found in the
93123 * LICENSE file in the root directory of this source tree. An additional grant
93124 * of patent rights can be found in the PATENTS file in the same directory.
93125 *
93126 */
93127
93128
93129
93130var emptyObject = {};
93131
93132if ("development" !== 'production') {
93133  Object.freeze(emptyObject);
93134}
93135
93136module.exports = emptyObject;
93137},{}],152:[function(_dereq_,module,exports){
93138/**
93139 * Copyright (c) 2013-present, Facebook, Inc.
93140 * All rights reserved.
93141 *
93142 * This source code is licensed under the BSD-style license found in the
93143 * LICENSE file in the root directory of this source tree. An additional grant
93144 * of patent rights can be found in the PATENTS file in the same directory.
93145 *
93146 */
93147
93148
93149
93150/**
93151 * @param {DOMElement} node input/textarea to focus
93152 */
93153
93154function focusNode(node) {
93155  // IE8 can throw "Can't move focus to the control because it is invisible,
93156  // not enabled, or of a type that does not accept the focus." for all kinds of
93157  // reasons that are too expensive and fragile to test.
93158  try {
93159    node.focus();
93160  } catch (e) {}
93161}
93162
93163module.exports = focusNode;
93164},{}],153:[function(_dereq_,module,exports){
93165'use strict';
93166
93167/**
93168 * Copyright (c) 2013-present, Facebook, Inc.
93169 * All rights reserved.
93170 *
93171 * This source code is licensed under the BSD-style license found in the
93172 * LICENSE file in the root directory of this source tree. An additional grant
93173 * of patent rights can be found in the PATENTS file in the same directory.
93174 *
93175 * @typechecks
93176 */
93177
93178/* eslint-disable fb-www/typeof-undefined */
93179
93180/**
93181 * Same as document.activeElement but wraps in a try-catch block. In IE it is
93182 * not safe to call document.activeElement if there is nothing focused.
93183 *
93184 * The activeElement will be null only if the document or document body is not
93185 * yet defined.
93186 */
93187function getActiveElement() /*?DOMElement*/{
93188  if (typeof document === 'undefined') {
93189    return null;
93190  }
93191  try {
93192    return document.activeElement || document.body;
93193  } catch (e) {
93194    return document.body;
93195  }
93196}
93197
93198module.exports = getActiveElement;
93199},{}],154:[function(_dereq_,module,exports){
93200'use strict';
93201
93202/**
93203 * Copyright (c) 2013-present, Facebook, Inc.
93204 * All rights reserved.
93205 *
93206 * This source code is licensed under the BSD-style license found in the
93207 * LICENSE file in the root directory of this source tree. An additional grant
93208 * of patent rights can be found in the PATENTS file in the same directory.
93209 *
93210 */
93211
93212/*eslint-disable fb-www/unsafe-html */
93213
93214var ExecutionEnvironment = _dereq_(144);
93215
93216var invariant = _dereq_(158);
93217
93218/**
93219 * Dummy container used to detect which wraps are necessary.
93220 */
93221var dummyNode = ExecutionEnvironment.canUseDOM ? document.createElement('div') : null;
93222
93223/**
93224 * Some browsers cannot use `innerHTML` to render certain elements standalone,
93225 * so we wrap them, render the wrapped nodes, then extract the desired node.
93226 *
93227 * In IE8, certain elements cannot render alone, so wrap all elements ('*').
93228 */
93229
93230var shouldWrap = {};
93231
93232var selectWrap = [1, '<select multiple="true">', '</select>'];
93233var tableWrap = [1, '<table>', '</table>'];
93234var trWrap = [3, '<table><tbody><tr>', '</tr></tbody></table>'];
93235
93236var svgWrap = [1, '<svg xmlns="http://www.w3.org/2000/svg">', '</svg>'];
93237
93238var markupWrap = {
93239  '*': [1, '?<div>', '</div>'],
93240
93241  'area': [1, '<map>', '</map>'],
93242  'col': [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
93243  'legend': [1, '<fieldset>', '</fieldset>'],
93244  'param': [1, '<object>', '</object>'],
93245  'tr': [2, '<table><tbody>', '</tbody></table>'],
93246
93247  'optgroup': selectWrap,
93248  'option': selectWrap,
93249
93250  'caption': tableWrap,
93251  'colgroup': tableWrap,
93252  'tbody': tableWrap,
93253  'tfoot': tableWrap,
93254  'thead': tableWrap,
93255
93256  'td': trWrap,
93257  'th': trWrap
93258};
93259
93260// Initialize the SVG elements since we know they'll always need to be wrapped
93261// consistently. If they are created inside a <div> they will be initialized in
93262// the wrong namespace (and will not display).
93263var svgElements = ['circle', 'clipPath', 'defs', 'ellipse', 'g', 'image', 'line', 'linearGradient', 'mask', 'path', 'pattern', 'polygon', 'polyline', 'radialGradient', 'rect', 'stop', 'text', 'tspan'];
93264svgElements.forEach(function (nodeName) {
93265  markupWrap[nodeName] = svgWrap;
93266  shouldWrap[nodeName] = true;
93267});
93268
93269/**
93270 * Gets the markup wrap configuration for the supplied `nodeName`.
93271 *
93272 * NOTE: This lazily detects which wraps are necessary for the current browser.
93273 *
93274 * @param {string} nodeName Lowercase `nodeName`.
93275 * @return {?array} Markup wrap configuration, if applicable.
93276 */
93277function getMarkupWrap(nodeName) {
93278  !!!dummyNode ? "development" !== 'production' ? invariant(false, 'Markup wrapping node not initialized') : invariant(false) : void 0;
93279  if (!markupWrap.hasOwnProperty(nodeName)) {
93280    nodeName = '*';
93281  }
93282  if (!shouldWrap.hasOwnProperty(nodeName)) {
93283    if (nodeName === '*') {
93284      dummyNode.innerHTML = '<link />';
93285    } else {
93286      dummyNode.innerHTML = '<' + nodeName + '></' + nodeName + '>';
93287    }
93288    shouldWrap[nodeName] = !dummyNode.firstChild;
93289  }
93290  return shouldWrap[nodeName] ? markupWrap[nodeName] : null;
93291}
93292
93293module.exports = getMarkupWrap;
93294},{"144":144,"158":158}],155:[function(_dereq_,module,exports){
93295/**
93296 * Copyright (c) 2013-present, Facebook, Inc.
93297 * All rights reserved.
93298 *
93299 * This source code is licensed under the BSD-style license found in the
93300 * LICENSE file in the root directory of this source tree. An additional grant
93301 * of patent rights can be found in the PATENTS file in the same directory.
93302 *
93303 * @typechecks
93304 */
93305
93306
93307
93308/**
93309 * Gets the scroll position of the supplied element or window.
93310 *
93311 * The return values are unbounded, unlike `getScrollPosition`. This means they
93312 * may be negative or exceed the element boundaries (which is possible using
93313 * inertial scrolling).
93314 *
93315 * @param {DOMWindow|DOMElement} scrollable
93316 * @return {object} Map with `x` and `y` keys.
93317 */
93318
93319function getUnboundedScrollPosition(scrollable) {
93320  if (scrollable === window) {
93321    return {
93322      x: window.pageXOffset || document.documentElement.scrollLeft,
93323      y: window.pageYOffset || document.documentElement.scrollTop
93324    };
93325  }
93326  return {
93327    x: scrollable.scrollLeft,
93328    y: scrollable.scrollTop
93329  };
93330}
93331
93332module.exports = getUnboundedScrollPosition;
93333},{}],156:[function(_dereq_,module,exports){
93334'use strict';
93335
93336/**
93337 * Copyright (c) 2013-present, Facebook, Inc.
93338 * All rights reserved.
93339 *
93340 * This source code is licensed under the BSD-style license found in the
93341 * LICENSE file in the root directory of this source tree. An additional grant
93342 * of patent rights can be found in the PATENTS file in the same directory.
93343 *
93344 * @typechecks
93345 */
93346
93347var _uppercasePattern = /([A-Z])/g;
93348
93349/**
93350 * Hyphenates a camelcased string, for example:
93351 *
93352 *   > hyphenate('backgroundColor')
93353 *   < "background-color"
93354 *
93355 * For CSS style names, use `hyphenateStyleName` instead which works properly
93356 * with all vendor prefixes, including `ms`.
93357 *
93358 * @param {string} string
93359 * @return {string}
93360 */
93361function hyphenate(string) {
93362  return string.replace(_uppercasePattern, '-$1').toLowerCase();
93363}
93364
93365module.exports = hyphenate;
93366},{}],157:[function(_dereq_,module,exports){
93367/**
93368 * Copyright (c) 2013-present, Facebook, Inc.
93369 * All rights reserved.
93370 *
93371 * This source code is licensed under the BSD-style license found in the
93372 * LICENSE file in the root directory of this source tree. An additional grant
93373 * of patent rights can be found in the PATENTS file in the same directory.
93374 *
93375 * @typechecks
93376 */
93377
93378
93379
93380var hyphenate = _dereq_(156);
93381
93382var msPattern = /^ms-/;
93383
93384/**
93385 * Hyphenates a camelcased CSS property name, for example:
93386 *
93387 *   > hyphenateStyleName('backgroundColor')
93388 *   < "background-color"
93389 *   > hyphenateStyleName('MozTransition')
93390 *   < "-moz-transition"
93391 *   > hyphenateStyleName('msTransition')
93392 *   < "-ms-transition"
93393 *
93394 * As Modernizr suggests (http://modernizr.com/docs/#prefixed), an `ms` prefix
93395 * is converted to `-ms-`.
93396 *
93397 * @param {string} string
93398 * @return {string}
93399 */
93400function hyphenateStyleName(string) {
93401  return hyphenate(string).replace(msPattern, '-ms-');
93402}
93403
93404module.exports = hyphenateStyleName;
93405},{"156":156}],158:[function(_dereq_,module,exports){
93406/**
93407 * Copyright (c) 2013-present, Facebook, Inc.
93408 * All rights reserved.
93409 *
93410 * This source code is licensed under the BSD-style license found in the
93411 * LICENSE file in the root directory of this source tree. An additional grant
93412 * of patent rights can be found in the PATENTS file in the same directory.
93413 *
93414 */
93415
93416
93417
93418/**
93419 * Use invariant() to assert state which your program assumes to be true.
93420 *
93421 * Provide sprintf-style format (only %s is supported) and arguments
93422 * to provide information about what broke and what you were
93423 * expecting.
93424 *
93425 * The invariant message will be stripped in production, but the invariant
93426 * will remain to ensure logic does not differ in production.
93427 */
93428
93429function invariant(condition, format, a, b, c, d, e, f) {
93430  if ("development" !== 'production') {
93431    if (format === undefined) {
93432      throw new Error('invariant requires an error message argument');
93433    }
93434  }
93435
93436  if (!condition) {
93437    var error;
93438    if (format === undefined) {
93439      error = new Error('Minified exception occurred; use the non-minified dev environment ' + 'for the full error message and additional helpful warnings.');
93440    } else {
93441      var args = [a, b, c, d, e, f];
93442      var argIndex = 0;
93443      error = new Error(format.replace(/%s/g, function () {
93444        return args[argIndex++];
93445      }));
93446      error.name = 'Invariant Violation';
93447    }
93448
93449    error.framesToPop = 1; // we don't care about invariant's own frame
93450    throw error;
93451  }
93452}
93453
93454module.exports = invariant;
93455},{}],159:[function(_dereq_,module,exports){
93456'use strict';
93457
93458/**
93459 * Copyright (c) 2013-present, Facebook, Inc.
93460 * All rights reserved.
93461 *
93462 * This source code is licensed under the BSD-style license found in the
93463 * LICENSE file in the root directory of this source tree. An additional grant
93464 * of patent rights can be found in the PATENTS file in the same directory.
93465 *
93466 * @typechecks
93467 */
93468
93469/**
93470 * @param {*} object The object to check.
93471 * @return {boolean} Whether or not the object is a DOM node.
93472 */
93473function isNode(object) {
93474  return !!(object && (typeof Node === 'function' ? object instanceof Node : typeof object === 'object' && typeof object.nodeType === 'number' && typeof object.nodeName === 'string'));
93475}
93476
93477module.exports = isNode;
93478},{}],160:[function(_dereq_,module,exports){
93479'use strict';
93480
93481/**
93482 * Copyright (c) 2013-present, Facebook, Inc.
93483 * All rights reserved.
93484 *
93485 * This source code is licensed under the BSD-style license found in the
93486 * LICENSE file in the root directory of this source tree. An additional grant
93487 * of patent rights can be found in the PATENTS file in the same directory.
93488 *
93489 * @typechecks
93490 */
93491
93492var isNode = _dereq_(159);
93493
93494/**
93495 * @param {*} object The object to check.
93496 * @return {boolean} Whether or not the object is a DOM text node.
93497 */
93498function isTextNode(object) {
93499  return isNode(object) && object.nodeType == 3;
93500}
93501
93502module.exports = isTextNode;
93503},{"159":159}],161:[function(_dereq_,module,exports){
93504/**
93505 * Copyright (c) 2013-present, Facebook, Inc.
93506 * All rights reserved.
93507 *
93508 * This source code is licensed under the BSD-style license found in the
93509 * LICENSE file in the root directory of this source tree. An additional grant
93510 * of patent rights can be found in the PATENTS file in the same directory.
93511 *
93512 * @typechecks static-only
93513 */
93514
93515
93516
93517var invariant = _dereq_(158);
93518
93519/**
93520 * Constructs an enumeration with keys equal to their value.
93521 *
93522 * For example:
93523 *
93524 *   var COLORS = keyMirror({blue: null, red: null});
93525 *   var myColor = COLORS.blue;
93526 *   var isColorValid = !!COLORS[myColor];
93527 *
93528 * The last line could not be performed if the values of the generated enum were
93529 * not equal to their keys.
93530 *
93531 *   Input:  {key1: val1, key2: val2}
93532 *   Output: {key1: key1, key2: key2}
93533 *
93534 * @param {object} obj
93535 * @return {object}
93536 */
93537var keyMirror = function (obj) {
93538  var ret = {};
93539  var key;
93540  !(obj instanceof Object && !Array.isArray(obj)) ? "development" !== 'production' ? invariant(false, 'keyMirror(...): Argument must be an object.') : invariant(false) : void 0;
93541  for (key in obj) {
93542    if (!obj.hasOwnProperty(key)) {
93543      continue;
93544    }
93545    ret[key] = key;
93546  }
93547  return ret;
93548};
93549
93550module.exports = keyMirror;
93551},{"158":158}],162:[function(_dereq_,module,exports){
93552"use strict";
93553
93554/**
93555 * Copyright (c) 2013-present, Facebook, Inc.
93556 * All rights reserved.
93557 *
93558 * This source code is licensed under the BSD-style license found in the
93559 * LICENSE file in the root directory of this source tree. An additional grant
93560 * of patent rights can be found in the PATENTS file in the same directory.
93561 *
93562 */
93563
93564/**
93565 * Allows extraction of a minified key. Let's the build system minify keys
93566 * without losing the ability to dynamically use key strings as values
93567 * themselves. Pass in an object with a single key/val pair and it will return
93568 * you the string key of that single record. Suppose you want to grab the
93569 * value for a key 'className' inside of an object. Key/val minification may
93570 * have aliased that key to be 'xa12'. keyOf({className: null}) will return
93571 * 'xa12' in that case. Resolve keys you want to use once at startup time, then
93572 * reuse those resolutions.
93573 */
93574var keyOf = function (oneKeyObj) {
93575  var key;
93576  for (key in oneKeyObj) {
93577    if (!oneKeyObj.hasOwnProperty(key)) {
93578      continue;
93579    }
93580    return key;
93581  }
93582  return null;
93583};
93584
93585module.exports = keyOf;
93586},{}],163:[function(_dereq_,module,exports){
93587/**
93588 * Copyright (c) 2013-present, Facebook, Inc.
93589 * All rights reserved.
93590 *
93591 * This source code is licensed under the BSD-style license found in the
93592 * LICENSE file in the root directory of this source tree. An additional grant
93593 * of patent rights can be found in the PATENTS file in the same directory.
93594 *
93595 */
93596
93597
93598
93599var hasOwnProperty = Object.prototype.hasOwnProperty;
93600
93601/**
93602 * Executes the provided `callback` once for each enumerable own property in the
93603 * object and constructs a new object from the results. The `callback` is
93604 * invoked with three arguments:
93605 *
93606 *  - the property value
93607 *  - the property name
93608 *  - the object being traversed
93609 *
93610 * Properties that are added after the call to `mapObject` will not be visited
93611 * by `callback`. If the values of existing properties are changed, the value
93612 * passed to `callback` will be the value at the time `mapObject` visits them.
93613 * Properties that are deleted before being visited are not visited.
93614 *
93615 * @grep function objectMap()
93616 * @grep function objMap()
93617 *
93618 * @param {?object} object
93619 * @param {function} callback
93620 * @param {*} context
93621 * @return {?object}
93622 */
93623function mapObject(object, callback, context) {
93624  if (!object) {
93625    return null;
93626  }
93627  var result = {};
93628  for (var name in object) {
93629    if (hasOwnProperty.call(object, name)) {
93630      result[name] = callback.call(context, object[name], name, object);
93631    }
93632  }
93633  return result;
93634}
93635
93636module.exports = mapObject;
93637},{}],164:[function(_dereq_,module,exports){
93638/**
93639 * Copyright (c) 2013-present, Facebook, Inc.
93640 * All rights reserved.
93641 *
93642 * This source code is licensed under the BSD-style license found in the
93643 * LICENSE file in the root directory of this source tree. An additional grant
93644 * of patent rights can be found in the PATENTS file in the same directory.
93645 *
93646 * @typechecks static-only
93647 */
93648
93649
93650
93651/**
93652 * Memoizes the return value of a function that accepts one string argument.
93653 *
93654 * @param {function} callback
93655 * @return {function}
93656 */
93657
93658function memoizeStringOnly(callback) {
93659  var cache = {};
93660  return function (string) {
93661    if (!cache.hasOwnProperty(string)) {
93662      cache[string] = callback.call(this, string);
93663    }
93664    return cache[string];
93665  };
93666}
93667
93668module.exports = memoizeStringOnly;
93669},{}],165:[function(_dereq_,module,exports){
93670/**
93671 * Copyright (c) 2013-present, Facebook, Inc.
93672 * All rights reserved.
93673 *
93674 * This source code is licensed under the BSD-style license found in the
93675 * LICENSE file in the root directory of this source tree. An additional grant
93676 * of patent rights can be found in the PATENTS file in the same directory.
93677 *
93678 * @typechecks
93679 */
93680
93681
93682
93683var ExecutionEnvironment = _dereq_(144);
93684
93685var performance;
93686
93687if (ExecutionEnvironment.canUseDOM) {
93688  performance = window.performance || window.msPerformance || window.webkitPerformance;
93689}
93690
93691module.exports = performance || {};
93692},{"144":144}],166:[function(_dereq_,module,exports){
93693'use strict';
93694
93695/**
93696 * Copyright (c) 2013-present, Facebook, Inc.
93697 * All rights reserved.
93698 *
93699 * This source code is licensed under the BSD-style license found in the
93700 * LICENSE file in the root directory of this source tree. An additional grant
93701 * of patent rights can be found in the PATENTS file in the same directory.
93702 *
93703 * @typechecks
93704 */
93705
93706var performance = _dereq_(165);
93707
93708var performanceNow;
93709
93710/**
93711 * Detect if we can use `window.performance.now()` and gracefully fallback to
93712 * `Date.now()` if it doesn't exist. We need to support Firefox < 15 for now
93713 * because of Facebook's testing infrastructure.
93714 */
93715if (performance.now) {
93716  performanceNow = function () {
93717    return performance.now();
93718  };
93719} else {
93720  performanceNow = function () {
93721    return Date.now();
93722  };
93723}
93724
93725module.exports = performanceNow;
93726},{"165":165}],167:[function(_dereq_,module,exports){
93727/**
93728 * Copyright (c) 2013-present, Facebook, Inc.
93729 * All rights reserved.
93730 *
93731 * This source code is licensed under the BSD-style license found in the
93732 * LICENSE file in the root directory of this source tree. An additional grant
93733 * of patent rights can be found in the PATENTS file in the same directory.
93734 *
93735 * @typechecks
93736 * 
93737 */
93738
93739/*eslint-disable no-self-compare */
93740
93741
93742
93743var hasOwnProperty = Object.prototype.hasOwnProperty;
93744
93745/**
93746 * inlined Object.is polyfill to avoid requiring consumers ship their own
93747 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
93748 */
93749function is(x, y) {
93750  // SameValue algorithm
93751  if (x === y) {
93752    // Steps 1-5, 7-10
93753    // Steps 6.b-6.e: +0 != -0
93754    return x !== 0 || 1 / x === 1 / y;
93755  } else {
93756    // Step 6.a: NaN == NaN
93757    return x !== x && y !== y;
93758  }
93759}
93760
93761/**
93762 * Performs equality by iterating through keys on an object and returning false
93763 * when any key has values which are not strictly equal between the arguments.
93764 * Returns true when the values of all keys are strictly equal.
93765 */
93766function shallowEqual(objA, objB) {
93767  if (is(objA, objB)) {
93768    return true;
93769  }
93770
93771  if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) {
93772    return false;
93773  }
93774
93775  var keysA = Object.keys(objA);
93776  var keysB = Object.keys(objB);
93777
93778  if (keysA.length !== keysB.length) {
93779    return false;
93780  }
93781
93782  // Test for A's keys different from B.
93783  for (var i = 0; i < keysA.length; i++) {
93784    if (!hasOwnProperty.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) {
93785      return false;
93786    }
93787  }
93788
93789  return true;
93790}
93791
93792module.exports = shallowEqual;
93793},{}],168:[function(_dereq_,module,exports){
93794/**
93795 * Copyright 2014-2015, Facebook, Inc.
93796 * All rights reserved.
93797 *
93798 * This source code is licensed under the BSD-style license found in the
93799 * LICENSE file in the root directory of this source tree. An additional grant
93800 * of patent rights can be found in the PATENTS file in the same directory.
93801 *
93802 */
93803
93804
93805
93806var emptyFunction = _dereq_(150);
93807
93808/**
93809 * Similar to invariant but only logs a warning if the condition is not met.
93810 * This can be used to log issues in development environments in critical
93811 * paths. Removing the logging code for production environments will keep the
93812 * same logic and follow the same code paths.
93813 */
93814
93815var warning = emptyFunction;
93816
93817if ("development" !== 'production') {
93818  warning = function (condition, format) {
93819    for (var _len = arguments.length, args = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
93820      args[_key - 2] = arguments[_key];
93821    }
93822
93823    if (format === undefined) {
93824      throw new Error('`warning(condition, format, ...args)` requires a warning ' + 'message argument');
93825    }
93826
93827    if (format.indexOf('Failed Composite propType: ') === 0) {
93828      return; // Ignore CompositeComponent proptype check.
93829    }
93830
93831    if (!condition) {
93832      var argIndex = 0;
93833      var message = 'Warning: ' + format.replace(/%s/g, function () {
93834        return args[argIndex++];
93835      });
93836      if (typeof console !== 'undefined') {
93837        console.error(message);
93838      }
93839      try {
93840        // --- Welcome to debugging React ---
93841        // This error was thrown as a convenience so that you can use this stack
93842        // to find the callsite that caused this warning to fire.
93843        throw new Error(message);
93844      } catch (x) {}
93845    }
93846  };
93847}
93848
93849module.exports = warning;
93850},{"150":150}],169:[function(_dereq_,module,exports){
93851/* eslint-disable no-unused-vars */
93852
93853var hasOwnProperty = Object.prototype.hasOwnProperty;
93854var propIsEnumerable = Object.prototype.propertyIsEnumerable;
93855
93856function toObject(val) {
93857	if (val === null || val === undefined) {
93858		throw new TypeError('Object.assign cannot be called with null or undefined');
93859	}
93860
93861	return Object(val);
93862}
93863
93864module.exports = Object.assign || function (target, source) {
93865	var from;
93866	var to = toObject(target);
93867	var symbols;
93868
93869	for (var s = 1; s < arguments.length; s++) {
93870		from = Object(arguments[s]);
93871
93872		for (var key in from) {
93873			if (hasOwnProperty.call(from, key)) {
93874				to[key] = from[key];
93875			}
93876		}
93877
93878		if (Object.getOwnPropertySymbols) {
93879			symbols = Object.getOwnPropertySymbols(from);
93880			for (var i = 0; i < symbols.length; i++) {
93881				if (propIsEnumerable.call(from, symbols[i])) {
93882					to[symbols[i]] = from[symbols[i]];
93883				}
93884			}
93885		}
93886	}
93887
93888	return to;
93889};
93890
93891},{}]},{},[92])(92)
93892});
93893/**
93894 * ReactDOM v15.0.2
93895 *
93896 * Copyright 2013-present, Facebook, Inc.
93897 * All rights reserved.
93898 *
93899 * This source code is licensed under the BSD-style license found in the
93900 * LICENSE file in the root directory of this source tree. An additional grant
93901 * of patent rights can be found in the PATENTS file in the same directory.
93902 *
93903 */
93904// Based off https://github.com/ForbesLindesay/umd/blob/master/template.js
93905;(function(f) {
93906  // CommonJS
93907  if (typeof exports === "object" && typeof module !== "undefined") {
93908    module.exports = f(require('react'));
93909
93910  // RequireJS
93911  } else if (typeof define === "function" && define.amd) {
93912    define('reactDom',['react'], f);
93913
93914  // <script>
93915  } else {
93916    var g;
93917    if (typeof window !== "undefined") {
93918      g = window;
93919    } else if (typeof global !== "undefined") {
93920      g = global;
93921    } else if (typeof self !== "undefined") {
93922      g = self;
93923    } else {
93924      // works providing we're not in "use strict";
93925      // needed for Java 8 Nashorn
93926      // see https://github.com/facebook/react/issues/3037
93927      g = this;
93928    }
93929    g.ReactDOM = f(g.React);
93930  }
93931
93932})(function(React) {
93933  return React.__SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
93934});
93935
93936/* jquery.signalR.core.js */
93937/*global window:false */
93938/*!
93939 * ASP.NET SignalR JavaScript Library v2.2.1
93940 * http://signalr.net/
93941 *
93942 * Copyright (c) .NET Foundation. All rights reserved.
93943 * Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
93944 *
93945 */
93946
93947///// <reference path="Scripts/jquery-1.6.4.js" />
vendor: 4,466 bytes, lines 93948-94040
93948///// <reference path="jquery.signalR.version.js" />
93949(function ($, window, undefined) {
93950
93951    var resources = {
93952        nojQuery: "jQuery was not found. Please ensure jQuery is referenced before the SignalR client JavaScript file.",
93953        noTransportOnInit: "No transport could be initialized successfully. Try specifying a different transport or none at all for auto initialization.",
93954        errorOnNegotiate: "Error during negotiation request.",
93955        stoppedWhileLoading: "The connection was stopped during page load.",
93956        stoppedWhileNegotiating: "The connection was stopped during the negotiate request.",
93957        errorParsingNegotiateResponse: "Error parsing negotiate response.",
93958        errorDuringStartRequest: "Error during start request. Stopping the connection.",
93959        stoppedDuringStartRequest: "The connection was stopped during the start request.",
93960        errorParsingStartResponse: "Error parsing start response: '{0}'. Stopping the connection.",
93961        invalidStartResponse: "Invalid start response: '{0}'. Stopping the connection.",
93962        protocolIncompatible: "You are using a version of the client that isn't compatible with the server. Client version {0}, server version {1}.",
93963        sendFailed: "Send failed.",
93964        parseFailed: "Failed at parsing response: {0}",
93965        longPollFailed: "Long polling request failed.",
93966        eventSourceFailedToConnect: "EventSource failed to connect.",
93967        eventSourceError: "Error raised by EventSource",
93968        webSocketClosed: "WebSocket closed.",
93969        pingServerFailedInvalidResponse: "Invalid ping response when pinging server: '{0}'.",
93970        pingServerFailed: "Failed to ping server.",
93971        pingServerFailedStatusCode: "Failed to ping server.  Server responded with status code {0}, stopping the connection.",
93972        pingServerFailedParse: "Failed to parse ping server response, stopping the connection.",
93973        noConnectionTransport: "Connection is in an invalid state, there is no transport active.",
93974        webSocketsInvalidState: "The Web Socket transport is in an invalid state, transitioning into reconnecting.",
93975        reconnectTimeout: "Couldn't reconnect within the configured timeout of {0} ms, disconnecting.",
93976        reconnectWindowTimeout: "The client has been inactive since {0} and it has exceeded the inactivity timeout of {1} ms. Stopping the connection."
93977    };
93978
93979    if (typeof ($) !== "function") {
93980        // no jQuery!
93981        throw new Error(resources.nojQuery);
93982    }
93983
93984    var signalR,
93985        _connection,
93986        _pageLoaded = (window.document.readyState === "complete"),
93987        _pageWindow = $(window),
93988        _negotiateAbortText = "__Negotiate Aborted__",
93989        events = {
93990            onStart: "onStart",
93991            onStarting: "onStarting",
93992            onReceived: "onReceived",
93993            onError: "onError",
93994            onConnectionSlow: "onConnectionSlow",
93995            onReconnecting: "onReconnecting",
93996            onReconnect: "onReconnect",
93997            onStateChanged: "onStateChanged",
93998            onDisconnect: "onDisconnect"
93999        },
94000        ajaxDefaults = {
94001            processData: true,
94002            timeout: null,
94003            async: true,
94004            global: false,
94005            cache: false
94006        },
94007        log = function (msg, logging) {
94008            if (logging === false) {
94009                return;
94010            }
94011            var m;
94012            if (typeof (window.console) === "undefined") {
94013                return;
94014            }
94015            m = "[" + new Date().toTimeString() + "] SignalR: " + msg;
94016            if (window.console.debug) {
94017                window.console.debug(m);
94018            } else if (window.console.log) {
94019                window.console.log(m);
94020            }
94021        },
94022
94023        changeState = function (connection, expectedState, newState) {
94024            if (expectedState === connection.state) {
94025                connection.state = newState;
94026
94027                $(connection).triggerHandler(events.onStateChanged, [{ oldState: expectedState, newState: newState }]);
94028                return true;
94029            }
94030
94031            return false;
94032        },
94033
94034        isDisconnecting = function (connection) {
94035            return connection.state === signalR.connectionState.disconnected;
94036        },
94037
94038        supportsKeepAlive = function (connection) {
94039            return connection._.keepAliveData.activated &&
94040   
vendor: 6,071 bytes, lines 94040-94188
94040                connection.transport.supportsKeepAlive(connection);
94041        },
94042
94043        configureStopReconnectingTimeout = function (connection) {
94044            var stopReconnectingTimeout,
94045                onReconnectTimeout;
94046
94047            // Check if this connection has already been configured to stop reconnecting after a specified timeout.
94048            // Without this check if a connection is stopped then started events will be bound multiple times.
94049            if (!connection._.configuredStopReconnectingTimeout) {
94050                onReconnectTimeout = function (connection) {
94051                    var message = signalR._.format(signalR.resources.reconnectTimeout, connection.disconnectTimeout);
94052                    connection.log(message);
94053                    $(connection).triggerHandler(events.onError, [signalR._.error(message, /* source */ "TimeoutException")]);
94054                    connection.stop(/* async */ false, /* notifyServer */ false);
94055                };
94056
94057                connection.reconnecting(function () {
94058                    var connection = this;
94059
94060                    // Guard against state changing in a previous user defined even handler
94061                    if (connection.state === signalR.connectionState.reconnecting) {
94062                        stopReconnectingTimeout = window.setTimeout(function () { onReconnectTimeout(connection); }, connection.disconnectTimeout);
94063                    }
94064                });
94065
94066                connection.stateChanged(function (data) {
94067                    if (data.oldState === signalR.connectionState.reconnecting) {
94068                        // Clear the pending reconnect timeout check
94069                        window.clearTimeout(stopReconnectingTimeout);
94070                    }
94071                });
94072
94073                connection._.configuredStopReconnectingTimeout = true;
94074            }
94075        };
94076
94077    signalR = function (url, qs, logging) {
94078        /// <summary>Creates a new SignalR connection for the given url</summary>
94079        /// <param name="url" type="String">The URL of the long polling endpoint</param>
94080        /// <param name="qs" type="Object">
94081        ///     [Optional] Custom querystring parameters to add to the connection URL.
94082        ///     If an object, every non-function member will be added to the querystring.
94083        ///     If a string, it's added to the QS as specified.
94084        /// </param>
94085        /// <param name="logging" type="Boolean">
94086        ///     [Optional] A flag indicating whether connection logging is enabled to the browser
94087        ///     console/log. Defaults to false.
94088        /// </param>
94089
94090        return new signalR.fn.init(url, qs, logging);
94091    };
94092
94093    signalR._ = {
94094        defaultContentType: "application/x-www-form-urlencoded; charset=UTF-8",
94095
94096        ieVersion: (function () {
94097            var version,
94098                matches;
94099
94100            if (window.navigator.appName === 'Microsoft Internet Explorer') {
94101                // Check if the user agent has the pattern "MSIE (one or more numbers).(one or more numbers)";
94102                matches = /MSIE ([0-9]+\.[0-9]+)/.exec(window.navigator.userAgent);
94103
94104                if (matches) {
94105                    version = window.parseFloat(matches[1]);
94106                }
94107            }
94108
94109            // undefined value means not IE
94110            return version;
94111        })(),
94112
94113        error: function (message, source, context) {
94114            var e = new Error(message);
94115            e.source = source;
94116
94117            if (typeof context !== "undefined") {
94118                e.context = context;
94119            }
94120
94121            return e;
94122        },
94123
94124        transportError: function (message, transport, source, context) {
94125            var e = this.error(message, source, context);
94126            e.transport = transport ? transport.name : undefined;
94127            return e;
94128        },
94129
94130        format: function () {
94131            /// <summary>Usage: format("Hi {0}, you are {1}!", "Foo", 100) </summary>
94132            var s = arguments[0];
94133            for (var i = 0; i < arguments.length - 1; i++) {
94134                s = s.replace("{" + i + "}", arguments[i + 1]);
94135            }
94136            return s;
94137        },
94138
94139        firefoxMajorVersion: function (userAgent) {
94140            // Firefox user agents: http://useragentstring.com/pages/Firefox/
94141            var matches = userAgent.match(/Firefox\/(\d+)/);
94142            if (!matches || !matches.length || matches.length < 2) {
94143                return 0;
94144            }
94145            return parseInt(matches[1], 10 /* radix */);
94146        },
94147
94148        configurePingInterval: function (connection) {
94149            var config = connection._.config,
94150                onFail = function (error) {
94151                    $(connection).triggerHandler(events.onError, [error]);
94152                };
94153
94154            if (config && !connection._.pingIntervalId && config.pingInterval) {
94155                connection._.pingIntervalId = window.setInterval(function () {
94156                    signalR.transports._logic.pingServer(connection).fail(onFail);
94157                }, config.pingInterval);
94158            }
94159        }
94160    };
94161
94162    signalR.events = events;
94163
94164    signalR.resources = resources;
94165
94166    signalR.ajaxDefaults = ajaxDefaults;
94167
94168    signalR.changeState = changeState;
94169
94170    signalR.isDisconnecting = isDisconnecting;
94171
94172    signalR.connectionState = {
94173        connecting: 0,
94174        connected: 1,
94175        reconnecting: 2,
94176        disconnected: 4
94177    };
94178
94179    signalR.hub = {
94180        start: function () {
94181            // This will get replaced with the real hub connection start method when hubs is referenced correctly
94182            throw new Error("SignalR: Error loading hubs. Ensure your hubs reference is correct, e.g. <script src='/signalr/js'></script>.");
94183        }
94184    };
94185
94186    // .on() was added in version 1.7.0, .load() was removed in version 3.0.0 so we fallback to .load() if .on() does
94187    // not exist to not break existing applications
94188    if (typeof _pageWindow.on ==
vendor: 32,723 bytes, lines 94188-94887
94188 "function") {
94189        _pageWindow.on("load", function () { _pageLoaded = true; });
94190    }
94191    else {
94192        _pageWindow.load(function () { _pageLoaded = true; });
94193    }
94194
94195    function validateTransport(requestedTransport, connection) {
94196        /// <summary>Validates the requested transport by cross checking it with the pre-defined signalR.transports</summary>
94197        /// <param name="requestedTransport" type="Object">The designated transports that the user has specified.</param>
94198        /// <param name="connection" type="signalR">The connection that will be using the requested transports.  Used for logging purposes.</param>
94199        /// <returns type="Object" />
94200
94201        if ($.isArray(requestedTransport)) {
94202            // Go through transport array and remove an "invalid" tranports
94203            for (var i = requestedTransport.length - 1; i >= 0; i--) {
94204                var transport = requestedTransport[i];
94205                if ($.type(transport) !== "string" || !signalR.transports[transport]) {
94206                    connection.log("Invalid transport: " + transport + ", removing it from the transports list.");
94207                    requestedTransport.splice(i, 1);
94208                }
94209            }
94210
94211            // Verify we still have transports left, if we dont then we have invalid transports
94212            if (requestedTransport.length === 0) {
94213                connection.log("No transports remain within the specified transport array.");
94214                requestedTransport = null;
94215            }
94216        } else if (!signalR.transports[requestedTransport] && requestedTransport !== "auto") {
94217            connection.log("Invalid transport: " + requestedTransport.toString() + ".");
94218            requestedTransport = null;
94219        } else if (requestedTransport === "auto" && signalR._.ieVersion <= 8) {
94220            // If we're doing an auto transport and we're IE8 then force longPolling, #1764
94221            return ["longPolling"];
94222
94223        }
94224
94225        return requestedTransport;
94226    }
94227
94228    function getDefaultPort(protocol) {
94229        if (protocol === "http:") {
94230            return 80;
94231        } else if (protocol === "https:") {
94232            return 443;
94233        }
94234    }
94235
94236    function addDefaultPort(protocol, url) {
94237        // Remove ports  from url.  We have to check if there's a / or end of line
94238        // following the port in order to avoid removing ports such as 8080.
94239        if (url.match(/:\d+$/)) {
94240            return url;
94241        } else {
94242            return url + ":" + getDefaultPort(protocol);
94243        }
94244    }
94245
94246    function ConnectingMessageBuffer(connection, drainCallback) {
94247        var that = this,
94248            buffer = [];
94249
94250        that.tryBuffer = function (message) {
94251            if (connection.state === $.signalR.connectionState.connecting) {
94252                buffer.push(message);
94253
94254                return true;
94255            }
94256
94257            return false;
94258        };
94259
94260        that.drain = function () {
94261            // Ensure that the connection is connected when we drain (do not want to drain while a connection is not active)
94262            if (connection.state === $.signalR.connectionState.connected) {
94263                while (buffer.length > 0) {
94264                    drainCallback(buffer.shift());
94265                }
94266            }
94267        };
94268
94269        that.clear = function () {
94270            buffer = [];
94271        };
94272    }
94273
94274    signalR.fn = signalR.prototype = {
94275        init: function (url, qs, logging) {
94276            var $connection = $(this);
94277
94278            this.url = url;
94279            this.qs = qs;
94280            this.lastError = null;
94281            this._ = {
94282                keepAliveData: {},
94283                connectingMessageBuffer: new ConnectingMessageBuffer(this, function (message) {
94284                    $connection.triggerHandler(events.onReceived, [message]);
94285                }),
94286                lastMessageAt: new Date().getTime(),
94287                lastActiveAt: new Date().getTime(),
94288                beatInterval: 5000, // Default value, will only be overridden if keep alive is enabled,
94289                beatHandle: null,
94290                totalTransportConnectTimeout: 0 // This will be the sum of the TransportConnectTimeout sent in response to negotiate and connection.transportConnectTimeout
94291            };
94292            if (typeof (logging) === "boolean") {
94293                this.logging = logging;
94294            }
94295        },
94296
94297        _parseResponse: function (response) {
94298            var that = this;
94299
94300            if (!response) {
94301                return response;
94302            } else if (typeof response === "string") {
94303                return that.json.parse(response);
94304            } else {
94305                return response;
94306            }
94307        },
94308
94309        _originalJson: window.JSON,
94310
94311        json: window.JSON,
94312
94313        isCrossDomain: function (url, against) {
94314            /// <summary>Checks if url is cross domain</summary>
94315            /// <param name="url" type="String">The base URL</param>
94316            /// <param name="against" type="Object">
94317            ///     An optional argument to compare the URL against, if not specified it will be set to window.location.
94318            ///     If specified it must contain a protocol and a host property.
94319            /// </param>
94320            var link;
94321
94322            url = $.trim(url);
94323
94324            against = against || window.location;
94325
94326            if (url.indexOf("http") !== 0) {
94327                return false;
94328            }
94329
94330            // Create an anchor tag.
94331            link = window.document.createElement("a");
94332            link.href = url;
94333
94334            // When checking for cross domain we have to special case port 80 because the window.location will remove the
94335            return link.protocol + addDefaultPort(link.protocol, link.host) !== against.protocol + addDefaultPort(against.protocol, against.host);
94336        },
94337
94338        ajaxDataType: "text",
94339
94340        contentType: "application/json; charset=UTF-8",
94341
94342        logging: false,
94343
94344        state: signalR.connectionState.disconnected,
94345
94346        clientProtocol: "1.5",
94347
94348        reconnectDelay: 2000,
94349
94350        transportConnectTimeout: 0,
94351
94352        disconnectTimeout: 30000, // This should be set by the server in response to the negotiate request (30s default)
94353
94354        reconnectWindow: 30000, // This should be set by the server in response to the negotiate request
94355
94356        keepAliveWarnAt: 2 / 3, // Warn user of slow connection if we breach the X% mark of the keep alive timeout
94357
94358        start: function (options, callback) {
94359            /// <summary>Starts the connection</summary>
94360            /// <param name="options" type="Object">Options map</param>
94361            /// <param name="callback" type="Function">A callback function to execute when the connection has started</param>
94362            var connection = this,
94363                config = {
94364                    pingInterval: 300000,
94365                    waitForPageLoad: true,
94366                    transport: "auto",
94367                    jsonp: false
94368                },
94369                initialize,
94370                deferred = connection._deferral || $.Deferred(), // Check to see if there is a pre-existing deferral that's being built on, if so we want to keep using it
94371                parser = window.document.createElement("a");
94372
94373            connection.lastError = null;
94374
94375            // Persist the deferral so that if start is called multiple times the same deferral is used.
94376            connection._deferral = deferred;
94377
94378            if (!connection.json) {
94379                // no JSON!
94380                throw new Error("SignalR: No JSON parser found. Please ensure json2.js is referenced before the SignalR.js file if you need to support clients without native JSON parsing support, e.g. IE<8.");
94381            }
94382
94383            if ($.type(options) === "function") {
94384                // Support calling with single callback parameter
94385                callback = options;
94386            } else if ($.type(options) === "object") {
94387                $.extend(config, options);
94388                if ($.type(config.callback) === "function") {
94389                    callback = config.callback;
94390                }
94391            }
94392
94393            config.transport = validateTransport(config.transport, connection);
94394
94395            // If the transport is invalid throw an error and abort start
94396            if (!config.transport) {
94397                throw new Error("SignalR: Invalid transport(s) specified, aborting start.");
94398            }
94399
94400            connection._.config = config;
94401
94402            // Check to see if start is being called prior to page load
94403            // If waitForPageLoad is true we then want to re-direct function call to the window load event
94404            if (!_pageLoaded && config.waitForPageLoad === true) {
94405                connection._.deferredStartHandler = function () {
94406                    connection.start(options, callback);
94407                };
94408                _pageWindow.bind("load", connection._.deferredStartHandler);
94409
94410                return deferred.promise();
94411            }
94412
94413            // If we're already connecting just return the same deferral as the original connection start
94414            if (connection.state === signalR.connectionState.connecting) {
94415                return deferred.promise();
94416            } else if (changeState(connection,
94417                            signalR.connectionState.disconnected,
94418                            signalR.connectionState.connecting) === false) {
94419                // We're not connecting so try and transition into connecting.
94420                // If we fail to transition then we're either in connected or reconnecting.
94421
94422                deferred.resolve(connection);
94423                return deferred.promise();
94424            }
94425
94426            configureStopReconnectingTimeout(connection);
94427
94428            // Resolve the full url
94429            parser.href = connection.url;
94430            if (!parser.protocol || parser.protocol === ":") {
94431                connection.protocol = window.document.location.protocol;
94432                connection.host = parser.host || window.document.location.host;
94433            } else {
94434                connection.protocol = parser.protocol;
94435                connection.host = parser.host;
94436            }
94437
94438            connection.baseUrl = connection.protocol + "//" + connection.host;
94439
94440            // Set the websocket protocol
94441            connection.wsProtocol = connection.protocol === "https:" ? "wss://" : "ws://";
94442
94443            // If jsonp with no/auto transport is specified, then set the transport to long polling
94444            // since that is the only transport for which jsonp really makes sense.
94445            // Some developers might actually choose to specify jsonp for same origin requests
94446            // as demonstrated by Issue #623.
94447            if (config.transport === "auto" && config.jsonp === true) {
94448                config.transport = "longPolling";
94449            }
94450
94451            // If the url is protocol relative, prepend the current windows protocol to the url.
94452            if (connection.url.indexOf("//") === 0) {
94453                connection.url = window.location.protocol + connection.url;
94454                connection.log("Protocol relative URL detected, normalizing it to '" + connection.url + "'.");
94455            }
94456
94457            if (this.isCrossDomain(connection.url)) {
94458                connection.log("Auto detected cross domain url.");
94459
94460                if (config.transport === "auto") {
94461                    // TODO: Support XDM with foreverFrame
94462                    config.transport = ["webSockets", "serverSentEvents", "longPolling"];
94463                }
94464
94465                if (typeof (config.withCredentials) === "undefined") {
94466                    config.withCredentials = true;
94467                }
94468
94469                // Determine if jsonp is the only choice for negotiation, ajaxSend and ajaxAbort.
94470                // i.e. if the browser doesn't supports CORS
94471                // If it is, ignore any preference to the contrary, and switch to jsonp.
94472                if (!config.jsonp) {
94473                    config.jsonp = !$.support.cors;
94474
94475                    if (config.jsonp) {
94476                        connection.log("Using jsonp because this browser doesn't support CORS.");
94477                    }
94478                }
94479
94480                connection.contentType = signalR._.defaultContentType;
94481            }
94482
94483            connection.withCredentials = config.withCredentials;
94484
94485            connection.ajaxDataType = config.jsonp ? "jsonp" : "text";
94486
94487            $(connection).bind(events.onStart, function (e, data) {
94488                if ($.type(callback) === "function") {
94489                    callback.call(connection);
94490                }
94491                deferred.resolve(connection);
94492            });
94493
94494            connection._.initHandler = signalR.transports._logic.initHandler(connection);
94495
94496            initialize = function (transports, index) {
94497                var noTransportError = signalR._.error(resources.noTransportOnInit);
94498
94499                index = index || 0;
94500                if (index >= transports.length) {
94501                    if (index === 0) {
94502                        connection.log("No transports supported by the server were selected.");
94503                    } else if (index === 1) {
94504                        connection.log("No fallback transports were selected.");
94505                    } else {
94506                        connection.log("Fallback transports exhausted.");
94507                    }
94508
94509                    // No transport initialized successfully
94510                    $(connection).triggerHandler(events.onError, [noTransportError]);
94511                    deferred.reject(noTransportError);
94512                    // Stop the connection if it has connected and move it into the disconnected state
94513                    connection.stop();
94514                    return;
94515                }
94516
94517                // The connection was aborted
94518                if (connection.state === signalR.connectionState.disconnected) {
94519                    return;
94520                }
94521
94522                var transportName = transports[index],
94523                    transport = signalR.transports[transportName],
94524                    onFallback = function () {
94525                        initialize(transports, index + 1);
94526                    };
94527
94528                connection.transport = transport;
94529
94530                try {
94531                    connection._.initHandler.start(transport, function () { // success
94532                        // Firefox 11+ doesn't allow sync XHR withCredentials: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest#withCredentials
94533                        var isFirefox11OrGreater = signalR._.firefoxMajorVersion(window.navigator.userAgent) >= 11,
94534                            asyncAbort = !!connection.withCredentials && isFirefox11OrGreater;
94535
94536                        connection.log("The start request succeeded. Transitioning to the connected state.");
94537
94538                        if (supportsKeepAlive(connection)) {
94539                            signalR.transports._logic.monitorKeepAlive(connection);
94540                        }
94541
94542                        signalR.transports._logic.startHeartbeat(connection);
94543
94544                        // Used to ensure low activity clients maintain their authentication.
94545                        // Must be configured once a transport has been decided to perform valid ping requests.
94546                        signalR._.configurePingInterval(connection);
94547
94548                        if (!changeState(connection,
94549                                            signalR.connectionState.connecting,
94550                                            signalR.connectionState.connected)) {
94551                            connection.log("WARNING! The connection was not in the connecting state.");
94552                        }
94553
94554                        // Drain any incoming buffered messages (messages that came in prior to connect)
94555                        connection._.connectingMessageBuffer.drain();
94556
94557                        $(connection).triggerHandler(events.onStart);
94558
94559                        // wire the stop handler for when the user leaves the page
94560                        _pageWindow.bind("unload", function () {
94561                            connection.log("Window unloading, stopping the connection.");
94562
94563                            connection.stop(asyncAbort);
94564                        });
94565
94566                        if (isFirefox11OrGreater) {
94567                            // Firefox does not fire cross-domain XHRs in the normal unload handler on tab close.
94568                            // #2400
94569                            _pageWindow.bind("beforeunload", function () {
94570                                // If connection.stop() runs runs in beforeunload and fails, it will also fail
94571                                // in unload unless connection.stop() runs after a timeout.
94572                                window.setTimeout(function () {
94573                                    connection.stop(asyncAbort);
94574                                }, 0);
94575                            });
94576                        }
94577                    }, onFallback);
94578                }
94579                catch (error) {
94580                    connection.log(transport.name + " transport threw '" + error.message + "' when attempting to start.");
94581                    onFallback();
94582                }
94583            };
94584
94585            var url = connection.url + "/negotiate",
94586                onFailed = function (error, connection) {
94587                    var err = signalR._.error(resources.errorOnNegotiate, error, connection._.negotiateRequest);
94588
94589                    $(connection).triggerHandler(events.onError, err);
94590                    deferred.reject(err);
94591                    // Stop the connection if negotiate failed
94592                    connection.stop();
94593                };
94594
94595            $(connection).triggerHandler(events.onStarting);
94596
94597            url = signalR.transports._logic.prepareQueryString(connection, url);
94598
94599            connection.log("Negotiating with '" + url + "'.");
94600
94601            // Save the ajax negotiate request object so we can abort it if stop is called while the request is in flight.
94602            connection._.negotiateRequest = signalR.transports._logic.ajax(connection, {
94603                url: url,
94604                error: function (error, statusText) {
94605                    // We don't want to cause any errors if we're aborting our own negotiate request.
94606                    if (statusText !== _negotiateAbortText) {
94607                        onFailed(error, connection);
94608                    } else {
94609                        // This rejection will noop if the deferred has already been resolved or rejected.
94610                        deferred.reject(signalR._.error(resources.stoppedWhileNegotiating, null /* error */, connection._.negotiateRequest));
94611                    }
94612                },
94613                success: function (result) {
94614                    var res,
94615                        keepAliveData,
94616                        protocolError,
94617                        transports = [],
94618                        supportedTransports = [];
94619
94620                    try {
94621                        res = connection._parseResponse(result);
94622                    } catch (error) {
94623                        onFailed(signalR._.error(resources.errorParsingNegotiateResponse, error), connection);
94624                        return;
94625                    }
94626
94627                    keepAliveData = connection._.keepAliveData;
94628                    connection.appRelativeUrl = res.Url;
94629                    connection.id = res.ConnectionId;
94630                    connection.token = res.ConnectionToken;
94631                    connection.webSocketServerUrl = res.WebSocketServerUrl;
94632
94633                    // The long poll timeout is the ConnectionTimeout plus 10 seconds
94634                    connection._.pollTimeout = res.ConnectionTimeout * 1000 + 10000; // in ms
94635
94636                    // Once the server has labeled the PersistentConnection as Disconnected, we should stop attempting to reconnect
94637                    // after res.DisconnectTimeout seconds.
94638                    connection.disconnectTimeout = res.DisconnectTimeout * 1000; // in ms
94639
94640                    // Add the TransportConnectTimeout from the response to the transportConnectTimeout from the client to calculate the total timeout
94641                    connection._.totalTransportConnectTimeout = connection.transportConnectTimeout + res.TransportConnectTimeout * 1000;
94642
94643                    // If we have a keep alive
94644                    if (res.KeepAliveTimeout) {
94645                        // Register the keep alive data as activated
94646                        keepAliveData.activated = true;
94647
94648                        // Timeout to designate when to force the connection into reconnecting converted to milliseconds
94649                        keepAliveData.timeout = res.KeepAliveTimeout * 1000;
94650
94651                        // Timeout to designate when to warn the developer that the connection may be dead or is not responding.
94652                        keepAliveData.timeoutWarning = keepAliveData.timeout * connection.keepAliveWarnAt;
94653
94654                        // Instantiate the frequency in which we check the keep alive.  It must be short in order to not miss/pick up any changes
94655                        connection._.beatInterval = (keepAliveData.timeout - keepAliveData.timeoutWarning) / 3;
94656                    } else {
94657                        keepAliveData.activated = false;
94658                    }
94659
94660                    connection.reconnectWindow = connection.disconnectTimeout + (keepAliveData.timeout || 0);
94661
94662                    if (!res.ProtocolVersion || res.ProtocolVersion !== connection.clientProtocol) {
94663                        protocolError = signalR._.error(signalR._.format(resources.protocolIncompatible, connection.clientProtocol, res.ProtocolVersion));
94664                        $(connection).triggerHandler(events.onError, [protocolError]);
94665                        deferred.reject(protocolError);
94666
94667                        return;
94668                    }
94669
94670                    $.each(signalR.transports, function (key) {
94671                        if ((key.indexOf("_") === 0) || (key === "webSockets" && !res.TryWebSockets)) {
94672                            return true;
94673                        }
94674                        supportedTransports.push(key);
94675                    });
94676
94677                    if ($.isArray(config.transport)) {
94678                        $.each(config.transport, function (_, transport) {
94679                            if ($.inArray(transport, supportedTransports) >= 0) {
94680                                transports.push(transport);
94681                            }
94682                        });
94683                    } else if (config.transport === "auto") {
94684                        transports = supportedTransports;
94685                    } else if ($.inArray(config.transport, supportedTransports) >= 0) {
94686                        transports.push(config.transport);
94687                    }
94688
94689                    initialize(transports);
94690                }
94691            });
94692
94693            return deferred.promise();
94694        },
94695
94696        starting: function (callback) {
94697            /// <summary>Adds a callback that will be invoked before anything is sent over the connection</summary>
94698            /// <param name="callback" type="Function">A callback function to execute before the connection is fully instantiated.</param>
94699            /// <returns type="signalR" />
94700            var connection = this;
94701            $(connection).bind(events.onStarting, function (e, data) {
94702                callback.call(connection);
94703            });
94704            return connection;
94705        },
94706
94707        send: function (data) {
94708            /// <summary>Sends data over the connection</summary>
94709            /// <param name="data" type="String">The data to send over the connection</param>
94710            /// <returns type="signalR" />
94711            var connection = this;
94712
94713            if (connection.state === signalR.connectionState.disconnected) {
94714                // Connection hasn't been started yet
94715                throw new Error("SignalR: Connection must be started before data can be sent. Call .start() before .send()");
94716            }
94717
94718            if (connection.state === signalR.connectionState.connecting) {
94719                // Connection hasn't been started yet
94720                throw new Error("SignalR: Connection has not been fully initialized. Use .start().done() or .start().fail() to run logic after the connection has started.");
94721            }
94722
94723            connection.transport.send(connection, data);
94724            // REVIEW: Should we return deferred here?
94725            return connection;
94726        },
94727
94728        received: function (callback) {
94729            /// <summary>Adds a callback that will be invoked after anything is received over the connection</summary>
94730            /// <param name="callback" type="Function">A callback function to execute when any data is received on the connection</param>
94731            /// <returns type="signalR" />
94732            var connection = this;
94733            $(connection).bind(events.onReceived, function (e, data) {
94734                callback.call(connection, data);
94735            });
94736            return connection;
94737        },
94738
94739        stateChanged: function (callback) {
94740            /// <summary>Adds a callback that will be invoked when the connection state changes</summary>
94741            /// <param name="callback" type="Function">A callback function to execute when the connection state changes</param>
94742            /// <returns type="signalR" />
94743            var connection = this;
94744            $(connection).bind(events.onStateChanged, function (e, data) {
94745                callback.call(connection, data);
94746            });
94747            return connection;
94748        },
94749
94750        error: function (callback) {
94751            /// <summary>Adds a callback that will be invoked after an error occurs with the connection</summary>
94752            /// <param name="callback" type="Function">A callback function to execute when an error occurs on the connection</param>
94753            /// <returns type="signalR" />
94754            var connection = this;
94755            $(connection).bind(events.onError, function (e, errorData, sendData) {
94756                connection.lastError = errorData;
94757                // In practice 'errorData' is the SignalR built error object.
94758                // In practice 'sendData' is undefined for all error events except those triggered by
94759                // 'ajaxSend' and 'webSockets.send'.'sendData' is the original send payload.
94760                callback.call(connection, errorData, sendData);
94761            });
94762            return connection;
94763        },
94764
94765        disconnected: function (callback) {
94766            /// <summary>Adds a callback that will be invoked when the client disconnects</summary>
94767            /// <param name="callback" type="Function">A callback function to execute when the connection is broken</param>
94768            /// <returns type="signalR" />
94769            var connection = this;
94770            $(connection).bind(events.onDisconnect, function (e, data) {
94771                callback.call(connection);
94772            });
94773            return connection;
94774        },
94775
94776        connectionSlow: function (callback) {
94777            /// <summary>Adds a callback that will be invoked when the client detects a slow connection</summary>
94778            /// <param name="callback" type="Function">A callback function to execute when the connection is slow</param>
94779            /// <returns type="signalR" />
94780            var connection = this;
94781            $(connection).bind(events.onConnectionSlow, function (e, data) {
94782                callback.call(connection);
94783            });
94784
94785            return connection;
94786        },
94787
94788        reconnecting: function (callback) {
94789            /// <summary>Adds a callback that will be invoked when the underlying transport begins reconnecting</summary>
94790            /// <param name="callback" type="Function">A callback function to execute when the connection enters a reconnecting state</param>
94791            /// <returns type="signalR" />
94792            var connection = this;
94793            $(connection).bind(events.onReconnecting, function (e, data) {
94794                callback.call(connection);
94795            });
94796            return connection;
94797        },
94798
94799        reconnected: function (callback) {
94800            /// <summary>Adds a callback that will be invoked when the underlying transport reconnects</summary>
94801            /// <param name="callback" type="Function">A callback function to execute when the connection is restored</param>
94802            /// <returns type="signalR" />
94803            var connection = this;
94804            $(connection).bind(events.onReconnect, function (e, data) {
94805                callback.call(connection);
94806            });
94807            return connection;
94808        },
94809
94810        stop: function (async, notifyServer) {
94811            /// <summary>Stops listening</summary>
94812            /// <param name="async" type="Boolean">Whether or not to asynchronously abort the connection</param>
94813            /// <param name="notifyServer" type="Boolean">Whether we want to notify the server that we are aborting the connection</param>
94814            /// <returns type="signalR" />
94815            var connection = this,
94816                // Save deferral because this is always cleaned up
94817                deferral = connection._deferral;
94818
94819            // Verify that we've bound a load event.
94820            if (connection._.deferredStartHandler) {
94821                // Unbind the event.
94822                _pageWindow.unbind("load", connection._.deferredStartHandler);
94823            }
94824
94825            // Always clean up private non-timeout based state.
94826            delete connection._.config;
94827            delete connection._.deferredStartHandler;
94828
94829            // This needs to be checked despite the connection state because a connection start can be deferred until page load.
94830            // If we've deferred the start due to a page load we need to unbind the "onLoad" -> start event.
94831            if (!_pageLoaded && (!connection._.config || connection._.config.waitForPageLoad === true)) {
94832                connection.log("Stopping connection prior to negotiate.");
94833
94834                // If we have a deferral we should reject it
94835                if (deferral) {
94836                    deferral.reject(signalR._.error(resources.stoppedWhileLoading));
94837                }
94838
94839                // Short-circuit because the start has not been fully started.
94840                return;
94841            }
94842
94843            if (connection.state === signalR.connectionState.disconnected) {
94844                return;
94845            }
94846
94847            connection.log("Stopping connection.");
94848
94849            // Clear this no matter what
94850            window.clearTimeout(connection._.beatHandle);
94851            window.clearInterval(connection._.pingIntervalId);
94852
94853            if (connection.transport) {
94854                connection.transport.stop(connection);
94855
94856                if (notifyServer !== false) {
94857                    connection.transport.abort(connection, async);
94858                }
94859
94860                if (supportsKeepAlive(connection)) {
94861                    signalR.transports._logic.stopMonitoringKeepAlive(connection);
94862                }
94863
94864                connection.transport = null;
94865            }
94866
94867            if (connection._.negotiateRequest) {
94868                // If the negotiation request has already completed this will noop.
94869                connection._.negotiateRequest.abort(_negotiateAbortText);
94870                delete connection._.negotiateRequest;
94871            }
94872
94873            // Ensure that initHandler.stop() is called before connection._deferral is deleted
94874            if (connection._.initHandler) {
94875                connection._.initHandler.stop();
94876            }
94877
94878            delete connection._deferral;
94879            delete connection.messageId;
94880            delete connection.groupsToken;
94881            delete connection.id;
94882            delete connection._.pingIntervalId;
94883            delete connection._.lastMessageAt;
94884            delete connection._.lastActiveAt;
94885
94886            // Clear out our message buffer
94887            connection._.connectingMessageBuffer.clear()
vendor: 8,847 bytes, lines 94887-95123
94887;
94888
94889            // Trigger the disconnect event
94890            changeState(connection, connection.state, signalR.connectionState.disconnected);
94891            $(connection).triggerHandler(events.onDisconnect);
94892
94893            return connection;
94894        },
94895
94896        log: function (msg) {
94897            log(msg, this.logging);
94898        }
94899    };
94900
94901    signalR.fn.init.prototype = signalR.fn;
94902
94903    signalR.noConflict = function () {
94904        /// <summary>Reinstates the original value of $.connection and returns the signalR object for manual assignment</summary>
94905        /// <returns type="signalR" />
94906        if ($.connection === signalR) {
94907            $.connection = _connection;
94908        }
94909        return signalR;
94910    };
94911
94912    if ($.connection) {
94913        _connection = $.connection;
94914    }
94915
94916    $.connection = $.signalR = signalR;
94917
94918}(window.jQuery, window));
94919/* jquery.signalR.transports.common.js */
94920// Copyright (c) .NET Foundation. All rights reserved.
94921// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
94922
94923/*global window:false */
94924/// <reference path="jquery.signalR.core.js" />
94925
94926(function ($, window, undefined) {
94927
94928    var signalR = $.signalR,
94929        events = $.signalR.events,
94930        changeState = $.signalR.changeState,
94931        startAbortText = "__Start Aborted__",
94932        transportLogic;
94933
94934    signalR.transports = {};
94935
94936    function beat(connection) {
94937        if (connection._.keepAliveData.monitoring) {
94938            checkIfAlive(connection);
94939        }
94940
94941        // Ensure that we successfully marked active before continuing the heartbeat.
94942        if (transportLogic.markActive(connection)) {
94943            connection._.beatHandle = window.setTimeout(function () {
94944                beat(connection);
94945            }, connection._.beatInterval);
94946        }
94947    }
94948
94949    function checkIfAlive(connection) {
94950        var keepAliveData = connection._.keepAliveData,
94951            timeElapsed;
94952
94953        // Only check if we're connected
94954        if (connection.state === signalR.connectionState.connected) {
94955            timeElapsed = new Date().getTime() - connection._.lastMessageAt;
94956
94957            // Check if the keep alive has completely timed out
94958            if (timeElapsed >= keepAliveData.timeout) {
94959                connection.log("Keep alive timed out.  Notifying transport that connection has been lost.");
94960
94961                // Notify transport that the connection has been lost
94962                connection.transport.lostConnection(connection);
94963            } else if (timeElapsed >= keepAliveData.timeoutWarning) {
94964                // This is to assure that the user only gets a single warning
94965                if (!keepAliveData.userNotified) {
94966                    connection.log("Keep alive has been missed, connection may be dead/slow.");
94967                    $(connection).triggerHandler(events.onConnectionSlow);
94968                    keepAliveData.userNotified = true;
94969                }
94970            } else {
94971                keepAliveData.userNotified = false;
94972            }
94973        }
94974    }
94975
94976    function getAjaxUrl(connection, path) {
94977        var url = connection.url + path;
94978
94979        if (connection.transport) {
94980            url += "?transport=" + connection.transport.name;
94981        }
94982
94983        return transportLogic.prepareQueryString(connection, url);
94984    }
94985
94986    function InitHandler(connection) {
94987        this.connection = connection;
94988
94989        this.startRequested = false;
94990        this.startCompleted = false;
94991        this.connectionStopped = false;
94992    }
94993
94994    InitHandler.prototype = {
94995        start: function (transport, onSuccess, onFallback) {
94996            var that = this,
94997                connection = that.connection,
94998                failCalled = false;
94999
95000            if (that.startRequested || that.connectionStopped) {
95001                connection.log("WARNING! " + transport.name + " transport cannot be started. Initialization ongoing or completed.");
95002                return;
95003            }
95004
95005            connection.log(transport.name + " transport starting.");
95006
95007            transport.start(connection, function () {
95008                if (!failCalled) {
95009                    that.initReceived(transport, onSuccess);
95010                }
95011            }, function (error) {
95012                // Don't allow the same transport to cause onFallback to be called twice
95013                if (!failCalled) {
95014                    failCalled = true;
95015                    that.transportFailed(transport, error, onFallback);
95016                }
95017
95018                // Returns true if the transport should stop;
95019                // false if it should attempt to reconnect
95020                return !that.startCompleted || that.connectionStopped;
95021            });
95022
95023            that.transportTimeoutHandle = window.setTimeout(function () {
95024                if (!failCalled) {
95025                    failCalled = true;
95026                    connection.log(transport.name + " transport timed out when trying to connect.");
95027                    that.transportFailed(transport, undefined, onFallback);
95028                }
95029            }, connection._.totalTransportConnectTimeout);
95030        },
95031
95032        stop: function () {
95033            this.connectionStopped = true;
95034            window.clearTimeout(this.transportTimeoutHandle);
95035            signalR.transports._logic.tryAbortStartRequest(this.connection);
95036        },
95037
95038        initReceived: function (transport, onSuccess) {
95039            var that = this,
95040                connection = that.connection;
95041
95042            if (that.startRequested) {
95043                connection.log("WARNING! The client received multiple init messages.");
95044                return;
95045            }
95046
95047            if (that.connectionStopped) {
95048                return;
95049            }
95050
95051            that.startRequested = true;
95052            window.clearTimeout(that.transportTimeoutHandle);
95053
95054            connection.log(transport.name + " transport connected. Initiating start request.");
95055            signalR.transports._logic.ajaxStart(connection, function () {
95056                that.startCompleted = true;
95057                onSuccess();
95058            });
95059        },
95060
95061        transportFailed: function (transport, error, onFallback) {
95062            var connection = this.connection,
95063                deferred = connection._deferral,
95064                wrappedError;
95065
95066            if (this.connectionStopped) {
95067                return;
95068            }
95069
95070            window.clearTimeout(this.transportTimeoutHandle);
95071
95072            if (!this.startRequested) {
95073                transport.stop(connection);
95074
95075                connection.log(transport.name + " transport failed to connect. Attempting to fall back.");
95076                onFallback();
95077            } else if (!this.startCompleted) {
95078                // Do not attempt to fall back if a start request is ongoing during a transport failure.
95079                // Instead, trigger an error and stop the connection.
95080                wrappedError = signalR._.error(signalR.resources.errorDuringStartRequest, error);
95081
95082                connection.log(transport.name + " transport failed during the start request. Stopping the connection.");
95083                $(connection).triggerHandler(events.onError, [wrappedError]);
95084                if (deferred) {
95085                    deferred.reject(wrappedError);
95086                }
95087
95088                connection.stop();
95089            } else {
95090                // The start request has completed, but the connection has not stopped.
95091                // No need to do anything here. The transport should attempt its normal reconnect logic.
95092            }
95093        }
95094    };
95095
95096    transportLogic = signalR.transports._logic = {
95097        ajax: function (connection, options) {
95098            return $.ajax(
95099                $.extend(/*deep copy*/ true, {}, $.signalR.ajaxDefaults, {
95100                    type: "GET",
95101                    data: {},
95102                    xhrFields: { withCredentials: connection.withCredentials },
95103                    contentType: connection.contentType,
95104                    dataType: connection.ajaxDataType
95105                }, options));
95106        },
95107
95108        pingServer: function (connection) {
95109            /// <summary>Pings the server</summary>
95110            /// <param name="connection" type="signalr">Connection associated with the server ping</param>
95111            /// <returns type="signalR" />
95112            var url,
95113                xhr,
95114                deferral = $.Deferred();
95115
95116            if (connection.transport) {
95117                url = connection.url + "/ping";
95118
95119                url = transportLogic.addQs(url, connection.qs);
95120
95121                xhr = transportLogic.ajax(connection, {
95122                    url: url,
95123                    
95123success: function (result) {
95124                        var data;
95125
95126                        try {
95127                            data = connection._parseResponse(result);
95128                        }
95129                        catch (error) {
95130                            deferral.reject(
95131                                signalR._.transportError(
95132                                    signalR.resources.pingServerFailedParse,
95133                                    connection.transport,
95134                                    error,
95135                                    xhr
95136                                )
95137                            );
95138                            connection.stop();
95139                            return;
95140                        }
95141
95142                        if (data.Response === "pong") {
95143                            deferral.resolve();
95144                        }
95145                        else {
95146                            deferral.reject(
95147                                signalR._.transportError(
95148                                    signalR._.format(signalR.resources.pingServerFailedInvalidResponse, result),
95149                                    connection.transport,
95150                                    null /* error */,
95151                                    xhr
95152                                )
95153                            );
95154                        }
95155                    },
95156                    error: function (error) {
95157                        if (error.status === 401 || error.status === 403) {
95158                            deferral.reject(
95159                                signalR._.transportError(
95160                                    signalR._.format(signalR.resources.pingServerFailedStatusCode, error.status),
95161                                    connection.transport,
95162                                    error,
95163                                    xhr
95164                                )
95165                            );
95166                            connection.stop();
95167                        }
95168                        else {
95169                            deferral.reject(
95170                                signalR._.transportError(
95171                                    signalR.resources.pingServerFailed,
95172                                    connection.transport,
vendor: 15,235 bytes, lines 95173-95554
95173                                    error,
95174                                    xhr
95175                                )
95176                            );
95177                        }
95178                    }
95179                });
95180            }
95181            else {
95182                deferral.reject(
95183                    signalR._.transportError(
95184                        signalR.resources.noConnectionTransport,
95185                        connection.transport
95186                    )
95187                );
95188            }
95189
95190            return deferral.promise();
95191        },
95192
95193        prepareQueryString: function (connection, url) {
95194            var preparedUrl;
95195
95196            // Use addQs to start since it handles the ?/& prefix for us
95197            preparedUrl = transportLogic.addQs(url, "clientProtocol=" + connection.clientProtocol);
95198
95199            // Add the user-specified query string params if any
95200            preparedUrl = transportLogic.addQs(preparedUrl, connection.qs);
95201
95202            if (connection.token) {
95203                preparedUrl += "&connectionToken=" + window.encodeURIComponent(connection.token);
95204            }
95205
95206            if (connection.data) {
95207                preparedUrl += "&connectionData=" + window.encodeURIComponent(connection.data);
95208            }
95209
95210            return preparedUrl;
95211        },
95212
95213        addQs: function (url, qs) {
95214            var appender = url.indexOf("?") !== -1 ? "&" : "?",
95215                firstChar;
95216
95217            if (!qs) {
95218                return url;
95219            }
95220
95221            if (typeof (qs) === "object") {
95222                return url + appender + $.param(qs);
95223            }
95224
95225            if (typeof (qs) === "string") {
95226                firstChar = qs.charAt(0);
95227
95228                if (firstChar === "?" || firstChar === "&") {
95229                    appender = "";
95230                }
95231
95232                return url + appender + qs;
95233            }
95234
95235            throw new Error("Query string property must be either a string or object.");
95236        },
95237
95238        // BUG #2953: The url needs to be same otherwise it will cause a memory leak
95239        getUrl: function (connection, transport, reconnecting, poll, ajaxPost) {
95240            /// <summary>Gets the url for making a GET based connect request</summary>
95241            var baseUrl = transport === "webSockets" ? "" : connection.baseUrl,
95242                url = baseUrl + connection.appRelativeUrl,
95243                qs = "transport=" + transport;
95244
95245            if (!ajaxPost && connection.groupsToken) {
95246                qs += "&groupsToken=" + window.encodeURIComponent(connection.groupsToken);
95247            }
95248
95249            if (!reconnecting) {
95250                url += "/connect";
95251            } else {
95252                if (poll) {
95253                    // longPolling transport specific
95254                    url += "/poll";
95255                } else {
95256                    url += "/reconnect";
95257                }
95258
95259                if (!ajaxPost && connection.messageId) {
95260                    qs += "&messageId=" + window.encodeURIComponent(connection.messageId);
95261                }
95262            }
95263            url += "?" + qs;
95264            url = transportLogic.prepareQueryString(connection, url);
95265
95266            if (!ajaxPost) {
95267                url += "&tid=" + Math.floor(Math.random() * 11);
95268            }
95269
95270            return url;
95271        },
95272
95273        maximizePersistentResponse: function (minPersistentResponse) {
95274            return {
95275                MessageId: minPersistentResponse.C,
95276                Messages: minPersistentResponse.M,
95277                Initialized: typeof (minPersistentResponse.S) !== "undefined" ? true : false,
95278                ShouldReconnect: typeof (minPersistentResponse.T) !== "undefined" ? true : false,
95279                LongPollDelay: minPersistentResponse.L,
95280                GroupsToken: minPersistentResponse.G
95281            };
95282        },
95283
95284        updateGroups: function (connection, groupsToken) {
95285            if (groupsToken) {
95286                connection.groupsToken = groupsToken;
95287            }
95288        },
95289
95290        stringifySend: function (connection, message) {
95291            if (typeof (message) === "string" || typeof (message) === "undefined" || message === null) {
95292                return message;
95293            }
95294            return connection.json.stringify(message);
95295        },
95296
95297        ajaxSend: function (connection, data) {
95298            var payload = transportLogic.stringifySend(connection, data),
95299                url = getAjaxUrl(connection, "/send"),
95300                xhr,
95301                onFail = function (error, connection) {
95302                    $(connection).triggerHandler(events.onError, [signalR._.transportError(signalR.resources.sendFailed, connection.transport, error, xhr), data]);
95303                };
95304
95305
95306            xhr = transportLogic.ajax(connection, {
95307                url: url,
95308                type: connection.ajaxDataType === "jsonp" ? "GET" : "POST",
95309                contentType: signalR._.defaultContentType,
95310                data: {
95311                    data: payload
95312                },
95313                success: function (result) {
95314                    var res;
95315
95316                    if (result) {
95317                        try {
95318                            res = connection._parseResponse(result);
95319                        }
95320                        catch (error) {
95321                            onFail(error, connection);
95322                            connection.stop();
95323                            return;
95324                        }
95325
95326                        transportLogic.triggerReceived(connection, res);
95327                    }
95328                },
95329                error: function (error, textStatus) {
95330                    if (textStatus === "abort" || textStatus === "parsererror") {
95331                        // The parsererror happens for sends that don't return any data, and hence
95332                        // don't write the jsonp callback to the response. This is harder to fix on the server
95333                        // so just hack around it on the client for now.
95334                        return;
95335                    }
95336
95337                    onFail(error, connection);
95338                }
95339            });
95340
95341            return xhr;
95342        },
95343
95344        ajaxAbort: function (connection, async) {
95345            if (typeof (connection.transport) === "undefined") {
95346                return;
95347            }
95348
95349            // Async by default unless explicitly overidden
95350            async = typeof async === "undefined" ? true : async;
95351
95352            var url = getAjaxUrl(connection, "/abort");
95353
95354            transportLogic.ajax(connection, {
95355                url: url,
95356                async: async,
95357                timeout: 1000,
95358                type: "POST"
95359            });
95360
95361            connection.log("Fired ajax abort async = " + async + ".");
95362        },
95363
95364        ajaxStart: function (connection, onSuccess) {
95365            var rejectDeferred = function (error) {
95366                    var deferred = connection._deferral;
95367                    if (deferred) {
95368                        deferred.reject(error);
95369                    }
95370                },
95371                triggerStartError = function (error) {
95372                    connection.log("The start request failed. Stopping the connection.");
95373                    $(connection).triggerHandler(events.onError, [error]);
95374                    rejectDeferred(error);
95375                    connection.stop();
95376                };
95377
95378            connection._.startRequest = transportLogic.ajax(connection, {
95379                url: getAjaxUrl(connection, "/start"),
95380                success: function (result, statusText, xhr) {
95381                    var data;
95382
95383                    try {
95384                        data = connection._parseResponse(result);
95385                    } catch (error) {
95386                        triggerStartError(signalR._.error(
95387                            signalR._.format(signalR.resources.errorParsingStartResponse, result),
95388                            error, xhr));
95389                        return;
95390                    }
95391
95392                    if (data.Response === "started") {
95393                        onSuccess();
95394                    } else {
95395                        triggerStartError(signalR._.error(
95396                            signalR._.format(signalR.resources.invalidStartResponse, result),
95397                            null /* error */, xhr));
95398                    }
95399                },
95400                error: function (xhr, statusText, error) {
95401                    if (statusText !== startAbortText) {
95402                        triggerStartError(signalR._.error(
95403                            signalR.resources.errorDuringStartRequest,
95404                            error, xhr));
95405                    } else {
95406                        // Stop has been called, no need to trigger the error handler
95407                        // or stop the connection again with onStartError
95408                        connection.log("The start request aborted because connection.stop() was called.");
95409                        rejectDeferred(signalR._.error(
95410                            signalR.resources.stoppedDuringStartRequest,
95411                            null /* error */, xhr));
95412                    }
95413                }
95414            });
95415        },
95416
95417        tryAbortStartRequest: function (connection) {
95418            if (connection._.startRequest) {
95419                // If the start request has already completed this will noop.
95420                connection._.startRequest.abort(startAbortText);
95421                delete connection._.startRequest;
95422            }
95423        },
95424
95425        tryInitialize: function (connection, persistentResponse, onInitialized) {
95426            if (persistentResponse.Initialized && onInitialized) {
95427                onInitialized();
95428            } else if (persistentResponse.Initialized) {
95429                connection.log("WARNING! The client received an init message after reconnecting.");
95430            }
95431
95432        },
95433
95434        triggerReceived: function (connection, data) {
95435            if (!connection._.connectingMessageBuffer.tryBuffer(data)) {
95436                $(connection).triggerHandler(events.onReceived, [data]);
95437            }
95438        },
95439
95440        processMessages: function (connection, minData, onInitialized) {
95441            var data;
95442
95443            // Update the last message time stamp
95444            transportLogic.markLastMessage(connection);
95445
95446            if (minData) {
95447                data = transportLogic.maximizePersistentResponse(minData);
95448
95449                transportLogic.updateGroups(connection, data.GroupsToken);
95450
95451                if (data.MessageId) {
95452                    connection.messageId = data.MessageId;
95453                }
95454
95455                if (data.Messages) {
95456                    $.each(data.Messages, function (index, message) {
95457                        transportLogic.triggerReceived(connection, message);
95458                    });
95459
95460                    transportLogic.tryInitialize(connection, data, onInitialized);
95461                }
95462            }
95463        },
95464
95465        monitorKeepAlive: function (connection) {
95466            var keepAliveData = connection._.keepAliveData;
95467
95468            // If we haven't initiated the keep alive timeouts then we need to
95469            if (!keepAliveData.monitoring) {
95470                keepAliveData.monitoring = true;
95471
95472                transportLogic.markLastMessage(connection);
95473
95474                // Save the function so we can unbind it on stop
95475                connection._.keepAliveData.reconnectKeepAliveUpdate = function () {
95476                    // Mark a new message so that keep alive doesn't time out connections
95477                    transportLogic.markLastMessage(connection);
95478                };
95479
95480                // Update Keep alive on reconnect
95481                $(connection).bind(events.onReconnect, connection._.keepAliveData.reconnectKeepAliveUpdate);
95482
95483                connection.log("Now monitoring keep alive with a warning timeout of " + keepAliveData.timeoutWarning + ", keep alive timeout of " + keepAliveData.timeout + " and disconnecting timeout of " + connection.disconnectTimeout);
95484            } else {
95485                connection.log("Tried to monitor keep alive but it's already being monitored.");
95486            }
95487        },
95488
95489        stopMonitoringKeepAlive: function (connection) {
95490            var keepAliveData = connection._.keepAliveData;
95491
95492            // Only attempt to stop the keep alive monitoring if its being monitored
95493            if (keepAliveData.monitoring) {
95494                // Stop monitoring
95495                keepAliveData.monitoring = false;
95496
95497                // Remove the updateKeepAlive function from the reconnect event
95498                $(connection).unbind(events.onReconnect, connection._.keepAliveData.reconnectKeepAliveUpdate);
95499
95500                // Clear all the keep alive data
95501                connection._.keepAliveData = {};
95502                connection.log("Stopping the monitoring of the keep alive.");
95503            }
95504        },
95505
95506        startHeartbeat: function (connection) {
95507            connection._.lastActiveAt = new Date().getTime();
95508            beat(connection);
95509        },
95510
95511        markLastMessage: function (connection) {
95512            connection._.lastMessageAt = new Date().getTime();
95513        },
95514
95515        markActive: function (connection) {
95516            if (transportLogic.verifyLastActive(connection)) {
95517                connection._.lastActiveAt = new Date().getTime();
95518                return true;
95519            }
95520
95521            return false;
95522        },
95523
95524        isConnectedOrReconnecting: function (connection) {
95525            return connection.state === signalR.connectionState.connected ||
95526                   connection.state === signalR.connectionState.reconnecting;
95527        },
95528
95529        ensureReconnectingState: function (connection) {
95530            if (changeState(connection,
95531                        signalR.connectionState.connected,
95532                        signalR.connectionState.reconnecting) === true) {
95533                $(connection).triggerHandler(events.onReconnecting);
95534            }
95535            return connection.state === signalR.connectionState.reconnecting;
95536        },
95537
95538        clearReconnectTimeout: function (connection) {
95539            if (connection && connection._.reconnectTimeout) {
95540                window.clearTimeout(connection._.reconnectTimeout);
95541                delete connection._.reconnectTimeout;
95542            }
95543        },
95544
95545        verifyLastActive: function (connection) {
95546            if (new Date().getTime() - connection._.lastActiveAt >= connection.reconnectWindow) {
95547                var message = signalR._.format(signalR.resources.reconnectWindowTimeout, new Date(connection._.lastActiveAt), connection.reconnectWindow);
95548                connection.log(message);
95549                $(connection).triggerHandler(events.onError, [signalR._.error(message, /* source */ "TimeoutException")]);
95550                connection.stop(/* async */ false, /* notifyServer */ false);
95551                return false;
95552            }
95553
95554            return tru
vendor: 6,932 bytes, lines 95554-95729
95554e;
95555        },
95556
95557        reconnect: function (connection, transportName) {
95558            var transport = signalR.transports[transportName];
95559
95560            // We should only set a reconnectTimeout if we are currently connected
95561            // and a reconnectTimeout isn't already set.
95562            if (transportLogic.isConnectedOrReconnecting(connection) && !connection._.reconnectTimeout) {
95563                // Need to verify before the setTimeout occurs because an application sleep could occur during the setTimeout duration.
95564                if (!transportLogic.verifyLastActive(connection)) {
95565                    return;
95566                }
95567
95568                connection._.reconnectTimeout = window.setTimeout(function () {
95569                    if (!transportLogic.verifyLastActive(connection)) {
95570                        return;
95571                    }
95572
95573                    transport.stop(connection);
95574
95575                    if (transportLogic.ensureReconnectingState(connection)) {
95576                        connection.log(transportName + " reconnecting.");
95577                        transport.start(connection);
95578                    }
95579                }, connection.reconnectDelay);
95580            }
95581        },
95582
95583        handleParseFailure: function (connection, result, error, onFailed, context) {
95584            var wrappedError = signalR._.transportError(
95585                signalR._.format(signalR.resources.parseFailed, result),
95586                connection.transport,
95587                error,
95588                context);
95589
95590            // If we're in the initialization phase trigger onFailed, otherwise stop the connection.
95591            if (onFailed && onFailed(wrappedError)) {
95592                connection.log("Failed to parse server response while attempting to connect.");
95593            } else {
95594                $(connection).triggerHandler(events.onError, [wrappedError]);
95595                connection.stop();
95596            }
95597        },
95598
95599        initHandler: function (connection) {
95600            return new InitHandler(connection);
95601        },
95602
95603        foreverFrame: {
95604            count: 0,
95605            connections: {}
95606        }
95607    };
95608
95609}(window.jQuery, window));
95610/* jquery.signalR.transports.webSockets.js */
95611// Copyright (c) .NET Foundation. All rights reserved.
95612// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
95613
95614
95615/*global window:false */
95616/// <reference path="jquery.signalR.transports.common.js" />
95617
95618(function ($, window, undefined) {
95619
95620    var signalR = $.signalR,
95621        events = $.signalR.events,
95622        changeState = $.signalR.changeState,
95623        transportLogic = signalR.transports._logic;
95624
95625    signalR.transports.webSockets = {
95626        name: "webSockets",
95627
95628        supportsKeepAlive: function () {
95629            return true;
95630        },
95631
95632        send: function (connection, data) {
95633            var payload = transportLogic.stringifySend(connection, data);
95634
95635            try {
95636                connection.socket.send(payload);
95637            } catch (ex) {
95638                $(connection).triggerHandler(events.onError,
95639                    [signalR._.transportError(
95640                        signalR.resources.webSocketsInvalidState,
95641                        connection.transport,
95642                        ex,
95643                        connection.socket
95644                    ),
95645                    data]);
95646            }
95647        },
95648
95649        start: function (connection, onSuccess, onFailed) {
95650            var url,
95651                opened = false,
95652                that = this,
95653                reconnecting = !onSuccess,
95654                $connection = $(connection);
95655
95656            if (!window.WebSocket) {
95657                onFailed();
95658                return;
95659            }
95660
95661            if (!connection.socket) {
95662                if (connection.webSocketServerUrl) {
95663                    url = connection.webSocketServerUrl;
95664                } else {
95665                    url = connection.wsProtocol + connection.host;
95666                }
95667
95668                url += transportLogic.getUrl(connection, this.name, reconnecting);
95669
95670                connection.log("Connecting to websocket endpoint '" + url + "'.");
95671                connection.socket = new window.WebSocket(url);
95672
95673                connection.socket.onopen = function () {
95674                    opened = true;
95675                    connection.log("Websocket opened.");
95676
95677                    transportLogic.clearReconnectTimeout(connection);
95678
95679                    if (changeState(connection,
95680                                    signalR.connectionState.reconnecting,
95681                                    signalR.connectionState.connected) === true) {
95682                        $connection.triggerHandler(events.onReconnect);
95683                    }
95684                };
95685
95686                connection.socket.onclose = function (event) {
95687                    var error;
95688
95689                    // Only handle a socket close if the close is from the current socket.
95690                    // Sometimes on disconnect the server will push down an onclose event
95691                    // to an expired socket.
95692
95693                    if (this === connection.socket) {
95694                        if (opened && typeof event.wasClean !== "undefined" && event.wasClean === false) {
95695                            // Ideally this would use the websocket.onerror handler (rather than checking wasClean in onclose) but
95696                            // I found in some circumstances Chrome won't call onerror. This implementation seems to work on all browsers.
95697                            error = signalR._.transportError(
95698                                signalR.resources.webSocketClosed,
95699                                connection.transport,
95700                                event);
95701
95702                            connection.log("Unclean disconnect from websocket: " + (event.reason || "[no reason given]."));
95703                        } else {
95704                            connection.log("Websocket closed.");
95705                        }
95706
95707                        if (!onFailed || !onFailed(error)) {
95708                            if (error) {
95709                                $(connection).triggerHandler(events.onError, [error]);
95710                            }
95711
95712                            that.reconnect(connection);
95713                        }
95714                    }
95715                };
95716
95717                connection.socket.onmessage = function (event) {
95718                    var data;
95719
95720                    try {
95721                        data = connection._parseResponse(event.data);
95722                    }
95723                    catch (error) {
95724                        transportLogic.handleParseFailure(connection, event.data, error, onFailed, event);
95725                        return;
95726                    }
95727
95728                    if (data) {
95729                        
95729// data.M is PersistentResponse.Messages
95730                        if ($.isEmptyObject(data) || data.M) {
95731                            transportLogic.processMessages(connection, data, onSuccess);
95732                        } else {
95733                            // For websockets we need to trigger onReceived
95734                            // for callbacks to outgoing hub calls.
95735                            transportLogic.triggerReceived(connection, data);
95736                        }
vendor: 11,128 bytes, lines 95736-96022
95736
95737                    }
95738                };
95739            }
95740        },
95741
95742        reconnect: function (connection) {
95743            transportLogic.reconnect(connection, this.name);
95744        },
95745
95746        lostConnection: function (connection) {
95747            this.reconnect(connection);
95748        },
95749
95750        stop: function (connection) {
95751            // Don't trigger a reconnect after stopping
95752            transportLogic.clearReconnectTimeout(connection);
95753
95754            if (connection.socket) {
95755                connection.log("Closing the Websocket.");
95756                connection.socket.close();
95757                connection.socket = null;
95758            }
95759        },
95760
95761        abort: function (connection, async) {
95762            transportLogic.ajaxAbort(connection, async);
95763        }
95764    };
95765
95766}(window.jQuery, window));
95767/* jquery.signalR.transports.serverSentEvents.js */
95768// Copyright (c) .NET Foundation. All rights reserved.
95769// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
95770
95771
95772/*global window:false */
95773/// <reference path="jquery.signalR.transports.common.js" />
95774
95775(function ($, window, undefined) {
95776
95777    var signalR = $.signalR,
95778        events = $.signalR.events,
95779        changeState = $.signalR.changeState,
95780        transportLogic = signalR.transports._logic,
95781        clearReconnectAttemptTimeout = function (connection) {
95782            window.clearTimeout(connection._.reconnectAttemptTimeoutHandle);
95783            delete connection._.reconnectAttemptTimeoutHandle;
95784        };
95785
95786    signalR.transports.serverSentEvents = {
95787        name: "serverSentEvents",
95788
95789        supportsKeepAlive: function () {
95790            return true;
95791        },
95792
95793        timeOut: 3000,
95794
95795        start: function (connection, onSuccess, onFailed) {
95796            var that = this,
95797                opened = false,
95798                $connection = $(connection),
95799                reconnecting = !onSuccess,
95800                url;
95801
95802            if (connection.eventSource) {
95803                connection.log("The connection already has an event source. Stopping it.");
95804                connection.stop();
95805            }
95806
95807            if (!window.EventSource) {
95808                if (onFailed) {
95809                    connection.log("This browser doesn't support SSE.");
95810                    onFailed();
95811                }
95812                return;
95813            }
95814
95815            url = transportLogic.getUrl(connection, this.name, reconnecting);
95816
95817            try {
95818                connection.log("Attempting to connect to SSE endpoint '" + url + "'.");
95819                connection.eventSource = new window.EventSource(url, { withCredentials: connection.withCredentials });
95820            }
95821            catch (e) {
95822                connection.log("EventSource failed trying to connect with error " + e.Message + ".");
95823                if (onFailed) {
95824                    // The connection failed, call the failed callback
95825                    onFailed();
95826                } else {
95827                    $connection.triggerHandler(events.onError, [signalR._.transportError(signalR.resources.eventSourceFailedToConnect, connection.transport, e)]);
95828                    if (reconnecting) {
95829                        // If we were reconnecting, rather than doing initial connect, then try reconnect again
95830                        that.reconnect(connection);
95831                    }
95832                }
95833                return;
95834            }
95835
95836            if (reconnecting) {
95837                connection._.reconnectAttemptTimeoutHandle = window.setTimeout(function () {
95838                    if (opened === false) {
95839                        // If we're reconnecting and the event source is attempting to connect,
95840                        // don't keep retrying. This causes duplicate connections to spawn.
95841                        if (connection.eventSource.readyState !== window.EventSource.OPEN) {
95842                            // If we were reconnecting, rather than doing initial connect, then try reconnect again
95843                            that.reconnect(connection);
95844                        }
95845                    }
95846                },
95847                that.timeOut);
95848            }
95849
95850            connection.eventSource.addEventListener("open", function (e) {
95851                connection.log("EventSource connected.");
95852
95853                clearReconnectAttemptTimeout(connection);
95854                transportLogic.clearReconnectTimeout(connection);
95855
95856                if (opened === false) {
95857                    opened = true;
95858
95859                    if (changeState(connection,
95860                                         signalR.connectionState.reconnecting,
95861                                         signalR.connectionState.connected) === true) {
95862                        $connection.triggerHandler(events.onReconnect);
95863                    }
95864                }
95865            }, false);
95866
95867            connection.eventSource.addEventListener("message", function (e) {
95868                var res;
95869
95870                // process messages
95871                if (e.data === "initialized") {
95872                    return;
95873                }
95874
95875                try {
95876                    res = connection._parseResponse(e.data);
95877                }
95878                catch (error) {
95879                    transportLogic.handleParseFailure(connection, e.data, error, onFailed, e);
95880                    return;
95881                }
95882
95883                transportLogic.processMessages(connection, res, onSuccess);
95884            }, false);
95885
95886            connection.eventSource.addEventListener("error", function (e) {
95887                var error = signalR._.transportError(
95888                    signalR.resources.eventSourceError,
95889                    connection.transport,
95890                    e);
95891
95892                // Only handle an error if the error is from the current Event Source.
95893                // Sometimes on disconnect the server will push down an error event
95894                // to an expired Event Source.
95895                if (this !== connection.eventSource) {
95896                    return;
95897                }
95898
95899                if (onFailed && onFailed(error)) {
95900                    return;
95901                }
95902
95903                connection.log("EventSource readyState: " + connection.eventSource.readyState + ".");
95904
95905                if (e.eventPhase === window.EventSource.CLOSED) {
95906                    // We don't use the EventSource's native reconnect function as it
95907                    // doesn't allow us to change the URL when reconnecting. We need
95908                    // to change the URL to not include the /connect suffix, and pass
95909                    // the last message id we received.
95910                    connection.log("EventSource reconnecting due to the server connection ending.");
95911                    that.reconnect(connection);
95912                } else {
95913                    // connection error
95914                    connection.log("EventSource error.");
95915                    $connection.triggerHandler(events.onError, [error]);
95916                }
95917            }, false);
95918        },
95919
95920        reconnect: function (connection) {
95921            transportLogic.reconnect(connection, this.name);
95922        },
95923
95924        lostConnection: function (connection) {
95925            this.reconnect(connection);
95926        },
95927
95928        send: function (connection, data) {
95929            transportLogic.ajaxSend(connection, data);
95930        },
95931
95932        stop: function (connection) {
95933            // Don't trigger a reconnect after stopping
95934            clearReconnectAttemptTimeout(connection);
95935            transportLogic.clearReconnectTimeout(connection);
95936
95937            if (connection && connection.eventSource) {
95938                connection.log("EventSource calling close().");
95939                connection.eventSource.close();
95940                connection.eventSource = null;
95941                delete connection.eventSource;
95942            }
95943        },
95944
95945        abort: function (connection, async) {
95946            transportLogic.ajaxAbort(connection, async);
95947        }
95948    };
95949
95950}(window.jQuery, window));
95951/* jquery.signalR.transports.foreverFrame.js */
95952// Copyright (c) .NET Foundation. All rights reserved.
95953// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
95954
95955
95956/*global window:false */
95957/// <reference path="jquery.signalR.transports.common.js" />
95958
95959(function ($, window, undefined) {
95960
95961    var signalR = $.signalR,
95962        events = $.signalR.events,
95963        changeState = $.signalR.changeState,
95964        transportLogic = signalR.transports._logic,
95965        createFrame = function () {
95966            var frame = window.document.createElement("iframe");
95967            frame.setAttribute("style", "position:absolute;top:0;left:0;width:0;height:0;visibility:hidden;");
95968            return frame;
95969        },
95970        // Used to prevent infinite loading icon spins in older versions of ie
95971        // We build this object inside a closure so we don't pollute the rest of
95972        // the foreverFrame transport with unnecessary functions/utilities.
95973        loadPreventer = (function () {
95974            var loadingFixIntervalId = null,
95975                loadingFixInterval = 1000,
95976                attachedTo = 0;
95977
95978            return {
95979                prevent: function () {
95980                    // Prevent additional iframe removal procedures from newer browsers
95981                    if (signalR._.ieVersion <= 8) {
95982                        // We only ever want to set the interval one time, so on the first attachedTo
95983                        if (attachedTo === 0) {
95984                            // Create and destroy iframe every 3 seconds to prevent loading icon, super hacky
95985                            loadingFixIntervalId = window.setInterval(function () {
95986                                var tempFrame = createFrame();
95987
95988                                window.document.body.appendChild(tempFrame);
95989                                window.document.body.removeChild(tempFrame);
95990
95991                                tempFrame = null;
95992                            }, loadingFixInterval);
95993                        }
95994
95995                        attachedTo++;
95996                    }
95997                },
95998                cancel: function () {
95999                    // Only clear the interval if there's only one more object that the loadPreventer is attachedTo
96000                    if (attachedTo === 1) {
96001                        window.clearInterval(loadingFixIntervalId);
96002                    }
96003
96004                    if (attachedTo > 0) {
96005                        attachedTo--;
96006                    }
96007                }
96008            };
96009        })();
96010
96011    signalR.transports.foreverFrame = {
96012        name: "foreverFrame",
96013
96014        supportsKeepAlive: function () {
96015            return true;
96016        },
96017
96018        // Added as a value here so we can create tests to verify functionality
96019        iframeClearThreshold: 50,
96020
96021        start: function (connection, onSuccess, onFailed) {
96022            
vendor: 11,846 bytes, lines 96022-96306
96022var that = this,
96023                frameId = (transportLogic.foreverFrame.count += 1),
96024                url,
96025                frame = createFrame(),
96026                frameLoadHandler = function () {
96027                    connection.log("Forever frame iframe finished loading and is no longer receiving messages.");
96028                    if (!onFailed || !onFailed()) {
96029                        that.reconnect(connection);
96030                    }
96031                };
96032
96033            if (window.EventSource) {
96034                // If the browser supports SSE, don't use Forever Frame
96035                if (onFailed) {
96036                    connection.log("Forever Frame is not supported by SignalR on browsers with SSE support.");
96037                    onFailed();
96038                }
96039                return;
96040            }
96041
96042            frame.setAttribute("data-signalr-connection-id", connection.id);
96043
96044            // Start preventing loading icon
96045            // This will only perform work if the loadPreventer is not attached to another connection.
96046            loadPreventer.prevent();
96047
96048            // Build the url
96049            url = transportLogic.getUrl(connection, this.name);
96050            url += "&frameId=" + frameId;
96051
96052            // add frame to the document prior to setting URL to avoid caching issues.
96053            window.document.documentElement.appendChild(frame);
96054
96055            connection.log("Binding to iframe's load event.");
96056
96057            if (frame.addEventListener) {
96058                frame.addEventListener("load", frameLoadHandler, false);
96059            } else if (frame.attachEvent) {
96060                frame.attachEvent("onload", frameLoadHandler);
96061            }
96062
96063            frame.src = url;
96064            transportLogic.foreverFrame.connections[frameId] = connection;
96065
96066            connection.frame = frame;
96067            connection.frameId = frameId;
96068
96069            if (onSuccess) {
96070                connection.onSuccess = function () {
96071                    connection.log("Iframe transport started.");
96072                    onSuccess();
96073                };
96074            }
96075        },
96076
96077        reconnect: function (connection) {
96078            var that = this;
96079
96080            // Need to verify connection state and verify before the setTimeout occurs because an application sleep could occur during the setTimeout duration.
96081            if (transportLogic.isConnectedOrReconnecting(connection) && transportLogic.verifyLastActive(connection)) {
96082                window.setTimeout(function () {
96083                    // Verify that we're ok to reconnect.
96084                    if (!transportLogic.verifyLastActive(connection)) {
96085                        return;
96086                    }
96087
96088                    if (connection.frame && transportLogic.ensureReconnectingState(connection)) {
96089                        var frame = connection.frame,
96090                            src = transportLogic.getUrl(connection, that.name, true) + "&frameId=" + connection.frameId;
96091                        connection.log("Updating iframe src to '" + src + "'.");
96092                        frame.src = src;
96093                    }
96094                }, connection.reconnectDelay);
96095            }
96096        },
96097
96098        lostConnection: function (connection) {
96099            this.reconnect(connection);
96100        },
96101
96102        send: function (connection, data) {
96103            transportLogic.ajaxSend(connection, data);
96104        },
96105
96106        receive: function (connection, data) {
96107            var cw,
96108                body,
96109                response;
96110
96111            if (connection.json !== connection._originalJson) {
96112                // If there's a custom JSON parser configured then serialize the object
96113                // using the original (browser) JSON parser and then deserialize it using
96114                // the custom parser (connection._parseResponse does that). This is so we
96115                // can easily send the response from the server as "raw" JSON but still
96116                // support custom JSON deserialization in the browser.
96117                data = connection._originalJson.stringify(data);
96118            }
96119
96120            response = connection._parseResponse(data);
96121
96122            transportLogic.processMessages(connection, response, connection.onSuccess);
96123
96124            // Protect against connection stopping from a callback trigger within the processMessages above.
96125            if (connection.state === $.signalR.connectionState.connected) {
96126                // Delete the script & div elements
96127                connection.frameMessageCount = (connection.frameMessageCount || 0) + 1;
96128                if (connection.frameMessageCount > signalR.transports.foreverFrame.iframeClearThreshold) {
96129                    connection.frameMessageCount = 0;
96130                    cw = connection.frame.contentWindow || connection.frame.contentDocument;
96131                    if (cw && cw.document && cw.document.body) {
96132                        body = cw.document.body;
96133
96134                        // Remove all the child elements from the iframe's body to conserver memory
96135                        while (body.firstChild) {
96136                            body.removeChild(body.firstChild);
96137                        }
96138                    }
96139                }
96140            }
96141        },
96142
96143        stop: function (connection) {
96144            var cw = null;
96145
96146            // Stop attempting to prevent loading icon
96147            loadPreventer.cancel();
96148
96149            if (connection.frame) {
96150                if (connection.frame.stop) {
96151                    connection.frame.stop();
96152                } else {
96153                    try {
96154                        cw = connection.frame.contentWindow || connection.frame.contentDocument;
96155                        if (cw.document && cw.document.execCommand) {
96156                            cw.document.execCommand("Stop");
96157                        }
96158                    }
96159                    catch (e) {
96160                        connection.log("Error occurred when stopping foreverFrame transport. Message = " + e.message + ".");
96161                    }
96162                }
96163
96164                // Ensure the iframe is where we left it
96165                if (connection.frame.parentNode === window.document.body) {
96166                    window.document.body.removeChild(connection.frame);
96167                }
96168
96169                delete transportLogic.foreverFrame.connections[connection.frameId];
96170                connection.frame = null;
96171                connection.frameId = null;
96172                delete connection.frame;
96173                delete connection.frameId;
96174                delete connection.onSuccess;
96175                delete connection.frameMessageCount;
96176                connection.log("Stopping forever frame.");
96177            }
96178        },
96179
96180        abort: function (connection, async) {
96181            transportLogic.ajaxAbort(connection, async);
96182        },
96183
96184        getConnection: function (id) {
96185            return transportLogic.foreverFrame.connections[id];
96186        },
96187
96188        started: function (connection) {
96189            if (changeState(connection,
96190                signalR.connectionState.reconnecting,
96191                signalR.connectionState.connected) === true) {
96192
96193                $(connection).triggerHandler(events.onReconnect);
96194            }
96195        }
96196    };
96197
96198}(window.jQuery, window));
96199/* jquery.signalR.transports.longPolling.js */
96200// Copyright (c) .NET Foundation. All rights reserved.
96201// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
96202
96203
96204/*global window:false */
96205/// <reference path="jquery.signalR.transports.common.js" />
96206
96207(function ($, window, undefined) {
96208
96209    var signalR = $.signalR,
96210        events = $.signalR.events,
96211        changeState = $.signalR.changeState,
96212        isDisconnecting = $.signalR.isDisconnecting,
96213        transportLogic = signalR.transports._logic;
96214
96215    signalR.transports.longPolling = {
96216        name: "longPolling",
96217
96218        supportsKeepAlive: function () {
96219            return false;
96220        },
96221
96222        reconnectDelay: 3000,
96223
96224        start: function (connection, onSuccess, onFailed) {
96225            /// <summary>Starts the long polling connection</summary>
96226            /// <param name="connection" type="signalR">The SignalR connection to start</param>
96227            var that = this,
96228                fireConnect = function () {
96229                    fireConnect = $.noop;
96230
96231                    connection.log("LongPolling connected.");
96232
96233                    if (onSuccess) {
96234                        onSuccess();
96235                    } else {
96236                        connection.log("WARNING! The client received an init message after reconnecting.");
96237                    }
96238                },
96239                tryFailConnect = function (error) {
96240                    if (onFailed(error)) {
96241                        connection.log("LongPolling failed to connect.");
96242                        return true;
96243                    }
96244
96245                    return false;
96246                },
96247                privateData = connection._,
96248                reconnectErrors = 0,
96249                fireReconnected = function (instance) {
96250                    window.clearTimeout(privateData.reconnectTimeoutId);
96251                    privateData.reconnectTimeoutId = null;
96252
96253                    if (changeState(instance,
96254                                    signalR.connectionState.reconnecting,
96255                                    signalR.connectionState.connected) === true) {
96256                        // Successfully reconnected!
96257                        instance.log("Raising the reconnect event");
96258                        $(instance).triggerHandler(events.onReconnect);
96259                    }
96260                },
96261                // 1 hour
96262                maxFireReconnectedTimeout = 3600000;
96263
96264            if (connection.pollXhr) {
96265                connection.log("Polling xhr requests already exists, aborting.");
96266                connection.stop();
96267            }
96268
96269            connection.messageId = null;
96270
96271            privateData.reconnectTimeoutId = null;
96272
96273            privateData.pollTimeoutId = window.setTimeout(function () {
96274                (function poll(instance, raiseReconnect) {
96275                    var messageId = instance.messageId,
96276                        connect = (messageId === null),
96277                        reconnecting = !connect,
96278                        polling = !raiseReconnect,
96279                        url = transportLogic.getUrl(instance, that.name, reconnecting, polling, true /* use Post for longPolling */),
96280                        postData = {};
96281
96282                    if (instance.messageId) {
96283                        postData.messageId = instance.messageId;
96284                    }
96285
96286                    if (instance.groupsToken) {
96287                        postData.groupsToken = instance.groupsToken;
96288                    }
96289
96290                    // If we've disconnected during the time we've tried to re-instantiate the poll then stop.
96291                    if (isDisconnecting(instance) === true) {
96292                        return;
96293                    }
96294
96295                    connection.log("Opening long polling request to '" + url + "'.");
96296                    instance.pollXhr = transportLogic.ajax(connection, {
96297                        xhrFields: {
96298                            onprogress: function () {
96299                                transportLogic.markLastMessage(connection);
96300                            }
96301                        },
96302                        url: url,
96303                        type: "POST",
96304                        contentType: signalR._.defaultContentType,
96305                        data: postData,
96306                        timeout: connection._.pollTimeout
vendor: 8,663 bytes, lines 96306-96470
96306,
96307                        success: function (result) {
96308                            var minData,
96309                                delay = 0,
96310                                data,
96311                                shouldReconnect;
96312
96313                            connection.log("Long poll complete.");
96314
96315                            // Reset our reconnect errors so if we transition into a reconnecting state again we trigger
96316                            // reconnected quickly
96317                            reconnectErrors = 0;
96318
96319                            try {
96320                                // Remove any keep-alives from the beginning of the result
96321                                minData = connection._parseResponse(result);
96322                            }
96323                            catch (error) {
96324                                transportLogic.handleParseFailure(instance, result, error, tryFailConnect, instance.pollXhr);
96325                                return;
96326                            }
96327
96328                            // If there's currently a timeout to trigger reconnect, fire it now before processing messages
96329                            if (privateData.reconnectTimeoutId !== null) {
96330                                fireReconnected(instance);
96331                            }
96332
96333                            if (minData) {
96334                                data = transportLogic.maximizePersistentResponse(minData);
96335                            }
96336
96337                            transportLogic.processMessages(instance, minData, fireConnect);
96338
96339                            if (data &&
96340                                $.type(data.LongPollDelay) === "number") {
96341                                delay = data.LongPollDelay;
96342                            }
96343
96344                            if (isDisconnecting(instance) === true) {
96345                                return;
96346                            }
96347
96348                            shouldReconnect = data && data.ShouldReconnect;
96349                            if (shouldReconnect) {
96350                                // Transition into the reconnecting state
96351                                // If this fails then that means that the user transitioned the connection into a invalid state in processMessages.
96352                                if (!transportLogic.ensureReconnectingState(instance)) {
96353                                    return;
96354                                }
96355                            }
96356
96357                            // We never want to pass a raiseReconnect flag after a successful poll.  This is handled via the error function
96358                            if (delay > 0) {
96359                                privateData.pollTimeoutId = window.setTimeout(function () {
96360                                    poll(instance, shouldReconnect);
96361                                }, delay);
96362                            } else {
96363                                poll(instance, shouldReconnect);
96364                            }
96365                        },
96366
96367                        error: function (data, textStatus) {
96368                            var error = signalR._.transportError(signalR.resources.longPollFailed, connection.transport, data, instance.pollXhr);
96369
96370                            // Stop trying to trigger reconnect, connection is in an error state
96371                            // If we're not in the reconnect state this will noop
96372                            window.clearTimeout(privateData.reconnectTimeoutId);
96373                            privateData.reconnectTimeoutId = null;
96374
96375                            if (textStatus === "abort") {
96376                                connection.log("Aborted xhr request.");
96377                                return;
96378                            }
96379
96380                            if (!tryFailConnect(error)) {
96381
96382                                // Increment our reconnect errors, we assume all errors to be reconnect errors
96383                                // In the case that it's our first error this will cause Reconnect to be fired
96384                                // after 1 second due to reconnectErrors being = 1.
96385                                reconnectErrors++;
96386
96387                                if (connection.state !== signalR.connectionState.reconnecting) {
96388                                    connection.log("An error occurred using longPolling. Status = " + textStatus + ".  Response = " + data.responseText + ".");
96389                                    $(instance).triggerHandler(events.onError, [error]);
96390                                }
96391
96392                                // We check the state here to verify that we're not in an invalid state prior to verifying Reconnect.
96393                                // If we're not in connected or reconnecting then the next ensureReconnectingState check will fail and will return.
96394                                // Therefore we don't want to change that failure code path.
96395                                if ((connection.state === signalR.connectionState.connected ||
96396                                    connection.state === signalR.connectionState.reconnecting) &&
96397                                    !transportLogic.verifyLastActive(connection)) {
96398                                    return;
96399                                }
96400
96401                                // Transition into the reconnecting state
96402                                // If this fails then that means that the user transitioned the connection into the disconnected or connecting state within the above error handler trigger.
96403                                if (!transportLogic.ensureReconnectingState(instance)) {
96404                                    return;
96405                                }
96406
96407                                // Call poll with the raiseReconnect flag as true after the reconnect delay
96408                                privateData.pollTimeoutId = window.setTimeout(function () {
96409                                    poll(instance, true);
96410                                }, that.reconnectDelay);
96411                            }
96412                        }
96413                    });
96414
96415                    // This will only ever pass after an error has occurred via the poll ajax procedure.
96416                    if (reconnecting && raiseReconnect === true) {
96417                        // We wait to reconnect depending on how many times we've failed to reconnect.
96418                        // This is essentially a heuristic that will exponentially increase in wait time before
96419                        // triggering reconnected.  This depends on the "error" handler of Poll to cancel this
96420                        // timeout if it triggers before the Reconnected event fires.
96421                        // The Math.min at the end is to ensure that the reconnect timeout does not overflow.
96422                        privateData.reconnectTimeoutId = window.setTimeout(function () { fireReconnected(instance); }, Math.min(1000 * (Math.pow(2, reconnectErrors) - 1), maxFireReconnectedTimeout));
96423                    }
96424                }(connection));
96425            }, 250); // Have to delay initial poll so Chrome doesn't show loader spinner in tab
96426        },
96427
96428        lostConnection: function (connection) {
96429            if (connection.pollXhr) {
96430                connection.pollXhr.abort("lostConnection");
96431            }
96432        },
96433
96434        send: function (connection, data) {
96435            transportLogic.ajaxSend(connection, data);
96436        },
96437
96438        stop: function (connection) {
96439            /// <summary>Stops the long polling connection</summary>
96440            /// <param name="connection" type="signalR">The SignalR connection to stop</param>
96441
96442            window.clearTimeout(connection._.pollTimeoutId);
96443            window.clearTimeout(connection._.reconnectTimeoutId);
96444
96445            delete connection._.pollTimeoutId;
96446            delete connection._.reconnectTimeoutId;
96447
96448            if (connection.pollXhr) {
96449                connection.pollXhr.abort();
96450                connection.pollXhr = null;
96451                delete connection.pollXhr;
96452            }
96453        },
96454
96455        abort: function (connection, async) {
96456            transportLogic.ajaxAbort(connection, async);
96457        }
96458    };
96459
96460}(window.jQuery, window));
96461/* jquery.signalR.hubs.js */
96462// Copyright (c) .NET Foundation. All rights reserved.
96463// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
96464
96465/*global window:false */
96466/// <reference path="jquery.signalR.core.js" />
96467
96468(function ($, window, undefined) {
96469
96470    var 
vendor: 2,287 bytes, lines 96470-96533
96470eventNamespace = ".hubProxy",
96471        signalR = $.signalR;
96472
96473    function makeEventName(event) {
96474        return event + eventNamespace;
96475    }
96476
96477    // Equivalent to Array.prototype.map
96478    function map(arr, fun, thisp) {
96479        var i,
96480            length = arr.length,
96481            result = [];
96482        for (i = 0; i < length; i += 1) {
96483            if (arr.hasOwnProperty(i)) {
96484                result[i] = fun.call(thisp, arr[i], i, arr);
96485            }
96486        }
96487        return result;
96488    }
96489
96490    function getArgValue(a) {
96491        return $.isFunction(a) ? null : ($.type(a) === "undefined" ? null : a);
96492    }
96493
96494    function hasMembers(obj) {
96495        for (var key in obj) {
96496            // If we have any properties in our callback map then we have callbacks and can exit the loop via return
96497            if (obj.hasOwnProperty(key)) {
96498                return true;
96499            }
96500        }
96501
96502        return false;
96503    }
96504
96505    function clearInvocationCallbacks(connection, error) {
96506        /// <param name="connection" type="hubConnection" />
96507        var callbacks = connection._.invocationCallbacks,
96508            callback;
96509
96510        if (hasMembers(callbacks)) {
96511            connection.log("Clearing hub invocation callbacks with error: " + error + ".");
96512        }
96513
96514        // Reset the callback cache now as we have a local var referencing it
96515        connection._.invocationCallbackId = 0;
96516        delete connection._.invocationCallbacks;
96517        connection._.invocationCallbacks = {};
96518
96519        // Loop over the callbacks and invoke them.
96520        // We do this using a local var reference and *after* we've cleared the cache
96521        // so that if a fail callback itself tries to invoke another method we don't
96522        // end up with its callback in the list we're looping over.
96523        for (var callbackId in callbacks) {
96524            callback = callbacks[callbackId];
96525            callback.method.call(callback.scope, { E: error });
96526        }
96527    }
96528
96529    // hubProxy
96530    function hubProxy(hubConnection, hubName) {
96531        /// <summary>
96532        ///     Creates a new proxy object for the given hub connection that can be used to invoke
96533        ///     methods on server hubs and handle client method invocation requests from the server.
96534        /// </summary>
96535        return new hubProxy.fn.init(hubConnection, hubName);
96536    }
96537
96538    hubProxy.fn = hubProxy.prototype = {
96539        init: function (connection, hubName) {
96540            this.state = {};
96541            this.connection = connection;
96542            this.hubName = hubName;
96543            this._ = {
96544                callbackMap: {}
96545            };
96546        },
96547
96548        constructor: hubProxy,
96549
96550        hasSubscriptions: function () {
96551            return hasMembers(this._.callbackMap);
96552        },
96553
96554        on: function (eventName, callback) {
96555            /// <summary>Wires up a callback to be invoked when a invocation request is received from the server hub.</summary>
96556            /// <param name="eventName" type="String">The name of the hub event to register the callback for.</param>
96557            /// <param name="callback" type="Function">The callback to be invoked.</param>
96558            var that = this,
96559                callbackMap = that._.callbackMap;
96560
96561            // Normalize the event name to lowercase
96562            eventName = eventName.toLowerCase();
96563
96564            // If there is not an event registered for this callback yet we want to create its event space in the callback map.
96565            if (!callbackMap[eventName]) {
96566                callbackMap[eventName] = {};
96567            }
96568
96569            // Map the callback to our encompassed function
96570            callbackMap[eventName][callback] = function (e, data) {
96571                callback.apply(that, data);
96572            };
96573
96574            $(that).bind(makeEventName(eventName), callbackMap[eventName][callback]);
96575
96576            return that;
96577        },
96578
96579        off: function (eventName, callback) {
96580            /// <summary>Removes the callback invocation request from the server hub for the given event name.</summary>
96581            /// <param name="eventName" type="String">The name of the hub event to unregister the callback for.</param>
96582            /// <param name="callback" type="Function">The callback to be invoked.</param>
96583            var that = this,
96584                callbackMap = that._.callbackMap,
96585                callbackSpace;
96586
96587            // Normalize the event name to lowercase
96588            eventName = eventName.toLowerCase();
96589
96590            callbackSpace = callbackMap[eventName];
96591
96592            // Verify that there is an event space to unbind
96593            if (callbackSpace) {
96594                // Only unbind if there's an event bound with eventName and a callback with the specified callback
96595                if (callbackSpace[callback]) {
96596                    $(that).unbind(makeEventName(eventName), callbackSpace[callback]);
96597
96598                    // Remove the callback from the callback map
96599                    delete callbackSpace[callback];
96600
96601                    // Check if there are any members left on the event, if not we need to destroy it.
96602                    if (!hasMembers(callbackSpace)) {
96603                        delete callbackMap[eventName];
96604                    }
96605                } else if (!callback) { // Check if we're removing the whole event and we didn't error because of an invalid callback
96606                    $(that).unbind(makeEventName(eventName));
96607
96608                    delete callbackMap[eventName];
96609                }
96610            }
96611
96612            return that;
96613        },
96614
96615        invoke: function (methodName) {
96616            /// <summary>Invokes a server hub method with the given arguments.</summary>
96617            /// <param name="methodName" type="String">The name of the server hub method.</param>
96618
96619            var that = this,
96620                connection = that.connection,
96621                args = $.makeArray(arguments).slice(1),
96622                argValues = map(args, getArgValue),
96623                data = { H: that.hubName, M: methodName, A: argValues, I: connection._.invocationCallbackId },
96624                d = $.Deferred(),
96625                callback = function (minResult) {
96626                    var result = that._maximizeHubResponse(minResult),
96627                        source,
96628                        error;
96629
96630                    // Update the hub state
96631                    $.extend(that.state, result.State);
96632
96633                    if (result.Progress) {
96634                        if (d.notifyWith) {
vendor: 8,250 bytes, lines 96635-96825
96635                            // Progress is only supported in jQuery 1.7+
96636                            d.notifyWith(that, [result.Progress.Data]);
96637                        } else if(!connection._.progressjQueryVersionLogged) {
96638                            connection.log("A hub method invocation progress update was received but the version of jQuery in use (" + $.prototype.jquery + ") does not support progress updates. Upgrade to jQuery 1.7+ to receive progress notifications.");
96639                            connection._.progressjQueryVersionLogged = true;
96640                        }
96641                    } else if (result.Error) {
96642                        // Server hub method threw an exception, log it & reject the deferred
96643                        if (result.StackTrace) {
96644                            connection.log(result.Error + "\n" + result.StackTrace + ".");
96645                        }
96646
96647                        // result.ErrorData is only set if a HubException was thrown
96648                        source = result.IsHubException ? "HubException" : "Exception";
96649                        error = signalR._.error(result.Error, source);
96650                        error.data = result.ErrorData;
96651
96652                        connection.log(that.hubName + "." + methodName + " failed to execute. Error: " + error.message);
96653                        d.rejectWith(that, [error]);
96654                    } else {
96655                        // Server invocation succeeded, resolve the deferred
96656                        connection.log("Invoked " + that.hubName + "." + methodName);
96657                        d.resolveWith(that, [result.Result]);
96658                    }
96659                };
96660
96661            connection._.invocationCallbacks[connection._.invocationCallbackId.toString()] = { scope: that, method: callback };
96662            connection._.invocationCallbackId += 1;
96663
96664            if (!$.isEmptyObject(that.state)) {
96665                data.S = that.state;
96666            }
96667
96668            connection.log("Invoking " + that.hubName + "." + methodName);
96669            connection.send(data);
96670
96671            return d.promise();
96672        },
96673
96674        _maximizeHubResponse: function (minHubResponse) {
96675            return {
96676                State: minHubResponse.S,
96677                Result: minHubResponse.R,
96678                Progress: minHubResponse.P ? {
96679                    Id: minHubResponse.P.I,
96680                    Data: minHubResponse.P.D
96681                } : null,
96682                Id: minHubResponse.I,
96683                IsHubException: minHubResponse.H,
96684                Error: minHubResponse.E,
96685                StackTrace: minHubResponse.T,
96686                ErrorData: minHubResponse.D
96687            };
96688        }
96689    };
96690
96691    hubProxy.fn.init.prototype = hubProxy.fn;
96692
96693    // hubConnection
96694    function hubConnection(url, options) {
96695        /// <summary>Creates a new hub connection.</summary>
96696        /// <param name="url" type="String">[Optional] The hub route url, defaults to "/signalr".</param>
96697        /// <param name="options" type="Object">[Optional] Settings to use when creating the hubConnection.</param>
96698        var settings = {
96699            qs: null,
96700            logging: false,
96701            useDefaultPath: true
96702        };
96703
96704        $.extend(settings, options);
96705
96706        if (!url || settings.useDefaultPath) {
96707            url = (url || "") + "/signalr";
96708        }
96709        return new hubConnection.fn.init(url, settings);
96710    }
96711
96712    hubConnection.fn = hubConnection.prototype = $.connection();
96713
96714    hubConnection.fn.init = function (url, options) {
96715        var settings = {
96716                qs: null,
96717                logging: false,
96718                useDefaultPath: true
96719            },
96720            connection = this;
96721
96722        $.extend(settings, options);
96723
96724        // Call the base constructor
96725        $.signalR.fn.init.call(connection, url, settings.qs, settings.logging);
96726
96727        // Object to store hub proxies for this connection
96728        connection.proxies = {};
96729
96730        connection._.invocationCallbackId = 0;
96731        connection._.invocationCallbacks = {};
96732
96733        // Wire up the received handler
96734        connection.received(function (minData) {
96735            var data, proxy, dataCallbackId, callback, hubName, eventName;
96736            if (!minData) {
96737                return;
96738            }
96739
96740            // We have to handle progress updates first in order to ensure old clients that receive
96741            // progress updates enter the return value branch and then no-op when they can't find
96742            // the callback in the map (because the minData.I value will not be a valid callback ID)
96743            if (typeof (minData.P) !== "undefined") {
96744                // Process progress notification
96745                dataCallbackId = minData.P.I.toString();
96746                callback = connection._.invocationCallbacks[dataCallbackId];
96747                if (callback) {
96748                    callback.method.call(callback.scope, minData);
96749                }
96750            } else if (typeof (minData.I) !== "undefined") {
96751                // We received the return value from a server method invocation, look up callback by id and call it
96752                dataCallbackId = minData.I.toString();
96753                callback = connection._.invocationCallbacks[dataCallbackId];
96754                if (callback) {
96755                    // Delete the callback from the proxy
96756                    connection._.invocationCallbacks[dataCallbackId] = null;
96757                    delete connection._.invocationCallbacks[dataCallbackId];
96758
96759                    // Invoke the callback
96760                    callback.method.call(callback.scope, minData);
96761                }
96762            } else {
96763                data = this._maximizeClientHubInvocation(minData);
96764
96765                // We received a client invocation request, i.e. broadcast from server hub
96766                connection.log("Triggering client hub event '" + data.Method + "' on hub '" + data.Hub + "'.");
96767
96768                // Normalize the names to lowercase
96769                hubName = data.Hub.toLowerCase();
96770                eventName = data.Method.toLowerCase();
96771
96772                // Trigger the local invocation event
96773                proxy = this.proxies[hubName];
96774
96775                // Update the hub state
96776                $.extend(proxy.state, data.State);
96777                $(proxy).triggerHandler(makeEventName(eventName), [data.Args]);
96778            }
96779        });
96780
96781        connection.error(function (errData, origData) {
96782            var callbackId, callback;
96783
96784            if (!origData) {
96785                // No original data passed so this is not a send error
96786                return;
96787            }
96788
96789            callbackId = origData.I;
96790            callback = connection._.invocationCallbacks[callbackId];
96791
96792            // Verify that there is a callback bound (could have been cleared)
96793            if (callback) {
96794                // Delete the callback
96795                connection._.invocationCallbacks[callbackId] = null;
96796                delete connection._.invocationCallbacks[callbackId];
96797
96798                // Invoke the callback with an error to reject the promise
96799                callback.method.call(callback.scope, { E: errData });
96800            }
96801        });
96802
96803        connection.reconnecting(function () {
96804            if (connection.transport && connection.transport.name === "webSockets") {
96805                clearInvocationCallbacks(connection, "Connection started reconnecting before invocation result was received.");
96806            }
96807        });
96808
96809        connection.disconnected(function () {
96810            clearInvocationCallbacks(connection, "Connection was disconnected before invocation result was received.");
96811        });
96812    };
96813
96814    hubConnection.fn._maximizeClientHubInvocation = function (minClientHubInvocation) {
96815        return {
96816            Hub: minClientHubInvocation.H,
96817            Method: minClientHubInvocation.M,
96818            Args: minClientHubInvocation.A,
96819            State: minClientHubInvocation.S
96820        };
96821    };
96822
96823    hubConnection.fn._registerSubscribedHubs = function () {
96824        /// <summary>
96825        ///     Sets the starting event to loop through the known hub
96825s and register any new hubs
96826        ///     that have been added to the proxy.
96827        /// </summary>
96828        var connection = this;
96829
96830        if (!connection._subscribedToHubs) {
96831            connection._subscribedToHubs = true;
96832            connection.starting(function () {
96833                // Set the connection's data object with all the hub proxies with active subscriptions.
96834                // These proxies will receive notifications from the server.
96835                var subscribedHubs = [];
96836
96837                $.each(connection.proxies, function (key) {
96838                    if (this.hasSubscriptions()) {
96839                        subscribedHubs.push({ name: key });
96840                        connection.log("Client subscribed to hub '" + key + "'.");
96841                    }
96842                });
96843
96844                if (subscribedHubs.length === 0) {
96845                    connection.log("No hubs have been subscribed to.  The client will not receive data from hubs.  To fix, declare at least one client side function prior to connection start for each hub you wish to subscribe to.");
96846                }
96847
96848                connection.data = connection.json.stringify(subscribedHubs);
96849            });
96850        }
96851    };
96852
96853    hubConnection.fn.createHubProxy = function (hubName) {
96854        /// <summary>
96855        ///     Creates a new proxy object for the given hub connection that can be used to invoke
96856        ///     methods on server hubs and handle client method invocation requests from the server.
96857        /// </summary>
96858        /// <param name="hubName" type="String">
96859        ///     The name of the hub on the server to create the proxy for.
96860        /// </param>
96861
96862        // Normalize the name to lowercase
96863        hubName = hubName.toLowerCase();
96864
96865        var proxy = this.proxies[hubName];
96866        if (!proxy) {
96867            proxy = hubProxy(this, hubName);
96868            this.proxies[hubName] = proxy;
96869        }
96870
96871        this._registerSubscribedHubs();
96872
96873        return proxy;
96874    };
96875
96876    hubConnection.fn.init.prototype = hubConnection.fn;
96877
96878    $.hubConnection = hubConnection;
96879
96880}(window.jQuery, window));
96881/* jquery.signalR.version.js */
96882// Copyright (c) .NET Foundation. All rights reserved.
96883// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
96884
96885
96886/*global window:false */
96887/// <reference path="jquery.signalR.core.js" />
96888(function ($, undefined) {
96889    $.signalR.version = "2.2.1";
96890}(window.jQuery));
96891
96892define("signalr", ["jquery"], (function (global) {
96893    return function () {
96894        var ret, fn;
96895        return ret || global.$.connection;
96896    };
96897}(this)));
96898
96899// Edited by Simon Woodhead on 21061116 to remove exports code which was causing issues in the browser.
96900
96901/*!
96902 * Retina.js v2.0.0
96903 *
96904 * Copyright 2016 Axial, LLC
96905 * Released under the MIT license
96906 *
96907 * Retina.js is an open source script that makes it easy to serve
96908 * high-resolution images to devices with retina displays.
96909 */
96910
96911
96912//Object.defineProperty(exports, "__esModule", {
96913//  value: true
96914//});
96915/*
96916 * Determine whether or not `window` is available.
96917 */
96918var hasWindow = typeof window !== 'undefined';
96919
96920/*
96921 * Get the device pixel ratio per our environment.
96922 * Default to 1.
96923 */
96924var environment = hasWindow ? parseInt(window.devicePixelRatio + 0.5, 10) || 1 : 1;
96925
96926/*
96927 * Define a pattern for capturing src url suffixes.
96928 */
96929var srcReplace = /(\.[A-z]{3,4}\/?(\?.*)?)$/;
96930var inlineReplace = /url\(('|")?([^\)'"]+)('|")?\)/i;
96931
96932/*
96933 * Define our selectors for elements to target.
96934 */
96935var selector = '[data-rjs]';
96936
96937/**
96938 * Chooses the actual image size to fetch, (for example 2 or 3) that
96939 * will be used to create a suffix like "@2x" or "@3x".
96940 *
96941 * @param  {String|Number} cap The number the user provided indicating that
96942 *                             they have prepared images up to this size.
96943 *
96944 * @return {Number} The number we'll be using to create a suffix.
96945 */
96946function chooseCap(cap) {
96947  var numericCap = parseInt(cap, 10);
96948
96949  /*
96950   * If the environment's device pixel ratio is less than what the user
96951   * provided, we'll only grab images at that size.
96952   */
96953  if (environment < numericCap) {
96954    return environment;
96955
96956    /*
96957     * If the device pixel ratio is greater than or equal to what the
96958     * user provided, we'll use what the user provided.
96959     */
96960  } else {
96961      return numericCap;
96962    }
96963}
96964
96965/**
96966 * Makes sure that, since we are going to swap out the source of an image,
96967 * the image does not change size on the page.
96968 *
96969 * @param  {Element} image An image element in the DOM.
96970 *
96971 * @return {Element} The same element that was passed in.
96972 */
96973function forceOriginalDimensions(image) {
96974  if (!image.hasAttribute('data-no-resize')) {
96975    if (image.offsetWidth === 0 && image.offsetHeight === 0) {
96976      image.setAttribute('width', image.naturalWidth);
96977      image.setAttribute('height', image.naturalHeight);
96978    } else {
96979      image.setAttribute('width', image.offsetWidth);
96980      image.setAttribute('height', image.offsetHeight);
96981    }
96982  }
96983  return image;
96984}
96985
96986/**
96987 * Determines whether the retina image actually exists on the server.
96988 * If so, swaps out the retina image for the standard one. If not,
96989 * leaves the original image alone.
96990 *
96991 * @param {Element} image  An image element in the DOM.
96992 * @param {String}  newSrc The url to the retina image.
96993 *
96994 * @return {undefined}
96995 */
96996function setSourceIfAvailable(image, retinaURL) {
96997  var imgType = image.nodeName.toLowerCase();
96998
96999  /*
97000   * Create a new image element and give it a load listener. When the
97001   * load listener fires, it means the URL is correct and we will then
97002   * attach it to the user's image.
97003   */
97004  var testImage = document.createElement('img');
97005  testImage.addEventListener('load', function () {
97006    /*
97007     * If we're dealing with an image tag, force it's dimensions
97008     * and set the source attribute. If not, go after the background-image
97009     * inline style.
97010     */
97011    if (imgType === 'img') {
97012      forceOriginalDimensions(image).setAttribute('src', retinaURL);
97013    } else {
97014      image.style.backgroundImage = 'url(' + retinaURL + ')';
97015    }
97016  });
97017
97018  /*
97019   * Attach the retina URL to our proxy image to load in the new
97020   * image resource.
97021   */
97022  testImage.setAttribute('src', retinaURL);
97023}
97024
97025/**
97026 * Attempts to do an image url swap on a given image.
97027 *
97028 * @param  {Element}       image An image in the DOM.
97029 * @param  {String}        src   The original image source attribute.
97030 * @param  {String|Number} rjs   The pixel density cap for images provided.
97031 *
97032 * @return {undefined}
97033 */
97034function dynamicSwapImage(image, src) {
97035  var rjs = arguments.length <= 2 || arguments[2] === undefined ? 1 : arguments[2];
97036
97037  var cap = chooseCap(rjs);
97038
97039  /*
97040   * Don't do anything if the cap is less than 2 or there is no src.
97041   */
97042  if (src && cap > 1) {
97043    var newSrc = src.replace(srcReplace, '@' + cap + 'x$1');
97044    setSourceIfAvailable(image, newSrc);
97045  }
97046}
97047
97048/**
97049 * Performs an image url swap on a given image with a provided url.
97050 *
97051 * @param  {Element} image  An image in the DOM.
97052 * @param  {String}  src    The original image source attribute.
97053 * @param  {String}  hdsrc  The path for a 2x image.
97054 *
97055 * @return {undefined}
97056 */
97057function manualSwapImage(image, src, hdsrc) {
97058  if (environment > 1) {
97059    setSourceIfAvailable(image, hdsrc);
97060  }
97061}
97062
97063/**
97064 * Collects all images matching our selector, and converts our
97065 * NodeList into an Array so that Array methods will be available to it.
97066 *
97067 * @return {Array} Contains all elements matching our selector.
97068 */
97069function getImages() {
97070  return typeof document !== 'undefined' ? Array.prototype.slice.call(document.querySelectorAll(selector)) : [];
97071}
97072
97073/**
97074 * Converts a string like "url(hello.png)" into "hello.png".
97075 *
97076 * @param  {Element} img An HTML element with a background image.
97077 *
97078 * @return {String}
97079 */
97080function cleanBgImg(img) {
97081  return img.style.backgroundImage.replace(inlineReplace, '$2');
97082}
97083
97084/**
97085 * Gets all participating images and dynamically swaps out each one for its
97086 * retina equivalent taking into account the environment capabilities and
97087 * the densities for which the user has provided images.
97088 *
97089 * @return {undefined}
97090 */
97091function retina() {
vendor: 12,318 bytes, lines 97092-97142
97092  getImages().forEach(function (img) {
97093    var isImg = img.nodeName.toLowerCase() === 'img';
97094    var src = isImg ? img.getAttribute('src') : cleanBgImg(img);
97095    var rjs = img.getAttribute('data-rjs');
97096    var rjsIsNumber = !isNaN(parseInt(rjs, 10));
97097
97098    /*
97099     * If the user provided a number, dynamically swap out the image.
97100     * If the user provided a url, do it manually.
97101     */
97102    if (rjsIsNumber) {
97103      dynamicSwapImage(img, src, rjs);
97104    } else {
97105      manualSwapImage(img, src, rjs);
97106    }
97107  });
97108}
97109
97110/*
97111 * If this environment has `window`, activate the plugin.
97112 */
97113if (hasWindow) {
97114  window.addEventListener('load', retina);
97115  window.retinajs = retina;
97116}
97117
97118//exports.default = retina;
97119define("retinajs", (function (global) {
97120    return function () {
97121        var ret, fn;
97122        return ret || global.retinajs;
97123    };
97124}(this)));
97125
97126/*
97127     _ _      _       _
97128 ___| (_) ___| | __  (_)___
97129/ __| | |/ __| |/ /  | / __|
97130\__ \ | | (__|   < _ | \__ \
97131|___/_|_|\___|_|\_(_)/ |___/
97132                   |__/
97133
97134 Version: 1.6.0
97135  Author: Ken Wheeler
97136 Website: http://kenwheeler.github.io
97137    Docs: http://kenwheeler.github.io/slick
97138    Repo: http://github.com/kenwheeler/slick
97139  Issues: http://github.com/kenwheeler/slick/issues
97140
97141 */
97142!function(a){"use strict";"function"==typeof define&&define.amd?define('slick',["jquery"],a):"undefined"!=typeof exports?module.exports=a(require("jquery")):a(jQuery)}(function(a){"use strict";var b=window.Slick||{};b=function(){function c(c,d){var f,e=this;e.defaults={accessibility:!0,adaptiveHeight:!1,appendArrows:a(c),appendDots:a(c),arrows:!0,asNavFor:null,prevArrow:'<button type="button" data-role="none" class="slick-prev" aria-label="Previous" tabindex="0" role="button">Previous</button>',nextArrow:'<button type="button" data-role="none" class="slick-next" aria-label="Next" tabindex="0" role="button">Next</button>',autoplay:!1,autoplaySpeed:3e3,centerMode:!1,centerPadding:"50px",cssEase:"ease",customPaging:function(b,c){return a('<button type="button" data-role="none" role="button" tabindex="0" />').text(c+1)},dots:!1,dotsClass:"slick-dots",draggable:!0,easing:"linear",edgeFriction:.35,fade:!1,focusOnSelect:!1,infinite:!0,initialSlide:0,lazyLoad:"ondemand",mobileFirst:!1,pauseOnHover:!0,pauseOnFocus:!0,pauseOnDotsHover:!1,respondTo:"window",responsive:null,rows:1,rtl:!1,slide:"",slidesPerRow:1,slidesToShow:1,slidesToScroll:1,speed:500,swipe:!0,swipeToSlide:!1,touchMove:!0,touchThreshold:5,useCSS:!0,useTransform:!0,variableWidth:!1,vertical:!1,verticalSwiping:!1,waitForAnimate:!0,zIndex:1e3},e.initials={animating:!1,dragging:!1,autoPlayTimer:null,currentDirection:0,currentLeft:null,currentSlide:0,direction:1,$dots:null,listWidth:null,listHeight:null,loadIndex:0,$nextArrow:null,$prevArrow:null,slideCount:null,slideWidth:null,$slideTrack:null,$slides:null,sliding:!1,slideOffset:0,swipeLeft:null,$list:null,touchObject:{},transformsEnabled:!1,unslicked:!1},a.extend(e,e.initials),e.activeBreakpoint=null,e.animType=null,e.animProp=null,e.breakpoints=[],e.breakpointSettings=[],e.cssTransitions=!1,e.focussed=!1,e.interrupted=!1,e.hidden="hidden",e.paused=!0,e.positionProp=null,e.respondTo=null,e.rowCount=1,e.shouldClick=!0,e.$slider=a(c),e.$slidesCache=null,e.transformType=null,e.transitionType=null,e.visibilityChange="visibilitychange",e.windowWidth=0,e.windowTimer=null,f=a(c).data("slick")||{},e.options=a.extend({},e.defaults,d,f),e.currentSlide=e.options.initialSlide,e.originalSettings=e.options,"undefined"!=typeof document.mozHidden?(e.hidden="mozHidden",e.visibilityChange="mozvisibilitychange"):"undefined"!=typeof document.webkitHidden&&(e.hidden="webkitHidden",e.visibilityChange="webkitvisibilitychange"),e.autoPlay=a.proxy(e.autoPlay,e),e.autoPlayClear=a.proxy(e.autoPlayClear,e),e.autoPlayIterator=a.proxy(e.autoPlayIterator,e),e.changeSlide=a.proxy(e.changeSlide,e),e.clickHandler=a.proxy(e.clickHandler,e),e.selectHandler=a.proxy(e.selectHandler,e),e.setPosition=a.proxy(e.setPosition,e),e.swipeHandler=a.proxy(e.swipeHandler,e),e.dragHandler=a.proxy(e.dragHandler,e),e.keyHandler=a.proxy(e.keyHandler,e),e.instanceUid=b++,e.htmlExpr=/^(?:\s*(<[\w\W]+>)[^>]*)$/,e.registerBreakpoints(),e.init(!0)}var b=0;return c}(),b.prototype.activateADA=function(){var a=this;a.$slideTrack.find(".slick-active").attr({"aria-hidden":"false"}).find("a, input, button, select").attr({tabindex:"0"})},b.prototype.addSlide=b.prototype.slickAdd=function(b,c,d){var e=this;if("boolean"==typeof c)d=c,c=null;else if(0>c||c>=e.slideCount)return!1;e.unload(),"number"==typeof c?0===c&&0===e.$slides.length?a(b).appendTo(e.$slideTrack):d?a(b).insertBefore(e.$slides.eq(c)):a(b).insertAfter(e.$slides.eq(c)):d===!0?a(b).prependTo(e.$slideTrack):a(b).appendTo(e.$slideTrack),e.$slides=e.$slideTrack.children(this.options.slide),e.$slideTrack.children(this.options.slide).detach(),e.$slideTrack.append(e.$slides),e.$slides.each(function(b,c){a(c).attr("data-slick-index",b)}),e.$slidesCache=e.$slides,e.reinit()},b.prototype.animateHeight=function(){var a=this;if(1===a.options.slidesToShow&&a.options.adaptiveHeight===!0&&a.options.vertical===!1){var b=a.$slides.eq(a.currentSlide).outerHeight(!0);a.$list.animate({height:b},a.options.speed)}},b.prototype.animateSlide=function(b,c){var d={},e=this;e.animateHeight(),e.options.rtl===!0&&e.options.vertical===!1&&(b=-b),e.transformsEnabled===!1?e.options.vertical===!1?e.$slideTrack.animate({left:b},e.options.speed,e.options.easing,c):e.$slideTrack.animate({top:b},e.options.speed,e.options.easing,c):e.cssTransitions===!1?(e.options.rtl===!0&&(e.currentLeft=-e.currentLeft),a({animStart:e.currentLeft}).animate({animStart:b},{duration:e.options.speed,easing:e.options.easing,step:function(a){a=Math.ceil(a),e.options.vertical===!1?(d[e.animType]="translate("+a+"px, 0px)",e.$slideTrack.css(d)):(d[e.animType]="translate(0px,"+a+"px)",e.$slideTrack.css(d))},complete:function(){c&&c.call()}})):(e.applyTransition(),b=Math.ceil(b),e.options.vertical===!1?d[e.animType]="translate3d("+b+"px, 0px, 0px)":d[e.animType]="translate3d(0px,"+b+"px, 0px)",e.$slideTrack.css(d),c&&setTimeout(function(){e.disableTransition(),c.call()},e.options.speed))},b.prototype.getNavTarget=function(){var b=this,c=b.options.asNavFor;return c&&null!==c&&(c=a(c).not(b.$slider)),c},b.prototype.asNavFor=function(b){var c=this,d=c.getNavTarget();null!==d&&"object"==typeof d&&d.each(function(){var c=a(this).slick("getSlick");c.unslicked||c.slideHandler(b,!0)})},b.prototype.applyTransition=function(a){var b=this,c={};b.options.fade===!1?c[b.transitionType]=b.transformType+" "+b.options.speed+"ms "+b.options.cssEase:c[b.transitionType]="opacity "+b.options.speed+"ms "+b.options.cssEase,b.options.fade===!1?b.$slideTrack.css(c):b.$slides.eq(a).css(c)},b.prototype.autoPlay=function(){var a=this;a.autoPlayClear(),a.slideCount>a.options.slidesToShow&&(a.autoPlayTimer=setInterval(a.autoPlayIterator,a.options.autoplaySpeed))},b.prototype.autoPlayClear=function(){var a=this;a.autoPlayTimer&&clearInterval(a.autoPlayTimer)},b.prototype.autoPlayIterator=function(){var a=this,b=a.currentSlide+a.options.slidesToScroll;a.paused||a.interrupted||a.focussed||(a.options.infinite===!1&&(1===a.direction&&a.currentSlide+1===a.slideCount-1?a.direction=0:0===a.direction&&(b=a.currentSlide-a.options.slidesToScroll,a.currentSlide-1===0&&(a.direction=1))),a.slideHandler(b))},b.prototype.buildArrows=function(){var b=this;b.options.arrows===!0&&(b.$prevArrow=a(b.options.prevArrow).addClass("slick-arrow"),b.$nextArrow=a(b.options.nextArrow).addClass("slick-arrow"),b.slideCount>b.options.slidesToShow?(b.$prevArrow.removeClass("slick-hidden").removeAttr("aria-hidden tabindex"),b.$nextArrow.removeClass("slick-hidden").removeAttr("aria-hidden tabindex"),b.htmlExpr.test(b.options.prevArrow)&&b.$prevArrow.prependTo(b.options.appendArrows),b.htmlExpr.test(b.options.nextArrow)&&b.$nextArrow.appendTo(b.options.appendArrows),b.options.infinite!==!0&&b.$prevArrow.addClass("slick-disabled").attr("aria-disabled","true")):b.$prevArrow.add(b.$nextArrow).addClass("slick-hidden").attr({"aria-disabled":"true",tabindex:"-1"}))},b.prototype.buildDots=function(){var c,d,b=this;if(b.options.dots===!0&&b.slideCount>b.options.slidesToShow){for(b.$slider.addClass("slick-dotted"),d=a("<ul />").addClass(b.options.dotsClass),c=0;c<=b.getDotCount();c+=1)d.append(a("<li />").append(b.options.customPaging.call(this,b,c)));b.$dots=d.appendTo(b.options.appendDots),b.$dots.find("li").first().addClass("slick-active").attr("aria-hidden","false")}},b.prototype.buildOut=function(){var b=this;b.$slides=b.$slider.children(b.options.slide+":not(.slick-cloned)").addClass("slick-slide"),b.slideCount=b.$slides.length,b.$slides.each(function(b,c){a(c).attr("data-slick-index",b).data("originalStyling",a(c).attr("style")||"")}),b.$slider.addClass("slick-slider"),b.$slideTrack=0===b.slideCount?a('<div class="slick-track"/>').appendTo(b.$slider):b.$slides.wrapAll('<div class="slick-track"/>').parent(),b.$list=b.$slideTrack.wrap('<div aria-live="polite" class="slick-list"/>').parent(),b.$slideTrack.css("opacity",0),(b.options.centerMode===!0||b.options.swipeToSlide===!0)&&(b.options.slidesToScroll=1),a("img[data-lazy]",b.$slider).not("[src]").addClass("slick-loading"),b.setupInfinite(),b.buildArrows(),b.buildDots(),b.updateDots(),b.setSlideClasses("number"==typeof b.currentSlide?b.currentSlide:0),b.options.draggable===!0&&b.$list.addClass("draggable")},b.prototype.buildRows=function(){var b,c,d,e,f,g,h,a=this;if(e=document.createDocumentFragment(),g=a.$slider.children(),a.options.rows>1){for(h=a.options.slidesPerRow*a.options.rows,f=Math.ceil(g.length/h),b=0;f>b;b++){var i=document.createElement("div");for(c=0;c<a.options.rows;c++){var j=document.createElement("div");for(d=0;d<a.options.slidesPerRow;d++){var k=b*h+(c*a.options.slidesPerRow+d);g.get(k)&&j.appendChild(g.get(k))}i.appendChild(j)}e.appendChild(i)}a.$slider.empty().append(e),a.$slider.children().children().children().css({width:100/a.options.slidesPerRow+"%",display:"inline-block"})}},b.prototype.checkResponsive=function(b,c){var e,f,g,d=this,h=!1,i=d.$slider.width(),j=window.innerWidth||a(window).width();if("window"===d.respondTo?g=j:"slider"===d.respondTo?g=i:"min"===d.respondTo&&(g=Math.min(j,i)),d.options.responsive&&d.options.responsive.length&&null!==d.options.responsive){f=null;for(e in d.breakpoints)d.breakpoints.hasOwnProperty(e)&&(d.originalSettings.mobileFirst===!1?g<d.breakpoints[e]&&(f=d.breakpoints[e]):g>d.breakpoints[e]&&(f=d.breakpoints[e]));null!==f?null!==d.activeBreakpoint?(f!==d.activeBreakpoint||c)&&(d.activeBreakpoint=f,"unslick"===d.breakpointSettings[f]?d.unslick(f):(d.options=a.extend({},d.originalSettings,d.breakpointSettings[f]),b===!0&&(d.currentSlide=d.options.initialSlide),d.refresh(b)),h=f):(d.activeBreakpoint=f,"unslick"===d.breakpointSettings[f]?d.unslick(f):(d.options=a.extend({},d.originalSettings,d.breakpointSettings[f]),b===!0&&(d.currentSlide=d.options.initialSlide),d.refresh(b)),h=f):null!==d.activeBreakpoint&&(d.activeBreakpoint=null,d.options=d.originalSettings,b===!0&&(d.currentSlide=d.options.initialSlide),d.refresh(b),h=f),b||h===!1||d.$slider.trigger("breakpoint",[d,h])}},b.prototype.changeSlide=function(b,c){var f,g,h,d=this,e=a(b.currentTarget);switch(e.is("a")&&b.preventDefault(),e.is("li")||(e=e.closest("li")),h=d.slideCount%d.options.slidesToScroll!==0,f=h?0:(d.slideCount-d.currentSlide)%d.options.slidesToScroll,b.data.message){case"previous":g=0===f?d.options.slidesToScroll:d.options.slidesToShow-f,d.slideCount>d.options.slidesToShow&&d.slideHandler(d.currentSlide-g,!1,c);break;case"next":g=0===f?d.options.slidesToScroll:f,d.slideCount>d.options.slidesToShow&&d.slideHandler(d.currentSlide+g,!1,c);break;case"index":var i=0===b.data.index?0:b.data.index||e.index()*d.options.slidesToScroll;d.slideHandler(d.checkNavigable(i),!1,c),e.children().trigger("focus");break;default:return}},b.prototype.checkNavigable=function(a){var c,d,b=this;if(c=b.getNavigableIndexes(),d=0,a>c[c.length-1])a=c[c.length-1];else for(var e in c){if(a<c[e]){a=d;break}d=c[e]}return a},b.prototype.cleanUpEvents=function(){var b=this;b.options.dots&&null!==b.$dots&&a("li",b.$dots).off("click.slick",b.changeSlide).off("mouseenter.slick",a.proxy(b.interrupt,b,!0)).off("mouseleave.
97142slick",a.proxy(b.interrupt,b,!1)),b.$slider.off("focus.slick blur.slick"),b.options.arrows===!0&&b.slideCount>b.options.slidesToShow&&(b.$prevArrow&&b.$prevArrow.off("click.slick",b.changeSlide),b.$nextArrow&&b.$nextArrow.off("click.slick",b.changeSlide)),b.$list.off("touchstart.slick mousedown.slick",b.swipeHandler),b.$list.off("touchmove.slick mousemove.slick",b.swipeHandler),b.$list.off("touchend.slick mouseup.slick",b.swipeHandler),b.$list.off("touchcancel.slick mouseleave.slick",b.swipeHandler),b.$list.off("click.slick",b.clickHandler),a(document).off(b.visibilityChange,b.visibility),b.cleanUpSlideEvents(),b.options.accessibility===!0&&b.$list.off("keydown.slick",b.keyHandler),b.options.focusOnSelect===!0&&a(b.$slideTrack).children().off("click.slick",b.selectHandler),a(window).off("orientationchange.slick.slick-"+b.instanceUid,b.orientationChange),a(window).off("resize.slick.slick-"+b.instanceUid,b.resize),a("[draggable!=true]",b.$slideTrack).off("dragstart",b.preventDefault),a(window).off("load.slick.slick-"+b.instanceUid,b.setPosition),a(document).off("ready.slick.slick-"+b.instanceUid,b.setPosition)},b.prototype.cleanUpSlideEvents=function(){var b=this;b.$list.off("mouseenter.slick",a.proxy(b.interrupt,b,!0)),b.$list.off("mouseleave.slick",a.proxy(b.interrupt,b,!1))},b.prototype.cleanUpRows=function(){var b,a=this;a.options.rows>1&&(b=a.$slides.children().children(),b.removeAttr("style"),a.$slider.empty().append(b))},b.prototype.clickHandler=function(a){var b=this;b.shouldClick===!1&&(a.stopImmediatePropagation(),a.stopPropagation(),a.preventDefault())},b.prototype.destroy=function(b){var c=this;c.autoPlayClear(),c.touchObject={},c.cleanUpEvents(),a(".slick-cloned",c.$slider).detach(),c.$dots&&c.$dots.remove(),c.$prevArrow&&c.$prevArrow.length&&(c.$prevArrow.removeClass("slick-disabled slick-arrow slick-hidden").removeAttr("aria-hidden aria-disabled tabindex").css("display",""),c.htmlExpr.test(c.options.prevArrow)&&c.$prevArrow.remove()),c.$nextArrow&&c.$nextArrow.length&&(c.$nextArrow.removeClass("slick-disabled slick-arrow slick-hidden").removeAttr("aria-hidden aria-disabled tabindex").css("display",""),c.htmlExpr.test(c.options.nextArrow)&&c.$nextArrow.remove()),c.$slides&&(c.$slides.removeClass("slick-slide slick-active slick-center slick-visible slick-current").removeAttr("aria-hidden").removeAttr("data-slick-index").each(function(){a(this).attr("style",a(this).data("originalStyling"))}),c.$slideTrack.children(this.options.slide).detach(),c.$slideTrack.detach(),c.$list.detach(),c.$slider.append(c.$slides)),c.cleanUpRows(),c.$slider.removeClass("slick-slider"),c.$slider.removeClass("slick-initialized"),c.$slider.removeClass("slick-dotted"),c.unslicked=!0,b||c.$slider.trigger("destroy",[c])},b.prototype.disableTransition=function(a){var b=this,c={};c[b.transitionType]="",b.options.fade===!1?b.$slideTrack.css(c):b.$slides.eq(a).css(c)},b.prototype.fadeSlide=function(a,b){var c=this;c.cssTransitions===!1?(c.$slides.eq(a).css({zIndex:c.options.zIndex}),c.$slides.eq(a).animate({opacity:1},c.options.speed,c.options.easing,b)):(c.applyTransition(a),c.$slides.eq(a).css({opacity:1,zIndex:c.options.zIndex}),b&&setTimeout(function(){c.disableTransition(a),b.call()},c.options.speed))},b.prototype.fadeSlideOut=function(a){var b=this;b.cssTransitions===!1?b.$slides.eq(a).animate({opacity:0,zIndex:b.options.zIndex-2},b.options.speed,b.options.easing):(b.applyTransition(a),b.$slides.eq(a).css({opacity:0,zIndex:b.options.zIndex-2}))},b.prototype.filterSlides=b.prototype.slickFilter=function(a){var b=this;null!==a&&(b.$slidesCache=b.$slides,b.unload(),b.$slideTrack.children(this.options.slide).detach(),b.$slidesCache.filter(a).appendTo(b.$slideTrack),b.reinit())},b.prototype.focusHandler=function(){var b=this;b.$slider.off("focus.slick blur.slick").on("focus.slick blur.slick","*:not(.slick-arrow)",function(c){c.stopImmediatePropagation();var d=a(this);setTimeout(function(){b.options.pauseOnFocus&&(b.focussed=d.is(":focus"),b.autoPlay())},0)})},b.prototype.getCurrent=b.prototype.slickCurrentSlide=function(){var a=this;return a.currentSlide},b.prototype.getDotCount=function(){var a=this,b=0,c=0,d=0;if(a.options.infinite===!0)for(;b<a.slideCount;)++d,b=c+a.options.slidesToScroll,c+=a.options.slidesToScroll<=a.options.slidesToShow?a.options.slidesToScroll:a.options.slidesToShow;else if(a.options.centerMode===!0)d=a.slideCount;else if(a.options.asNavFor)for(;b<a.slideCount;)++d,b=c+a.options.slidesToScroll,c+=a.options.slidesToScroll<=a.options.slidesToShow?a.options.slidesToScroll:a.options.slidesToShow;else d=1+Math.ceil((a.slideCount-a.options.slidesToShow)/a.options.slidesToScroll);return d-1},b.prototype.getLeft=function(a){var c,d,f,b=this,e=0;return b.slideOffset=0,d=b.$slides.first().outerHeight(!0),b.options.infinite===!0?(b.slideCount>b.options.slidesToShow&&(b.slideOffset=b.slideWidth*b.options.slidesToShow*-1,e=d*b.options.slidesToShow*-1),b.slideCount%b.options.slidesToScroll!==0&&a+b.options.slidesToScroll>b.slideCount&&b.slideCount>b.options.slidesToShow&&(a>b.slideCount?(b.slideOffset=(b.options.slidesToShow-(a-b.slideCount))*b.slideWidth*-1,e=(b.options.slidesToShow-(a-b.slideCount))*d*-1):(b.slideOffset=b.slideCount%b.options.slidesToScroll*b.slideWidth*-1,e=b.slideCount%b.options.slidesToScroll*d*-1))):a+b.o
vendor: 4,100 bytes, line 97142
97142ptions.slidesToShow>b.slideCount&&(b.slideOffset=(a+b.options.slidesToShow-b.slideCount)*b.slideWidth,e=(a+b.options.slidesToShow-b.slideCount)*d),b.slideCount<=b.options.slidesToShow&&(b.slideOffset=0,e=0),b.options.centerMode===!0&&b.options.infinite===!0?b.slideOffset+=b.slideWidth*Math.floor(b.options.slidesToShow/2)-b.slideWidth:b.options.centerMode===!0&&(b.slideOffset=0,b.slideOffset+=b.slideWidth*Math.floor(b.options.slidesToShow/2)),c=b.options.vertical===!1?a*b.slideWidth*-1+b.slideOffset:a*d*-1+e,b.options.variableWidth===!0&&(f=b.slideCount<=b.options.slidesToShow||b.options.infinite===!1?b.$slideTrack.children(".slick-slide").eq(a):b.$slideTrack.children(".slick-slide").eq(a+b.options.slidesToShow),c=b.options.rtl===!0?f[0]?-1*(b.$slideTrack.width()-f[0].offsetLeft-f.width()):0:f[0]?-1*f[0].offsetLeft:0,b.options.centerMode===!0&&(f=b.slideCount<=b.options.slidesToShow||b.options.infinite===!1?b.$slideTrack.children(".slick-slide").eq(a):b.$slideTrack.children(".slick-slide").eq(a+b.options.slidesToShow+1),c=b.options.rtl===!0?f[0]?-1*(b.$slideTrack.width()-f[0].offsetLeft-f.width()):0:f[0]?-1*f[0].offsetLeft:0,c+=(b.$list.width()-f.outerWidth())/2)),c},b.prototype.getOption=b.prototype.slickGetOption=function(a){var b=this;return b.options[a]},b.prototype.getNavigableIndexes=function(){var e,a=this,b=0,c=0,d=[];for(a.options.infinite===!1?e=a.slideCount:(b=-1*a.options.slidesToScroll,c=-1*a.options.slidesToScroll,e=2*a.slideCount);e>b;)d.push(b),b=c+a.options.slidesToScroll,c+=a.options.slidesToScroll<=a.options.slidesToShow?a.options.slidesToScroll:a.options.slidesToShow;return d},b.prototype.getSlick=function(){return this},b.prototype.getSlideCount=function(){var c,d,e,b=this;return e=b.options.centerMode===!0?b.slideWidth*Math.floor(b.options.slidesToShow/2):0,b.options.swipeToSlide===!0?(b.$slideTrack.find(".slick-slide").each(function(c,f){return f.offsetLeft-e+a(f).outerWidth()/2>-1*b.swipeLeft?(d=f,!1):void 0}),c=Math.abs(a(d).attr("data-slick-index")-b.currentSlide)||1):b.options.slidesToScroll},b.prototype.goTo=b.prototype.slickGoTo=function(a,b){var c=this;c.changeSlide({data:{message:"index",index:parseInt(a)}},b)},b.prototype.init=function(b){var c=this;a(c.$slider).hasClass("slick-initialized")||(a(c.$slider).addClass("slick-initialized"),c.buildRows(),c.buildOut(),c.setProps(),c.startLoad(),c.loadSlider(),c.initializeEvents(),c.updateArrows(),c.updateDots(),c.checkResponsive(!0),c.focusHandler()),b&&c.$slider.trigger("init",[c]),c.options.accessibility===!0&&c.initADA(),c.options.autoplay&&(c.paused=!1,c.autoPlay())},b.prototype.initADA=function(){var b=this;b.$slides.add(b.$slideTrack.find(".slick-cloned")).attr({"aria-hidden":"true",tabindex:"-1"}).find("a, input, button, select").attr({tabindex:"-1"}),b.$slideTrack.attr("role","listbox"),b.$slides.not(b.$slideTrack.find(".slick-cloned")).each(function(c){a(this).attr({role:"option","aria-describedby":"slick-slide"+b.instanceUid+c})}),null!==b.$dots&&b.$dots.attr("role","tablist").find("li").each(function(c){a(this).attr({role:"presentation","aria-selected":"false","aria-controls":"navigation"+b.instanceUid+c,id:"slick-slide"+b.instanceUid+c})}).first().attr("aria-selected","true").end().find("button").attr("role","button").end().closest("div").attr("role","toolbar"),b.activateADA()},b.prototype.initArrowEvents=function(){var a=this;a.options.arrows===!0&&a.slideCount>a.options.slidesToShow&&(a.$prevArrow.off("click.slick").on("click.slick",{message:"previous"},a.changeSlide),a.$nextArrow.off("click.slick").on("click.slick",{message:"next"},a.changeSlide))},b.prototype.initDotEvents=function(){var b=this;b.options.dots===!0&&b.slideCount>b.options.slidesToShow&&a("li",b.$dots).on("click.slick",{message:"index"},b.changeSlide),b.options.dots===!0&&b.options.pauseOnDotsHover===!0&&a("li",b.$dots).on("mouseenter.slick",a.proxy(b.interrupt,b,!0)).on("mouseleave.slick",a.proxy(b.interrupt,b,!1))},b.prototype.initSlideEvents=function(){var b=this;b.options.pauseOnHover&&(b.$list.on("mouseenter.slick",a.proxy(b.interrupt,b,!0)),b.$list.on("mouseleave.
97142slick",a.proxy(b.interrupt,b,!1)))},b.prototype.initializeEvents=function(){var b=this;b.initArrowEvents(),b.initDotEvents(),b.initSlideEvents(),b.$list.on("touchstart.slick mousedown.slick",{action:"start"},b.swipeHandler),b.$list.on("touchmove.slick mousemove.slick",{action:"move"},b.swipeHandler),b.$list.on("touchend.slick mouseup.slick",{action:"end"},b.swipeHandler),b.$list.on("touchcancel.slick mouseleave.slick",{action:"end"},b.swipeHandler),b.$list.on("click.slick",b.clickHandler),a(document).on(b.visibilityChange,a.proxy(b.visibility,b)),b.options.accessibility===!0&&b.$list.on("keydown.slick",b.keyHandler),b.options.focusOnSelect===!0&&a(b.$slideTrack).children().on("click.slick",b.selectHandler),a(window).on("orientationchange.slick.slick-"+b.instanceUid,a.proxy(b.orientationChange,b)),a(window).on("resize.slick.slick-"+b.instanceUid,a.proxy(b.resize,b)),a("[draggable!=true]",b.$slideTrack).on("dragstart",b.preventDefault),a(window).on("load.slick.slick-"+b.instanceUid,b.setPosition),a(document).on("ready.slick.slick-"+b.instanceUid,b.setPosition)},b.prototype.initUI=function(){var a=this;a.options.arrows===!0&&a.slideCount>a.options.slidesToShow&&(a.$prevArrow.show(),a.$nextArrow.show()),a.options.dots===!0&&a.slideCount>a.options.slidesToShow&&a.$dots.show()},b.prototype.keyHandler=function(a){var b=this;a.target.tagName.match("TEXTAREA|INPUT|SELECT")||(37===a.keyCode&&b.options.accessibility===!0?b.changeSlide({data:{message:b.options.rtl===!0?"next":"previous"}}):39===a.keyCode&&b.options.accessibility===!0&&b.changeSlide({data:{message:b.options.rtl===!0?"previous":"next"}}))},b.prototype.lazyLoad=function(){function g(c){a("img[data-lazy]",c).each(function(){var c=a(this),d=a(this).attr("data-lazy"),e=document.createElement("img");e.onload=function(){c.animate({opacity:0}
vendor: 4,284 bytes, line 97142
97142,100,function(){c.attr("src",d).animate({opacity:1},200,function(){c.removeAttr("data-lazy").removeClass("slick-loading")}),b.$slider.trigger("lazyLoaded",[b,c,d])})},e.onerror=function(){c.removeAttr("data-lazy").removeClass("slick-loading").addClass("slick-lazyload-error"),b.$slider.trigger("lazyLoadError",[b,c,d])},e.src=d})}var c,d,e,f,b=this;b.options.centerMode===!0?b.options.infinite===!0?(e=b.currentSlide+(b.options.slidesToShow/2+1),f=e+b.options.slidesToShow+2):(e=Math.max(0,b.currentSlide-(b.options.slidesToShow/2+1)),f=2+(b.options.slidesToShow/2+1)+b.currentSlide):(e=b.options.infinite?b.options.slidesToShow+b.currentSlide:b.currentSlide,f=Math.ceil(e+b.options.slidesToShow),b.options.fade===!0&&(e>0&&e--,f<=b.slideCount&&f++)),c=b.$slider.find(".slick-slide").slice(e,f),g(c),b.slideCount<=b.options.slidesToShow?(d=b.$slider.find(".slick-slide"),g(d)):b.currentSlide>=b.slideCount-b.options.slidesToShow?(d=b.$slider.find(".slick-cloned").slice(0,b.options.slidesToShow),g(d)):0===b.currentSlide&&(d=b.$slider.find(".slick-cloned").slice(-1*b.options.slidesToShow),g(d))},b.prototype.loadSlider=function(){var a=this;a.setPosition(),a.$slideTrack.css({opacity:1}),a.$slider.removeClass("slick-loading"),a.initUI(),"progressive"===a.options.lazyLoad&&a.progressiveLazyLoad()},b.prototype.next=b.prototype.slickNext=function(){var a=this;a.changeSlide({data:{message:"next"}})},b.prototype.orientationChange=function(){var a=this;a.checkResponsive(),a.setPosition()},b.prototype.pause=b.prototype.slickPause=function(){var a=this;a.autoPlayClear(),a.paused=!0},b.prototype.play=b.prototype.slickPlay=function(){var a=this;a.autoPlay(),a.options.autoplay=!0,a.paused=!1,a.focussed=!1,a.interrupted=!1},b.prototype.postSlide=function(a){var b=this;b.unslicked||(b.$slider.trigger("afterChange",[b,a]),b.animating=!1,b.setPosition(),b.swipeLeft=null,b.options.autoplay&&b.autoPlay(),b.options.accessibility===!0&&b.initADA())},b.prototype.prev=b.prototype.slickPrev=function(){var a=this;a.changeSlide({data:{message:"previous"}})},b.prototype.preventDefault=function(a){a.preventDefault()},b.prototype.progressiveLazyLoad=function(b){b=b||1;var e,f,g,c=this,d=a("img[data-lazy]",c.$slider);d.length?(e=d.first(),f=e.attr("data-lazy"),g=document.createElement("img"),g.onload=function(){e.attr("src",f).removeAttr("data-lazy").removeClass("slick-loading"),c.options.adaptiveHeight===!0&&c.setPosition(),c.$slider.trigger("lazyLoaded",[c,e,f]),c.progressiveLazyLoad()},g.onerror=function(){3>b?setTimeout(function(){c.progressiveLazyLoad(b+1)},500):(e.removeAttr("data-lazy").removeClass("slick-loading").addClass("slick-lazyload-error"),c.$slider.trigger("lazyLoadError",[c,e,f]),c.progressiveLazyLoad())},g.src=f):c.$slider.trigger("allImagesLoaded",[c])},b.prototype.refresh=function(b){var d,e,c=this;e=c.slideCount-c.options.slidesToShow,!c.options.infinite&&c.currentSlide>e&&(c.currentSlide=e),c.slideCount<=c.options.slidesToShow&&(c.currentSlide=0),d=c.currentSlide,c.destroy(!0),a.extend(c,c.initials,{currentSlide:d}),c.init(),b||c.changeSlide({data:{message:"index",index:d}},!1)},b.prototype.registerBreakpoints=function(){var c,d,e,b=this,f=b.options.responsive||null;if("array"===a.type(f)&&f.length){b.respondTo=b.options.respondTo||"window";for(c in f)if(e=b.breakpoints.length-1,d=f[c].breakpoint,f.hasOwnProperty(c)){for(;e>=0;)b.breakpoints[e]&&b.breakpoints[e]===d&&b.breakpoints.splice(e,1),e--;b.breakpoints.push(d),b.breakpointSettings[d]=f[c].settings}b.breakpoints.sort(function(a,c){return b.options.mobileFirst?a-c:c-a})}},b.prototype.reinit=function(){var b=this;b.$slides=b.$slideTrack.children(b.options.slide).addClass("slick-slide"),b.slideCount=b.$slides.length,b.currentSlide>=b.slideCount&&0!==b.currentSlide&&(b.currentSlide=b.currentSlide-b.options.slidesToScroll),b.slideCount<=b.options.slidesToShow&&(b.currentSlide=0),b.registerBreakpoints(),b.setProps(),b.setupInfinite(),b.buildArrows(),b.updateArrows(),b.initArrowEvents(),b.buildDots(),b.updateDots(),b.initDotEvents(),b.cleanUpSlideEvents(),b.initSlideEvents(),b.checkResponsive(!1,!0),b.options.focusOnSelect===!0&&a(b.$slideTrack).children().on("click.slick",b.selectHandler),b.setSlideClasses("number"==typeof b.currentSlide?b.currentSlide:0),b.setPosition(),b.focu
vendor: 2,346 bytes, line 97142
97142sHandler(),b.paused=!b.options.autoplay,b.autoPlay(),b.$slider.trigger("reInit",[b])},b.prototype.resize=function(){var b=this;a(window).width()!==b.windowWidth&&(clearTimeout(b.windowDelay),b.windowDelay=window.setTimeout(function(){b.windowWidth=a(window).width(),b.checkResponsive(),b.unslicked||b.setPosition()},50))},b.prototype.removeSlide=b.prototype.slickRemove=function(a,b,c){var d=this;return"boolean"==typeof a?(b=a,a=b===!0?0:d.slideCount-1):a=b===!0?--a:a,d.slideCount<1||0>a||a>d.slideCount-1?!1:(d.unload(),c===!0?d.$slideTrack.children().remove():d.$slideTrack.children(this.options.slide).eq(a).remove(),d.$slides=d.$slideTrack.children(this.options.slide),d.$slideTrack.children(this.options.slide).detach(),d.$slideTrack.append(d.$slides),d.$slidesCache=d.$slides,void d.reinit())},b.prototype.setCSS=function(a){var d,e,b=this,c={};b.options.rtl===!0&&(a=-a),d="left"==b.positionProp?Math.ceil(a)+"px":"0px",e="top"==b.positionProp?Math.ceil(a)+"px":"0px",c[b.positionProp]=a,b.transformsEnabled===!1?b.$slideTrack.css(c):(c={},b.cssTransitions===!1?(c[b.animType]="translate("+d+", "+e+")",b.$slideTrack.css(c)):(c[b.animType]="translate3d("+d+", "+e+", 0px)",b.$slideTrack.css(c)))},b.prototype.setDimensions=function(){var a=this;a.options.vertical===!1?a.options.centerMode===!0&&a.$list.css({padding:"0px "+a.options.centerPadding}):(a.$list.height(a.$slides.first().outerHeight(!0)*a.options.slidesToShow),a.options.centerMode===!0&&a.$list.css({padding:a.options.centerPadding+" 0px"})),a.listWidth=a.$list.width(),a.listHeight=a.$list.height(),a.options.vertical===!1&&a.options.variableWidth===!1?(a.slideWidth=Math.ceil(a.listWidth/a.options.slidesToShow),a.$slideTrack.width(Math.ceil(a.slideWidth*a.$slideTrack.children(".slick-slide").length))):a.options.variableWidth===!0?a.$slideTrack.width(5e3*a.slideCount):(a.slideWidth=Math.ceil(a.listWidth),a.$slideTrack.height(Math.ceil(a.$slides.first().outerHeight(!0)*a.$slideTrack.children(".slick-slide").length)));var b=a.$slides.first().outerWidth(!0)-a.$slides.first().width();a.options.variableWidth===!1&&a.$slideTrack.children(".slick-slide").width(a.slideWidth-b)},b.prototype.setFade=function(){var c,b=this;b.$slides.each(function(d,e){c=b.slideWidth*d*-1,b.options.rtl===!0?a(e).css({position:"relative",right:c,top:0,zIndex:b.options.zIndex-2,opacity:0}
vendor: 3,178 bytes, line 97142
97142):a(e).css({position:"relative",left:c,top:0,zIndex:b.options.zIndex-2,opacity:0})}),b.$slides.eq(b.currentSlide).css({zIndex:b.options.zIndex-1,opacity:1})},b.prototype.setHeight=function(){var a=this;if(1===a.options.slidesToShow&&a.options.adaptiveHeight===!0&&a.options.vertical===!1){var b=a.$slides.eq(a.currentSlide).outerHeight(!0);a.$list.css("height",b)}},b.prototype.setOption=b.prototype.slickSetOption=function(){var c,d,e,f,h,b=this,g=!1;if("object"===a.type(arguments[0])?(e=arguments[0],g=arguments[1],h="multiple"):"string"===a.type(arguments[0])&&(e=arguments[0],f=arguments[1],g=arguments[2],"responsive"===arguments[0]&&"array"===a.type(arguments[1])?h="responsive":"undefined"!=typeof arguments[1]&&(h="single")),"single"===h)b.options[e]=f;else if("multiple"===h)a.each(e,function(a,c){b.options[a]=c});else if("responsive"===h)for(d in f)if("array"!==a.type(b.options.responsive))b.options.responsive=[f[d]];else{for(c=b.options.responsive.length-1;c>=0;)b.options.responsive[c].breakpoint===f[d].breakpoint&&b.options.responsive.splice(c,1),c--;b.options.responsive.push(f[d])}g&&(b.unload(),b.reinit())},b.prototype.setPosition=function(){var a=this;a.setDimensions(),a.setHeight(),a.options.fade===!1?a.setCSS(a.getLeft(a.currentSlide)):a.setFade(),a.$slider.trigger("setPosition",[a])},b.prototype.setProps=function(){var a=this,b=document.body.style;a.positionProp=a.options.vertical===!0?"top":"left","top"===a.positionProp?a.$slider.addClass("slick-vertical"):a.$slider.removeClass("slick-vertical"),(void 0!==b.WebkitTransition||void 0!==b.MozTransition||void 0!==b.msTransition)&&a.options.useCSS===!0&&(a.cssTransitions=!0),a.options.fade&&("number"==typeof a.options.zIndex?a.options.zIndex<3&&(a.options.zIndex=3):a.options.zIndex=a.defaults.zIndex),void 0!==b.OTransform&&(a.animType="OTransform",a.transformType="-o-transform",a.transitionType="OTransition",void 0===b.perspectiveProperty&&void 0===b.webkitPerspective&&(a.animType=!1)),void 0!==b.MozTransform&&(a.animType="MozTransform",a.transformType="-moz-transform",a.transitionType="MozTransition",void 0===b.perspectiveProperty&&void 0===b.MozPerspective&&(a.animType=!1)),void 0!==b.webkitTransform&&(a.animType="webkitTransform",a.transformType="-webkit-transform",a.transitionType="webkitTransition",void 0===b.perspectiveProperty&&void 0===b.webkitPerspective&&(a.animType=!1)),void 0!==b.msTransform&&(a.animType="msTransform",a.transformType="-ms-transform",a.transitionType="msTransition",void 0===b.msTransform&&(a.animType=!1)),void 0!==b.transform&&a.animType!==!1&&(a.animType="transform",a.transformType="transform",a.transitionType="transition"),a.transformsEnabled=a.options.useTransform&&null!==a.animType&&a.animType!==!1},b.prototype.setSlideClasses=function(a){var c,d,e,f,b=this;d=b.$slider.find(".slick-slide").removeClass("slick-active slick-center slick-current").attr("aria-hidden","true"),b.$slides.eq(a).addClass("slick-current"),b.options.centerMode===!0?(c=Math.floor(b.options.slidesToShow/2),b.options.infinite===!0&&(a>=c&&a<=b.slideCount-1-c?b.$slides.slice(a-c,a+c+1).addClass("slick-active").attr("aria-hidden","false"):(e=b.options.slidesToShow+a,
vendor: 1,607 bytes, line 97143
97143d.slice(e-c+1,e+c+2).addClass("slick-active").attr("aria-hidden","false")),0===a?d.eq(d.length-1-b.options.slidesToShow).addClass("slick-center"):a===b.slideCount-1&&d.eq(b.options.slidesToShow).addClass("slick-center")),b.$slides.eq(a).addClass("slick-center")):a>=0&&a<=b.slideCount-b.options.slidesToShow?b.$slides.slice(a,a+b.options.slidesToShow).addClass("slick-active").attr("aria-hidden","false"):d.length<=b.options.slidesToShow?d.addClass("slick-active").attr("aria-hidden","false"):(f=b.slideCount%b.options.slidesToShow,e=b.options.infinite===!0?b.options.slidesToShow+a:a,b.options.slidesToShow==b.options.slidesToScroll&&b.slideCount-a<b.options.slidesToShow?d.slice(e-(b.options.slidesToShow-f),e+f).addClass("slick-active").attr("aria-hidden","false"):d.slice(e,e+b.options.slidesToShow).addClass("slick-active").attr("aria-hidden","false")),"ondemand"===b.options.lazyLoad&&b.lazyLoad()},b.prototype.setupInfinite=function(){var c,d,e,b=this;if(b.options.fade===!0&&(b.options.centerMode=!1),b.options.infinite===!0&&b.options.fade===!1&&(d=null,b.slideCount>b.options.slidesToShow)){for(e=b.options.centerMode===!0?b.options.slidesToShow+1:b.options.slidesToShow,c=b.slideCount;c>b.slideCount-e;c-=1)d=c-1,a(b.$slides[d]).clone(!0).attr("id","").attr("data-slick-index",d-b.slideCount).prependTo(b.$slideTrack).addClass("slick-cloned");for(c=0;e>c;c+=1)d=c,a(b.$slides[d]).clone(!0).attr("id","").attr("data-slick-index",d+b.slideCount).appendTo(b.$slideTrack).addClass("slick-cloned");b.$slideTrack.find(".slick-cloned").find("[id]").each(function(){a(this).attr("id","")})}},b.prototype.
vendor: 8,958 bytes, lines 97143-97185
97143interrupt=function(a){var b=this;a||b.autoPlay(),b.interrupted=a},b.prototype.selectHandler=function(b){var c=this,d=a(b.target).is(".slick-slide")?a(b.target):a(b.target).parents(".slick-slide"),e=parseInt(d.attr("data-slick-index"));return e||(e=0),c.slideCount<=c.options.slidesToShow?(c.setSlideClasses(e),void c.asNavFor(e)):void c.slideHandler(e)},b.prototype.slideHandler=function(a,b,c){var d,e,f,g,j,h=null,i=this;return b=b||!1,i.animating===!0&&i.options.waitForAnimate===!0||i.options.fade===!0&&i.currentSlide===a||i.slideCount<=i.options.slidesToShow?void 0:(b===!1&&i.asNavFor(a),d=a,h=i.getLeft(d),g=i.getLeft(i.currentSlide),i.currentLeft=null===i.swipeLeft?g:i.swipeLeft,i.options.infinite===!1&&i.options.centerMode===!1&&(0>a||a>i.getDotCount()*i.options.slidesToScroll)?void(i.options.fade===!1&&(d=i.currentSlide,c!==!0?i.animateSlide(g,function(){i.postSlide(d)}):i.postSlide(d))):i.options.infinite===!1&&i.options.centerMode===!0&&(0>a||a>i.slideCount-i.options.slidesToScroll)?void(i.options.fade===!1&&(d=i.currentSlide,c!==!0?i.animateSlide(g,function(){i.postSlide(d)}):i.postSlide(d))):(i.options.autoplay&&clearInterval(i.autoPlayTimer),e=0>d?i.slideCount%i.options.slidesToScroll!==0?i.slideCount-i.slideCount%i.options.slidesToScroll:i.slideCount+d:d>=i.slideCount?i.slideCount%i.options.slidesToScroll!==0?0:d-i.slideCount:d,i.animating=!0,i.$slider.trigger("beforeChange",[i,i.currentSlide,e]),f=i.currentSlide,i.currentSlide=e,i.setSlideClasses(i.currentSlide),i.options.asNavFor&&(j=i.getNavTarget(),j=j.slick("getSlick"),j.slideCount<=j.options.slidesToShow&&j.setSlideClasses(i.currentSlide)),i.updateDots(),i.updateArrows(),i.options.fade===!0?(c!==!0?(i.fadeSlideOut(f),i.fadeSlide(e,function(){i.postSlide(e)})):i.postSlide(e),void i.animateHeight()):void(c!==!0?i.animateSlide(h,function(){i.postSlide(e)}):i.postSlide(e))))},b.prototype.startLoad=function(){var a=this;a.options.arrows===!0&&a.slideCount>a.options.slidesToShow&&(a.$prevArrow.hide(),a.$nextArrow.hide()),a.options.dots===!0&&a.slideCount>a.options.slidesToShow&&a.$dots.hide(),a.$slider.addClass("slick-loading")},b.prototype.swipeDirection=function(){var a,b,c,d,e=this;return a=e.touchObject.startX-e.touchObject.curX,b=e.touchObject.startY-e.touchObject.curY,c=Math.atan2(b,a),d=Math.round(180*c/Math.PI),0>d&&(d=360-Math.abs(d)),45>=d&&d>=0?e.options.rtl===!1?"left":"right":360>=d&&d>=315?e.options.rtl===!1?"left":"right":d>=135&&225>=d?e.options.rtl===!1?"right":"left":e.options.verticalSwiping===!0?d>=35&&135>=d?"down":"up":"vertical"},b.prototype.swipeEnd=function(a){var c,d,b=this;if(b.dragging=!1,b.interrupted=!1,b.shouldClick=b.touchObject.swipeLength>10?!1:!0,void 0===b.touchObject.curX)return!1;if(b.touchObject.edgeHit===!0&&b.$slider.trigger("edge",[b,b.swipeDirection()]),b.touchObject.swipeLength>=b.touchObject.minSwipe){switch(d=b.swipeDirection()){case"left":case"down":c=b.options.swipeToSlide?b.checkNavigable(b.currentSlide+b.getSlideCount()):b.currentSlide+b.getSlideCount(),b.currentDirection=0;break;case"right":case"up":c=b.options.swipeToSlide?b.checkNavigable(b.currentSlide-b.getSlideCount()):b.currentSlide-b.getSlideCount(),b.currentDirection=1}"vertical"!=d&&(b.slideHandler(c),b.touchObject={},b.$slider.trigger("swipe",[b,d]))}else b.touchObject.startX!==b.touchObject.curX&&(b.slideHandler(b.currentSlide),b.touchObject={})},b.prototype.swipeHandler=function(a){var b=this;if(!(b.options.swipe===!1||"ontouchend"in document&&b.options.swipe===!1||b.options.draggable===!1&&-1!==a.type.indexOf("mouse")))switch(b.touchObject.fingerCount=a.originalEvent&&void 0!==a.originalEvent.touches?a.originalEvent.touches.length:1,b.touchObject.minSwipe=b.listWidth/b.options.touchThreshold,b.options.verticalSwiping===!0&&(b.touchObject.minSwipe=b.listHeight/b.options.touchThreshold),a.data.action){case"start":b.swipeStart(a);break;case"move":b.swipeMove(a);break;case"end":b.swipeEnd(a)}},b.prototype.swipeMove=function(a){var d,e,f,g,h,b=this;return h=void 0!==a.originalEvent?a.originalEvent.touches:null,!b.dragging||h&&1!==h.length?!1:(d=b.getLeft(b.currentSlide),b.touchObject.curX=void 0!==h?h[0].pageX:a.clientX,b.touchObject.curY=void 0!==h?h[0].pageY:a.clientY,b.touchObject.swipeLength=Math.round(Math.sqrt(Math.pow(b.touchObject.curX-b.touchObject.startX,2))),b.options.verticalSwiping===!0&&(b.touchObject.swipeLength=Math.round(Math.sqrt(Math.pow(b.touchObject.curY-b.touchObject.startY,2)))),e=b.swipeDirection(),"vertical"!==e?(void 0!==a.originalEvent&&b.touchObject.swipeLength>4&&a.preventDefault(),g=(b.options.rtl===!1?1:-1)*(b.touchObject.curX>b.touchObject.startX?1:-1),b.options.verticalSwiping===!0&&(g=b.touchObject.curY>b.touchObject.startY?1:-1),f=b.touchObject.swipeLength,b.touchObject.edgeHit=!1,b.options.infinite===!1&&(0===b.currentSlide&&"right"===e||b.currentSlide>=b.getDotCount()&&"left"===e)&&(f=b.touchObject.swipeLength*b.options.edgeFriction,b.touchObject.edgeHit=!0),b.options.vertical===!1?b.swipeLeft=d+f*g:b.swipeLeft=d+f*(b.$list.height()/b.listWidth)*g,b.options.verticalSwiping===!0&&(b.swipeLeft=d+f*g),b.options.fade===!0||b.options.touchMove===!1?!1:b.animating===!0?(b.swipeLeft=null,!1):void b.setCSS(b.swipeLeft)):void 0)},b.prototype.swipeStart=function(a){var c,b=this;return b.interrupted=!0,1!==b.touchObject.fingerCount||b.slideCount<=b.options.slidesToShow?(b.touchObject={},!1):(void 0!==a.originalEvent&&void 0!==a.originalEvent.touches&&(c=a.originalEvent.touches[0]),b.touchObject.startX=b.touchObject.curX=void 0!==c?c.pageX:a.clientX,b.touchObject.startY=b.touchObject.curY=void 0!==c?c.pageY:a.clientY,void(b.dragging=!0))},b.prototype.unfilterSlides=b.prototype.slickUnfilter=function(){var a=this;null!==a.$slidesCache&&(a.unload(),a.$slideTrack.children(this.options.slide).detach(),a.$slidesCache.appendTo(a.$slideTrack),a.reinit())},b.prototype.unload=function(){var b=this;a(".slick-cloned",b.$slider).remove(),b.$dots&&b.$dots.remove(),b.$prevArrow&&b.htmlExpr.test(b.options.prevArrow)&&b.$prevArrow.remove(),b.$nextArrow&&b.htmlExpr.test(b.options.nextArrow)&&b.$nextArrow.remove(),b.$slides.removeClass("slick-slide slick-active slick-visible slick-current").attr("aria-hidden","true").css("width","")},b.prototype.unslick=function(a){var b=this;b.$slider.trigger("unslick",[b,a]),b.destroy()},b.prototype.updateArrows=function(){var b,a=this;b=Math.floor(a.options.slidesToShow/2),a.options.arrows===!0&&a.slideCount>a.options.slidesToShow&&!a.options.infinite&&(a.$prevArrow.removeClass("slick-disabled").attr("aria-disabled","false"),a.$nextArrow.removeClass("slick-disabled").attr("aria-disabled","false"),0===a.currentSlide?(a.$prevArrow.addClass("slick-disabled").attr("aria-disabled","true"),a.$nextArrow.removeClass("slick-disabled").attr("aria-disabled","false")):a.currentSlide>=a.slideCount-a.options.slidesToShow&&a.options.centerMode===!1?(a.$nextArrow.addClass("slick-disabled").attr("aria-disabled","true"),a.$prevArrow.removeClass("slick-disabled").attr("aria-disabled","false")):a.currentSlide>=a.slideCount-1&&a.options.centerMode===!0&&(a.$nextArrow.addClass("slick-disabled").attr("aria-disabled","true"),a.$prevArrow.removeClass("slick-disabled").attr("aria-disabled","false")))},b.prototype.updateDots=function(){var a=this;null!==a.$dots&&(a.$dots.find("li").removeClass("slick-active").attr("aria-hidden","true"),a.$dots.find("li").eq(Math.floor(a.currentSlide/a.options.slidesToScroll)).addClass("slick-active").attr("aria-hidden","false"))},b.prototype.visibility=function(){var a=this;a.options.autoplay&&(document[a.hidden]?a.interrupted=!0:a.interrupted=!1)},a.fn.slick=function(){var f,g,a=this,c=arguments[0],d=Array.prototype.slice.call(arguments,1),e=a.length;for(f=0;e>f;f++)if("object"==typeof c||"undefined"==typeof c?a[f].slick=new b(a[f],c):g=a[f].slick[c].apply(a[f].slick,d),"undefined"!=typeof g)return g;return a}});
97144// Spectrum Colorpicker v1.1.2
97145// https://github.com/bgrins/spectrum
97146// Author: Brian Grinstead
97147// License: MIT
97148
97149(function (window, $, undefined) {
97150    var defaultOpts = {
97151
97152        // Callbacks
97153        beforeShow: noop,
97154        move: noop,
97155        change: noop,
97156        show: noop,
97157        hide: noop,
97158
97159        // Options
97160        color: false,
97161        flat: false,
97162        showInput: false,
97163        showButtons: true,
97164        clickoutFiresChange: false,
97165        showInitial: false,
97166        showPalette: false,
97167        showPaletteOnly: false,
97168        showSelectionPalette: true,
97169        localStorageKey: false,
97170        appendTo: "body",
97171        maxSelectionSize: 7,
97172        cancelText: "cancel",
97173        chooseText: "choose",
97174        preferredFormat: false,
97175        className: "",
97176        showAlpha: false,
97177        theme: "sp-light",
97178        palette: ['fff', '000'],
97179        selectionPalette: [],
97180        disabled: false
97181    },
97182    spectrums = [],
97183    IE = !!/msie/i.exec( window.navigator.userAgent ),
97184    rgbaSupport = (function() {
97185        function contains( str, substr ) {
vendor: 4,456 bytes, lines 97186-97292
97186            return !!~('' + str).indexOf(substr);
97187        }
97188
97189        var elem = document.createElement('div');
97190        var style = elem.style;
97191        style.cssText = 'background-color:rgba(0,0,0,.5)';
97192        return contains(style.backgroundColor, 'rgba') || contains(style.backgroundColor, 'hsla');
97193    })(),
97194    replaceInput = [
97195        "<div class='sp-replacer'>",
97196            "<div class='sp-preview'><div class='sp-preview-inner'></div></div>",
97197            "<div class='sp-dd'>&#9660;</div>",
97198        "</div>"
97199    ].join(''),
97200    markup = (function () {
97201
97202        // IE does not support gradients with multiple stops, so we need to simulate
97203        //  that for the rainbow slider with 8 divs that each have a single gradient
97204        var gradientFix = "";
97205        if (IE) {
97206            for (var i = 1; i <= 6; i++) {
97207                gradientFix += "<div class='sp-" + i + "'></div>";
97208            }
97209        }
97210
97211        return [
97212            "<div class='sp-container sp-hidden'>",
97213                "<div class='sp-palette-container'>",
97214                    "<div class='sp-palette sp-thumb sp-cf'></div>",
97215                "</div>",
97216                "<div class='sp-picker-container'>",
97217                    "<div class='sp-top sp-cf'>",
97218                        "<div class='sp-fill'></div>",
97219                        "<div class='sp-top-inner'>",
97220                            "<div class='sp-color'>",
97221                                "<div class='sp-sat'>",
97222                                    "<div class='sp-val'>",
97223                                        "<div class='sp-dragger'></div>",
97224                                    "</div>",
97225                                "</div>",
97226                            "</div>",
97227                            "<div class='sp-hue'>",
97228                                "<div class='sp-slider'></div>",
97229                                gradientFix,
97230                            "</div>",
97231                        "</div>",
97232                        "<div class='sp-alpha'><div class='sp-alpha-inner'><div class='sp-alpha-handle'></div></div></div>",
97233                    "</div>",
97234                    "<div class='sp-input-container sp-cf'>",
97235                        "<input class='sp-input' type='text' spellcheck='false'  />",
97236                    "</div>",
97237                    "<div class='sp-initial sp-thumb sp-cf'></div>",
97238                    "<div class='sp-button-container sp-cf'>",
97239                        "<a class='sp-cancel' href='#'></a>",
97240                        "<button class='sp-choose'></button>",
97241                    "</div>",
97242                "</div>",
97243            "</div>"
97244        ].join("");
97245    })();
97246
97247    function paletteTemplate (p, color, className) {
97248        var html = [];
97249        for (var i = 0; i < p.length; i++) {
97250            var tiny = tinycolor(p[i]);
97251            var c = tiny.toHsl().l < 0.5 ? "sp-thumb-el sp-thumb-dark" : "sp-thumb-el sp-thumb-light";
97252            c += (tinycolor.equals(color, p[i])) ? " sp-thumb-active" : "";
97253
97254            var swatchStyle = rgbaSupport ? ("background-color:" + tiny.toRgbString()) : "filter:" + tiny.toFilter();
97255            html.push('<span title="' + tiny.toRgbString() + '" data-color="' + tiny.toRgbString() + '" class="' + c + '"><span class="sp-thumb-inner" style="' + swatchStyle + ';" /></span>');
97256        }
97257        return "<div class='sp-cf " + className + "'>" + html.join('') + "</div>";
97258    }
97259
97260    function hideAll() {
97261        for (var i = 0; i < spectrums.length; i++) {
97262            if (spectrums[i]) {
97263                spectrums[i].hide();
97264            }
97265        }
97266    }
97267
97268    function instanceOptions(o, callbackContext) {
97269        var opts = $.extend({}, defaultOpts, o);
97270        opts.callbacks = {
97271            'move': bind(opts.move, callbackContext),
97272            'change': bind(opts.change, callbackContext),
97273            'show': bind(opts.show, callbackContext),
97274            'hide': bind(opts.hide, callbackContext),
97275            'beforeShow': bind(opts.beforeShow, callbackContext)
97276        };
97277
97278        return opts;
97279    }
97280
97281    function spectrum(element, o) {
97282
97283        var opts = instanceOptions(o, element),
97284            flat = opts.flat,
97285            showSelectionPalette = opts.showSelectionPalette,
97286            localStorageKey = opts.localStorageKey,
97287            theme = opts.theme,
97288            callbacks = opts.callbacks,
97289            resize = throttle(reflow, 10),
97290            visible = false,
97291            dragWidth = 0,
97292            dragHeight = 0,
vendor: 7,994 bytes, lines 97293-97507
97293            dragHelperHeight = 0,
97294            slideHeight = 0,
97295            slideWidth = 0,
97296            alphaWidth = 0,
97297            alphaSlideHelperWidth = 0,
97298            slideHelperHeight = 0,
97299            currentHue = 0,
97300            currentSaturation = 0,
97301            currentValue = 0,
97302            currentAlpha = 1,
97303            palette = opts.palette.slice(0),
97304            paletteArray = $.isArray(palette[0]) ? palette : [palette],
97305            selectionPalette = opts.selectionPalette.slice(0),
97306            maxSelectionSize = opts.maxSelectionSize,
97307            draggingClass = "sp-dragging",
97308            shiftMovementDirection = null;
97309
97310        var doc = element.ownerDocument,
97311            body = doc.body,
97312            boundElement = $(element),
97313            disabled = false,
97314            container = $(markup, doc).addClass(theme),
97315            dragger = container.find(".sp-color"),
97316            dragHelper = container.find(".sp-dragger"),
97317            slider = container.find(".sp-hue"),
97318            slideHelper = container.find(".sp-slider"),
97319            alphaSliderInner = container.find(".sp-alpha-inner"),
97320            alphaSlider = container.find(".sp-alpha"),
97321            alphaSlideHelper = container.find(".sp-alpha-handle"),
97322            textInput = container.find(".sp-input"),
97323            paletteContainer = container.find(".sp-palette"),
97324            initialColorContainer = container.find(".sp-initial"),
97325            cancelButton = container.find(".sp-cancel"),
97326            chooseButton = container.find(".sp-choose"),
97327            isInput = boundElement.is("input"),
97328            shouldReplace = isInput && !flat,
97329            replacer = (shouldReplace) ? $(replaceInput).addClass(theme).addClass(opts.className) : $([]),
97330            offsetElement = (shouldReplace) ? replacer : boundElement,
97331            previewElement = replacer.find(".sp-preview-inner"),
97332            initialColor = opts.color || (isInput && boundElement.val()),
97333            colorOnShow = false,
97334            preferredFormat = opts.preferredFormat,
97335            currentPreferredFormat = preferredFormat,
97336            clickoutFiresChange = !opts.showButtons || opts.clickoutFiresChange;
97337
97338
97339        function applyOptions() {
97340
97341            if (opts.showPaletteOnly) {
97342                opts.showPalette = true;
97343            }
97344
97345            container.toggleClass("sp-flat", flat);
97346            container.toggleClass("sp-input-disabled", !opts.showInput);
97347            container.toggleClass("sp-alpha-enabled", opts.showAlpha);
97348            container.toggleClass("sp-buttons-disabled", !opts.showButtons);
97349            container.toggleClass("sp-palette-disabled", !opts.showPalette);
97350            container.toggleClass("sp-palette-only", opts.showPaletteOnly);
97351            container.toggleClass("sp-initial-disabled", !opts.showInitial);
97352            container.addClass(opts.className);
97353
97354            reflow();
97355        }
97356
97357        function initialize() {
97358
97359            if (IE) {
97360                container.find("*:not(input)").attr("unselectable", "on");
97361            }
97362
97363            applyOptions();
97364
97365            if (shouldReplace) {
97366                boundElement.after(replacer).hide();
97367            }
97368
97369            if (flat) {
97370                boundElement.after(container).hide();
97371            }
97372            else {
97373
97374                var appendTo = opts.appendTo === "parent" ? boundElement.parent() : $(opts.appendTo);
97375                if (appendTo.length !== 1) {
97376                    appendTo = $("body");
97377                }
97378
97379                appendTo.append(container);
97380            }
97381
97382            if (localStorageKey && window.localStorage) {
97383
97384                // Migrate old palettes over to new format.  May want to remove this eventually.
97385                try {
97386                    var oldPalette = window.localStorage[localStorageKey].split(",#");
97387                    if (oldPalette.length > 1) {
97388                        delete window.localStorage[localStorageKey];
97389                        $.each(oldPalette, function(i, c) {
97390                             addColorToSelectionPalette(c);
97391                        });
97392                    }
97393                }
97394                catch(e) { }
97395
97396                try {
97397                    selectionPalette = window.localStorage[localStorageKey].split(";");
97398                }
97399                catch (e) { }
97400            }
97401
97402            offsetElement.bind("click.spectrum touchstart.spectrum", function (e) {
97403                if (!disabled) {
97404                    toggle();
97405                }
97406
97407                e.stopPropagation();
97408
97409                if (!$(e.target).is("input")) {
97410                    e.preventDefault();
97411                }
97412            });
97413
97414            if(boundElement.is(":disabled") || (opts.disabled === true)) {
97415                disable();
97416            }
97417
97418            // Prevent clicks from bubbling up to document.  This would cause it to be hidden.
97419            container.click(stopPropagation);
97420
97421            // Handle user typed input
97422            textInput.change(setFromTextInput);
97423            textInput.bind("paste", function () {
97424                setTimeout(setFromTextInput, 1);
97425            });
97426            textInput.keydown(function (e) { if (e.keyCode == 13) { setFromTextInput(); } });
97427
97428            cancelButton.text(opts.cancelText);
97429            cancelButton.bind("click.spectrum", function (e) {
97430                e.stopPropagation();
97431                e.preventDefault();
97432                hide("cancel");
97433            });
97434
97435            chooseButton.text(opts.chooseText);
97436            chooseButton.bind("click.spectrum", function (e) {
97437                e.stopPropagation();
97438                e.preventDefault();
97439
97440                if (isValid()) {
97441                    updateOriginalInput(true);
97442                    hide();
97443                }
97444            });
97445
97446            draggable(alphaSlider, function (dragX, dragY, e) {
97447                currentAlpha = (dragX / alphaWidth);
97448                if (e.shiftKey) {
97449                    currentAlpha = Math.round(currentAlpha * 10) / 10;
97450                }
97451
97452                move();
97453            });
97454
97455            draggable(slider, function (dragX, dragY) {
97456                currentHue = parseFloat(dragY / slideHeight);
97457                move();
97458            }, dragStart, dragStop);
97459
97460            draggable(dragger, function (dragX, dragY, e) {
97461
97462                // shift+drag should snap the movement to either the x or y axis.
97463                if (!e.shiftKey) {
97464                    shiftMovementDirection = null;
97465                }
97466                else if (!shiftMovementDirection) {
97467                    var oldDragX = currentSaturation * dragWidth;
97468                    var oldDragY = dragHeight - (currentValue * dragHeight);
97469                    var furtherFromX = Math.abs(dragX - oldDragX) > Math.abs(dragY - oldDragY);
97470
97471                    shiftMovementDirection = furtherFromX ? "x" : "y";
97472                }
97473
97474                var setSaturation = !shiftMovementDirection || shiftMovementDirection === "x";
97475                var setValue = !shiftMovementDirection || shiftMovementDirection === "y";
97476
97477                if (setSaturation) {
97478                    currentSaturation = parseFloat(dragX / dragWidth);
97479                }
97480                if (setValue) {
97481                    currentValue = parseFloat((dragHeight - dragY) / dragHeight);
97482                }
97483
97484                move();
97485
97486            }, dragStart, dragStop);
97487
97488            if (!!initialColor) {
97489                set(initialColor);
97490
97491                // In case color was black - update the preview UI and set the format
97492                // since the set function will not run (default color is black).
97493                updateUI();
97494                currentPreferredFormat = preferredFormat || tinycolor(initialColor).format;
97495
97496                addColorToSelectionPalette(initialColor);
97497            }
97498            else {
97499                updateUI();
97500            }
97501
97502            if (flat) {
97503                show();
97504            }
97505
97506            function palletElementClick(e) {
97507                if (e.data && e.data.ignore) {
97508                    set($(this).data("color"));
97509                    move();
97510                }
97511                else {
97512                    set($(this).data("color"));
97513                    updateOriginalInput(true);
97514                    move();
97515                    hide();
97516                }
97517
97518                return false;
97519            }
97520
97521            var paletteEvent = IE ? "mousedown.spectrum" : "click.spectrum touchstart.spectrum";
97522            paletteContainer.delegate(".sp-thumb-el", paletteEvent, palletElementClick);
97523            initialColorContainer.delegate(".sp-thumb-el:nth-child(1)", paletteEvent, { ignore: true }, palletElementClick);
97524        }
97525
97526        function addColorToSelectionPalette(color) {
97527            if (showSelectionPalette) {
97528                var colorRgb = tinycolor(color).toRgbString();
97529                if ($.inArray(colorRgb, selectionPalette) === -1) {
97530                    selectionPalette.push(colorRgb);
97531                    while(selectionPalette.length > maxSelectionSize) {
97532                        selectionPalette.shift();
97533                    }
97534                }
97535
97536                if (localStorageKey && window.localStorage) {
97537                    try {
97538                        window.localStorage[localStorageKey] = selectionPalette.join(";");
97539                    }
97540                    catch(e) { }
97541                }
97542            }
97543        }
97544
97545        function getUniqueSelectionPalette() {
97546            var unique = [];
97547            var p = selectionPalette;
97548            var paletteLookup = {};
97549            var rgb;
97550
97551            if (opts.showPalette) {
97552
97553                for (var i = 0; i < paletteArray.length; i++) {
97554                    for (var j = 0; j < paletteArray[i].length; j++) {
97555                        rgb = tinycolor(paletteArray[i][j]).toRgbString();
97556                        paletteLookup[rgb] = true;
97557                    }
97558                }
97559
97560                for (i = 0; i < p.length; i++) {
97561                    rgb = tinycolor(p[i]).toRgbString();
97562
97563                    if (!paletteLookup.hasOwnProperty(rgb)) {
97564                        unique.push(p[i]);
97565                        paletteLookup[rgb] = true;
97566                    }
97567                }
97568            }
97569
97570            return unique.reverse().slice(0, opts.maxSelectionSize);
97571        }
97572
97573        function drawPalette() {
97574
97575            var currentColor = get();
97576
97577            var html = $.map(paletteArray, function (palette, i) {
97578                return paletteTemplate(palette, currentColor, "sp-palette-row sp-palette-row-" + i);
97579            });
97580
97581            if (selectionPalette) {
97582                html.push(paletteTemplate(getUniqueSelectionPalette(), currentColor, "sp-palette-row sp-palette-row-selection"));
97583            }
97584
97585            paletteContainer.html(html.join(""));
97586        }
97587
97588        function drawInitial() {
97589            if (opts.showInitial) {
97590                var initial = colorOnShow;
97591                var current = get();
97592                initialColorContainer.html(paletteTemplate([initial, current], current, "sp-palette-row-initial"));
97593            }
97594        }
97595
97596        function dragStart() {
97597            if (dragHeight <= 0 || dragWidth <= 0 || slideHeight <= 0) {
97598                reflow();
97599            }
97600            container.addClass(draggingClass);
97601            shiftMovementDirection = null;
97602        }
97603
97604        function dragStop() {
97605            container.removeClass(draggingClass);
97606        }
97607
97608        function setFromTextInput() {
97609            var tiny = tinycolor(textInput.val());
97610            if (tiny.ok) {
97611                set(tiny);
97612            }
97613            else {
97614                textInput.addClass("sp-validation-error");
97615            }
97616        }
97617
97618        function toggle() {
97619            if (visible) {
97620                hide();
97621            }
97622            else {
97623                show();
97624            }
97625        }
97626
97627        function show() {
97628            var event = $.Event('beforeShow.spectrum');
97629
97630            if (visible) {
97631                reflow();
97632                return;
97633            }
97634
97635            boundElement.trigger(event, [ get() ]);
97636
97637            if (callbacks.beforeShow(get()) === false || event.isDefaultPrevented()) {
97638                return;
97639            }
97640
97641            hideAll();
97642            visible = true;
97643
97644            $(doc).bind("click.spectrum", hide);
97645            $(window).bind("resize.spectrum", resize);
97646            replacer.addClass("sp-active");
97647            container.removeClass("sp-hidden");
97648
97649            if (opts.showPalette) {
97650                drawPalette();
97651            }
97652            reflow();
97653            updateUI();
97654
97655            colorOnShow = get();
97656
97657            drawInitial();
97658            callbacks.show(colorOnShow);
97659            boundElement.trigger('show.spectrum', [ colorOnShow ]);
97660        }
97661
97662        function hide(e) {
97663
97664            // Return on right click
97665            if (e && e.type == "click" && e.button == 2) { return; }
97666
97667            // Return if hiding is unnecessary
97668            if (!visible || flat) { return; }
97669            visible = false;
97670
97671            $(doc).unbind("click.spectrum", hide);
97672            $(window).unbind("resize.spectrum", resize);
97673
97674            replacer.removeClass("sp-active");
97675            container.addClass("sp-hidden");
97676
97677            var colorHasChanged = !tinycolor.equals(get(), colorOnShow);
97678
97679            if (colorHasChanged) {
97680                if (clickoutFiresChange && e !== "cancel") {
97681                    updateOriginalInput(true);
97682                }
97683                else {
97684                    revert();
97685                }
97686            }
97687
97688            callbacks.hide(get());
97689            boundElement.trigger('hide.spectrum', [ get() ]);
97690        }
97691
97692        function revert() {
97693            set(colorOnShow, true);
97694        }
97695
97696        function set(color, ignoreFormatChange) {
97697            if (tinycolor.equals(color, get())) {
97698                return;
97699            }
97700
97701            var newColor = tinycolor(color);
97702            var newHsv = newColor.toHsv();
97703
97704            currentHue = (newHsv.h % 360) / 360;
97705            currentSaturation = newHsv.s;
97706            currentValue = newHsv.v;
97707            currentAlpha = newHsv.a;
97708
97709            updateUI();
97710
97711            if (newColor.ok && !ignoreFormatChange) {
97712                currentPreferredFormat = preferredFormat || newColor.format;
97713            }
97714        }
97715
97716        function get(opts) {
97717            opts = opts || { };
97718            return tinycolor.fromRatio({
97719                h: currentHue,
97720                s: currentSaturation,
97721                v: currentValue,
97722                a: Math.round(currentAlpha * 100) / 100
97723            }, { format: opts.format || currentPreferredFormat });
97724        }
97725
97726        function isValid() {
97727            return !textInput.hasClass("sp-validation-error");
97728        }
97729
97730        function move() {
97731            updateUI();
97732
97733            callbacks.move(get());
97734            boundElement.trigger('move.spectrum', [ get() ]);
97735        }
97736
97737        function updateUI() {
97738
97739            textInput.removeClass("sp-validation-error");
97740
97741            updateHelperLocations();
97742
97743            // Update dragger background color (gradients take care of saturation and value).
97744            var flatColor = tinycolor.fromRatio({ h: currentHue, s: 1, v: 1 });
97745            dragger.css("background-color", flatColor.toHexString());
97746
97747            // Get a format that alpha will be included in (hex and names ignore alpha)
97748            var format = currentPreferredFormat;
97749            if (currentAlpha < 1) {
97750                if (format === "hex" || format === "hex3" || format === "hex6" || format === "name") {
97751                    format = "rgb";
97752                }
97753            }
97754
97755            var realColor = get({ format: format }),
97756                realHex = realColor.toHexString(),
97757                realRgb = realColor.toRgbString();
97758
97759            // Update the replaced elements background color (with actual selected color)
97760            if (rgbaSupport || realColor.alpha === 1) {
97761                previewElement.css("background-color", realRgb);
97762            }
97763            else {
97764                previewElement.css("background-color", "transparent");
97765                previewElement.css("filter", realColor.toFilter());
97766            }
97767
97768            if (opts.showAlpha) {
97769                var rgb = realColor.toRgb();
97770                rgb.a = 0;
97771                var realAlpha = tinycolor(rgb).toRgbString();
97772                var gradient = "linear-gradient(left, " + realAlpha + ", " + realHex + ")";
97773
97774                if (IE) {
97775                    alphaSliderInner.css("filter", tinycolor(realAlpha).toFilter({ gradientType: 1 }, realHex));
97776                }
97777                else {
97778                    alphaSliderInner.css("background", "-webkit-" + gradient);
97779                    alphaSliderInner.css("background", "-moz-" + gradient);
97780                    alphaSliderInner.css("background", "-ms-" + gradient);
97781                    alphaSliderInner.css("background", gradient);
97782                }
97783            }
97784
97785
97786            // Update the text entry input as it changes happen
97787            if (opts.showInput) {
97788                textInput.val(realColor.toString(format));
97789            }
97790
97791            if (opts.showPalette) {
97792                drawPalette();
97793            }
97794
97795            drawInitial();
97796        }
97797
97798        function updateHelperLocations() {
97799            var s = currentSaturation;
97800            var v = currentValue;
97801
97802            // Where to show the little circle in that displays your current selected color
97803            var dragX = s * dragWidth;
97804            var dragY = dragHeight - (v * dragHeight);
97805            dragX = Math.max(
97806                -dragHelperHeight,
97807                Math.min(dragWidth - dragHelperHeight, dragX - dragHelperHeight)
97808            );
97809            dragY = Math.max(
97810                -dragHelperHeight,
97811                Math.min(dragHeight - dragHelperHeight, dragY - dragHelperHeight)
97812            );
97813            dragHelper.css({
97814                "top": dragY,
97815                "left": dragX
97816            });
97817
97818            var alphaX = currentAlpha * alphaWidth;
97819            alphaSlideHelper.css({
97820                "left": alphaX - (alphaSlideHelperWidth / 2)
97821            });
97822
97823            // Where to show the bar that displays your current selected hue
97824            var slideY = (currentHue) * slideHeight;
97825            slideHelper.css({
97826                "top": slideY - slideHelperHeight
97827            });
97828        }
97829
97830        function updateOriginalInput(fireCallback) {
97831            var color = get();
97832
97833            if (isInput) {
97834                boundElement.val(color.toString(currentPreferredFormat));
97835            }
97836
97837            var hasChanged = !tinycolor.equals(color, colorOnShow);
97838            colorOnShow = color;
97839
97840            // Update the selection palette with the current color
97841            addColorToSelectionPalette(color);
97842            if (fireCallback && hasChanged) {
97843                callbacks.change(color);
97844                boundElement.trigger('change', [ color ]);
97845            }
97846        }
97847
97848        function reflow() {
97849            dragWidth = dragger.width();
97850            dragHeight = dragger.height();
97851            dragHelperHeight = dragHelper.height();
97852            slideWidth = slider.width();
97853            slideHeight = slider.height();
97854            slideHelperHeight = slideHelper.height();
97855            alphaWidth = alphaSlider.width();
97856            alphaSlideHelperWidth = alphaSlideHelper.width();
97857
97858            if (!flat) {
97859                container.css("position", "absolute");
97860                container.offset(getOffset(container, offsetElement));
97861            }
97862
97863            updateHelperLocations();
97864        }
97865
97866        function destroy() {
97867            boundElement.show();
97868            offsetElement.unbind("click.spectrum touchstart.spectrum");
97869            container.remove();
97870            replacer.remove();
97871            spectrums[spect.id] = null;
97872        }
97873
97874        function option(optionName, optionValue) {
97875            if (optionName === undefined) {
97876                return $.extend({}, opts);
97877            }
97878            if (optionValue === undefined) {
97879                return opts[optionName];
97880            }
97881
97882            opts[optionName] = optionValue;
97883            applyOptions();
97884        }
97885
97886        function enable() {
97887            disabled = false;
97888            boundElement.attr("disabled", false);
97889            offsetElement.removeClass("sp-disabled");
97890        }
97891
97892        function disable() {
97893            hide();
97894            disabled = true;
97895            boundElement.attr("disabled", true);
97896            offsetElement.addClass("sp-disabled");
97897        }
97898
97899        initialize();
97900
97901        var spect = {
97902            show: show,
97903            hide: hide,
97904            toggle: toggle,
97905            reflow: reflow,
97906            option: option,
97907            enable: enable,
97908            disable: disable,
97909            set: function (c) {
97910                set(c);
97911                updateOriginalInput();
97912            },
97913            get: get,
97914            destroy: destroy,
97915            container: container
97916        };
97917
97918        spect.id = spectrums.push(spect) - 1;
97919
97920        return spect;
97921    }
97922
97923    /**
97924    * checkOffset - get the offset below/above and left/right element depending on screen position
97925    * Thanks https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.datepicker.js
97926    */
97927    function getOffset(picker, input) {
97928        var extraY = 0;
97929        var dpWidth = picker.outerWidth();
97930        var dpHeight = picker.outerHeight();
97931        var inputHeight = input.outerHeight();
97932        var doc = picker[0].ownerDocument;
97933        var docElem = doc.documentElement;
97934        var viewWidth = docElem.clientWidth + $(doc).scrollLeft();
97935        var viewHeight = docElem.clientHeight + $(doc).scrollTop();
97936        var offset = input.offset();
97937        offset.top += inputHeight;
97938
97939        offset.left -=
97940            Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
97941            Math.abs(offset.left + dpWidth - viewWidth) : 0);
97942
97943        offset.top -=
97944            Math.min(offset.top, ((offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
97945            Math.abs(dpHeight + inputHeight - extraY) : extraY));
97946
97947        return offset;
97948    }
97949
97950    /**
97951    * noop - do nothing
97952    */
97953    function noop() {
97954
97955    }
97956
97957    /**
97958    * stopPropagation - makes the code only doing this a little easier to read in line
97959    */
97960    function stopPropagation(e) {
97961        e.stopPropagation();
97962    }
97963
97964    /**
97965    * Create a function bound to a given object
97966    * Thanks to underscore.js
97967    */
97968    function bind(func, obj) {
97969        var slice = Array.prototype.slice;
97970        var args = slice.call(arguments, 2);
97971        return function () {
97972            return func.apply(obj, args.concat(slice.call(arguments)));
97973        };
97974    }
97975
97976    /**
97977    * Lightweight drag helper.  Handles containment within the element, so that
97978    * when dragging, the x is within [0,element.width] and y is within [0,element.height]
97979    */
97980    function draggable(element, onmove, onstart, onstop) {
97981        onmove = onmove || function () { };
97982        onstart = onstart || function () { };
97983        onstop = onstop || function () { };
97984        var doc = element.ownerDocument || document;
97985        var dragging = false;
vendor: 5,687 bytes, lines 97986-98164
97986        var offset = {};
97987        var maxHeight = 0;
97988        var maxWidth = 0;
97989        var hasTouch = ('ontouchstart' in window);
97990
97991        var duringDragEvents = {};
97992        duringDragEvents["selectstart"] = prevent;
97993        duringDragEvents["dragstart"] = prevent;
97994        duringDragEvents["touchmove mousemove"] = move;
97995        duringDragEvents["touchend mouseup"] = stop;
97996
97997        function prevent(e) {
97998            if (e.stopPropagation) {
97999                e.stopPropagation();
98000            }
98001            if (e.preventDefault) {
98002                e.preventDefault();
98003            }
98004            e.returnValue = false;
98005        }
98006
98007        function move(e) {
98008            if (dragging) {
98009                // Mouseup happened outside of window
98010                if (IE && document.documentMode < 9 && !e.button) {
98011                    return stop();
98012                }
98013
98014                var touches = e.originalEvent.touches;
98015                var pageX = touches ? touches[0].pageX : e.pageX;
98016                var pageY = touches ? touches[0].pageY : e.pageY;
98017
98018                var dragX = Math.max(0, Math.min(pageX - offset.left, maxWidth));
98019                var dragY = Math.max(0, Math.min(pageY - offset.top, maxHeight));
98020
98021                if (hasTouch) {
98022                    // Stop scrolling in iOS
98023                    prevent(e);
98024                }
98025
98026                onmove.apply(element, [dragX, dragY, e]);
98027            }
98028        }
98029        function start(e) {
98030            var rightclick = (e.which) ? (e.which == 3) : (e.button == 2);
98031            var touches = e.originalEvent.touches;
98032
98033            if (!rightclick && !dragging) {
98034                if (onstart.apply(element, arguments) !== false) {
98035                    dragging = true;
98036                    maxHeight = $(element).height();
98037                    maxWidth = $(element).width();
98038                    offset = $(element).offset();
98039
98040                    $(doc).bind(duringDragEvents);
98041                    $(doc.body).addClass("sp-dragging");
98042
98043                    if (!hasTouch) {
98044                        move(e);
98045                    }
98046
98047                    prevent(e);
98048                }
98049            }
98050        }
98051        function stop() {
98052            if (dragging) {
98053                $(doc).unbind(duringDragEvents);
98054                $(doc.body).removeClass("sp-dragging");
98055                onstop.apply(element, arguments);
98056            }
98057            dragging = false;
98058        }
98059
98060        $(element).bind("touchstart mousedown", start);
98061    }
98062
98063    function throttle(func, wait, debounce) {
98064        var timeout;
98065        return function () {
98066            var context = this, args = arguments;
98067            var throttler = function () {
98068                timeout = null;
98069                func.apply(context, args);
98070            };
98071            if (debounce) clearTimeout(timeout);
98072            if (debounce || !timeout) timeout = setTimeout(throttler, wait);
98073        };
98074    }
98075
98076
98077    function log(){/* jshint -W021 */if(window.console){if(Function.prototype.bind)log=Function.prototype.bind.call(console.log,console);else log=function(){Function.prototype.apply.call(console.log,console,arguments);};log.apply(this,arguments);}}
98078
98079    /**
98080    * Define a jQuery plugin
98081    */
98082    var dataID = "spectrum.id";
98083    $.fn.spectrum = function (opts, extra) {
98084
98085        if (typeof opts == "string") {
98086
98087            var returnValue = this;
98088            var args = Array.prototype.slice.call( arguments, 1 );
98089
98090            this.each(function () {
98091                var spect = spectrums[$(this).data(dataID)];
98092                if (spect) {
98093
98094                    var method = spect[opts];
98095                    if (!method) {
98096                        throw new Error( "Spectrum: no such method: '" + opts + "'" );
98097                    }
98098
98099                    if (opts == "get") {
98100                        returnValue = spect.get();
98101                    }
98102                    else if (opts == "container") {
98103                        returnValue = spect.container;
98104                    }
98105                    else if (opts == "option") {
98106                        returnValue = spect.option.apply(spect, args);
98107                    }
98108                    else if (opts == "destroy") {
98109                        spect.destroy();
98110                        $(this).removeData(dataID);
98111                    }
98112                    else {
98113                        method.apply(spect, args);
98114                    }
98115                }
98116            });
98117
98118            return returnValue;
98119        }
98120
98121        // Initializing a new instance of spectrum
98122        return this.spectrum("destroy").each(function () {
98123            var spect = spectrum(this, opts);
98124            $(this).data(dataID, spect.id);
98125        });
98126    };
98127
98128    $.fn.spectrum.load = true;
98129    $.fn.spectrum.loadOpts = {};
98130    $.fn.spectrum.draggable = draggable;
98131    $.fn.spectrum.defaults = defaultOpts;
98132
98133    $.spectrum = { };
98134    $.spectrum.localization = { };
98135    $.spectrum.palettes = { };
98136
98137    $.fn.spectrum.processNativeColorInputs = function () {
98138        var colorInput = $("<input type='color' value='!' />")[0];
98139        var supportsColor = colorInput.type === "color" && colorInput.value != "!";
98140
98141        if (!supportsColor) {
98142            $("input[type=color]").spectrum({
98143                preferredFormat: "hex6"
98144            });
98145        }
98146    };
98147
98148    // TinyColor v0.9.16
98149    // https://github.com/bgrins/TinyColor
98150    // 2013-08-10, Brian Grinstead, MIT License
98151
98152    (function() {
98153
98154    var trimLeft = /^[\s,#]+/,
98155        trimRight = /\s+$/,
98156        tinyCounter = 0,
98157        math = Math,
98158        mathRound = math.round,
98159        mathMin = math.min,
98160        mathMax = math.max,
98161        mathRandom = math.random;
98162
98163    function tinycolor (color, opts) {
98164
98165        color = (color) ? color : '';
98166        opts = opts || { };
98167
98168        // If input is already a tinycolor, return itself
98169        if (typeof color == "object" && color.hasOwnProperty("_tc_id")) {
98170           return color;
98171        }
98172
98173        var rgb = inputToRGB(color);
98174        var r = rgb.r,
98175            g = rgb.g,
98176            b = rgb.b,
98177            a = rgb.a,
98178            roundA = mathRound(100*a) / 100,
98179            format = opts.format || rgb.format;
98180
98181        // Don't let the range of [0,255] come back in [0,1].
98182        // Potentially lose a little bit of precision here, but will fix issues where
98183        // .5 gets interpreted as half of the total, instead of half of 1
98184        // If it was supposed to be 128, this was already taken care of by `inputToRgb`
98185        if (r < 1) { r = mathRound(r); }
98186        if (g < 1) { g = mathRound(g); }
98187        if (b < 1) { b = mathRound(b); }
98188
98189        return {
98190            ok: rgb.ok,
98191            format: format,
98192            _tc_id: tinyCounter++,
98193            alpha: a,
98194            getAlpha: function() {
98195                return a;
98196            },
98197            setAlpha: function(value) {
98198                a = boundAlpha(value);
98199                roundA = mathRound(100*a) / 100;
98200            },
98201            toHsv: function() {
98202                var hsv = rgbToHsv(r, g, b);
98203                return { h: hsv.h * 360, s: hsv.s, v: hsv.v, a: a };
98204            },
98205            toHsvString: function() {
98206                var hsv = rgbToHsv(r, g, b);
98207                var h = mathRound(hsv.h * 360), s = mathRound(hsv.s * 100), v = mathRound(hsv.v * 100);
98208                return (a == 1) ?
98209                  "hsv("  + h + ", " + s + "%, " + v + "%)" :
98210                  "hsva(" + h + ", " + s + "%, " + v + "%, "+ roundA + ")";
98211            },
98212            toHsl: function() {
98213                var hsl = rgbToHsl(r, g, b);
98214                return { h: hsl.h * 360, s: hsl.s, l: hsl.l, a: a };
98215            },
98216            toHslString: function() {
98217                var hsl = rgbToHsl(r, g, b);
98218                var h = mathRound(hsl.h * 360), s = mathRound(hsl.s * 100), l = mathRound(hsl.l * 100);
98219                return (a == 1) ?
98220                  "hsl("  + h + ", " + s + "%, " + l + "%)" :
98221                  "hsla(" + h + ", " + s + "%, " + l + "%, "+ roundA + ")";
98222            },
98223            toHex: function(allow3Char) {
98224                return rgbToHex(r, g, b, allow3Char);
98225            },
98226            toHexString: function(allow3Char) {
98227                return '#' + rgbToHex(r, g, b, allow3Char);
98228            },
98229            toRgb: function() {
98230                return { r: mathRound(r), g: mathRound(g), b: mathRound(b), a: a };
98231            },
98232            toRgbString: function() {
98233                return (a == 1) ?
98234                  "rgb("  + mathRound(r) + ", " + mathRound(g) + ", " + mathRound(b) + ")" :
98235                  "rgba(" + mathRound(r) + ", " + mathRound(g) + ", " + mathRound(b) + ", " + roundA + ")";
98236            },
98237            toPercentageRgb: function() {
98238                return { r: mathRound(bound01(r, 255) * 100) + "%", g: mathRound(bound01(g, 255) * 100) + "%", b: mathRound(bound01(b, 255) * 100) + "%", a: a };
98239            },
98240            toPercentageRgbString: function() {
98241                return (a == 1) ?
98242                  "rgb("  + mathRound(bound01(r, 255) * 100) + "%, " + mathRound(bound01(g, 255) * 100) + "%, " + mathRound(bound01(b, 255) * 100) + "%)" :
98243                  "rgba(" + mathRound(bound01(r, 255) * 100) + "%, " + mathRound(bound01(g, 255) * 100) + "%, " + mathRound(bound01(b, 255) * 100) + "%, " + roundA + ")";
98244            },
98245            toName: function() {
98246                if (a === 0) {
98247                    return "transparent";
98248                }
98249
98250                return hexNames[rgbToHex(r, g, b, true)] || false;
98251            },
98252            toFilter: function(secondColor) {
98253                var hex = rgbToHex(r, g, b);
98254                var secondHex = hex;
98255                var alphaHex = Math.round(parseFloat(a) * 255).toString(16);
98256                var secondAlphaHex = alphaHex;
98257                var gradientType = opts && opts.gradientType ? "GradientType = 1, " : "";
98258
98259                if (secondColor) {
98260                    var s = tinycolor(secondColor);
98261                    secondHex = s.toHex();
98262                    secondAlphaHex = Math.round(parseFloat(s.alpha) * 255).toString(16);
98263                }
98264
98265                return "progid:DXImageTransform.Microsoft.gradient("+gradientType+"startColorstr=#" + pad2(alphaHex) + hex + ",endColorstr=#" + pad2(secondAlphaHex) + secondHex + ")";
98266            },
98267            toString: function(format) {
98268                var formatSet = !!format;
98269                format = format || this.format;
98270
98271                var formattedString = false;
vendor: 26,266 bytes, lines 98272-99084
98272                var hasAlphaAndFormatNotSet = !formatSet && a < 1 && a > 0;
98273                var formatWithAlpha = hasAlphaAndFormatNotSet && (format === "hex" || format === "hex6" || format === "hex3" || format === "name");
98274
98275                if (format === "rgb") {
98276                    formattedString = this.toRgbString();
98277                }
98278                if (format === "prgb") {
98279                    formattedString = this.toPercentageRgbString();
98280                }
98281                if (format === "hex" || format === "hex6") {
98282                    formattedString = this.toHexString();
98283                }
98284                if (format === "hex3") {
98285                    formattedString = this.toHexString(true);
98286                }
98287                if (format === "name") {
98288                    formattedString = this.toName();
98289                }
98290                if (format === "hsl") {
98291                    formattedString = this.toHslString();
98292                }
98293                if (format === "hsv") {
98294                    formattedString = this.toHsvString();
98295                }
98296
98297                if (formatWithAlpha) {
98298                    return this.toRgbString();
98299                }
98300
98301                return formattedString || this.toHexString();
98302            }
98303        };
98304    }
98305
98306    // If input is an object, force 1 into "1.0" to handle ratios properly
98307    // String input requires "1.0" as input, so 1 will be treated as 1
98308    tinycolor.fromRatio = function(color, opts) {
98309        if (typeof color == "object") {
98310            var newColor = {};
98311            for (var i in color) {
98312                if (color.hasOwnProperty(i)) {
98313                    if (i === "a") {
98314                        newColor[i] = color[i];
98315                    }
98316                    else {
98317                        newColor[i] = convertToPercentage(color[i]);
98318                    }
98319                }
98320            }
98321            color = newColor;
98322        }
98323
98324        return tinycolor(color, opts);
98325    };
98326
98327    // Given a string or object, convert that input to RGB
98328    // Possible string inputs:
98329    //
98330    //     "red"
98331    //     "#f00" or "f00"
98332    //     "#ff0000" or "ff0000"
98333    //     "rgb 255 0 0" or "rgb (255, 0, 0)"
98334    //     "rgb 1.0 0 0" or "rgb (1, 0, 0)"
98335    //     "rgba (255, 0, 0, 1)" or "rgba 255, 0, 0, 1"
98336    //     "rgba (1.0, 0, 0, 1)" or "rgba 1.0, 0, 0, 1"
98337    //     "hsl(0, 100%, 50%)" or "hsl 0 100% 50%"
98338    //     "hsla(0, 100%, 50%, 1)" or "hsla 0 100% 50%, 1"
98339    //     "hsv(0, 100%, 100%)" or "hsv 0 100% 100%"
98340    //
98341    function inputToRGB(color) {
98342
98343        var rgb = { r: 0, g: 0, b: 0 };
98344        var a = 1;
98345        var ok = false;
98346        var format = false;
98347
98348        if (typeof color == "string") {
98349            color = stringInputToObject(color);
98350        }
98351
98352        if (typeof color == "object") {
98353            if (color.hasOwnProperty("r") && color.hasOwnProperty("g") && color.hasOwnProperty("b")) {
98354                rgb = rgbToRgb(color.r, color.g, color.b);
98355                ok = true;
98356                format = String(color.r).substr(-1) === "%" ? "prgb" : "rgb";
98357            }
98358            else if (color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("v")) {
98359                color.s = convertToPercentage(color.s);
98360                color.v = convertToPercentage(color.v);
98361                rgb = hsvToRgb(color.h, color.s, color.v);
98362                ok = true;
98363                format = "hsv";
98364            }
98365            else if (color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("l")) {
98366                color.s = convertToPercentage(color.s);
98367                color.l = convertToPercentage(color.l);
98368                rgb = hslToRgb(color.h, color.s, color.l);
98369                ok = true;
98370                format = "hsl";
98371            }
98372
98373            if (color.hasOwnProperty("a")) {
98374                a = color.a;
98375            }
98376        }
98377
98378        a = boundAlpha(a);
98379
98380        return {
98381            ok: ok,
98382            format: color.format || format,
98383            r: mathMin(255, mathMax(rgb.r, 0)),
98384            g: mathMin(255, mathMax(rgb.g, 0)),
98385            b: mathMin(255, mathMax(rgb.b, 0)),
98386            a: a
98387        };
98388    }
98389
98390
98391    // Conversion Functions
98392    // --------------------
98393
98394    // `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from:
98395    // <http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript>
98396
98397    // `rgbToRgb`
98398    // Handle bounds / percentage checking to conform to CSS color spec
98399    // <http://www.w3.org/TR/css3-color/>
98400    // *Assumes:* r, g, b in [0, 255] or [0, 1]
98401    // *Returns:* { r, g, b } in [0, 255]
98402    function rgbToRgb(r, g, b){
98403        return {
98404            r: bound01(r, 255) * 255,
98405            g: bound01(g, 255) * 255,
98406            b: bound01(b, 255) * 255
98407        };
98408    }
98409
98410    // `rgbToHsl`
98411    // Converts an RGB color value to HSL.
98412    // *Assumes:* r, g, and b are contained in [0, 255] or [0, 1]
98413    // *Returns:* { h, s, l } in [0,1]
98414    function rgbToHsl(r, g, b) {
98415
98416        r = bound01(r, 255);
98417        g = bound01(g, 255);
98418        b = bound01(b, 255);
98419
98420        var max = mathMax(r, g, b), min = mathMin(r, g, b);
98421        var h, s, l = (max + min) / 2;
98422
98423        if(max == min) {
98424            h = s = 0; // achromatic
98425        }
98426        else {
98427            var d = max - min;
98428            s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
98429            switch(max) {
98430                case r: h = (g - b) / d + (g < b ? 6 : 0); break;
98431                case g: h = (b - r) / d + 2; break;
98432                case b: h = (r - g) / d + 4; break;
98433            }
98434
98435            h /= 6;
98436        }
98437
98438        return { h: h, s: s, l: l };
98439    }
98440
98441    // `hslToRgb`
98442    // Converts an HSL color value to RGB.
98443    // *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100]
98444    // *Returns:* { r, g, b } in the set [0, 255]
98445    function hslToRgb(h, s, l) {
98446        var r, g, b;
98447
98448        h = bound01(h, 360);
98449        s = bound01(s, 100);
98450        l = bound01(l, 100);
98451
98452        function hue2rgb(p, q, t) {
98453            if(t < 0) t += 1;
98454            if(t > 1) t -= 1;
98455            if(t < 1/6) return p + (q - p) * 6 * t;
98456            if(t < 1/2) return q;
98457            if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
98458            return p;
98459        }
98460
98461        if(s === 0) {
98462            r = g = b = l; // achromatic
98463        }
98464        else {
98465            var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
98466            var p = 2 * l - q;
98467            r = hue2rgb(p, q, h + 1/3);
98468            g = hue2rgb(p, q, h);
98469            b = hue2rgb(p, q, h - 1/3);
98470        }
98471
98472        return { r: r * 255, g: g * 255, b: b * 255 };
98473    }
98474
98475    // `rgbToHsv`
98476    // Converts an RGB color value to HSV
98477    // *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1]
98478    // *Returns:* { h, s, v } in [0,1]
98479    function rgbToHsv(r, g, b) {
98480
98481        r = bound01(r, 255);
98482        g = bound01(g, 255);
98483        b = bound01(b, 255);
98484
98485        var max = mathMax(r, g, b), min = mathMin(r, g, b);
98486        var h, s, v = max;
98487
98488        var d = max - min;
98489        s = max === 0 ? 0 : d / max;
98490
98491        if(max == min) {
98492            h = 0; // achromatic
98493        }
98494        else {
98495            switch(max) {
98496                case r: h = (g - b) / d + (g < b ? 6 : 0); break;
98497                case g: h = (b - r) / d + 2; break;
98498                case b: h = (r - g) / d + 4; break;
98499            }
98500            h /= 6;
98501        }
98502        return { h: h, s: s, v: v };
98503    }
98504
98505    // `hsvToRgb`
98506    // Converts an HSV color value to RGB.
98507    // *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100]
98508    // *Returns:* { r, g, b } in the set [0, 255]
98509     function hsvToRgb(h, s, v) {
98510
98511        h = bound01(h, 360) * 6;
98512        s = bound01(s, 100);
98513        v = bound01(v, 100);
98514
98515        var i = math.floor(h),
98516            f = h - i,
98517            p = v * (1 - s),
98518            q = v * (1 - f * s),
98519            t = v * (1 - (1 - f) * s),
98520            mod = i % 6,
98521            r = [v, q, p, p, t, v][mod],
98522            g = [t, v, v, q, p, p][mod],
98523            b = [p, p, t, v, v, q][mod];
98524
98525        return { r: r * 255, g: g * 255, b: b * 255 };
98526    }
98527
98528    // `rgbToHex`
98529    // Converts an RGB color to hex
98530    // Assumes r, g, and b are contained in the set [0, 255]
98531    // Returns a 3 or 6 character hex
98532    function rgbToHex(r, g, b, allow3Char) {
98533
98534        var hex = [
98535            pad2(mathRound(r).toString(16)),
98536            pad2(mathRound(g).toString(16)),
98537            pad2(mathRound(b).toString(16))
98538        ];
98539
98540        // Return a 3 character hex if possible
98541        if (allow3Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1)) {
98542            return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0);
98543        }
98544
98545        return hex.join("");
98546    }
98547
98548    // `equals`
98549    // Can be called with any tinycolor input
98550    tinycolor.equals = function (color1, color2) {
98551        if (!color1 || !color2) { return false; }
98552        return tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString();
98553    };
98554    tinycolor.random = function() {
98555        return tinycolor.fromRatio({
98556            r: mathRandom(),
98557            g: mathRandom(),
98558            b: mathRandom()
98559        });
98560    };
98561
98562
98563    // Modification Functions
98564    // ----------------------
98565    // Thanks to less.js for some of the basics here
98566    // <https://github.com/cloudhead/less.js/blob/master/lib/less/functions.js>
98567
98568    tinycolor.desaturate = function (color, amount) {
98569        amount = (amount === 0) ? 0 : (amount || 10);
98570        var hsl = tinycolor(color).toHsl();
98571        hsl.s -= amount / 100;
98572        hsl.s = clamp01(hsl.s);
98573        return tinycolor(hsl);
98574    };
98575    tinycolor.saturate = function (color, amount) {
98576        amount = (amount === 0) ? 0 : (amount || 10);
98577        var hsl = tinycolor(color).toHsl();
98578        hsl.s += amount / 100;
98579        hsl.s = clamp01(hsl.s);
98580        return tinycolor(hsl);
98581    };
98582    tinycolor.greyscale = function(color) {
98583        return tinycolor.desaturate(color, 100);
98584    };
98585    tinycolor.lighten = function(color, amount) {
98586        amount = (amount === 0) ? 0 : (amount || 10);
98587        var hsl = tinycolor(color).toHsl();
98588        hsl.l += amount / 100;
98589        hsl.l = clamp01(hsl.l);
98590        return tinycolor(hsl);
98591    };
98592    tinycolor.darken = function (color, amount) {
98593        amount = (amount === 0) ? 0 : (amount || 10);
98594        var hsl = tinycolor(color).toHsl();
98595        hsl.l -= amount / 100;
98596        hsl.l = clamp01(hsl.l);
98597        return tinycolor(hsl);
98598    };
98599    tinycolor.complement = function(color) {
98600        var hsl = tinycolor(color).toHsl();
98601        hsl.h = (hsl.h + 180) % 360;
98602        return tinycolor(hsl);
98603    };
98604
98605
98606    // Combination Functions
98607    // ---------------------
98608    // Thanks to jQuery xColor for some of the ideas behind these
98609    // <https://github.com/infusion/jQuery-xcolor/blob/master/jquery.xcolor.js>
98610
98611    tinycolor.triad = function(color) {
98612        var hsl = tinycolor(color).toHsl();
98613        var h = hsl.h;
98614        return [
98615            tinycolor(color),
98616            tinycolor({ h: (h + 120) % 360, s: hsl.s, l: hsl.l }),
98617            tinycolor({ h: (h + 240) % 360, s: hsl.s, l: hsl.l })
98618        ];
98619    };
98620    tinycolor.tetrad = function(color) {
98621        var hsl = tinycolor(color).toHsl();
98622        var h = hsl.h;
98623        return [
98624            tinycolor(color),
98625            tinycolor({ h: (h + 90) % 360, s: hsl.s, l: hsl.l }),
98626            tinycolor({ h: (h + 180) % 360, s: hsl.s, l: hsl.l }),
98627            tinycolor({ h: (h + 270) % 360, s: hsl.s, l: hsl.l })
98628        ];
98629    };
98630    tinycolor.splitcomplement = function(color) {
98631        var hsl = tinycolor(color).toHsl();
98632        var h = hsl.h;
98633        return [
98634            tinycolor(color),
98635            tinycolor({ h: (h + 72) % 360, s: hsl.s, l: hsl.l}),
98636            tinycolor({ h: (h + 216) % 360, s: hsl.s, l: hsl.l})
98637        ];
98638    };
98639    tinycolor.analogous = function(color, results, slices) {
98640        results = results || 6;
98641        slices = slices || 30;
98642
98643        var hsl = tinycolor(color).toHsl();
98644        var part = 360 / slices;
98645        var ret = [tinycolor(color)];
98646
98647        for (hsl.h = ((hsl.h - (part * results >> 1)) + 720) % 360; --results; ) {
98648            hsl.h = (hsl.h + part) % 360;
98649            ret.push(tinycolor(hsl));
98650        }
98651        return ret;
98652    };
98653    tinycolor.monochromatic = function(color, results) {
98654        results = results || 6;
98655        var hsv = tinycolor(color).toHsv();
98656        var h = hsv.h, s = hsv.s, v = hsv.v;
98657        var ret = [];
98658        var modification = 1 / results;
98659
98660        while (results--) {
98661            ret.push(tinycolor({ h: h, s: s, v: v}));
98662            v = (v + modification) % 1;
98663        }
98664
98665        return ret;
98666    };
98667
98668
98669    // Readability Functions
98670    // ---------------------
98671    // <http://www.w3.org/TR/AERT#color-contrast>
98672
98673    // `readability`
98674    // Analyze the 2 colors and returns an object with the following properties:
98675    //    `brightness`: difference in brightness between the two colors
98676    //    `color`: difference in color/hue between the two colors
98677    tinycolor.readability = function(color1, color2) {
98678        var a = tinycolor(color1).toRgb();
98679        var b = tinycolor(color2).toRgb();
98680        var brightnessA = (a.r * 299 + a.g * 587 + a.b * 114) / 1000;
98681        var brightnessB = (b.r * 299 + b.g * 587 + b.b * 114) / 1000;
98682        var colorDiff = (
98683            Math.max(a.r, b.r) - Math.min(a.r, b.r) +
98684            Math.max(a.g, b.g) - Math.min(a.g, b.g) +
98685            Math.max(a.b, b.b) - Math.min(a.b, b.b)
98686        );
98687
98688        return {
98689            brightness: Math.abs(brightnessA - brightnessB),
98690            color: colorDiff
98691        };
98692    };
98693
98694    // `readable`
98695    // http://www.w3.org/TR/AERT#color-contrast
98696    // Ensure that foreground and background color combinations provide sufficient contrast.
98697    // *Example*
98698    //    tinycolor.readable("#000", "#111") => false
98699    tinycolor.readable = function(color1, color2) {
98700        var readability = tinycolor.readability(color1, color2);
98701        return readability.brightness > 125 && readability.color > 500;
98702    };
98703
98704    // `mostReadable`
98705    // Given a base color and a list of possible foreground or background
98706    // colors for that base, returns the most readable color.
98707    // *Example*
98708    //    tinycolor.mostReadable("#123", ["#fff", "#000"]) => "#000"
98709    tinycolor.mostReadable = function(baseColor, colorList) {
98710        var bestColor = null;
98711        var bestScore = 0;
98712        var bestIsReadable = false;
98713        for (var i=0; i < colorList.length; i++) {
98714
98715            // We normalize both around the "acceptable" breaking point,
98716            // but rank brightness constrast higher than hue.
98717
98718            var readability = tinycolor.readability(baseColor, colorList[i]);
98719            var readable = readability.brightness > 125 && readability.color > 500;
98720            var score = 3 * (readability.brightness / 125) + (readability.color / 500);
98721
98722            if ((readable && ! bestIsReadable) ||
98723                (readable && bestIsReadable && score > bestScore) ||
98724                ((! readable) && (! bestIsReadable) && score > bestScore)) {
98725                bestIsReadable = readable;
98726                bestScore = score;
98727                bestColor = tinycolor(colorList[i]);
98728            }
98729        }
98730        return bestColor;
98731    };
98732
98733
98734    // Big List of Colors
98735    // ------------------
98736    // <http://www.w3.org/TR/css3-color/#svg-color>
98737    var names = tinycolor.names = {
98738        aliceblue: "f0f8ff",
98739        antiquewhite: "faebd7",
98740        aqua: "0ff",
98741        aquamarine: "7fffd4",
98742        azure: "f0ffff",
98743        beige: "f5f5dc",
98744        bisque: "ffe4c4",
98745        black: "000",
98746        blanchedalmond: "ffebcd",
98747        blue: "00f",
98748        blueviolet: "8a2be2",
98749        brown: "a52a2a",
98750        burlywood: "deb887",
98751        burntsienna: "ea7e5d",
98752        cadetblue: "5f9ea0",
98753        chartreuse: "7fff00",
98754        chocolate: "d2691e",
98755        coral: "ff7f50",
98756        cornflowerblue: "6495ed",
98757        cornsilk: "fff8dc",
98758        crimson: "dc143c",
98759        cyan: "0ff",
98760        darkblue: "00008b",
98761        darkcyan: "008b8b",
98762        darkgoldenrod: "b8860b",
98763        darkgray: "a9a9a9",
98764        darkgreen: "006400",
98765        darkgrey: "a9a9a9",
98766        darkkhaki: "bdb76b",
98767        darkmagenta: "8b008b",
98768        darkolivegreen: "556b2f",
98769        darkorange: "ff8c00",
98770        darkorchid: "9932cc",
98771        darkred: "8b0000",
98772        darksalmon: "e9967a",
98773        darkseagreen: "8fbc8f",
98774        darkslateblue: "483d8b",
98775        darkslategray: "2f4f4f",
98776        darkslategrey: "2f4f4f",
98777        darkturquoise: "00ced1",
98778        darkviolet: "9400d3",
98779        deeppink: "ff1493",
98780        deepskyblue: "00bfff",
98781        dimgray: "696969",
98782        dimgrey: "696969",
98783        dodgerblue: "1e90ff",
98784        firebrick: "b22222",
98785        floralwhite: "fffaf0",
98786        forestgreen: "228b22",
98787        fuchsia: "f0f",
98788        gainsboro: "dcdcdc",
98789        ghostwhite: "f8f8ff",
98790        gold: "ffd700",
98791        goldenrod: "daa520",
98792        gray: "808080",
98793        green: "008000",
98794        greenyellow: "adff2f",
98795        grey: "808080",
98796        honeydew: "f0fff0",
98797        hotpink: "ff69b4",
98798        indianred: "cd5c5c",
98799        indigo: "4b0082",
98800        ivory: "fffff0",
98801        khaki: "f0e68c",
98802        lavender: "e6e6fa",
98803        lavenderblush: "fff0f5",
98804        lawngreen: "7cfc00",
98805        lemonchiffon: "fffacd",
98806        lightblue: "add8e6",
98807        lightcoral: "f08080",
98808        lightcyan: "e0ffff",
98809        lightgoldenrodyellow: "fafad2",
98810        lightgray: "d3d3d3",
98811        lightgreen: "90ee90",
98812        lightgrey: "d3d3d3",
98813        lightpink: "ffb6c1",
98814        lightsalmon: "ffa07a",
98815        lightseagreen: "20b2aa",
98816        lightskyblue: "87cefa",
98817        lightslategray: "789",
98818        lightslategrey: "789",
98819        lightsteelblue: "b0c4de",
98820        lightyellow: "ffffe0",
98821        lime: "0f0",
98822        limegreen: "32cd32",
98823        linen: "faf0e6",
98824        magenta: "f0f",
98825        maroon: "800000",
98826        mediumaquamarine: "66cdaa",
98827        mediumblue: "0000cd",
98828        mediumorchid: "ba55d3",
98829        mediumpurple: "9370db",
98830        mediumseagreen: "3cb371",
98831        mediumslateblue: "7b68ee",
98832        mediumspringgreen: "00fa9a",
98833        mediumturquoise: "48d1cc",
98834        mediumvioletred: "c71585",
98835        midnightblue: "191970",
98836        mintcream: "f5fffa",
98837        mistyrose: "ffe4e1",
98838        moccasin: "ffe4b5",
98839        navajowhite: "ffdead",
98840        navy: "000080",
98841        oldlace: "fdf5e6",
98842        olive: "808000",
98843        olivedrab: "6b8e23",
98844        orange: "ffa500",
98845        orangered: "ff4500",
98846        orchid: "da70d6",
98847        palegoldenrod: "eee8aa",
98848        palegreen: "98fb98",
98849        paleturquoise: "afeeee",
98850        palevioletred: "db7093",
98851        papayawhip: "ffefd5",
98852        peachpuff: "ffdab9",
98853        peru: "cd853f",
98854        pink: "ffc0cb",
98855        plum: "dda0dd",
98856        powderblue: "b0e0e6",
98857        purple: "800080",
98858        red: "f00",
98859        rosybrown: "bc8f8f",
98860        royalblue: "4169e1",
98861        saddlebrown: "8b4513",
98862        salmon: "fa8072",
98863        sandybrown: "f4a460",
98864        seagreen: "2e8b57",
98865        seashell: "fff5ee",
98866        sienna: "a0522d",
98867        silver: "c0c0c0",
98868        skyblue: "87ceeb",
98869        slateblue: "6a5acd",
98870        slategray: "708090",
98871        slategrey: "708090",
98872        snow: "fffafa",
98873        springgreen: "00ff7f",
98874        steelblue: "4682b4",
98875        tan: "d2b48c",
98876        teal: "008080",
98877        thistle: "d8bfd8",
98878        tomato: "ff6347",
98879        turquoise: "40e0d0",
98880        violet: "ee82ee",
98881        wheat: "f5deb3",
98882        white: "fff",
98883        whitesmoke: "f5f5f5",
98884        yellow: "ff0",
98885        yellowgreen: "9acd32"
98886    };
98887
98888    // Make it easy to access colors via `hexNames[hex]`
98889    var hexNames = tinycolor.hexNames = flip(names);
98890
98891
98892    // Utilities
98893    // ---------
98894
98895    // `{ 'name1': 'val1' }` becomes `{ 'val1': 'name1' }`
98896    function flip(o) {
98897        var flipped = { };
98898        for (var i in o) {
98899            if (o.hasOwnProperty(i)) {
98900                flipped[o[i]] = i;
98901            }
98902        }
98903        return flipped;
98904    }
98905
98906    // Return a valid alpha value [0,1] with all invalid values being set to 1
98907    function boundAlpha(a) {
98908        a = parseFloat(a);
98909
98910        if (isNaN(a) || a < 0 || a > 1) {
98911            a = 1;
98912        }
98913
98914        return a;
98915    }
98916
98917    // Take input from [0, n] and return it as [0, 1]
98918    function bound01(n, max) {
98919        if (isOnePointZero(n)) { n = "100%"; }
98920
98921        var processPercent = isPercentage(n);
98922        n = mathMin(max, mathMax(0, parseFloat(n)));
98923
98924        // Automatically convert percentage into number
98925        if (processPercent) {
98926            n = parseInt(n * max, 10) / 100;
98927        }
98928
98929        // Handle floating point rounding errors
98930        if ((math.abs(n - max) < 0.000001)) {
98931            return 1;
98932        }
98933
98934        // Convert into [0, 1] range if it isn't already
98935        return (n % max) / parseFloat(max);
98936    }
98937
98938    // Force a number between 0 and 1
98939    function clamp01(val) {
98940        return mathMin(1, mathMax(0, val));
98941    }
98942
98943    // Parse an integer into hex
98944    function parseHex(val) {
98945        return parseInt(val, 16);
98946    }
98947
98948    // Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1
98949    // <http://stackoverflow.com/questions/7422072/javascript-how-to-detect-number-as-a-decimal-including-1-0>
98950    function isOnePointZero(n) {
98951        return typeof n == "string" && n.indexOf('.') != -1 && parseFloat(n) === 1;
98952    }
98953
98954    // Check to see if string passed in is a percentage
98955    function isPercentage(n) {
98956        return typeof n === "string" && n.indexOf('%') != -1;
98957    }
98958
98959    // Force a hex value to have 2 characters
98960    function pad2(c) {
98961        return c.length == 1 ? '0' + c : '' + c;
98962    }
98963
98964    // Replace a decimal with it's percentage value
98965    function convertToPercentage(n) {
98966        if (n <= 1) {
98967            n = (n * 100) + "%";
98968        }
98969
98970        return n;
98971    }
98972
98973    var matchers = (function() {
98974
98975        // <http://www.w3.org/TR/css3-values/#integers>
98976        var CSS_INTEGER = "[-\\+]?\\d+%?";
98977
98978        // <http://www.w3.org/TR/css3-values/#number-value>
98979        var CSS_NUMBER = "[-\\+]?\\d*\\.\\d+%?";
98980
98981        // Allow positive/negative integer/number.  Don't capture the either/or, just the entire outcome.
98982        var CSS_UNIT = "(?:" + CSS_NUMBER + ")|(?:" + CSS_INTEGER + ")";
98983
98984        // Actual matching.
98985        // Parentheses and commas are optional, but not required.
98986        // Whitespace can take the place of commas or opening paren
98987        var PERMISSIVE_MATCH3 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?";
98988        var PERMISSIVE_MATCH4 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?";
98989
98990        return {
98991            rgb: new RegExp("rgb" + PERMISSIVE_MATCH3),
98992            rgba: new RegExp("rgba" + PERMISSIVE_MATCH4),
98993            hsl: new RegExp("hsl" + PERMISSIVE_MATCH3),
98994            hsla: new RegExp("hsla" + PERMISSIVE_MATCH4),
98995            hsv: new RegExp("hsv" + PERMISSIVE_MATCH3),
98996            hex3: /^([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,
98997            hex6: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/
98998        };
98999    })();
99000
99001    // `stringInputToObject`
99002    // Permissive string parsing.  Take in a number of formats, and output an object
99003    // based on detected format.  Returns `{ r, g, b }` or `{ h, s, l }` or `{ h, s, v}`
99004    function stringInputToObject(color) {
99005
99006        color = color.replace(trimLeft,'').replace(trimRight, '').toLowerCase();
99007        var named = false;
99008        if (names[color]) {
99009            color = names[color];
99010            named = true;
99011        }
99012        else if (color == 'transparent') {
99013            return { r: 0, g: 0, b: 0, a: 0, format: "name" };
99014        }
99015
99016        // Try to match string input using regular expressions.
99017        // Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360]
99018        // Just return an object and let the conversion functions handle that.
99019        // This way the result will be the same whether the tinycolor is initialized with string or object.
99020        var match;
99021        if ((match = matchers.rgb.exec(color))) {
99022            return { r: match[1], g: match[2], b: match[3] };
99023        }
99024        if ((match = matchers.rgba.exec(color))) {
99025            return { r: match[1], g: match[2], b: match[3], a: match[4] };
99026        }
99027        if ((match = matchers.hsl.exec(color))) {
99028            return { h: match[1], s: match[2], l: match[3] };
99029        }
99030        if ((match = matchers.hsla.exec(color))) {
99031            return { h: match[1], s: match[2], l: match[3], a: match[4] };
99032        }
99033        if ((match = matchers.hsv.exec(color))) {
99034            return { h: match[1], s: match[2], v: match[3] };
99035        }
99036        if ((match = matchers.hex6.exec(color))) {
99037            return {
99038                r: parseHex(match[1]),
99039                g: parseHex(match[2]),
99040                b: parseHex(match[3]),
99041                format: named ? "name" : "hex"
99042            };
99043        }
99044        if ((match = matchers.hex3.exec(color))) {
99045            return {
99046                r: parseHex(match[1] + '' + match[1]),
99047                g: parseHex(match[2] + '' + match[2]),
99048                b: parseHex(match[3] + '' + match[3]),
99049                format: named ? "name" : "hex"
99050            };
99051        }
99052
99053        return false;
99054    }
99055
99056    // Expose tinycolor to window, does not need to run in non-browser context.
99057    window.tinycolor = tinycolor;
99058
99059    })();
99060
99061
99062    $(function () {
99063        if ($.fn.spectrum.load) {
99064            $.fn.spectrum.processNativeColorInputs();
99065        }
99066    });
99067
99068})(window, jQuery);
99069
99070define("spectrum", ["jquery"], function(){});
99071
99072// SweetAlert
99073// 2014 (c) - Tristan Edwards
99074// github.com/t4t5/sweetalert
99075(function(window, document) {
99076
99077  var modalClass   = '.sweet-alert',
99078      overlayClass = '.sweet-overlay',
99079      alertTypes   = ['error', 'warning', 'info', 'success'],
99080      defaultParams = {
99081        title: '',
99082        text: '',
99083        type: null,
99084        allowOutsideClick: false,
99085        showCancelButton: false,
99086        showConfirmButton: true,
99087        closeOnConfirm: true,
99088        closeOnCancel: true,
99089        confirmButtonText: 'OK',
99090        confirmButtonClass: 'btn-primary',
99091        cancelButtonText: 'Cancel',
99092        cancelButtonClass: 'btn-default',
99093        containerClass: '',
99094        titleClass: '',
99095        textClass: '',
99096        imageUrl: null,
99097        imageSize: null,
99098        timer: null
99099      };
99100
99101
99102  /*
99103   * Manipulate DOM
99104   */
99105
99106  var getModal = function() {
99107      return document.querySelector(modalClass);
99108    },
99109    getOverlay = function() {
99110      return document.querySelector(overlayClass);
99111    },
99112    hasClass = function(elem, className) {
99113      return new RegExp(' ' + className + ' ').test(' ' + elem.className + ' ');
99114    },
99115    addClass = function(elem, className) {
99116      if (className && !hasClass(elem, className)) {
99117        elem.className += ' ' + className;
99118      }
99119    },
99120    removeClass = function(elem, className) {
99121      var newClass = ' ' + elem.className.replace(/[\t\r\n]/g, ' ') + ' ';
99122      if (hasClass(elem, className)) {
99123        while (newClass.indexOf(' ' + className + ' ') >= 0) {
99124          newClass = newClass.replace(' ' + className + ' ', ' ');
99125        }
99126        elem.className = newClass.replace(/^\s+|\s+$/g, '');
99127      }
99128    },
99129    escapeHtml = function(str) {
99130      var div = document.createElement('div');
99131      div.appendChild(document.createTextNode(str));
99132      return div.innerHTML;
99133    },
99134    _show = function(elem) {
99135      elem.style.opacity = '';
99136      elem.style.display = 'block';
99137    },
99138    show = function(elems) {
99139      if (elems && !elems.length) {
99140        return _show(elems);
99141      }
99142      for (var i = 0; i < elems.length; ++i) {
99143        _show(elems[i]);
99144      }
99145    },
99146    _hide = function(elem) {
99147      elem.style.opacity = '';
99148      elem.style.display = 'none';
99149    },
99150    hide = function(elems) {
99151      if (elems && !elems.length) {
99152        return _hide(elems);
99153      }
99154      for (var i = 0; i < elems.length; ++i) {
99155        _hide(elems[i]);
99156      }
99157    },
99158    isDescendant = function(parent, child) {
99159      var node = child.parentNode;
99160      while (node !== null) {
99161        if (node === parent) {
99162          return true;
99163        }
99164        node = node.parentNode;
99165      }
99166      return false;
99167    },
99168    getTopMargin = function(elem) {
99169      elem.style.left = '-9999px';
99170      elem.style.display = 'block';
99171
99172      var height = elem.clientHeight;
99173      var padding = parseInt(getComputedStyle(elem).getPropertyValue('padding'), 10);
99174
99175      elem.style.left = '';
99176      elem.style.display = 'none';
99177      return ('-' + parseInt(height / 2 + padding) + 'px');
99178    },
99179    fadeIn = function(elem, interval) {
99180      if(+elem.style.opacity < 1) {
99181        interval = interval || 16;
99182        elem.style.opacity = 0;
99183        elem.style.display = 'block';
99184        var last = +new Date();
99185        var tick = function() {
99186          elem.style.opacity = +elem.style.opacity + (new Date() - last) / 100;
99187          last = +new Date();
99188
99189          if (+elem.style.opacity < 1) {
99190            setTimeout(tick, interval);
99191          }
99192        };
99193        tick();
99194      }
99195    },
99196    fadeOut = function(elem, interval) {
99197      interval = interval || 16;
99198      elem.style.opacity = 1;
99199      var last = +new Date();
99200      var tick = function() {
99201        elem.style.opacity = +elem.style.opacity - (new Date() - last) / 100;
99202        last = +new Date();
99203
99204        if (+elem.style.opacity > 0) {
99205          setTimeout(tick, interval);
99206        } else {
99207          elem.style.display = 'none';
99208        }
99209      };
99210      tick();
99211    },
99212    fireClick = function(node) {
99213      // Taken from http://www.nonobtrusive.com/2011/11/29/programatically-fire-crossbrowser-click-event-with-javascript/
99214      // Then fixed for today's Chrome browser.
99215      if (MouseEvent) {
99216        // Up-to-date approach
99217        var mevt = new MouseEvent('click', {
99218          view: window,
99219          bubbles: false,
99220          cancelable: true
99221        });
99222        node.dispatchEvent(mevt);
99223      } else if ( document.createEvent ) {
99224        // Fallback
99225        var evt = document.createEvent('MouseEvents');
99226        evt.initEvent('click', false, false);
99227        node.dispatchEvent(evt);
99228      } else if( document.createEventObject ) {
99229        node.fireEvent('onclick') ;
99230      } else if (typeof node.onclick === 'function' ) {
99231        node.onclick();
99232      }
99233    },
99234    stopEventPropagation = function(e) {
99235      // In particular, make sure the space bar doesn't scroll the main window.
99236      if (typeof e.stopPropagation === 'function') {
99237        e.stopPropagation();
99238        e.preventDefault();
99239      } else if (window.event && window.event.hasOwnProperty('cancelBubble')) {
99240        window.event.cancelBubble = true;
99241      }
99242    };
99243
99244  // Remember state in cases where opening and handling a modal will fiddle with it.
99245  var previousActiveElement,
99246      previousDocumentClick,
99247      previousWindowKeyDown,
99248      lastFocusedButton;
99249
99250  /*
99251   * Add modal + overlay to DOM
99252   */
99253
99254  window.sweetAlertInitialize = function() {
99255    var sweetHTML = '<div class="sweet-overlay" tabIndex="-1"></div><div class="sweet-alert" tabIndex="-1"><div class="icon error"><span class="x-mark"><span class="line left"></span><span class="line right"></span></span></div><div class="icon warning"> <span class="body"></span> <span class="dot"></span> </div> <div class="icon info"></div> <div class="icon success"> <span class="line tip"></span> <span class="line long"></span> <div class="placeholder"></div> <div class="fix"></div> </div> <div class="icon custom"></div> <h2>Title</h2><p class="lead text-muted">Text</p><p><button class="cancel btn btn-lg" tabIndex="2">Cancel</button> <button class="confirm btn btn-lg" tabIndex="1">OK</button></p></div>',
99256        sweetWrap = document.createElement('div');
99257
99258    sweetWrap.innerHTML = sweetHTML;
99259
99260    // For readability: check sweet-alert.html
99261    document.body.appendChild(sweetWrap);
99262
99263    // For development use only!
99264    /*jQuery.ajax({
99265      url: '../lib/sweet-alert.html', // Change path depending on file location
99266      dataType: 'html'
99267    })
99268    .done(function(html) {
99269      jQuery('body').append(html);
99270    });*/
99271  }
99272
99273  /*
99274   * Global sweetAlert function
99275   */
99276
99277  window.sweetAlert = window.swal = function() {
99278    if (arguments[0] === undefined) {
99279      window.console.error('sweetAlert expects at least 1 attribute!');
99280      return false;
99281    }
99282
99283    var params = extend({}, defaultParams);
99284
99285    switch (typeof arguments[0]) {
99286
99287      case 'string':
99288        params.title = arguments[0];
99289        params.text  = arguments[1] || '';
99290        params.type  = arguments[2] || '';
99291
99292        break;
99293
99294      case 'object':
99295        if (arguments[0].title === undefined) {
99296          window.console.error('Missing "title" argument!');
99297          return false;
99298        }
99299
99300        params.title              = arguments[0].title;
99301        params.text               = arguments[0].text || defaultParams.text;
99302        params.type               = arguments[0].type || defaultParams.type;
99303        params.allowOutsideClick  = arguments[0].allowOutsideClick || defaultParams.allowOutsideClick;
99304        params.showCancelButton   = arguments[0].showCancelButton !== undefined ? arguments[0].showCancelButton : defaultParams.showCancelButton;
99305        params.showConfirmButton  = arguments[0].showConfirmButton !== undefined ? arguments[0].showConfirmButton : defaultParams.showConfirmButton;
99306        params.closeOnConfirm     = arguments[0].closeOnConfirm !== undefined ? arguments[0].closeOnConfirm : defaultParams.closeOnConfirm;
99307        params.closeOnCancel      = arguments[0].closeOnCancel !== undefined ? arguments[0].closeOnCancel : defaultParams.closeOnCancel;
99308        params.timer              = arguments[0].timer || defaultParams.timer;
99309
99310        // Show "Confirm" instead of "OK" if cancel button is visible
99311        params.confirmButtonText  = (defaultParams.showCancelButton) ? 'Confirm' : defaultParams.confirmButtonText;
99312        params.confirmButtonText  = arguments[0].confirmButtonText || defaultParams.confirmButtonText;
99313        params.confirmButtonClass = arguments[0].confirmButtonClass || (arguments[0].type ? 'btn-' + arguments[0].type : null) || defaultParams.confirmButtonClass;
99314        params.cancelButtonText   = arguments[0].cancelButtonText || defaultParams.cancelButtonText;
99315        params.cancelButtonClass  = arguments[0].cancelButtonClass || defaultParams.cancelButtonClass;
99316        params.containerClass     = arguments[0].containerClass || defaultParams.containerClass;
99317        params.titleClass         = arguments[0].titleClass || defaultParams.titleClass;
99318        params.textClass          = arguments[0].textClass || defaultParams.textClass;
99319        params.imageUrl           = arguments[0].imageUrl || defaultParams.imageUrl;
99320        params.imageSize          = arguments[0].imageSize || defaultParams.imageSize;
99321        params.doneFunction       = arguments[1] || null;
99322
99323        break;
99324
99325      default:
99326        window.console.error('Unexpected type of argument! Expected "string" or "object", got ' + typeof arguments[0]);
99327        return false;
99328
99329    }
99330
99331    setParameters(params);
99332    fixVerticalPosition();
99333    openModal();
99334
99335
99336    // Modal interactions
99337    var modal = getModal();
99338
99339    // Mouse interactions
99340    var onButtonEvent = function(e) {
99341
99342      var target = e.target || e.srcElement,
99343          targetedConfirm    = (target.className.indexOf('confirm') > -1),
99344          modalIsVisible     = hasClass(modal, 'visible'),
99345          doneFunctionExists = (params.doneFunction && modal.getAttribute('data-has-done-function') === 'true');
99346
99347      switch (e.type) {
99348        case ("click"):
99349          if (targetedConfirm && doneFunctionExists && modalIsVisible) { // Clicked "confirm"
99350
99351            params.doneFunction(true);
99352
99353            if (params.closeOnConfirm) {
99354              closeModal();
99355            }
99356          } else if (doneFunctionExists && modalIsVisible) { // Clicked "cancel"
99357
99358            // Check if callback function expects a parameter (to track cancel actions)
99359            var functionAsStr          = String(params.doneFunction).replace(/\s/g, '');
99360            var functionHandlesCancel  = functionAsStr.substring(0, 9) === "function(" && functionAsStr.substring(9, 10) !== ")";
99361
99362            if (functionHandlesCancel) {
99363              params.doneFunction(false);
99364            }
99365
99366            if (params.closeOnCancel) {
99367              closeModal();
99368            }
99369          } else {
99370            closeModal();
99371          }
99372
99373          break;
99374      }
99375    };
99376
99377    var $buttons = modal.querySelectorAll('button');
99378    for (var i = 0; i < $buttons.length; i++) {
99379      $buttons[i].onclick     = onButtonEvent;
99380    }
99381
99382    // Remember the current document.onclick event.
99383    previousDocumentClick = document.onclick;
99384    document.onclick = function(e) {
99385      var target = e.target || e.srcElement;
99386
99387      var clickedOnModal = (modal === target),
99388          clickedOnModalChild = isDescendant(modal, e.target),
99389          modalIsVisible = hasClass(modal, 'visible'),
99390          outsideClickIsAllowed = modal.getAttribute('data-allow-ouside-click') === 'true';
99391
99392      if (!clickedOnModal && !clickedOnModalChild && modalIsVisible && outsideClickIsAllowed) {
99393        closeModal();
99394      }
99395    };
99396
99397
99398    // Keyboard interactions
99399    var $okButton = modal.querySelector('button.confirm'),
99400        $cancelButton = modal.querySelector('button.cancel'),
99401        $modalButtons = modal.querySelectorAll('button:not([type=hidden])');
99402
99403
99404    function handleKeyDown(e) {
99405      var keyCode = e.keyCode || e.which;
99406
99407      if ([9,13,32,27].indexOf(keyCode) === -1) {
99408        // Don't do work on keys we don't care about.
99409        return;
99410      }
99411
99412      var $targetElement = e.target || e.srcElement;
99413
99414      var btnIndex = -1; // Find the button - note, this is a nodelist, not an array.
99415      for (var i = 0; i < $modalButtons.length; i++) {
99416        if ($targetElement === $modalButtons[i]) {
99417          btnIndex = i;
99418          break;
99419        }
99420      }
99421
99422      if (keyCode === 9) {
99423        // TAB
99424        if (btnIndex === -1) {
99425          // No button focused. Jump to the confirm button.
99426          $targetElement = $okButton;
99427        } else {
99428          // Cycle to the next button
99429          if (btnIndex === $modalButtons.length - 1) {
99430            $targetElement = $modalButtons[0];
99431          } else {
99432            $targetElement = $modalButtons[btnIndex + 1];
99433          }
99434        }
99435
99436        stopEventPropagation(e);
99437        $targetElement.focus();
99438
99439      } else {
99440        if (keyCode === 13 || keyCode === 32) {
99441            if (btnIndex === -1) {
99442              // ENTER/SPACE clicked outside of a button.
99443              $targetElement = $okButton;
99444            } else {
99445              // Do nothing - let the browser handle it.
99446              $targetElement = undefined;
99447            }
99448        } else if (keyCode === 27 && !($cancelButton.hidden || $cancelButton.style.display === 'none')) {
99449          // ESC to cancel only if there's a cancel button displayed (like the alert() window).
99450          $targetElement = $cancelButton;
99451        } else {
99452          // Fallback - let the browser handle it.
99453          $targetElement = undefined;
99454        }
99455
99456        if ($targetElement !== undefined) {
99457          fireClick($targetElement, e);
99458        }
99459      }
99460    }
99461
99462    previousWindowKeyDown = window.onkeydown;
99463    window.onkeydown = handleKeyDown;
99464
99465    function handleOnBlur(e) {
99466      var $targetElement = e.target || e.srcElement,
99467          $focusElement = e.relatedTarget,
99468          modalIsVisible = hasClass(modal, 'visible');
99469
99470      if (modalIsVisible) {
99471        var btnIndex = -1; // Find the button - note, this is a nodelist, not an array.
99472
99473        if ($focusElement !== null) {
99474          // If we picked something in the DOM to focus to, let's see if it was a button.
99475          for (var i = 0; i < $modalButtons.length; i++) {
99476            if ($focusElement === $modalButtons[i]) {
99477              btnIndex = i;
99478              break;
99479            }
99480          }
99481
99482          if (btnIndex === -1) {
99483            // Something in the dom, but not a visible button. Focus back on the button.
99484            $targetElement.focus();
99485          }
99486        } else {
99487          // Exiting the DOM (e.g. clicked in the URL bar);
99488          lastFocusedButton = $targetElement;
99489        }
99490      }
99491    }
99492
99493    $okButton.onblur = handleOnBlur;
99494    $cancelButton.onblur = handleOnBlur;
99495
99496    window.onfocus = function() {
99497      // When the user has focused away and focused back from the whole window.
99498      window.setTimeout(function() {
99499        // Put in a timeout to jump out of the event sequence. Calling focus() in the event
99500        // sequence confuses things.
99501        if (lastFocusedButton !== undefined) {
99502          lastFocusedButton.focus();
99503          lastFocusedButton = undefined;
99504        }
99505      }, 0);
99506    };
99507  };
99508
99509  /**
99510   * Set default params for each popup
99511   * @param {Object} userParams
99512   */
99513  window.swal.setDefaults = function(userParams) {
99514    if (!userParams) {
99515      throw new Error('userParams is required');
99516    }
99517    if (typeof userParams !== 'object') {
99518      throw new Error('userParams has to be a object');
99519    }
99520
99521    extend(defaultParams, userParams);
99522  };
99523
99524  /**
99525   * Closes the current modal
99526   */
99527  window.swal.close = function() {
99528    closeModal();
99529  }
99530
99531  /*
99532   * Set type, text and actions on modal
99533   */
99534
99535  function setParameters(params) {
99536    var modal = getModal();
99537
99538    var $title = modal.querySelector('h2'),
99539        $text = modal.querySelector('p'),
99540        $cancelBtn = modal.querySelector('button.cancel'),
99541        $confirmBtn = modal.querySelector('button.confirm');
99542
99543    // Title
99544    $title.innerHTML = escapeHtml(params.title).split("\n").join("<br>");
99545
99546    // Text
99547    $text.innerHTML = escapeHtml(params.text || '').split("\n").join("<br>");
99548    if (params.text) {
99549      show($text);
99550    }
99551
99552    // Icon
99553    hide(modal.querySelectorAll('.icon'));
99554    if (params.type) {
99555      var validType = false;
99556      for (var i = 0; i < alertTypes.length; i++) {
99557        if (params.type === alertTypes[i]) {
99558          validType = true;
99559          break;
99560        }
99561      }
99562      if (!validType) {
99563        window.console.error('Unknown alert type: ' + params.type);
99564        return false;
99565      }
99566      var $icon = modal.querySelector('.icon.' + params.type);
99567      show($icon);
99568
99569      // Animate icon
99570      switch (params.type) {
99571        case "success":
99572          addClass($icon, 'animate');
99573          addClass($icon.querySelector('.tip'), 'animateSuccessTip');
99574          addClass($icon.querySelector('.long'), 'animateSuccessLong');
99575          break;
99576        case "error":
99577          addClass($icon, 'animateErrorIcon');
99578          addClass($icon.querySelector('.x-mark'), 'animateXMark');
99579          break;
99580        case "warning":
99581          addClass($icon, 'pulseWarning');
99582          addClass($icon.querySelector('.body'), 'pulseWarningIns');
99583          addClass($icon.querySelector('.dot'), 'pulseWarningIns');
99584          break;
99585      }
99586
99587    }
99588
99589    // Custom image
99590    if (params.imageUrl) {
99591      var $customIcon = modal.querySelector('.icon.custom');
99592
99593      $customIcon.style.backgroundImage = 'url(' + params.imageUrl + ')';
99594      show($customIcon);
99595
99596      var _imgWidth  = 80,
99597          _imgHeight = 80;
99598
99599      if (params.imageSize) {
99600        var imgWidth  = params.imageSize.split('x')[0];
99601        var imgHeight = params.imageSize.split('x')[1];
99602
99603        if (!imgWidth || !imgHeight) {
99604          window.console.error("Parameter imageSize expects value with format WIDTHxHEIGHT, got " + params.imageSize);
99605        } else {
99606          _imgWidth  = imgWidth;
99607          _imgHeight = imgHeight;
99608
99609          $customIcon.css({
99610            'width': imgWidth + 'px',
99611            'height': imgHeight + 'px'
99612          });
99613        }
99614      }
99615      $customIcon.setAttribute('style', $customIcon.getAttribute('style') + 'width:' + _imgWidth + 'px; height:' + _imgHeight + 'px');
99616    }
99617
99618    // Cancel button
99619    modal.setAttribute('data-has-cancel-button', params.showCancelButton);
99620    if (params.showCancelButton) {
99621      $cancelBtn.style.display = 'inline-block';
99622    } else {
99623      hide($cancelBtn);
99624    }
99625    
99626    //Confirm button
99627    modal.setAttribute('data-has-confirm-button', params.showConfirmButton);
99628    if (params.showConfirmButton) {
99629      $confirmBtn.style.display = 'inline-block';
99630    } else {
99631      hide($confirmBtn);
99632    }
99633    
99634
99635    // Edit text on cancel and confirm buttons
99636    if (params.cancelButtonText) {
99637      $cancelBtn.innerHTML = escapeHtml(params.cancelButtonText);
99638    }
99639    if (params.confirmButtonText) {
99640      $confirmBtn.innerHTML = escapeHtml(params.confirmButtonText);
99641    }
99642
99643    // Reset confirm buttons to default class (Ugly fix)
99644    $confirmBtn.className = 'confirm btn btn-lg';
99645
99646    // Attach selected class to the sweet alert modal
99647    addClass(modal, params.containerClass);
99648
99649    // Set confirm button to selected class
99650    addClass($confirmBtn, params.confirmButtonClass);
99651
99652    // Set cancel button to selected class
99653    addClass($cancelBtn, params.cancelButtonClass);
99654
99655    // Set title to selected class
99656    addClass($title, params.titleClass);
99657
99658    // Set text to selected class
99659    addClass($text, params.textClass);
99660
99661    // Allow outside click?
99662    modal.setAttribute('data-allow-ouside-click', params.allowOutsideClick);
99663
99664    // Done-function
99665    var hasDoneFunction = (params.doneFunction) ? true : false;
99666    modal.setAttribute('data-has-done-function', hasDoneFunction);
99667
99668    // Close timer
99669    modal.setAttribute('data-timer', params.timer);
99670  }
99671
99672
99673  /*
99674   * Set hover, active and focus-states for buttons (source: http://www.sitepoint.com/javascript-generate-lighter-darker-color)
99675   */
99676
99677  function colorLuminance(hex, lum) {
99678    // Validate hex string
99679    hex = String(hex).replace(/[^0-9a-f]/gi, '');
99680    if (hex.length < 6) {
99681      hex = hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2];
99682    }
99683    lum = lum || 0;
99684
99685    // Convert to decimal and change luminosity
99686    var rgb = "#", c, i;
99687    for (i = 0; i < 3; i++) {
99688      c = parseInt(hex.substr(i*2,2), 16);
99689      c = Math.round(Math.min(Math.max(0, c + (c * lum)), 255)).toString(16);
99690      rgb += ("00"+c).substr(c.length);
99691    }
99692
99693    return rgb;
99694  }
99695
99696  function extend(a, b){
99697    for (var key in b) {
99698      if (b.hasOwnProperty(key)) {
99699        a[key] = b[key];
99700      }
99701    }
99702
99703    return a;
99704  }
99705
99706  function hexToRgb(hex) {
99707    var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
99708    return result ? parseInt(result[1], 16) + ', ' + parseInt(result[2], 16) + ', ' + parseInt(result[3], 16) : null;
99709  }
99710
99711  // Add box-shadow style to button (depending on its chosen bg-color)
99712  function setFocusStyle($button, bgColor) {
99713    var rgbColor = hexToRgb(bgColor);
99714    $button.style.boxShadow = '0 0 2px rgba(' + rgbColor +', 0.8), inset 0 0 0 1px rgba(0, 0, 0, 0.05)';
99715  }
99716
99717
99718  /*
99719   * Animations
99720   */
99721
99722  function openModal() {
99723    var modal = getModal();
99724    fadeIn(getOverlay(), 10);
99725    show(modal);
99726    addClass(modal, 'showSweetAlert');
99727    removeClass(modal, 'hideSweetAlert');
99728
99729    previousActiveElement = document.activeElement;
99730    var $okButton = modal.querySelector('button.confirm');
99731    $okButton.focus();
99732
99733    setTimeout(function() {
99734      addClass(modal, 'visible');
99735    }, 500);
99736
99737    var timer = modal.getAttribute('data-timer');
99738    if (timer !== "null" && timer !== "") {
99739      setTimeout(function() {
99740        closeModal();
99741      }, timer);
99742    }
99743  }
99744
99745  function closeModal() {
99746    var modal = getModal();
99747    fadeOut(getOverlay(), 5);
99748    fadeOut(modal, 5);
99749    removeClass(modal, 'showSweetAlert');
99750    addClass(modal, 'hideSweetAlert');
99751    removeClass(modal, 'visible');
99752
99753
99754    // Reset icon animations
99755
99756    var $successIcon = modal.querySelector('.icon.success');
99757    removeClass($successIcon, 'animate');
99758    removeClass($successIcon.querySelector('.tip'), 'animateSuccessTip');
99759    removeClass($successIcon.querySelector('.long'), 'animateSuccessLong');
99760
99761    var $errorIcon = modal.querySelector('.icon.error');
99762    removeClass($errorIcon, 'animateErrorIcon');
99763    removeClass($errorIcon.querySelector('.x-mark'), 'animateXMark');
99764
99765    var $warningIcon = modal.querySelector('.icon.warning');
99766    removeClass($warningIcon, 'pulseWarning');
99767    removeClass($warningIcon.querySelector('.body'), 'pulseWarningIns');
99768    removeClass($warningIcon.querySelector('.dot'), 'pulseWarningIns');
99769
99770
99771    // Reset the page to its previous state
99772    window.onkeydown = previousWindowKeyDown;
99773    document.onclick = previousDocumentClick;
99774    if (previousActiveElement) {
99775      previousActiveElement.focus();
99776    }
99777    lastFocusedButton = undefined;
99778  }
99779
99780
99781  /*
99782   * Set "margin-top"-property on modal based on its computed height
99783   */
99784
99785  function fixVerticalPosition() {
99786    var modal = getModal();
99787    modal.style.marginTop = getTopMargin(getModal());
99788  }
99789
99790
99791  /*
99792   * If library is injected after page has loaded
99793   */
99794
99795  (function () {
99796    if (document.readyState === "complete" || document.readyState === "interactive" && document.body) {
99797      sweetAlertInitialize();
99798    } else {
99799      if (document.addEventListener) {
99800        document.addEventListener('DOMContentLoaded', function handler() {
99801          document.removeEventListener('DOMContentLoaded', handler, false);
99802          sweetAlertInitialize();
99803        }, false);
99804      } else if (document.attachEvent) {
99805        document.attachEvent('onreadystatechange', function handler() {
99806          if (document.readyState === 'complete') {
99807            document.detachEvent('onreadystatechange', handler);
99808            sweetAlertInitialize();
99809          }
99810        });
99811      }
99812    }
99813  })();
99814
99815})(window, document);
99816
99817define("sweetalert", (function (global) {
99818    return function () {
99819        var ret, fn;
99820        return ret || global.swal;
99821    };
99822}(this)));
99823
99824(function(factory) {
99825	if (typeof define === 'function' && define.amd) {
99826		define('tablesorter',['jquery'], factory);
99827	} else if (typeof module === 'object' && typeof module.exports === 'object') {
99828		module.exports = factory(require('jquery'));
99829	} else {
99830		factory(jQuery);
99831	}
99832}(function($) {
99833
99834/*! TableSorter (FORK) v2.22.5 *//*
99835* Client-side table sorting with ease!
99836* @requires jQuery v1.2.6+
99837*
99838* Copyright (c) 2007 Christian Bach
99839* fork maintained by Rob Garrison
99840*
99841* Examples and docs at: http://tablesorter.com
99842* Dual licensed under the MIT and GPL licenses:
99843* http://www.opensource.org/licenses/mit-license.php
99844* http://www.gnu.org/licenses/gpl.html
99845*
99846* @type jQuery
99847* @name tablesorter (FORK)
99848* @cat Plugins/Tablesorter
99849* @author Christian Bach - [email protected]
99850* @contributor Rob Garrison - https://github.com/Mottie/tablesorter
99851*/
99852/*jshint browser:true, jquery:true, unused:false, expr: true */
99853/*global console:false */
99854;(function($){
99855	'use strict';
99856	$.extend({
99857		/*jshint supernew:true */
99858		tablesorter: new function() {
99859
99860			var ts = this;
99861
99862			ts.version = '2.22.5';
99863
99864			ts.parsers = [];
99865			ts.widgets = [];
99866			ts.defaults = {
99867
99868				// *** appearance
99869				theme            : 'default',  // adds tablesorter-{theme} to the table for styling
99870				widthFixed       : false,      // adds colgroup to fix widths of columns
99871				showProcessing   : false,      // show an indeterminate timer icon in the header when the table is sorted or filtered.
99872
99873				headerTemplate   : '{content}',// header layout template (HTML ok); {content} = innerHTML, {icon} = <i/> (class from cssIcon)
99874				onRenderTemplate : null,       // function(index, template){ return template; }, (template is a string)
99875				onRenderHeader   : null,       // function(index){}, (nothing to return)
99876
99877				// *** functionality
99878				cancelSelection  : true,       // prevent text selection in the header
99879				tabIndex         : true,       // add tabindex to header for keyboard accessibility
99880				dateFormat       : 'mmddyyyy', // other options: 'ddmmyyy' or 'yyyymmdd'
99881				sortMultiSortKey : 'shiftKey', // key used to select additional columns
99882				sortResetKey     : 'ctrlKey',  // key used to remove sorting on a column
99883				usNumberFormat   : true,       // false for German '1.234.567,89' or French '1 234 567,89'
99884				delayInit        : false,      // if false, the parsed table contents will not update until the first sort
99885				serverSideSorting: false,      // if true, server-side sorting should be performed because client-side sorting will be disabled, but the ui and events will still be used.
99886				resort           : true,       // default setting to trigger a resort after an 'update', 'addRows', 'updateCell', etc has completed
99887
99888				// *** sort options
99889				headers          : {},         // set sorter, string, empty, locked order, sortInitialOrder, filter, etc.
99890				ignoreCase       : true,       // ignore case while sorting
99891				sortForce        : null,       // column(s) first sorted; always applied
99892				sortList         : [],         // Initial sort order; applied initially; updated when manually sorted
99893				sortAppend       : null,       // column(s) sorted last; always applied
99894				sortStable       : false,      // when sorting two rows with exactly the same content, the original sort order is maintained
99895
99896				sortInitialOrder : 'asc',      // sort direction on first click
99897				sortLocaleCompare: false,      // replace equivalent character (accented characters)
99898				sortReset        : false,      // third click on the header will reset column to default - unsorted
99899				sortRestart      : false,      // restart sort to 'sortInitialOrder' when clicking on previously unsorted columns
99900
99901				emptyTo          : 'bottom',   // sort empty cell to bottom, top, none, zero, emptyMax, emptyMin
99902				stringTo         : 'max',      // sort strings in numerical column as max, min, top, bottom, zero
99903				textExtraction   : 'basic',    // text extraction method/function - function(node, table, cellIndex){}
99904				textAttribute    : 'data-text',// data-attribute that contains alternate cell text (used in default textExtraction function)
99905				textSorter       : null,       // choose overall or specific column sorter function(a, b, direction, table, columnIndex) [alt: ts.sortText]
99906				numberSorter     : null,       // choose overall numeric sorter function(a, b, direction, maxColumnValue)
99907
99908				// *** widget options
99909				widgets: [],                   // method to add widgets, e.g. widgets: ['zebra']
99910				widgetOptions    : {
99911					zebra : [ 'even', 'odd' ]    // zebra widget alternating row class names
99912				},
99913				initWidgets      : true,       // apply widgets on tablesorter initialization
99914				widgetClass     : 'widget-{name}', // table class name template to match to include a widget
99915
99916				// *** callbacks
99917				initialized      : null,       // function(table){},
99918
99919				// *** extra css class names
99920				tableClass       : '',
99921				cssAsc           : '',
99922				cssDesc          : '',
99923				cssNone          : '',
99924				cssHeader        : '',
99925				cssHeaderRow     : '',
99926				cssProcessing    : '', // processing icon applied to header during sort/filter
99927
99928				cssChildRow      : 'tablesorter-childRow', // class name indiciating that a row is to be attached to the its parent
99929				cssIcon          : 'tablesorter-icon', // if this class does not exist, the {icon} will not be added from the headerTemplate
99930				cssIconNone      : '', // class name added to the icon when there is no column sort
99931				cssIconAsc       : '', // class name added to the icon when the column has an ascending sort
99932				cssIconDesc      : '', // class name added to the icon when the column has a descending sort
99933				cssInfoBlock     : 'tablesorter-infoOnly', // don't sort tbody with this class name (only one class name allowed here!)
99934				cssNoSort        : 'tablesorter-noSort',      // class name added to element inside header;
vendor: 6,380 bytes, lines 99934-100112
99934 clicking on it won't cause a sort
99935				cssIgnoreRow     : 'tablesorter-ignoreRow',   // header row to ignore; cells within this row will not be added to c.$headers
99936
99937				// *** events
99938				pointerClick     : 'click',
99939				pointerDown      : 'mousedown',
99940				pointerUp        : 'mouseup',
99941
99942				// *** selectors
99943				selectorHeaders  : '> thead th, > thead td',
99944				selectorSort     : 'th, td',   // jQuery selector of content within selectorHeaders that is clickable to trigger a sort
99945				selectorRemove   : '.remove-me',
99946
99947				// *** advanced
99948				debug            : false,
99949
99950				// *** Internal variables
99951				headerList: [],
99952				empties: {},
99953				strings: {},
99954				parsers: []
99955
99956				// removed: widgetZebra: { css: ['even', 'odd'] }
99957
99958			};
99959
99960			// internal css classes - these will ALWAYS be added to
99961			// the table and MUST only contain one class name - fixes #381
99962			ts.css = {
99963				table      : 'tablesorter',
99964				cssHasChild: 'tablesorter-hasChildRow',
99965				childRow   : 'tablesorter-childRow',
99966				colgroup   : 'tablesorter-colgroup',
99967				header     : 'tablesorter-header',
99968				headerRow  : 'tablesorter-headerRow',
99969				headerIn   : 'tablesorter-header-inner',
99970				icon       : 'tablesorter-icon',
99971				processing : 'tablesorter-processing',
99972				sortAsc    : 'tablesorter-headerAsc',
99973				sortDesc   : 'tablesorter-headerDesc',
99974				sortNone   : 'tablesorter-headerUnSorted'
99975			};
99976
99977			// labels applied to sortable headers for accessibility (aria) support
99978			ts.language = {
99979				sortAsc  : 'Ascending sort applied, ',
99980				sortDesc : 'Descending sort applied, ',
99981				sortNone : 'No sort applied, ',
99982				nextAsc  : 'activate to apply an ascending sort',
99983				nextDesc : 'activate to apply a descending sort',
99984				nextNone : 'activate to remove the sort'
99985			};
99986
99987			// These methods can be applied on table.config instance
99988			ts.instanceMethods = {};
99989
99990			// $.isEmptyObject from jQuery v1.4
99991			function isEmptyObject(obj) {
99992				/*jshint forin: false */
99993				for (var name in obj) {
99994					return false;
99995				}
99996				return true;
99997			}
99998
99999			ts.getElementText = function(c, node, cellIndex) {
100000				if (!node) { return ''; }
100001				var te,
100002					t = c.textExtraction || '',
100003					// node could be a jquery object
100004					// http://jsperf.com/jquery-vs-instanceof-jquery/2
100005					$node = node.jquery ? node : $(node);
100006				if (typeof t === 'string') {
100007					// check data-attribute first when set to 'basic'; don't use node.innerText - it's really slow!
100008					// http://www.kellegous.com/j/2013/02/27/innertext-vs-textcontent/
100009					if ( t === 'basic' && typeof ( te = $node.attr(c.textAttribute) ) !== 'undefined' ) {
100010						return $.trim( te );
100011					}
100012					return $.trim( node.textContent || $node.text() );
100013				} else {
100014					if (typeof t === 'function') {
100015						return $.trim( t($node[0], c.table, cellIndex) );
100016					} else if (typeof (te = ts.getColumnData( c.table, t, cellIndex )) === 'function') {
100017						return $.trim( te($node[0], c.table, cellIndex) );
100018					}
100019				}
100020				// fallback
100021				return $.trim( $node[0].textContent || $node.text() );
100022			};
100023
100024			function detectParserForColumn(c, rows, rowIndex, cellIndex) {
100025				var cur, $node,
100026					i = ts.parsers.length,
100027					node = false,
100028					nodeValue = '',
100029					keepLooking = true;
100030				while (nodeValue === '' && keepLooking) {
100031					rowIndex++;
100032					if (rows[rowIndex]) {
100033						node = rows[rowIndex].cells[cellIndex];
100034						nodeValue = ts.getElementText(c, node, cellIndex);
100035						$node = $(node);
100036						if (c.debug) {
100037							console.log('Checking if value was empty on row ' + rowIndex + ', column: ' + cellIndex + ': "' + nodeValue + '"');
100038						}
100039					} else {
100040						keepLooking = false;
100041					}
100042				}
100043				while (--i >= 0) {
100044					cur = ts.parsers[i];
100045					// ignore the default text parser because it will always be true
100046					if (cur && cur.id !== 'text' && cur.is && cur.is(nodeValue, c.table, node, $node)) {
100047						return cur;
100048					}
100049				}
100050				// nothing found, return the generic parser (text)
100051				return ts.getParserById('text');
100052			}
100053
100054			// centralized function to extract/parse cell contents
100055			ts.getParsedText = function( c, cell, colIndex, txt ) {
100056				if ( typeof txt === 'undefined' ) {
100057					txt = ts.getElementText( c, cell, colIndex );
100058				}
100059				// if no parser, make sure to return the txt
100060				var val = '' + txt,
100061					parser = c.parsers[ colIndex ],
100062					extractor = c.extractors[ colIndex ];
100063				if ( parser ) {
100064					// do extract before parsing, if there is one
100065					if ( extractor && typeof extractor.format === 'function' ) {
100066						txt = extractor.format( txt, c.table, cell, colIndex );
100067					}
100068					// allow parsing if the string is empty, previously parsing would change it to zero,
100069					// in case the parser needs to extract data from the table cell attributes
100070					val = parser.id === 'no-parser' ? '' :
100071						// make sure txt is a string (extractor may have converted it)
100072						parser.format( '' + txt, c.table, cell, colIndex );
100073					if ( c.ignoreCase && typeof val === 'string' ) {
100074						val = val.toLowerCase();
100075					}
100076				}
100077				return val;
100078			};
100079
100080			function buildParserCache( c, $tbodies ) {
100081				var rows, list, l, i, h, ch, np, p, e, time, tb, len,
100082					table = c.table,
100083					j = 0,
100084					debug = {};
100085				// update table bodies in case we start with an empty table
100086				c.$tbodies = c.$table.children('tbody:not(.' + c.cssInfoBlock + ')');
100087				tb = typeof $tbodies === 'undefined' ? c.$tbodies : $tbodies;
100088				len = tb.length;
100089				if ( len === 0) {
100090					return c.debug ? console.warn('Warning: *Empty table!* Not building a parser cache') : '';
100091				} else if (c.debug) {
100092					time = new Date();
100093					console[ console.group ? 'group' : 'log' ]('Detecting parsers for each column');
100094				}
100095				list = {
100096					extractors: [],
100097					parsers: []
100098				};
100099				while (j < len) {
100100					rows = tb[j].rows;
100101					if (rows.length) {
100102						l = c.columns; // rows[j].cells.length;
100103						for (i = 0; i < l; i++) {
100104							h = c.$headerIndexed[i];
100105							// get column indexed table cell
100106							ch = ts.getColumnData( table, c.headers, i );
100107							// get column parser/extractor
100108							e = ts.getParserById( ts.getData(h, ch, 'extractor') );
100109							p = ts.getParserById( ts.getData(h, ch, 'sorter') );
100110							np = ts.getData(h, ch, 'parser') === 'false';
100111							// empty cells behaviour - keeping emptyToBottom for backwards compatibility
100112							c.empties[i] = ( ts.getData(h, ch, 'empty') || c.emptyTo || (c.emptyToBottom ? 'bottom' : 'top' ) ).toLowerCase();
100113							// text strings behaviour in numerical sorts
100114							c.strings[i] = ( ts.getData(h, ch, 'string') || c.stringTo || 'max' ).toLowerCase();
100115							if (np) {
100116								p = ts.getParserById('no-parser');
100117							}
100118							if (!e) {
100119								// For now, maybe detect someday
100120								e = false;
100121							}
100122							if (!p) {
100123								p = detectParserForColumn(c, rows, -1, i);
100124							}
100125							if (c.debug) {
100126								debug[ '(' + i + ') ' + h.text() ] = {
100127									parser : p.id,
100128									extractor : e ? e.id : 'none',
100129									string : c.strings[i],
100130									empty  : c.empties[i]
100131								};
100132							}
100133							list.parsers[i] = p;
100134							list.extractors[i] = e;
100135						}
100136					}
100137					j += (list.parsers.length) ? len : 1;
100138				}
100139				if ( c.debug ) {
100140					if ( !isEmptyObject( debug ) ) {
100141						console[ console.table ? 'table' : 'log' ]( debug );
100142					} else {
100143						console.warn( '  No parsers detected!' );
100144					}
100145					console.log( 'Completed detecting parsers' + ts.benchmark( time ) );
100146					if ( console.groupEnd ) { console.groupEnd(); }
100147				}
100148				c.parsers = list.parsers;
100149				c.extractors = list.extractors;
100150			}
100151
100152			/* utils */
100153			function buildCache(table, $tbodies) {
100154				var cc, t, v, i, j, k, $tb, $row, cols, cacheTime,
100155					totalRows, rowData, prevRowData, colMax,
100156					c = table.config,
100157					parsers = c.parsers;
100158				// update tbody variable
100159				c.$tbodies = c.$table.children('tbody:not(.' + c.cssInfoBlock + ')');
100160				$tb = typeof $tbodies === 'undefined' ? c.$tbodies : $tbodies,
100161				c.cache = {};
100162				c.totalRows = 0;
100163				// if no parsers found, return - it's an empty table.
100164				if (!parsers) {
100165					return c.debug ? console.warn('Warning: *Empty table!* Not building a cache') : '';
100166				}
100167				if (c.debug) {
100168					cacheTime = new Date();
100169				}
100170				// processing icon
100171				if (c.showProcessing) {
100172					ts.isProcessing(table, true);
100173				}
100174				for (k = 0; k < $tb.length; k++) {
100175					colMax = []; // column max value per tbody
100176					cc = c.cache[k] = {
100177						normalized: [] // array of normalized row data; last entry contains 'rowData' above
100178						// colMax: #   // added at the end
100179					};
100180
100181					totalRows = ($tb[k] && $tb[k].rows.length) || 0;
100182					for (i = 0; i < totalRows; ++i) {
100183						rowData = {
100184							// order: original row order #
100185							// $row : jQuery Object[]
100186							child: [], // child row text (filter widget)
100187							raw: []    // original row text
100188						};
100189						/** Add the table data to main data array */
100190						$row = $( $tb[ k ].rows[ i ] );
100191						cols = [];
100192						// if this is a child row, add it to the last row's children and continue to the next row
100193						// ignore child row class, if it is the first row
100194						if ( $row.hasClass( c.cssChildRow ) && i !== 0 ) {
100195							t = cc.normalized.length - 1;
100196							prevRowData = cc.normalized[ t ][ c.columns ];
100197							prevRowData.$row = prevRowData.$row.add( $row );
100198							// add 'hasChild' class name to parent row
100199							if ( !$row.prev().hasClass( c.cssChildRow ) ) {
100200								$row.prev().addClass( ts.css.cssHasChild );
100201							}
100202							// save child row content (un-parsed!)
100203							v = $row.children( 'th, td' );
100204							t = prevRowData.child.length;
100205							prevRowData.child[ t ] = [];
100206							// child row content does not account for colspans/rowspans; so indexing may be off
100207							for ( j = 0; j < c.columns; j++ ) {
100208								prevRowData.child[ t ][ j ] = ts.getParsedText( c, v[ j ], j );
100209							}
100210							// go to the next for loop
100211							continue;
100212						}
100213						rowData.$row = $row;
100214						rowData.order = i; // add original row position to rowCache
100215						for ( j = 0; j < c.columns; ++j ) {
100216							if (typeof parsers[ j ] === 'undefined') {
100217								if ( c.debug ) {
100218									console.warn( 'No parser found for cell:', $row[ 0 ].cells[ j ], 'does it have a header?' );
100219								}
100220								continue;
100221							}
100222							t = ts.getElementText( c, $row[ 0 ].cells[j], j );
100223							rowData.raw.push( t ); // save original row text
100224							v = ts.getParsedText( c, $row[ 0 ].cells[ j ], j, t );
100225							cols.push( v );
100226							if ( ( parsers[ j ].type || '' ).toLowerCase() === 'numeric' ) {
100227								// determine column max value (ignore sign)
100228								colMax[ j ] = Math.max( Math.abs( v ) || 0, colMax[ j ] || 0 );
100229							}
100230						}
100231						// ensure rowData is always in the same location (after the last column)
100232						cols[ c.columns ] = rowData;
100233						cc.normalized.push( cols );
100234					}
100235					cc.colMax = colMax;
100236					// total up rows, not including child rows
100237					c.totalRows += cc.normalized.length;
100238
100239				}
100240				if ( c.showProcessing ) {
100241					ts.isProcessing( table ); // remove processing icon
100242				}
100243				if ( c.debug ) {
100244					console.log( 'Building cache for ' + totalRows + ' rows' + ts.benchmark( cacheTime ) );
100245				}
100246			}
100247
100248			// init flag (true) used by pager plugin to prevent widget application
100249			function appendToTable(table, init) {
100250				var c = table.config,
100251					wo = c.widgetOptions,
100252					$tbodies = c.$tbodies,
100253					rows = [],
100254					cc = c.cache,
100255					n, totalRows, $bk, $tb,
100256					i, k, appendTime;
100257				// empty table - fixes #206/#346
100258				if (isEmptyObject(cc)) {
100259					// run pager appender in case the table was just emptied
100260					return c.appender ? c.appender(table, rows) :
100261						table.isUpdating ? c.$table.trigger('updateComplete', table) : ''; // Fixes #532
100262				}
100263				if (c.debug) {
100264					appendTime = new Date();
100265				}
100266				for (k = 0; k < $tbodies.length; k++) {
100267					$bk = $tbodies.eq(k);
100268					if ($bk.length) {
100269						// get tbody
100270						$tb = ts.processTbody(table, $bk, true);
100271						n = cc[k].normalized;
100272						totalRows = n.length;
100273						for (i = 0; i < totalRows; i++) {
100274							rows.push(n[i][c.columns].$row);
100275							// removeRows used by the pager plugin; don't render if using ajax - fixes #411
100276							if (!c.appender || (c.pager && (!c.pager.removeRows || !wo.pager_removeRows) && !c.pager.ajax)) {
100277								$tb.append(n[i][c.columns].$row);
100278							}
100279						}
100280						// restore tbody
100281						ts.processTbody(table, $tb, false);
100282					}
100283				}
100284				if (c.appender) {
100285					c.appender(table, rows);
100286				}
100287				if (c.debug) {
100288					console.log( 'Rebuilt table' + ts.benchmark(appendTime) );
100289				}
100290				// apply table widgets; but not before ajax completes
100291				if (!init && !c.appender) { ts.applyWidget(table); }
100292				if (table.isUpdating) {
100293					c.$table.trigger('updateComplete', table);
100294				}
100295			}
100296
100297			function formatSortingOrder(v) {
100298				// look for 'd' in 'desc' order; return true
100299				return (/^d/i.test(v) || v === 1);
100300			}
100301
100302			function buildHeaders(table) {
100303				var ch, $t, h, i, t, lock, time, indx,
100304					c = table.config;
100305				c.headerList = [];
100306				c.headerContent = [];
100307				if (c.debug) {
100308					time = new Date();
100309				}
100310				// children tr in tfoot - see issue #196 & #547
100311				c.columns = ts.computeColumnIndex( c.$table.children('thead, tfoot').children('tr') );
100312				// add icon if cssIcon option exists
100313				i = c.cssIcon ? '<i class="' + ( c.cssIcon === ts.css.icon ? ts.css.icon : c.cssIcon + ' ' + ts.css.icon ) + '"></i>' : '';
100314				// redefine c.$headers here in case of an updateAll that replaces or adds an entire header cell - see #683
100315				c.$headers = $( $.map( $(table).find(c.selectorHeaders), function(elem, index) {
100316					$t = $(elem);
100317					// ignore cell (don't add it to c.$headers) if row has ignoreRow class
100318					if ($t.parent().hasClass(c.cssIgnoreRow)) { return; }
100319					// make sure to get header cell & not column indexed cell
100320					ch = ts.getColumnData( table, c.headers, index, true );
100321					// save original header content
100322					c.headerContent[index] = $t.html();
100323					// if headerTemplate is empty, don't reformat the header cell
100324					if ( c.headerTemplate !== '' && !$t.find('.' + ts.css.headerIn).length ) {
100325						// set up header template
100326						t = c.headerTemplate.replace(/\{content\}/g, $t.html()).replace(/\{icon\}/g, $t.find('.' + ts.css.icon).length ? '' : i);
100327						if (c.onRenderTemplate) {
100328							h = c.onRenderTemplate.apply( $t, [ index, t ] );
100329							if (h && typeof h === 'string') { t = h; } // only change t if something is returned
100330						}
100331						$t.html('<div class="' + ts.css.headerIn + '">' + t + '</div>'); // faster than wrapInner
100332					}
100333					if (c.onRenderHeader) { c.onRenderHeader.apply( $t, [ index, c, c.$table ] ); }
100334					// *** remove this.column value if no conflicts found
100335					elem.column = parseInt( $t.attr('data-column'), 10);
100336					elem.order = formatSortingOrder( ts.getData( $t, ch, 'sortInitialOrder' ) || c.sortInitialOrder ) ?
100337						[ 1, 0, 2 ] : // desc, asc, unsorted
100338						[ 0, 1, 2 ];  // asc, desc, unsorted
100339					elem.count = -1; // set to -1 because clicking on the header automatically adds one
100340					elem.lockedOrder = false;
100341					lock = ts.getData($t, ch, 'lockedOrder') || false;
100342					if (typeof lock !== 'undefined' && lock !== false) {
100343						elem.order = elem.lockedOrder = formatSortingOrder(lock) ? [ 1, 1, 1 ] : [ 0, 0, 0 ];
100344					}
100345					$t.addClass(ts.css.header + ' ' + c.cssHeader);
100346					// add cell to headerList
100347					c.headerList[index] = elem;
100348					// add to parent in case there are multiple rows
100349					$t.parent().addClass(ts.css.headerRow + ' ' + c.cssHeaderRow).attr('role', 'row');
100350					// allow keyboard cursor to focus on element
100351					if (c.tabIndex) { $t.attr('tabindex', 0); }
100352					return elem;
100353				}));
100354				// cache headers per column
100355				c.$headerIndexed = [];
100356				for (indx = 0; indx < c.columns; indx++) {
100357					$t = c.$headers.filter('[data-column="' + indx + '"]');
100358					// target sortable column cells, unless there are none, then use non-sortable cells
100359					// .last() added in jQuery 1.4; use .filter(':last') to maintain compatibility with jQuery v1.2.6
100360					c.$headerIndexed[indx] = $t.not('.sorter-false').length ? $t.not('.sorter-false').filter(':last') : $t.filter(':last');
100361				}
100362				$(table).find(c.selectorHeaders).attr({
100363					scope: 'col',
100364					role : 'columnheader'
100365				});
100366				// enable/disable sorting
100367				updateHeader(table);
100368				if (c.debug) {
100369					console.log( 'Built headers:' + ts.benchmark( time ) );
100370					console.log( c.$headers );
100371				}
100372			}
100373
100374			function commonUpdate(table, resort, callback) {
100375				var c = table.config;
100376				// remove rows/elements before update
100377				c.$table.find(c.selectorRemove).remove();
100378				// rebuild parsers
100379				buildParserCache(c);
100380				// rebuild the cache map
100381				buildCache(table);
100382				checkResort(c, resort, callback);
100383			}
100384
100385			function updateHeader(table) {
100386				var index, s, $th, col,
100387					c = table.config,
100388					len = c.$headers.length;
100389				for ( index = 0; index < len; index++ ) {
100390					$th = c.$headers.eq( index );
100391					col = ts.getColumnData( table, c.headers, index, true );
100392					// add 'sorter-false' class if 'parser-false' is set
100393					s = ts.getData( $th, col, 'sorter' ) === 'false' || ts.getData( $th, col, 'parser' ) === 'false';
100394					$th[0].sortDisabled = s;
100395					$th[ s ? 'addClass' : 'removeClass' ]('sorter-false').attr('aria-disabled', '' + s);
100396					// aria-controls - requires table ID
100397					if (table.id) {
100398						if (s) {
100399							$th.removeAttr('aria-controls');
100400						} else {
100401							$th.attr('aria-controls', table.id);
100402						}
100403					}
100404				}
100405			}
100406
100407			function setHeadersCss(table) {
100408				var f, h, i, j, $headers, $h, nextSort, txt,
100409					c = table.config,
100410					list = c.sortList,
100411					len = list.length,
100412					none = ts.css.sortNone + ' ' + c.cssNone,
100413					css = [ ts.css.sortAsc + ' ' + c.cssAsc, ts.css.sortDesc + ' ' + c.cssDesc ],
100414					cssIcon = [ c.cssIconAsc, c.cssIconDesc, c.cssIconNone ],
100415					aria = [ 'ascending', 'descending' ],
100416					// find the footer
100417					$t = $(table).find('tfoot tr').children()
100418						.add( $( c.namespace + '_extra_headers' ) )
100419						.removeClass( css.join( ' ' ) );
100420				// remove all header information
100421				c.$headers
100422					.removeClass(css.join(' '))
100423					.addClass(none).attr('aria-sort', 'none')
100424					.find('.' + ts.css.icon)
100425					.removeClass(cssIcon.join(' '))
100426					.addClass(cssIcon[2]);
100427				for (i = 0; i < len; i++) {
100428					// direction = 2 means reset!
100429					if (list[i][1] !== 2) {
100430						// multicolumn sorting updating - choose the :last in case there are nested columns
100431						f = c.$headers.not('.sorter-false').filter('[data-column="' + list[i][0] + '"]' + (len === 1 ? ':last' : '') );
100432						if (f.length) {
100433							for (j = 0; j < f.length; j++) {
100434								if (!f[j].sortDisabled) {
100435									f.eq(j)
100436										.removeClass(none)
100437										.addClass(css[list[i][1]])
100438										.attr('aria-sort', aria[list[i][1]])
100439										.find('.' + ts.css.icon)
100440										.removeClass(cssIcon[2])
100441										.addClass(cssIcon[list[i][1]]);
100442								}
100443							}
100444							// add sorted class to footer & extra headers, if they exist
100445							if ($t.length) {
100446								$t.filter('[data-column="' + list[i][0] + '"]').removeClass(none).addClass(css[list[i][1]]);
100447							}
100448						}
100449					}
100450				}
100451				// add verbose aria labels
100452				len = c.$headers.length;
100453				$headers = c.$headers.not('.sorter-false');
100454				for ( i = 0; i < len; i++ ) {
100455					$h = $headers.eq( i );
100456					if ( $h.length ) {
100457						h = $headers[ i ];
100458						nextSort = h.order[ ( h.count + 1 ) % ( c.sortReset ? 3 : 2 ) ],
100459						txt = $.trim( $h.text() ) + ': ' +
100460							ts.language[ $h.hasClass( ts.css.sortAsc ) ? 'sortAsc' : $h.hasClass( ts.css.sortDesc ) ? 'sortDesc' : 'sortNone' ] +
100461							ts.language[ nextSort === 0 ? 'nextAsc' : nextSort === 1 ? 'nextDesc' : 'nextNone' ];
100462						$h.attr( 'aria-label', txt );
100463					}
100464				}
100465			}
100466
100467			function updateHeaderSortCount( table, list ) {
100468				var col, dir, group, header, indx, primary, temp, val,
100469					c = table.config,
100470					sortList = list || c.sortList,
100471					len = sortList.length;
100472				c.sortList = [];
100473				for (indx = 0; indx < len; indx++) {
100474					val = sortList[indx];
100475					// ensure all sortList values are numeric - fixes #127
100476					col = parseInt(val[0], 10);
100477					// prevents error if sorton array is wrong
100478					if ( col < c.columns && c.$headerIndexed[col] ) {
100479						// make sure header exists
100480						header = c.$headerIndexed[col][0];
100481						// o.count = o.count + 1;
100482						dir = ('' + val[1]).match(/^(1|d|s|o|n)/);
100483						dir = dir ? dir[0] : '';
100484						// 0/(a)sc (default), 1/(d)esc, (s)ame, (o)pposite, (n)ext
100485						switch (dir) {
100486							case '1': case 'd': // descending
100487								dir = 1;
100488								break;
100489							case 's': // same direction (as primary column)
100490								// if primary sort is set to 's', make it ascending
100491								dir = primary || 0;
100492								break;
100493							case 'o':
100494								temp = header.order[(primary || 0) % (c.sortReset ? 3 : 2)];
100495								// opposite of primary column; but resets if primary resets
100496								dir = temp === 0 ? 1 : temp === 1 ? 0 : 2;
100497								break;
100498							case 'n':
100499								header.count = header.count + 1;
100500								dir = header.order[(header.count) % (c.sortReset ? 3 : 2)];
100501								break;
100502							default: // ascending
100503								dir = 0;
100504								break;
100505						}
100506						primary = indx === 0 ? dir : primary;
100507						group = [ col, parseInt(dir, 10) || 0 ];
100508						c.sortList.push(group);
100509						dir = $.inArray(group[1], header.order); // fixes issue #167
100510						header.count = dir >= 0 ? dir : group[1] % (c.sortReset ? 3 : 2);
100511					}
100512				}
100513			}
100514
100515			function getCachedSortType(parsers, i) {
100516				return (parsers && parsers[i]) ? parsers[i].type || '' : '';
100517			}
100518
100519			function initSort(table, cell, event){
100520				if (table.isUpdating) {
100521					// let any updates complete before initializing a sort
100522					return setTimeout(function(){ initSort(table, cell, event); }, 50);
100523				}
100524				var arry, indx, i, col, order, s, $header,
100525					c = table.config,
100526					key = !event[c.sortMultiSortKey],
100527					$table = c.$table,
100528					len = c.$headers.length;
100529				// Only call sortStart if sorting is enabled
100530				$table.trigger('sortStart', table);
100531				// get current column sort order
100532				cell.count = event[c.sortResetKey] ? 2 : (cell.count + 1) % (c.sortReset ? 3 : 2);
100533				// reset all sorts on non-current column - issue #30
100534				if (c.sortRestart) {
100535					indx = cell;
100536					for ( i = 0; i < len; i++ ) {
100537						$header = c.$headers.eq( i );
100538						// only reset counts on columns that weren't just clicked on and if not included in a multisort
100539						if ( $header[0] !== indx && ( key || !$header.is('.' + ts.css.sortDe
100539sc + ',.' + ts.css.sortAsc) ) ) {
100540							$header[0].count = -1;
100541						}
100542					}
100543				}
100544				// get current column index
100545				indx = parseInt( $(cell).attr('data-column'), 10 );
100546				// user only wants to sort on one column
100547				if (key) {
100548					// flush the sort list
100549					c.sortList = [];
100550					if (c.sortForce !== null) {
100551						arry = c.sortForce;
100552						for (col = 0; col < arry.length; col++) {
100553							if (arry[col][0] !== indx) {
100554								c.sortList.push(arry[col]);
100555							}
100556						}
100557					}
100558					// add column to sort list
100559					order = cell.order[cell.count];
100560					if (order < 2) {
100561						c.sortList.push([ indx, order ]);
100562						// add other columns if header spans across multiple
100563						if (cell.colSpan > 1) {
100564							for (col = 1; col < cell.colSpan; col++) {
100565								c.sortList.push([ indx + col, order ]);
100566							}
100567						}
100568					}
100569					// multi column sorting
100570				} else {
100571					// get rid of the sortAppend before adding more - fixes issue #115 & #523
100572					if (c.sortAppend && c.sortList.length > 1) {
100573						for (col = 0; col < c.sortAppend.length; col++) {
100574							s = ts.isValueInArray(c.sortAppend[col][0], c.sortList);
100575							if (s >= 0) {
100576								c.sortList.splice(s, 1);
100577							}
100578						}
100579					}
100580					// the user has clicked on an already sorted column
100581					if (ts.isValueInArray(indx, c.sortList) >= 0) {
100582						// reverse the sorting direction
100583						for (col = 0; col < c.sortList.length; col++) {
100584							s = c.sortList[col];
100585							order = c.$headerIndexed[ s[0] ][0];
100586							if (s[0] === indx) {
100587								// order.count seems to be incorrect when compared to cell.count
100588								s[1] = order.order[cell.count];
100589								if (s[1] === 2) {
100590									c.sortList.splice(col, 1);
100591									order.count = -1;
100592								}
100593							}
100594						}
100595					} else {
100596						// add column to sort list array
100597						order = cell.order[cell.count];
100598						if (order < 2) {
100599							c.sortList.push([ indx, order ]);
100600							// add other columns if header spans across multiple
100601							if (cell.colSpan > 1) {
100602								for (col = 1; col < cell.colSpan; col++) {
100603									c.sortList.push([ indx + col, order ]);
100604								}
100605							}
100606						}
100607					}
100608				}
100609				if (c.sortAppend !== null) {
100610					arry = c.sortAppend;
100611					for (col = 0; col < arry.length; col++) {
100612						if (arry[col][0] !== indx) {
100613							c.sortList.push(arry[col]);
100614						}
100615					}
100616				}
100617				// sortBegin event triggered immediately before the sort
100618				$table.trigger('sortBegin', table);
100619				// setTimeout needed so the processing icon shows up
100620				setTimeout(function(){
100621					// set css for headers
100622					setHeadersCss(table);
100623					multisort(table);
100624					appendToTable(table);
100625					$table.trigger('sortEnd', table);
100626				}, 1);
100627			}
100628
100629			// sort multiple columns
100630			function multisort(table) { /*jshint loopfunc:true */
100631				var i, k, num, col, sortTime, colMax,
100632					rows, order, sort, x, y,
100633					dir = 0,
100634					c = table.config,
100635					cts = c.textSorter || '',
100636					sortList = c.sortList,
100637					l = sortList.length,
100638					bl = c.$tbodies.length;
100639				if (c.serverSideSorting || isEmptyObject(c.cache)) { // empty table - fixes #206/#346
100640					return;
100641				}
100642				if (c.debug) { sortTime = new Date(); }
100643				for (k = 0; k < bl; k++) {
100644					colMax = c.cache[k].colMax;
100645					rows = c.cache[k].normalized;
100646
100647					rows.sort(function(a, b) {
100648						// rows is undefined here in IE, so don't use it!
100649						for (i = 0; i < l; i++) {
100650							col = sortList[i][0];
100651							order = sortList[i][1];
100652							// sort direction, true = asc, false = desc
100653							dir = order === 0;
100654
100655							if (c.sortStable && a[col] === b[col] && l === 1) {
100656								return a[c.columns].order - b[c.columns].order;
100657							}
100658
100659							// fallback to natural sort since it is more robust
100660							num = /n/i.test(getCachedSortType(c.parsers, col));
100661							if (num && c.strings[col]) {
100662								// sort strings in numerical columns
100663								if (typeof (c.string[c.strings[col]]) === 'boolean') {
100664									num = (dir ? 1 : -1) * (c.string[c.strings[col]] ? -1 : 1);
100665								} else {
100666									num = (c.strings[col]) ? c.string[c.strings[col]] || 0 : 0;
100667								}
100668								// fall back to built-in numeric sort
100669								// var sort = $.tablesorter['sort' + s]( a[c], b[c], dir, colMax[c], table);
100670								sort = c.numberSorter ? c.numberSorter(a[col], b[col], dir, colMax[col], table) :
100671									ts[ 'sortNumeric' + (dir ? 'Asc' : 'Desc') ](a[col], b[col], num, colMax[col], col, table);
100672							} else {
100673								// set a & b depending on sort direction
100674								x = dir ? a : b;
100675								y = dir ? b : a;
100676								// text sort function
100677								if (typeof cts === 'function') {
100678									// custom OVERALL text sorter
100679									sort = cts(x[col], y[col], dir, col, table);
100680								} else if (typeof cts === 'object' && cts.hasOwnProperty(col)) {
100681									// custom text sorter for a SPECIFIC COLUMN
100682									sort = cts[col](x[col], y[col], dir, col, table);
100683								} else {
100684									// fall back to natural sort
100685									sort = ts[ 'sortNatural' + (dir ? 'Asc' : 'Desc') ](a[col], b[col], col, table, c);
100686								}
100687							}
100688							if (sort) { return sort; }
100689						}
100690						return a[c.columns].order - b[c.columns].order;
100691					});
100692				}
100693				if (c.debug) {
100694					console.log( 'Sorting on ' + sortList.toString() + ' and dir ' + order + ' time' + ts.benchmark(sortTime) );
100695				}
100696			}
100697
100698			function resortComplete(c, callback){
100699				if (c.table.isUpdating) {
100700					c.$table.trigger('updateComplete', c.table);
100701				}
100702				if ($.isFunction(callback)) {
100703					callback(c.table);
100704				}
100705			}
100706
100707			function checkResort(c, resort, callback) {
100708				var sl = $.isArray(resort) ? resort : c.sortList,
100709					// if no resort parameter is passed, fallback to config.resort (true by default)
100710					resrt = typeof resort === 'undefined' ? c.resort : resort;
100711				// don't try to resort if the table is still processing
100712				// this will catch spamming of the updateCell method
100713				if (resrt !== false && !c.serverSideSorting && !c.table.isProcessing) {
100714					if (sl.length) {
100715						c.$table.trigger('sorton', [ sl, function(){
100716							resortComplete(c, callback);
100717						}, true ]);
100718					} else {
100719						c.$table.trigger('sortReset', [ function(){
100720							resortComplete(c, callback);
100721							ts.applyWidget(c.table, false);
100722						} ]);
100723					}
100724				} else {
100725					resortComplete(c, callback);
100726					ts.applyWidget(c.table, false);
100727				}
100728			}
100729
100730			function bindMethods(table){
100731				var c = table.config,
100732					$table = c.$table,
100733					events = ('sortReset update updateRows updateCell updateAll addRows updateComplete sorton appendCache ' +
100734						'updateCache applyWidgetId applyWidgets refreshWidgets destroy mouseup mouseleave ').split(' ')
100735						.join(c.namespace + ' ');
100736				// apply easy methods that trigger bound events
100737				$table
100738				.unbind( events.replace(/\s+/g, ' ') )
100739				.bind('sortReset' + c.namespace, function(e, callback){
100740					e.stopPropagation();
100741					c.sortList = [];
100742					setHeadersCss(table);
100743					multisort(table);
100744					appendToTable(table);
100745					if ($.isFunction(callback)) {
100746						callback(table);
100747					}
100748				})
100749				.bind('updateAll' + c.namespace, function(e, resort, callback){
100750					e.stopPropagation();
100751					table.isUpdating = true;
100752					ts.refreshWidgets(table, true, true);
100753					buildHeaders(table);
100754					ts.bindEvents(table, c.$headers, true);
100755					bindMethods(table);
100756					commonUpdate(table, resort, callback);
100757				})
100758				.bind('update' + c.namespace + ' updateRows' + c.namespace, function(e, resort, callback) {
100759					e.stopPropagation();
100760					table.isUpdating = true;
100761					// update sorting (if enabled/disabled)
100762					updateHeader(table);
100763					commonUpdate(table, resort, callback);
100764				})
100765				.bind('updateCell' + c.namespace, function(e, cell, resort, callback) {
100766					e.stopPropagation();
100767					table.isUpdating = true;
100768					$table.find(c.selectorRemove).remove();
100769					// get position from the dom
100770					var t, row, icell, cache,
100771					$tb = c.$tbodies,
100772					$cell = $(cell),
100773					// update cache - format: function(s, table, cell, cellIndex)
100774					// no closest in jQuery v1.2.6 - tbdy = $tb.index( $(cell).closest('tbody') ),$row = $(cell).closest('tr');
100775					tbdy = $tb.index( $.fn.closest ? $cell.closest('tbody') : $cell.parents('tbody').filter(':first') ),
100776					tbcache = c.cache[ tbdy ],
100777					$row = $.fn.closest ? $cell.closest('tr') : $cell.parents('tr').filter(':first');
100778					cell = $cell[0]; // in case cell is a jQuery object
100779					// tbody may not exist if update is initialized while tbody is removed for processing
100780					if ($tb.length && tbdy >= 0) {
100781						row = $tb.eq( tbdy ).find( 'tr' ).index( $row );
100782						cache = tbcache.normalized[ row ];
100783						icell = $cell.index();
100784						t = ts.getParsedText( c, cell, icell );
100785						cache[ icell ] = t;
100786						cache[ c.columns ].$row = $row;
100787						if ( (c.parsers[icell].type || '').toLowerCase() === 'numeric' ) {
100788							// update column max value (ignore sign)
100789							tbcache.colMax[icell] = Math.max(Math.abs(t) || 0, tbcache.colMax[icell] || 0);
100790						}
100791						t = resort !== 'undefined' ? resort : c.resort;
100792						if (t !== false) {
100793							// widgets will be reapplied
100794							checkResort(c, t, callback);
100795						} else {
100796							// don't reapply widgets is resort is false, just in case it causes
100797							// problems with element focus
100798							if ($.isFunction(callback)) {
100799								callback(table);
100800							}
100801							c.$table.trigger('updateComplete', c.table);
100802						}
100803					}
100804				})
100805				.bind('addRows' + c.namespace, function(e, $row, resort, callback) {
100806					e.stopPropagation();
100807					table.isUpdating = true;
100808					if (isEmptyObject(c.cache)) {
100809						// empty table, do an update instead - fixes #450
100810						updateHeader(table);
100811						commonUpdate(table, resort, callback);
100812					} else {
100813						$row = $($row).attr('role', 'row'); // make sure we're using a jQuery object
100814						var i, j, l, rowData, cells,
100815						rows = $row.filter('tr').length,
100816						tbdy = c.$tbodies.index( $row.parents('tbody').filter(':first') );
100817						// fixes adding rows to an empty table - see issue #179
100818						if (!(c.parsers && c.parsers.length)) {
100819							buildParserCache(c);
100820						}
100821						// add each row
100822						for (i = 0; i < rows; i++) {
100823							l = $row[i].cells.length;
100824							cells = [];
100825							rowData = {
100826								child: [],
100827								$row : $row.eq(i),
100828								order: c.cache[tbdy].normalized.length
100829							};
100830							// add each cell
100831							for (j = 0; j < l; j++) {
100832								cells[j] = ts.getParsedText( c, $row[i].cells[j], j );
100833								if ((c.parsers[j].type || '').toLowerCase() === 'numeric') {
100834									// update column max value (ignore sign)
100835									c.cache[tbdy].colMax[j] = Math.max(Math.abs(cells[j]) || 0, c.cache[tbdy].colMax[j] || 0);
100836								}
100837							}
100838							// add the row data to the end
100839							cells.push(rowData);
100840							// update cache
100841							c.cache[tbdy].normalized.push(cells);
100842						}
100843						// resort using current settings
100844						checkResort(c, resort, callback);
100845					}
100846				})
100847				.bind('updateComplete' + c.namespace, function(){
100848					table.isUpdating = false;
100849				})
100850				.bind('sorton' + c.namespace, function(e, list, callback, init) {
100851					var c = table.config;
100852					e.stopPropagation();
100853					$table.trigger('sortStart', this);
100854					// update header count index
100855					updateHeaderSortCount(table, list);
100856					// set css for headers
100857					setHeadersCss(table);
100858					// fixes #346
100859					if (c.delayInit && isEmptyObject(c.cache)) { buildCache(table); }
100860					$table.trigger('sortBegin', this);
100861					// sort the table and append it to the dom
100862					multisort(table);
100863					appendToTable(table, init);
100864					$table.trigger('sortEnd', this);
100865					ts.applyWidget(table);
100866					if ($.isFunction(callback)) {
100867						callback(table);
100868					}
100869				})
100870				.bind('appendCache' + c.namespace, function(e, callback, init) {
100871					e.stopPropagation();
100872					appendToTable(table, init);
100873					if ($.isFunction(callback)) {
100874						callback(table);
100875					}
100876				})
100877				// $tbodies variable is used by the tbody sorting widget
100878				.bind('updateCache' + c.namespace, function(e, callback, $tbodies){
100879					// rebuild parsers
100880					if (!(c.parsers && c.parsers.length)) {
100881						buildParserCache(c, $tbodies);
100882					}
100883					// rebuild the cache map
100884					buildCache(table, $tbodies);
100885					if ($.isFunction(callback)) {
100886						callback(table);
100887					}
100888				})
100889				.bind('applyWidgetId' + c.namespace, function(e, id) {
100890					e.stopPropagation();
100891					ts.getWidgetById(id).format(table, c, c.widgetOptions);
100892				})
100893				.bind('applyWidgets' + c.namespace, function(e, init) {
100894					e.stopPropagation();
100895					// apply widgets
100896					ts.applyWidget(table, init);
100897				})
100898				.bind('refreshWidgets' + c.namespace, function(e, all, dontapply){
100899					e.stopPropagation();
100900					ts.refreshWidgets(table, all, dontapply);
100901				})
100902				.bind('destroy' + c.namespace, function(e, c, cb){
100903					e.stopPropagation();
100904					ts.destroy(table, c, cb);
100905				})
100906				.bind('resetToLoadState' + c.namespace, function(){
100907					// remove all widgets
100908					ts.removeWidget(table, true, false);
100909					// restore original settings; this clears out current settings, but does not clear
100910					// values saved to storage.
100911					c = $.extend(true, ts.defaults, c.originalSettings);
100912					table.hasInitialized = false;
100913					// setup the entire table again
100914					ts.setup( table, c );
100915				});
100916			}
100917
100918			/* public methods */
100919			ts.construct = function(settings) {
100920				return this.each(function() {
100921					var table = this,
100922					// merge & extend config options
100923					c = $.extend(true, {}, ts.defaults, settings, ts.instanceMethods);
100924					// save initial settings
100925					c.originalSettings = settings;
100926					// create a table from data (build table widget)
100927					if (!table.hasInitialized && ts.buildTable && this.nodeName !== 'TABLE') {
100928						// return the table (in case the original target is the table's container)
100929						ts.buildTable(table, c);
100930					} else {
100931						ts.setup(table, c);
100932					}
100933				});
100934			};
100935
100936			ts.setup = function(table, c) {
100937				// if no thead or tbody, or tablesorter is already present, quit
100938				if (!table || !table.tHead || table.tBodies.length === 0 || table.hasInitialized === true) {
100939					if ( c.debug ) {
100940						if ( table.hasInitialized ) {
100941							console.warn( 'Stopping initialization. Tablesorter has already been initialized' );
100942						} else {
100943							console.error( 'Stopping initialization! No table, thead or tbody' );
100944						}
100945					}
100946					return;
100947				}
100948
100949				var k = '',
100950					$table = $(table),
100951					m = $.metadata;
100952				// initialization flag
100953				table.hasInitialized = false;
100954				// table is being processed flag
100955				table.isProcessing = true;
100956				// make sure to store the config object
100957				table.config = c;
100958				// save the settings where they read
100959				$.data(table, 'tablesorter', c);
100960				if (c.debug) {
100961					console[ console.group ? 'group' : 'log' ]( 'Initializing tablesorter' );
100962					$.data( table, 'startoveralltimer', new Date());
100963				}
100964
100965				// removing this in version 3 (only supports jQuery 1.7+)
100966				c.supportsDataObject = (function(version) {
100967					version[0] = parseInt(version[0], 10);
100968					return (version[0] > 1) || (version[0] === 1 && parseInt(version[1], 10) >= 4);
100969				})($.fn.jquery.split('.'));
100970				// digit sort text location; keeping max+/- for backwards compatibility
100971				c.string = { 'max': 1, 'min': -1, 'emptymin': 1, 'emptymax': -1, 'zero': 0, 'none': 0, 'null': 0, 'top': true, 'bottom': false };
100972				// ensure case insensitivity
100973				c.emptyTo = c.emptyTo.toLowerCase();
100974				c.stringTo = c.stringTo.toLowerCase();
100975				// add table theme class only if there isn't already one there
100976				if (!/tablesorter\-/.test($table.attr('class'))) {
100977					k = (c.theme !== '' ? ' tablesorter-' + c.theme : '');
100978				}
100979				c.table = table;
100980				c.$table = $table
100981					.addClass(ts.css.table + ' ' + c.tableClass + k)
100982					.attr('role', 'grid');
100983				c.$headers = $table.find(c.selectorHeaders);
100984
100985				// give the table a unique id, which will be used in namespace binding
100986				if (!c.namespace) {
100987					c.namespace = '.tablesorter' + Math.random().toString(16).slice(2);
100988				} else {
100989					// make sure namespace starts with a period & doesn't have weird characters
100990					c.namespace = '.' + c.namespace.replace(/\W/g, '');
100991				}
100992
100993				c.$table.children().children('tr').attr('role', 'row');
100994				c.$tbodies = $table.children('tbody:not(.' + c.cssInfoBlock + ')').attr({
100995					'aria-live' : 'polite',
100996					'aria-relevant' : 'all'
100997				});
100998				if (c.$table.children('caption').length) {
100999					k = c.$table.children('caption')[0];
101000					if (!k.id) { k.id = c.namespace.slice(1) + 'caption'; }
101001					c.$table.attr('aria-labelledby', k.id);
101002				}
101003				c.widgetInit = {}; // keep a list of initialized widgets
101004				// change textExtraction via data-attribute
101005				c.textExtraction = c.$table.attr('data-text-extraction') || c.textExtraction || 'basic';
101006				// build headers
101007				buildHeaders(table);
101008				// fixate columns if the users supplies the fixedWidth option
101009				// do this after theme has been applied
101010				ts.fixColumnWidth(table);
101011				// add widget options before parsing (e.g. grouping widget has parser settings)
101012				ts.applyWidgetOptions(table, c);
101013				// try to auto detect column type, and store in tables config
101014				buildParserCache(c);
101015				// start total row count at zero
101016				c.totalRows = 0;
101017				// build the cache for the tbody cells
101018				// delayInit will delay building the cache until the user starts a sort
101019				if (!c.delayInit) { buildCache(table); }
101020				// bind all header events and methods
101021				ts.bindEvents(table, c.$headers, true);
101022				bindMethods(table);
101023				// get sort list from jQuery data or metadata
101024				// in jQuery < 1.4, an error occurs when calling $table.data()
vendor: 5,435 bytes, lines 101025-101178
101025				if (c.supportsDataObject && typeof $table.data().sortlist !== 'undefined') {
101026					c.sortList = $table.data().sortlist;
101027				} else if (m && ($table.metadata() && $table.metadata().sortlist)) {
101028					c.sortList = $table.metadata().sortlist;
101029				}
101030				// apply widget init code
101031				ts.applyWidget(table, true);
101032				// if user has supplied a sort list to constructor
101033				if (c.sortList.length > 0) {
101034					$table.trigger('sorton', [ c.sortList, {}, !c.initWidgets, true ]);
101035				} else {
101036					setHeadersCss(table);
101037					if (c.initWidgets) {
101038						// apply widget format
101039						ts.applyWidget(table, false);
101040					}
101041				}
101042
101043				// show processesing icon
101044				if (c.showProcessing) {
101045					$table
101046					.unbind('sortBegin' + c.namespace + ' sortEnd' + c.namespace)
101047					.bind('sortBegin' + c.namespace + ' sortEnd' + c.namespace, function(e) {
101048						clearTimeout(c.processTimer);
101049						ts.isProcessing(table);
101050						if (e.type === 'sortBegin') {
101051							c.processTimer = setTimeout(function(){
101052								ts.isProcessing(table, true);
101053							}, 500);
101054						}
101055					});
101056				}
101057
101058				// initialized
101059				table.hasInitialized = true;
101060				table.isProcessing = false;
101061				if (c.debug) {
101062					console.log( 'Overall initialization time: ' + ts.benchmark( $.data( table, 'startoveralltimer') ) );
101063					if ( c.debug && console.groupEnd ) { console.groupEnd(); }
101064				}
101065				$table.trigger('tablesorter-initialized', table);
101066				if (typeof c.initialized === 'function') { c.initialized(table); }
101067			};
101068
101069			// automatically add a colgroup with col elements set to a percentage width
101070			ts.fixColumnWidth = function(table) {
101071				table = $(table)[0];
101072				var overallWidth, percent, $tbodies, len, index,
101073					c = table.config,
101074					$colgroup = c.$table.children('colgroup');
101075				// remove plugin-added colgroup, in case we need to refresh the widths
101076				if ($colgroup.length && $colgroup.hasClass(ts.css.colgroup)) {
101077					$colgroup.remove();
101078				}
101079				if (c.widthFixed && c.$table.children('colgroup').length === 0) {
101080					$colgroup = $('<colgroup class="' + ts.css.colgroup + '">');
101081					overallWidth = c.$table.width();
101082					// only add col for visible columns - fixes #371
101083					$tbodies = c.$tbodies.find('tr:first').children(':visible'); // .each(function()
101084					len = $tbodies.length;
101085					for ( index = 0; index < len; index++ ) {
101086						percent = parseInt( ( $tbodies.eq( index ).width() / overallWidth ) * 1000, 10 ) / 10 + '%';
101087						$colgroup.append( $('<col>').css('width', percent) );
101088					}
101089					c.$table.prepend($colgroup);
101090				}
101091			};
101092
101093			ts.getColumnData = function(table, obj, indx, getCell, $headers){
101094				if (typeof obj === 'undefined' || obj === null) { return; }
101095				table = $(table)[0];
101096				var $h, k,
101097					c = table.config,
101098					$cells = ( $headers || c.$headers ),
101099					// c.$headerIndexed is not defined initially
101100					$cell = c.$headerIndexed && c.$headerIndexed[indx] || $cells.filter('[data-column="' + indx + '"]:last');
101101				if (obj[indx]) {
101102					return getCell ? obj[indx] : obj[$cells.index( $cell )];
101103				}
101104				for (k in obj) {
101105					if (typeof k === 'string') {
101106						$h = $cell
101107							// header cell with class/id
101108							.filter(k)
101109							// find elements within the header cell with cell/id
101110							.add( $cell.find(k) );
101111						if ($h.length) {
101112							return obj[k];
101113						}
101114					}
101115				}
101116				return;
101117			};
101118
101119			// computeTableHeaderCellIndexes from:
101120			// http://www.javascripttoolbox.com/lib/table/examples.php
101121			// http://www.javascripttoolbox.com/temp/table_cellindex.html
101122			ts.computeColumnIndex = function(trs) {
101123				var i, j, k, l, $cell, cell, cells, rowIndex, cellId, rowSpan, colSpan, firstAvailCol,
101124					matrix = [],
101125					matrixrow = [],
101126					lookup = {};
101127				for (i = 0; i < trs.length; i++) {
101128					cells = trs[i].cells;
101129					for (j = 0; j < cells.length; j++) {
101130						cell = cells[j];
101131						$cell = $(cell);
101132						rowIndex = cell.parentNode.rowIndex;
101133						cellId = rowIndex + '-' + $cell.index();
101134						rowSpan = cell.rowSpan || 1;
101135						colSpan = cell.colSpan || 1;
101136						if (typeof matrix[rowIndex] === 'undefined') {
101137							matrix[rowIndex] = [];
101138						}
101139						// Find first available column in the first row
101140						for (k = 0; k < matrix[rowIndex].length + 1; k++) {
101141							if (typeof matrix[rowIndex][k] === 'undefined') {
101142								firstAvailCol = k;
101143								break;
101144							}
101145						}
101146						lookup[cellId] = firstAvailCol;
101147						// add data-column
101148						$cell.attr({ 'data-column' : firstAvailCol }); // 'data-row' : rowIndex
101149						for (k = rowIndex; k < rowIndex + rowSpan; k++) {
101150							if (typeof matrix[k] === 'undefined') {
101151								matrix[k] = [];
101152							}
101153							matrixrow = matrix[k];
101154							for (l = firstAvailCol; l < firstAvailCol + colSpan; l++) {
101155								matrixrow[l] = 'x';
101156							}
101157						}
101158					}
101159				}
101160				return matrixrow.length;
101161			};
101162
101163			// *** Process table ***
101164			// add processing indicator
101165			ts.isProcessing = function( $table, toggle, $ths ) {
101166				$table = $( $table );
101167				var c = $table[0].config,
101168					// default to all headers
101169					$h = $ths || $table.find('.' + ts.css.header);
101170				if (toggle) {
101171					// don't use sortList if custom $ths used
101172					if (typeof $ths !== 'undefined' && c.sortList.length > 0) {
101173						// get headers from the sortList
101174						$h = $h.filter(function(){
101175							// get data-column from attr to keep compatibility with jQuery 1.2.6
101176							return this.sortDisabled ? false : ts.isValueInArray( parseFloat($(this).attr('data-column')), c.sortList) >= 0;
101177						});
101178					}
101179					$table.add($h).addClass(ts.css.processing + ' ' + c.cssProcessing);
101180				} else {
101181					$table.add($h).removeClass(ts.css.processing + ' ' + c.cssProcessing);
101182				}
101183			};
101184
101185			// detach tbody but save the position
101186			// don't use tbody because there are portions that look for a tbody index (updateCell)
101187			ts.processTbody = function(table, $tb, getIt){
101188				table = $(table)[0];
101189				var holdr;
101190				if (getIt) {
101191					table.isProcessing = true;
101192					$tb.before('<colgroup class="tablesorter-savemyplace"/>');
101193					holdr = ($.fn.detach) ? $tb.detach() : $tb.remove();
101194					return holdr;
101195				}
101196				holdr = $(table).find('colgroup.tablesorter-savemyplace');
101197				$tb.insertAfter( holdr );
101198				holdr.remove();
101199				table.isProcessing = false;
101200			};
101201
101202			ts.clearTableBody = function(table) {
101203				$(table)[0].config.$tbodies.children().detach();
101204			};
101205
101206			ts.bindEvents = function(table, $headers, core) {
101207				table = $(table)[0];
101208				var t, downTarget = null,
101209					c = table.config;
101210				if (core !== true) {
101211					$headers.addClass( c.namespace.slice(1) + '_extra_headers' );
101212					t = $.fn.closest ? $headers.closest('table')[0] : $headers.parents('table')[0];
101213					if (t && t.nodeName === 'TABLE' && t !== table) {
101214						$(t).addClass( c.namespace.slice(1) + '_extra_table' );
101215					}
101216				}
101217				t = ( c.pointerDown + ' ' + c.pointerUp + ' ' + c.pointerClick + ' sort keyup ' )
101218					.replace(/\s+/g, ' ')
101219					.split(' ')
101220					.join(c.namespace + ' ');
101221				// apply event handling to headers and/or additional headers (stickyheaders, scroller, etc)
101222				$headers
101223				// http://stackoverflow.com/questions/5312849/jquery-find-self;
101224				.find(c.selectorSort).add( $headers.filter(c.selectorSort) )
101225				.unbind(t)
101226				.bind(t, function(e, external) {
101227					var cell, temp,
101228						$target = $(e.target),
101229						// wrap event type in spaces, so the match doesn't trigger on inner words
101230						type = ' ' + e.type + ' ';
101231					// only recognize left clicks
101232					if ( ( ( e.which || e.button ) !== 1 && !type.match( ' ' + c.pointerClick + ' | sort | keyup ' ) ) ||
101233						// allow pressing enter
101234						( type === ' keyup ' && e.which !== 13 ) ||
101235						// allow triggering a click event (e.which is undefined) & ignore physical clicks
101236						( type.match(' ' + c.pointerClick + ' ') && typeof e.which !== 'undefined' ) ) {
101237						return;
101238					}
101239					// ignore mouseup if mousedown wasn't on the same target
101240					if ( type.match(' ' + c.pointerUp + ' ') && downTarget !== e.target && external !== true ) { return; }
101241					// set target on mousedown
101242					if ( type.match(' ' + c.pointerDown + ' ') ) {
101243						downTarget = e.target;
101244						// preventDefault needed or jQuery v1.3.2 and older throws an
101245						// "Uncaught TypeError: handler.apply is not a function" error
101246						temp = $target.jquery.split( '.' );
101247						if ( temp[0] === '1' && temp[1] < 4 ) { e.preventDefault(); }
101248						return;
101249					}
101250					downTarget = null;
101251					// prevent sort being triggered on form elements
101252					if ( /(input|select|button|textarea)/i.test(e.target.nodeName) ||
101253						// nosort class name, or elements within a nosort container
101254						$target.hasClass(c.cssNoSort) || $target.parents('.' + c.cssNoSort).length > 0 ||
101255						// elements within a button
101256						$target.parents('button').length > 0 ) {
101257						return !c.cancelSelection;
101258					}
101259					if (c.delayInit && isEmptyObject(c.cache)) { buildCache(table); }
101260					// jQuery v1.2.6 doesn't have closest()
101261					cell = $.fn.closest ? $(this).closest('th, td')[0] : /TH|TD/.test(this.nodeName) ? this : $(this).parents('th, td')[0];
101262					// reference original table headers and find the same cell
101263					cell = c.$headers[ $headers.index( cell ) ];
101264					if (!cell.sortDisabled) {
101265						initSort(table, cell, e);
101266					}
101267				});
101268				if (c.cancelSelection) {
101269					// cancel selection
101270					$headers
101271						.attr('unselectable', 'on')
101272						.bind('selectstart', false)
101273						.css({
101274							'user-select': 'none',
101275							'MozUserSelect': 'none' // not needed for jQuery 1.8+
101276						});
101277				}
101278			};
101279
101280			// restore headers
101281			ts.restoreHeaders = function(table){
101282				var index, $cell,
101283					c = $(table)[0].config,
101284					$headers = c.$table.find( c.selectorHeaders ),
101285					len = $headers.length;
101286				// don't use c.$headers here in case header cells were swapped
101287				for ( index = 0; index < len; index++ ) {
101288					// c.$table.find(c.selectorHeaders).each(function(i){
101289					$cell = $headers.eq( index );
vendor: 7,285 bytes, lines 101290-101465
101290					// only restore header cells if it is wrapped
101291					// because this is also used by the updateAll method
101292					if ( $cell.find( '.' + ts.css.headerIn ).length ) {
101293						$cell.html( c.headerContent[ index ] );
101294					}
101295				}
101296			};
101297
101298			ts.destroy = function(table, removeClasses, callback){
101299				table = $(table)[0];
101300				if (!table.hasInitialized) { return; }
101301				// remove all widgets
101302				ts.removeWidget(table, true, false);
101303				var events,
101304					$t = $(table),
101305					c = table.config,
101306					debug = c.debug,
101307					$h = $t.find('thead:first'),
101308					$r = $h.find('tr.' + ts.css.headerRow).removeClass(ts.css.headerRow + ' ' + c.cssHeaderRow),
101309					$f = $t.find('tfoot:first > tr').children('th, td');
101310				if (removeClasses === false && $.inArray('uitheme', c.widgets) >= 0) {
101311					// reapply uitheme classes, in case we want to maintain appearance
101312					$t.trigger('applyWidgetId', [ 'uitheme' ]);
101313					$t.trigger('applyWidgetId', [ 'zebra' ]);
101314				}
101315				// remove widget added rows, just in case
101316				$h.find('tr').not($r).remove();
101317				// disable tablesorter
101318				events = 'sortReset update updateAll updateRows updateCell addRows updateComplete sorton appendCache updateCache ' +
101319					'applyWidgetId applyWidgets refreshWidgets destroy mouseup mouseleave keypress sortBegin sortEnd resetToLoadState '.split(' ')
101320					.join(c.namespace + ' ');
101321				$t
101322					.removeData('tablesorter')
101323					.unbind( events.replace(/\s+/g, ' ') );
101324				c.$headers.add($f)
101325					.removeClass( [ ts.css.header, c.cssHeader, c.cssAsc, c.cssDesc, ts.css.sortAsc, ts.css.sortDesc, ts.css.sortNone ].join(' ') )
101326					.removeAttr('data-column')
101327					.removeAttr('aria-label')
101328					.attr('aria-disabled', 'true');
101329				$r.find(c.selectorSort).unbind( ('mousedown mouseup keypress '.split(' ').join(c.namespace + ' ')).replace(/\s+/g, ' ') );
101330				ts.restoreHeaders(table);
101331				$t.toggleClass(ts.css.table + ' ' + c.tableClass + ' tablesorter-' + c.theme, removeClasses === false);
101332				// clear flag in case the plugin is initialized again
101333				table.hasInitialized = false;
101334				delete table.config.cache;
101335				if (typeof callback === 'function') {
101336					callback(table);
101337				}
101338				if (debug) {
101339					console.log( 'tablesorter has been removed' );
101340				}
101341			};
101342
101343			// *** sort functions ***
101344			// regex used in natural sort
101345			ts.regex = {
101346				chunk : /(^([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)?$|^0x[0-9a-f]+$|\d+)/gi, // chunk/tokenize numbers & letters
101347				chunks: /(^\\0|\\0$)/, // replace chunks @ ends
101348				hex: /^0x[0-9a-f]+$/i // hex
101349			};
101350
101351			// Natural sort - https://github.com/overset/javascript-natural-sort (date sorting removed)
101352			// this function will only accept strings, or you'll see 'TypeError: undefined is not a function'
101353			// I could add a = a.toString(); b = b.toString(); but it'll slow down the sort overall
101354			ts.sortNatural = function(a, b) {
101355				if (a === b) { return 0; }
101356				var xN, xD, yN, yD, xF, yF, i, mx,
101357					r = ts.regex;
101358				// first try and sort Hex codes
101359				if (r.hex.test(b)) {
101360					xD = parseInt(a.match(r.hex), 16);
101361					yD = parseInt(b.match(r.hex), 16);
101362					if ( xD < yD ) { return -1; }
101363					if ( xD > yD ) { return 1; }
101364				}
101365				// chunk/tokenize
101366				xN = a.replace(r.chunk, '\\0$1\\0').replace(r.chunks, '').split('\\0');
101367				yN = b.replace(r.chunk, '\\0$1\\0').replace(r.chunks, '').split('\\0');
101368				mx = Math.max(xN.length, yN.length);
101369				// natural sorting through split numeric strings and default strings
101370				for (i = 0; i < mx; i++) {
101371					// find floats not starting with '0', string or 0 if not defined
101372					xF = isNaN(xN[i]) ? xN[i] || 0 : parseFloat(xN[i]) || 0;
101373					yF = isNaN(yN[i]) ? yN[i] || 0 : parseFloat(yN[i]) || 0;
101374					// handle numeric vs string comparison - number < string - (Kyle Adams)
101375					if (isNaN(xF) !== isNaN(yF)) { return (isNaN(xF)) ? 1 : -1; }
101376					// rely on string comparison if different types - i.e. '02' < 2 != '02' < '2'
101377					if (typeof xF !== typeof yF) {
101378						xF += '';
101379						yF += '';
101380					}
101381					if (xF < yF) { return -1; }
101382					if (xF > yF) { return 1; }
101383				}
101384				return 0;
101385			};
101386
101387			ts.sortNaturalAsc = function(a, b, col, table, c) {
101388				if (a === b) { return 0; }
101389				var e = c.string[ (c.empties[col] || c.emptyTo ) ];
101390				if (a === '' && e !== 0) { return typeof e === 'boolean' ? (e ? -1 : 1) : -e || -1; }
101391				if (b === '' && e !== 0) { return typeof e === 'boolean' ? (e ? 1 : -1) : e || 1; }
101392				return ts.sortNatural(a, b);
101393			};
101394
101395			ts.sortNaturalDesc = function(a, b, col, table, c) {
101396				if (a === b) { return 0; }
101397				var e = c.string[ (c.empties[col] || c.emptyTo ) ];
101398				if (a === '' && e !== 0) { return typeof e === 'boolean' ? (e ? -1 : 1) : e || 1; }
101399				if (b === '' && e !== 0) { return typeof e === 'boolean' ? (e ? 1 : -1) : -e || -1; }
101400				return ts.sortNatural(b, a);
101401			};
101402
101403			// basic alphabetical sort
101404			ts.sortText = function(a, b) {
101405				return a > b ? 1 : (a < b ? -1 : 0);
101406			};
101407
101408			// return text string value by adding up ascii value
101409			// so the text is somewhat sorted when using a digital sort
101410			// this is NOT an alphanumeric sort
101411			ts.getTextValue = function(a, num, mx) {
101412				if (mx) {
101413					// make sure the text value is greater than the max numerical value (mx)
101414					var i, l = a ? a.length : 0, n = mx + num;
101415					for (i = 0; i < l; i++) {
101416						n += a.charCodeAt(i);
101417					}
101418					return num * n;
101419				}
101420				return 0;
101421			};
101422
101423			ts.sortNumericAsc = function(a, b, num, mx, col, table) {
101424				if (a === b) { return 0; }
101425				var c = table.config,
101426					e = c.string[ (c.empties[col] || c.emptyTo ) ];
101427				if (a === '' && e !== 0) { return typeof e === 'boolean' ? (e ? -1 : 1) : -e || -1; }
101428				if (b === '' && e !== 0) { return typeof e === 'boolean' ? (e ? 1 : -1) : e || 1; }
101429				if (isNaN(a)) { a = ts.getTextValue(a, num, mx); }
101430				if (isNaN(b)) { b = ts.getTextValue(b, num, mx); }
101431				return a - b;
101432			};
101433
101434			ts.sortNumericDesc = function(a, b, num, mx, col, table) {
101435				if (a === b) { return 0; }
101436				var c = table.config,
101437					e = c.string[ (c.empties[col] || c.emptyTo ) ];
101438				if (a === '' && e !== 0) { return typeof e === 'boolean' ? (e ? -1 : 1) : e || 1; }
101439				if (b === '' && e !== 0) { return typeof e === 'boolean' ? (e ? 1 : -1) : -e || -1; }
101440				if (isNaN(a)) { a = ts.getTextValue(a, num, mx); }
101441				if (isNaN(b)) { b = ts.getTextValue(b, num, mx); }
101442				return b - a;
101443			};
101444
101445			ts.sortNumeric = function(a, b) {
101446				return a - b;
101447			};
101448
101449			// used when replacing accented characters during sorting
101450			ts.characterEquivalents = {
101451				'a' : '\u00e1\u00e0\u00e2\u00e3\u00e4\u0105\u00e5', // áàâãäąå
101452				'A' : '\u00c1\u00c0\u00c2\u00c3\u00c4\u0104\u00c5', // ÁÀÂÃÄĄÅ
101453				'c' : '\u00e7\u0107\u010d', // çćč
101454				'C' : '\u00c7\u0106\u010c', // ÇĆČ
101455				'e' : '\u00e9\u00e8\u00ea\u00eb\u011b\u0119', // éèêëěę
101456				'E' : '\u00c9\u00c8\u00ca\u00cb\u011a\u0118', // ÉÈÊËĚĘ
101457				'i' : '\u00ed\u00ec\u0130\u00ee\u00ef\u0131', // íìİîïı
101458				'I' : '\u00cd\u00cc\u0130\u00ce\u00cf', // ÍÌİÎÏ
101459				'o' : '\u00f3\u00f2\u00f4\u00f5\u00f6\u014d', // óòôõöō
101460				'O' : '\u00d3\u00d2\u00d4\u00d5\u00d6\u014c', // ÓÒÔÕÖŌ
101461				'ss': '\u00df', // ß (s sharp)
101462				'SS': '\u1e9e', // ẞ (Capital sharp s)
101463				'u' : '\u00fa\u00f9\u00fb\u00fc\u016f', // úùûüů
101464				'U' : '\u00da\u00d9\u00db\u00dc\u016e' // ÚÙÛÜŮ
101465			};
101466			ts.replaceAccents = function(s) {
101467				var a, acc = '[', eq = ts.characterEquivalents;
101468				if (!ts.characterRegex) {
101469					ts.characterRegexArray = {};
101470					for (a in eq) {
101471						if (typeof a === 'string') {
101472							acc += eq[a];
101473							ts.characterRegexArray[a] = new RegExp('[' + eq[a] + ']', 'g');
101474						}
101475					}
101476					ts.characterRegex = new RegExp(acc + ']');
101477				}
101478				if (ts.characterRegex.test(s)) {
101479					for (a in eq) {
101480						if (typeof a === 'string') {
101481							s = s.replace( ts.characterRegexArray[a], a );
101482						}
101483					}
101484				}
101485				return s;
101486			};
101487
101488			// *** utilities ***
101489			ts.isValueInArray = function( column, arry ) {
101490				var indx,
101491					len = arry && arry.length || 0;
101492				for ( indx = 0; indx < len; indx++ ) {
101493					if ( arry[ indx ][ 0 ] === column ) {
101494						return indx;
101495					}
101496				}
101497				return -1;
101498			};
101499
101500			ts.addParser = function(parser) {
101501				var i, l = ts.parsers.length, a = true;
101502				for (i = 0; i < l; i++) {
101503					if (ts.parsers[i].id.toLowerCase() === parser.id.toLowerCase()) {
101504						a = false;
101505					}
101506				}
101507				if (a) {
101508					ts.parsers.push(parser);
101509				}
101510			};
101511
101512			// Use it to add a set of methods to table.config which will be available for all tables.
101513			// This should be done before table initialization
101514			ts.addInstanceMethods = function(methods) {
101515				$.extend(ts.instanceMethods, methods);
101516			};
101517
101518			ts.getParserById = function(name) {
101519				/*jshint eqeqeq:false */
101520				if (name == 'false') { return false; }
101521				var i, l = ts.parsers.length;
101522				for (i = 0; i < l; i++) {
101523					if (ts.parsers[i].id.toLowerCase() === (name.toString()).toLowerCase()) {
101524						return ts.parsers[i];
101525					}
101526				}
101527				return false;
101528			};
101529
101530			ts.addWidget = function(widget) {
101531				ts.widgets.push(widget);
101532			};
101533
101534			ts.hasWidget = function( $table, name ) {
101535				$table = $( $table );
101536				return $table.length && $table[0].config && $table[0].config.widgetInit[name] || false;
101537			};
101538
101539			ts.getWidgetById = function(name) {
101540				var i, w, l = ts.widgets.length;
101541				for (i = 0; i < l; i++) {
101542					w = ts.widgets[i];
101543					if (w && w.hasOwnProperty('id') && w.id.toLowerCase() === name.toLowerCase()) {
101544						return w;
101545					}
101546				}
101547			};
101548
101549			ts.applyWidgetOptions = function( table, c ){
101550				var indx, widget,
101551					len = c.widgets.length,
101552					wo = c.widgetOptions;
101553				if (len) {
101554					for (indx = 0; indx < len; indx++) {
101555						widget = ts.getWidgetById( c.widgets[indx] );
101556						if ( widget && 'options' in widget ) {
101557							wo = table.config.widgetOptions = $.extend( true, {}, widget.options, wo );
101558						}
101559					}
101560				}
101561			};
101562
101563			ts.applyWidget = function(table, init, callback) {
101564				table = $(table)[0]; // in case this is called externally
101565				var indx, len, names, widget, name, applied,
101566					c = table.config,
101567					wo = c.widgetOptions,
101568					tableClass = ' ' + c.table.className + ' ',
101569					widgets = [],
101570					time, time2, w, wd;
101571				// prevent numerous consecutive widget applications
101572				if (init !== false && table.hasInitialized && (table.isApplyingWidgets || table.isUpdating)) { return; }
101573				if (c.debug) { time = new Date(); }
101574				// look for widgets to apply from in table class
101575				// stop using \b otherwise this matches 'ui-widget-content' & adds 'content' widget
101576				wd = new RegExp( '\\s' + c.widgetClass.replace( /\{name\}/i, '([\\w-]+)' ) + '\\s', 'g' );
101577				if ( tableClass.match( wd ) ) {
101578					// extract out the widget id from the table class (widget id's can include dashes)
101579					w = tableClass.match( wd );
101580					if ( w ) {
101581						len = w.length;
101582						for (indx = 0; indx < len; indx++) {
101583							c.widgets.push( w[indx].replace( wd, '$1' ) );
101584						}
101585					}
101586				}
101587				if (c.widgets.length) {
101588					table.isApplyingWidgets = true;
101589					// ensure unique widget ids
101590					c.widgets = $.grep(c.widgets, function(v, k){
101591						return $.inArray(v, c.widgets) === k;
101592					});
101593					names = c.widgets || [];
101594					len = names.length;
101595					// build widget array & add priority as needed
101596					for (indx = 0; indx < len; indx++) {
101597						wd = ts.getWidgetById(names[indx]);
101598						if (wd && wd.id) {
101599							// set priority to 10 if not defined
101600							if (!wd.priority) { wd.priority = 10; }
101601							widgets[indx] = wd;
101602						}
101603					}
101604					// sort widgets by priority
101605					widgets.sort(function(a, b){
101606						return a.priority < b.priority ? -1 : a.priority === b.priority ? 0 : 1;
101607					});
101608					// add/update selected widgets
101609					len = widgets.length;
101610					if (c.debug) {
101611						console[ console.group ? 'group' : 'log' ]( 'Start ' + ( init ? 'initializing' : 'applying' ) + ' widgets' );
101612					}
101613					for (indx = 0; indx < len; indx++) {
101614						widget = widgets[indx];
101615						if (widget) {
101616							name = widget.id;
101617							applied = false;
101618							if (c.debug) { time2 = new Date(); }
101619
101620							if ( init || !( c.widgetInit[ name ] ) ) {
101621								// set init flag first to prevent calling init more than once (e.g. pager)
101622								c.widgetInit[ name ] = true;
101623								if (table.hasInitialized) {
101624									// don't reapply widget options on tablesorter init
101625									ts.applyWidgetOptions( table, c );
101626								}
101627								if ( 'init' in widget ) {
101628									applied = true;
101629									if (c.debug) {
101630										console[ console.group ? 'group' : 'log' ]( 'Initializing ' + name + ' widget' );
101631									}
101632									widget.init(table, widget, c, wo);
101633								}
101634							}
101635							if ( !init && 'format' in widget ) {
101636								applied = true;
101637								if (c.debug) {
101638									console[ console.group ? 'group' : 'log' ]( 'Updating ' + name + ' widget' );
101639								}
101640								widget.format(table, c, wo, false);
101641							}
101642							if (c.debug) {
101643								if (applied) {
101644									console.log( 'Completed ' + ( init ? 'initializing ' : 'applying ' ) + name + ' widget' + ts.benchmark( time2 ) );
101645									if ( console.groupEnd ) { console.groupEnd(); }
101646								}
101647							}
101648						}
101649					}
101650					if ( c.debug && console.groupEnd ) { console.groupEnd(); }
101651					// callback executed on init only
101652					if (!init && typeof callback === 'function') {
101653						callback(table);
101654					}
101655				}
101656				setTimeout(function(){
101657					table.isApplyingWidgets = false;
101658					$.data(table, 'lastWidgetApplication', new Date());
101659				}, 0);
101660				if (c.debug) {
101661					w = c.widgets.length;
101662					console.log( 'Completed ' + (init === true ? 'initializing ' : 'applying ') + w + ' widget' + (w !== 1 ? 's' : '') + ts.benchmark(time) );
101663				}
101664			};
101665
101666			ts.removeWidget = function(table, name, refreshing){
101667				table = $(table)[0];
101668				var i, widget, indx, len,
101669					c = table.config;
101670				// if name === true, add all widgets from $.tablesorter.widgets
101671				if (name === true) {
101672					name = [];
101673					len = ts.widgets.length;
101674					for (indx = 0; indx < len; indx++) {
101675						widget = ts.widgets[indx];
101676						if (widget && widget.id) {
101677							name.push( widget.id );
101678						}
101679					}
101680				} else {
101681					// name can be either an array of widgets names,
101682					// or a space/comma separated list of widget names
101683					name = ( $.isArray(name) ? name.join(',') : name || '' ).toLowerCase().split( /[\s,]+/ );
101684				}
101685				len = name.length;
101686				for (i = 0; i < len; i++) {
101687					widget = ts.getWidgetById(name[i]);
101688					indx = $.inArray( name[i], c.widgets );
101689					if ( widget && 'remove' in widget ) {
101690						if (c.debug && indx >= 0) { console.log( 'Removing "' + name[i] + '" widget' ); }
101691						if ( c.debug ) {
101692							console.log( ( refreshing ? 'Refreshing' : 'Removing' ) + ' "' + name[i] + '" widget' );
101693						}
101694						widget.remove(table, c, c.widgetOptions, refreshing);
101695						c.widgetInit[ name[i] ] = false;
101696					}
101697					// don't remove the widget from config.widget if refreshing
101698					if (indx >= 0 && refreshing !== true) {
101699						c.widgets.splice( indx, 1 );
101700					}
101701				}
101702			};
101703
101704			ts.refreshWidgets = function(table, doAll, dontapply) {
101705				table = $(table)[0]; // see issue #243
101706				var indx,
101707					c = table.config,
101708					cw = c.widgets,
101709					widgets = ts.widgets,
101710					len = widgets.length,
101711					list = [],
101712					callback = function(table){
101713						$(table).trigger('refreshComplete');
101714					};
101715				// remove widgets not defined in config.widgets, unless doAll is true
101716				for (indx = 0; indx < len; indx++) {
101717					if (widgets[indx] && widgets[indx].id && (doAll || $.inArray( widgets[indx].id, cw ) < 0)) {
101718						list.push( widgets[indx].id );
101719					}
101720				}
101721				ts.removeWidget( table, list.join(','), true );
101722				if (dontapply !== true) {
101723					// call widget init if
101724					ts.applyWidget(table, doAll || false, callback );
101725					if (doAll) {
101726						// apply widget format
101727						ts.applyWidget(table, false, callback);
101728					}
101729				} else {
101730					callback(table);
101731				}
101732			};
101733
101734			ts.getColumnText = function( table, column, callback ) {
101735				table = $( table )[0];
101736				var tbodyIndex, rowIndex, cache, row, tbodyLen, rowLen, raw, parsed, $cell, result,
101737					hasCallback = typeof callback === 'function',
101738					allColumns = column === 'all',
101739					data = { raw : [], parsed: [], $cell: [] },
101740					c = table.config;
101741				if ( isEmptyObject( c ) ) {
101742					if ( c.debug ) {
101743						console.warn( 'No cache found - aborting getColumnText function!' );
101744					}
101745				} else {
101746					tbodyLen = c.$tbodies.length;
101747					for ( tbodyIndex = 0; tbodyIndex < tbodyLen; tbodyIndex++ ) {
101748						cache = c.cache[ tbodyIndex ].normalized;
101749						rowLen = cache.length;
101750						for ( rowIndex = 0; rowIndex < rowLen; rowIndex++ ) {
101751							result = true;
101752							row =	cache[ rowIndex ];
101753							parsed = ( allColumns ) ? row.slice(0, c.columns) : row[ column ];
101754							row = row[ c.columns ];
101755							raw = ( allColumns ) ? row.raw : row.raw[ column ];
101756							$cell = ( allColumns ) ? row.$row.children() : row.$row.children().eq( column );
101757							if ( hasCallback ) {
101758								result = callback({
101759									tbodyIndex: tbodyIndex,
101760									rowIndex: rowIndex,
101761									parsed: parsed,
101762									raw: raw,
101763									$row: row.$row,
101764									$cell: $cell
101765								});
101766							}
101767							if ( result !== false ) {
101768								data.parsed.push( parsed );
101769								data.raw.push( raw );
101770								data.$cell.push( $cell );
101771							}
101772						}
101773					}
101774					// return everything
101775					return data;
101776				}
101777			};
101778
101779			// get sorter, string, empty, etc options for each column from
101780			// jQuery data, metadata, header option or header class name ('sorter-false')
101781			// priority = jQuery data > meta > headers option > header class name
101782			ts.getData = function(h, ch, key) {
101783				var val = '', $h = $(h), m, cl;
101784				if (!$h.length) { return ''; }
101785				m = $.metadata ? $h.metadata() : false;
101786				cl = ' ' + ($h.attr('class') || '');
101787				if (typeof $h.data(key) !== 'undefined' || typeof $h.data(key.toLowerCase()) !== 'undefined'){
101788					// 'data-lockedOrder' is assigned to 'lockedorder'; but 'data-locked-order' is assigned to 'lockedOrder'
101789					// 'data-sort-initial-order' is assigned to 'sortInitialOrder'
101790					val += $h.data(key) || $h.data(key.toLowerCase());
101791				} else if (m && typeof m[key] !== 'undefined') {
101792					val += m[key];
101793				} else if (ch && typeof ch[key] !== 'undefined') {
101794					val += ch[key];
101795				} else if (cl !== ' ' && cl.match(' ' + key + '-')) {
101796					// include sorter class name 'sorter-text', etc; now works with 'sorter-my-custom-parser'
101797					val = cl.match( new RegExp('\\s' + key + '-([\\w-]+)') )[1] || '';
101798				}
101799				return $.trim(val);
101800			};
101801
101802			ts.formatFloat = function(s, table) {
101803				if (typeof s !== 'string' || s === '') { return s; }
101804				// allow using formatFloat without a table; defaults to US number format
101805				var i,
101806					t = table && table.config ? table.config.usNumberFormat !== false :
101807						typeof table !== 'undefined' ? table : true;
101808				if (t) {
101809					// US Format - 1,234,567.89 -> 1234567.89
101810					s = s.replace(/,/g, '');
101811				} else {
101812					// German Format = 1.234.567,89 -> 1234567.89
101813					// French Format = 1 234 567,89 -> 1234567.89
101814					s = s.replace(/[\s|\.]/g, '').replace(/,/g, '.');
101815				}
101816				if (/^\s*\([.\d]+\)/.test(s)) {
101817					// make (#) into a negative number -> (10) = -10
101818					s = s.replace(/^\s*\(([.\d]+)\)/, '-$1');
101819				}
101820				i = parseFloat(s);
101821				// return the text instead of zero
101822				return isNaN(i) ? $.trim(s) : i;
101823			};
101824
101825			ts.isDigit = function(s) {
101826				// replace all unwanted chars and match
101827				return isNaN(s) ? (/^[\-+(]?\d+[)]?$/).test(s.toString().replace(/[,.'"\s]/g, '')) : s !== '';
101828			};
101829
101830		}()
101831	});
101832
101833	// make shortcut
101834	var ts = $.tablesorter;
101835
101836	// extend plugin scope
101837	$.fn.extend({
101838		tablesorter: ts.construct
101839	});
101840
101841	// set up debug logs
101842	if ( !( console && console.log ) ) {
101843		ts.logs = [];
101844		/*jshint -W020 */
101845		console = {};
101846		console.log = console.warn = console.error = console.table = function() {
101847			ts.logs.push( [ Date.now(), arguments ] );
101848		};
101849	}
101850
101851	ts.log = function(){
101852		console.log( arguments );
101853	};
101854	ts.benchmark = function( diff ) {
101855		return ( ' (' + ( new Date().getTime() - diff.getTime() ) + 'ms)' );
101856	};
101857
101858	// add default parsers
101859	ts.addParser({
101860		id: 'no-parser',
101861		is: function() {
101862			return false;
101863		},
101864		format: function() {
101865			return '';
101866		},
101867		type: 'text'
101868	});
101869
101870	ts.addParser({
101871		id: 'text',
101872		is: function() {
101873			return true;
101874		},
101875		format: function(s, table) {
101876			var c = table.config;
101877			if (s) {
101878				s = $.trim( c.ignoreCase ? s.toLocaleLowerCase() : s );
101879				s = c.sortLocaleCompare ? ts.replaceAccents(s) : s;
101880			}
101881			return s;
101882		},
101883		type: 'text'
101884	});
101885
101886	ts.addParser({
101887		id: 'digit',
101888		is: function(s) {
101889			return ts.isDigit(s);
101890		},
101891		format: function(s, table) {
101892			var n = ts.formatFloat((s || '').replace(/[^\w,. \-()]/g, ''), table);
101893			return s && typeof n === 'number' ? n : s ? $.trim( s && table.config.ignoreCase ? s.toLocaleLowerCase() : s ) : s;
101894		},
101895		type: 'numeric'
101896	});
101897
101898	ts.addParser({
101899		id: 'currency',
101900		is: function(s) {
101901			return (/^\(?\d+[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]|[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]\d+\)?$/).test((s || '').replace(/[+\-,. ]/g, '')); // £$€¤¥¢
101902		},
101903		format: function(s, table) {
101904			var n = ts.formatFloat((s || '').replace(/[^\w,. \-()]/g, ''), table);
101905			return s && typeof n === 'number' ? n : s ? $.trim( s && table.config.ignoreCase ? s.toLocaleLowerCase() : s ) : s;
101906		},
101907		type: 'numeric'
101908	});
101909
101910	ts.addParser({
101911		id: 'url',
101912		is: function(s) {
101913			return (/^(https?|ftp|file):\/\//).test(s);
101914		},
101915		format: function(s) {
101916			return s ? $.trim(s.replace(/(https?|ftp|file):\/\//, '')) : s;
101917		},
101918		parsed : true, // filter widget flag
101919		type: 'text'
101920	});
101921
101922	ts.addParser({
101923		id: 'isoDate',
101924		is: function(s) {
101925			return (/^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}/).test(s);
101926		},
101927		format: function(s, table) {
101928			var date = s ? new Date( s.replace(/-/g, '/') ) : s;
101929			return date instanceof Date && isFinite(date) ? date.getTime() : s;
101930		},
101931		type: 'numeric'
101932	});
101933
101934	ts.addParser({
101935		id: 'percent',
101936		is: function(s) {
101937			return (/(\d\s*?%|%\s*?\d)/).test(s) && s.length < 15;
101938		},
101939		format: function(s, table) {
101940			return s ? ts.formatFloat(s.replace(/%/g, ''), table) : s;
101941		},
101942		type: 'numeric'
101943	});
101944
101945	// added image parser to core v2.17.9
101946	ts.addParser({
101947		id: 'image',
101948		is: function(s, table, node, $node){
101949			return $node.find('img').length > 0;
101950		},
101951		format: function(s, table, cell) {
101952			return $(cell).find('img').attr(table.config.imgAttr || 'alt') || s;
101953		},
101954		parsed : true, // filter widget flag
101955		type: 'text'
101956	});
101957
101958	ts.addParser({
101959		id: 'usLongDate',
101960		is: function(s) {
101961			// two digit years are not allowed cross-browser
101962			// Jan 01, 2013 12:34:56 PM or 01 Jan 2013
101963			return (/^[A-Z]{3,10}\.?\s+\d{1,2},?\s+(\d{4})(\s+\d{1,2}:\d{2}(:\d{2})?(\s+[AP]M)?)?$/i).test(s) || (/^\d{1,2}\s+[A-Z]{3,10}\s+\d{4}/i).test(s);
101964		},
101965		format: function(s, table) {
101966			var date = s ? new Date( s.replace(/(\S)([AP]M)$/i, '$1 $2') ) : s;
101967			return date instanceof Date && isFinite(date) ? date.getTime() : s;
101968		},
101969		type: 'numeric'
101970	});
101971
101972	ts.addParser({
101973		id: 'shortDate', // 'mmddyyyy', 'ddmmyyyy' or 'yyyymmdd'
101974		is: function(s) {
101975			// testing for ##-##-#### or ####-##-##, so it's not perfect; time can be included
101976			return (/(^\d{1,2}[\/\s]\d{1,2}[\/\s]\d{4})|(^\d{4}[\/\s]\d{1,2}[\/\s]\d{1,2})/).test((s || '').replace(/\s+/g, ' ').replace(/[\-.,]/g, '/'));
101977		},
101978		format: function(s, table, cell, cellIndex) {
101979			if (s) {
101980				var date, d,
101981					c = table.config,
101982					ci = c.$headerIndexed[ cellIndex ],
101983					format = ci.length && ci[0].dateFormat || ts.getData( ci, ts.getColumnData( table, c.headers, cellIndex ), 'dateFormat') || c.dateFormat;
101984				d = s.replace(/\s+/g, ' ').replace(/[\-.,]/g, '/'); // escaped - because JSHint in Firefox was showing it as an error
101985				if (format === 'mmddyyyy') {
101986					d = d.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/, '$3/$1/$2');
101987				} else if (format === 'ddmmyyyy') {
101988					d = d.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/, '$3/$2/$1');
101989				} else if (format === 'yyyymmdd') {
101990					d = d.replace(/(\d{4})[\/\s](\d{1,2})[\/\s](\d{1,2})/, '$1/$2/$3');
101991				}
101992				date = new Date(d);
101993				return date instanceof Date && isFinite(date) ? date.getTime() : s;
101994			}
101995			return s;
101996		},
101997		type: 'numeric'
101998	});
101999
102000	ts.addParser({
102001		id: 'time',
102002		is: function(s) {
102003			return (/^(([0-2]?\d:[0-5]\d)|([0-1]?\d:[0-5]\d\s?([AP]M)))$/i).test(s);
102004		},
102005		format: function(s, table) {
102006			var date = s ? new Date( '2000/01/01 ' + s.replace(/(\S)([AP]M)$/i, '$1 $2') ) : s;
102007			return date instanceof Date && isFinite(date) ? date.getTime() : s;
102008		},
102009		type: 'numeric'
102010	});
102011
102012	ts.addParser({
102013		id: 'metadata',
102014		is: function() {
102015			return false;
102016		},
102017		format: function(s, table, cell) {
102018			var c = table.config,
102019			p = (!c.parserMetadataName) ? 'sortValue' : c.parserMetadataName;
102020			return $(cell).metadata()[p];
102021		},
102022		type: 'numeric'
102023	});
102024
102025	// add default widgets
102026	ts.addWidget({
102027		id: 'zebra',
102028		priority: 90,
102029		format: function(table, c, wo) {
102030			var $tv, $tr, row, even, time, k, i, len,
102031				child = new RegExp(c.cssChildRow, 'i'),
102032				b = c.$tbodies.add( $( c.namespace + '_extra_table' ).children( 'tbody:not(.' + c.cssInfoBlock + ')' ) );
102033			if (c.debug) {
102034				time = new Date();
102035			}
102036			for (k = 0; k < b.length; k++ ) {
102037				// loop through the visible rows
102038				row = 0;
102039				$tv = b.eq( k ).children( 'tr:visible' ).not( c.selectorRemove );
102040				len = $tv.length;
102041				for ( i = 0; i < len; i++ ) {
102042					$tr = $tv.eq( i );
102043					// style child rows the same way the parent row was styled
102044					if ( !child.test( $tr[0].className ) ) { row++; }
102045					even = ( row % 2 === 0 );
102046					$tr
102047						.removeClass( wo.zebra[ even ? 1 : 0 ] )
102048						.addClass( wo.zebra[ even ? 0 : 1 ] );
102049				}
102050			}
102051		},
102052		remove: function(table, c, wo, refreshing){
102053			if (refreshing) { return; }
102054			var k, $tb,
102055				b = c.$tbodies,
102056				rmv = (wo.zebra || [ 'even', 'odd' ]).join(' ');
102057			for (k = 0; k < b.length; k++ ){
102058				$tb = ts.processTbody(table, b.eq(k), true); // remove tbody
102059				$tb.children().removeClass(rmv);
102060				ts.processTbody(table, $tb, false); // restore tbody
102061			}
102062		}
102063	});
102064
102065})(jQuery);
102066
102067return $.tablesorter;
102068}));
102069
102070/**
102071 * @license text 2.0.16 Copyright jQuery Foundation and other contributors.
102072 * Released under MIT license, http://github.com/requirejs/text/LICENSE
102073 */
102074/*jslint regexp: true */
102075/*global require, XMLHttpRequest, ActiveXObject,
102076  define, window, process, Packages,
102077  java, location, Components, FileUtils */
102078
102079define('text',['module'], function (module) {
102080    'use strict';
102081
102082    var text, fs, Cc, Ci, xpcIsWindows,
102083        progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'],
102084        xmlRegExp = /^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im,
102085        bodyRegExp = /<body[^>]*>\s*([\s\S]+)\s*<\/body>/im,
102086        hasLocation = typeof location !== 'undefined' && location.href,
102087        defaultProtocol = hasLocation && location.protocol && location.protocol.replace(/\:/, ''),
102088        defaultHostName = hasLocation && location.hostname,
102089        defaultPort = hasLocation && (location.port || undefined),
102090        buildMap = {},
102091        masterConfig = (module.config && module.config()) || {};
102092
102093    function useDefault(value, defaultValue) {
102094        return value === undefined || value === '' ? defaultValue : value;
102095    }
102096
102097    //Allow for default ports for http and https.
102098    function isSamePort(protocol1, port1, protocol2, port2) {
102099        if (port1 === port2) {
102100            return true;
102101        } else if (protocol1 === protocol2) {
102102            if (protocol1 === 'http') {
102103                return useDefault(port1, '80') === useDefault(port2, '80');
102104            } else if (protocol1 === 'https') {
102105                return useDefault(port1, '443') === useDefault(port2, '443');
102106            }
102107        }
102108        return false;
102109    }
102110
102111    text = {
102112        version: '2.0.16',
102113
102114        strip: function (content) {
102115            //Strips <?xml ...?> declarations so that external SVG and XML
102116            //documents can be added to a document without worry. Also, if the string
102117            //is an HTML document, only the part inside the body tag is returned.
102118            if (content) {
102119                content = content.replace(xmlRegExp, "");
102120                var matches = content.match(bodyRegExp);
102121                if (matches) {
102122                    content = matches[1];
102123                }
102124            } else {
102125                content = "";
102126            }
102127            return content;
102128        },
102129
102130        jsEscape: function (content) {
102131            return content.replace(/(['\\])/g, '\\$1')
102132                .replace(/[\f]/g, "\\f")
102133                .replace(/[\b]/g, "\\b")
102134                .replace(/[\n]/g, "\\n")
102135                .replace(/[\t]/g, "\\t")
102136                .replace(/[\r]/g, "\\r")
102137                .replace(/[\u2028]/g, "\\u2028")
102138                .replace(/[\u2029]/g, "\\u2029");
102139        },
102140
102141        createXhr: masterConfig.createXhr || function () {
102142            //Would love to dump the ActiveX crap in here. Need IE 6 to die first.
102143            var xhr, i, progId;
102144            if (typeof XMLHttpRequest !== "undefined") {
102145                return new XMLHttpRequest();
102146            } else if (typeof ActiveXObject !== "undefined") {
102147                for (i = 0; i < 3; i += 1) {
102148                    progId = progIds[i];
102149                    try {
102150                        xhr = new ActiveXObject(progId);
102151                    } catch (e) {}
102152
102153                    if (xhr) {
102154                        progIds = [progId];  // so faster next time
102155                        break;
102156                    }
102157                }
102158            }
102159
102160            return xhr;
102161        },
102162
102163        /**
vendor: 9,622 bytes, lines 102164-102405
102164         * Parses a resource name into its component parts. Resource names
102165         * look like: module/name.ext!strip, where the !strip part is
102166         * optional.
102167         * @param {String} name the resource name
102168         * @returns {Object} with properties "moduleName", "ext" and "strip"
102169         * where strip is a boolean.
102170         */
102171        parseName: function (name) {
102172            var modName, ext, temp,
102173                strip = false,
102174                index = name.lastIndexOf("."),
102175                isRelative = name.indexOf('./') === 0 ||
102176                             name.indexOf('../') === 0;
102177
102178            if (index !== -1 && (!isRelative || index > 1)) {
102179                modName = name.substring(0, index);
102180                ext = name.substring(index + 1);
102181            } else {
102182                modName = name;
102183            }
102184
102185            temp = ext || modName;
102186            index = temp.indexOf("!");
102187            if (index !== -1) {
102188                //Pull off the strip arg.
102189                strip = temp.substring(index + 1) === "strip";
102190                temp = temp.substring(0, index);
102191                if (ext) {
102192                    ext = temp;
102193                } else {
102194                    modName = temp;
102195                }
102196            }
102197
102198            return {
102199                moduleName: modName,
102200                ext: ext,
102201                strip: strip
102202            };
102203        },
102204
102205        xdRegExp: /^((\w+)\:)?\/\/([^\/\\]+)/,
102206
102207        /**
102208         * Is an URL on another domain. Only works for browser use, returns
102209         * false in non-browser environments. Only used to know if an
102210         * optimized .js version of a text resource should be loaded
102211         * instead.
102212         * @param {String} url
102213         * @returns Boolean
102214         */
102215        useXhr: function (url, protocol, hostname, port) {
102216            var uProtocol, uHostName, uPort,
102217                match = text.xdRegExp.exec(url);
102218            if (!match) {
102219                return true;
102220            }
102221            uProtocol = match[2];
102222            uHostName = match[3];
102223
102224            uHostName = uHostName.split(':');
102225            uPort = uHostName[1];
102226            uHostName = uHostName[0];
102227
102228            return (!uProtocol || uProtocol === protocol) &&
102229                   (!uHostName || uHostName.toLowerCase() === hostname.toLowerCase()) &&
102230                   ((!uPort && !uHostName) || isSamePort(uProtocol, uPort, protocol, port));
102231        },
102232
102233        finishLoad: function (name, strip, content, onLoad) {
102234            content = strip ? text.strip(content) : content;
102235            if (masterConfig.isBuild) {
102236                buildMap[name] = content;
102237            }
102238            onLoad(content);
102239        },
102240
102241        load: function (name, req, onLoad, config) {
102242            //Name has format: some.module.filext!strip
102243            //The strip part is optional.
102244            //if strip is present, then that means only get the string contents
102245            //inside a body tag in an HTML string. For XML/SVG content it means
102246            //removing the <?xml ...?> declarations so the content can be inserted
102247            //into the current doc without problems.
102248
102249            // Do not bother with the work if a build and text will
102250            // not be inlined.
102251            if (config && config.isBuild && !config.inlineText) {
102252                onLoad();
102253                return;
102254            }
102255
102256            masterConfig.isBuild = config && config.isBuild;
102257
102258            var parsed = text.parseName(name),
102259                nonStripName = parsed.moduleName +
102260                    (parsed.ext ? '.' + parsed.ext : ''),
102261                url = req.toUrl(nonStripName),
102262                useXhr = (masterConfig.useXhr) ||
102263                         text.useXhr;
102264
102265            // Do not load if it is an empty: url
102266            if (url.indexOf('empty:') === 0) {
102267                onLoad();
102268                return;
102269            }
102270
102271            //Load the text. Use XHR if possible and in a browser.
102272            if (!hasLocation || useXhr(url, defaultProtocol, defaultHostName, defaultPort)) {
102273                text.get(url, function (content) {
102274                    text.finishLoad(name, parsed.strip, content, onLoad);
102275                }, function (err) {
102276                    if (onLoad.error) {
102277                        onLoad.error(err);
102278                    }
102279                });
102280            } else {
102281                //Need to fetch the resource across domains. Assume
102282                //the resource has been optimized into a JS module. Fetch
102283                //by the module name + extension, but do not include the
102284                //!strip part to avoid file system issues.
102285                req([nonStripName], function (content) {
102286                    text.finishLoad(parsed.moduleName + '.' + parsed.ext,
102287                                    parsed.strip, content, onLoad);
102288                }, function (err) {
102289                    if (onLoad.error) {
102290                        onLoad.error(err);
102291                    }
102292                });
102293            }
102294        },
102295
102296        write: function (pluginName, moduleName, write, config) {
102297            if (buildMap.hasOwnProperty(moduleName)) {
102298                var content = text.jsEscape(buildMap[moduleName]);
102299                write.asModule(pluginName + "!" + moduleName,
102300                               "define(function () { return '" +
102301                                   content +
102302                               "';});\n");
102303            }
102304        },
102305
102306        writeFile: function (pluginName, moduleName, req, write, config) {
102307            var parsed = text.parseName(moduleName),
102308                extPart = parsed.ext ? '.' + parsed.ext : '',
102309                nonStripName = parsed.moduleName + extPart,
102310                //Use a '.js' file name so that it indicates it is a
102311                //script that can be loaded across domains.
102312                fileName = req.toUrl(parsed.moduleName + extPart) + '.js';
102313
102314            //Leverage own load() method to load plugin value, but only
102315            //write out values that do not have the strip argument,
102316            //to avoid any potential issues with ! in file names.
102317            text.load(nonStripName, req, function (value) {
102318                //Use own write() method to construct full module value.
102319                //But need to create shell that translates writeFile's
102320                //write() to the right interface.
102321                var textWrite = function (contents) {
102322                    return write(fileName, contents);
102323                };
102324                textWrite.asModule = function (moduleName, contents) {
102325                    return write.asModule(moduleName, fileName, contents);
102326                };
102327
102328                text.write(pluginName, nonStripName, textWrite, config);
102329            }, config);
102330        }
102331    };
102332
102333    if (masterConfig.env === 'node' || (!masterConfig.env &&
102334            typeof process !== "undefined" &&
102335            process.versions &&
102336            !!process.versions.node &&
102337            !process.versions['node-webkit'] &&
102338            !process.versions['atom-shell'])) {
102339        //Using special require.nodeRequire, something added by r.js.
102340        fs = require.nodeRequire('fs');
102341
102342        text.get = function (url, callback, errback) {
102343            try {
102344                var file = fs.readFileSync(url, 'utf8');
102345                //Remove BOM (Byte Mark Order) from utf8 files if it is there.
102346                if (file[0] === '\uFEFF') {
102347                    file = file.substring(1);
102348                }
102349                callback(file);
102350            } catch (e) {
102351                if (errback) {
102352                    errback(e);
102353                }
102354            }
102355        };
102356    } else if (masterConfig.env === 'xhr' || (!masterConfig.env &&
102357            text.createXhr())) {
102358        text.get = function (url, callback, errback, headers) {
102359            var xhr = text.createXhr(), header;
102360            xhr.open('GET', url, true);
102361
102362            //Allow plugins direct access to xhr headers
102363            if (headers) {
102364                for (header in headers) {
102365                    if (headers.hasOwnProperty(header)) {
102366                        xhr.setRequestHeader(header.toLowerCase(), headers[header]);
102367                    }
102368                }
102369            }
102370
102371            //Allow overrides specified in config
102372            if (masterConfig.onXhr) {
102373                masterConfig.onXhr(xhr, url);
102374            }
102375
102376            xhr.onreadystatechange = function (evt) {
102377                var status, err;
102378                //Do not explicitly handle errors, those should be
102379                //visible via console output in the browser.
102380                if (xhr.readyState === 4) {
102381                    status = xhr.status || 0;
102382                    if (status > 399 && status < 600) {
102383                        //An http 4xx or 5xx error. Signal an error.
102384                        err = new Error(url + ' HTTP status: ' + status);
102385                        err.xhr = xhr;
102386                        if (errback) {
102387                            errback(err);
102388                        }
102389                    } else {
102390                        callback(xhr.responseText);
102391                    }
102392
102393                    if (masterConfig.onXhrComplete) {
102394                        masterConfig.onXhrComplete(xhr, url);
102395                    }
102396                }
102397            };
102398            xhr.send(null);
102399        };
102400    } else if (masterConfig.env === 'rhino' || (!masterConfig.env &&
102401            typeof Packages !== 'undefined' && typeof java !== 'undefined')) {
102402        //Why Java, why is this so awkward?
102403        text.get = function (url, callback) {
102404            var stringBuffer, line,
102405                encoding = "utf-8",
102406                file = new java.io.File(url),
102407                lineSeparator = java.lang.System.getProperty("line.separator"),
102408                input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(file), encoding)),
102409                content = '';
102410            try {
102411                stringBuffer = new java.lang.StringBuffer();
102412                line = input.readLine();
102413
102414                // Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324
102415                // http://www.unicode.org/faq/utf_bom.html
102416
102417                // Note that when we use utf-8, the BOM should appear as "EF BB BF", but it doesn't due to this bug in the JDK:
102418                // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058
102419                if (line && line.length() && line.charAt(0) === 0xfeff) {
102420                    // Eat the BOM, since we've already found the encoding on this file,
102421                    // and we plan to concatenating this buffer with others; the BOM should
102422                    // only appear at the top of a file.
102423                    line = line.substring(1);
102424                }
102425
102426                if (line !== null) {
102427                    stringBuffer.append(line);
102428                }
102429
102430                while ((line = input.readLine()) !== null) {
102431                    stringBuffer.append(lineSeparator);
102432                    stringBuffer.append(line);
102433                }
102434                //Make sure we return a JavaScript string and not a Java string.
102435                content = String(stringBuffer.toString()); //String
102436            } finally {
102437                input.close();
102438            }
102439            callback(content);
102440        };
102441    } else if (masterConfig.env === 'xpconnect' || (!masterConfig.env &&
102442            typeof Components !== 'undefined' && Components.classes &&
102443            Components.interfaces)) {
102444        //Avert your gaze!
102445        Cc = Components.classes;
102446        Ci = Components.interfaces;
102447        Components.utils['import']('resource://gre/modules/FileUtils.jsm');
102448        xpcIsWindows = ('@mozilla.org/windows-registry-key;1' in Cc);
102449
102450        text.get = function (url, callback) {
102451            var inStream, convertStream, fileObj,
102452                readData = {};
102453
102454            if (xpcIsWindows) {
102455                url = url.replace(/\//g, '\\');
102456            }
102457
102458            fileObj = new FileUtils.File(url);
102459
102460            //XPCOM, you so crazy
102461            try {
102462                inStream = Cc['@mozilla.org/network/file-input-stream;1']
102463                           .createInstance(Ci.nsIFileInputStream);
102464                inStream.init(fileObj, 1, 0, false);
102465
102466                convertStream = Cc['@mozilla.org/intl/converter-input-stream;1']
102467                                .createInstance(Ci.nsIConverterInputStream);
102468                convertStream.init(inStream, "utf-8", inStream.available(),
102469                Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
102470
102471                convertStream.readString(inStream.available(), readData);
102472                convertStream.close();
102473                inStream.close();
102474                callback(readData.value);
102475            } catch (e) {
102476                throw new Error((fileObj && fileObj.path || '') + ': ' + e);
102477            }
102478        };
102479    }
102480    return text;
102481});
102482
102483/*
102484 * JavaScript Templates
102485 * https://github.com/blueimp/JavaScript-Templates
102486 *
102487 * Copyright 2011, Sebastian Tschan
102488 * https://blueimp.net
102489 *
102490 * Licensed under the MIT license:
102491 * https://opensource.org/licenses/MIT
102492 *
102493 * Inspired by John Resig's JavaScript Micro-Templating:
102494 * http://ejohn.org/blog/javascript-micro-templating/
102495 */
102496
102497/* global define */
102498
102499/* eslint-disable strict */
102500
102501;(function ($) {
102502  'use strict'
102503  var tmpl = function (str, data) {
102504    var f = !/[^\w\-.:]/.test(str)
102505      ? (tmpl.cache[str] = tmpl.cache[str] || tmpl(tmpl.load(str)))
102506      : new Function( // eslint-disable-line no-new-func
102507          tmpl.arg + ',tmpl',
102508          'var _e=tmpl.encode' +
102509            tmpl.helper +
102510            ",_s='" +
102511            str.replace(tmpl.regexp, tmpl.func) +
102512            "';return _s;"
102513        )
102514    return data
102515      ? f(data, tmpl)
102516      : function (data) {
102517          return f(data, tmpl)
102518        }
102519  }
102520  tmpl.cache = {}
102521  tmpl.load = function (id) {
102522    return document.getElementById(id).innerHTML
102523  }
102524  tmpl.regexp =
102525    /([\s'\\])(?!(?:[^{]|\{(?!%))*%\})|(?:\{%(=|#)([\s\S]+?)%\})|(\{%)|(%\})/g
102526  tmpl.func = function (s, p1, p2, p3, p4, p5) {
102527    if (p1) {
102528      // whitespace, quote and backspace in HTML context
102529      return (
102530        {
102531          '\n': '\\n',
102532          '\r': '\\r',
102533          '\t': '\\t',
102534          ' ': ' '
102535        }[p1] || '\\' + p1
102536      )
102537    }
102538    if (p2) {
102539      // interpolation: {%=prop%}, or unescaped: {%#prop%}
102540      if (p2 === '=') {
102541        return "'+_e(" + p3 + ")+'"
102542      }
102543      return "'+(" + p3 + "==null?'':" + p3 + ")+'"
102544    }
102545    if (p4) {
102546      // evaluation start tag: {%
102547      return "';"
102548    }
102549    if (p5) {
102550      // evaluation end tag: %}
102551      return "_s+='"
102552    }
102553  }
102554  tmpl.encReg = /[<>&"'\x00]/g // eslint-disable-line no-control-regex
102555  tmpl.encMap = {
102556    '<': '&lt;',
102557    '>': '&gt;',
102558    '&': '&amp;',
102559    '"': '&quot;',
102560    "'": '&#39;'
102561  }
102562  tmpl.encode = function (s) {
102563    // eslint-disable-next-line eqeqeq
102564    return (s == null ? '' : '' + s).replace(tmpl.encReg, function (c) {
102565      return tmpl.encMap[c] || ''
102566    })
102567  }
102568  tmpl.arg = 'o'
102569  tmpl.helper =
102570    ",print=function(s,e){_s+=e?(s==null?'':s):_e(s);}" +
102571    ',include=function(s,d){_s+=tmpl(s,d);}'
102572  if (typeof define === 'function' && define.amd) {
102573    define('tmpl',[],function () {
102574      return tmpl
102575    })
102576  } else if (typeof module === 'object' && module.exports) {
102577    module.exports = tmpl
102578  } else {
102579    $.tmpl = tmpl
102580  }
102581})(this)
102582;
102583/*
102584 * Toastr
102585 * Copyright 2012-2015
102586 * Authors: John Papa, Hans Fjällemark, and Tim Ferrell.
102587 * All Rights Reserved.
102588 * Use, reproduction, distribution, and modification of this code is subject to the terms and
102589 * conditions of the MIT license, available at http://www.opensource.org/licenses/mit-license.php
102590 *
102591 * ARIA Support: Greta Krafsig
102592 *
102593 * Project: https://github.com/CodeSeven/toastr
102594 */
102595/* global define */
102596(function (define) {
102597    define('toastr',['jquery'], function ($) {
102598        return (function () {
102599            var $container;
102600            var listener;
102601            var toastId = 0;
102602            var toastType = {
102603                error: 'error',
102604                info: 'info',
102605                success: 'success',
102606                warning: 'warning'
102607            };
102608
102609            var toastr = {
102610                clear: clear,
102611                remove: remove,
102612                error: error,
102613                getContainer: getContainer,
102614                info: info,
102615                options: {},
102616                subscribe: subscribe,
102617                success: success,
102618                version: '2.1.3
vendor: 16,635 bytes, lines 102618-103058
102618',
102619                warning: warning
102620            };
102621
102622            var previousToast;
102623
102624            return toastr;
102625
102626            ////////////////
102627
102628            function error(message, title, optionsOverride) {
102629                return notify({
102630                    type: toastType.error,
102631                    iconClass: getOptions().iconClasses.error,
102632                    message: message,
102633                    optionsOverride: optionsOverride,
102634                    title: title
102635                });
102636            }
102637
102638            function getContainer(options, create) {
102639                if (!options) { options = getOptions(); }
102640                $container = $('#' + options.containerId);
102641                if ($container.length) {
102642                    return $container;
102643                }
102644                if (create) {
102645                    $container = createContainer(options);
102646                }
102647                return $container;
102648            }
102649
102650            function info(message, title, optionsOverride) {
102651                return notify({
102652                    type: toastType.info,
102653                    iconClass: getOptions().iconClasses.info,
102654                    message: message,
102655                    optionsOverride: optionsOverride,
102656                    title: title
102657                });
102658            }
102659
102660            function subscribe(callback) {
102661                listener = callback;
102662            }
102663
102664            function success(message, title, optionsOverride) {
102665                return notify({
102666                    type: toastType.success,
102667                    iconClass: getOptions().iconClasses.success,
102668                    message: message,
102669                    optionsOverride: optionsOverride,
102670                    title: title
102671                });
102672            }
102673
102674            function warning(message, title, optionsOverride) {
102675                return notify({
102676                    type: toastType.warning,
102677                    iconClass: getOptions().iconClasses.warning,
102678                    message: message,
102679                    optionsOverride: optionsOverride,
102680                    title: title
102681                });
102682            }
102683
102684            function clear($toastElement, clearOptions) {
102685                var options = getOptions();
102686                if (!$container) { getContainer(options); }
102687                if (!clearToast($toastElement, options, clearOptions)) {
102688                    clearContainer(options);
102689                }
102690            }
102691
102692            function remove($toastElement) {
102693                var options = getOptions();
102694                if (!$container) { getContainer(options); }
102695                if ($toastElement && $(':focus', $toastElement).length === 0) {
102696                    removeToast($toastElement);
102697                    return;
102698                }
102699                if ($container.children().length) {
102700                    $container.remove();
102701                }
102702            }
102703
102704            // internal functions
102705
102706            function clearContainer (options) {
102707                var toastsToClear = $container.children();
102708                for (var i = toastsToClear.length - 1; i >= 0; i--) {
102709                    clearToast($(toastsToClear[i]), options);
102710                }
102711            }
102712
102713            function clearToast ($toastElement, options, clearOptions) {
102714                var force = clearOptions && clearOptions.force ? clearOptions.force : false;
102715                if ($toastElement && (force || $(':focus', $toastElement).length === 0)) {
102716                    $toastElement[options.hideMethod]({
102717                        duration: options.hideDuration,
102718                        easing: options.hideEasing,
102719                        complete: function () { removeToast($toastElement); }
102720                    });
102721                    return true;
102722                }
102723                return false;
102724            }
102725
102726            function createContainer(options) {
102727                $container = $('<div/>')
102728                    .attr('id', options.containerId)
102729                    .addClass(options.positionClass);
102730
102731                $container.appendTo($(options.target));
102732                return $container;
102733            }
102734
102735            function getDefaults() {
102736                return {
102737                    tapToDismiss: true,
102738                    toastClass: 'toast',
102739                    containerId: 'toast-container',
102740                    debug: false,
102741
102742                    showMethod: 'fadeIn', //fadeIn, slideDown, and show are built into jQuery
102743                    showDuration: 300,
102744                    showEasing: 'swing', //swing and linear are built into jQuery
102745                    onShown: undefined,
102746                    hideMethod: 'fadeOut',
102747                    hideDuration: 1000,
102748                    hideEasing: 'swing',
102749                    onHidden: undefined,
102750                    closeMethod: false,
102751                    closeDuration: false,
102752                    closeEasing: false,
102753                    closeOnHover: true,
102754
102755                    extendedTimeOut: 1000,
102756                    iconClasses: {
102757                        error: 'toast-error',
102758                        info: 'toast-info',
102759                        success: 'toast-success',
102760                        warning: 'toast-warning'
102761                    },
102762                    iconClass: 'toast-info',
102763                    positionClass: 'toast-top-right',
102764                    timeOut: 5000, // Set timeOut and extendedTimeOut to 0 to make it sticky
102765                    titleClass: 'toast-title',
102766                    messageClass: 'toast-message',
102767                    escapeHtml: false,
102768                    target: 'body',
102769                    closeHtml: '<button type="button">&times;</button>',
102770                    closeClass: 'toast-close-button',
102771                    newestOnTop: true,
102772                    preventDuplicates: false,
102773                    progressBar: false,
102774                    progressClass: 'toast-progress',
102775                    rtl: false
102776                };
102777            }
102778
102779            function publish(args) {
102780                if (!listener) { return; }
102781                listener(args);
102782            }
102783
102784            function notify(map) {
102785                var options = getOptions();
102786                var iconClass = map.iconClass || options.iconClass;
102787
102788                if (typeof (map.optionsOverride) !== 'undefined') {
102789                    options = $.extend(options, map.optionsOverride);
102790                    iconClass = map.optionsOverride.iconClass || iconClass;
102791                }
102792
102793                if (shouldExit(options, map)) { return; }
102794
102795                toastId++;
102796
102797                $container = getContainer(options, true);
102798
102799                var intervalId = null;
102800                var $toastElement = $('<div/>');
102801                var $titleElement = $('<div/>');
102802                var $messageElement = $('<div/>');
102803                var $progressElement = $('<div/>');
102804                var $closeElement = $(options.closeHtml);
102805                var progressBar = {
102806                    intervalId: null,
102807                    hideEta: null,
102808                    maxHideTime: null
102809                };
102810                var response = {
102811                    toastId: toastId,
102812                    state: 'visible',
102813                    startTime: new Date(),
102814                    options: options,
102815                    map: map
102816                };
102817
102818                personalizeToast();
102819
102820                displayToast();
102821
102822                handleEvents();
102823
102824                publish(response);
102825
102826                if (options.debug && console) {
102827                    console.log(response);
102828                }
102829
102830                return $toastElement;
102831
102832                function escapeHtml(source) {
102833                    if (source == null) {
102834                        source = '';
102835                    }
102836
102837                    return source
102838                        .replace(/&/g, '&amp;')
102839                        .replace(/"/g, '&quot;')
102840                        .replace(/'/g, '&#39;')
102841                        .replace(/</g, '&lt;')
102842                        .replace(/>/g, '&gt;');
102843                }
102844
102845                function personalizeToast() {
102846                    setIcon();
102847                    setTitle();
102848                    setMessage();
102849                    setCloseButton();
102850                    setProgressBar();
102851                    setRTL();
102852                    setSequence();
102853                    setAria();
102854                }
102855
102856                function setAria() {
102857                    var ariaValue = '';
102858                    switch (map.iconClass) {
102859                        case 'toast-success':
102860                        case 'toast-info':
102861                            ariaValue =  'polite';
102862                            break;
102863                        default:
102864                            ariaValue = 'assertive';
102865                    }
102866                    $toastElement.attr('aria-live', ariaValue);
102867                }
102868
102869                function handleEvents() {
102870                    if (options.closeOnHover) {
102871                        $toastElement.hover(stickAround, delayedHideToast);
102872                    }
102873
102874                    if (!options.onclick && options.tapToDismiss) {
102875                        $toastElement.click(hideToast);
102876                    }
102877
102878                    if (options.closeButton && $closeElement) {
102879                        $closeElement.click(function (event) {
102880                            if (event.stopPropagation) {
102881                                event.stopPropagation();
102882                            } else if (event.cancelBubble !== undefined && event.cancelBubble !== true) {
102883                                event.cancelBubble = true;
102884                            }
102885
102886                            if (options.onCloseClick) {
102887                                options.onCloseClick(event);
102888                            }
102889
102890                            hideToast(true);
102891                        });
102892                    }
102893
102894                    if (options.onclick) {
102895                        $toastElement.click(function (event) {
102896                            options.onclick(event);
102897                            hideToast();
102898                        });
102899                    }
102900                }
102901
102902                function displayToast() {
102903                    $toastElement.hide();
102904
102905                    $toastElement[options.showMethod](
102906                        {duration: options.showDuration, easing: options.showEasing, complete: options.onShown}
102907                    );
102908
102909                    if (options.timeOut > 0) {
102910                        intervalId = setTimeout(hideToast, options.timeOut);
102911                        progressBar.maxHideTime = parseFloat(options.timeOut);
102912                        progressBar.hideEta = new Date().getTime() + progressBar.maxHideTime;
102913                        if (options.progressBar) {
102914                            progressBar.intervalId = setInterval(updateProgress, 10);
102915                        }
102916                    }
102917                }
102918
102919                function setIcon() {
102920                    if (map.iconClass) {
102921                        $toastElement.addClass(options.toastClass).addClass(iconClass);
102922                    }
102923                }
102924
102925                function setSequence() {
102926                    if (options.newestOnTop) {
102927                        $container.prepend($toastElement);
102928                    } else {
102929                        $container.append($toastElement);
102930                    }
102931                }
102932
102933                function setTitle() {
102934                    if (map.title) {
102935                        var suffix = map.title;
102936                        if (options.escapeHtml) {
102937                            suffix = escapeHtml(map.title);
102938                        }
102939                        $titleElement.append(suffix).addClass(options.titleClass);
102940                        $toastElement.append($titleElement);
102941                    }
102942                }
102943
102944                function setMessage() {
102945                    if (map.message) {
102946                        var suffix = map.message;
102947                        if (options.escapeHtml) {
102948                            suffix = escapeHtml(map.message);
102949                        }
102950                        $messageElement.append(suffix).addClass(options.messageClass);
102951                        $toastElement.append($messageElement);
102952                    }
102953                }
102954
102955                function setCloseButton() {
102956                    if (options.closeButton) {
102957                        $closeElement.addClass(options.closeClass).attr('role', 'button');
102958                        $toastElement.prepend($closeElement);
102959                    }
102960                }
102961
102962                function setProgressBar() {
102963                    if (options.progressBar) {
102964                        $progressElement.addClass(options.progressClass);
102965                        $toastElement.prepend($progressElement);
102966                    }
102967                }
102968
102969                function setRTL() {
102970                    if (options.rtl) {
102971                        $toastElement.addClass('rtl');
102972                    }
102973                }
102974
102975                function shouldExit(options, map) {
102976                    if (options.preventDuplicates) {
102977                        if (map.message === previousToast) {
102978                            return true;
102979                        } else {
102980                            previousToast = map.message;
102981                        }
102982                    }
102983                    return false;
102984                }
102985
102986                function hideToast(override) {
102987                    var method = override && options.closeMethod !== false ? options.closeMethod : options.hideMethod;
102988                    var duration = override && options.closeDuration !== false ?
102989                        options.closeDuration : options.hideDuration;
102990                    var easing = override && options.closeEasing !== false ? options.closeEasing : options.hideEasing;
102991                    if ($(':focus', $toastElement).length && !override) {
102992                        return;
102993                    }
102994                    clearTimeout(progressBar.intervalId);
102995                    return $toastElement[method]({
102996                        duration: duration,
102997                        easing: easing,
102998                        complete: function () {
102999                            removeToast($toastElement);
103000                            clearTimeout(intervalId);
103001                            if (options.onHidden && response.state !== 'hidden') {
103002                                options.onHidden();
103003                            }
103004                            response.state = 'hidden';
103005                            response.endTime = new Date();
103006                            publish(response);
103007                        }
103008                    });
103009                }
103010
103011                function delayedHideToast() {
103012                    if (options.timeOut > 0 || options.extendedTimeOut > 0) {
103013                        intervalId = setTimeout(hideToast, options.extendedTimeOut);
103014                        progressBar.maxHideTime = parseFloat(options.extendedTimeOut);
103015                        progressBar.hideEta = new Date().getTime() + progressBar.maxHideTime;
103016                    }
103017                }
103018
103019                function stickAround() {
103020                    clearTimeout(intervalId);
103021                    progressBar.hideEta = 0;
103022                    $toastElement.stop(true, true)[options.showMethod](
103023                        {duration: options.showDuration, easing: options.showEasing}
103024                    );
103025                }
103026
103027                function updateProgress() {
103028                    var percentage = ((progressBar.hideEta - (new Date().getTime())) / progressBar.maxHideTime) * 100;
103029                    $progressElement.width(percentage + '%');
103030                }
103031            }
103032
103033            function getOptions() {
103034                return $.extend({}, getDefaults(), toastr.options);
103035            }
103036
103037            function removeToast($toastElement) {
103038                if (!$container) { $container = getContainer(); }
103039                if ($toastElement.is(':visible')) {
103040                    return;
103041                }
103042                $toastElement.remove();
103043                $toastElement = null;
103044                if ($container.children().length === 0) {
103045                    $container.remove();
103046                    previousToast = undefined;
103047                }
103048            }
103049
103050        })();
103051    });
103052}(typeof define === 'function' && define.amd ? define : function (deps, factory) {
103053    if (typeof module !== 'undefined' && module.exports) { //Node
103054        module.exports = factory(require('jquery'));
103055    } else {
103056        window.toastr = factory(window.jQuery);
103057    }
103058}));
103059
103060(function ($) {
103061    $.fn.uniformHeight = function () {
103062        var maxHeight = 0,
103063            wrapper,
103064            wrapperHeight;
103065
103066        return this.each(function () {
103067
103068            // TODO Doesn't take account of image scaling when in bootstrap thumbnails.
103069            // For example when you use very large images and use this plugin it
103070            // incorrectly calculates the height as very large large. This is probably
103071            // because it prevents the styles getting to the image to make it 
103072            // max-width: 100%.
103073
103074            // Applying a wrapper to the contents of the current element to get reliable height
103075            wrapper = $(this).wrapInner('<div class="wrapper" />').children('.wrapper');
103076            wrapperHeight = wrapper.outerHeight();
103077
103078            maxHeight = Math.max(maxHeight, wrapperHeight);
103079
103080            // Remove the wrapper
103081            wrapper.children().unwrap();
103082
103083        }).height(maxHeight);
103084    }
103085})(jQuery);
103086
103087define("uniformHeight", ["jquery"], (function (global) {
103088    return function () {
103089        var ret, fn;
103090        return ret || global.$;
103091    };
103092}(this)));
103093
103094define('userHeartBeat',[],
103095    function () {
103096        return {
103097            heartbeat: function (token, userId, apiUrl) {
103098                if (!token || !userId || !apiUrl) {
103099                    console.warn('invalid token || userId || apiUrl supplied!');
103100                    return;
103101                }
103102
103103                try {
103104                    var key = `heartbeat-${userId}`;
103105                    var seconds = 300
103106                    var isSending = true;
103107                    var now = new Date();
103108                    var lastHeartBeat = sessionStorage.getItem(key);
103109
103110                    if (lastHeartBeat !== null) {
103111                        var dateLastLogged = new Date(lastHeartBeat);
103112                        var secondsSinceLastLogged = (now.getTime() - dateLastLogged.getTime()) / 1000;
103113                        console.warn('Last hearbeat found', dateLastLogged, now, secondsSinceLastLogged);
103114                        isSending = secondsSinceLastLogged > seconds;
103115                    }
103116
103117                    if (!isSending) return;
103118
103119                    console.warn('Sending heartbeat...');
103120
103121                    sessionStorage.setItem(key, now.toISOString());
103122
103123                    var apiUri = `${apiUrl}/v3/users/${userId}/heartbeat`;
103124                    var httpRequest = new XMLHttpRequest();
103125                    httpRequest.open('POST', apiUri);
103126
103127                    httpRequest.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
103128                    httpRequest.setRequestHeader("Authorization", "Bearer " + token);
103129
103130                    httpRequest.send(JSON.stringify({
103131                        source: 'DiagnosticQuestions'
103132                    }));
103133                } catch (e) {
103134                    console.error(e);
103135                }
103136            }
103137        }
103138    });
103139
103140//# sourceMappingURL=vendor-bundle.js.c0933e4a.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.