PageSourceSearch

https://inspirationsnews.com/bundles/js?v=xWOoNwvxCgMFoY3WzaytbYm7cHd3OA_vb5OUVzFnc_g1

js inspirationsnews.com collected 2026-09-30 14:04:16 UTC 1,408,641 bytes, 41,193 lines download raw bytes

vendor: 113,528 bytes, lines 1-4080
1/* Minification failed. Returning unminified contents.
2(32337,9-15): run-time error JS1300: Strict-mode does not allow assignment to undefined variables: Base64
3 */
4/*!
5 * jQuery JavaScript Library v3.7.1
6 * https://jquery.com/
7 *
8 * Copyright OpenJS Foundation and other contributors
9 * Released under the MIT license
10 * https://jquery.org/license
11 *
12 * Date: 2023-08-28T13:37Z
13 */
14( function( global, factory ) {
15
16	"use strict";
17
18	if ( typeof module === "object" && typeof module.exports === "object" ) {
19
20		// For CommonJS and CommonJS-like environments where a proper `window`
21		// is present, execute the factory and get jQuery.
22		// For environments that do not have a `window` with a `document`
23		// (such as Node.js), expose a factory as module.exports.
24		// This accentuates the need for the creation of a real `window`.
25		// e.g. var jQuery = require("jquery")(window);
26		// See ticket trac-14549 for more info.
27		module.exports = global.document ?
28			factory( global, true ) :
29			function( w ) {
30				if ( !w.document ) {
31					throw new Error( "jQuery requires a window with a document" );
32				}
33				return factory( w );
34			};
35	} else {
36		factory( global );
37	}
38
39// Pass this if window is not defined yet
40} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
41
42// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1
43// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode
44// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common
45// enough that all such attempts are guarded in a try block.
46"use strict";
47
48var arr = [];
49
50var getProto = Object.getPrototypeOf;
51
52var slice = arr.slice;
53
54var flat = arr.flat ? function( array ) {
55	return arr.flat.call( array );
56} : function( array ) {
57	return arr.concat.apply( [], array );
58};
59
60
61var push = arr.push;
62
63var indexOf = arr.indexOf;
64
65var class2type = {};
66
67var toString = class2type.toString;
68
69var hasOwn = class2type.hasOwnProperty;
70
71var fnToString = hasOwn.toString;
72
73var ObjectFunctionString = fnToString.call( Object );
74
75var support = {};
76
77var isFunction = function isFunction( obj ) {
78
79		// Support: Chrome <=57, Firefox <=52
80		// In some browsers, typeof returns "function" for HTML <object> elements
81		// (i.e., `typeof document.createElement( "object" ) === "function"`).
82		// We don't want to classify *any* DOM node as a function.
83		// Support: QtWeb <=3.8.5, WebKit <=534.34, wkhtmltopdf tool <=0.12.5
84		// Plus for old WebKit, typeof returns "function" for HTML collections
85		// (e.g., `typeof document.getElementsByTagName("div") === "function"`). (gh-4756)
86		return typeof obj === "function" && typeof obj.nodeType !== "number" &&
87			typeof obj.item !== "function";
88	};
89
90
91var isWindow = function isWindow( obj ) {
92		return obj != null && obj === obj.window;
93	};
94
95
96var document = window.document;
97
98
99
100	var preservedScriptAttributes = {
101		type: true,
102		src: true,
103		nonce: true,
104		noModule: true
105	};
106
107	function DOMEval( code, node, doc ) {
108		doc = doc || document;
109
110		var i, val,
111			script = doc.createElement( "script" );
112
113		script.text = code;
114		if ( node ) {
115			for ( i in preservedScriptAttributes ) {
116
117				// Support: Firefox 64+, Edge 18+
118				// Some browsers don't support the "nonce" property on scripts.
119				// On the other hand, just using `getAttribute` is not enough as
120				// the `nonce` attribute is reset to an empty string whenever it
121				// becomes browsing-context connected.
122				// See https://github.com/whatwg/html/issues/2369
123				// See https://html.spec.whatwg.org/#nonce-attributes
124				// The `node.getAttribute` check was added for the sake of
125				// `jQuery.globalEval` so that it can fake a nonce-containing node
126				// via an object.
127				val = node[ i ] || node.getAttribute && node.getAttribute( i );
128				if ( val ) {
129					script.setAttribute( i, val );
130				}
131			}
132		}
133		doc.head.appendChild( script ).parentNode.removeChild( script );
134	}
135
136
137function toType( obj ) {
138	if ( obj == null ) {
139		return obj + "";
140	}
141
142	// Support: Android <=2.3 only (functionish RegExp)
143	return typeof obj === "object" || typeof obj === "function" ?
144		class2type[ toString.call( obj ) ] || "object" :
145		typeof obj;
146}
147/* global Symbol */
148// Defining this global in .eslintrc.json would create a danger of using the global
149// unguarded in another place, it seems safer to define global only for this module
150
151
152
153var version = "3.7.1",
154
155	rhtmlSuffix = /HTML$/i,
156
157	// Define a local copy of jQuery
158	jQuery = function( selector, context ) {
159
160		// The jQuery object is actually just the init constructor 'enhanced'
161		// Need init if jQuery is called (just allow error to be thrown if not included)
162		return new jQuery.fn.init( selector, context );
163	};
164
165jQuery.fn = jQuery.prototype = {
166
167	// The current version of jQuery being used
168	jquery: version,
169
170	constructor: jQuery,
171
172	// The default length of a jQuery object is 0
173	length: 0,
174
175	toArray: function() {
176		return slice.call( this );
177	},
178
179	// Get the Nth element in the matched element set OR
180	// Get the whole matched element set as a clean array
181	get: function( num ) {
182
183		// Return all the elements in a clean array
184		if ( num == null ) {
185			return slice.call( this );
186		}
187
188		// Return just the one element from the set
189		return num < 0 ? this[ num + this.length ] : this[ num ];
190	},
191
192	// Take an array of elements and push it onto the stack
193	// (returning the new matched element set)
194	pushStack: function( elems ) {
195
196		// Build a new jQuery matched element set
197		var ret = jQuery.merge( this.constructor(), elems );
198
199		// Add the old object onto the stack (as a reference)
200		ret.prevObject = this;
201
202		// Return the newly-formed element set
203		return ret;
204	},
205
206	// Execute a callback for every element in the matched set.
207	each: function( callback ) {
208		return jQuery.each( this, callback );
209	},
210
211	map: function( callback ) {
212		return this.pushStack( jQuery.map( this, function( elem, i ) {
213			return callback.call( elem, i, elem );
214		} ) );
215	},
216
217	slice: function() {
218		return this.pushStack( slice.apply( this, arguments ) );
219	},
220
221	first: function() {
222		return this.eq( 0 );
223	},
224
225	last: function() {
226		return this.eq( -1 );
227	},
228
229	even: function() {
230		return this.pushStack( jQuery.grep( this, function( _elem, i ) {
231			return ( i + 1 ) % 2;
232		} ) );
233	},
234
235	odd: function() {
236		return this.pushStack( jQuery.grep( this, function( _elem, i ) {
237			return i % 2;
238		} ) );
239	},
240
241	eq: function( i ) {
242		var len = this.length,
243			j = +i + ( i < 0 ? len : 0 );
244		return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] );
245	},
246
247	end: function() {
248		return this.prevObject || this.constructor();
249	},
250
251	// For internal use only.
252	// Behaves like an Array's method, not like a jQuery method.
253	push: push,
254	sort: arr.sort,
255	splice: arr.splice
256};
257
258jQuery.extend = jQuery.fn.extend = function() {
259	var options, name, src, copy, copyIsArray, clone,
260		target = arguments[ 0 ] || {},
261		i = 1,
262		length = arguments.length,
263		deep = false;
264
265	// Handle a deep copy situation
266	if ( typeof target === "boolean" ) {
267		deep = target;
268
269		// Skip the boolean and the target
270		target = arguments[ i ] || {};
271		i++;
272	}
273
274	// Handle case when target is a string or something (possible in deep copy)
275	if ( typeof target !== "object" && !isFunction( target ) ) {
276		target = {};
277	}
278
279	// Extend jQuery itself if only one argument is passed
280	if ( i === length ) {
281		target = this;
282		i--;
283	}
284
285	for ( ; i < length; i++ ) {
286
287		// Only deal with non-null/undefined values
288		if ( ( options = arguments[ i ] ) != null ) {
289
290			// Extend the base object
291			for ( name in options ) {
292				copy = options[ name ];
293
294				// Prevent Object.prototype pollution
295				// Prevent never-ending loop
296				if ( name === "__proto__" || target === copy ) {
297					continue;
298				}
299
300				// Recurse if we're merging plain objects or arrays
301				if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
302					( copyIsArray = Array.isArray( copy ) ) ) ) {
303					src = target[ name ];
304
305					// Ensure proper type for the source value
306					if ( copyIsArray && !Array.isArray( src ) ) {
307						clone = [];
308					} else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) {
309						clone = {};
310					} else {
311						clone = src;
312					}
313					copyIsArray = false;
314
315					// Never move original objects, clone them
316					target[ name ] = jQuery.extend( deep, clone, copy );
317
318				// Don't bring in undefined values
319				} else if ( copy !== undefined ) {
320					target[ name ] = copy;
321				}
322			}
323		}
324	}
325
326	// Return the modified object
327	return target;
328};
329
330jQuery.extend( {
331
332	// Unique for each copy of jQuery on the page
333	expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
334
335	// Assume jQuery is ready without the ready module
336	isReady: true,
337
338	error: function( msg ) {
339		throw new Error( msg );
340	},
341
342	noop: function() {},
343
344	isPlainObject: function( obj ) {
345		var proto, Ctor;
346
347		// Detect obvious negatives
348		// Use toString instead of jQuery.type to catch host objects
349		if ( !obj || toString.call( obj ) !== "[object Object]" ) {
350			return false;
351		}
352
353		proto = getProto( obj );
354
355		// Objects with no prototype (e.g., `Object.create( null )`) are plain
356		if ( !proto ) {
357			return true;
358		}
359
360		// Objects with prototype are plain iff they were constructed by a global Object function
361		Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor;
362		return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString;
363	},
364
365	isEmptyObject: function( obj ) {
366		var name;
367
368		for ( name in obj ) {
369			return false;
370		}
371		return true;
372	},
373
374	// Evaluates a script in a provided context; falls back to the global one
375	// if not specified.
376	globalEval: function( code, options, doc ) {
377		DOMEval( code, { nonce: options && options.nonce }, doc );
378	},
379
380	each: function( obj, callback ) {
381		var length, i = 0;
382
383		if ( isArrayLike( obj ) ) {
384			length = obj.length;
385			for ( ; i < length; i++ ) {
386				if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
387					break;
388				}
389			}
390		} else {
391			for ( i in obj ) {
392				if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
393					break;
394				}
395			}
396		}
397
398		return obj;
399	},
400
401
402	// Retrieve the text value of an array of DOM nodes
403	text: function( elem ) {
404		var node,
405			ret = "",
406			i = 0,
407			nodeType = elem.nodeType;
408
409		if ( !nodeType ) {
410
411			// If no nodeType, this is expected to be an array
412			while ( ( node = elem[ i++ ] ) ) {
413
414				// Do not traverse comment nodes
415				ret += jQuery.text( node );
416			}
417		}
418		if ( nodeType === 1 || nodeType === 11 ) {
419			return elem.textContent;
420		}
421		if ( nodeType === 9 ) {
422			return elem.documentElement.textContent;
423		}
424		if ( nodeType === 3 || nodeType === 4 ) {
425			return elem.nodeValue;
426		}
427
428		// Do not include comment or processing instruction nodes
429
430		return ret;
431	},
432
433	// results is for internal usage only
434	makeArray: function( arr, results ) {
435		var ret = results || [];
436
437		if ( arr != null ) {
438			if ( isArrayLike( Object( arr ) ) ) {
439				jQuery.merge( ret,
440					typeof arr === "string" ?
441						[ arr ] : arr
442				);
443			} else {
444				push.call( ret, arr );
445			}
446		}
447
448		return ret;
449	},
450
451	inArray: function( elem, arr, i ) {
452		return arr == null ? -1 : indexOf.call( arr, elem, i );
453	},
454
455	isXMLDoc: function( elem ) {
456		var namespace = elem && elem.namespaceURI,
457			docElem = elem && ( elem.ownerDocument || elem ).documentElement;
458
459		// Assume HTML when documentElement doesn't yet exist, such as inside
460		// document fragments.
461		return !rhtmlSuffix.test( namespace || docElem && docElem.nodeName || "HTML" );
462	},
463
464	// Support: Android <=4.0 only, PhantomJS 1 only
465	// push.apply(_, arraylike) throws on ancient WebKit
466	merge: function( first, second ) {
467		var len = +second.length,
468			j = 0,
469			i = first.length;
470
471		for ( ; j < len; j++ ) {
472			first[ i++ ] = second[ j ];
473		}
474
475		first.length = i;
476
477		return first;
478	},
479
480	grep: function( elems, callback, invert ) {
481		var callbackInverse,
482			matches = [],
483			i = 0,
484			length = elems.length,
485			callbackExpect = !invert;
486
487		// Go through the array, only saving the items
488		// that pass the validator function
489		for ( ; i < length; i++ ) {
490			callbackInverse = !callback( elems[ i ], i );
491			if ( callbackInverse !== callbackExpect ) {
492				matches.push( elems[ i ] );
493			}
494		}
495
496		return matches;
497	},
498
499	// arg is for internal usage only
500	map: function( elems, callback, arg ) {
501		var length, value,
502			i = 0,
503			ret = [];
504
505		// Go through the array, translating each of the items to their new values
506		if ( isArrayLike( elems ) ) {
507			length = elems.length;
508			for ( ; i < length; i++ ) {
509				value = callback( elems[ i ], i, arg );
510
511				if ( value != null ) {
512					ret.push( value );
513				}
514			}
515
516		// Go through every key on the object,
517		} else {
518			for ( i in elems ) {
519				value = callback( elems[ i ], i, arg );
520
521				if ( value != null ) {
522					ret.push( value );
523				}
524			}
525		}
526
527		// Flatten any nested arrays
528		return flat( ret );
529	},
530
531	// A global GUID counter for objects
532	guid: 1,
533
534	// jQuery.support is not used in Core but other projects attach their
535	// properties to it so it needs to exist.
536	support: support
537} );
538
539if ( typeof Symbol === "function" ) {
540	jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ];
541}
542
543// Populate the class2type map
544jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
545	function( _i, name ) {
546		class2type[ "[object " + name + "]" ] = name.toLowerCase();
547	} );
548
549function isArrayLike( obj ) {
550
551	// Support: real iOS 8.2 only (not reproducible in simulator)
552	// `in` check used to prevent JIT error (gh-2145)
553	// hasOwn isn't used here due to false negatives
554	// regarding Nodelist length in IE
555	var length = !!obj && "length" in obj && obj.length,
556		type = toType( obj );
557
558	if ( isFunction( obj ) || isWindow( obj ) ) {
559		return false;
560	}
561
562	return type === "array" || length === 0 ||
563		typeof length === "number" && length > 0 && ( length - 1 ) in obj;
564}
565
566
567function nodeName( elem, name ) {
568
569	return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
570
571}
572var pop = arr.pop;
573
574
575var sort = arr.sort;
576
577
578var splice = arr.splice;
579
580
581var whitespace = "[\\x20\\t\\r\\n\\f]";
582
583
584var rtrimCSS = new RegExp(
585	"^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$",
586	"g"
587);
588
589
590
591
592// Note: an element does not contain itself
593jQuery.contains = function( a, b ) {
594	var bup = b && b.parentNode;
595
596	return a === bup || !!( bup && bup.nodeType === 1 && (
597
598		// Support: IE 9 - 11+
599		// IE doesn't have `contains` on SVG.
600		a.contains ?
601			a.contains( bup ) :
602			a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
603	) );
604};
605
606
607
608
609// CSS string/identifier serialization
610// https://drafts.csswg.org/cssom/#common-serializing-idioms
611var rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g;
612
613function fcssescape( ch, asCodePoint ) {
614	if ( asCodePoint ) {
615
616		// U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER
617		if ( ch === "\0" ) {
618			return "\uFFFD";
619		}
620
621		// Control characters and (dependent upon position) numbers get escaped as code points
622		return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " ";
623	}
624
625	// Other potentially-special ASCII characters get backslash-escaped
626	return "\\" + ch;
627}
628
629jQuery.escapeSelector = function( sel ) {
630	return ( sel + "" ).replace( rcssescape, fcssescape );
631};
632
633
634
635
636var preferredDoc = document,
637	pushNative = push;
638
639( function() {
640
641var i,
642	Expr,
643	outermostContext,
644	sortInput,
645	hasDuplicate,
646	push = pushNative,
647
648	// Local document vars
649	document,
650	documentElement,
651	documentIsHTML,
652	rbuggyQSA,
653	matches,
654
655	// Instance-specific data
656	expando = jQuery.expando,
657	dirruns = 0,
658	done = 0,
659	classCache = createCache(),
660	tokenCache = createCache(),
661	compilerCache = createCache(),
662	nonnativeSelectorCache = createCache(),
663	sortOrder = function( a, b ) {
664		if ( a === b ) {
665			hasDuplicate = true;
666		}
667		return 0;
668	},
669
670	booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|" +
671		"loop|multiple|open|readonly|required|scoped",
672
673	// Regular expressions
674
675	// https://www.w3.org/TR/css-syntax-3/#ident-token-diagram
676	identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace +
677		"?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+",
678
679	// Attribute selectors: https://www.w3.org/TR/selectors/#attribute-selectors
680	attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace +
681
682		// Operator (capture 2)
683		"*([*^$|!~]?=)" + whitespace +
684
685		// "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
686		"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" +
687		whitespace + "*\\]",
688
689	pseudos = ":(" + identifier + ")(?:\\((" +
690
691		// To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
692		// 1. quoted (capture 3; capture 4 or capture 5)
693		"('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
694
695		// 2. simple (capture 6)
696		"((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
697
698		// 3. anything else (capture 2)
699		".*" +
700		")\\)|)",
701
702	// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
703	rwhitespace = new RegExp( whitespace + "+", "g" ),
704
705	rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
706	rleadingCombinator = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" +
707		whitespace + "*" ),
708	rdescend = new RegExp( whitespace + "|>" ),
709
710	rpseudo = new RegExp( pseudos ),
711	ridentifier = new RegExp( "^" + identifier + "$" ),
712
713	matchExpr = {
714		ID: new RegExp( "^#(" + identifier + ")" ),
715		CLASS: new RegExp( "^\\.(" + identifier + ")" ),
716		TAG: new RegExp( "^(" + identifier + "|[*])" ),
717		ATTR: new RegExp( "^" + attributes ),
718		PSEUDO: new RegExp( "^" + pseudos ),
719		CHILD: new RegExp(
720			"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" +
721				whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" +
722				whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
723		bool: new RegExp( "^(?:" + booleans + ")$", "i" ),
724
725		// For use in libraries implementing .is()
726		// We use this for POS matching in `select`
727		needsContext: new RegExp( "^" + whitespace +
728			"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace +
729			"*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
730	},
731
732	rinputs = /^(?:input|select|textarea|button)$/i,
733	rheader = /^h\d$/i,
734
735	// Easily-parseable/retrievable ID or TAG or CLASS selectors
736	rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
737
738	rsibling = /[+~]/,
739
740	// CSS escapes
741	// https://www.w3.org/TR/CSS21/syndata.html#escaped-characters
742	runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace +
743		"?|\\\\([^\\r\\n\\f])", "g" ),
744	funescape = function( escape, nonHex ) {
745		var high = "0x" + escape.slice( 1 ) - 0x10000;
746
747		if ( nonHex ) {
748
749			// Strip the backslash prefix from a non-hex escape sequence
750			return nonHex;
751		}
752
753		// Replace a hexadecimal escape sequence with the encoded Unicode code point
754		// Support: IE <=11+
755		// For values outside the Basic Multilingual Plane (BMP), manually construct a
756		// surrogate pair
757		return high < 0 ?
758			String.fromCharCode( high + 0x10000 ) :
759			String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
760	},
761
762	// Used for iframes; see `setDocument`.
763	// Support: IE 9 - 11+, Edge 12 - 18+
764	// Removing the function wrapper causes a "Permission Denied"
765	// error in IE/Edge.
766	unloadHandler = function() {
767		setDocument();
768	},
769
770	inDisabledFieldset = addCombinator(
771		function( elem ) {
772			return elem.disabled === true && nodeName( elem, "fieldset" );
773		},
774		{ dir: "parentNode", next: "legend" }
775	);
776
777// Support: IE <=9 only
778// Accessing document.activeElement can throw unexpectedly
779// https://bugs.jquery.com/ticket/13393
780function safeActiveElement() {
781	try {
782		return document.activeElement;
783	} catch ( err ) { }
784}
785
786// Optimize for push.apply( _, NodeList )
787try {
788	push.apply(
789		( arr = slice.call( preferredDoc.childNodes ) ),
790		preferredDoc.childNodes
791	);
792
793	// Support: Android <=4.0
794	// Detect silently failing push.apply
795	// eslint-disable-next-line no-unused-expressions
796	arr[ preferredDoc.childNodes.length ].nodeType;
797} catch ( e ) {
798	push = {
799		apply: function( target, els ) {
800			pushNative.apply( target, slice.call( els ) );
801		},
802		call: function( target ) {
803			pushNative.apply( target, slice.call( arguments, 1 ) );
804		}
805	};
806}
807
808function find( selector, context, results, seed ) {
809	var m, i, elem, nid, match, groups, newSelector,
810		newContext = context && context.ownerDocument,
811
812		// nodeType defaults to 9, since context defaults to document
813		nodeType = context ? context.nodeType : 9;
814
815	results = results || [];
816
817	// Return early from calls with invalid selector or context
818	if ( typeof selector !== "string" || !selector ||
819		nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
820
821		return results;
822	}
823
824	// Try to shortcut find operations (as opposed to filters) in HTML documents
825	if ( !seed ) {
826		setDocument( context );
827		context = context || document;
828
829		if ( documentIsHTML ) {
830
831			// If the selector is sufficiently simple, try using a "get*By*" DOM method
832			// (excepting DocumentFragment context, where the methods don't exist)
833			if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) {
834
835				// ID selector
836				if ( ( m = match[ 1 ] ) ) {
837
838					// Document context
839					if ( nodeType === 9 ) {
840						if ( ( elem = context.getElementById( m ) ) ) {
841
842							// Support: IE 9 only
843							// getElementById can match elements by name instead of ID
844							if ( elem.id === m ) {
845								push.call( results, elem );
846								return results;
847							}
848						} else {
849							return results;
850						}
851
852					// Element context
853					} else {
854
855						// Support: IE 9 only
856						// getElementById can match elements by name instead of ID
857						if ( newContext && ( elem = newContext.getElementById( m ) ) &&
858							find.contains( context, elem ) &&
859							elem.id === m ) {
860
861							push.call( results, elem );
862							return results;
863						}
864					}
865
866				// Type selector
867				} else if ( match[ 2 ] ) {
868					push.apply( results, context.getElementsByTagName( selector ) );
869					return results;
870
871				// Class selector
872				} else if ( ( m = match[ 3 ] ) && context.getElementsByClassName ) {
873					push.apply( results, context.getElementsByClassName( m ) );
874					return results;
875				}
876			}
877
878			// Take advantage of querySelectorAll
879			if ( !nonnativeSelectorCache[ selector + " " ] &&
880				( !rbuggyQSA || !rbuggyQSA.test( selector ) ) ) {
881
882				newSelector = selector;
883				newContext = context;
884
885				// qSA considers elements outside a scoping root when evaluating child or
886				// descendant combinators, which is not what we want.
887				// In such cases, we work around the behavior by prefixing every selector in the
888				// list with an ID selector referencing the scope context.
889				// The technique has to be used as well when a leading combinator is used
890				// as such selectors are not recognized by querySelectorAll.
891				// Thanks to Andrew Dupont for this technique.
892				if ( nodeType === 1 &&
893					( rdescend.test( selector ) || rleadingCombinator.test( selector ) ) ) {
894
895					// Expand context for sibling selectors
896					newContext = rsibling.test( selector ) && testContext( context.parentNode ) ||
897						context;
898
899					// We can use :scope instead of the ID hack if the browser
900					// supports it & if we're not changing the context.
901					// Support: IE 11+, Edge 17 - 18+
902					// IE/Edge sometimes throw a "Permission denied" error when
903					// strict-comparing two documents; shallow comparisons work.
904					// eslint-disable-next-line eqeqeq
905					if ( newContext != context || !support.scope ) {
906
907						// Capture the context ID, setting it first if necessary
908						if ( ( nid = context.getAttribute( "id" ) ) ) {
909							nid = jQuery.escapeSelector( nid );
910						} else {
911							context.setAttribute( "id", ( nid = expando ) );
912						}
913					}
914
915					// Prefix every selector in the list
916					groups = tokenize( selector );
917					i = groups.length;
918					while ( i-- ) {
919						groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " +
920							toSelector( groups[ i ] );
921					}
922					newSelector = groups.join( "," );
923				}
924
925				try {
926					push.apply( results,
927						newContext.querySelectorAll( newSelector )
928					);
929					return results;
930				} catch ( qsaError ) {
931					nonnativeSelectorCache( selector, true );
932				} finally {
933					if ( nid === expando ) {
934						context.removeAttribute( "id" );
935					}
936				}
937			}
938		}
939	}
940
941	// All others
942	return select( selector.replace( rtrimCSS, "$1" ), context, results, seed );
943}
944
945/**
946 * Create key-value caches of limited size
947 * @returns {function(string, object)} Returns the Object data after storing it on itself with
948 *	property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
949 *	deleting the oldest entry
950 */
951function createCache() {
952	var keys = [];
953
954	function cache( key, value ) {
955
956		// Use (key + " ") to avoid collision with native prototype properties
957		// (see https://github.com/jquery/sizzle/issues/157)
958		if ( keys.push( key + " " ) > Expr.cacheLength ) {
959
960			// Only keep the most recent entries
961			delete cache[ keys.shift() ];
962		}
963		return ( cache[ key + " " ] = value );
964	}
965	return cache;
966}
967
968/**
969 * Mark a function for special use by jQuery selector module
970 * @param {Function} fn The function to mark
971 */
972function markFunction( fn ) {
973	fn[ expando ] = true;
974	return fn;
975}
976
977/**
978 * Support testing using an element
979 * @param {Function} fn Passed the created element and returns a boolean result
980 */
981function assert( fn ) {
982	var el = document.createElement( "fieldset" );
983
984	try {
985		return !!fn( el );
986	} catch ( e ) {
987		return false;
988	} finally {
989
990		// Remove from its parent by default
991		if ( el.parentNode ) {
992			el.parentNode.removeChild( el );
993		}
994
995		// release memory in IE
996		el = null;
997	}
998}
999
1000/**
1001 * Returns a function to use in pseudos for input types
1002 * @param {String} type
1003 */
1004function createInputPseudo( type ) {
1005	return function( elem ) {
1006		return nodeName( elem, "input" ) && elem.type === type;
1007	};
1008}
1009
1010/**
1011 * Returns a function to use in pseudos for buttons
1012 * @param {String} type
1013 */
1014function createButtonPseudo( type ) {
1015	return function( elem ) {
1016		return ( nodeName( elem, "input" ) || nodeName( elem, "button" ) ) &&
1017			elem.type === type;
1018	};
1019}
1020
1021/**
1022 * Returns a function to use in pseudos for :enabled/:disabled
1023 * @param {Boolean} disabled true for :disabled; false for :enabled
1024 */
1025function createDisabledPseudo( disabled ) {
1026
1027	// Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable
1028	return function( elem ) {
1029
1030		// Only certain elements can match :enabled or :disabled
1031		// https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled
1032		// https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled
1033		if ( "form" in elem ) {
1034
1035			// Check for inherited disabledness on relevant non-disabled elements:
1036			// * listed form-associated elements in a disabled fieldset
1037			//   https://html.spec.whatwg.org/multipage/forms.html#category-listed
1038			//   https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled
1039			// * option elements in a disabled optgroup
1040			//   https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled
1041			// All such elements have a "form" property.
1042			if ( elem.parentNode && elem.disabled === false ) {
1043
1044				// Option elements defer to a parent optgroup if present
1045				if ( "label" in elem ) {
1046					if ( "label" in elem.parentNode ) {
1047						return elem.parentNode.disabled === disabled;
1048					} else {
1049						return elem.disabled === disabled;
1050					}
1051				}
1052
1053				// Support: IE 6 - 11+
1054				// Use the isDisabled shortcut property to check for disabled fieldset ancestors
1055				return elem.isDisabled === disabled ||
1056
1057					// Where there is no isDisabled, check manually
1058					elem.isDisabled !== !disabled &&
1059						inDisabledFieldset( elem ) === disabled;
1060			}
1061
1062			return elem.disabled === disabled;
1063
1064		// Try to winnow out elements that can't be disabled before trusting the disabled property.
1065		// Some victims get caught in our net (label, legend, menu, track), but it shouldn't
1066		// even exist on them, let alone have a boolean value.
1067		} else if ( "label" in elem ) {
1068			return elem.disabled === disabled;
1069		}
1070
1071		// Remaining elements are neither :enabled nor :disabled
1072		return false;
1073	};
1074}
1075
1076/**
1077 * Returns a function to use in pseudos for positionals
1078 * @param {Function} fn
1079 */
1080function createPositionalPseudo( fn ) {
1081	return markFunction( function( argument ) {
1082		argument = +argument;
1083		return markFunction( function( seed, matches ) {
1084			var j,
1085				matchIndexes = fn( [], seed.length, argument ),
1086				i = matchIndexes.length;
1087
1088			// Match elements found at the specified indexes
1089			while ( i-- ) {
1090				if ( seed[ ( j = matchIndexes[ i ] ) ] ) {
1091					seed[ j ] = !( matches[ j ] = seed[ j ] );
1092				}
1093			}
1094		} );
1095	} );
1096}
1097
1098/**
1099 * Checks a node for validity as a jQuery selector context
1100 * @param {Element|Object=} context
1101 * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
1102 */
1103function testContext( context ) {
1104	return context && typeof context.getElementsByTagName !== "undefined" && context;
1105}
1106
1107/**
1108 * Sets document-related variables once based on the current document
1109 * @param {Element|Object} [node] An element or document object to use to set the document
1110 * @returns {Object} Returns the current document
1111 */
1112function setDocument( node ) {
1113	var subWindow,
1114		doc = node ? node.ownerDocument || node : preferredDoc;
1115
1116	// Return early if doc is invalid or already selected
1117	// Support: IE 11+, Edge 17 - 18+
1118	// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
1119	// two documents; shallow comparisons work.
1120	// eslint-disable-next-line eqeqeq
1121	if ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) {
1122		return document;
1123	}
1124
1125	// Update global variables
1126	document = doc;
1127	documentElement = document.documentElement;
1128	documentIsHTML = !jQuery.isXMLDoc( document );
1129
1130	// Support: iOS 7 only, IE 9 - 11+
1131	// Older browsers didn't support unprefixed `matches`.
1132	matches = documentElement.matches ||
1133		documentElement.webkitMatchesSelector ||
1134		documentElement.msMatchesSelector;
1135
1136	// Support: IE 9 - 11+, Edge 12 - 18+
1137	// Accessing iframe documents after unload throws "permission denied" errors
1138	// (see trac-13936).
1139	// Limit the fix to IE & Edge Legacy; despite Edge 15+ implementing `matches`,
1140	// all IE 9+ and Edge Legacy versions implement `msMatchesSelector` as well.
1141	if ( documentElement.msMatchesSelector &&
1142
1143		// Support: IE 11+, Edge 17 - 18+
1144		// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
1145		// two documents; shallow comparisons work.
1146		// eslint-disable-next-line eqeqeq
1147		preferredDoc != document &&
1148		( subWindow = document.defaultView ) && subWindow.top !== subWindow ) {
1149
1150		// Support: IE 9 - 11+, Edge 12 - 18+
1151		subWindow.addEventListener( "unload", unloadHandler );
1152	}
1153
1154	// Support: IE <10
1155	// Check if getElementById returns elements by name
1156	// The broken getElementById methods don't pick up programmatically-set names,
1157	// so use a roundabout getElementsByName test
1158	support.getById = assert( function( el ) {
1159		documentElement.appendChild( el ).id = jQuery.expando;
1160		return !document.getElementsByName ||
1161			!document.getElementsByName( jQuery.expando ).length;
1162	} );
1163
1164	// Support: IE 9 only
1165	// Check to see if it's possible to do matchesSelector
1166	// on a disconnected node.
1167	support.disconnectedMatch = assert( function( el ) {
1168		return matches.call( el, "*" );
1169	} );
1170
1171	// Support: IE 9 - 11+, Edge 12 - 18+
1172	// IE/Edge don't support the :scope pseudo-class.
1173	support.scope = assert( function() {
1174		return document.querySelectorAll( ":scope" );
1175	} );
1176
1177	// Support: Chrome 105 - 111 only, Safari 15.4 - 16.3 only
1178	// Make sure the `:has()` argument is parsed unforgivingly.
1179	// We include `*` in the test to detect buggy implementations that are
1180	// _selectively_ forgiving (specifically when the list includes at least
1181	// one valid selector).
1182	// Note that we treat complete lack of support for `:has()` as if it were
1183	// spec-compliant support, which is fine because use of `:has()` in such
1184	// environments will fail in the qSA path and fall back to jQuery traversal
1185	// anyway.
1186	support.cssHas = assert( function() {
1187		try {
1188			document.querySelector( ":has(*,:jqfake)" );
1189			return false;
1190		} catch ( e ) {
1191			return true;
1192		}
1193	} );
1194
1195	// ID filter and find
1196	if ( support.getById ) {
1197		Expr.filter.ID = function( id ) {
1198			var attrId = id.replace( runescape, funescape );
1199			return function( elem ) {
1200				return elem.getAttribute( "id" ) === attrId;
1201			};
1202		};
1203		Expr.find.ID = function( id, context ) {
1204			if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
1205				var elem = context.getElementById( id );
1206				return elem ? [ elem ] : [];
1207			}
1208		};
1209	} else {
1210		Expr.filter.ID =  function( id ) {
1211			var attrId = id.replace( runescape, funescape );
1212			return function( elem ) {
1213				var node = typeof elem.getAttributeNode !== "undefined" &&
1214					elem.getAttributeNode( "id" );
1215				return node && node.value === attrId;
1216			};
1217		};
1218
1219		// Support: IE 6 - 7 only
1220		// getElementById is not reliable as a find shortcut
1221		Expr.find.ID = function( id, context ) {
1222			if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
1223				var node, i, elems,
1224					elem = context.getElementById( id );
1225
1226				if ( elem ) {
1227
1228					// Verify the id attribute
1229					node = elem.getAttributeNode( "id" );
1230					if ( node && node.value === id ) {
1231						return [ elem ];
1232					}
1233
1234					// Fall back on getElementsByName
1235					elems = context.getElementsByName( id );
1236					i = 0;
1237					while ( ( elem = elems[ i++ ] ) ) {
1238						node = elem.getAttributeNode( "id" );
1239						if ( node && node.value === id ) {
1240							return [ elem ];
1241						}
1242					}
1243				}
1244
1245				return [];
1246			}
1247		};
1248	}
1249
1250	// Tag
1251	Expr.find.TAG = function( tag, context ) {
1252		if ( typeof context.getElementsByTagName !== "undefined" ) {
1253			return context.getElementsByTagName( tag );
1254
1255		// DocumentFragment nodes don't have gEBTN
1256		} else {
1257			return context.querySelectorAll( tag );
1258		}
1259	};
1260
1261	// Class
1262	Expr.find.CLASS = function( className, context ) {
1263		if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) {
1264			return context.getElementsByClassName( className );
1265		}
1266	};
1267
1268	/* QSA/matchesSelector
1269	---------------------------------------------------------------------- */
1270
1271	// QSA and matchesSelector support
1272
1273	rbuggyQSA = [];
1274
1275	// Build QSA regex
1276	// Regex strategy adopted from Diego Perini
1277	assert( function( el ) {
1278
1279		var input;
1280
1281		documentElement.appendChild( el ).innerHTML =
1282			"<a id='" + expando + "' href='' disabled='disabled'></a>" +
1283			"<select id='" + expando + "-\r\\' disabled='disabled'>" +
1284			"<option selected=''></option></select>";
1285
1286		// Support: iOS <=7 - 8 only
1287		// Boolean attributes and "value" are not treated correctly in some XML documents
1288		if ( !el.querySelectorAll( "[selected]" ).length ) {
1289			rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
1290		}
1291
1292		// Support: iOS <=7 - 8 only
1293		if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
1294			rbuggyQSA.push( "~=" );
1295		}
1296
1297		// Support: iOS 8 only
1298		// https://bugs.webkit.org/show_bug.cgi?id=136851
1299		// In-page `selector#id sibling-combinator selector` fails
1300		if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) {
1301			rbuggyQSA.push( ".#.+[+~]" );
1302		}
1303
1304		// Support: Chrome <=105+, Firefox <=104+, Safari <=15.4+
1305		// In some of the document kinds, these selectors wouldn't work natively.
1306		// This is probably OK but for backwards compatibility we want to maintain
1307		// handling them through jQuery traversal in jQuery 3.x.
1308		if ( !el.querySelectorAll( ":checked" ).length ) {
1309			rbuggyQSA.push( ":checked" );
1310		}
1311
1312		// Support: Windows 8 Native Apps
1313		// The type and name attributes are restricted during .innerHTML assignment
1314		input = document.createElement( "input" );
1315		input.setAttribute( "type", "hidden" );
1316		el.appendChild( input ).setAttribute( "name", "D" );
1317
1318		// Support: IE 9 - 11+
1319		// IE's :disabled selector does not pick up the children of disabled fieldsets
1320		// Support: Chrome <=105+, Firefox <=104+, Safari <=15.4+
1321		// In some of the document kinds, these selectors wouldn't work natively.
1322		// This is probably OK but for backwards compatibility we want to maintain
1323		// handling them through jQuery traversal in jQuery 3.x.
1324		documentElement.appendChild( el ).disabled = true;
1325		if ( el.querySelectorAll( ":disabled" ).length !== 2 ) {
1326			rbuggyQSA.push( ":enabled", ":disabled" );
1327		}
1328
1329		// Support: IE 11+, Edge 15 - 18+
1330		// IE 11/Edge don't find elements on a `[name='']` query in some cases.
1331		// Adding a temporary attribute to the document before the selection works
1332		// around the issue.
1333		// Interestingly, IE 10 & older don't seem to have the issue.
1334		input = document.createElement( "input" );
1335		input.setAttribute( "name", "" );
1336		el.appendChild( input );
1337		if ( !el.querySelectorAll( "[name='']" ).length ) {
1338			rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" +
1339				whitespace + "*(?:''|\"\")" );
1340		}
1341	} );
1342
1343	if ( !support.cssHas ) {
1344
1345		// Support: Chrome 105 - 110+, Safari 15.4 - 16.3+
1346		// Our regular `try-catch` mechanism fails to detect natively-unsupported
1347		// pseudo-classes inside `:has()` (such as `:has(:contains("Foo"))`)
1348		// in browsers that parse the `:has()` argument as a forgiving selector list.
1349		// https://drafts.csswg.org/selectors/#relational now requires the argument
1350		// to be parsed unforgivingly, but browsers have not yet fully adjusted.
1351		rbuggyQSA.push( ":has" );
1352	}
1353
1354	rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) );
1355
1356	/* Sorting
1357	---------------------------------------------------------------------- */
1358
1359	// Document order sorting
1360	sortOrder = function( a, b ) {
1361
1362		// Flag for duplicate removal
1363		if ( a === b ) {
1364			hasDuplicate = true;
1365			return 0;
1366		}
1367
1368		// Sort on method existence if only one input has compareDocumentPosition
1369		var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
1370		if ( compare ) {
1371			return compare;
1372		}
1373
1374		// Calculate position if both inputs belong to the same document
1375		// Support: IE 11+, Edge 17 - 18+
1376		// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
1377		// two documents; shallow comparisons work.
1378		// eslint-disable-next-line eqeqeq
1379		compare = ( a.ownerDocument || a ) == ( b.ownerDocument || b ) ?
1380			a.compareDocumentPosition( b ) :
1381
1382			// Otherwise we know they are disconnected
1383			1;
1384
1385		// Disconnected nodes
1386		if ( compare & 1 ||
1387			( !support.sortDetached && b.compareDocumentPosition( a ) === compare ) ) {
1388
1389			// Choose the first element that is related to our preferred document
1390			// Support: IE 11+, Edge 17 - 18+
1391			// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
1392			// two documents; shallow comparisons work.
1393			// eslint-disable-next-line eqeqeq
1394			if ( a === document || a.ownerDocument == preferredDoc &&
1395				find.contains( preferredDoc, a ) ) {
1396				return -1;
1397			}
1398
1399			// Support: IE 11+, Edge 17 - 18+
1400			// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
1401			// two documents; shallow comparisons work.
1402			// eslint-disable-next-line eqeqeq
1403			if ( b === document || b.ownerDocument == preferredDoc &&
1404				find.contains( preferredDoc, b ) ) {
1405				return 1;
1406			}
1407
1408			// Maintain original order
1409			return sortInput ?
1410				( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
1411				0;
1412		}
1413
1414		return compare & 4 ? -1 : 1;
1415	};
1416
1417	return document;
1418}
1419
1420find.matches = function( expr, elements ) {
1421	return find( expr, null, null, elements );
1422};
1423
1424find.matchesSelector = function( elem, expr ) {
1425	setDocument( elem );
1426
1427	if ( documentIsHTML &&
1428		!nonnativeSelectorCache[ expr + " " ] &&
1429		( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) {
1430
1431		try {
1432			var ret = matches.call( elem, expr );
1433
1434			// IE 9's matchesSelector returns false on disconnected nodes
1435			if ( ret || support.disconnectedMatch ||
1436
1437					// As well, disconnected nodes are said to be in a document
1438					// fragment in IE 9
1439					elem.document && elem.document.nodeType !== 11 ) {
1440				return ret;
1441			}
1442		} catch ( e ) {
1443			nonnativeSelectorCache( expr, true );
1444		}
1445	}
1446
1447	return find( expr, document, null, [ elem ] ).length > 0;
1448};
1449
1450find.contains = function( context, elem ) {
1451
1452	// Set document vars if needed
1453	// Support: IE 11+, Edge 17 - 18+
1454	// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
1455	// two documents; shallow comparisons work.
1456	// eslint-disable-next-line eqeqeq
1457	if ( ( context.ownerDocument || context ) != document ) {
1458		setDocument( context );
1459	}
1460	return jQuery.contains( context, elem );
1461};
1462
1463
1464find.attr = function( elem, name ) {
1465
1466	// Set document vars if needed
1467	// Support: IE 11+, Edge 17 - 18+
1468	// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
1469	// two documents; shallow comparisons work.
1470	// eslint-disable-next-line eqeqeq
1471	if ( ( elem.ownerDocument || elem ) != document ) {
1472		setDocument( elem );
1473	}
1474
1475	var fn = Expr.attrHandle[ name.toLowerCase() ],
1476
1477		// Don't get fooled by Object.prototype properties (see trac-13807)
1478		val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
1479			fn( elem, name, !documentIsHTML ) :
1480			undefined;
1481
1482	if ( val !== undefined ) {
1483		return val;
1484	}
1485
1486	return elem.getAttribute( name );
1487};
1488
1489find.error = function( msg ) {
1490	throw new Error( "Syntax error, unrecognized expression: " + msg );
1491};
1492
1493/**
1494 * Document sorting and removing duplicates
1495 * @param {ArrayLike} results
1496 */
1497jQuery.uniqueSort = function( results ) {
1498	var elem,
1499		duplicates = [],
1500		j = 0,
1501		i = 0;
1502
1503	// Unless we *know* we can detect duplicates, assume their presence
1504	//
1505	// Support: Android <=4.0+
1506	// Testing for detecting duplicates is unpredictable so instead assume we can't
1507	// depend on duplicate detection in all browsers without a stable sort.
1508	hasDuplicate = !support.sortStable;
1509	sortInput = !support.sortStable && slice.call( results, 0 );
1510	sort.call( results, sortOrder );
1511
1512	if ( hasDuplicate ) {
1513		while ( ( elem = results[ i++ ] ) ) {
1514			if ( elem === results[ i ] ) {
1515				j = duplicates.push( i );
1516			}
1517		}
1518		while ( j-- ) {
1519			splice.call( results, duplicates[ j ], 1 );
1520		}
1521	}
1522
1523	// Clear input after sorting to release objects
1524	// See https://github.com/jquery/sizzle/pull/225
1525	sortInput = null;
1526
1527	return results;
1528};
1529
1530jQuery.fn.uniqueSort = function() {
1531	return this.pushStack( jQuery.uniqueSort( slice.apply( this ) ) );
1532};
1533
1534Expr = jQuery.expr = {
1535
1536	// Can be adjusted by the user
1537	cacheLength: 50,
1538
1539	createPseudo: markFunction,
1540
1541	match: matchExpr,
1542
1543	attrHandle: {},
1544
1545	find: {},
1546
1547	relative: {
1548		">": { dir: "parentNode", first: true },
1549		" ": { dir: "parentNode" },
1550		"+": { dir: "previousSibling", first: true },
1551		"~": { dir: "previousSibling" }
1552	},
1553
1554	preFilter: {
1555		ATTR: function( match ) {
1556			match[ 1 ] = match[ 1 ].replace( runescape, funescape );
1557
1558			// Move the given value to match[3] whether quoted or unquoted
1559			match[ 3 ] = ( match[ 3 ] || match[ 4 ] || match[ 5 ] || "" )
1560				.replace( runescape, funescape );
1561
1562			if ( match[ 2 ] === "~=" ) {
1563				match[ 3 ] = " " + match[ 3 ] + " ";
1564			}
1565
1566			return match.slice( 0, 4 );
1567		},
1568
1569		CHILD: function( match ) {
1570
1571			/* matches from matchExpr["CHILD"]
1572				1 type (only|nth|...)
1573				2 what (child|of-type)
1574				3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
1575				4 xn-component of xn+y argument ([+-]?\d*n|)
1576				5 sign of xn-component
1577				6 x of xn-component
1578				7 sign of y-component
1579				8 y of y-component
1580			*/
1581			match[ 1 ] = match[ 1 ].toLowerCase();
1582
1583			if ( match[ 1 ].slice( 0, 3 ) === "nth" ) {
1584
1585				// nth-* requires argument
1586				if ( !match[ 3 ] ) {
1587					find.error( match[ 0 ] );
1588				}
1589
1590				// numeric x and y parameters for Expr.filter.CHILD
1591				// remember that false/true cast respectively to 0/1
1592				match[ 4 ] = +( match[ 4 ] ?
1593					match[ 5 ] + ( match[ 6 ] || 1 ) :
1594					2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" )
1595				);
1596				match[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === "odd" );
1597
1598			// other types prohibit arguments
1599			} else if ( match[ 3 ] ) {
1600				find.error( match[ 0 ] );
1601			}
1602
1603			return match;
1604		},
1605
1606		PSEUDO: function( match ) {
1607			var excess,
1608				unquoted = !match[ 6 ] && match[ 2 ];
1609
1610			if ( matchExpr.CHILD.test( match[ 0 ] ) ) {
1611				return null;
1612			}
1613
1614			// Accept quoted arguments as-is
1615			if ( match[ 3 ] ) {
1616				match[ 2 ] = match[ 4 ] || match[ 5 ] || "";
1617
1618			// Strip excess characters from unquoted arguments
1619			} else if ( unquoted && rpseudo.test( unquoted ) &&
1620
1621				// Get excess from tokenize (recursively)
1622				( excess = tokenize( unquoted, true ) ) &&
1623
1624				// advance to the next closing parenthesis
1625				( excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length ) ) {
1626
1627				// excess is a negative index
1628				match[ 0 ] = match[ 0 ].slice( 0, excess );
1629				match[ 2 ] = unquoted.slice( 0, excess );
1630			}
1631
1632			// Return only captures needed by the pseudo filter method (type and argument)
1633			return match.slice( 0, 3 );
1634		}
1635	},
1636
1637	filter: {
1638
1639		TAG: function( nodeNameSelector ) {
1640			var expectedNodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
1641			return nodeNameSelector === "*" ?
1642				function() {
1643					return true;
1644				} :
1645				function( elem ) {
1646					return nodeName( elem, expectedNodeName );
1647				};
1648		},
1649
1650		CLASS: function( className ) {
1651			var pattern = classCache[ className + " " ];
1652
1653			return pattern ||
1654				( pattern = new RegExp( "(^|" + whitespace + ")" + className +
1655					"(" + whitespace + "|$)" ) ) &&
1656				classCache( className, function( elem ) {
1657					return pattern.test(
1658						typeof elem.className === "string" && elem.className ||
1659							typeof elem.getAttribute !== "undefined" &&
1660								elem.getAttribute( "class" ) ||
1661							""
1662					);
1663				} );
1664		},
1665
1666		ATTR: function( name, operator, check ) {
1667			return function( elem ) {
1668				var result = find.attr( elem, name );
1669
1670				if ( result == null ) {
1671					return operator === "!=";
1672				}
1673				if ( !operator ) {
1674					return true;
1675				}
1676
1677				result += "";
1678
1679				if ( operator === "=" ) {
1680					return result === check;
1681				}
1682				if ( operator === "!=" ) {
1683					return result !== check;
1684				}
1685				if ( operator === "^=" ) {
1686					return check && result.indexOf( check ) === 0;
1687				}
1688				if ( operator === "*=" ) {
1689					return check && result.indexOf( check ) > -1;
1690				}
1691				if ( operator === "$=" ) {
1692					return check && result.slice( -check.length ) === check;
1693				}
1694				if ( operator === "~=" ) {
1695					return ( " " + result.replace( rwhitespace, " " ) + " " )
1696						.indexOf( check ) > -1;
1697				}
1698				if ( operator === "|=" ) {
1699					return result === check || result.slice( 0, check.length + 1 ) === check + "-";
1700				}
1701
1702				return false;
1703			};
1704		},
1705
1706		CHILD: function( type, what, _argument, first, last ) {
1707			var simple = type.slice( 0, 3 ) !== "nth",
1708				forward = type.slice( -4 ) !== "last",
1709				ofType = what === "of-type";
1710
1711			return first === 1 && last === 0 ?
1712
1713				// Shortcut for :nth-*(n)
1714				function( elem ) {
1715					return !!elem.parentNode;
1716				} :
1717
1718				function( elem, _context, xml ) {
1719					var cache, outerCache, node, nodeIndex, start,
1720						dir = simple !== forward ? "nextSibling" : "previousSibling",
1721						parent = elem.parentNode,
1722						name = ofType && elem.nodeName.toLowerCase(),
1723						useCache = !xml && !ofType,
1724						diff = false;
1725
1726					if ( parent ) {
1727
1728						// :(first|last|only)-(child|of-type)
1729						if ( simple ) {
1730							while ( dir ) {
1731								node = elem;
1732								while ( ( node = node[ dir ] ) ) {
1733									if ( ofType ?
1734										nodeName( node, name ) :
1735										node.nodeType === 1 ) {
1736
1737										return false;
1738									}
1739								}
1740
1741								// Reverse direction for :only-* (if we haven't yet done so)
1742								start = dir = type === "only" && !start && "nextSibling";
1743							}
1744							return true;
1745						}
1746
1747						start = [ forward ? parent.firstChild : parent.lastChild ];
1748
1749						// non-xml :nth-child(...) stores cache data on `parent`
1750						if ( forward && useCache ) {
1751
1752							// Seek `elem` from a previously-cached index
1753							outerCache = parent[ expando ] || ( parent[ expando ] = {} );
1754							cache = outerCache[ type ] || [];
1755							nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
1756							diff = nodeIndex && cache[ 2 ];
1757							node = nodeIndex && parent.childNodes[ nodeIndex ];
1758
1759							while ( ( node = ++nodeIndex && node && node[ dir ] ||
1760
1761								// Fallback to seeking `elem` from the start
1762								( diff = nodeIndex = 0 ) || start.pop() ) ) {
1763
1764								// When found, cache indexes on `parent` and break
1765								if ( node.nodeType === 1 && ++diff && node === elem ) {
1766									outerCache[ type ] = [ dirruns, nodeIndex, diff ];
1767									break;
1768								}
1769							}
1770
1771						} else {
1772
1773							// Use previously-cached element index if available
1774							if ( useCache ) {
1775								outerCache = elem[ expando ] || ( elem[ expando ] = {} );
1776								cache = outerCache[ type ] || [];
1777								nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
1778								diff = nodeIndex;
1779							}
1780
1781							// xml :nth-child(...)
1782							// or :nth-last-child(...) or :nth(-last)?-of-type(...)
1783							if ( diff === false ) {
1784
1785								// Use the same loop as above to seek `elem` from the start
1786								while ( ( node = ++nodeIndex && node && node[ dir ] ||
1787									( diff = nodeIndex = 0 ) || start.pop() ) ) {
1788
1789									if ( ( ofType ?
1790										nodeName( node, name ) :
1791										node.nodeType === 1 ) &&
1792										++diff ) {
1793
1794										// Cache the index of each encountered element
1795										if ( useCache ) {
1796											outerCache = node[ expando ] ||
1797												( node[ expando ] = {} );
1798											outerCache[ type ] = [ dirruns, diff ];
1799										}
1800
1801										if ( node === elem ) {
1802											break;
1803										}
1804									}
1805								}
1806							}
1807						}
1808
1809						// Incorporate the offset, then check against cycle size
1810						diff -= last;
1811						return diff === first || ( diff % first === 0 && diff / first >= 0 );
1812					}
1813				};
1814		},
1815
1816		PSEUDO: function( pseudo, argument ) {
1817
1818			// pseudo-class names are case-insensitive
1819			// https://www.w3.org/TR/selectors/#pseudo-classes
1820			// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
1821			// Remember that setFilters inherits from pseudos
1822			var args,
1823				fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
1824					find.error( "unsupported pseudo: " + pseudo );
1825
1826			// The user may use createPseudo to indicate that
1827			// arguments are needed to create the filter function
1828			// just as jQuery does
1829			if ( fn[ expando ] ) {
1830				return fn( argument );
1831			}
1832
1833			// But maintain support for old signatures
1834			if ( fn.length > 1 ) {
1835				args = [ pseudo, pseudo, "", argument ];
1836				return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
1837					markFunction( function( seed, matches ) {
1838						var idx,
1839							matched = fn( seed, argument ),
1840							i = matched.length;
1841						while ( i-- ) {
1842							idx = indexOf.call( seed, matched[ i ] );
1843							seed[ idx ] = !( matches[ idx ] = matched[ i ] );
1844						}
1845					} ) :
1846					function( elem ) {
1847						return fn( elem, 0, args );
1848					};
1849			}
1850
1851			return fn;
1852		}
1853	},
1854
1855	pseudos: {
1856
1857		// Potentially complex pseudos
1858		not: markFunction( function( selector ) {
1859
1860			// Trim the selector passed to compile
1861			// to avoid treating leading and trailing
1862			// spaces as combinators
1863			var input = [],
1864				results = [],
1865				matcher = compile( selector.replace( rtrimCSS, "$1" ) );
1866
1867			return matcher[ expando ] ?
1868				markFunction( function( seed, matches, _context, xml ) {
1869					var elem,
1870						unmatched = matcher( seed, null, xml, [] ),
1871						i = seed.length;
1872
1873					// Match elements unmatched by `matcher`
1874					while ( i-- ) {
1875						if ( ( elem = unmatched[ i ] ) ) {
1876							seed[ i ] = !( matches[ i ] = elem );
1877						}
1878					}
1879				} ) :
1880				function( elem, _context, xml ) {
1881					input[ 0 ] = elem;
1882					matcher( input, null, xml, results );
1883
1884					// Don't keep the element
1885					// (see https://github.com/jquery/sizzle/issues/299)
1886					input[ 0 ] = null;
1887					return !results.pop();
1888				};
1889		} ),
1890
1891		has: markFunction( function( selector ) {
1892			return function( elem ) {
1893				return find( selector, elem ).length > 0;
1894			};
1895		} ),
1896
1897		contains: markFunction( function( text ) {
1898			text = text.replace( runescape, funescape );
1899			return function( elem ) {
1900				return ( elem.textContent || jQuery.text( elem ) ).indexOf( text ) > -1;
1901			};
1902		} ),
1903
1904		// "Whether an element is represented by a :lang() selector
1905		// is based solely on the element's language value
1906		// being equal to the identifier C,
1907		// or beginning with the identifier C immediately followed by "-".
1908		// The matching of C against the element's language value is performed case-insensitively.
1909		// The identifier C does not have to be a valid language name."
1910		// https://www.w3.org/TR/selectors/#lang-pseudo
1911		lang: markFunction( function( lang ) {
1912
1913			// lang value must be a valid identifier
1914			if ( !ridentifier.test( lang || "" ) ) {
1915				find.error( "unsupported lang: " + lang );
1916			}
1917			lang = lang.replace( runescape, funescape ).toLowerCase();
1918			return function( elem ) {
1919				var elemLang;
1920				do {
1921					if ( ( elemLang = documentIsHTML ?
1922						elem.lang :
1923						elem.getAttribute( "xml:lang" ) || elem.getAttribute( "lang" ) ) ) {
1924
1925						elemLang = elemLang.toLowerCase();
1926						return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
1927					}
1928				} while ( ( elem = elem.parentNode ) && elem.nodeType === 1 );
1929				return false;
1930			};
1931		} ),
1932
1933		// Miscellaneous
1934		target: function( elem ) {
1935			var hash = window.location && window.location.hash;
1936			return hash && hash.slice( 1 ) === elem.id;
1937		},
1938
1939		root: function( elem ) {
1940			return elem === documentElement;
1941		},
1942
1943		focus: function( elem ) {
1944			return elem === safeActiveElement() &&
1945				document.hasFocus() &&
1946				!!( elem.type || elem.href || ~elem.tabIndex );
1947		},
1948
1949		// Boolean properties
1950		enabled: createDisabledPseudo( false ),
1951		disabled: createDisabledPseudo( true ),
1952
1953		checked: function( elem ) {
1954
1955			// In CSS3, :checked should return both checked and selected elements
1956			// https://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
1957			return ( nodeName( elem, "input" ) && !!elem.checked ) ||
1958				( nodeName( elem, "option" ) && !!elem.selected );
1959		},
1960
1961		selected: function( elem ) {
1962
1963			// Support: IE <=11+
1964			// Accessing the selectedIndex property
1965			// forces the browser to treat the default option as
1966			// selected when in an optgroup.
1967			if ( elem.parentNode ) {
1968				// eslint-disable-next-line no-unused-expressions
1969				elem.parentNode.selectedIndex;
1970			}
1971
1972			return elem.selected === true;
1973		},
1974
1975		// Contents
1976		empty: function( elem ) {
1977
1978			// https://www.w3.org/TR/selectors/#empty-pseudo
1979			// :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
1980			//   but not by others (comment: 8; processing instruction: 7; etc.)
1981			// nodeType < 6 works because attributes (2) do not appear as children
1982			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
1983				if ( elem.nodeType < 6 ) {
1984					return false;
1985				}
1986			}
1987			return true;
1988		},
1989
1990		parent: function( elem ) {
1991			return !Expr.pseudos.empty( elem );
1992		},
1993
1994		// Element/input types
1995		header: function( elem ) {
1996			return rheader.test( elem.nodeName );
1997		},
1998
1999		input: function( elem ) {
2000			return rinputs.test( elem.nodeName );
2001		},
2002
2003		button: function( elem ) {
2004			return nodeName( elem, "input" ) && elem.type === "button" ||
2005				nodeName( elem, "button" );
2006		},
2007
2008		text: function( elem ) {
2009			var attr;
2010			return nodeName( elem, "input" ) && elem.type === "text" &&
2011
2012				// Support: IE <10 only
2013				// New HTML5 attribute values (e.g., "search") appear
2014				// with elem.type === "text"
2015				( ( attr = elem.getAttribute( "type" ) ) == null ||
2016					attr.toLowerCase() === "text" );
2017		},
2018
2019		// Position-in-collection
2020		first: createPositionalPseudo( function() {
2021			return [ 0 ];
2022		} ),
2023
2024		last: createPositionalPseudo( function( _matchIndexes, length ) {
2025			return [ length - 1 ];
2026		} ),
2027
2028		eq: createPositionalPseudo( function( _matchIndexes, length, argument ) {
2029			return [ argument < 0 ? argument + length : argument ];
2030		} ),
2031
2032		even: createPositionalPseudo( function( matchIndexes, length ) {
2033			var i = 0;
2034			for ( ; i < length; i += 2 ) {
2035				matchIndexes.push( i );
2036			}
2037			return matchIndexes;
2038		} ),
2039
2040		odd: createPositionalPseudo( function( matchIndexes, length ) {
2041			var i = 1;
2042			for ( ; i < length; i += 2 ) {
2043				matchIndexes.push( i );
2044			}
2045			return matchIndexes;
2046		} ),
2047
2048		lt: createPositionalPseudo( function( matchIndexes, length, argument ) {
2049			var i;
2050
2051			if ( argument < 0 ) {
2052				i = argument + length;
2053			} else if ( argument > length ) {
2054				i = length;
2055			} else {
2056				i = argument;
2057			}
2058
2059			for ( ; --i >= 0; ) {
2060				matchIndexes.push( i );
2061			}
2062			return matchIndexes;
2063		} ),
2064
2065		gt: createPositionalPseudo( function( matchIndexes, length, argument ) {
2066			var i = argument < 0 ? argument + length : argument;
2067			for ( ; ++i < length; ) {
2068				matchIndexes.push( i );
2069			}
2070			return matchIndexes;
2071		} )
2072	}
2073};
2074
2075Expr.pseudos.nth = Expr.pseudos.eq;
2076
2077// Add button/input type pseudos
2078for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
2079	Expr.pseudos[ i ] = createInputPseudo( i );
2080}
2081for ( i in { submit: true, reset: true } ) {
2082	Expr.pseudos[ i ] = createButtonPseudo( i );
2083}
2084
2085// Easy API for creating new setFilters
2086function setFilters() {}
2087setFilters.prototype = Expr.filters = Expr.pseudos;
2088Expr.setFilters = new setFilters();
2089
2090function tokenize( selector, parseOnly ) {
2091	var matched, match, tokens, type,
2092		soFar, groups, preFilters,
2093		cached = tokenCache[ selector + " " ];
2094
2095	if ( cached ) {
2096		return parseOnly ? 0 : cached.slice( 0 );
2097	}
2098
2099	soFar = selector;
2100	groups = [];
2101	preFilters = Expr.preFilter;
2102
2103	while ( soFar ) {
2104
2105		// Comma and first run
2106		if ( !matched || ( match = rcomma.exec( soFar ) ) ) {
2107			if ( match ) {
2108
2109				// Don't consume trailing commas as valid
2110				soFar = soFar.slice( match[ 0 ].length ) || soFar;
2111			}
2112			groups.push( ( tokens = [] ) );
2113		}
2114
2115		matched = false;
2116
2117		// Combinators
2118		if ( ( match = rleadingCombinator.exec( soFar ) ) ) {
2119			matched = match.shift();
2120			tokens.push( {
2121				value: matched,
2122
2123				// Cast descendant combinators to space
2124				type: match[ 0 ].replace( rtrimCSS, " " )
2125			} );
2126			soFar = soFar.slice( matched.length );
2127		}
2128
2129		// Filters
2130		for ( type in Expr.filter ) {
2131			if ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] ||
2132				( match = preFilters[ type ]( match ) ) ) ) {
2133				matched = match.shift();
2134				tokens.push( {
2135					value: matched,
2136					type: type,
2137					matches: match
2138				} );
2139				soFar = soFar.slice( matched.length );
2140			}
2141		}
2142
2143		if ( !matched ) {
2144			break;
2145		}
2146	}
2147
2148	// Return the length of the invalid excess
2149	// if we're just parsing
2150	// Otherwise, throw an error or return tokens
2151	if ( parseOnly ) {
2152		return soFar.length;
2153	}
2154
2155	return soFar ?
2156		find.error( selector ) :
2157
2158		// Cache the tokens
2159		tokenCache( selector, groups ).slice( 0 );
2160}
2161
2162function toSelector( tokens ) {
2163	var i = 0,
2164		len = tokens.length,
2165		selector = "";
2166	for ( ; i < len; i++ ) {
2167		selector += tokens[ i ].value;
2168	}
2169	return selector;
2170}
2171
2172function addCombinator( matcher, combinator, base ) {
2173	var dir = combinator.dir,
2174		skip = combinator.next,
2175		key = skip || dir,
2176		checkNonElements = base && key === "parentNode",
2177		doneName = done++;
2178
2179	return combinator.first ?
2180
2181		// Check against closest ancestor/preceding element
2182		function( elem, context, xml ) {
2183			while ( ( elem = elem[ dir ] ) ) {
2184				if ( elem.nodeType === 1 || checkNonElements ) {
2185					return matcher( elem, context, xml );
2186				}
2187			}
2188			return false;
2189		} :
2190
2191		// Check against all ancestor/preceding elements
2192		function( elem, context, xml ) {
2193			var oldCache, outerCache,
2194				newCache = [ dirruns, doneName ];
2195
2196			// We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching
2197			if ( xml ) {
2198				while ( ( elem = elem[ dir ] ) ) {
2199					if ( elem.nodeType === 1 || checkNonElements ) {
2200						if ( matcher( elem, context, xml ) ) {
2201							return true;
2202						}
2203					}
2204				}
2205			} else {
2206				while ( ( elem = elem[ dir ] ) ) {
2207					if ( elem.nodeType === 1 || checkNonElements ) {
2208						outerCache = elem[ expando ] || ( elem[ expando ] = {} );
2209
2210						if ( skip && nodeName( elem, skip ) ) {
2211							elem = elem[ dir ] || elem;
2212						} else if ( ( oldCache = outerCache[ key ] ) &&
2213							oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
2214
2215							// Assign to newCache so results back-propagate to previous elements
2216							return ( newCache[ 2 ] = oldCache[ 2 ] );
2217						} else {
2218
2219							// Reuse newcache so results back-propagate to previous elements
2220							outerCache[ key ] = newCache;
2221
2222							// A match means we're done; a fail means we have to keep checking
2223							if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) {
2224								return true;
2225							}
2226						}
2227					}
2228				}
2229			}
2230			return false;
2231		};
2232}
2233
2234function elementMatcher( matchers ) {
2235	return matchers.length > 1 ?
2236		function( elem, context, xml ) {
2237			var i = matchers.length;
2238			while ( i-- ) {
2239				if ( !matchers[ i ]( elem, context, xml ) ) {
2240					return false;
2241				}
2242			}
2243			return true;
2244		} :
2245		matchers[ 0 ];
2246}
2247
2248function multipleContexts( selector, contexts, results ) {
2249	var i = 0,
2250		len = contexts.length;
2251	for ( ; i < len; i++ ) {
2252		find( selector, contexts[ i ], results );
2253	}
2254	return results;
2255}
2256
2257function condense( unmatched, map, filter, context, xml ) {
2258	var elem,
2259		newUnmatched = [],
2260		i = 0,
2261		len = unmatched.length,
2262		mapped = map != null;
2263
2264	for ( ; i < len; i++ ) {
2265		if ( ( elem = unmatched[ i ] ) ) {
2266			if ( !filter || filter( elem, context, xml ) ) {
2267				newUnmatched.push( elem );
2268				if ( mapped ) {
2269					map.push( i );
2270				}
2271			}
2272		}
2273	}
2274
2275	return newUnmatched;
2276}
2277
2278function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
2279	if ( postFilter && !postFilter[ expando ] ) {
2280		postFilter = setMatcher( postFilter );
2281	}
2282	if ( postFinder && !postFinder[ expando ] ) {
2283		postFinder = setMatcher( postFinder, postSelector );
2284	}
2285	return markFunction( function( seed, results, context, xml ) {
2286		var temp, i, elem, matcherOut,
2287			preMap = [],
2288			postMap = [],
2289			preexisting = results.length,
2290
2291			// Get initial elements from seed or context
2292			elems = seed ||
2293				multipleContexts( selector || "*",
2294					context.nodeType ? [ context ] : context, [] ),
2295
2296			// Prefilter to get matcher input, preserving a map for seed-results synchronization
2297			matcherIn = preFilter && ( seed || !selector ) ?
2298				condense( elems, preMap, preFilter, context, xml ) :
2299				elems;
2300
2301		if ( matcher ) {
2302
2303			// If we have a postFinder, or filtered seed, or non-seed postFilter
2304			// or preexisting results,
2305			matcherOut = postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
2306
2307				// ...intermediate processing is necessary
2308				[] :
2309
2310				// ...otherwise use results directly
2311				results;
2312
2313			// Find primary matches
2314			matcher( matcherIn, matcherOut, context, xml );
2315		} else {
2316			matcherOut = matcherIn;
2317		}
2318
2319		// Apply postFilter
2320		if ( postFilter ) {
2321			temp = condense( matcherOut, postMap );
2322			postFilter( temp, [], context, xml );
2323
2324			// Un-match failing elements by moving them back to matcherIn
2325			i = temp.length;
2326			while ( i-- ) {
2327				if ( ( elem = temp[ i ] ) ) {
2328					matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem );
2329				}
2330			}
2331		}
2332
2333		if ( seed ) {
2334			if ( postFinder || preFilter ) {
2335				if ( postFinder ) {
2336
2337					// Get the final matcherOut by condensing this intermediate into postFinder contexts
2338					temp = [];
2339					i = matcherOut.length;
2340					while ( i-- ) {
2341						if ( ( elem = matcherOut[ i ] ) ) {
2342
2343							// Restore matcherIn since elem is not yet a final match
2344							temp.push( ( matcherIn[ i ] = elem ) );
2345						}
2346					}
2347					postFinder( null, ( matcherOut = [] ), temp, xml );
2348				}
2349
2350				// Move matched elements from seed to results to keep them synchronized
2351				i = matcherOut.length;
2352				while ( i-- ) {
2353					if ( ( elem = matcherOut[ i ] ) &&
2354						( temp = postFinder ? indexOf.call( seed, elem ) : preMap[ i ] ) > -1 ) {
2355
2356						seed[ temp ] = !( results[ temp ] = elem );
2357					}
2358				}
2359			}
2360
2361		// Add elements to results, through postFinder if defined
2362		} else {
2363			matcherOut = condense(
2364				matcherOut === results ?
2365					matcherOut.splice( preexisting, matcherOut.length ) :
2366					matcherOut
2367			);
2368			if ( postFinder ) {
2369				postFinder( null, results, matcherOut, xml );
2370			} else {
2371				push.apply( results, matcherOut );
2372			}
2373		}
2374	} );
2375}
2376
2377function matcherFromTokens( tokens ) {
2378	var checkContext, matcher, j,
2379		len = tokens.length,
2380		leadingRelative = Expr.relative[ tokens[ 0 ].type ],
2381		implicitRelative = leadingRelative || Expr.relative[ " " ],
2382		i = leadingRelative ? 1 : 0,
2383
2384		// The foundational matcher ensures that elements are reachable from top-level context(s)
2385		matchContext = addCombinator( function( elem ) {
2386			return elem === checkContext;
2387		}, implicitRelative, true ),
2388		matchAnyContext = addCombinator( function( elem ) {
2389			return indexOf.call( checkContext, elem ) > -1;
2390		}, implicitRelative, true ),
2391		matchers = [ function( elem, context, xml ) {
2392
2393			// Support: IE 11+, Edge 17 - 18+
2394			// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
2395			// two documents; shallow comparisons work.
2396			// eslint-disable-next-line eqeqeq
2397			var ret = ( !leadingRelative && ( xml || context != outermostContext ) ) || (
2398				( checkContext = context ).nodeType ?
2399					matchContext( elem, context, xml ) :
2400					matchAnyContext( elem, context, xml ) );
2401
2402			// Avoid hanging onto element
2403			// (see https://github.com/jquery/sizzle/issues/299)
2404			checkContext = null;
2405			return ret;
2406		} ];
2407
2408	for ( ; i < len; i++ ) {
2409		if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) {
2410			matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ];
2411		} else {
2412			matcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches );
2413
2414			// Return special upon seeing a positional matcher
2415			if ( matcher[ expando ] ) {
2416
2417				// Find the next relative operator (if any) for proper handling
2418				j = ++i;
2419				for ( ; j < len; j++ ) {
2420					if ( Expr.relative[ tokens[ j ].type ] ) {
2421						break;
2422					}
2423				}
2424				return setMatcher(
2425					i > 1 && elementMatcher( matchers ),
2426					i > 1 && toSelector(
2427
2428						// If the preceding token was a descendant combinator, insert an implicit any-element `*`
2429						tokens.slice( 0, i - 1 )
2430							.concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } )
2431					).replace( rtrimCSS, "$1" ),
2432					matcher,
2433					i < j && matcherFromTokens( tokens.slice( i, j ) ),
2434					j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ),
2435					j < len && toSelector( tokens )
2436				);
2437			}
2438			matchers.push( matcher );
2439		}
2440	}
2441
2442	return elementMatcher( matchers );
2443}
2444
2445function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
2446	var bySet = setMatchers.length > 0,
2447		byElement = elementMatchers.length > 0,
2448		superMatcher = function( seed, context, xml, results, outermost ) {
2449			var elem, j, matcher,
2450				matchedCount = 0,
2451				i = "0",
2452				unmatched = seed && [],
2453				setMatched = [],
2454				contextBackup = outermostContext,
2455
2456				// We must always have either seed elements or outermost context
2457				elems = seed || byElement && Expr.find.TAG( "*", outermost ),
2458
2459				// Use integer dirruns iff this is the outermost matcher
2460				dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ),
2461				len = elems.length;
2462
2463			if ( outermost ) {
2464
2465				// Support: IE 11+, Edge 17 - 18+
2466				// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
2467				// two documents; shallow comparisons work.
2468				// eslint-disable-next-line eqeqeq
2469				outermostContext = context == document || context || outermost;
2470			}
2471
2472			// Add elements passing elementMatchers directly to results
2473			// Support: iOS <=7 - 9 only
2474			// Tolerate NodeList properties (IE: "length"; Safari: <number>) matching
2475			// elements by id. (see trac-14142)
2476			for ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) {
2477				if ( byElement && elem ) {
2478					j = 0;
2479
2480					// Support: IE 11+, Edge 17 - 18+
2481					// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
2482					// two documents; shallow comparisons work.
2483					// eslint-disable-next-line eqeqeq
2484					if ( !context && elem.ownerDocument != document ) {
2485						setDocument( elem );
2486						xml = !documentIsHTML;
2487					}
2488					while ( ( matcher = elementMatchers[ j++ ] ) ) {
2489						if ( matcher( elem, context || document, xml ) ) {
2490							push.call( results, elem );
2491							break;
2492						}
2493					}
2494					if ( outermost ) {
2495						dirruns = dirrunsUnique;
2496					}
2497				}
2498
2499				// Track unmatched elements for set filters
2500				if ( bySet ) {
2501
2502					// They will have gone through all possible matchers
2503					if ( ( elem = !matcher && elem ) ) {
2504						matchedCount--;
2505					}
2506
2507					// Lengthen the array for every element, matched or not
2508					if ( seed ) {
2509						unmatched.push( elem );
2510					}
2511				}
2512			}
2513
2514			// `i` is now the count of elements visited above, and adding it to `matchedCount`
2515			// makes the latter nonnegative.
2516			matchedCount += i;
2517
2518			// Apply set filters to unmatched elements
2519			// NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`
2520			// equals `i`), unless we didn't visit _any_ elements in the above loop because we have
2521			// no element matchers and no seed.
2522			// Incrementing an initially-string "0" `i` allows `i` to remain a string only in that
2523			// case, which will result in a "00" `matchedCount` that differs from `i` but is also
2524			// numerically zero.
2525			if ( bySet && i !== matchedCount ) {
2526				j = 0;
2527				while ( ( matcher = setMatchers[ j++ ] ) ) {
2528					matcher( unmatched, setMatched, context, xml );
2529				}
2530
2531				if ( seed ) {
2532
2533					// Reintegrate element matches to eliminate the need for sorting
2534					if ( matchedCount > 0 ) {
2535						while ( i-- ) {
2536							if ( !( unmatched[ i ] || setMatched[ i ] ) ) {
2537								setMatched[ i ] = pop.call( results );
2538							}
2539						}
2540					}
2541
2542					// Discard index placeholder values to get only actual matches
2543					setMatched = condense( setMatched );
2544				}
2545
2546				// Add matches to results
2547				push.apply( results, setMatched );
2548
2549				// Seedless set matches succeeding multiple successful matchers stipulate sorting
2550				if ( outermost && !seed && setMatched.length > 0 &&
2551					( matchedCount + setMatchers.length ) > 1 ) {
2552
2553					jQuery.uniqueSort( results );
2554				}
2555			}
2556
2557			// Override manipulation of globals by nested matchers
2558			if ( outermost ) {
2559				dirruns = dirrunsUnique;
2560				outermostContext = contextBackup;
2561			}
2562
2563			return unmatched;
2564		};
2565
2566	return bySet ?
2567		markFunction( superMatcher ) :
2568		superMatcher;
2569}
2570
2571function compile( selector, match /* Internal Use Only */ ) {
2572	var i,
2573		setMatchers = [],
2574		elementMatchers = [],
2575		cached = compilerCache[ selector + " " ];
2576
2577	if ( !cached ) {
2578
2579		// Generate a function of recursive functions that can be used to check each element
2580		if ( !match ) {
2581			match = tokenize( selector );
2582		}
2583		i = match.length;
2584		while ( i-- ) {
2585			cached = matcherFromTokens( match[ i ] );
2586			if ( cached[ expando ] ) {
2587				setMatchers.push( cached );
2588			} else {
2589				elementMatchers.push( cached );
2590			}
2591		}
2592
2593		// Cache the compiled function
2594		cached = compilerCache( selector,
2595			matcherFromGroupMatchers( elementMatchers, setMatchers ) );
2596
2597		// Save selector and tokenization
2598		cached.selector = selector;
2599	}
2600	return cached;
2601}
2602
2603/**
2604 * A low-level selection function that works with jQuery's compiled
2605 *  selector functions
2606 * @param {String|Function} selector A selector or a pre-compiled
2607 *  selector function built with jQuery selector compile
2608 * @param {Element} context
2609 * @param {Array} [results]
2610 * @param {Array} [seed] A set of elements to match against
2611 */
2612function select( selector, context, results, seed ) {
2613	var i, tokens, token, type, find,
2614		compiled = typeof selector === "function" && selector,
2615		match = !seed && tokenize( ( selector = compiled.selector || selector ) );
2616
2617	results = results || [];
2618
2619	// Try to minimize operations if there is only one selector in the list and no seed
2620	// (the latter of which guarantees us context)
2621	if ( match.length === 1 ) {
2622
2623		// Reduce context if the leading compound selector is an ID
2624		tokens = match[ 0 ] = match[ 0 ].slice( 0 );
2625		if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" &&
2626				context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) {
2627
2628			context = ( Expr.find.ID(
2629				token.matches[ 0 ].replace( runescape, funescape ),
2630				context
2631			) || [] )[ 0 ];
2632			if ( !context ) {
2633				return results;
2634
2635			// Precompiled matchers will still verify ancestry, so step up a level
2636			} else if ( compiled ) {
2637				context = context.parentNode;
2638			}
2639
2640			selector = selector.slice( tokens.shift().value.length );
2641		}
2642
2643		// Fetch a seed set for right-to-left matching
2644		i = matchExpr.needsContext.test( selector ) ? 0 : tokens.length;
2645		while ( i-- ) {
2646			token = tokens[ i ];
2647
2648			// Abort if we hit a combinator
2649			if ( Expr.relative[ ( type = token.type ) ] ) {
2650				break;
2651			}
2652			if ( ( find = Expr.find[ type ] ) ) {
2653
2654				// Search, expanding context for leading sibling combinators
2655				if ( ( seed = find(
2656					token.matches[ 0 ].replace( runescape, funescape ),
2657					rsibling.test( tokens[ 0 ].type ) &&
2658						testContext( context.parentNode ) || context
2659				) ) ) {
2660
2661					// If seed is empty or no tokens remain, we can return early
2662					tokens.splice( i, 1 );
2663					selector = seed.length && toSelector( tokens );
2664					if ( !selector ) {
2665						push.apply( results, seed );
2666						return results;
2667					}
2668
2669					break;
2670				}
2671			}
2672		}
2673	}
2674
2675	// Compile and execute a filtering function if one is not provided
2676	// Provide `match` to avoid retokenization if we modified the selector above
2677	( compiled || compile( selector, match ) )(
2678		seed,
2679		context,
2680		!documentIsHTML,
2681		results,
2682		!context || rsibling.test( selector ) && testContext( context.parentNode ) || context
2683	);
2684	return results;
2685}
2686
2687// One-time assignments
2688
2689// Support: Android <=4.0 - 4.1+
2690// Sort stability
2691support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando;
2692
2693// Initialize against the default document
2694setDocument();
2695
2696// Support: Android <=4.0 - 4.1+
2697// Detached nodes confoundingly follow *each other*
2698support.sortDetached = assert( function( el ) {
2699
2700	// Should return 1, but returns 4 (following)
2701	return el.compareDocumentPosition( document.createElement( "fieldset" ) ) & 1;
2702} );
2703
2704jQuery.find = find;
2705
2706// Deprecated
2707jQuery.expr[ ":" ] = jQuery.expr.pseudos;
2708jQuery.unique = jQuery.uniqueSort;
2709
2710// These have always been private, but they used to be documented as part of
2711// Sizzle so let's maintain them for now for backwards compatibility purposes.
2712find.compile = compile;
2713find.select = select;
2714find.setDocument = setDocument;
2715find.tokenize = tokenize;
2716
2717find.escape = jQuery.escapeSelector;
2718find.getText = jQuery.text;
2719find.isXML = jQuery.isXMLDoc;
2720find.selectors = jQuery.expr;
2721find.support = jQuery.support;
2722find.uniqueSort = jQuery.uniqueSort;
2723
2724	/* eslint-enable */
2725
2726} )();
2727
2728
2729var dir = function( elem, dir, until ) {
2730	var matched = [],
2731		truncate = until !== undefined;
2732
2733	while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) {
2734		if ( elem.nodeType === 1 ) {
2735			if ( truncate && jQuery( elem ).is( until ) ) {
2736				break;
2737			}
2738			matched.push( elem );
2739		}
2740	}
2741	return matched;
2742};
2743
2744
2745var siblings = function( n, elem ) {
2746	var matched = [];
2747
2748	for ( ; n; n = n.nextSibling ) {
2749		if ( n.nodeType === 1 && n !== elem ) {
2750			matched.push( n );
2751		}
2752	}
2753
2754	return matched;
2755};
2756
2757
2758var rneedsContext = jQuery.expr.match.needsContext;
2759
2760var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i );
2761
2762
2763
2764// Implement the identical functionality for filter and not
2765function winnow( elements, qualifier, not ) {
2766	if ( isFunction( qualifier ) ) {
2767		return jQuery.grep( elements, function( elem, i ) {
2768			return !!qualifier.call( elem, i, elem ) !== not;
2769		} );
2770	}
2771
2772	// Single element
2773	if ( qualifier.nodeType ) {
2774		return jQuery.grep( elements, function( elem ) {
2775			return ( elem === qualifier ) !== not;
2776		} );
2777	}
2778
2779	// Arraylike of elements (jQuery, arguments, Array)
2780	if ( typeof qualifier !== "string" ) {
2781		return jQuery.grep( elements, function( elem ) {
2782			return ( indexOf.call( qualifier, elem ) > -1 ) !== not;
2783		} );
2784	}
2785
2786	// Filtered directly for both simple and complex selectors
2787	return jQuery.filter( qualifier, elements, not );
2788}
2789
2790jQuery.filter = function( expr, elems, not ) {
2791	var elem = elems[ 0 ];
2792
2793	if ( not ) {
2794		expr = ":not(" + expr + ")";
2795	}
2796
2797	if ( elems.length === 1 && elem.nodeType === 1 ) {
2798		return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [];
2799	}
2800
2801	return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
2802		return elem.nodeType === 1;
2803	} ) );
2804};
2805
2806jQuery.fn.extend( {
2807	find: function( selector ) {
2808		var i, ret,
2809			len = this.length,
2810			self = this;
2811
2812		if ( typeof selector !== "string" ) {
2813			return this.pushStack( jQuery( selector ).filter( function() {
2814				for ( i = 0; i < len; i++ ) {
2815					if ( jQuery.contains( self[ i ], this ) ) {
2816						return true;
2817					}
2818				}
2819			} ) );
2820		}
2821
2822		ret = this.pushStack( [] );
2823
2824		for ( i = 0; i < len; i++ ) {
2825			jQuery.find( selector, self[ i ], ret );
2826		}
2827
2828		return len > 1 ? jQuery.uniqueSort( ret ) : ret;
2829	},
2830	filter: function( selector ) {
2831		return this.pushStack( winnow( this, selector || [], false ) );
2832	},
2833	not: function( selector ) {
2834		return this.pushStack( winnow( this, selector || [], true ) );
2835	},
2836	is: function( selector ) {
2837		return !!winnow(
2838			this,
2839
2840			// If this is a positional/relative selector, check membership in the returned set
2841			// so $("p:first").is("p:last") won't return true for a doc with two "p".
2842			typeof selector === "string" && rneedsContext.test( selector ) ?
2843				jQuery( selector ) :
2844				selector || [],
2845			false
2846		).length;
2847	}
2848} );
2849
2850
2851// Initialize a jQuery object
2852
2853
2854// A central reference to the root jQuery(document)
2855var rootjQuery,
2856
2857	// A simple way to check for HTML strings
2858	// Prioritize #id over <tag> to avoid XSS via location.hash (trac-9521)
2859	// Strict HTML recognition (trac-11290: must start with <)
2860	// Shortcut simple #id case for speed
2861	rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,
2862
2863	init = jQuery.fn.init = function( selector, context, root ) {
2864		var match, elem;
2865
2866		// HANDLE: $(""), $(null), $(undefined), $(false)
2867		if ( !selector ) {
2868			return this;
2869		}
2870
2871		// Method init() accepts an alternate rootjQuery
2872		// so migrate can support jQuery.sub (gh-2101)
2873		root = root || rootjQuery;
2874
2875		// Handle HTML strings
2876		if ( typeof selector === "string" ) {
2877			if ( selector[ 0 ] === "<" &&
2878				selector[ selector.length - 1 ] === ">" &&
2879				selector.length >= 3 ) {
2880
2881				// Assume that strings that start and end with <> are HTML and skip the regex check
2882				match = [ null, selector, null ];
2883
2884			} else {
2885				match = rquickExpr.exec( selector );
2886			}
2887
2888			// Match html or make sure no context is specified for #id
2889			if ( match && ( match[ 1 ] || !context ) ) {
2890
2891				// HANDLE: $(html) -> $(array)
2892				if ( match[ 1 ] ) {
2893					context = context instanceof jQuery ? context[ 0 ] : context;
2894
2895					// Option to run scripts is true for back-compat
2896					// Intentionally let the error be thrown if parseHTML is not present
2897					jQuery.merge( this, jQuery.parseHTML(
2898						match[ 1 ],
2899						context && context.nodeType ? context.ownerDocument || context : document,
2900						true
2901					) );
2902
2903					// HANDLE: $(html, props)
2904					if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) {
2905						for ( match in context ) {
2906
2907							// Properties of context are called as methods if possible
2908							if ( isFunction( this[ match ] ) ) {
2909								this[ match ]( context[ match ] );
2910
2911							// ...and otherwise set as attributes
2912							} else {
2913								this.attr( match, context[ match ] );
2914							}
2915						}
2916					}
2917
2918					return this;
2919
2920				// HANDLE: $(#id)
2921				} else {
2922					elem = document.getElementById( match[ 2 ] );
2923
2924					if ( elem ) {
2925
2926						// Inject the element directly into the jQuery object
2927						this[ 0 ] = elem;
2928						this.length = 1;
2929					}
2930					return this;
2931				}
2932
2933			// HANDLE: $(expr, $(...))
2934			} else if ( !context || context.jquery ) {
2935				return ( context || root ).find( selector );
2936
2937			// HANDLE: $(expr, context)
2938			// (which is just equivalent to: $(context).find(expr)
2939			} else {
2940				return this.constructor( context ).find( selector );
2941			}
2942
2943		// HANDLE: $(DOMElement)
2944		} else if ( selector.nodeType ) {
2945			this[ 0 ] = selector;
2946			this.length = 1;
2947			return this;
2948
2949		// HANDLE: $(function)
2950		// Shortcut for document ready
2951		} else if ( isFunction( selector ) ) {
2952			return root.ready !== undefined ?
2953				root.ready( selector ) :
2954
2955				// Execute immediately if ready is not present
2956				selector( jQuery );
2957		}
2958
2959		return jQuery.makeArray( selector, this );
2960	};
2961
2962// Give the init function the jQuery prototype for later instantiation
2963init.prototype = jQuery.fn;
2964
2965// Initialize central reference
2966rootjQuery = jQuery( document );
2967
2968
2969var rparentsprev = /^(?:parents|prev(?:Until|All))/,
2970
2971	// Methods guaranteed to produce a unique set when starting from a unique set
2972	guaranteedUnique = {
2973		children: true,
2974		contents: true,
2975		next: true,
2976		prev: true
2977	};
2978
2979jQuery.fn.extend( {
2980	has: function( target ) {
2981		var targets = jQuery( target, this ),
2982			l = targets.length;
2983
2984		return this.filter( function() {
2985			var i = 0;
2986			for ( ; i < l; i++ ) {
2987				if ( jQuery.contains( this, targets[ i ] ) ) {
2988					return true;
2989				}
2990			}
2991		} );
2992	},
2993
2994	closest: function( selectors, context ) {
2995		var cur,
2996			i = 0,
2997			l = this.length,
2998			matched = [],
2999			targets = typeof selectors !== "string" && jQuery( selectors );
3000
3001		// Positional selectors never match, since there's no _selection_ context
3002		if ( !rneedsContext.test( selectors ) ) {
3003			for ( ; i < l; i++ ) {
3004				for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) {
3005
3006					// Always skip document fragments
3007					if ( cur.nodeType < 11 && ( targets ?
3008						targets.index( cur ) > -1 :
3009
3010						// Don't pass non-elements to jQuery#find
3011						cur.nodeType === 1 &&
3012							jQuery.find.matchesSelector( cur, selectors ) ) ) {
3013
3014						matched.push( cur );
3015						break;
3016					}
3017				}
3018			}
3019		}
3020
3021		return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched );
3022	},
3023
3024	// Determine the position of an element within the set
3025	index: function( elem ) {
3026
3027		// No argument, return index in parent
3028		if ( !elem ) {
3029			return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
3030		}
3031
3032		// Index in selector
3033		if ( typeof elem === "string" ) {
3034			return indexOf.call( jQuery( elem ), this[ 0 ] );
3035		}
3036
3037		// Locate the position of the desired element
3038		return indexOf.call( this,
3039
3040			// If it receives a jQuery object, the first element is used
3041			elem.jquery ? elem[ 0 ] : elem
3042		);
3043	},
3044
3045	add: function( selector, context ) {
3046		return this.pushStack(
3047			jQuery.uniqueSort(
3048				jQuery.merge( this.get(), jQuery( selector, context ) )
3049			)
3050		);
3051	},
3052
3053	addBack: function( selector ) {
3054		return this.add( selector == null ?
3055			this.prevObject : this.prevObject.filter( selector )
3056		);
3057	}
3058} );
3059
3060function sibling( cur, dir ) {
3061	while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {}
3062	return cur;
3063}
3064
3065jQuery.each( {
3066	parent: function( elem ) {
3067		var parent = elem.parentNode;
3068		return parent && parent.nodeType !== 11 ? parent : null;
3069	},
3070	parents: function( elem ) {
3071		return dir( elem, "parentNode" );
3072	},
3073	parentsUntil: function( elem, _i, until ) {
3074		return dir( elem, "parentNode", until );
3075	},
3076	next: function( elem ) {
3077		return sibling( elem, "nextSibling" );
3078	},
3079	prev: function( elem ) {
3080		return sibling( elem, "previousSibling" );
3081	},
3082	nextAll: function( elem ) {
3083		return dir( elem, "nextSibling" );
3084	},
3085	prevAll: function( elem ) {
3086		return dir( elem, "previousSibling" );
3087	},
3088	nextUntil: function( elem, _i, until ) {
3089		return dir( elem, "nextSibling", until );
3090	},
3091	prevUntil: function( elem, _i, until ) {
3092		return dir( elem, "previousSibling", until );
3093	},
3094	siblings: function( elem ) {
3095		return siblings( ( elem.parentNode || {} ).firstChild, elem );
3096	},
3097	children: function( elem ) {
3098		return siblings( elem.firstChild );
3099	},
3100	contents: function( elem ) {
3101		if ( elem.contentDocument != null &&
3102
3103			// Support: IE 11+
3104			// <object> elements with no `data` attribute has an object
3105			// `contentDocument` with a `null` prototype.
3106			getProto( elem.contentDocument ) ) {
3107
3108			return elem.contentDocument;
3109		}
3110
3111		// Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only
3112		// Treat the template element as a regular one in browsers that
3113		// don't support it.
3114		if ( nodeName( elem, "template" ) ) {
3115			elem = elem.content || elem;
3116		}
3117
3118		return jQuery.merge( [], elem.childNodes );
3119	}
3120}, function( name, fn ) {
3121	jQuery.fn[ name ] = function( until, selector ) {
3122		var matched = jQuery.map( this, fn, until );
3123
3124		if ( name.slice( -5 ) !== "Until" ) {
3125			selector = until;
3126		}
3127
3128		if ( selector && typeof selector === "string" ) {
3129			matched = jQuery.filter( selector, matched );
3130		}
3131
3132		if ( this.length > 1 ) {
3133
3134			// Remove duplicates
3135			if ( !guaranteedUnique[ name ] ) {
3136				jQuery.uniqueSort( matched );
3137			}
3138
3139			// Reverse order for parents* and prev-derivatives
3140			if ( rparentsprev.test( name ) ) {
3141				matched.reverse();
3142			}
3143		}
3144
3145		return this.pushStack( matched );
3146	};
3147} );
3148var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g );
3149
3150
3151
3152// Convert String-formatted options into Object-formatted ones
3153function createOptions( options ) {
3154	var object = {};
3155	jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) {
3156		object[ flag ] = true;
3157	} );
3158	return object;
3159}
3160
3161/*
3162 * Create a callback list using the following parameters:
3163 *
3164 *	options: an optional list of space-separated options that will change how
3165 *			the callback list behaves or a more traditional option object
3166 *
3167 * By default a callback list will act like an event callback list and can be
3168 * "fired" multiple times.
3169 *
3170 * Possible options:
3171 *
3172 *	once:			will ensure the callback list can only be fired once (like a Deferred)
3173 *
3174 *	memory:			will keep track of previous values and will call any callback added
3175 *					after the list has been fired right away with the latest "memorized"
3176 *					values (like a Deferred)
3177 *
3178 *	unique:			will ensure a callback can only be added once (no duplicate in the list)
3179 *
3180 *	stopOnFalse:	interrupt callings when a callback returns false
3181 *
3182 */
3183jQuery.Callbacks = function( options ) {
3184
3185	// Convert options from String-formatted to Object-formatted if needed
3186	// (we check in cache first)
3187	options = typeof options === "string" ?
3188		createOptions( options ) :
3189		jQuery.extend( {}, options );
3190
3191	var // Flag to know if list is currently firing
3192		firing,
3193
3194		// Last fire value for non-forgettable lists
3195		memory,
3196
3197		// Flag to know if list was already fired
3198		fired,
3199
3200		// Flag to prevent firing
3201		locked,
3202
3203		// Actual callback list
3204		list = [],
3205
3206		// Queue of execution data for repeatable lists
3207		queue = [],
3208
3209		// Index of currently firing callback (modified by add/remove as needed)
3210		firingIndex = -1,
3211
3212		// Fire callbacks
3213		fire = function() {
3214
3215			// Enforce single-firing
3216			locked = locked || options.once;
3217
3218			// Execute callbacks for all pending executions,
3219			// respecting firingIndex overrides and runtime changes
3220			fired = firing = true;
3221			for ( ; queue.length; firingIndex = -1 ) {
3222				memory = queue.shift();
3223				while ( ++firingIndex < list.length ) {
3224
3225					// Run callback and check for early termination
3226					if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false &&
3227						options.stopOnFalse ) {
3228
3229						// Jump to end and forget the data so .add doesn't re-fire
3230						firingIndex = list.length;
3231						memory = false;
3232					}
3233				}
3234			}
3235
3236			// Forget the data if we're done with it
3237			if ( !options.memory ) {
3238				memory = false;
3239			}
3240
3241			firing = false;
3242
3243			// Clean up if we're done firing for good
3244			if ( locked ) {
3245
3246				// Keep an empty list if we have data for future add calls
3247				if ( memory ) {
3248					list = [];
3249
3250				// Otherwise, this object is spent
3251				} else {
3252					list = "";
3253				}
3254			}
3255		},
3256
3257		// Actual Callbacks object
3258		self = {
3259
3260			// Add a callback or a collection of callbacks to the list
3261			add: function() {
3262				if ( list ) {
3263
3264					// If we have memory from a past run, we should fire after adding
3265					if ( memory && !firing ) {
3266						firingIndex = list.length - 1;
3267						queue.push( memory );
3268					}
3269
3270					( function add( args ) {
3271						jQuery.each( args, function( _, arg ) {
3272							if ( isFunction( arg ) ) {
3273								if ( !options.unique || !self.has( arg ) ) {
3274									list.push( arg );
3275								}
3276							} else if ( arg && arg.length && toType( arg ) !== "string" ) {
3277
3278								// Inspect recursively
3279								add( arg );
3280							}
3281						} );
3282					} )( arguments );
3283
3284					if ( memory && !firing ) {
3285						fire();
3286					}
3287				}
3288				return this;
3289			},
3290
3291			// Remove a callback from the list
3292			remove: function() {
3293				jQuery.each( arguments, function( _, arg ) {
3294					var index;
3295					while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
3296						list.splice( index, 1 );
3297
3298						// Handle firing indexes
3299						if ( index <= firingIndex ) {
3300							firingIndex--;
3301						}
3302					}
3303				} );
3304				return this;
3305			},
3306
3307			// Check if a given callback is in the list.
3308			// If no argument is given, return whether or not list has callbacks attached.
3309			has: function( fn ) {
3310				return fn ?
3311					jQuery.inArray( fn, list ) > -1 :
3312					list.length > 0;
3313			},
3314
3315			// Remove all callbacks from the list
3316			empty: function() {
3317				if ( list ) {
3318					list = [];
3319				}
3320				return this;
3321			},
3322
3323			// Disable .fire and .add
3324			// Abort any current/pending executions
3325			// Clear all callbacks and values
3326			disable: function() {
3327				locked = queue = [];
3328				list = memory = "";
3329				return this;
3330			},
3331			disabled: function() {
3332				return !list;
3333			},
3334
3335			// Disable .fire
3336			// Also disable .add unless we have memory (since it would have no effect)
3337			// Abort any pending executions
3338			lock: function() {
3339				locked = queue = [];
3340				if ( !memory && !firing ) {
3341					list = memory = "";
3342				}
3343				return this;
3344			},
3345			locked: function() {
3346				return !!locked;
3347			},
3348
3349			// Call all callbacks with the given context and arguments
3350			fireWith: function( context, args ) {
3351				if ( !locked ) {
3352					args = args || [];
3353					args = [ context, args.slice ? args.slice() : args ];
3354					queue.push( args );
3355					if ( !firing ) {
3356						fire();
3357					}
3358				}
3359				return this;
3360			},
3361
3362			// Call all the callbacks with the given arguments
3363			fire: function() {
3364				self.fireWith( this, arguments );
3365				return this;
3366			},
3367
3368			// To know if the callbacks have already been called at least once
3369			fired: function() {
3370				return !!fired;
3371			}
3372		};
3373
3374	return self;
3375};
3376
3377
3378function Identity( v ) {
3379	return v;
3380}
3381function Thrower( ex ) {
3382	throw ex;
3383}
3384
3385function adoptValue( value, resolve, reject, noValue ) {
3386	var method;
3387
3388	try {
3389
3390		// Check for promise aspect first to privilege synchronous behavior
3391		if ( value && isFunction( ( method = value.promise ) ) ) {
3392			method.call( value ).done( resolve ).fail( reject );
3393
3394		// Other thenables
3395		} else if ( value && isFunction( ( method = value.then ) ) ) {
3396			method.call( value, resolve, reject );
3397
3398		// Other non-thenables
3399		} else {
3400
3401			// Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer:
3402			// * false: [ value ].slice( 0 ) => resolve( value )
3403			// * true: [ value ].slice( 1 ) => resolve()
3404			resolve.apply( undefined, [ value ].slice( noValue ) );
3405		}
3406
3407	// For Promises/A+, convert exceptions into rejections
3408	// Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in
3409	// Deferred#then to conditionally suppress rejection.
3410	} catch ( value ) {
3411
3412		// Support: Android 4.0 only
3413		// Strict mode functions invoked without .call/.apply get global-object context
3414		reject.apply( undefined, [ value ] );
3415	}
3416}
3417
3418jQuery.extend( {
3419
3420	Deferred: function( func ) {
3421		var tuples = [
3422
3423				// action, add listener, callbacks,
3424				// ... .then handlers, argument index, [final state]
3425				[ "notify", "progress", jQuery.Callbacks( "memory" ),
3426					jQuery.Callbacks( "memory" ), 2 ],
3427				[ "resolve", "done", jQuery.Callbacks( "once memory" ),
3428					jQuery.Callbacks( "once memory" ), 0, "resolved" ],
3429				[ "reject", "fail", jQuery.Callbacks( "once memory" ),
3430					jQuery.Callbacks( "once memory" ), 1, "rejected" ]
3431			],
3432			state = "pending",
3433			promise = {
3434				state: function() {
3435					return state;
3436				},
3437				always: function() {
3438					deferred.done( arguments ).fail( arguments );
3439					return this;
3440				},
3441				"catch": function( fn ) {
3442					return promise.then( null, fn );
3443				},
3444
3445				// Keep pipe for back-compat
3446				pipe: function( /* fnDone, fnFail, fnProgress */ ) {
3447					var fns = arguments;
3448
3449					return jQuery.Deferred( function( newDefer ) {
3450						jQuery.each( tuples, function( _i, tuple ) {
3451
3452							// Map tuples (progress, done, fail) to arguments (done, fail, progress)
3453							var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ];
3454
3455							// deferred.progress(function() { bind to newDefer or newDefer.notify })
3456							// deferred.done(function() { bind to newDefer or newDefer.resolve })
3457							// deferred.fail(function() { bind to newDefer or newDefer.reject })
3458							deferred[ tuple[ 1 ] ]( function() {
3459								var returned = fn && fn.apply( this, arguments );
3460								if ( returned && isFunction( returned.promise ) ) {
3461									returned.promise()
3462										.progress( newDefer.notify )
3463										.done( newDefer.resolve )
3464										.fail( newDefer.reject );
3465								} else {
3466									newDefer[ tuple[ 0 ] + "With" ](
3467										this,
3468										fn ? [ returned ] : arguments
3469									);
3470								}
3471							} );
3472						} );
3473						fns = null;
3474					} ).promise();
3475				},
3476				then: function( onFulfilled, onRejected, onProgress ) {
3477					var maxDepth = 0;
3478					function resolve( depth, deferred, handler, special ) {
3479						return function() {
3480							var that = this,
3481								args = arguments,
3482								mightThrow = function() {
3483									var returned, then;
3484
3485									// Support: Promises/A+ section 2.3.3.3.3
3486									// https://promisesaplus.com/#point-59
3487									// Ignore double-resolution attempts
3488									if ( depth < maxDepth ) {
3489										return;
3490									}
3491
3492									returned = handler.apply( that, args );
3493
3494									// Support: Promises/A+ section 2.3.1
3495									// https://promisesaplus.com/#point-48
3496									if ( returned === deferred.promise() ) {
3497										throw new TypeError( "Thenable self-resolution" );
3498									}
3499
3500									// Support: Promises/A+ sections 2.3.3.1, 3.5
3501									// https://promisesaplus.com/#point-54
3502									// https://promisesaplus.com/#point-75
3503									// Retrieve `then` only once
3504									then = returned &&
3505
3506										// Support: Promises/A+ section 2.3.4
3507										// https://promisesaplus.com/#point-64
3508										// Only check objects and functions for thenability
3509										( typeof returned === "object" ||
3510											typeof returned === "function" ) &&
3511										returned.then;
3512
3513									// Handle a returned thenable
3514									if ( isFunction( then ) ) {
3515
3516										// Special processors (notify) just wait for resolution
3517										if ( special ) {
3518											then.call(
3519												returned,
3520												resolve( maxDepth, deferred, Identity, special ),
3521												resolve( maxDepth, deferred, Thrower, special )
3522											);
3523
3524										// Normal processors (resolve) also hook into progress
3525										} else {
3526
3527											// ...and disregard older resolution values
3528											maxDepth++;
3529
3530											then.call(
3531												returned,
3532												resolve( maxDepth, deferred, Identity, special ),
3533												resolve( maxDepth, deferred, Thrower, special ),
3534												resolve( maxDepth, deferred, Identity,
3535													deferred.notifyWith )
3536											);
3537										}
3538
3539									// Handle all other returned values
3540									} else {
3541
3542										// Only substitute handlers pass on context
3543										// and multiple values (non-spec behavior)
3544										if ( handler !== Identity ) {
3545											that = undefined;
3546											args = [ returned ];
3547										}
3548
3549										// Process the value(s)
3550										// Default process is resolve
3551										( special || deferred.resolveWith )( that, args );
3552									}
3553								},
3554
3555								// Only normal processors (resolve) catch and reject exceptions
3556								process = special ?
3557									mightThrow :
3558									function() {
3559										try {
3560											mightThrow();
3561										} catch ( e ) {
3562
3563											if ( jQuery.Deferred.exceptionHook ) {
3564												jQuery.Deferred.exceptionHook( e,
3565													process.error );
3566											}
3567
3568											// Support: Promises/A+ section 2.3.3.3.4.1
3569											// https://promisesaplus.com/#point-61
3570											// Ignore post-resolution exceptions
3571											if ( depth + 1 >= maxDepth ) {
3572
3573												// Only substitute handlers pass on context
3574												// and multiple values (non-spec behavior)
3575												if ( handler !== Thrower ) {
3576													that = undefined;
3577													args = [ e ];
3578												}
3579
3580												deferred.rejectWith( that, args );
3581											}
3582										}
3583									};
3584
3585							// Support: Promises/A+ section 2.3.3.3.1
3586							// https://promisesaplus.com/#point-57
3587							// Re-resolve promises immediately to dodge false rejection from
3588							// subsequent errors
3589							if ( depth ) {
3590								process();
3591							} else {
3592
3593								// Call an optional hook to record the error, in case of exception
3594								// since it's otherwise lost when execution goes async
3595								if ( jQuery.Deferred.getErrorHook ) {
3596									process.error = jQuery.Deferred.getErrorHook();
3597
3598								// The deprecated alias of the above. While the name suggests
3599								// returning the stack, not an error instance, jQuery just passes
3600								// it directly to `console.warn` so both will work; an instance
3601								// just better cooperates with source maps.
3602								} else if ( jQuery.Deferred.getStackHook ) {
3603									process.error = jQuery.Deferred.getStackHook();
3604								}
3605								window.setTimeout( process );
3606							}
3607						};
3608					}
3609
3610					return jQuery.Deferred( function( newDefer ) {
3611
3612						// progress_handlers.add( ... )
3613						tuples[ 0 ][ 3 ].add(
3614							resolve(
3615								0,
3616								newDefer,
3617								isFunction( onProgress ) ?
3618									onProgress :
3619									Identity,
3620								newDefer.notifyWith
3621							)
3622						);
3623
3624						// fulfilled_handlers.add( ... )
3625						tuples[ 1 ][ 3 ].add(
3626							resolve(
3627								0,
3628								newDefer,
3629								isFunction( onFulfilled ) ?
3630									onFulfilled :
3631									Identity
3632							)
3633						);
3634
3635						// rejected_handlers.add( ... )
3636						tuples[ 2 ][ 3 ].add(
3637							resolve(
3638								0,
3639								newDefer,
3640								isFunction( onRejected ) ?
3641									onRejected :
3642									Thrower
3643							)
3644						);
3645					} ).promise();
3646				},
3647
3648				// Get a promise for this deferred
3649				// If obj is provided, the promise aspect is added to the object
3650				promise: function( obj ) {
3651					return obj != null ? jQuery.extend( obj, promise ) : promise;
3652				}
3653			},
3654			deferred = {};
3655
3656		// Add list-specific methods
3657		jQuery.each( tuples, function( i, tuple ) {
3658			var list = tuple[ 2 ],
3659				stateString = tuple[ 5 ];
3660
3661			// promise.progress = list.add
3662			// promise.done = list.add
3663			// promise.fail = list.add
3664			promise[ tuple[ 1 ] ] = list.add;
3665
3666			// Handle state
3667			if ( stateString ) {
3668				list.add(
3669					function() {
3670
3671						// state = "resolved" (i.e., fulfilled)
3672						// state = "rejected"
3673						state = stateString;
3674					},
3675
3676					// rejected_callbacks.disable
3677					// fulfilled_callbacks.disable
3678					tuples[ 3 - i ][ 2 ].disable,
3679
3680					// rejected_handlers.disable
3681					// fulfilled_handlers.disable
3682					tuples[ 3 - i ][ 3 ].disable,
3683
3684					// progress_callbacks.lock
3685					tuples[ 0 ][ 2 ].lock,
3686
3687					// progress_handlers.lock
3688					tuples[ 0 ][ 3 ].lock
3689				);
3690			}
3691
3692			// progress_handlers.fire
3693			// fulfilled_handlers.fire
3694			// rejected_handlers.fire
3695			list.add( tuple[ 3 ].fire );
3696
3697			// deferred.notify = function() { deferred.notifyWith(...) }
3698			// deferred.resolve = function() { deferred.resolveWith(...) }
3699			// deferred.reject = function() { deferred.rejectWith(...) }
3700			deferred[ tuple[ 0 ] ] = function() {
3701				deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments );
3702				return this;
3703			};
3704
3705			// deferred.notifyWith = list.fireWith
3706			// deferred.resolveWith = list.fireWith
3707			// deferred.rejectWith = list.fireWith
3708			deferred[ tuple[ 0 ] + "With" ] = list.fireWith;
3709		} );
3710
3711		// Make the deferred a promise
3712		promise.promise( deferred );
3713
3714		// Call given func if any
3715		if ( func ) {
3716			func.call( deferred, deferred );
3717		}
3718
3719		// All done!
3720		return deferred;
3721	},
3722
3723	// Deferred helper
3724	when: function( singleValue ) {
3725		var
3726
3727			// count of uncompleted subordinates
3728			remaining = arguments.length,
3729
3730			// count of unprocessed arguments
3731			i = remaining,
3732
3733			// subordinate fulfillment data
3734			resolveContexts = Array( i ),
3735			resolveValues = slice.call( arguments ),
3736
3737			// the primary Deferred
3738			primary = jQuery.Deferred(),
3739
3740			// subordinate callback factory
3741			updateFunc = function( i ) {
3742				return function( value ) {
3743					resolveContexts[ i ] = this;
3744					resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
3745					if ( !( --remaining ) ) {
3746						primary.resolveWith( resolveContexts, resolveValues );
3747					}
3748				};
3749			};
3750
3751		// Single- and empty arguments are adopted like Promise.resolve
3752		if ( remaining <= 1 ) {
3753			adoptValue( singleValue, primary.done( updateFunc( i ) ).resolve, primary.reject,
3754				!remaining );
3755
3756			// Use .then() to unwrap secondary thenables (cf. gh-3000)
3757			if ( primary.state() === "pending" ||
3758				isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) {
3759
3760				return primary.then();
3761			}
3762		}
3763
3764		// Multiple arguments are aggregated like Promise.all array elements
3765		while ( i-- ) {
3766			adoptValue( resolveValues[ i ], updateFunc( i ), primary.reject );
3767		}
3768
3769		return primary.promise();
3770	}
3771} );
3772
3773
3774// These usually indicate a programmer mistake during development,
3775// warn about them ASAP rather than swallowing them by default.
3776var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;
3777
3778// If `jQuery.Deferred.getErrorHook` is defined, `asyncError` is an error
3779// captured before the async barrier to get the original error cause
3780// which may otherwise be hidden.
3781jQuery.Deferred.exceptionHook = function( error, asyncError ) {
3782
3783	// Support: IE 8 - 9 only
3784	// Console exists when dev tools are open, which can happen at any time
3785	if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) {
3786		window.console.warn( "jQuery.Deferred exception: " + error.message,
3787			error.stack, asyncError );
3788	}
3789};
3790
3791
3792
3793
3794jQuery.readyException = function( error ) {
3795	window.setTimeout( function() {
3796		throw error;
3797	} );
3798};
3799
3800
3801
3802
3803// The deferred used on DOM ready
3804var readyList = jQuery.Deferred();
3805
3806jQuery.fn.ready = function( fn ) {
3807
3808	readyList
3809		.then( fn )
3810
3811		// Wrap jQuery.readyException in a function so that the lookup
3812		// happens at the time of error handling instead of callback
3813		// registration.
3814		.catch( function( error ) {
3815			jQuery.readyException( error );
3816		} );
3817
3818	return this;
3819};
3820
3821jQuery.extend( {
3822
3823	// Is the DOM ready to be used? Set to true once it occurs.
3824	isReady: false,
3825
3826	// A counter to track how many items to wait for before
3827	// the ready event fires. See trac-6781
3828	readyWait: 1,
3829
3830	// Handle when the DOM is ready
3831	ready: function( wait ) {
3832
3833		// Abort if there are pending holds or we're already ready
3834		if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
3835			return;
3836		}
3837
3838		// Remember that the DOM is ready
3839		jQuery.isReady = true;
3840
3841		// If a normal DOM Ready event fired, decrement, and wait if need be
3842		if ( wait !== true && --jQuery.readyWait > 0 ) {
3843			return;
3844		}
3845
3846		// If there are functions bound, to execute
3847		readyList.resolveWith( document, [ jQuery ] );
3848	}
3849} );
3850
3851jQuery.ready.then = readyList.then;
3852
3853// The ready event handler and self cleanup method
3854function completed() {
3855	document.removeEventListener( "DOMContentLoaded", completed );
3856	window.removeEventListener( "load", completed );
3857	jQuery.ready();
3858}
3859
3860// Catch cases where $(document).ready() is called
3861// after the browser event has already occurred.
3862// Support: IE <=9 - 10 only
3863// Older IE sometimes signals "interactive" too soon
3864if ( document.readyState === "complete" ||
3865	( document.readyState !== "loading" && !document.documentElement.doScroll ) ) {
3866
3867	// Handle it asynchronously to allow scripts the opportunity to delay ready
3868	window.setTimeout( jQuery.ready );
3869
3870} else {
3871
3872	// Use the handy event callback
3873	document.addEventListener( "DOMContentLoaded", completed );
3874
3875	// A fallback to window.onload, that will always work
3876	window.addEventListener( "load", completed );
3877}
3878
3879
3880
3881
3882// Multifunctional method to get and set values of a collection
3883// The value/s can optionally be executed if it's a function
3884var access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
3885	var i = 0,
3886		len = elems.length,
3887		bulk = key == null;
3888
3889	// Sets many values
3890	if ( toType( key ) === "object" ) {
3891		chainable = true;
3892		for ( i in key ) {
3893			access( elems, fn, i, key[ i ], true, emptyGet, raw );
3894		}
3895
3896	// Sets one value
3897	} else if ( value !== undefined ) {
3898		chainable = true;
3899
3900		if ( !isFunction( value ) ) {
3901			raw = true;
3902		}
3903
3904		if ( bulk ) {
3905
3906			// Bulk operations run against the entire set
3907			if ( raw ) {
3908				fn.call( elems, value );
3909				fn = null;
3910
3911			// ...except when executing function values
3912			} else {
3913				bulk = fn;
3914				fn = function( elem, _key, value ) {
3915					return bulk.call( jQuery( elem ), value );
3916				};
3917			}
3918		}
3919
3920		if ( fn ) {
3921			for ( ; i < len; i++ ) {
3922				fn(
3923					elems[ i ], key, raw ?
3924						value :
3925						value.call( elems[ i ], i, fn( elems[ i ], key ) )
3926				);
3927			}
3928		}
3929	}
3930
3931	if ( chainable ) {
3932		return elems;
3933	}
3934
3935	// Gets
3936	if ( bulk ) {
3937		return fn.call( elems );
3938	}
3939
3940	return len ? fn( elems[ 0 ], key ) : emptyGet;
3941};
3942
3943
3944// Matches dashed string for camelizing
3945var rmsPrefix = /^-ms-/,
3946	rdashAlpha = /-([a-z])/g;
3947
3948// Used by camelCase as callback to replace()
3949function fcamelCase( _all, letter ) {
3950	return letter.toUpperCase();
3951}
3952
3953// Convert dashed to camelCase; used by the css and data modules
3954// Support: IE <=9 - 11, Edge 12 - 15
3955// Microsoft forgot to hump their vendor prefix (trac-9572)
3956function camelCase( string ) {
3957	return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
3958}
3959var acceptData = function( owner ) {
3960
3961	// Accepts only:
3962	//  - Node
3963	//    - Node.ELEMENT_NODE
3964	//    - Node.DOCUMENT_NODE
3965	//  - Object
3966	//    - Any
3967	return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );
3968};
3969
3970
3971
3972
3973function Data() {
3974	this.expando = jQuery.expando + Data.uid++;
3975}
3976
3977Data.uid = 1;
3978
3979Data.prototype = {
3980
3981	cache: function( owner ) {
3982
3983		// Check if the owner object already has a cache
3984		var value = owner[ this.expando ];
3985
3986		// If not, create one
3987		if ( !value ) {
3988			value = {};
3989
3990			// We can accept data for non-element nodes in modern browsers,
3991			// but we should not, see trac-8335.
3992			// Always return an empty object.
3993			if ( acceptData( owner ) ) {
3994
3995				// If it is a node unlikely to be stringify-ed or looped over
3996				// use plain assignment
3997				if ( owner.nodeType ) {
3998					owner[ this.expando ] = value;
3999
4000				// Otherwise secure it in a non-enumerable property
4001				// configurable must be true to allow the property to be
4002				// deleted when data is removed
4003				} else {
4004					Object.defineProperty( owner, this.expando, {
4005						value: value,
4006						configurable: true
4007					} );
4008				}
4009			}
4010		}
4011
4012		return value;
4013	},
4014	set: function( owner, data, value ) {
4015		var prop,
4016			cache = this.cache( owner );
4017
4018		// Handle: [ owner, key, value ] args
4019		// Always use camelCase key (gh-2257)
4020		if ( typeof data === "string" ) {
4021			cache[ camelCase( data ) ] = value;
4022
4023		// Handle: [ owner, { properties } ] args
4024		} else {
4025
4026			// Copy the properties one-by-one to the cache object
4027			for ( prop in data ) {
4028				cache[ camelCase( prop ) ] = data[ prop ];
4029			}
4030		}
4031		return cache;
4032	},
4033	get: function( owner, key ) {
4034		return key === undefined ?
4035			this.cache( owner ) :
4036
4037			// Always use camelCase key (gh-2257)
4038			owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ];
4039	},
4040	access: function( owner, key, value ) {
4041
4042		// In cases where either:
4043		//
4044		//   1. No key was specified
4045		//   2. A string key was specified, but no value provided
4046		//
4047		// Take the "read" path and allow the get method to determine
4048		// which value to return, respectively either:
4049		//
4050		//   1. The entire cache object
4051		//   2. The data stored at the key
4052		//
4053		if ( key === undefined ||
4054				( ( key && typeof key === "string" ) && value === undefined ) ) {
4055
4056			return this.get( owner, key );
4057		}
4058
4059		// When the key is not a string, or both a key and value
4060		// are specified, set or extend (existing objects) with either:
4061		//
4062		//   1. An object of properties
4063		//   2. A key and value
4064		//
4065		this.set( owner, key, value );
4066
4067		// Since the "set" path can have two possible entry points
4068		// return the expected data based on which path was taken[*]
4069		return value !== undefined ? value : key;
4070	},
4071	remove: function( owner, key ) {
4072		var i,
4073			cache = owner[ this.expando ];
4074
4075		if ( cache === undefined ) {
4076			return;
4077		}
4078
4079		if ( key !== undefined ) {
4080
vendor: 4,799 bytes, lines 4081-4263
4081			// Support array or space separated string of keys
4082			if ( Array.isArray( key ) ) {
4083
4084				// If key is an array of keys...
4085				// We always set camelCase keys, so remove that.
4086				key = key.map( camelCase );
4087			} else {
4088				key = camelCase( key );
4089
4090				// If a key with the spaces exists, use it.
4091				// Otherwise, create an array by matching non-whitespace
4092				key = key in cache ?
4093					[ key ] :
4094					( key.match( rnothtmlwhite ) || [] );
4095			}
4096
4097			i = key.length;
4098
4099			while ( i-- ) {
4100				delete cache[ key[ i ] ];
4101			}
4102		}
4103
4104		// Remove the expando if there's no more data
4105		if ( key === undefined || jQuery.isEmptyObject( cache ) ) {
4106
4107			// Support: Chrome <=35 - 45
4108			// Webkit & Blink performance suffers when deleting properties
4109			// from DOM nodes, so set to undefined instead
4110			// https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted)
4111			if ( owner.nodeType ) {
4112				owner[ this.expando ] = undefined;
4113			} else {
4114				delete owner[ this.expando ];
4115			}
4116		}
4117	},
4118	hasData: function( owner ) {
4119		var cache = owner[ this.expando ];
4120		return cache !== undefined && !jQuery.isEmptyObject( cache );
4121	}
4122};
4123var dataPriv = new Data();
4124
4125var dataUser = new Data();
4126
4127
4128
4129//	Implementation Summary
4130//
4131//	1. Enforce API surface and semantic compatibility with 1.9.x branch
4132//	2. Improve the module's maintainability by reducing the storage
4133//		paths to a single mechanism.
4134//	3. Use the same single mechanism to support "private" and "user" data.
4135//	4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData)
4136//	5. Avoid exposing implementation details on user objects (eg. expando properties)
4137//	6. Provide a clear path for implementation upgrade to WeakMap in 2014
4138
4139var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
4140	rmultiDash = /[A-Z]/g;
4141
4142function getData( data ) {
4143	if ( data === "true" ) {
4144		return true;
4145	}
4146
4147	if ( data === "false" ) {
4148		return false;
4149	}
4150
4151	if ( data === "null" ) {
4152		return null;
4153	}
4154
4155	// Only convert to a number if it doesn't change the string
4156	if ( data === +data + "" ) {
4157		return +data;
4158	}
4159
4160	if ( rbrace.test( data ) ) {
4161		return JSON.parse( data );
4162	}
4163
4164	return data;
4165}
4166
4167function dataAttr( elem, key, data ) {
4168	var name;
4169
4170	// If nothing was found internally, try to fetch any
4171	// data from the HTML5 data-* attribute
4172	if ( data === undefined && elem.nodeType === 1 ) {
4173		name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase();
4174		data = elem.getAttribute( name );
4175
4176		if ( typeof data === "string" ) {
4177			try {
4178				data = getData( data );
4179			} catch ( e ) {}
4180
4181			// Make sure we set the data so it isn't changed later
4182			dataUser.set( elem, key, data );
4183		} else {
4184			data = undefined;
4185		}
4186	}
4187	return data;
4188}
4189
4190jQuery.extend( {
4191	hasData: function( elem ) {
4192		return dataUser.hasData( elem ) || dataPriv.hasData( elem );
4193	},
4194
4195	data: function( elem, name, data ) {
4196		return dataUser.access( elem, name, data );
4197	},
4198
4199	removeData: function( elem, name ) {
4200		dataUser.remove( elem, name );
4201	},
4202
4203	// TODO: Now that all calls to _data and _removeData have been replaced
4204	// with direct calls to dataPriv methods, these can be deprecated.
4205	_data: function( elem, name, data ) {
4206		return dataPriv.access( elem, name, data );
4207	},
4208
4209	_removeData: function( elem, name ) {
4210		dataPriv.remove( elem, name );
4211	}
4212} );
4213
4214jQuery.fn.extend( {
4215	data: function( key, value ) {
4216		var i, name, data,
4217			elem = this[ 0 ],
4218			attrs = elem && elem.attributes;
4219
4220		// Gets all values
4221		if ( key === undefined ) {
4222			if ( this.length ) {
4223				data = dataUser.get( elem );
4224
4225				if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) {
4226					i = attrs.length;
4227					while ( i-- ) {
4228
4229						// Support: IE 11 only
4230						// The attrs elements can be null (trac-14894)
4231						if ( attrs[ i ] ) {
4232							name = attrs[ i ].name;
4233							if ( name.indexOf( "data-" ) === 0 ) {
4234								name = camelCase( name.slice( 5 ) );
4235								dataAttr( elem, name, data[ name ] );
4236							}
4237						}
4238					}
4239					dataPriv.set( elem, "hasDataAttrs", true );
4240				}
4241			}
4242
4243			return data;
4244		}
4245
4246		// Sets multiple values
4247		if ( typeof key === "object" ) {
4248			return this.each( function() {
4249				dataUser.set( this, key );
4250			} );
4251		}
4252
4253		return access( this, function( value ) {
4254			var data;
4255
4256			// The calling jQuery object (element matches) is not empty
4257			// (and therefore has an element appears at this[ 0 ]) and the
4258			// `value` parameter was not undefined. An empty jQuery object
4259			// will result in `undefined` for elem = this[ 0 ] which will
4260			// throw an exception if an attempt to read a data cache is made.
4261			if ( elem && value === undefined ) {
4262
4263				// Attempt to get data from the cache
vendor: 20,334 bytes, lines 4264-5037
4264				// The key will always be camelCased in Data
4265				data = dataUser.get( elem, key );
4266				if ( data !== undefined ) {
4267					return data;
4268				}
4269
4270				// Attempt to "discover" the data in
4271				// HTML5 custom data-* attrs
4272				data = dataAttr( elem, key );
4273				if ( data !== undefined ) {
4274					return data;
4275				}
4276
4277				// We tried really hard, but the data doesn't exist.
4278				return;
4279			}
4280
4281			// Set the data...
4282			this.each( function() {
4283
4284				// We always store the camelCased key
4285				dataUser.set( this, key, value );
4286			} );
4287		}, null, value, arguments.length > 1, null, true );
4288	},
4289
4290	removeData: function( key ) {
4291		return this.each( function() {
4292			dataUser.remove( this, key );
4293		} );
4294	}
4295} );
4296
4297
4298jQuery.extend( {
4299	queue: function( elem, type, data ) {
4300		var queue;
4301
4302		if ( elem ) {
4303			type = ( type || "fx" ) + "queue";
4304			queue = dataPriv.get( elem, type );
4305
4306			// Speed up dequeue by getting out quickly if this is just a lookup
4307			if ( data ) {
4308				if ( !queue || Array.isArray( data ) ) {
4309					queue = dataPriv.access( elem, type, jQuery.makeArray( data ) );
4310				} else {
4311					queue.push( data );
4312				}
4313			}
4314			return queue || [];
4315		}
4316	},
4317
4318	dequeue: function( elem, type ) {
4319		type = type || "fx";
4320
4321		var queue = jQuery.queue( elem, type ),
4322			startLength = queue.length,
4323			fn = queue.shift(),
4324			hooks = jQuery._queueHooks( elem, type ),
4325			next = function() {
4326				jQuery.dequeue( elem, type );
4327			};
4328
4329		// If the fx queue is dequeued, always remove the progress sentinel
4330		if ( fn === "inprogress" ) {
4331			fn = queue.shift();
4332			startLength--;
4333		}
4334
4335		if ( fn ) {
4336
4337			// Add a progress sentinel to prevent the fx queue from being
4338			// automatically dequeued
4339			if ( type === "fx" ) {
4340				queue.unshift( "inprogress" );
4341			}
4342
4343			// Clear up the last queue stop function
4344			delete hooks.stop;
4345			fn.call( elem, next, hooks );
4346		}
4347
4348		if ( !startLength && hooks ) {
4349			hooks.empty.fire();
4350		}
4351	},
4352
4353	// Not public - generate a queueHooks object, or return the current one
4354	_queueHooks: function( elem, type ) {
4355		var key = type + "queueHooks";
4356		return dataPriv.get( elem, key ) || dataPriv.access( elem, key, {
4357			empty: jQuery.Callbacks( "once memory" ).add( function() {
4358				dataPriv.remove( elem, [ type + "queue", key ] );
4359			} )
4360		} );
4361	}
4362} );
4363
4364jQuery.fn.extend( {
4365	queue: function( type, data ) {
4366		var setter = 2;
4367
4368		if ( typeof type !== "string" ) {
4369			data = type;
4370			type = "fx";
4371			setter--;
4372		}
4373
4374		if ( arguments.length < setter ) {
4375			return jQuery.queue( this[ 0 ], type );
4376		}
4377
4378		return data === undefined ?
4379			this :
4380			this.each( function() {
4381				var queue = jQuery.queue( this, type, data );
4382
4383				// Ensure a hooks for this queue
4384				jQuery._queueHooks( this, type );
4385
4386				if ( type === "fx" && queue[ 0 ] !== "inprogress" ) {
4387					jQuery.dequeue( this, type );
4388				}
4389			} );
4390	},
4391	dequeue: function( type ) {
4392		return this.each( function() {
4393			jQuery.dequeue( this, type );
4394		} );
4395	},
4396	clearQueue: function( type ) {
4397		return this.queue( type || "fx", [] );
4398	},
4399
4400	// Get a promise resolved when queues of a certain type
4401	// are emptied (fx is the type by default)
4402	promise: function( type, obj ) {
4403		var tmp,
4404			count = 1,
4405			defer = jQuery.Deferred(),
4406			elements = this,
4407			i = this.length,
4408			resolve = function() {
4409				if ( !( --count ) ) {
4410					defer.resolveWith( elements, [ elements ] );
4411				}
4412			};
4413
4414		if ( typeof type !== "string" ) {
4415			obj = type;
4416			type = undefined;
4417		}
4418		type = type || "fx";
4419
4420		while ( i-- ) {
4421			tmp = dataPriv.get( elements[ i ], type + "queueHooks" );
4422			if ( tmp && tmp.empty ) {
4423				count++;
4424				tmp.empty.add( resolve );
4425			}
4426		}
4427		resolve();
4428		return defer.promise( obj );
4429	}
4430} );
4431var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source;
4432
4433var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" );
4434
4435
4436var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
4437
4438var documentElement = document.documentElement;
4439
4440
4441
4442	var isAttached = function( elem ) {
4443			return jQuery.contains( elem.ownerDocument, elem );
4444		},
4445		composed = { composed: true };
4446
4447	// Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only
4448	// Check attachment across shadow DOM boundaries when possible (gh-3504)
4449	// Support: iOS 10.0-10.2 only
4450	// Early iOS 10 versions support `attachShadow` but not `getRootNode`,
4451	// leading to errors. We need to check for `getRootNode`.
4452	if ( documentElement.getRootNode ) {
4453		isAttached = function( elem ) {
4454			return jQuery.contains( elem.ownerDocument, elem ) ||
4455				elem.getRootNode( composed ) === elem.ownerDocument;
4456		};
4457	}
4458var isHiddenWithinTree = function( elem, el ) {
4459
4460		// isHiddenWithinTree might be called from jQuery#filter function;
4461		// in that case, element will be second argument
4462		elem = el || elem;
4463
4464		// Inline style trumps all
4465		return elem.style.display === "none" ||
4466			elem.style.display === "" &&
4467
4468			// Otherwise, check computed style
4469			// Support: Firefox <=43 - 45
4470			// Disconnected elements can have computed display: none, so first confirm that elem is
4471			// in the document.
4472			isAttached( elem ) &&
4473
4474			jQuery.css( elem, "display" ) === "none";
4475	};
4476
4477
4478
4479function adjustCSS( elem, prop, valueParts, tween ) {
4480	var adjusted, scale,
4481		maxIterations = 20,
4482		currentValue = tween ?
4483			function() {
4484				return tween.cur();
4485			} :
4486			function() {
4487				return jQuery.css( elem, prop, "" );
4488			},
4489		initial = currentValue(),
4490		unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
4491
4492		// Starting value computation is required for potential unit mismatches
4493		initialInUnit = elem.nodeType &&
4494			( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) &&
4495			rcssNum.exec( jQuery.css( elem, prop ) );
4496
4497	if ( initialInUnit && initialInUnit[ 3 ] !== unit ) {
4498
4499		// Support: Firefox <=54
4500		// Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144)
4501		initial = initial / 2;
4502
4503		// Trust units reported by jQuery.css
4504		unit = unit || initialInUnit[ 3 ];
4505
4506		// Iteratively approximate from a nonzero starting point
4507		initialInUnit = +initial || 1;
4508
4509		while ( maxIterations-- ) {
4510
4511			// Evaluate and update our best guess (doubling guesses that zero out).
4512			// Finish if the scale equals or crosses 1 (making the old*new product non-positive).
4513			jQuery.style( elem, prop, initialInUnit + unit );
4514			if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) {
4515				maxIterations = 0;
4516			}
4517			initialInUnit = initialInUnit / scale;
4518
4519		}
4520
4521		initialInUnit = initialInUnit * 2;
4522		jQuery.style( elem, prop, initialInUnit + unit );
4523
4524		// Make sure we update the tween properties later on
4525		valueParts = valueParts || [];
4526	}
4527
4528	if ( valueParts ) {
4529		initialInUnit = +initialInUnit || +initial || 0;
4530
4531		// Apply relative offset (+=/-=) if specified
4532		adjusted = valueParts[ 1 ] ?
4533			initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] :
4534			+valueParts[ 2 ];
4535		if ( tween ) {
4536			tween.unit = unit;
4537			tween.start = initialInUnit;
4538			tween.end = adjusted;
4539		}
4540	}
4541	return adjusted;
4542}
4543
4544
4545var defaultDisplayMap = {};
4546
4547function getDefaultDisplay( elem ) {
4548	var temp,
4549		doc = elem.ownerDocument,
4550		nodeName = elem.nodeName,
4551		display = defaultDisplayMap[ nodeName ];
4552
4553	if ( display ) {
4554		return display;
4555	}
4556
4557	temp = doc.body.appendChild( doc.createElement( nodeName ) );
4558	display = jQuery.css( temp, "display" );
4559
4560	temp.parentNode.removeChild( temp );
4561
4562	if ( display === "none" ) {
4563		display = "block";
4564	}
4565	defaultDisplayMap[ nodeName ] = display;
4566
4567	return display;
4568}
4569
4570function showHide( elements, show ) {
4571	var display, elem,
4572		values = [],
4573		index = 0,
4574		length = elements.length;
4575
4576	// Determine new display value for elements that need to change
4577	for ( ; index < length; index++ ) {
4578		elem = elements[ index ];
4579		if ( !elem.style ) {
4580			continue;
4581		}
4582
4583		display = elem.style.display;
4584		if ( show ) {
4585
4586			// Since we force visibility upon cascade-hidden elements, an immediate (and slow)
4587			// check is required in this first loop unless we have a nonempty display value (either
4588			// inline or about-to-be-restored)
4589			if ( display === "none" ) {
4590				values[ index ] = dataPriv.get( elem, "display" ) || null;
4591				if ( !values[ index ] ) {
4592					elem.style.display = "";
4593				}
4594			}
4595			if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) {
4596				values[ index ] = getDefaultDisplay( elem );
4597			}
4598		} else {
4599			if ( display !== "none" ) {
4600				values[ index ] = "none";
4601
4602				// Remember what we're overwriting
4603				dataPriv.set( elem, "display", display );
4604			}
4605		}
4606	}
4607
4608	// Set the display of the elements in a second loop to avoid constant reflow
4609	for ( index = 0; index < length; index++ ) {
4610		if ( values[ index ] != null ) {
4611			elements[ index ].style.display = values[ index ];
4612		}
4613	}
4614
4615	return elements;
4616}
4617
4618jQuery.fn.extend( {
4619	show: function() {
4620		return showHide( this, true );
4621	},
4622	hide: function() {
4623		return showHide( this );
4624	},
4625	toggle: function( state ) {
4626		if ( typeof state === "boolean" ) {
4627			return state ? this.show() : this.hide();
4628		}
4629
4630		return this.each( function() {
4631			if ( isHiddenWithinTree( this ) ) {
4632				jQuery( this ).show();
4633			} else {
4634				jQuery( this ).hide();
4635			}
4636		} );
4637	}
4638} );
4639var rcheckableType = ( /^(?:checkbox|radio)$/i );
4640
4641var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]*)/i );
4642
4643var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i );
4644
4645
4646
4647( function() {
4648	var fragment = document.createDocumentFragment(),
4649		div = fragment.appendChild( document.createElement( "div" ) ),
4650		input = document.createElement( "input" );
4651
4652	// Support: Android 4.0 - 4.3 only
4653	// Check state lost if the name is set (trac-11217)
4654	// Support: Windows Web Apps (WWA)
4655	// `name` and `type` must use .setAttribute for WWA (trac-14901)
4656	input.setAttribute( "type", "radio" );
4657	input.setAttribute( "checked", "checked" );
4658	input.setAttribute( "name", "t" );
4659
4660	div.appendChild( input );
4661
4662	// Support: Android <=4.1 only
4663	// Older WebKit doesn't clone checked state correctly in fragments
4664	support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
4665
4666	// Support: IE <=11 only
4667	// Make sure textarea (and checkbox) defaultValue is properly cloned
4668	div.innerHTML = "<textarea>x</textarea>";
4669	support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
4670
4671	// Support: IE <=9 only
4672	// IE <=9 replaces <option> tags with their contents when inserted outside of
4673	// the select element.
4674	div.innerHTML = "<option></option>";
4675	support.option = !!div.lastChild;
4676} )();
4677
4678
4679// We have to close these tags to support XHTML (trac-13200)
4680var wrapMap = {
4681
4682	// XHTML parsers do not magically insert elements in the
4683	// same way that tag soup parsers do. So we cannot shorten
4684	// this by omitting <tbody> or other required elements.
4685	thead: [ 1, "<table>", "</table>" ],
4686	col: [ 2, "<table><colgroup>", "</colgroup></table>" ],
4687	tr: [ 2, "<table><tbody>", "</tbody></table>" ],
4688	td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
4689
4690	_default: [ 0, "", "" ]
4691};
4692
4693wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
4694wrapMap.th = wrapMap.td;
4695
4696// Support: IE <=9 only
4697if ( !support.option ) {
4698	wrapMap.optgroup = wrapMap.option = [ 1, "<select multiple='multiple'>", "</select>" ];
4699}
4700
4701
4702function getAll( context, tag ) {
4703
4704	// Support: IE <=9 - 11 only
4705	// Use typeof to avoid zero-argument method invocation on host objects (trac-15151)
4706	var ret;
4707
4708	if ( typeof context.getElementsByTagName !== "undefined" ) {
4709		ret = context.getElementsByTagName( tag || "*" );
4710
4711	} else if ( typeof context.querySelectorAll !== "undefined" ) {
4712		ret = context.querySelectorAll( tag || "*" );
4713
4714	} else {
4715		ret = [];
4716	}
4717
4718	if ( tag === undefined || tag && nodeName( context, tag ) ) {
4719		return jQuery.merge( [ context ], ret );
4720	}
4721
4722	return ret;
4723}
4724
4725
4726// Mark scripts as having already been evaluated
4727function setGlobalEval( elems, refElements ) {
4728	var i = 0,
4729		l = elems.length;
4730
4731	for ( ; i < l; i++ ) {
4732		dataPriv.set(
4733			elems[ i ],
4734			"globalEval",
4735			!refElements || dataPriv.get( refElements[ i ], "globalEval" )
4736		);
4737	}
4738}
4739
4740
4741var rhtml = /<|&#?\w+;/;
4742
4743function buildFragment( elems, context, scripts, selection, ignored ) {
4744	var elem, tmp, tag, wrap, attached, j,
4745		fragment = context.createDocumentFragment(),
4746		nodes = [],
4747		i = 0,
4748		l = elems.length;
4749
4750	for ( ; i < l; i++ ) {
4751		elem = elems[ i ];
4752
4753		if ( elem || elem === 0 ) {
4754
4755			// Add nodes directly
4756			if ( toType( elem ) === "object" ) {
4757
4758				// Support: Android <=4.0 only, PhantomJS 1 only
4759				// push.apply(_, arraylike) throws on ancient WebKit
4760				jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
4761
4762			// Convert non-html into a text node
4763			} else if ( !rhtml.test( elem ) ) {
4764				nodes.push( context.createTextNode( elem ) );
4765
4766			// Convert html into DOM nodes
4767			} else {
4768				tmp = tmp || fragment.appendChild( context.createElement( "div" ) );
4769
4770				// Deserialize a standard representation
4771				tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase();
4772				wrap = wrapMap[ tag ] || wrapMap._default;
4773				tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ];
4774
4775				// Descend through wrappers to the right content
4776				j = wrap[ 0 ];
4777				while ( j-- ) {
4778					tmp = tmp.lastChild;
4779				}
4780
4781				// Support: Android <=4.0 only, PhantomJS 1 only
4782				// push.apply(_, arraylike) throws on ancient WebKit
4783				jQuery.merge( nodes, tmp.childNodes );
4784
4785				// Remember the top-level container
4786				tmp = fragment.firstChild;
4787
4788				// Ensure the created nodes are orphaned (trac-12392)
4789				tmp.textContent = "";
4790			}
4791		}
4792	}
4793
4794	// Remove wrapper from fragment
4795	fragment.textContent = "";
4796
4797	i = 0;
4798	while ( ( elem = nodes[ i++ ] ) ) {
4799
4800		// Skip elements already in the context collection (trac-4087)
4801		if ( selection && jQuery.inArray( elem, selection ) > -1 ) {
4802			if ( ignored ) {
4803				ignored.push( elem );
4804			}
4805			continue;
4806		}
4807
4808		attached = isAttached( elem );
4809
4810		// Append to fragment
4811		tmp = getAll( fragment.appendChild( elem ), "script" );
4812
4813		// Preserve script evaluation history
4814		if ( attached ) {
4815			setGlobalEval( tmp );
4816		}
4817
4818		// Capture executables
4819		if ( scripts ) {
4820			j = 0;
4821			while ( ( elem = tmp[ j++ ] ) ) {
4822				if ( rscriptType.test( elem.type || "" ) ) {
4823					scripts.push( elem );
4824				}
4825			}
4826		}
4827	}
4828
4829	return fragment;
4830}
4831
4832
4833var rtypenamespace = /^([^.]*)(?:\.(.+)|)/;
4834
4835function returnTrue() {
4836	return true;
4837}
4838
4839function returnFalse() {
4840	return false;
4841}
4842
4843function on( elem, types, selector, data, fn, one ) {
4844	var origFn, type;
4845
4846	// Types can be a map of types/handlers
4847	if ( typeof types === "object" ) {
4848
4849		// ( types-Object, selector, data )
4850		if ( typeof selector !== "string" ) {
4851
4852			// ( types-Object, data )
4853			data = data || selector;
4854			selector = undefined;
4855		}
4856		for ( type in types ) {
4857			on( elem, type, selector, data, types[ type ], one );
4858		}
4859		return elem;
4860	}
4861
4862	if ( data == null && fn == null ) {
4863
4864		// ( types, fn )
4865		fn = selector;
4866		data = selector = undefined;
4867	} else if ( fn == null ) {
4868		if ( typeof selector === "string" ) {
4869
4870			// ( types, selector, fn )
4871			fn = data;
4872			data = undefined;
4873		} else {
4874
4875			// ( types, data, fn )
4876			fn = data;
4877			data = selector;
4878			selector = undefined;
4879		}
4880	}
4881	if ( fn === false ) {
4882		fn = returnFalse;
4883	} else if ( !fn ) {
4884		return elem;
4885	}
4886
4887	if ( one === 1 ) {
4888		origFn = fn;
4889		fn = function( event ) {
4890
4891			// Can use an empty set, since event contains the info
4892			jQuery().off( event );
4893			return origFn.apply( this, arguments );
4894		};
4895
4896		// Use same guid so caller can remove using origFn
4897		fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
4898	}
4899	return elem.each( function() {
4900		jQuery.event.add( this, types, fn, data, selector );
4901	} );
4902}
4903
4904/*
4905 * Helper functions for managing events -- not part of the public interface.
4906 * Props to Dean Edwards' addEvent library for many of the ideas.
4907 */
4908jQuery.event = {
4909
4910	global: {},
4911
4912	add: function( elem, types, handler, data, selector ) {
4913
4914		var handleObjIn, eventHandle, tmp,
4915			events, t, handleObj,
4916			special, handlers, type, namespaces, origType,
4917			elemData = dataPriv.get( elem );
4918
4919		// Only attach events to objects that accept data
4920		if ( !acceptData( elem ) ) {
4921			return;
4922		}
4923
4924		// Caller can pass in an object of custom data in lieu of the handler
4925		if ( handler.handler ) {
4926			handleObjIn = handler;
4927			handler = handleObjIn.handler;
4928			selector = handleObjIn.selector;
4929		}
4930
4931		// Ensure that invalid selectors throw exceptions at attach time
4932		// Evaluate against documentElement in case elem is a non-element node (e.g., document)
4933		if ( selector ) {
4934			jQuery.find.matchesSelector( documentElement, selector );
4935		}
4936
4937		// Make sure that the handler has a unique ID, used to find/remove it later
4938		if ( !handler.guid ) {
4939			handler.guid = jQuery.guid++;
4940		}
4941
4942		// Init the element's event structure and main handler, if this is the first
4943		if ( !( events = elemData.events ) ) {
4944			events = elemData.events = Object.create( null );
4945		}
4946		if ( !( eventHandle = elemData.handle ) ) {
4947			eventHandle = elemData.handle = function( e ) {
4948
4949				// Discard the second event of a jQuery.event.trigger() and
4950				// when an event is called after a page has unloaded
4951				return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ?
4952					jQuery.event.dispatch.apply( elem, arguments ) : undefined;
4953			};
4954		}
4955
4956		// Handle multiple events separated by a space
4957		types = ( types || "" ).match( rnothtmlwhite ) || [ "" ];
4958		t = types.length;
4959		while ( t-- ) {
4960			tmp = rtypenamespace.exec( types[ t ] ) || [];
4961			type = origType = tmp[ 1 ];
4962			namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
4963
4964			// There *must* be a type, no attaching namespace-only handlers
4965			if ( !type ) {
4966				continue;
4967			}
4968
4969			// If event changes its type, use the special event handlers for the changed type
4970			special = jQuery.event.special[ type ] || {};
4971
4972			// If selector defined, determine special event api type, otherwise given type
4973			type = ( selector ? special.delegateType : special.bindType ) || type;
4974
4975			// Update special based on newly reset type
4976			special = jQuery.event.special[ type ] || {};
4977
4978			// handleObj is passed to all event handlers
4979			handleObj = jQuery.extend( {
4980				type: type,
4981				origType: origType,
4982				data: data,
4983				handler: handler,
4984				guid: handler.guid,
4985				selector: selector,
4986				needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
4987				namespace: namespaces.join( "." )
4988			}, handleObjIn );
4989
4990			// Init the event handler queue if we're the first
4991			if ( !( handlers = events[ type ] ) ) {
4992				handlers = events[ type ] = [];
4993				handlers.delegateCount = 0;
4994
4995				// Only use addEventListener if the special events handler returns false
4996				if ( !special.setup ||
4997					special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
4998
4999					if ( elem.addEventListener ) {
5000						elem.addEventListener( type, eventHandle );
5001					}
5002				}
5003			}
5004
5005			if ( special.add ) {
5006				special.add.call( elem, handleObj );
5007
5008				if ( !handleObj.handler.guid ) {
5009					handleObj.handler.guid = handler.guid;
5010				}
5011			}
5012
5013			// Add to the element's handler list, delegates in front
5014			if ( selector ) {
5015				handlers.splice( handlers.delegateCount++, 0, handleObj );
5016			} else {
5017				handlers.push( handleObj );
5018			}
5019
5020			// Keep track of which events have ever been used, for event optimization
5021			jQuery.event.global[ type ] = true;
5022		}
5023
5024	},
5025
5026	// Detach an event or set of events from an element
5027	remove: function( elem, types, handler, selector, mappedTypes ) {
5028
5029		var j, origCount, tmp,
5030			events, t, handleObj,
5031			special, handlers, type, namespaces, origType,
5032			elemData = dataPriv.hasData( elem ) && dataPriv.get( elem );
5033
5034		if ( !elemData || !( events = elemData.events ) ) {
5035			return;
5036		}
5037
vendor: 4,336 bytes, lines 5038-5176
5038		// Once for each type.namespace in types; type may be omitted
5039		types = ( types || "" ).match( rnothtmlwhite ) || [ "" ];
5040		t = types.length;
5041		while ( t-- ) {
5042			tmp = rtypenamespace.exec( types[ t ] ) || [];
5043			type = origType = tmp[ 1 ];
5044			namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
5045
5046			// Unbind all events (on this namespace, if provided) for the element
5047			if ( !type ) {
5048				for ( type in events ) {
5049					jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
5050				}
5051				continue;
5052			}
5053
5054			special = jQuery.event.special[ type ] || {};
5055			type = ( selector ? special.delegateType : special.bindType ) || type;
5056			handlers = events[ type ] || [];
5057			tmp = tmp[ 2 ] &&
5058				new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" );
5059
5060			// Remove matching events
5061			origCount = j = handlers.length;
5062			while ( j-- ) {
5063				handleObj = handlers[ j ];
5064
5065				if ( ( mappedTypes || origType === handleObj.origType ) &&
5066					( !handler || handler.guid === handleObj.guid ) &&
5067					( !tmp || tmp.test( handleObj.namespace ) ) &&
5068					( !selector || selector === handleObj.selector ||
5069						selector === "**" && handleObj.selector ) ) {
5070					handlers.splice( j, 1 );
5071
5072					if ( handleObj.selector ) {
5073						handlers.delegateCount--;
5074					}
5075					if ( special.remove ) {
5076						special.remove.call( elem, handleObj );
5077					}
5078				}
5079			}
5080
5081			// Remove generic event handler if we removed something and no more handlers exist
5082			// (avoids potential for endless recursion during removal of special event handlers)
5083			if ( origCount && !handlers.length ) {
5084				if ( !special.teardown ||
5085					special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
5086
5087					jQuery.removeEvent( elem, type, elemData.handle );
5088				}
5089
5090				delete events[ type ];
5091			}
5092		}
5093
5094		// Remove data and the expando if it's no longer used
5095		if ( jQuery.isEmptyObject( events ) ) {
5096			dataPriv.remove( elem, "handle events" );
5097		}
5098	},
5099
5100	dispatch: function( nativeEvent ) {
5101
5102		var i, j, ret, matched, handleObj, handlerQueue,
5103			args = new Array( arguments.length ),
5104
5105			// Make a writable jQuery.Event from the native event object
5106			event = jQuery.event.fix( nativeEvent ),
5107
5108			handlers = (
5109				dataPriv.get( this, "events" ) || Object.create( null )
5110			)[ event.type ] || [],
5111			special = jQuery.event.special[ event.type ] || {};
5112
5113		// Use the fix-ed jQuery.Event rather than the (read-only) native event
5114		args[ 0 ] = event;
5115
5116		for ( i = 1; i < arguments.length; i++ ) {
5117			args[ i ] = arguments[ i ];
5118		}
5119
5120		event.delegateTarget = this;
5121
5122		// Call the preDispatch hook for the mapped type, and let it bail if desired
5123		if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
5124			return;
5125		}
5126
5127		// Determine handlers
5128		handlerQueue = jQuery.event.handlers.call( this, event, handlers );
5129
5130		// Run delegates first; they may want to stop propagation beneath us
5131		i = 0;
5132		while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) {
5133			event.currentTarget = matched.elem;
5134
5135			j = 0;
5136			while ( ( handleObj = matched.handlers[ j++ ] ) &&
5137				!event.isImmediatePropagationStopped() ) {
5138
5139				// If the event is namespaced, then each handler is only invoked if it is
5140				// specially universal or its namespaces are a superset of the event's.
5141				if ( !event.rnamespace || handleObj.namespace === false ||
5142					event.rnamespace.test( handleObj.namespace ) ) {
5143
5144					event.handleObj = handleObj;
5145					event.data = handleObj.data;
5146
5147					ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle ||
5148						handleObj.handler ).apply( matched.elem, args );
5149
5150					if ( ret !== undefined ) {
5151						if ( ( event.result = ret ) === false ) {
5152							event.preventDefault();
5153							event.stopPropagation();
5154						}
5155					}
5156				}
5157			}
5158		}
5159
5160		// Call the postDispatch hook for the mapped type
5161		if ( special.postDispatch ) {
5162			special.postDispatch.call( this, event );
5163		}
5164
5165		return event.result;
5166	},
5167
5168	handlers: function( event, handlers ) {
5169		var i, handleObj, sel, matchedHandlers, matchedSelectors,
5170			handlerQueue = [],
5171			delegateCount = handlers.delegateCount,
5172			cur = event.target;
5173
5174		// Find delegate handlers
5175		if ( delegateCount &&
5176
vendor: 26,293 bytes, lines 5177-6053
5177			// Support: IE <=9
5178			// Black-hole SVG <use> instance trees (trac-13180)
5179			cur.nodeType &&
5180
5181			// Support: Firefox <=42
5182			// Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861)
5183			// https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click
5184			// Support: IE 11 only
5185			// ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343)
5186			!( event.type === "click" && event.button >= 1 ) ) {
5187
5188			for ( ; cur !== this; cur = cur.parentNode || this ) {
5189
5190				// Don't check non-elements (trac-13208)
5191				// Don't process clicks on disabled elements (trac-6911, trac-8165, trac-11382, trac-11764)
5192				if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) {
5193					matchedHandlers = [];
5194					matchedSelectors = {};
5195					for ( i = 0; i < delegateCount; i++ ) {
5196						handleObj = handlers[ i ];
5197
5198						// Don't conflict with Object.prototype properties (trac-13203)
5199						sel = handleObj.selector + " ";
5200
5201						if ( matchedSelectors[ sel ] === undefined ) {
5202							matchedSelectors[ sel ] = handleObj.needsContext ?
5203								jQuery( sel, this ).index( cur ) > -1 :
5204								jQuery.find( sel, this, null, [ cur ] ).length;
5205						}
5206						if ( matchedSelectors[ sel ] ) {
5207							matchedHandlers.push( handleObj );
5208						}
5209					}
5210					if ( matchedHandlers.length ) {
5211						handlerQueue.push( { elem: cur, handlers: matchedHandlers } );
5212					}
5213				}
5214			}
5215		}
5216
5217		// Add the remaining (directly-bound) handlers
5218		cur = this;
5219		if ( delegateCount < handlers.length ) {
5220			handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } );
5221		}
5222
5223		return handlerQueue;
5224	},
5225
5226	addProp: function( name, hook ) {
5227		Object.defineProperty( jQuery.Event.prototype, name, {
5228			enumerable: true,
5229			configurable: true,
5230
5231			get: isFunction( hook ) ?
5232				function() {
5233					if ( this.originalEvent ) {
5234						return hook( this.originalEvent );
5235					}
5236				} :
5237				function() {
5238					if ( this.originalEvent ) {
5239						return this.originalEvent[ name ];
5240					}
5241				},
5242
5243			set: function( value ) {
5244				Object.defineProperty( this, name, {
5245					enumerable: true,
5246					configurable: true,
5247					writable: true,
5248					value: value
5249				} );
5250			}
5251		} );
5252	},
5253
5254	fix: function( originalEvent ) {
5255		return originalEvent[ jQuery.expando ] ?
5256			originalEvent :
5257			new jQuery.Event( originalEvent );
5258	},
5259
5260	special: {
5261		load: {
5262
5263			// Prevent triggered image.load events from bubbling to window.load
5264			noBubble: true
5265		},
5266		click: {
5267
5268			// Utilize native event to ensure correct state for checkable inputs
5269			setup: function( data ) {
5270
5271				// For mutual compressibility with _default, replace `this` access with a local var.
5272				// `|| data` is dead code meant only to preserve the variable through minification.
5273				var el = this || data;
5274
5275				// Claim the first handler
5276				if ( rcheckableType.test( el.type ) &&
5277					el.click && nodeName( el, "input" ) ) {
5278
5279					// dataPriv.set( el, "click", ... )
5280					leverageNative( el, "click", true );
5281				}
5282
5283				// Return false to allow normal processing in the caller
5284				return false;
5285			},
5286			trigger: function( data ) {
5287
5288				// For mutual compressibility with _default, replace `this` access with a local var.
5289				// `|| data` is dead code meant only to preserve the variable through minification.
5290				var el = this || data;
5291
5292				// Force setup before triggering a click
5293				if ( rcheckableType.test( el.type ) &&
5294					el.click && nodeName( el, "input" ) ) {
5295
5296					leverageNative( el, "click" );
5297				}
5298
5299				// Return non-false to allow normal event-path propagation
5300				return true;
5301			},
5302
5303			// For cross-browser consistency, suppress native .click() on links
5304			// Also prevent it if we're currently inside a leveraged native-event stack
5305			_default: function( event ) {
5306				var target = event.target;
5307				return rcheckableType.test( target.type ) &&
5308					target.click && nodeName( target, "input" ) &&
5309					dataPriv.get( target, "click" ) ||
5310					nodeName( target, "a" );
5311			}
5312		},
5313
5314		beforeunload: {
5315			postDispatch: function( event ) {
5316
5317				// Support: Firefox 20+
5318				// Firefox doesn't alert if the returnValue field is not set.
5319				if ( event.result !== undefined && event.originalEvent ) {
5320					event.originalEvent.returnValue = event.result;
5321				}
5322			}
5323		}
5324	}
5325};
5326
5327// Ensure the presence of an event listener that handles manually-triggered
5328// synthetic events by interrupting progress until reinvoked in response to
5329// *native* events that it fires directly, ensuring that state changes have
5330// already occurred before other listeners are invoked.
5331function leverageNative( el, type, isSetup ) {
5332
5333	// Missing `isSetup` indicates a trigger call, which must force setup through jQuery.event.add
5334	if ( !isSetup ) {
5335		if ( dataPriv.get( el, type ) === undefined ) {
5336			jQuery.event.add( el, type, returnTrue );
5337		}
5338		return;
5339	}
5340
5341	// Register the controller as a special universal handler for all event namespaces
5342	dataPriv.set( el, type, false );
5343	jQuery.event.add( el, type, {
5344		namespace: false,
5345		handler: function( event ) {
5346			var result,
5347				saved = dataPriv.get( this, type );
5348
5349			if ( ( event.isTrigger & 1 ) && this[ type ] ) {
5350
5351				// Interrupt processing of the outer synthetic .trigger()ed event
5352				if ( !saved ) {
5353
5354					// Store arguments for use when handling the inner native event
5355					// There will always be at least one argument (an event object), so this array
5356					// will not be confused with a leftover capture object.
5357					saved = slice.call( arguments );
5358					dataPriv.set( this, type, saved );
5359
5360					// Trigger the native event and capture its result
5361					this[ type ]();
5362					result = dataPriv.get( this, type );
5363					dataPriv.set( this, type, false );
5364
5365					if ( saved !== result ) {
5366
5367						// Cancel the outer synthetic event
5368						event.stopImmediatePropagation();
5369						event.preventDefault();
5370
5371						return result;
5372					}
5373
5374				// If this is an inner synthetic event for an event with a bubbling surrogate
5375				// (focus or blur), assume that the surrogate already propagated from triggering
5376				// the native event and prevent that from happening again here.
5377				// This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the
5378				// bubbling surrogate propagates *after* the non-bubbling base), but that seems
5379				// less bad than duplication.
5380				} else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) {
5381					event.stopPropagation();
5382				}
5383
5384			// If this is a native event triggered above, everything is now in order
5385			// Fire an inner synthetic event with the original arguments
5386			} else if ( saved ) {
5387
5388				// ...and capture the result
5389				dataPriv.set( this, type, jQuery.event.trigger(
5390					saved[ 0 ],
5391					saved.slice( 1 ),
5392					this
5393				) );
5394
5395				// Abort handling of the native event by all jQuery handlers while allowing
5396				// native handlers on the same element to run. On target, this is achieved
5397				// by stopping immediate propagation just on the jQuery event. However,
5398				// the native event is re-wrapped by a jQuery one on each level of the
5399				// propagation so the only way to stop it for jQuery is to stop it for
5400				// everyone via native `stopPropagation()`. This is not a problem for
5401				// focus/blur which don't bubble, but it does also stop click on checkboxes
5402				// and radios. We accept this limitation.
5403				event.stopPropagation();
5404				event.isImmediatePropagationStopped = returnTrue;
5405			}
5406		}
5407	} );
5408}
5409
5410jQuery.removeEvent = function( elem, type, handle ) {
5411
5412	// This "if" is needed for plain objects
5413	if ( elem.removeEventListener ) {
5414		elem.removeEventListener( type, handle );
5415	}
5416};
5417
5418jQuery.Event = function( src, props ) {
5419
5420	// Allow instantiation without the 'new' keyword
5421	if ( !( this instanceof jQuery.Event ) ) {
5422		return new jQuery.Event( src, props );
5423	}
5424
5425	// Event object
5426	if ( src && src.type ) {
5427		this.originalEvent = src;
5428		this.type = src.type;
5429
5430		// Events bubbling up the document may have been marked as prevented
5431		// by a handler lower down the tree; reflect the correct value.
5432		this.isDefaultPrevented = src.defaultPrevented ||
5433				src.defaultPrevented === undefined &&
5434
5435				// Support: Android <=2.3 only
5436				src.returnValue === false ?
5437			returnTrue :
5438			returnFalse;
5439
5440		// Create target properties
5441		// Support: Safari <=6 - 7 only
5442		// Target should not be a text node (trac-504, trac-13143)
5443		this.target = ( src.target && src.target.nodeType === 3 ) ?
5444			src.target.parentNode :
5445			src.target;
5446
5447		this.currentTarget = src.currentTarget;
5448		this.relatedTarget = src.relatedTarget;
5449
5450	// Event type
5451	} else {
5452		this.type = src;
5453	}
5454
5455	// Put explicitly provided properties onto the event object
5456	if ( props ) {
5457		jQuery.extend( this, props );
5458	}
5459
5460	// Create a timestamp if incoming event doesn't have one
5461	this.timeStamp = src && src.timeStamp || Date.now();
5462
5463	// Mark it as fixed
5464	this[ jQuery.expando ] = true;
5465};
5466
5467// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
5468// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
5469jQuery.Event.prototype = {
5470	constructor: jQuery.Event,
5471	isDefaultPrevented: returnFalse,
5472	isPropagationStopped: returnFalse,
5473	isImmediatePropagationStopped: returnFalse,
5474	isSimulated: false,
5475
5476	preventDefault: function() {
5477		var e = this.originalEvent;
5478
5479		this.isDefaultPrevented = returnTrue;
5480
5481		if ( e && !this.isSimulated ) {
5482			e.preventDefault();
5483		}
5484	},
5485	stopPropagation: function() {
5486		var e = this.originalEvent;
5487
5488		this.isPropagationStopped = returnTrue;
5489
5490		if ( e && !this.isSimulated ) {
5491			e.stopPropagation();
5492		}
5493	},
5494	stopImmediatePropagation: function() {
5495		var e = this.originalEvent;
5496
5497		this.isImmediatePropagationStopped = returnTrue;
5498
5499		if ( e && !this.isSimulated ) {
5500			e.stopImmediatePropagation();
5501		}
5502
5503		this.stopPropagation();
5504	}
5505};
5506
5507// Includes all common event props including KeyEvent and MouseEvent specific props
5508jQuery.each( {
5509	altKey: true,
5510	bubbles: true,
5511	cancelable: true,
5512	changedTouches: true,
5513	ctrlKey: true,
5514	detail: true,
5515	eventPhase: true,
5516	metaKey: true,
5517	pageX: true,
5518	pageY: true,
5519	shiftKey: true,
5520	view: true,
5521	"char": true,
5522	code: true,
5523	charCode: true,
5524	key: true,
5525	keyCode: true,
5526	button: true,
5527	buttons: true,
5528	clientX: true,
5529	clientY: true,
5530	offsetX: true,
5531	offsetY: true,
5532	pointerId: true,
5533	pointerType: true,
5534	screenX: true,
5535	screenY: true,
5536	targetTouches: true,
5537	toElement: true,
5538	touches: true,
5539	which: true
5540}, jQuery.event.addProp );
5541
5542jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) {
5543
5544	function focusMappedHandler( nativeEvent ) {
5545		if ( document.documentMode ) {
5546
5547			// Support: IE 11+
5548			// Attach a single focusin/focusout handler on the document while someone wants
5549			// focus/blur. This is because the former are synchronous in IE while the latter
5550			// are async. In other browsers, all those handlers are invoked synchronously.
5551
5552			// `handle` from private data would already wrap the event, but we need
5553			// to change the `type` here.
5554			var handle = dataPriv.get( this, "handle" ),
5555				event = jQuery.event.fix( nativeEvent );
5556			event.type = nativeEvent.type === "focusin" ? "focus" : "blur";
5557			event.isSimulated = true;
5558
5559			// First, handle focusin/focusout
5560			handle( nativeEvent );
5561
5562			// ...then, handle focus/blur
5563			//
5564			// focus/blur don't bubble while focusin/focusout do; simulate the former by only
5565			// invoking the handler at the lower level.
5566			if ( event.target === event.currentTarget ) {
5567
5568				// The setup part calls `leverageNative`, which, in turn, calls
5569				// `jQuery.event.add`, so event handle will already have been set
5570				// by this point.
5571				handle( event );
5572			}
5573		} else {
5574
5575			// For non-IE browsers, attach a single capturing handler on the document
5576			// while someone wants focusin/focusout.
5577			jQuery.event.simulate( delegateType, nativeEvent.target,
5578				jQuery.event.fix( nativeEvent ) );
5579		}
5580	}
5581
5582	jQuery.event.special[ type ] = {
5583
5584		// Utilize native event if possible so blur/focus sequence is correct
5585		setup: function() {
5586
5587			var attaches;
5588
5589			// Claim the first handler
5590			// dataPriv.set( this, "focus", ... )
5591			// dataPriv.set( this, "blur", ... )
5592			leverageNative( this, type, true );
5593
5594			if ( document.documentMode ) {
5595
5596				// Support: IE 9 - 11+
5597				// We use the same native handler for focusin & focus (and focusout & blur)
5598				// so we need to coordinate setup & teardown parts between those events.
5599				// Use `delegateType` as the key as `type` is already used by `leverageNative`.
5600				attaches = dataPriv.get( this, delegateType );
5601				if ( !attaches ) {
5602					this.addEventListener( delegateType, focusMappedHandler );
5603				}
5604				dataPriv.set( this, delegateType, ( attaches || 0 ) + 1 );
5605			} else {
5606
5607				// Return false to allow normal processing in the caller
5608				return false;
5609			}
5610		},
5611		trigger: function() {
5612
5613			// Force setup before trigger
5614			leverageNative( this, type );
5615
5616			// Return non-false to allow normal event-path propagation
5617			return true;
5618		},
5619
5620		teardown: function() {
5621			var attaches;
5622
5623			if ( document.documentMode ) {
5624				attaches = dataPriv.get( this, delegateType ) - 1;
5625				if ( !attaches ) {
5626					this.removeEventListener( delegateType, focusMappedHandler );
5627					dataPriv.remove( this, delegateType );
5628				} else {
5629					dataPriv.set( this, delegateType, attaches );
5630				}
5631			} else {
5632
5633				// Return false to indicate standard teardown should be applied
5634				return false;
5635			}
5636		},
5637
5638		// Suppress native focus or blur if we're currently inside
5639		// a leveraged native-event stack
5640		_default: function( event ) {
5641			return dataPriv.get( event.target, type );
5642		},
5643
5644		delegateType: delegateType
5645	};
5646
5647	// Support: Firefox <=44
5648	// Firefox doesn't have focus(in | out) events
5649	// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787
5650	//
5651	// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1
5652	// focus(in | out) events fire after focus & blur events,
5653	// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order
5654	// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857
5655	//
5656	// Support: IE 9 - 11+
5657	// To preserve relative focusin/focus & focusout/blur event order guaranteed on the 3.x branch,
5658	// attach a single handler for both events in IE.
5659	jQuery.event.special[ delegateType ] = {
5660		setup: function() {
5661
5662			// Handle: regular nodes (via `this.ownerDocument`), window
5663			// (via `this.document`) & document (via `this`).
5664			var doc = this.ownerDocument || this.document || this,
5665				dataHolder = document.documentMode ? this : doc,
5666				attaches = dataPriv.get( dataHolder, delegateType );
5667
5668			// Support: IE 9 - 11+
5669			// We use the same native handler for focusin & focus (and focusout & blur)
5670			// so we need to coordinate setup & teardown parts between those events.
5671			// Use `delegateType` as the key as `type` is already used by `leverageNative`.
5672			if ( !attaches ) {
5673				if ( document.documentMode ) {
5674					this.addEventListener( delegateType, focusMappedHandler );
5675				} else {
5676					doc.addEventListener( type, focusMappedHandler, true );
5677				}
5678			}
5679			dataPriv.set( dataHolder, delegateType, ( attaches || 0 ) + 1 );
5680		},
5681		teardown: function() {
5682			var doc = this.ownerDocument || this.document || this,
5683				dataHolder = document.documentMode ? this : doc,
5684				attaches = dataPriv.get( dataHolder, delegateType ) - 1;
5685
5686			if ( !attaches ) {
5687				if ( document.documentMode ) {
5688					this.removeEventListener( delegateType, focusMappedHandler );
5689				} else {
5690					doc.removeEventListener( type, focusMappedHandler, true );
5691				}
5692				dataPriv.remove( dataHolder, delegateType );
5693			} else {
5694				dataPriv.set( dataHolder, delegateType, attaches );
5695			}
5696		}
5697	};
5698} );
5699
5700// Create mouseenter/leave events using mouseover/out and event-time checks
5701// so that event delegation works in jQuery.
5702// Do the same for pointerenter/pointerleave and pointerover/pointerout
5703//
5704// Support: Safari 7 only
5705// Safari sends mouseenter too often; see:
5706// https://bugs.chromium.org/p/chromium/issues/detail?id=470258
5707// for the description of the bug (it existed in older Chrome versions as well).
5708jQuery.each( {
5709	mouseenter: "mouseover",
5710	mouseleave: "mouseout",
5711	pointerenter: "pointerover",
5712	pointerleave: "pointerout"
5713}, function( orig, fix ) {
5714	jQuery.event.special[ orig ] = {
5715		delegateType: fix,
5716		bindType: fix,
5717
5718		handle: function( event ) {
5719			var ret,
5720				target = this,
5721				related = event.relatedTarget,
5722				handleObj = event.handleObj;
5723
5724			// For mouseenter/leave call the handler if related is outside the target.
5725			// NB: No relatedTarget if the mouse left/entered the browser window
5726			if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) {
5727				event.type = handleObj.origType;
5728				ret = handleObj.handler.apply( this, arguments );
5729				event.type = fix;
5730			}
5731			return ret;
5732		}
5733	};
5734} );
5735
5736jQuery.fn.extend( {
5737
5738	on: function( types, selector, data, fn ) {
5739		return on( this, types, selector, data, fn );
5740	},
5741	one: function( types, selector, data, fn ) {
5742		return on( this, types, selector, data, fn, 1 );
5743	},
5744	off: function( types, selector, fn ) {
5745		var handleObj, type;
5746		if ( types && types.preventDefault && types.handleObj ) {
5747
5748			// ( event )  dispatched jQuery.Event
5749			handleObj = types.handleObj;
5750			jQuery( types.delegateTarget ).off(
5751				handleObj.namespace ?
5752					handleObj.origType + "." + handleObj.namespace :
5753					handleObj.origType,
5754				handleObj.selector,
5755				handleObj.handler
5756			);
5757			return this;
5758		}
5759		if ( typeof types === "object" ) {
5760
5761			// ( types-object [, selector] )
5762			for ( type in types ) {
5763				this.off( type, selector, types[ type ] );
5764			}
5765			return this;
5766		}
5767		if ( selector === false || typeof selector === "function" ) {
5768
5769			// ( types [, fn] )
5770			fn = selector;
5771			selector = undefined;
5772		}
5773		if ( fn === false ) {
5774			fn = returnFalse;
5775		}
5776		return this.each( function() {
5777			jQuery.event.remove( this, types, fn, selector );
5778		} );
5779	}
5780} );
5781
5782
5783var
5784
5785	// Support: IE <=10 - 11, Edge 12 - 13 only
5786	// In IE/Edge using regex groups here causes severe slowdowns.
5787	// See https://connect.microsoft.com/IE/feedback/details/1736512/
5788	rnoInnerhtml = /<script|<style|<link/i,
5789
5790	// checked="checked" or checked
5791	rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
5792
5793	rcleanScript = /^\s*<!\[CDATA\[|\]\]>\s*$/g;
5794
5795// Prefer a tbody over its parent table for containing new rows
5796function manipulationTarget( elem, content ) {
5797	if ( nodeName( elem, "table" ) &&
5798		nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) {
5799
5800		return jQuery( elem ).children( "tbody" )[ 0 ] || elem;
5801	}
5802
5803	return elem;
5804}
5805
5806// Replace/restore the type attribute of script elements for safe DOM manipulation
5807function disableScript( elem ) {
5808	elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type;
5809	return elem;
5810}
5811function restoreScript( elem ) {
5812	if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) {
5813		elem.type = elem.type.slice( 5 );
5814	} else {
5815		elem.removeAttribute( "type" );
5816	}
5817
5818	return elem;
5819}
5820
5821function cloneCopyEvent( src, dest ) {
5822	var i, l, type, pdataOld, udataOld, udataCur, events;
5823
5824	if ( dest.nodeType !== 1 ) {
5825		return;
5826	}
5827
5828	// 1. Copy private data: events, handlers, etc.
5829	if ( dataPriv.hasData( src ) ) {
5830		pdataOld = dataPriv.get( src );
5831		events = pdataOld.events;
5832
5833		if ( events ) {
5834			dataPriv.remove( dest, "handle events" );
5835
5836			for ( type in events ) {
5837				for ( i = 0, l = events[ type ].length; i < l; i++ ) {
5838					jQuery.event.add( dest, type, events[ type ][ i ] );
5839				}
5840			}
5841		}
5842	}
5843
5844	// 2. Copy user data
5845	if ( dataUser.hasData( src ) ) {
5846		udataOld = dataUser.access( src );
5847		udataCur = jQuery.extend( {}, udataOld );
5848
5849		dataUser.set( dest, udataCur );
5850	}
5851}
5852
5853// Fix IE bugs, see support tests
5854function fixInput( src, dest ) {
5855	var nodeName = dest.nodeName.toLowerCase();
5856
5857	// Fails to persist the checked state of a cloned checkbox or radio button.
5858	if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
5859		dest.checked = src.checked;
5860
5861	// Fails to return the selected option to the default selected state when cloning options
5862	} else if ( nodeName === "input" || nodeName === "textarea" ) {
5863		dest.defaultValue = src.defaultValue;
5864	}
5865}
5866
5867function domManip( collection, args, callback, ignored ) {
5868
5869	// Flatten any nested arrays
5870	args = flat( args );
5871
5872	var fragment, first, scripts, hasScripts, node, doc,
5873		i = 0,
5874		l = collection.length,
5875		iNoClone = l - 1,
5876		value = args[ 0 ],
5877		valueIsFunction = isFunction( value );
5878
5879	// We can't cloneNode fragments that contain checked, in WebKit
5880	if ( valueIsFunction ||
5881			( l > 1 && typeof value === "string" &&
5882				!support.checkClone && rchecked.test( value ) ) ) {
5883		return collection.each( function( index ) {
5884			var self = collection.eq( index );
5885			if ( valueIsFunction ) {
5886				args[ 0 ] = value.call( this, index, self.html() );
5887			}
5888			domManip( self, args, callback, ignored );
5889		} );
5890	}
5891
5892	if ( l ) {
5893		fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored );
5894		first = fragment.firstChild;
5895
5896		if ( fragment.childNodes.length === 1 ) {
5897			fragment = first;
5898		}
5899
5900		// Require either new content or an interest in ignored elements to invoke the callback
5901		if ( first || ignored ) {
5902			scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
5903			hasScripts = scripts.length;
5904
5905			// Use the original fragment for the last item
5906			// instead of the first because it can end up
5907			// being emptied incorrectly in certain situations (trac-8070).
5908			for ( ; i < l; i++ ) {
5909				node = fragment;
5910
5911				if ( i !== iNoClone ) {
5912					node = jQuery.clone( node, true, true );
5913
5914					// Keep references to cloned scripts for later restoration
5915					if ( hasScripts ) {
5916
5917						// Support: Android <=4.0 only, PhantomJS 1 only
5918						// push.apply(_, arraylike) throws on ancient WebKit
5919						jQuery.merge( scripts, getAll( node, "script" ) );
5920					}
5921				}
5922
5923				callback.call( collection[ i ], node, i );
5924			}
5925
5926			if ( hasScripts ) {
5927				doc = scripts[ scripts.length - 1 ].ownerDocument;
5928
5929				// Re-enable scripts
5930				jQuery.map( scripts, restoreScript );
5931
5932				// Evaluate executable scripts on first document insertion
5933				for ( i = 0; i < hasScripts; i++ ) {
5934					node = scripts[ i ];
5935					if ( rscriptType.test( node.type || "" ) &&
5936						!dataPriv.access( node, "globalEval" ) &&
5937						jQuery.contains( doc, node ) ) {
5938
5939						if ( node.src && ( node.type || "" ).toLowerCase()  !== "module" ) {
5940
5941							// Optional AJAX dependency, but won't run scripts if not present
5942							if ( jQuery._evalUrl && !node.noModule ) {
5943								jQuery._evalUrl( node.src, {
5944									nonce: node.nonce || node.getAttribute( "nonce" )
5945								}, doc );
5946							}
5947						} else {
5948
5949							// Unwrap a CDATA section containing script contents. This shouldn't be
5950							// needed as in XML documents they're already not visible when
5951							// inspecting element contents and in HTML documents they have no
5952							// meaning but we're preserving that logic for backwards compatibility.
5953							// This will be removed completely in 4.0. See gh-4904.
5954							DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc );
5955						}
5956					}
5957				}
5958			}
5959		}
5960	}
5961
5962	return collection;
5963}
5964
5965function remove( elem, selector, keepData ) {
5966	var node,
5967		nodes = selector ? jQuery.filter( selector, elem ) : elem,
5968		i = 0;
5969
5970	for ( ; ( node = nodes[ i ] ) != null; i++ ) {
5971		if ( !keepData && node.nodeType === 1 ) {
5972			jQuery.cleanData( getAll( node ) );
5973		}
5974
5975		if ( node.parentNode ) {
5976			if ( keepData && isAttached( node ) ) {
5977				setGlobalEval( getAll( node, "script" ) );
5978			}
5979			node.parentNode.removeChild( node );
5980		}
5981	}
5982
5983	return elem;
5984}
5985
5986jQuery.extend( {
5987	htmlPrefilter: function( html ) {
5988		return html;
5989	},
5990
5991	clone: function( elem, dataAndEvents, deepDataAndEvents ) {
5992		var i, l, srcElements, destElements,
5993			clone = elem.cloneNode( true ),
5994			inPage = isAttached( elem );
5995
5996		// Fix IE cloning issues
5997		if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&
5998				!jQuery.isXMLDoc( elem ) ) {
5999
6000			// We eschew jQuery#find here for performance reasons:
6001			// https://jsperf.com/getall-vs-sizzle/2
6002			destElements = getAll( clone );
6003			srcElements = getAll( elem );
6004
6005			for ( i = 0, l = srcElements.length; i < l; i++ ) {
6006				fixInput( srcElements[ i ], destElements[ i ] );
6007			}
6008		}
6009
6010		// Copy the events from the original to the clone
6011		if ( dataAndEvents ) {
6012			if ( deepDataAndEvents ) {
6013				srcElements = srcElements || getAll( elem );
6014				destElements = destElements || getAll( clone );
6015
6016				for ( i = 0, l = srcElements.length; i < l; i++ ) {
6017					cloneCopyEvent( srcElements[ i ], destElements[ i ] );
6018				}
6019			} else {
6020				cloneCopyEvent( elem, clone );
6021			}
6022		}
6023
6024		// Preserve script evaluation history
6025		destElements = getAll( clone, "script" );
6026		if ( destElements.length > 0 ) {
6027			setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
6028		}
6029
6030		// Return the cloned set
6031		return clone;
6032	},
6033
6034	cleanData: function( elems ) {
6035		var data, elem, type,
6036			special = jQuery.event.special,
6037			i = 0;
6038
6039		for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) {
6040			if ( acceptData( elem ) ) {
6041				if ( ( data = elem[ dataPriv.expando ] ) ) {
6042					if ( data.events ) {
6043						for ( type in data.events ) {
6044							if ( special[ type ] ) {
6045								jQuery.event.remove( elem, type );
6046
6047							// This is a shortcut to avoid jQuery.event.remove's overhead
6048							} else {
6049								jQuery.removeEvent( elem, type, data.handle );
6050							}
6051						}
6052					}
6053
vendor: 4,139 bytes, lines 6054-6218
6054					// Support: Chrome <=35 - 45+
6055					// Assign undefined instead of using delete, see Data#remove
6056					elem[ dataPriv.expando ] = undefined;
6057				}
6058				if ( elem[ dataUser.expando ] ) {
6059
6060					// Support: Chrome <=35 - 45+
6061					// Assign undefined instead of using delete, see Data#remove
6062					elem[ dataUser.expando ] = undefined;
6063				}
6064			}
6065		}
6066	}
6067} );
6068
6069jQuery.fn.extend( {
6070	detach: function( selector ) {
6071		return remove( this, selector, true );
6072	},
6073
6074	remove: function( selector ) {
6075		return remove( this, selector );
6076	},
6077
6078	text: function( value ) {
6079		return access( this, function( value ) {
6080			return value === undefined ?
6081				jQuery.text( this ) :
6082				this.empty().each( function() {
6083					if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
6084						this.textContent = value;
6085					}
6086				} );
6087		}, null, value, arguments.length );
6088	},
6089
6090	append: function() {
6091		return domManip( this, arguments, function( elem ) {
6092			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
6093				var target = manipulationTarget( this, elem );
6094				target.appendChild( elem );
6095			}
6096		} );
6097	},
6098
6099	prepend: function() {
6100		return domManip( this, arguments, function( elem ) {
6101			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
6102				var target = manipulationTarget( this, elem );
6103				target.insertBefore( elem, target.firstChild );
6104			}
6105		} );
6106	},
6107
6108	before: function() {
6109		return domManip( this, arguments, function( elem ) {
6110			if ( this.parentNode ) {
6111				this.parentNode.insertBefore( elem, this );
6112			}
6113		} );
6114	},
6115
6116	after: function() {
6117		return domManip( this, arguments, function( elem ) {
6118			if ( this.parentNode ) {
6119				this.parentNode.insertBefore( elem, this.nextSibling );
6120			}
6121		} );
6122	},
6123
6124	empty: function() {
6125		var elem,
6126			i = 0;
6127
6128		for ( ; ( elem = this[ i ] ) != null; i++ ) {
6129			if ( elem.nodeType === 1 ) {
6130
6131				// Prevent memory leaks
6132				jQuery.cleanData( getAll( elem, false ) );
6133
6134				// Remove any remaining nodes
6135				elem.textContent = "";
6136			}
6137		}
6138
6139		return this;
6140	},
6141
6142	clone: function( dataAndEvents, deepDataAndEvents ) {
6143		dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
6144		deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
6145
6146		return this.map( function() {
6147			return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
6148		} );
6149	},
6150
6151	html: function( value ) {
6152		return access( this, function( value ) {
6153			var elem = this[ 0 ] || {},
6154				i = 0,
6155				l = this.length;
6156
6157			if ( value === undefined && elem.nodeType === 1 ) {
6158				return elem.innerHTML;
6159			}
6160
6161			// See if we can take a shortcut and just use innerHTML
6162			if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
6163				!wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) {
6164
6165				value = jQuery.htmlPrefilter( value );
6166
6167				try {
6168					for ( ; i < l; i++ ) {
6169						elem = this[ i ] || {};
6170
6171						// Remove element nodes and prevent memory leaks
6172						if ( elem.nodeType === 1 ) {
6173							jQuery.cleanData( getAll( elem, false ) );
6174							elem.innerHTML = value;
6175						}
6176					}
6177
6178					elem = 0;
6179
6180				// If using innerHTML throws an exception, use the fallback method
6181				} catch ( e ) {}
6182			}
6183
6184			if ( elem ) {
6185				this.empty().append( value );
6186			}
6187		}, null, value, arguments.length );
6188	},
6189
6190	replaceWith: function() {
6191		var ignored = [];
6192
6193		// Make the changes, replacing each non-ignored context element with the new content
6194		return domManip( this, arguments, function( elem ) {
6195			var parent = this.parentNode;
6196
6197			if ( jQuery.inArray( this, ignored ) < 0 ) {
6198				jQuery.cleanData( getAll( this ) );
6199				if ( parent ) {
6200					parent.replaceChild( elem, this );
6201				}
6202			}
6203
6204		// Force callback invocation
6205		}, ignored );
6206	}
6207} );
6208
6209jQuery.each( {
6210	appendTo: "append",
6211	prependTo: "prepend",
6212	insertBefore: "before",
6213	insertAfter: "after",
6214	replaceAll: "replaceWith"
6215}, function( name, original ) {
6216	jQuery.fn[ name ] = function( selector ) {
6217		var elems,
6218			ret = [],
vendor: 31,588 bytes, lines 6219-7281
6219			insert = jQuery( selector ),
6220			last = insert.length - 1,
6221			i = 0;
6222
6223		for ( ; i <= last; i++ ) {
6224			elems = i === last ? this : this.clone( true );
6225			jQuery( insert[ i ] )[ original ]( elems );
6226
6227			// Support: Android <=4.0 only, PhantomJS 1 only
6228			// .get() because push.apply(_, arraylike) throws on ancient WebKit
6229			push.apply( ret, elems.get() );
6230		}
6231
6232		return this.pushStack( ret );
6233	};
6234} );
6235var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
6236
6237var rcustomProp = /^--/;
6238
6239
6240var getStyles = function( elem ) {
6241
6242		// Support: IE <=11 only, Firefox <=30 (trac-15098, trac-14150)
6243		// IE throws on elements created in popups
6244		// FF meanwhile throws on frame elements through "defaultView.getComputedStyle"
6245		var view = elem.ownerDocument.defaultView;
6246
6247		if ( !view || !view.opener ) {
6248			view = window;
6249		}
6250
6251		return view.getComputedStyle( elem );
6252	};
6253
6254var swap = function( elem, options, callback ) {
6255	var ret, name,
6256		old = {};
6257
6258	// Remember the old values, and insert the new ones
6259	for ( name in options ) {
6260		old[ name ] = elem.style[ name ];
6261		elem.style[ name ] = options[ name ];
6262	}
6263
6264	ret = callback.call( elem );
6265
6266	// Revert the old values
6267	for ( name in options ) {
6268		elem.style[ name ] = old[ name ];
6269	}
6270
6271	return ret;
6272};
6273
6274
6275var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" );
6276
6277
6278
6279( function() {
6280
6281	// Executing both pixelPosition & boxSizingReliable tests require only one layout
6282	// so they're executed at the same time to save the second computation.
6283	function computeStyleTests() {
6284
6285		// This is a singleton, we need to execute it only once
6286		if ( !div ) {
6287			return;
6288		}
6289
6290		container.style.cssText = "position:absolute;left:-11111px;width:60px;" +
6291			"margin-top:1px;padding:0;border:0";
6292		div.style.cssText =
6293			"position:relative;display:block;box-sizing:border-box;overflow:scroll;" +
6294			"margin:auto;border:1px;padding:1px;" +
6295			"width:60%;top:1%";
6296		documentElement.appendChild( container ).appendChild( div );
6297
6298		var divStyle = window.getComputedStyle( div );
6299		pixelPositionVal = divStyle.top !== "1%";
6300
6301		// Support: Android 4.0 - 4.3 only, Firefox <=3 - 44
6302		reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12;
6303
6304		// Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3
6305		// Some styles come back with percentage values, even though they shouldn't
6306		div.style.right = "60%";
6307		pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36;
6308
6309		// Support: IE 9 - 11 only
6310		// Detect misreporting of content dimensions for box-sizing:border-box elements
6311		boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36;
6312
6313		// Support: IE 9 only
6314		// Detect overflow:scroll screwiness (gh-3699)
6315		// Support: Chrome <=64
6316		// Don't get tricked when zoom affects offsetWidth (gh-4029)
6317		div.style.position = "absolute";
6318		scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12;
6319
6320		documentElement.removeChild( container );
6321
6322		// Nullify the div so it wouldn't be stored in the memory and
6323		// it will also be a sign that checks already performed
6324		div = null;
6325	}
6326
6327	function roundPixelMeasures( measure ) {
6328		return Math.round( parseFloat( measure ) );
6329	}
6330
6331	var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal,
6332		reliableTrDimensionsVal, reliableMarginLeftVal,
6333		container = document.createElement( "div" ),
6334		div = document.createElement( "div" );
6335
6336	// Finish early in limited (non-browser) environments
6337	if ( !div.style ) {
6338		return;
6339	}
6340
6341	// Support: IE <=9 - 11 only
6342	// Style of cloned element affects source element cloned (trac-8908)
6343	div.style.backgroundClip = "content-box";
6344	div.cloneNode( true ).style.backgroundClip = "";
6345	support.clearCloneStyle = div.style.backgroundClip === "content-box";
6346
6347	jQuery.extend( support, {
6348		boxSizingReliable: function() {
6349			computeStyleTests();
6350			return boxSizingReliableVal;
6351		},
6352		pixelBoxStyles: function() {
6353			computeStyleTests();
6354			return pixelBoxStylesVal;
6355		},
6356		pixelPosition: function() {
6357			computeStyleTests();
6358			return pixelPositionVal;
6359		},
6360		reliableMarginLeft: function() {
6361			computeStyleTests();
6362			return reliableMarginLeftVal;
6363		},
6364		scrollboxSize: function() {
6365			computeStyleTests();
6366			return scrollboxSizeVal;
6367		},
6368
6369		// Support: IE 9 - 11+, Edge 15 - 18+
6370		// IE/Edge misreport `getComputedStyle` of table rows with width/height
6371		// set in CSS while `offset*` properties report correct values.
6372		// Behavior in IE 9 is more subtle than in newer versions & it passes
6373		// some versions of this test; make sure not to make it pass there!
6374		//
6375		// Support: Firefox 70+
6376		// Only Firefox includes border widths
6377		// in computed dimensions. (gh-4529)
6378		reliableTrDimensions: function() {
6379			var table, tr, trChild, trStyle;
6380			if ( reliableTrDimensionsVal == null ) {
6381				table = document.createElement( "table" );
6382				tr = document.createElement( "tr" );
6383				trChild = document.createElement( "div" );
6384
6385				table.style.cssText = "position:absolute;left:-11111px;border-collapse:separate";
6386				tr.style.cssText = "box-sizing:content-box;border:1px solid";
6387
6388				// Support: Chrome 86+
6389				// Height set through cssText does not get applied.
6390				// Computed height then comes back as 0.
6391				tr.style.height = "1px";
6392				trChild.style.height = "9px";
6393
6394				// Support: Android 8 Chrome 86+
6395				// In our bodyBackground.html iframe,
6396				// display for all div elements is set to "inline",
6397				// which causes a problem only in Android 8 Chrome 86.
6398				// Ensuring the div is `display: block`
6399				// gets around this issue.
6400				trChild.style.display = "block";
6401
6402				documentElement
6403					.appendChild( table )
6404					.appendChild( tr )
6405					.appendChild( trChild );
6406
6407				trStyle = window.getComputedStyle( tr );
6408				reliableTrDimensionsVal = ( parseInt( trStyle.height, 10 ) +
6409					parseInt( trStyle.borderTopWidth, 10 ) +
6410					parseInt( trStyle.borderBottomWidth, 10 ) ) === tr.offsetHeight;
6411
6412				documentElement.removeChild( table );
6413			}
6414			return reliableTrDimensionsVal;
6415		}
6416	} );
6417} )();
6418
6419
6420function curCSS( elem, name, computed ) {
6421	var width, minWidth, maxWidth, ret,
6422		isCustomProp = rcustomProp.test( name ),
6423
6424		// Support: Firefox 51+
6425		// Retrieving style before computed somehow
6426		// fixes an issue with getting wrong values
6427		// on detached elements
6428		style = elem.style;
6429
6430	computed = computed || getStyles( elem );
6431
6432	// getPropertyValue is needed for:
6433	//   .css('filter') (IE 9 only, trac-12537)
6434	//   .css('--customProperty) (gh-3144)
6435	if ( computed ) {
6436
6437		// Support: IE <=9 - 11+
6438		// IE only supports `"float"` in `getPropertyValue`; in computed styles
6439		// it's only available as `"cssFloat"`. We no longer modify properties
6440		// sent to `.css()` apart from camelCasing, so we need to check both.
6441		// Normally, this would create difference in behavior: if
6442		// `getPropertyValue` returns an empty string, the value returned
6443		// by `.css()` would be `undefined`. This is usually the case for
6444		// disconnected elements. However, in IE even disconnected elements
6445		// with no styles return `"none"` for `getPropertyValue( "float" )`
6446		ret = computed.getPropertyValue( name ) || computed[ name ];
6447
6448		if ( isCustomProp && ret ) {
6449
6450			// Support: Firefox 105+, Chrome <=105+
6451			// Spec requires trimming whitespace for custom properties (gh-4926).
6452			// Firefox only trims leading whitespace. Chrome just collapses
6453			// both leading & trailing whitespace to a single space.
6454			//
6455			// Fall back to `undefined` if empty string returned.
6456			// This collapses a missing definition with property defined
6457			// and set to an empty string but there's no standard API
6458			// allowing us to differentiate them without a performance penalty
6459			// and returning `undefined` aligns with older jQuery.
6460			//
6461			// rtrimCSS treats U+000D CARRIAGE RETURN and U+000C FORM FEED
6462			// as whitespace while CSS does not, but this is not a problem
6463			// because CSS preprocessing replaces them with U+000A LINE FEED
6464			// (which *is* CSS whitespace)
6465			// https://www.w3.org/TR/css-syntax-3/#input-preprocessing
6466			ret = ret.replace( rtrimCSS, "$1" ) || undefined;
6467		}
6468
6469		if ( ret === "" && !isAttached( elem ) ) {
6470			ret = jQuery.style( elem, name );
6471		}
6472
6473		// A tribute to the "awesome hack by Dean Edwards"
6474		// Android Browser returns percentage for some values,
6475		// but width seems to be reliably pixels.
6476		// This is against the CSSOM draft spec:
6477		// https://drafts.csswg.org/cssom/#resolved-values
6478		if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) {
6479
6480			// Remember the original values
6481			width = style.width;
6482			minWidth = style.minWidth;
6483			maxWidth = style.maxWidth;
6484
6485			// Put in the new values to get a computed value out
6486			style.minWidth = style.maxWidth = style.width = ret;
6487			ret = computed.width;
6488
6489			// Revert the changed values
6490			style.width = width;
6491			style.minWidth = minWidth;
6492			style.maxWidth = maxWidth;
6493		}
6494	}
6495
6496	return ret !== undefined ?
6497
6498		// Support: IE <=9 - 11 only
6499		// IE returns zIndex value as an integer.
6500		ret + "" :
6501		ret;
6502}
6503
6504
6505function addGetHookIf( conditionFn, hookFn ) {
6506
6507	// Define the hook, we'll check on the first run if it's really needed.
6508	return {
6509		get: function() {
6510			if ( conditionFn() ) {
6511
6512				// Hook not needed (or it's not possible to use it due
6513				// to missing dependency), remove it.
6514				delete this.get;
6515				return;
6516			}
6517
6518			// Hook needed; redefine it so that the support test is not executed again.
6519			return ( this.get = hookFn ).apply( this, arguments );
6520		}
6521	};
6522}
6523
6524
6525var cssPrefixes = [ "Webkit", "Moz", "ms" ],
6526	emptyStyle = document.createElement( "div" ).style,
6527	vendorProps = {};
6528
6529// Return a vendor-prefixed property or undefined
6530function vendorPropName( name ) {
6531
6532	// Check for vendor prefixed names
6533	var capName = name[ 0 ].toUpperCase() + name.slice( 1 ),
6534		i = cssPrefixes.length;
6535
6536	while ( i-- ) {
6537		name = cssPrefixes[ i ] + capName;
6538		if ( name in emptyStyle ) {
6539			return name;
6540		}
6541	}
6542}
6543
6544// Return a potentially-mapped jQuery.cssProps or vendor prefixed property
6545function finalPropName( name ) {
6546	var final = jQuery.cssProps[ name ] || vendorProps[ name ];
6547
6548	if ( final ) {
6549		return final;
6550	}
6551	if ( name in emptyStyle ) {
6552		return name;
6553	}
6554	return vendorProps[ name ] = vendorPropName( name ) || name;
6555}
6556
6557
6558var
6559
6560	// Swappable if display is none or starts with table
6561	// except "table", "table-cell", or "table-caption"
6562	// See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
6563	rdisplayswap = /^(none|table(?!-c[ea]).+)/,
6564	cssShow = { position: "absolute", visibility: "hidden", display: "block" },
6565	cssNormalTransform = {
6566		letterSpacing: "0",
6567		fontWeight: "400"
6568	};
6569
6570function setPositiveNumber( _elem, value, subtract ) {
6571
6572	// Any relative (+/-) values have already been
6573	// normalized at this point
6574	var matches = rcssNum.exec( value );
6575	return matches ?
6576
6577		// Guard against undefined "subtract", e.g., when used as in cssHooks
6578		Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) :
6579		value;
6580}
6581
6582function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) {
6583	var i = dimension === "width" ? 1 : 0,
6584		extra = 0,
6585		delta = 0,
6586		marginDelta = 0;
6587
6588	// Adjustment may not be necessary
6589	if ( box === ( isBorderBox ? "border" : "content" ) ) {
6590		return 0;
6591	}
6592
6593	for ( ; i < 4; i += 2 ) {
6594
6595		// Both box models exclude margin
6596		// Count margin delta separately to only add it after scroll gutter adjustment.
6597		// This is needed to make negative margins work with `outerHeight( true )` (gh-3982).
6598		if ( box === "margin" ) {
6599			marginDelta += jQuery.css( elem, box + cssExpand[ i ], true, styles );
6600		}
6601
6602		// If we get here with a content-box, we're seeking "padding" or "border" or "margin"
6603		if ( !isBorderBox ) {
6604
6605			// Add padding
6606			delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
6607
6608			// For "border" or "margin", add border
6609			if ( box !== "padding" ) {
6610				delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
6611
6612			// But still keep track of it otherwise
6613			} else {
6614				extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
6615			}
6616
6617		// If we get here with a border-box (content + padding + border), we're seeking "content" or
6618		// "padding" or "margin"
6619		} else {
6620
6621			// For "content", subtract padding
6622			if ( box === "content" ) {
6623				delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
6624			}
6625
6626			// For "content" or "padding", subtract border
6627			if ( box !== "margin" ) {
6628				delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
6629			}
6630		}
6631	}
6632
6633	// Account for positive content-box scroll gutter when requested by providing computedVal
6634	if ( !isBorderBox && computedVal >= 0 ) {
6635
6636		// offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border
6637		// Assuming integer scroll gutter, subtract the rest and round down
6638		delta += Math.max( 0, Math.ceil(
6639			elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] -
6640			computedVal -
6641			delta -
6642			extra -
6643			0.5
6644
6645		// If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter
6646		// Use an explicit zero to avoid NaN (gh-3964)
6647		) ) || 0;
6648	}
6649
6650	return delta + marginDelta;
6651}
6652
6653function getWidthOrHeight( elem, dimension, extra ) {
6654
6655	// Start with computed style
6656	var styles = getStyles( elem ),
6657
6658		// To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322).
6659		// Fake content-box until we know it's needed to know the true value.
6660		boxSizingNeeded = !support.boxSizingReliable() || extra,
6661		isBorderBox = boxSizingNeeded &&
6662			jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
6663		valueIsBorderBox = isBorderBox,
6664
6665		val = curCSS( elem, dimension, styles ),
6666		offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 );
6667
6668	// Support: Firefox <=54
6669	// Return a confounding non-pixel value or feign ignorance, as appropriate.
6670	if ( rnumnonpx.test( val ) ) {
6671		if ( !extra ) {
6672			return val;
6673		}
6674		val = "auto";
6675	}
6676
6677
6678	// Support: IE 9 - 11 only
6679	// Use offsetWidth/offsetHeight for when box sizing is unreliable.
6680	// In those cases, the computed value can be trusted to be border-box.
6681	if ( ( !support.boxSizingReliable() && isBorderBox ||
6682
6683		// Support: IE 10 - 11+, Edge 15 - 18+
6684		// IE/Edge misreport `getComputedStyle` of table rows with width/height
6685		// set in CSS while `offset*` properties report correct values.
6686		// Interestingly, in some cases IE 9 doesn't suffer from this issue.
6687		!support.reliableTrDimensions() && nodeName( elem, "tr" ) ||
6688
6689		// Fall back to offsetWidth/offsetHeight when value is "auto"
6690		// This happens for inline elements with no explicit setting (gh-3571)
6691		val === "auto" ||
6692
6693		// Support: Android <=4.1 - 4.3 only
6694		// Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602)
6695		!parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) &&
6696
6697		// Make sure the element is visible & connected
6698		elem.getClientRects().length ) {
6699
6700		isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
6701
6702		// Where available, offsetWidth/offsetHeight approximate border box dimensions.
6703		// Where not available (e.g., SVG), assume unreliable box-sizing and interpret the
6704		// retrieved value as a content box dimension.
6705		valueIsBorderBox = offsetProp in elem;
6706		if ( valueIsBorderBox ) {
6707			val = elem[ offsetProp ];
6708		}
6709	}
6710
6711	// Normalize "" and auto
6712	val = parseFloat( val ) || 0;
6713
6714	// Adjust for the element's box model
6715	return ( val +
6716		boxModelAdjustment(
6717			elem,
6718			dimension,
6719			extra || ( isBorderBox ? "border" : "content" ),
6720			valueIsBorderBox,
6721			styles,
6722
6723			// Provide the current computed size to request scroll gutter calculation (gh-3589)
6724			val
6725		)
6726	) + "px";
6727}
6728
6729jQuery.extend( {
6730
6731	// Add in style property hooks for overriding the default
6732	// behavior of getting and setting a style property
6733	cssHooks: {
6734		opacity: {
6735			get: function( elem, computed ) {
6736				if ( computed ) {
6737
6738					// We should always get a number back from opacity
6739					var ret = curCSS( elem, "opacity" );
6740					return ret === "" ? "1" : ret;
6741				}
6742			}
6743		}
6744	},
6745
6746	// Don't automatically add "px" to these possibly-unitless properties
6747	cssNumber: {
6748		animationIterationCount: true,
6749		aspectRatio: true,
6750		borderImageSlice: true,
6751		columnCount: true,
6752		flexGrow: true,
6753		flexShrink: true,
6754		fontWeight: true,
6755		gridArea: true,
6756		gridColumn: true,
6757		gridColumnEnd: true,
6758		gridColumnStart: true,
6759		gridRow: true,
6760		gridRowEnd: true,
6761		gridRowStart: true,
6762		lineHeight: true,
6763		opacity: true,
6764		order: true,
6765		orphans: true,
6766		scale: true,
6767		widows: true,
6768		zIndex: true,
6769		zoom: true,
6770
6771		// SVG-related
6772		fillOpacity: true,
6773		floodOpacity: true,
6774		stopOpacity: true,
6775		strokeMiterlimit: true,
6776		strokeOpacity: true
6777	},
6778
6779	// Add in properties whose names you wish to fix before
6780	// setting or getting the value
6781	cssProps: {},
6782
6783	// Get and set the style property on a DOM Node
6784	style: function( elem, name, value, extra ) {
6785
6786		// Don't set styles on text and comment nodes
6787		if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
6788			return;
6789		}
6790
6791		// Make sure that we're working with the right name
6792		var ret, type, hooks,
6793			origName = camelCase( name ),
6794			isCustomProp = rcustomProp.test( name ),
6795			style = elem.style;
6796
6797		// Make sure that we're working with the right name. We don't
6798		// want to query the value if it is a CSS custom property
6799		// since they are user-defined.
6800		if ( !isCustomProp ) {
6801			name = finalPropName( origName );
6802		}
6803
6804		// Gets hook for the prefixed version, then unprefixed version
6805		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
6806
6807		// Check if we're setting a value
6808		if ( value !== undefined ) {
6809			type = typeof value;
6810
6811			// Convert "+=" or "-=" to relative numbers (trac-7345)
6812			if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) {
6813				value = adjustCSS( elem, name, ret );
6814
6815				// Fixes bug trac-9237
6816				type = "number";
6817			}
6818
6819			// Make sure that null and NaN values aren't set (trac-7116)
6820			if ( value == null || value !== value ) {
6821				return;
6822			}
6823
6824			// If a number was passed in, add the unit (except for certain CSS properties)
6825			// The isCustomProp check can be removed in jQuery 4.0 when we only auto-append
6826			// "px" to a few hardcoded values.
6827			if ( type === "number" && !isCustomProp ) {
6828				value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" );
6829			}
6830
6831			// background-* props affect original clone's values
6832			if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) {
6833				style[ name ] = "inherit";
6834			}
6835
6836			// If a hook was provided, use that value, otherwise just set the specified value
6837			if ( !hooks || !( "set" in hooks ) ||
6838				( value = hooks.set( elem, value, extra ) ) !== undefined ) {
6839
6840				if ( isCustomProp ) {
6841					style.setProperty( name, value );
6842				} else {
6843					style[ name ] = value;
6844				}
6845			}
6846
6847		} else {
6848
6849			// If a hook was provided get the non-computed value from there
6850			if ( hooks && "get" in hooks &&
6851				( ret = hooks.get( elem, false, extra ) ) !== undefined ) {
6852
6853				return ret;
6854			}
6855
6856			// Otherwise just get the value from the style object
6857			return style[ name ];
6858		}
6859	},
6860
6861	css: function( elem, name, extra, styles ) {
6862		var val, num, hooks,
6863			origName = camelCase( name ),
6864			isCustomProp = rcustomProp.test( name );
6865
6866		// Make sure that we're working with the right name. We don't
6867		// want to modify the value if it is a CSS custom property
6868		// since they are user-defined.
6869		if ( !isCustomProp ) {
6870			name = finalPropName( origName );
6871		}
6872
6873		// Try prefixed name followed by the unprefixed name
6874		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
6875
6876		// If a hook was provided get the computed value from there
6877		if ( hooks && "get" in hooks ) {
6878			val = hooks.get( elem, true, extra );
6879		}
6880
6881		// Otherwise, if a way to get the computed value exists, use that
6882		if ( val === undefined ) {
6883			val = curCSS( elem, name, styles );
6884		}
6885
6886		// Convert "normal" to computed value
6887		if ( val === "normal" && name in cssNormalTransform ) {
6888			val = cssNormalTransform[ name ];
6889		}
6890
6891		// Make numeric if forced or a qualifier was provided and val looks numeric
6892		if ( extra === "" || extra ) {
6893			num = parseFloat( val );
6894			return extra === true || isFinite( num ) ? num || 0 : val;
6895		}
6896
6897		return val;
6898	}
6899} );
6900
6901jQuery.each( [ "height", "width" ], function( _i, dimension ) {
6902	jQuery.cssHooks[ dimension ] = {
6903		get: function( elem, computed, extra ) {
6904			if ( computed ) {
6905
6906				// Certain elements can have dimension info if we invisibly show them
6907				// but it must have a current display style that would benefit
6908				return rdisplayswap.test( jQuery.css( elem, "display" ) ) &&
6909
6910					// Support: Safari 8+
6911					// Table columns in Safari have non-zero offsetWidth & zero
6912					// getBoundingClientRect().width unless display is changed.
6913					// Support: IE <=11 only
6914					// Running getBoundingClientRect on a disconnected node
6915					// in IE throws an error.
6916					( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ?
6917					swap( elem, cssShow, function() {
6918						return getWidthOrHeight( elem, dimension, extra );
6919					} ) :
6920					getWidthOrHeight( elem, dimension, extra );
6921			}
6922		},
6923
6924		set: function( elem, value, extra ) {
6925			var matches,
6926				styles = getStyles( elem ),
6927
6928				// Only read styles.position if the test has a chance to fail
6929				// to avoid forcing a reflow.
6930				scrollboxSizeBuggy = !support.scrollboxSize() &&
6931					styles.position === "absolute",
6932
6933				// To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991)
6934				boxSizingNeeded = scrollboxSizeBuggy || extra,
6935				isBorderBox = boxSizingNeeded &&
6936					jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
6937				subtract = extra ?
6938					boxModelAdjustment(
6939						elem,
6940						dimension,
6941						extra,
6942						isBorderBox,
6943						styles
6944					) :
6945					0;
6946
6947			// Account for unreliable border-box dimensions by comparing offset* to computed and
6948			// faking a content-box to get border and padding (gh-3699)
6949			if ( isBorderBox && scrollboxSizeBuggy ) {
6950				subtract -= Math.ceil(
6951					elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] -
6952					parseFloat( styles[ dimension ] ) -
6953					boxModelAdjustment( elem, dimension, "border", false, styles ) -
6954					0.5
6955				);
6956			}
6957
6958			// Convert to pixels if value adjustment is needed
6959			if ( subtract && ( matches = rcssNum.exec( value ) ) &&
6960				( matches[ 3 ] || "px" ) !== "px" ) {
6961
6962				elem.style[ dimension ] = value;
6963				value = jQuery.css( elem, dimension );
6964			}
6965
6966			return setPositiveNumber( elem, value, subtract );
6967		}
6968	};
6969} );
6970
6971jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft,
6972	function( elem, computed ) {
6973		if ( computed ) {
6974			return ( parseFloat( curCSS( elem, "marginLeft" ) ) ||
6975				elem.getBoundingClientRect().left -
6976					swap( elem, { marginLeft: 0 }, function() {
6977						return elem.getBoundingClientRect().left;
6978					} )
6979			) + "px";
6980		}
6981	}
6982);
6983
6984// These hooks are used by animate to expand properties
6985jQuery.each( {
6986	margin: "",
6987	padding: "",
6988	border: "Width"
6989}, function( prefix, suffix ) {
6990	jQuery.cssHooks[ prefix + suffix ] = {
6991		expand: function( value ) {
6992			var i = 0,
6993				expanded = {},
6994
6995				// Assumes a single number if not a string
6996				parts = typeof value === "string" ? value.split( " " ) : [ value ];
6997
6998			for ( ; i < 4; i++ ) {
6999				expanded[ prefix + cssExpand[ i ] + suffix ] =
7000					parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
7001			}
7002
7003			return expanded;
7004		}
7005	};
7006
7007	if ( prefix !== "margin" ) {
7008		jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
7009	}
7010} );
7011
7012jQuery.fn.extend( {
7013	css: function( name, value ) {
7014		return access( this, function( elem, name, value ) {
7015			var styles, len,
7016				map = {},
7017				i = 0;
7018
7019			if ( Array.isArray( name ) ) {
7020				styles = getStyles( elem );
7021				len = name.length;
7022
7023				for ( ; i < len; i++ ) {
7024					map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
7025				}
7026
7027				return map;
7028			}
7029
7030			return value !== undefined ?
7031				jQuery.style( elem, name, value ) :
7032				jQuery.css( elem, name );
7033		}, name, value, arguments.length > 1 );
7034	}
7035} );
7036
7037
7038function Tween( elem, options, prop, end, easing ) {
7039	return new Tween.prototype.init( elem, options, prop, end, easing );
7040}
7041jQuery.Tween = Tween;
7042
7043Tween.prototype = {
7044	constructor: Tween,
7045	init: function( elem, options, prop, end, easing, unit ) {
7046		this.elem = elem;
7047		this.prop = prop;
7048		this.easing = easing || jQuery.easing._default;
7049		this.options = options;
7050		this.start = this.now = this.cur();
7051		this.end = end;
7052		this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
7053	},
7054	cur: function() {
7055		var hooks = Tween.propHooks[ this.prop ];
7056
7057		return hooks && hooks.get ?
7058			hooks.get( this ) :
7059			Tween.propHooks._default.get( this );
7060	},
7061	run: function( percent ) {
7062		var eased,
7063			hooks = Tween.propHooks[ this.prop ];
7064
7065		if ( this.options.duration ) {
7066			this.pos = eased = jQuery.easing[ this.easing ](
7067				percent, this.options.duration * percent, 0, 1, this.options.duration
7068			);
7069		} else {
7070			this.pos = eased = percent;
7071		}
7072		this.now = ( this.end - this.start ) * eased + this.start;
7073
7074		if ( this.options.step ) {
7075			this.options.step.call( this.elem, this.now, this );
7076		}
7077
7078		if ( hooks && hooks.set ) {
7079			hooks.set( this );
7080		} else {
7081			Tween.propHooks._default.set( this );
7082		}
7083		return this;
7084	}
7085};
7086
7087Tween.prototype.init.prototype = Tween.prototype;
7088
7089Tween.propHooks = {
7090	_default: {
7091		get: function( tween ) {
7092			var result;
7093
7094			// Use a property on the element directly when it is not a DOM element,
7095			// or when there is no matching style property that exists.
7096			if ( tween.elem.nodeType !== 1 ||
7097				tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) {
7098				return tween.elem[ tween.prop ];
7099			}
7100
7101			// Passing an empty string as a 3rd parameter to .css will automatically
7102			// attempt a parseFloat and fallback to a string if the parse fails.
7103			// Simple values such as "10px" are parsed to Float;
7104			// complex values such as "rotate(1rad)" are returned as-is.
7105			result = jQuery.css( tween.elem, tween.prop, "" );
7106
7107			// Empty strings, null, undefined and "auto" are converted to 0.
7108			return !result || result === "auto" ? 0 : result;
7109		},
7110		set: function( tween ) {
7111
7112			// Use step hook for back compat.
7113			// Use cssHook if its there.
7114			// Use .style if available and use plain properties where available.
7115			if ( jQuery.fx.step[ tween.prop ] ) {
7116				jQuery.fx.step[ tween.prop ]( tween );
7117			} else if ( tween.elem.nodeType === 1 && (
7118				jQuery.cssHooks[ tween.prop ] ||
7119					tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) {
7120				jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
7121			} else {
7122				tween.elem[ tween.prop ] = tween.now;
7123			}
7124		}
7125	}
7126};
7127
7128// Support: IE <=9 only
7129// Panic based approach to setting things on disconnected nodes
7130Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
7131	set: function( tween ) {
7132		if ( tween.elem.nodeType && tween.elem.parentNode ) {
7133			tween.elem[ tween.prop ] = tween.now;
7134		}
7135	}
7136};
7137
7138jQuery.easing = {
7139	linear: function( p ) {
7140		return p;
7141	},
7142	swing: function( p ) {
7143		return 0.5 - Math.cos( p * Math.PI ) / 2;
7144	},
7145	_default: "swing"
7146};
7147
7148jQuery.fx = Tween.prototype.init;
7149
7150// Back compat <1.8 extension point
7151jQuery.fx.step = {};
7152
7153
7154
7155
7156var
7157	fxNow, inProgress,
7158	rfxtypes = /^(?:toggle|show|hide)$/,
7159	rrun = /queueHooks$/;
7160
7161function schedule() {
7162	if ( inProgress ) {
7163		if ( document.hidden === false && window.requestAnimationFrame ) {
7164			window.requestAnimationFrame( schedule );
7165		} else {
7166			window.setTimeout( schedule, jQuery.fx.interval );
7167		}
7168
7169		jQuery.fx.tick();
7170	}
7171}
7172
7173// Animations created synchronously will run synchronously
7174function createFxNow() {
7175	window.setTimeout( function() {
7176		fxNow = undefined;
7177	} );
7178	return ( fxNow = Date.now() );
7179}
7180
7181// Generate parameters to create a standard animation
7182function genFx( type, includeWidth ) {
7183	var which,
7184		i = 0,
7185		attrs = { height: type };
7186
7187	// If we include width, step value is 1 to do all cssExpand values,
7188	// otherwise step value is 2 to skip over Left and Right
7189	includeWidth = includeWidth ? 1 : 0;
7190	for ( ; i < 4; i += 2 - includeWidth ) {
7191		which = cssExpand[ i ];
7192		attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
7193	}
7194
7195	if ( includeWidth ) {
7196		attrs.opacity = attrs.width = type;
7197	}
7198
7199	return attrs;
7200}
7201
7202function createTween( value, prop, animation ) {
7203	var tween,
7204		collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ),
7205		index = 0,
7206		length = collection.length;
7207	for ( ; index < length; index++ ) {
7208		if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) {
7209
7210			// We're done with this property
7211			return tween;
7212		}
7213	}
7214}
7215
7216function defaultPrefilter( elem, props, opts ) {
7217	var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display,
7218		isBox = "width" in props || "height" in props,
7219		anim = this,
7220		orig = {},
7221		style = elem.style,
7222		hidden = elem.nodeType && isHiddenWithinTree( elem ),
7223		dataShow = dataPriv.get( elem, "fxshow" );
7224
7225	// Queue-skipping animations hijack the fx hooks
7226	if ( !opts.queue ) {
7227		hooks = jQuery._queueHooks( elem, "fx" );
7228		if ( hooks.unqueued == null ) {
7229			hooks.unqueued = 0;
7230			oldfire = hooks.empty.fire;
7231			hooks.empty.fire = function() {
7232				if ( !hooks.unqueued ) {
7233					oldfire();
7234				}
7235			};
7236		}
7237		hooks.unqueued++;
7238
7239		anim.always( function() {
7240
7241			// Ensure the complete handler is called before this completes
7242			anim.always( function() {
7243				hooks.unqueued--;
7244				if ( !jQuery.queue( elem, "fx" ).length ) {
7245					hooks.empty.fire();
7246				}
7247			} );
7248		} );
7249	}
7250
7251	// Detect show/hide animations
7252	for ( prop in props ) {
7253		value = props[ prop ];
7254		if ( rfxtypes.test( value ) ) {
7255			delete props[ prop ];
7256			toggle = toggle || value === "toggle";
7257			if ( value === ( hidden ? "hide" : "show" ) ) {
7258
7259				// Pretend to be hidden if this is a "show" and
7260				// there is still data from a stopped show/hide
7261				if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
7262					hidden = true;
7263
7264				// Ignore all other no-op show/hide data
7265				} else {
7266					continue;
7267				}
7268			}
7269			orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
7270		}
7271	}
7272
7273	// Bail out if this is a no-op like .hide().hide()
7274	propTween = !jQuery.isEmptyObject( props );
7275	if ( !propTween && jQuery.isEmptyObject( orig ) ) {
7276		return;
7277	}
7278
7279	// Restrict "overflow" and "display" styles during box animations
7280	if ( isBox && elem.nodeType === 1 ) {
7281
vendor: 4,381 bytes, lines 7282-7441
7282		// Support: IE <=9 - 11, Edge 12 - 15
7283		// Record all 3 overflow attributes because IE does not infer the shorthand
7284		// from identically-valued overflowX and overflowY and Edge just mirrors
7285		// the overflowX value there.
7286		opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
7287
7288		// Identify a display type, preferring old show/hide data over the CSS cascade
7289		restoreDisplay = dataShow && dataShow.display;
7290		if ( restoreDisplay == null ) {
7291			restoreDisplay = dataPriv.get( elem, "display" );
7292		}
7293		display = jQuery.css( elem, "display" );
7294		if ( display === "none" ) {
7295			if ( restoreDisplay ) {
7296				display = restoreDisplay;
7297			} else {
7298
7299				// Get nonempty value(s) by temporarily forcing visibility
7300				showHide( [ elem ], true );
7301				restoreDisplay = elem.style.display || restoreDisplay;
7302				display = jQuery.css( elem, "display" );
7303				showHide( [ elem ] );
7304			}
7305		}
7306
7307		// Animate inline elements as inline-block
7308		if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) {
7309			if ( jQuery.css( elem, "float" ) === "none" ) {
7310
7311				// Restore the original display value at the end of pure show/hide animations
7312				if ( !propTween ) {
7313					anim.done( function() {
7314						style.display = restoreDisplay;
7315					} );
7316					if ( restoreDisplay == null ) {
7317						display = style.display;
7318						restoreDisplay = display === "none" ? "" : display;
7319					}
7320				}
7321				style.display = "inline-block";
7322			}
7323		}
7324	}
7325
7326	if ( opts.overflow ) {
7327		style.overflow = "hidden";
7328		anim.always( function() {
7329			style.overflow = opts.overflow[ 0 ];
7330			style.overflowX = opts.overflow[ 1 ];
7331			style.overflowY = opts.overflow[ 2 ];
7332		} );
7333	}
7334
7335	// Implement show/hide animations
7336	propTween = false;
7337	for ( prop in orig ) {
7338
7339		// General show/hide setup for this element animation
7340		if ( !propTween ) {
7341			if ( dataShow ) {
7342				if ( "hidden" in dataShow ) {
7343					hidden = dataShow.hidden;
7344				}
7345			} else {
7346				dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } );
7347			}
7348
7349			// Store hidden/visible for toggle so `.stop().toggle()` "reverses"
7350			if ( toggle ) {
7351				dataShow.hidden = !hidden;
7352			}
7353
7354			// Show elements before animating them
7355			if ( hidden ) {
7356				showHide( [ elem ], true );
7357			}
7358
7359			/* eslint-disable no-loop-func */
7360
7361			anim.done( function() {
7362
7363				/* eslint-enable no-loop-func */
7364
7365				// The final step of a "hide" animation is actually hiding the element
7366				if ( !hidden ) {
7367					showHide( [ elem ] );
7368				}
7369				dataPriv.remove( elem, "fxshow" );
7370				for ( prop in orig ) {
7371					jQuery.style( elem, prop, orig[ prop ] );
7372				}
7373			} );
7374		}
7375
7376		// Per-property setup
7377		propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
7378		if ( !( prop in dataShow ) ) {
7379			dataShow[ prop ] = propTween.start;
7380			if ( hidden ) {
7381				propTween.end = propTween.start;
7382				propTween.start = 0;
7383			}
7384		}
7385	}
7386}
7387
7388function propFilter( props, specialEasing ) {
7389	var index, name, easing, value, hooks;
7390
7391	// camelCase, specialEasing and expand cssHook pass
7392	for ( index in props ) {
7393		name = camelCase( index );
7394		easing = specialEasing[ name ];
7395		value = props[ index ];
7396		if ( Array.isArray( value ) ) {
7397			easing = value[ 1 ];
7398			value = props[ index ] = value[ 0 ];
7399		}
7400
7401		if ( index !== name ) {
7402			props[ name ] = value;
7403			delete props[ index ];
7404		}
7405
7406		hooks = jQuery.cssHooks[ name ];
7407		if ( hooks && "expand" in hooks ) {
7408			value = hooks.expand( value );
7409			delete props[ name ];
7410
7411			// Not quite $.extend, this won't overwrite existing keys.
7412			// Reusing 'index' because we have the correct "name"
7413			for ( index in value ) {
7414				if ( !( index in props ) ) {
7415					props[ index ] = value[ index ];
7416					specialEasing[ index ] = easing;
7417				}
7418			}
7419		} else {
7420			specialEasing[ name ] = easing;
7421		}
7422	}
7423}
7424
7425function Animation( elem, properties, options ) {
7426	var result,
7427		stopped,
7428		index = 0,
7429		length = Animation.prefilters.length,
7430		deferred = jQuery.Deferred().always( function() {
7431
7432			// Don't match elem in the :animated selector
7433			delete tick.elem;
7434		} ),
7435		tick = function() {
7436			if ( stopped ) {
7437				return false;
7438			}
7439			var currentTime = fxNow || createFxNow(),
7440				remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
7441
vendor: 39,713 bytes, lines 7442-8992
7442				// Support: Android 2.3 only
7443				// Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (trac-12497)
7444				temp = remaining / animation.duration || 0,
7445				percent = 1 - temp,
7446				index = 0,
7447				length = animation.tweens.length;
7448
7449			for ( ; index < length; index++ ) {
7450				animation.tweens[ index ].run( percent );
7451			}
7452
7453			deferred.notifyWith( elem, [ animation, percent, remaining ] );
7454
7455			// If there's more to do, yield
7456			if ( percent < 1 && length ) {
7457				return remaining;
7458			}
7459
7460			// If this was an empty animation, synthesize a final progress notification
7461			if ( !length ) {
7462				deferred.notifyWith( elem, [ animation, 1, 0 ] );
7463			}
7464
7465			// Resolve the animation and report its conclusion
7466			deferred.resolveWith( elem, [ animation ] );
7467			return false;
7468		},
7469		animation = deferred.promise( {
7470			elem: elem,
7471			props: jQuery.extend( {}, properties ),
7472			opts: jQuery.extend( true, {
7473				specialEasing: {},
7474				easing: jQuery.easing._default
7475			}, options ),
7476			originalProperties: properties,
7477			originalOptions: options,
7478			startTime: fxNow || createFxNow(),
7479			duration: options.duration,
7480			tweens: [],
7481			createTween: function( prop, end ) {
7482				var tween = jQuery.Tween( elem, animation.opts, prop, end,
7483					animation.opts.specialEasing[ prop ] || animation.opts.easing );
7484				animation.tweens.push( tween );
7485				return tween;
7486			},
7487			stop: function( gotoEnd ) {
7488				var index = 0,
7489
7490					// If we are going to the end, we want to run all the tweens
7491					// otherwise we skip this part
7492					length = gotoEnd ? animation.tweens.length : 0;
7493				if ( stopped ) {
7494					return this;
7495				}
7496				stopped = true;
7497				for ( ; index < length; index++ ) {
7498					animation.tweens[ index ].run( 1 );
7499				}
7500
7501				// Resolve when we played the last frame; otherwise, reject
7502				if ( gotoEnd ) {
7503					deferred.notifyWith( elem, [ animation, 1, 0 ] );
7504					deferred.resolveWith( elem, [ animation, gotoEnd ] );
7505				} else {
7506					deferred.rejectWith( elem, [ animation, gotoEnd ] );
7507				}
7508				return this;
7509			}
7510		} ),
7511		props = animation.props;
7512
7513	propFilter( props, animation.opts.specialEasing );
7514
7515	for ( ; index < length; index++ ) {
7516		result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts );
7517		if ( result ) {
7518			if ( isFunction( result.stop ) ) {
7519				jQuery._queueHooks( animation.elem, animation.opts.queue ).stop =
7520					result.stop.bind( result );
7521			}
7522			return result;
7523		}
7524	}
7525
7526	jQuery.map( props, createTween, animation );
7527
7528	if ( isFunction( animation.opts.start ) ) {
7529		animation.opts.start.call( elem, animation );
7530	}
7531
7532	// Attach callbacks from options
7533	animation
7534		.progress( animation.opts.progress )
7535		.done( animation.opts.done, animation.opts.complete )
7536		.fail( animation.opts.fail )
7537		.always( animation.opts.always );
7538
7539	jQuery.fx.timer(
7540		jQuery.extend( tick, {
7541			elem: elem,
7542			anim: animation,
7543			queue: animation.opts.queue
7544		} )
7545	);
7546
7547	return animation;
7548}
7549
7550jQuery.Animation = jQuery.extend( Animation, {
7551
7552	tweeners: {
7553		"*": [ function( prop, value ) {
7554			var tween = this.createTween( prop, value );
7555			adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween );
7556			return tween;
7557		} ]
7558	},
7559
7560	tweener: function( props, callback ) {
7561		if ( isFunction( props ) ) {
7562			callback = props;
7563			props = [ "*" ];
7564		} else {
7565			props = props.match( rnothtmlwhite );
7566		}
7567
7568		var prop,
7569			index = 0,
7570			length = props.length;
7571
7572		for ( ; index < length; index++ ) {
7573			prop = props[ index ];
7574			Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || [];
7575			Animation.tweeners[ prop ].unshift( callback );
7576		}
7577	},
7578
7579	prefilters: [ defaultPrefilter ],
7580
7581	prefilter: function( callback, prepend ) {
7582		if ( prepend ) {
7583			Animation.prefilters.unshift( callback );
7584		} else {
7585			Animation.prefilters.push( callback );
7586		}
7587	}
7588} );
7589
7590jQuery.speed = function( speed, easing, fn ) {
7591	var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
7592		complete: fn || !fn && easing ||
7593			isFunction( speed ) && speed,
7594		duration: speed,
7595		easing: fn && easing || easing && !isFunction( easing ) && easing
7596	};
7597
7598	// Go to the end state if fx are off
7599	if ( jQuery.fx.off ) {
7600		opt.duration = 0;
7601
7602	} else {
7603		if ( typeof opt.duration !== "number" ) {
7604			if ( opt.duration in jQuery.fx.speeds ) {
7605				opt.duration = jQuery.fx.speeds[ opt.duration ];
7606
7607			} else {
7608				opt.duration = jQuery.fx.speeds._default;
7609			}
7610		}
7611	}
7612
7613	// Normalize opt.queue - true/undefined/null -> "fx"
7614	if ( opt.queue == null || opt.queue === true ) {
7615		opt.queue = "fx";
7616	}
7617
7618	// Queueing
7619	opt.old = opt.complete;
7620
7621	opt.complete = function() {
7622		if ( isFunction( opt.old ) ) {
7623			opt.old.call( this );
7624		}
7625
7626		if ( opt.queue ) {
7627			jQuery.dequeue( this, opt.queue );
7628		}
7629	};
7630
7631	return opt;
7632};
7633
7634jQuery.fn.extend( {
7635	fadeTo: function( speed, to, easing, callback ) {
7636
7637		// Show any hidden elements after setting opacity to 0
7638		return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show()
7639
7640			// Animate to the value specified
7641			.end().animate( { opacity: to }, speed, easing, callback );
7642	},
7643	animate: function( prop, speed, easing, callback ) {
7644		var empty = jQuery.isEmptyObject( prop ),
7645			optall = jQuery.speed( speed, easing, callback ),
7646			doAnimation = function() {
7647
7648				// Operate on a copy of prop so per-property easing won't be lost
7649				var anim = Animation( this, jQuery.extend( {}, prop ), optall );
7650
7651				// Empty animations, or finishing resolves immediately
7652				if ( empty || dataPriv.get( this, "finish" ) ) {
7653					anim.stop( true );
7654				}
7655			};
7656
7657		doAnimation.finish = doAnimation;
7658
7659		return empty || optall.queue === false ?
7660			this.each( doAnimation ) :
7661			this.queue( optall.queue, doAnimation );
7662	},
7663	stop: function( type, clearQueue, gotoEnd ) {
7664		var stopQueue = function( hooks ) {
7665			var stop = hooks.stop;
7666			delete hooks.stop;
7667			stop( gotoEnd );
7668		};
7669
7670		if ( typeof type !== "string" ) {
7671			gotoEnd = clearQueue;
7672			clearQueue = type;
7673			type = undefined;
7674		}
7675		if ( clearQueue ) {
7676			this.queue( type || "fx", [] );
7677		}
7678
7679		return this.each( function() {
7680			var dequeue = true,
7681				index = type != null && type + "queueHooks",
7682				timers = jQuery.timers,
7683				data = dataPriv.get( this );
7684
7685			if ( index ) {
7686				if ( data[ index ] && data[ index ].stop ) {
7687					stopQueue( data[ index ] );
7688				}
7689			} else {
7690				for ( index in data ) {
7691					if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
7692						stopQueue( data[ index ] );
7693					}
7694				}
7695			}
7696
7697			for ( index = timers.length; index--; ) {
7698				if ( timers[ index ].elem === this &&
7699					( type == null || timers[ index ].queue === type ) ) {
7700
7701					timers[ index ].anim.stop( gotoEnd );
7702					dequeue = false;
7703					timers.splice( index, 1 );
7704				}
7705			}
7706
7707			// Start the next in the queue if the last step wasn't forced.
7708			// Timers currently will call their complete callbacks, which
7709			// will dequeue but only if they were gotoEnd.
7710			if ( dequeue || !gotoEnd ) {
7711				jQuery.dequeue( this, type );
7712			}
7713		} );
7714	},
7715	finish: function( type ) {
7716		if ( type !== false ) {
7717			type = type || "fx";
7718		}
7719		return this.each( function() {
7720			var index,
7721				data = dataPriv.get( this ),
7722				queue = data[ type + "queue" ],
7723				hooks = data[ type + "queueHooks" ],
7724				timers = jQuery.timers,
7725				length = queue ? queue.length : 0;
7726
7727			// Enable finishing flag on private data
7728			data.finish = true;
7729
7730			// Empty the queue first
7731			jQuery.queue( this, type, [] );
7732
7733			if ( hooks && hooks.stop ) {
7734				hooks.stop.call( this, true );
7735			}
7736
7737			// Look for any active animations, and finish them
7738			for ( index = timers.length; index--; ) {
7739				if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
7740					timers[ index ].anim.stop( true );
7741					timers.splice( index, 1 );
7742				}
7743			}
7744
7745			// Look for any animations in the old queue and finish them
7746			for ( index = 0; index < length; index++ ) {
7747				if ( queue[ index ] && queue[ index ].finish ) {
7748					queue[ index ].finish.call( this );
7749				}
7750			}
7751
7752			// Turn off finishing flag
7753			delete data.finish;
7754		} );
7755	}
7756} );
7757
7758jQuery.each( [ "toggle", "show", "hide" ], function( _i, name ) {
7759	var cssFn = jQuery.fn[ name ];
7760	jQuery.fn[ name ] = function( speed, easing, callback ) {
7761		return speed == null || typeof speed === "boolean" ?
7762			cssFn.apply( this, arguments ) :
7763			this.animate( genFx( name, true ), speed, easing, callback );
7764	};
7765} );
7766
7767// Generate shortcuts for custom animations
7768jQuery.each( {
7769	slideDown: genFx( "show" ),
7770	slideUp: genFx( "hide" ),
7771	slideToggle: genFx( "toggle" ),
7772	fadeIn: { opacity: "show" },
7773	fadeOut: { opacity: "hide" },
7774	fadeToggle: { opacity: "toggle" }
7775}, function( name, props ) {
7776	jQuery.fn[ name ] = function( speed, easing, callback ) {
7777		return this.animate( props, speed, easing, callback );
7778	};
7779} );
7780
7781jQuery.timers = [];
7782jQuery.fx.tick = function() {
7783	var timer,
7784		i = 0,
7785		timers = jQuery.timers;
7786
7787	fxNow = Date.now();
7788
7789	for ( ; i < timers.length; i++ ) {
7790		timer = timers[ i ];
7791
7792		// Run the timer and safely remove it when done (allowing for external removal)
7793		if ( !timer() && timers[ i ] === timer ) {
7794			timers.splice( i--, 1 );
7795		}
7796	}
7797
7798	if ( !timers.length ) {
7799		jQuery.fx.stop();
7800	}
7801	fxNow = undefined;
7802};
7803
7804jQuery.fx.timer = function( timer ) {
7805	jQuery.timers.push( timer );
7806	jQuery.fx.start();
7807};
7808
7809jQuery.fx.interval = 13;
7810jQuery.fx.start = function() {
7811	if ( inProgress ) {
7812		return;
7813	}
7814
7815	inProgress = true;
7816	schedule();
7817};
7818
7819jQuery.fx.stop = function() {
7820	inProgress = null;
7821};
7822
7823jQuery.fx.speeds = {
7824	slow: 600,
7825	fast: 200,
7826
7827	// Default speed
7828	_default: 400
7829};
7830
7831
7832// Based off of the plugin by Clint Helfers, with permission.
7833jQuery.fn.delay = function( time, type ) {
7834	time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
7835	type = type || "fx";
7836
7837	return this.queue( type, function( next, hooks ) {
7838		var timeout = window.setTimeout( next, time );
7839		hooks.stop = function() {
7840			window.clearTimeout( timeout );
7841		};
7842	} );
7843};
7844
7845
7846( function() {
7847	var input = document.createElement( "input" ),
7848		select = document.createElement( "select" ),
7849		opt = select.appendChild( document.createElement( "option" ) );
7850
7851	input.type = "checkbox";
7852
7853	// Support: Android <=4.3 only
7854	// Default value for a checkbox should be "on"
7855	support.checkOn = input.value !== "";
7856
7857	// Support: IE <=11 only
7858	// Must access selectedIndex to make default options select
7859	support.optSelected = opt.selected;
7860
7861	// Support: IE <=11 only
7862	// An input loses its value after becoming a radio
7863	input = document.createElement( "input" );
7864	input.value = "t";
7865	input.type = "radio";
7866	support.radioValue = input.value === "t";
7867} )();
7868
7869
7870var boolHook,
7871	attrHandle = jQuery.expr.attrHandle;
7872
7873jQuery.fn.extend( {
7874	attr: function( name, value ) {
7875		return access( this, jQuery.attr, name, value, arguments.length > 1 );
7876	},
7877
7878	removeAttr: function( name ) {
7879		return this.each( function() {
7880			jQuery.removeAttr( this, name );
7881		} );
7882	}
7883} );
7884
7885jQuery.extend( {
7886	attr: function( elem, name, value ) {
7887		var ret, hooks,
7888			nType = elem.nodeType;
7889
7890		// Don't get/set attributes on text, comment and attribute nodes
7891		if ( nType === 3 || nType === 8 || nType === 2 ) {
7892			return;
7893		}
7894
7895		// Fallback to prop when attributes are not supported
7896		if ( typeof elem.getAttribute === "undefined" ) {
7897			return jQuery.prop( elem, name, value );
7898		}
7899
7900		// Attribute hooks are determined by the lowercase version
7901		// Grab necessary hook if one is defined
7902		if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
7903			hooks = jQuery.attrHooks[ name.toLowerCase() ] ||
7904				( jQuery.expr.match.bool.test( name ) ? boolHook : undefined );
7905		}
7906
7907		if ( value !== undefined ) {
7908			if ( value === null ) {
7909				jQuery.removeAttr( elem, name );
7910				return;
7911			}
7912
7913			if ( hooks && "set" in hooks &&
7914				( ret = hooks.set( elem, value, name ) ) !== undefined ) {
7915				return ret;
7916			}
7917
7918			elem.setAttribute( name, value + "" );
7919			return value;
7920		}
7921
7922		if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
7923			return ret;
7924		}
7925
7926		ret = jQuery.find.attr( elem, name );
7927
7928		// Non-existent attributes return null, we normalize to undefined
7929		return ret == null ? undefined : ret;
7930	},
7931
7932	attrHooks: {
7933		type: {
7934			set: function( elem, value ) {
7935				if ( !support.radioValue && value === "radio" &&
7936					nodeName( elem, "input" ) ) {
7937					var val = elem.value;
7938					elem.setAttribute( "type", value );
7939					if ( val ) {
7940						elem.value = val;
7941					}
7942					return value;
7943				}
7944			}
7945		}
7946	},
7947
7948	removeAttr: function( elem, value ) {
7949		var name,
7950			i = 0,
7951
7952			// Attribute names can contain non-HTML whitespace characters
7953			// https://html.spec.whatwg.org/multipage/syntax.html#attributes-2
7954			attrNames = value && value.match( rnothtmlwhite );
7955
7956		if ( attrNames && elem.nodeType === 1 ) {
7957			while ( ( name = attrNames[ i++ ] ) ) {
7958				elem.removeAttribute( name );
7959			}
7960		}
7961	}
7962} );
7963
7964// Hooks for boolean attributes
7965boolHook = {
7966	set: function( elem, value, name ) {
7967		if ( value === false ) {
7968
7969			// Remove boolean attributes when set to false
7970			jQuery.removeAttr( elem, name );
7971		} else {
7972			elem.setAttribute( name, name );
7973		}
7974		return name;
7975	}
7976};
7977
7978jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( _i, name ) {
7979	var getter = attrHandle[ name ] || jQuery.find.attr;
7980
7981	attrHandle[ name ] = function( elem, name, isXML ) {
7982		var ret, handle,
7983			lowercaseName = name.toLowerCase();
7984
7985		if ( !isXML ) {
7986
7987			// Avoid an infinite loop by temporarily removing this function from the getter
7988			handle = attrHandle[ lowercaseName ];
7989			attrHandle[ lowercaseName ] = ret;
7990			ret = getter( elem, name, isXML ) != null ?
7991				lowercaseName :
7992				null;
7993			attrHandle[ lowercaseName ] = handle;
7994		}
7995		return ret;
7996	};
7997} );
7998
7999
8000
8001
8002var rfocusable = /^(?:input|select|textarea|button)$/i,
8003	rclickable = /^(?:a|area)$/i;
8004
8005jQuery.fn.extend( {
8006	prop: function( name, value ) {
8007		return access( this, jQuery.prop, name, value, arguments.length > 1 );
8008	},
8009
8010	removeProp: function( name ) {
8011		return this.each( function() {
8012			delete this[ jQuery.propFix[ name ] || name ];
8013		} );
8014	}
8015} );
8016
8017jQuery.extend( {
8018	prop: function( elem, name, value ) {
8019		var ret, hooks,
8020			nType = elem.nodeType;
8021
8022		// Don't get/set properties on text, comment and attribute nodes
8023		if ( nType === 3 || nType === 8 || nType === 2 ) {
8024			return;
8025		}
8026
8027		if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
8028
8029			// Fix name and attach hooks
8030			name = jQuery.propFix[ name ] || name;
8031			hooks = jQuery.propHooks[ name ];
8032		}
8033
8034		if ( value !== undefined ) {
8035			if ( hooks && "set" in hooks &&
8036				( ret = hooks.set( elem, value, name ) ) !== undefined ) {
8037				return ret;
8038			}
8039
8040			return ( elem[ name ] = value );
8041		}
8042
8043		if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
8044			return ret;
8045		}
8046
8047		return elem[ name ];
8048	},
8049
8050	propHooks: {
8051		tabIndex: {
8052			get: function( elem ) {
8053
8054				// Support: IE <=9 - 11 only
8055				// elem.tabIndex doesn't always return the
8056				// correct value when it hasn't been explicitly set
8057				// Use proper attribute retrieval (trac-12072)
8058				var tabindex = jQuery.find.attr( elem, "tabindex" );
8059
8060				if ( tabindex ) {
8061					return parseInt( tabindex, 10 );
8062				}
8063
8064				if (
8065					rfocusable.test( elem.nodeName ) ||
8066					rclickable.test( elem.nodeName ) &&
8067					elem.href
8068				) {
8069					return 0;
8070				}
8071
8072				return -1;
8073			}
8074		}
8075	},
8076
8077	propFix: {
8078		"for": "htmlFor",
8079		"class": "className"
8080	}
8081} );
8082
8083// Support: IE <=11 only
8084// Accessing the selectedIndex property
8085// forces the browser to respect setting selected
8086// on the option
8087// The getter ensures a default option is selected
8088// when in an optgroup
8089// eslint rule "no-unused-expressions" is disabled for this code
8090// since it considers such accessions noop
8091if ( !support.optSelected ) {
8092	jQuery.propHooks.selected = {
8093		get: function( elem ) {
8094
8095			/* eslint no-unused-expressions: "off" */
8096
8097			var parent = elem.parentNode;
8098			if ( parent && parent.parentNode ) {
8099				parent.parentNode.selectedIndex;
8100			}
8101			return null;
8102		},
8103		set: function( elem ) {
8104
8105			/* eslint no-unused-expressions: "off" */
8106
8107			var parent = elem.parentNode;
8108			if ( parent ) {
8109				parent.selectedIndex;
8110
8111				if ( parent.parentNode ) {
8112					parent.parentNode.selectedIndex;
8113				}
8114			}
8115		}
8116	};
8117}
8118
8119jQuery.each( [
8120	"tabIndex",
8121	"readOnly",
8122	"maxLength",
8123	"cellSpacing",
8124	"cellPadding",
8125	"rowSpan",
8126	"colSpan",
8127	"useMap",
8128	"frameBorder",
8129	"contentEditable"
8130], function() {
8131	jQuery.propFix[ this.toLowerCase() ] = this;
8132} );
8133
8134
8135
8136
8137	// Strip and collapse whitespace according to HTML spec
8138	// https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace
8139	function stripAndCollapse( value ) {
8140		var tokens = value.match( rnothtmlwhite ) || [];
8141		return tokens.join( " " );
8142	}
8143
8144
8145function getClass( elem ) {
8146	return elem.getAttribute && elem.getAttribute( "class" ) || "";
8147}
8148
8149function classesToArray( value ) {
8150	if ( Array.isArray( value ) ) {
8151		return value;
8152	}
8153	if ( typeof value === "string" ) {
8154		return value.match( rnothtmlwhite ) || [];
8155	}
8156	return [];
8157}
8158
8159jQuery.fn.extend( {
8160	addClass: function( value ) {
8161		var classNames, cur, curValue, className, i, finalValue;
8162
8163		if ( isFunction( value ) ) {
8164			return this.each( function( j ) {
8165				jQuery( this ).addClass( value.call( this, j, getClass( this ) ) );
8166			} );
8167		}
8168
8169		classNames = classesToArray( value );
8170
8171		if ( classNames.length ) {
8172			return this.each( function() {
8173				curValue = getClass( this );
8174				cur = this.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " );
8175
8176				if ( cur ) {
8177					for ( i = 0; i < classNames.length; i++ ) {
8178						className = classNames[ i ];
8179						if ( cur.indexOf( " " + className + " " ) < 0 ) {
8180							cur += className + " ";
8181						}
8182					}
8183
8184					// Only assign if different to avoid unneeded rendering.
8185					finalValue = stripAndCollapse( cur );
8186					if ( curValue !== finalValue ) {
8187						this.setAttribute( "class", finalValue );
8188					}
8189				}
8190			} );
8191		}
8192
8193		return this;
8194	},
8195
8196	removeClass: function( value ) {
8197		var classNames, cur, curValue, className, i, finalValue;
8198
8199		if ( isFunction( value ) ) {
8200			return this.each( function( j ) {
8201				jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) );
8202			} );
8203		}
8204
8205		if ( !arguments.length ) {
8206			return this.attr( "class", "" );
8207		}
8208
8209		classNames = classesToArray( value );
8210
8211		if ( classNames.length ) {
8212			return this.each( function() {
8213				curValue = getClass( this );
8214
8215				// This expression is here for better compressibility (see addClass)
8216				cur = this.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " );
8217
8218				if ( cur ) {
8219					for ( i = 0; i < classNames.length; i++ ) {
8220						className = classNames[ i ];
8221
8222						// Remove *all* instances
8223						while ( cur.indexOf( " " + className + " " ) > -1 ) {
8224							cur = cur.replace( " " + className + " ", " " );
8225						}
8226					}
8227
8228					// Only assign if different to avoid unneeded rendering.
8229					finalValue = stripAndCollapse( cur );
8230					if ( curValue !== finalValue ) {
8231						this.setAttribute( "class", finalValue );
8232					}
8233				}
8234			} );
8235		}
8236
8237		return this;
8238	},
8239
8240	toggleClass: function( value, stateVal ) {
8241		var classNames, className, i, self,
8242			type = typeof value,
8243			isValidValue = type === "string" || Array.isArray( value );
8244
8245		if ( isFunction( value ) ) {
8246			return this.each( function( i ) {
8247				jQuery( this ).toggleClass(
8248					value.call( this, i, getClass( this ), stateVal ),
8249					stateVal
8250				);
8251			} );
8252		}
8253
8254		if ( typeof stateVal === "boolean" && isValidValue ) {
8255			return stateVal ? this.addClass( value ) : this.removeClass( value );
8256		}
8257
8258		classNames = classesToArray( value );
8259
8260		return this.each( function() {
8261			if ( isValidValue ) {
8262
8263				// Toggle individual class names
8264				self = jQuery( this );
8265
8266				for ( i = 0; i < classNames.length; i++ ) {
8267					className = classNames[ i ];
8268
8269					// Check each className given, space separated list
8270					if ( self.hasClass( className ) ) {
8271						self.removeClass( className );
8272					} else {
8273						self.addClass( className );
8274					}
8275				}
8276
8277			// Toggle whole class name
8278			} else if ( value === undefined || type === "boolean" ) {
8279				className = getClass( this );
8280				if ( className ) {
8281
8282					// Store className if set
8283					dataPriv.set( this, "__className__", className );
8284				}
8285
8286				// If the element has a class name or if we're passed `false`,
8287				// then remove the whole classname (if there was one, the above saved it).
8288				// Otherwise bring back whatever was previously saved (if anything),
8289				// falling back to the empty string if nothing was stored.
8290				if ( this.setAttribute ) {
8291					this.setAttribute( "class",
8292						className || value === false ?
8293							"" :
8294							dataPriv.get( this, "__className__" ) || ""
8295					);
8296				}
8297			}
8298		} );
8299	},
8300
8301	hasClass: function( selector ) {
8302		var className, elem,
8303			i = 0;
8304
8305		className = " " + selector + " ";
8306		while ( ( elem = this[ i++ ] ) ) {
8307			if ( elem.nodeType === 1 &&
8308				( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) {
8309				return true;
8310			}
8311		}
8312
8313		return false;
8314	}
8315} );
8316
8317
8318
8319
8320var rreturn = /\r/g;
8321
8322jQuery.fn.extend( {
8323	val: function( value ) {
8324		var hooks, ret, valueIsFunction,
8325			elem = this[ 0 ];
8326
8327		if ( !arguments.length ) {
8328			if ( elem ) {
8329				hooks = jQuery.valHooks[ elem.type ] ||
8330					jQuery.valHooks[ elem.nodeName.toLowerCase() ];
8331
8332				if ( hooks &&
8333					"get" in hooks &&
8334					( ret = hooks.get( elem, "value" ) ) !== undefined
8335				) {
8336					return ret;
8337				}
8338
8339				ret = elem.value;
8340
8341				// Handle most common string cases
8342				if ( typeof ret === "string" ) {
8343					return ret.replace( rreturn, "" );
8344				}
8345
8346				// Handle cases where value is null/undef or number
8347				return ret == null ? "" : ret;
8348			}
8349
8350			return;
8351		}
8352
8353		valueIsFunction = isFunction( value );
8354
8355		return this.each( function( i ) {
8356			var val;
8357
8358			if ( this.nodeType !== 1 ) {
8359				return;
8360			}
8361
8362			if ( valueIsFunction ) {
8363				val = value.call( this, i, jQuery( this ).val() );
8364			} else {
8365				val = value;
8366			}
8367
8368			// Treat null/undefined as ""; convert numbers to string
8369			if ( val == null ) {
8370				val = "";
8371
8372			} else if ( typeof val === "number" ) {
8373				val += "";
8374
8375			} else if ( Array.isArray( val ) ) {
8376				val = jQuery.map( val, function( value ) {
8377					return value == null ? "" : value + "";
8378				} );
8379			}
8380
8381			hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
8382
8383			// If set returns undefined, fall back to normal setting
8384			if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) {
8385				this.value = val;
8386			}
8387		} );
8388	}
8389} );
8390
8391jQuery.extend( {
8392	valHooks: {
8393		option: {
8394			get: function( elem ) {
8395
8396				var val = jQuery.find.attr( elem, "value" );
8397				return val != null ?
8398					val :
8399
8400					// Support: IE <=10 - 11 only
8401					// option.text throws exceptions (trac-14686, trac-14858)
8402					// Strip and collapse whitespace
8403					// https://html.spec.whatwg.org/#strip-and-collapse-whitespace
8404					stripAndCollapse( jQuery.text( elem ) );
8405			}
8406		},
8407		select: {
8408			get: function( elem ) {
8409				var value, option, i,
8410					options = elem.options,
8411					index = elem.selectedIndex,
8412					one = elem.type === "select-one",
8413					values = one ? null : [],
8414					max = one ? index + 1 : options.length;
8415
8416				if ( index < 0 ) {
8417					i = max;
8418
8419				} else {
8420					i = one ? index : 0;
8421				}
8422
8423				// Loop through all the selected options
8424				for ( ; i < max; i++ ) {
8425					option = options[ i ];
8426
8427					// Support: IE <=9 only
8428					// IE8-9 doesn't update selected after form reset (trac-2551)
8429					if ( ( option.selected || i === index ) &&
8430
8431							// Don't return options that are disabled or in a disabled optgroup
8432							!option.disabled &&
8433							( !option.parentNode.disabled ||
8434								!nodeName( option.parentNode, "optgroup" ) ) ) {
8435
8436						// Get the specific value for the option
8437						value = jQuery( option ).val();
8438
8439						// We don't need an array for one selects
8440						if ( one ) {
8441							return value;
8442						}
8443
8444						// Multi-Selects return an array
8445						values.push( value );
8446					}
8447				}
8448
8449				return values;
8450			},
8451
8452			set: function( elem, value ) {
8453				var optionSet, option,
8454					options = elem.options,
8455					values = jQuery.makeArray( value ),
8456					i = options.length;
8457
8458				while ( i-- ) {
8459					option = options[ i ];
8460
8461					/* eslint-disable no-cond-assign */
8462
8463					if ( option.selected =
8464						jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1
8465					) {
8466						optionSet = true;
8467					}
8468
8469					/* eslint-enable no-cond-assign */
8470				}
8471
8472				// Force browsers to behave consistently when non-matching value is set
8473				if ( !optionSet ) {
8474					elem.selectedIndex = -1;
8475				}
8476				return values;
8477			}
8478		}
8479	}
8480} );
8481
8482// Radios and checkboxes getter/setter
8483jQuery.each( [ "radio", "checkbox" ], function() {
8484	jQuery.valHooks[ this ] = {
8485		set: function( elem, value ) {
8486			if ( Array.isArray( value ) ) {
8487				return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 );
8488			}
8489		}
8490	};
8491	if ( !support.checkOn ) {
8492		jQuery.valHooks[ this ].get = function( elem ) {
8493			return elem.getAttribute( "value" ) === null ? "on" : elem.value;
8494		};
8495	}
8496} );
8497
8498
8499
8500
8501// Return jQuery for attributes-only inclusion
8502var location = window.location;
8503
8504var nonce = { guid: Date.now() };
8505
8506var rquery = ( /\?/ );
8507
8508
8509
8510// Cross-browser xml parsing
8511jQuery.parseXML = function( data ) {
8512	var xml, parserErrorElem;
8513	if ( !data || typeof data !== "string" ) {
8514		return null;
8515	}
8516
8517	// Support: IE 9 - 11 only
8518	// IE throws on parseFromString with invalid input.
8519	try {
8520		xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" );
8521	} catch ( e ) {}
8522
8523	parserErrorElem = xml && xml.getElementsByTagName( "parsererror" )[ 0 ];
8524	if ( !xml || parserErrorElem ) {
8525		jQuery.error( "Invalid XML: " + (
8526			parserErrorElem ?
8527				jQuery.map( parserErrorElem.childNodes, function( el ) {
8528					return el.textContent;
8529				} ).join( "\n" ) :
8530				data
8531		) );
8532	}
8533	return xml;
8534};
8535
8536
8537var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
8538	stopPropagationCallback = function( e ) {
8539		e.stopPropagation();
8540	};
8541
8542jQuery.extend( jQuery.event, {
8543
8544	trigger: function( event, data, elem, onlyHandlers ) {
8545
8546		var i, cur, tmp, bubbleType, ontype, handle, special, lastElement,
8547			eventPath = [ elem || document ],
8548			type = hasOwn.call( event, "type" ) ? event.type : event,
8549			namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : [];
8550
8551		cur = lastElement = tmp = elem = elem || document;
8552
8553		// Don't do events on text and comment nodes
8554		if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
8555			return;
8556		}
8557
8558		// focus/blur morphs to focusin/out; ensure we're not firing them right now
8559		if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
8560			return;
8561		}
8562
8563		if ( type.indexOf( "." ) > -1 ) {
8564
8565			// Namespaced trigger; create a regexp to match event type in handle()
8566			namespaces = type.split( "." );
8567			type = namespaces.shift();
8568			namespaces.sort();
8569		}
8570		ontype = type.indexOf( ":" ) < 0 && "on" + type;
8571
8572		// Caller can pass in a jQuery.Event object, Object, or just an event type string
8573		event = event[ jQuery.expando ] ?
8574			event :
8575			new jQuery.Event( type, typeof event === "object" && event );
8576
8577		// Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
8578		event.isTrigger = onlyHandlers ? 2 : 3;
8579		event.namespace = namespaces.join( "." );
8580		event.rnamespace = event.namespace ?
8581			new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) :
8582			null;
8583
8584		// Clean up the event in case it is being reused
8585		event.result = undefined;
8586		if ( !event.target ) {
8587			event.target = elem;
8588		}
8589
8590		// Clone any incoming data and prepend the event, creating the handler arg list
8591		data = data == null ?
8592			[ event ] :
8593			jQuery.makeArray( data, [ event ] );
8594
8595		// Allow special events to draw outside the lines
8596		special = jQuery.event.special[ type ] || {};
8597		if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
8598			return;
8599		}
8600
8601		// Determine event propagation path in advance, per W3C events spec (trac-9951)
8602		// Bubble up to document, then to window; watch for a global ownerDocument var (trac-9724)
8603		if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) {
8604
8605			bubbleType = special.delegateType || type;
8606			if ( !rfocusMorph.test( bubbleType + type ) ) {
8607				cur = cur.parentNode;
8608			}
8609			for ( ; cur; cur = cur.parentNode ) {
8610				eventPath.push( cur );
8611				tmp = cur;
8612			}
8613
8614			// Only add window if we got to document (e.g., not plain obj or detached DOM)
8615			if ( tmp === ( elem.ownerDocument || document ) ) {
8616				eventPath.push( tmp.defaultView || tmp.parentWindow || window );
8617			}
8618		}
8619
8620		// Fire handlers on the event path
8621		i = 0;
8622		while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) {
8623			lastElement = cur;
8624			event.type = i > 1 ?
8625				bubbleType :
8626				special.bindType || type;
8627
8628			// jQuery handler
8629			handle = ( dataPriv.get( cur, "events" ) || Object.create( null ) )[ event.type ] &&
8630				dataPriv.get( cur, "handle" );
8631			if ( handle ) {
8632				handle.apply( cur, data );
8633			}
8634
8635			// Native handler
8636			handle = ontype && cur[ ontype ];
8637			if ( handle && handle.apply && acceptData( cur ) ) {
8638				event.result = handle.apply( cur, data );
8639				if ( event.result === false ) {
8640					event.preventDefault();
8641				}
8642			}
8643		}
8644		event.type = type;
8645
8646		// If nobody prevented the default action, do it now
8647		if ( !onlyHandlers && !event.isDefaultPrevented() ) {
8648
8649			if ( ( !special._default ||
8650				special._default.apply( eventPath.pop(), data ) === false ) &&
8651				acceptData( elem ) ) {
8652
8653				// Call a native DOM method on the target with the same name as the event.
8654				// Don't do default actions on window, that's where global variables be (trac-6170)
8655				if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) {
8656
8657					// Don't re-trigger an onFOO event when we call its FOO() method
8658					tmp = elem[ ontype ];
8659
8660					if ( tmp ) {
8661						elem[ ontype ] = null;
8662					}
8663
8664					// Prevent re-triggering of the same event, since we already bubbled it above
8665					jQuery.event.triggered = type;
8666
8667					if ( event.isPropagationStopped() ) {
8668						lastElement.addEventListener( type, stopPropagationCallback );
8669					}
8670
8671					elem[ type ]();
8672
8673					if ( event.isPropagationStopped() ) {
8674						lastElement.removeEventListener( type, stopPropagationCallback );
8675					}
8676
8677					jQuery.event.triggered = undefined;
8678
8679					if ( tmp ) {
8680						elem[ ontype ] = tmp;
8681					}
8682				}
8683			}
8684		}
8685
8686		return event.result;
8687	},
8688
8689	// Piggyback on a donor event to simulate a different one
8690	// Used only for `focus(in | out)` events
8691	simulate: function( type, elem, event ) {
8692		var e = jQuery.extend(
8693			new jQuery.Event(),
8694			event,
8695			{
8696				type: type,
8697				isSimulated: true
8698			}
8699		);
8700
8701		jQuery.event.trigger( e, null, elem );
8702	}
8703
8704} );
8705
8706jQuery.fn.extend( {
8707
8708	trigger: function( type, data ) {
8709		return this.each( function() {
8710			jQuery.event.trigger( type, data, this );
8711		} );
8712	},
8713	triggerHandler: function( type, data ) {
8714		var elem = this[ 0 ];
8715		if ( elem ) {
8716			return jQuery.event.trigger( type, data, elem, true );
8717		}
8718	}
8719} );
8720
8721
8722var
8723	rbracket = /\[\]$/,
8724	rCRLF = /\r?\n/g,
8725	rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
8726	rsubmittable = /^(?:input|select|textarea|keygen)/i;
8727
8728function buildParams( prefix, obj, traditional, add ) {
8729	var name;
8730
8731	if ( Array.isArray( obj ) ) {
8732
8733		// Serialize array item.
8734		jQuery.each( obj, function( i, v ) {
8735			if ( traditional || rbracket.test( prefix ) ) {
8736
8737				// Treat each array item as a scalar.
8738				add( prefix, v );
8739
8740			} else {
8741
8742				// Item is non-scalar (array or object), encode its numeric index.
8743				buildParams(
8744					prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]",
8745					v,
8746					traditional,
8747					add
8748				);
8749			}
8750		} );
8751
8752	} else if ( !traditional && toType( obj ) === "object" ) {
8753
8754		// Serialize object item.
8755		for ( name in obj ) {
8756			buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
8757		}
8758
8759	} else {
8760
8761		// Serialize scalar item.
8762		add( prefix, obj );
8763	}
8764}
8765
8766// Serialize an array of form elements or a set of
8767// key/values into a query string
8768jQuery.param = function( a, traditional ) {
8769	var prefix,
8770		s = [],
8771		add = function( key, valueOrFunction ) {
8772
8773			// If value is a function, invoke it and use its return value
8774			var value = isFunction( valueOrFunction ) ?
8775				valueOrFunction() :
8776				valueOrFunction;
8777
8778			s[ s.length ] = encodeURIComponent( key ) + "=" +
8779				encodeURIComponent( value == null ? "" : value );
8780		};
8781
8782	if ( a == null ) {
8783		return "";
8784	}
8785
8786	// If an array was passed in, assume that it is an array of form elements.
8787	if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
8788
8789		// Serialize the form elements
8790		jQuery.each( a, function() {
8791			add( this.name, this.value );
8792		} );
8793
8794	} else {
8795
8796		// If traditional, encode the "old" way (the way 1.3.2 or older
8797		// did it), otherwise encode params recursively.
8798		for ( prefix in a ) {
8799			buildParams( prefix, a[ prefix ], traditional, add );
8800		}
8801	}
8802
8803	// Return the resulting serialization
8804	return s.join( "&" );
8805};
8806
8807jQuery.fn.extend( {
8808	serialize: function() {
8809		return jQuery.param( this.serializeArray() );
8810	},
8811	serializeArray: function() {
8812		return this.map( function() {
8813
8814			// Can add propHook for "elements" to filter or add form elements
8815			var elements = jQuery.prop( this, "elements" );
8816			return elements ? jQuery.makeArray( elements ) : this;
8817		} ).filter( function() {
8818			var type = this.type;
8819
8820			// Use .is( ":disabled" ) so that fieldset[disabled] works
8821			return this.name && !jQuery( this ).is( ":disabled" ) &&
8822				rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
8823				( this.checked || !rcheckableType.test( type ) );
8824		} ).map( function( _i, elem ) {
8825			var val = jQuery( this ).val();
8826
8827			if ( val == null ) {
8828				return null;
8829			}
8830
8831			if ( Array.isArray( val ) ) {
8832				return jQuery.map( val, function( val ) {
8833					return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
8834				} );
8835			}
8836
8837			return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
8838		} ).get();
8839	}
8840} );
8841
8842
8843var
8844	r20 = /%20/g,
8845	rhash = /#.*$/,
8846	rantiCache = /([?&])_=[^&]*/,
8847	rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg,
8848
8849	// trac-7653, trac-8125, trac-8152: local protocol detection
8850	rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
8851	rnoContent = /^(?:GET|HEAD)$/,
8852	rprotocol = /^\/\//,
8853
8854	/* Prefilters
8855	 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
8856	 * 2) These are called:
8857	 *    - BEFORE asking for a transport
8858	 *    - AFTER param serialization (s.data is a string if s.processData is true)
8859	 * 3) key is the dataType
8860	 * 4) the catchall symbol "*" can be used
8861	 * 5) execution will start with transport dataType and THEN continue down to "*" if needed
8862	 */
8863	prefilters = {},
8864
8865	/* Transports bindings
8866	 * 1) key is the dataType
8867	 * 2) the catchall symbol "*" can be used
8868	 * 3) selection will start with transport dataType and THEN go to "*" if needed
8869	 */
8870	transports = {},
8871
8872	// Avoid comment-prolog char sequence (trac-10098); must appease lint and evade compression
8873	allTypes = "*/".concat( "*" ),
8874
8875	// Anchor tag for parsing the document origin
8876	originAnchor = document.createElement( "a" );
8877
8878originAnchor.href = location.href;
8879
8880// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
8881function addToPrefiltersOrTransports( structure ) {
8882
8883	// dataTypeExpression is optional and defaults to "*"
8884	return function( dataTypeExpression, func ) {
8885
8886		if ( typeof dataTypeExpression !== "string" ) {
8887			func = dataTypeExpression;
8888			dataTypeExpression = "*";
8889		}
8890
8891		var dataType,
8892			i = 0,
8893			dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || [];
8894
8895		if ( isFunction( func ) ) {
8896
8897			// For each dataType in the dataTypeExpression
8898			while ( ( dataType = dataTypes[ i++ ] ) ) {
8899
8900				// Prepend if requested
8901				if ( dataType[ 0 ] === "+" ) {
8902					dataType = dataType.slice( 1 ) || "*";
8903					( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func );
8904
8905				// Otherwise append
8906				} else {
8907					( structure[ dataType ] = structure[ dataType ] || [] ).push( func );
8908				}
8909			}
8910		}
8911	};
8912}
8913
8914// Base inspection function for prefilters and transports
8915function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
8916
8917	var inspected = {},
8918		seekingTransport = ( structure === transports );
8919
8920	function inspect( dataType ) {
8921		var selected;
8922		inspected[ dataType ] = true;
8923		jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
8924			var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
8925			if ( typeof dataTypeOrTransport === "string" &&
8926				!seekingTransport && !inspected[ dataTypeOrTransport ] ) {
8927
8928				options.dataTypes.unshift( dataTypeOrTransport );
8929				inspect( dataTypeOrTransport );
8930				return false;
8931			} else if ( seekingTransport ) {
8932				return !( selected = dataTypeOrTransport );
8933			}
8934		} );
8935		return selected;
8936	}
8937
8938	return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
8939}
8940
8941// A special extend for ajax options
8942// that takes "flat" options (not to be deep extended)
8943// Fixes trac-9887
8944function ajaxExtend( target, src ) {
8945	var key, deep,
8946		flatOptions = jQuery.ajaxSettings.flatOptions || {};
8947
8948	for ( key in src ) {
8949		if ( src[ key ] !== undefined ) {
8950			( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
8951		}
8952	}
8953	if ( deep ) {
8954		jQuery.extend( true, target, deep );
8955	}
8956
8957	return target;
8958}
8959
8960/* Handles responses to an ajax request:
8961 * - finds the right dataType (mediates between content-type and expected dataType)
8962 * - returns the corresponding response
8963 */
8964function ajaxHandleResponses( s, jqXHR, responses ) {
8965
8966	var ct, type, finalDataType, firstDataType,
8967		contents = s.contents,
8968		dataTypes = s.dataTypes;
8969
8970	// Remove auto dataType and get content-type in the process
8971	while ( dataTypes[ 0 ] === "*" ) {
8972		dataTypes.shift();
8973		if ( ct === undefined ) {
8974			ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" );
8975		}
8976	}
8977
8978	// Check if we're dealing with a known content-type
8979	if ( ct ) {
8980		for ( type in contents ) {
8981			if ( contents[ type ] && contents[ type ].test( ct ) ) {
8982				dataTypes.unshift( type );
8983				break;
8984			}
8985		}
8986	}
8987
8988	// Check to see if we have a response for the expected dataType
8989	if ( dataTypes[ 0 ] in responses ) {
8990		finalDataType = dataTypes[ 0 ];
8991	} else {
8992
vendor: 9,527 bytes, lines 8993-9368
8993		// Try convertible dataTypes
8994		for ( type in responses ) {
8995			if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) {
8996				finalDataType = type;
8997				break;
8998			}
8999			if ( !firstDataType ) {
9000				firstDataType = type;
9001			}
9002		}
9003
9004		// Or just use first one
9005		finalDataType = finalDataType || firstDataType;
9006	}
9007
9008	// If we found a dataType
9009	// We add the dataType to the list if needed
9010	// and return the corresponding response
9011	if ( finalDataType ) {
9012		if ( finalDataType !== dataTypes[ 0 ] ) {
9013			dataTypes.unshift( finalDataType );
9014		}
9015		return responses[ finalDataType ];
9016	}
9017}
9018
9019/* Chain conversions given the request and the original response
9020 * Also sets the responseXXX fields on the jqXHR instance
9021 */
9022function ajaxConvert( s, response, jqXHR, isSuccess ) {
9023	var conv2, current, conv, tmp, prev,
9024		converters = {},
9025
9026		// Work with a copy of dataTypes in case we need to modify it for conversion
9027		dataTypes = s.dataTypes.slice();
9028
9029	// Create converters map with lowercased keys
9030	if ( dataTypes[ 1 ] ) {
9031		for ( conv in s.converters ) {
9032			converters[ conv.toLowerCase() ] = s.converters[ conv ];
9033		}
9034	}
9035
9036	current = dataTypes.shift();
9037
9038	// Convert to each sequential dataType
9039	while ( current ) {
9040
9041		if ( s.responseFields[ current ] ) {
9042			jqXHR[ s.responseFields[ current ] ] = response;
9043		}
9044
9045		// Apply the dataFilter if provided
9046		if ( !prev && isSuccess && s.dataFilter ) {
9047			response = s.dataFilter( response, s.dataType );
9048		}
9049
9050		prev = current;
9051		current = dataTypes.shift();
9052
9053		if ( current ) {
9054
9055			// There's only work to do if current dataType is non-auto
9056			if ( current === "*" ) {
9057
9058				current = prev;
9059
9060			// Convert response if prev dataType is non-auto and differs from current
9061			} else if ( prev !== "*" && prev !== current ) {
9062
9063				// Seek a direct converter
9064				conv = converters[ prev + " " + current ] || converters[ "* " + current ];
9065
9066				// If none found, seek a pair
9067				if ( !conv ) {
9068					for ( conv2 in converters ) {
9069
9070						// If conv2 outputs current
9071						tmp = conv2.split( " " );
9072						if ( tmp[ 1 ] === current ) {
9073
9074							// If prev can be converted to accepted input
9075							conv = converters[ prev + " " + tmp[ 0 ] ] ||
9076								converters[ "* " + tmp[ 0 ] ];
9077							if ( conv ) {
9078
9079								// Condense equivalence converters
9080								if ( conv === true ) {
9081									conv = converters[ conv2 ];
9082
9083								// Otherwise, insert the intermediate dataType
9084								} else if ( converters[ conv2 ] !== true ) {
9085									current = tmp[ 0 ];
9086									dataTypes.unshift( tmp[ 1 ] );
9087								}
9088								break;
9089							}
9090						}
9091					}
9092				}
9093
9094				// Apply converter (if not an equivalence)
9095				if ( conv !== true ) {
9096
9097					// Unless errors are allowed to bubble, catch and return them
9098					if ( conv && s.throws ) {
9099						response = conv( response );
9100					} else {
9101						try {
9102							response = conv( response );
9103						} catch ( e ) {
9104							return {
9105								state: "parsererror",
9106								error: conv ? e : "No conversion from " + prev + " to " + current
9107							};
9108						}
9109					}
9110				}
9111			}
9112		}
9113	}
9114
9115	return { state: "success", data: response };
9116}
9117
9118jQuery.extend( {
9119
9120	// Counter for holding the number of active queries
9121	active: 0,
9122
9123	// Last-Modified header cache for next request
9124	lastModified: {},
9125	etag: {},
9126
9127	ajaxSettings: {
9128		url: location.href,
9129		type: "GET",
9130		isLocal: rlocalProtocol.test( location.protocol ),
9131		global: true,
9132		processData: true,
9133		async: true,
9134		contentType: "application/x-www-form-urlencoded; charset=UTF-8",
9135
9136		/*
9137		timeout: 0,
9138		data: null,
9139		dataType: null,
9140		username: null,
9141		password: null,
9142		cache: null,
9143		throws: false,
9144		traditional: false,
9145		headers: {},
9146		*/
9147
9148		accepts: {
9149			"*": allTypes,
9150			text: "text/plain",
9151			html: "text/html",
9152			xml: "application/xml, text/xml",
9153			json: "application/json, text/javascript"
9154		},
9155
9156		contents: {
9157			xml: /\bxml\b/,
9158			html: /\bhtml/,
9159			json: /\bjson\b/
9160		},
9161
9162		responseFields: {
9163			xml: "responseXML",
9164			text: "responseText",
9165			json: "responseJSON"
9166		},
9167
9168		// Data converters
9169		// Keys separate source (or catchall "*") and destination types with a single space
9170		converters: {
9171
9172			// Convert anything to text
9173			"* text": String,
9174
9175			// Text to html (true = no transformation)
9176			"text html": true,
9177
9178			// Evaluate text as a json expression
9179			"text json": JSON.parse,
9180
9181			// Parse text as xml
9182			"text xml": jQuery.parseXML
9183		},
9184
9185		// For options that shouldn't be deep extended:
9186		// you can add your own custom options here if
9187		// and when you create one that shouldn't be
9188		// deep extended (see ajaxExtend)
9189		flatOptions: {
9190			url: true,
9191			context: true
9192		}
9193	},
9194
9195	// Creates a full fledged settings object into target
9196	// with both ajaxSettings and settings fields.
9197	// If target is omitted, writes into ajaxSettings.
9198	ajaxSetup: function( target, settings ) {
9199		return settings ?
9200
9201			// Building a settings object
9202			ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
9203
9204			// Extending ajaxSettings
9205			ajaxExtend( jQuery.ajaxSettings, target );
9206	},
9207
9208	ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
9209	ajaxTransport: addToPrefiltersOrTransports( transports ),
9210
9211	// Main method
9212	ajax: function( url, options ) {
9213
9214		// If url is an object, simulate pre-1.5 signature
9215		if ( typeof url === "object" ) {
9216			options = url;
9217			url = undefined;
9218		}
9219
9220		// Force options to be an object
9221		options = options || {};
9222
9223		var transport,
9224
9225			// URL without anti-cache param
9226			cacheURL,
9227
9228			// Response headers
9229			responseHeadersString,
9230			responseHeaders,
9231
9232			// timeout handle
9233			timeoutTimer,
9234
9235			// Url cleanup var
9236			urlAnchor,
9237
9238			// Request state (becomes false upon send and true upon completion)
9239			completed,
9240
9241			// To know if global events are to be dispatched
9242			fireGlobals,
9243
9244			// Loop variable
9245			i,
9246
9247			// uncached part of the url
9248			uncached,
9249
9250			// Create the final options object
9251			s = jQuery.ajaxSetup( {}, options ),
9252
9253			// Callbacks context
9254			callbackContext = s.context || s,
9255
9256			// Context for global events is callbackContext if it is a DOM node or jQuery collection
9257			globalEventContext = s.context &&
9258				( callbackContext.nodeType || callbackContext.jquery ) ?
9259				jQuery( callbackContext ) :
9260				jQuery.event,
9261
9262			// Deferreds
9263			deferred = jQuery.Deferred(),
9264			completeDeferred = jQuery.Callbacks( "once memory" ),
9265
9266			// Status-dependent callbacks
9267			statusCode = s.statusCode || {},
9268
9269			// Headers (they are sent all at once)
9270			requestHeaders = {},
9271			requestHeadersNames = {},
9272
9273			// Default abort message
9274			strAbort = "canceled",
9275
9276			// Fake xhr
9277			jqXHR = {
9278				readyState: 0,
9279
9280				// Builds headers hashtable if needed
9281				getResponseHeader: function( key ) {
9282					var match;
9283					if ( completed ) {
9284						if ( !responseHeaders ) {
9285							responseHeaders = {};
9286							while ( ( match = rheaders.exec( responseHeadersString ) ) ) {
9287								responseHeaders[ match[ 1 ].toLowerCase() + " " ] =
9288									( responseHeaders[ match[ 1 ].toLowerCase() + " " ] || [] )
9289										.concat( match[ 2 ] );
9290							}
9291						}
9292						match = responseHeaders[ key.toLowerCase() + " " ];
9293					}
9294					return match == null ? null : match.join( ", " );
9295				},
9296
9297				// Raw string
9298				getAllResponseHeaders: function() {
9299					return completed ? responseHeadersString : null;
9300				},
9301
9302				// Caches the header
9303				setRequestHeader: function( name, value ) {
9304					if ( completed == null ) {
9305						name = requestHeadersNames[ name.toLowerCase() ] =
9306							requestHeadersNames[ name.toLowerCase() ] || name;
9307						requestHeaders[ name ] = value;
9308					}
9309					return this;
9310				},
9311
9312				// Overrides response content-type header
9313				overrideMimeType: function( type ) {
9314					if ( completed == null ) {
9315						s.mimeType = type;
9316					}
9317					return this;
9318				},
9319
9320				// Status-dependent callbacks
9321				statusCode: function( map ) {
9322					var code;
9323					if ( map ) {
9324						if ( completed ) {
9325
9326							// Execute the appropriate callbacks
9327							jqXHR.always( map[ jqXHR.status ] );
9328						} else {
9329
9330							// Lazy-add the new callbacks in a way that preserves old ones
9331							for ( code in map ) {
9332								statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
9333							}
9334						}
9335					}
9336					return this;
9337				},
9338
9339				// Cancel the request
9340				abort: function( statusText ) {
9341					var finalText = statusText || strAbort;
9342					if ( transport ) {
9343						transport.abort( finalText );
9344					}
9345					done( 0, finalText );
9346					return this;
9347				}
9348			};
9349
9350		// Attach deferreds
9351		deferred.promise( jqXHR );
9352
9353		// Add protocol if not provided (prefilters might expect it)
9354		// Handle falsy url in the settings object (trac-10093: consistency with old signature)
9355		// We also use the url parameter if available
9356		s.url = ( ( url || s.url || location.href ) + "" )
9357			.replace( rprotocol, location.protocol + "//" );
9358
9359		// Alias method option to type as per ticket trac-12004
9360		s.type = options.method || options.type || s.method || s.type;
9361
9362		// Extract dataTypes list
9363		s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ];
9364
9365		// A cross-domain request is in order when the origin doesn't match the current origin.
9366		if ( s.crossDomain == null ) {
9367			urlAnchor = document.createElement( "a" );
9368
vendor: 37,628 bytes, lines 9369-10722
9369			// Support: IE <=8 - 11, Edge 12 - 15
9370			// IE throws exception on accessing the href property if url is malformed,
9371			// e.g. http://example.com:80x/
9372			try {
9373				urlAnchor.href = s.url;
9374
9375				// Support: IE <=8 - 11 only
9376				// Anchor's host property isn't correctly set when s.url is relative
9377				urlAnchor.href = urlAnchor.href;
9378				s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !==
9379					urlAnchor.protocol + "//" + urlAnchor.host;
9380			} catch ( e ) {
9381
9382				// If there is an error parsing the URL, assume it is crossDomain,
9383				// it can be rejected by the transport if it is invalid
9384				s.crossDomain = true;
9385			}
9386		}
9387
9388		// Convert data if not already a string
9389		if ( s.data && s.processData && typeof s.data !== "string" ) {
9390			s.data = jQuery.param( s.data, s.traditional );
9391		}
9392
9393		// Apply prefilters
9394		inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
9395
9396		// If request was aborted inside a prefilter, stop there
9397		if ( completed ) {
9398			return jqXHR;
9399		}
9400
9401		// We can fire global events as of now if asked to
9402		// Don't fire events if jQuery.event is undefined in an AMD-usage scenario (trac-15118)
9403		fireGlobals = jQuery.event && s.global;
9404
9405		// Watch for a new set of requests
9406		if ( fireGlobals && jQuery.active++ === 0 ) {
9407			jQuery.event.trigger( "ajaxStart" );
9408		}
9409
9410		// Uppercase the type
9411		s.type = s.type.toUpperCase();
9412
9413		// Determine if request has content
9414		s.hasContent = !rnoContent.test( s.type );
9415
9416		// Save the URL in case we're toying with the If-Modified-Since
9417		// and/or If-None-Match header later on
9418		// Remove hash to simplify url manipulation
9419		cacheURL = s.url.replace( rhash, "" );
9420
9421		// More options handling for requests with no content
9422		if ( !s.hasContent ) {
9423
9424			// Remember the hash so we can put it back
9425			uncached = s.url.slice( cacheURL.length );
9426
9427			// If data is available and should be processed, append data to url
9428			if ( s.data && ( s.processData || typeof s.data === "string" ) ) {
9429				cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data;
9430
9431				// trac-9682: remove data so that it's not used in an eventual retry
9432				delete s.data;
9433			}
9434
9435			// Add or update anti-cache param if needed
9436			if ( s.cache === false ) {
9437				cacheURL = cacheURL.replace( rantiCache, "$1" );
9438				uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce.guid++ ) +
9439					uncached;
9440			}
9441
9442			// Put hash and anti-cache on the URL that will be requested (gh-1732)
9443			s.url = cacheURL + uncached;
9444
9445		// Change '%20' to '+' if this is encoded form body content (gh-2658)
9446		} else if ( s.data && s.processData &&
9447			( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) {
9448			s.data = s.data.replace( r20, "+" );
9449		}
9450
9451		// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
9452		if ( s.ifModified ) {
9453			if ( jQuery.lastModified[ cacheURL ] ) {
9454				jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
9455			}
9456			if ( jQuery.etag[ cacheURL ] ) {
9457				jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
9458			}
9459		}
9460
9461		// Set the correct header, if data is being sent
9462		if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
9463			jqXHR.setRequestHeader( "Content-Type", s.contentType );
9464		}
9465
9466		// Set the Accepts header for the server, depending on the dataType
9467		jqXHR.setRequestHeader(
9468			"Accept",
9469			s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ?
9470				s.accepts[ s.dataTypes[ 0 ] ] +
9471					( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
9472				s.accepts[ "*" ]
9473		);
9474
9475		// Check for headers option
9476		for ( i in s.headers ) {
9477			jqXHR.setRequestHeader( i, s.headers[ i ] );
9478		}
9479
9480		// Allow custom headers/mimetypes and early abort
9481		if ( s.beforeSend &&
9482			( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) {
9483
9484			// Abort if not done already and return
9485			return jqXHR.abort();
9486		}
9487
9488		// Aborting is no longer a cancellation
9489		strAbort = "abort";
9490
9491		// Install callbacks on deferreds
9492		completeDeferred.add( s.complete );
9493		jqXHR.done( s.success );
9494		jqXHR.fail( s.error );
9495
9496		// Get transport
9497		transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
9498
9499		// If no transport, we auto-abort
9500		if ( !transport ) {
9501			done( -1, "No Transport" );
9502		} else {
9503			jqXHR.readyState = 1;
9504
9505			// Send global event
9506			if ( fireGlobals ) {
9507				globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
9508			}
9509
9510			// If request was aborted inside ajaxSend, stop there
9511			if ( completed ) {
9512				return jqXHR;
9513			}
9514
9515			// Timeout
9516			if ( s.async && s.timeout > 0 ) {
9517				timeoutTimer = window.setTimeout( function() {
9518					jqXHR.abort( "timeout" );
9519				}, s.timeout );
9520			}
9521
9522			try {
9523				completed = false;
9524				transport.send( requestHeaders, done );
9525			} catch ( e ) {
9526
9527				// Rethrow post-completion exceptions
9528				if ( completed ) {
9529					throw e;
9530				}
9531
9532				// Propagate others as results
9533				done( -1, e );
9534			}
9535		}
9536
9537		// Callback for when everything is done
9538		function done( status, nativeStatusText, responses, headers ) {
9539			var isSuccess, success, error, response, modified,
9540				statusText = nativeStatusText;
9541
9542			// Ignore repeat invocations
9543			if ( completed ) {
9544				return;
9545			}
9546
9547			completed = true;
9548
9549			// Clear timeout if it exists
9550			if ( timeoutTimer ) {
9551				window.clearTimeout( timeoutTimer );
9552			}
9553
9554			// Dereference transport for early garbage collection
9555			// (no matter how long the jqXHR object will be used)
9556			transport = undefined;
9557
9558			// Cache response headers
9559			responseHeadersString = headers || "";
9560
9561			// Set readyState
9562			jqXHR.readyState = status > 0 ? 4 : 0;
9563
9564			// Determine if successful
9565			isSuccess = status >= 200 && status < 300 || status === 304;
9566
9567			// Get response data
9568			if ( responses ) {
9569				response = ajaxHandleResponses( s, jqXHR, responses );
9570			}
9571
9572			// Use a noop converter for missing script but not if jsonp
9573			if ( !isSuccess &&
9574				jQuery.inArray( "script", s.dataTypes ) > -1 &&
9575				jQuery.inArray( "json", s.dataTypes ) < 0 ) {
9576				s.converters[ "text script" ] = function() {};
9577			}
9578
9579			// Convert no matter what (that way responseXXX fields are always set)
9580			response = ajaxConvert( s, response, jqXHR, isSuccess );
9581
9582			// If successful, handle type chaining
9583			if ( isSuccess ) {
9584
9585				// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
9586				if ( s.ifModified ) {
9587					modified = jqXHR.getResponseHeader( "Last-Modified" );
9588					if ( modified ) {
9589						jQuery.lastModified[ cacheURL ] = modified;
9590					}
9591					modified = jqXHR.getResponseHeader( "etag" );
9592					if ( modified ) {
9593						jQuery.etag[ cacheURL ] = modified;
9594					}
9595				}
9596
9597				// if no content
9598				if ( status === 204 || s.type === "HEAD" ) {
9599					statusText = "nocontent";
9600
9601				// if not modified
9602				} else if ( status === 304 ) {
9603					statusText = "notmodified";
9604
9605				// If we have data, let's convert it
9606				} else {
9607					statusText = response.state;
9608					success = response.data;
9609					error = response.error;
9610					isSuccess = !error;
9611				}
9612			} else {
9613
9614				// Extract error from statusText and normalize for non-aborts
9615				error = statusText;
9616				if ( status || !statusText ) {
9617					statusText = "error";
9618					if ( status < 0 ) {
9619						status = 0;
9620					}
9621				}
9622			}
9623
9624			// Set data for the fake xhr object
9625			jqXHR.status = status;
9626			jqXHR.statusText = ( nativeStatusText || statusText ) + "";
9627
9628			// Success/Error
9629			if ( isSuccess ) {
9630				deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
9631			} else {
9632				deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
9633			}
9634
9635			// Status-dependent callbacks
9636			jqXHR.statusCode( statusCode );
9637			statusCode = undefined;
9638
9639			if ( fireGlobals ) {
9640				globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
9641					[ jqXHR, s, isSuccess ? success : error ] );
9642			}
9643
9644			// Complete
9645			completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
9646
9647			if ( fireGlobals ) {
9648				globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
9649
9650				// Handle the global AJAX counter
9651				if ( !( --jQuery.active ) ) {
9652					jQuery.event.trigger( "ajaxStop" );
9653				}
9654			}
9655		}
9656
9657		return jqXHR;
9658	},
9659
9660	getJSON: function( url, data, callback ) {
9661		return jQuery.get( url, data, callback, "json" );
9662	},
9663
9664	getScript: function( url, callback ) {
9665		return jQuery.get( url, undefined, callback, "script" );
9666	}
9667} );
9668
9669jQuery.each( [ "get", "post" ], function( _i, method ) {
9670	jQuery[ method ] = function( url, data, callback, type ) {
9671
9672		// Shift arguments if data argument was omitted
9673		if ( isFunction( data ) ) {
9674			type = type || callback;
9675			callback = data;
9676			data = undefined;
9677		}
9678
9679		// The url can be an options object (which then must have .url)
9680		return jQuery.ajax( jQuery.extend( {
9681			url: url,
9682			type: method,
9683			dataType: type,
9684			data: data,
9685			success: callback
9686		}, jQuery.isPlainObject( url ) && url ) );
9687	};
9688} );
9689
9690jQuery.ajaxPrefilter( function( s ) {
9691	var i;
9692	for ( i in s.headers ) {
9693		if ( i.toLowerCase() === "content-type" ) {
9694			s.contentType = s.headers[ i ] || "";
9695		}
9696	}
9697} );
9698
9699
9700jQuery._evalUrl = function( url, options, doc ) {
9701	return jQuery.ajax( {
9702		url: url,
9703
9704		// Make this explicit, since user can override this through ajaxSetup (trac-11264)
9705		type: "GET",
9706		dataType: "script",
9707		cache: true,
9708		async: false,
9709		global: false,
9710
9711		// Only evaluate the response if it is successful (gh-4126)
9712		// dataFilter is not invoked for failure responses, so using it instead
9713		// of the default converter is kludgy but it works.
9714		converters: {
9715			"text script": function() {}
9716		},
9717		dataFilter: function( response ) {
9718			jQuery.globalEval( response, options, doc );
9719		}
9720	} );
9721};
9722
9723
9724jQuery.fn.extend( {
9725	wrapAll: function( html ) {
9726		var wrap;
9727
9728		if ( this[ 0 ] ) {
9729			if ( isFunction( html ) ) {
9730				html = html.call( this[ 0 ] );
9731			}
9732
9733			// The elements to wrap the target around
9734			wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );
9735
9736			if ( this[ 0 ].parentNode ) {
9737				wrap.insertBefore( this[ 0 ] );
9738			}
9739
9740			wrap.map( function() {
9741				var elem = this;
9742
9743				while ( elem.firstElementChild ) {
9744					elem = elem.firstElementChild;
9745				}
9746
9747				return elem;
9748			} ).append( this );
9749		}
9750
9751		return this;
9752	},
9753
9754	wrapInner: function( html ) {
9755		if ( isFunction( html ) ) {
9756			return this.each( function( i ) {
9757				jQuery( this ).wrapInner( html.call( this, i ) );
9758			} );
9759		}
9760
9761		return this.each( function() {
9762			var self = jQuery( this ),
9763				contents = self.contents();
9764
9765			if ( contents.length ) {
9766				contents.wrapAll( html );
9767
9768			} else {
9769				self.append( html );
9770			}
9771		} );
9772	},
9773
9774	wrap: function( html ) {
9775		var htmlIsFunction = isFunction( html );
9776
9777		return this.each( function( i ) {
9778			jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html );
9779		} );
9780	},
9781
9782	unwrap: function( selector ) {
9783		this.parent( selector ).not( "body" ).each( function() {
9784			jQuery( this ).replaceWith( this.childNodes );
9785		} );
9786		return this;
9787	}
9788} );
9789
9790
9791jQuery.expr.pseudos.hidden = function( elem ) {
9792	return !jQuery.expr.pseudos.visible( elem );
9793};
9794jQuery.expr.pseudos.visible = function( elem ) {
9795	return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length );
9796};
9797
9798
9799
9800
9801jQuery.ajaxSettings.xhr = function() {
9802	try {
9803		return new window.XMLHttpRequest();
9804	} catch ( e ) {}
9805};
9806
9807var xhrSuccessStatus = {
9808
9809		// File protocol always yields status code 0, assume 200
9810		0: 200,
9811
9812		// Support: IE <=9 only
9813		// trac-1450: sometimes IE returns 1223 when it should be 204
9814		1223: 204
9815	},
9816	xhrSupported = jQuery.ajaxSettings.xhr();
9817
9818support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
9819support.ajax = xhrSupported = !!xhrSupported;
9820
9821jQuery.ajaxTransport( function( options ) {
9822	var callback, errorCallback;
9823
9824	// Cross domain only allowed if supported through XMLHttpRequest
9825	if ( support.cors || xhrSupported && !options.crossDomain ) {
9826		return {
9827			send: function( headers, complete ) {
9828				var i,
9829					xhr = options.xhr();
9830
9831				xhr.open(
9832					options.type,
9833					options.url,
9834					options.async,
9835					options.username,
9836					options.password
9837				);
9838
9839				// Apply custom fields if provided
9840				if ( options.xhrFields ) {
9841					for ( i in options.xhrFields ) {
9842						xhr[ i ] = options.xhrFields[ i ];
9843					}
9844				}
9845
9846				// Override mime type if needed
9847				if ( options.mimeType && xhr.overrideMimeType ) {
9848					xhr.overrideMimeType( options.mimeType );
9849				}
9850
9851				// X-Requested-With header
9852				// For cross-domain requests, seeing as conditions for a preflight are
9853				// akin to a jigsaw puzzle, we simply never set it to be sure.
9854				// (it can always be set on a per-request basis or even using ajaxSetup)
9855				// For same-domain requests, won't change header if already provided.
9856				if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) {
9857					headers[ "X-Requested-With" ] = "XMLHttpRequest";
9858				}
9859
9860				// Set headers
9861				for ( i in headers ) {
9862					xhr.setRequestHeader( i, headers[ i ] );
9863				}
9864
9865				// Callback
9866				callback = function( type ) {
9867					return function() {
9868						if ( callback ) {
9869							callback = errorCallback = xhr.onload =
9870								xhr.onerror = xhr.onabort = xhr.ontimeout =
9871									xhr.onreadystatechange = null;
9872
9873							if ( type === "abort" ) {
9874								xhr.abort();
9875							} else if ( type === "error" ) {
9876
9877								// Support: IE <=9 only
9878								// On a manual native abort, IE9 throws
9879								// errors on any property access that is not readyState
9880								if ( typeof xhr.status !== "number" ) {
9881									complete( 0, "error" );
9882								} else {
9883									complete(
9884
9885										// File: protocol always yields status 0; see trac-8605, trac-14207
9886										xhr.status,
9887										xhr.statusText
9888									);
9889								}
9890							} else {
9891								complete(
9892									xhrSuccessStatus[ xhr.status ] || xhr.status,
9893									xhr.statusText,
9894
9895									// Support: IE <=9 only
9896									// IE9 has no XHR2 but throws on binary (trac-11426)
9897									// For XHR2 non-text, let the caller handle it (gh-2498)
9898									( xhr.responseType || "text" ) !== "text"  ||
9899									typeof xhr.responseText !== "string" ?
9900										{ binary: xhr.response } :
9901										{ text: xhr.responseText },
9902									xhr.getAllResponseHeaders()
9903								);
9904							}
9905						}
9906					};
9907				};
9908
9909				// Listen to events
9910				xhr.onload = callback();
9911				errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" );
9912
9913				// Support: IE 9 only
9914				// Use onreadystatechange to replace onabort
9915				// to handle uncaught aborts
9916				if ( xhr.onabort !== undefined ) {
9917					xhr.onabort = errorCallback;
9918				} else {
9919					xhr.onreadystatechange = function() {
9920
9921						// Check readyState before timeout as it changes
9922						if ( xhr.readyState === 4 ) {
9923
9924							// Allow onerror to be called first,
9925							// but that will not handle a native abort
9926							// Also, save errorCallback to a variable
9927							// as xhr.onerror cannot be accessed
9928							window.setTimeout( function() {
9929								if ( callback ) {
9930									errorCallback();
9931								}
9932							} );
9933						}
9934					};
9935				}
9936
9937				// Create the abort callback
9938				callback = callback( "abort" );
9939
9940				try {
9941
9942					// Do send the request (this may raise an exception)
9943					xhr.send( options.hasContent && options.data || null );
9944				} catch ( e ) {
9945
9946					// trac-14683: Only rethrow if this hasn't been notified as an error yet
9947					if ( callback ) {
9948						throw e;
9949					}
9950				}
9951			},
9952
9953			abort: function() {
9954				if ( callback ) {
9955					callback();
9956				}
9957			}
9958		};
9959	}
9960} );
9961
9962
9963
9964
9965// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432)
9966jQuery.ajaxPrefilter( function( s ) {
9967	if ( s.crossDomain ) {
9968		s.contents.script = false;
9969	}
9970} );
9971
9972// Install script dataType
9973jQuery.ajaxSetup( {
9974	accepts: {
9975		script: "text/javascript, application/javascript, " +
9976			"application/ecmascript, application/x-ecmascript"
9977	},
9978	contents: {
9979		script: /\b(?:java|ecma)script\b/
9980	},
9981	converters: {
9982		"text script": function( text ) {
9983			jQuery.globalEval( text );
9984			return text;
9985		}
9986	}
9987} );
9988
9989// Handle cache's special case and crossDomain
9990jQuery.ajaxPrefilter( "script", function( s ) {
9991	if ( s.cache === undefined ) {
9992		s.cache = false;
9993	}
9994	if ( s.crossDomain ) {
9995		s.type = "GET";
9996	}
9997} );
9998
9999// Bind script tag hack transport
10000jQuery.ajaxTransport( "script", function( s ) {
10001
10002	// This transport only deals with cross domain or forced-by-attrs requests
10003	if ( s.crossDomain || s.scriptAttrs ) {
10004		var script, callback;
10005		return {
10006			send: function( _, complete ) {
10007				script = jQuery( "<script>" )
10008					.attr( s.scriptAttrs || {} )
10009					.prop( { charset: s.scriptCharset, src: s.url } )
10010					.on( "load error", callback = function( evt ) {
10011						script.remove();
10012						callback = null;
10013						if ( evt ) {
10014							complete( evt.type === "error" ? 404 : 200, evt.type );
10015						}
10016					} );
10017
10018				// Use native DOM manipulation to avoid our domManip AJAX trickery
10019				document.head.appendChild( script[ 0 ] );
10020			},
10021			abort: function() {
10022				if ( callback ) {
10023					callback();
10024				}
10025			}
10026		};
10027	}
10028} );
10029
10030
10031
10032
10033var oldCallbacks = [],
10034	rjsonp = /(=)\?(?=&|$)|\?\?/;
10035
10036// Default jsonp settings
10037jQuery.ajaxSetup( {
10038	jsonp: "callback",
10039	jsonpCallback: function() {
10040		var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce.guid++ ) );
10041		this[ callback ] = true;
10042		return callback;
10043	}
10044} );
10045
10046// Detect, normalize options and install callbacks for jsonp requests
10047jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
10048
10049	var callbackName, overwritten, responseContainer,
10050		jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
10051			"url" :
10052			typeof s.data === "string" &&
10053				( s.contentType || "" )
10054					.indexOf( "application/x-www-form-urlencoded" ) === 0 &&
10055				rjsonp.test( s.data ) && "data"
10056		);
10057
10058	// Handle iff the expected data type is "jsonp" or we have a parameter to set
10059	if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
10060
10061		// Get callback name, remembering preexisting value associated with it
10062		callbackName = s.jsonpCallback = isFunction( s.jsonpCallback ) ?
10063			s.jsonpCallback() :
10064			s.jsonpCallback;
10065
10066		// Insert callback into url or form data
10067		if ( jsonProp ) {
10068			s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
10069		} else if ( s.jsonp !== false ) {
10070			s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
10071		}
10072
10073		// Use data converter to retrieve json after script execution
10074		s.converters[ "script json" ] = function() {
10075			if ( !responseContainer ) {
10076				jQuery.error( callbackName + " was not called" );
10077			}
10078			return responseContainer[ 0 ];
10079		};
10080
10081		// Force json dataType
10082		s.dataTypes[ 0 ] = "json";
10083
10084		// Install callback
10085		overwritten = window[ callbackName ];
10086		window[ callbackName ] = function() {
10087			responseContainer = arguments;
10088		};
10089
10090		// Clean-up function (fires after converters)
10091		jqXHR.always( function() {
10092
10093			// If previous value didn't exist - remove it
10094			if ( overwritten === undefined ) {
10095				jQuery( window ).removeProp( callbackName );
10096
10097			// Otherwise restore preexisting value
10098			} else {
10099				window[ callbackName ] = overwritten;
10100			}
10101
10102			// Save back as free
10103			if ( s[ callbackName ] ) {
10104
10105				// Make sure that re-using the options doesn't screw things around
10106				s.jsonpCallback = originalSettings.jsonpCallback;
10107
10108				// Save the callback name for future use
10109				oldCallbacks.push( callbackName );
10110			}
10111
10112			// Call if it was a function and we have a response
10113			if ( responseContainer && isFunction( overwritten ) ) {
10114				overwritten( responseContainer[ 0 ] );
10115			}
10116
10117			responseContainer = overwritten = undefined;
10118		} );
10119
10120		// Delegate to script
10121		return "script";
10122	}
10123} );
10124
10125
10126
10127
10128// Support: Safari 8 only
10129// In Safari 8 documents created via document.implementation.createHTMLDocument
10130// collapse sibling forms: the second one becomes a child of the first one.
10131// Because of that, this security measure has to be disabled in Safari 8.
10132// https://bugs.webkit.org/show_bug.cgi?id=137337
10133support.createHTMLDocument = ( function() {
10134	var body = document.implementation.createHTMLDocument( "" ).body;
10135	body.innerHTML = "<form></form><form></form>";
10136	return body.childNodes.length === 2;
10137} )();
10138
10139
10140// Argument "data" should be string of html
10141// context (optional): If specified, the fragment will be created in this context,
10142// defaults to document
10143// keepScripts (optional): If true, will include scripts passed in the html string
10144jQuery.parseHTML = function( data, context, keepScripts ) {
10145	if ( typeof data !== "string" ) {
10146		return [];
10147	}
10148	if ( typeof context === "boolean" ) {
10149		keepScripts = context;
10150		context = false;
10151	}
10152
10153	var base, parsed, scripts;
10154
10155	if ( !context ) {
10156
10157		// Stop scripts or inline event handlers from being executed immediately
10158		// by using document.implementation
10159		if ( support.createHTMLDocument ) {
10160			context = document.implementation.createHTMLDocument( "" );
10161
10162			// Set the base href for the created document
10163			// so any parsed elements with URLs
10164			// are based on the document's URL (gh-2965)
10165			base = context.createElement( "base" );
10166			base.href = document.location.href;
10167			context.head.appendChild( base );
10168		} else {
10169			context = document;
10170		}
10171	}
10172
10173	parsed = rsingleTag.exec( data );
10174	scripts = !keepScripts && [];
10175
10176	// Single tag
10177	if ( parsed ) {
10178		return [ context.createElement( parsed[ 1 ] ) ];
10179	}
10180
10181	parsed = buildFragment( [ data ], context, scripts );
10182
10183	if ( scripts && scripts.length ) {
10184		jQuery( scripts ).remove();
10185	}
10186
10187	return jQuery.merge( [], parsed.childNodes );
10188};
10189
10190
10191/**
10192 * Load a url into a page
10193 */
10194jQuery.fn.load = function( url, params, callback ) {
10195	var selector, type, response,
10196		self = this,
10197		off = url.indexOf( " " );
10198
10199	if ( off > -1 ) {
10200		selector = stripAndCollapse( url.slice( off ) );
10201		url = url.slice( 0, off );
10202	}
10203
10204	// If it's a function
10205	if ( isFunction( params ) ) {
10206
10207		// We assume that it's the callback
10208		callback = params;
10209		params = undefined;
10210
10211	// Otherwise, build a param string
10212	} else if ( params && typeof params === "object" ) {
10213		type = "POST";
10214	}
10215
10216	// If we have elements to modify, make the request
10217	if ( self.length > 0 ) {
10218		jQuery.ajax( {
10219			url: url,
10220
10221			// If "type" variable is undefined, then "GET" method will be used.
10222			// Make value of this field explicit since
10223			// user can override it through ajaxSetup method
10224			type: type || "GET",
10225			dataType: "html",
10226			data: params
10227		} ).done( function( responseText ) {
10228
10229			// Save response for use in complete callback
10230			response = arguments;
10231
10232			self.html( selector ?
10233
10234				// If a selector was specified, locate the right elements in a dummy div
10235				// Exclude scripts to avoid IE 'Permission Denied' errors
10236				jQuery( "<div>" ).append( jQuery.parseHTML( responseText ) ).find( selector ) :
10237
10238				// Otherwise use the full result
10239				responseText );
10240
10241		// If the request succeeds, this function gets "data", "status", "jqXHR"
10242		// but they are ignored because response was set above.
10243		// If it fails, this function gets "jqXHR", "status", "error"
10244		} ).always( callback && function( jqXHR, status ) {
10245			self.each( function() {
10246				callback.apply( this, response || [ jqXHR.responseText, status, jqXHR ] );
10247			} );
10248		} );
10249	}
10250
10251	return this;
10252};
10253
10254
10255
10256
10257jQuery.expr.pseudos.animated = function( elem ) {
10258	return jQuery.grep( jQuery.timers, function( fn ) {
10259		return elem === fn.elem;
10260	} ).length;
10261};
10262
10263
10264
10265
10266jQuery.offset = {
10267	setOffset: function( elem, options, i ) {
10268		var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
10269			position = jQuery.css( elem, "position" ),
10270			curElem = jQuery( elem ),
10271			props = {};
10272
10273		// Set position first, in-case top/left are set even on static elem
10274		if ( position === "static" ) {
10275			elem.style.position = "relative";
10276		}
10277
10278		curOffset = curElem.offset();
10279		curCSSTop = jQuery.css( elem, "top" );
10280		curCSSLeft = jQuery.css( elem, "left" );
10281		calculatePosition = ( position === "absolute" || position === "fixed" ) &&
10282			( curCSSTop + curCSSLeft ).indexOf( "auto" ) > -1;
10283
10284		// Need to be able to calculate position if either
10285		// top or left is auto and position is either absolute or fixed
10286		if ( calculatePosition ) {
10287			curPosition = curElem.position();
10288			curTop = curPosition.top;
10289			curLeft = curPosition.left;
10290
10291		} else {
10292			curTop = parseFloat( curCSSTop ) || 0;
10293			curLeft = parseFloat( curCSSLeft ) || 0;
10294		}
10295
10296		if ( isFunction( options ) ) {
10297
10298			// Use jQuery.extend here to allow modification of coordinates argument (gh-1848)
10299			options = options.call( elem, i, jQuery.extend( {}, curOffset ) );
10300		}
10301
10302		if ( options.top != null ) {
10303			props.top = ( options.top - curOffset.top ) + curTop;
10304		}
10305		if ( options.left != null ) {
10306			props.left = ( options.left - curOffset.left ) + curLeft;
10307		}
10308
10309		if ( "using" in options ) {
10310			options.using.call( elem, props );
10311
10312		} else {
10313			curElem.css( props );
10314		}
10315	}
10316};
10317
10318jQuery.fn.extend( {
10319
10320	// offset() relates an element's border box to the document origin
10321	offset: function( options ) {
10322
10323		// Preserve chaining for setter
10324		if ( arguments.length ) {
10325			return options === undefined ?
10326				this :
10327				this.each( function( i ) {
10328					jQuery.offset.setOffset( this, options, i );
10329				} );
10330		}
10331
10332		var rect, win,
10333			elem = this[ 0 ];
10334
10335		if ( !elem ) {
10336			return;
10337		}
10338
10339		// Return zeros for disconnected and hidden (display: none) elements (gh-2310)
10340		// Support: IE <=11 only
10341		// Running getBoundingClientRect on a
10342		// disconnected node in IE throws an error
10343		if ( !elem.getClientRects().length ) {
10344			return { top: 0, left: 0 };
10345		}
10346
10347		// Get document-relative position by adding viewport scroll to viewport-relative gBCR
10348		rect = elem.getBoundingClientRect();
10349		win = elem.ownerDocument.defaultView;
10350		return {
10351			top: rect.top + win.pageYOffset,
10352			left: rect.left + win.pageXOffset
10353		};
10354	},
10355
10356	// position() relates an element's margin box to its offset parent's padding box
10357	// This corresponds to the behavior of CSS absolute positioning
10358	position: function() {
10359		if ( !this[ 0 ] ) {
10360			return;
10361		}
10362
10363		var offsetParent, offset, doc,
10364			elem = this[ 0 ],
10365			parentOffset = { top: 0, left: 0 };
10366
10367		// position:fixed elements are offset from the viewport, which itself always has zero offset
10368		if ( jQuery.css( elem, "position" ) === "fixed" ) {
10369
10370			// Assume position:fixed implies availability of getBoundingClientRect
10371			offset = elem.getBoundingClientRect();
10372
10373		} else {
10374			offset = this.offset();
10375
10376			// Account for the *real* offset parent, which can be the document or its root element
10377			// when a statically positioned element is identified
10378			doc = elem.ownerDocument;
10379			offsetParent = elem.offsetParent || doc.documentElement;
10380			while ( offsetParent &&
10381				( offsetParent === doc.body || offsetParent === doc.documentElement ) &&
10382				jQuery.css( offsetParent, "position" ) === "static" ) {
10383
10384				offsetParent = offsetParent.parentNode;
10385			}
10386			if ( offsetParent && offsetParent !== elem && offsetParent.nodeType === 1 ) {
10387
10388				// Incorporate borders into its offset, since they are outside its content origin
10389				parentOffset = jQuery( offsetParent ).offset();
10390				parentOffset.top += jQuery.css( offsetParent, "borderTopWidth", true );
10391				parentOffset.left += jQuery.css( offsetParent, "borderLeftWidth", true );
10392			}
10393		}
10394
10395		// Subtract parent offsets and element margins
10396		return {
10397			top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
10398			left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true )
10399		};
10400	},
10401
10402	// This method will return documentElement in the following cases:
10403	// 1) For the element inside the iframe without offsetParent, this method will return
10404	//    documentElement of the parent window
10405	// 2) For the hidden or detached element
10406	// 3) For body or html element, i.e. in case of the html node - it will return itself
10407	//
10408	// but those exceptions were never presented as a real life use-cases
10409	// and might be considered as more preferable results.
10410	//
10411	// This logic, however, is not guaranteed and can change at any point in the future
10412	offsetParent: function() {
10413		return this.map( function() {
10414			var offsetParent = this.offsetParent;
10415
10416			while ( offsetParent && jQuery.css( offsetParent, "position" ) === "static" ) {
10417				offsetParent = offsetParent.offsetParent;
10418			}
10419
10420			return offsetParent || documentElement;
10421		} );
10422	}
10423} );
10424
10425// Create scrollLeft and scrollTop methods
10426jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
10427	var top = "pageYOffset" === prop;
10428
10429	jQuery.fn[ method ] = function( val ) {
10430		return access( this, function( elem, method, val ) {
10431
10432			// Coalesce documents and windows
10433			var win;
10434			if ( isWindow( elem ) ) {
10435				win = elem;
10436			} else if ( elem.nodeType === 9 ) {
10437				win = elem.defaultView;
10438			}
10439
10440			if ( val === undefined ) {
10441				return win ? win[ prop ] : elem[ method ];
10442			}
10443
10444			if ( win ) {
10445				win.scrollTo(
10446					!top ? val : win.pageXOffset,
10447					top ? val : win.pageYOffset
10448				);
10449
10450			} else {
10451				elem[ method ] = val;
10452			}
10453		}, method, val, arguments.length );
10454	};
10455} );
10456
10457// Support: Safari <=7 - 9.1, Chrome <=37 - 49
10458// Add the top/left cssHooks using jQuery.fn.position
10459// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
10460// Blink bug: https://bugs.chromium.org/p/chromium/issues/detail?id=589347
10461// getComputedStyle returns percent when specified for top/left/bottom/right;
10462// rather than make the css module depend on the offset module, just check for it here
10463jQuery.each( [ "top", "left" ], function( _i, prop ) {
10464	jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
10465		function( elem, computed ) {
10466			if ( computed ) {
10467				computed = curCSS( elem, prop );
10468
10469				// If curCSS returns percentage, fallback to offset
10470				return rnumnonpx.test( computed ) ?
10471					jQuery( elem ).position()[ prop ] + "px" :
10472					computed;
10473			}
10474		}
10475	);
10476} );
10477
10478
10479// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
10480jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
10481	jQuery.each( {
10482		padding: "inner" + name,
10483		content: type,
10484		"": "outer" + name
10485	}, function( defaultExtra, funcName ) {
10486
10487		// Margin is only for outerHeight, outerWidth
10488		jQuery.fn[ funcName ] = function( margin, value ) {
10489			var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
10490				extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
10491
10492			return access( this, function( elem, type, value ) {
10493				var doc;
10494
10495				if ( isWindow( elem ) ) {
10496
10497					// $( window ).outerWidth/Height return w/h including scrollbars (gh-1729)
10498					return funcName.indexOf( "outer" ) === 0 ?
10499						elem[ "inner" + name ] :
10500						elem.document.documentElement[ "client" + name ];
10501				}
10502
10503				// Get document width or height
10504				if ( elem.nodeType === 9 ) {
10505					doc = elem.documentElement;
10506
10507					// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],
10508					// whichever is greatest
10509					return Math.max(
10510						elem.body[ "scroll" + name ], doc[ "scroll" + name ],
10511						elem.body[ "offset" + name ], doc[ "offset" + name ],
10512						doc[ "client" + name ]
10513					);
10514				}
10515
10516				return value === undefined ?
10517
10518					// Get width or height on the element, requesting but not forcing parseFloat
10519					jQuery.css( elem, type, extra ) :
10520
10521					// Set width or height on the element
10522					jQuery.style( elem, type, value, extra );
10523			}, type, chainable ? margin : undefined, chainable );
10524		};
10525	} );
10526} );
10527
10528
10529jQuery.each( [
10530	"ajaxStart",
10531	"ajaxStop",
10532	"ajaxComplete",
10533	"ajaxError",
10534	"ajaxSuccess",
10535	"ajaxSend"
10536], function( _i, type ) {
10537	jQuery.fn[ type ] = function( fn ) {
10538		return this.on( type, fn );
10539	};
10540} );
10541
10542
10543
10544
10545jQuery.fn.extend( {
10546
10547	bind: function( types, data, fn ) {
10548		return this.on( types, null, data, fn );
10549	},
10550	unbind: function( types, fn ) {
10551		return this.off( types, null, fn );
10552	},
10553
10554	delegate: function( selector, types, data, fn ) {
10555		return this.on( types, selector, data, fn );
10556	},
10557	undelegate: function( selector, types, fn ) {
10558
10559		// ( namespace ) or ( selector, types [, fn] )
10560		return arguments.length === 1 ?
10561			this.off( selector, "**" ) :
10562			this.off( types, selector || "**", fn );
10563	},
10564
10565	hover: function( fnOver, fnOut ) {
10566		return this
10567			.on( "mouseenter", fnOver )
10568			.on( "mouseleave", fnOut || fnOver );
10569	}
10570} );
10571
10572jQuery.each(
10573	( "blur focus focusin focusout resize scroll click dblclick " +
10574	"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
10575	"change select submit keydown keypress keyup contextmenu" ).split( " " ),
10576	function( _i, name ) {
10577
10578		// Handle event binding
10579		jQuery.fn[ name ] = function( data, fn ) {
10580			return arguments.length > 0 ?
10581				this.on( name, null, data, fn ) :
10582				this.trigger( name );
10583		};
10584	}
10585);
10586
10587
10588
10589
10590// Support: Android <=4.0 only
10591// Make sure we trim BOM and NBSP
10592// Require that the "whitespace run" starts from a non-whitespace
10593// to avoid O(N^2) behavior when the engine would try matching "\s+$" at each space position.
10594var rtrim = /^[\s\uFEFF\xA0]+|([^\s\uFEFF\xA0])[\s\uFEFF\xA0]+$/g;
10595
10596// Bind a function to a context, optionally partially applying any
10597// arguments.
10598// jQuery.proxy is deprecated to promote standards (specifically Function#bind)
10599// However, it is not slated for removal any time soon
10600jQuery.proxy = function( fn, context ) {
10601	var tmp, args, proxy;
10602
10603	if ( typeof context === "string" ) {
10604		tmp = fn[ context ];
10605		context = fn;
10606		fn = tmp;
10607	}
10608
10609	// Quick check to determine if target is callable, in the spec
10610	// this throws a TypeError, but we will just return undefined.
10611	if ( !isFunction( fn ) ) {
10612		return undefined;
10613	}
10614
10615	// Simulated bind
10616	args = slice.call( arguments, 2 );
10617	proxy = function() {
10618		return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
10619	};
10620
10621	// Set the guid of unique handler to the same of original handler, so it can be removed
10622	proxy.guid = fn.guid = fn.guid || jQuery.guid++;
10623
10624	return proxy;
10625};
10626
10627jQuery.holdReady = function( hold ) {
10628	if ( hold ) {
10629		jQuery.readyWait++;
10630	} else {
10631		jQuery.ready( true );
10632	}
10633};
10634jQuery.isArray = Array.isArray;
10635jQuery.parseJSON = JSON.parse;
10636jQuery.nodeName = nodeName;
10637jQuery.isFunction = isFunction;
10638jQuery.isWindow = isWindow;
10639jQuery.camelCase = camelCase;
10640jQuery.type = toType;
10641
10642jQuery.now = Date.now;
10643
10644jQuery.isNumeric = function( obj ) {
10645
10646	// As of jQuery 3.0, isNumeric is limited to
10647	// strings and numbers (primitives or objects)
10648	// that can be coerced to finite numbers (gh-2662)
10649	var type = jQuery.type( obj );
10650	return ( type === "number" || type === "string" ) &&
10651
10652		// parseFloat NaNs numeric-cast false positives ("")
10653		// ...but misinterprets leading-number strings, particularly hex literals ("0x...")
10654		// subtraction forces infinities to NaN
10655		!isNaN( obj - parseFloat( obj ) );
10656};
10657
10658jQuery.trim = function( text ) {
10659	return text == null ?
10660		"" :
10661		( text + "" ).replace( rtrim, "$1" );
10662};
10663
10664
10665
10666// Register as a named AMD module, since jQuery can be concatenated with other
10667// files that may use define, but not via a proper concatenation script that
10668// understands anonymous AMD modules. A named AMD is safest and most robust
10669// way to register. Lowercase jquery is used because AMD module names are
10670// derived from file names, and jQuery is normally delivered in a lowercase
10671// file name. Do this after creating the global so that if an AMD module wants
10672// to call noConflict to hide this version of jQuery, it will work.
10673
10674// Note that for maximum portability, libraries that are not jQuery should
10675// declare themselves as anonymous modules, and avoid setting a global if an
10676// AMD loader is present. jQuery is a special case. For more information, see
10677// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon
10678
10679if ( typeof define === "function" && define.amd ) {
10680	define( "jquery", [], function() {
10681		return jQuery;
10682	} );
10683}
10684
10685
10686
10687
10688var
10689
10690	// Map over jQuery in case of overwrite
10691	_jQuery = window.jQuery,
10692
10693	// Map over the $ in case of overwrite
10694	_$ = window.$;
10695
10696jQuery.noConflict = function( deep ) {
10697	if ( window.$ === jQuery ) {
10698		window.$ = _$;
10699	}
10700
10701	if ( deep && window.jQuery === jQuery ) {
10702		window.jQuery = _jQuery;
10703	}
10704
10705	return jQuery;
10706};
10707
10708// Expose jQuery and $ identifiers, even in AMD
10709// (trac-7102#comment:10, https://github.com/jquery/jquery/pull/557)
10710// and CommonJS for browser emulators (trac-13566)
10711if ( typeof noGlobal === "undefined" ) {
10712	window.jQuery = window.$ = jQuery;
10713}
10714
10715
10716
10717
10718return jQuery;
10719} );
10720;
10721/*! jQuery UI - v1.14.1 - 2024-10-30
10722* https://jqueryui.com
vendor: 498,311 bytes, lines 10723-27993
10723* Includes: widget.js, position.js, data.js, disable-selection.js, effect.js, effects/effect-blind.js, effects/effect-bounce.js, effects/effect-clip.js, effects/effect-drop.js, effects/effect-explode.js, effects/effect-fade.js, effects/effect-fold.js, effects/effect-highlight.js, effects/effect-puff.js, effects/effect-pulsate.js, effects/effect-scale.js, effects/effect-shake.js, effects/effect-size.js, effects/effect-slide.js, effects/effect-transfer.js, focusable.js, form-reset-mixin.js, jquery-patch.js, keycode.js, labels.js, scroll-parent.js, tabbable.js, unique-id.js, widgets/accordion.js, widgets/autocomplete.js, widgets/button.js, widgets/checkboxradio.js, widgets/controlgroup.js, widgets/datepicker.js, widgets/dialog.js, widgets/draggable.js, widgets/droppable.js, widgets/menu.js, widgets/mouse.js, widgets/progressbar.js, widgets/resizable.js, widgets/selectable.js, widgets/selectmenu.js, widgets/slider.js, widgets/sortable.js, widgets/spinner.js, widgets/tabs.js, widgets/tooltip.js
10724* Copyright OpenJS Foundation and other contributors; Licensed MIT */
10725
10726( function( factory ) {
10727	"use strict";
10728
10729	if ( typeof define === "function" && define.amd ) {
10730
10731		// AMD. Register as an anonymous module.
10732		define( [ "jquery" ], factory );
10733	} else {
10734
10735		// Browser globals
10736		factory( jQuery );
10737	}
10738} )( function( $ ) {
10739"use strict";
10740
10741$.ui = $.ui || {};
10742
10743var version = $.ui.version = "1.14.1";
10744
10745
10746/*!
10747 * jQuery UI Widget 1.14.1
10748 * https://jqueryui.com
10749 *
10750 * Copyright OpenJS Foundation and other contributors
10751 * Released under the MIT license.
10752 * https://jquery.org/license
10753 */
10754
10755//>>label: Widget
10756//>>group: Core
10757//>>description: Provides a factory for creating stateful widgets with a common API.
10758//>>docs: https://api.jqueryui.com/jQuery.widget/
10759//>>demos: https://jqueryui.com/widget/
10760
10761
10762var widgetUuid = 0;
10763var widgetHasOwnProperty = Array.prototype.hasOwnProperty;
10764var widgetSlice = Array.prototype.slice;
10765
10766$.cleanData = ( function( orig ) {
10767	return function( elems ) {
10768		var events, elem, i;
10769		for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) {
10770
10771			// Only trigger remove when necessary to save time
10772			events = $._data( elem, "events" );
10773			if ( events && events.remove ) {
10774				$( elem ).triggerHandler( "remove" );
10775			}
10776		}
10777		orig( elems );
10778	};
10779} )( $.cleanData );
10780
10781$.widget = function( name, base, prototype ) {
10782	var existingConstructor, constructor, basePrototype;
10783
10784	// ProxiedPrototype allows the provided prototype to remain unmodified
10785	// so that it can be used as a mixin for multiple widgets (#8876)
10786	var proxiedPrototype = {};
10787
10788	var namespace = name.split( "." )[ 0 ];
10789	name = name.split( "." )[ 1 ];
10790	if ( name === "__proto__" || name === "constructor" ) {
10791		return $.error( "Invalid widget name: " + name );
10792	}
10793	var fullName = namespace + "-" + name;
10794
10795	if ( !prototype ) {
10796		prototype = base;
10797		base = $.Widget;
10798	}
10799
10800	if ( Array.isArray( prototype ) ) {
10801		prototype = $.extend.apply( null, [ {} ].concat( prototype ) );
10802	}
10803
10804	// Create selector for plugin
10805	$.expr.pseudos[ fullName.toLowerCase() ] = function( elem ) {
10806		return !!$.data( elem, fullName );
10807	};
10808
10809	$[ namespace ] = $[ namespace ] || {};
10810	existingConstructor = $[ namespace ][ name ];
10811	constructor = $[ namespace ][ name ] = function( options, element ) {
10812
10813		// Allow instantiation without "new" keyword
10814		if ( !this || !this._createWidget ) {
10815			return new constructor( options, element );
10816		}
10817
10818		// Allow instantiation without initializing for simple inheritance
10819		// must use "new" keyword (the code above always passes args)
10820		if ( arguments.length ) {
10821			this._createWidget( options, element );
10822		}
10823	};
10824
10825	// Extend with the existing constructor to carry over any static properties
10826	$.extend( constructor, existingConstructor, {
10827		version: prototype.version,
10828
10829		// Copy the object used to create the prototype in case we need to
10830		// redefine the widget later
10831		_proto: $.extend( {}, prototype ),
10832
10833		// Track widgets that inherit from this widget in case this widget is
10834		// redefined after a widget inherits from it
10835		_childConstructors: []
10836	} );
10837
10838	basePrototype = new base();
10839
10840	// We need to make the options hash a property directly on the new instance
10841	// otherwise we'll modify the options hash on the prototype that we're
10842	// inheriting from
10843	basePrototype.options = $.widget.extend( {}, basePrototype.options );
10844	$.each( prototype, function( prop, value ) {
10845		if ( typeof value !== "function" ) {
10846			proxiedPrototype[ prop ] = value;
10847			return;
10848		}
10849		proxiedPrototype[ prop ] = ( function() {
10850			function _super() {
10851				return base.prototype[ prop ].apply( this, arguments );
10852			}
10853
10854			function _superApply( args ) {
10855				return base.prototype[ prop ].apply( this, args );
10856			}
10857
10858			return function() {
10859				var __super = this._super;
10860				var __superApply = this._superApply;
10861				var returnValue;
10862
10863				this._super = _super;
10864				this._superApply = _superApply;
10865
10866				returnValue = value.apply( this, arguments );
10867
10868				this._super = __super;
10869				this._superApply = __superApply;
10870
10871				return returnValue;
10872			};
10873		} )();
10874	} );
10875	constructor.prototype = $.widget.extend( basePrototype, {
10876
10877		// TODO: remove support for widgetEventPrefix
10878		// always use the name + a colon as the prefix, e.g., draggable:start
10879		// don't prefix for widgets that aren't DOM-based
10880		widgetEventPrefix: existingConstructor ? ( basePrototype.widgetEventPrefix || name ) : name
10881	}, proxiedPrototype, {
10882		constructor: constructor,
10883		namespace: namespace,
10884		widgetName: name,
10885		widgetFullName: fullName
10886	} );
10887
10888	// If this widget is being redefined then we need to find all widgets that
10889	// are inheriting from it and redefine all of them so that they inherit from
10890	// the new version of this widget. We're essentially trying to replace one
10891	// level in the prototype chain.
10892	if ( existingConstructor ) {
10893		$.each( existingConstructor._childConstructors, function( i, child ) {
10894			var childPrototype = child.prototype;
10895
10896			// Redefine the child widget using the same prototype that was
10897			// originally used, but inherit from the new version of the base
10898			$.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor,
10899				child._proto );
10900		} );
10901
10902		// Remove the list of existing child constructors from the old constructor
10903		// so the old child constructors can be garbage collected
10904		delete existingConstructor._childConstructors;
10905	} else {
10906		base._childConstructors.push( constructor );
10907	}
10908
10909	$.widget.bridge( name, constructor );
10910
10911	return constructor;
10912};
10913
10914$.widget.extend = function( target ) {
10915	var input = widgetSlice.call( arguments, 1 );
10916	var inputIndex = 0;
10917	var inputLength = input.length;
10918	var key;
10919	var value;
10920
10921	for ( ; inputIndex < inputLength; inputIndex++ ) {
10922		for ( key in input[ inputIndex ] ) {
10923			value = input[ inputIndex ][ key ];
10924			if ( widgetHasOwnProperty.call( input[ inputIndex ], key ) && value !== undefined ) {
10925
10926				// Clone objects
10927				if ( $.isPlainObject( value ) ) {
10928					target[ key ] = $.isPlainObject( target[ key ] ) ?
10929						$.widget.extend( {}, target[ key ], value ) :
10930
10931						// Don't extend strings, arrays, etc. with objects
10932						$.widget.extend( {}, value );
10933
10934				// Copy everything else by reference
10935				} else {
10936					target[ key ] = value;
10937				}
10938			}
10939		}
10940	}
10941	return target;
10942};
10943
10944$.widget.bridge = function( name, object ) {
10945	var fullName = object.prototype.widgetFullName || name;
10946	$.fn[ name ] = function( options ) {
10947		var isMethodCall = typeof options === "string";
10948		var args = widgetSlice.call( arguments, 1 );
10949		var returnValue = this;
10950
10951		if ( isMethodCall ) {
10952
10953			// If this is an empty collection, we need to have the instance method
10954			// return undefined instead of the jQuery instance
10955			if ( !this.length && options === "instance" ) {
10956				returnValue = undefined;
10957			} else {
10958				this.each( function() {
10959					var methodValue;
10960					var instance = $.data( this, fullName );
10961
10962					if ( options === "instance" ) {
10963						returnValue = instance;
10964						return false;
10965					}
10966
10967					if ( !instance ) {
10968						return $.error( "cannot call methods on " + name +
10969							" prior to initialization; " +
10970							"attempted to call method '" + options + "'" );
10971					}
10972
10973					if ( typeof instance[ options ] !== "function" ||
10974						options.charAt( 0 ) === "_" ) {
10975						return $.error( "no such method '" + options + "' for " + name +
10976							" widget instance" );
10977					}
10978
10979					methodValue = instance[ options ].apply( instance, args );
10980
10981					if ( methodValue !== instance && methodValue !== undefined ) {
10982						returnValue = methodValue && methodValue.jquery ?
10983							returnValue.pushStack( methodValue.get() ) :
10984							methodValue;
10985						return false;
10986					}
10987				} );
10988			}
10989		} else {
10990
10991			// Allow multiple hashes to be passed on init
10992			if ( args.length ) {
10993				options = $.widget.extend.apply( null, [ options ].concat( args ) );
10994			}
10995
10996			this.each( function() {
10997				var instance = $.data( this, fullName );
10998				if ( instance ) {
10999					instance.option( options || {} );
11000					if ( instance._init ) {
11001						instance._init();
11002					}
11003				} else {
11004					$.data( this, fullName, new object( options, this ) );
11005				}
11006			} );
11007		}
11008
11009		return returnValue;
11010	};
11011};
11012
11013$.Widget = function( /* options, element */ ) {};
11014$.Widget._childConstructors = [];
11015
11016$.Widget.prototype = {
11017	widgetName: "widget",
11018	widgetEventPrefix: "",
11019	defaultElement: "<div>",
11020
11021	options: {
11022		classes: {},
11023		disabled: false,
11024
11025		// Callbacks
11026		create: null
11027	},
11028
11029	_createWidget: function( options, element ) {
11030		element = $( element || this.defaultElement || this )[ 0 ];
11031		this.element = $( element );
11032		this.uuid = widgetUuid++;
11033		this.eventNamespace = "." + this.widgetName + this.uuid;
11034
11035		this.bindings = $();
11036		this.hoverable = $();
11037		this.focusable = $();
11038		this.classesElementLookup = {};
11039
11040		if ( element !== this ) {
11041			$.data( element, this.widgetFullName, this );
11042			this._on( true, this.element, {
11043				remove: function( event ) {
11044					if ( event.target === element ) {
11045						this.destroy();
11046					}
11047				}
11048			} );
11049			this.document = $( element.style ?
11050
11051				// Element within the document
11052				element.ownerDocument :
11053
11054				// Element is window or document
11055				element.document || element );
11056			this.window = $( this.document[ 0 ].defaultView || this.document[ 0 ].parentWindow );
11057		}
11058
11059		this.options = $.widget.extend( {},
11060			this.options,
11061			this._getCreateOptions(),
11062			options );
11063
11064		this._create();
11065
11066		if ( this.options.disabled ) {
11067			this._setOptionDisabled( this.options.disabled );
11068		}
11069
11070		this._trigger( "create", null, this._getCreateEventData() );
11071		this._init();
11072	},
11073
11074	_getCreateOptions: function() {
11075		return {};
11076	},
11077
11078	_getCreateEventData: $.noop,
11079
11080	_create: $.noop,
11081
11082	_init: $.noop,
11083
11084	destroy: function() {
11085		var that = this;
11086
11087		this._destroy();
11088		$.each( this.classesElementLookup, function( key, value ) {
11089			that._removeClass( value, key );
11090		} );
11091
11092		// We can probably remove the unbind calls in 2.0
11093		// all event bindings should go through this._on()
11094		this.element
11095			.off( this.eventNamespace )
11096			.removeData( this.widgetFullName );
11097		this.widget()
11098			.off( this.eventNamespace )
11099			.removeAttr( "aria-disabled" );
11100
11101		// Clean up events and states
11102		this.bindings.off( this.eventNamespace );
11103	},
11104
11105	_destroy: $.noop,
11106
11107	widget: function() {
11108		return this.element;
11109	},
11110
11111	option: function( key, value ) {
11112		var options = key;
11113		var parts;
11114		var curOption;
11115		var i;
11116
11117		if ( arguments.length === 0 ) {
11118
11119			// Don't return a reference to the internal hash
11120			return $.widget.extend( {}, this.options );
11121		}
11122
11123		if ( typeof key === "string" ) {
11124
11125			// Handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
11126			options = {};
11127			parts = key.split( "." );
11128			key = parts.shift();
11129			if ( parts.length ) {
11130				curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
11131				for ( i = 0; i < parts.length - 1; i++ ) {
11132					curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
11133					curOption = curOption[ parts[ i ] ];
11134				}
11135				key = parts.pop();
11136				if ( arguments.length === 1 ) {
11137					return curOption[ key ] === undefined ? null : curOption[ key ];
11138				}
11139				curOption[ key ] = value;
11140			} else {
11141				if ( arguments.length === 1 ) {
11142					return this.options[ key ] === undefined ? null : this.options[ key ];
11143				}
11144				options[ key ] = value;
11145			}
11146		}
11147
11148		this._setOptions( options );
11149
11150		return this;
11151	},
11152
11153	_setOptions: function( options ) {
11154		var key;
11155
11156		for ( key in options ) {
11157			this._setOption( key, options[ key ] );
11158		}
11159
11160		return this;
11161	},
11162
11163	_setOption: function( key, value ) {
11164		if ( key === "classes" ) {
11165			this._setOptionClasses( value );
11166		}
11167
11168		this.options[ key ] = value;
11169
11170		if ( key === "disabled" ) {
11171			this._setOptionDisabled( value );
11172		}
11173
11174		return this;
11175	},
11176
11177	_setOptionClasses: function( value ) {
11178		var classKey, elements, currentElements;
11179
11180		for ( classKey in value ) {
11181			currentElements = this.classesElementLookup[ classKey ];
11182			if ( value[ classKey ] === this.options.classes[ classKey ] ||
11183					!currentElements ||
11184					!currentElements.length ) {
11185				continue;
11186			}
11187
11188			// We are doing this to create a new jQuery object because the _removeClass() call
11189			// on the next line is going to destroy the reference to the current elements being
11190			// tracked. We need to save a copy of this collection so that we can add the new classes
11191			// below.
11192			elements = $( currentElements.get() );
11193			this._removeClass( currentElements, classKey );
11194
11195			// We don't use _addClass() here, because that uses this.options.classes
11196			// for generating the string of classes. We want to use the value passed in from
11197			// _setOption(), this is the new value of the classes option which was passed to
11198			// _setOption(). We pass this value directly to _classes().
11199			elements.addClass( this._classes( {
11200				element: elements,
11201				keys: classKey,
11202				classes: value,
11203				add: true
11204			} ) );
11205		}
11206	},
11207
11208	_setOptionDisabled: function( value ) {
11209		this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, !!value );
11210
11211		// If the widget is becoming disabled, then nothing is interactive
11212		if ( value ) {
11213			this._removeClass( this.hoverable, null, "ui-state-hover" );
11214			this._removeClass( this.focusable, null, "ui-state-focus" );
11215		}
11216	},
11217
11218	enable: function() {
11219		return this._setOptions( { disabled: false } );
11220	},
11221
11222	disable: function() {
11223		return this._setOptions( { disabled: true } );
11224	},
11225
11226	_classes: function( options ) {
11227		var full = [];
11228		var that = this;
11229
11230		options = $.extend( {
11231			element: this.element,
11232			classes: this.options.classes || {}
11233		}, options );
11234
11235		function bindRemoveEvent() {
11236			var nodesToBind = [];
11237
11238			options.element.each( function( _, element ) {
11239				var isTracked = $.map( that.classesElementLookup, function( elements ) {
11240					return elements;
11241				} )
11242					.some( function( elements ) {
11243						return elements.is( element );
11244					} );
11245
11246				if ( !isTracked ) {
11247					nodesToBind.push( element );
11248				}
11249			} );
11250
11251			that._on( $( nodesToBind ), {
11252				remove: "_untrackClassesElement"
11253			} );
11254		}
11255
11256		function processClassString( classes, checkOption ) {
11257			var current, i;
11258			for ( i = 0; i < classes.length; i++ ) {
11259				current = that.classesElementLookup[ classes[ i ] ] || $();
11260				if ( options.add ) {
11261					bindRemoveEvent();
11262					current = $( $.uniqueSort( current.get().concat( options.element.get() ) ) );
11263				} else {
11264					current = $( current.not( options.element ).get() );
11265				}
11266				that.classesElementLookup[ classes[ i ] ] = current;
11267				full.push( classes[ i ] );
11268				if ( checkOption && options.classes[ classes[ i ] ] ) {
11269					full.push( options.classes[ classes[ i ] ] );
11270				}
11271			}
11272		}
11273
11274		if ( options.keys ) {
11275			processClassString( options.keys.match( /\S+/g ) || [], true );
11276		}
11277		if ( options.extra ) {
11278			processClassString( options.extra.match( /\S+/g ) || [] );
11279		}
11280
11281		return full.join( " " );
11282	},
11283
11284	_untrackClassesElement: function( event ) {
11285		var that = this;
11286		$.each( that.classesElementLookup, function( key, value ) {
11287			if ( $.inArray( event.target, value ) !== -1 ) {
11288				that.classesElementLookup[ key ] = $( value.not( event.target ).get() );
11289			}
11290		} );
11291
11292		this._off( $( event.target ) );
11293	},
11294
11295	_removeClass: function( element, keys, extra ) {
11296		return this._toggleClass( element, keys, extra, false );
11297	},
11298
11299	_addClass: function( element, keys, extra ) {
11300		return this._toggleClass( element, keys, extra, true );
11301	},
11302
11303	_toggleClass: function( element, keys, extra, add ) {
11304		add = ( typeof add === "boolean" ) ? add : extra;
11305		var shift = ( typeof element === "string" || element === null ),
11306			options = {
11307				extra: shift ? keys : extra,
11308				keys: shift ? element : keys,
11309				element: shift ? this.element : element,
11310				add: add
11311			};
11312		options.element.toggleClass( this._classes( options ), add );
11313		return this;
11314	},
11315
11316	_on: function( suppressDisabledCheck, element, handlers ) {
11317		var delegateElement;
11318		var instance = this;
11319
11320		// No suppressDisabledCheck flag, shuffle arguments
11321		if ( typeof suppressDisabledCheck !== "boolean" ) {
11322			handlers = element;
11323			element = suppressDisabledCheck;
11324			suppressDisabledCheck = false;
11325		}
11326
11327		// No element argument, shuffle and use this.element
11328		if ( !handlers ) {
11329			handlers = element;
11330			element = this.element;
11331			delegateElement = this.widget();
11332		} else {
11333			element = delegateElement = $( element );
11334			this.bindings = this.bindings.add( element );
11335		}
11336
11337		$.each( handlers, function( event, handler ) {
11338			function handlerProxy() {
11339
11340				// Allow widgets to customize the disabled handling
11341				// - disabled as an array instead of boolean
11342				// - disabled class as method for disabling individual parts
11343				if ( !suppressDisabledCheck &&
11344						( instance.options.disabled === true ||
11345						$( this ).hasClass( "ui-state-disabled" ) ) ) {
11346					return;
11347				}
11348				return ( typeof handler === "string" ? instance[ handler ] : handler )
11349					.apply( instance, arguments );
11350			}
11351
11352			// Copy the guid so direct unbinding works
11353			if ( typeof handler !== "string" ) {
11354				handlerProxy.guid = handler.guid =
11355					handler.guid || handlerProxy.guid || $.guid++;
11356			}
11357
11358			var match = event.match( /^([\w:-]*)\s*(.*)$/ );
11359			var eventName = match[ 1 ] + instance.eventNamespace;
11360			var selector = match[ 2 ];
11361
11362			if ( selector ) {
11363				delegateElement.on( eventName, selector, handlerProxy );
11364			} else {
11365				element.on( eventName, handlerProxy );
11366			}
11367		} );
11368	},
11369
11370	_off: function( element, eventName ) {
11371		eventName = ( eventName || "" ).split( " " ).join( this.eventNamespace + " " ) +
11372			this.eventNamespace;
11373		element.off( eventName );
11374
11375		// Clear the stack to avoid memory leaks (#10056)
11376		this.bindings = $( this.bindings.not( element ).get() );
11377		this.focusable = $( this.focusable.not( element ).get() );
11378		this.hoverable = $( this.hoverable.not( element ).get() );
11379	},
11380
11381	_delay: function( handler, delay ) {
11382		function handlerProxy() {
11383			return ( typeof handler === "string" ? instance[ handler ] : handler )
11384				.apply( instance, arguments );
11385		}
11386		var instance = this;
11387		return setTimeout( handlerProxy, delay || 0 );
11388	},
11389
11390	_hoverable: function( element ) {
11391		this.hoverable = this.hoverable.add( element );
11392		this._on( element, {
11393			mouseenter: function( event ) {
11394				this._addClass( $( event.currentTarget ), null, "ui-state-hover" );
11395			},
11396			mouseleave: function( event ) {
11397				this._removeClass( $( event.currentTarget ), null, "ui-state-hover" );
11398			}
11399		} );
11400	},
11401
11402	_focusable: function( element ) {
11403		this.focusable = this.focusable.add( element );
11404		this._on( element, {
11405			focusin: function( event ) {
11406				this._addClass( $( event.currentTarget ), null, "ui-state-focus" );
11407			},
11408			focusout: function( event ) {
11409				this._removeClass( $( event.currentTarget ), null, "ui-state-focus" );
11410			}
11411		} );
11412	},
11413
11414	_trigger: function( type, event, data ) {
11415		var prop, orig;
11416		var callback = this.options[ type ];
11417
11418		data = data || {};
11419		event = $.Event( event );
11420		event.type = ( type === this.widgetEventPrefix ?
11421			type :
11422			this.widgetEventPrefix + type ).toLowerCase();
11423
11424		// The original event may come from any element
11425		// so we need to reset the target on the new event
11426		event.target = this.element[ 0 ];
11427
11428		// Copy original event properties over to the new event
11429		orig = event.originalEvent;
11430		if ( orig ) {
11431			for ( prop in orig ) {
11432				if ( !( prop in event ) ) {
11433					event[ prop ] = orig[ prop ];
11434				}
11435			}
11436		}
11437
11438		this.element.trigger( event, data );
11439		return !( typeof callback === "function" &&
11440			callback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false ||
11441			event.isDefaultPrevented() );
11442	}
11443};
11444
11445$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
11446	$.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
11447		if ( typeof options === "string" ) {
11448			options = { effect: options };
11449		}
11450
11451		var hasOptions;
11452		var effectName = !options ?
11453			method :
11454			options === true || typeof options === "number" ?
11455				defaultEffect :
11456				options.effect || defaultEffect;
11457
11458		options = options || {};
11459		if ( typeof options === "number" ) {
11460			options = { duration: options };
11461		} else if ( options === true ) {
11462			options = {};
11463		}
11464
11465		hasOptions = !$.isEmptyObject( options );
11466		options.complete = callback;
11467
11468		if ( options.delay ) {
11469			element.delay( options.delay );
11470		}
11471
11472		if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
11473			element[ method ]( options );
11474		} else if ( effectName !== method && element[ effectName ] ) {
11475			element[ effectName ]( options.duration, options.easing, callback );
11476		} else {
11477			element.queue( function( next ) {
11478				$( this )[ method ]();
11479				if ( callback ) {
11480					callback.call( element[ 0 ] );
11481				}
11482				next();
11483			} );
11484		}
11485	};
11486} );
11487
11488var widget = $.widget;
11489
11490
11491/*!
11492 * jQuery UI Position 1.14.1
11493 * https://jqueryui.com
11494 *
11495 * Copyright OpenJS Foundation and other contributors
11496 * Released under the MIT license.
11497 * https://jquery.org/license
11498 *
11499 * https://api.jqueryui.com/position/
11500 */
11501
11502//>>label: Position
11503//>>group: Core
11504//>>description: Positions elements relative to other elements.
11505//>>docs: https://api.jqueryui.com/position/
11506//>>demos: https://jqueryui.com/position/
11507
11508
11509( function() {
11510var cachedScrollbarWidth,
11511	max = Math.max,
11512	abs = Math.abs,
11513	rhorizontal = /left|center|right/,
11514	rvertical = /top|center|bottom/,
11515	roffset = /[\+\-]\d+(\.[\d]+)?%?/,
11516	rposition = /^\w+/,
11517	rpercent = /%$/,
11518	_position = $.fn.position;
11519
11520function getOffsets( offsets, width, height ) {
11521	return [
11522		parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
11523		parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
11524	];
11525}
11526
11527function parseCss( element, property ) {
11528	return parseInt( $.css( element, property ), 10 ) || 0;
11529}
11530
11531function isWindow( obj ) {
11532	return obj != null && obj === obj.window;
11533}
11534
11535function getDimensions( elem ) {
11536	var raw = elem[ 0 ];
11537	if ( raw.nodeType === 9 ) {
11538		return {
11539			width: elem.width(),
11540			height: elem.height(),
11541			offset: { top: 0, left: 0 }
11542		};
11543	}
11544	if ( isWindow( raw ) ) {
11545		return {
11546			width: elem.width(),
11547			height: elem.height(),
11548			offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
11549		};
11550	}
11551	if ( raw.preventDefault ) {
11552		return {
11553			width: 0,
11554			height: 0,
11555			offset: { top: raw.pageY, left: raw.pageX }
11556		};
11557	}
11558	return {
11559		width: elem.outerWidth(),
11560		height: elem.outerHeight(),
11561		offset: elem.offset()
11562	};
11563}
11564
11565$.position = {
11566	scrollbarWidth: function() {
11567		if ( cachedScrollbarWidth !== undefined ) {
11568			return cachedScrollbarWidth;
11569		}
11570		var w1, w2,
11571			div = $( "<div style=" +
11572				"'display:block;position:absolute;width:200px;height:200px;overflow:hidden;'>" +
11573				"<div style='height:300px;width:auto;'></div></div>" ),
11574			innerDiv = div.children()[ 0 ];
11575
11576		$( "body" ).append( div );
11577		w1 = innerDiv.offsetWidth;
11578		div.css( "overflow", "scroll" );
11579
11580		w2 = innerDiv.offsetWidth;
11581
11582		if ( w1 === w2 ) {
11583			w2 = div[ 0 ].clientWidth;
11584		}
11585
11586		div.remove();
11587
11588		return ( cachedScrollbarWidth = w1 - w2 );
11589	},
11590	getScrollInfo: function( within ) {
11591		var overflowX = within.isWindow || within.isDocument ? "" :
11592				within.element.css( "overflow-x" ),
11593			overflowY = within.isWindow || within.isDocument ? "" :
11594				within.element.css( "overflow-y" ),
11595			hasOverflowX = overflowX === "scroll" ||
11596				( overflowX === "auto" && within.width < within.element[ 0 ].scrollWidth ),
11597			hasOverflowY = overflowY === "scroll" ||
11598				( overflowY === "auto" && within.height < within.element[ 0 ].scrollHeight );
11599		return {
11600			width: hasOverflowY ? $.position.scrollbarWidth() : 0,
11601			height: hasOverflowX ? $.position.scrollbarWidth() : 0
11602		};
11603	},
11604	getWithinInfo: function( element ) {
11605		var withinElement = $( element || window ),
11606			isElemWindow = isWindow( withinElement[ 0 ] ),
11607			isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9,
11608			hasOffset = !isElemWindow && !isDocument;
11609		return {
11610			element: withinElement,
11611			isWindow: isElemWindow,
11612			isDocument: isDocument,
11613			offset: hasOffset ? $( element ).offset() : { left: 0, top: 0 },
11614			scrollLeft: withinElement.scrollLeft(),
11615			scrollTop: withinElement.scrollTop(),
11616			width: withinElement.outerWidth(),
11617			height: withinElement.outerHeight()
11618		};
11619	}
11620};
11621
11622$.fn.position = function( options ) {
11623	if ( !options || !options.of ) {
11624		return _position.apply( this, arguments );
11625	}
11626
11627	// Make a copy, we don't want to modify arguments
11628	options = $.extend( {}, options );
11629
11630	var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
11631
11632		// Make sure string options are treated as CSS selectors
11633		target = typeof options.of === "string" ?
11634			$( document ).find( options.of ) :
11635			$( options.of ),
11636
11637		within = $.position.getWithinInfo( options.within ),
11638		scrollInfo = $.position.getScrollInfo( within ),
11639		collision = ( options.collision || "flip" ).split( " " ),
11640		offsets = {};
11641
11642	dimensions = getDimensions( target );
11643	if ( target[ 0 ].preventDefault ) {
11644
11645		// Force left top to allow flipping
11646		options.at = "left top";
11647	}
11648	targetWidth = dimensions.width;
11649	targetHeight = dimensions.height;
11650	targetOffset = dimensions.offset;
11651
11652	// Clone to reuse original targetOffset later
11653	basePosition = $.extend( {}, targetOffset );
11654
11655	// Force my and at to have valid horizontal and vertical positions
11656	// if a value is missing or invalid, it will be converted to center
11657	$.each( [ "my", "at" ], function() {
11658		var pos = ( options[ this ] || "" ).split( " " ),
11659			horizontalOffset,
11660			verticalOffset;
11661
11662		if ( pos.length === 1 ) {
11663			pos = rhorizontal.test( pos[ 0 ] ) ?
11664				pos.concat( [ "center" ] ) :
11665				rvertical.test( pos[ 0 ] ) ?
11666					[ "center" ].concat( pos ) :
11667					[ "center", "center" ];
11668		}
11669		pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
11670		pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
11671
11672		// Calculate offsets
11673		horizontalOffset = roffset.exec( pos[ 0 ] );
11674		verticalOffset = roffset.exec( pos[ 1 ] );
11675		offsets[ this ] = [
11676			horizontalOffset ? horizontalOffset[ 0 ] : 0,
11677			verticalOffset ? verticalOffset[ 0 ] : 0
11678		];
11679
11680		// Reduce to just the positions without the offsets
11681		options[ this ] = [
11682			rposition.exec( pos[ 0 ] )[ 0 ],
11683			rposition.exec( pos[ 1 ] )[ 0 ]
11684		];
11685	} );
11686
11687	// Normalize collision option
11688	if ( collision.length === 1 ) {
11689		collision[ 1 ] = collision[ 0 ];
11690	}
11691
11692	if ( options.at[ 0 ] === "right" ) {
11693		basePosition.left += targetWidth;
11694	} else if ( options.at[ 0 ] === "center" ) {
11695		basePosition.left += targetWidth / 2;
11696	}
11697
11698	if ( options.at[ 1 ] === "bottom" ) {
11699		basePosition.top += targetHeight;
11700	} else if ( options.at[ 1 ] === "center" ) {
11701		basePosition.top += targetHeight / 2;
11702	}
11703
11704	atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
11705	basePosition.left += atOffset[ 0 ];
11706	basePosition.top += atOffset[ 1 ];
11707
11708	return this.each( function() {
11709		var collisionPosition, using,
11710			elem = $( this ),
11711			elemWidth = elem.outerWidth(),
11712			elemHeight = elem.outerHeight(),
11713			marginLeft = parseCss( this, "marginLeft" ),
11714			marginTop = parseCss( this, "marginTop" ),
11715			collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) +
11716				scrollInfo.width,
11717			collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) +
11718				scrollInfo.height,
11719			position = $.extend( {}, basePosition ),
11720			myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
11721
11722		if ( options.my[ 0 ] === "right" ) {
11723			position.left -= elemWidth;
11724		} else if ( options.my[ 0 ] === "center" ) {
11725			position.left -= elemWidth / 2;
11726		}
11727
11728		if ( options.my[ 1 ] === "bottom" ) {
11729			position.top -= elemHeight;
11730		} else if ( options.my[ 1 ] === "center" ) {
11731			position.top -= elemHeight / 2;
11732		}
11733
11734		position.left += myOffset[ 0 ];
11735		position.top += myOffset[ 1 ];
11736
11737		collisionPosition = {
11738			marginLeft: marginLeft,
11739			marginTop: marginTop
11740		};
11741
11742		$.each( [ "left", "top" ], function( i, dir ) {
11743			if ( $.ui.position[ collision[ i ] ] ) {
11744				$.ui.position[ collision[ i ] ][ dir ]( position, {
11745					targetWidth: targetWidth,
11746					targetHeight: targetHeight,
11747					elemWidth: elemWidth,
11748					elemHeight: elemHeight,
11749					collisionPosition: collisionPosition,
11750					collisionWidth: collisionWidth,
11751					collisionHeight: collisionHeight,
11752					offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
11753					my: options.my,
11754					at: options.at,
11755					within: within,
11756					elem: elem
11757				} );
11758			}
11759		} );
11760
11761		if ( options.using ) {
11762
11763			// Adds feedback as second argument to using callback, if present
11764			using = function( props ) {
11765				var left = targetOffset.left - position.left,
11766					right = left + targetWidth - elemWidth,
11767					top = targetOffset.top - position.top,
11768					bottom = top + targetHeight - elemHeight,
11769					feedback = {
11770						target: {
11771							element: target,
11772							left: targetOffset.left,
11773							top: targetOffset.top,
11774							width: targetWidth,
11775							height: targetHeight
11776						},
11777						element: {
11778							element: elem,
11779							left: position.left,
11780							top: position.top,
11781							width: elemWidth,
11782							height: elemHeight
11783						},
11784						horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
11785						vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
11786					};
11787				if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
11788					feedback.horizontal = "center";
11789				}
11790				if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
11791					feedback.vertical = "middle";
11792				}
11793				if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
11794					feedback.important = "horizontal";
11795				} else {
11796					feedback.important = "vertical";
11797				}
11798				options.using.call( this, props, feedback );
11799			};
11800		}
11801
11802		elem.offset( $.extend( position, { using: using } ) );
11803	} );
11804};
11805
11806$.ui.position = {
11807	fit: {
11808		left: function( position, data ) {
11809			var within = data.within,
11810				withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
11811				outerWidth = within.width,
11812				collisionPosLeft = position.left - data.collisionPosition.marginLeft,
11813				overLeft = withinOffset - collisionPosLeft,
11814				overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
11815				newOverRight;
11816
11817			// Element is wider than within
11818			if ( data.collisionWidth > outerWidth ) {
11819
11820				// Element is initially over the left side of within
11821				if ( overLeft > 0 && overRight <= 0 ) {
11822					newOverRight = position.left + overLeft + data.collisionWidth - outerWidth -
11823						withinOffset;
11824					position.left += overLeft - newOverRight;
11825
11826				// Element is initially over right side of within
11827				} else if ( overRight > 0 && overLeft <= 0 ) {
11828					position.left = withinOffset;
11829
11830				// Element is initially over both left and right sides of within
11831				} else {
11832					if ( overLeft > overRight ) {
11833						position.left = withinOffset + outerWidth - data.collisionWidth;
11834					} else {
11835						position.left = withinOffset;
11836					}
11837				}
11838
11839			// Too far left -> align with left edge
11840			} else if ( overLeft > 0 ) {
11841				position.left += overLeft;
11842
11843			// Too far right -> align with right edge
11844			} else if ( overRight > 0 ) {
11845				position.left -= overRight;
11846
11847			// Adjust based on position and margin
11848			} else {
11849				position.left = max( position.left - collisionPosLeft, position.left );
11850			}
11851		},
11852		top: function( position, data ) {
11853			var within = data.within,
11854				withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
11855				outerHeight = data.within.height,
11856				collisionPosTop = position.top - data.collisionPosition.marginTop,
11857				overTop = withinOffset - collisionPosTop,
11858				overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
11859				newOverBottom;
11860
11861			// Element is taller than within
11862			if ( data.collisionHeight > outerHeight ) {
11863
11864				// Element is initially over the top of within
11865				if ( overTop > 0 && overBottom <= 0 ) {
11866					newOverBottom = position.top + overTop + data.collisionHeight - outerHeight -
11867						withinOffset;
11868					position.top += overTop - newOverBottom;
11869
11870				// Element is initially over bottom of within
11871				} else if ( overBottom > 0 && overTop <= 0 ) {
11872					position.top = withinOffset;
11873
11874				// Element is initially over both top and bottom of within
11875				} else {
11876					if ( overTop > overBottom ) {
11877						position.top = withinOffset + outerHeight - data.collisionHeight;
11878					} else {
11879						position.top = withinOffset;
11880					}
11881				}
11882
11883			// Too far up -> align with top
11884			} else if ( overTop > 0 ) {
11885				position.top += overTop;
11886
11887			// Too far down -> align with bottom edge
11888			} else if ( overBottom > 0 ) {
11889				position.top -= overBottom;
11890
11891			// Adjust based on position and margin
11892			} else {
11893				position.top = max( position.top - collisionPosTop, position.top );
11894			}
11895		}
11896	},
11897	flip: {
11898		left: function( position, data ) {
11899			var within = data.within,
11900				withinOffset = within.offset.left + within.scrollLeft,
11901				outerWidth = within.width,
11902				offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
11903				collisionPosLeft = position.left - data.collisionPosition.marginLeft,
11904				overLeft = collisionPosLeft - offsetLeft,
11905				overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
11906				myOffset = data.my[ 0 ] === "left" ?
11907					-data.elemWidth :
11908					data.my[ 0 ] === "right" ?
11909						data.elemWidth :
11910						0,
11911				atOffset = data.at[ 0 ] === "left" ?
11912					data.targetWidth :
11913					data.at[ 0 ] === "right" ?
11914						-data.targetWidth :
11915						0,
11916				offset = -2 * data.offset[ 0 ],
11917				newOverRight,
11918				newOverLeft;
11919
11920			if ( overLeft < 0 ) {
11921				newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth -
11922					outerWidth - withinOffset;
11923				if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
11924					position.left += myOffset + atOffset + offset;
11925				}
11926			} else if ( overRight > 0 ) {
11927				newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset +
11928					atOffset + offset - offsetLeft;
11929				if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
11930					position.left += myOffset + atOffset + offset;
11931				}
11932			}
11933		},
11934		top: function( position, data ) {
11935			var within = data.within,
11936				withinOffset = within.offset.top + within.scrollTop,
11937				outerHeight = within.height,
11938				offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
11939				collisionPosTop = position.top - data.collisionPosition.marginTop,
11940				overTop = collisionPosTop - offsetTop,
11941				overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
11942				top = data.my[ 1 ] === "top",
11943				myOffset = top ?
11944					-data.elemHeight :
11945					data.my[ 1 ] === "bottom" ?
11946						data.elemHeight :
11947						0,
11948				atOffset = data.at[ 1 ] === "top" ?
11949					data.targetHeight :
11950					data.at[ 1 ] === "bottom" ?
11951						-data.targetHeight :
11952						0,
11953				offset = -2 * data.offset[ 1 ],
11954				newOverTop,
11955				newOverBottom;
11956			if ( overTop < 0 ) {
11957				newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight -
11958					outerHeight - withinOffset;
11959				if ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) {
11960					position.top += myOffset + atOffset + offset;
11961				}
11962			} else if ( overBottom > 0 ) {
11963				newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset +
11964					offset - offsetTop;
11965				if ( newOverTop > 0 || abs( newOverTop ) < overBottom ) {
11966					position.top += myOffset + atOffset + offset;
11967				}
11968			}
11969		}
11970	},
11971	flipfit: {
11972		left: function() {
11973			$.ui.position.flip.left.apply( this, arguments );
11974			$.ui.position.fit.left.apply( this, arguments );
11975		},
11976		top: function() {
11977			$.ui.position.flip.top.apply( this, arguments );
11978			$.ui.position.fit.top.apply( this, arguments );
11979		}
11980	}
11981};
11982
11983} )();
11984
11985var position = $.ui.position;
11986
11987
11988/*!
11989 * jQuery UI :data 1.14.1
11990 * https://jqueryui.com
11991 *
11992 * Copyright OpenJS Foundation and other contributors
11993 * Released under the MIT license.
11994 * https://jquery.org/license
11995 */
11996
11997//>>label: :data Selector
11998//>>group: Core
11999//>>description: Selects elements which have data stored under the specified key.
12000//>>docs: https://api.jqueryui.com/data-selector/
12001
12002
12003var data = $.extend( $.expr.pseudos, {
12004	data: $.expr.createPseudo( function( dataName ) {
12005		return function( elem ) {
12006			return !!$.data( elem, dataName );
12007		};
12008	} )
12009} );
12010
12011/*!
12012 * jQuery UI Disable Selection 1.14.1
12013 * https://jqueryui.com
12014 *
12015 * Copyright OpenJS Foundation and other contributors
12016 * Released under the MIT license.
12017 * https://jquery.org/license
12018 */
12019
12020//>>label: disableSelection
12021//>>group: Core
12022//>>description: Disable selection of text content within the set of matched elements.
12023//>>docs: https://api.jqueryui.com/disableSelection/
12024
12025// This file is deprecated
12026
12027var disableSelection = $.fn.extend( {
12028	disableSelection: ( function() {
12029		var eventType = "onselectstart" in document.createElement( "div" ) ?
12030			"selectstart" :
12031			"mousedown";
12032
12033		return function() {
12034			return this.on( eventType + ".ui-disableSelection", function( event ) {
12035				event.preventDefault();
12036			} );
12037		};
12038	} )(),
12039
12040	enableSelection: function() {
12041		return this.off( ".ui-disableSelection" );
12042	}
12043} );
12044
12045
12046
12047// Create a local jQuery because jQuery Color relies on it and the
12048// global may not exist with AMD and a custom build (#10199).
12049// This module is a noop if used as a regular AMD module.
12050// eslint-disable-next-line no-unused-vars
12051var jQuery = $;
12052
12053
12054/*!
12055 * jQuery Color Animations v3.0.0
12056 * https://github.com/jquery/jquery-color
12057 *
12058 * Copyright OpenJS Foundation and other contributors
12059 * Released under the MIT license.
12060 * https://jquery.org/license
12061 *
12062 * Date: Wed May 15 16:49:44 2024 +0200
12063 */
12064
12065
12066	var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor " +
12067		"borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",
12068
12069	class2type = {},
12070	toString = class2type.toString,
12071
12072	// plusequals test for += 100 -= 100
12073	rplusequals = /^([\-+])=\s*(\d+\.?\d*)/,
12074
12075	// a set of RE's that can match strings and generate color tuples.
12076	stringParsers = [ {
12077			re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
12078			parse: function( execResult ) {
12079				return [
12080					execResult[ 1 ],
12081					execResult[ 2 ],
12082					execResult[ 3 ],
12083					execResult[ 4 ]
12084				];
12085			}
12086		}, {
12087			re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
12088			parse: function( execResult ) {
12089				return [
12090					execResult[ 1 ] * 2.55,
12091					execResult[ 2 ] * 2.55,
12092					execResult[ 3 ] * 2.55,
12093					execResult[ 4 ]
12094				];
12095			}
12096		}, {
12097
12098			// this regex ignores A-F because it's compared against an already lowercased string
12099			re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})?/,
12100			parse: function( execResult ) {
12101				return [
12102					parseInt( execResult[ 1 ], 16 ),
12103					parseInt( execResult[ 2 ], 16 ),
12104					parseInt( execResult[ 3 ], 16 ),
12105					execResult[ 4 ] ?
12106						( parseInt( execResult[ 4 ], 16 ) / 255 ).toFixed( 2 ) :
12107						1
12108				];
12109			}
12110		}, {
12111
12112			// this regex ignores A-F because it's compared against an already lowercased string
12113			re: /#([a-f0-9])([a-f0-9])([a-f0-9])([a-f0-9])?/,
12114			parse: function( execResult ) {
12115				return [
12116					parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),
12117					parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),
12118					parseInt( execResult[ 3 ] + execResult[ 3 ], 16 ),
12119					execResult[ 4 ] ?
12120						( parseInt( execResult[ 4 ] + execResult[ 4 ], 16 ) / 255 )
12121							.toFixed( 2 ) :
12122						1
12123				];
12124			}
12125		}, {
12126			re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
12127			space: "hsla",
12128			parse: function( execResult ) {
12129				return [
12130					execResult[ 1 ],
12131					execResult[ 2 ] / 100,
12132					execResult[ 3 ] / 100,
12133					execResult[ 4 ]
12134				];
12135			}
12136		} ],
12137
12138	// jQuery.Color( )
12139	color = jQuery.Color = function( color, green, blue, alpha ) {
12140		return new jQuery.Color.fn.parse( color, green, blue, alpha );
12141	},
12142	spaces = {
12143		rgba: {
12144			props: {
12145				red: {
12146					idx: 0,
12147					type: "byte"
12148				},
12149				green: {
12150					idx: 1,
12151					type: "byte"
12152				},
12153				blue: {
12154					idx: 2,
12155					type: "byte"
12156				}
12157			}
12158		},
12159
12160		hsla: {
12161			props: {
12162				hue: {
12163					idx: 0,
12164					type: "degrees"
12165				},
12166				saturation: {
12167					idx: 1,
12168					type: "percent"
12169				},
12170				lightness: {
12171					idx: 2,
12172					type: "percent"
12173				}
12174			}
12175		}
12176	},
12177	propTypes = {
12178		"byte": {
12179			floor: true,
12180			max: 255
12181		},
12182		"percent": {
12183			max: 1
12184		},
12185		"degrees": {
12186			mod: 360,
12187			floor: true
12188		}
12189	},
12190
12191	// colors = jQuery.Color.names
12192	colors,
12193
12194	// local aliases of functions called often
12195	each = jQuery.each;
12196
12197// define cache name and alpha properties
12198// for rgba and hsla spaces
12199each( spaces, function( spaceName, space ) {
12200	space.cache = "_" + spaceName;
12201	space.props.alpha = {
12202		idx: 3,
12203		type: "percent",
12204		def: 1
12205	};
12206} );
12207
12208// Populate the class2type map
12209jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
12210	function( _i, name ) {
12211		class2type[ "[object " + name + "]" ] = name.toLowerCase();
12212	} );
12213
12214function getType( obj ) {
12215	if ( obj == null ) {
12216		return obj + "";
12217	}
12218
12219	return typeof obj === "object" ?
12220		class2type[ toString.call( obj ) ] || "object" :
12221		typeof obj;
12222}
12223
12224function clamp( value, prop, allowEmpty ) {
12225	var type = propTypes[ prop.type ] || {};
12226
12227	if ( value == null ) {
12228		return ( allowEmpty || !prop.def ) ? null : prop.def;
12229	}
12230
12231	// ~~ is an short way of doing floor for positive numbers
12232	value = type.floor ? ~~value : parseFloat( value );
12233
12234	if ( type.mod ) {
12235
12236		// we add mod before modding to make sure that negatives values
12237		// get converted properly: -10 -> 350
12238		return ( value + type.mod ) % type.mod;
12239	}
12240
12241	// for now all property types without mod have min and max
12242	return Math.min( type.max, Math.max( 0, value ) );
12243}
12244
12245function stringParse( string ) {
12246	var inst = color(),
12247		rgba = inst._rgba = [];
12248
12249	string = string.toLowerCase();
12250
12251	each( stringParsers, function( _i, parser ) {
12252		var parsed,
12253			match = parser.re.exec( string ),
12254			values = match && parser.parse( match ),
12255			spaceName = parser.space || "rgba";
12256
12257		if ( values ) {
12258			parsed = inst[ spaceName ]( values );
12259
12260			// if this was an rgba parse the assignment might happen twice
12261			// oh well....
12262			inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ];
12263			rgba = inst._rgba = parsed._rgba;
12264
12265			// exit each( stringParsers ) here because we matched
12266			return false;
12267		}
12268	} );
12269
12270	// Found a stringParser that handled it
12271	if ( rgba.length ) {
12272
12273		// if this came from a parsed string, force "transparent" when alpha is 0
12274		// chrome, (and maybe others) return "transparent" as rgba(0,0,0,0)
12275		if ( rgba.join() === "0,0,0,0" ) {
12276			jQuery.extend( rgba, colors.transparent );
12277		}
12278		return inst;
12279	}
12280
12281	// named colors
12282	return colors[ string ];
12283}
12284
12285color.fn = jQuery.extend( color.prototype, {
12286	parse: function( red, green, blue, alpha ) {
12287		if ( red === undefined ) {
12288			this._rgba = [ null, null, null, null ];
12289			return this;
12290		}
12291		if ( red.jquery || red.nodeType ) {
12292			red = jQuery( red ).css( green );
12293			green = undefined;
12294		}
12295
12296		var inst = this,
12297			type = getType( red ),
12298			rgba = this._rgba = [];
12299
12300		// more than 1 argument specified - assume ( red, green, blue, alpha )
12301		if ( green !== undefined ) {
12302			red = [ red, green, blue, alpha ];
12303			type = "array";
12304		}
12305
12306		if ( type === "string" ) {
12307			return this.parse( stringParse( red ) || colors._default );
12308		}
12309
12310		if ( type === "array" ) {
12311			each( spaces.rgba.props, function( _key, prop ) {
12312				rgba[ prop.idx ] = clamp( red[ prop.idx ], prop );
12313			} );
12314			return this;
12315		}
12316
12317		if ( type === "object" ) {
12318			if ( red instanceof color ) {
12319				each( spaces, function( _spaceName, space ) {
12320					if ( red[ space.cache ] ) {
12321						inst[ space.cache ] = red[ space.cache ].slice();
12322					}
12323				} );
12324			} else {
12325				each( spaces, function( _spaceName, space ) {
12326					var cache = space.cache;
12327					each( space.props, function( key, prop ) {
12328
12329						// if the cache doesn't exist, and we know how to convert
12330						if ( !inst[ cache ] && space.to ) {
12331
12332							// if the value was null, we don't need to copy it
12333							// if the key was alpha, we don't need to copy it either
12334							if ( key === "alpha" || red[ key ] == null ) {
12335								return;
12336							}
12337							inst[ cache ] = space.to( inst._rgba );
12338						}
12339
12340						// this is the only case where we allow nulls for ALL properties.
12341						// call clamp with alwaysAllowEmpty
12342						inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true );
12343					} );
12344
12345					// everything defined but alpha?
12346					if ( inst[ cache ] && jQuery.inArray(
12347						null,
12348						inst[ cache ].slice( 0, 3 )
12349					) < 0 ) {
12350
12351						// use the default of 1
12352						if ( inst[ cache ][ 3 ] == null ) {
12353							inst[ cache ][ 3 ] = 1;
12354						}
12355
12356						if ( space.from ) {
12357							inst._rgba = space.from( inst[ cache ] );
12358						}
12359					}
12360				} );
12361			}
12362			return this;
12363		}
12364	},
12365	is: function( compare ) {
12366		var is = color( compare ),
12367			same = true,
12368			inst = this;
12369
12370		each( spaces, function( _, space ) {
12371			var localCache,
12372				isCache = is[ space.cache ];
12373			if ( isCache ) {
12374				localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || [];
12375				each( space.props, function( _, prop ) {
12376					if ( isCache[ prop.idx ] != null ) {
12377						same = ( isCache[ prop.idx ] === localCache[ prop.idx ] );
12378						return same;
12379					}
12380				} );
12381			}
12382			return same;
12383		} );
12384		return same;
12385	},
12386	_space: function() {
12387		var used = [],
12388			inst = this;
12389		each( spaces, function( spaceName, space ) {
12390			if ( inst[ space.cache ] ) {
12391				used.push( spaceName );
12392			}
12393		} );
12394		return used.pop();
12395	},
12396	transition: function( other, distance ) {
12397		var end = color( other ),
12398			spaceName = end._space(),
12399			space = spaces[ spaceName ],
12400			startColor = this.alpha() === 0 ? color( "transparent" ) : this,
12401			start = startColor[ space.cache ] || space.to( startColor._rgba ),
12402			result = start.slice();
12403
12404		end = end[ space.cache ];
12405		each( space.props, function( _key, prop ) {
12406			var index = prop.idx,
12407				startValue = start[ index ],
12408				endValue = end[ index ],
12409				type = propTypes[ prop.type ] || {};
12410
12411			// if null, don't override start value
12412			if ( endValue === null ) {
12413				return;
12414			}
12415
12416			// if null - use end
12417			if ( startValue === null ) {
12418				result[ index ] = endValue;
12419			} else {
12420				if ( type.mod ) {
12421					if ( endValue - startValue > type.mod / 2 ) {
12422						startValue += type.mod;
12423					} else if ( startValue - endValue > type.mod / 2 ) {
12424						startValue -= type.mod;
12425					}
12426				}
12427				result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop );
12428			}
12429		} );
12430		return this[ spaceName ]( result );
12431	},
12432	blend: function( opaque ) {
12433
12434		// if we are already opaque - return ourself
12435		if ( this._rgba[ 3 ] === 1 ) {
12436			return this;
12437		}
12438
12439		var rgb = this._rgba.slice(),
12440			a = rgb.pop(),
12441			blend = color( opaque )._rgba;
12442
12443		return color( jQuery.map( rgb, function( v, i ) {
12444			return ( 1 - a ) * blend[ i ] + a * v;
12445		} ) );
12446	},
12447	toRgbaString: function() {
12448		var prefix = "rgba(",
12449			rgba = jQuery.map( this._rgba, function( v, i ) {
12450				if ( v != null ) {
12451					return v;
12452				}
12453				return i > 2 ? 1 : 0;
12454			} );
12455
12456		if ( rgba[ 3 ] === 1 ) {
12457			rgba.pop();
12458			prefix = "rgb(";
12459		}
12460
12461		return prefix + rgba.join( ", " ) + ")";
12462	},
12463	toHslaString: function() {
12464		var prefix = "hsla(",
12465			hsla = jQuery.map( this.hsla(), function( v, i ) {
12466				if ( v == null ) {
12467					v = i > 2 ? 1 : 0;
12468				}
12469
12470				// catch 1 and 2
12471				if ( i && i < 3 ) {
12472					v = Math.round( v * 100 ) + "%";
12473				}
12474				return v;
12475			} );
12476
12477		if ( hsla[ 3 ] === 1 ) {
12478			hsla.pop();
12479			prefix = "hsl(";
12480		}
12481		return prefix + hsla.join( ", " ) + ")";
12482	},
12483	toHexString: function( includeAlpha ) {
12484		var rgba = this._rgba.slice(),
12485			alpha = rgba.pop();
12486
12487		if ( includeAlpha ) {
12488			rgba.push( ~~( alpha * 255 ) );
12489		}
12490
12491		return "#" + jQuery.map( rgba, function( v ) {
12492
12493			// default to 0 when nulls exist
12494			return ( "0" + ( v || 0 ).toString( 16 ) ).substr( -2 );
12495		} ).join( "" );
12496	},
12497	toString: function() {
12498		return this.toRgbaString();
12499	}
12500} );
12501color.fn.parse.prototype = color.fn;
12502
12503// hsla conversions adapted from:
12504// https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021
12505
12506function hue2rgb( p, q, h ) {
12507	h = ( h + 1 ) % 1;
12508	if ( h * 6 < 1 ) {
12509		return p + ( q - p ) * h * 6;
12510	}
12511	if ( h * 2 < 1 ) {
12512		return q;
12513	}
12514	if ( h * 3 < 2 ) {
12515		return p + ( q - p ) * ( ( 2 / 3 ) - h ) * 6;
12516	}
12517	return p;
12518}
12519
12520spaces.hsla.to = function( rgba ) {
12521	if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) {
12522		return [ null, null, null, rgba[ 3 ] ];
12523	}
12524	var r = rgba[ 0 ] / 255,
12525		g = rgba[ 1 ] / 255,
12526		b = rgba[ 2 ] / 255,
12527		a = rgba[ 3 ],
12528		max = Math.max( r, g, b ),
12529		min = Math.min( r, g, b ),
12530		diff = max - min,
12531		add = max + min,
12532		l = add * 0.5,
12533		h, s;
12534
12535	if ( min === max ) {
12536		h = 0;
12537	} else if ( r === max ) {
12538		h = ( 60 * ( g - b ) / diff ) + 360;
12539	} else if ( g === max ) {
12540		h = ( 60 * ( b - r ) / diff ) + 120;
12541	} else {
12542		h = ( 60 * ( r - g ) / diff ) + 240;
12543	}
12544
12545	// chroma (diff) == 0 means greyscale which, by definition, saturation = 0%
12546	// otherwise, saturation is based on the ratio of chroma (diff) to lightness (add)
12547	if ( diff === 0 ) {
12548		s = 0;
12549	} else if ( l <= 0.5 ) {
12550		s = diff / add;
12551	} else {
12552		s = diff / ( 2 - add );
12553	}
12554	return [ Math.round( h ) % 360, s, l, a == null ? 1 : a ];
12555};
12556
12557spaces.hsla.from = function( hsla ) {
12558	if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) {
12559		return [ null, null, null, hsla[ 3 ] ];
12560	}
12561	var h = hsla[ 0 ] / 360,
12562		s = hsla[ 1 ],
12563		l = hsla[ 2 ],
12564		a = hsla[ 3 ],
12565		q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s,
12566		p = 2 * l - q;
12567
12568	return [
12569		Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ),
12570		Math.round( hue2rgb( p, q, h ) * 255 ),
12571		Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ),
12572		a
12573	];
12574};
12575
12576
12577each( spaces, function( spaceName, space ) {
12578	var props = space.props,
12579		cache = space.cache,
12580		to = space.to,
12581		from = space.from;
12582
12583	// makes rgba() and hsla()
12584	color.fn[ spaceName ] = function( value ) {
12585
12586		// generate a cache for this space if it doesn't exist
12587		if ( to && !this[ cache ] ) {
12588			this[ cache ] = to( this._rgba );
12589		}
12590		if ( value === undefined ) {
12591			return this[ cache ].slice();
12592		}
12593
12594		var ret,
12595			type = getType( value ),
12596			arr = ( type === "array" || type === "object" ) ? value : arguments,
12597			local = this[ cache ].slice();
12598
12599		each( props, function( key, prop ) {
12600			var val = arr[ type === "object" ? key : prop.idx ];
12601			if ( val == null ) {
12602				val = local[ prop.idx ];
12603			}
12604			local[ prop.idx ] = clamp( val, prop );
12605		} );
12606
12607		if ( from ) {
12608			ret = color( from( local ) );
12609			ret[ cache ] = local;
12610			return ret;
12611		} else {
12612			return color( local );
12613		}
12614	};
12615
12616	// makes red() green() blue() alpha() hue() saturation() lightness()
12617	each( props, function( key, prop ) {
12618
12619		// alpha is included in more than one space
12620		if ( color.fn[ key ] ) {
12621			return;
12622		}
12623		color.fn[ key ] = function( value ) {
12624			var local, cur, match, fn,
12625				vtype = getType( value );
12626
12627			if ( key === "alpha" ) {
12628				fn = this._hsla ? "hsla" : "rgba";
12629			} else {
12630				fn = spaceName;
12631			}
12632			local = this[ fn ]();
12633			cur = local[ prop.idx ];
12634
12635			if ( vtype === "undefined" ) {
12636				return cur;
12637			}
12638
12639			if ( vtype === "function" ) {
12640				value = value.call( this, cur );
12641				vtype = getType( value );
12642			}
12643			if ( value == null && prop.empty ) {
12644				return this;
12645			}
12646			if ( vtype === "string" ) {
12647				match = rplusequals.exec( value );
12648				if ( match ) {
12649					value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 );
12650				}
12651			}
12652			local[ prop.idx ] = value;
12653			return this[ fn ]( local );
12654		};
12655	} );
12656} );
12657
12658// add cssHook and .fx.step function for each named hook.
12659// accept a space separated string of properties
12660color.hook = function( hook ) {
12661	var hooks = hook.split( " " );
12662	each( hooks, function( _i, hook ) {
12663		jQuery.cssHooks[ hook ] = {
12664			set: function( elem, value ) {
12665				var parsed;
12666
12667				if ( value !== "transparent" &&
12668					( getType( value ) !== "string" ||
12669						( parsed = stringParse( value ) ) ) ) {
12670					value = color( parsed || value );
12671					value = value.toRgbaString();
12672				}
12673				elem.style[ hook ] = value;
12674			}
12675		};
12676		jQuery.fx.step[ hook ] = function( fx ) {
12677			if ( !fx.colorInit ) {
12678				fx.start = color( fx.elem, hook );
12679				fx.end = color( fx.end );
12680				fx.colorInit = true;
12681			}
12682			jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) );
12683		};
12684	} );
12685
12686};
12687
12688color.hook( stepHooks );
12689
12690jQuery.cssHooks.borderColor = {
12691	expand: function( value ) {
12692		var expanded = {};
12693
12694		each( [ "Top", "Right", "Bottom", "Left" ], function( _i, part ) {
12695			expanded[ "border" + part + "Color" ] = value;
12696		} );
12697		return expanded;
12698	}
12699};
12700
12701// Basic color names only.
12702// Usage of any of the other color names requires adding yourself or including
12703// jquery.color.svg-names.js.
12704colors = jQuery.Color.names = {
12705
12706	// 4.1. Basic color keywords
12707	aqua: "#00ffff",
12708	black: "#000000",
12709	blue: "#0000ff",
12710	fuchsia: "#ff00ff",
12711	gray: "#808080",
12712	green: "#008000",
12713	lime: "#00ff00",
12714	maroon: "#800000",
12715	navy: "#000080",
12716	olive: "#808000",
12717	purple: "#800080",
12718	red: "#ff0000",
12719	silver: "#c0c0c0",
12720	teal: "#008080",
12721	white: "#ffffff",
12722	yellow: "#ffff00",
12723
12724	// 4.2.3. "transparent" color keyword
12725	transparent: [ null, null, null, 0 ],
12726
12727	_default: "#ffffff"
12728};
12729
12730
12731/*!
12732 * jQuery UI Effects 1.14.1
12733 * https://jqueryui.com
12734 *
12735 * Copyright OpenJS Foundation and other contributors
12736 * Released under the MIT license.
12737 * https://jquery.org/license
12738 */
12739
12740//>>label: Effects Core
12741//>>group: Effects
12742/* eslint-disable max-len */
12743//>>description: Extends the internal jQuery effects. Includes morphing and easing. Required by all other effects.
12744/* eslint-enable max-len */
12745//>>docs: https://api.jqueryui.com/category/effects-core/
12746//>>demos: https://jqueryui.com/effect/
12747
12748
12749var dataSpace = "ui-effects-",
12750	dataSpaceStyle = "ui-effects-style",
12751	dataSpaceAnimated = "ui-effects-animated";
12752
12753$.effects = {
12754	effect: {}
12755};
12756
12757/******************************************************************************/
12758/****************************** CLASS ANIMATIONS ******************************/
12759/******************************************************************************/
12760( function() {
12761
12762var classAnimationActions = [ "add", "remove", "toggle" ],
12763	shorthandStyles = {
12764		border: 1,
12765		borderBottom: 1,
12766		borderColor: 1,
12767		borderLeft: 1,
12768		borderRight: 1,
12769		borderTop: 1,
12770		borderWidth: 1,
12771		margin: 1,
12772		padding: 1
12773	};
12774
12775$.each(
12776	[ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ],
12777	function( _, prop ) {
12778		$.fx.step[ prop ] = function( fx ) {
12779			if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) {
12780				jQuery.style( fx.elem, prop, fx.end );
12781				fx.setAttr = true;
12782			}
12783		};
12784	}
12785);
12786
12787function camelCase( string ) {
12788	return string.replace( /-([\da-z])/gi, function( all, letter ) {
12789		return letter.toUpperCase();
12790	} );
12791}
12792
12793function getElementStyles( elem ) {
12794	var key, len,
12795		style = elem.ownerDocument.defaultView.getComputedStyle( elem ),
12796		styles = {};
12797
12798	len = style.length;
12799	while ( len-- ) {
12800		key = style[ len ];
12801		if ( typeof style[ key ] === "string" ) {
12802			styles[ camelCase( key ) ] = style[ key ];
12803		}
12804	}
12805
12806	return styles;
12807}
12808
12809function styleDifference( oldStyle, newStyle ) {
12810	var diff = {},
12811		name, value;
12812
12813	for ( name in newStyle ) {
12814		value = newStyle[ name ];
12815		if ( oldStyle[ name ] !== value ) {
12816			if ( !shorthandStyles[ name ] ) {
12817				if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) {
12818					diff[ name ] = value;
12819				}
12820			}
12821		}
12822	}
12823
12824	return diff;
12825}
12826
12827$.effects.animateClass = function( value, duration, easing, callback ) {
12828	var o = $.speed( duration, easing, callback );
12829
12830	return this.queue( function() {
12831		var animated = $( this ),
12832			baseClass = animated.attr( "class" ) || "",
12833			applyClassChange,
12834			allAnimations = o.children ? animated.find( "*" ).addBack() : animated;
12835
12836		// Map the animated objects to store the original styles.
12837		allAnimations = allAnimations.map( function() {
12838			var el = $( this );
12839			return {
12840				el: el,
12841				start: getElementStyles( this )
12842			};
12843		} );
12844
12845		// Apply class change
12846		applyClassChange = function() {
12847			$.each( classAnimationActions, function( i, action ) {
12848				if ( value[ action ] ) {
12849					animated[ action + "Class" ]( value[ action ] );
12850				}
12851			} );
12852		};
12853		applyClassChange();
12854
12855		// Map all animated objects again - calculate new styles and diff
12856		allAnimations = allAnimations.map( function() {
12857			this.end = getElementStyles( this.el[ 0 ] );
12858			this.diff = styleDifference( this.start, this.end );
12859			return this;
12860		} );
12861
12862		// Apply original class
12863		animated.attr( "class", baseClass );
12864
12865		// Map all animated objects again - this time collecting a promise
12866		allAnimations = allAnimations.map( function() {
12867			var styleInfo = this,
12868				dfd = $.Deferred(),
12869				opts = $.extend( {}, o, {
12870					queue: false,
12871					complete: function() {
12872						dfd.resolve( styleInfo );
12873					}
12874				} );
12875
12876			this.el.animate( this.diff, opts );
12877			return dfd.promise();
12878		} );
12879
12880		// Once all animations have completed:
12881		$.when.apply( $, allAnimations.get() ).done( function() {
12882
12883			// Set the final class
12884			applyClassChange();
12885
12886			// For each animated element,
12887			// clear all css properties that were animated
12888			$.each( arguments, function() {
12889				var el = this.el;
12890				$.each( this.diff, function( key ) {
12891					el.css( key, "" );
12892				} );
12893			} );
12894
12895			// This is guarnteed to be there if you use jQuery.speed()
12896			// it also handles dequeuing the next anim...
12897			o.complete.call( animated[ 0 ] );
12898		} );
12899	} );
12900};
12901
12902$.fn.extend( {
12903	addClass: ( function( orig ) {
12904		return function( classNames, speed, easing, callback ) {
12905			return speed ?
12906				$.effects.animateClass.call( this,
12907					{ add: classNames }, speed, easing, callback ) :
12908				orig.apply( this, arguments );
12909		};
12910	} )( $.fn.addClass ),
12911
12912	removeClass: ( function( orig ) {
12913		return function( classNames, speed, easing, callback ) {
12914			return arguments.length > 1 ?
12915				$.effects.animateClass.call( this,
12916					{ remove: classNames }, speed, easing, callback ) :
12917				orig.apply( this, arguments );
12918		};
12919	} )( $.fn.removeClass ),
12920
12921	toggleClass: ( function( orig ) {
12922		return function( classNames, force, speed, easing, callback ) {
12923			if ( typeof force === "boolean" || force === undefined ) {
12924				if ( !speed ) {
12925
12926					// Without speed parameter
12927					return orig.apply( this, arguments );
12928				} else {
12929					return $.effects.animateClass.call( this,
12930						( force ? { add: classNames } : { remove: classNames } ),
12931						speed, easing, callback );
12932				}
12933			} else {
12934
12935				// Without force parameter
12936				return $.effects.animateClass.call( this,
12937					{ toggle: classNames }, force, speed, easing );
12938			}
12939		};
12940	} )( $.fn.toggleClass ),
12941
12942	switchClass: function( remove, add, speed, easing, callback ) {
12943		return $.effects.animateClass.call( this, {
12944			add: add,
12945			remove: remove
12946		}, speed, easing, callback );
12947	}
12948} );
12949
12950} )();
12951
12952/******************************************************************************/
12953/*********************************** EFFECTS **********************************/
12954/******************************************************************************/
12955
12956( function() {
12957
12958if ( $.expr && $.expr.pseudos && $.expr.pseudos.animated ) {
12959	$.expr.pseudos.animated = ( function( orig ) {
12960		return function( elem ) {
12961			return !!$( elem ).data( dataSpaceAnimated ) || orig( elem );
12962		};
12963	} )( $.expr.pseudos.animated );
12964}
12965
12966if ( $.uiBackCompat === true ) {
12967	$.extend( $.effects, {
12968
12969		// Saves a set of properties in a data storage
12970		save: function( element, set ) {
12971			var i = 0, length = set.length;
12972			for ( ; i < length; i++ ) {
12973				if ( set[ i ] !== null ) {
12974					element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] );
12975				}
12976			}
12977		},
12978
12979		// Restores a set of previously saved properties from a data storage
12980		restore: function( element, set ) {
12981			var val, i = 0, length = set.length;
12982			for ( ; i < length; i++ ) {
12983				if ( set[ i ] !== null ) {
12984					val = element.data( dataSpace + set[ i ] );
12985					element.css( set[ i ], val );
12986				}
12987			}
12988		},
12989
12990		setMode: function( el, mode ) {
12991			if ( mode === "toggle" ) {
12992				mode = el.is( ":hidden" ) ? "show" : "hide";
12993			}
12994			return mode;
12995		},
12996
12997		// Wraps the element around a wrapper that copies position properties
12998		createWrapper: function( element ) {
12999
13000			// If the element is already wrapped, return it
13001			if ( element.parent().is( ".ui-effects-wrapper" ) ) {
13002				return element.parent();
13003			}
13004
13005			// Wrap the element
13006			var props = {
13007					width: element.outerWidth( true ),
13008					height: element.outerHeight( true ),
13009					"float": element.css( "float" )
13010				},
13011				wrapper = $( "<div></div>" )
13012					.addClass( "ui-effects-wrapper" )
13013					.css( {
13014						fontSize: "100%",
13015						background: "transparent",
13016						border: "none",
13017						margin: 0,
13018						padding: 0
13019					} ),
13020
13021				// Store the size in case width/height are defined in % - Fixes #5245
13022				size = {
13023					width: element.width(),
13024					height: element.height()
13025				},
13026				active = document.activeElement;
13027
13028			// Support: Firefox
13029			// Firefox incorrectly exposes anonymous content
13030			// https://bugzilla.mozilla.org/show_bug.cgi?id=561664
13031			try {
13032				// eslint-disable-next-line no-unused-expressions
13033				active.id;
13034			} catch ( e ) {
13035				active = document.body;
13036			}
13037
13038			element.wrap( wrapper );
13039
13040			// Fixes #7595 - Elements lose focus when wrapped.
13041			if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
13042				$( active ).trigger( "focus" );
13043			}
13044
13045			// Hotfix for jQuery 1.4 since some change in wrap() seems to actually
13046			// lose the reference to the wrapped element
13047			wrapper = element.parent();
13048
13049			// Transfer positioning properties to the wrapper
13050			if ( element.css( "position" ) === "static" ) {
13051				wrapper.css( { position: "relative" } );
13052				element.css( { position: "relative" } );
13053			} else {
13054				$.extend( props, {
13055					position: element.css( "position" ),
13056					zIndex: element.css( "z-index" )
13057				} );
13058				$.each( [ "top", "left", "bottom", "right" ], function( i, pos ) {
13059					props[ pos ] = element.css( pos );
13060					if ( isNaN( parseInt( props[ pos ], 10 ) ) ) {
13061						props[ pos ] = "auto";
13062					}
13063				} );
13064				element.css( {
13065					position: "relative",
13066					top: 0,
13067					left: 0,
13068					right: "auto",
13069					bottom: "auto"
13070				} );
13071			}
13072			element.css( size );
13073
13074			return wrapper.css( props ).show();
13075		},
13076
13077		removeWrapper: function( element ) {
13078			var active = document.activeElement;
13079
13080			if ( element.parent().is( ".ui-effects-wrapper" ) ) {
13081				element.parent().replaceWith( element );
13082
13083				// Fixes #7595 - Elements lose focus when wrapped.
13084				if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
13085					$( active ).trigger( "focus" );
13086				}
13087			}
13088
13089			return element;
13090		}
13091	} );
13092}
13093
13094$.extend( $.effects, {
13095	version: "1.14.1",
13096
13097	define: function( name, mode, effect ) {
13098		if ( !effect ) {
13099			effect = mode;
13100			mode = "effect";
13101		}
13102
13103		$.effects.effect[ name ] = effect;
13104		$.effects.effect[ name ].mode = mode;
13105
13106		return effect;
13107	},
13108
13109	scaledDimensions: function( element, percent, direction ) {
13110		if ( percent === 0 ) {
13111			return {
13112				height: 0,
13113				width: 0,
13114				outerHeight: 0,
13115				outerWidth: 0
13116			};
13117		}
13118
13119		var x = direction !== "horizontal" ? ( ( percent || 100 ) / 100 ) : 1,
13120			y = direction !== "vertical" ? ( ( percent || 100 ) / 100 ) : 1;
13121
13122		return {
13123			height: element.height() * y,
13124			width: element.width() * x,
13125			outerHeight: element.outerHeight() * y,
13126			outerWidth: element.outerWidth() * x
13127		};
13128
13129	},
13130
13131	clipToBox: function( animation ) {
13132		return {
13133			width: animation.clip.right - animation.clip.left,
13134			height: animation.clip.bottom - animation.clip.top,
13135			left: animation.clip.left,
13136			top: animation.clip.top
13137		};
13138	},
13139
13140	// Injects recently queued functions to be first in line (after "inprogress")
13141	unshift: function( element, queueLength, count ) {
13142		var queue = element.queue();
13143
13144		if ( queueLength > 1 ) {
13145			queue.splice.apply( queue,
13146				[ 1, 0 ].concat( queue.splice( queueLength, count ) ) );
13147		}
13148		element.dequeue();
13149	},
13150
13151	saveStyle: function( element ) {
13152		element.data( dataSpaceStyle, element[ 0 ].style.cssText );
13153	},
13154
13155	restoreStyle: function( element ) {
13156		element[ 0 ].style.cssText = element.data( dataSpaceStyle ) || "";
13157		element.removeData( dataSpaceStyle );
13158	},
13159
13160	mode: function( element, mode ) {
13161		var hidden = element.is( ":hidden" );
13162
13163		if ( mode === "toggle" ) {
13164			mode = hidden ? "show" : "hide";
13165		}
13166		if ( hidden ? mode === "hide" : mode === "show" ) {
13167			mode = "none";
13168		}
13169		return mode;
13170	},
13171
13172	// Translates a [top,left] array into a baseline value
13173	getBaseline: function( origin, original ) {
13174		var y, x;
13175
13176		switch ( origin[ 0 ] ) {
13177		case "top":
13178			y = 0;
13179			break;
13180		case "middle":
13181			y = 0.5;
13182			break;
13183		case "bottom":
13184			y = 1;
13185			break;
13186		default:
13187			y = origin[ 0 ] / original.height;
13188		}
13189
13190		switch ( origin[ 1 ] ) {
13191		case "left":
13192			x = 0;
13193			break;
13194		case "center":
13195			x = 0.5;
13196			break;
13197		case "right":
13198			x = 1;
13199			break;
13200		default:
13201			x = origin[ 1 ] / original.width;
13202		}
13203
13204		return {
13205			x: x,
13206			y: y
13207		};
13208	},
13209
13210	// Creates a placeholder element so that the original element can be made absolute
13211	createPlaceholder: function( element ) {
13212		var placeholder,
13213			cssPosition = element.css( "position" ),
13214			position = element.position();
13215
13216		// Lock in margins first to account for form elements, which
13217		// will change margin if you explicitly set height
13218		// see: https://jsfiddle.net/JZSMt/3/ https://bugs.webkit.org/show_bug.cgi?id=107380
13219		// Support: Safari
13220		element.css( {
13221			marginTop: element.css( "marginTop" ),
13222			marginBottom: element.css( "marginBottom" ),
13223			marginLeft: element.css( "marginLeft" ),
13224			marginRight: element.css( "marginRight" )
13225		} )
13226		.outerWidth( element.outerWidth() )
13227		.outerHeight( element.outerHeight() );
13228
13229		if ( /^(static|relative)/.test( cssPosition ) ) {
13230			cssPosition = "absolute";
13231
13232			placeholder = $( "<" + element[ 0 ].nodeName + ">" ).insertAfter( element ).css( {
13233
13234				// Convert inline to inline block to account for inline elements
13235				// that turn to inline block based on content (like img)
13236				display: /^(inline|ruby)/.test( element.css( "display" ) ) ?
13237					"inline-block" :
13238					"block",
13239				visibility: "hidden",
13240
13241				// Margins need to be set to account for margin collapse
13242				marginTop: element.css( "marginTop" ),
13243				marginBottom: element.css( "marginBottom" ),
13244				marginLeft: element.css( "marginLeft" ),
13245				marginRight: element.css( "marginRight" ),
13246				"float": element.css( "float" )
13247			} )
13248			.outerWidth( element.outerWidth() )
13249			.outerHeight( element.outerHeight() )
13250			.addClass( "ui-effects-placeholder" );
13251
13252			element.data( dataSpace + "placeholder", placeholder );
13253		}
13254
13255		element.css( {
13256			position: cssPosition,
13257			left: position.left,
13258			top: position.top
13259		} );
13260
13261		return placeholder;
13262	},
13263
13264	removePlaceholder: function( element ) {
13265		var dataKey = dataSpace + "placeholder",
13266				placeholder = element.data( dataKey );
13267
13268		if ( placeholder ) {
13269			placeholder.remove();
13270			element.removeData( dataKey );
13271		}
13272	},
13273
13274	// Removes a placeholder if it exists and restores
13275	// properties that were modified during placeholder creation
13276	cleanUp: function( element ) {
13277		$.effects.restoreStyle( element );
13278		$.effects.removePlaceholder( element );
13279	},
13280
13281	setTransition: function( element, list, factor, value ) {
13282		value = value || {};
13283		$.each( list, function( i, x ) {
13284			var unit = element.cssUnit( x );
13285			if ( unit[ 0 ] > 0 ) {
13286				value[ x ] = unit[ 0 ] * factor + unit[ 1 ];
13287			}
13288		} );
13289		return value;
13290	}
13291} );
13292
13293// Return an effect options object for the given parameters:
13294function _normalizeArguments( effect, options, speed, callback ) {
13295
13296	// Allow passing all options as the first parameter
13297	if ( $.isPlainObject( effect ) ) {
13298		options = effect;
13299		effect = effect.effect;
13300	}
13301
13302	// Convert to an object
13303	effect = { effect: effect };
13304
13305	// Catch (effect, null, ...)
13306	if ( options == null ) {
13307		options = {};
13308	}
13309
13310	// Catch (effect, callback)
13311	if ( typeof options === "function" ) {
13312		callback = options;
13313		speed = null;
13314		options = {};
13315	}
13316
13317	// Catch (effect, speed, ?)
13318	if ( typeof options === "number" || $.fx.speeds[ options ] ) {
13319		callback = speed;
13320		speed = options;
13321		options = {};
13322	}
13323
13324	// Catch (effect, options, callback)
13325	if ( typeof speed === "function" ) {
13326		callback = speed;
13327		speed = null;
13328	}
13329
13330	// Add options to effect
13331	if ( options ) {
13332		$.extend( effect, options );
13333	}
13334
13335	speed = speed || options.duration;
13336	effect.duration = $.fx.off ? 0 :
13337		typeof speed === "number" ? speed :
13338		speed in $.fx.speeds ? $.fx.speeds[ speed ] :
13339		$.fx.speeds._default;
13340
13341	effect.complete = callback || options.complete;
13342
13343	return effect;
13344}
13345
13346function standardAnimationOption( option ) {
13347
13348	// Valid standard speeds (nothing, number, named speed)
13349	if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) {
13350		return true;
13351	}
13352
13353	// Invalid strings - treat as "normal" speed
13354	if ( typeof option === "string" && !$.effects.effect[ option ] ) {
13355		return true;
13356	}
13357
13358	// Complete callback
13359	if ( typeof option === "function" ) {
13360		return true;
13361	}
13362
13363	// Options hash (but not naming an effect)
13364	if ( typeof option === "object" && !option.effect ) {
13365		return true;
13366	}
13367
13368	// Didn't match any standard API
13369	return false;
13370}
13371
13372$.fn.extend( {
13373	effect: function( /* effect, options, speed, callback */ ) {
13374		var args = _normalizeArguments.apply( this, arguments ),
13375			effectMethod = $.effects.effect[ args.effect ],
13376			defaultMode = effectMethod.mode,
13377			queue = args.queue,
13378			queueName = queue || "fx",
13379			complete = args.complete,
13380			mode = args.mode,
13381			modes = [],
13382			prefilter = function( next ) {
13383				var el = $( this ),
13384					normalizedMode = $.effects.mode( el, mode ) || defaultMode;
13385
13386				// Sentinel for duck-punching the :animated pseudo-selector
13387				el.data( dataSpaceAnimated, true );
13388
13389				// Save effect mode for later use,
13390				// we can't just call $.effects.mode again later,
13391				// as the .show() below destroys the initial state
13392				modes.push( normalizedMode );
13393
13394				// See $.uiBackCompat inside of run() for removal of defaultMode in 1.14
13395				if ( defaultMode && ( normalizedMode === "show" ||
13396						( normalizedMode === defaultMode && normalizedMode === "hide" ) ) ) {
13397					el.show();
13398				}
13399
13400				if ( !defaultMode || normalizedMode !== "none" ) {
13401					$.effects.saveStyle( el );
13402				}
13403
13404				if ( typeof next === "function" ) {
13405					next();
13406				}
13407			};
13408
13409		if ( $.fx.off || !effectMethod ) {
13410
13411			// Delegate to the original method (e.g., .show()) if possible
13412			if ( mode ) {
13413				return this[ mode ]( args.duration, complete );
13414			} else {
13415				return this.each( function() {
13416					if ( complete ) {
13417						complete.call( this );
13418					}
13419				} );
13420			}
13421		}
13422
13423		function run( next ) {
13424			var elem = $( this );
13425
13426			function cleanup() {
13427				elem.removeData( dataSpaceAnimated );
13428
13429				$.effects.cleanUp( elem );
13430
13431				if ( args.mode === "hide" ) {
13432					elem.hide();
13433				}
13434
13435				done();
13436			}
13437
13438			function done() {
13439				if ( typeof complete === "function" ) {
13440					complete.call( elem[ 0 ] );
13441				}
13442
13443				if ( typeof next === "function" ) {
13444					next();
13445				}
13446			}
13447
13448			// Override mode option on a per element basis,
13449			// as toggle can be either show or hide depending on element state
13450			args.mode = modes.shift();
13451
13452			if ( $.uiBackCompat === true && !defaultMode ) {
13453				if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) {
13454
13455					// Call the core method to track "olddisplay" properly
13456					elem[ mode ]();
13457					done();
13458				} else {
13459					effectMethod.call( elem[ 0 ], args, done );
13460				}
13461			} else {
13462				if ( args.mode === "none" ) {
13463
13464					// Call the core method to track "olddisplay" properly
13465					elem[ mode ]();
13466					done();
13467				} else {
13468					effectMethod.call( elem[ 0 ], args, cleanup );
13469				}
13470			}
13471		}
13472
13473		// Run prefilter on all elements first to ensure that
13474		// any showing or hiding happens before placeholder creation,
13475		// which ensures that any layout changes are correctly captured.
13476		return queue === false ?
13477			this.each( prefilter ).each( run ) :
13478			this.queue( queueName, prefilter ).queue( queueName, run );
13479	},
13480
13481	show: ( function( orig ) {
13482		return function( option ) {
13483			if ( standardAnimationOption( option ) ) {
13484				return orig.apply( this, arguments );
13485			} else {
13486				var args = _normalizeArguments.apply( this, arguments );
13487				args.mode = "show";
13488				return this.effect.call( this, args );
13489			}
13490		};
13491	} )( $.fn.show ),
13492
13493	hide: ( function( orig ) {
13494		return function( option ) {
13495			if ( standardAnimationOption( option ) ) {
13496				return orig.apply( this, arguments );
13497			} else {
13498				var args = _normalizeArguments.apply( this, arguments );
13499				args.mode = "hide";
13500				return this.effect.call( this, args );
13501			}
13502		};
13503	} )( $.fn.hide ),
13504
13505	toggle: ( function( orig ) {
13506		return function( option ) {
13507			if ( standardAnimationOption( option ) || typeof option === "boolean" ) {
13508				return orig.apply( this, arguments );
13509			} else {
13510				var args = _normalizeArguments.apply( this, arguments );
13511				args.mode = "toggle";
13512				return this.effect.call( this, args );
13513			}
13514		};
13515	} )( $.fn.toggle ),
13516
13517	cssUnit: function( key ) {
13518		var style = this.css( key ),
13519			val = [];
13520
13521		$.each( [ "em", "px", "%", "pt" ], function( i, unit ) {
13522			if ( style.indexOf( unit ) > 0 ) {
13523				val = [ parseFloat( style ), unit ];
13524			}
13525		} );
13526		return val;
13527	},
13528
13529	cssClip: function( clipObj ) {
13530		if ( clipObj ) {
13531			return this.css( "clip", "rect(" + clipObj.top + "px " + clipObj.right + "px " +
13532				clipObj.bottom + "px " + clipObj.left + "px)" );
13533		}
13534		return parseClip( this.css( "clip" ), this );
13535	},
13536
13537	transfer: function( options, done ) {
13538		var element = $( this ),
13539			target = $( options.to ),
13540			targetFixed = target.css( "position" ) === "fixed",
13541			body = $( "body" ),
13542			fixTop = targetFixed ? body.scrollTop() : 0,
13543			fixLeft = targetFixed ? body.scrollLeft() : 0,
13544			endPosition = target.offset(),
13545			animation = {
13546				top: endPosition.top - fixTop,
13547				left: endPosition.left - fixLeft,
13548				height: target.innerHeight(),
13549				width: target.innerWidth()
13550			},
13551			startPosition = element.offset(),
13552			transfer = $( "<div class='ui-effects-transfer'></div>" );
13553
13554		transfer
13555			.appendTo( "body" )
13556			.addClass( options.className )
13557			.css( {
13558				top: startPosition.top - fixTop,
13559				left: startPosition.left - fixLeft,
13560				height: element.innerHeight(),
13561				width: element.innerWidth(),
13562				position: targetFixed ? "fixed" : "absolute"
13563			} )
13564			.animate( animation, options.duration, options.easing, function() {
13565				transfer.remove();
13566				if ( typeof done === "function" ) {
13567					done();
13568				}
13569			} );
13570	}
13571} );
13572
13573function parseClip( str, element ) {
13574		var outerWidth = element.outerWidth(),
13575			outerHeight = element.outerHeight(),
13576			clipRegex = /^rect\((-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto)\)$/,
13577			values = clipRegex.exec( str ) || [ "", 0, outerWidth, outerHeight, 0 ];
13578
13579		return {
13580			top: parseFloat( values[ 1 ] ) || 0,
13581			right: values[ 2 ] === "auto" ? outerWidth : parseFloat( values[ 2 ] ),
13582			bottom: values[ 3 ] === "auto" ? outerHeight : parseFloat( values[ 3 ] ),
13583			left: parseFloat( values[ 4 ] ) || 0
13584		};
13585}
13586
13587$.fx.step.clip = function( fx ) {
13588	if ( !fx.clipInit ) {
13589		fx.start = $( fx.elem ).cssClip();
13590		if ( typeof fx.end === "string" ) {
13591			fx.end = parseClip( fx.end, fx.elem );
13592		}
13593		fx.clipInit = true;
13594	}
13595
13596	$( fx.elem ).cssClip( {
13597		top: fx.pos * ( fx.end.top - fx.start.top ) + fx.start.top,
13598		right: fx.pos * ( fx.end.right - fx.start.right ) + fx.start.right,
13599		bottom: fx.pos * ( fx.end.bottom - fx.start.bottom ) + fx.start.bottom,
13600		left: fx.pos * ( fx.end.left - fx.start.left ) + fx.start.left
13601	} );
13602};
13603
13604} )();
13605
13606/******************************************************************************/
13607/*********************************** EASING ***********************************/
13608/******************************************************************************/
13609
13610( function() {
13611
13612// Based on easing equations from Robert Penner (http://robertpenner.com/easing)
13613
13614var baseEasings = {};
13615
13616$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) {
13617	baseEasings[ name ] = function( p ) {
13618		return Math.pow( p, i + 2 );
13619	};
13620} );
13621
13622$.extend( baseEasings, {
13623	Sine: function( p ) {
13624		return 1 - Math.cos( p * Math.PI / 2 );
13625	},
13626	Circ: function( p ) {
13627		return 1 - Math.sqrt( 1 - p * p );
13628	},
13629	Elastic: function( p ) {
13630		return p === 0 || p === 1 ? p :
13631			-Math.pow( 2, 8 * ( p - 1 ) ) * Math.sin( ( ( p - 1 ) * 80 - 7.5 ) * Math.PI / 15 );
13632	},
13633	Back: function( p ) {
13634		return p * p * ( 3 * p - 2 );
13635	},
13636	Bounce: function( p ) {
13637		var pow2,
13638			bounce = 4;
13639
13640		while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}
13641		return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 );
13642	}
13643} );
13644
13645$.each( baseEasings, function( name, easeIn ) {
13646	$.easing[ "easeIn" + name ] = easeIn;
13647	$.easing[ "easeOut" + name ] = function( p ) {
13648		return 1 - easeIn( 1 - p );
13649	};
13650	$.easing[ "easeInOut" + name ] = function( p ) {
13651		return p < 0.5 ?
13652			easeIn( p * 2 ) / 2 :
13653			1 - easeIn( p * -2 + 2 ) / 2;
13654	};
13655} );
13656
13657} )();
13658
13659var effect = $.effects;
13660
13661
13662/*!
13663 * jQuery UI Effects Blind 1.14.1
13664 * https://jqueryui.com
13665 *
13666 * Copyright OpenJS Foundation and other contributors
13667 * Released under the MIT license.
13668 * https://jquery.org/license
13669 */
13670
13671//>>label: Blind Effect
13672//>>group: Effects
13673//>>description: Blinds the element.
13674//>>docs: https://api.jqueryui.com/blind-effect/
13675//>>demos: https://jqueryui.com/effect/
13676
13677
13678var effectsEffectBlind = $.effects.define( "blind", "hide", function( options, done ) {
13679	var map = {
13680			up: [ "bottom", "top" ],
13681			vertical: [ "bottom", "top" ],
13682			down: [ "top", "bottom" ],
13683			left: [ "right", "left" ],
13684			horizontal: [ "right", "left" ],
13685			right: [ "left", "right" ]
13686		},
13687		element = $( this ),
13688		direction = options.direction || "up",
13689		start = element.cssClip(),
13690		animate = { clip: $.extend( {}, start ) },
13691		placeholder = $.effects.createPlaceholder( element );
13692
13693	animate.clip[ map[ direction ][ 0 ] ] = animate.clip[ map[ direction ][ 1 ] ];
13694
13695	if ( options.mode === "show" ) {
13696		element.cssClip( animate.clip );
13697		if ( placeholder ) {
13698			placeholder.css( $.effects.clipToBox( animate ) );
13699		}
13700
13701		animate.clip = start;
13702	}
13703
13704	if ( placeholder ) {
13705		placeholder.animate( $.effects.clipToBox( animate ), options.duration, options.easing );
13706	}
13707
13708	element.animate( animate, {
13709		queue: false,
13710		duration: options.duration,
13711		easing: options.easing,
13712		complete: done
13713	} );
13714} );
13715
13716
13717/*!
13718 * jQuery UI Effects Bounce 1.14.1
13719 * https://jqueryui.com
13720 *
13721 * Copyright OpenJS Foundation and other contributors
13722 * Released under the MIT license.
13723 * https://jquery.org/license
13724 */
13725
13726//>>label: Bounce Effect
13727//>>group: Effects
13728//>>description: Bounces an element horizontally or vertically n times.
13729//>>docs: https://api.jqueryui.com/bounce-effect/
13730//>>demos: https://jqueryui.com/effect/
13731
13732
13733var effectsEffectBounce = $.effects.define( "bounce", function( options, done ) {
13734	var upAnim, downAnim, refValue,
13735		element = $( this ),
13736
13737		// Defaults:
13738		mode = options.mode,
13739		hide = mode === "hide",
13740		show = mode === "show",
13741		direction = options.direction || "up",
13742		distance = options.distance,
13743		times = options.times || 5,
13744
13745		// Number of internal animations
13746		anims = times * 2 + ( show || hide ? 1 : 0 ),
13747		speed = options.duration / anims,
13748		easing = options.easing,
13749
13750		// Utility:
13751		ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
13752		motion = ( direction === "up" || direction === "left" ),
13753		i = 0,
13754
13755		queuelen = element.queue().length;
13756
13757	$.effects.createPlaceholder( element );
13758
13759	refValue = element.css( ref );
13760
13761	// Default distance for the BIGGEST bounce is the outer Distance / 3
13762	if ( !distance ) {
13763		distance = element[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3;
13764	}
13765
13766	if ( show ) {
13767		downAnim = { opacity: 1 };
13768		downAnim[ ref ] = refValue;
13769
13770		// If we are showing, force opacity 0 and set the initial position
13771		// then do the "first" animation
13772		element
13773			.css( "opacity", 0 )
13774			.css( ref, motion ? -distance * 2 : distance * 2 )
13775			.animate( downAnim, speed, easing );
13776	}
13777
13778	// Start at the smallest distance if we are hiding
13779	if ( hide ) {
13780		distance = distance / Math.pow( 2, times - 1 );
13781	}
13782
13783	downAnim = {};
13784	downAnim[ ref ] = refValue;
13785
13786	// Bounces up/down/left/right then back to 0 -- times * 2 animations happen here
13787	for ( ; i < times; i++ ) {
13788		upAnim = {};
13789		upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
13790
13791		element
13792			.animate( upAnim, speed, easing )
13793			.animate( downAnim, speed, easing );
13794
13795		distance = hide ? distance * 2 : distance / 2;
13796	}
13797
13798	// Last Bounce when Hiding
13799	if ( hide ) {
13800		upAnim = { opacity: 0 };
13801		upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
13802
13803		element.animate( upAnim, speed, easing );
13804	}
13805
13806	element.queue( done );
13807
13808	$.effects.unshift( element, queuelen, anims + 1 );
13809} );
13810
13811
13812/*!
13813 * jQuery UI Effects Clip 1.14.1
13814 * https://jqueryui.com
13815 *
13816 * Copyright OpenJS Foundation and other contributors
13817 * Released under the MIT license.
13818 * https://jquery.org/license
13819 */
13820
13821//>>label: Clip Effect
13822//>>group: Effects
13823//>>description: Clips the element on and off like an old TV.
13824//>>docs: https://api.jqueryui.com/clip-effect/
13825//>>demos: https://jqueryui.com/effect/
13826
13827
13828var effectsEffectClip = $.effects.define( "clip", "hide", function( options, done ) {
13829	var start,
13830		animate = {},
13831		element = $( this ),
13832		direction = options.direction || "vertical",
13833		both = direction === "both",
13834		horizontal = both || direction === "horizontal",
13835		vertical = both || direction === "vertical";
13836
13837	start = element.cssClip();
13838	animate.clip = {
13839		top: vertical ? ( start.bottom - start.top ) / 2 : start.top,
13840		right: horizontal ? ( start.right - start.left ) / 2 : start.right,
13841		bottom: vertical ? ( start.bottom - start.top ) / 2 : start.bottom,
13842		left: horizontal ? ( start.right - start.left ) / 2 : start.left
13843	};
13844
13845	$.effects.createPlaceholder( element );
13846
13847	if ( options.mode === "show" ) {
13848		element.cssClip( animate.clip );
13849		animate.clip = start;
13850	}
13851
13852	element.animate( animate, {
13853		queue: false,
13854		duration: options.duration,
13855		easing: options.easing,
13856		complete: done
13857	} );
13858
13859} );
13860
13861
13862/*!
13863 * jQuery UI Effects Drop 1.14.1
13864 * https://jqueryui.com
13865 *
13866 * Copyright OpenJS Foundation and other contributors
13867 * Released under the MIT license.
13868 * https://jquery.org/license
13869 */
13870
13871//>>label: Drop Effect
13872//>>group: Effects
13873//>>description: Moves an element in one direction and hides it at the same time.
13874//>>docs: https://api.jqueryui.com/drop-effect/
13875//>>demos: https://jqueryui.com/effect/
13876
13877
13878var effectsEffectDrop = $.effects.define( "drop", "hide", function( options, done ) {
13879
13880	var distance,
13881		element = $( this ),
13882		mode = options.mode,
13883		show = mode === "show",
13884		direction = options.direction || "left",
13885		ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
13886		motion = ( direction === "up" || direction === "left" ) ? "-=" : "+=",
13887		oppositeMotion = ( motion === "+=" ) ? "-=" : "+=",
13888		animation = {
13889			opacity: 0
13890		};
13891
13892	$.effects.createPlaceholder( element );
13893
13894	distance = options.distance ||
13895		element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ) / 2;
13896
13897	animation[ ref ] = motion + distance;
13898
13899	if ( show ) {
13900		element.css( animation );
13901
13902		animation[ ref ] = oppositeMotion + distance;
13903		animation.opacity = 1;
13904	}
13905
13906	// Animate
13907	element.animate( animation, {
13908		queue: false,
13909		duration: options.duration,
13910		easing: options.easing,
13911		complete: done
13912	} );
13913} );
13914
13915
13916/*!
13917 * jQuery UI Effects Explode 1.14.1
13918 * https://jqueryui.com
13919 *
13920 * Copyright OpenJS Foundation and other contributors
13921 * Released under the MIT license.
13922 * https://jquery.org/license
13923 */
13924
13925//>>label: Explode Effect
13926//>>group: Effects
13927/* eslint-disable max-len */
13928//>>description: Explodes an element in all directions into n pieces. Implodes an element to its original wholeness.
13929/* eslint-enable max-len */
13930//>>docs: https://api.jqueryui.com/explode-effect/
13931//>>demos: https://jqueryui.com/effect/
13932
13933
13934var effectsEffectExplode = $.effects.define( "explode", "hide", function( options, done ) {
13935
13936	var i, j, left, top, mx, my,
13937		rows = options.pieces ? Math.round( Math.sqrt( options.pieces ) ) : 3,
13938		cells = rows,
13939		element = $( this ),
13940		mode = options.mode,
13941		show = mode === "show",
13942
13943		// Show and then visibility:hidden the element before calculating offset
13944		offset = element.show().css( "visibility", "hidden" ).offset(),
13945
13946		// Width and height of a piece
13947		width = Math.ceil( element.outerWidth() / cells ),
13948		height = Math.ceil( element.outerHeight() / rows ),
13949		pieces = [];
13950
13951	// Children animate complete:
13952	function childComplete() {
13953		pieces.push( this );
13954		if ( pieces.length === rows * cells ) {
13955			animComplete();
13956		}
13957	}
13958
13959	// Clone the element for each row and cell.
13960	for ( i = 0; i < rows; i++ ) { // ===>
13961		top = offset.top + i * height;
13962		my = i - ( rows - 1 ) / 2;
13963
13964		for ( j = 0; j < cells; j++ ) { // |||
13965			left = offset.left + j * width;
13966			mx = j - ( cells - 1 ) / 2;
13967
13968			// Create a clone of the now hidden main element that will be absolute positioned
13969			// within a wrapper div off the -left and -top equal to size of our pieces
13970			element
13971				.clone()
13972				.appendTo( "body" )
13973				.wrap( "<div></div>" )
13974				.css( {
13975					position: "absolute",
13976					visibility: "visible",
13977					left: -j * width,
13978					top: -i * height
13979				} )
13980
13981				// Select the wrapper - make it overflow: hidden and absolute positioned based on
13982				// where the original was located +left and +top equal to the size of pieces
13983				.parent()
13984					.addClass( "ui-effects-explode" )
13985					.css( {
13986						position: "absolute",
13987						overflow: "hidden",
13988						width: width,
13989						height: height,
13990						left: left + ( show ? mx * width : 0 ),
13991						top: top + ( show ? my * height : 0 ),
13992						opacity: show ? 0 : 1
13993					} )
13994					.animate( {
13995						left: left + ( show ? 0 : mx * width ),
13996						top: top + ( show ? 0 : my * height ),
13997						opacity: show ? 1 : 0
13998					}, options.duration || 500, options.easing, childComplete );
13999		}
14000	}
14001
14002	function animComplete() {
14003		element.css( {
14004			visibility: "visible"
14005		} );
14006		$( pieces ).remove();
14007		done();
14008	}
14009} );
14010
14011
14012/*!
14013 * jQuery UI Effects Fade 1.14.1
14014 * https://jqueryui.com
14015 *
14016 * Copyright OpenJS Foundation and other contributors
14017 * Released under the MIT license.
14018 * https://jquery.org/license
14019 */
14020
14021//>>label: Fade Effect
14022//>>group: Effects
14023//>>description: Fades the element.
14024//>>docs: https://api.jqueryui.com/fade-effect/
14025//>>demos: https://jqueryui.com/effect/
14026
14027
14028var effectsEffectFade = $.effects.define( "fade", "toggle", function( options, done ) {
14029	var show = options.mode === "show";
14030
14031	$( this )
14032		.css( "opacity", show ? 0 : 1 )
14033		.animate( {
14034			opacity: show ? 1 : 0
14035		}, {
14036			queue: false,
14037			duration: options.duration,
14038			easing: options.easing,
14039			complete: done
14040		} );
14041} );
14042
14043
14044/*!
14045 * jQuery UI Effects Fold 1.14.1
14046 * https://jqueryui.com
14047 *
14048 * Copyright OpenJS Foundation and other contributors
14049 * Released under the MIT license.
14050 * https://jquery.org/license
14051 */
14052
14053//>>label: Fold Effect
14054//>>group: Effects
14055//>>description: Folds an element first horizontally and then vertically.
14056//>>docs: https://api.jqueryui.com/fold-effect/
14057//>>demos: https://jqueryui.com/effect/
14058
14059
14060var effectsEffectFold = $.effects.define( "fold", "hide", function( options, done ) {
14061
14062	// Create element
14063	var element = $( this ),
14064		mode = options.mode,
14065		show = mode === "show",
14066		hide = mode === "hide",
14067		size = options.size || 15,
14068		percent = /([0-9]+)%/.exec( size ),
14069		horizFirst = !!options.horizFirst,
14070		ref = horizFirst ? [ "right", "bottom" ] : [ "bottom", "right" ],
14071		duration = options.duration / 2,
14072
14073		placeholder = $.effects.createPlaceholder( element ),
14074
14075		start = element.cssClip(),
14076		animation1 = { clip: $.extend( {}, start ) },
14077		animation2 = { clip: $.extend( {}, start ) },
14078
14079		distance = [ start[ ref[ 0 ] ], start[ ref[ 1 ] ] ],
14080
14081		queuelen = element.queue().length;
14082
14083	if ( percent ) {
14084		size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ];
14085	}
14086	animation1.clip[ ref[ 0 ] ] = size;
14087	animation2.clip[ ref[ 0 ] ] = size;
14088	animation2.clip[ ref[ 1 ] ] = 0;
14089
14090	if ( show ) {
14091		element.cssClip( animation2.clip );
14092		if ( placeholder ) {
14093			placeholder.css( $.effects.clipToBox( animation2 ) );
14094		}
14095
14096		animation2.clip = start;
14097	}
14098
14099	// Animate
14100	element
14101		.queue( function( next ) {
14102			if ( placeholder ) {
14103				placeholder
14104					.animate( $.effects.clipToBox( animation1 ), duration, options.easing )
14105					.animate( $.effects.clipToBox( animation2 ), duration, options.easing );
14106			}
14107
14108			next();
14109		} )
14110		.animate( animation1, duration, options.easing )
14111		.animate( animation2, duration, options.easing )
14112		.queue( done );
14113
14114	$.effects.unshift( element, queuelen, 4 );
14115} );
14116
14117
14118/*!
14119 * jQuery UI Effects Highlight 1.14.1
14120 * https://jqueryui.com
14121 *
14122 * Copyright OpenJS Foundation and other contributors
14123 * Released under the MIT license.
14124 * https://jquery.org/license
14125 */
14126
14127//>>label: Highlight Effect
14128//>>group: Effects
14129//>>description: Highlights the background of an element in a defined color for a custom duration.
14130//>>docs: https://api.jqueryui.com/highlight-effect/
14131//>>demos: https://jqueryui.com/effect/
14132
14133
14134var effectsEffectHighlight = $.effects.define( "highlight", "show", function( options, done ) {
14135	var element = $( this ),
14136		animation = {
14137			backgroundColor: element.css( "backgroundColor" )
14138		};
14139
14140	if ( options.mode === "hide" ) {
14141		animation.opacity = 0;
14142	}
14143
14144	$.effects.saveStyle( element );
14145
14146	element
14147		.css( {
14148			backgroundImage: "none",
14149			backgroundColor: options.color || "#ffff99"
14150		} )
14151		.animate( animation, {
14152			queue: false,
14153			duration: options.duration,
14154			easing: options.easing,
14155			complete: done
14156		} );
14157} );
14158
14159
14160/*!
14161 * jQuery UI Effects Size 1.14.1
14162 * https://jqueryui.com
14163 *
14164 * Copyright OpenJS Foundation and other contributors
14165 * Released under the MIT license.
14166 * https://jquery.org/license
14167 */
14168
14169//>>label: Size Effect
14170//>>group: Effects
14171//>>description: Resize an element to a specified width and height.
14172//>>docs: https://api.jqueryui.com/size-effect/
14173//>>demos: https://jqueryui.com/effect/
14174
14175
14176var effectsEffectSize = $.effects.define( "size", function( options, done ) {
14177
14178	// Create element
14179	var baseline, factor, temp,
14180		element = $( this ),
14181
14182		// Copy for children
14183		cProps = [ "fontSize" ],
14184		vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ],
14185		hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ],
14186
14187		// Set options
14188		mode = options.mode,
14189		restore = mode !== "effect",
14190		scale = options.scale || "both",
14191		origin = options.origin || [ "middle", "center" ],
14192		position = element.css( "position" ),
14193		pos = element.position(),
14194		original = $.effects.scaledDimensions( element ),
14195		from = options.from || original,
14196		to = options.to || $.effects.scaledDimensions( element, 0 );
14197
14198	$.effects.createPlaceholder( element );
14199
14200	if ( mode === "show" ) {
14201		temp = from;
14202		from = to;
14203		to = temp;
14204	}
14205
14206	// Set scaling factor
14207	factor = {
14208		from: {
14209			y: from.height / original.height,
14210			x: from.width / original.width
14211		},
14212		to: {
14213			y: to.height / original.height,
14214			x: to.width / original.width
14215		}
14216	};
14217
14218	// Scale the css box
14219	if ( scale === "box" || scale === "both" ) {
14220
14221		// Vertical props scaling
14222		if ( factor.from.y !== factor.to.y ) {
14223			from = $.effects.setTransition( element, vProps, factor.from.y, from );
14224			to = $.effects.setTransition( element, vProps, factor.to.y, to );
14225		}
14226
14227		// Horizontal props scaling
14228		if ( factor.from.x !== factor.to.x ) {
14229			from = $.effects.setTransition( element, hProps, factor.from.x, from );
14230			to = $.effects.setTransition( element, hProps, factor.to.x, to );
14231		}
14232	}
14233
14234	// Scale the content
14235	if ( scale === "content" || scale === "both" ) {
14236
14237		// Vertical props scaling
14238		if ( factor.from.y !== factor.to.y ) {
14239			from = $.effects.setTransition( element, cProps, factor.from.y, from );
14240			to = $.effects.setTransition( element, cProps, factor.to.y, to );
14241		}
14242	}
14243
14244	// Adjust the position properties based on the provided origin points
14245	if ( origin ) {
14246		baseline = $.effects.getBaseline( origin, original );
14247		from.top = ( original.outerHeight - from.outerHeight ) * baseline.y + pos.top;
14248		from.left = ( original.outerWidth - from.outerWidth ) * baseline.x + pos.left;
14249		to.top = ( original.outerHeight - to.outerHeight ) * baseline.y + pos.top;
14250		to.left = ( original.outerWidth - to.outerWidth ) * baseline.x + pos.left;
14251	}
14252	delete from.outerHeight;
14253	delete from.outerWidth;
14254	element.css( from );
14255
14256	// Animate the children if desired
14257	if ( scale === "content" || scale === "both" ) {
14258
14259		vProps = vProps.concat( [ "marginTop", "marginBottom" ] ).concat( cProps );
14260		hProps = hProps.concat( [ "marginLeft", "marginRight" ] );
14261
14262		// Only animate children with width attributes specified
14263		// TODO: is this right? should we include anything with css width specified as well
14264		element.find( "*[width]" ).each( function() {
14265			var child = $( this ),
14266				childOriginal = $.effects.scaledDimensions( child ),
14267				childFrom = {
14268					height: childOriginal.height * factor.from.y,
14269					width: childOriginal.width * factor.from.x,
14270					outerHeight: childOriginal.outerHeight * factor.from.y,
14271					outerWidth: childOriginal.outerWidth * factor.from.x
14272				},
14273				childTo = {
14274					height: childOriginal.height * factor.to.y,
14275					width: childOriginal.width * factor.to.x,
14276					outerHeight: childOriginal.height * factor.to.y,
14277					outerWidth: childOriginal.width * factor.to.x
14278				};
14279
14280			// Vertical props scaling
14281			if ( factor.from.y !== factor.to.y ) {
14282				childFrom = $.effects.setTransition( child, vProps, factor.from.y, childFrom );
14283				childTo = $.effects.setTransition( child, vProps, factor.to.y, childTo );
14284			}
14285
14286			// Horizontal props scaling
14287			if ( factor.from.x !== factor.to.x ) {
14288				childFrom = $.effects.setTransition( child, hProps, factor.from.x, childFrom );
14289				childTo = $.effects.setTransition( child, hProps, factor.to.x, childTo );
14290			}
14291
14292			if ( restore ) {
14293				$.effects.saveStyle( child );
14294			}
14295
14296			// Animate children
14297			child.css( childFrom );
14298			child.animate( childTo, options.duration, options.easing, function() {
14299
14300				// Restore children
14301				if ( restore ) {
14302					$.effects.restoreStyle( child );
14303				}
14304			} );
14305		} );
14306	}
14307
14308	// Animate
14309	element.animate( to, {
14310		queue: false,
14311		duration: options.duration,
14312		easing: options.easing,
14313		complete: function() {
14314
14315			var offset = element.offset();
14316
14317			if ( to.opacity === 0 ) {
14318				element.css( "opacity", from.opacity );
14319			}
14320
14321			if ( !restore ) {
14322				element
14323					.css( "position", position === "static" ? "relative" : position )
14324					.offset( offset );
14325
14326				// Need to save style here so that automatic style restoration
14327				// doesn't restore to the original styles from before the animation.
14328				$.effects.saveStyle( element );
14329			}
14330
14331			done();
14332		}
14333	} );
14334
14335} );
14336
14337
14338/*!
14339 * jQuery UI Effects Scale 1.14.1
14340 * https://jqueryui.com
14341 *
14342 * Copyright OpenJS Foundation and other contributors
14343 * Released under the MIT license.
14344 * https://jquery.org/license
14345 */
14346
14347//>>label: Scale Effect
14348//>>group: Effects
14349//>>description: Grows or shrinks an element and its content.
14350//>>docs: https://api.jqueryui.com/scale-effect/
14351//>>demos: https://jqueryui.com/effect/
14352
14353
14354var effectsEffectScale = $.effects.define( "scale", function( options, done ) {
14355
14356	// Create element
14357	var el = $( this ),
14358		mode = options.mode,
14359		percent = parseInt( options.percent, 10 ) ||
14360			( parseInt( options.percent, 10 ) === 0 ? 0 : ( mode !== "effect" ? 0 : 100 ) ),
14361
14362		newOptions = $.extend( true, {
14363			from: $.effects.scaledDimensions( el ),
14364			to: $.effects.scaledDimensions( el, percent, options.direction || "both" ),
14365			origin: options.origin || [ "middle", "center" ]
14366		}, options );
14367
14368	// Fade option to support puff
14369	if ( options.fade ) {
14370		newOptions.from.opacity = 1;
14371		newOptions.to.opacity = 0;
14372	}
14373
14374	$.effects.effect.size.call( this, newOptions, done );
14375} );
14376
14377
14378/*!
14379 * jQuery UI Effects Puff 1.14.1
14380 * https://jqueryui.com
14381 *
14382 * Copyright OpenJS Foundation and other contributors
14383 * Released under the MIT license.
14384 * https://jquery.org/license
14385 */
14386
14387//>>label: Puff Effect
14388//>>group: Effects
14389//>>description: Creates a puff effect by scaling the element up and hiding it at the same time.
14390//>>docs: https://api.jqueryui.com/puff-effect/
14391//>>demos: https://jqueryui.com/effect/
14392
14393
14394var effectsEffectPuff = $.effects.define( "puff", "hide", function( options, done ) {
14395	var newOptions = $.extend( true, {}, options, {
14396		fade: true,
14397		percent: parseInt( options.percent, 10 ) || 150
14398	} );
14399
14400	$.effects.effect.scale.call( this, newOptions, done );
14401} );
14402
14403
14404/*!
14405 * jQuery UI Effects Pulsate 1.14.1
14406 * https://jqueryui.com
14407 *
14408 * Copyright OpenJS Foundation and other contributors
14409 * Released under the MIT license.
14410 * https://jquery.org/license
14411 */
14412
14413//>>label: Pulsate Effect
14414//>>group: Effects
14415//>>description: Pulsates an element n times by changing the opacity to zero and back.
14416//>>docs: https://api.jqueryui.com/pulsate-effect/
14417//>>demos: https://jqueryui.com/effect/
14418
14419
14420var effectsEffectPulsate = $.effects.define( "pulsate", "show", function( options, done ) {
14421	var element = $( this ),
14422		mode = options.mode,
14423		show = mode === "show",
14424		hide = mode === "hide",
14425		showhide = show || hide,
14426
14427		// Showing or hiding leaves off the "last" animation
14428		anims = ( ( options.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ),
14429		duration = options.duration / anims,
14430		animateTo = 0,
14431		i = 1,
14432		queuelen = element.queue().length;
14433
14434	if ( show || !element.is( ":visible" ) ) {
14435		element.css( "opacity", 0 ).show();
14436		animateTo = 1;
14437	}
14438
14439	// Anims - 1 opacity "toggles"
14440	for ( ; i < anims; i++ ) {
14441		element.animate( { opacity: animateTo }, duration, options.easing );
14442		animateTo = 1 - animateTo;
14443	}
14444
14445	element.animate( { opacity: animateTo }, duration, options.easing );
14446
14447	element.queue( done );
14448
14449	$.effects.unshift( element, queuelen, anims + 1 );
14450} );
14451
14452
14453/*!
14454 * jQuery UI Effects Shake 1.14.1
14455 * https://jqueryui.com
14456 *
14457 * Copyright OpenJS Foundation and other contributors
14458 * Released under the MIT license.
14459 * https://jquery.org/license
14460 */
14461
14462//>>label: Shake Effect
14463//>>group: Effects
14464//>>description: Shakes an element horizontally or vertically n times.
14465//>>docs: https://api.jqueryui.com/shake-effect/
14466//>>demos: https://jqueryui.com/effect/
14467
14468
14469var effectsEffectShake = $.effects.define( "shake", function( options, done ) {
14470
14471	var i = 1,
14472		element = $( this ),
14473		direction = options.direction || "left",
14474		distance = options.distance || 20,
14475		times = options.times || 3,
14476		anims = times * 2 + 1,
14477		speed = Math.round( options.duration / anims ),
14478		ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
14479		positiveMotion = ( direction === "up" || direction === "left" ),
14480		animation = {},
14481		animation1 = {},
14482		animation2 = {},
14483
14484		queuelen = element.queue().length;
14485
14486	$.effects.createPlaceholder( element );
14487
14488	// Animation
14489	animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance;
14490	animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2;
14491	animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2;
14492
14493	// Animate
14494	element.animate( animation, speed, options.easing );
14495
14496	// Shakes
14497	for ( ; i < times; i++ ) {
14498		element
14499			.animate( animation1, speed, options.easing )
14500			.animate( animation2, speed, options.easing );
14501	}
14502
14503	element
14504		.animate( animation1, speed, options.easing )
14505		.animate( animation, speed / 2, options.easing )
14506		.queue( done );
14507
14508	$.effects.unshift( element, queuelen, anims + 1 );
14509} );
14510
14511
14512/*!
14513 * jQuery UI Effects Slide 1.14.1
14514 * https://jqueryui.com
14515 *
14516 * Copyright OpenJS Foundation and other contributors
14517 * Released under the MIT license.
14518 * https://jquery.org/license
14519 */
14520
14521//>>label: Slide Effect
14522//>>group: Effects
14523//>>description: Slides an element in and out of the viewport.
14524//>>docs: https://api.jqueryui.com/slide-effect/
14525//>>demos: https://jqueryui.com/effect/
14526
14527
14528var effectsEffectSlide = $.effects.define( "slide", "show", function( options, done ) {
14529	var startClip, startRef,
14530		element = $( this ),
14531		map = {
14532			up: [ "bottom", "top" ],
14533			down: [ "top", "bottom" ],
14534			left: [ "right", "left" ],
14535			right: [ "left", "right" ]
14536		},
14537		mode = options.mode,
14538		direction = options.direction || "left",
14539		ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
14540		positiveMotion = ( direction === "up" || direction === "left" ),
14541		distance = options.distance ||
14542			element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ),
14543		animation = {};
14544
14545	$.effects.createPlaceholder( element );
14546
14547	startClip = element.cssClip();
14548	startRef = element.position()[ ref ];
14549
14550	// Define hide animation
14551	animation[ ref ] = ( positiveMotion ? -1 : 1 ) * distance + startRef;
14552	animation.clip = element.cssClip();
14553	animation.clip[ map[ direction ][ 1 ] ] = animation.clip[ map[ direction ][ 0 ] ];
14554
14555	// Reverse the animation if we're showing
14556	if ( mode === "show" ) {
14557		element.cssClip( animation.clip );
14558		element.css( ref, animation[ ref ] );
14559		animation.clip = startClip;
14560		animation[ ref ] = startRef;
14561	}
14562
14563	// Actually animate
14564	element.animate( animation, {
14565		queue: false,
14566		duration: options.duration,
14567		easing: options.easing,
14568		complete: done
14569	} );
14570} );
14571
14572
14573/*!
14574 * jQuery UI Effects Transfer 1.14.1
14575 * https://jqueryui.com
14576 *
14577 * Copyright OpenJS Foundation and other contributors
14578 * Released under the MIT license.
14579 * https://jquery.org/license
14580 */
14581
14582//>>label: Transfer Effect
14583//>>group: Effects
14584//>>description: Displays a transfer effect from one element to another.
14585//>>docs: https://api.jqueryui.com/transfer-effect/
14586//>>demos: https://jqueryui.com/effect/
14587
14588
14589var effect;
14590if ( $.uiBackCompat === true ) {
14591	effect = $.effects.define( "transfer", function( options, done ) {
14592		$( this ).transfer( options, done );
14593	} );
14594}
14595var effectsEffectTransfer = effect;
14596
14597
14598/*!
14599 * jQuery UI Focusable 1.14.1
14600 * https://jqueryui.com
14601 *
14602 * Copyright OpenJS Foundation and other contributors
14603 * Released under the MIT license.
14604 * https://jquery.org/license
14605 */
14606
14607//>>label: :focusable Selector
14608//>>group: Core
14609//>>description: Selects elements which can be focused.
14610//>>docs: https://api.jqueryui.com/focusable-selector/
14611
14612
14613// Selectors
14614$.ui.focusable = function( element, hasTabindex ) {
14615	var map, mapName, img, focusableIfVisible, fieldset,
14616		nodeName = element.nodeName.toLowerCase();
14617
14618	if ( "area" === nodeName ) {
14619		map = element.parentNode;
14620		mapName = map.name;
14621		if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
14622			return false;
14623		}
14624		img = $( "img[usemap='#" + mapName + "']" );
14625		return img.length > 0 && img.is( ":visible" );
14626	}
14627
14628	if ( /^(input|select|textarea|button|object)$/.test( nodeName ) ) {
14629		focusableIfVisible = !element.disabled;
14630
14631		if ( focusableIfVisible ) {
14632
14633			// Form controls within a disabled fieldset are disabled.
14634			// However, controls within the fieldset's legend do not get disabled.
14635			// Since controls generally aren't placed inside legends, we skip
14636			// this portion of the check.
14637			fieldset = $( element ).closest( "fieldset" )[ 0 ];
14638			if ( fieldset ) {
14639				focusableIfVisible = !fieldset.disabled;
14640			}
14641		}
14642	} else if ( "a" === nodeName ) {
14643		focusableIfVisible = element.href || hasTabindex;
14644	} else {
14645		focusableIfVisible = hasTabindex;
14646	}
14647
14648	return focusableIfVisible && $( element ).is( ":visible" ) &&
14649		$( element ).css( "visibility" ) === "visible";
14650};
14651
14652$.extend( $.expr.pseudos, {
14653	focusable: function( element ) {
14654		return $.ui.focusable( element, $.attr( element, "tabindex" ) != null );
14655	}
14656} );
14657
14658var focusable = $.ui.focusable;
14659
14660
14661/*!
14662 * jQuery UI Form Reset Mixin 1.14.1
14663 * https://jqueryui.com
14664 *
14665 * Copyright OpenJS Foundation and other contributors
14666 * Released under the MIT license.
14667 * https://jquery.org/license
14668 */
14669
14670//>>label: Form Reset Mixin
14671//>>group: Core
14672//>>description: Refresh input widgets when their form is reset
14673//>>docs: https://api.jqueryui.com/form-reset-mixin/
14674
14675
14676var formResetMixin = $.ui.formResetMixin = {
14677	_formResetHandler: function() {
14678		var form = $( this );
14679
14680		// Wait for the form reset to actually happen before refreshing
14681		setTimeout( function() {
14682			var instances = form.data( "ui-form-reset-instances" );
14683			$.each( instances, function() {
14684				this.refresh();
14685			} );
14686		} );
14687	},
14688
14689	_bindFormResetHandler: function() {
14690		this.form = $( this.element.prop( "form" ) );
14691		if ( !this.form.length ) {
14692			return;
14693		}
14694
14695		var instances = this.form.data( "ui-form-reset-instances" ) || [];
14696		if ( !instances.length ) {
14697
14698			// We don't use _on() here because we use a single event handler per form
14699			this.form.on( "reset.ui-form-reset", this._formResetHandler );
14700		}
14701		instances.push( this );
14702		this.form.data( "ui-form-reset-instances", instances );
14703	},
14704
14705	_unbindFormResetHandler: function() {
14706		if ( !this.form.length ) {
14707			return;
14708		}
14709
14710		var instances = this.form.data( "ui-form-reset-instances" );
14711		instances.splice( $.inArray( this, instances ), 1 );
14712		if ( instances.length ) {
14713			this.form.data( "ui-form-reset-instances", instances );
14714		} else {
14715			this.form
14716				.removeData( "ui-form-reset-instances" )
14717				.off( "reset.ui-form-reset" );
14718		}
14719	}
14720};
14721
14722
14723/*!
14724 * jQuery UI Legacy jQuery Core patches 1.14.1
14725 * https://jqueryui.com
14726 *
14727 * Copyright OpenJS Foundation and other contributors
14728 * Released under the MIT license.
14729 * https://jquery.org/license
14730 *
14731 */
14732
14733//>>label: Legacy jQuery Core patches
14734//>>group: Core
14735//>>description: Backport `.even()`, `.odd()` and `$.escapeSelector` to older jQuery Core versions (deprecated)
14736
14737
14738// Support: jQuery 2.2.x or older.
14739// This method has been defined in jQuery 3.0.0.
14740// Code from https://github.com/jquery/jquery/blob/e539bac79e666bba95bba86d690b4e609dca2286/src/selector/escapeSelector.js
14741if ( !$.escapeSelector ) {
14742	$.escapeSelector = function( id ) {
14743		return CSS.escape( id + "" );
14744	};
14745}
14746
14747// Support: jQuery 3.4.x or older
14748// These methods have been defined in jQuery 3.5.0.
14749if ( !$.fn.even || !$.fn.odd ) {
14750	$.fn.extend( {
14751		even: function() {
14752			return this.filter( function( i ) {
14753				return i % 2 === 0;
14754			} );
14755		},
14756		odd: function() {
14757			return this.filter( function( i ) {
14758				return i % 2 === 1;
14759			} );
14760		}
14761	} );
14762}
14763
14764;
14765/*!
14766 * jQuery UI Keycode 1.14.1
14767 * https://jqueryui.com
14768 *
14769 * Copyright OpenJS Foundation and other contributors
14770 * Released under the MIT license.
14771 * https://jquery.org/license
14772 */
14773
14774//>>label: Keycode
14775//>>group: Core
14776//>>description: Provide keycodes as keynames
14777//>>docs: https://api.jqueryui.com/jQuery.ui.keyCode/
14778
14779
14780var keycode = $.ui.keyCode = {
14781	BACKSPACE: 8,
14782	COMMA: 188,
14783	DELETE: 46,
14784	DOWN: 40,
14785	END: 35,
14786	ENTER: 13,
14787	ESCAPE: 27,
14788	HOME: 36,
14789	LEFT: 37,
14790	PAGE_DOWN: 34,
14791	PAGE_UP: 33,
14792	PERIOD: 190,
14793	RIGHT: 39,
14794	SPACE: 32,
14795	TAB: 9,
14796	UP: 38
14797};
14798
14799
14800/*!
14801 * jQuery UI Labels 1.14.1
14802 * https://jqueryui.com
14803 *
14804 * Copyright OpenJS Foundation and other contributors
14805 * Released under the MIT license.
14806 * https://jquery.org/license
14807 */
14808
14809//>>label: labels
14810//>>group: Core
14811//>>description: Find all the labels associated with a given input
14812//>>docs: https://api.jqueryui.com/labels/
14813
14814
14815var labels = $.fn.labels = function() {
14816	var ancestor, selector, id, labels, ancestors;
14817
14818	if ( !this.length ) {
14819		return this.pushStack( [] );
14820	}
14821
14822	// Check control.labels first
14823	if ( this[ 0 ].labels && this[ 0 ].labels.length ) {
14824		return this.pushStack( this[ 0 ].labels );
14825	}
14826
14827	// If `control.labels` is empty - e.g. inside of document fragments - find
14828	// the labels manually
14829	labels = this.eq( 0 ).parents( "label" );
14830
14831	// Look for the label based on the id
14832	id = this.attr( "id" );
14833	if ( id ) {
14834
14835		// We don't search against the document in case the element
14836		// is disconnected from the DOM
14837		ancestor = this.eq( 0 ).parents().last();
14838
14839		// Get a full set of top level ancestors
14840		ancestors = ancestor.add( ancestor.length ? ancestor.siblings() : this.siblings() );
14841
14842		// Create a selector for the label based on the id
14843		selector = "label[for='" + CSS.escape( id ) + "']";
14844
14845		labels = labels.add( ancestors.find( selector ).addBack( selector ) );
14846
14847	}
14848
14849	// Return whatever we have found for labels
14850	return this.pushStack( labels );
14851};
14852
14853
14854/*!
14855 * jQuery UI Scroll Parent 1.14.1
14856 * https://jqueryui.com
14857 *
14858 * Copyright OpenJS Foundation and other contributors
14859 * Released under the MIT license.
14860 * https://jquery.org/license
14861 */
14862
14863//>>label: scrollParent
14864//>>group: Core
14865//>>description: Get the closest ancestor element that is scrollable.
14866//>>docs: https://api.jqueryui.com/scrollParent/
14867
14868
14869var scrollParent = $.fn.scrollParent = function( includeHidden ) {
14870	var position = this.css( "position" ),
14871		excludeStaticParent = position === "absolute",
14872		overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/,
14873		scrollParent = this.parents().filter( function() {
14874			var parent = $( this );
14875			if ( excludeStaticParent && parent.css( "position" ) === "static" ) {
14876				return false;
14877			}
14878			return overflowRegex.test( parent.css( "overflow" ) + parent.css( "overflow-y" ) +
14879				parent.css( "overflow-x" ) );
14880		} ).eq( 0 );
14881
14882	return position === "fixed" || !scrollParent.length ?
14883		$( this[ 0 ].ownerDocument || document ) :
14884		scrollParent;
14885};
14886
14887
14888/*!
14889 * jQuery UI Tabbable 1.14.1
14890 * https://jqueryui.com
14891 *
14892 * Copyright OpenJS Foundation and other contributors
14893 * Released under the MIT license.
14894 * https://jquery.org/license
14895 */
14896
14897//>>label: :tabbable Selector
14898//>>group: Core
14899//>>description: Selects elements which can be tabbed to.
14900//>>docs: https://api.jqueryui.com/tabbable-selector/
14901
14902
14903var tabbable = $.extend( $.expr.pseudos, {
14904	tabbable: function( element ) {
14905		var tabIndex = $.attr( element, "tabindex" ),
14906			hasTabindex = tabIndex != null;
14907		return ( !hasTabindex || tabIndex >= 0 ) && $.ui.focusable( element, hasTabindex );
14908	}
14909} );
14910
14911
14912/*!
14913 * jQuery UI Unique ID 1.14.1
14914 * https://jqueryui.com
14915 *
14916 * Copyright OpenJS Foundation and other contributors
14917 * Released under the MIT license.
14918 * https://jquery.org/license
14919 */
14920
14921//>>label: uniqueId
14922//>>group: Core
14923//>>description: Functions to generate and remove uniqueId's
14924//>>docs: https://api.jqueryui.com/uniqueId/
14925
14926
14927var uniqueId = $.fn.extend( {
14928	uniqueId: ( function() {
14929		var uuid = 0;
14930
14931		return function() {
14932			return this.each( function() {
14933				if ( !this.id ) {
14934					this.id = "ui-id-" + ( ++uuid );
14935				}
14936			} );
14937		};
14938	} )(),
14939
14940	removeUniqueId: function() {
14941		return this.each( function() {
14942			if ( /^ui-id-\d+$/.test( this.id ) ) {
14943				$( this ).removeAttr( "id" );
14944			}
14945		} );
14946	}
14947} );
14948
14949
14950/*!
14951 * jQuery UI Accordion 1.14.1
14952 * https://jqueryui.com
14953 *
14954 * Copyright OpenJS Foundation and other contributors
14955 * Released under the MIT license.
14956 * https://jquery.org/license
14957 */
14958
14959//>>label: Accordion
14960//>>group: Widgets
14961/* eslint-disable max-len */
14962//>>description: Displays collapsible content panels for presenting information in a limited amount of space.
14963/* eslint-enable max-len */
14964//>>docs: https://api.jqueryui.com/accordion/
14965//>>demos: https://jqueryui.com/accordion/
14966//>>css.structure: ../../themes/base/core.css
14967//>>css.structure: ../../themes/base/accordion.css
14968//>>css.theme: ../../themes/base/theme.css
14969
14970
14971var widgetsAccordion = $.widget( "ui.accordion", {
14972	version: "1.14.1",
14973	options: {
14974		active: 0,
14975		animate: {},
14976		classes: {
14977			"ui-accordion-header": "ui-corner-top",
14978			"ui-accordion-header-collapsed": "ui-corner-all",
14979			"ui-accordion-content": "ui-corner-bottom"
14980		},
14981		collapsible: false,
14982		event: "click",
14983		header: function( elem ) {
14984			return elem
14985				.find( "> li > :first-child" )
14986				.add(
14987					elem.find( "> :not(li)" )
14988
14989						// Support: jQuery <3.5 only
14990						// We could use `.even()` but that's unavailable in older jQuery.
14991						.filter( function( i ) {
14992							return i % 2 === 0;
14993						} )
14994				);
14995		},
14996		heightStyle: "auto",
14997		icons: {
14998			activeHeader: "ui-icon-triangle-1-s",
14999			header: "ui-icon-triangle-1-e"
15000		},
15001
15002		// Callbacks
15003		activate: null,
15004		beforeActivate: null
15005	},
15006
15007	hideProps: {
15008		borderTopWidth: "hide",
15009		borderBottomWidth: "hide",
15010		paddingTop: "hide",
15011		paddingBottom: "hide",
15012		height: "hide"
15013	},
15014
15015	showProps: {
15016		borderTopWidth: "show",
15017		borderBottomWidth: "show",
15018		paddingTop: "show",
15019		paddingBottom: "show",
15020		height: "show"
15021	},
15022
15023	_create: function() {
15024		var options = this.options;
15025
15026		this.prevShow = this.prevHide = $();
15027		this._addClass( "ui-accordion", "ui-widget ui-helper-reset" );
15028		this.element.attr( "role", "tablist" );
15029
15030		// Don't allow collapsible: false and active: false / null
15031		if ( !options.collapsible && ( options.active === false || options.active == null ) ) {
15032			options.active = 0;
15033		}
15034
15035		this._processPanels();
15036
15037		// handle negative values
15038		if ( options.active < 0 ) {
15039			options.active += this.headers.length;
15040		}
15041		this._refresh();
15042	},
15043
15044	_getCreateEventData: function() {
15045		return {
15046			header: this.active,
15047			panel: !this.active.length ? $() : this.active.next()
15048		};
15049	},
15050
15051	_createIcons: function() {
15052		var icon, children,
15053			icons = this.options.icons;
15054
15055		if ( icons ) {
15056			icon = $( "<span>" );
15057			this._addClass( icon, "ui-accordion-header-icon", "ui-icon " + icons.header );
15058			icon.prependTo( this.headers );
15059			children = this.active.children( ".ui-accordion-header-icon" );
15060			this._removeClass( children, icons.header )
15061				._addClass( children, null, icons.activeHeader )
15062				._addClass( this.headers, "ui-accordion-icons" );
15063		}
15064	},
15065
15066	_destroyIcons: function() {
15067		this._removeClass( this.headers, "ui-accordion-icons" );
15068		this.headers.children( ".ui-accordion-header-icon" ).remove();
15069	},
15070
15071	_destroy: function() {
15072		var contents;
15073
15074		// Clean up main element
15075		this.element.removeAttr( "role" );
15076
15077		// Clean up headers
15078		this.headers
15079			.removeAttr( "role aria-expanded aria-selected aria-controls tabIndex" )
15080			.removeUniqueId();
15081
15082		this._destroyIcons();
15083
15084		// Clean up content panels
15085		contents = this.headers.next()
15086			.css( "display", "" )
15087			.removeAttr( "role aria-hidden aria-labelledby" )
15088			.removeUniqueId();
15089
15090		if ( this.options.heightStyle !== "content" ) {
15091			contents.css( "height", "" );
15092		}
15093	},
15094
15095	_setOption: function( key, value ) {
15096		if ( key === "active" ) {
15097
15098			// _activate() will handle invalid values and update this.options
15099			this._activate( value );
15100			return;
15101		}
15102
15103		if ( key === "event" ) {
15104			if ( this.options.event ) {
15105				this._off( this.headers, this.options.event );
15106			}
15107			this._setupEvents( value );
15108		}
15109
15110		this._super( key, value );
15111
15112		// Setting collapsible: false while collapsed; open first panel
15113		if ( key === "collapsible" && !value && this.options.active === false ) {
15114			this._activate( 0 );
15115		}
15116
15117		if ( key === "icons" ) {
15118			this._destroyIcons();
15119			if ( value ) {
15120				this._createIcons();
15121			}
15122		}
15123	},
15124
15125	_setOptionDisabled: function( value ) {
15126		this._super( value );
15127
15128		this.element.attr( "aria-disabled", value );
15129		this._toggleClass( null, "ui-state-disabled", !!value );
15130	},
15131
15132	_keydown: function( event ) {
15133		if ( event.altKey || event.ctrlKey ) {
15134			return;
15135		}
15136
15137		var keyCode = $.ui.keyCode,
15138			length = this.headers.length,
15139			currentIndex = this.headers.index( event.target ),
15140			toFocus = false;
15141
15142		switch ( event.keyCode ) {
15143		case keyCode.RIGHT:
15144		case keyCode.DOWN:
15145			toFocus = this.headers[ ( currentIndex + 1 ) % length ];
15146			break;
15147		case keyCode.LEFT:
15148		case keyCode.UP:
15149			toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
15150			break;
15151		case keyCode.SPACE:
15152		case keyCode.ENTER:
15153			this._eventHandler( event );
15154			break;
15155		case keyCode.HOME:
15156			toFocus = this.headers[ 0 ];
15157			break;
15158		case keyCode.END:
15159			toFocus = this.headers[ length - 1 ];
15160			break;
15161		}
15162
15163		if ( toFocus ) {
15164			$( event.target ).attr( "tabIndex", -1 );
15165			$( toFocus ).attr( "tabIndex", 0 );
15166			$( toFocus ).trigger( "focus" );
15167			event.preventDefault();
15168		}
15169	},
15170
15171	_panelKeyDown: function( event ) {
15172		if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) {
15173			$( event.currentTarget ).prev().trigger( "focus" );
15174		}
15175	},
15176
15177	refresh: function() {
15178		var options = this.options;
15179		this._processPanels();
15180
15181		// Was collapsed or no panel
15182		if ( ( options.active === false && options.collapsible === true ) ||
15183				!this.headers.length ) {
15184			options.active = false;
15185			this.active = $();
15186
15187		// active false only when collapsible is true
15188		} else if ( options.active === false ) {
15189			this._activate( 0 );
15190
15191		// was active, but active panel is gone
15192		} else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
15193
15194			// all remaining panel are disabled
15195			if ( this.headers.length === this.headers.find( ".ui-state-disabled" ).length ) {
15196				options.active = false;
15197				this.active = $();
15198
15199			// activate previous panel
15200			} else {
15201				this._activate( Math.max( 0, options.active - 1 ) );
15202			}
15203
15204		// was active, active panel still exists
15205		} else {
15206
15207			// make sure active index is correct
15208			options.active = this.headers.index( this.active );
15209		}
15210
15211		this._destroyIcons();
15212
15213		this._refresh();
15214	},
15215
15216	_processPanels: function() {
15217		var prevHeaders = this.headers,
15218			prevPanels = this.panels;
15219
15220		if ( typeof this.options.header === "function" ) {
15221			this.headers = this.options.header( this.element );
15222		} else {
15223			this.headers = this.element.find( this.options.header );
15224		}
15225		this._addClass( this.headers, "ui-accordion-header ui-accordion-header-collapsed",
15226			"ui-state-default" );
15227
15228		this.panels = this.headers.next().filter( ":not(.ui-accordion-content-active)" ).hide();
15229		this._addClass( this.panels, "ui-accordion-content", "ui-helper-reset ui-widget-content" );
15230
15231		// Avoid memory leaks (#10056)
15232		if ( prevPanels ) {
15233			this._off( prevHeaders.not( this.headers ) );
15234			this._off( prevPanels.not( this.panels ) );
15235		}
15236	},
15237
15238	_refresh: function() {
15239		var maxHeight,
15240			options = this.options,
15241			heightStyle = options.heightStyle,
15242			parent = this.element.parent();
15243
15244		this.active = this._findActive( options.active );
15245		this._addClass( this.active, "ui-accordion-header-active", "ui-state-active" )
15246			._removeClass( this.active, "ui-accordion-header-collapsed" );
15247		this._addClass( this.active.next(), "ui-accordion-content-active" );
15248		this.active.next().show();
15249
15250		this.headers
15251			.attr( "role", "tab" )
15252			.each( function() {
15253				var header = $( this ),
15254					headerId = header.uniqueId().attr( "id" ),
15255					panel = header.next(),
15256					panelId = panel.uniqueId().attr( "id" );
15257				header.attr( "aria-controls", panelId );
15258				panel.attr( "aria-labelledby", headerId );
15259			} )
15260			.next()
15261				.attr( "role", "tabpanel" );
15262
15263		this.headers
15264			.not( this.active )
15265				.attr( {
15266					"aria-selected": "false",
15267					"aria-expanded": "false",
15268					tabIndex: -1
15269				} )
15270				.next()
15271					.attr( {
15272						"aria-hidden": "true"
15273					} )
15274					.hide();
15275
15276		// Make sure at least one header is in the tab order
15277		if ( !this.active.length ) {
15278			this.headers.eq( 0 ).attr( "tabIndex", 0 );
15279		} else {
15280			this.active.attr( {
15281				"aria-selected": "true",
15282				"aria-expanded": "true",
15283				tabIndex: 0
15284			} )
15285				.next()
15286					.attr( {
15287						"aria-hidden": "false"
15288					} );
15289		}
15290
15291		this._createIcons();
15292
15293		this._setupEvents( options.event );
15294
15295		if ( heightStyle === "fill" ) {
15296			maxHeight = parent.height();
15297			this.element.siblings( ":visible" ).each( function() {
15298				var elem = $( this ),
15299					position = elem.css( "position" );
15300
15301				if ( position === "absolute" || position === "fixed" ) {
15302					return;
15303				}
15304				maxHeight -= elem.outerHeight( true );
15305			} );
15306
15307			this.headers.each( function() {
15308				maxHeight -= $( this ).outerHeight( true );
15309			} );
15310
15311			this.headers.next()
15312				.each( function() {
15313					$( this ).height( Math.max( 0, maxHeight -
15314						$( this ).innerHeight() + $( this ).height() ) );
15315				} )
15316				.css( "overflow", "auto" );
15317		} else if ( heightStyle === "auto" ) {
15318			maxHeight = 0;
15319			this.headers.next()
15320				.each( function() {
15321					var isVisible = $( this ).is( ":visible" );
15322					if ( !isVisible ) {
15323						$( this ).show();
15324					}
15325					maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() );
15326					if ( !isVisible ) {
15327						$( this ).hide();
15328					}
15329				} )
15330				.height( maxHeight );
15331		}
15332	},
15333
15334	_activate: function( index ) {
15335		var active = this._findActive( index )[ 0 ];
15336
15337		// Trying to activate the already active panel
15338		if ( active === this.active[ 0 ] ) {
15339			return;
15340		}
15341
15342		// Trying to collapse, simulate a click on the currently active header
15343		active = active || this.active[ 0 ];
15344
15345		this._eventHandler( {
15346			target: active,
15347			currentTarget: active,
15348			preventDefault: $.noop
15349		} );
15350	},
15351
15352	_findActive: function( selector ) {
15353		return typeof selector === "number" ? this.headers.eq( selector ) : $();
15354	},
15355
15356	_setupEvents: function( event ) {
15357		var events = {
15358			keydown: "_keydown"
15359		};
15360		if ( event ) {
15361			$.each( event.split( " " ), function( index, eventName ) {
15362				events[ eventName ] = "_eventHandler";
15363			} );
15364		}
15365
15366		this._off( this.headers.add( this.headers.next() ) );
15367		this._on( this.headers, events );
15368		this._on( this.headers.next(), { keydown: "_panelKeyDown" } );
15369		this._hoverable( this.headers );
15370		this._focusable( this.headers );
15371	},
15372
15373	_eventHandler: function( event ) {
15374		var activeChildren, clickedChildren,
15375			options = this.options,
15376			active = this.active,
15377			clicked = $( event.currentTarget ),
15378			clickedIsActive = clicked[ 0 ] === active[ 0 ],
15379			collapsing = clickedIsActive && options.collapsible,
15380			toShow = collapsing ? $() : clicked.next(),
15381			toHide = active.next(),
15382			eventData = {
15383				oldHeader: active,
15384				oldPanel: toHide,
15385				newHeader: collapsing ? $() : clicked,
15386				newPanel: toShow
15387			};
15388
15389		event.preventDefault();
15390
15391		if (
15392
15393				// click on active header, but not collapsible
15394				( clickedIsActive && !options.collapsible ) ||
15395
15396				// allow canceling activation
15397				( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
15398			return;
15399		}
15400
15401		options.active = collapsing ? false : this.headers.index( clicked );
15402
15403		// When the call to ._toggle() comes after the class changes
15404		// it causes a very odd bug in IE 8 (see #6720)
15405		this.active = clickedIsActive ? $() : clicked;
15406		this._toggle( eventData );
15407
15408		// Switch classes
15409		// corner classes on the previously active header stay after the animation
15410		this._removeClass( active, "ui-accordion-header-active", "ui-state-active" );
15411		if ( options.icons ) {
15412			activeChildren = active.children( ".ui-accordion-header-icon" );
15413			this._removeClass( activeChildren, null, options.icons.activeHeader )
15414				._addClass( activeChildren, null, options.icons.header );
15415		}
15416
15417		if ( !clickedIsActive ) {
15418			this._removeClass( clicked, "ui-accordion-header-collapsed" )
15419				._addClass( clicked, "ui-accordion-header-active", "ui-state-active" );
15420			if ( options.icons ) {
15421				clickedChildren = clicked.children( ".ui-accordion-header-icon" );
15422				this._removeClass( clickedChildren, null, options.icons.header )
15423					._addClass( clickedChildren, null, options.icons.activeHeader );
15424			}
15425
15426			this._addClass( clicked.next(), "ui-accordion-content-active" );
15427		}
15428	},
15429
15430	_toggle: function( data ) {
15431		var toShow = data.newPanel,
15432			toHide = this.prevShow.length ? this.prevShow : data.oldPanel;
15433
15434		// Handle activating a panel during the animation for another activation
15435		this.prevShow.add( this.prevHide ).stop( true, true );
15436		this.prevShow = toShow;
15437		this.prevHide = toHide;
15438
15439		if ( this.options.animate ) {
15440			this._animate( toShow, toHide, data );
15441		} else {
15442			toHide.hide();
15443			toShow.show();
15444			this._toggleComplete( data );
15445		}
15446
15447		toHide.attr( {
15448			"aria-hidden": "true"
15449		} );
15450		toHide.prev().attr( {
15451			"aria-selected": "false",
15452			"aria-expanded": "false"
15453		} );
15454
15455		// if we're switching panels, remove the old header from the tab order
15456		// if we're opening from collapsed state, remove the previous header from the tab order
15457		// if we're collapsing, then keep the collapsing header in the tab order
15458		if ( toShow.length && toHide.length ) {
15459			toHide.prev().attr( {
15460				"tabIndex": -1,
15461				"aria-expanded": "false"
15462			} );
15463		} else if ( toShow.length ) {
15464			this.headers.filter( function() {
15465				return parseInt( $( this ).attr( "tabIndex" ), 10 ) === 0;
15466			} )
15467				.attr( "tabIndex", -1 );
15468		}
15469
15470		toShow
15471			.attr( "aria-hidden", "false" )
15472			.prev()
15473				.attr( {
15474					"aria-selected": "true",
15475					"aria-expanded": "true",
15476					tabIndex: 0
15477				} );
15478	},
15479
15480	_animate: function( toShow, toHide, data ) {
15481		var total, easing, duration,
15482			that = this,
15483			adjust = 0,
15484			boxSizing = toShow.css( "box-sizing" ),
15485			down = toShow.length &&
15486				( !toHide.length || ( toShow.index() < toHide.index() ) ),
15487			animate = this.options.animate || {},
15488			options = down && animate.down || animate,
15489			complete = function() {
15490				that._toggleComplete( data );
15491			};
15492
15493		if ( typeof options === "number" ) {
15494			duration = options;
15495		}
15496		if ( typeof options === "string" ) {
15497			easing = options;
15498		}
15499
15500		// fall back from options to animation in case of partial down settings
15501		easing = easing || options.easing || animate.easing;
15502		duration = duration || options.duration || animate.duration;
15503
15504		if ( !toHide.length ) {
15505			return toShow.animate( this.showProps, duration, easing, complete );
15506		}
15507		if ( !toShow.length ) {
15508			return toHide.animate( this.hideProps, duration, easing, complete );
15509		}
15510
15511		total = toShow.show().outerHeight();
15512		toHide.animate( this.hideProps, {
15513			duration: duration,
15514			easing: easing,
15515			step: function( now, fx ) {
15516				fx.now = Math.round( now );
15517			}
15518		} );
15519		toShow
15520			.hide()
15521			.animate( this.showProps, {
15522				duration: duration,
15523				easing: easing,
15524				complete: complete,
15525				step: function( now, fx ) {
15526					fx.now = Math.round( now );
15527					if ( fx.prop !== "height" ) {
15528						if ( boxSizing === "content-box" ) {
15529							adjust += fx.now;
15530						}
15531					} else if ( that.options.heightStyle !== "content" ) {
15532						fx.now = Math.round( total - toHide.outerHeight() - adjust );
15533						adjust = 0;
15534					}
15535				}
15536			} );
15537	},
15538
15539	_toggleComplete: function( data ) {
15540		var toHide = data.oldPanel,
15541			prev = toHide.prev();
15542
15543		this._removeClass( toHide, "ui-accordion-content-active" );
15544		this._removeClass( prev, "ui-accordion-header-active" )
15545			._addClass( prev, "ui-accordion-header-collapsed" );
15546
15547		this._trigger( "activate", null, data );
15548	}
15549} );
15550
15551
15552/*!
15553 * jQuery UI Menu 1.14.1
15554 * https://jqueryui.com
15555 *
15556 * Copyright OpenJS Foundation and other contributors
15557 * Released under the MIT license.
15558 * https://jquery.org/license
15559 */
15560
15561//>>label: Menu
15562//>>group: Widgets
15563//>>description: Creates nestable menus.
15564//>>docs: https://api.jqueryui.com/menu/
15565//>>demos: https://jqueryui.com/menu/
15566//>>css.structure: ../../themes/base/core.css
15567//>>css.structure: ../../themes/base/menu.css
15568//>>css.theme: ../../themes/base/theme.css
15569
15570
15571var widgetsMenu = $.widget( "ui.menu", {
15572	version: "1.14.1",
15573	defaultElement: "<ul>",
15574	delay: 300,
15575	options: {
15576		icons: {
15577			submenu: "ui-icon-caret-1-e"
15578		},
15579		items: "> *",
15580		menus: "ul",
15581		position: {
15582			my: "left top",
15583			at: "right top"
15584		},
15585		role: "menu",
15586
15587		// Callbacks
15588		blur: null,
15589		focus: null,
15590		select: null
15591	},
15592
15593	_create: function() {
15594		this.activeMenu = this.element;
15595
15596		// Flag used to prevent firing of the click handler
15597		// as the event bubbles up through nested menus
15598		this.mouseHandled = false;
15599		this.lastMousePosition = { x: null, y: null };
15600		this.element
15601			.uniqueId()
15602			.attr( {
15603				role: this.options.role,
15604				tabIndex: 0
15605			} );
15606
15607		this._addClass( "ui-menu", "ui-widget ui-widget-content" );
15608		this._on( {
15609
15610			// Prevent focus from sticking to links inside menu after clicking
15611			// them (focus should always stay on UL during navigation).
15612			"mousedown .ui-menu-item": function( event ) {
15613				event.preventDefault();
15614
15615				this._activateItem( event );
15616			},
15617			"click .ui-menu-item": function( event ) {
15618				var target = $( event.target );
15619				var active = $( this.document[ 0 ].activeElement );
15620				if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) {
15621					this.select( event );
15622
15623					// Only set the mouseHandled flag if the event will bubble, see #9469.
15624					if ( !event.isPropagationStopped() ) {
15625						this.mouseHandled = true;
15626					}
15627
15628					// Open submenu on click
15629					if ( target.has( ".ui-menu" ).length ) {
15630						this.expand( event );
15631					} else if ( !this.element.is( ":focus" ) &&
15632							active.closest( ".ui-menu" ).length ) {
15633
15634						// Redirect focus to the menu
15635						this.element.trigger( "focus", [ true ] );
15636
15637						// If the active item is on the top level, let it stay active.
15638						// Otherwise, blur the active item since it is no longer visible.
15639						if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) {
15640							clearTimeout( this.timer );
15641						}
15642					}
15643				}
15644			},
15645			"mouseenter .ui-menu-item": "_activateItem",
15646			"mousemove .ui-menu-item": "_activateItem",
15647			mouseleave: "collapseAll",
15648			"mouseleave .ui-menu": "collapseAll",
15649			focus: function( event, keepActiveItem ) {
15650
15651				// If there's already an active item, keep it active
15652				// If not, activate the first item
15653				var item = this.active || this._menuItems().first();
15654
15655				if ( !keepActiveItem ) {
15656					this.focus( event, item );
15657				}
15658			},
15659			blur: function( event ) {
15660				this._delay( function() {
15661					var notContained = !$.contains(
15662						this.element[ 0 ],
15663						this.document[ 0 ].activeElement
15664					);
15665					if ( notContained ) {
15666						this.collapseAll( event );
15667					}
15668				} );
15669			},
15670			keydown: "_keydown"
15671		} );
15672
15673		this.refresh();
15674
15675		// Clicks outside of a menu collapse any open menus
15676		this._on( this.document, {
15677			click: function( event ) {
15678				if ( this._closeOnDocumentClick( event ) ) {
15679					this.collapseAll( event, true );
15680				}
15681
15682				// Reset the mouseHandled flag
15683				this.mouseHandled = false;
15684			}
15685		} );
15686	},
15687
15688	_activateItem: function( event ) {
15689
15690		// Ignore mouse events while typeahead is active, see #10458.
15691		// Prevents focusing the wrong item when typeahead causes a scroll while the mouse
15692		// is over an item in the menu
15693		if ( this.previousFilter ) {
15694			return;
15695		}
15696
15697		// If the mouse didn't actually move, but the page was scrolled, ignore the event (#9356)
15698		if ( event.clientX === this.lastMousePosition.x &&
15699				event.clientY === this.lastMousePosition.y ) {
15700			return;
15701		}
15702
15703		this.lastMousePosition = {
15704			x: event.clientX,
15705			y: event.clientY
15706		};
15707
15708		var actualTarget = $( event.target ).closest( ".ui-menu-item" ),
15709			target = $( event.currentTarget );
15710
15711		// Ignore bubbled events on parent items, see #11641
15712		if ( actualTarget[ 0 ] !== target[ 0 ] ) {
15713			return;
15714		}
15715
15716		// If the item is already active, there's nothing to do
15717		if ( target.is( ".ui-state-active" ) ) {
15718			return;
15719		}
15720
15721		// Remove ui-state-active class from siblings of the newly focused menu item
15722		// to avoid a jump caused by adjacent elements both having a class with a border
15723		this._removeClass( target.siblings().children( ".ui-state-active" ),
15724			null, "ui-state-active" );
15725		this.focus( event, target );
15726	},
15727
15728	_destroy: function() {
15729		var items = this.element.find( ".ui-menu-item" )
15730				.removeAttr( "role aria-disabled" ),
15731			submenus = items.children( ".ui-menu-item-wrapper" )
15732				.removeUniqueId()
15733				.removeAttr( "tabIndex role aria-haspopup" );
15734
15735		// Destroy (sub)menus
15736		this.element
15737			.removeAttr( "aria-activedescendant" )
15738			.find( ".ui-menu" ).addBack()
15739				.removeAttr( "role aria-labelledby aria-expanded aria-hidden aria-disabled " +
15740					"tabIndex" )
15741				.removeUniqueId()
15742				.show();
15743
15744		submenus.children().each( function() {
15745			var elem = $( this );
15746			if ( elem.data( "ui-menu-submenu-caret" ) ) {
15747				elem.remove();
15748			}
15749		} );
15750	},
15751
15752	_keydown: function( event ) {
15753		var match, prev, character, skip,
15754			preventDefault = true;
15755
15756		switch ( event.keyCode ) {
15757		case $.ui.keyCode.PAGE_UP:
15758			this.previousPage( event );
15759			break;
15760		case $.ui.keyCode.PAGE_DOWN:
15761			this.nextPage( event );
15762			break;
15763		case $.ui.keyCode.HOME:
15764			this._move( "first", "first", event );
15765			break;
15766		case $.ui.keyCode.END:
15767			this._move( "last", "last", event );
15768			break;
15769		case $.ui.keyCode.UP:
15770			this.previous( event );
15771			break;
15772		case $.ui.keyCode.DOWN:
15773			this.next( event );
15774			break;
15775		case $.ui.keyCode.LEFT:
15776			this.collapse( event );
15777			break;
15778		case $.ui.keyCode.RIGHT:
15779			if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
15780				this.expand( event );
15781			}
15782			break;
15783		case $.ui.keyCode.ENTER:
15784		case $.ui.keyCode.SPACE:
15785			this._activate( event );
15786			break;
15787		case $.ui.keyCode.ESCAPE:
15788			this.collapse( event );
15789			break;
15790		default:
15791			preventDefault = false;
15792			prev = this.previousFilter || "";
15793			skip = false;
15794
15795			// Support number pad values
15796			character = event.keyCode >= 96 && event.keyCode <= 105 ?
15797				( event.keyCode - 96 ).toString() : String.fromCharCode( event.keyCode );
15798
15799			clearTimeout( this.filterTimer );
15800
15801			if ( character === prev ) {
15802				skip = true;
15803			} else {
15804				character = prev + character;
15805			}
15806
15807			match = this._filterMenuItems( character );
15808			match = skip && match.index( this.active.next() ) !== -1 ?
15809				this.active.nextAll( ".ui-menu-item" ) :
15810				match;
15811
15812			// If no matches on the current filter, reset to the last character pressed
15813			// to move down the menu to the first item that starts with that character
15814			if ( !match.length ) {
15815				character = String.fromCharCode( event.keyCode );
15816				match = this._filterMenuItems( character );
15817			}
15818
15819			if ( match.length ) {
15820				this.focus( event, match );
15821				this.previousFilter = character;
15822				this.filterTimer = this._delay( function() {
15823					delete this.previousFilter;
15824				}, 1000 );
15825			} else {
15826				delete this.previousFilter;
15827			}
15828		}
15829
15830		if ( preventDefault ) {
15831			event.preventDefault();
15832		}
15833	},
15834
15835	_activate: function( event ) {
15836		if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
15837			if ( this.active.children( "[aria-haspopup='true']" ).length ) {
15838				this.expand( event );
15839			} else {
15840				this.select( event );
15841			}
15842		}
15843	},
15844
15845	refresh: function() {
15846		var menus, items, newSubmenus, newItems, newWrappers,
15847			that = this,
15848			icon = this.options.icons.submenu,
15849			submenus = this.element.find( this.options.menus );
15850
15851		this._toggleClass( "ui-menu-icons", null, !!this.element.find( ".ui-icon" ).length );
15852
15853		// Initialize nested menus
15854		newSubmenus = submenus.filter( ":not(.ui-menu)" )
15855			.hide()
15856			.attr( {
15857				role: this.options.role,
15858				"aria-hidden": "true",
15859				"aria-expanded": "false"
15860			} )
15861			.each( function() {
15862				var menu = $( this ),
15863					item = menu.prev(),
15864					submenuCaret = $( "<span>" ).data( "ui-menu-submenu-caret", true );
15865
15866				that._addClass( submenuCaret, "ui-menu-icon", "ui-icon " + icon );
15867				item
15868					.attr( "aria-haspopup", "true" )
15869					.prepend( submenuCaret );
15870				menu.attr( "aria-labelledby", item.attr( "id" ) );
15871			} );
15872
15873		this._addClass( newSubmenus, "ui-menu", "ui-widget ui-widget-content ui-front" );
15874
15875		menus = submenus.add( this.element );
15876		items = menus.find( this.options.items );
15877
15878		// Initialize menu-items containing spaces and/or dashes only as dividers
15879		items.not( ".ui-menu-item" ).each( function() {
15880			var item = $( this );
15881			if ( that._isDivider( item ) ) {
15882				that._addClass( item, "ui-menu-divider", "ui-widget-content" );
15883			}
15884		} );
15885
15886		// Don't refresh list items that are already adapted
15887		newItems = items.not( ".ui-menu-item, .ui-menu-divider" );
15888		newWrappers = newItems.children()
15889			.not( ".ui-menu" )
15890				.uniqueId()
15891				.attr( {
15892					tabIndex: -1,
15893					role: this._itemRole()
15894				} );
15895		this._addClass( newItems, "ui-menu-item" )
15896			._addClass( newWrappers, "ui-menu-item-wrapper" );
15897
15898		// Add aria-disabled attribute to any disabled menu item
15899		items.filter( ".ui-state-disabled" ).attr( "aria-disabled", "true" );
15900
15901		// If the active item has been removed, blur the menu
15902		if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
15903			this.blur();
15904		}
15905	},
15906
15907	_itemRole: function() {
15908		return {
15909			menu: "menuitem",
15910			listbox: "option"
15911		}[ this.options.role ];
15912	},
15913
15914	_setOption: function( key, value ) {
15915		if ( key === "icons" ) {
15916			var icons = this.element.find( ".ui-menu-icon" );
15917			this._removeClass( icons, null, this.options.icons.submenu )
15918				._addClass( icons, null, value.submenu );
15919		}
15920		this._super( key, value );
15921	},
15922
15923	_setOptionDisabled: function( value ) {
15924		this._super( value );
15925
15926		this.element.attr( "aria-disabled", String( value ) );
15927		this._toggleClass( null, "ui-state-disabled", !!value );
15928	},
15929
15930	focus: function( event, item ) {
15931		var nested, focused, activeParent;
15932		this.blur( event, event && event.type === "focus" );
15933
15934		this._scrollIntoView( item );
15935
15936		this.active = item.first();
15937
15938		focused = this.active.children( ".ui-menu-item-wrapper" );
15939		this._addClass( focused, null, "ui-state-active" );
15940
15941		// Only update aria-activedescendant if there's a role
15942		// otherwise we assume focus is managed elsewhere
15943		if ( this.options.role ) {
15944			this.element.attr( "aria-activedescendant", focused.attr( "id" ) );
15945		}
15946
15947		// Highlight active parent menu item, if any
15948		activeParent = this.active
15949			.parent()
15950				.closest( ".ui-menu-item" )
15951					.children( ".ui-menu-item-wrapper" );
15952		this._addClass( activeParent, null, "ui-state-active" );
15953
15954		if ( event && event.type === "keydown" ) {
15955			this._close();
15956		} else {
15957			this.timer = this._delay( function() {
15958				this._close();
15959			}, this.delay );
15960		}
15961
15962		nested = item.children( ".ui-menu" );
15963		if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) {
15964			this._startOpening( nested );
15965		}
15966		this.activeMenu = item.parent();
15967
15968		this._trigger( "focus", event, { item: item } );
15969	},
15970
15971	_scrollIntoView: function( item ) {
15972		var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
15973		if ( this._hasScroll() ) {
15974			borderTop = parseFloat( $.css( this.activeMenu[ 0 ], "borderTopWidth" ) ) || 0;
15975			paddingTop = parseFloat( $.css( this.activeMenu[ 0 ], "paddingTop" ) ) || 0;
15976			offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
15977			scroll = this.activeMenu.scrollTop();
15978			elementHeight = this.activeMenu.height();
15979			itemHeight = item.outerHeight();
15980
15981			if ( offset < 0 ) {
15982				this.activeMenu.scrollTop( scroll + offset );
15983			} else if ( offset + itemHeight > elementHeight ) {
15984				this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );
15985			}
15986		}
15987	},
15988
15989	blur: function( event, fromFocus ) {
15990		if ( !fromFocus ) {
15991			clearTimeout( this.timer );
15992		}
15993
15994		if ( !this.active ) {
15995			return;
15996		}
15997
15998		this._removeClass( this.active.children( ".ui-menu-item-wrapper" ),
15999			null, "ui-state-active" );
16000
16001		this._trigger( "blur", event, { item: this.active } );
16002		this.active = null;
16003	},
16004
16005	_startOpening: function( submenu ) {
16006		clearTimeout( this.timer );
16007
16008		// Don't open if already open fixes a Firefox bug that caused a .5 pixel
16009		// shift in the submenu position when mousing over the caret icon
16010		if ( submenu.attr( "aria-hidden" ) !== "true" ) {
16011			return;
16012		}
16013
16014		this.timer = this._delay( function() {
16015			this._close();
16016			this._open( submenu );
16017		}, this.delay );
16018	},
16019
16020	_open: function( submenu ) {
16021		var position = $.extend( {
16022			of: this.active
16023		}, this.options.position );
16024
16025		clearTimeout( this.timer );
16026		this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) )
16027			.hide()
16028			.attr( "aria-hidden", "true" );
16029
16030		submenu
16031			.show()
16032			.removeAttr( "aria-hidden" )
16033			.attr( "aria-expanded", "true" )
16034			.position( position );
16035	},
16036
16037	collapseAll: function( event, all ) {
16038		clearTimeout( this.timer );
16039		this.timer = this._delay( function() {
16040
16041			// If we were passed an event, look for the submenu that contains the event
16042			var currentMenu = all ? this.element :
16043				$( event && event.target ).closest( this.element.find( ".ui-menu" ) );
16044
16045			// If we found no valid submenu ancestor, use the main menu to close all
16046			// sub menus anyway
16047			if ( !currentMenu.length ) {
16048				currentMenu = this.element;
16049			}
16050
16051			this._close( currentMenu );
16052
16053			this.blur( event );
16054
16055			// Work around active item staying active after menu is blurred
16056			this._removeClass( currentMenu.find( ".ui-state-active" ), null, "ui-state-active" );
16057
16058			this.activeMenu = currentMenu;
16059		}, all ? 0 : this.delay );
16060	},
16061
16062	// With no arguments, closes the currently active menu - if nothing is active
16063	// it closes all menus.  If passed an argument, it will search for menus BELOW
16064	_close: function( startMenu ) {
16065		if ( !startMenu ) {
16066			startMenu = this.active ? this.active.parent() : this.element;
16067		}
16068
16069		startMenu.find( ".ui-menu" )
16070			.hide()
16071			.attr( "aria-hidden", "true" )
16072			.attr( "aria-expanded", "false" );
16073	},
16074
16075	_closeOnDocumentClick: function( event ) {
16076		return !$( event.target ).closest( ".ui-menu" ).length;
16077	},
16078
16079	_isDivider: function( item ) {
16080
16081		// Match hyphen, em dash, en dash
16082		return !/[^\-\u2014\u2013\s]/.test( item.text() );
16083	},
16084
16085	collapse: function( event ) {
16086		var newItem = this.active &&
16087			this.active.parent().closest( ".ui-menu-item", this.element );
16088		if ( newItem && newItem.length ) {
16089			this._close();
16090			this.focus( event, newItem );
16091		}
16092	},
16093
16094	expand: function( event ) {
16095		var newItem = this.active && this._menuItems( this.active.children( ".ui-menu" ) ).first();
16096
16097		if ( newItem && newItem.length ) {
16098			this._open( newItem.parent() );
16099
16100			// Delay so Firefox will not hide activedescendant change in expanding submenu from AT
16101			this._delay( function() {
16102				this.focus( event, newItem );
16103			} );
16104		}
16105	},
16106
16107	next: function( event ) {
16108		this._move( "next", "first", event );
16109	},
16110
16111	previous: function( event ) {
16112		this._move( "prev", "last", event );
16113	},
16114
16115	isFirstItem: function() {
16116		return this.active && !this.active.prevAll( ".ui-menu-item" ).length;
16117	},
16118
16119	isLastItem: function() {
16120		return this.active && !this.active.nextAll( ".ui-menu-item" ).length;
16121	},
16122
16123	_menuItems: function( menu ) {
16124		return ( menu || this.element )
16125			.find( this.options.items )
16126			.filter( ".ui-menu-item" );
16127	},
16128
16129	_move: function( direction, filter, event ) {
16130		var next;
16131		if ( this.active ) {
16132			if ( direction === "first" || direction === "last" ) {
16133				next = this.active
16134					[ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )
16135					.last();
16136			} else {
16137				next = this.active
16138					[ direction + "All" ]( ".ui-menu-item" )
16139					.first();
16140			}
16141		}
16142		if ( !next || !next.length || !this.active ) {
16143			next = this._menuItems( this.activeMenu )[ filter ]();
16144		}
16145
16146		this.focus( event, next );
16147	},
16148
16149	nextPage: function( event ) {
16150		var item, base, height;
16151
16152		if ( !this.active ) {
16153			this.next( event );
16154			return;
16155		}
16156		if ( this.isLastItem() ) {
16157			return;
16158		}
16159		if ( this._hasScroll() ) {
16160			base = this.active.offset().top;
16161			height = this.element.innerHeight();
16162
16163			// jQuery 3.2 doesn't include scrollbars in innerHeight, add it back.
16164			if ( $.fn.jquery.indexOf( "3.2." ) === 0 ) {
16165				height += this.element[ 0 ].offsetHeight - this.element.outerHeight();
16166			}
16167
16168			this.active.nextAll( ".ui-menu-item" ).each( function() {
16169				item = $( this );
16170				return item.offset().top - base - height < 0;
16171			} );
16172
16173			this.focus( event, item );
16174		} else {
16175			this.focus( event, this._menuItems( this.activeMenu )
16176				[ !this.active ? "first" : "last" ]() );
16177		}
16178	},
16179
16180	previousPage: function( event ) {
16181		var item, base, height;
16182		if ( !this.active ) {
16183			this.next( event );
16184			return;
16185		}
16186		if ( this.isFirstItem() ) {
16187			return;
16188		}
16189		if ( this._hasScroll() ) {
16190			base = this.active.offset().top;
16191			height = this.element.innerHeight();
16192
16193			// jQuery 3.2 doesn't include scrollbars in innerHeight, add it back.
16194			if ( $.fn.jquery.indexOf( "3.2." ) === 0 ) {
16195				height += this.element[ 0 ].offsetHeight - this.element.outerHeight();
16196			}
16197
16198			this.active.prevAll( ".ui-menu-item" ).each( function() {
16199				item = $( this );
16200				return item.offset().top - base + height > 0;
16201			} );
16202
16203			this.focus( event, item );
16204		} else {
16205			this.focus( event, this._menuItems( this.activeMenu ).first() );
16206		}
16207	},
16208
16209	_hasScroll: function() {
16210		return this.element.outerHeight() < this.element.prop( "scrollHeight" );
16211	},
16212
16213	select: function( event ) {
16214
16215		// TODO: It should never be possible to not have an active item at this
16216		// point, but the tests don't trigger mouseenter before click.
16217		this.active = this.active || $( event.target ).closest( ".ui-menu-item" );
16218		var ui = { item: this.active };
16219		if ( !this.active.has( ".ui-menu" ).length ) {
16220			this.collapseAll( event, true );
16221		}
16222		this._trigger( "select", event, ui );
16223	},
16224
16225	_filterMenuItems: function( character ) {
16226		var escapedCharacter = character.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ),
16227			regex = new RegExp( "^" + escapedCharacter, "i" );
16228
16229		return this.activeMenu
16230			.find( this.options.items )
16231
16232				// Only match on items, not dividers or other content (#10571)
16233				.filter( ".ui-menu-item" )
16234					.filter( function() {
16235						return regex.test(
16236							String.prototype.trim.call(
16237								$( this ).children( ".ui-menu-item-wrapper" ).text() ) );
16238					} );
16239	}
16240} );
16241
16242
16243/*!
16244 * jQuery UI Autocomplete 1.14.1
16245 * https://jqueryui.com
16246 *
16247 * Copyright OpenJS Foundation and other contributors
16248 * Released under the MIT license.
16249 * https://jquery.org/license
16250 */
16251
16252//>>label: Autocomplete
16253//>>group: Widgets
16254//>>description: Lists suggested words as the user is typing.
16255//>>docs: https://api.jqueryui.com/autocomplete/
16256//>>demos: https://jqueryui.com/autocomplete/
16257//>>css.structure: ../../themes/base/core.css
16258//>>css.structure: ../../themes/base/autocomplete.css
16259//>>css.theme: ../../themes/base/theme.css
16260
16261
16262$.widget( "ui.autocomplete", {
16263	version: "1.14.1",
16264	defaultElement: "<input>",
16265	options: {
16266		appendTo: null,
16267		autoFocus: false,
16268		delay: 300,
16269		minLength: 1,
16270		position: {
16271			my: "left top",
16272			at: "left bottom",
16273			collision: "none"
16274		},
16275		source: null,
16276
16277		// Callbacks
16278		change: null,
16279		close: null,
16280		focus: null,
16281		open: null,
16282		response: null,
16283		search: null,
16284		select: null
16285	},
16286
16287	requestIndex: 0,
16288	pending: 0,
16289	liveRegionTimer: null,
16290
16291	_create: function() {
16292
16293		// Some browsers only repeat keydown events, not keypress events,
16294		// so we use the suppressKeyPress flag to determine if we've already
16295		// handled the keydown event. #7269
16296		// Unfortunately the code for & in keypress is the same as the up arrow,
16297		// so we use the suppressKeyPressRepeat flag to avoid handling keypress
16298		// events when we know the keydown event was used to modify the
16299		// search term. #7799
16300		var suppressKeyPress, suppressKeyPressRepeat, suppressInput,
16301			nodeName = this.element[ 0 ].nodeName.toLowerCase(),
16302			isTextarea = nodeName === "textarea",
16303			isInput = nodeName === "input";
16304
16305		// Textareas are always multi-line
16306		// Inputs are always single-line, even if inside a contentEditable element
16307		// All other element types are determined by whether they're contentEditable
16308		this.isMultiLine = isTextarea ||
16309			!isInput && this.element.prop( "contentEditable" ) === "true";
16310
16311		this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ];
16312		this.isNewMenu = true;
16313
16314		this._addClass( "ui-autocomplete-input" );
16315		this.element.attr( "autocomplete", "off" );
16316
16317		this._on( this.element, {
16318			keydown: function( event ) {
16319				if ( this.element.prop( "readOnly" ) ) {
16320					suppressKeyPress = true;
16321					suppressInput = true;
16322					suppressKeyPressRepeat = true;
16323					return;
16324				}
16325
16326				suppressKeyPress = false;
16327				suppressInput = false;
16328				suppressKeyPressRepeat = false;
16329				var keyCode = $.ui.keyCode;
16330				switch ( event.keyCode ) {
16331				case keyCode.PAGE_UP:
16332					suppressKeyPress = true;
16333					this._move( "previousPage", event );
16334					break;
16335				case keyCode.PAGE_DOWN:
16336					suppressKeyPress = true;
16337					this._move( "nextPage", event );
16338					break;
16339				case keyCode.UP:
16340					suppressKeyPress = true;
16341					this._keyEvent( "previous", event );
16342					break;
16343				case keyCode.DOWN:
16344					suppressKeyPress = true;
16345					this._keyEvent( "next", event );
16346					break;
16347				case keyCode.ENTER:
16348
16349					// when menu is open and has focus
16350					if ( this.menu.active ) {
16351
16352						// #6055 - Opera still allows the keypress to occur
16353						// which causes forms to submit
16354						suppressKeyPress = true;
16355						event.preventDefault();
16356						this.menu.select( event );
16357					}
16358					break;
16359				case keyCode.TAB:
16360					if ( this.menu.active ) {
16361						this.menu.select( event );
16362					}
16363					break;
16364				case keyCode.ESCAPE:
16365					if ( this.menu.element.is( ":visible" ) ) {
16366						if ( !this.isMultiLine ) {
16367							this._value( this.term );
16368						}
16369						this.close( event );
16370
16371						// Different browsers have different default behavior for escape
16372						// Single press can mean undo or clear
16373						event.preventDefault();
16374					}
16375					break;
16376				default:
16377					suppressKeyPressRepeat = true;
16378
16379					// search timeout should be triggered before the input value is changed
16380					this._searchTimeout( event );
16381					break;
16382				}
16383			},
16384			keypress: function( event ) {
16385				if ( suppressKeyPress ) {
16386					suppressKeyPress = false;
16387					if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
16388						event.preventDefault();
16389					}
16390					return;
16391				}
16392				if ( suppressKeyPressRepeat ) {
16393					return;
16394				}
16395
16396				// Replicate some key handlers to allow them to repeat in Firefox and Opera
16397				var keyCode = $.ui.keyCode;
16398				switch ( event.keyCode ) {
16399				case keyCode.PAGE_UP:
16400					this._move( "previousPage", event );
16401					break;
16402				case keyCode.PAGE_DOWN:
16403					this._move( "nextPage", event );
16404					break;
16405				case keyCode.UP:
16406					this._keyEvent( "previous", event );
16407					break;
16408				case keyCode.DOWN:
16409					this._keyEvent( "next", event );
16410					break;
16411				}
16412			},
16413			input: function( event ) {
16414				if ( suppressInput ) {
16415					suppressInput = false;
16416					event.preventDefault();
16417					return;
16418				}
16419				this._searchTimeout( event );
16420			},
16421			focus: function() {
16422				this.selectedItem = null;
16423				this.previous = this._value();
16424			},
16425			blur: function( event ) {
16426				clearTimeout( this.searching );
16427				this.close( event );
16428				this._change( event );
16429			}
16430		} );
16431
16432		this._initSource();
16433		this.menu = $( "<ul>" )
16434			.appendTo( this._appendTo() )
16435			.menu( {
16436
16437				// disable ARIA support, the live region takes care of that
16438				role: null
16439			} )
16440			.hide()
16441			.menu( "instance" );
16442
16443		this._addClass( this.menu.element, "ui-autocomplete", "ui-front" );
16444		this._on( this.menu.element, {
16445			mousedown: function( event ) {
16446
16447				// Prevent moving focus out of the text field
16448				event.preventDefault();
16449			},
16450			menufocus: function( event, ui ) {
16451				var label, item;
16452
16453				// Support: Firefox
16454				// Prevent accidental activation of menu items in Firefox (#7024 #9118)
16455				if ( this.isNewMenu ) {
16456					this.isNewMenu = false;
16457					if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {
16458						this.menu.blur();
16459
16460						this.document.one( "mousemove", function() {
16461							$( event.target ).trigger( event.originalEvent );
16462						} );
16463
16464						return;
16465					}
16466				}
16467
16468				item = ui.item.data( "ui-autocomplete-item" );
16469				if ( false !== this._trigger( "focus", event, { item: item } ) ) {
16470
16471					// use value to match what will end up in the input, if it was a key event
16472					if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
16473						this._value( item.value );
16474					}
16475				}
16476
16477				// Announce the value in the liveRegion
16478				label = ui.item.attr( "aria-label" ) || item.value;
16479				if ( label && String.prototype.trim.call( label ).length ) {
16480					clearTimeout( this.liveRegionTimer );
16481					this.liveRegionTimer = this._delay( function() {
16482						this.liveRegion.html( $( "<div>" ).text( label ) );
16483					}, 100 );
16484				}
16485			},
16486			menuselect: function( event, ui ) {
16487				var item = ui.item.data( "ui-autocomplete-item" ),
16488					previous = this.previous;
16489
16490				// Only trigger when focus was lost (click on menu)
16491				if ( this.element[ 0 ] !== this.document[ 0 ].activeElement ) {
16492					this.element.trigger( "focus" );
16493					this.previous = previous;
16494				}
16495
16496				if ( false !== this._trigger( "select", event, { item: item } ) ) {
16497					this._value( item.value );
16498				}
16499
16500				// reset the term after the select event
16501				// this allows custom select handling to work properly
16502				this.term = this._value();
16503
16504				this.close( event );
16505				this.selectedItem = item;
16506			}
16507		} );
16508
16509		this.liveRegion = $( "<div>", {
16510			role: "status",
16511			"aria-live": "assertive",
16512			"aria-relevant": "additions"
16513		} )
16514			.appendTo( this.document[ 0 ].body );
16515
16516		this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" );
16517
16518		// Turning off autocomplete prevents the browser from remembering the
16519		// value when navigating through history, so we re-enable autocomplete
16520		// if the page is unloaded before the widget is destroyed. #7790
16521		this._on( this.window, {
16522			beforeunload: function() {
16523				this.element.removeAttr( "autocomplete" );
16524			}
16525		} );
16526	},
16527
16528	_destroy: function() {
16529		clearTimeout( this.searching );
16530		this.element.removeAttr( "autocomplete" );
16531		this.menu.element.remove();
16532		this.liveRegion.remove();
16533	},
16534
16535	_setOption: function( key, value ) {
16536		this._super( key, value );
16537		if ( key === "source" ) {
16538			this._initSource();
16539		}
16540		if ( key === "appendTo" ) {
16541			this.menu.element.appendTo( this._appendTo() );
16542		}
16543		if ( key === "disabled" && value && this.xhr ) {
16544			this.xhr.abort();
16545		}
16546	},
16547
16548	_isEventTargetInWidget: function( event ) {
16549		var menuElement = this.menu.element[ 0 ];
16550
16551		return event.target === this.element[ 0 ] ||
16552			event.target === menuElement ||
16553			$.contains( menuElement, event.target );
16554	},
16555
16556	_closeOnClickOutside: function( event ) {
16557		if ( !this._isEventTargetInWidget( event ) ) {
16558			this.close();
16559		}
16560	},
16561
16562	_appendTo: function() {
16563		var element = this.options.appendTo;
16564
16565		if ( element ) {
16566			element = element.jquery || element.nodeType ?
16567				$( element ) :
16568				this.document.find( element ).eq( 0 );
16569		}
16570
16571		if ( !element || !element[ 0 ] ) {
16572			element = this.element.closest( ".ui-front, dialog" );
16573		}
16574
16575		if ( !element.length ) {
16576			element = this.document[ 0 ].body;
16577		}
16578
16579		return element;
16580	},
16581
16582	_initSource: function() {
16583		var array, url,
16584			that = this;
16585		if ( Array.isArray( this.options.source ) ) {
16586			array = this.options.source;
16587			this.source = function( request, response ) {
16588				response( $.ui.autocomplete.filter( array, request.term ) );
16589			};
16590		} else if ( typeof this.options.source === "string" ) {
16591			url = this.options.source;
16592			this.source = function( request, response ) {
16593				if ( that.xhr ) {
16594					that.xhr.abort();
16595				}
16596				that.xhr = $.ajax( {
16597					url: url,
16598					data: request,
16599					dataType: "json",
16600					success: function( data ) {
16601						response( data );
16602					},
16603					error: function() {
16604						response( [] );
16605					}
16606				} );
16607			};
16608		} else {
16609			this.source = this.options.source;
16610		}
16611	},
16612
16613	_searchTimeout: function( event ) {
16614		clearTimeout( this.searching );
16615		this.searching = this._delay( function() {
16616
16617			// Search if the value has changed, or if the user retypes the same value (see #7434)
16618			var equalValues = this.term === this._value(),
16619				menuVisible = this.menu.element.is( ":visible" ),
16620				modifierKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
16621
16622			if ( !equalValues || ( equalValues && !menuVisible && !modifierKey ) ) {
16623				this.selectedItem = null;
16624				this.search( null, event );
16625			}
16626		}, this.options.delay );
16627	},
16628
16629	search: function( value, event ) {
16630		value = value != null ? value : this._value();
16631
16632		// Always save the actual value, not the one passed as an argument
16633		this.term = this._value();
16634
16635		if ( value.length < this.options.minLength ) {
16636			return this.close( event );
16637		}
16638
16639		if ( this._trigger( "search", event ) === false ) {
16640			return;
16641		}
16642
16643		return this._search( value );
16644	},
16645
16646	_search: function( value ) {
16647		this.pending++;
16648		this._addClass( "ui-autocomplete-loading" );
16649		this.cancelSearch = false;
16650
16651		this.source( { term: value }, this._response() );
16652	},
16653
16654	_response: function() {
16655		var index = ++this.requestIndex;
16656
16657		return function( content ) {
16658			if ( index === this.requestIndex ) {
16659				this.__response( content );
16660			}
16661
16662			this.pending--;
16663			if ( !this.pending ) {
16664				this._removeClass( "ui-autocomplete-loading" );
16665			}
16666		}.bind( this );
16667	},
16668
16669	__response: function( content ) {
16670		if ( content ) {
16671			content = this._normalize( content );
16672		}
16673		this._trigger( "response", null, { content: content } );
16674		if ( !this.options.disabled && content && content.length && !this.cancelSearch ) {
16675			this._suggest( content );
16676			this._trigger( "open" );
16677		} else {
16678
16679			// use ._close() instead of .close() so we don't cancel future searches
16680			this._close();
16681		}
16682	},
16683
16684	close: function( event ) {
16685		this.cancelSearch = true;
16686		this._close( event );
16687	},
16688
16689	_close: function( event ) {
16690
16691		// Remove the handler that closes the menu on outside clicks
16692		this._off( this.document, "mousedown" );
16693
16694		if ( this.menu.element.is( ":visible" ) ) {
16695			this.menu.element.hide();
16696			this.menu.blur();
16697			this.isNewMenu = true;
16698			this._trigger( "close", event );
16699		}
16700	},
16701
16702	_change: function( event ) {
16703		if ( this.previous !== this._value() ) {
16704			this._trigger( "change", event, { item: this.selectedItem } );
16705		}
16706	},
16707
16708	_normalize: function( items ) {
16709
16710		// assume all items have the right format when the first item is complete
16711		if ( items.length && items[ 0 ].label && items[ 0 ].value ) {
16712			return items;
16713		}
16714		return $.map( items, function( item ) {
16715			if ( typeof item === "string" ) {
16716				return {
16717					label: item,
16718					value: item
16719				};
16720			}
16721			return $.extend( {}, item, {
16722				label: item.label || item.value,
16723				value: item.value || item.label
16724			} );
16725		} );
16726	},
16727
16728	_suggest: function( items ) {
16729		var ul = this.menu.element.empty();
16730		this._renderMenu( ul, items );
16731		this.isNewMenu = true;
16732		this.menu.refresh();
16733
16734		// Size and position menu
16735		ul.show();
16736		this._resizeMenu();
16737		ul.position( $.extend( {
16738			of: this.element
16739		}, this.options.position ) );
16740
16741		if ( this.options.autoFocus ) {
16742			this.menu.next();
16743		}
16744
16745		// Listen for interactions outside of the widget (#6642)
16746		this._on( this.document, {
16747			mousedown: "_closeOnClickOutside"
16748		} );
16749	},
16750
16751	_resizeMenu: function() {
16752		var ul = this.menu.element;
16753		ul.outerWidth( Math.max(
16754
16755			// Firefox wraps long text (possibly a rounding bug)
16756			// so we add 1px to avoid the wrapping (#7513)
16757			ul.width( "" ).outerWidth() + 1,
16758			this.element.outerWidth()
16759		) );
16760	},
16761
16762	_renderMenu: function( ul, items ) {
16763		var that = this;
16764		$.each( items, function( index, item ) {
16765			that._renderItemData( ul, item );
16766		} );
16767	},
16768
16769	_renderItemData: function( ul, item ) {
16770		return this._renderItem( ul, item ).data( "ui-autocomplete-item", item );
16771	},
16772
16773	_renderItem: function( ul, item ) {
16774		return $( "<li>" )
16775			.append( $( "<div>" ).text( item.label ) )
16776			.appendTo( ul );
16777	},
16778
16779	_move: function( direction, event ) {
16780		if ( !this.menu.element.is( ":visible" ) ) {
16781			this.search( null, event );
16782			return;
16783		}
16784		if ( this.menu.isFirstItem() && /^previous/.test( direction ) ||
16785				this.menu.isLastItem() && /^next/.test( direction ) ) {
16786
16787			if ( !this.isMultiLine ) {
16788				this._value( this.term );
16789			}
16790
16791			this.menu.blur();
16792			return;
16793		}
16794		this.menu[ direction ]( event );
16795	},
16796
16797	widget: function() {
16798		return this.menu.element;
16799	},
16800
16801	_value: function() {
16802		return this.valueMethod.apply( this.element, arguments );
16803	},
16804
16805	_keyEvent: function( keyEvent, event ) {
16806		if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
16807			this._move( keyEvent, event );
16808
16809			// Prevents moving cursor to beginning/end of the text field in some browsers
16810			event.preventDefault();
16811		}
16812	}
16813} );
16814
16815$.extend( $.ui.autocomplete, {
16816	escapeRegex: function( value ) {
16817		return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
16818	},
16819	filter: function( array, term ) {
16820		var matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), "i" );
16821		return $.grep( array, function( value ) {
16822			return matcher.test( value.label || value.value || value );
16823		} );
16824	}
16825} );
16826
16827// Live region extension, adding a `messages` option
16828// NOTE: This is an experimental API. We are still investigating
16829// a full solution for string manipulation and internationalization.
16830$.widget( "ui.autocomplete", $.ui.autocomplete, {
16831	options: {
16832		messages: {
16833			noResults: "No search results.",
16834			results: function( amount ) {
16835				return amount + ( amount > 1 ? " results are" : " result is" ) +
16836					" available, use up and down arrow keys to navigate.";
16837			}
16838		}
16839	},
16840
16841	__response: function( content ) {
16842		var message;
16843		this._superApply( arguments );
16844		if ( this.options.disabled || this.cancelSearch ) {
16845			return;
16846		}
16847		if ( content && content.length ) {
16848			message = this.options.messages.results( content.length );
16849		} else {
16850			message = this.options.messages.noResults;
16851		}
16852		clearTimeout( this.liveRegionTimer );
16853		this.liveRegionTimer = this._delay( function() {
16854			this.liveRegion.html( $( "<div>" ).text( message ) );
16855		}, 100 );
16856	}
16857} );
16858
16859var widgetsAutocomplete = $.ui.autocomplete;
16860
16861
16862/*!
16863 * jQuery UI Controlgroup 1.14.1
16864 * https://jqueryui.com
16865 *
16866 * Copyright OpenJS Foundation and other contributors
16867 * Released under the MIT license.
16868 * https://jquery.org/license
16869 */
16870
16871//>>label: Controlgroup
16872//>>group: Widgets
16873//>>description: Visually groups form control widgets
16874//>>docs: https://api.jqueryui.com/controlgroup/
16875//>>demos: https://jqueryui.com/controlgroup/
16876//>>css.structure: ../../themes/base/core.css
16877//>>css.structure: ../../themes/base/controlgroup.css
16878//>>css.theme: ../../themes/base/theme.css
16879
16880
16881var controlgroupCornerRegex = /ui-corner-([a-z]){2,6}/g;
16882
16883var widgetsControlgroup = $.widget( "ui.controlgroup", {
16884	version: "1.14.1",
16885	defaultElement: "<div>",
16886	options: {
16887		direction: "horizontal",
16888		disabled: null,
16889		onlyVisible: true,
16890		items: {
16891			"button": "input[type=button], input[type=submit], input[type=reset], button, a",
16892			"controlgroupLabel": ".ui-controlgroup-label",
16893			"checkboxradio": "input[type='checkbox'], input[type='radio']",
16894			"selectmenu": "select",
16895			"spinner": ".ui-spinner-input"
16896		}
16897	},
16898
16899	_create: function() {
16900		this._enhance();
16901	},
16902
16903	// To support the enhanced option in jQuery Mobile, we isolate DOM manipulation
16904	_enhance: function() {
16905		this.element.attr( "role", "toolbar" );
16906		this.refresh();
16907	},
16908
16909	_destroy: function() {
16910		this._callChildMethod( "destroy" );
16911		this.childWidgets.removeData( "ui-controlgroup-data" );
16912		this.element.removeAttr( "role" );
16913		if ( this.options.items.controlgroupLabel ) {
16914			this.element
16915				.find( this.options.items.controlgroupLabel )
16916				.find( ".ui-controlgroup-label-contents" )
16917				.contents().unwrap();
16918		}
16919	},
16920
16921	_initWidgets: function() {
16922		var that = this,
16923			childWidgets = [];
16924
16925		// First we iterate over each of the items options
16926		$.each( this.options.items, function( widget, selector ) {
16927			var labels;
16928			var options = {};
16929
16930			// Make sure the widget has a selector set
16931			if ( !selector ) {
16932				return;
16933			}
16934
16935			if ( widget === "controlgroupLabel" ) {
16936				labels = that.element.find( selector );
16937				labels.each( function() {
16938					var element = $( this );
16939
16940					if ( element.children( ".ui-controlgroup-label-contents" ).length ) {
16941						return;
16942					}
16943					element.contents()
16944						.wrapAll( "<span class='ui-controlgroup-label-contents'></span>" );
16945				} );
16946				that._addClass( labels, null, "ui-widget ui-widget-content ui-state-default" );
16947				childWidgets = childWidgets.concat( labels.get() );
16948				return;
16949			}
16950
16951			// Make sure the widget actually exists
16952			if ( !$.fn[ widget ] ) {
16953				return;
16954			}
16955
16956			// We assume everything is in the middle to start because we can't determine
16957			// first / last elements until all enhancments are done.
16958			if ( that[ "_" + widget + "Options" ] ) {
16959				options = that[ "_" + widget + "Options" ]( "middle" );
16960			} else {
16961				options = { classes: {} };
16962			}
16963
16964			// Find instances of this widget inside controlgroup and init them
16965			that.element
16966				.find( selector )
16967				.each( function() {
16968					var element = $( this );
16969					var instance = element[ widget ]( "instance" );
16970
16971					// We need to clone the default options for this type of widget to avoid
16972					// polluting the variable options which has a wider scope than a single widget.
16973					var instanceOptions = $.widget.extend( {}, options );
16974
16975					// If the button is the child of a spinner ignore it
16976					// TODO: Find a more generic solution
16977					if ( widget === "button" && element.parent( ".ui-spinner" ).length ) {
16978						return;
16979					}
16980
16981					// Create the widget if it doesn't exist
16982					if ( !instance ) {
16983						instance = element[ widget ]()[ widget ]( "instance" );
16984					}
16985					if ( instance ) {
16986						instanceOptions.classes =
16987							that._resolveClassesValues( instanceOptions.classes, instance );
16988					}
16989					element[ widget ]( instanceOptions );
16990
16991					// Store an instance of the controlgroup to be able to reference
16992					// from the outermost element for changing options and refresh
16993					var widgetElement = element[ widget ]( "widget" );
16994					$.data( widgetElement[ 0 ], "ui-controlgroup-data",
16995						instance ? instance : element[ widget ]( "instance" ) );
16996
16997					childWidgets.push( widgetElement[ 0 ] );
16998				} );
16999		} );
17000
17001		this.childWidgets = $( $.uniqueSort( childWidgets ) );
17002		this._addClass( this.childWidgets, "ui-controlgroup-item" );
17003	},
17004
17005	_callChildMethod: function( method ) {
17006		this.childWidgets.each( function() {
17007			var element = $( this ),
17008				data = element.data( "ui-controlgroup-data" );
17009			if ( data && data[ method ] ) {
17010				data[ method ]();
17011			}
17012		} );
17013	},
17014
17015	_updateCornerClass: function( element, position ) {
17016		var remove = "ui-corner-top ui-corner-bottom ui-corner-left ui-corner-right ui-corner-all";
17017		var add = this._buildSimpleOptions( position, "label" ).classes.label;
17018
17019		this._removeClass( element, null, remove );
17020		this._addClass( element, null, add );
17021	},
17022
17023	_buildSimpleOptions: function( position, key ) {
17024		var direction = this.options.direction === "vertical";
17025		var result = {
17026			classes: {}
17027		};
17028		result.classes[ key ] = {
17029			"middle": "",
17030			"first": "ui-corner-" + ( direction ? "top" : "left" ),
17031			"last": "ui-corner-" + ( direction ? "bottom" : "right" ),
17032			"only": "ui-corner-all"
17033		}[ position ];
17034
17035		return result;
17036	},
17037
17038	_spinnerOptions: function( position ) {
17039		var options = this._buildSimpleOptions( position, "ui-spinner" );
17040
17041		options.classes[ "ui-spinner-up" ] = "";
17042		options.classes[ "ui-spinner-down" ] = "";
17043
17044		return options;
17045	},
17046
17047	_buttonOptions: function( position ) {
17048		return this._buildSimpleOptions( position, "ui-button" );
17049	},
17050
17051	_checkboxradioOptions: function( position ) {
17052		return this._buildSimpleOptions( position, "ui-checkboxradio-label" );
17053	},
17054
17055	_selectmenuOptions: function( position ) {
17056		var direction = this.options.direction === "vertical";
17057		return {
17058			width: direction ? "auto" : false,
17059			classes: {
17060				middle: {
17061					"ui-selectmenu-button-open": "",
17062					"ui-selectmenu-button-closed": ""
17063				},
17064				first: {
17065					"ui-selectmenu-button-open": "ui-corner-" + ( direction ? "top" : "tl" ),
17066					"ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "top" : "left" )
17067				},
17068				last: {
17069					"ui-selectmenu-button-open": direction ? "" : "ui-corner-tr",
17070					"ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "bottom" : "right" )
17071				},
17072				only: {
17073					"ui-selectmenu-button-open": "ui-corner-top",
17074					"ui-selectmenu-button-closed": "ui-corner-all"
17075				}
17076
17077			}[ position ]
17078		};
17079	},
17080
17081	_resolveClassesValues: function( classes, instance ) {
17082		var result = {};
17083		$.each( classes, function( key ) {
17084			var current = instance.options.classes[ key ] || "";
17085			current = String.prototype.trim.call( current.replace( controlgroupCornerRegex, "" ) );
17086			result[ key ] = ( current + " " + classes[ key ] ).replace( /\s+/g, " " );
17087		} );
17088		return result;
17089	},
17090
17091	_setOption: function( key, value ) {
17092		if ( key === "direction" ) {
17093			this._removeClass( "ui-controlgroup-" + this.options.direction );
17094		}
17095
17096		this._super( key, value );
17097		if ( key === "disabled" ) {
17098			this._callChildMethod( value ? "disable" : "enable" );
17099			return;
17100		}
17101
17102		this.refresh();
17103	},
17104
17105	refresh: function() {
17106		var children,
17107			that = this;
17108
17109		this._addClass( "ui-controlgroup ui-controlgroup-" + this.options.direction );
17110
17111		if ( this.options.direction === "horizontal" ) {
17112			this._addClass( null, "ui-helper-clearfix" );
17113		}
17114		this._initWidgets();
17115
17116		children = this.childWidgets;
17117
17118		// We filter here because we need to track all childWidgets not just the visible ones
17119		if ( this.options.onlyVisible ) {
17120			children = children.filter( ":visible" );
17121		}
17122
17123		if ( children.length ) {
17124
17125			// We do this last because we need to make sure all enhancment is done
17126			// before determining first and last
17127			$.each( [ "first", "last" ], function( index, value ) {
17128				var instance = children[ value ]().data( "ui-controlgroup-data" );
17129
17130				if ( instance && that[ "_" + instance.widgetName + "Options" ] ) {
17131					var options = that[ "_" + instance.widgetName + "Options" ](
17132						children.length === 1 ? "only" : value
17133					);
17134					options.classes = that._resolveClassesValues( options.classes, instance );
17135					instance.element[ instance.widgetName ]( options );
17136				} else {
17137					that._updateCornerClass( children[ value ](), value );
17138				}
17139			} );
17140
17141			// Finally call the refresh method on each of the child widgets.
17142			this._callChildMethod( "refresh" );
17143		}
17144	}
17145} );
17146
17147/*!
17148 * jQuery UI Checkboxradio 1.14.1
17149 * https://jqueryui.com
17150 *
17151 * Copyright OpenJS Foundation and other contributors
17152 * Released under the MIT license.
17153 * https://jquery.org/license
17154 */
17155
17156//>>label: Checkboxradio
17157//>>group: Widgets
17158//>>description: Enhances a form with multiple themeable checkboxes or radio buttons.
17159//>>docs: https://api.jqueryui.com/checkboxradio/
17160//>>demos: https://jqueryui.com/checkboxradio/
17161//>>css.structure: ../../themes/base/core.css
17162//>>css.structure: ../../themes/base/button.css
17163//>>css.structure: ../../themes/base/checkboxradio.css
17164//>>css.theme: ../../themes/base/theme.css
17165
17166
17167$.widget( "ui.checkboxradio", [ $.ui.formResetMixin, {
17168	version: "1.14.1",
17169	options: {
17170		disabled: null,
17171		label: null,
17172		icon: true,
17173		classes: {
17174			"ui-checkboxradio-label": "ui-corner-all",
17175			"ui-checkboxradio-icon": "ui-corner-all"
17176		}
17177	},
17178
17179	_getCreateOptions: function() {
17180		var disabled, labels, labelContents;
17181		var options = this._super() || {};
17182
17183		// We read the type here, because it makes more sense to throw a element type error first,
17184		// rather then the error for lack of a label. Often if its the wrong type, it
17185		// won't have a label (e.g. calling on a div, btn, etc)
17186		this._readType();
17187
17188		labels = this.element.labels();
17189
17190		// If there are multiple labels, use the last one
17191		this.label = $( labels[ labels.length - 1 ] );
17192		if ( !this.label.length ) {
17193			$.error( "No label found for checkboxradio widget" );
17194		}
17195
17196		this.originalLabel = "";
17197
17198		// We need to get the label text but this may also need to make sure it does not contain the
17199		// input itself.
17200		// The label contents could be text, html, or a mix. We wrap all elements
17201		// and read the wrapper's `innerHTML` to get a string representation of
17202		// the label, without the input as part of it.
17203		labelContents = this.label.contents().not( this.element[ 0 ] );
17204
17205		if ( labelContents.length ) {
17206			this.originalLabel += labelContents
17207				.clone()
17208				.wrapAll( "<div></div>" )
17209				.parent()
17210				.html();
17211		}
17212
17213		// Set the label option if we found label text
17214		if ( this.originalLabel ) {
17215			options.label = this.originalLabel;
17216		}
17217
17218		disabled = this.element[ 0 ].disabled;
17219		if ( disabled != null ) {
17220			options.disabled = disabled;
17221		}
17222		return options;
17223	},
17224
17225	_create: function() {
17226		var checked = this.element[ 0 ].checked;
17227
17228		this._bindFormResetHandler();
17229
17230		if ( this.options.disabled == null ) {
17231			this.options.disabled = this.element[ 0 ].disabled;
17232		}
17233
17234		this._setOption( "disabled", this.options.disabled );
17235		this._addClass( "ui-checkboxradio", "ui-helper-hidden-accessible" );
17236		this._addClass( this.label, "ui-checkboxradio-label", "ui-button ui-widget" );
17237
17238		if ( this.type === "radio" ) {
17239			this._addClass( this.label, "ui-checkboxradio-radio-label" );
17240		}
17241
17242		if ( this.options.label && this.options.label !== this.originalLabel ) {
17243			this._updateLabel();
17244		} else if ( this.originalLabel ) {
17245			this.options.label = this.originalLabel;
17246		}
17247
17248		this._enhance();
17249
17250		if ( checked ) {
17251			this._addClass( this.label, "ui-checkboxradio-checked", "ui-state-active" );
17252		}
17253
17254		this._on( {
17255			change: "_toggleClasses",
17256			focus: function() {
17257				this._addClass( this.label, null, "ui-state-focus ui-visual-focus" );
17258			},
17259			blur: function() {
17260				this._removeClass( this.label, null, "ui-state-focus ui-visual-focus" );
17261			}
17262		} );
17263	},
17264
17265	_readType: function() {
17266		var nodeName = this.element[ 0 ].nodeName.toLowerCase();
17267		this.type = this.element[ 0 ].type;
17268		if ( nodeName !== "input" || !/radio|checkbox/.test( this.type ) ) {
17269			$.error( "Can't create checkboxradio on element.nodeName=" + nodeName +
17270				" and element.type=" + this.type );
17271		}
17272	},
17273
17274	// Support jQuery Mobile enhanced option
17275	_enhance: function() {
17276		this._updateIcon( this.element[ 0 ].checked );
17277	},
17278
17279	widget: function() {
17280		return this.label;
17281	},
17282
17283	_getRadioGroup: function() {
17284		var group;
17285		var name = this.element[ 0 ].name;
17286		var nameSelector = "input[name='" + CSS.escape( name ) + "']";
17287
17288		if ( !name ) {
17289			return $( [] );
17290		}
17291
17292		if ( this.form.length ) {
17293			group = $( this.form[ 0 ].elements ).filter( nameSelector );
17294		} else {
17295
17296			// Not inside a form, check all inputs that also are not inside a form
17297			group = $( nameSelector ).filter( function() {
17298				return $( $( this ).prop( "form" ) ).length === 0;
17299			} );
17300		}
17301
17302		return group.not( this.element );
17303	},
17304
17305	_toggleClasses: function() {
17306		var checked = this.element[ 0 ].checked;
17307		this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked );
17308
17309		if ( this.options.icon && this.type === "checkbox" ) {
17310			this._toggleClass( this.icon, null, "ui-icon-check ui-state-checked", checked )
17311				._toggleClass( this.icon, null, "ui-icon-blank", !checked );
17312		}
17313
17314		if ( this.type === "radio" ) {
17315			this._getRadioGroup()
17316				.each( function() {
17317					var instance = $( this ).checkboxradio( "instance" );
17318
17319					if ( instance ) {
17320						instance._removeClass( instance.label,
17321							"ui-checkboxradio-checked", "ui-state-active" );
17322					}
17323				} );
17324		}
17325	},
17326
17327	_destroy: function() {
17328		this._unbindFormResetHandler();
17329
17330		if ( this.icon ) {
17331			this.icon.remove();
17332			this.iconSpace.remove();
17333		}
17334	},
17335
17336	_setOption: function( key, value ) {
17337
17338		// We don't allow the value to be set to nothing
17339		if ( key === "label" && !value ) {
17340			return;
17341		}
17342
17343		this._super( key, value );
17344
17345		if ( key === "disabled" ) {
17346			this._toggleClass( this.label, null, "ui-state-disabled", value );
17347			this.element[ 0 ].disabled = value;
17348
17349			// Don't refresh when setting disabled
17350			return;
17351		}
17352		this.refresh();
17353	},
17354
17355	_updateIcon: function( checked ) {
17356		var toAdd = "ui-icon ui-icon-background ";
17357
17358		if ( this.options.icon ) {
17359			if ( !this.icon ) {
17360				this.icon = $( "<span>" );
17361				this.iconSpace = $( "<span> </span>" );
17362				this._addClass( this.iconSpace, "ui-checkboxradio-icon-space" );
17363			}
17364
17365			if ( this.type === "checkbox" ) {
17366				toAdd += checked ? "ui-icon-check ui-state-checked" : "ui-icon-blank";
17367				this._removeClass( this.icon, null, checked ? "ui-icon-blank" : "ui-icon-check" );
17368			} else {
17369				toAdd += "ui-icon-blank";
17370			}
17371			this._addClass( this.icon, "ui-checkboxradio-icon", toAdd );
17372			if ( !checked ) {
17373				this._removeClass( this.icon, null, "ui-icon-check ui-state-checked" );
17374			}
17375			this.icon.prependTo( this.label ).after( this.iconSpace );
17376		} else if ( this.icon !== undefined ) {
17377			this.icon.remove();
17378			this.iconSpace.remove();
17379			delete this.icon;
17380		}
17381	},
17382
17383	_updateLabel: function() {
17384
17385		// Remove the contents of the label ( minus the icon, icon space, and input )
17386		var contents = this.label.contents().not( this.element[ 0 ] );
17387		if ( this.icon ) {
17388			contents = contents.not( this.icon[ 0 ] );
17389		}
17390		if ( this.iconSpace ) {
17391			contents = contents.not( this.iconSpace[ 0 ] );
17392		}
17393		contents.remove();
17394
17395		this.label.append( this.options.label );
17396	},
17397
17398	refresh: function() {
17399		var checked = this.element[ 0 ].checked,
17400			isDisabled = this.element[ 0 ].disabled;
17401
17402		this._updateIcon( checked );
17403		this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked );
17404		if ( this.options.label !== null ) {
17405			this._updateLabel();
17406		}
17407
17408		if ( isDisabled !== this.options.disabled ) {
17409			this._setOptions( { "disabled": isDisabled } );
17410		}
17411	}
17412
17413} ] );
17414
17415var widgetsCheckboxradio = $.ui.checkboxradio;
17416
17417
17418/*!
17419 * jQuery UI Button 1.14.1
17420 * https://jqueryui.com
17421 *
17422 * Copyright OpenJS Foundation and other contributors
17423 * Released under the MIT license.
17424 * https://jquery.org/license
17425 */
17426
17427//>>label: Button
17428//>>group: Widgets
17429//>>description: Enhances a form with themeable buttons.
17430//>>docs: https://api.jqueryui.com/button/
17431//>>demos: https://jqueryui.com/button/
17432//>>css.structure: ../../themes/base/core.css
17433//>>css.structure: ../../themes/base/button.css
17434//>>css.theme: ../../themes/base/theme.css
17435
17436
17437$.widget( "ui.button", {
17438	version: "1.14.1",
17439	defaultElement: "<button>",
17440	options: {
17441		classes: {
17442			"ui-button": "ui-corner-all"
17443		},
17444		disabled: null,
17445		icon: null,
17446		iconPosition: "beginning",
17447		label: null,
17448		showLabel: true
17449	},
17450
17451	_getCreateOptions: function() {
17452		var disabled,
17453
17454			// This is to support cases like in jQuery Mobile where the base widget does have
17455			// an implementation of _getCreateOptions
17456			options = this._super() || {};
17457
17458		this.isInput = this.element.is( "input" );
17459
17460		disabled = this.element[ 0 ].disabled;
17461		if ( disabled != null ) {
17462			options.disabled = disabled;
17463		}
17464
17465		this.originalLabel = this.isInput ? this.element.val() : this.element.html();
17466		if ( this.originalLabel ) {
17467			options.label = this.originalLabel;
17468		}
17469
17470		return options;
17471	},
17472
17473	_create: function() {
17474		if ( !this.option.showLabel & !this.options.icon ) {
17475			this.options.showLabel = true;
17476		}
17477
17478		// We have to check the option again here even though we did in _getCreateOptions,
17479		// because null may have been passed on init which would override what was set in
17480		// _getCreateOptions
17481		if ( this.options.disabled == null ) {
17482			this.options.disabled = this.element[ 0 ].disabled || false;
17483		}
17484
17485		this.hasTitle = !!this.element.attr( "title" );
17486
17487		// Check to see if the label needs to be set or if its already correct
17488		if ( this.options.label && this.options.label !== this.originalLabel ) {
17489			if ( this.isInput ) {
17490				this.element.val( this.options.label );
17491			} else {
17492				this.element.html( this.options.label );
17493			}
17494		}
17495		this._addClass( "ui-button", "ui-widget" );
17496		this._setOption( "disabled", this.options.disabled );
17497		this._enhance();
17498
17499		if ( this.element.is( "a" ) ) {
17500			this._on( {
17501				"keyup": function( event ) {
17502					if ( event.keyCode === $.ui.keyCode.SPACE ) {
17503						event.preventDefault();
17504
17505						// If a native click is available use it, so we
17506						// actually cause navigation. Otherwise, just trigger
17507						// a click event.
17508						if ( this.element[ 0 ].click ) {
17509							this.element[ 0 ].click();
17510						} else {
17511							this.element.trigger( "click" );
17512						}
17513					}
17514				}
17515			} );
17516		}
17517	},
17518
17519	_enhance: function() {
17520		if ( !this.element.is( "button" ) ) {
17521			this.element.attr( "role", "button" );
17522		}
17523
17524		if ( this.options.icon ) {
17525			this._updateIcon( "icon", this.options.icon );
17526			this._updateTooltip();
17527		}
17528	},
17529
17530	_updateTooltip: function() {
17531		this.title = this.element.attr( "title" );
17532
17533		if ( !this.options.showLabel && !this.title ) {
17534			this.element.attr( "title", this.options.label );
17535		}
17536	},
17537
17538	_updateIcon: function( option, value ) {
17539		var icon = option !== "iconPosition",
17540			position = icon ? this.options.iconPosition : value,
17541			displayBlock = position === "top" || position === "bottom";
17542
17543		// Create icon
17544		if ( !this.icon ) {
17545			this.icon = $( "<span>" );
17546
17547			this._addClass( this.icon, "ui-button-icon", "ui-icon" );
17548
17549			if ( !this.options.showLabel ) {
17550				this._addClass( "ui-button-icon-only" );
17551			}
17552		} else if ( icon ) {
17553
17554			// If we are updating the icon remove the old icon class
17555			this._removeClass( this.icon, null, this.options.icon );
17556		}
17557
17558		// If we are updating the icon add the new icon class
17559		if ( icon ) {
17560			this._addClass( this.icon, null, value );
17561		}
17562
17563		this._attachIcon( position );
17564
17565		// If the icon is on top or bottom we need to add the ui-widget-icon-block class and remove
17566		// the iconSpace if there is one.
17567		if ( displayBlock ) {
17568			this._addClass( this.icon, null, "ui-widget-icon-block" );
17569			if ( this.iconSpace ) {
17570				this.iconSpace.remove();
17571			}
17572		} else {
17573
17574			// Position is beginning or end so remove the ui-widget-icon-block class and add the
17575			// space if it does not exist
17576			if ( !this.iconSpace ) {
17577				this.iconSpace = $( "<span> </span>" );
17578				this._addClass( this.iconSpace, "ui-button-icon-space" );
17579			}
17580			this._removeClass( this.icon, null, "ui-wiget-icon-block" );
17581			this._attachIconSpace( position );
17582		}
17583	},
17584
17585	_destroy: function() {
17586		this.element.removeAttr( "role" );
17587
17588		if ( this.icon ) {
17589			this.icon.remove();
17590		}
17591		if ( this.iconSpace ) {
17592			this.iconSpace.remove();
17593		}
17594		if ( !this.hasTitle ) {
17595			this.element.removeAttr( "title" );
17596		}
17597	},
17598
17599	_attachIconSpace: function( iconPosition ) {
17600		this.icon[ /^(?:end|bottom)/.test( iconPosition ) ? "before" : "after" ]( this.iconSpace );
17601	},
17602
17603	_attachIcon: function( iconPosition ) {
17604		this.element[ /^(?:end|bottom)/.test( iconPosition ) ? "append" : "prepend" ]( this.icon );
17605	},
17606
17607	_setOptions: function( options ) {
17608		var newShowLabel = options.showLabel === undefined ?
17609				this.options.showLabel :
17610				options.showLabel,
17611			newIcon = options.icon === undefined ? this.options.icon : options.icon;
17612
17613		if ( !newShowLabel && !newIcon ) {
17614			options.showLabel = true;
17615		}
17616		this._super( options );
17617	},
17618
17619	_setOption: function( key, value ) {
17620		if ( key === "icon" ) {
17621			if ( value ) {
17622				this._updateIcon( key, value );
17623			} else if ( this.icon ) {
17624				this.icon.remove();
17625				if ( this.iconSpace ) {
17626					this.iconSpace.remove();
17627				}
17628			}
17629		}
17630
17631		if ( key === "iconPosition" ) {
17632			this._updateIcon( key, value );
17633		}
17634
17635		// Make sure we can't end up with a button that has neither text nor icon
17636		if ( key === "showLabel" ) {
17637				this._toggleClass( "ui-button-icon-only", null, !value );
17638				this._updateTooltip();
17639		}
17640
17641		if ( key === "label" ) {
17642			if ( this.isInput ) {
17643				this.element.val( value );
17644			} else {
17645
17646				// If there is an icon, append it, else nothing then append the value
17647				// this avoids removal of the icon when setting label text
17648				this.element.html( value );
17649				if ( this.icon ) {
17650					this._attachIcon( this.options.iconPosition );
17651					this._attachIconSpace( this.options.iconPosition );
17652				}
17653			}
17654		}
17655
17656		this._super( key, value );
17657
17658		if ( key === "disabled" ) {
17659			this._toggleClass( null, "ui-state-disabled", value );
17660			this.element[ 0 ].disabled = value;
17661			if ( value ) {
17662				this.element.trigger( "blur" );
17663			}
17664		}
17665	},
17666
17667	refresh: function() {
17668
17669		// Make sure to only check disabled if its an element that supports this otherwise
17670		// check for the disabled class to determine state
17671		var isDisabled = this.element.is( "input, button" ) ?
17672			this.element[ 0 ].disabled : this.element.hasClass( "ui-button-disabled" );
17673
17674		if ( isDisabled !== this.options.disabled ) {
17675			this._setOptions( { disabled: isDisabled } );
17676		}
17677
17678		this._updateTooltip();
17679	}
17680} );
17681
17682// DEPRECATED
17683if ( $.uiBackCompat === true ) {
17684
17685	// Text and Icons options
17686	$.widget( "ui.button", $.ui.button, {
17687		options: {
17688			text: true,
17689			icons: {
17690				primary: null,
17691				secondary: null
17692			}
17693		},
17694
17695		_create: function() {
17696			if ( this.options.showLabel && !this.options.text ) {
17697				this.options.showLabel = this.options.text;
17698			}
17699			if ( !this.options.showLabel && this.options.text ) {
17700				this.options.text = this.options.showLabel;
17701			}
17702			if ( !this.options.icon && ( this.options.icons.primary ||
17703					this.options.icons.secondary ) ) {
17704				if ( this.options.icons.primary ) {
17705					this.options.icon = this.options.icons.primary;
17706				} else {
17707					this.options.icon = this.options.icons.secondary;
17708					this.options.iconPosition = "end";
17709				}
17710			} else if ( this.options.icon ) {
17711				this.options.icons.primary = this.options.icon;
17712			}
17713			this._super();
17714		},
17715
17716		_setOption: function( key, value ) {
17717			if ( key === "text" ) {
17718				this._super( "showLabel", value );
17719				return;
17720			}
17721			if ( key === "showLabel" ) {
17722				this.options.text = value;
17723			}
17724			if ( key === "icon" ) {
17725				this.options.icons.primary = value;
17726			}
17727			if ( key === "icons" ) {
17728				if ( value.primary ) {
17729					this._super( "icon", value.primary );
17730					this._super( "iconPosition", "beginning" );
17731				} else if ( value.secondary ) {
17732					this._super( "icon", value.secondary );
17733					this._super( "iconPosition", "end" );
17734				}
17735			}
17736			this._superApply( arguments );
17737		}
17738	} );
17739
17740	$.fn.button = ( function( orig ) {
17741		return function( options ) {
17742			var isMethodCall = typeof options === "string";
17743			var args = Array.prototype.slice.call( arguments, 1 );
17744			var returnValue = this;
17745
17746			if ( isMethodCall ) {
17747
17748				// If this is an empty collection, we need to have the instance method
17749				// return undefined instead of the jQuery instance
17750				if ( !this.length && options === "instance" ) {
17751					returnValue = undefined;
17752				} else {
17753					this.each( function() {
17754						var methodValue;
17755						var type = $( this ).attr( "type" );
17756						var name = type !== "checkbox" && type !== "radio" ?
17757							"button" :
17758							"checkboxradio";
17759						var instance = $.data( this, "ui-" + name );
17760
17761						if ( options === "instance" ) {
17762							returnValue = instance;
17763							return false;
17764						}
17765
17766						if ( !instance ) {
17767							return $.error( "cannot call methods on button" +
17768								" prior to initialization; " +
17769								"attempted to call method '" + options + "'" );
17770						}
17771
17772						if ( typeof instance[ options ] !== "function" ||
17773							options.charAt( 0 ) === "_" ) {
17774							return $.error( "no such method '" + options + "' for button" +
17775								" widget instance" );
17776						}
17777
17778						methodValue = instance[ options ].apply( instance, args );
17779
17780						if ( methodValue !== instance && methodValue !== undefined ) {
17781							returnValue = methodValue && methodValue.jquery ?
17782								returnValue.pushStack( methodValue.get() ) :
17783								methodValue;
17784							return false;
17785						}
17786					} );
17787				}
17788			} else {
17789
17790				// Allow multiple hashes to be passed on init
17791				if ( args.length ) {
17792					options = $.widget.extend.apply( null, [ options ].concat( args ) );
17793				}
17794
17795				this.each( function() {
17796					var type = $( this ).attr( "type" );
17797					var name = type !== "checkbox" && type !== "radio" ? "button" : "checkboxradio";
17798					var instance = $.data( this, "ui-" + name );
17799
17800					if ( instance ) {
17801						instance.option( options || {} );
17802						if ( instance._init ) {
17803							instance._init();
17804						}
17805					} else {
17806						if ( name === "button" ) {
17807							orig.call( $( this ), options );
17808							return;
17809						}
17810
17811						$( this ).checkboxradio( $.extend( { icon: false }, options ) );
17812					}
17813				} );
17814			}
17815
17816			return returnValue;
17817		};
17818	} )( $.fn.button );
17819
17820	$.fn.buttonset = function() {
17821		if ( !$.ui.controlgroup ) {
17822			$.error( "Controlgroup widget missing" );
17823		}
17824		if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" && arguments[ 2 ] ) {
17825			return this.controlgroup.apply( this,
17826				[ arguments[ 0 ], "items.button", arguments[ 2 ] ] );
17827		}
17828		if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" ) {
17829			return this.controlgroup.apply( this, [ arguments[ 0 ], "items.button" ] );
17830		}
17831		if ( typeof arguments[ 0 ] === "object" && arguments[ 0 ].items ) {
17832			arguments[ 0 ].items = {
17833				button: arguments[ 0 ].items
17834			};
17835		}
17836		return this.controlgroup.apply( this, arguments );
17837	};
17838}
17839
17840var widgetsButton = $.ui.button;
17841
17842
17843/* eslint-disable max-len, camelcase */
17844/*!
17845 * jQuery UI Datepicker 1.14.1
17846 * https://jqueryui.com
17847 *
17848 * Copyright OpenJS Foundation and other contributors
17849 * Released under the MIT license.
17850 * https://jquery.org/license
17851 */
17852
17853//>>label: Datepicker
17854//>>group: Widgets
17855//>>description: Displays a calendar from an input or inline for selecting dates.
17856//>>docs: https://api.jqueryui.com/datepicker/
17857//>>demos: https://jqueryui.com/datepicker/
17858//>>css.structure: ../../themes/base/core.css
17859//>>css.structure: ../../themes/base/datepicker.css
17860//>>css.theme: ../../themes/base/theme.css
17861
17862
17863$.extend( $.ui, { datepicker: { version: "1.14.1" } } );
17864
17865var datepicker_instActive;
17866
17867function datepicker_getZindex( elem ) {
17868	var position, value;
17869	while ( elem.length && elem[ 0 ] !== document ) {
17870
17871		// Ignore z-index if position is set to a value where z-index is ignored by the browser
17872		// This makes behavior of this function consistent across browsers
17873		// WebKit always returns auto if the element is positioned
17874		position = elem.css( "position" );
17875		if ( position === "absolute" || position === "relative" || position === "fixed" ) {
17876
17877			// IE returns 0 when zIndex is not specified
17878			// other browsers return a string
17879			// we ignore the case of nested elements with an explicit value of 0
17880			// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
17881			value = parseInt( elem.css( "zIndex" ), 10 );
17882			if ( !isNaN( value ) && value !== 0 ) {
17883				return value;
17884			}
17885		}
17886		elem = elem.parent();
17887	}
17888
17889	return 0;
17890}
17891
17892/* Date picker manager.
17893   Use the singleton instance of this class, $.datepicker, to interact with the date picker.
17894   Settings for (groups of) date pickers are maintained in an instance object,
17895   allowing multiple different settings on the same page. */
17896
17897function Datepicker() {
17898	this._curInst = null; // The current instance in use
17899	this._keyEvent = false; // If the last event was a key event
17900	this._disabledInputs = []; // List of date picker inputs that have been disabled
17901	this._datepickerShowing = false; // True if the popup picker is showing , false if not
17902	this._inDialog = false; // True if showing within a "dialog", false if not
17903	this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division
17904	this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class
17905	this._appendClass = "ui-datepicker-append"; // The name of the append marker class
17906	this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class
17907	this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class
17908	this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class
17909	this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class
17910	this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class
17911	this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class
17912	this.regional = []; // Available regional settings, indexed by language code
17913	this.regional[ "" ] = { // Default regional settings
17914		closeText: "Done", // Display text for close link
17915		prevText: "Prev", // Display text for previous month link
17916		nextText: "Next", // Display text for next month link
17917		currentText: "Today", // Display text for current month link
17918		monthNames: [ "January", "February", "March", "April", "May", "June",
17919			"July", "August", "September", "October", "November", "December" ], // Names of months for drop-down and formatting
17920		monthNamesShort: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ], // For formatting
17921		dayNames: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], // For formatting
17922		dayNamesShort: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], // For formatting
17923		dayNamesMin: [ "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" ], // Column headings for days starting at Sunday
17924		weekHeader: "Wk", // Column header for week of the year
17925		dateFormat: "mm/dd/yy", // See format options on parseDate
17926		firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
17927		isRTL: false, // True if right-to-left language, false if left-to-right
17928		showMonthAfterYear: false, // True if the year select precedes month, false for month then year
17929		yearSuffix: "", // Additional text to append to the year in the month headers,
17930		selectMonthLabel: "Select month", // Invisible label for month selector
17931		selectYearLabel: "Select year" // Invisible label for year selector
17932	};
17933	this._defaults = { // Global defaults for all the date picker instances
17934		showOn: "focus", // "focus" for popup on focus,
17935			// "button" for trigger button, or "both" for either
17936		showAnim: "fadeIn", // Name of jQuery animation for popup
17937		showOptions: {}, // Options for enhanced animations
17938		defaultDate: null, // Used when field is blank: actual date,
17939			// +/-number for offset from today, null for today
17940		appendText: "", // Display text following the input box, e.g. showing the format
17941		buttonText: "...", // Text for trigger button
17942		buttonImage: "", // URL for trigger button image
17943		buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
17944		hideIfNoPrevNext: false, // True to hide next/previous month links
17945			// if not applicable, false to just disable them
17946		navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
17947		gotoCurrent: false, // True if today link goes back to current selection instead
17948		changeMonth: false, // True if month can be selected directly, false if only prev/next
17949		changeYear: false, // True if year can be selected directly, false if only prev/next
17950		yearRange: "c-10:c+10", // Range of years to display in drop-down,
17951			// either relative to today's year (-nn:+nn), relative to currently displayed year
17952			// (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
17953		showOtherMonths: false, // True to show dates in other months, false to leave blank
17954		selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
17955		showWeek: false, // True to show week of the year, false to not show it
17956		calculateWeek: this.iso8601Week, // How to calculate the week of the year,
17957			// takes a Date and returns the number of the week for it
17958		shortYearCutoff: "+10", // Short year values < this are in the current century,
17959			// > this are in the previous century,
17960			// string value starting with "+" for current year + value
17961		minDate: null, // The earliest selectable date, or null for no limit
17962		maxDate: null, // The latest selectable date, or null for no limit
17963		duration: "fast", // Duration of display/closure
17964		beforeShowDay: null, // Function that takes a date and returns an array with
17965			// [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "",
17966			// [2] = cell title (optional), e.g. $.datepicker.noWeekends
17967		beforeShow: null, // Function that takes an input field and
17968			// returns a set of custom settings for the date picker
17969		onSelect: null, // Define a callback function when a date is selected
17970		onChangeMonthYear: null, // Define a callback function when the month or year is changed
17971		onClose: null, // Define a callback function when the datepicker is closed
17972		onUpdateDatepicker: null, // Define a callback function when the datepicker is updated
17973		numberOfMonths: 1, // Number of months to show at a time
17974		showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
17975		stepMonths: 1, // Number of months to step back/forward
17976		stepBigMonths: 12, // Number of months to step back/forward for the big links
17977		altField: "", // Selector for an alternate field to store selected dates into
17978		altFormat: "", // The date format to use for the alternate field
17979		constrainInput: true, // The input is constrained by the current date format
17980		showButtonPanel: false, // True to show button panel, false to not show it
17981		autoSize: false, // True to size the input for the date format, false to leave as is
17982		disabled: false // The initial disabled state
17983	};
17984	$.extend( this._defaults, this.regional[ "" ] );
17985	this.regional.en = $.extend( true, {}, this.regional[ "" ] );
17986	this.regional[ "en-US" ] = $.extend( true, {}, this.regional.en );
17987	this.dpDiv = datepicker_bindHover( $( "<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) );
17988}
17989
17990$.extend( Datepicker.prototype, {
17991
17992	/* Class name added to elements to indicate already configured with a date picker. */
17993	markerClassName: "hasDatepicker",
17994
17995	//Keep track of the maximum number of rows displayed (see #7043)
17996	maxRows: 4,
17997
17998	// TODO rename to "widget" when switching to widget factory
17999	_widgetDatepicker: function() {
18000		return this.dpDiv;
18001	},
18002
18003	/* Override the default settings for all instances of the date picker.
18004	 * @param  settings  object - the new settings to use as defaults (anonymous object)
18005	 * @return the manager object
18006	 */
18007	setDefaults: function( settings ) {
18008		datepicker_extendRemove( this._defaults, settings || {} );
18009		return this;
18010	},
18011
18012	/* Attach the date picker to a jQuery selection.
18013	 * @param  target	element - the target input field or division or span
18014	 * @param  settings  object - the new settings to use for this date picker instance (anonymous)
18015	 */
18016	_attachDatepicker: function( target, settings ) {
18017		var nodeName, inline, inst;
18018		nodeName = target.nodeName.toLowerCase();
18019		inline = ( nodeName === "div" || nodeName === "span" );
18020		if ( !target.id ) {
18021			this.uuid += 1;
18022			target.id = "dp" + this.uuid;
18023		}
18024		inst = this._newInst( $( target ), inline );
18025		inst.settings = $.extend( {}, settings || {} );
18026		if ( nodeName === "input" ) {
18027			this._connectDatepicker( target, inst );
18028		} else if ( inline ) {
18029			this._inlineDatepicker( target, inst );
18030		}
18031	},
18032
18033	/* Create a new instance object. */
18034	_newInst: function( target, inline ) {
18035		var id = target[ 0 ].id.replace( /([^A-Za-z0-9_\-])/g, "\\\\$1" ); // escape jQuery meta chars
18036		return { id: id, input: target, // associated target
18037			selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
18038			drawMonth: 0, drawYear: 0, // month being drawn
18039			inline: inline, // is datepicker inline or not
18040			dpDiv: ( !inline ? this.dpDiv : // presentation div
18041			datepicker_bindHover( $( "<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) ) ) };
18042	},
18043
18044	/* Attach the date picker to an input field. */
18045	_connectDatepicker: function( target, inst ) {
18046		var input = $( target );
18047		inst.append = $( [] );
18048		inst.trigger = $( [] );
18049		if ( input.hasClass( this.markerClassName ) ) {
18050			return;
18051		}
18052		this._attachments( input, inst );
18053		input.addClass( this.markerClassName ).on( "keydown", this._doKeyDown ).
18054			on( "keypress", this._doKeyPress ).on( "keyup", this._doKeyUp );
18055		this._autoSize( inst );
18056		$.data( target, "datepicker", inst );
18057
18058		//If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
18059		if ( inst.settings.disabled ) {
18060			this._disableDatepicker( target );
18061		}
18062	},
18063
18064	/* Make attachments based on settings. */
18065	_attachments: function( input, inst ) {
18066		var showOn, buttonText, buttonImage,
18067			appendText = this._get( inst, "appendText" ),
18068			isRTL = this._get( inst, "isRTL" );
18069
18070		if ( inst.append ) {
18071			inst.append.remove();
18072		}
18073		if ( appendText ) {
18074			inst.append = $( "<span>" )
18075				.addClass( this._appendClass )
18076				.text( appendText );
18077			input[ isRTL ? "before" : "after" ]( inst.append );
18078		}
18079
18080		input.off( "focus", this._showDatepicker );
18081
18082		if ( inst.trigger ) {
18083			inst.trigger.remove();
18084		}
18085
18086		showOn = this._get( inst, "showOn" );
18087		if ( showOn === "focus" || showOn === "both" ) { // pop-up date picker when in the marked field
18088			input.on( "focus", this._showDatepicker );
18089		}
18090		if ( showOn === "button" || showOn === "both" ) { // pop-up date picker when button clicked
18091			buttonText = this._get( inst, "buttonText" );
18092			buttonImage = this._get( inst, "buttonImage" );
18093
18094			if ( this._get( inst, "buttonImageOnly" ) ) {
18095				inst.trigger = $( "<img>" )
18096					.addClass( this._triggerClass )
18097					.attr( {
18098						src: buttonImage,
18099						alt: buttonText,
18100						title: buttonText
18101					} );
18102			} else {
18103				inst.trigger = $( "<button type='button'>" )
18104					.addClass( this._triggerClass );
18105				if ( buttonImage ) {
18106					inst.trigger.html(
18107						$( "<img>" )
18108							.attr( {
18109								src: buttonImage,
18110								alt: buttonText,
18111								title: buttonText
18112							} )
18113					);
18114				} else {
18115					inst.trigger.text( buttonText );
18116				}
18117			}
18118
18119			input[ isRTL ? "before" : "after" ]( inst.trigger );
18120			inst.trigger.on( "click", function() {
18121				if ( $.datepicker._datepickerShowing && $.datepicker._lastInput === input[ 0 ] ) {
18122					$.datepicker._hideDatepicker();
18123				} else if ( $.datepicker._datepickerShowing && $.datepicker._lastInput !== input[ 0 ] ) {
18124					$.datepicker._hideDatepicker();
18125					$.datepicker._showDatepicker( input[ 0 ] );
18126				} else {
18127					$.datepicker._showDatepicker( input[ 0 ] );
18128				}
18129				return false;
18130			} );
18131		}
18132	},
18133
18134	/* Apply the maximum length for the date format. */
18135	_autoSize: function( inst ) {
18136		if ( this._get( inst, "autoSize" ) && !inst.inline ) {
18137			var findMax, max, maxI, i,
18138				date = new Date( 2009, 12 - 1, 20 ), // Ensure double digits
18139				dateFormat = this._get( inst, "dateFormat" );
18140
18141			if ( dateFormat.match( /[DM]/ ) ) {
18142				findMax = function( names ) {
18143					max = 0;
18144					maxI = 0;
18145					for ( i = 0; i < names.length; i++ ) {
18146						if ( names[ i ].length > max ) {
18147							max = names[ i ].length;
18148							maxI = i;
18149						}
18150					}
18151					return maxI;
18152				};
18153				date.setMonth( findMax( this._get( inst, ( dateFormat.match( /MM/ ) ?
18154					"monthNames" : "monthNamesShort" ) ) ) );
18155				date.setDate( findMax( this._get( inst, ( dateFormat.match( /DD/ ) ?
18156					"dayNames" : "dayNamesShort" ) ) ) + 20 - date.getDay() );
18157			}
18158			inst.input.attr( "size", this._formatDate( inst, date ).length );
18159		}
18160	},
18161
18162	/* Attach an inline date picker to a div. */
18163	_inlineDatepicker: function( target, inst ) {
18164		var divSpan = $( target );
18165		if ( divSpan.hasClass( this.markerClassName ) ) {
18166			return;
18167		}
18168		divSpan.addClass( this.markerClassName ).append( inst.dpDiv );
18169		$.data( target, "datepicker", inst );
18170		this._setDate( inst, this._getDefaultDate( inst ), true );
18171		this._updateDatepicker( inst );
18172		this._updateAlternate( inst );
18173
18174		//If disabled option is true, disable the datepicker before showing it (see ticket #5665)
18175		if ( inst.settings.disabled ) {
18176			this._disableDatepicker( target );
18177		}
18178
18179		// Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
18180		// https://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
18181		inst.dpDiv.css( "display", "block" );
18182	},
18183
18184	/* Pop-up the date picker in a "dialog" box.
18185	 * @param  input element - ignored
18186	 * @param  date	string or Date - the initial date to display
18187	 * @param  onSelect  function - the function to call when a date is selected
18188	 * @param  settings  object - update the dialog date picker instance's settings (anonymous object)
18189	 * @param  pos int[2] - coordinates for the dialog's position within the screen or
18190	 *					event - with x/y coordinates or
18191	 *					leave empty for default (screen centre)
18192	 * @return the manager object
18193	 */
18194	_dialogDatepicker: function( input, date, onSelect, settings, pos ) {
18195		var id, browserWidth, browserHeight, scrollX, scrollY,
18196			inst = this._dialogInst; // internal instance
18197
18198		if ( !inst ) {
18199			this.uuid += 1;
18200			id = "dp" + this.uuid;
18201			this._dialogInput = $( "<input type='text' id='" + id +
18202				"' style='position: absolute; top: -100px; width: 0px;'/>" );
18203			this._dialogInput.on( "keydown", this._doKeyDown );
18204			$( "body" ).append( this._dialogInput );
18205			inst = this._dialogInst = this._newInst( this._dialogInput, false );
18206			inst.settings = {};
18207			$.data( this._dialogInput[ 0 ], "datepicker", inst );
18208		}
18209		datepicker_extendRemove( inst.settings, settings || {} );
18210		date = ( date && date.constructor === Date ? this._formatDate( inst, date ) : date );
18211		this._dialogInput.val( date );
18212
18213		this._pos = ( pos ? ( pos.length ? pos : [ pos.pageX, pos.pageY ] ) : null );
18214		if ( !this._pos ) {
18215			browserWidth = document.documentElement.clientWidth;
18216			browserHeight = document.documentElement.clientHeight;
18217			scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
18218			scrollY = document.documentElement.scrollTop || document.body.scrollTop;
18219			this._pos = // should use actual width/height below
18220				[ ( browserWidth / 2 ) - 100 + scrollX, ( browserHeight / 2 ) - 150 + scrollY ];
18221		}
18222
18223		// Move input on screen for focus, but hidden behind dialog
18224		this._dialogInput.css( "left", ( this._pos[ 0 ] + 20 ) + "px" ).css( "top", this._pos[ 1 ] + "px" );
18225		inst.settings.onSelect = onSelect;
18226		this._inDialog = true;
18227		this.dpDiv.addClass( this._dialogClass );
18228		this._showDatepicker( this._dialogInput[ 0 ] );
18229		if ( $.blockUI ) {
18230			$.blockUI( this.dpDiv );
18231		}
18232		$.data( this._dialogInput[ 0 ], "datepicker", inst );
18233		return this;
18234	},
18235
18236	/* Detach a datepicker from its control.
18237	 * @param  target	element - the target input field or division or span
18238	 */
18239	_destroyDatepicker: function( target ) {
18240		var nodeName,
18241			$target = $( target ),
18242			inst = $.data( target, "datepicker" );
18243
18244		if ( !$target.hasClass( this.markerClassName ) ) {
18245			return;
18246		}
18247
18248		nodeName = target.nodeName.toLowerCase();
18249		$.removeData( target, "datepicker" );
18250		if ( nodeName === "input" ) {
18251			inst.append.remove();
18252			inst.trigger.remove();
18253			$target.removeClass( this.markerClassName ).
18254				off( "focus", this._showDatepicker ).
18255				off( "keydown", this._doKeyDown ).
18256				off( "keypress", this._doKeyPress ).
18257				off( "keyup", this._doKeyUp );
18258		} else if ( nodeName === "div" || nodeName === "span" ) {
18259			$target.removeClass( this.markerClassName ).empty();
18260		}
18261
18262		$.datepicker._hideDatepicker();
18263		if ( datepicker_instActive === inst ) {
18264			datepicker_instActive = null;
18265			this._curInst = null;
18266		}
18267	},
18268
18269	/* Enable the date picker to a jQuery selection.
18270	 * @param  target	element - the target input field or division or span
18271	 */
18272	_enableDatepicker: function( target ) {
18273		var nodeName, inline,
18274			$target = $( target ),
18275			inst = $.data( target, "datepicker" );
18276
18277		if ( !$target.hasClass( this.markerClassName ) ) {
18278			return;
18279		}
18280
18281		nodeName = target.nodeName.toLowerCase();
18282		if ( nodeName === "input" ) {
18283			target.disabled = false;
18284			inst.trigger.filter( "button" ).
18285				each( function() {
18286					this.disabled = false;
18287				} ).end().
18288				filter( "img" ).css( { opacity: "1.0", cursor: "" } );
18289		} else if ( nodeName === "div" || nodeName === "span" ) {
18290			inline = $target.children( "." + this._inlineClass );
18291			inline.children().removeClass( "ui-state-disabled" );
18292			inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ).
18293				prop( "disabled", false );
18294		}
18295		this._disabledInputs = $.map( this._disabledInputs,
18296
18297			// Delete entry
18298			function( value ) {
18299				return ( value === target ? null : value );
18300			} );
18301	},
18302
18303	/* Disable the date picker to a jQuery selection.
18304	 * @param  target	element - the target input field or division or span
18305	 */
18306	_disableDatepicker: function( target ) {
18307		var nodeName, inline,
18308			$target = $( target ),
18309			inst = $.data( target, "datepicker" );
18310
18311		if ( !$target.hasClass( this.markerClassName ) ) {
18312			return;
18313		}
18314
18315		nodeName = target.nodeName.toLowerCase();
18316		if ( nodeName === "input" ) {
18317			target.disabled = true;
18318			inst.trigger.filter( "button" ).
18319				each( function() {
18320					this.disabled = true;
18321				} ).end().
18322				filter( "img" ).css( { opacity: "0.5", cursor: "default" } );
18323		} else if ( nodeName === "div" || nodeName === "span" ) {
18324			inline = $target.children( "." + this._inlineClass );
18325			inline.children().addClass( "ui-state-disabled" );
18326			inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ).
18327				prop( "disabled", true );
18328		}
18329		this._disabledInputs = $.map( this._disabledInputs,
18330
18331			// Delete entry
18332			function( value ) {
18333				return ( value === target ? null : value );
18334			} );
18335		this._disabledInputs[ this._disabledInputs.length ] = target;
18336	},
18337
18338	/* Is the first field in a jQuery collection disabled as a datepicker?
18339	 * @param  target	element - the target input field or division or span
18340	 * @return boolean - true if disabled, false if enabled
18341	 */
18342	_isDisabledDatepicker: function( target ) {
18343		if ( !target ) {
18344			return false;
18345		}
18346		for ( var i = 0; i < this._disabledInputs.length; i++ ) {
18347			if ( this._disabledInputs[ i ] === target ) {
18348				return true;
18349			}
18350		}
18351		return false;
18352	},
18353
18354	/* Retrieve the instance data for the target control.
18355	 * @param  target  element - the target input field or division or span
18356	 * @return  object - the associated instance data
18357	 * @throws  error if a jQuery problem getting data
18358	 */
18359	_getInst: function( target ) {
18360		try {
18361			return $.data( target, "datepicker" );
18362		} catch ( err ) {
18363			throw "Missing instance data for this datepicker";
18364		}
18365	},
18366
18367	/* Update or retrieve the settings for a date picker attached to an input field or division.
18368	 * @param  target  element - the target input field or division or span
18369	 * @param  name	object - the new settings to update or
18370	 *				string - the name of the setting to change or retrieve,
18371	 *				when retrieving also "all" for all instance settings or
18372	 *				"defaults" for all global defaults
18373	 * @param  value   any - the new value for the setting
18374	 *				(omit if above is an object or to retrieve a value)
18375	 */
18376	_optionDatepicker: function( target, name, value ) {
18377		var settings, date, minDate, maxDate,
18378			inst = this._getInst( target );
18379
18380		if ( arguments.length === 2 && typeof name === "string" ) {
18381			return ( name === "defaults" ? $.extend( {}, $.datepicker._defaults ) :
18382				( inst ? ( name === "all" ? $.extend( {}, inst.settings ) :
18383				this._get( inst, name ) ) : null ) );
18384		}
18385
18386		settings = name || {};
18387		if ( typeof name === "string" ) {
18388			settings = {};
18389			settings[ name ] = value;
18390		}
18391
18392		if ( inst ) {
18393			if ( this._curInst === inst ) {
18394				this._hideDatepicker();
18395			}
18396
18397			date = this._getDateDatepicker( target, true );
18398			minDate = this._getMinMaxDate( inst, "min" );
18399			maxDate = this._getMinMaxDate( inst, "max" );
18400			datepicker_extendRemove( inst.settings, settings );
18401
18402			// reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
18403			if ( minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined ) {
18404				inst.settings.minDate = this._formatDate( inst, minDate );
18405			}
18406			if ( maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined ) {
18407				inst.settings.maxDate = this._formatDate( inst, maxDate );
18408			}
18409			if ( "disabled" in settings ) {
18410				if ( settings.disabled ) {
18411					this._disableDatepicker( target );
18412				} else {
18413					this._enableDatepicker( target );
18414				}
18415			}
18416			this._attachments( $( target ), inst );
18417			this._autoSize( inst );
18418			this._setDate( inst, date );
18419			this._updateAlternate( inst );
18420			this._updateDatepicker( inst );
18421		}
18422	},
18423
18424	// Change method deprecated
18425	_changeDatepicker: function( target, name, value ) {
18426		this._optionDatepicker( target, name, value );
18427	},
18428
18429	/* Redraw the date picker attached to an input field or division.
18430	 * @param  target  element - the target input field or division or span
18431	 */
18432	_refreshDatepicker: function( target ) {
18433		var inst = this._getInst( target );
18434		if ( inst ) {
18435			this._updateDatepicker( inst );
18436		}
18437	},
18438
18439	/* Set the dates for a jQuery selection.
18440	 * @param  target element - the target input field or division or span
18441	 * @param  date	Date - the new date
18442	 */
18443	_setDateDatepicker: function( target, date ) {
18444		var inst = this._getInst( target );
18445		if ( inst ) {
18446			this._setDate( inst, date );
18447			this._updateDatepicker( inst );
18448			this._updateAlternate( inst );
18449		}
18450	},
18451
18452	/* Get the date(s) for the first entry in a jQuery selection.
18453	 * @param  target element - the target input field or division or span
18454	 * @param  noDefault boolean - true if no default date is to be used
18455	 * @return Date - the current date
18456	 */
18457	_getDateDatepicker: function( target, noDefault ) {
18458		var inst = this._getInst( target );
18459		if ( inst && !inst.inline ) {
18460			this._setDateFromField( inst, noDefault );
18461		}
18462		return ( inst ? this._getDate( inst ) : null );
18463	},
18464
18465	/* Handle keystrokes. */
18466	_doKeyDown: function( event ) {
18467		var onSelect, dateStr, sel,
18468			inst = $.datepicker._getInst( event.target ),
18469			handled = true,
18470			isRTL = inst.dpDiv.is( ".ui-datepicker-rtl" );
18471
18472		inst._keyEvent = true;
18473		if ( $.datepicker._datepickerShowing ) {
18474			switch ( event.keyCode ) {
18475				case 9: $.datepicker._hideDatepicker();
18476						handled = false;
18477						break; // hide on tab out
18478				case 13: sel = $( "td." + $.datepicker._dayOverClass + ":not(." +
18479									$.datepicker._currentClass + ")", inst.dpDiv );
18480						if ( sel[ 0 ] ) {
18481							$.datepicker._selectDay( event.target, inst.selectedMonth, inst.selectedYear, sel[ 0 ] );
18482						}
18483
18484						onSelect = $.datepicker._get( inst, "onSelect" );
18485						if ( onSelect ) {
18486							dateStr = $.datepicker._formatDate( inst );
18487
18488							// Trigger custom callback
18489							onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] );
18490						} else {
18491							$.datepicker._hideDatepicker();
18492						}
18493
18494						return false; // don't submit the form
18495				case 27: $.datepicker._hideDatepicker();
18496						break; // hide on escape
18497				case 33: $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
18498							-$.datepicker._get( inst, "stepBigMonths" ) :
18499							-$.datepicker._get( inst, "stepMonths" ) ), "M" );
18500						break; // previous month/year on page up/+ ctrl
18501				case 34: $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
18502							+$.datepicker._get( inst, "stepBigMonths" ) :
18503							+$.datepicker._get( inst, "stepMonths" ) ), "M" );
18504						break; // next month/year on page down/+ ctrl
18505				case 35: if ( event.ctrlKey || event.metaKey ) {
18506							$.datepicker._clearDate( event.target );
18507						}
18508						handled = event.ctrlKey || event.metaKey;
18509						break; // clear on ctrl or command +end
18510				case 36: if ( event.ctrlKey || event.metaKey ) {
18511							$.datepicker._gotoToday( event.target );
18512						}
18513						handled = event.ctrlKey || event.metaKey;
18514						break; // current on ctrl or command +home
18515				case 37: if ( event.ctrlKey || event.metaKey ) {
18516							$.datepicker._adjustDate( event.target, ( isRTL ? +1 : -1 ), "D" );
18517						}
18518						handled = event.ctrlKey || event.metaKey;
18519
18520						// -1 day on ctrl or command +left
18521						if ( event.originalEvent.altKey ) {
18522							$.datepicker._adjustDate( event.target, ( event.ctrlKey ?
18523								-$.datepicker._get( inst, "stepBigMonths" ) :
18524								-$.datepicker._get( inst, "stepMonths" ) ), "M" );
18525						}
18526
18527						// next month/year on alt +left on Mac
18528						break;
18529				case 38: if ( event.ctrlKey || event.metaKey ) {
18530							$.datepicker._adjustDate( event.target, -7, "D" );
18531						}
18532						handled = event.ctrlKey || event.metaKey;
18533						break; // -1 week on ctrl or command +up
18534				case 39: if ( event.ctrlKey || event.metaKey ) {
18535							$.datepicker._adjustDate( event.target, ( isRTL ? -1 : +1 ), "D" );
18536						}
18537						handled = event.ctrlKey || event.metaKey;
18538
18539						// +1 day on ctrl or command +right
18540						if ( event.originalEvent.altKey ) {
18541							$.datepicker._adjustDate( event.target, ( event.ctrlKey ?
18542								+$.datepicker._get( inst, "stepBigMonths" ) :
18543								+$.datepicker._get( inst, "stepMonths" ) ), "M" );
18544						}
18545
18546						// next month/year on alt +right
18547						break;
18548				case 40: if ( event.ctrlKey || event.metaKey ) {
18549							$.datepicker._adjustDate( event.target, +7, "D" );
18550						}
18551						handled = event.ctrlKey || event.metaKey;
18552						break; // +1 week on ctrl or command +down
18553				default: handled = false;
18554			}
18555		} else if ( event.keyCode === 36 && event.ctrlKey ) { // display the date picker on ctrl+home
18556			$.datepicker._showDatepicker( this );
18557		} else {
18558			handled = false;
18559		}
18560
18561		if ( handled ) {
18562			event.preventDefault();
18563			event.stopPropagation();
18564		}
18565	},
18566
18567	/* Filter entered characters - based on date format. */
18568	_doKeyPress: function( event ) {
18569		var chars, chr,
18570			inst = $.datepicker._getInst( event.target );
18571
18572		if ( $.datepicker._get( inst, "constrainInput" ) ) {
18573			chars = $.datepicker._possibleChars( $.datepicker._get( inst, "dateFormat" ) );
18574			chr = String.fromCharCode( event.charCode == null ? event.keyCode : event.charCode );
18575			return event.ctrlKey || event.metaKey || ( chr < " " || !chars || chars.indexOf( chr ) > -1 );
18576		}
18577	},
18578
18579	/* Synchronise manual entry and field/alternate field. */
18580	_doKeyUp: function( event ) {
18581		var date,
18582			inst = $.datepicker._getInst( event.target );
18583
18584		if ( inst.input.val() !== inst.lastVal ) {
18585			try {
18586				date = $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ),
18587					( inst.input ? inst.input.val() : null ),
18588					$.datepicker._getFormatConfig( inst ) );
18589
18590				if ( date ) { // only if valid
18591					$.datepicker._setDateFromField( inst );
18592					$.datepicker._updateAlternate( inst );
18593					$.datepicker._updateDatepicker( inst );
18594				}
18595			} catch ( err ) {
18596			}
18597		}
18598		return true;
18599	},
18600
18601	/* Pop-up the date picker for a given input field.
18602	 * If false returned from beforeShow event handler do not show.
18603	 * @param  input  element - the input field attached to the date picker or
18604	 *					event - if triggered by focus
18605	 */
18606	_showDatepicker: function( input ) {
18607		input = input.target || input;
18608		if ( input.nodeName.toLowerCase() !== "input" ) { // find from button/image trigger
18609			input = $( "input", input.parentNode )[ 0 ];
18610		}
18611
18612		if ( $.datepicker._isDisabledDatepicker( input ) || $.datepicker._lastInput === input ) { // already here
18613			return;
18614		}
18615
18616		var inst, beforeShow, beforeShowSettings, isFixed,
18617			offset, showAnim, duration;
18618
18619		inst = $.datepicker._getInst( input );
18620		if ( $.datepicker._curInst && $.datepicker._curInst !== inst ) {
18621			$.datepicker._curInst.dpDiv.stop( true, true );
18622			if ( inst && $.datepicker._datepickerShowing ) {
18623				$.datepicker._hideDatepicker( $.datepicker._curInst.input[ 0 ] );
18624			}
18625		}
18626
18627		beforeShow = $.datepicker._get( inst, "beforeShow" );
18628		beforeShowSettings = beforeShow ? beforeShow.apply( input, [ input, inst ] ) : {};
18629		if ( beforeShowSettings === false ) {
18630			return;
18631		}
18632		datepicker_extendRemove( inst.settings, beforeShowSettings );
18633
18634		inst.lastVal = null;
18635		$.datepicker._lastInput = input;
18636		$.datepicker._setDateFromField( inst );
18637
18638		if ( $.datepicker._inDialog ) { // hide cursor
18639			input.value = "";
18640		}
18641		if ( !$.datepicker._pos ) { // position below input
18642			$.datepicker._pos = $.datepicker._findPos( input );
18643			$.datepicker._pos[ 1 ] += input.offsetHeight; // add the height
18644		}
18645
18646		isFixed = false;
18647		$( input ).parents().each( function() {
18648			isFixed |= $( this ).css( "position" ) === "fixed";
18649			return !isFixed;
18650		} );
18651
18652		offset = { left: $.datepicker._pos[ 0 ], top: $.datepicker._pos[ 1 ] };
18653		$.datepicker._pos = null;
18654
18655		//to avoid flashes on Firefox
18656		inst.dpDiv.empty();
18657
18658		// determine sizing offscreen
18659		inst.dpDiv.css( { position: "absolute", display: "block", top: "-1000px" } );
18660		$.datepicker._updateDatepicker( inst );
18661
18662		// fix width for dynamic number of date pickers
18663		// and adjust position before showing
18664		offset = $.datepicker._checkOffset( inst, offset, isFixed );
18665		inst.dpDiv.css( { position: ( $.datepicker._inDialog && $.blockUI ?
18666			"static" : ( isFixed ? "fixed" : "absolute" ) ), display: "none",
18667			left: offset.left + "px", top: offset.top + "px" } );
18668
18669		if ( !inst.inline ) {
18670			showAnim = $.datepicker._get( inst, "showAnim" );
18671			duration = $.datepicker._get( inst, "duration" );
18672			inst.dpDiv.css( "z-index", datepicker_getZindex( $( input ) ) + 1 );
18673			$.datepicker._datepickerShowing = true;
18674
18675			if ( $.effects && $.effects.effect[ showAnim ] ) {
18676				inst.dpDiv.show( showAnim, $.datepicker._get( inst, "showOptions" ), duration );
18677			} else {
18678				inst.dpDiv[ showAnim || "show" ]( showAnim ? duration : null );
18679			}
18680
18681			if ( $.datepicker._shouldFocusInput( inst ) ) {
18682				inst.input.trigger( "focus" );
18683			}
18684
18685			$.datepicker._curInst = inst;
18686		}
18687	},
18688
18689	/* Generate the date picker content. */
18690	_updateDatepicker: function( inst ) {
18691		this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
18692		datepicker_instActive = inst; // for delegate hover events
18693		inst.dpDiv.empty().append( this._generateHTML( inst ) );
18694		this._attachHandlers( inst );
18695
18696		var origyearshtml,
18697			numMonths = this._getNumberOfMonths( inst ),
18698			cols = numMonths[ 1 ],
18699			width = 17,
18700			activeCell = inst.dpDiv.find( "." + this._dayOverClass + " a" ),
18701			onUpdateDatepicker = $.datepicker._get( inst, "onUpdateDatepicker" );
18702
18703		if ( activeCell.length > 0 ) {
18704			datepicker_handleMouseover.apply( activeCell.get( 0 ) );
18705		}
18706
18707		inst.dpDiv.removeClass( "ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4" ).width( "" );
18708		if ( cols > 1 ) {
18709			inst.dpDiv.addClass( "ui-datepicker-multi-" + cols ).css( "width", ( width * cols ) + "em" );
18710		}
18711		inst.dpDiv[ ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ? "add" : "remove" ) +
18712			"Class" ]( "ui-datepicker-multi" );
18713		inst.dpDiv[ ( this._get( inst, "isRTL" ) ? "add" : "remove" ) +
18714			"Class" ]( "ui-datepicker-rtl" );
18715
18716		if ( inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {
18717			inst.input.trigger( "focus" );
18718		}
18719
18720		// Deffered render of the years select (to avoid flashes on Firefox)
18721		if ( inst.yearshtml ) {
18722			origyearshtml = inst.yearshtml;
18723			setTimeout( function() {
18724
18725				//assure that inst.yearshtml didn't change.
18726				if ( origyearshtml === inst.yearshtml && inst.yearshtml ) {
18727					inst.dpDiv.find( "select.ui-datepicker-year" ).first().replaceWith( inst.yearshtml );
18728				}
18729				origyearshtml = inst.yearshtml = null;
18730			}, 0 );
18731		}
18732
18733		if ( onUpdateDatepicker ) {
18734			onUpdateDatepicker.apply( ( inst.input ? inst.input[ 0 ] : null ), [ inst ] );
18735		}
18736	},
18737
18738	_shouldFocusInput: function( inst ) {
18739		return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" );
18740	},
18741
18742	/* Check positioning to remain on screen. */
18743	_checkOffset: function( inst, offset, isFixed ) {
18744		var dpWidth = inst.dpDiv.outerWidth(),
18745			dpHeight = inst.dpDiv.outerHeight(),
18746			inputWidth = inst.input ? inst.input.outerWidth() : 0,
18747			inputHeight = inst.input ? inst.input.outerHeight() : 0,
18748			viewWidth = document.documentElement.clientWidth + ( isFixed ? 0 : $( document ).scrollLeft() ),
18749			viewHeight = document.documentElement.clientHeight + ( isFixed ? 0 : $( document ).scrollTop() );
18750
18751		offset.left -= ( this._get( inst, "isRTL" ) ? ( dpWidth - inputWidth ) : 0 );
18752		offset.left -= ( isFixed && offset.left === inst.input.offset().left ) ? $( document ).scrollLeft() : 0;
18753		offset.top -= ( isFixed && offset.top === ( inst.input.offset().top + inputHeight ) ) ? $( document ).scrollTop() : 0;
18754
18755		// Now check if datepicker is showing outside window viewport - move to a better place if so.
18756		offset.left -= Math.min( offset.left, ( offset.left + dpWidth > viewWidth && viewWidth > dpWidth ) ?
18757			Math.abs( offset.left + dpWidth - viewWidth ) : 0 );
18758		offset.top -= Math.min( offset.top, ( offset.top + dpHeight > viewHeight && viewHeight > dpHeight ) ?
18759			Math.abs( dpHeight + inputHeight ) : 0 );
18760
18761		return offset;
18762	},
18763
18764	/* Find an object's position on the screen. */
18765	_findPos: function( obj ) {
18766		var position,
18767			inst = this._getInst( obj ),
18768			isRTL = this._get( inst, "isRTL" );
18769
18770		while ( obj && ( obj.type === "hidden" || obj.nodeType !== 1 || $.expr.pseudos.hidden( obj ) ) ) {
18771			obj = obj[ isRTL ? "previousSibling" : "nextSibling" ];
18772		}
18773
18774		position = $( obj ).offset();
18775		return [ position.left, position.top ];
18776	},
18777
18778	/* Hide the date picker from view.
18779	 * @param  input  element - the input field attached to the date picker
18780	 */
18781	_hideDatepicker: function( input ) {
18782		var showAnim, duration, postProcess, onClose,
18783			inst = this._curInst;
18784
18785		if ( !inst || ( input && inst !== $.data( input, "datepicker" ) ) ) {
18786			return;
18787		}
18788
18789		if ( this._datepickerShowing ) {
18790			showAnim = this._get( inst, "showAnim" );
18791			duration = this._get( inst, "duration" );
18792			postProcess = function() {
18793				$.datepicker._tidyDialog( inst );
18794			};
18795
18796			if ( $.effects && ( $.effects.effect[ showAnim ] ) ) {
18797				inst.dpDiv.hide( showAnim, $.datepicker._get( inst, "showOptions" ), duration, postProcess );
18798			} else {
18799				inst.dpDiv[ ( showAnim === "slideDown" ? "slideUp" :
18800					( showAnim === "fadeIn" ? "fadeOut" : "hide" ) ) ]( ( showAnim ? duration : null ), postProcess );
18801			}
18802
18803			if ( !showAnim ) {
18804				postProcess();
18805			}
18806			this._datepickerShowing = false;
18807
18808			onClose = this._get( inst, "onClose" );
18809			if ( onClose ) {
18810				onClose.apply( ( inst.input ? inst.input[ 0 ] : null ), [ ( inst.input ? inst.input.val() : "" ), inst ] );
18811			}
18812
18813			this._lastInput = null;
18814			if ( this._inDialog ) {
18815				this._dialogInput.css( { position: "absolute", left: "0", top: "-100px" } );
18816				if ( $.blockUI ) {
18817					$.unblockUI();
18818					$( "body" ).append( this.dpDiv );
18819				}
18820			}
18821			this._inDialog = false;
18822		}
18823	},
18824
18825	/* Tidy up after a dialog display. */
18826	_tidyDialog: function( inst ) {
18827		inst.dpDiv.removeClass( this._dialogClass ).off( ".ui-datepicker-calendar" );
18828	},
18829
18830	/* Close date picker if clicked elsewhere. */
18831	_checkExternalClick: function( event ) {
18832		if ( !$.datepicker._curInst ) {
18833			return;
18834		}
18835
18836		var $target = $( event.target ),
18837			inst = $.datepicker._getInst( $target[ 0 ] );
18838
18839		if ( ( ( $target[ 0 ].id !== $.datepicker._mainDivId &&
18840				$target.parents( "#" + $.datepicker._mainDivId ).length === 0 &&
18841				!$target.hasClass( $.datepicker.markerClassName ) &&
18842				!$target.closest( "." + $.datepicker._triggerClass ).length &&
18843				$.datepicker._datepickerShowing && !( $.datepicker._inDialog && $.blockUI ) ) ) ||
18844			( $target.hasClass( $.datepicker.markerClassName ) && $.datepicker._curInst !== inst ) ) {
18845				$.datepicker._hideDatepicker();
18846		}
18847	},
18848
18849	/* Adjust one of the date sub-fields. */
18850	_adjustDate: function( id, offset, period ) {
18851		var target = $( id ),
18852			inst = this._getInst( target[ 0 ] );
18853
18854		if ( this._isDisabledDatepicker( target[ 0 ] ) ) {
18855			return;
18856		}
18857		this._adjustInstDate( inst, offset, period );
18858		this._updateDatepicker( inst );
18859	},
18860
18861	/* Action for current link. */
18862	_gotoToday: function( id ) {
18863		var date,
18864			target = $( id ),
18865			inst = this._getInst( target[ 0 ] );
18866
18867		if ( this._get( inst, "gotoCurrent" ) && inst.currentDay ) {
18868			inst.selectedDay = inst.currentDay;
18869			inst.drawMonth = inst.selectedMonth = inst.currentMonth;
18870			inst.drawYear = inst.selectedYear = inst.currentYear;
18871		} else {
18872			date = new Date();
18873			inst.selectedDay = date.getDate();
18874			inst.drawMonth = inst.selectedMonth = date.getMonth();
18875			inst.drawYear = inst.selectedYear = date.getFullYear();
18876		}
18877		this._notifyChange( inst );
18878		this._adjustDate( target );
18879	},
18880
18881	/* Action for selecting a new month/year. */
18882	_selectMonthYear: function( id, select, period ) {
18883		var target = $( id ),
18884			inst = this._getInst( target[ 0 ] );
18885
18886		inst[ "selected" + ( period === "M" ? "Month" : "Year" ) ] =
18887		inst[ "draw" + ( period === "M" ? "Month" : "Year" ) ] =
18888			parseInt( select.options[ select.selectedIndex ].value, 10 );
18889
18890		this._notifyChange( inst );
18891		this._adjustDate( target );
18892	},
18893
18894	/* Action for selecting a day. */
18895	_selectDay: function( id, month, year, td ) {
18896		var inst,
18897			target = $( id );
18898
18899		if ( $( td ).hasClass( this._unselectableClass ) || this._isDisabledDatepicker( target[ 0 ] ) ) {
18900			return;
18901		}
18902
18903		inst = this._getInst( target[ 0 ] );
18904		inst.selectedDay = inst.currentDay = parseInt( $( "a", td ).attr( "data-date" ) );
18905		inst.selectedMonth = inst.currentMonth = month;
18906		inst.selectedYear = inst.currentYear = year;
18907		this._selectDate( id, this._formatDate( inst,
18908			inst.currentDay, inst.currentMonth, inst.currentYear ) );
18909	},
18910
18911	/* Erase the input field and hide the date picker. */
18912	_clearDate: function( id ) {
18913		var target = $( id );
18914		this._selectDate( target, "" );
18915	},
18916
18917	/* Update the input field with the selected date. */
18918	_selectDate: function( id, dateStr ) {
18919		var onSelect,
18920			target = $( id ),
18921			inst = this._getInst( target[ 0 ] );
18922
18923		dateStr = ( dateStr != null ? dateStr : this._formatDate( inst ) );
18924		if ( inst.input ) {
18925			inst.input.val( dateStr );
18926		}
18927		this._updateAlternate( inst );
18928
18929		onSelect = this._get( inst, "onSelect" );
18930		if ( onSelect ) {
18931			onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] );  // trigger custom callback
18932		} else if ( inst.input ) {
18933			inst.input.trigger( "change" ); // fire the change event
18934		}
18935
18936		if ( inst.inline ) {
18937			this._updateDatepicker( inst );
18938		} else {
18939			this._hideDatepicker();
18940			this._lastInput = inst.input[ 0 ];
18941			if ( typeof( inst.input[ 0 ] ) !== "object" ) {
18942				inst.input.trigger( "focus" ); // restore focus
18943			}
18944			this._lastInput = null;
18945		}
18946	},
18947
18948	/* Update any alternate field to synchronise with the main field. */
18949	_updateAlternate: function( inst ) {
18950		var altFormat, date, dateStr,
18951			altField = this._get( inst, "altField" );
18952
18953		if ( altField ) { // update alternate field too
18954			altFormat = this._get( inst, "altFormat" ) || this._get( inst, "dateFormat" );
18955			date = this._getDate( inst );
18956			dateStr = this.formatDate( altFormat, date, this._getFormatConfig( inst ) );
18957			$( document ).find( altField ).val( dateStr );
18958		}
18959	},
18960
18961	/* Set as beforeShowDay function to prevent selection of weekends.
18962	 * @param  date  Date - the date to customise
18963	 * @return [boolean, string] - is this date selectable?, what is its CSS class?
18964	 */
18965	noWeekends: function( date ) {
18966		var day = date.getDay();
18967		return [ ( day > 0 && day < 6 ), "" ];
18968	},
18969
18970	/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
18971	 * @param  date  Date - the date to get the week for
18972	 * @return  number - the number of the week within the year that contains this date
18973	 */
18974	iso8601Week: function( date ) {
18975		var time,
18976			checkDate = new Date( date.getTime() );
18977
18978		// Find Thursday of this week starting on Monday
18979		checkDate.setDate( checkDate.getDate() + 4 - ( checkDate.getDay() || 7 ) );
18980
18981		time = checkDate.getTime();
18982		checkDate.setMonth( 0 ); // Compare with Jan 1
18983		checkDate.setDate( 1 );
18984		return Math.floor( Math.round( ( time - checkDate ) / 86400000 ) / 7 ) + 1;
18985	},
18986
18987	/* Parse a string value into a date object.
18988	 * See formatDate below for the possible formats.
18989	 *
18990	 * @param  format string - the expected format of the date
18991	 * @param  value string - the date in the above format
18992	 * @param  settings Object - attributes include:
18993	 *					shortYearCutoff  number - the cutoff year for determining the century (optional)
18994	 *					dayNamesShort	string[7] - abbreviated names of the days from Sunday (optional)
18995	 *					dayNames		string[7] - names of the days from Sunday (optional)
18996	 *					monthNamesShort string[12] - abbreviated names of the months (optional)
18997	 *					monthNames		string[12] - names of the months (optional)
18998	 * @return  Date - the extracted date value or null if value is blank
18999	 */
19000	parseDate: function( format, value, settings ) {
19001		if ( format == null || value == null ) {
19002			throw "Invalid arguments";
19003		}
19004
19005		value = ( typeof value === "object" ? value.toString() : value + "" );
19006		if ( value === "" ) {
19007			return null;
19008		}
19009
19010		var iFormat, dim, extra,
19011			iValue = 0,
19012			shortYearCutoffTemp = ( settings ? settings.shortYearCutoff : null ) || this._defaults.shortYearCutoff,
19013			shortYearCutoff = ( typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp :
19014				new Date().getFullYear() % 100 + parseInt( shortYearCutoffTemp, 10 ) ),
19015			dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort,
19016			dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames,
19017			monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort,
19018			monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames,
19019			year = -1,
19020			month = -1,
19021			day = -1,
19022			doy = -1,
19023			literal = false,
19024			date,
19025
19026			// Check whether a format character is doubled
19027			lookAhead = function( match ) {
19028				var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
19029				if ( matches ) {
19030					iFormat++;
19031				}
19032				return matches;
19033			},
19034
19035			// Extract a number from the string value
19036			getNumber = function( match ) {
19037				var isDoubled = lookAhead( match ),
19038					size = ( match === "@" ? 14 : ( match === "!" ? 20 :
19039					( match === "y" && isDoubled ? 4 : ( match === "o" ? 3 : 2 ) ) ) ),
19040					minSize = ( match === "y" ? size : 1 ),
19041					digits = new RegExp( "^\\d{" + minSize + "," + size + "}" ),
19042					num = value.substring( iValue ).match( digits );
19043				if ( !num ) {
19044					throw "Missing number at position " + iValue;
19045				}
19046				iValue += num[ 0 ].length;
19047				return parseInt( num[ 0 ], 10 );
19048			},
19049
19050			// Extract a name from the string value and convert to an index
19051			getName = function( match, shortNames, longNames ) {
19052				var index = -1,
19053					names = $.map( lookAhead( match ) ? longNames : shortNames, function( v, k ) {
19054						return [ [ k, v ] ];
19055					} ).sort( function( a, b ) {
19056						return -( a[ 1 ].length - b[ 1 ].length );
19057					} );
19058
19059				$.each( names, function( i, pair ) {
19060					var name = pair[ 1 ];
19061					if ( value.substr( iValue, name.length ).toLowerCase() === name.toLowerCase() ) {
19062						index = pair[ 0 ];
19063						iValue += name.length;
19064						return false;
19065					}
19066				} );
19067				if ( index !== -1 ) {
19068					return index + 1;
19069				} else {
19070					throw "Unknown name at position " + iValue;
19071				}
19072			},
19073
19074			// Confirm that a literal character matches the string value
19075			checkLiteral = function() {
19076				if ( value.charAt( iValue ) !== format.charAt( iFormat ) ) {
19077					throw "Unexpected literal at position " + iValue;
19078				}
19079				iValue++;
19080			};
19081
19082		for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
19083			if ( literal ) {
19084				if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
19085					literal = false;
19086				} else {
19087					checkLiteral();
19088				}
19089			} else {
19090				switch ( format.charAt( iFormat ) ) {
19091					case "d":
19092						day = getNumber( "d" );
19093						break;
19094					case "D":
19095						getName( "D", dayNamesShort, dayNames );
19096						break;
19097					case "o":
19098						doy = getNumber( "o" );
19099						break;
19100					case "m":
19101						month = getNumber( "m" );
19102						break;
19103					case "M":
19104						month = getName( "M", monthNamesShort, monthNames );
19105						break;
19106					case "y":
19107						year = getNumber( "y" );
19108						break;
19109					case "@":
19110						date = new Date( getNumber( "@" ) );
19111						year = date.getFullYear();
19112						month = date.getMonth() + 1;
19113						day = date.getDate();
19114						break;
19115					case "!":
19116						date = new Date( ( getNumber( "!" ) - this._ticksTo1970 ) / 10000 );
19117						year = date.getFullYear();
19118						month = date.getMonth() + 1;
19119						day = date.getDate();
19120						break;
19121					case "'":
19122						if ( lookAhead( "'" ) ) {
19123							checkLiteral();
19124						} else {
19125							literal = true;
19126						}
19127						break;
19128					default:
19129						checkLiteral();
19130				}
19131			}
19132		}
19133
19134		if ( iValue < value.length ) {
19135			extra = value.substr( iValue );
19136			if ( !/^\s+/.test( extra ) ) {
19137				throw "Extra/unparsed characters found in date: " + extra;
19138			}
19139		}
19140
19141		if ( year === -1 ) {
19142			year = new Date().getFullYear();
19143		} else if ( year < 100 ) {
19144			year += new Date().getFullYear() - new Date().getFullYear() % 100 +
19145				( year <= shortYearCutoff ? 0 : -100 );
19146		}
19147
19148		if ( doy > -1 ) {
19149			month = 1;
19150			day = doy;
19151			do {
19152				dim = this._getDaysInMonth( year, month - 1 );
19153				if ( day <= dim ) {
19154					break;
19155				}
19156				month++;
19157				day -= dim;
19158			} while ( true );
19159		}
19160
19161		date = this._daylightSavingAdjust( new Date( year, month - 1, day ) );
19162		if ( date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day ) {
19163			throw "Invalid date"; // E.g. 31/02/00
19164		}
19165		return date;
19166	},
19167
19168	/* Standard date formats. */
19169	ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601)
19170	COOKIE: "D, dd M yy",
19171	ISO_8601: "yy-mm-dd",
19172	RFC_822: "D, d M y",
19173	RFC_850: "DD, dd-M-y",
19174	RFC_1036: "D, d M y",
19175	RFC_1123: "D, d M yy",
19176	RFC_2822: "D, d M yy",
19177	RSS: "D, d M y", // RFC 822
19178	TICKS: "!",
19179	TIMESTAMP: "@",
19180	W3C: "yy-mm-dd", // ISO 8601
19181
19182	_ticksTo1970: ( ( ( 1970 - 1 ) * 365 + Math.floor( 1970 / 4 ) - Math.floor( 1970 / 100 ) +
19183		Math.floor( 1970 / 400 ) ) * 24 * 60 * 60 * 10000000 ),
19184
19185	/* Format a date object into a string value.
19186	 * The format can be combinations of the following:
19187	 * d  - day of month (no leading zero)
19188	 * dd - day of month (two digit)
19189	 * o  - day of year (no leading zeros)
19190	 * oo - day of year (three digit)
19191	 * D  - day name short
19192	 * DD - day name long
19193	 * m  - month of year (no leading zero)
19194	 * mm - month of year (two digit)
19195	 * M  - month name short
19196	 * MM - month name long
19197	 * y  - year (two digit)
19198	 * yy - year (four digit)
19199	 * @ - Unix timestamp (ms since 01/01/1970)
19200	 * ! - Windows ticks (100ns since 01/01/0001)
19201	 * "..." - literal text
19202	 * '' - single quote
19203	 *
19204	 * @param  format string - the desired format of the date
19205	 * @param  date Date - the date value to format
19206	 * @param  settings Object - attributes include:
19207	 *					dayNamesShort	string[7] - abbreviated names of the days from Sunday (optional)
19208	 *					dayNames		string[7] - names of the days from Sunday (optional)
19209	 *					monthNamesShort string[12] - abbreviated names of the months (optional)
19210	 *					monthNames		string[12] - names of the months (optional)
19211	 * @return  string - the date in the above format
19212	 */
19213	formatDate: function( format, date, settings ) {
19214		if ( !date ) {
19215			return "";
19216		}
19217
19218		var iFormat,
19219			dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort,
19220			dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames,
19221			monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort,
19222			monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames,
19223
19224			// Check whether a format character is doubled
19225			lookAhead = function( match ) {
19226				var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
19227				if ( matches ) {
19228					iFormat++;
19229				}
19230				return matches;
19231			},
19232
19233			// Format a number, with leading zero if necessary
19234			formatNumber = function( match, value, len ) {
19235				var num = "" + value;
19236				if ( lookAhead( match ) ) {
19237					while ( num.length < len ) {
19238						num = "0" + num;
19239					}
19240				}
19241				return num;
19242			},
19243
19244			// Format a name, short or long as requested
19245			formatName = function( match, value, shortNames, longNames ) {
19246				return ( lookAhead( match ) ? longNames[ value ] : shortNames[ value ] );
19247			},
19248			output = "",
19249			literal = false;
19250
19251		if ( date ) {
19252			for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
19253				if ( literal ) {
19254					if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
19255						literal = false;
19256					} else {
19257						output += format.charAt( iFormat );
19258					}
19259				} else {
19260					switch ( format.charAt( iFormat ) ) {
19261						case "d":
19262							output += formatNumber( "d", date.getDate(), 2 );
19263							break;
19264						case "D":
19265							output += formatName( "D", date.getDay(), dayNamesShort, dayNames );
19266							break;
19267						case "o":
19268							output += formatNumber( "o",
19269								Math.round( ( new Date( date.getFullYear(), date.getMonth(), date.getDate() ).getTime() - new Date( date.getFullYear(), 0, 0 ).getTime() ) / 86400000 ), 3 );
19270							break;
19271						case "m":
19272							output += formatNumber( "m", date.getMonth() + 1, 2 );
19273							break;
19274						case "M":
19275							output += formatName( "M", date.getMonth(), monthNamesShort, monthNames );
19276							break;
19277						case "y":
19278							output += ( lookAhead( "y" ) ? date.getFullYear() :
19279								( date.getFullYear() % 100 < 10 ? "0" : "" ) + date.getFullYear() % 100 );
19280							break;
19281						case "@":
19282							output += date.getTime();
19283							break;
19284						case "!":
19285							output += date.getTime() * 10000 + this._ticksTo1970;
19286							break;
19287						case "'":
19288							if ( lookAhead( "'" ) ) {
19289								output += "'";
19290							} else {
19291								literal = true;
19292							}
19293							break;
19294						default:
19295							output += format.charAt( iFormat );
19296					}
19297				}
19298			}
19299		}
19300		return output;
19301	},
19302
19303	/* Extract all possible characters from the date format. */
19304	_possibleChars: function( format ) {
19305		var iFormat,
19306			chars = "",
19307			literal = false,
19308
19309			// Check whether a format character is doubled
19310			lookAhead = function( match ) {
19311				var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
19312				if ( matches ) {
19313					iFormat++;
19314				}
19315				return matches;
19316			};
19317
19318		for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
19319			if ( literal ) {
19320				if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
19321					literal = false;
19322				} else {
19323					chars += format.charAt( iFormat );
19324				}
19325			} else {
19326				switch ( format.charAt( iFormat ) ) {
19327					case "d": case "m": case "y": case "@":
19328						chars += "0123456789";
19329						break;
19330					case "D": case "M":
19331						return null; // Accept anything
19332					case "'":
19333						if ( lookAhead( "'" ) ) {
19334							chars += "'";
19335						} else {
19336							literal = true;
19337						}
19338						break;
19339					default:
19340						chars += format.charAt( iFormat );
19341				}
19342			}
19343		}
19344		return chars;
19345	},
19346
19347	/* Get a setting value, defaulting if necessary. */
19348	_get: function( inst, name ) {
19349		return inst.settings[ name ] !== undefined ?
19350			inst.settings[ name ] : this._defaults[ name ];
19351	},
19352
19353	/* Parse existing date and initialise date picker. */
19354	_setDateFromField: function( inst, noDefault ) {
19355		if ( inst.input.val() === inst.lastVal ) {
19356			return;
19357		}
19358
19359		var dateFormat = this._get( inst, "dateFormat" ),
19360			dates = inst.lastVal = inst.input ? inst.input.val() : null,
19361			defaultDate = this._getDefaultDate( inst ),
19362			date = defaultDate,
19363			settings = this._getFormatConfig( inst );
19364
19365		try {
19366			date = this.parseDate( dateFormat, dates, settings ) || defaultDate;
19367		} catch ( event ) {
19368			dates = ( noDefault ? "" : dates );
19369		}
19370		inst.selectedDay = date.getDate();
19371		inst.drawMonth = inst.selectedMonth = date.getMonth();
19372		inst.drawYear = inst.selectedYear = date.getFullYear();
19373		inst.currentDay = ( dates ? date.getDate() : 0 );
19374		inst.currentMonth = ( dates ? date.getMonth() : 0 );
19375		inst.currentYear = ( dates ? date.getFullYear() : 0 );
19376		this._adjustInstDate( inst );
19377	},
19378
19379	/* Retrieve the default date shown on opening. */
19380	_getDefaultDate: function( inst ) {
19381		return this._restrictMinMax( inst,
19382			this._determineDate( inst, this._get( inst, "defaultDate" ), new Date() ) );
19383	},
19384
19385	/* A date may be specified as an exact value or a relative one. */
19386	_determineDate: function( inst, date, defaultDate ) {
19387		var offsetNumeric = function( offset ) {
19388				var date = new Date();
19389				date.setDate( date.getDate() + offset );
19390				return date;
19391			},
19392			offsetString = function( offset ) {
19393				try {
19394					return $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ),
19395						offset, $.datepicker._getFormatConfig( inst ) );
19396				} catch ( e ) {
19397
19398					// Ignore
19399				}
19400
19401				var date = ( offset.toLowerCase().match( /^c/ ) ?
19402					$.datepicker._getDate( inst ) : null ) || new Date(),
19403					year = date.getFullYear(),
19404					month = date.getMonth(),
19405					day = date.getDate(),
19406					pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,
19407					matches = pattern.exec( offset );
19408
19409				while ( matches ) {
19410					switch ( matches[ 2 ] || "d" ) {
19411						case "d" : case "D" :
19412							day += parseInt( matches[ 1 ], 10 ); break;
19413						case "w" : case "W" :
19414							day += parseInt( matches[ 1 ], 10 ) * 7; break;
19415						case "m" : case "M" :
19416							month += parseInt( matches[ 1 ], 10 );
19417							day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) );
19418							break;
19419						case "y": case "Y" :
19420							year += parseInt( matches[ 1 ], 10 );
19421							day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) );
19422							break;
19423					}
19424					matches = pattern.exec( offset );
19425				}
19426				return new Date( year, month, day );
19427			},
19428			newDate = ( date == null || date === "" ? defaultDate : ( typeof date === "string" ? offsetString( date ) :
19429				( typeof date === "number" ? ( isNaN( date ) ? defaultDate : offsetNumeric( date ) ) : new Date( date.getTime() ) ) ) );
19430
19431		newDate = ( newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate );
19432		if ( newDate ) {
19433			newDate.setHours( 0 );
19434			newDate.setMinutes( 0 );
19435			newDate.setSeconds( 0 );
19436			newDate.setMilliseconds( 0 );
19437		}
19438		return this._daylightSavingAdjust( newDate );
19439	},
19440
19441	/* Handle switch to/from daylight saving.
19442	 * Hours may be non-zero on daylight saving cut-over:
19443	 * > 12 when midnight changeover, but then cannot generate
19444	 * midnight datetime, so jump to 1AM, otherwise reset.
19445	 * @param  date  (Date) the date to check
19446	 * @return  (Date) the corrected date
19447	 */
19448	_daylightSavingAdjust: function( date ) {
19449		if ( !date ) {
19450			return null;
19451		}
19452		date.setHours( date.getHours() > 12 ? date.getHours() + 2 : 0 );
19453		return date;
19454	},
19455
19456	/* Set the date(s) directly. */
19457	_setDate: function( inst, date, noChange ) {
19458		var clear = !date,
19459			origMonth = inst.selectedMonth,
19460			origYear = inst.selectedYear,
19461			newDate = this._restrictMinMax( inst, this._determineDate( inst, date, new Date() ) );
19462
19463		inst.selectedDay = inst.currentDay = newDate.getDate();
19464		inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
19465		inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
19466		if ( ( origMonth !== inst.selectedMonth || origYear !== inst.selectedYear ) && !noChange ) {
19467			this._notifyChange( inst );
19468		}
19469		this._adjustInstDate( inst );
19470		if ( inst.input ) {
19471			inst.input.val( clear ? "" : this._formatDate( inst ) );
19472		}
19473	},
19474
19475	/* Retrieve the date(s) directly. */
19476	_getDate: function( inst ) {
19477		var startDate = ( !inst.currentYear || ( inst.input && inst.input.val() === "" ) ? null :
19478			this._daylightSavingAdjust( new Date(
19479			inst.currentYear, inst.currentMonth, inst.currentDay ) ) );
19480			return startDate;
19481	},
19482
19483	/* Attach the onxxx handlers.  These are declared statically so
19484	 * they work with static code transformers like Caja.
19485	 */
19486	_attachHandlers: function( inst ) {
19487		var stepMonths = this._get( inst, "stepMonths" ),
19488			id = "#" + inst.id.replace( /\\\\/g, "\\" );
19489		inst.dpDiv.find( "[data-handler]" ).map( function() {
19490			var handler = {
19491				prev: function() {
19492					$.datepicker._adjustDate( id, -stepMonths, "M" );
19493				},
19494				next: function() {
19495					$.datepicker._adjustDate( id, +stepMonths, "M" );
19496				},
19497				hide: function() {
19498					$.datepicker._hideDatepicker();
19499				},
19500				today: function() {
19501					$.datepicker._gotoToday( id );
19502				},
19503				selectDay: function() {
19504					$.datepicker._selectDay( id, +this.getAttribute( "data-month" ), +this.getAttribute( "data-year" ), this );
19505					return false;
19506				},
19507				selectMonth: function() {
19508					$.datepicker._selectMonthYear( id, this, "M" );
19509					return false;
19510				},
19511				selectYear: function() {
19512					$.datepicker._selectMonthYear( id, this, "Y" );
19513					return false;
19514				}
19515			};
19516			$( this ).on( this.getAttribute( "data-event" ), handler[ this.getAttribute( "data-handler" ) ] );
19517		} );
19518	},
19519
19520	/* Generate the HTML for the current state of the date picker. */
19521	_generateHTML: function( inst ) {
19522		var maxDraw, prevText, prev, nextText, next, currentText, gotoDate,
19523			controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,
19524			monthNames, monthNamesShort, beforeShowDay, showOtherMonths,
19525			selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,
19526			cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,
19527			printDate, dRow, tbody, daySettings, otherMonth, unselectable,
19528			tempDate = new Date(),
19529			today = this._daylightSavingAdjust(
19530				new Date( tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate() ) ), // clear time
19531			isRTL = this._get( inst, "isRTL" ),
19532			showButtonPanel = this._get( inst, "showButtonPanel" ),
19533			hideIfNoPrevNext = this._get( inst, "hideIfNoPrevNext" ),
19534			navigationAsDateFormat = this._get( inst, "navigationAsDateFormat" ),
19535			numMonths = this._getNumberOfMonths( inst ),
19536			showCurrentAtPos = this._get( inst, "showCurrentAtPos" ),
19537			stepMonths = this._get( inst, "stepMonths" ),
19538			isMultiMonth = ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ),
19539			currentDate = this._daylightSavingAdjust( ( !inst.currentDay ? new Date( 9999, 9, 9 ) :
19540				new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) ),
19541			minDate = this._getMinMaxDate( inst, "min" ),
19542			maxDate = this._getMinMaxDate( inst, "max" ),
19543			drawMonth = inst.drawMonth - showCurrentAtPos,
19544			drawYear = inst.drawYear;
19545
19546		if ( drawMonth < 0 ) {
19547			drawMonth += 12;
19548			drawYear--;
19549		}
19550		if ( maxDate ) {
19551			maxDraw = this._daylightSavingAdjust( new Date( maxDate.getFullYear(),
19552				maxDate.getMonth() - ( numMonths[ 0 ] * numMonths[ 1 ] ) + 1, maxDate.getDate() ) );
19553			maxDraw = ( minDate && maxDraw < minDate ? minDate : maxDraw );
19554			while ( this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 ) ) > maxDraw ) {
19555				drawMonth--;
19556				if ( drawMonth < 0 ) {
19557					drawMonth = 11;
19558					drawYear--;
19559				}
19560			}
19561		}
19562		inst.drawMonth = drawMonth;
19563		inst.drawYear = drawYear;
19564
19565		prevText = this._get( inst, "prevText" );
19566		prevText = ( !navigationAsDateFormat ? prevText : this.formatDate( prevText,
19567			this._daylightSavingAdjust( new Date( drawYear, drawMonth - stepMonths, 1 ) ),
19568			this._getFormatConfig( inst ) ) );
19569
19570		if ( this._canAdjustMonth( inst, -1, drawYear, drawMonth ) ) {
19571			prev = $( "<a>" )
19572				.attr( {
19573					"class": "ui-datepicker-prev ui-corner-all",
19574					"data-handler": "prev",
19575					"data-event": "click",
19576					title: prevText
19577				} )
19578				.append(
19579					$( "<span>" )
19580						.addClass( "ui-icon ui-icon-circle-triangle-" +
19581							( isRTL ? "e" : "w" ) )
19582						.text( prevText )
19583				)[ 0 ].outerHTML;
19584		} else if ( hideIfNoPrevNext ) {
19585			prev = "";
19586		} else {
19587			prev = $( "<a>" )
19588				.attr( {
19589					"class": "ui-datepicker-prev ui-corner-all ui-state-disabled",
19590					title: prevText
19591				} )
19592				.append(
19593					$( "<span>" )
19594						.addClass( "ui-icon ui-icon-circle-triangle-" +
19595							( isRTL ? "e" : "w" ) )
19596						.text( prevText )
19597				)[ 0 ].outerHTML;
19598		}
19599
19600		nextText = this._get( inst, "nextText" );
19601		nextText = ( !navigationAsDateFormat ? nextText : this.formatDate( nextText,
19602			this._daylightSavingAdjust( new Date( drawYear, drawMonth + stepMonths, 1 ) ),
19603			this._getFormatConfig( inst ) ) );
19604
19605		if ( this._canAdjustMonth( inst, +1, drawYear, drawMonth ) ) {
19606			next = $( "<a>" )
19607				.attr( {
19608					"class": "ui-datepicker-next ui-corner-all",
19609					"data-handler": "next",
19610					"data-event": "click",
19611					title: nextText
19612				} )
19613				.append(
19614					$( "<span>" )
19615						.addClass( "ui-icon ui-icon-circle-triangle-" +
19616							( isRTL ? "w" : "e" ) )
19617						.text( nextText )
19618				)[ 0 ].outerHTML;
19619		} else if ( hideIfNoPrevNext ) {
19620			next = "";
19621		} else {
19622			next = $( "<a>" )
19623				.attr( {
19624					"class": "ui-datepicker-next ui-corner-all ui-state-disabled",
19625					title: nextText
19626				} )
19627				.append(
19628					$( "<span>" )
19629						.attr( "class", "ui-icon ui-icon-circle-triangle-" +
19630							( isRTL ? "w" : "e" ) )
19631						.text( nextText )
19632				)[ 0 ].outerHTML;
19633		}
19634
19635		currentText = this._get( inst, "currentText" );
19636		gotoDate = ( this._get( inst, "gotoCurrent" ) && inst.currentDay ? currentDate : today );
19637		currentText = ( !navigationAsDateFormat ? currentText :
19638			this.formatDate( currentText, gotoDate, this._getFormatConfig( inst ) ) );
19639
19640		controls = "";
19641		if ( !inst.inline ) {
19642			controls = $( "<button>" )
19643				.attr( {
19644					type: "button",
19645					"class": "ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all",
19646					"data-handler": "hide",
19647					"data-event": "click"
19648				} )
19649				.text( this._get( inst, "closeText" ) )[ 0 ].outerHTML;
19650		}
19651
19652		buttonPanel = "";
19653		if ( showButtonPanel ) {
19654			buttonPanel = $( "<div class='ui-datepicker-buttonpane ui-widget-content'>" )
19655				.append( isRTL ? controls : "" )
19656				.append( this._isInRange( inst, gotoDate ) ?
19657					$( "<button>" )
19658						.attr( {
19659							type: "button",
19660							"class": "ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all",
19661							"data-handler": "today",
19662							"data-event": "click"
19663						} )
19664						.text( currentText ) :
19665					"" )
19666				.append( isRTL ? "" : controls )[ 0 ].outerHTML;
19667		}
19668
19669		firstDay = parseInt( this._get( inst, "firstDay" ), 10 );
19670		firstDay = ( isNaN( firstDay ) ? 0 : firstDay );
19671
19672		showWeek = this._get( inst, "showWeek" );
19673		dayNames = this._get( inst, "dayNames" );
19674		dayNamesMin = this._get( inst, "dayNamesMin" );
19675		monthNames = this._get( inst, "monthNames" );
19676		monthNamesShort = this._get( inst, "monthNamesShort" );
19677		beforeShowDay = this._get( inst, "beforeShowDay" );
19678		showOtherMonths = this._get( inst, "showOtherMonths" );
19679		selectOtherMonths = this._get( inst, "selectOtherMonths" );
19680		defaultDate = this._getDefaultDate( inst );
19681		html = "";
19682
19683		for ( row = 0; row < numMonths[ 0 ]; row++ ) {
19684			group = "";
19685			this.maxRows = 4;
19686			for ( col = 0; col < numMonths[ 1 ]; col++ ) {
19687				selectedDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, inst.selectedDay ) );
19688				cornerClass = " ui-corner-all";
19689				calender = "";
19690				if ( isMultiMonth ) {
19691					calender += "<div class='ui-datepicker-group";
19692					if ( numMonths[ 1 ] > 1 ) {
19693						switch ( col ) {
19694							case 0: calender += " ui-datepicker-group-first";
19695								cornerClass = " ui-corner-" + ( isRTL ? "right" : "left" ); break;
19696							case numMonths[ 1 ] - 1: calender += " ui-datepicker-group-last";
19697								cornerClass = " ui-corner-" + ( isRTL ? "left" : "right" ); break;
19698							default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break;
19699						}
19700					}
19701					calender += "'>";
19702				}
19703				calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" +
19704					( /all|left/.test( cornerClass ) && row === 0 ? ( isRTL ? next : prev ) : "" ) +
19705					( /all|right/.test( cornerClass ) && row === 0 ? ( isRTL ? prev : next ) : "" ) +
19706					this._generateMonthYearHeader( inst, drawMonth, drawYear, minDate, maxDate,
19707					row > 0 || col > 0, monthNames, monthNamesShort ) + // draw month headers
19708					"</div><table class='ui-datepicker-calendar'><thead>" +
19709					"<tr>";
19710				thead = ( showWeek ? "<th class='ui-datepicker-week-col'>" + this._get( inst, "weekHeader" ) + "</th>" : "" );
19711				for ( dow = 0; dow < 7; dow++ ) { // days of the week
19712					day = ( dow + firstDay ) % 7;
19713					thead += "<th scope='col'" + ( ( dow + firstDay + 6 ) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "" ) + ">" +
19714						"<span title='" + dayNames[ day ] + "'>" + dayNamesMin[ day ] + "</span></th>";
19715				}
19716				calender += thead + "</tr></thead><tbody>";
19717				daysInMonth = this._getDaysInMonth( drawYear, drawMonth );
19718				if ( drawYear === inst.selectedYear && drawMonth === inst.selectedMonth ) {
19719					inst.selectedDay = Math.min( inst.selectedDay, daysInMonth );
19720				}
19721				leadDays = ( this._getFirstDayOfMonth( drawYear, drawMonth ) - firstDay + 7 ) % 7;
19722				curRows = Math.ceil( ( leadDays + daysInMonth ) / 7 ); // calculate the number of rows to generate
19723				numRows = ( isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows ); //If multiple months, use the higher number of rows (see #7043)
19724				this.maxRows = numRows;
19725				printDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 - leadDays ) );
19726				for ( dRow = 0; dRow < numRows; dRow++ ) { // create date picker rows
19727					calender += "<tr>";
19728					tbody = ( !showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
19729						this._get( inst, "calculateWeek" )( printDate ) + "</td>" );
19730					for ( dow = 0; dow < 7; dow++ ) { // create date picker days
19731						daySettings = ( beforeShowDay ?
19732							beforeShowDay.apply( ( inst.input ? inst.input[ 0 ] : null ), [ printDate ] ) : [ true, "" ] );
19733						otherMonth = ( printDate.getMonth() !== drawMonth );
19734						unselectable = ( otherMonth && !selectOtherMonths ) || !daySettings[ 0 ] ||
19735							( minDate && printDate < minDate ) || ( maxDate && printDate > maxDate );
19736						tbody += "<td class='" +
19737							( ( dow + firstDay + 6 ) % 7 >= 5 ? " ui-datepicker-week-end" : "" ) + // highlight weekends
19738							( otherMonth ? " ui-datepicker-other-month" : "" ) + // highlight days from other months
19739							( ( printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent ) || // user pressed key
19740							( defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime() ) ?
19741
19742							// or defaultDate is current printedDate and defaultDate is selectedDate
19743							" " + this._dayOverClass : "" ) + // highlight selected day
19744							( unselectable ? " " + this._unselectableClass + " ui-state-disabled" : "" ) +  // highlight unselectable days
19745							( otherMonth && !showOtherMonths ? "" : " " + daySettings[ 1 ] + // highlight custom dates
19746							( printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "" ) + // highlight selected day
19747							( printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "" ) ) + "'" + // highlight today (if different)
19748							( ( !otherMonth || showOtherMonths ) && daySettings[ 2 ] ? " title='" + daySettings[ 2 ].replace( /'/g, "&#39;" ) + "'" : "" ) + // cell title
19749							( unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'" ) + ">" + // actions
19750							( otherMonth && !showOtherMonths ? "&#xa0;" : // display for other months
19751							( unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" +
19752							( printDate.getTime() === today.getTime() ? " ui-state-highlight" : "" ) +
19753							( printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "" ) + // highlight selected day
19754							( otherMonth ? " ui-priority-secondary" : "" ) + // distinguish dates from other months
19755							"' href='#' aria-current='" + ( printDate.getTime() === currentDate.getTime() ? "true" : "false" ) + // mark date as selected for screen reader
19756							"' data-date='" + printDate.getDate() + // store date as data
19757							"'>" + printDate.getDate() + "</a>" ) ) + "</td>"; // display selectable date
19758						printDate.setDate( printDate.getDate() + 1 );
19759						printDate = this._daylightSavingAdjust( printDate );
19760					}
19761					calender += tbody + "</tr>";
19762				}
19763				drawMonth++;
19764				if ( drawMonth > 11 ) {
19765					drawMonth = 0;
19766					drawYear++;
19767				}
19768				calender += "</tbody></table>" + ( isMultiMonth ? "</div>" +
19769							( ( numMonths[ 0 ] > 0 && col === numMonths[ 1 ] - 1 ) ? "<div class='ui-datepicker-row-break'></div>" : "" ) : "" );
19770				group += calender;
19771			}
19772			html += group;
19773		}
19774		html += buttonPanel;
19775		inst._keyEvent = false;
19776		return html;
19777	},
19778
19779	/* Generate the month and year header. */
19780	_generateMonthYearHeader: function( inst, drawMonth, drawYear, minDate, maxDate,
19781			secondary, monthNames, monthNamesShort ) {
19782
19783		var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,
19784			changeMonth = this._get( inst, "changeMonth" ),
19785			changeYear = this._get( inst, "changeYear" ),
19786			showMonthAfterYear = this._get( inst, "showMonthAfterYear" ),
19787			selectMonthLabel = this._get( inst, "selectMonthLabel" ),
19788			selectYearLabel = this._get( inst, "selectYearLabel" ),
19789			html = "<div class='ui-datepicker-title'>",
19790			monthHtml = "";
19791
19792		// Month selection
19793		if ( secondary || !changeMonth ) {
19794			monthHtml += "<span class='ui-datepicker-month'>" + monthNames[ drawMonth ] + "</span>";
19795		} else {
19796			inMinYear = ( minDate && minDate.getFullYear() === drawYear );
19797			inMaxYear = ( maxDate && maxDate.getFullYear() === drawYear );
19798			monthHtml += "<select class='ui-datepicker-month' aria-label='" + selectMonthLabel + "' data-handler='selectMonth' data-event='change'>";
19799			for ( month = 0; month < 12; month++ ) {
19800				if ( ( !inMinYear || month >= minDate.getMonth() ) && ( !inMaxYear || month <= maxDate.getMonth() ) ) {
19801					monthHtml += "<option value='" + month + "'" +
19802						( month === drawMonth ? " selected='selected'" : "" ) +
19803						">" + monthNamesShort[ month ] + "</option>";
19804				}
19805			}
19806			monthHtml += "</select>";
19807		}
19808
19809		if ( !showMonthAfterYear ) {
19810			html += monthHtml + ( secondary || !( changeMonth && changeYear ) ? "&#xa0;" : "" );
19811		}
19812
19813		// Year selection
19814		if ( !inst.yearshtml ) {
19815			inst.yearshtml = "";
19816			if ( secondary || !changeYear ) {
19817				html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
19818			} else {
19819
19820				// determine range of years to display
19821				years = this._get( inst, "yearRange" ).split( ":" );
19822				thisYear = new Date().getFullYear();
19823				determineYear = function( value ) {
19824					var year = ( value.match( /c[+\-].*/ ) ? drawYear + parseInt( value.substring( 1 ), 10 ) :
19825						( value.match( /[+\-].*/ ) ? thisYear + parseInt( value, 10 ) :
19826						parseInt( value, 10 ) ) );
19827					return ( isNaN( year ) ? thisYear : year );
19828				};
19829				year = determineYear( years[ 0 ] );
19830				endYear = Math.max( year, determineYear( years[ 1 ] || "" ) );
19831				year = ( minDate ? Math.max( year, minDate.getFullYear() ) : year );
19832				endYear = ( maxDate ? Math.min( endYear, maxDate.getFullYear() ) : endYear );
19833				inst.yearshtml += "<select class='ui-datepicker-year' aria-label='" + selectYearLabel + "' data-handler='selectYear' data-event='change'>";
19834				for ( ; year <= endYear; year++ ) {
19835					inst.yearshtml += "<option value='" + year + "'" +
19836						( year === drawYear ? " selected='selected'" : "" ) +
19837						">" + year + "</option>";
19838				}
19839				inst.yearshtml += "</select>";
19840
19841				html += inst.yearshtml;
19842				inst.yearshtml = null;
19843			}
19844		}
19845
19846		html += this._get( inst, "yearSuffix" );
19847		if ( showMonthAfterYear ) {
19848			html += ( secondary || !( changeMonth && changeYear ) ? "&#xa0;" : "" ) + monthHtml;
19849		}
19850		html += "</div>"; // Close datepicker_header
19851		return html;
19852	},
19853
19854	/* Adjust one of the date sub-fields. */
19855	_adjustInstDate: function( inst, offset, period ) {
19856		var year = inst.selectedYear + ( period === "Y" ? offset : 0 ),
19857			month = inst.selectedMonth + ( period === "M" ? offset : 0 ),
19858			day = Math.min( inst.selectedDay, this._getDaysInMonth( year, month ) ) + ( period === "D" ? offset : 0 ),
19859			date = this._restrictMinMax( inst, this._daylightSavingAdjust( new Date( year, month, day ) ) );
19860
19861		inst.selectedDay = date.getDate();
19862		inst.drawMonth = inst.selectedMonth = date.getMonth();
19863		inst.drawYear = inst.selectedYear = date.getFullYear();
19864		if ( period === "M" || period === "Y" ) {
19865			this._notifyChange( inst );
19866		}
19867	},
19868
19869	/* Ensure a date is within any min/max bounds. */
19870	_restrictMinMax: function( inst, date ) {
19871		var minDate = this._getMinMaxDate( inst, "min" ),
19872			maxDate = this._getMinMaxDate( inst, "max" ),
19873			newDate = ( minDate && date < minDate ? minDate : date );
19874		return ( maxDate && newDate > maxDate ? maxDate : newDate );
19875	},
19876
19877	/* Notify change of month/year. */
19878	_notifyChange: function( inst ) {
19879		var onChange = this._get( inst, "onChangeMonthYear" );
19880		if ( onChange ) {
19881			onChange.apply( ( inst.input ? inst.input[ 0 ] : null ),
19882				[ inst.selectedYear, inst.selectedMonth + 1, inst ] );
19883		}
19884	},
19885
19886	/* Determine the number of months to show. */
19887	_getNumberOfMonths: function( inst ) {
19888		var numMonths = this._get( inst, "numberOfMonths" );
19889		return ( numMonths == null ? [ 1, 1 ] : ( typeof numMonths === "number" ? [ 1, numMonths ] : numMonths ) );
19890	},
19891
19892	/* Determine the current maximum date - ensure no time components are set. */
19893	_getMinMaxDate: function( inst, minMax ) {
19894		return this._determineDate( inst, this._get( inst, minMax + "Date" ), null );
19895	},
19896
19897	/* Find the number of days in a given month. */
19898	_getDaysInMonth: function( year, month ) {
19899		return 32 - this._daylightSavingAdjust( new Date( year, month, 32 ) ).getDate();
19900	},
19901
19902	/* Find the day of the week of the first of a month. */
19903	_getFirstDayOfMonth: function( year, month ) {
19904		return new Date( year, month, 1 ).getDay();
19905	},
19906
19907	/* Determines if we should allow a "next/prev" month display change. */
19908	_canAdjustMonth: function( inst, offset, curYear, curMonth ) {
19909		var numMonths = this._getNumberOfMonths( inst ),
19910			date = this._daylightSavingAdjust( new Date( curYear,
19911			curMonth + ( offset < 0 ? offset : numMonths[ 0 ] * numMonths[ 1 ] ), 1 ) );
19912
19913		if ( offset < 0 ) {
19914			date.setDate( this._getDaysInMonth( date.getFullYear(), date.getMonth() ) );
19915		}
19916		return this._isInRange( inst, date );
19917	},
19918
19919	/* Is the given date in the accepted range? */
19920	_isInRange: function( inst, date ) {
19921		var yearSplit, currentYear,
19922			minDate = this._getMinMaxDate( inst, "min" ),
19923			maxDate = this._getMinMaxDate( inst, "max" ),
19924			minYear = null,
19925			maxYear = null,
19926			years = this._get( inst, "yearRange" );
19927			if ( years ) {
19928				yearSplit = years.split( ":" );
19929				currentYear = new Date().getFullYear();
19930				minYear = parseInt( yearSplit[ 0 ], 10 );
19931				maxYear = parseInt( yearSplit[ 1 ], 10 );
19932				if ( yearSplit[ 0 ].match( /[+\-].*/ ) ) {
19933					minYear += currentYear;
19934				}
19935				if ( yearSplit[ 1 ].match( /[+\-].*/ ) ) {
19936					maxYear += currentYear;
19937				}
19938			}
19939
19940		return ( ( !minDate || date.getTime() >= minDate.getTime() ) &&
19941			( !maxDate || date.getTime() <= maxDate.getTime() ) &&
19942			( !minYear || date.getFullYear() >= minYear ) &&
19943			( !maxYear || date.getFullYear() <= maxYear ) );
19944	},
19945
19946	/* Provide the configuration settings for formatting/parsing. */
19947	_getFormatConfig: function( inst ) {
19948		var shortYearCutoff = this._get( inst, "shortYearCutoff" );
19949		shortYearCutoff = ( typeof shortYearCutoff !== "string" ? shortYearCutoff :
19950			new Date().getFullYear() % 100 + parseInt( shortYearCutoff, 10 ) );
19951		return { shortYearCutoff: shortYearCutoff,
19952			dayNamesShort: this._get( inst, "dayNamesShort" ), dayNames: this._get( inst, "dayNames" ),
19953			monthNamesShort: this._get( inst, "monthNamesShort" ), monthNames: this._get( inst, "monthNames" ) };
19954	},
19955
19956	/* Format the given date for display. */
19957	_formatDate: function( inst, day, month, year ) {
19958		if ( !day ) {
19959			inst.currentDay = inst.selectedDay;
19960			inst.currentMonth = inst.selectedMonth;
19961			inst.currentYear = inst.selectedYear;
19962		}
19963		var date = ( day ? ( typeof day === "object" ? day :
19964			this._daylightSavingAdjust( new Date( year, month, day ) ) ) :
19965			this._daylightSavingAdjust( new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) );
19966		return this.formatDate( this._get( inst, "dateFormat" ), date, this._getFormatConfig( inst ) );
19967	}
19968} );
19969
19970/*
19971 * Bind hover events for datepicker elements.
19972 * Done via delegate so the binding only occurs once in the lifetime of the parent div.
19973 * Global datepicker_instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
19974 */
19975function datepicker_bindHover( dpDiv ) {
19976	var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";
19977	return dpDiv.on( "mouseout", selector, function() {
19978			$( this ).removeClass( "ui-state-hover" );
19979			if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) {
19980				$( this ).removeClass( "ui-datepicker-prev-hover" );
19981			}
19982			if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) {
19983				$( this ).removeClass( "ui-datepicker-next-hover" );
19984			}
19985		} )
19986		.on( "mouseover", selector, datepicker_handleMouseover );
19987}
19988
19989function datepicker_handleMouseover() {
19990	if ( !$.datepicker._isDisabledDatepicker( datepicker_instActive.inline ? datepicker_instActive.dpDiv.parent()[ 0 ] : datepicker_instActive.input[ 0 ] ) ) {
19991		$( this ).parents( ".ui-datepicker-calendar" ).find( "a" ).removeClass( "ui-state-hover" );
19992		$( this ).addClass( "ui-state-hover" );
19993		if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) {
19994			$( this ).addClass( "ui-datepicker-prev-hover" );
19995		}
19996		if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) {
19997			$( this ).addClass( "ui-datepicker-next-hover" );
19998		}
19999	}
20000}
20001
20002/* jQuery extend now ignores nulls! */
20003function datepicker_extendRemove( target, props ) {
20004	$.extend( target, props );
20005	for ( var name in props ) {
20006		if ( props[ name ] == null ) {
20007			target[ name ] = props[ name ];
20008		}
20009	}
20010	return target;
20011}
20012
20013/* Invoke the datepicker functionality.
20014   @param  options  string - a command, optionally followed by additional parameters or
20015					Object - settings for attaching new datepicker functionality
20016   @return  jQuery object */
20017$.fn.datepicker = function( options ) {
20018
20019	/* Verify an empty collection wasn't passed - Fixes #6976 */
20020	if ( !this.length ) {
20021		return this;
20022	}
20023
20024	/* Initialise the date picker. */
20025	if ( !$.datepicker.initialized ) {
20026		$( document ).on( "mousedown", $.datepicker._checkExternalClick );
20027		$.datepicker.initialized = true;
20028	}
20029
20030	/* Append datepicker main container to body if not exist. */
20031	if ( $( "#" + $.datepicker._mainDivId ).length === 0 ) {
20032		$( "body" ).append( $.datepicker.dpDiv );
20033	}
20034
20035	var otherArgs = Array.prototype.slice.call( arguments, 1 );
20036	if ( typeof options === "string" && ( options === "isDisabled" || options === "getDate" || options === "widget" ) ) {
20037		return $.datepicker[ "_" + options + "Datepicker" ].
20038			apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) );
20039	}
20040	if ( options === "option" && arguments.length === 2 && typeof arguments[ 1 ] === "string" ) {
20041		return $.datepicker[ "_" + options + "Datepicker" ].
20042			apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) );
20043	}
20044	return this.each( function() {
20045		if ( typeof options === "string" ) {
20046			$.datepicker[ "_" + options + "Datepicker" ]
20047				.apply( $.datepicker, [ this ].concat( otherArgs ) );
20048		} else {
20049			$.datepicker._attachDatepicker( this, options );
20050		}
20051	} );
20052};
20053
20054$.datepicker = new Datepicker(); // singleton instance
20055$.datepicker.initialized = false;
20056$.datepicker.uuid = new Date().getTime();
20057$.datepicker.version = "1.14.1";
20058
20059var widgetsDatepicker = $.datepicker;
20060
20061
20062/*!
20063 * jQuery UI Mouse 1.14.1
20064 * https://jqueryui.com
20065 *
20066 * Copyright OpenJS Foundation and other contributors
20067 * Released under the MIT license.
20068 * https://jquery.org/license
20069 */
20070
20071//>>label: Mouse
20072//>>group: Widgets
20073//>>description: Abstracts mouse-based interactions to assist in creating certain widgets.
20074//>>docs: https://api.jqueryui.com/mouse/
20075
20076
20077var mouseHandled = false;
20078$( document ).on( "mouseup", function() {
20079	mouseHandled = false;
20080} );
20081
20082var widgetsMouse = $.widget( "ui.mouse", {
20083	version: "1.14.1",
20084	options: {
20085		cancel: "input, textarea, button, select, option",
20086		distance: 1,
20087		delay: 0
20088	},
20089	_mouseInit: function() {
20090		var that = this;
20091
20092		this.element
20093			.on( "mousedown." + this.widgetName, function( event ) {
20094				return that._mouseDown( event );
20095			} )
20096			.on( "click." + this.widgetName, function( event ) {
20097				if ( true === $.data( event.target, that.widgetName + ".preventClickEvent" ) ) {
20098					$.removeData( event.target, that.widgetName + ".preventClickEvent" );
20099					event.stopImmediatePropagation();
20100					return false;
20101				}
20102			} );
20103
20104		this.started = false;
20105	},
20106
20107	// TODO: make sure destroying one instance of mouse doesn't mess with
20108	// other instances of mouse
20109	_mouseDestroy: function() {
20110		this.element.off( "." + this.widgetName );
20111		if ( this._mouseMoveDelegate ) {
20112			this.document
20113				.off( "mousemove." + this.widgetName, this._mouseMoveDelegate )
20114				.off( "mouseup." + this.widgetName, this._mouseUpDelegate );
20115		}
20116	},
20117
20118	_mouseDown: function( event ) {
20119
20120		// don't let more than one widget handle mouseStart
20121		if ( mouseHandled ) {
20122			return;
20123		}
20124
20125		this._mouseMoved = false;
20126
20127		// We may have missed mouseup (out of window)
20128		if ( this._mouseStarted ) {
20129			this._mouseUp( event );
20130		}
20131
20132		this._mouseDownEvent = event;
20133
20134		var that = this,
20135			btnIsLeft = event.which === 1,
20136			elIsCancel = typeof this.options.cancel === "string" ?
20137				$( event.target ).closest( this.options.cancel ).length :
20138				false;
20139		if ( !btnIsLeft || elIsCancel || !this._mouseCapture( event ) ) {
20140			return true;
20141		}
20142
20143		this.mouseDelayMet = !this.options.delay;
20144		if ( !this.mouseDelayMet ) {
20145			this._mouseDelayTimer = setTimeout( function() {
20146				that.mouseDelayMet = true;
20147			}, this.options.delay );
20148		}
20149
20150		if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) {
20151			this._mouseStarted = ( this._mouseStart( event ) !== false );
20152			if ( !this._mouseStarted ) {
20153				event.preventDefault();
20154				return true;
20155			}
20156		}
20157
20158		// Click event may never have fired (Gecko & Opera)
20159		if ( true === $.data( event.target, this.widgetName + ".preventClickEvent" ) ) {
20160			$.removeData( event.target, this.widgetName + ".preventClickEvent" );
20161		}
20162
20163		// These delegates are required to keep context
20164		this._mouseMoveDelegate = function( event ) {
20165			return that._mouseMove( event );
20166		};
20167		this._mouseUpDelegate = function( event ) {
20168			return that._mouseUp( event );
20169		};
20170
20171		this.document
20172			.on( "mousemove." + this.widgetName, this._mouseMoveDelegate )
20173			.on( "mouseup." + this.widgetName, this._mouseUpDelegate );
20174
20175		event.preventDefault();
20176
20177		mouseHandled = true;
20178		return true;
20179	},
20180
20181	_mouseMove: function( event ) {
20182
20183		// Only check for mouseups outside the document if you've moved inside the document
20184		// at least once.
20185		if ( this._mouseMoved && !event.which ) {
20186
20187			// Support: Safari <=8 - 9
20188			// Safari sets which to 0 if you press any of the following keys
20189			// during a drag (#14461)
20190			if ( event.originalEvent.altKey || event.originalEvent.ctrlKey ||
20191					event.originalEvent.metaKey || event.originalEvent.shiftKey ) {
20192				this.ignoreMissingWhich = true;
20193			} else if ( !this.ignoreMissingWhich ) {
20194				return this._mouseUp( event );
20195			}
20196		}
20197
20198		if ( event.which || event.button ) {
20199			this._mouseMoved = true;
20200		}
20201
20202		if ( this._mouseStarted ) {
20203			this._mouseDrag( event );
20204			return event.preventDefault();
20205		}
20206
20207		if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) {
20208			this._mouseStarted =
20209				( this._mouseStart( this._mouseDownEvent, event ) !== false );
20210			if ( this._mouseStarted ) {
20211				this._mouseDrag( event );
20212			} else {
20213				this._mouseUp( event );
20214			}
20215		}
20216
20217		return !this._mouseStarted;
20218	},
20219
20220	_mouseUp: function( event ) {
20221		this.document
20222			.off( "mousemove." + this.widgetName, this._mouseMoveDelegate )
20223			.off( "mouseup." + this.widgetName, this._mouseUpDelegate );
20224
20225		if ( this._mouseStarted ) {
20226			this._mouseStarted = false;
20227
20228			if ( event.target === this._mouseDownEvent.target ) {
20229				$.data( event.target, this.widgetName + ".preventClickEvent", true );
20230			}
20231
20232			this._mouseStop( event );
20233		}
20234
20235		if ( this._mouseDelayTimer ) {
20236			clearTimeout( this._mouseDelayTimer );
20237			delete this._mouseDelayTimer;
20238		}
20239
20240		this.ignoreMissingWhich = false;
20241		mouseHandled = false;
20242		event.preventDefault();
20243	},
20244
20245	_mouseDistanceMet: function( event ) {
20246		return ( Math.max(
20247				Math.abs( this._mouseDownEvent.pageX - event.pageX ),
20248				Math.abs( this._mouseDownEvent.pageY - event.pageY )
20249			) >= this.options.distance
20250		);
20251	},
20252
20253	_mouseDelayMet: function( /* event */ ) {
20254		return this.mouseDelayMet;
20255	},
20256
20257	// These are placeholder methods, to be overriden by extending plugin
20258	_mouseStart: function( /* event */ ) {},
20259	_mouseDrag: function( /* event */ ) {},
20260	_mouseStop: function( /* event */ ) {},
20261	_mouseCapture: function( /* event */ ) {
20262		return true;
20263	}
20264} );
20265
20266
20267
20268// $.ui.plugin is deprecated. Use $.widget() extensions instead.
20269var plugin = $.ui.plugin = {
20270	add: function( module, option, set ) {
20271		var i,
20272			proto = $.ui[ module ].prototype;
20273		for ( i in set ) {
20274			proto.plugins[ i ] = proto.plugins[ i ] || [];
20275			proto.plugins[ i ].push( [ option, set[ i ] ] );
20276		}
20277	},
20278	call: function( instance, name, args, allowDisconnected ) {
20279		var i,
20280			set = instance.plugins[ name ];
20281
20282		if ( !set ) {
20283			return;
20284		}
20285
20286		if ( !allowDisconnected && ( !instance.element[ 0 ].parentNode ||
20287				instance.element[ 0 ].parentNode.nodeType === 11 ) ) {
20288			return;
20289		}
20290
20291		for ( i = 0; i < set.length; i++ ) {
20292			if ( instance.options[ set[ i ][ 0 ] ] ) {
20293				set[ i ][ 1 ].apply( instance.element, args );
20294			}
20295		}
20296	}
20297};
20298
20299
20300/*!
20301 * jQuery UI Draggable 1.14.1
20302 * https://jqueryui.com
20303 *
20304 * Copyright OpenJS Foundation and other contributors
20305 * Released under the MIT license.
20306 * https://jquery.org/license
20307 */
20308
20309//>>label: Draggable
20310//>>group: Interactions
20311//>>description: Enables dragging functionality for any element.
20312//>>docs: https://api.jqueryui.com/draggable/
20313//>>demos: https://jqueryui.com/draggable/
20314//>>css.structure: ../../themes/base/draggable.css
20315
20316
20317$.widget( "ui.draggable", $.ui.mouse, {
20318	version: "1.14.1",
20319	widgetEventPrefix: "drag",
20320	options: {
20321		addClasses: true,
20322		appendTo: "parent",
20323		axis: false,
20324		connectToSortable: false,
20325		containment: false,
20326		cursor: "auto",
20327		cursorAt: false,
20328		grid: false,
20329		handle: false,
20330		helper: "original",
20331		iframeFix: false,
20332		opacity: false,
20333		refreshPositions: false,
20334		revert: false,
20335		revertDuration: 500,
20336		scope: "default",
20337		scroll: true,
20338		scrollSensitivity: 20,
20339		scrollSpeed: 20,
20340		snap: false,
20341		snapMode: "both",
20342		snapTolerance: 20,
20343		stack: false,
20344		zIndex: false,
20345
20346		// Callbacks
20347		drag: null,
20348		start: null,
20349		stop: null
20350	},
20351	_create: function() {
20352
20353		if ( this.options.helper === "original" ) {
20354			this._setPositionRelative();
20355		}
20356		if ( this.options.addClasses ) {
20357			this._addClass( "ui-draggable" );
20358		}
20359		this._setHandleClassName();
20360
20361		this._mouseInit();
20362	},
20363
20364	_setOption: function( key, value ) {
20365		this._super( key, value );
20366		if ( key === "handle" ) {
20367			this._removeHandleClassName();
20368			this._setHandleClassName();
20369		}
20370	},
20371
20372	_destroy: function() {
20373		if ( ( this.helper || this.element ).is( ".ui-draggable-dragging" ) ) {
20374			this.destroyOnClear = true;
20375			return;
20376		}
20377		this._removeHandleClassName();
20378		this._mouseDestroy();
20379	},
20380
20381	_mouseCapture: function( event ) {
20382		var o = this.options;
20383
20384		// Among others, prevent a drag on a resizable-handle
20385		if ( this.helper || o.disabled ||
20386				$( event.target ).closest( ".ui-resizable-handle" ).length > 0 ) {
20387			return false;
20388		}
20389
20390		//Quit if we're not on a valid handle
20391		this.handle = this._getHandle( event );
20392		if ( !this.handle ) {
20393			return false;
20394		}
20395
20396		this._blurActiveElement( event );
20397
20398		this._blockFrames( o.iframeFix === true ? "iframe" : o.iframeFix );
20399
20400		return true;
20401
20402	},
20403
20404	_blockFrames: function( selector ) {
20405		this.iframeBlocks = this.document.find( selector ).map( function() {
20406			var iframe = $( this );
20407
20408			return $( "<div>" )
20409				.css( "position", "absolute" )
20410				.appendTo( iframe.parent() )
20411				.outerWidth( iframe.outerWidth() )
20412				.outerHeight( iframe.outerHeight() )
20413				.offset( iframe.offset() )[ 0 ];
20414		} );
20415	},
20416
20417	_unblockFrames: function() {
20418		if ( this.iframeBlocks ) {
20419			this.iframeBlocks.remove();
20420			delete this.iframeBlocks;
20421		}
20422	},
20423
20424	_blurActiveElement: function( event ) {
20425		var activeElement = this.document[ 0 ].activeElement,
20426			target = $( event.target );
20427
20428		// Don't blur if the event occurred on an element that is within
20429		// the currently focused element
20430		// See #10527, #12472
20431		if ( target.closest( activeElement ).length ) {
20432			return;
20433		}
20434
20435		// Blur any element that currently has focus, see #4261
20436		$( activeElement ).trigger( "blur" );
20437	},
20438
20439	_mouseStart: function( event ) {
20440
20441		var o = this.options;
20442
20443		//Create and append the visible helper
20444		this.helper = this._createHelper( event );
20445
20446		this._addClass( this.helper, "ui-draggable-dragging" );
20447
20448		//Cache the helper size
20449		this._cacheHelperProportions();
20450
20451		//If ddmanager is used for droppables, set the global draggable
20452		if ( $.ui.ddmanager ) {
20453			$.ui.ddmanager.current = this;
20454		}
20455
20456		/*
20457		 * - Position generation -
20458		 * This block generates everything position related - it's the core of draggables.
20459		 */
20460
20461		//Cache the margins of the original element
20462		this._cacheMargins();
20463
20464		//Store the helper's css position
20465		this.cssPosition = this.helper.css( "position" );
20466		this.scrollParent = this.helper.scrollParent( true );
20467		this.offsetParent = this.helper.offsetParent();
20468		this.hasFixedAncestor = this.helper.parents().filter( function() {
20469				return $( this ).css( "position" ) === "fixed";
20470			} ).length > 0;
20471
20472		//The element's absolute position on the page minus margins
20473		this.positionAbs = this.element.offset();
20474		this._refreshOffsets( event );
20475
20476		//Generate the original position
20477		this.originalPosition = this.position = this._generatePosition( event, false );
20478		this.originalPageX = event.pageX;
20479		this.originalPageY = event.pageY;
20480
20481		//Adjust the mouse offset relative to the helper if "cursorAt" is supplied
20482		if ( o.cursorAt ) {
20483			this._adjustOffsetFromHelper( o.cursorAt );
20484		}
20485
20486		//Set a containment if given in the options
20487		this._setContainment();
20488
20489		//Trigger event + callbacks
20490		if ( this._trigger( "start", event ) === false ) {
20491			this._clear();
20492			return false;
20493		}
20494
20495		//Recache the helper size
20496		this._cacheHelperProportions();
20497
20498		//Prepare the droppable offsets
20499		if ( $.ui.ddmanager && !o.dropBehaviour ) {
20500			$.ui.ddmanager.prepareOffsets( this, event );
20501		}
20502
20503		// Execute the drag once - this causes the helper not to be visible before getting its
20504		// correct position
20505		this._mouseDrag( event, true );
20506
20507		// If the ddmanager is used for droppables, inform the manager that dragging has started
20508		// (see #5003)
20509		if ( $.ui.ddmanager ) {
20510			$.ui.ddmanager.dragStart( this, event );
20511		}
20512
20513		return true;
20514	},
20515
20516	_refreshOffsets: function( event ) {
20517		this.offset = {
20518			top: this.positionAbs.top - this.margins.top,
20519			left: this.positionAbs.left - this.margins.left,
20520			scroll: false,
20521			parent: this._getParentOffset(),
20522			relative: this._getRelativeOffset()
20523		};
20524
20525		this.offset.click = {
20526			left: event.pageX - this.offset.left,
20527			top: event.pageY - this.offset.top
20528		};
20529	},
20530
20531	_mouseDrag: function( event, noPropagation ) {
20532
20533		// reset any necessary cached properties (see #5009)
20534		if ( this.hasFixedAncestor ) {
20535			this.offset.parent = this._getParentOffset();
20536		}
20537
20538		//Compute the helpers position
20539		this.position = this._generatePosition( event, true );
20540		this.positionAbs = this._convertPositionTo( "absolute" );
20541
20542		//Call plugins and callbacks and use the resulting position if something is returned
20543		if ( !noPropagation ) {
20544			var ui = this._uiHash();
20545			if ( this._trigger( "drag", event, ui ) === false ) {
20546				this._mouseUp( new $.Event( "mouseup", event ) );
20547				return false;
20548			}
20549			this.position = ui.position;
20550		}
20551
20552		this.helper[ 0 ].style.left = this.position.left + "px";
20553		this.helper[ 0 ].style.top = this.position.top + "px";
20554
20555		if ( $.ui.ddmanager ) {
20556			$.ui.ddmanager.drag( this, event );
20557		}
20558
20559		return false;
20560	},
20561
20562	_mouseStop: function( event ) {
20563
20564		//If we are using droppables, inform the manager about the drop
20565		var that = this,
20566			dropped = false;
20567		if ( $.ui.ddmanager && !this.options.dropBehaviour ) {
20568			dropped = $.ui.ddmanager.drop( this, event );
20569		}
20570
20571		//if a drop comes from outside (a sortable)
20572		if ( this.dropped ) {
20573			dropped = this.dropped;
20574			this.dropped = false;
20575		}
20576
20577		if ( ( this.options.revert === "invalid" && !dropped ) ||
20578				( this.options.revert === "valid" && dropped ) ||
20579				this.options.revert === true || ( typeof this.options.revert === "function" &&
20580				this.options.revert.call( this.element, dropped ) )
20581		) {
20582			$( this.helper ).animate(
20583				this.originalPosition,
20584				parseInt( this.options.revertDuration, 10 ),
20585				function() {
20586					if ( that._trigger( "stop", event ) !== false ) {
20587						that._clear();
20588					}
20589				}
20590			);
20591		} else {
20592			if ( this._trigger( "stop", event ) !== false ) {
20593				this._clear();
20594			}
20595		}
20596
20597		return false;
20598	},
20599
20600	_mouseUp: function( event ) {
20601		this._unblockFrames();
20602
20603		// If the ddmanager is used for droppables, inform the manager that dragging has stopped
20604		// (see #5003)
20605		if ( $.ui.ddmanager ) {
20606			$.ui.ddmanager.dragStop( this, event );
20607		}
20608
20609		// Only need to focus if the event occurred on the draggable itself, see #10527
20610		if ( this.handleElement.is( event.target ) ) {
20611
20612			// The interaction is over; whether or not the click resulted in a drag,
20613			// focus the element
20614			this.element.trigger( "focus" );
20615		}
20616
20617		return $.ui.mouse.prototype._mouseUp.call( this, event );
20618	},
20619
20620	cancel: function() {
20621
20622		if ( this.helper.is( ".ui-draggable-dragging" ) ) {
20623			this._mouseUp( new $.Event( "mouseup", { target: this.element[ 0 ] } ) );
20624		} else {
20625			this._clear();
20626		}
20627
20628		return this;
20629
20630	},
20631
20632	_getHandle: function( event ) {
20633		return this.options.handle ?
20634			!!$( event.target ).closest( this.element.find( this.options.handle ) ).length :
20635			true;
20636	},
20637
20638	_setHandleClassName: function() {
20639		this.handleElement = this.options.handle ?
20640			this.element.find( this.options.handle ) : this.element;
20641		this._addClass( this.handleElement, "ui-draggable-handle" );
20642	},
20643
20644	_removeHandleClassName: function() {
20645		this._removeClass( this.handleElement, "ui-draggable-handle" );
20646	},
20647
20648	_createHelper: function( event ) {
20649
20650		var o = this.options,
20651			helperIsFunction = typeof o.helper === "function",
20652			helper = helperIsFunction ?
20653				$( o.helper.apply( this.element[ 0 ], [ event ] ) ) :
20654				( o.helper === "clone" ?
20655					this.element.clone().removeAttr( "id" ) :
20656					this.element );
20657
20658		if ( !helper.parents( "body" ).length ) {
20659			helper.appendTo( ( o.appendTo === "parent" ?
20660				this.element[ 0 ].parentNode :
20661				o.appendTo ) );
20662		}
20663
20664		// https://bugs.jqueryui.com/ticket/9446
20665		// a helper function can return the original element
20666		// which wouldn't have been set to relative in _create
20667		if ( helperIsFunction && helper[ 0 ] === this.element[ 0 ] ) {
20668			this._setPositionRelative();
20669		}
20670
20671		if ( helper[ 0 ] !== this.element[ 0 ] &&
20672				!( /(fixed|absolute)/ ).test( helper.css( "position" ) ) ) {
20673			helper.css( "position", "absolute" );
20674		}
20675
20676		return helper;
20677
20678	},
20679
20680	_setPositionRelative: function() {
20681		if ( !( /^(?:r|a|f)/ ).test( this.element.css( "position" ) ) ) {
20682			this.element[ 0 ].style.position = "relative";
20683		}
20684	},
20685
20686	_adjustOffsetFromHelper: function( obj ) {
20687		if ( typeof obj === "string" ) {
20688			obj = obj.split( " " );
20689		}
20690		if ( Array.isArray( obj ) ) {
20691			obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 };
20692		}
20693		if ( "left" in obj ) {
20694			this.offset.click.left = obj.left + this.margins.left;
20695		}
20696		if ( "right" in obj ) {
20697			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
20698		}
20699		if ( "top" in obj ) {
20700			this.offset.click.top = obj.top + this.margins.top;
20701		}
20702		if ( "bottom" in obj ) {
20703			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
20704		}
20705	},
20706
20707	_isRootNode: function( element ) {
20708		return ( /(html|body)/i ).test( element.tagName ) || element === this.document[ 0 ];
20709	},
20710
20711	_getParentOffset: function() {
20712
20713		//Get the offsetParent and cache its position
20714		var po = this.offsetParent.offset(),
20715			document = this.document[ 0 ];
20716
20717		// This is a special case where we need to modify a offset calculated on start, since the
20718		// following happened:
20719		// 1. The position of the helper is absolute, so it's position is calculated based on the
20720		// next positioned parent
20721		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't
20722		// the document, which means that the scroll is included in the initial calculation of the
20723		// offset of the parent, and never recalculated upon drag
20724		if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== document &&
20725				$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) {
20726			po.left += this.scrollParent.scrollLeft();
20727			po.top += this.scrollParent.scrollTop();
20728		}
20729
20730		if ( this._isRootNode( this.offsetParent[ 0 ] ) ) {
20731			po = { top: 0, left: 0 };
20732		}
20733
20734		return {
20735			top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ),
20736			left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 )
20737		};
20738
20739	},
20740
20741	_getRelativeOffset: function() {
20742		if ( this.cssPosition !== "relative" ) {
20743			return { top: 0, left: 0 };
20744		}
20745
20746		var p = this.element.position(),
20747			scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
20748
20749		return {
20750			top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) +
20751				( !scrollIsRootNode ? this.scrollParent.scrollTop() : 0 ),
20752			left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) +
20753				( !scrollIsRootNode ? this.scrollParent.scrollLeft() : 0 )
20754		};
20755
20756	},
20757
20758	_cacheMargins: function() {
20759		this.margins = {
20760			left: ( parseInt( this.element.css( "marginLeft" ), 10 ) || 0 ),
20761			top: ( parseInt( this.element.css( "marginTop" ), 10 ) || 0 ),
20762			right: ( parseInt( this.element.css( "marginRight" ), 10 ) || 0 ),
20763			bottom: ( parseInt( this.element.css( "marginBottom" ), 10 ) || 0 )
20764		};
20765	},
20766
20767	_cacheHelperProportions: function() {
20768		this.helperProportions = {
20769			width: this.helper.outerWidth(),
20770			height: this.helper.outerHeight()
20771		};
20772	},
20773
20774	_setContainment: function() {
20775
20776		var isUserScrollable, c, ce,
20777			o = this.options,
20778			document = this.document[ 0 ];
20779
20780		this.relativeContainer = null;
20781
20782		if ( !o.containment ) {
20783			this.containment = null;
20784			return;
20785		}
20786
20787		if ( o.containment === "window" ) {
20788			this.containment = [
20789				$( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
20790				$( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top,
20791				$( window ).scrollLeft() + $( window ).width() -
20792					this.helperProportions.width - this.margins.left,
20793				$( window ).scrollTop() +
20794					( $( window ).height() || document.body.parentNode.scrollHeight ) -
20795					this.helperProportions.height - this.margins.top
20796			];
20797			return;
20798		}
20799
20800		if ( o.containment === "document" ) {
20801			this.containment = [
20802				0,
20803				0,
20804				$( document ).width() - this.helperProportions.width - this.margins.left,
20805				( $( document ).height() || document.body.parentNode.scrollHeight ) -
20806					this.helperProportions.height - this.margins.top
20807			];
20808			return;
20809		}
20810
20811		if ( o.containment.constructor === Array ) {
20812			this.containment = o.containment;
20813			return;
20814		}
20815
20816		if ( o.containment === "parent" ) {
20817			o.containment = this.helper[ 0 ].parentNode;
20818		}
20819
20820		c = $( o.containment );
20821		ce = c[ 0 ];
20822
20823		if ( !ce ) {
20824			return;
20825		}
20826
20827		isUserScrollable = /(scroll|auto)/.test( c.css( "overflow" ) );
20828
20829		this.containment = [
20830			( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) +
20831				( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ),
20832			( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) +
20833				( parseInt( c.css( "paddingTop" ), 10 ) || 0 ),
20834			( isUserScrollable ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -
20835				( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) -
20836				( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) -
20837				this.helperProportions.width -
20838				this.margins.left -
20839				this.margins.right,
20840			( isUserScrollable ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -
20841				( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) -
20842				( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) -
20843				this.helperProportions.height -
20844				this.margins.top -
20845				this.margins.bottom
20846		];
20847		this.relativeContainer = c;
20848	},
20849
20850	_convertPositionTo: function( d, pos ) {
20851
20852		if ( !pos ) {
20853			pos = this.position;
20854		}
20855
20856		var mod = d === "absolute" ? 1 : -1,
20857			scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
20858
20859		return {
20860			top: (
20861
20862				// The absolute mouse position
20863				pos.top	+
20864
20865				// Only for relative positioned nodes: Relative offset from element to offset parent
20866				this.offset.relative.top * mod +
20867
20868				// The offsetParent's offset without borders (offset + border)
20869				this.offset.parent.top * mod -
20870				( ( this.cssPosition === "fixed" ?
20871					-this.offset.scroll.top :
20872					( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) * mod )
20873			),
20874			left: (
20875
20876				// The absolute mouse position
20877				pos.left +
20878
20879				// Only for relative positioned nodes: Relative offset from element to offset parent
20880				this.offset.relative.left * mod +
20881
20882				// The offsetParent's offset without borders (offset + border)
20883				this.offset.parent.left * mod	-
20884				( ( this.cssPosition === "fixed" ?
20885					-this.offset.scroll.left :
20886					( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) * mod )
20887			)
20888		};
20889
20890	},
20891
20892	_generatePosition: function( event, constrainPosition ) {
20893
20894		var containment, co, top, left,
20895			o = this.options,
20896			scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ),
20897			pageX = event.pageX,
20898			pageY = event.pageY;
20899
20900		// Cache the scroll
20901		if ( !scrollIsRootNode || !this.offset.scroll ) {
20902			this.offset.scroll = {
20903				top: this.scrollParent.scrollTop(),
20904				left: this.scrollParent.scrollLeft()
20905			};
20906		}
20907
20908		/*
20909		 * - Position constraining -
20910		 * Constrain the position to a mix of grid, containment.
20911		 */
20912
20913		// If we are not dragging yet, we won't check for options
20914		if ( constrainPosition ) {
20915			if ( this.containment ) {
20916				if ( this.relativeContainer ) {
20917					co = this.relativeContainer.offset();
20918					containment = [
20919						this.containment[ 0 ] + co.left,
20920						this.containment[ 1 ] + co.top,
20921						this.containment[ 2 ] + co.left,
20922						this.containment[ 3 ] + co.top
20923					];
20924				} else {
20925					containment = this.containment;
20926				}
20927
20928				if ( event.pageX - this.offset.click.left < containment[ 0 ] ) {
20929					pageX = containment[ 0 ] + this.offset.click.left;
20930				}
20931				if ( event.pageY - this.offset.click.top < containment[ 1 ] ) {
20932					pageY = containment[ 1 ] + this.offset.click.top;
20933				}
20934				if ( event.pageX - this.offset.click.left > containment[ 2 ] ) {
20935					pageX = containment[ 2 ] + this.offset.click.left;
20936				}
20937				if ( event.pageY - this.offset.click.top > containment[ 3 ] ) {
20938					pageY = containment[ 3 ] + this.offset.click.top;
20939				}
20940			}
20941
20942			if ( o.grid ) {
20943
20944				//Check for grid elements set to 0 to prevent divide by 0 error causing invalid
20945				// argument errors in IE (see ticket #6950)
20946				top = o.grid[ 1 ] ? this.originalPageY + Math.round( ( pageY -
20947					this.originalPageY ) / o.grid[ 1 ] ) * o.grid[ 1 ] : this.originalPageY;
20948				pageY = containment ? ( ( top - this.offset.click.top >= containment[ 1 ] ||
20949					top - this.offset.click.top > containment[ 3 ] ) ?
20950						top :
20951						( ( top - this.offset.click.top >= containment[ 1 ] ) ?
20952							top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) : top;
20953
20954				left = o.grid[ 0 ] ? this.originalPageX +
20955					Math.round( ( pageX - this.originalPageX ) / o.grid[ 0 ] ) * o.grid[ 0 ] :
20956					this.originalPageX;
20957				pageX = containment ? ( ( left - this.offset.click.left >= containment[ 0 ] ||
20958					left - this.offset.click.left > containment[ 2 ] ) ?
20959						left :
20960						( ( left - this.offset.click.left >= containment[ 0 ] ) ?
20961							left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) : left;
20962			}
20963
20964			if ( o.axis === "y" ) {
20965				pageX = this.originalPageX;
20966			}
20967
20968			if ( o.axis === "x" ) {
20969				pageY = this.originalPageY;
20970			}
20971		}
20972
20973		return {
20974			top: (
20975
20976				// The absolute mouse position
20977				pageY -
20978
20979				// Click offset (relative to the element)
20980				this.offset.click.top -
20981
20982				// Only for relative positioned nodes: Relative offset from element to offset parent
20983				this.offset.relative.top -
20984
20985				// The offsetParent's offset without borders (offset + border)
20986				this.offset.parent.top +
20987				( this.cssPosition === "fixed" ?
20988					-this.offset.scroll.top :
20989					( scrollIsRootNode ? 0 : this.offset.scroll.top ) )
20990			),
20991			left: (
20992
20993				// The absolute mouse position
20994				pageX -
20995
20996				// Click offset (relative to the element)
20997				this.offset.click.left -
20998
20999				// Only for relative positioned nodes: Relative offset from element to offset parent
21000				this.offset.relative.left -
21001
21002				// The offsetParent's offset without borders (offset + border)
21003				this.offset.parent.left +
21004				( this.cssPosition === "fixed" ?
21005					-this.offset.scroll.left :
21006					( scrollIsRootNode ? 0 : this.offset.scroll.left ) )
21007			)
21008		};
21009
21010	},
21011
21012	_clear: function() {
21013		this._removeClass( this.helper, "ui-draggable-dragging" );
21014		if ( this.helper[ 0 ] !== this.element[ 0 ] && !this.cancelHelperRemoval ) {
21015			this.helper.remove();
21016		}
21017		this.helper = null;
21018		this.cancelHelperRemoval = false;
21019		if ( this.destroyOnClear ) {
21020			this.destroy();
21021		}
21022	},
21023
21024	// From now on bulk stuff - mainly helpers
21025
21026	_trigger: function( type, event, ui ) {
21027		ui = ui || this._uiHash();
21028		$.ui.plugin.call( this, type, [ event, ui, this ], true );
21029
21030		// Absolute position and offset (see #6884 ) have to be recalculated after plugins
21031		if ( /^(drag|start|stop)/.test( type ) ) {
21032			this.positionAbs = this._convertPositionTo( "absolute" );
21033			ui.offset = this.positionAbs;
21034		}
21035		return $.Widget.prototype._trigger.call( this, type, event, ui );
21036	},
21037
21038	plugins: {},
21039
21040	_uiHash: function() {
21041		return {
21042			helper: this.helper,
21043			position: this.position,
21044			originalPosition: this.originalPosition,
21045			offset: this.positionAbs
21046		};
21047	}
21048
21049} );
21050
21051$.ui.plugin.add( "draggable", "connectToSortable", {
21052	start: function( event, ui, draggable ) {
21053		var uiSortable = $.extend( {}, ui, {
21054			item: draggable.element
21055		} );
21056
21057		draggable.sortables = [];
21058		$( draggable.options.connectToSortable ).each( function() {
21059			var sortable = $( this ).sortable( "instance" );
21060
21061			if ( sortable && !sortable.options.disabled ) {
21062				draggable.sortables.push( sortable );
21063
21064				// RefreshPositions is called at drag start to refresh the containerCache
21065				// which is used in drag. This ensures it's initialized and synchronized
21066				// with any changes that might have happened on the page since initialization.
21067				sortable.refreshPositions();
21068				sortable._trigger( "activate", event, uiSortable );
21069			}
21070		} );
21071	},
21072	stop: function( event, ui, draggable ) {
21073		var uiSortable = $.extend( {}, ui, {
21074			item: draggable.element
21075		} );
21076
21077		draggable.cancelHelperRemoval = false;
21078
21079		$.each( draggable.sortables, function() {
21080			var sortable = this;
21081
21082			if ( sortable.isOver ) {
21083				sortable.isOver = 0;
21084
21085				// Allow this sortable to handle removing the helper
21086				draggable.cancelHelperRemoval = true;
21087				sortable.cancelHelperRemoval = false;
21088
21089				// Use _storedCSS To restore properties in the sortable,
21090				// as this also handles revert (#9675) since the draggable
21091				// may have modified them in unexpected ways (#8809)
21092				sortable._storedCSS = {
21093					position: sortable.placeholder.css( "position" ),
21094					top: sortable.placeholder.css( "top" ),
21095					left: sortable.placeholder.css( "left" )
21096				};
21097
21098				sortable._mouseStop( event );
21099
21100				// Once drag has ended, the sortable should return to using
21101				// its original helper, not the shared helper from draggable
21102				sortable.options.helper = sortable.options._helper;
21103			} else {
21104
21105				// Prevent this Sortable from removing the helper.
21106				// However, don't set the draggable to remove the helper
21107				// either as another connected Sortable may yet handle the removal.
21108				sortable.cancelHelperRemoval = true;
21109
21110				sortable._trigger( "deactivate", event, uiSortable );
21111			}
21112		} );
21113	},
21114	drag: function( event, ui, draggable ) {
21115		$.each( draggable.sortables, function() {
21116			var innermostIntersecting = false,
21117				sortable = this;
21118
21119			// Copy over variables that sortable's _intersectsWith uses
21120			sortable.positionAbs = draggable.positionAbs;
21121			sortable.helperProportions = draggable.helperProportions;
21122			sortable.offset.click = draggable.offset.click;
21123
21124			if ( sortable._intersectsWith( sortable.containerCache ) ) {
21125				innermostIntersecting = true;
21126
21127				$.each( draggable.sortables, function() {
21128
21129					// Copy over variables that sortable's _intersectsWith uses
21130					this.positionAbs = draggable.positionAbs;
21131					this.helperProportions = draggable.helperProportions;
21132					this.offset.click = draggable.offset.click;
21133
21134					if ( this !== sortable &&
21135							this._intersectsWith( this.containerCache ) &&
21136							$.contains( sortable.element[ 0 ], this.element[ 0 ] ) ) {
21137						innermostIntersecting = false;
21138					}
21139
21140					return innermostIntersecting;
21141				} );
21142			}
21143
21144			if ( innermostIntersecting ) {
21145
21146				// If it intersects, we use a little isOver variable and set it once,
21147				// so that the move-in stuff gets fired only once.
21148				if ( !sortable.isOver ) {
21149					sortable.isOver = 1;
21150
21151					// Store draggable's parent in case we need to reappend to it later.
21152					draggable._parent = ui.helper.parent();
21153
21154					sortable.currentItem = ui.helper
21155						.appendTo( sortable.element )
21156						.data( "ui-sortable-item", true );
21157
21158					// Store helper option to later restore it
21159					sortable.options._helper = sortable.options.helper;
21160
21161					sortable.options.helper = function() {
21162						return ui.helper[ 0 ];
21163					};
21164
21165					// Fire the start events of the sortable with our passed browser event,
21166					// and our own helper (so it doesn't create a new one)
21167					event.target = sortable.currentItem[ 0 ];
21168					sortable._mouseCapture( event, true );
21169					sortable._mouseStart( event, true, true );
21170
21171					// Because the browser event is way off the new appended portlet,
21172					// modify necessary variables to reflect the changes
21173					sortable.offset.click.top = draggable.offset.click.top;
21174					sortable.offset.click.left = draggable.offset.click.left;
21175					sortable.offset.parent.left -= draggable.offset.parent.left -
21176						sortable.offset.parent.left;
21177					sortable.offset.parent.top -= draggable.offset.parent.top -
21178						sortable.offset.parent.top;
21179
21180					draggable._trigger( "toSortable", event );
21181
21182					// Inform draggable that the helper is in a valid drop zone,
21183					// used solely in the revert option to handle "valid/invalid".
21184					draggable.dropped = sortable.element;
21185
21186					// Need to refreshPositions of all sortables in the case that
21187					// adding to one sortable changes the location of the other sortables (#9675)
21188					$.each( draggable.sortables, function() {
21189						this.refreshPositions();
21190					} );
21191
21192					// Hack so receive/update callbacks work (mostly)
21193					draggable.currentItem = draggable.element;
21194					sortable.fromOutside = draggable;
21195				}
21196
21197				if ( sortable.currentItem ) {
21198					sortable._mouseDrag( event );
21199
21200					// Copy the sortable's position because the draggable's can potentially reflect
21201					// a relative position, while sortable is always absolute, which the dragged
21202					// element has now become. (#8809)
21203					ui.position = sortable.position;
21204				}
21205			} else {
21206
21207				// If it doesn't intersect with the sortable, and it intersected before,
21208				// we fake the drag stop of the sortable, but make sure it doesn't remove
21209				// the helper by using cancelHelperRemoval.
21210				if ( sortable.isOver ) {
21211
21212					sortable.isOver = 0;
21213					sortable.cancelHelperRemoval = true;
21214
21215					// Calling sortable's mouseStop would trigger a revert,
21216					// so revert must be temporarily false until after mouseStop is called.
21217					sortable.options._revert = sortable.options.revert;
21218					sortable.options.revert = false;
21219
21220					sortable._trigger( "out", event, sortable._uiHash( sortable ) );
21221					sortable._mouseStop( event, true );
21222
21223					// Restore sortable behaviors that were modfied
21224					// when the draggable entered the sortable area (#9481)
21225					sortable.options.revert = sortable.options._revert;
21226					sortable.options.helper = sortable.options._helper;
21227
21228					if ( sortable.placeholder ) {
21229						sortable.placeholder.remove();
21230					}
21231
21232					// Restore and recalculate the draggable's offset considering the sortable
21233					// may have modified them in unexpected ways. (#8809, #10669)
21234					ui.helper.appendTo( draggable._parent );
21235					draggable._refreshOffsets( event );
21236					ui.position = draggable._generatePosition( event, true );
21237
21238					draggable._trigger( "fromSortable", event );
21239
21240					// Inform draggable that the helper is no longer in a valid drop zone
21241					draggable.dropped = false;
21242
21243					// Need to refreshPositions of all sortables just in case removing
21244					// from one sortable changes the location of other sortables (#9675)
21245					$.each( draggable.sortables, function() {
21246						this.refreshPositions();
21247					} );
21248				}
21249			}
21250		} );
21251	}
21252} );
21253
21254$.ui.plugin.add( "draggable", "cursor", {
21255	start: function( event, ui, instance ) {
21256		var t = $( "body" ),
21257			o = instance.options;
21258
21259		if ( t.css( "cursor" ) ) {
21260			o._cursor = t.css( "cursor" );
21261		}
21262		t.css( "cursor", o.cursor );
21263	},
21264	stop: function( event, ui, instance ) {
21265		var o = instance.options;
21266		if ( o._cursor ) {
21267			$( "body" ).css( "cursor", o._cursor );
21268		}
21269	}
21270} );
21271
21272$.ui.plugin.add( "draggable", "opacity", {
21273	start: function( event, ui, instance ) {
21274		var t = $( ui.helper ),
21275			o = instance.options;
21276		if ( t.css( "opacity" ) ) {
21277			o._opacity = t.css( "opacity" );
21278		}
21279		t.css( "opacity", o.opacity );
21280	},
21281	stop: function( event, ui, instance ) {
21282		var o = instance.options;
21283		if ( o._opacity ) {
21284			$( ui.helper ).css( "opacity", o._opacity );
21285		}
21286	}
21287} );
21288
21289$.ui.plugin.add( "draggable", "scroll", {
21290	start: function( event, ui, i ) {
21291		if ( !i.scrollParentNotHidden ) {
21292			i.scrollParentNotHidden = i.helper.scrollParent( false );
21293		}
21294
21295		if ( i.scrollParentNotHidden[ 0 ] !== i.document[ 0 ] &&
21296				i.scrollParentNotHidden[ 0 ].tagName !== "HTML" ) {
21297			i.overflowOffset = i.scrollParentNotHidden.offset();
21298		}
21299	},
21300	drag: function( event, ui, i  ) {
21301
21302		var o = i.options,
21303			scrolled = false,
21304			scrollParent = i.scrollParentNotHidden[ 0 ],
21305			document = i.document[ 0 ];
21306
21307		if ( scrollParent !== document && scrollParent.tagName !== "HTML" ) {
21308			if ( !o.axis || o.axis !== "x" ) {
21309				if ( ( i.overflowOffset.top + scrollParent.offsetHeight ) - event.pageY <
21310						o.scrollSensitivity ) {
21311					scrollParent.scrollTop = scrolled = scrollParent.scrollTop + o.scrollSpeed;
21312				} else if ( event.pageY - i.overflowOffset.top < o.scrollSensitivity ) {
21313					scrollParent.scrollTop = scrolled = scrollParent.scrollTop - o.scrollSpeed;
21314				}
21315			}
21316
21317			if ( !o.axis || o.axis !== "y" ) {
21318				if ( ( i.overflowOffset.left + scrollParent.offsetWidth ) - event.pageX <
21319						o.scrollSensitivity ) {
21320					scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft + o.scrollSpeed;
21321				} else if ( event.pageX - i.overflowOffset.left < o.scrollSensitivity ) {
21322					scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft - o.scrollSpeed;
21323				}
21324			}
21325
21326		} else {
21327
21328			if ( !o.axis || o.axis !== "x" ) {
21329				if ( event.pageY - $( document ).scrollTop() < o.scrollSensitivity ) {
21330					scrolled = $( document ).scrollTop( $( document ).scrollTop() - o.scrollSpeed );
21331				} else if ( $( window ).height() - ( event.pageY - $( document ).scrollTop() ) <
21332						o.scrollSensitivity ) {
21333					scrolled = $( document ).scrollTop( $( document ).scrollTop() + o.scrollSpeed );
21334				}
21335			}
21336
21337			if ( !o.axis || o.axis !== "y" ) {
21338				if ( event.pageX - $( document ).scrollLeft() < o.scrollSensitivity ) {
21339					scrolled = $( document ).scrollLeft(
21340						$( document ).scrollLeft() - o.scrollSpeed
21341					);
21342				} else if ( $( window ).width() - ( event.pageX - $( document ).scrollLeft() ) <
21343						o.scrollSensitivity ) {
21344					scrolled = $( document ).scrollLeft(
21345						$( document ).scrollLeft() + o.scrollSpeed
21346					);
21347				}
21348			}
21349
21350		}
21351
21352		if ( scrolled !== false && $.ui.ddmanager && !o.dropBehaviour ) {
21353			$.ui.ddmanager.prepareOffsets( i, event );
21354		}
21355
21356	}
21357} );
21358
21359$.ui.plugin.add( "draggable", "snap", {
21360	start: function( event, ui, i ) {
21361
21362		var o = i.options;
21363
21364		i.snapElements = [];
21365
21366		$( o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap )
21367			.each( function() {
21368				var $t = $( this ),
21369					$o = $t.offset();
21370				if ( this !== i.element[ 0 ] ) {
21371					i.snapElements.push( {
21372						item: this,
21373						width: $t.outerWidth(), height: $t.outerHeight(),
21374						top: $o.top, left: $o.left
21375					} );
21376				}
21377			} );
21378
21379	},
21380	drag: function( event, ui, inst ) {
21381
21382		var ts, bs, ls, rs, l, r, t, b, i, first,
21383			o = inst.options,
21384			d = o.snapTolerance,
21385			x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
21386			y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
21387
21388		for ( i = inst.snapElements.length - 1; i >= 0; i-- ) {
21389
21390			l = inst.snapElements[ i ].left - inst.margins.left;
21391			r = l + inst.snapElements[ i ].width;
21392			t = inst.snapElements[ i ].top - inst.margins.top;
21393			b = t + inst.snapElements[ i ].height;
21394
21395			if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d ||
21396					!$.contains( inst.snapElements[ i ].item.ownerDocument,
21397					inst.snapElements[ i ].item ) ) {
21398				if ( inst.snapElements[ i ].snapping ) {
21399					if ( inst.options.snap.release ) {
21400						inst.options.snap.release.call(
21401							inst.element,
21402							event,
21403							$.extend( inst._uiHash(), { snapItem: inst.snapElements[ i ].item } )
21404						);
21405					}
21406				}
21407				inst.snapElements[ i ].snapping = false;
21408				continue;
21409			}
21410
21411			if ( o.snapMode !== "inner" ) {
21412				ts = Math.abs( t - y2 ) <= d;
21413				bs = Math.abs( b - y1 ) <= d;
21414				ls = Math.abs( l - x2 ) <= d;
21415				rs = Math.abs( r - x1 ) <= d;
21416				if ( ts ) {
21417					ui.position.top = inst._convertPositionTo( "relative", {
21418						top: t - inst.helperProportions.height,
21419						left: 0
21420					} ).top;
21421				}
21422				if ( bs ) {
21423					ui.position.top = inst._convertPositionTo( "relative", {
21424						top: b,
21425						left: 0
21426					} ).top;
21427				}
21428				if ( ls ) {
21429					ui.position.left = inst._convertPositionTo( "relative", {
21430						top: 0,
21431						left: l - inst.helperProportions.width
21432					} ).left;
21433				}
21434				if ( rs ) {
21435					ui.position.left = inst._convertPositionTo( "relative", {
21436						top: 0,
21437						left: r
21438					} ).left;
21439				}
21440			}
21441
21442			first = ( ts || bs || ls || rs );
21443
21444			if ( o.snapMode !== "outer" ) {
21445				ts = Math.abs( t - y1 ) <= d;
21446				bs = Math.abs( b - y2 ) <= d;
21447				ls = Math.abs( l - x1 ) <= d;
21448				rs = Math.abs( r - x2 ) <= d;
21449				if ( ts ) {
21450					ui.position.top = inst._convertPositionTo( "relative", {
21451						top: t,
21452						left: 0
21453					} ).top;
21454				}
21455				if ( bs ) {
21456					ui.position.top = inst._convertPositionTo( "relative", {
21457						top: b - inst.helperProportions.height,
21458						left: 0
21459					} ).top;
21460				}
21461				if ( ls ) {
21462					ui.position.left = inst._convertPositionTo( "relative", {
21463						top: 0,
21464						left: l
21465					} ).left;
21466				}
21467				if ( rs ) {
21468					ui.position.left = inst._convertPositionTo( "relative", {
21469						top: 0,
21470						left: r - inst.helperProportions.width
21471					} ).left;
21472				}
21473			}
21474
21475			if ( !inst.snapElements[ i ].snapping && ( ts || bs || ls || rs || first ) ) {
21476				if ( inst.options.snap.snap ) {
21477					inst.options.snap.snap.call(
21478						inst.element,
21479						event,
21480						$.extend( inst._uiHash(), {
21481							snapItem: inst.snapElements[ i ].item
21482						} ) );
21483				}
21484			}
21485			inst.snapElements[ i ].snapping = ( ts || bs || ls || rs || first );
21486
21487		}
21488
21489	}
21490} );
21491
21492$.ui.plugin.add( "draggable", "stack", {
21493	start: function( event, ui, instance ) {
21494		var min,
21495			o = instance.options,
21496			group = $.makeArray( $( o.stack ) ).sort( function( a, b ) {
21497				return ( parseInt( $( a ).css( "zIndex" ), 10 ) || 0 ) -
21498					( parseInt( $( b ).css( "zIndex" ), 10 ) || 0 );
21499			} );
21500
21501		if ( !group.length ) {
21502			return;
21503		}
21504
21505		min = parseInt( $( group[ 0 ] ).css( "zIndex" ), 10 ) || 0;
21506		$( group ).each( function( i ) {
21507			$( this ).css( "zIndex", min + i );
21508		} );
21509		this.css( "zIndex", ( min + group.length ) );
21510	}
21511} );
21512
21513$.ui.plugin.add( "draggable", "zIndex", {
21514	start: function( event, ui, instance ) {
21515		var t = $( ui.helper ),
21516			o = instance.options;
21517
21518		if ( t.css( "zIndex" ) ) {
21519			o._zIndex = t.css( "zIndex" );
21520		}
21521		t.css( "zIndex", o.zIndex );
21522	},
21523	stop: function( event, ui, instance ) {
21524		var o = instance.options;
21525
21526		if ( o._zIndex ) {
21527			$( ui.helper ).css( "zIndex", o._zIndex );
21528		}
21529	}
21530} );
21531
21532var widgetsDraggable = $.ui.draggable;
21533
21534
21535/*!
21536 * jQuery UI Resizable 1.14.1
21537 * https://jqueryui.com
21538 *
21539 * Copyright OpenJS Foundation and other contributors
21540 * Released under the MIT license.
21541 * https://jquery.org/license
21542 */
21543
21544//>>label: Resizable
21545//>>group: Interactions
21546//>>description: Enables resize functionality for any element.
21547//>>docs: https://api.jqueryui.com/resizable/
21548//>>demos: https://jqueryui.com/resizable/
21549//>>css.structure: ../../themes/base/core.css
21550//>>css.structure: ../../themes/base/resizable.css
21551//>>css.theme: ../../themes/base/theme.css
21552
21553
21554$.widget( "ui.resizable", $.ui.mouse, {
21555	version: "1.14.1",
21556	widgetEventPrefix: "resize",
21557	options: {
21558		alsoResize: false,
21559		animate: false,
21560		animateDuration: "slow",
21561		animateEasing: "swing",
21562		aspectRatio: false,
21563		autoHide: false,
21564		classes: {
21565			"ui-resizable-se": "ui-icon ui-icon-gripsmall-diagonal-se"
21566		},
21567		containment: false,
21568		ghost: false,
21569		grid: false,
21570		handles: "e,s,se",
21571		helper: false,
21572		maxHeight: null,
21573		maxWidth: null,
21574		minHeight: 10,
21575		minWidth: 10,
21576
21577		// See #7960
21578		zIndex: 90,
21579
21580		// Callbacks
21581		resize: null,
21582		start: null,
21583		stop: null
21584	},
21585
21586	_num: function( value ) {
21587		return parseFloat( value ) || 0;
21588	},
21589
21590	_isNumber: function( value ) {
21591		return !isNaN( parseFloat( value ) );
21592	},
21593
21594	_hasScroll: function( el, a ) {
21595
21596		var scroll,
21597			has = false,
21598			overflow = $( el ).css( "overflow" );
21599
21600		if ( overflow === "hidden" ) {
21601			return false;
21602		}
21603		if ( overflow === "scroll" ) {
21604			return true;
21605		}
21606
21607		scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop";
21608
21609		if ( el[ scroll ] > 0 ) {
21610			return true;
21611		}
21612
21613		// TODO: determine which cases actually cause this to happen
21614		// if the element doesn't have the scroll set, see if it's possible to
21615		// set the scroll
21616		try {
21617			el[ scroll ] = 1;
21618			has = ( el[ scroll ] > 0 );
21619			el[ scroll ] = 0;
21620		} catch ( e ) {
21621
21622			// `el` might be a string, then setting `scroll` will throw
21623			// an error in strict mode; ignore it.
21624		}
21625		return has;
21626	},
21627
21628	_create: function() {
21629
21630		var margins,
21631			o = this.options,
21632			that = this;
21633		this._addClass( "ui-resizable" );
21634
21635		$.extend( this, {
21636			_aspectRatio: !!( o.aspectRatio ),
21637			aspectRatio: o.aspectRatio,
21638			originalElement: this.element,
21639			_proportionallyResizeElements: [],
21640			_helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null
21641		} );
21642
21643		// Wrap the element if it cannot hold child nodes
21644		if ( this.element[ 0 ].nodeName.match( /^(canvas|textarea|input|select|button|img)$/i ) ) {
21645
21646			this.element.wrap(
21647				$( "<div class='ui-wrapper'></div>" ).css( {
21648					overflow: "hidden",
21649					position: this.element.css( "position" ),
21650					width: this.element.outerWidth(),
21651					height: this.element.outerHeight(),
21652					top: this.element.css( "top" ),
21653					left: this.element.css( "left" )
21654				} )
21655			);
21656
21657			this.element = this.element.parent().data(
21658				"ui-resizable", this.element.resizable( "instance" )
21659			);
21660
21661			this.elementIsWrapper = true;
21662
21663			margins = {
21664				marginTop: this.originalElement.css( "marginTop" ),
21665				marginRight: this.originalElement.css( "marginRight" ),
21666				marginBottom: this.originalElement.css( "marginBottom" ),
21667				marginLeft: this.originalElement.css( "marginLeft" )
21668			};
21669
21670			this.element.css( margins );
21671
21672			// Support: Safari
21673			// Prevent Safari textarea resize
21674			this.originalResizeStyle = this.originalElement.css( "resize" );
21675			this.originalElement.css( "resize", "none" );
21676
21677			this._proportionallyResizeElements.push( this.originalElement.css( {
21678				position: "static",
21679				zoom: 1,
21680				display: "block"
21681			} ) );
21682
21683			this._proportionallyResize();
21684		}
21685
21686		this._setupHandles();
21687
21688		if ( o.autoHide ) {
21689			$( this.element )
21690				.on( "mouseenter", function() {
21691					if ( o.disabled ) {
21692						return;
21693					}
21694					that._removeClass( "ui-resizable-autohide" );
21695					that._handles.show();
21696				} )
21697				.on( "mouseleave", function() {
21698					if ( o.disabled ) {
21699						return;
21700					}
21701					if ( !that.resizing ) {
21702						that._addClass( "ui-resizable-autohide" );
21703						that._handles.hide();
21704					}
21705				} );
21706		}
21707
21708		this._mouseInit();
21709	},
21710
21711	_destroy: function() {
21712
21713		this._mouseDestroy();
21714		this._addedHandles.remove();
21715
21716		var wrapper,
21717			_destroy = function( exp ) {
21718				$( exp )
21719					.removeData( "resizable" )
21720					.removeData( "ui-resizable" )
21721					.off( ".resizable" );
21722			};
21723
21724		// TODO: Unwrap at same DOM position
21725		if ( this.elementIsWrapper ) {
21726			_destroy( this.element );
21727			wrapper = this.element;
21728			this.originalElement.css( {
21729				position: wrapper.css( "position" ),
21730				width: wrapper.outerWidth(),
21731				height: wrapper.outerHeight(),
21732				top: wrapper.css( "top" ),
21733				left: wrapper.css( "left" )
21734			} ).insertAfter( wrapper );
21735			wrapper.remove();
21736		}
21737
21738		this.originalElement.css( "resize", this.originalResizeStyle );
21739		_destroy( this.originalElement );
21740
21741		return this;
21742	},
21743
21744	_setOption: function( key, value ) {
21745		this._super( key, value );
21746
21747		switch ( key ) {
21748		case "handles":
21749			this._removeHandles();
21750			this._setupHandles();
21751			break;
21752		case "aspectRatio":
21753			this._aspectRatio = !!value;
21754			break;
21755		default:
21756			break;
21757		}
21758	},
21759
21760	_setupHandles: function() {
21761		var o = this.options, handle, i, n, hname, axis, that = this;
21762		this.handles = o.handles ||
21763			( !$( ".ui-resizable-handle", this.element ).length ?
21764				"e,s,se" : {
21765					n: ".ui-resizable-n",
21766					e: ".ui-resizable-e",
21767					s: ".ui-resizable-s",
21768					w: ".ui-resizable-w",
21769					se: ".ui-resizable-se",
21770					sw: ".ui-resizable-sw",
21771					ne: ".ui-resizable-ne",
21772					nw: ".ui-resizable-nw"
21773				} );
21774
21775		this._handles = $();
21776		this._addedHandles = $();
21777		if ( this.handles.constructor === String ) {
21778
21779			if ( this.handles === "all" ) {
21780				this.handles = "n,e,s,w,se,sw,ne,nw";
21781			}
21782
21783			n = this.handles.split( "," );
21784			this.handles = {};
21785
21786			for ( i = 0; i < n.length; i++ ) {
21787
21788				handle = String.prototype.trim.call( n[ i ] );
21789				hname = "ui-resizable-" + handle;
21790				axis = $( "<div>" );
21791				this._addClass( axis, "ui-resizable-handle " + hname );
21792
21793				axis.css( { zIndex: o.zIndex } );
21794
21795				this.handles[ handle ] = ".ui-resizable-" + handle;
21796				if ( !this.element.children( this.handles[ handle ] ).length ) {
21797					this.element.append( axis );
21798					this._addedHandles = this._addedHandles.add( axis );
21799				}
21800			}
21801
21802		}
21803
21804		this._renderAxis = function( target ) {
21805
21806			var i, axis, padPos, padWrapper;
21807
21808			target = target || this.element;
21809
21810			for ( i in this.handles ) {
21811
21812				if ( this.handles[ i ].constructor === String ) {
21813					this.handles[ i ] = this.element.children( this.handles[ i ] ).first().show();
21814				} else if ( this.handles[ i ].jquery || this.handles[ i ].nodeType ) {
21815					this.handles[ i ] = $( this.handles[ i ] );
21816					this._on( this.handles[ i ], { "mousedown": that._mouseDown } );
21817				}
21818
21819				if ( this.elementIsWrapper &&
21820						this.originalElement[ 0 ]
21821							.nodeName
21822							.match( /^(textarea|input|select|button)$/i ) ) {
21823					axis = $( this.handles[ i ], this.element );
21824
21825					padWrapper = /sw|ne|nw|se|n|s/.test( i ) ?
21826						axis.outerHeight() :
21827						axis.outerWidth();
21828
21829					padPos = [ "padding",
21830						/ne|nw|n/.test( i ) ? "Top" :
21831						/se|sw|s/.test( i ) ? "Bottom" :
21832						/^e$/.test( i ) ? "Right" : "Left" ].join( "" );
21833
21834					target.css( padPos, padWrapper );
21835
21836					this._proportionallyResize();
21837				}
21838
21839				this._handles = this._handles.add( this.handles[ i ] );
21840			}
21841		};
21842
21843		// TODO: make renderAxis a prototype function
21844		this._renderAxis( this.element );
21845
21846		this._handles = this._handles.add( this.element.find( ".ui-resizable-handle" ) );
21847		this._handles.disableSelection();
21848
21849		this._handles.on( "mouseover", function() {
21850			if ( !that.resizing ) {
21851				if ( this.className ) {
21852					axis = this.className.match( /ui-resizable-(se|sw|ne|nw|n|e|s|w)/i );
21853				}
21854				that.axis = axis && axis[ 1 ] ? axis[ 1 ] : "se";
21855			}
21856		} );
21857
21858		if ( o.autoHide ) {
21859			this._handles.hide();
21860			this._addClass( "ui-resizable-autohide" );
21861		}
21862	},
21863
21864	_removeHandles: function() {
21865		this._addedHandles.remove();
21866	},
21867
21868	_mouseCapture: function( event ) {
21869		var i, handle,
21870			capture = false;
21871
21872		for ( i in this.handles ) {
21873			handle = $( this.handles[ i ] )[ 0 ];
21874			if ( handle === event.target || $.contains( handle, event.target ) ) {
21875				capture = true;
21876			}
21877		}
21878
21879		return !this.options.disabled && capture;
21880	},
21881
21882	_mouseStart: function( event ) {
21883
21884		var curleft, curtop, cursor, calculatedSize,
21885			o = this.options,
21886			el = this.element;
21887
21888		this.resizing = true;
21889
21890		this._renderProxy();
21891
21892		curleft = this._num( this.helper.css( "left" ) );
21893		curtop = this._num( this.helper.css( "top" ) );
21894
21895		if ( o.containment ) {
21896			curleft += $( o.containment ).scrollLeft() || 0;
21897			curtop += $( o.containment ).scrollTop() || 0;
21898		}
21899
21900		this.offset = this.helper.offset();
21901		this.position = { left: curleft, top: curtop };
21902
21903		if ( !this._helper ) {
21904			calculatedSize = this._calculateAdjustedElementDimensions( el );
21905		}
21906
21907		this.size = this._helper ? {
21908				width: this.helper.width(),
21909				height: this.helper.height()
21910			} : {
21911				width: calculatedSize.width,
21912				height: calculatedSize.height
21913			};
21914
21915		this.originalSize = this._helper ? {
21916				width: el.outerWidth(),
21917				height: el.outerHeight()
21918			} : {
21919				width: calculatedSize.width,
21920				height: calculatedSize.height
21921			};
21922
21923		this.sizeDiff = {
21924			width: el.outerWidth() - el.width(),
21925			height: el.outerHeight() - el.height()
21926		};
21927
21928		this.originalPosition = { left: curleft, top: curtop };
21929		this.originalMousePosition = { left: event.pageX, top: event.pageY };
21930
21931		this.aspectRatio = ( typeof o.aspectRatio === "number" ) ?
21932			o.aspectRatio :
21933			( ( this.originalSize.width / this.originalSize.height ) || 1 );
21934
21935		cursor = $( ".ui-resizable-" + this.axis ).css( "cursor" );
21936		$( "body" ).css( "cursor", cursor === "auto" ? this.axis + "-resize" : cursor );
21937
21938		this._addClass( "ui-resizable-resizing" );
21939		this._propagate( "start", event );
21940		return true;
21941	},
21942
21943	_mouseDrag: function( event ) {
21944
21945		var data, props,
21946			smp = this.originalMousePosition,
21947			a = this.axis,
21948			dx = ( event.pageX - smp.left ) || 0,
21949			dy = ( event.pageY - smp.top ) || 0,
21950			trigger = this._change[ a ];
21951
21952		this._updatePrevProperties();
21953
21954		if ( !trigger ) {
21955			return false;
21956		}
21957
21958		data = trigger.apply( this, [ event, dx, dy ] );
21959
21960		this._updateVirtualBoundaries( event.shiftKey );
21961		if ( this._aspectRatio || event.shiftKey ) {
21962			data = this._updateRatio( data, event );
21963		}
21964
21965		data = this._respectSize( data, event );
21966
21967		this._updateCache( data );
21968
21969		this._propagate( "resize", event );
21970
21971		props = this._applyChanges();
21972
21973		if ( !this._helper && this._proportionallyResizeElements.length ) {
21974			this._proportionallyResize();
21975		}
21976
21977		if ( !$.isEmptyObject( props ) ) {
21978			this._updatePrevProperties();
21979			this._trigger( "resize", event, this.ui() );
21980			this._applyChanges();
21981		}
21982
21983		return false;
21984	},
21985
21986	_mouseStop: function( event ) {
21987
21988		this.resizing = false;
21989		var pr, ista, soffseth, soffsetw, s, left, top,
21990			o = this.options, that = this;
21991
21992		if ( this._helper ) {
21993
21994			pr = this._proportionallyResizeElements;
21995			ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName );
21996			soffseth = ista && this._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height;
21997			soffsetw = ista ? 0 : that.sizeDiff.width;
21998
21999			s = {
22000				width: ( that.helper.width()  - soffsetw ),
22001				height: ( that.helper.height() - soffseth )
22002			};
22003			left = ( parseFloat( that.element.css( "left" ) ) +
22004				( that.position.left - that.originalPosition.left ) ) || null;
22005			top = ( parseFloat( that.element.css( "top" ) ) +
22006				( that.position.top - that.originalPosition.top ) ) || null;
22007
22008			if ( !o.animate ) {
22009				this.element.css( $.extend( s, { top: top, left: left } ) );
22010			}
22011
22012			that.helper.height( that.size.height );
22013			that.helper.width( that.size.width );
22014
22015			if ( this._helper && !o.animate ) {
22016				this._proportionallyResize();
22017			}
22018		}
22019
22020		$( "body" ).css( "cursor", "auto" );
22021
22022		this._removeClass( "ui-resizable-resizing" );
22023
22024		this._propagate( "stop", event );
22025
22026		if ( this._helper ) {
22027			this.helper.remove();
22028		}
22029
22030		return false;
22031
22032	},
22033
22034	_updatePrevProperties: function() {
22035		this.prevPosition = {
22036			top: this.position.top,
22037			left: this.position.left
22038		};
22039		this.prevSize = {
22040			width: this.size.width,
22041			height: this.size.height
22042		};
22043	},
22044
22045	_applyChanges: function() {
22046		var props = {};
22047
22048		if ( this.position.top !== this.prevPosition.top ) {
22049			props.top = this.position.top + "px";
22050		}
22051		if ( this.position.left !== this.prevPosition.left ) {
22052			props.left = this.position.left + "px";
22053		}
22054
22055		this.helper.css( props );
22056
22057		if ( this.size.width !== this.prevSize.width ) {
22058			props.width = this.size.width + "px";
22059			this.helper.width( props.width );
22060		}
22061		if ( this.size.height !== this.prevSize.height ) {
22062			props.height = this.size.height + "px";
22063			this.helper.height( props.height );
22064		}
22065
22066		return props;
22067	},
22068
22069	_updateVirtualBoundaries: function( forceAspectRatio ) {
22070		var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b,
22071			o = this.options;
22072
22073		b = {
22074			minWidth: this._isNumber( o.minWidth ) ? o.minWidth : 0,
22075			maxWidth: this._isNumber( o.maxWidth ) ? o.maxWidth : Infinity,
22076			minHeight: this._isNumber( o.minHeight ) ? o.minHeight : 0,
22077			maxHeight: this._isNumber( o.maxHeight ) ? o.maxHeight : Infinity
22078		};
22079
22080		if ( this._aspectRatio || forceAspectRatio ) {
22081			pMinWidth = b.minHeight * this.aspectRatio;
22082			pMinHeight = b.minWidth / this.aspectRatio;
22083			pMaxWidth = b.maxHeight * this.aspectRatio;
22084			pMaxHeight = b.maxWidth / this.aspectRatio;
22085
22086			if ( pMinWidth > b.minWidth ) {
22087				b.minWidth = pMinWidth;
22088			}
22089			if ( pMinHeight > b.minHeight ) {
22090				b.minHeight = pMinHeight;
22091			}
22092			if ( pMaxWidth < b.maxWidth ) {
22093				b.maxWidth = pMaxWidth;
22094			}
22095			if ( pMaxHeight < b.maxHeight ) {
22096				b.maxHeight = pMaxHeight;
22097			}
22098		}
22099		this._vBoundaries = b;
22100	},
22101
22102	_updateCache: function( data ) {
22103		this.offset = this.helper.offset();
22104		if ( this._isNumber( data.left ) ) {
22105			this.position.left = data.left;
22106		}
22107		if ( this._isNumber( data.top ) ) {
22108			this.position.top = data.top;
22109		}
22110		if ( this._isNumber( data.height ) ) {
22111			this.size.height = data.height;
22112		}
22113		if ( this._isNumber( data.width ) ) {
22114			this.size.width = data.width;
22115		}
22116	},
22117
22118	_updateRatio: function( data ) {
22119
22120		var cpos = this.position,
22121			csize = this.size,
22122			a = this.axis;
22123
22124		if ( this._isNumber( data.height ) ) {
22125			data.width = ( data.height * this.aspectRatio );
22126		} else if ( this._isNumber( data.width ) ) {
22127			data.height = ( data.width / this.aspectRatio );
22128		}
22129
22130		if ( a === "sw" ) {
22131			data.left = cpos.left + ( csize.width - data.width );
22132			data.top = null;
22133		}
22134		if ( a === "nw" ) {
22135			data.top = cpos.top + ( csize.height - data.height );
22136			data.left = cpos.left + ( csize.width - data.width );
22137		}
22138
22139		return data;
22140	},
22141
22142	_respectSize: function( data ) {
22143
22144		var o = this._vBoundaries,
22145			a = this.axis,
22146			ismaxw = this._isNumber( data.width ) && o.maxWidth && ( o.maxWidth < data.width ),
22147			ismaxh = this._isNumber( data.height ) && o.maxHeight && ( o.maxHeight < data.height ),
22148			isminw = this._isNumber( data.width ) && o.minWidth && ( o.minWidth > data.width ),
22149			isminh = this._isNumber( data.height ) && o.minHeight && ( o.minHeight > data.height ),
22150			dw = this.originalPosition.left + this.originalSize.width,
22151			dh = this.originalPosition.top + this.originalSize.height,
22152			cw = /sw|nw|w/.test( a ), ch = /nw|ne|n/.test( a );
22153		if ( isminw ) {
22154			data.width = o.minWidth;
22155		}
22156		if ( isminh ) {
22157			data.height = o.minHeight;
22158		}
22159		if ( ismaxw ) {
22160			data.width = o.maxWidth;
22161		}
22162		if ( ismaxh ) {
22163			data.height = o.maxHeight;
22164		}
22165
22166		if ( isminw && cw ) {
22167			data.left = dw - o.minWidth;
22168		}
22169		if ( ismaxw && cw ) {
22170			data.left = dw - o.maxWidth;
22171		}
22172		if ( isminh && ch ) {
22173			data.top = dh - o.minHeight;
22174		}
22175		if ( ismaxh && ch ) {
22176			data.top = dh - o.maxHeight;
22177		}
22178
22179		// Fixing jump error on top/left - bug #2330
22180		if ( !data.width && !data.height && !data.left && data.top ) {
22181			data.top = null;
22182		} else if ( !data.width && !data.height && !data.top && data.left ) {
22183			data.left = null;
22184		}
22185
22186		return data;
22187	},
22188
22189	_getPaddingPlusBorderDimensions: function( element ) {
22190		var i = 0,
22191			widths = [],
22192			borders = [
22193				element.css( "borderTopWidth" ),
22194				element.css( "borderRightWidth" ),
22195				element.css( "borderBottomWidth" ),
22196				element.css( "borderLeftWidth" )
22197			],
22198			paddings = [
22199				element.css( "paddingTop" ),
22200				element.css( "paddingRight" ),
22201				element.css( "paddingBottom" ),
22202				element.css( "paddingLeft" )
22203			];
22204
22205		for ( ; i < 4; i++ ) {
22206			widths[ i ] = ( parseFloat( borders[ i ] ) || 0 );
22207			widths[ i ] += ( parseFloat( paddings[ i ] ) || 0 );
22208		}
22209
22210		return {
22211			height: widths[ 0 ] + widths[ 2 ],
22212			width: widths[ 1 ] + widths[ 3 ]
22213		};
22214	},
22215
22216	_calculateAdjustedElementDimensions: function( element ) {
22217		var elWidth, elHeight, paddingBorder,
22218			ce = element.get( 0 );
22219
22220		if ( element.css( "box-sizing" ) !== "content-box" ||
22221			( !this._hasScroll( ce ) && !this._hasScroll( ce, "left" ) ) ) {
22222				return {
22223					height: parseFloat( element.css( "height" ) ),
22224					width: parseFloat( element.css( "width" ) )
22225				};
22226		}
22227
22228		// Check if CSS inline styles are set and use those (usually from previous resizes)
22229		elWidth = parseFloat( ce.style.width );
22230		elHeight = parseFloat( ce.style.height );
22231
22232		paddingBorder = this._getPaddingPlusBorderDimensions( element );
22233		elWidth = isNaN( elWidth ) ?
22234			this._getElementTheoreticalSize( element, paddingBorder, "width" ) :
22235			elWidth;
22236		elHeight = isNaN( elHeight ) ?
22237			this._getElementTheoreticalSize( element, paddingBorder, "height" ) :
22238			elHeight;
22239
22240		return {
22241			height: elHeight,
22242			width: elWidth
22243		};
22244	},
22245
22246	_getElementTheoreticalSize: function( element, extraSize, dimension ) {
22247
22248		// offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border
22249		var size = Math.max( 0, Math.ceil(
22250			element.get( 0 )[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] -
22251			extraSize[ dimension ] -
22252			0.5
22253
22254		// If offsetWidth/offsetHeight is unknown, then we can't determine theoretical size.
22255		// Use an explicit zero to avoid NaN.
22256		// See https://github.com/jquery/jquery/issues/3964
22257		) ) || 0;
22258
22259		return size;
22260	},
22261
22262	_proportionallyResize: function() {
22263
22264		if ( !this._proportionallyResizeElements.length ) {
22265			return;
22266		}
22267
22268		var prel,
22269			i = 0,
22270			element = this.helper || this.element;
22271
22272		for ( ; i < this._proportionallyResizeElements.length; i++ ) {
22273
22274			prel = this._proportionallyResizeElements[ i ];
22275
22276			// TODO: Seems like a bug to cache this.outerDimensions
22277			// considering that we are in a loop.
22278			if ( !this.outerDimensions ) {
22279				this.outerDimensions = this._getPaddingPlusBorderDimensions( prel );
22280			}
22281
22282			prel.css( {
22283				height: ( element.height() - this.outerDimensions.height ) || 0,
22284				width: ( element.width() - this.outerDimensions.width ) || 0
22285			} );
22286
22287		}
22288
22289	},
22290
22291	_renderProxy: function() {
22292
22293		var el = this.element, o = this.options;
22294		this.elementOffset = el.offset();
22295
22296		if ( this._helper ) {
22297
22298			this.helper = this.helper || $( "<div></div>" ).css( { overflow: "hidden" } );
22299
22300			this._addClass( this.helper, this._helper );
22301			this.helper.css( {
22302				width: this.element.outerWidth(),
22303				height: this.element.outerHeight(),
22304				position: "absolute",
22305				left: this.elementOffset.left + "px",
22306				top: this.elementOffset.top + "px",
22307				zIndex: ++o.zIndex //TODO: Don't modify option
22308			} );
22309
22310			this.helper
22311				.appendTo( "body" )
22312				.disableSelection();
22313
22314		} else {
22315			this.helper = this.element;
22316		}
22317
22318	},
22319
22320	_change: {
22321		e: function( event, dx ) {
22322			return { width: this.originalSize.width + dx };
22323		},
22324		w: function( event, dx ) {
22325			var cs = this.originalSize, sp = this.originalPosition;
22326			return { left: sp.left + dx, width: cs.width - dx };
22327		},
22328		n: function( event, dx, dy ) {
22329			var cs = this.originalSize, sp = this.originalPosition;
22330			return { top: sp.top + dy, height: cs.height - dy };
22331		},
22332		s: function( event, dx, dy ) {
22333			return { height: this.originalSize.height + dy };
22334		},
22335		se: function( event, dx, dy ) {
22336			return $.extend( this._change.s.apply( this, arguments ),
22337				this._change.e.apply( this, [ event, dx, dy ] ) );
22338		},
22339		sw: function( event, dx, dy ) {
22340			return $.extend( this._change.s.apply( this, arguments ),
22341				this._change.w.apply( this, [ event, dx, dy ] ) );
22342		},
22343		ne: function( event, dx, dy ) {
22344			return $.extend( this._change.n.apply( this, arguments ),
22345				this._change.e.apply( this, [ event, dx, dy ] ) );
22346		},
22347		nw: function( event, dx, dy ) {
22348			return $.extend( this._change.n.apply( this, arguments ),
22349				this._change.w.apply( this, [ event, dx, dy ] ) );
22350		}
22351	},
22352
22353	_propagate: function( n, event ) {
22354		$.ui.plugin.call( this, n, [ event, this.ui() ] );
22355		if ( n !== "resize" ) {
22356			this._trigger( n, event, this.ui() );
22357		}
22358	},
22359
22360	plugins: {},
22361
22362	ui: function() {
22363		return {
22364			originalElement: this.originalElement,
22365			element: this.element,
22366			helper: this.helper,
22367			position: this.position,
22368			size: this.size,
22369			originalSize: this.originalSize,
22370			originalPosition: this.originalPosition
22371		};
22372	}
22373
22374} );
22375
22376/*
22377 * Resizable Extensions
22378 */
22379
22380$.ui.plugin.add( "resizable", "animate", {
22381
22382	stop: function( event ) {
22383		var that = $( this ).resizable( "instance" ),
22384			o = that.options,
22385			pr = that._proportionallyResizeElements,
22386			ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName ),
22387			soffseth = ista && that._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height,
22388			soffsetw = ista ? 0 : that.sizeDiff.width,
22389			style = {
22390				width: ( that.size.width - soffsetw ),
22391				height: ( that.size.height - soffseth )
22392			},
22393			left = ( parseFloat( that.element.css( "left" ) ) +
22394				( that.position.left - that.originalPosition.left ) ) || null,
22395			top = ( parseFloat( that.element.css( "top" ) ) +
22396				( that.position.top - that.originalPosition.top ) ) || null;
22397
22398		that.element.animate(
22399			$.extend( style, top && left ? { top: top, left: left } : {} ), {
22400				duration: o.animateDuration,
22401				easing: o.animateEasing,
22402				step: function() {
22403
22404					var data = {
22405						width: parseFloat( that.element.css( "width" ) ),
22406						height: parseFloat( that.element.css( "height" ) ),
22407						top: parseFloat( that.element.css( "top" ) ),
22408						left: parseFloat( that.element.css( "left" ) )
22409					};
22410
22411					if ( pr && pr.length ) {
22412						$( pr[ 0 ] ).css( { width: data.width, height: data.height } );
22413					}
22414
22415					// Propagating resize, and updating values for each animation step
22416					that._updateCache( data );
22417					that._propagate( "resize", event );
22418
22419				}
22420			}
22421		);
22422	}
22423
22424} );
22425
22426$.ui.plugin.add( "resizable", "containment", {
22427
22428	start: function() {
22429		var element, p, co, ch, cw, width, height,
22430			that = $( this ).resizable( "instance" ),
22431			o = that.options,
22432			el = that.element,
22433			oc = o.containment,
22434			ce = ( oc instanceof $ ) ?
22435				oc.get( 0 ) :
22436				( /parent/.test( oc ) ) ? el.parent().get( 0 ) : oc;
22437
22438		if ( !ce ) {
22439			return;
22440		}
22441
22442		that.containerElement = $( ce );
22443
22444		if ( /document/.test( oc ) || oc === document ) {
22445			that.containerOffset = {
22446				left: 0,
22447				top: 0
22448			};
22449			that.containerPosition = {
22450				left: 0,
22451				top: 0
22452			};
22453
22454			that.parentData = {
22455				element: $( document ),
22456				left: 0,
22457				top: 0,
22458				width: $( document ).width(),
22459				height: $( document ).height() || document.body.parentNode.scrollHeight
22460			};
22461		} else {
22462			element = $( ce );
22463			p = [];
22464			$( [ "Top", "Right", "Left", "Bottom" ] ).each( function( i, name ) {
22465				p[ i ] = that._num( element.css( "padding" + name ) );
22466			} );
22467
22468			that.containerOffset = element.offset();
22469			that.containerPosition = element.position();
22470			that.containerSize = {
22471				height: ( element.innerHeight() - p[ 3 ] ),
22472				width: ( element.innerWidth() - p[ 1 ] )
22473			};
22474
22475			co = that.containerOffset;
22476			ch = that.containerSize.height;
22477			cw = that.containerSize.width;
22478			width = ( that._hasScroll( ce, "left" ) ? ce.scrollWidth : cw );
22479			height = ( that._hasScroll( ce ) ? ce.scrollHeight : ch );
22480
22481			that.parentData = {
22482				element: ce,
22483				left: co.left,
22484				top: co.top,
22485				width: width,
22486				height: height
22487			};
22488		}
22489	},
22490
22491	resize: function( event ) {
22492		var woset, hoset, isParent, isOffsetRelative,
22493			that = $( this ).resizable( "instance" ),
22494			o = that.options,
22495			co = that.containerOffset,
22496			cp = that.position,
22497			pRatio = that._aspectRatio || event.shiftKey,
22498			cop = {
22499				top: 0,
22500				left: 0
22501			},
22502			ce = that.containerElement,
22503			continueResize = true;
22504
22505		if ( ce[ 0 ] !== document && ( /static/ ).test( ce.css( "position" ) ) ) {
22506			cop = co;
22507		}
22508
22509		if ( cp.left < ( that._helper ? co.left : 0 ) ) {
22510			that.size.width = that.size.width +
22511				( that._helper ?
22512					( that.position.left - co.left ) :
22513					( that.position.left - cop.left ) );
22514
22515			if ( pRatio ) {
22516				that.size.height = that.size.width / that.aspectRatio;
22517				continueResize = false;
22518			}
22519			that.position.left = o.helper ? co.left : 0;
22520		}
22521
22522		if ( cp.top < ( that._helper ? co.top : 0 ) ) {
22523			that.size.height = that.size.height +
22524				( that._helper ?
22525					( that.position.top - co.top ) :
22526					that.position.top );
22527
22528			if ( pRatio ) {
22529				that.size.width = that.size.height * that.aspectRatio;
22530				continueResize = false;
22531			}
22532			that.position.top = that._helper ? co.top : 0;
22533		}
22534
22535		isParent = that.containerElement.get( 0 ) === that.element.parent().get( 0 );
22536		isOffsetRelative = /relative|absolute/.test( that.containerElement.css( "position" ) );
22537
22538		if ( isParent && isOffsetRelative ) {
22539			that.offset.left = that.parentData.left + that.position.left;
22540			that.offset.top = that.parentData.top + that.position.top;
22541		} else {
22542			that.offset.left = that.element.offset().left;
22543			that.offset.top = that.element.offset().top;
22544		}
22545
22546		woset = Math.abs( that.sizeDiff.width +
22547			( that._helper ?
22548				that.offset.left - cop.left :
22549				( that.offset.left - co.left ) ) );
22550
22551		hoset = Math.abs( that.sizeDiff.height +
22552			( that._helper ?
22553				that.offset.top - cop.top :
22554				( that.offset.top - co.top ) ) );
22555
22556		if ( woset + that.size.width >= that.parentData.width ) {
22557			that.size.width = that.parentData.width - woset;
22558			if ( pRatio ) {
22559				that.size.height = that.size.width / that.aspectRatio;
22560				continueResize = false;
22561			}
22562		}
22563
22564		if ( hoset + that.size.height >= that.parentData.height ) {
22565			that.size.height = that.parentData.height - hoset;
22566			if ( pRatio ) {
22567				that.size.width = that.size.height * that.aspectRatio;
22568				continueResize = false;
22569			}
22570		}
22571
22572		if ( !continueResize ) {
22573			that.position.left = that.prevPosition.left;
22574			that.position.top = that.prevPosition.top;
22575			that.size.width = that.prevSize.width;
22576			that.size.height = that.prevSize.height;
22577		}
22578	},
22579
22580	stop: function() {
22581		var that = $( this ).resizable( "instance" ),
22582			o = that.options,
22583			co = that.containerOffset,
22584			cop = that.containerPosition,
22585			ce = that.containerElement,
22586			helper = $( that.helper ),
22587			ho = helper.offset(),
22588			w = helper.outerWidth() - that.sizeDiff.width,
22589			h = helper.outerHeight() - that.sizeDiff.height;
22590
22591		if ( that._helper && !o.animate && ( /relative/ ).test( ce.css( "position" ) ) ) {
22592			$( this ).css( {
22593				left: ho.left - cop.left - co.left,
22594				width: w,
22595				height: h
22596			} );
22597		}
22598
22599		if ( that._helper && !o.animate && ( /static/ ).test( ce.css( "position" ) ) ) {
22600			$( this ).css( {
22601				left: ho.left - cop.left - co.left,
22602				width: w,
22603				height: h
22604			} );
22605		}
22606	}
22607} );
22608
22609$.ui.plugin.add( "resizable", "alsoResize", {
22610
22611	start: function() {
22612		var that = $( this ).resizable( "instance" ),
22613			o = that.options;
22614
22615		$( o.alsoResize ).each( function() {
22616			var el = $( this ),
22617				elSize = that._calculateAdjustedElementDimensions( el );
22618
22619			el.data( "ui-resizable-alsoresize", {
22620				width: elSize.width, height: elSize.height,
22621				left: parseFloat( el.css( "left" ) ), top: parseFloat( el.css( "top" ) )
22622			} );
22623		} );
22624	},
22625
22626	resize: function( event, ui ) {
22627		var that = $( this ).resizable( "instance" ),
22628			o = that.options,
22629			os = that.originalSize,
22630			op = that.originalPosition,
22631			delta = {
22632				height: ( that.size.height - os.height ) || 0,
22633				width: ( that.size.width - os.width ) || 0,
22634				top: ( that.position.top - op.top ) || 0,
22635				left: ( that.position.left - op.left ) || 0
22636			};
22637
22638			$( o.alsoResize ).each( function() {
22639				var el = $( this ), start = $( this ).data( "ui-resizable-alsoresize" ), style = {},
22640					css = el.parents( ui.originalElement[ 0 ] ).length ?
22641							[ "width", "height" ] :
22642							[ "width", "height", "top", "left" ];
22643
22644				$.each( css, function( i, prop ) {
22645					var sum = ( start[ prop ] || 0 ) + ( delta[ prop ] || 0 );
22646					if ( sum && sum >= 0 ) {
22647						style[ prop ] = sum || null;
22648					}
22649				} );
22650
22651				el.css( style );
22652			} );
22653	},
22654
22655	stop: function() {
22656		$( this ).removeData( "ui-resizable-alsoresize" );
22657	}
22658} );
22659
22660$.ui.plugin.add( "resizable", "ghost", {
22661
22662	start: function() {
22663
22664		var that = $( this ).resizable( "instance" ), cs = that.size;
22665
22666		that.ghost = that.originalElement.clone();
22667		that.ghost.css( {
22668			opacity: 0.25,
22669			display: "block",
22670			position: "relative",
22671			height: cs.height,
22672			width: cs.width,
22673			margin: 0,
22674			left: 0,
22675			top: 0
22676		} );
22677
22678		that._addClass( that.ghost, "ui-resizable-ghost" );
22679
22680		// DEPRECATED
22681		// TODO: remove after 1.12
22682		if ( $.uiBackCompat === true && typeof that.options.ghost === "string" ) {
22683
22684			// Ghost option
22685			that.ghost.addClass( this.options.ghost );
22686		}
22687
22688		that.ghost.appendTo( that.helper );
22689
22690	},
22691
22692	resize: function() {
22693		var that = $( this ).resizable( "instance" );
22694		if ( that.ghost ) {
22695			that.ghost.css( {
22696				position: "relative",
22697				height: that.size.height,
22698				width: that.size.width
22699			} );
22700		}
22701	},
22702
22703	stop: function() {
22704		var that = $( this ).resizable( "instance" );
22705		if ( that.ghost && that.helper ) {
22706			that.helper.get( 0 ).removeChild( that.ghost.get( 0 ) );
22707		}
22708	}
22709
22710} );
22711
22712$.ui.plugin.add( "resizable", "grid", {
22713
22714	resize: function() {
22715		var outerDimensions,
22716			that = $( this ).resizable( "instance" ),
22717			o = that.options,
22718			cs = that.size,
22719			os = that.originalSize,
22720			op = that.originalPosition,
22721			a = that.axis,
22722			grid = typeof o.grid === "number" ? [ o.grid, o.grid ] : o.grid,
22723			gridX = ( grid[ 0 ] || 1 ),
22724			gridY = ( grid[ 1 ] || 1 ),
22725			ox = Math.round( ( cs.width - os.width ) / gridX ) * gridX,
22726			oy = Math.round( ( cs.height - os.height ) / gridY ) * gridY,
22727			newWidth = os.width + ox,
22728			newHeight = os.height + oy,
22729			isMaxWidth = o.maxWidth && ( o.maxWidth < newWidth ),
22730			isMaxHeight = o.maxHeight && ( o.maxHeight < newHeight ),
22731			isMinWidth = o.minWidth && ( o.minWidth > newWidth ),
22732			isMinHeight = o.minHeight && ( o.minHeight > newHeight );
22733
22734		o.grid = grid;
22735
22736		if ( isMinWidth ) {
22737			newWidth += gridX;
22738		}
22739		if ( isMinHeight ) {
22740			newHeight += gridY;
22741		}
22742		if ( isMaxWidth ) {
22743			newWidth -= gridX;
22744		}
22745		if ( isMaxHeight ) {
22746			newHeight -= gridY;
22747		}
22748
22749		if ( /^(se|s|e)$/.test( a ) ) {
22750			that.size.width = newWidth;
22751			that.size.height = newHeight;
22752		} else if ( /^(ne)$/.test( a ) ) {
22753			that.size.width = newWidth;
22754			that.size.height = newHeight;
22755			that.position.top = op.top - oy;
22756		} else if ( /^(sw)$/.test( a ) ) {
22757			that.size.width = newWidth;
22758			that.size.height = newHeight;
22759			that.position.left = op.left - ox;
22760		} else {
22761			if ( newHeight - gridY <= 0 || newWidth - gridX <= 0 ) {
22762				outerDimensions = that._getPaddingPlusBorderDimensions( this );
22763			}
22764
22765			if ( newHeight - gridY > 0 ) {
22766				that.size.height = newHeight;
22767				that.position.top = op.top - oy;
22768			} else {
22769				newHeight = gridY - outerDimensions.height;
22770				that.size.height = newHeight;
22771				that.position.top = op.top + os.height - newHeight;
22772			}
22773			if ( newWidth - gridX > 0 ) {
22774				that.size.width = newWidth;
22775				that.position.left = op.left - ox;
22776			} else {
22777				newWidth = gridX - outerDimensions.width;
22778				that.size.width = newWidth;
22779				that.position.left = op.left + os.width - newWidth;
22780			}
22781		}
22782	}
22783
22784} );
22785
22786var widgetsResizable = $.ui.resizable;
22787
22788
22789/*!
22790 * jQuery UI Dialog 1.14.1
22791 * https://jqueryui.com
22792 *
22793 * Copyright OpenJS Foundation and other contributors
22794 * Released under the MIT license.
22795 * https://jquery.org/license
22796 */
22797
22798//>>label: Dialog
22799//>>group: Widgets
22800//>>description: Displays customizable dialog windows.
22801//>>docs: https://api.jqueryui.com/dialog/
22802//>>demos: https://jqueryui.com/dialog/
22803//>>css.structure: ../../themes/base/core.css
22804//>>css.structure: ../../themes/base/dialog.css
22805//>>css.theme: ../../themes/base/theme.css
22806
22807
22808$.widget( "ui.dialog", {
22809	version: "1.14.1",
22810	options: {
22811		appendTo: "body",
22812		autoOpen: true,
22813		buttons: [],
22814		classes: {
22815			"ui-dialog": "ui-corner-all",
22816			"ui-dialog-titlebar": "ui-corner-all"
22817		},
22818		closeOnEscape: true,
22819		closeText: "Close",
22820		draggable: true,
22821		hide: null,
22822		height: "auto",
22823		maxHeight: null,
22824		maxWidth: null,
22825		minHeight: 150,
22826		minWidth: 150,
22827		modal: false,
22828		position: {
22829			my: "center",
22830			at: "center",
22831			of: window,
22832			collision: "fit",
22833
22834			// Ensure the titlebar is always visible
22835			using: function( pos ) {
22836				var topOffset = $( this ).css( pos ).offset().top;
22837				if ( topOffset < 0 ) {
22838					$( this ).css( "top", pos.top - topOffset );
22839				}
22840			}
22841		},
22842		resizable: true,
22843		show: null,
22844		title: null,
22845		uiDialogTitleHeadingLevel: 0,
22846		width: 300,
22847
22848		// Callbacks
22849		beforeClose: null,
22850		close: null,
22851		drag: null,
22852		dragStart: null,
22853		dragStop: null,
22854		focus: null,
22855		open: null,
22856		resize: null,
22857		resizeStart: null,
22858		resizeStop: null
22859	},
22860
22861	sizeRelatedOptions: {
22862		buttons: true,
22863		height: true,
22864		maxHeight: true,
22865		maxWidth: true,
22866		minHeight: true,
22867		minWidth: true,
22868		width: true
22869	},
22870
22871	resizableRelatedOptions: {
22872		maxHeight: true,
22873		maxWidth: true,
22874		minHeight: true,
22875		minWidth: true
22876	},
22877
22878	_create: function() {
22879		this.originalCss = {
22880			display: this.element[ 0 ].style.display,
22881			width: this.element[ 0 ].style.width,
22882			minHeight: this.element[ 0 ].style.minHeight,
22883			maxHeight: this.element[ 0 ].style.maxHeight,
22884			height: this.element[ 0 ].style.height
22885		};
22886		this.originalPosition = {
22887			parent: this.element.parent(),
22888			index: this.element.parent().children().index( this.element )
22889		};
22890		this.originalTitle = this.element.attr( "title" );
22891		if ( this.options.title == null && this.originalTitle != null ) {
22892			this.options.title = this.originalTitle;
22893		}
22894
22895		// Dialogs can't be disabled
22896		if ( this.options.disabled ) {
22897			this.options.disabled = false;
22898		}
22899
22900		this._createWrapper();
22901
22902		this.element
22903			.show()
22904			.removeAttr( "title" )
22905			.appendTo( this.uiDialog );
22906
22907		this._addClass( "ui-dialog-content", "ui-widget-content" );
22908
22909		this._createTitlebar();
22910		this._createButtonPane();
22911
22912		if ( this.options.draggable && $.fn.draggable ) {
22913			this._makeDraggable();
22914		}
22915		if ( this.options.resizable && $.fn.resizable ) {
22916			this._makeResizable();
22917		}
22918
22919		this._isOpen = false;
22920
22921		this._trackFocus();
22922	},
22923
22924	_init: function() {
22925		if ( this.options.autoOpen ) {
22926			this.open();
22927		}
22928	},
22929
22930	_appendTo: function() {
22931		var element = this.options.appendTo;
22932		if ( element && ( element.jquery || element.nodeType ) ) {
22933			return $( element );
22934		}
22935		return this.document.find( element || "body" ).eq( 0 );
22936	},
22937
22938	_destroy: function() {
22939		var next,
22940			originalPosition = this.originalPosition;
22941
22942		this._untrackInstance();
22943		this._destroyOverlay();
22944
22945		this.element
22946			.removeUniqueId()
22947			.css( this.originalCss )
22948
22949			// Without detaching first, the following becomes really slow
22950			.detach();
22951
22952		this.uiDialog.remove();
22953
22954		if ( this.originalTitle ) {
22955			this.element.attr( "title", this.originalTitle );
22956		}
22957
22958		next = originalPosition.parent.children().eq( originalPosition.index );
22959
22960		// Don't try to place the dialog next to itself (#8613)
22961		if ( next.length && next[ 0 ] !== this.element[ 0 ] ) {
22962			next.before( this.element );
22963		} else {
22964			originalPosition.parent.append( this.element );
22965		}
22966	},
22967
22968	widget: function() {
22969		return this.uiDialog;
22970	},
22971
22972	disable: $.noop,
22973	enable: $.noop,
22974
22975	close: function( event ) {
22976		var that = this;
22977
22978		if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) {
22979			return;
22980		}
22981
22982		this._isOpen = false;
22983		this._focusedElement = null;
22984		this._destroyOverlay();
22985		this._untrackInstance();
22986
22987		if ( !this.opener.filter( ":focusable" ).trigger( "focus" ).length ) {
22988
22989			// Hiding a focused element doesn't trigger blur in WebKit
22990			// so in case we have nothing to focus on, explicitly blur the active element
22991			// https://bugs.webkit.org/show_bug.cgi?id=47182
22992			$( this.document[ 0 ].activeElement ).trigger( "blur" );
22993		}
22994
22995		this._hide( this.uiDialog, this.options.hide, function() {
22996			that._trigger( "close", event );
22997		} );
22998	},
22999
23000	isOpen: function() {
23001		return this._isOpen;
23002	},
23003
23004	moveToTop: function() {
23005		this._moveToTop();
23006	},
23007
23008	_moveToTop: function( event, silent ) {
23009		var moved = false,
23010			zIndices = this.uiDialog.siblings( ".ui-front:visible" ).map( function() {
23011				return +$( this ).css( "z-index" );
23012			} ).get(),
23013			zIndexMax = Math.max.apply( null, zIndices );
23014
23015		if ( zIndexMax >= +this.uiDialog.css( "z-index" ) ) {
23016			this.uiDialog.css( "z-index", zIndexMax + 1 );
23017			moved = true;
23018		}
23019
23020		if ( moved && !silent ) {
23021			this._trigger( "focus", event );
23022		}
23023		return moved;
23024	},
23025
23026	open: function() {
23027		var that = this;
23028		if ( this._isOpen ) {
23029			if ( this._moveToTop() ) {
23030				this._focusTabbable();
23031			}
23032			return;
23033		}
23034
23035		this._isOpen = true;
23036		this.opener = $( this.document[ 0 ].activeElement );
23037
23038		this._size();
23039		this._position();
23040		this._createOverlay();
23041		this._moveToTop( null, true );
23042
23043		// Ensure the overlay is moved to the top with the dialog, but only when
23044		// opening. The overlay shouldn't move after the dialog is open so that
23045		// modeless dialogs opened after the modal dialog stack properly.
23046		if ( this.overlay ) {
23047			this.overlay.css( "z-index", this.uiDialog.css( "z-index" ) - 1 );
23048		}
23049
23050		this._show( this.uiDialog, this.options.show, function() {
23051			that._focusTabbable();
23052			that._trigger( "focus" );
23053		} );
23054
23055		// Track the dialog immediately upon opening in case a focus event
23056		// somehow occurs outside of the dialog before an element inside the
23057		// dialog is focused (#10152)
23058		this._makeFocusTarget();
23059
23060		this._trigger( "open" );
23061	},
23062
23063	_focusTabbable: function() {
23064
23065		// Set focus to the first match:
23066		// 1. An element that was focused previously
23067		// 2. First element inside the dialog matching [autofocus]
23068		// 3. Tabbable element inside the content element
23069		// 4. Tabbable element inside the buttonpane
23070		// 5. The close button
23071		// 6. The dialog itself
23072		var hasFocus = this._focusedElement;
23073		if ( !hasFocus ) {
23074			hasFocus = this.element.find( "[autofocus]" );
23075		}
23076		if ( !hasFocus.length ) {
23077			hasFocus = this.element.find( ":tabbable" );
23078		}
23079		if ( !hasFocus.length ) {
23080			hasFocus = this.uiDialogButtonPane.find( ":tabbable" );
23081		}
23082		if ( !hasFocus.length ) {
23083			hasFocus = this.uiDialogTitlebarClose.filter( ":tabbable" );
23084		}
23085		if ( !hasFocus.length ) {
23086			hasFocus = this.uiDialog;
23087		}
23088		hasFocus.eq( 0 ).trigger( "focus" );
23089	},
23090
23091	_restoreTabbableFocus: function() {
23092		var activeElement = this.document[ 0 ].activeElement,
23093			isActive = this.uiDialog[ 0 ] === activeElement ||
23094				$.contains( this.uiDialog[ 0 ], activeElement );
23095		if ( !isActive ) {
23096			this._focusTabbable();
23097		}
23098	},
23099
23100	_keepFocus: function( event ) {
23101		event.preventDefault();
23102		this._restoreTabbableFocus();
23103	},
23104
23105	_createWrapper: function() {
23106		this.uiDialog = $( "<div>" )
23107			.hide()
23108			.attr( {
23109
23110				// Setting tabIndex makes the div focusable
23111				tabIndex: -1,
23112				role: "dialog",
23113				"aria-modal": this.options.modal ? "true" : null
23114			} )
23115			.appendTo( this._appendTo() );
23116
23117		this._addClass( this.uiDialog, "ui-dialog", "ui-widget ui-widget-content ui-front" );
23118		this._on( this.uiDialog, {
23119			keydown: function( event ) {
23120				if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
23121						event.keyCode === $.ui.keyCode.ESCAPE ) {
23122					event.preventDefault();
23123					this.close( event );
23124					return;
23125				}
23126
23127				// Prevent tabbing out of dialogs
23128				if ( event.keyCode !== $.ui.keyCode.TAB || event.isDefaultPrevented() ) {
23129					return;
23130				}
23131				var tabbables = this.uiDialog.find( ":tabbable" ),
23132					first = tabbables.first(),
23133					last = tabbables.last();
23134
23135				if ( ( event.target === last[ 0 ] || event.target === this.uiDialog[ 0 ] ) &&
23136						!event.shiftKey ) {
23137					this._delay( function() {
23138						first.trigger( "focus" );
23139					} );
23140					event.preventDefault();
23141				} else if ( ( event.target === first[ 0 ] ||
23142						event.target === this.uiDialog[ 0 ] ) && event.shiftKey ) {
23143					this._delay( function() {
23144						last.trigger( "focus" );
23145					} );
23146					event.preventDefault();
23147				}
23148			},
23149			mousedown: function( event ) {
23150				if ( this._moveToTop( event ) ) {
23151					this._focusTabbable();
23152				}
23153			}
23154		} );
23155
23156		// We assume that any existing aria-describedby attribute means
23157		// that the dialog content is marked up properly
23158		// otherwise we brute force the content as the description
23159		if ( !this.element.find( "[aria-describedby]" ).length ) {
23160			this.uiDialog.attr( {
23161				"aria-describedby": this.element.uniqueId().attr( "id" )
23162			} );
23163		}
23164	},
23165
23166	_createTitlebar: function() {
23167		var uiDialogTitle;
23168
23169		this.uiDialogTitlebar = $( "<div>" );
23170		this._addClass( this.uiDialogTitlebar,
23171			"ui-dialog-titlebar", "ui-widget-header ui-helper-clearfix" );
23172		this._on( this.uiDialogTitlebar, {
23173			mousedown: function( event ) {
23174
23175				// Don't prevent click on close button (#8838)
23176				// Focusing a dialog that is partially scrolled out of view
23177				// causes the browser to scroll it into view, preventing the click event
23178				if ( !$( event.target ).closest( ".ui-dialog-titlebar-close" ) ) {
23179
23180					// Dialog isn't getting focus when dragging (#8063)
23181					this.uiDialog.trigger( "focus" );
23182				}
23183			}
23184		} );
23185
23186		this.uiDialogTitlebarClose = $( "<button type='button'></button>" )
23187			.button( {
23188				label: $( "<a>" ).text( this.options.closeText ).html(),
23189				icon: "ui-icon-closethick",
23190				showLabel: false
23191			} )
23192			.appendTo( this.uiDialogTitlebar );
23193
23194		this._addClass( this.uiDialogTitlebarClose, "ui-dialog-titlebar-close" );
23195		this._on( this.uiDialogTitlebarClose, {
23196			click: function( event ) {
23197				event.preventDefault();
23198				this.close( event );
23199			}
23200		} );
23201
23202		var uiDialogHeadingLevel = Number.isInteger( this.options.uiDialogTitleHeadingLevel ) &&
23203			this.options.uiDialogTitleHeadingLevel > 0 &&
23204			this.options.uiDialogTitleHeadingLevel <= 6 ?
23205			"h" + this.options.uiDialogTitleHeadingLevel : "span";
23206
23207		uiDialogTitle = $( "<" + uiDialogHeadingLevel + ">" )
23208			.uniqueId().prependTo( this.uiDialogTitlebar );
23209		this._addClass( uiDialogTitle, "ui-dialog-title" );
23210		this._title( uiDialogTitle );
23211
23212		this.uiDialogTitlebar.prependTo( this.uiDialog );
23213
23214		this.uiDialog.attr( {
23215			"aria-labelledby": uiDialogTitle.attr( "id" )
23216		} );
23217	},
23218
23219	_title: function( title ) {
23220		if ( this.options.title ) {
23221			title.text( this.options.title );
23222		} else {
23223			title.html( "&#160;" );
23224		}
23225	},
23226
23227	_createButtonPane: function() {
23228		this.uiDialogButtonPane = $( "<div>" );
23229		this._addClass( this.uiDialogButtonPane, "ui-dialog-buttonpane",
23230			"ui-widget-content ui-helper-clearfix" );
23231
23232		this.uiButtonSet = $( "<div>" )
23233			.appendTo( this.uiDialogButtonPane );
23234		this._addClass( this.uiButtonSet, "ui-dialog-buttonset" );
23235
23236		this._createButtons();
23237	},
23238
23239	_createButtons: function() {
23240		var that = this,
23241			buttons = this.options.buttons;
23242
23243		// If we already have a button pane, remove it
23244		this.uiDialogButtonPane.remove();
23245		this.uiButtonSet.empty();
23246
23247		if ( $.isEmptyObject( buttons ) || ( Array.isArray( buttons ) && !buttons.length ) ) {
23248			this._removeClass( this.uiDialog, "ui-dialog-buttons" );
23249			return;
23250		}
23251
23252		$.each( buttons, function( name, props ) {
23253			var click, buttonOptions;
23254			props = typeof props === "function" ?
23255				{ click: props, text: name } :
23256				props;
23257
23258			// Default to a non-submitting button
23259			props = $.extend( { type: "button" }, props );
23260
23261			// Change the context for the click callback to be the main element
23262			click = props.click;
23263			buttonOptions = {
23264				icon: props.icon,
23265				iconPosition: props.iconPosition,
23266				showLabel: props.showLabel,
23267
23268				// Deprecated options
23269				icons: props.icons,
23270				text: props.text
23271			};
23272
23273			delete props.click;
23274			delete props.icon;
23275			delete props.iconPosition;
23276			delete props.showLabel;
23277
23278			// Deprecated options
23279			delete props.icons;
23280			if ( typeof props.text === "boolean" ) {
23281				delete props.text;
23282			}
23283
23284			$( "<button></button>", props )
23285				.button( buttonOptions )
23286				.appendTo( that.uiButtonSet )
23287				.on( "click", function() {
23288					click.apply( that.element[ 0 ], arguments );
23289				} );
23290		} );
23291		this._addClass( this.uiDialog, "ui-dialog-buttons" );
23292		this.uiDialogButtonPane.appendTo( this.uiDialog );
23293	},
23294
23295	_makeDraggable: function() {
23296		var that = this,
23297			options = this.options;
23298
23299		function filteredUi( ui ) {
23300			return {
23301				position: ui.position,
23302				offset: ui.offset
23303			};
23304		}
23305
23306		this.uiDialog.draggable( {
23307			cancel: ".ui-dialog-content, .ui-dialog-titlebar-close",
23308			handle: ".ui-dialog-titlebar",
23309			containment: "document",
23310			start: function( event, ui ) {
23311				that._addClass( $( this ), "ui-dialog-dragging" );
23312				that._blockFrames();
23313				that._trigger( "dragStart", event, filteredUi( ui ) );
23314			},
23315			drag: function( event, ui ) {
23316				that._trigger( "drag", event, filteredUi( ui ) );
23317			},
23318			stop: function( event, ui ) {
23319				var left = ui.offset.left - that.document.scrollLeft(),
23320					top = ui.offset.top - that.document.scrollTop();
23321
23322				options.position = {
23323					my: "left top",
23324					at: "left" + ( left >= 0 ? "+" : "" ) + left + " " +
23325						"top" + ( top >= 0 ? "+" : "" ) + top,
23326					of: that.window
23327				};
23328				that._removeClass( $( this ), "ui-dialog-dragging" );
23329				that._unblockFrames();
23330				that._trigger( "dragStop", event, filteredUi( ui ) );
23331			}
23332		} );
23333	},
23334
23335	_makeResizable: function() {
23336		var that = this,
23337			options = this.options,
23338			handles = options.resizable,
23339
23340			// .ui-resizable has position: relative defined in the stylesheet
23341			// but dialogs have to use absolute or fixed positioning
23342			position = this.uiDialog.css( "position" ),
23343			resizeHandles = typeof handles === "string" ?
23344				handles :
23345				"n,e,s,w,se,sw,ne,nw";
23346
23347		function filteredUi( ui ) {
23348			return {
23349				originalPosition: ui.originalPosition,
23350				originalSize: ui.originalSize,
23351				position: ui.position,
23352				size: ui.size
23353			};
23354		}
23355
23356		this.uiDialog.resizable( {
23357			cancel: ".ui-dialog-content",
23358			containment: "document",
23359			alsoResize: this.element,
23360			maxWidth: options.maxWidth,
23361			maxHeight: options.maxHeight,
23362			minWidth: options.minWidth,
23363			minHeight: this._minHeight(),
23364			handles: resizeHandles,
23365			start: function( event, ui ) {
23366				that._addClass( $( this ), "ui-dialog-resizing" );
23367				that._blockFrames();
23368				that._trigger( "resizeStart", event, filteredUi( ui ) );
23369			},
23370			resize: function( event, ui ) {
23371				that._trigger( "resize", event, filteredUi( ui ) );
23372			},
23373			stop: function( event, ui ) {
23374				var offset = that.uiDialog.offset(),
23375					left = offset.left - that.document.scrollLeft(),
23376					top = offset.top - that.document.scrollTop();
23377
23378				options.height = that.uiDialog.height();
23379				options.width = that.uiDialog.width();
23380				options.position = {
23381					my: "left top",
23382					at: "left" + ( left >= 0 ? "+" : "" ) + left + " " +
23383						"top" + ( top >= 0 ? "+" : "" ) + top,
23384					of: that.window
23385				};
23386				that._removeClass( $( this ), "ui-dialog-resizing" );
23387				that._unblockFrames();
23388				that._trigger( "resizeStop", event, filteredUi( ui ) );
23389			}
23390		} )
23391			.css( "position", position );
23392	},
23393
23394	_trackFocus: function() {
23395		this._on( this.widget(), {
23396			focusin: function( event ) {
23397				this._makeFocusTarget();
23398				this._focusedElement = $( event.target );
23399			}
23400		} );
23401	},
23402
23403	_makeFocusTarget: function() {
23404		this._untrackInstance();
23405		this._trackingInstances().unshift( this );
23406	},
23407
23408	_untrackInstance: function() {
23409		var instances = this._trackingInstances(),
23410			exists = $.inArray( this, instances );
23411		if ( exists !== -1 ) {
23412			instances.splice( exists, 1 );
23413		}
23414	},
23415
23416	_trackingInstances: function() {
23417		var instances = this.document.data( "ui-dialog-instances" );
23418		if ( !instances ) {
23419			instances = [];
23420			this.document.data( "ui-dialog-instances", instances );
23421		}
23422		return instances;
23423	},
23424
23425	_minHeight: function() {
23426		var options = this.options;
23427
23428		return options.height === "auto" ?
23429			options.minHeight :
23430			Math.min( options.minHeight, options.height );
23431	},
23432
23433	_position: function() {
23434
23435		// Need to show the dialog to get the actual offset in the position plugin
23436		var isVisible = this.uiDialog.is( ":visible" );
23437		if ( !isVisible ) {
23438			this.uiDialog.show();
23439		}
23440		this.uiDialog.position( this.options.position );
23441		if ( !isVisible ) {
23442			this.uiDialog.hide();
23443		}
23444	},
23445
23446	_setOptions: function( options ) {
23447		var that = this,
23448			resize = false,
23449			resizableOptions = {};
23450
23451		$.each( options, function( key, value ) {
23452			that._setOption( key, value );
23453
23454			if ( key in that.sizeRelatedOptions ) {
23455				resize = true;
23456			}
23457			if ( key in that.resizableRelatedOptions ) {
23458				resizableOptions[ key ] = value;
23459			}
23460		} );
23461
23462		if ( resize ) {
23463			this._size();
23464			this._position();
23465		}
23466		if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
23467			this.uiDialog.resizable( "option", resizableOptions );
23468		}
23469	},
23470
23471	_setOption: function( key, value ) {
23472		var isDraggable, isResizable,
23473			uiDialog = this.uiDialog;
23474
23475		if ( key === "disabled" ) {
23476			return;
23477		}
23478
23479		this._super( key, value );
23480
23481		if ( key === "appendTo" ) {
23482			this.uiDialog.appendTo( this._appendTo() );
23483		}
23484
23485		if ( key === "buttons" ) {
23486			this._createButtons();
23487		}
23488
23489		if ( key === "closeText" ) {
23490			this.uiDialogTitlebarClose.button( {
23491
23492				// Ensure that we always pass a string
23493				label: $( "<a>" ).text( "" + this.options.closeText ).html()
23494			} );
23495		}
23496
23497		if ( key === "draggable" ) {
23498			isDraggable = uiDialog.is( ":data(ui-draggable)" );
23499			if ( isDraggable && !value ) {
23500				uiDialog.draggable( "destroy" );
23501			}
23502
23503			if ( !isDraggable && value ) {
23504				this._makeDraggable();
23505			}
23506		}
23507
23508		if ( key === "position" ) {
23509			this._position();
23510		}
23511
23512		if ( key === "resizable" ) {
23513
23514			// currently resizable, becoming non-resizable
23515			isResizable = uiDialog.is( ":data(ui-resizable)" );
23516			if ( isResizable && !value ) {
23517				uiDialog.resizable( "destroy" );
23518			}
23519
23520			// Currently resizable, changing handles
23521			if ( isResizable && typeof value === "string" ) {
23522				uiDialog.resizable( "option", "handles", value );
23523			}
23524
23525			// Currently non-resizable, becoming resizable
23526			if ( !isResizable && value !== false ) {
23527				this._makeResizable();
23528			}
23529		}
23530
23531		if ( key === "title" ) {
23532			this._title( this.uiDialogTitlebar.find( ".ui-dialog-title" ) );
23533		}
23534
23535		if ( key === "modal" ) {
23536			uiDialog.attr( "aria-modal", value ? "true" : null );
23537		}
23538	},
23539
23540	_size: function() {
23541
23542		// If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
23543		// divs will both have width and height set, so we need to reset them
23544		var nonContentHeight, minContentHeight, maxContentHeight,
23545			options = this.options;
23546
23547		// Reset content sizing
23548		this.element.show().css( {
23549			width: "auto",
23550			minHeight: 0,
23551			maxHeight: "none",
23552			height: 0
23553		} );
23554
23555		if ( options.minWidth > options.width ) {
23556			options.width = options.minWidth;
23557		}
23558
23559		// Reset wrapper sizing
23560		// determine the height of all the non-content elements
23561		nonContentHeight = this.uiDialog.css( {
23562			height: "auto",
23563			width: options.width
23564		} )
23565			.outerHeight();
23566		minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
23567		maxContentHeight = typeof options.maxHeight === "number" ?
23568			Math.max( 0, options.maxHeight - nonContentHeight ) :
23569			"none";
23570
23571		if ( options.height === "auto" ) {
23572			this.element.css( {
23573				minHeight: minContentHeight,
23574				maxHeight: maxContentHeight,
23575				height: "auto"
23576			} );
23577		} else {
23578			this.element.height( Math.max( 0, options.height - nonContentHeight ) );
23579		}
23580
23581		if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
23582			this.uiDialog.resizable( "option", "minHeight", this._minHeight() );
23583		}
23584	},
23585
23586	_blockFrames: function() {
23587		this.iframeBlocks = this.document.find( "iframe" ).map( function() {
23588			var iframe = $( this );
23589
23590			return $( "<div>" )
23591				.css( {
23592					position: "absolute",
23593					width: iframe.outerWidth(),
23594					height: iframe.outerHeight()
23595				} )
23596				.appendTo( iframe.parent() )
23597				.offset( iframe.offset() )[ 0 ];
23598		} );
23599	},
23600
23601	_unblockFrames: function() {
23602		if ( this.iframeBlocks ) {
23603			this.iframeBlocks.remove();
23604			delete this.iframeBlocks;
23605		}
23606	},
23607
23608	_allowInteraction: function( event ) {
23609		if ( $( event.target ).closest( ".ui-dialog" ).length ) {
23610			return true;
23611		}
23612
23613		// TODO: Remove hack when datepicker implements
23614		// the .ui-front logic (#8989)
23615		return !!$( event.target ).closest( ".ui-datepicker" ).length;
23616	},
23617
23618	_createOverlay: function() {
23619		if ( !this.options.modal ) {
23620			return;
23621		}
23622
23623		// We use a delay in case the overlay is created from an
23624		// event that we're going to be cancelling (#2804)
23625		var isOpening = true;
23626		this._delay( function() {
23627			isOpening = false;
23628		} );
23629
23630		if ( !this.document.data( "ui-dialog-overlays" ) ) {
23631
23632			// Prevent use of anchors and inputs
23633			// This doesn't use `_on()` because it is a shared event handler
23634			// across all open modal dialogs.
23635			this.document.on( "focusin.ui-dialog", function( event ) {
23636				if ( isOpening ) {
23637					return;
23638				}
23639
23640				var instance = this._trackingInstances()[ 0 ];
23641				if ( !instance._allowInteraction( event ) ) {
23642					event.preventDefault();
23643					instance._focusTabbable();
23644				}
23645			}.bind( this ) );
23646		}
23647
23648		this.overlay = $( "<div>" )
23649			.appendTo( this._appendTo() );
23650
23651		this._addClass( this.overlay, null, "ui-widget-overlay ui-front" );
23652		this._on( this.overlay, {
23653			mousedown: "_keepFocus"
23654		} );
23655		this.document.data( "ui-dialog-overlays",
23656			( this.document.data( "ui-dialog-overlays" ) || 0 ) + 1 );
23657	},
23658
23659	_destroyOverlay: function() {
23660		if ( !this.options.modal ) {
23661			return;
23662		}
23663
23664		if ( this.overlay ) {
23665			var overlays = this.document.data( "ui-dialog-overlays" ) - 1;
23666
23667			if ( !overlays ) {
23668				this.document.off( "focusin.ui-dialog" );
23669				this.document.removeData( "ui-dialog-overlays" );
23670			} else {
23671				this.document.data( "ui-dialog-overlays", overlays );
23672			}
23673
23674			this.overlay.remove();
23675			this.overlay = null;
23676		}
23677	}
23678} );
23679
23680// DEPRECATED
23681// TODO: switch return back to widget declaration at top of file when this is removed
23682if ( $.uiBackCompat === true ) {
23683
23684	// Backcompat for dialogClass option
23685	$.widget( "ui.dialog", $.ui.dialog, {
23686		options: {
23687			dialogClass: ""
23688		},
23689		_createWrapper: function() {
23690			this._super();
23691			this.uiDialog.addClass( this.options.dialogClass );
23692		},
23693		_setOption: function( key, value ) {
23694			if ( key === "dialogClass" ) {
23695				this.uiDialog
23696					.removeClass( this.options.dialogClass )
23697					.addClass( value );
23698			}
23699			this._superApply( arguments );
23700		}
23701	} );
23702}
23703
23704var widgetsDialog = $.ui.dialog;
23705
23706
23707/*!
23708 * jQuery UI Droppable 1.14.1
23709 * https://jqueryui.com
23710 *
23711 * Copyright OpenJS Foundation and other contributors
23712 * Released under the MIT license.
23713 * https://jquery.org/license
23714 */
23715
23716//>>label: Droppable
23717//>>group: Interactions
23718//>>description: Enables drop targets for draggable elements.
23719//>>docs: https://api.jqueryui.com/droppable/
23720//>>demos: https://jqueryui.com/droppable/
23721
23722
23723$.widget( "ui.droppable", {
23724	version: "1.14.1",
23725	widgetEventPrefix: "drop",
23726	options: {
23727		accept: "*",
23728		addClasses: true,
23729		greedy: false,
23730		scope: "default",
23731		tolerance: "intersect",
23732
23733		// Callbacks
23734		activate: null,
23735		deactivate: null,
23736		drop: null,
23737		out: null,
23738		over: null
23739	},
23740	_create: function() {
23741
23742		var proportions,
23743			o = this.options,
23744			accept = o.accept;
23745
23746		this.isover = false;
23747		this.isout = true;
23748
23749		this.accept = typeof accept === "function" ? accept : function( d ) {
23750			return d.is( accept );
23751		};
23752
23753		this.proportions = function( /* valueToWrite */ ) {
23754			if ( arguments.length ) {
23755
23756				// Store the droppable's proportions
23757				proportions = arguments[ 0 ];
23758			} else {
23759
23760				// Retrieve or derive the droppable's proportions
23761				return proportions ?
23762					proportions :
23763					proportions = {
23764						width: this.element[ 0 ].offsetWidth,
23765						height: this.element[ 0 ].offsetHeight
23766					};
23767			}
23768		};
23769
23770		this._addToManager( o.scope );
23771
23772		if ( o.addClasses ) {
23773			this._addClass( "ui-droppable" );
23774		}
23775
23776	},
23777
23778	_addToManager: function( scope ) {
23779
23780		// Add the reference and positions to the manager
23781		$.ui.ddmanager.droppables[ scope ] = $.ui.ddmanager.droppables[ scope ] || [];
23782		$.ui.ddmanager.droppables[ scope ].push( this );
23783	},
23784
23785	_splice: function( drop ) {
23786		var i = 0;
23787		for ( ; i < drop.length; i++ ) {
23788			if ( drop[ i ] === this ) {
23789				drop.splice( i, 1 );
23790			}
23791		}
23792	},
23793
23794	_destroy: function() {
23795		var drop = $.ui.ddmanager.droppables[ this.options.scope ];
23796
23797		this._splice( drop );
23798	},
23799
23800	_setOption: function( key, value ) {
23801
23802		if ( key === "accept" ) {
23803			this.accept = typeof value === "function" ? value : function( d ) {
23804				return d.is( value );
23805			};
23806		} else if ( key === "scope" ) {
23807			var drop = $.ui.ddmanager.droppables[ this.options.scope ];
23808
23809			this._splice( drop );
23810			this._addToManager( value );
23811		}
23812
23813		this._super( key, value );
23814	},
23815
23816	_activate: function( event ) {
23817		var draggable = $.ui.ddmanager.current;
23818
23819		this._addActiveClass();
23820		if ( draggable ) {
23821			this._trigger( "activate", event, this.ui( draggable ) );
23822		}
23823	},
23824
23825	_deactivate: function( event ) {
23826		var draggable = $.ui.ddmanager.current;
23827
23828		this._removeActiveClass();
23829		if ( draggable ) {
23830			this._trigger( "deactivate", event, this.ui( draggable ) );
23831		}
23832	},
23833
23834	_over: function( event ) {
23835
23836		var draggable = $.ui.ddmanager.current;
23837
23838		// Bail if draggable and droppable are same element
23839		if ( !draggable || ( draggable.currentItem ||
23840				draggable.element )[ 0 ] === this.element[ 0 ] ) {
23841			return;
23842		}
23843
23844		if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem ||
23845				draggable.element ) ) ) {
23846			this._addHoverClass();
23847			this._trigger( "over", event, this.ui( draggable ) );
23848		}
23849
23850	},
23851
23852	_out: function( event ) {
23853
23854		var draggable = $.ui.ddmanager.current;
23855
23856		// Bail if draggable and droppable are same element
23857		if ( !draggable || ( draggable.currentItem ||
23858				draggable.element )[ 0 ] === this.element[ 0 ] ) {
23859			return;
23860		}
23861
23862		if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem ||
23863				draggable.element ) ) ) {
23864			this._removeHoverClass();
23865			this._trigger( "out", event, this.ui( draggable ) );
23866		}
23867
23868	},
23869
23870	_drop: function( event, custom ) {
23871
23872		var draggable = custom || $.ui.ddmanager.current,
23873			childrenIntersection = false;
23874
23875		// Bail if draggable and droppable are same element
23876		if ( !draggable || ( draggable.currentItem ||
23877				draggable.element )[ 0 ] === this.element[ 0 ] ) {
23878			return false;
23879		}
23880
23881		this.element
23882			.find( ":data(ui-droppable)" )
23883			.not( ".ui-draggable-dragging" )
23884			.each( function() {
23885				var inst = $( this ).droppable( "instance" );
23886				if (
23887					inst.options.greedy &&
23888					!inst.options.disabled &&
23889					inst.options.scope === draggable.options.scope &&
23890					inst.accept.call(
23891						inst.element[ 0 ], ( draggable.currentItem || draggable.element )
23892					) &&
23893					$.ui.intersect(
23894						draggable,
23895						$.extend( inst, { offset: inst.element.offset() } ),
23896						inst.options.tolerance, event
23897					)
23898				) {
23899					childrenIntersection = true;
23900					return false;
23901				}
23902			} );
23903		if ( childrenIntersection ) {
23904			return false;
23905		}
23906
23907		if ( this.accept.call( this.element[ 0 ],
23908				( draggable.currentItem || draggable.element ) ) ) {
23909			this._removeActiveClass();
23910			this._removeHoverClass();
23911
23912			this._trigger( "drop", event, this.ui( draggable ) );
23913			return this.element;
23914		}
23915
23916		return false;
23917
23918	},
23919
23920	ui: function( c ) {
23921		return {
23922			draggable: ( c.currentItem || c.element ),
23923			helper: c.helper,
23924			position: c.position,
23925			offset: c.positionAbs
23926		};
23927	},
23928
23929	// Extension points just to make backcompat sane and avoid duplicating logic
23930	// TODO: Remove in 1.14 along with call to it below
23931	_addHoverClass: function() {
23932		this._addClass( "ui-droppable-hover" );
23933	},
23934
23935	_removeHoverClass: function() {
23936		this._removeClass( "ui-droppable-hover" );
23937	},
23938
23939	_addActiveClass: function() {
23940		this._addClass( "ui-droppable-active" );
23941	},
23942
23943	_removeActiveClass: function() {
23944		this._removeClass( "ui-droppable-active" );
23945	}
23946} );
23947
23948$.ui.intersect = ( function() {
23949	function isOverAxis( x, reference, size ) {
23950		return ( x >= reference ) && ( x < ( reference + size ) );
23951	}
23952
23953	return function( draggable, droppable, toleranceMode, event ) {
23954
23955		if ( !droppable.offset ) {
23956			return false;
23957		}
23958
23959		var x1 = ( draggable.positionAbs ||
23960				draggable.position.absolute ).left + draggable.margins.left,
23961			y1 = ( draggable.positionAbs ||
23962				draggable.position.absolute ).top + draggable.margins.top,
23963			x2 = x1 + draggable.helperProportions.width,
23964			y2 = y1 + draggable.helperProportions.height,
23965			l = droppable.offset.left,
23966			t = droppable.offset.top,
23967			r = l + droppable.proportions().width,
23968			b = t + droppable.proportions().height;
23969
23970		switch ( toleranceMode ) {
23971		case "fit":
23972			return ( l <= x1 && x2 <= r && t <= y1 && y2 <= b );
23973		case "intersect":
23974			return ( l < x1 + ( draggable.helperProportions.width / 2 ) && // Right Half
23975				x2 - ( draggable.helperProportions.width / 2 ) < r && // Left Half
23976				t < y1 + ( draggable.helperProportions.height / 2 ) && // Bottom Half
23977				y2 - ( draggable.helperProportions.height / 2 ) < b ); // Top Half
23978		case "pointer":
23979			return isOverAxis( event.pageY, t, droppable.proportions().height ) &&
23980				isOverAxis( event.pageX, l, droppable.proportions().width );
23981		case "touch":
23982			return (
23983				( y1 >= t && y1 <= b ) || // Top edge touching
23984				( y2 >= t && y2 <= b ) || // Bottom edge touching
23985				( y1 < t && y2 > b ) // Surrounded vertically
23986			) && (
23987				( x1 >= l && x1 <= r ) || // Left edge touching
23988				( x2 >= l && x2 <= r ) || // Right edge touching
23989				( x1 < l && x2 > r ) // Surrounded horizontally
23990			);
23991		default:
23992			return false;
23993		}
23994	};
23995} )();
23996
23997/*
23998	This manager tracks offsets of draggables and droppables
23999*/
24000$.ui.ddmanager = {
24001	current: null,
24002	droppables: { "default": [] },
24003	prepareOffsets: function( t, event ) {
24004
24005		var i, j,
24006			m = $.ui.ddmanager.droppables[ t.options.scope ] || [],
24007			type = event ? event.type : null, // workaround for #2317
24008			list = ( t.currentItem || t.element ).find( ":data(ui-droppable)" ).addBack();
24009
24010		droppablesLoop: for ( i = 0; i < m.length; i++ ) {
24011
24012			// No disabled and non-accepted
24013			if ( m[ i ].options.disabled || ( t && !m[ i ].accept.call( m[ i ].element[ 0 ],
24014					( t.currentItem || t.element ) ) ) ) {
24015				continue;
24016			}
24017
24018			// Filter out elements in the current dragged item
24019			for ( j = 0; j < list.length; j++ ) {
24020				if ( list[ j ] === m[ i ].element[ 0 ] ) {
24021					m[ i ].proportions().height = 0;
24022					continue droppablesLoop;
24023				}
24024			}
24025
24026			m[ i ].visible = m[ i ].element.css( "display" ) !== "none";
24027			if ( !m[ i ].visible ) {
24028				continue;
24029			}
24030
24031			// Activate the droppable if used directly from draggables
24032			if ( type === "mousedown" ) {
24033				m[ i ]._activate.call( m[ i ], event );
24034			}
24035
24036			m[ i ].offset = m[ i ].element.offset();
24037			m[ i ].proportions( {
24038				width: m[ i ].element[ 0 ].offsetWidth,
24039				height: m[ i ].element[ 0 ].offsetHeight
24040			} );
24041
24042		}
24043
24044	},
24045	drop: function( draggable, event ) {
24046
24047		var dropped = false;
24048
24049		// Create a copy of the droppables in case the list changes during the drop (#9116)
24050		$.each( ( $.ui.ddmanager.droppables[ draggable.options.scope ] || [] ).slice(), function() {
24051
24052			if ( !this.options ) {
24053				return;
24054			}
24055			if ( !this.options.disabled && this.visible &&
24056					$.ui.intersect( draggable, this, this.options.tolerance, event ) ) {
24057				dropped = this._drop.call( this, event ) || dropped;
24058			}
24059
24060			if ( !this.options.disabled && this.visible && this.accept.call( this.element[ 0 ],
24061					( draggable.currentItem || draggable.element ) ) ) {
24062				this.isout = true;
24063				this.isover = false;
24064				this._deactivate.call( this, event );
24065			}
24066
24067		} );
24068		return dropped;
24069
24070	},
24071	dragStart: function( draggable, event ) {
24072
24073		// Listen for scrolling so that if the dragging causes scrolling the position of the
24074		// droppables can be recalculated (see #5003)
24075		draggable.element.parentsUntil( "body" ).on( "scroll.droppable", function() {
24076			if ( !draggable.options.refreshPositions ) {
24077				$.ui.ddmanager.prepareOffsets( draggable, event );
24078			}
24079		} );
24080	},
24081	drag: function( draggable, event ) {
24082
24083		// If you have a highly dynamic page, you might try this option. It renders positions
24084		// every time you move the mouse.
24085		if ( draggable.options.refreshPositions ) {
24086			$.ui.ddmanager.prepareOffsets( draggable, event );
24087		}
24088
24089		// Run through all droppables and check their positions based on specific tolerance options
24090		$.each( $.ui.ddmanager.droppables[ draggable.options.scope ] || [], function() {
24091
24092			if ( this.options.disabled || this.greedyChild || !this.visible ) {
24093				return;
24094			}
24095
24096			var parentInstance, scope, parent,
24097				intersects = $.ui.intersect( draggable, this, this.options.tolerance, event ),
24098				c = !intersects && this.isover ?
24099					"isout" :
24100					( intersects && !this.isover ? "isover" : null );
24101			if ( !c ) {
24102				return;
24103			}
24104
24105			if ( this.options.greedy ) {
24106
24107				// find droppable parents with same scope
24108				scope = this.options.scope;
24109				parent = this.element.parents( ":data(ui-droppable)" ).filter( function() {
24110					return $( this ).droppable( "instance" ).options.scope === scope;
24111				} );
24112
24113				if ( parent.length ) {
24114					parentInstance = $( parent[ 0 ] ).droppable( "instance" );
24115					parentInstance.greedyChild = ( c === "isover" );
24116				}
24117			}
24118
24119			// We just moved into a greedy child
24120			if ( parentInstance && c === "isover" ) {
24121				parentInstance.isover = false;
24122				parentInstance.isout = true;
24123				parentInstance._out.call( parentInstance, event );
24124			}
24125
24126			this[ c ] = true;
24127			this[ c === "isout" ? "isover" : "isout" ] = false;
24128			this[ c === "isover" ? "_over" : "_out" ].call( this, event );
24129
24130			// We just moved out of a greedy child
24131			if ( parentInstance && c === "isout" ) {
24132				parentInstance.isout = false;
24133				parentInstance.isover = true;
24134				parentInstance._over.call( parentInstance, event );
24135			}
24136		} );
24137
24138	},
24139	dragStop: function( draggable, event ) {
24140		draggable.element.parentsUntil( "body" ).off( "scroll.droppable" );
24141
24142		// Call prepareOffsets one final time since IE does not fire return scroll events when
24143		// overflow was caused by drag (see #5003)
24144		if ( !draggable.options.refreshPositions ) {
24145			$.ui.ddmanager.prepareOffsets( draggable, event );
24146		}
24147	}
24148};
24149
24150// DEPRECATED
24151// TODO: switch return back to widget declaration at top of file when this is removed
24152if ( $.uiBackCompat === true ) {
24153
24154	// Backcompat for activeClass and hoverClass options
24155	$.widget( "ui.droppable", $.ui.droppable, {
24156		options: {
24157			hoverClass: false,
24158			activeClass: false
24159		},
24160		_addActiveClass: function() {
24161			this._super();
24162			if ( this.options.activeClass ) {
24163				this.element.addClass( this.options.activeClass );
24164			}
24165		},
24166		_removeActiveClass: function() {
24167			this._super();
24168			if ( this.options.activeClass ) {
24169				this.element.removeClass( this.options.activeClass );
24170			}
24171		},
24172		_addHoverClass: function() {
24173			this._super();
24174			if ( this.options.hoverClass ) {
24175				this.element.addClass( this.options.hoverClass );
24176			}
24177		},
24178		_removeHoverClass: function() {
24179			this._super();
24180			if ( this.options.hoverClass ) {
24181				this.element.removeClass( this.options.hoverClass );
24182			}
24183		}
24184	} );
24185}
24186
24187var widgetsDroppable = $.ui.droppable;
24188
24189
24190/*!
24191 * jQuery UI Progressbar 1.14.1
24192 * https://jqueryui.com
24193 *
24194 * Copyright OpenJS Foundation and other contributors
24195 * Released under the MIT license.
24196 * https://jquery.org/license
24197 */
24198
24199//>>label: Progressbar
24200//>>group: Widgets
24201/* eslint-disable max-len */
24202//>>description: Displays a status indicator for loading state, standard percentage, and other progress indicators.
24203/* eslint-enable max-len */
24204//>>docs: https://api.jqueryui.com/progressbar/
24205//>>demos: https://jqueryui.com/progressbar/
24206//>>css.structure: ../../themes/base/core.css
24207//>>css.structure: ../../themes/base/progressbar.css
24208//>>css.theme: ../../themes/base/theme.css
24209
24210
24211var widgetsProgressbar = $.widget( "ui.progressbar", {
24212	version: "1.14.1",
24213	options: {
24214		classes: {
24215			"ui-progressbar": "ui-corner-all",
24216			"ui-progressbar-value": "ui-corner-left",
24217			"ui-progressbar-complete": "ui-corner-right"
24218		},
24219		max: 100,
24220		value: 0,
24221
24222		change: null,
24223		complete: null
24224	},
24225
24226	min: 0,
24227
24228	_create: function() {
24229
24230		// Constrain initial value
24231		this.oldValue = this.options.value = this._constrainedValue();
24232
24233		this.element.attr( {
24234
24235			// Only set static values; aria-valuenow and aria-valuemax are
24236			// set inside _refreshValue()
24237			role: "progressbar",
24238			"aria-valuemin": this.min
24239		} );
24240		this._addClass( "ui-progressbar", "ui-widget ui-widget-content" );
24241
24242		this.valueDiv = $( "<div>" ).appendTo( this.element );
24243		this._addClass( this.valueDiv, "ui-progressbar-value", "ui-widget-header" );
24244		this._refreshValue();
24245	},
24246
24247	_destroy: function() {
24248		this.element.removeAttr( "role aria-valuemin aria-valuemax aria-valuenow" );
24249
24250		this.valueDiv.remove();
24251	},
24252
24253	value: function( newValue ) {
24254		if ( newValue === undefined ) {
24255			return this.options.value;
24256		}
24257
24258		this.options.value = this._constrainedValue( newValue );
24259		this._refreshValue();
24260	},
24261
24262	_constrainedValue: function( newValue ) {
24263		if ( newValue === undefined ) {
24264			newValue = this.options.value;
24265		}
24266
24267		this.indeterminate = newValue === false;
24268
24269		// Sanitize value
24270		if ( typeof newValue !== "number" ) {
24271			newValue = 0;
24272		}
24273
24274		return this.indeterminate ? false :
24275			Math.min( this.options.max, Math.max( this.min, newValue ) );
24276	},
24277
24278	_setOptions: function( options ) {
24279
24280		// Ensure "value" option is set after other values (like max)
24281		var value = options.value;
24282		delete options.value;
24283
24284		this._super( options );
24285
24286		this.options.value = this._constrainedValue( value );
24287		this._refreshValue();
24288	},
24289
24290	_setOption: function( key, value ) {
24291		if ( key === "max" ) {
24292
24293			// Don't allow a max less than min
24294			value = Math.max( this.min, value );
24295		}
24296		this._super( key, value );
24297	},
24298
24299	_setOptionDisabled: function( value ) {
24300		this._super( value );
24301
24302		this.element.attr( "aria-disabled", value );
24303		this._toggleClass( null, "ui-state-disabled", !!value );
24304	},
24305
24306	_percentage: function() {
24307		return this.indeterminate ?
24308			100 :
24309			100 * ( this.options.value - this.min ) / ( this.options.max - this.min );
24310	},
24311
24312	_refreshValue: function() {
24313		var value = this.options.value,
24314			percentage = this._percentage();
24315
24316		this.valueDiv
24317			.toggle( this.indeterminate || value > this.min )
24318			.width( percentage.toFixed( 0 ) + "%" );
24319
24320		this
24321			._toggleClass( this.valueDiv, "ui-progressbar-complete", null,
24322				value === this.options.max )
24323			._toggleClass( "ui-progressbar-indeterminate", null, this.indeterminate );
24324
24325		if ( this.indeterminate ) {
24326			this.element.removeAttr( "aria-valuenow" );
24327			if ( !this.overlayDiv ) {
24328				this.overlayDiv = $( "<div>" ).appendTo( this.valueDiv );
24329				this._addClass( this.overlayDiv, "ui-progressbar-overlay" );
24330			}
24331		} else {
24332			this.element.attr( {
24333				"aria-valuemax": this.options.max,
24334				"aria-valuenow": value
24335			} );
24336			if ( this.overlayDiv ) {
24337				this.overlayDiv.remove();
24338				this.overlayDiv = null;
24339			}
24340		}
24341
24342		if ( this.oldValue !== value ) {
24343			this.oldValue = value;
24344			this._trigger( "change" );
24345		}
24346		if ( value === this.options.max ) {
24347			this._trigger( "complete" );
24348		}
24349	}
24350} );
24351
24352
24353/*!
24354 * jQuery UI Selectable 1.14.1
24355 * https://jqueryui.com
24356 *
24357 * Copyright OpenJS Foundation and other contributors
24358 * Released under the MIT license.
24359 * https://jquery.org/license
24360 */
24361
24362//>>label: Selectable
24363//>>group: Interactions
24364//>>description: Allows groups of elements to be selected with the mouse.
24365//>>docs: https://api.jqueryui.com/selectable/
24366//>>demos: https://jqueryui.com/selectable/
24367//>>css.structure: ../../themes/base/selectable.css
24368
24369
24370var widgetsSelectable = $.widget( "ui.selectable", $.ui.mouse, {
24371	version: "1.14.1",
24372	options: {
24373		appendTo: "body",
24374		autoRefresh: true,
24375		distance: 0,
24376		filter: "*",
24377		tolerance: "touch",
24378
24379		// Callbacks
24380		selected: null,
24381		selecting: null,
24382		start: null,
24383		stop: null,
24384		unselected: null,
24385		unselecting: null
24386	},
24387	_create: function() {
24388		var that = this;
24389
24390		this._addClass( "ui-selectable" );
24391
24392		this.dragged = false;
24393
24394		// Cache selectee children based on filter
24395		this.refresh = function() {
24396			that.elementPos = $( that.element[ 0 ] ).offset();
24397			that.selectees = $( that.options.filter, that.element[ 0 ] );
24398			that._addClass( that.selectees, "ui-selectee" );
24399			that.selectees.each( function() {
24400				var $this = $( this ),
24401					selecteeOffset = $this.offset(),
24402					pos = {
24403						left: selecteeOffset.left - that.elementPos.left,
24404						top: selecteeOffset.top - that.elementPos.top
24405					};
24406				$.data( this, "selectable-item", {
24407					element: this,
24408					$element: $this,
24409					left: pos.left,
24410					top: pos.top,
24411					right: pos.left + $this.outerWidth(),
24412					bottom: pos.top + $this.outerHeight(),
24413					startselected: false,
24414					selected: $this.hasClass( "ui-selected" ),
24415					selecting: $this.hasClass( "ui-selecting" ),
24416					unselecting: $this.hasClass( "ui-unselecting" )
24417				} );
24418			} );
24419		};
24420		this.refresh();
24421
24422		this._mouseInit();
24423
24424		this.helper = $( "<div>" );
24425		this._addClass( this.helper, "ui-selectable-helper" );
24426	},
24427
24428	_destroy: function() {
24429		this.selectees.removeData( "selectable-item" );
24430		this._mouseDestroy();
24431	},
24432
24433	_mouseStart: function( event ) {
24434		var that = this,
24435			options = this.options;
24436
24437		this.opos = [ event.pageX, event.pageY ];
24438		this.elementPos = $( this.element[ 0 ] ).offset();
24439
24440		if ( this.options.disabled ) {
24441			return;
24442		}
24443
24444		this.selectees = $( options.filter, this.element[ 0 ] );
24445
24446		this._trigger( "start", event );
24447
24448		$( options.appendTo ).append( this.helper );
24449
24450		// position helper (lasso)
24451		this.helper.css( {
24452			"left": event.pageX,
24453			"top": event.pageY,
24454			"width": 0,
24455			"height": 0
24456		} );
24457
24458		if ( options.autoRefresh ) {
24459			this.refresh();
24460		}
24461
24462		this.selectees.filter( ".ui-selected" ).each( function() {
24463			var selectee = $.data( this, "selectable-item" );
24464			selectee.startselected = true;
24465			if ( !event.metaKey && !event.ctrlKey ) {
24466				that._removeClass( selectee.$element, "ui-selected" );
24467				selectee.selected = false;
24468				that._addClass( selectee.$element, "ui-unselecting" );
24469				selectee.unselecting = true;
24470
24471				// selectable UNSELECTING callback
24472				that._trigger( "unselecting", event, {
24473					unselecting: selectee.element
24474				} );
24475			}
24476		} );
24477
24478		$( event.target ).parents().addBack().each( function() {
24479			var doSelect,
24480				selectee = $.data( this, "selectable-item" );
24481			if ( selectee ) {
24482				doSelect = ( !event.metaKey && !event.ctrlKey ) ||
24483					!selectee.$element.hasClass( "ui-selected" );
24484				that._removeClass( selectee.$element, doSelect ? "ui-unselecting" : "ui-selected" )
24485					._addClass( selectee.$element, doSelect ? "ui-selecting" : "ui-unselecting" );
24486				selectee.unselecting = !doSelect;
24487				selectee.selecting = doSelect;
24488				selectee.selected = doSelect;
24489
24490				// selectable (UN)SELECTING callback
24491				if ( doSelect ) {
24492					that._trigger( "selecting", event, {
24493						selecting: selectee.element
24494					} );
24495				} else {
24496					that._trigger( "unselecting", event, {
24497						unselecting: selectee.element
24498					} );
24499				}
24500				return false;
24501			}
24502		} );
24503
24504	},
24505
24506	_mouseDrag: function( event ) {
24507
24508		this.dragged = true;
24509
24510		if ( this.options.disabled ) {
24511			return;
24512		}
24513
24514		var tmp,
24515			that = this,
24516			options = this.options,
24517			x1 = this.opos[ 0 ],
24518			y1 = this.opos[ 1 ],
24519			x2 = event.pageX,
24520			y2 = event.pageY;
24521
24522		if ( x1 > x2 ) {
24523			tmp = x2; x2 = x1; x1 = tmp;
24524		}
24525		if ( y1 > y2 ) {
24526			tmp = y2; y2 = y1; y1 = tmp;
24527		}
24528		this.helper.css( { left: x1, top: y1, width: x2 - x1, height: y2 - y1 } );
24529
24530		this.selectees.each( function() {
24531			var selectee = $.data( this, "selectable-item" ),
24532				hit = false,
24533				offset = {};
24534
24535			//prevent helper from being selected if appendTo: selectable
24536			if ( !selectee || selectee.element === that.element[ 0 ] ) {
24537				return;
24538			}
24539
24540			offset.left   = selectee.left   + that.elementPos.left;
24541			offset.right  = selectee.right  + that.elementPos.left;
24542			offset.top    = selectee.top    + that.elementPos.top;
24543			offset.bottom = selectee.bottom + that.elementPos.top;
24544
24545			if ( options.tolerance === "touch" ) {
24546				hit = ( !( offset.left > x2 || offset.right < x1 || offset.top > y2 ||
24547                    offset.bottom < y1 ) );
24548			} else if ( options.tolerance === "fit" ) {
24549				hit = ( offset.left > x1 && offset.right < x2 && offset.top > y1 &&
24550                    offset.bottom < y2 );
24551			}
24552
24553			if ( hit ) {
24554
24555				// SELECT
24556				if ( selectee.selected ) {
24557					that._removeClass( selectee.$element, "ui-selected" );
24558					selectee.selected = false;
24559				}
24560				if ( selectee.unselecting ) {
24561					that._removeClass( selectee.$element, "ui-unselecting" );
24562					selectee.unselecting = false;
24563				}
24564				if ( !selectee.selecting ) {
24565					that._addClass( selectee.$element, "ui-selecting" );
24566					selectee.selecting = true;
24567
24568					// selectable SELECTING callback
24569					that._trigger( "selecting", event, {
24570						selecting: selectee.element
24571					} );
24572				}
24573			} else {
24574
24575				// UNSELECT
24576				if ( selectee.selecting ) {
24577					if ( ( event.metaKey || event.ctrlKey ) && selectee.startselected ) {
24578						that._removeClass( selectee.$element, "ui-selecting" );
24579						selectee.selecting = false;
24580						that._addClass( selectee.$element, "ui-selected" );
24581						selectee.selected = true;
24582					} else {
24583						that._removeClass( selectee.$element, "ui-selecting" );
24584						selectee.selecting = false;
24585						if ( selectee.startselected ) {
24586							that._addClass( selectee.$element, "ui-unselecting" );
24587							selectee.unselecting = true;
24588						}
24589
24590						// selectable UNSELECTING callback
24591						that._trigger( "unselecting", event, {
24592							unselecting: selectee.element
24593						} );
24594					}
24595				}
24596				if ( selectee.selected ) {
24597					if ( !event.metaKey && !event.ctrlKey && !selectee.startselected ) {
24598						that._removeClass( selectee.$element, "ui-selected" );
24599						selectee.selected = false;
24600
24601						that._addClass( selectee.$element, "ui-unselecting" );
24602						selectee.unselecting = true;
24603
24604						// selectable UNSELECTING callback
24605						that._trigger( "unselecting", event, {
24606							unselecting: selectee.element
24607						} );
24608					}
24609				}
24610			}
24611		} );
24612
24613		return false;
24614	},
24615
24616	_mouseStop: function( event ) {
24617		var that = this;
24618
24619		this.dragged = false;
24620
24621		$( ".ui-unselecting", this.element[ 0 ] ).each( function() {
24622			var selectee = $.data( this, "selectable-item" );
24623			that._removeClass( selectee.$element, "ui-unselecting" );
24624			selectee.unselecting = false;
24625			selectee.startselected = false;
24626			that._trigger( "unselected", event, {
24627				unselected: selectee.element
24628			} );
24629		} );
24630		$( ".ui-selecting", this.element[ 0 ] ).each( function() {
24631			var selectee = $.data( this, "selectable-item" );
24632			that._removeClass( selectee.$element, "ui-selecting" )
24633				._addClass( selectee.$element, "ui-selected" );
24634			selectee.selecting = false;
24635			selectee.selected = true;
24636			selectee.startselected = true;
24637			that._trigger( "selected", event, {
24638				selected: selectee.element
24639			} );
24640		} );
24641		this._trigger( "stop", event );
24642
24643		this.helper.remove();
24644
24645		return false;
24646	}
24647
24648} );
24649
24650
24651/*!
24652 * jQuery UI Selectmenu 1.14.1
24653 * https://jqueryui.com
24654 *
24655 * Copyright OpenJS Foundation and other contributors
24656 * Released under the MIT license.
24657 * https://jquery.org/license
24658 */
24659
24660//>>label: Selectmenu
24661//>>group: Widgets
24662/* eslint-disable max-len */
24663//>>description: Duplicates and extends the functionality of a native HTML select element, allowing it to be customizable in behavior and appearance far beyond the limitations of a native select.
24664/* eslint-enable max-len */
24665//>>docs: https://api.jqueryui.com/selectmenu/
24666//>>demos: https://jqueryui.com/selectmenu/
24667//>>css.structure: ../../themes/base/core.css
24668//>>css.structure: ../../themes/base/selectmenu.css, ../../themes/base/button.css
24669//>>css.theme: ../../themes/base/theme.css
24670
24671
24672var widgetsSelectmenu = $.widget( "ui.selectmenu", [ $.ui.formResetMixin, {
24673	version: "1.14.1",
24674	defaultElement: "<select>",
24675	options: {
24676		appendTo: null,
24677		classes: {
24678			"ui-selectmenu-button-open": "ui-corner-top",
24679			"ui-selectmenu-button-closed": "ui-corner-all"
24680		},
24681		disabled: null,
24682		icons: {
24683			button: "ui-icon-triangle-1-s"
24684		},
24685		position: {
24686			my: "left top",
24687			at: "left bottom",
24688			collision: "none"
24689		},
24690		width: false,
24691
24692		// Callbacks
24693		change: null,
24694		close: null,
24695		focus: null,
24696		open: null,
24697		select: null
24698	},
24699
24700	_create: function() {
24701		var selectmenuId = this.element.uniqueId().attr( "id" );
24702		this.ids = {
24703			element: selectmenuId,
24704			button: selectmenuId + "-button",
24705			menu: selectmenuId + "-menu"
24706		};
24707
24708		this._drawButton();
24709		this._drawMenu();
24710		this._bindFormResetHandler();
24711
24712		this._rendered = false;
24713		this.menuItems = $();
24714	},
24715
24716	_drawButton: function() {
24717		var icon,
24718			that = this,
24719			item = this._parseOption(
24720				this.element.find( "option:selected" ),
24721				this.element[ 0 ].selectedIndex
24722			);
24723
24724		// Associate existing label with the new button
24725		this.labels = this.element.labels().attr( "for", this.ids.button );
24726		this._on( this.labels, {
24727			click: function( event ) {
24728				this.button.trigger( "focus" );
24729				event.preventDefault();
24730			}
24731		} );
24732
24733		// Hide original select element
24734		this.element.hide();
24735
24736		// Create button
24737		this.button = $( "<span>", {
24738			tabindex: this.options.disabled ? -1 : 0,
24739			id: this.ids.button,
24740			role: "combobox",
24741			"aria-expanded": "false",
24742			"aria-autocomplete": "list",
24743			"aria-owns": this.ids.menu,
24744			"aria-haspopup": "true",
24745			title: this.element.attr( "title" )
24746		} )
24747			.insertAfter( this.element );
24748
24749		this._addClass( this.button, "ui-selectmenu-button ui-selectmenu-button-closed",
24750			"ui-button ui-widget" );
24751
24752		icon = $( "<span>" ).appendTo( this.button );
24753		this._addClass( icon, "ui-selectmenu-icon", "ui-icon " + this.options.icons.button );
24754		this.buttonItem = this._renderButtonItem( item )
24755			.appendTo( this.button );
24756
24757		if ( this.options.width !== false ) {
24758			this._resizeButton();
24759		}
24760
24761		this._on( this.button, this._buttonEvents );
24762		this.button.one( "focusin", function() {
24763
24764			// Delay rendering the menu items until the button receives focus.
24765			// The menu may have already been rendered via a programmatic open.
24766			if ( !that._rendered ) {
24767				that._refreshMenu();
24768			}
24769		} );
24770	},
24771
24772	_drawMenu: function() {
24773		var that = this;
24774
24775		// Create menu
24776		this.menu = $( "<ul>", {
24777			"aria-hidden": "true",
24778			"aria-labelledby": this.ids.button,
24779			id: this.ids.menu
24780		} );
24781
24782		// Wrap menu
24783		this.menuWrap = $( "<div>" ).append( this.menu );
24784		this._addClass( this.menuWrap, "ui-selectmenu-menu", "ui-front" );
24785		this.menuWrap.appendTo( this._appendTo() );
24786
24787		// Initialize menu widget
24788		this.menuInstance = this.menu
24789			.menu( {
24790				classes: {
24791					"ui-menu": "ui-corner-bottom"
24792				},
24793				role: "listbox",
24794				select: function( event, ui ) {
24795					event.preventDefault();
24796					that._select( ui.item.data( "ui-selectmenu-item" ), event );
24797				},
24798				focus: function( event, ui ) {
24799					var item = ui.item.data( "ui-selectmenu-item" );
24800
24801					// Prevent inital focus from firing and check if its a newly focused item
24802					if ( that.focusIndex != null && item.index !== that.focusIndex ) {
24803						that._trigger( "focus", event, { item: item } );
24804						if ( !that.isOpen ) {
24805							that._select( item, event );
24806						}
24807					}
24808					that.focusIndex = item.index;
24809
24810					that.button.attr( "aria-activedescendant",
24811						that.menuItems.eq( item.index ).attr( "id" ) );
24812				}
24813			} )
24814			.menu( "instance" );
24815
24816		// Don't close the menu on mouseleave
24817		this.menuInstance._off( this.menu, "mouseleave" );
24818
24819		// Cancel the menu's collapseAll on document click
24820		this.menuInstance._closeOnDocumentClick = function() {
24821			return false;
24822		};
24823
24824		// Selects often contain empty items, but never contain dividers
24825		this.menuInstance._isDivider = function() {
24826			return false;
24827		};
24828	},
24829
24830	refresh: function() {
24831		this._refreshMenu();
24832		this.buttonItem.replaceWith(
24833			this.buttonItem = this._renderButtonItem(
24834
24835				// Fall back to an empty object in case there are no options
24836				this._getSelectedItem().data( "ui-selectmenu-item" ) || {}
24837			)
24838		);
24839		if ( this.options.width === null ) {
24840			this._resizeButton();
24841		}
24842	},
24843
24844	_refreshMenu: function() {
24845		var item,
24846			options = this.element.find( "option" );
24847
24848		this.menu.empty();
24849
24850		this._parseOptions( options );
24851		this._renderMenu( this.menu, this.items );
24852
24853		this.menuInstance.refresh();
24854		this.menuItems = this.menu.find( "li" )
24855			.not( ".ui-selectmenu-optgroup" )
24856				.find( ".ui-menu-item-wrapper" );
24857
24858		this._rendered = true;
24859
24860		if ( !options.length ) {
24861			return;
24862		}
24863
24864		item = this._getSelectedItem();
24865
24866		// Update the menu to have the correct item focused
24867		this.menuInstance.focus( null, item );
24868		this._setAria( item.data( "ui-selectmenu-item" ) );
24869
24870		// Set disabled state
24871		this._setOption( "disabled", this.element.prop( "disabled" ) );
24872	},
24873
24874	open: function( event ) {
24875		if ( this.options.disabled ) {
24876			return;
24877		}
24878
24879		// If this is the first time the menu is being opened, render the items
24880		if ( !this._rendered ) {
24881			this._refreshMenu();
24882		} else {
24883
24884			// Menu clears focus on close, reset focus to selected item
24885			this._removeClass( this.menu.find( ".ui-state-active" ), null, "ui-state-active" );
24886			this.menuInstance.focus( null, this._getSelectedItem() );
24887		}
24888
24889		// If there are no options, don't open the menu
24890		if ( !this.menuItems.length ) {
24891			return;
24892		}
24893
24894		this.isOpen = true;
24895		this._toggleAttr();
24896		this._resizeMenu();
24897		this._position();
24898
24899		this._on( this.document, this._documentClick );
24900
24901		this._trigger( "open", event );
24902	},
24903
24904	_position: function() {
24905		this.menuWrap.position( $.extend( { of: this.button }, this.options.position ) );
24906	},
24907
24908	close: function( event ) {
24909		if ( !this.isOpen ) {
24910			return;
24911		}
24912
24913		this.isOpen = false;
24914		this._toggleAttr();
24915
24916		this.range = null;
24917		this._off( this.document );
24918
24919		this._trigger( "close", event );
24920	},
24921
24922	widget: function() {
24923		return this.button;
24924	},
24925
24926	menuWidget: function() {
24927		return this.menu;
24928	},
24929
24930	_renderButtonItem: function( item ) {
24931		var buttonItem = $( "<span>" );
24932
24933		this._setText( buttonItem, item.label );
24934		this._addClass( buttonItem, "ui-selectmenu-text" );
24935
24936		return buttonItem;
24937	},
24938
24939	_renderMenu: function( ul, items ) {
24940		var that = this,
24941			currentOptgroup = "";
24942
24943		$.each( items, function( index, item ) {
24944			var li;
24945
24946			if ( item.optgroup !== currentOptgroup ) {
24947				li = $( "<li>", {
24948					text: item.optgroup
24949				} );
24950				that._addClass( li, "ui-selectmenu-optgroup", "ui-menu-divider" +
24951					( item.element.parent( "optgroup" ).prop( "disabled" ) ?
24952						" ui-state-disabled" :
24953						"" ) );
24954
24955				li.appendTo( ul );
24956
24957				currentOptgroup = item.optgroup;
24958			}
24959
24960			that._renderItemData( ul, item );
24961		} );
24962	},
24963
24964	_renderItemData: function( ul, item ) {
24965		return this._renderItem( ul, item ).data( "ui-selectmenu-item", item );
24966	},
24967
24968	_renderItem: function( ul, item ) {
24969		var li = $( "<li>" ),
24970			wrapper = $( "<div>", {
24971				title: item.element.attr( "title" )
24972			} );
24973
24974		if ( item.disabled ) {
24975			this._addClass( li, null, "ui-state-disabled" );
24976		}
24977
24978		if ( item.hidden ) {
24979			li.prop( "hidden", true );
24980		} else {
24981			this._setText( wrapper, item.label );
24982		}
24983
24984		return li.append( wrapper ).appendTo( ul );
24985	},
24986
24987	_setText: function( element, value ) {
24988		if ( value ) {
24989			element.text( value );
24990		} else {
24991			element.html( "&#160;" );
24992		}
24993	},
24994
24995	_move: function( direction, event ) {
24996		var item, next,
24997			filter = ".ui-menu-item";
24998
24999		if ( this.isOpen ) {
25000			item = this.menuItems.eq( this.focusIndex ).parent( "li" );
25001		} else {
25002			item = this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( "li" );
25003			filter += ":not(.ui-state-disabled)";
25004		}
25005
25006		if ( direction === "first" || direction === "last" ) {
25007			next = item[ direction === "first" ? "prevAll" : "nextAll" ]( filter ).eq( -1 );
25008		} else {
25009			next = item[ direction + "All" ]( filter ).eq( 0 );
25010		}
25011
25012		if ( next.length ) {
25013			this.menuInstance.focus( event, next );
25014		}
25015	},
25016
25017	_getSelectedItem: function() {
25018		return this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( "li" );
25019	},
25020
25021	_toggle: function( event ) {
25022		this[ this.isOpen ? "close" : "open" ]( event );
25023	},
25024
25025	_setSelection: function() {
25026		var selection;
25027
25028		if ( !this.range ) {
25029			return;
25030		}
25031
25032		selection = window.getSelection();
25033		selection.removeAllRanges();
25034		selection.addRange( this.range );
25035	},
25036
25037	_documentClick: {
25038		mousedown: function( event ) {
25039			if ( !this.isOpen ) {
25040				return;
25041			}
25042
25043			if ( !$( event.target ).closest( ".ui-selectmenu-menu, #" +
25044				CSS.escape( this.ids.button ) ).length ) {
25045				this.close( event );
25046			}
25047		}
25048	},
25049
25050	_buttonEvents: {
25051
25052		// Prevent text selection from being reset when interacting with the selectmenu (#10144)
25053		mousedown: function() {
25054			var selection = window.getSelection();
25055			if ( selection.rangeCount ) {
25056				this.range = selection.getRangeAt( 0 );
25057			}
25058		},
25059
25060		click: function( event ) {
25061			this._setSelection();
25062			this._toggle( event );
25063		},
25064
25065		keydown: function( event ) {
25066			var preventDefault = true;
25067			switch ( event.keyCode ) {
25068			case $.ui.keyCode.TAB:
25069			case $.ui.keyCode.ESCAPE:
25070				this.close( event );
25071				preventDefault = false;
25072				break;
25073			case $.ui.keyCode.ENTER:
25074				if ( this.isOpen ) {
25075					this._selectFocusedItem( event );
25076				}
25077				break;
25078			case $.ui.keyCode.UP:
25079				if ( event.altKey ) {
25080					this._toggle( event );
25081				} else {
25082					this._move( "prev", event );
25083				}
25084				break;
25085			case $.ui.keyCode.DOWN:
25086				if ( event.altKey ) {
25087					this._toggle( event );
25088				} else {
25089					this._move( "next", event );
25090				}
25091				break;
25092			case $.ui.keyCode.SPACE:
25093				if ( this.isOpen ) {
25094					this._selectFocusedItem( event );
25095				} else {
25096					this._toggle( event );
25097				}
25098				break;
25099			case $.ui.keyCode.LEFT:
25100				this._move( "prev", event );
25101				break;
25102			case $.ui.keyCode.RIGHT:
25103				this._move( "next", event );
25104				break;
25105			case $.ui.keyCode.HOME:
25106			case $.ui.keyCode.PAGE_UP:
25107				this._move( "first", event );
25108				break;
25109			case $.ui.keyCode.END:
25110			case $.ui.keyCode.PAGE_DOWN:
25111				this._move( "last", event );
25112				break;
25113			default:
25114				this.menu.trigger( event );
25115				preventDefault = false;
25116			}
25117
25118			if ( preventDefault ) {
25119				event.preventDefault();
25120			}
25121		}
25122	},
25123
25124	_selectFocusedItem: function( event ) {
25125		var item = this.menuItems.eq( this.focusIndex ).parent( "li" );
25126		if ( !item.hasClass( "ui-state-disabled" ) ) {
25127			this._select( item.data( "ui-selectmenu-item" ), event );
25128		}
25129	},
25130
25131	_select: function( item, event ) {
25132		var oldIndex = this.element[ 0 ].selectedIndex;
25133
25134		// Change native select element
25135		this.element[ 0 ].selectedIndex = item.index;
25136		this.buttonItem.replaceWith( this.buttonItem = this._renderButtonItem( item ) );
25137		this._setAria( item );
25138		this._trigger( "select", event, { item: item } );
25139
25140		if ( item.index !== oldIndex ) {
25141			this._trigger( "change", event, { item: item } );
25142		}
25143
25144		this.close( event );
25145	},
25146
25147	_setAria: function( item ) {
25148		var id = this.menuItems.eq( item.index ).attr( "id" );
25149
25150		this.button.attr( {
25151			"aria-labelledby": id,
25152			"aria-activedescendant": id
25153		} );
25154		this.menu.attr( "aria-activedescendant", id );
25155	},
25156
25157	_setOption: function( key, value ) {
25158		if ( key === "icons" ) {
25159			var icon = this.button.find( "span.ui-icon" );
25160			this._removeClass( icon, null, this.options.icons.button )
25161				._addClass( icon, null, value.button );
25162		}
25163
25164		this._super( key, value );
25165
25166		if ( key === "appendTo" ) {
25167			this.menuWrap.appendTo( this._appendTo() );
25168		}
25169
25170		if ( key === "width" ) {
25171			this._resizeButton();
25172		}
25173	},
25174
25175	_setOptionDisabled: function( value ) {
25176		this._super( value );
25177
25178		this.menuInstance.option( "disabled", value );
25179		this.button.attr( "aria-disabled", value );
25180		this._toggleClass( this.button, null, "ui-state-disabled", value );
25181
25182		this.element.prop( "disabled", value );
25183		if ( value ) {
25184			this.button.attr( "tabindex", -1 );
25185			this.close();
25186		} else {
25187			this.button.attr( "tabindex", 0 );
25188		}
25189	},
25190
25191	_appendTo: function() {
25192		var element = this.options.appendTo;
25193
25194		if ( element ) {
25195			element = element.jquery || element.nodeType ?
25196				$( element ) :
25197				this.document.find( element ).eq( 0 );
25198		}
25199
25200		if ( !element || !element[ 0 ] ) {
25201			element = this.element.closest( ".ui-front, dialog" );
25202		}
25203
25204		if ( !element.length ) {
25205			element = this.document[ 0 ].body;
25206		}
25207
25208		return element;
25209	},
25210
25211	_toggleAttr: function() {
25212		this.button.attr( "aria-expanded", this.isOpen );
25213
25214		// We can't use two _toggleClass() calls here, because we need to make sure
25215		// we always remove classes first and add them second, otherwise if both classes have the
25216		// same theme class, it will be removed after we add it.
25217		this._removeClass( this.button, "ui-selectmenu-button-" +
25218			( this.isOpen ? "closed" : "open" ) )
25219			._addClass( this.button, "ui-selectmenu-button-" +
25220				( this.isOpen ? "open" : "closed" ) )
25221			._toggleClass( this.menuWrap, "ui-selectmenu-open", null, this.isOpen );
25222
25223		this.menu.attr( "aria-hidden", !this.isOpen );
25224	},
25225
25226	_resizeButton: function() {
25227		var width = this.options.width;
25228
25229		// For `width: false`, just remove inline style and stop
25230		if ( width === false ) {
25231			this.button.css( "width", "" );
25232			return;
25233		}
25234
25235		// For `width: null`, match the width of the original element
25236		if ( width === null ) {
25237			width = this.element.show().outerWidth();
25238			this.element.hide();
25239		}
25240
25241		this.button.outerWidth( width );
25242	},
25243
25244	_resizeMenu: function() {
25245		this.menu.outerWidth( Math.max(
25246			this.button.outerWidth(),
25247			this.menu.width( "" ).outerWidth()
25248		) );
25249	},
25250
25251	_getCreateOptions: function() {
25252		var options = this._super();
25253
25254		options.disabled = this.element.prop( "disabled" );
25255
25256		return options;
25257	},
25258
25259	_parseOptions: function( options ) {
25260		var that = this,
25261			data = [];
25262		options.each( function( index, item ) {
25263			data.push( that._parseOption( $( item ), index ) );
25264		} );
25265		this.items = data;
25266	},
25267
25268	_parseOption: function( option, index ) {
25269		var optgroup = option.parent( "optgroup" );
25270
25271		return {
25272			element: option,
25273			index: index,
25274			value: option.val(),
25275			label: option.text(),
25276			hidden: optgroup.prop( "hidden" ) || option.prop( "hidden" ),
25277			optgroup: optgroup.attr( "label" ) || "",
25278			disabled: optgroup.prop( "disabled" ) || option.prop( "disabled" )
25279		};
25280	},
25281
25282	_destroy: function() {
25283		this._unbindFormResetHandler();
25284		this.menuWrap.remove();
25285		this.button.remove();
25286		this.element.show();
25287		this.element.removeUniqueId();
25288		this.labels.attr( "for", this.ids.element );
25289	}
25290} ] );
25291
25292
25293/*!
25294 * jQuery UI Slider 1.14.1
25295 * https://jqueryui.com
25296 *
25297 * Copyright OpenJS Foundation and other contributors
25298 * Released under the MIT license.
25299 * https://jquery.org/license
25300 */
25301
25302//>>label: Slider
25303//>>group: Widgets
25304//>>description: Displays a flexible slider with ranges and accessibility via keyboard.
25305//>>docs: https://api.jqueryui.com/slider/
25306//>>demos: https://jqueryui.com/slider/
25307//>>css.structure: ../../themes/base/core.css
25308//>>css.structure: ../../themes/base/slider.css
25309//>>css.theme: ../../themes/base/theme.css
25310
25311
25312var widgetsSlider = $.widget( "ui.slider", $.ui.mouse, {
25313	version: "1.14.1",
25314	widgetEventPrefix: "slide",
25315
25316	options: {
25317		animate: false,
25318		classes: {
25319			"ui-slider": "ui-corner-all",
25320			"ui-slider-handle": "ui-corner-all",
25321
25322			// Note: ui-widget-header isn't the most fittingly semantic framework class for this
25323			// element, but worked best visually with a variety of themes
25324			"ui-slider-range": "ui-corner-all ui-widget-header"
25325		},
25326		distance: 0,
25327		max: 100,
25328		min: 0,
25329		orientation: "horizontal",
25330		range: false,
25331		step: 1,
25332		value: 0,
25333		values: null,
25334
25335		// Callbacks
25336		change: null,
25337		slide: null,
25338		start: null,
25339		stop: null
25340	},
25341
25342	// Number of pages in a slider
25343	// (how many times can you page up/down to go through the whole range)
25344	numPages: 5,
25345
25346	_create: function() {
25347		this._keySliding = false;
25348		this._mouseSliding = false;
25349		this._animateOff = true;
25350		this._handleIndex = null;
25351		this._detectOrientation();
25352		this._mouseInit();
25353		this._calculateNewMax();
25354
25355		this._addClass( "ui-slider ui-slider-" + this.orientation,
25356			"ui-widget ui-widget-content" );
25357
25358		this._refresh();
25359
25360		this._animateOff = false;
25361	},
25362
25363	_refresh: function() {
25364		this._createRange();
25365		this._createHandles();
25366		this._setupEvents();
25367		this._refreshValue();
25368	},
25369
25370	_createHandles: function() {
25371		var i, handleCount,
25372			options = this.options,
25373			existingHandles = this.element.find( ".ui-slider-handle" ),
25374			handle = "<span tabindex='0'></span>",
25375			handles = [];
25376
25377		handleCount = ( options.values && options.values.length ) || 1;
25378
25379		if ( existingHandles.length > handleCount ) {
25380			existingHandles.slice( handleCount ).remove();
25381			existingHandles = existingHandles.slice( 0, handleCount );
25382		}
25383
25384		for ( i = existingHandles.length; i < handleCount; i++ ) {
25385			handles.push( handle );
25386		}
25387
25388		this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) );
25389
25390		this._addClass( this.handles, "ui-slider-handle", "ui-state-default" );
25391
25392		this.handle = this.handles.eq( 0 );
25393
25394		this.handles.each( function( i ) {
25395			$( this )
25396				.data( "ui-slider-handle-index", i )
25397				.attr( "tabIndex", 0 );
25398		} );
25399	},
25400
25401	_createRange: function() {
25402		var options = this.options;
25403
25404		if ( options.range ) {
25405			if ( options.range === true ) {
25406				if ( !options.values ) {
25407					options.values = [ this._valueMin(), this._valueMin() ];
25408				} else if ( options.values.length && options.values.length !== 2 ) {
25409					options.values = [ options.values[ 0 ], options.values[ 0 ] ];
25410				} else if ( Array.isArray( options.values ) ) {
25411					options.values = options.values.slice( 0 );
25412				}
25413			}
25414
25415			if ( !this.range || !this.range.length ) {
25416				this.range = $( "<div>" )
25417					.appendTo( this.element );
25418
25419				this._addClass( this.range, "ui-slider-range" );
25420			} else {
25421				this._removeClass( this.range, "ui-slider-range-min ui-slider-range-max" );
25422
25423				// Handle range switching from true to min/max
25424				this.range.css( {
25425					"left": "",
25426					"bottom": ""
25427				} );
25428			}
25429			if ( options.range === "min" || options.range === "max" ) {
25430				this._addClass( this.range, "ui-slider-range-" + options.range );
25431			}
25432		} else {
25433			if ( this.range ) {
25434				this.range.remove();
25435			}
25436			this.range = null;
25437		}
25438	},
25439
25440	_setupEvents: function() {
25441		this._off( this.handles );
25442		this._on( this.handles, this._handleEvents );
25443		this._hoverable( this.handles );
25444		this._focusable( this.handles );
25445	},
25446
25447	_destroy: function() {
25448		this.handles.remove();
25449		if ( this.range ) {
25450			this.range.remove();
25451		}
25452
25453		this._mouseDestroy();
25454	},
25455
25456	_mouseCapture: function( event ) {
25457		var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle,
25458			that = this,
25459			o = this.options;
25460
25461		if ( o.disabled ) {
25462			return false;
25463		}
25464
25465		this.elementSize = {
25466			width: this.element.outerWidth(),
25467			height: this.element.outerHeight()
25468		};
25469		this.elementOffset = this.element.offset();
25470
25471		position = { x: event.pageX, y: event.pageY };
25472		normValue = this._normValueFromMouse( position );
25473		distance = this._valueMax() - this._valueMin() + 1;
25474		this.handles.each( function( i ) {
25475			var thisDistance = Math.abs( normValue - that.values( i ) );
25476			if ( ( distance > thisDistance ) ||
25477				( distance === thisDistance &&
25478					( i === that._lastChangedValue || that.values( i ) === o.min ) ) ) {
25479				distance = thisDistance;
25480				closestHandle = $( this );
25481				index = i;
25482			}
25483		} );
25484
25485		allowed = this._start( event, index );
25486		if ( allowed === false ) {
25487			return false;
25488		}
25489		this._mouseSliding = true;
25490
25491		this._handleIndex = index;
25492
25493		this._addClass( closestHandle, null, "ui-state-active" );
25494		closestHandle.trigger( "focus" );
25495
25496		offset = closestHandle.offset();
25497		mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" );
25498		this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
25499			left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
25500			top: event.pageY - offset.top -
25501				( closestHandle.height() / 2 ) -
25502				( parseInt( closestHandle.css( "borderTopWidth" ), 10 ) || 0 ) -
25503				( parseInt( closestHandle.css( "borderBottomWidth" ), 10 ) || 0 ) +
25504				( parseInt( closestHandle.css( "marginTop" ), 10 ) || 0 )
25505		};
25506
25507		if ( !this.handles.hasClass( "ui-state-hover" ) ) {
25508			this._slide( event, index, normValue );
25509		}
25510		this._animateOff = true;
25511		return true;
25512	},
25513
25514	_mouseStart: function() {
25515		return true;
25516	},
25517
25518	_mouseDrag: function( event ) {
25519		var position = { x: event.pageX, y: event.pageY },
25520			normValue = this._normValueFromMouse( position );
25521
25522		this._slide( event, this._handleIndex, normValue );
25523
25524		return false;
25525	},
25526
25527	_mouseStop: function( event ) {
25528		this._removeClass( this.handles, null, "ui-state-active" );
25529		this._mouseSliding = false;
25530
25531		this._stop( event, this._handleIndex );
25532		this._change( event, this._handleIndex );
25533
25534		this._handleIndex = null;
25535		this._clickOffset = null;
25536		this._animateOff = false;
25537
25538		return false;
25539	},
25540
25541	_detectOrientation: function() {
25542		this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
25543	},
25544
25545	_normValueFromMouse: function( position ) {
25546		var pixelTotal,
25547			pixelMouse,
25548			percentMouse,
25549			valueTotal,
25550			valueMouse;
25551
25552		if ( this.orientation === "horizontal" ) {
25553			pixelTotal = this.elementSize.width;
25554			pixelMouse = position.x - this.elementOffset.left -
25555				( this._clickOffset ? this._clickOffset.left : 0 );
25556		} else {
25557			pixelTotal = this.elementSize.height;
25558			pixelMouse = position.y - this.elementOffset.top -
25559				( this._clickOffset ? this._clickOffset.top : 0 );
25560		}
25561
25562		percentMouse = ( pixelMouse / pixelTotal );
25563		if ( percentMouse > 1 ) {
25564			percentMouse = 1;
25565		}
25566		if ( percentMouse < 0 ) {
25567			percentMouse = 0;
25568		}
25569		if ( this.orientation === "vertical" ) {
25570			percentMouse = 1 - percentMouse;
25571		}
25572
25573		valueTotal = this._valueMax() - this._valueMin();
25574		valueMouse = this._valueMin() + percentMouse * valueTotal;
25575
25576		return this._trimAlignValue( valueMouse );
25577	},
25578
25579	_uiHash: function( index, value, values ) {
25580		var uiHash = {
25581			handle: this.handles[ index ],
25582			handleIndex: index,
25583			value: value !== undefined ? value : this.value()
25584		};
25585
25586		if ( this._hasMultipleValues() ) {
25587			uiHash.value = value !== undefined ? value : this.values( index );
25588			uiHash.values = values || this.values();
25589		}
25590
25591		return uiHash;
25592	},
25593
25594	_hasMultipleValues: function() {
25595		return this.options.values && this.options.values.length;
25596	},
25597
25598	_start: function( event, index ) {
25599		return this._trigger( "start", event, this._uiHash( index ) );
25600	},
25601
25602	_slide: function( event, index, newVal ) {
25603		var allowed, otherVal,
25604			currentValue = this.value(),
25605			newValues = this.values();
25606
25607		if ( this._hasMultipleValues() ) {
25608			otherVal = this.values( index ? 0 : 1 );
25609			currentValue = this.values( index );
25610
25611			if ( this.options.values.length === 2 && this.options.range === true ) {
25612				newVal =  index === 0 ? Math.min( otherVal, newVal ) : Math.max( otherVal, newVal );
25613			}
25614
25615			newValues[ index ] = newVal;
25616		}
25617
25618		if ( newVal === currentValue ) {
25619			return;
25620		}
25621
25622		allowed = this._trigger( "slide", event, this._uiHash( index, newVal, newValues ) );
25623
25624		// A slide can be canceled by returning false from the slide callback
25625		if ( allowed === false ) {
25626			return;
25627		}
25628
25629		if ( this._hasMultipleValues() ) {
25630			this.values( index, newVal );
25631		} else {
25632			this.value( newVal );
25633		}
25634	},
25635
25636	_stop: function( event, index ) {
25637		this._trigger( "stop", event, this._uiHash( index ) );
25638	},
25639
25640	_change: function( event, index ) {
25641		if ( !this._keySliding && !this._mouseSliding ) {
25642
25643			//store the last changed value index for reference when handles overlap
25644			this._lastChangedValue = index;
25645			this._trigger( "change", event, this._uiHash( index ) );
25646		}
25647	},
25648
25649	value: function( newValue ) {
25650		if ( arguments.length ) {
25651			this.options.value = this._trimAlignValue( newValue );
25652			this._refreshValue();
25653			this._change( null, 0 );
25654			return;
25655		}
25656
25657		return this._value();
25658	},
25659
25660	values: function( index, newValue ) {
25661		var vals,
25662			newValues,
25663			i;
25664
25665		if ( arguments.length > 1 ) {
25666			this.options.values[ index ] = this._trimAlignValue( newValue );
25667			this._refreshValue();
25668			this._change( null, index );
25669			return;
25670		}
25671
25672		if ( arguments.length ) {
25673			if ( Array.isArray( arguments[ 0 ] ) ) {
25674				vals = this.options.values;
25675				newValues = arguments[ 0 ];
25676				for ( i = 0; i < vals.length; i += 1 ) {
25677					vals[ i ] = this._trimAlignValue( newValues[ i ] );
25678					this._change( null, i );
25679				}
25680				this._refreshValue();
25681			} else {
25682				if ( this._hasMultipleValues() ) {
25683					return this._values( index );
25684				} else {
25685					return this.value();
25686				}
25687			}
25688		} else {
25689			return this._values();
25690		}
25691	},
25692
25693	_setOption: function( key, value ) {
25694		var i,
25695			valsLength = 0;
25696
25697		if ( key === "range" && this.options.range === true ) {
25698			if ( value === "min" ) {
25699				this.options.value = this._values( 0 );
25700				this.options.values = null;
25701			} else if ( value === "max" ) {
25702				this.options.value = this._values( this.options.values.length - 1 );
25703				this.options.values = null;
25704			}
25705		}
25706
25707		if ( Array.isArray( this.options.values ) ) {
25708			valsLength = this.options.values.length;
25709		}
25710
25711		this._super( key, value );
25712
25713		switch ( key ) {
25714			case "orientation":
25715				this._detectOrientation();
25716				this._removeClass( "ui-slider-horizontal ui-slider-vertical" )
25717					._addClass( "ui-slider-" + this.orientation );
25718				this._refreshValue();
25719				if ( this.options.range ) {
25720					this._refreshRange( value );
25721				}
25722
25723				// Reset positioning from previous orientation
25724				this.handles.css( value === "horizontal" ? "bottom" : "left", "" );
25725				break;
25726			case "value":
25727				this._animateOff = true;
25728				this._refreshValue();
25729				this._change( null, 0 );
25730				this._animateOff = false;
25731				break;
25732			case "values":
25733				this._animateOff = true;
25734				this._refreshValue();
25735
25736				// Start from the last handle to prevent unreachable handles (#9046)
25737				for ( i = valsLength - 1; i >= 0; i-- ) {
25738					this._change( null, i );
25739				}
25740				this._animateOff = false;
25741				break;
25742			case "step":
25743			case "min":
25744			case "max":
25745				this._animateOff = true;
25746				this._calculateNewMax();
25747				this._refreshValue();
25748				this._animateOff = false;
25749				break;
25750			case "range":
25751				this._animateOff = true;
25752				this._refresh();
25753				this._animateOff = false;
25754				break;
25755		}
25756	},
25757
25758	_setOptionDisabled: function( value ) {
25759		this._super( value );
25760
25761		this._toggleClass( null, "ui-state-disabled", !!value );
25762	},
25763
25764	//internal value getter
25765	// _value() returns value trimmed by min and max, aligned by step
25766	_value: function() {
25767		var val = this.options.value;
25768		val = this._trimAlignValue( val );
25769
25770		return val;
25771	},
25772
25773	//internal values getter
25774	// _values() returns array of values trimmed by min and max, aligned by step
25775	// _values( index ) returns single value trimmed by min and max, aligned by step
25776	_values: function( index ) {
25777		var val,
25778			vals,
25779			i;
25780
25781		if ( arguments.length ) {
25782			val = this.options.values[ index ];
25783			val = this._trimAlignValue( val );
25784
25785			return val;
25786		} else if ( this._hasMultipleValues() ) {
25787
25788			// .slice() creates a copy of the array
25789			// this copy gets trimmed by min and max and then returned
25790			vals = this.options.values.slice();
25791			for ( i = 0; i < vals.length; i += 1 ) {
25792				vals[ i ] = this._trimAlignValue( vals[ i ] );
25793			}
25794
25795			return vals;
25796		} else {
25797			return [];
25798		}
25799	},
25800
25801	// Returns the step-aligned value that val is closest to, between (inclusive) min and max
25802	_trimAlignValue: function( val ) {
25803		if ( val <= this._valueMin() ) {
25804			return this._valueMin();
25805		}
25806		if ( val >= this._valueMax() ) {
25807			return this._valueMax();
25808		}
25809		var step = ( this.options.step > 0 ) ? this.options.step : 1,
25810			valModStep = ( val - this._valueMin() ) % step,
25811			alignValue = val - valModStep;
25812
25813		if ( Math.abs( valModStep ) * 2 >= step ) {
25814			alignValue += ( valModStep > 0 ) ? step : ( -step );
25815		}
25816
25817		// Since JavaScript has problems with large floats, round
25818		// the final value to 5 digits after the decimal point (see #4124)
25819		return parseFloat( alignValue.toFixed( 5 ) );
25820	},
25821
25822	_calculateNewMax: function() {
25823		var max = this.options.max,
25824			min = this._valueMin(),
25825			step = this.options.step,
25826			aboveMin = Math.round( ( max - min ) / step ) * step;
25827		max = aboveMin + min;
25828		if ( max > this.options.max ) {
25829
25830			//If max is not divisible by step, rounding off may increase its value
25831			max -= step;
25832		}
25833		this.max = parseFloat( max.toFixed( this._precision() ) );
25834	},
25835
25836	_precision: function() {
25837		var precision = this._precisionOf( this.options.step );
25838		if ( this.options.min !== null ) {
25839			precision = Math.max( precision, this._precisionOf( this.options.min ) );
25840		}
25841		return precision;
25842	},
25843
25844	_precisionOf: function( num ) {
25845		var str = num.toString(),
25846			decimal = str.indexOf( "." );
25847		return decimal === -1 ? 0 : str.length - decimal - 1;
25848	},
25849
25850	_valueMin: function() {
25851		return this.options.min;
25852	},
25853
25854	_valueMax: function() {
25855		return this.max;
25856	},
25857
25858	_refreshRange: function( orientation ) {
25859		if ( orientation === "vertical" ) {
25860			this.range.css( { "width": "", "left": "" } );
25861		}
25862		if ( orientation === "horizontal" ) {
25863			this.range.css( { "height": "", "bottom": "" } );
25864		}
25865	},
25866
25867	_refreshValue: function() {
25868		var lastValPercent, valPercent, value, valueMin, valueMax,
25869			oRange = this.options.range,
25870			o = this.options,
25871			that = this,
25872			animate = ( !this._animateOff ) ? o.animate : false,
25873			_set = {};
25874
25875		if ( this._hasMultipleValues() ) {
25876			this.handles.each( function( i ) {
25877				valPercent = ( that.values( i ) - that._valueMin() ) / ( that._valueMax() -
25878					that._valueMin() ) * 100;
25879				_set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
25880				$( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
25881				if ( that.options.range === true ) {
25882					if ( that.orientation === "horizontal" ) {
25883						if ( i === 0 ) {
25884							that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
25885								left: valPercent + "%"
25886							}, o.animate );
25887						}
25888						if ( i === 1 ) {
25889							that.range[ animate ? "animate" : "css" ]( {
25890								width: ( valPercent - lastValPercent ) + "%"
25891							}, {
25892								queue: false,
25893								duration: o.animate
25894							} );
25895						}
25896					} else {
25897						if ( i === 0 ) {
25898							that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
25899								bottom: ( valPercent ) + "%"
25900							}, o.animate );
25901						}
25902						if ( i === 1 ) {
25903							that.range[ animate ? "animate" : "css" ]( {
25904								height: ( valPercent - lastValPercent ) + "%"
25905							}, {
25906								queue: false,
25907								duration: o.animate
25908							} );
25909						}
25910					}
25911				}
25912				lastValPercent = valPercent;
25913			} );
25914		} else {
25915			value = this.value();
25916			valueMin = this._valueMin();
25917			valueMax = this._valueMax();
25918			valPercent = ( valueMax !== valueMin ) ?
25919					( value - valueMin ) / ( valueMax - valueMin ) * 100 :
25920					0;
25921			_set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
25922			this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
25923
25924			if ( oRange === "min" && this.orientation === "horizontal" ) {
25925				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
25926					width: valPercent + "%"
25927				}, o.animate );
25928			}
25929			if ( oRange === "max" && this.orientation === "horizontal" ) {
25930				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
25931					width: ( 100 - valPercent ) + "%"
25932				}, o.animate );
25933			}
25934			if ( oRange === "min" && this.orientation === "vertical" ) {
25935				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
25936					height: valPercent + "%"
25937				}, o.animate );
25938			}
25939			if ( oRange === "max" && this.orientation === "vertical" ) {
25940				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
25941					height: ( 100 - valPercent ) + "%"
25942				}, o.animate );
25943			}
25944		}
25945	},
25946
25947	_handleEvents: {
25948		keydown: function( event ) {
25949			var allowed, curVal, newVal, step,
25950				index = $( event.target ).data( "ui-slider-handle-index" );
25951
25952			switch ( event.keyCode ) {
25953				case $.ui.keyCode.HOME:
25954				case $.ui.keyCode.END:
25955				case $.ui.keyCode.PAGE_UP:
25956				case $.ui.keyCode.PAGE_DOWN:
25957				case $.ui.keyCode.UP:
25958				case $.ui.keyCode.RIGHT:
25959				case $.ui.keyCode.DOWN:
25960				case $.ui.keyCode.LEFT:
25961					event.preventDefault();
25962					if ( !this._keySliding ) {
25963						this._keySliding = true;
25964						this._addClass( $( event.target ), null, "ui-state-active" );
25965						allowed = this._start( event, index );
25966						if ( allowed === false ) {
25967							return;
25968						}
25969					}
25970					break;
25971			}
25972
25973			step = this.options.step;
25974			if ( this._hasMultipleValues() ) {
25975				curVal = newVal = this.values( index );
25976			} else {
25977				curVal = newVal = this.value();
25978			}
25979
25980			switch ( event.keyCode ) {
25981				case $.ui.keyCode.HOME:
25982					newVal = this._valueMin();
25983					break;
25984				case $.ui.keyCode.END:
25985					newVal = this._valueMax();
25986					break;
25987				case $.ui.keyCode.PAGE_UP:
25988					newVal = this._trimAlignValue(
25989						curVal + ( ( this._valueMax() - this._valueMin() ) / this.numPages )
25990					);
25991					break;
25992				case $.ui.keyCode.PAGE_DOWN:
25993					newVal = this._trimAlignValue(
25994						curVal - ( ( this._valueMax() - this._valueMin() ) / this.numPages ) );
25995					break;
25996				case $.ui.keyCode.UP:
25997				case $.ui.keyCode.RIGHT:
25998					if ( curVal === this._valueMax() ) {
25999						return;
26000					}
26001					newVal = this._trimAlignValue( curVal + step );
26002					break;
26003				case $.ui.keyCode.DOWN:
26004				case $.ui.keyCode.LEFT:
26005					if ( curVal === this._valueMin() ) {
26006						return;
26007					}
26008					newVal = this._trimAlignValue( curVal - step );
26009					break;
26010			}
26011
26012			this._slide( event, index, newVal );
26013		},
26014		keyup: function( event ) {
26015			var index = $( event.target ).data( "ui-slider-handle-index" );
26016
26017			if ( this._keySliding ) {
26018				this._keySliding = false;
26019				this._stop( event, index );
26020				this._change( event, index );
26021				this._removeClass( $( event.target ), null, "ui-state-active" );
26022			}
26023		}
26024	}
26025} );
26026
26027
26028/*!
26029 * jQuery UI Sortable 1.14.1
26030 * https://jqueryui.com
26031 *
26032 * Copyright OpenJS Foundation and other contributors
26033 * Released under the MIT license.
26034 * https://jquery.org/license
26035 */
26036
26037//>>label: Sortable
26038//>>group: Interactions
26039//>>description: Enables items in a list to be sorted using the mouse.
26040//>>docs: https://api.jqueryui.com/sortable/
26041//>>demos: https://jqueryui.com/sortable/
26042//>>css.structure: ../../themes/base/sortable.css
26043
26044
26045var widgetsSortable = $.widget( "ui.sortable", $.ui.mouse, {
26046	version: "1.14.1",
26047	widgetEventPrefix: "sort",
26048	ready: false,
26049	options: {
26050		appendTo: "parent",
26051		axis: false,
26052		connectWith: false,
26053		containment: false,
26054		cursor: "auto",
26055		cursorAt: false,
26056		dropOnEmpty: true,
26057		forcePlaceholderSize: false,
26058		forceHelperSize: false,
26059		grid: false,
26060		handle: false,
26061		helper: "original",
26062		items: "> *",
26063		opacity: false,
26064		placeholder: false,
26065		revert: false,
26066		scroll: true,
26067		scrollSensitivity: 20,
26068		scrollSpeed: 20,
26069		scope: "default",
26070		tolerance: "intersect",
26071		zIndex: 1000,
26072
26073		// Callbacks
26074		activate: null,
26075		beforeStop: null,
26076		change: null,
26077		deactivate: null,
26078		out: null,
26079		over: null,
26080		receive: null,
26081		remove: null,
26082		sort: null,
26083		start: null,
26084		stop: null,
26085		update: null
26086	},
26087
26088	_isOverAxis: function( x, reference, size ) {
26089		return ( x >= reference ) && ( x < ( reference + size ) );
26090	},
26091
26092	_isFloating: function( item ) {
26093		return ( /left|right/ ).test( item.css( "float" ) ) ||
26094			( /inline|table-cell/ ).test( item.css( "display" ) );
26095	},
26096
26097	_create: function() {
26098		this.containerCache = {};
26099		this._addClass( "ui-sortable" );
26100
26101		//Get the items
26102		this.refresh();
26103
26104		//Let's determine the parent's offset
26105		this.offset = this.element.offset();
26106
26107		//Initialize mouse events for interaction
26108		this._mouseInit();
26109
26110		this._setHandleClassName();
26111
26112		//We're ready to go
26113		this.ready = true;
26114
26115	},
26116
26117	_setOption: function( key, value ) {
26118		this._super( key, value );
26119
26120		if ( key === "handle" ) {
26121			this._setHandleClassName();
26122		}
26123	},
26124
26125	_setHandleClassName: function() {
26126		var that = this;
26127		this._removeClass( this.element.find( ".ui-sortable-handle" ), "ui-sortable-handle" );
26128		$.each( this.items, function() {
26129			that._addClass(
26130				this.instance.options.handle ?
26131					this.item.find( this.instance.options.handle ) :
26132					this.item,
26133				"ui-sortable-handle"
26134			);
26135		} );
26136	},
26137
26138	_destroy: function() {
26139		this._mouseDestroy();
26140
26141		for ( var i = this.items.length - 1; i >= 0; i-- ) {
26142			this.items[ i ].item.removeData( this.widgetName + "-item" );
26143		}
26144
26145		return this;
26146	},
26147
26148	_mouseCapture: function( event, overrideHandle ) {
26149		var currentItem = null,
26150			validHandle = false,
26151			that = this;
26152
26153		if ( this.reverting ) {
26154			return false;
26155		}
26156
26157		if ( this.options.disabled || this.options.type === "static" ) {
26158			return false;
26159		}
26160
26161		//We have to refresh the items data once first
26162		this._refreshItems( event );
26163
26164		//Find out if the clicked node (or one of its parents) is a actual item in this.items
26165		$( event.target ).parents().each( function() {
26166			if ( $.data( this, that.widgetName + "-item" ) === that ) {
26167				currentItem = $( this );
26168				return false;
26169			}
26170		} );
26171		if ( $.data( event.target, that.widgetName + "-item" ) === that ) {
26172			currentItem = $( event.target );
26173		}
26174
26175		if ( !currentItem ) {
26176			return false;
26177		}
26178		if ( this.options.handle && !overrideHandle ) {
26179			$( this.options.handle, currentItem ).find( "*" ).addBack().each( function() {
26180				if ( this === event.target ) {
26181					validHandle = true;
26182				}
26183			} );
26184			if ( !validHandle ) {
26185				return false;
26186			}
26187		}
26188
26189		this.currentItem = currentItem;
26190		this._removeCurrentsFromItems();
26191		return true;
26192
26193	},
26194
26195	_mouseStart: function( event, overrideHandle, noActivation ) {
26196
26197		var i, body,
26198			o = this.options;
26199
26200		this.currentContainer = this;
26201
26202		//We only need to call refreshPositions, because the refreshItems call has been moved to
26203		// mouseCapture
26204		this.refreshPositions();
26205
26206		//Prepare the dragged items parent
26207		this.appendTo = $( o.appendTo !== "parent" ?
26208				o.appendTo :
26209				this.currentItem.parent() );
26210
26211		//Create and append the visible helper
26212		this.helper = this._createHelper( event );
26213
26214		//Cache the helper size
26215		this._cacheHelperProportions();
26216
26217		/*
26218		 * - Position generation -
26219		 * This block generates everything position related - it's the core of draggables.
26220		 */
26221
26222		//Cache the margins of the original element
26223		this._cacheMargins();
26224
26225		//The element's absolute position on the page minus margins
26226		this.offset = this.currentItem.offset();
26227		this.offset = {
26228			top: this.offset.top - this.margins.top,
26229			left: this.offset.left - this.margins.left
26230		};
26231
26232		$.extend( this.offset, {
26233			click: { //Where the click happened, relative to the element
26234				left: event.pageX - this.offset.left,
26235				top: event.pageY - this.offset.top
26236			},
26237
26238			// This is a relative to absolute position minus the actual position calculation -
26239			// only used for relative positioned helper
26240			relative: this._getRelativeOffset()
26241		} );
26242
26243		// After we get the helper offset, but before we get the parent offset we can
26244		// change the helper's position to absolute
26245		// TODO: Still need to figure out a way to make relative sorting possible
26246		this.helper.css( "position", "absolute" );
26247		this.cssPosition = this.helper.css( "position" );
26248
26249		//Adjust the mouse offset relative to the helper if "cursorAt" is supplied
26250		if ( o.cursorAt ) {
26251			this._adjustOffsetFromHelper( o.cursorAt );
26252		}
26253
26254		//Cache the former DOM position
26255		this.domPosition = {
26256			prev: this.currentItem.prev()[ 0 ],
26257			parent: this.currentItem.parent()[ 0 ]
26258		};
26259
26260		// If the helper is not the original, hide the original so it's not playing any role during
26261		// the drag, won't cause anything bad this way
26262		if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {
26263			this.currentItem.hide();
26264		}
26265
26266		//Create the placeholder
26267		this._createPlaceholder();
26268
26269		//Get the next scrolling parent
26270		this.scrollParent = this.placeholder.scrollParent();
26271
26272		$.extend( this.offset, {
26273			parent: this._getParentOffset()
26274		} );
26275
26276		//Set a containment if given in the options
26277		if ( o.containment ) {
26278			this._setContainment();
26279		}
26280
26281		if ( o.cursor && o.cursor !== "auto" ) { // cursor option
26282			body = this.document.find( "body" );
26283
26284			this._storedStylesheet =
26285				$( "<style>*{ cursor: " + o.cursor + " !important; }</style>" ).appendTo( body );
26286		}
26287
26288		// We need to make sure to grab the zIndex before setting the
26289		// opacity, because setting the opacity to anything lower than 1
26290		// causes the zIndex to change from "auto" to 0.
26291		if ( o.zIndex ) { // zIndex option
26292			if ( this.helper.css( "zIndex" ) ) {
26293				this._storedZIndex = this.helper.css( "zIndex" );
26294			}
26295			this.helper.css( "zIndex", o.zIndex );
26296		}
26297
26298		if ( o.opacity ) { // opacity option
26299			if ( this.helper.css( "opacity" ) ) {
26300				this._storedOpacity = this.helper.css( "opacity" );
26301			}
26302			this.helper.css( "opacity", o.opacity );
26303		}
26304
26305		//Prepare scrolling
26306		if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
26307				this.scrollParent[ 0 ].tagName !== "HTML" ) {
26308			this.overflowOffset = this.scrollParent.offset();
26309		}
26310
26311		//Call callbacks
26312		this._trigger( "start", event, this._uiHash() );
26313
26314		//Recache the helper size
26315		if ( !this._preserveHelperProportions ) {
26316			this._cacheHelperProportions();
26317		}
26318
26319		//Post "activate" events to possible containers
26320		if ( !noActivation ) {
26321			for ( i = this.containers.length - 1; i >= 0; i-- ) {
26322				this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) );
26323			}
26324		}
26325
26326		//Prepare possible droppables
26327		if ( $.ui.ddmanager ) {
26328			$.ui.ddmanager.current = this;
26329		}
26330
26331		if ( $.ui.ddmanager && !o.dropBehaviour ) {
26332			$.ui.ddmanager.prepareOffsets( this, event );
26333		}
26334
26335		this.dragging = true;
26336
26337		this._addClass( this.helper, "ui-sortable-helper" );
26338
26339		//Move the helper, if needed
26340		if ( !this.helper.parent().is( this.appendTo ) ) {
26341			this.helper.detach().appendTo( this.appendTo );
26342
26343			//Update position
26344			this.offset.parent = this._getParentOffset();
26345		}
26346
26347		//Generate the original position
26348		this.position = this.originalPosition = this._generatePosition( event );
26349		this.originalPageX = event.pageX;
26350		this.originalPageY = event.pageY;
26351		this.lastPositionAbs = this.positionAbs = this._convertPositionTo( "absolute" );
26352
26353		this._mouseDrag( event );
26354
26355		return true;
26356
26357	},
26358
26359	_scroll: function( event ) {
26360		var o = this.options,
26361			scrolled = false;
26362
26363		if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
26364				this.scrollParent[ 0 ].tagName !== "HTML" ) {
26365
26366			if ( ( this.overflowOffset.top + this.scrollParent[ 0 ].offsetHeight ) -
26367					event.pageY < o.scrollSensitivity ) {
26368				this.scrollParent[ 0 ].scrollTop =
26369					scrolled = this.scrollParent[ 0 ].scrollTop + o.scrollSpeed;
26370			} else if ( event.pageY - this.overflowOffset.top < o.scrollSensitivity ) {
26371				this.scrollParent[ 0 ].scrollTop =
26372					scrolled = this.scrollParent[ 0 ].scrollTop - o.scrollSpeed;
26373			}
26374
26375			if ( ( this.overflowOffset.left + this.scrollParent[ 0 ].offsetWidth ) -
26376					event.pageX < o.scrollSensitivity ) {
26377				this.scrollParent[ 0 ].scrollLeft = scrolled =
26378					this.scrollParent[ 0 ].scrollLeft + o.scrollSpeed;
26379			} else if ( event.pageX - this.overflowOffset.left < o.scrollSensitivity ) {
26380				this.scrollParent[ 0 ].scrollLeft = scrolled =
26381					this.scrollParent[ 0 ].scrollLeft - o.scrollSpeed;
26382			}
26383
26384		} else {
26385
26386			if ( event.pageY - this.document.scrollTop() < o.scrollSensitivity ) {
26387				scrolled = this.document.scrollTop( this.document.scrollTop() - o.scrollSpeed );
26388			} else if ( this.window.height() - ( event.pageY - this.document.scrollTop() ) <
26389					o.scrollSensitivity ) {
26390				scrolled = this.document.scrollTop( this.document.scrollTop() + o.scrollSpeed );
26391			}
26392
26393			if ( event.pageX - this.document.scrollLeft() < o.scrollSensitivity ) {
26394				scrolled = this.document.scrollLeft(
26395					this.document.scrollLeft() - o.scrollSpeed
26396				);
26397			} else if ( this.window.width() - ( event.pageX - this.document.scrollLeft() ) <
26398					o.scrollSensitivity ) {
26399				scrolled = this.document.scrollLeft(
26400					this.document.scrollLeft() + o.scrollSpeed
26401				);
26402			}
26403
26404		}
26405
26406		return scrolled;
26407	},
26408
26409	_mouseDrag: function( event ) {
26410		var i, item, itemElement, intersection,
26411			o = this.options;
26412
26413		//Compute the helpers position
26414		this.position = this._generatePosition( event );
26415		this.positionAbs = this._convertPositionTo( "absolute" );
26416
26417		//Set the helper position
26418		if ( !this.options.axis || this.options.axis !== "y" ) {
26419			this.helper[ 0 ].style.left = this.position.left + "px";
26420		}
26421		if ( !this.options.axis || this.options.axis !== "x" ) {
26422			this.helper[ 0 ].style.top = this.position.top + "px";
26423		}
26424
26425		//Do scrolling
26426		if ( o.scroll ) {
26427			if ( this._scroll( event ) !== false ) {
26428
26429				//Update item positions used in position checks
26430				this._refreshItemPositions( true );
26431
26432				if ( $.ui.ddmanager && !o.dropBehaviour ) {
26433					$.ui.ddmanager.prepareOffsets( this, event );
26434				}
26435			}
26436		}
26437
26438		this.dragDirection = {
26439			vertical: this._getDragVerticalDirection(),
26440			horizontal: this._getDragHorizontalDirection()
26441		};
26442
26443		//Rearrange
26444		for ( i = this.items.length - 1; i >= 0; i-- ) {
26445
26446			//Cache variables and intersection, continue if no intersection
26447			item = this.items[ i ];
26448			itemElement = item.item[ 0 ];
26449			intersection = this._intersectsWithPointer( item );
26450			if ( !intersection ) {
26451				continue;
26452			}
26453
26454			// Only put the placeholder inside the current Container, skip all
26455			// items from other containers. This works because when moving
26456			// an item from one container to another the
26457			// currentContainer is switched before the placeholder is moved.
26458			//
26459			// Without this, moving items in "sub-sortables" can cause
26460			// the placeholder to jitter between the outer and inner container.
26461			if ( item.instance !== this.currentContainer ) {
26462				continue;
26463			}
26464
26465			// Cannot intersect with itself
26466			// no useless actions that have been done before
26467			// no action if the item moved is the parent of the item checked
26468			if ( itemElement !== this.currentItem[ 0 ] &&
26469				this.placeholder[ intersection === 1 ?
26470				"next" : "prev" ]()[ 0 ] !== itemElement &&
26471				!$.contains( this.placeholder[ 0 ], itemElement ) &&
26472				( this.options.type === "semi-dynamic" ?
26473					!$.contains( this.element[ 0 ], itemElement ) :
26474					true
26475				)
26476			) {
26477
26478				this.direction = intersection === 1 ? "down" : "up";
26479
26480				if ( this.options.tolerance === "pointer" ||
26481						this._intersectsWithSides( item ) ) {
26482					this._rearrange( event, item );
26483				} else {
26484					break;
26485				}
26486
26487				this._trigger( "change", event, this._uiHash() );
26488				break;
26489			}
26490		}
26491
26492		//Post events to containers
26493		this._contactContainers( event );
26494
26495		//Interconnect with droppables
26496		if ( $.ui.ddmanager ) {
26497			$.ui.ddmanager.drag( this, event );
26498		}
26499
26500		//Call callbacks
26501		this._trigger( "sort", event, this._uiHash() );
26502
26503		this.lastPositionAbs = this.positionAbs;
26504		return false;
26505
26506	},
26507
26508	_mouseStop: function( event, noPropagation ) {
26509
26510		if ( !event ) {
26511			return;
26512		}
26513
26514		//If we are using droppables, inform the manager about the drop
26515		if ( $.ui.ddmanager && !this.options.dropBehaviour ) {
26516			$.ui.ddmanager.drop( this, event );
26517		}
26518
26519		if ( this.options.revert ) {
26520			var that = this,
26521				cur = this.placeholder.offset(),
26522				axis = this.options.axis,
26523				animation = {};
26524
26525			if ( !axis || axis === "x" ) {
26526				animation.left = cur.left - this.offset.parent.left - this.margins.left +
26527					( this.offsetParent[ 0 ] === this.document[ 0 ].body ?
26528						0 :
26529						this.offsetParent[ 0 ].scrollLeft
26530					);
26531			}
26532			if ( !axis || axis === "y" ) {
26533				animation.top = cur.top - this.offset.parent.top - this.margins.top +
26534					( this.offsetParent[ 0 ] === this.document[ 0 ].body ?
26535						0 :
26536						this.offsetParent[ 0 ].scrollTop
26537					);
26538			}
26539			this.reverting = true;
26540			$( this.helper ).animate(
26541				animation,
26542				parseInt( this.options.revert, 10 ) || 500,
26543				function() {
26544					that._clear( event );
26545				}
26546			);
26547		} else {
26548			this._clear( event, noPropagation );
26549		}
26550
26551		return false;
26552
26553	},
26554
26555	cancel: function() {
26556
26557		if ( this.dragging ) {
26558
26559			this._mouseUp( new $.Event( "mouseup", { target: null } ) );
26560
26561			if ( this.options.helper === "original" ) {
26562				this.currentItem.css( this._storedCSS );
26563				this._removeClass( this.currentItem, "ui-sortable-helper" );
26564			} else {
26565				this.currentItem.show();
26566			}
26567
26568			//Post deactivating events to containers
26569			for ( var i = this.containers.length - 1; i >= 0; i-- ) {
26570				this.containers[ i ]._trigger( "deactivate", null, this._uiHash( this ) );
26571				if ( this.containers[ i ].containerCache.over ) {
26572					this.containers[ i ]._trigger( "out", null, this._uiHash( this ) );
26573					this.containers[ i ].containerCache.over = 0;
26574				}
26575			}
26576
26577		}
26578
26579		if ( this.placeholder ) {
26580
26581			//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately,
26582			// it unbinds ALL events from the original node!
26583			if ( this.placeholder[ 0 ].parentNode ) {
26584				this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] );
26585			}
26586			if ( this.options.helper !== "original" && this.helper &&
26587					this.helper[ 0 ].parentNode ) {
26588				this.helper.remove();
26589			}
26590
26591			$.extend( this, {
26592				helper: null,
26593				dragging: false,
26594				reverting: false,
26595				_noFinalSort: null
26596			} );
26597
26598			if ( this.domPosition.prev ) {
26599				$( this.domPosition.prev ).after( this.currentItem );
26600			} else {
26601				$( this.domPosition.parent ).prepend( this.currentItem );
26602			}
26603		}
26604
26605		return this;
26606
26607	},
26608
26609	serialize: function( o ) {
26610
26611		var items = this._getItemsAsjQuery( o && o.connected ),
26612			str = [];
26613		o = o || {};
26614
26615		$( items ).each( function() {
26616			var res = ( $( o.item || this ).attr( o.attribute || "id" ) || "" )
26617				.match( o.expression || ( /(.+)[\-=_](.+)/ ) );
26618			if ( res ) {
26619				str.push(
26620					( o.key || res[ 1 ] + "[]" ) +
26621					"=" + ( o.key && o.expression ? res[ 1 ] : res[ 2 ] ) );
26622			}
26623		} );
26624
26625		if ( !str.length && o.key ) {
26626			str.push( o.key + "=" );
26627		}
26628
26629		return str.join( "&" );
26630
26631	},
26632
26633	toArray: function( o ) {
26634
26635		var items = this._getItemsAsjQuery( o && o.connected ),
26636			ret = [];
26637
26638		o = o || {};
26639
26640		items.each( function() {
26641			ret.push( $( o.item || this ).attr( o.attribute || "id" ) || "" );
26642		} );
26643		return ret;
26644
26645	},
26646
26647	/* Be careful with the following core functions */
26648	_intersectsWith: function( item ) {
26649
26650		var x1 = this.positionAbs.left,
26651			x2 = x1 + this.helperProportions.width,
26652			y1 = this.positionAbs.top,
26653			y2 = y1 + this.helperProportions.height,
26654			l = item.left,
26655			r = l + item.width,
26656			t = item.top,
26657			b = t + item.height,
26658			dyClick = this.offset.click.top,
26659			dxClick = this.offset.click.left,
26660			isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t &&
26661				( y1 + dyClick ) < b ),
26662			isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l &&
26663				( x1 + dxClick ) < r ),
26664			isOverElement = isOverElementHeight && isOverElementWidth;
26665
26666		if ( this.options.tolerance === "pointer" ||
26667			this.options.forcePointerForContainers ||
26668			( this.options.tolerance !== "pointer" &&
26669				this.helperProportions[ this.floating ? "width" : "height" ] >
26670				item[ this.floating ? "width" : "height" ] )
26671		) {
26672			return isOverElement;
26673		} else {
26674
26675			return ( l < x1 + ( this.helperProportions.width / 2 ) && // Right Half
26676				x2 - ( this.helperProportions.width / 2 ) < r && // Left Half
26677				t < y1 + ( this.helperProportions.height / 2 ) && // Bottom Half
26678				y2 - ( this.helperProportions.height / 2 ) < b ); // Top Half
26679
26680		}
26681	},
26682
26683	_intersectsWithPointer: function( item ) {
26684		var verticalDirection, horizontalDirection,
26685			isOverElementHeight = ( this.options.axis === "x" ) ||
26686				this._isOverAxis(
26687					this.positionAbs.top + this.offset.click.top, item.top, item.height ),
26688			isOverElementWidth = ( this.options.axis === "y" ) ||
26689				this._isOverAxis(
26690					this.positionAbs.left + this.offset.click.left, item.left, item.width ),
26691			isOverElement = isOverElementHeight && isOverElementWidth;
26692
26693		if ( !isOverElement ) {
26694			return false;
26695		}
26696
26697		verticalDirection = this.dragDirection.vertical;
26698		horizontalDirection = this.dragDirection.horizontal;
26699
26700		return this.floating ?
26701			( ( horizontalDirection === "right" || verticalDirection === "down" ) ? 2 : 1 ) :
26702			( verticalDirection && ( verticalDirection === "down" ? 2 : 1 ) );
26703
26704	},
26705
26706	_intersectsWithSides: function( item ) {
26707
26708		var isOverBottomHalf = this._isOverAxis( this.positionAbs.top +
26709				this.offset.click.top, item.top + ( item.height / 2 ), item.height ),
26710			isOverRightHalf = this._isOverAxis( this.positionAbs.left +
26711				this.offset.click.left, item.left + ( item.width / 2 ), item.width ),
26712			verticalDirection = this.dragDirection.vertical,
26713			horizontalDirection = this.dragDirection.horizontal;
26714
26715		if ( this.floating && horizontalDirection ) {
26716			return ( ( horizontalDirection === "right" && isOverRightHalf ) ||
26717				( horizontalDirection === "left" && !isOverRightHalf ) );
26718		} else {
26719			return verticalDirection && ( ( verticalDirection === "down" && isOverBottomHalf ) ||
26720				( verticalDirection === "up" && !isOverBottomHalf ) );
26721		}
26722
26723	},
26724
26725	_getDragVerticalDirection: function() {
26726		var delta = this.positionAbs.top - this.lastPositionAbs.top;
26727		return delta !== 0 && ( delta > 0 ? "down" : "up" );
26728	},
26729
26730	_getDragHorizontalDirection: function() {
26731		var delta = this.positionAbs.left - this.lastPositionAbs.left;
26732		return delta !== 0 && ( delta > 0 ? "right" : "left" );
26733	},
26734
26735	refresh: function( event ) {
26736		this._refreshItems( event );
26737		this._setHandleClassName();
26738		this.refreshPositions();
26739		return this;
26740	},
26741
26742	_connectWith: function() {
26743		var options = this.options;
26744		return options.connectWith.constructor === String ?
26745			[ options.connectWith ] :
26746			options.connectWith;
26747	},
26748
26749	_getItemsAsjQuery: function( connected ) {
26750
26751		var i, j, cur, inst,
26752			items = [],
26753			queries = [],
26754			connectWith = this._connectWith();
26755
26756		if ( connectWith && connected ) {
26757			for ( i = connectWith.length - 1; i >= 0; i-- ) {
26758				cur = $( connectWith[ i ], this.document[ 0 ] );
26759				for ( j = cur.length - 1; j >= 0; j-- ) {
26760					inst = $.data( cur[ j ], this.widgetFullName );
26761					if ( inst && inst !== this && !inst.options.disabled ) {
26762						queries.push( [ typeof inst.options.items === "function" ?
26763							inst.options.items.call( inst.element ) :
26764							$( inst.options.items, inst.element )
26765								.not( ".ui-sortable-helper" )
26766								.not( ".ui-sortable-placeholder" ), inst ] );
26767					}
26768				}
26769			}
26770		}
26771
26772		queries.push( [ typeof this.options.items === "function" ?
26773			this.options.items
26774				.call( this.element, null, { options: this.options, item: this.currentItem } ) :
26775			$( this.options.items, this.element )
26776				.not( ".ui-sortable-helper" )
26777				.not( ".ui-sortable-placeholder" ), this ] );
26778
26779		function addItems() {
26780			items.push( this );
26781		}
26782		for ( i = queries.length - 1; i >= 0; i-- ) {
26783			queries[ i ][ 0 ].each( addItems );
26784		}
26785
26786		return $( items );
26787
26788	},
26789
26790	_removeCurrentsFromItems: function() {
26791
26792		var list = this.currentItem.find( ":data(" + this.widgetName + "-item)" );
26793
26794		this.items = $.grep( this.items, function( item ) {
26795			for ( var j = 0; j < list.length; j++ ) {
26796				if ( list[ j ] === item.item[ 0 ] ) {
26797					return false;
26798				}
26799			}
26800			return true;
26801		} );
26802
26803	},
26804
26805	_refreshItems: function( event ) {
26806
26807		this.items = [];
26808		this.containers = [ this ];
26809
26810		var i, j, cur, inst, targetData, _queries, item, queriesLength,
26811			items = this.items,
26812			queries = [ [ typeof this.options.items === "function" ?
26813				this.options.items.call( this.element[ 0 ], event, { item: this.currentItem } ) :
26814				$( this.options.items, this.element ), this ] ],
26815			connectWith = this._connectWith();
26816
26817		//Shouldn't be run the first time through due to massive slow-down
26818		if ( connectWith && this.ready ) {
26819			for ( i = connectWith.length - 1; i >= 0; i-- ) {
26820				cur = $( connectWith[ i ], this.document[ 0 ] );
26821				for ( j = cur.length - 1; j >= 0; j-- ) {
26822					inst = $.data( cur[ j ], this.widgetFullName );
26823					if ( inst && inst !== this && !inst.options.disabled ) {
26824						queries.push( [ typeof inst.options.items === "function" ?
26825							inst.options.items
26826								.call( inst.element[ 0 ], event, { item: this.currentItem } ) :
26827							$( inst.options.items, inst.element ), inst ] );
26828						this.containers.push( inst );
26829					}
26830				}
26831			}
26832		}
26833
26834		for ( i = queries.length - 1; i >= 0; i-- ) {
26835			targetData = queries[ i ][ 1 ];
26836			_queries = queries[ i ][ 0 ];
26837
26838			for ( j = 0, queriesLength = _queries.length; j < queriesLength; j++ ) {
26839				item = $( _queries[ j ] );
26840
26841				// Data for target checking (mouse manager)
26842				item.data( this.widgetName + "-item", targetData );
26843
26844				items.push( {
26845					item: item,
26846					instance: targetData,
26847					width: 0, height: 0,
26848					left: 0, top: 0
26849				} );
26850			}
26851		}
26852
26853	},
26854
26855	_refreshItemPositions: function( fast ) {
26856		var i, item, t, p;
26857
26858		for ( i = this.items.length - 1; i >= 0; i-- ) {
26859			item = this.items[ i ];
26860
26861			//We ignore calculating positions of all connected containers when we're not over them
26862			if ( this.currentContainer && item.instance !== this.currentContainer &&
26863					item.item[ 0 ] !== this.currentItem[ 0 ] ) {
26864				continue;
26865			}
26866
26867			t = this.options.toleranceElement ?
26868				$( this.options.toleranceElement, item.item ) :
26869				item.item;
26870
26871			if ( !fast ) {
26872				item.width = t.outerWidth();
26873				item.height = t.outerHeight();
26874			}
26875
26876			p = t.offset();
26877			item.left = p.left;
26878			item.top = p.top;
26879		}
26880	},
26881
26882	refreshPositions: function( fast ) {
26883
26884		// Determine whether items are being displayed horizontally
26885		this.floating = this.items.length ?
26886			this.options.axis === "x" || this._isFloating( this.items[ 0 ].item ) :
26887			false;
26888
26889		// This has to be redone because due to the item being moved out/into the offsetParent,
26890		// the offsetParent's position will change
26891		if ( this.offsetParent && this.helper ) {
26892			this.offset.parent = this._getParentOffset();
26893		}
26894
26895		this._refreshItemPositions( fast );
26896
26897		var i, p;
26898
26899		if ( this.options.custom && this.options.custom.refreshContainers ) {
26900			this.options.custom.refreshContainers.call( this );
26901		} else {
26902			for ( i = this.containers.length - 1; i >= 0; i-- ) {
26903				p = this.containers[ i ].element.offset();
26904				this.containers[ i ].containerCache.left = p.left;
26905				this.containers[ i ].containerCache.top = p.top;
26906				this.containers[ i ].containerCache.width =
26907					this.containers[ i ].element.outerWidth();
26908				this.containers[ i ].containerCache.height =
26909					this.containers[ i ].element.outerHeight();
26910			}
26911		}
26912
26913		return this;
26914	},
26915
26916	_createPlaceholder: function( that ) {
26917		that = that || this;
26918		var className, nodeName,
26919			o = that.options;
26920
26921		if ( !o.placeholder || o.placeholder.constructor === String ) {
26922			className = o.placeholder;
26923			nodeName = that.currentItem[ 0 ].nodeName.toLowerCase();
26924			o.placeholder = {
26925				element: function() {
26926
26927					var element = $( "<" + nodeName + ">", that.document[ 0 ] );
26928
26929					that._addClass( element, "ui-sortable-placeholder",
26930							className || that.currentItem[ 0 ].className )
26931						._removeClass( element, "ui-sortable-helper" );
26932
26933					if ( nodeName === "tbody" ) {
26934						that._createTrPlaceholder(
26935							that.currentItem.find( "tr" ).eq( 0 ),
26936							$( "<tr>", that.document[ 0 ] ).appendTo( element )
26937						);
26938					} else if ( nodeName === "tr" ) {
26939						that._createTrPlaceholder( that.currentItem, element );
26940					} else if ( nodeName === "img" ) {
26941						element.attr( "src", that.currentItem.attr( "src" ) );
26942					}
26943
26944					if ( !className ) {
26945						element.css( "visibility", "hidden" );
26946					}
26947
26948					return element;
26949				},
26950				update: function( container, p ) {
26951
26952					// 1. If a className is set as 'placeholder option, we don't force sizes -
26953					// the class is responsible for that
26954					// 2. The option 'forcePlaceholderSize can be enabled to force it even if a
26955					// class name is specified
26956					if ( className && !o.forcePlaceholderSize ) {
26957						return;
26958					}
26959
26960					// If the element doesn't have a actual height or width by itself (without
26961					// styles coming from a stylesheet), it receives the inline height and width
26962					// from the dragged item. Or, if it's a tbody or tr, it's going to have a height
26963					// anyway since we're populating them with <td>s above, but they're unlikely to
26964					// be the correct height on their own if the row heights are dynamic, so we'll
26965					// always assign the height of the dragged item given forcePlaceholderSize
26966					// is true.
26967					if ( !p.height() || ( o.forcePlaceholderSize &&
26968							( nodeName === "tbody" || nodeName === "tr" ) ) ) {
26969						p.height(
26970							that.currentItem.innerHeight() -
26971							parseInt( that.currentItem.css( "paddingTop" ) || 0, 10 ) -
26972							parseInt( that.currentItem.css( "paddingBottom" ) || 0, 10 ) );
26973					}
26974					if ( !p.width() ) {
26975						p.width(
26976							that.currentItem.innerWidth() -
26977							parseInt( that.currentItem.css( "paddingLeft" ) || 0, 10 ) -
26978							parseInt( that.currentItem.css( "paddingRight" ) || 0, 10 ) );
26979					}
26980				}
26981			};
26982		}
26983
26984		//Create the placeholder
26985		that.placeholder = $( o.placeholder.element.call( that.element, that.currentItem ) );
26986
26987		//Append it after the actual current item
26988		that.currentItem.after( that.placeholder );
26989
26990		//Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
26991		o.placeholder.update( that, that.placeholder );
26992
26993	},
26994
26995	_createTrPlaceholder: function( sourceTr, targetTr ) {
26996		var that = this;
26997
26998		sourceTr.children().each( function() {
26999			$( "<td>&#160;</td>", that.document[ 0 ] )
27000				.attr( "colspan", $( this ).attr( "colspan" ) || 1 )
27001				.appendTo( targetTr );
27002		} );
27003	},
27004
27005	_contactContainers: function( event ) {
27006		var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, cur, nearBottom,
27007			floating, axis,
27008			innermostContainer = null,
27009			innermostIndex = null;
27010
27011		// Get innermost container that intersects with item
27012		for ( i = this.containers.length - 1; i >= 0; i-- ) {
27013
27014			// Never consider a container that's located within the item itself
27015			if ( $.contains( this.currentItem[ 0 ], this.containers[ i ].element[ 0 ] ) ) {
27016				continue;
27017			}
27018
27019			if ( this._intersectsWith( this.containers[ i ].containerCache ) ) {
27020
27021				// If we've already found a container and it's more "inner" than this, then continue
27022				if ( innermostContainer &&
27023						$.contains(
27024							this.containers[ i ].element[ 0 ],
27025							innermostContainer.element[ 0 ] ) ) {
27026					continue;
27027				}
27028
27029				innermostContainer = this.containers[ i ];
27030				innermostIndex = i;
27031
27032			} else {
27033
27034				// container doesn't intersect. trigger "out" event if necessary
27035				if ( this.containers[ i ].containerCache.over ) {
27036					this.containers[ i ]._trigger( "out", event, this._uiHash( this ) );
27037					this.containers[ i ].containerCache.over = 0;
27038				}
27039			}
27040
27041		}
27042
27043		// If no intersecting containers found, return
27044		if ( !innermostContainer ) {
27045			return;
27046		}
27047
27048		// Move the item into the container if it's not there already
27049		if ( this.containers.length === 1 ) {
27050			if ( !this.containers[ innermostIndex ].containerCache.over ) {
27051				this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) );
27052				this.containers[ innermostIndex ].containerCache.over = 1;
27053			}
27054		} else {
27055
27056			// When entering a new container, we will find the item with the least distance and
27057			// append our item near it
27058			dist = 10000;
27059			itemWithLeastDistance = null;
27060			floating = innermostContainer.floating || this._isFloating( this.currentItem );
27061			posProperty = floating ? "left" : "top";
27062			sizeProperty = floating ? "width" : "height";
27063			axis = floating ? "pageX" : "pageY";
27064
27065			for ( j = this.items.length - 1; j >= 0; j-- ) {
27066				if ( !$.contains(
27067						this.containers[ innermostIndex ].element[ 0 ], this.items[ j ].item[ 0 ] )
27068				) {
27069					continue;
27070				}
27071				if ( this.items[ j ].item[ 0 ] === this.currentItem[ 0 ] ) {
27072					continue;
27073				}
27074
27075				cur = this.items[ j ].item.offset()[ posProperty ];
27076				nearBottom = false;
27077				if ( event[ axis ] - cur > this.items[ j ][ sizeProperty ] / 2 ) {
27078					nearBottom = true;
27079				}
27080
27081				if ( Math.abs( event[ axis ] - cur ) < dist ) {
27082					dist = Math.abs( event[ axis ] - cur );
27083					itemWithLeastDistance = this.items[ j ];
27084					this.direction = nearBottom ? "up" : "down";
27085				}
27086			}
27087
27088			//Check if dropOnEmpty is enabled
27089			if ( !itemWithLeastDistance && !this.options.dropOnEmpty ) {
27090				return;
27091			}
27092
27093			if ( this.currentContainer === this.containers[ innermostIndex ] ) {
27094				if ( !this.currentContainer.containerCache.over ) {
27095					this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash() );
27096					this.currentContainer.containerCache.over = 1;
27097				}
27098				return;
27099			}
27100
27101			if ( itemWithLeastDistance ) {
27102				this._rearrange( event, itemWithLeastDistance, null, true );
27103			} else {
27104				this._rearrange( event, null, this.containers[ innermostIndex ].element, true );
27105			}
27106			this._trigger( "change", event, this._uiHash() );
27107			this.containers[ innermostIndex ]._trigger( "change", event, this._uiHash( this ) );
27108			this.currentContainer = this.containers[ innermostIndex ];
27109
27110			//Update the placeholder
27111			this.options.placeholder.update( this.currentContainer, this.placeholder );
27112
27113			//Update scrollParent
27114			this.scrollParent = this.placeholder.scrollParent();
27115
27116			//Update overflowOffset
27117			if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
27118					this.scrollParent[ 0 ].tagName !== "HTML" ) {
27119				this.overflowOffset = this.scrollParent.offset();
27120			}
27121
27122			this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) );
27123			this.containers[ innermostIndex ].containerCache.over = 1;
27124		}
27125
27126	},
27127
27128	_createHelper: function( event ) {
27129
27130		var o = this.options,
27131			helper = typeof o.helper === "function" ?
27132				$( o.helper.apply( this.element[ 0 ], [ event, this.currentItem ] ) ) :
27133				( o.helper === "clone" ? this.currentItem.clone() : this.currentItem );
27134
27135		//Add the helper to the DOM if that didn't happen already
27136		if ( !helper.parents( "body" ).length ) {
27137			this.appendTo[ 0 ].appendChild( helper[ 0 ] );
27138		}
27139
27140		if ( helper[ 0 ] === this.currentItem[ 0 ] ) {
27141			this._storedCSS = {
27142				width: this.currentItem[ 0 ].style.width,
27143				height: this.currentItem[ 0 ].style.height,
27144				position: this.currentItem.css( "position" ),
27145				top: this.currentItem.css( "top" ),
27146				left: this.currentItem.css( "left" )
27147			};
27148		}
27149
27150		if ( !helper[ 0 ].style.width || o.forceHelperSize ) {
27151			helper.width( this.currentItem.width() );
27152		}
27153		if ( !helper[ 0 ].style.height || o.forceHelperSize ) {
27154			helper.height( this.currentItem.height() );
27155		}
27156
27157		return helper;
27158
27159	},
27160
27161	_adjustOffsetFromHelper: function( obj ) {
27162		if ( typeof obj === "string" ) {
27163			obj = obj.split( " " );
27164		}
27165		if ( Array.isArray( obj ) ) {
27166			obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 };
27167		}
27168		if ( "left" in obj ) {
27169			this.offset.click.left = obj.left + this.margins.left;
27170		}
27171		if ( "right" in obj ) {
27172			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
27173		}
27174		if ( "top" in obj ) {
27175			this.offset.click.top = obj.top + this.margins.top;
27176		}
27177		if ( "bottom" in obj ) {
27178			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
27179		}
27180	},
27181
27182	_getParentOffset: function() {
27183
27184		//Get the offsetParent and cache its position
27185		this.offsetParent = this.helper.offsetParent();
27186		var po = this.offsetParent.offset();
27187
27188		// This is a special case where we need to modify a offset calculated on start, since the
27189		// following happened:
27190		// 1. The position of the helper is absolute, so it's position is calculated based on the
27191		// next positioned parent
27192		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't
27193		// the document, which means that the scroll is included in the initial calculation of the
27194		// offset of the parent, and never recalculated upon drag
27195		if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== this.document[ 0 ] &&
27196				$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) {
27197			po.left += this.scrollParent.scrollLeft();
27198			po.top += this.scrollParent.scrollTop();
27199		}
27200
27201		// This needs to be actually done for all browsers, since pageX/pageY includes
27202		// this information.
27203		if ( this.offsetParent[ 0 ] === this.document[ 0 ].body ) {
27204			po = { top: 0, left: 0 };
27205		}
27206
27207		return {
27208			top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ),
27209			left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 )
27210		};
27211
27212	},
27213
27214	_getRelativeOffset: function() {
27215
27216		if ( this.cssPosition === "relative" ) {
27217			var p = this.currentItem.position();
27218			return {
27219				top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) +
27220					this.scrollParent.scrollTop(),
27221				left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) +
27222					this.scrollParent.scrollLeft()
27223			};
27224		} else {
27225			return { top: 0, left: 0 };
27226		}
27227
27228	},
27229
27230	_cacheMargins: function() {
27231		this.margins = {
27232			left: ( parseInt( this.currentItem.css( "marginLeft" ), 10 ) || 0 ),
27233			top: ( parseInt( this.currentItem.css( "marginTop" ), 10 ) || 0 )
27234		};
27235	},
27236
27237	_cacheHelperProportions: function() {
27238		this.helperProportions = {
27239			width: this.helper.outerWidth(),
27240			height: this.helper.outerHeight()
27241		};
27242	},
27243
27244	_setContainment: function() {
27245
27246		var ce, co, over,
27247			o = this.options;
27248		if ( o.containment === "parent" ) {
27249			o.containment = this.helper[ 0 ].parentNode;
27250		}
27251		if ( o.containment === "document" || o.containment === "window" ) {
27252			this.containment = [
27253				0 - this.offset.relative.left - this.offset.parent.left,
27254				0 - this.offset.relative.top - this.offset.parent.top,
27255				o.containment === "document" ?
27256					this.document.width() :
27257					this.window.width() - this.helperProportions.width - this.margins.left,
27258				( o.containment === "document" ?
27259					( this.document.height() || document.body.parentNode.scrollHeight ) :
27260					this.window.height() || this.document[ 0 ].body.parentNode.scrollHeight
27261				) - this.helperProportions.height - this.margins.top
27262			];
27263		}
27264
27265		if ( !( /^(document|window|parent)$/ ).test( o.containment ) ) {
27266			ce = $( o.containment )[ 0 ];
27267			co = $( o.containment ).offset();
27268			over = ( $( ce ).css( "overflow" ) !== "hidden" );
27269
27270			this.containment = [
27271				co.left + ( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) +
27272					( parseInt( $( ce ).css( "paddingLeft" ), 10 ) || 0 ) - this.margins.left,
27273				co.top + ( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) +
27274					( parseInt( $( ce ).css( "paddingTop" ), 10 ) || 0 ) - this.margins.top,
27275				co.left + ( over ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -
27276					( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) -
27277					( parseInt( $( ce ).css( "paddingRight" ), 10 ) || 0 ) -
27278					this.helperProportions.width - this.margins.left,
27279				co.top + ( over ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -
27280					( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) -
27281					( parseInt( $( ce ).css( "paddingBottom" ), 10 ) || 0 ) -
27282					this.helperProportions.height - this.margins.top
27283			];
27284		}
27285
27286	},
27287
27288	_convertPositionTo: function( d, pos ) {
27289
27290		if ( !pos ) {
27291			pos = this.position;
27292		}
27293		var mod = d === "absolute" ? 1 : -1,
27294			scroll = this.cssPosition === "absolute" &&
27295				!( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
27296				$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ?
27297					this.offsetParent :
27298					this.scrollParent,
27299			scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName );
27300
27301		return {
27302			top: (
27303
27304				// The absolute mouse position
27305				pos.top	+
27306
27307				// Only for relative positioned nodes: Relative offset from element to offset parent
27308				this.offset.relative.top * mod +
27309
27310				// The offsetParent's offset without borders (offset + border)
27311				this.offset.parent.top * mod -
27312				( ( this.cssPosition === "fixed" ?
27313					-this.scrollParent.scrollTop() :
27314					( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod )
27315			),
27316			left: (
27317
27318				// The absolute mouse position
27319				pos.left +
27320
27321				// Only for relative positioned nodes: Relative offset from element to offset parent
27322				this.offset.relative.left * mod +
27323
27324				// The offsetParent's offset without borders (offset + border)
27325				this.offset.parent.left * mod	-
27326				( ( this.cssPosition === "fixed" ?
27327					-this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 :
27328					scroll.scrollLeft() ) * mod )
27329			)
27330		};
27331
27332	},
27333
27334	_generatePosition: function( event ) {
27335
27336		var top, left,
27337			o = this.options,
27338			pageX = event.pageX,
27339			pageY = event.pageY,
27340			scroll = this.cssPosition === "absolute" &&
27341				!( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
27342				$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ?
27343					this.offsetParent :
27344					this.scrollParent,
27345				scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName );
27346
27347		// This is another very weird special case that only happens for relative elements:
27348		// 1. If the css position is relative
27349		// 2. and the scroll parent is the document or similar to the offset parent
27350		// we have to refresh the relative offset during the scroll so there are no jumps
27351		if ( this.cssPosition === "relative" && !( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
27352				this.scrollParent[ 0 ] !== this.offsetParent[ 0 ] ) ) {
27353			this.offset.relative = this._getRelativeOffset();
27354		}
27355
27356		/*
27357		 * - Position constraining -
27358		 * Constrain the position to a mix of grid, containment.
27359		 */
27360
27361		if ( this.originalPosition ) { //If we are not dragging yet, we won't check for options
27362
27363			if ( this.containment ) {
27364				if ( event.pageX - this.offset.click.left < this.containment[ 0 ] ) {
27365					pageX = this.containment[ 0 ] + this.offset.click.left;
27366				}
27367				if ( event.pageY - this.offset.click.top < this.containment[ 1 ] ) {
27368					pageY = this.containment[ 1 ] + this.offset.click.top;
27369				}
27370				if ( event.pageX - this.offset.click.left > this.containment[ 2 ] ) {
27371					pageX = this.containment[ 2 ] + this.offset.click.left;
27372				}
27373				if ( event.pageY - this.offset.click.top > this.containment[ 3 ] ) {
27374					pageY = this.containment[ 3 ] + this.offset.click.top;
27375				}
27376			}
27377
27378			if ( o.grid ) {
27379				top = this.originalPageY + Math.round( ( pageY - this.originalPageY ) /
27380					o.grid[ 1 ] ) * o.grid[ 1 ];
27381				pageY = this.containment ?
27382					( ( top - this.offset.click.top >= this.containment[ 1 ] &&
27383						top - this.offset.click.top <= this.containment[ 3 ] ) ?
27384							top :
27385							( ( top - this.offset.click.top >= this.containment[ 1 ] ) ?
27386								top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) :
27387								top;
27388
27389				left = this.originalPageX + Math.round( ( pageX - this.originalPageX ) /
27390					o.grid[ 0 ] ) * o.grid[ 0 ];
27391				pageX = this.containment ?
27392					( ( left - this.offset.click.left >= this.containment[ 0 ] &&
27393						left - this.offset.click.left <= this.containment[ 2 ] ) ?
27394							left :
27395							( ( left - this.offset.click.left >= this.containment[ 0 ] ) ?
27396								left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) :
27397								left;
27398			}
27399
27400		}
27401
27402		return {
27403			top: (
27404
27405				// The absolute mouse position
27406				pageY -
27407
27408				// Click offset (relative to the element)
27409				this.offset.click.top -
27410
27411				// Only for relative positioned nodes: Relative offset from element to offset parent
27412				this.offset.relative.top -
27413
27414				// The offsetParent's offset without borders (offset + border)
27415				this.offset.parent.top +
27416				( ( this.cssPosition === "fixed" ?
27417					-this.scrollParent.scrollTop() :
27418					( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) )
27419			),
27420			left: (
27421
27422				// The absolute mouse position
27423				pageX -
27424
27425				// Click offset (relative to the element)
27426				this.offset.click.left -
27427
27428				// Only for relative positioned nodes: Relative offset from element to offset parent
27429				this.offset.relative.left -
27430
27431				// The offsetParent's offset without borders (offset + border)
27432				this.offset.parent.left +
27433				( ( this.cssPosition === "fixed" ?
27434					-this.scrollParent.scrollLeft() :
27435					scrollIsRootNode ? 0 : scroll.scrollLeft() ) )
27436			)
27437		};
27438
27439	},
27440
27441	_rearrange: function( event, i, a, hardRefresh ) {
27442
27443		if ( a ) {
27444			a[ 0 ].appendChild( this.placeholder[ 0 ] );
27445		} else {
27446			i.item[ 0 ].parentNode.insertBefore( this.placeholder[ 0 ],
27447				( this.direction === "down" ? i.item[ 0 ] : i.item[ 0 ].nextSibling ) );
27448		}
27449
27450		//Various things done here to improve the performance:
27451		// 1. we create a setTimeout, that calls refreshPositions
27452		// 2. on the instance, we have a counter variable, that get's higher after every append
27453		// 3. on the local scope, we copy the counter variable, and check in the timeout,
27454		// if it's still the same
27455		// 4. this lets only the last addition to the timeout stack through
27456		this.counter = this.counter ? ++this.counter : 1;
27457		var counter = this.counter;
27458
27459		this._delay( function() {
27460			if ( counter === this.counter ) {
27461
27462				//Precompute after each DOM insertion, NOT on mousemove
27463				this.refreshPositions( !hardRefresh );
27464			}
27465		} );
27466
27467	},
27468
27469	_clear: function( event, noPropagation ) {
27470
27471		this.reverting = false;
27472
27473		// We delay all events that have to be triggered to after the point where the placeholder
27474		// has been removed and everything else normalized again
27475		var i,
27476			delayedTriggers = [];
27477
27478		// We first have to update the dom position of the actual currentItem
27479		// Note: don't do it if the current item is already removed (by a user), or it gets
27480		// reappended (see #4088)
27481		if ( !this._noFinalSort && this.currentItem.parent().length ) {
27482			this.placeholder.before( this.currentItem );
27483		}
27484		this._noFinalSort = null;
27485
27486		if ( this.helper[ 0 ] === this.currentItem[ 0 ] ) {
27487			for ( i in this._storedCSS ) {
27488				if ( this._storedCSS[ i ] === "auto" || this._storedCSS[ i ] === "static" ) {
27489					this._storedCSS[ i ] = "";
27490				}
27491			}
27492			this.currentItem.css( this._storedCSS );
27493			this._removeClass( this.currentItem, "ui-sortable-helper" );
27494		} else {
27495			this.currentItem.show();
27496		}
27497
27498		if ( this.fromOutside && !noPropagation ) {
27499			delayedTriggers.push( function( event ) {
27500				this._trigger( "receive", event, this._uiHash( this.fromOutside ) );
27501			} );
27502		}
27503		if ( ( this.fromOutside ||
27504				this.domPosition.prev !==
27505				this.currentItem.prev().not( ".ui-sortable-helper" )[ 0 ] ||
27506				this.domPosition.parent !== this.currentItem.parent()[ 0 ] ) && !noPropagation ) {
27507
27508			// Trigger update callback if the DOM position has changed
27509			delayedTriggers.push( function( event ) {
27510				this._trigger( "update", event, this._uiHash() );
27511			} );
27512		}
27513
27514		// Check if the items Container has Changed and trigger appropriate
27515		// events.
27516		if ( this !== this.currentContainer ) {
27517			if ( !noPropagation ) {
27518				delayedTriggers.push( function( event ) {
27519					this._trigger( "remove", event, this._uiHash() );
27520				} );
27521				delayedTriggers.push( ( function( c ) {
27522					return function( event ) {
27523						c._trigger( "receive", event, this._uiHash( this ) );
27524					};
27525				} ).call( this, this.currentContainer ) );
27526				delayedTriggers.push( ( function( c ) {
27527					return function( event ) {
27528						c._trigger( "update", event, this._uiHash( this ) );
27529					};
27530				} ).call( this, this.currentContainer ) );
27531			}
27532		}
27533
27534		//Post events to containers
27535		function delayEvent( type, instance, container ) {
27536			return function( event ) {
27537				container._trigger( type, event, instance._uiHash( instance ) );
27538			};
27539		}
27540		for ( i = this.containers.length - 1; i >= 0; i-- ) {
27541			if ( !noPropagation ) {
27542				delayedTriggers.push( delayEvent( "deactivate", this, this.containers[ i ] ) );
27543			}
27544			if ( this.containers[ i ].containerCache.over ) {
27545				delayedTriggers.push( delayEvent( "out", this, this.containers[ i ] ) );
27546				this.containers[ i ].containerCache.over = 0;
27547			}
27548		}
27549
27550		//Do what was originally in plugins
27551		if ( this._storedStylesheet ) {
27552			this._storedStylesheet.remove();
27553			this._storedStylesheet = null;
27554		}
27555		if ( this._storedOpacity ) {
27556			this.helper.css( "opacity", this._storedOpacity );
27557		}
27558		if ( this._storedZIndex ) {
27559			this.helper.css( "zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex );
27560		}
27561
27562		this.dragging = false;
27563
27564		if ( !noPropagation ) {
27565			this._trigger( "beforeStop", event, this._uiHash() );
27566		}
27567
27568		//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately,
27569		// it unbinds ALL events from the original node!
27570		this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] );
27571
27572		if ( !this.cancelHelperRemoval ) {
27573			if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {
27574				this.helper.remove();
27575			}
27576			this.helper = null;
27577		}
27578
27579		if ( !noPropagation ) {
27580			for ( i = 0; i < delayedTriggers.length; i++ ) {
27581
27582				// Trigger all delayed events
27583				delayedTriggers[ i ].call( this, event );
27584			}
27585			this._trigger( "stop", event, this._uiHash() );
27586		}
27587
27588		this.fromOutside = false;
27589		return !this.cancelHelperRemoval;
27590
27591	},
27592
27593	_trigger: function() {
27594		if ( $.Widget.prototype._trigger.apply( this, arguments ) === false ) {
27595			this.cancel();
27596		}
27597	},
27598
27599	_uiHash: function( _inst ) {
27600		var inst = _inst || this;
27601		return {
27602			helper: inst.helper,
27603			placeholder: inst.placeholder || $( [] ),
27604			position: inst.position,
27605			originalPosition: inst.originalPosition,
27606			offset: inst.positionAbs,
27607			item: inst.currentItem,
27608			sender: _inst ? _inst.element : null
27609		};
27610	}
27611
27612} );
27613
27614
27615/*!
27616 * jQuery UI Spinner 1.14.1
27617 * https://jqueryui.com
27618 *
27619 * Copyright OpenJS Foundation and other contributors
27620 * Released under the MIT license.
27621 * https://jquery.org/license
27622 */
27623
27624//>>label: Spinner
27625//>>group: Widgets
27626//>>description: Displays buttons to easily input numbers via the keyboard or mouse.
27627//>>docs: https://api.jqueryui.com/spinner/
27628//>>demos: https://jqueryui.com/spinner/
27629//>>css.structure: ../../themes/base/core.css
27630//>>css.structure: ../../themes/base/spinner.css
27631//>>css.theme: ../../themes/base/theme.css
27632
27633
27634function spinnerModifier( fn ) {
27635	return function() {
27636		var previous = this.element.val();
27637		fn.apply( this, arguments );
27638		this._refresh();
27639		if ( previous !== this.element.val() ) {
27640			this._trigger( "change" );
27641		}
27642	};
27643}
27644
27645$.widget( "ui.spinner", {
27646	version: "1.14.1",
27647	defaultElement: "<input>",
27648	widgetEventPrefix: "spin",
27649	options: {
27650		classes: {
27651			"ui-spinner": "ui-corner-all",
27652			"ui-spinner-down": "ui-corner-br",
27653			"ui-spinner-up": "ui-corner-tr"
27654		},
27655		culture: null,
27656		icons: {
27657			down: "ui-icon-triangle-1-s",
27658			up: "ui-icon-triangle-1-n"
27659		},
27660		incremental: true,
27661		max: null,
27662		min: null,
27663		numberFormat: null,
27664		page: 10,
27665		step: 1,
27666
27667		change: null,
27668		spin: null,
27669		start: null,
27670		stop: null
27671	},
27672
27673	_create: function() {
27674
27675		// handle string values that need to be parsed
27676		this._setOption( "max", this.options.max );
27677		this._setOption( "min", this.options.min );
27678		this._setOption( "step", this.options.step );
27679
27680		// Only format if there is a value, prevents the field from being marked
27681		// as invalid in Firefox, see #9573.
27682		if ( this.value() !== "" ) {
27683
27684			// Format the value, but don't constrain.
27685			this._value( this.element.val(), true );
27686		}
27687
27688		this._draw();
27689		this._on( this._events );
27690		this._refresh();
27691
27692		// Turning off autocomplete prevents the browser from remembering the
27693		// value when navigating through history, so we re-enable autocomplete
27694		// if the page is unloaded before the widget is destroyed. #7790
27695		this._on( this.window, {
27696			beforeunload: function() {
27697				this.element.removeAttr( "autocomplete" );
27698			}
27699		} );
27700	},
27701
27702	_getCreateOptions: function() {
27703		var options = this._super();
27704		var element = this.element;
27705
27706		$.each( [ "min", "max", "step" ], function( i, option ) {
27707			var value = element.attr( option );
27708			if ( value != null && value.length ) {
27709				options[ option ] = value;
27710			}
27711		} );
27712
27713		return options;
27714	},
27715
27716	_events: {
27717		keydown: function( event ) {
27718			if ( this._start( event ) && this._keydown( event ) ) {
27719				event.preventDefault();
27720			}
27721		},
27722		keyup: "_stop",
27723		focus: function() {
27724			this.previous = this.element.val();
27725		},
27726		blur: function( event ) {
27727			this._stop();
27728			this._refresh();
27729			if ( this.previous !== this.element.val() ) {
27730				this._trigger( "change", event );
27731			}
27732		},
27733		mousewheel: function( event, delta ) {
27734			var activeElement = this.document[ 0 ].activeElement;
27735			var isActive = this.element[ 0 ] === activeElement;
27736
27737			if ( !isActive || !delta ) {
27738				return;
27739			}
27740
27741			if ( !this.spinning && !this._start( event ) ) {
27742				return false;
27743			}
27744
27745			this._spin( ( delta > 0 ? 1 : -1 ) * this.options.step, event );
27746			clearTimeout( this.mousewheelTimer );
27747			this.mousewheelTimer = this._delay( function() {
27748				if ( this.spinning ) {
27749					this._stop( event );
27750				}
27751			}, 100 );
27752			event.preventDefault();
27753		},
27754		"mousedown .ui-spinner-button": function( event ) {
27755			var previous;
27756
27757			// We never want the buttons to have focus; whenever the user is
27758			// interacting with the spinner, the focus should be on the input.
27759			// If the input is focused then this.previous is properly set from
27760			// when the input first received focus. If the input is not focused
27761			// then we need to set this.previous based on the value before spinning.
27762			previous = this.element[ 0 ] === this.document[ 0 ].activeElement ?
27763				this.previous : this.element.val();
27764			function checkFocus() {
27765				var isActive = this.element[ 0 ] === this.document[ 0 ].activeElement;
27766				if ( !isActive ) {
27767					this.element.trigger( "focus" );
27768					this.previous = previous;
27769				}
27770			}
27771
27772			// Ensure focus is on (or stays on) the text field
27773			event.preventDefault();
27774			checkFocus.call( this );
27775
27776			if ( this._start( event ) === false ) {
27777				return;
27778			}
27779
27780			this._repeat( null, $( event.currentTarget )
27781				.hasClass( "ui-spinner-up" ) ? 1 : -1, event );
27782		},
27783		"mouseup .ui-spinner-button": "_stop",
27784		"mouseenter .ui-spinner-button": function( event ) {
27785
27786			// button will add ui-state-active if mouse was down while mouseleave and kept down
27787			if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) {
27788				return;
27789			}
27790
27791			if ( this._start( event ) === false ) {
27792				return false;
27793			}
27794			this._repeat( null, $( event.currentTarget )
27795				.hasClass( "ui-spinner-up" ) ? 1 : -1, event );
27796		},
27797
27798		// TODO: do we really want to consider this a stop?
27799		// shouldn't we just stop the repeater and wait until mouseup before
27800		// we trigger the stop event?
27801		"mouseleave .ui-spinner-button": "_stop"
27802	},
27803
27804	// Support mobile enhanced option and make backcompat more sane
27805	_enhance: function() {
27806		this.uiSpinner = this.element
27807			.attr( "autocomplete", "off" )
27808			.wrap( "<span>" )
27809			.parent()
27810
27811				// Add buttons
27812				.append(
27813					"<a></a><a></a>"
27814				);
27815	},
27816
27817	_draw: function() {
27818		this._enhance();
27819
27820		this._addClass( this.uiSpinner, "ui-spinner", "ui-widget ui-widget-content" );
27821		this._addClass( "ui-spinner-input" );
27822
27823		this.element.attr( "role", "spinbutton" );
27824
27825		// Button bindings
27826		this.buttons = this.uiSpinner.children( "a" )
27827			.attr( "tabIndex", -1 )
27828			.attr( "aria-hidden", true )
27829			.button( {
27830				classes: {
27831					"ui-button": ""
27832				}
27833			} );
27834
27835		// TODO: Right now button does not support classes this is already updated in button PR
27836		this._removeClass( this.buttons, "ui-corner-all" );
27837
27838		this._addClass( this.buttons.first(), "ui-spinner-button ui-spinner-up" );
27839		this._addClass( this.buttons.last(), "ui-spinner-button ui-spinner-down" );
27840		this.buttons.first().button( {
27841			"icon": this.options.icons.up,
27842			"showLabel": false
27843		} );
27844		this.buttons.last().button( {
27845			"icon": this.options.icons.down,
27846			"showLabel": false
27847		} );
27848
27849		// IE 6 doesn't understand height: 50% for the buttons
27850		// unless the wrapper has an explicit height
27851		if ( this.buttons.height() > Math.ceil( this.uiSpinner.height() * 0.5 ) &&
27852				this.uiSpinner.height() > 0 ) {
27853			this.uiSpinner.height( this.uiSpinner.height() );
27854		}
27855	},
27856
27857	_keydown: function( event ) {
27858		var options = this.options,
27859			keyCode = $.ui.keyCode;
27860
27861		switch ( event.keyCode ) {
27862		case keyCode.UP:
27863			this._repeat( null, 1, event );
27864			return true;
27865		case keyCode.DOWN:
27866			this._repeat( null, -1, event );
27867			return true;
27868		case keyCode.PAGE_UP:
27869			this._repeat( null, options.page, event );
27870			return true;
27871		case keyCode.PAGE_DOWN:
27872			this._repeat( null, -options.page, event );
27873			return true;
27874		}
27875
27876		return false;
27877	},
27878
27879	_start: function( event ) {
27880		if ( !this.spinning && this._trigger( "start", event ) === false ) {
27881			return false;
27882		}
27883
27884		if ( !this.counter ) {
27885			this.counter = 1;
27886		}
27887		this.spinning = true;
27888		return true;
27889	},
27890
27891	_repeat: function( i, steps, event ) {
27892		i = i || 500;
27893
27894		clearTimeout( this.timer );
27895		this.timer = this._delay( function() {
27896			this._repeat( 40, steps, event );
27897		}, i );
27898
27899		this._spin( steps * this.options.step, event );
27900	},
27901
27902	_spin: function( step, event ) {
27903		var value = this.value() || 0;
27904
27905		if ( !this.counter ) {
27906			this.counter = 1;
27907		}
27908
27909		value = this._adjustValue( value + step * this._increment( this.counter ) );
27910
27911		if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false ) {
27912			this._value( value );
27913			this.counter++;
27914		}
27915	},
27916
27917	_increment: function( i ) {
27918		var incremental = this.options.incremental;
27919
27920		if ( incremental ) {
27921			return typeof incremental === "function" ?
27922				incremental( i ) :
27923				Math.floor( i * i * i / 50000 - i * i / 500 + 17 * i / 200 + 1 );
27924		}
27925
27926		return 1;
27927	},
27928
27929	_precision: function() {
27930		var precision = this._precisionOf( this.options.step );
27931		if ( this.options.min !== null ) {
27932			precision = Math.max( precision, this._precisionOf( this.options.min ) );
27933		}
27934		return precision;
27935	},
27936
27937	_precisionOf: function( num ) {
27938		var str = num.toString(),
27939			decimal = str.indexOf( "." );
27940		return decimal === -1 ? 0 : str.length - decimal - 1;
27941	},
27942
27943	_adjustValue: function( value ) {
27944		var base, aboveMin,
27945			options = this.options;
27946
27947		// Make sure we're at a valid step
27948		// - find out where we are relative to the base (min or 0)
27949		base = options.min !== null ? options.min : 0;
27950		aboveMin = value - base;
27951
27952		// - round to the nearest step
27953		aboveMin = Math.round( aboveMin / options.step ) * options.step;
27954
27955		// - rounding is based on 0, so adjust back to our base
27956		value = base + aboveMin;
27957
27958		// Fix precision from bad JS floating point math
27959		value = parseFloat( value.toFixed( this._precision() ) );
27960
27961		// Clamp the value
27962		if ( options.max !== null && value > options.max ) {
27963			return options.max;
27964		}
27965		if ( options.min !== null && value < options.min ) {
27966			return options.min;
27967		}
27968
27969		return value;
27970	},
27971
27972	_stop: function( event ) {
27973		if ( !this.spinning ) {
27974			return;
27975		}
27976
27977		clearTimeout( this.timer );
27978		clearTimeout( this.mousewheelTimer );
27979		this.counter = 0;
27980		this.spinning = false;
27981		this._trigger( "stop", event );
27982	},
27983
27984	_setOption: function( key, value ) {
27985		var prevValue, first, last;
27986
27987		if ( key === "culture" || key === "numberFormat" ) {
27988			prevValue = this._parse( this.element.val() );
27989			this.options[ key ] = value;
27990			this.element.val( this._format( prevValue ) );
27991			return;
27992		}
27993
vendor: 6,415 bytes, lines 27994-28247
27994		if ( key === "max" || key === "min" || key === "step" ) {
27995			if ( typeof value === "string" ) {
27996				value = this._parse( value );
27997			}
27998		}
27999		if ( key === "icons" ) {
28000			first = this.buttons.first().find( ".ui-icon" );
28001			this._removeClass( first, null, this.options.icons.up );
28002			this._addClass( first, null, value.up );
28003			last = this.buttons.last().find( ".ui-icon" );
28004			this._removeClass( last, null, this.options.icons.down );
28005			this._addClass( last, null, value.down );
28006		}
28007
28008		this._super( key, value );
28009	},
28010
28011	_setOptionDisabled: function( value ) {
28012		this._super( value );
28013
28014		this._toggleClass( this.uiSpinner, null, "ui-state-disabled", !!value );
28015		this.element.prop( "disabled", !!value );
28016		this.buttons.button( value ? "disable" : "enable" );
28017	},
28018
28019	_setOptions: spinnerModifier( function( options ) {
28020		this._super( options );
28021	} ),
28022
28023	_parse: function( val ) {
28024		if ( typeof val === "string" && val !== "" ) {
28025			val = window.Globalize && this.options.numberFormat ?
28026				Globalize.parseFloat( val, 10, this.options.culture ) : +val;
28027		}
28028		return val === "" || isNaN( val ) ? null : val;
28029	},
28030
28031	_format: function( value ) {
28032		if ( value === "" ) {
28033			return "";
28034		}
28035		return window.Globalize && this.options.numberFormat ?
28036			Globalize.format( value, this.options.numberFormat, this.options.culture ) :
28037			value;
28038	},
28039
28040	_refresh: function() {
28041		this.element.attr( {
28042			"aria-valuemin": this.options.min,
28043			"aria-valuemax": this.options.max,
28044
28045			// TODO: what should we do with values that can't be parsed?
28046			"aria-valuenow": this._parse( this.element.val() )
28047		} );
28048	},
28049
28050	isValid: function() {
28051		var value = this.value();
28052
28053		// Null is invalid
28054		if ( value === null ) {
28055			return false;
28056		}
28057
28058		// If value gets adjusted, it's invalid
28059		return value === this._adjustValue( value );
28060	},
28061
28062	// Update the value without triggering change
28063	_value: function( value, allowAny ) {
28064		var parsed;
28065		if ( value !== "" ) {
28066			parsed = this._parse( value );
28067			if ( parsed !== null ) {
28068				if ( !allowAny ) {
28069					parsed = this._adjustValue( parsed );
28070				}
28071				value = this._format( parsed );
28072			}
28073		}
28074		this.element.val( value );
28075		this._refresh();
28076	},
28077
28078	_destroy: function() {
28079		this.element
28080			.prop( "disabled", false )
28081			.removeAttr( "autocomplete role aria-valuemin aria-valuemax aria-valuenow" );
28082
28083		this.uiSpinner.replaceWith( this.element );
28084	},
28085
28086	stepUp: spinnerModifier( function( steps ) {
28087		this._stepUp( steps );
28088	} ),
28089	_stepUp: function( steps ) {
28090		if ( this._start() ) {
28091			this._spin( ( steps || 1 ) * this.options.step );
28092			this._stop();
28093		}
28094	},
28095
28096	stepDown: spinnerModifier( function( steps ) {
28097		this._stepDown( steps );
28098	} ),
28099	_stepDown: function( steps ) {
28100		if ( this._start() ) {
28101			this._spin( ( steps || 1 ) * -this.options.step );
28102			this._stop();
28103		}
28104	},
28105
28106	pageUp: spinnerModifier( function( pages ) {
28107		this._stepUp( ( pages || 1 ) * this.options.page );
28108	} ),
28109
28110	pageDown: spinnerModifier( function( pages ) {
28111		this._stepDown( ( pages || 1 ) * this.options.page );
28112	} ),
28113
28114	value: function( newVal ) {
28115		if ( !arguments.length ) {
28116			return this._parse( this.element.val() );
28117		}
28118		spinnerModifier( this._value ).call( this, newVal );
28119	},
28120
28121	widget: function() {
28122		return this.uiSpinner;
28123	}
28124} );
28125
28126// DEPRECATED
28127// TODO: switch return back to widget declaration at top of file when this is removed
28128if ( $.uiBackCompat === true ) {
28129
28130	// Backcompat for spinner html extension points
28131	$.widget( "ui.spinner", $.ui.spinner, {
28132		_enhance: function() {
28133			this.uiSpinner = this.element
28134				.attr( "autocomplete", "off" )
28135				.wrap( this._uiSpinnerHtml() )
28136				.parent()
28137
28138					// Add buttons
28139					.append( this._buttonHtml() );
28140		},
28141		_uiSpinnerHtml: function() {
28142			return "<span>";
28143		},
28144
28145		_buttonHtml: function() {
28146			return "<a></a><a></a>";
28147		}
28148	} );
28149}
28150
28151var widgetsSpinner = $.ui.spinner;
28152
28153
28154/*!
28155 * jQuery UI Tabs 1.14.1
28156 * https://jqueryui.com
28157 *
28158 * Copyright OpenJS Foundation and other contributors
28159 * Released under the MIT license.
28160 * https://jquery.org/license
28161 */
28162
28163//>>label: Tabs
28164//>>group: Widgets
28165//>>description: Transforms a set of container elements into a tab structure.
28166//>>docs: https://api.jqueryui.com/tabs/
28167//>>demos: https://jqueryui.com/tabs/
28168//>>css.structure: ../../themes/base/core.css
28169//>>css.structure: ../../themes/base/tabs.css
28170//>>css.theme: ../../themes/base/theme.css
28171
28172
28173$.widget( "ui.tabs", {
28174	version: "1.14.1",
28175	delay: 300,
28176	options: {
28177		active: null,
28178		classes: {
28179			"ui-tabs": "ui-corner-all",
28180			"ui-tabs-nav": "ui-corner-all",
28181			"ui-tabs-panel": "ui-corner-bottom",
28182			"ui-tabs-tab": "ui-corner-top"
28183		},
28184		collapsible: false,
28185		event: "click",
28186		heightStyle: "content",
28187		hide: null,
28188		show: null,
28189
28190		// Callbacks
28191		activate: null,
28192		beforeActivate: null,
28193		beforeLoad: null,
28194		load: null
28195	},
28196
28197	_isLocal: ( function() {
28198		var rhash = /#.*$/;
28199
28200		return function( anchor ) {
28201			var anchorUrl, locationUrl;
28202
28203			anchorUrl = anchor.href.replace( rhash, "" );
28204			locationUrl = location.href.replace( rhash, "" );
28205
28206			// Decoding may throw an error if the URL isn't UTF-8 (#9518)
28207			try {
28208				anchorUrl = decodeURIComponent( anchorUrl );
28209			} catch ( error ) {}
28210			try {
28211				locationUrl = decodeURIComponent( locationUrl );
28212			} catch ( error ) {}
28213
28214			return anchor.hash.length > 1 && anchorUrl === locationUrl;
28215		};
28216	} )(),
28217
28218	_create: function() {
28219		var that = this,
28220			options = this.options;
28221
28222		this.running = false;
28223
28224		this._addClass( "ui-tabs", "ui-widget ui-widget-content" );
28225		this._toggleClass( "ui-tabs-collapsible", null, options.collapsible );
28226
28227		this._processTabs();
28228		options.active = this._initialActive();
28229
28230		// Take disabling tabs via class attribute from HTML
28231		// into account and update option properly.
28232		if ( Array.isArray( options.disabled ) ) {
28233			options.disabled = $.uniqueSort( options.disabled.concat(
28234				$.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) {
28235					return that.tabs.index( li );
28236				} )
28237			) ).sort();
28238		}
28239
28240		// Check for length avoids error when initializing empty list
28241		if ( this.options.active !== false && this.anchors.length ) {
28242			this.active = this._findActive( options.active );
28243		} else {
28244			this.active = $();
28245		}
28246
28247		this._refresh();
vendor: 30,881 bytes, lines 28248-29378
28248
28249		if ( this.active.length ) {
28250			this.load( options.active );
28251		}
28252	},
28253
28254	_initialActive: function() {
28255		var active = this.options.active,
28256			collapsible = this.options.collapsible,
28257			locationHashDecoded = decodeURIComponent( location.hash.substring( 1 ) );
28258
28259		if ( active === null ) {
28260
28261			// check the fragment identifier in the URL
28262			if ( locationHashDecoded ) {
28263				this.tabs.each( function( i, tab ) {
28264					if ( $( tab ).attr( "aria-controls" ) === locationHashDecoded ) {
28265						active = i;
28266						return false;
28267					}
28268				} );
28269			}
28270
28271			// Check for a tab marked active via a class
28272			if ( active === null ) {
28273				active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) );
28274			}
28275
28276			// No active tab, set to false
28277			if ( active === null || active === -1 ) {
28278				active = this.tabs.length ? 0 : false;
28279			}
28280		}
28281
28282		// Handle numbers: negative, out of range
28283		if ( active !== false ) {
28284			active = this.tabs.index( this.tabs.eq( active ) );
28285			if ( active === -1 ) {
28286				active = collapsible ? false : 0;
28287			}
28288		}
28289
28290		// Don't allow collapsible: false and active: false
28291		if ( !collapsible && active === false && this.anchors.length ) {
28292			active = 0;
28293		}
28294
28295		return active;
28296	},
28297
28298	_getCreateEventData: function() {
28299		return {
28300			tab: this.active,
28301			panel: !this.active.length ? $() : this._getPanelForTab( this.active )
28302		};
28303	},
28304
28305	_tabKeydown: function( event ) {
28306		var focusedTab = $( this.document[ 0 ].activeElement ).closest( "li" ),
28307			selectedIndex = this.tabs.index( focusedTab ),
28308			goingForward = true;
28309
28310		if ( this._handlePageNav( event ) ) {
28311			return;
28312		}
28313
28314		switch ( event.keyCode ) {
28315		case $.ui.keyCode.RIGHT:
28316		case $.ui.keyCode.DOWN:
28317			selectedIndex++;
28318			break;
28319		case $.ui.keyCode.UP:
28320		case $.ui.keyCode.LEFT:
28321			goingForward = false;
28322			selectedIndex--;
28323			break;
28324		case $.ui.keyCode.END:
28325			selectedIndex = this.anchors.length - 1;
28326			break;
28327		case $.ui.keyCode.HOME:
28328			selectedIndex = 0;
28329			break;
28330		case $.ui.keyCode.SPACE:
28331
28332			// Activate only, no collapsing
28333			event.preventDefault();
28334			clearTimeout( this.activating );
28335			this._activate( selectedIndex );
28336			return;
28337		case $.ui.keyCode.ENTER:
28338
28339			// Toggle (cancel delayed activation, allow collapsing)
28340			event.preventDefault();
28341			clearTimeout( this.activating );
28342
28343			// Determine if we should collapse or activate
28344			this._activate( selectedIndex === this.options.active ? false : selectedIndex );
28345			return;
28346		default:
28347			return;
28348		}
28349
28350		// Focus the appropriate tab, based on which key was pressed
28351		event.preventDefault();
28352		clearTimeout( this.activating );
28353		selectedIndex = this._focusNextTab( selectedIndex, goingForward );
28354
28355		// Navigating with control/command key will prevent automatic activation
28356		if ( !event.ctrlKey && !event.metaKey ) {
28357
28358			// Update aria-selected immediately so that AT think the tab is already selected.
28359			// Otherwise AT may confuse the user by stating that they need to activate the tab,
28360			// but the tab will already be activated by the time the announcement finishes.
28361			focusedTab.attr( "aria-selected", "false" );
28362			this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" );
28363
28364			this.activating = this._delay( function() {
28365				this.option( "active", selectedIndex );
28366			}, this.delay );
28367		}
28368	},
28369
28370	_panelKeydown: function( event ) {
28371		if ( this._handlePageNav( event ) ) {
28372			return;
28373		}
28374
28375		// Ctrl+up moves focus to the current tab
28376		if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {
28377			event.preventDefault();
28378			this.active.trigger( "focus" );
28379		}
28380	},
28381
28382	// Alt+page up/down moves focus to the previous/next tab (and activates)
28383	_handlePageNav: function( event ) {
28384		if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {
28385			this._activate( this._focusNextTab( this.options.active - 1, false ) );
28386			return true;
28387		}
28388		if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {
28389			this._activate( this._focusNextTab( this.options.active + 1, true ) );
28390			return true;
28391		}
28392	},
28393
28394	_findNextTab: function( index, goingForward ) {
28395		var lastTabIndex = this.tabs.length - 1;
28396
28397		function constrain() {
28398			if ( index > lastTabIndex ) {
28399				index = 0;
28400			}
28401			if ( index < 0 ) {
28402				index = lastTabIndex;
28403			}
28404			return index;
28405		}
28406
28407		while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {
28408			index = goingForward ? index + 1 : index - 1;
28409		}
28410
28411		return index;
28412	},
28413
28414	_focusNextTab: function( index, goingForward ) {
28415		index = this._findNextTab( index, goingForward );
28416		this.tabs.eq( index ).trigger( "focus" );
28417		return index;
28418	},
28419
28420	_setOption: function( key, value ) {
28421		if ( key === "active" ) {
28422
28423			// _activate() will handle invalid values and update this.options
28424			this._activate( value );
28425			return;
28426		}
28427
28428		this._super( key, value );
28429
28430		if ( key === "collapsible" ) {
28431			this._toggleClass( "ui-tabs-collapsible", null, value );
28432
28433			// Setting collapsible: false while collapsed; open first panel
28434			if ( !value && this.options.active === false ) {
28435				this._activate( 0 );
28436			}
28437		}
28438
28439		if ( key === "event" ) {
28440			this._setupEvents( value );
28441		}
28442
28443		if ( key === "heightStyle" ) {
28444			this._setupHeightStyle( value );
28445		}
28446	},
28447
28448	refresh: function() {
28449		var options = this.options,
28450			lis = this.tablist.children( ":has(a[href])" );
28451
28452		// Get disabled tabs from class attribute from HTML
28453		// this will get converted to a boolean if needed in _refresh()
28454		options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) {
28455			return lis.index( tab );
28456		} );
28457
28458		this._processTabs();
28459
28460		// Was collapsed or no tabs
28461		if ( options.active === false || !this.anchors.length ) {
28462			options.active = false;
28463			this.active = $();
28464
28465		// was active, but active tab is gone
28466		} else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {
28467
28468			// all remaining tabs are disabled
28469			if ( this.tabs.length === options.disabled.length ) {
28470				options.active = false;
28471				this.active = $();
28472
28473			// activate previous tab
28474			} else {
28475				this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );
28476			}
28477
28478		// was active, active tab still exists
28479		} else {
28480
28481			// make sure active index is correct
28482			options.active = this.tabs.index( this.active );
28483		}
28484
28485		this._refresh();
28486	},
28487
28488	_refresh: function() {
28489		this._setOptionDisabled( this.options.disabled );
28490		this._setupEvents( this.options.event );
28491		this._setupHeightStyle( this.options.heightStyle );
28492
28493		this.tabs.not( this.active ).attr( {
28494			"aria-selected": "false",
28495			"aria-expanded": "false",
28496			tabIndex: -1
28497		} );
28498		this.panels.not( this._getPanelForTab( this.active ) )
28499			.hide()
28500			.attr( {
28501				"aria-hidden": "true"
28502			} );
28503
28504		// Make sure one tab is in the tab order
28505		if ( !this.active.length ) {
28506			this.tabs.eq( 0 ).attr( "tabIndex", 0 );
28507		} else {
28508			this.active
28509				.attr( {
28510					"aria-selected": "true",
28511					"aria-expanded": "true",
28512					tabIndex: 0
28513				} );
28514			this._addClass( this.active, "ui-tabs-active", "ui-state-active" );
28515			this._getPanelForTab( this.active )
28516				.show()
28517				.attr( {
28518					"aria-hidden": "false"
28519				} );
28520		}
28521	},
28522
28523	_processTabs: function() {
28524		var that = this,
28525			prevTabs = this.tabs,
28526			prevAnchors = this.anchors,
28527			prevPanels = this.panels;
28528
28529		this.tablist = this._getList().attr( "role", "tablist" );
28530		this._addClass( this.tablist, "ui-tabs-nav",
28531			"ui-helper-reset ui-helper-clearfix ui-widget-header" );
28532
28533		// Prevent users from focusing disabled tabs via click
28534		this.tablist
28535			.on( "mousedown" + this.eventNamespace, "> li", function( event ) {
28536				if ( $( this ).is( ".ui-state-disabled" ) ) {
28537					event.preventDefault();
28538				}
28539			} );
28540
28541		this.tabs = this.tablist.find( "> li:has(a[href])" )
28542			.attr( {
28543				role: "tab",
28544				tabIndex: -1
28545			} );
28546		this._addClass( this.tabs, "ui-tabs-tab", "ui-state-default" );
28547
28548		this.anchors = this.tabs.map( function() {
28549			return $( "a", this )[ 0 ];
28550		} )
28551			.attr( {
28552				tabIndex: -1
28553			} );
28554		this._addClass( this.anchors, "ui-tabs-anchor" );
28555
28556		this.panels = $();
28557
28558		this.anchors.each( function( i, anchor ) {
28559			var selector, panel, panelId,
28560				anchorId = $( anchor ).uniqueId().attr( "id" ),
28561				tab = $( anchor ).closest( "li" ),
28562				originalAriaControls = tab.attr( "aria-controls" );
28563
28564			// Inline tab
28565			if ( that._isLocal( anchor ) ) {
28566				selector = decodeURIComponent( anchor.hash );
28567				panelId = selector.substring( 1 );
28568				panel = that.element.find( "#" + CSS.escape( panelId ) );
28569
28570			// remote tab
28571			} else {
28572
28573				// If the tab doesn't already have aria-controls,
28574				// generate an id by using a throw-away element
28575				panelId = tab.attr( "aria-controls" ) || $( {} ).uniqueId()[ 0 ].id;
28576				selector = "#" + panelId;
28577				panel = that.element.find( selector );
28578				if ( !panel.length ) {
28579					panel = that._createPanel( panelId );
28580					panel.insertAfter( that.panels[ i - 1 ] || that.tablist );
28581				}
28582				panel.attr( "aria-live", "polite" );
28583			}
28584
28585			if ( panel.length ) {
28586				that.panels = that.panels.add( panel );
28587			}
28588			if ( originalAriaControls ) {
28589				tab.data( "ui-tabs-aria-controls", originalAriaControls );
28590			}
28591			tab.attr( {
28592				"aria-controls": panelId,
28593				"aria-labelledby": anchorId
28594			} );
28595			panel.attr( "aria-labelledby", anchorId );
28596		} );
28597
28598		this.panels.attr( "role", "tabpanel" );
28599		this._addClass( this.panels, "ui-tabs-panel", "ui-widget-content" );
28600
28601		// Avoid memory leaks (#10056)
28602		if ( prevTabs ) {
28603			this._off( prevTabs.not( this.tabs ) );
28604			this._off( prevAnchors.not( this.anchors ) );
28605			this._off( prevPanels.not( this.panels ) );
28606		}
28607	},
28608
28609	// Allow overriding how to find the list for rare usage scenarios (#7715)
28610	_getList: function() {
28611		return this.tablist || this.element.find( "ol, ul" ).eq( 0 );
28612	},
28613
28614	_createPanel: function( id ) {
28615		return $( "<div>" )
28616			.attr( "id", id )
28617			.data( "ui-tabs-destroy", true );
28618	},
28619
28620	_setOptionDisabled: function( disabled ) {
28621		var currentItem, li, i;
28622
28623		if ( Array.isArray( disabled ) ) {
28624			if ( !disabled.length ) {
28625				disabled = false;
28626			} else if ( disabled.length === this.anchors.length ) {
28627				disabled = true;
28628			}
28629		}
28630
28631		// Disable tabs
28632		for ( i = 0; ( li = this.tabs[ i ] ); i++ ) {
28633			currentItem = $( li );
28634			if ( disabled === true || $.inArray( i, disabled ) !== -1 ) {
28635				currentItem.attr( "aria-disabled", "true" );
28636				this._addClass( currentItem, null, "ui-state-disabled" );
28637			} else {
28638				currentItem.removeAttr( "aria-disabled" );
28639				this._removeClass( currentItem, null, "ui-state-disabled" );
28640			}
28641		}
28642
28643		this.options.disabled = disabled;
28644
28645		this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null,
28646			disabled === true );
28647	},
28648
28649	_setupEvents: function( event ) {
28650		var events = {};
28651		if ( event ) {
28652			$.each( event.split( " " ), function( index, eventName ) {
28653				events[ eventName ] = "_eventHandler";
28654			} );
28655		}
28656
28657		this._off( this.anchors.add( this.tabs ).add( this.panels ) );
28658
28659		// Always prevent the default action, even when disabled
28660		this._on( true, this.anchors, {
28661			click: function( event ) {
28662				event.preventDefault();
28663			}
28664		} );
28665		this._on( this.anchors, events );
28666		this._on( this.tabs, { keydown: "_tabKeydown" } );
28667		this._on( this.panels, { keydown: "_panelKeydown" } );
28668
28669		this._focusable( this.tabs );
28670		this._hoverable( this.tabs );
28671	},
28672
28673	_setupHeightStyle: function( heightStyle ) {
28674		var maxHeight,
28675			parent = this.element.parent();
28676
28677		if ( heightStyle === "fill" ) {
28678			maxHeight = parent.height();
28679			maxHeight -= this.element.outerHeight() - this.element.height();
28680
28681			this.element.siblings( ":visible" ).each( function() {
28682				var elem = $( this ),
28683					position = elem.css( "position" );
28684
28685				if ( position === "absolute" || position === "fixed" ) {
28686					return;
28687				}
28688				maxHeight -= elem.outerHeight( true );
28689			} );
28690
28691			this.element.children().not( this.panels ).each( function() {
28692				maxHeight -= $( this ).outerHeight( true );
28693			} );
28694
28695			this.panels.each( function() {
28696				$( this ).height( Math.max( 0, maxHeight -
28697					$( this ).innerHeight() + $( this ).height() ) );
28698			} )
28699				.css( "overflow", "auto" );
28700		} else if ( heightStyle === "auto" ) {
28701			maxHeight = 0;
28702			this.panels.each( function() {
28703				maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
28704			} ).height( maxHeight );
28705		}
28706	},
28707
28708	_eventHandler: function( event ) {
28709		var options = this.options,
28710			active = this.active,
28711			anchor = $( event.currentTarget ),
28712			tab = anchor.closest( "li" ),
28713			clickedIsActive = tab[ 0 ] === active[ 0 ],
28714			collapsing = clickedIsActive && options.collapsible,
28715			toShow = collapsing ? $() : this._getPanelForTab( tab ),
28716			toHide = !active.length ? $() : this._getPanelForTab( active ),
28717			eventData = {
28718				oldTab: active,
28719				oldPanel: toHide,
28720				newTab: collapsing ? $() : tab,
28721				newPanel: toShow
28722			};
28723
28724		event.preventDefault();
28725
28726		if ( tab.hasClass( "ui-state-disabled" ) ||
28727
28728				// tab is already loading
28729				tab.hasClass( "ui-tabs-loading" ) ||
28730
28731				// can't switch durning an animation
28732				this.running ||
28733
28734				// click on active header, but not collapsible
28735				( clickedIsActive && !options.collapsible ) ||
28736
28737				// allow canceling activation
28738				( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
28739			return;
28740		}
28741
28742		options.active = collapsing ? false : this.tabs.index( tab );
28743
28744		this.active = clickedIsActive ? $() : tab;
28745		if ( this.xhr ) {
28746			this.xhr.abort();
28747		}
28748
28749		if ( !toHide.length && !toShow.length ) {
28750			$.error( "jQuery UI Tabs: Mismatching fragment identifier." );
28751		}
28752
28753		if ( toShow.length ) {
28754			this.load( this.tabs.index( tab ), event );
28755		}
28756		this._toggle( event, eventData );
28757	},
28758
28759	// Handles show/hide for selecting tabs
28760	_toggle: function( event, eventData ) {
28761		var that = this,
28762			toShow = eventData.newPanel,
28763			toHide = eventData.oldPanel;
28764
28765		this.running = true;
28766
28767		function complete() {
28768			that.running = false;
28769			that._trigger( "activate", event, eventData );
28770		}
28771
28772		function show() {
28773			that._addClass( eventData.newTab.closest( "li" ), "ui-tabs-active", "ui-state-active" );
28774
28775			if ( toShow.length && that.options.show ) {
28776				that._show( toShow, that.options.show, complete );
28777			} else {
28778				toShow.show();
28779				complete();
28780			}
28781		}
28782
28783		// Start out by hiding, then showing, then completing
28784		if ( toHide.length && this.options.hide ) {
28785			this._hide( toHide, this.options.hide, function() {
28786				that._removeClass( eventData.oldTab.closest( "li" ),
28787					"ui-tabs-active", "ui-state-active" );
28788				show();
28789			} );
28790		} else {
28791			this._removeClass( eventData.oldTab.closest( "li" ),
28792				"ui-tabs-active", "ui-state-active" );
28793			toHide.hide();
28794			show();
28795		}
28796
28797		toHide.attr( "aria-hidden", "true" );
28798		eventData.oldTab.attr( {
28799			"aria-selected": "false",
28800			"aria-expanded": "false"
28801		} );
28802
28803		// If we're switching tabs, remove the old tab from the tab order.
28804		// If we're opening from collapsed state, remove the previous tab from the tab order.
28805		// If we're collapsing, then keep the collapsing tab in the tab order.
28806		if ( toShow.length && toHide.length ) {
28807			eventData.oldTab.attr( "tabIndex", -1 );
28808		} else if ( toShow.length ) {
28809			this.tabs.filter( function() {
28810				return $( this ).attr( "tabIndex" ) === 0;
28811			} )
28812				.attr( "tabIndex", -1 );
28813		}
28814
28815		toShow.attr( "aria-hidden", "false" );
28816		eventData.newTab.attr( {
28817			"aria-selected": "true",
28818			"aria-expanded": "true",
28819			tabIndex: 0
28820		} );
28821	},
28822
28823	_activate: function( index ) {
28824		var anchor,
28825			active = this._findActive( index );
28826
28827		// Trying to activate the already active panel
28828		if ( active[ 0 ] === this.active[ 0 ] ) {
28829			return;
28830		}
28831
28832		// Trying to collapse, simulate a click on the current active header
28833		if ( !active.length ) {
28834			active = this.active;
28835		}
28836
28837		anchor = active.find( ".ui-tabs-anchor" )[ 0 ];
28838		this._eventHandler( {
28839			target: anchor,
28840			currentTarget: anchor,
28841			preventDefault: $.noop
28842		} );
28843	},
28844
28845	_findActive: function( index ) {
28846		return index === false ? $() : this.tabs.eq( index );
28847	},
28848
28849	_getIndex: function( index ) {
28850
28851		// meta-function to give users option to provide a href string instead of a numerical index.
28852		if ( typeof index === "string" ) {
28853			index = this.anchors.index( this.anchors.filter( "[href$='" +
28854				CSS.escape( index ) + "']" ) );
28855		}
28856
28857		return index;
28858	},
28859
28860	_destroy: function() {
28861		if ( this.xhr ) {
28862			this.xhr.abort();
28863		}
28864
28865		this.tablist
28866			.removeAttr( "role" )
28867			.off( this.eventNamespace );
28868
28869		this.anchors
28870			.removeAttr( "role tabIndex" )
28871			.removeUniqueId();
28872
28873		this.tabs.add( this.panels ).each( function() {
28874			if ( $.data( this, "ui-tabs-destroy" ) ) {
28875				$( this ).remove();
28876			} else {
28877				$( this ).removeAttr( "role tabIndex " +
28878					"aria-live aria-busy aria-selected aria-labelledby aria-hidden aria-expanded" );
28879			}
28880		} );
28881
28882		this.tabs.each( function() {
28883			var li = $( this ),
28884				prev = li.data( "ui-tabs-aria-controls" );
28885			if ( prev ) {
28886				li
28887					.attr( "aria-controls", prev )
28888					.removeData( "ui-tabs-aria-controls" );
28889			} else {
28890				li.removeAttr( "aria-controls" );
28891			}
28892		} );
28893
28894		this.panels.show();
28895
28896		if ( this.options.heightStyle !== "content" ) {
28897			this.panels.css( "height", "" );
28898		}
28899	},
28900
28901	enable: function( index ) {
28902		var disabled = this.options.disabled;
28903		if ( disabled === false ) {
28904			return;
28905		}
28906
28907		if ( index === undefined ) {
28908			disabled = false;
28909		} else {
28910			index = this._getIndex( index );
28911			if ( Array.isArray( disabled ) ) {
28912				disabled = $.map( disabled, function( num ) {
28913					return num !== index ? num : null;
28914				} );
28915			} else {
28916				disabled = $.map( this.tabs, function( li, num ) {
28917					return num !== index ? num : null;
28918				} );
28919			}
28920		}
28921		this._setOptionDisabled( disabled );
28922	},
28923
28924	disable: function( index ) {
28925		var disabled = this.options.disabled;
28926		if ( disabled === true ) {
28927			return;
28928		}
28929
28930		if ( index === undefined ) {
28931			disabled = true;
28932		} else {
28933			index = this._getIndex( index );
28934			if ( $.inArray( index, disabled ) !== -1 ) {
28935				return;
28936			}
28937			if ( Array.isArray( disabled ) ) {
28938				disabled = $.merge( [ index ], disabled ).sort();
28939			} else {
28940				disabled = [ index ];
28941			}
28942		}
28943		this._setOptionDisabled( disabled );
28944	},
28945
28946	load: function( index, event ) {
28947		index = this._getIndex( index );
28948		var that = this,
28949			tab = this.tabs.eq( index ),
28950			anchor = tab.find( ".ui-tabs-anchor" ),
28951			panel = this._getPanelForTab( tab ),
28952			eventData = {
28953				tab: tab,
28954				panel: panel
28955			},
28956			complete = function( jqXHR, status ) {
28957				if ( status === "abort" ) {
28958					that.panels.stop( false, true );
28959				}
28960
28961				that._removeClass( tab, "ui-tabs-loading" );
28962				panel.removeAttr( "aria-busy" );
28963
28964				if ( jqXHR === that.xhr ) {
28965					delete that.xhr;
28966				}
28967			};
28968
28969		// Not remote
28970		if ( this._isLocal( anchor[ 0 ] ) ) {
28971			return;
28972		}
28973
28974		this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );
28975
28976		if ( this.xhr.statusText !== "canceled" ) {
28977			this._addClass( tab, "ui-tabs-loading" );
28978			panel.attr( "aria-busy", "true" );
28979
28980			this.xhr
28981				.done( function( response, status, jqXHR ) {
28982					panel.html( response );
28983					that._trigger( "load", event, eventData );
28984
28985					complete( jqXHR, status );
28986				} )
28987				.fail( function( jqXHR, status ) {
28988					complete( jqXHR, status );
28989				} );
28990		}
28991	},
28992
28993	_ajaxSettings: function( anchor, event, eventData ) {
28994		var that = this;
28995		return {
28996			url: anchor.attr( "href" ),
28997			beforeSend: function( jqXHR, settings ) {
28998				return that._trigger( "beforeLoad", event,
28999					$.extend( { jqXHR: jqXHR, ajaxSettings: settings }, eventData ) );
29000			}
29001		};
29002	},
29003
29004	_getPanelForTab: function( tab ) {
29005		var id = $( tab ).attr( "aria-controls" );
29006		return this.element.find( "#" + CSS.escape( id ) );
29007	}
29008} );
29009
29010// DEPRECATED
29011// TODO: Switch return back to widget declaration at top of file when this is removed
29012if ( $.uiBackCompat === true ) {
29013
29014	// Backcompat for ui-tab class (now ui-tabs-tab)
29015	$.widget( "ui.tabs", $.ui.tabs, {
29016		_processTabs: function() {
29017			this._superApply( arguments );
29018			this._addClass( this.tabs, "ui-tab" );
29019		}
29020	} );
29021}
29022
29023var widgetsTabs = $.ui.tabs;
29024
29025
29026/*!
29027 * jQuery UI Tooltip 1.14.1
29028 * https://jqueryui.com
29029 *
29030 * Copyright OpenJS Foundation and other contributors
29031 * Released under the MIT license.
29032 * https://jquery.org/license
29033 */
29034
29035//>>label: Tooltip
29036//>>group: Widgets
29037//>>description: Shows additional information for any element on hover or focus.
29038//>>docs: https://api.jqueryui.com/tooltip/
29039//>>demos: https://jqueryui.com/tooltip/
29040//>>css.structure: ../../themes/base/core.css
29041//>>css.structure: ../../themes/base/tooltip.css
29042//>>css.theme: ../../themes/base/theme.css
29043
29044
29045$.widget( "ui.tooltip", {
29046	version: "1.14.1",
29047	options: {
29048		classes: {
29049			"ui-tooltip": "ui-corner-all ui-widget-shadow"
29050		},
29051		content: function() {
29052			var title = $( this ).attr( "title" );
29053
29054			// Escape title, since we're going from an attribute to raw HTML
29055			return $( "<a>" ).text( title ).html();
29056		},
29057		hide: true,
29058
29059		// Disabled elements have inconsistent behavior across browsers (#8661)
29060		items: "[title]:not([disabled])",
29061		position: {
29062			my: "left top+15",
29063			at: "left bottom",
29064			collision: "flipfit flip"
29065		},
29066		show: true,
29067		track: false,
29068
29069		// Callbacks
29070		close: null,
29071		open: null
29072	},
29073
29074	_addDescribedBy: function( elem, id ) {
29075		var describedby = ( elem.attr( "aria-describedby" ) || "" ).split( /\s+/ );
29076		describedby.push( id );
29077		elem
29078			.data( "ui-tooltip-id", id )
29079			.attr( "aria-describedby", String.prototype.trim.call( describedby.join( " " ) ) );
29080	},
29081
29082	_removeDescribedBy: function( elem ) {
29083		var id = elem.data( "ui-tooltip-id" ),
29084			describedby = ( elem.attr( "aria-describedby" ) || "" ).split( /\s+/ ),
29085			index = $.inArray( id, describedby );
29086
29087		if ( index !== -1 ) {
29088			describedby.splice( index, 1 );
29089		}
29090
29091		elem.removeData( "ui-tooltip-id" );
29092		describedby = String.prototype.trim.call( describedby.join( " " ) );
29093		if ( describedby ) {
29094			elem.attr( "aria-describedby", describedby );
29095		} else {
29096			elem.removeAttr( "aria-describedby" );
29097		}
29098	},
29099
29100	_create: function() {
29101		this._on( {
29102			mouseover: "open",
29103			focusin: "open"
29104		} );
29105
29106		// IDs of generated tooltips, needed for destroy
29107		this.tooltips = {};
29108
29109		// IDs of parent tooltips where we removed the title attribute
29110		this.parents = {};
29111
29112		// Append the aria-live region so tooltips announce correctly
29113		this.liveRegion = $( "<div>" )
29114			.attr( {
29115				role: "log",
29116				"aria-live": "assertive",
29117				"aria-relevant": "additions"
29118			} )
29119			.appendTo( this.document[ 0 ].body );
29120		this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" );
29121
29122		this.disabledTitles = $( [] );
29123	},
29124
29125	_setOption: function( key, value ) {
29126		var that = this;
29127
29128		this._super( key, value );
29129
29130		if ( key === "content" ) {
29131			$.each( this.tooltips, function( id, tooltipData ) {
29132				that._updateContent( tooltipData.element );
29133			} );
29134		}
29135	},
29136
29137	_setOptionDisabled: function( value ) {
29138		this[ value ? "_disable" : "_enable" ]();
29139	},
29140
29141	_disable: function() {
29142		var that = this;
29143
29144		// Close open tooltips
29145		$.each( this.tooltips, function( id, tooltipData ) {
29146			var event = $.Event( "blur" );
29147			event.target = event.currentTarget = tooltipData.element[ 0 ];
29148			that.close( event, true );
29149		} );
29150
29151		// Remove title attributes to prevent native tooltips
29152		this.disabledTitles = this.disabledTitles.add(
29153			this.element.find( this.options.items ).addBack()
29154				.filter( function() {
29155					var element = $( this );
29156					if ( element.is( "[title]" ) ) {
29157						return element
29158							.data( "ui-tooltip-title", element.attr( "title" ) )
29159							.removeAttr( "title" );
29160					}
29161				} )
29162		);
29163	},
29164
29165	_enable: function() {
29166
29167		// restore title attributes
29168		this.disabledTitles.each( function() {
29169			var element = $( this );
29170			if ( element.data( "ui-tooltip-title" ) ) {
29171				element.attr( "title", element.data( "ui-tooltip-title" ) );
29172			}
29173		} );
29174		this.disabledTitles = $( [] );
29175	},
29176
29177	open: function( event ) {
29178		var that = this,
29179			target = $( event ? event.target : this.element )
29180
29181				// we need closest here due to mouseover bubbling,
29182				// but always pointing at the same event target
29183				.closest( this.options.items );
29184
29185		// No element to show a tooltip for or the tooltip is already open
29186		if ( !target.length || target.data( "ui-tooltip-id" ) ) {
29187			return;
29188		}
29189
29190		if ( target.attr( "title" ) ) {
29191			target.data( "ui-tooltip-title", target.attr( "title" ) );
29192		}
29193
29194		target.data( "ui-tooltip-open", true );
29195
29196		// Kill parent tooltips, custom or native, for hover
29197		if ( event && event.type === "mouseover" ) {
29198			target.parents().each( function() {
29199				var parent = $( this ),
29200					blurEvent;
29201				if ( parent.data( "ui-tooltip-open" ) ) {
29202					blurEvent = $.Event( "blur" );
29203					blurEvent.target = blurEvent.currentTarget = this;
29204					that.close( blurEvent, true );
29205				}
29206				if ( parent.attr( "title" ) ) {
29207					parent.uniqueId();
29208					that.parents[ this.id ] = {
29209						element: this,
29210						title: parent.attr( "title" )
29211					};
29212					parent.attr( "title", "" );
29213				}
29214			} );
29215		}
29216
29217		this._registerCloseHandlers( event, target );
29218		this._updateContent( target, event );
29219	},
29220
29221	_updateContent: function( target, event ) {
29222		var content,
29223			contentOption = this.options.content,
29224			that = this,
29225			eventType = event ? event.type : null;
29226
29227		if ( typeof contentOption === "string" || contentOption.nodeType ||
29228				contentOption.jquery ) {
29229			return this._open( event, target, contentOption );
29230		}
29231
29232		content = contentOption.call( target[ 0 ], function( response ) {
29233
29234			// Ignore async response if tooltip was closed already
29235			if ( !target.data( "ui-tooltip-open" ) ) {
29236				return;
29237			}
29238
29239			// JQuery creates a special event for focusin when it doesn't
29240			// exist natively. To improve performance, the native event
29241			// object is reused and the type is changed. Therefore, we can't
29242			// rely on the type being correct after the event finished
29243			// bubbling, so we set it back to the previous value. (#8740)
29244			if ( event ) {
29245				event.type = eventType;
29246			}
29247			that._open( event, target, response );
29248		} );
29249		if ( content ) {
29250			this._open( event, target, content );
29251		}
29252	},
29253
29254	_open: function( event, target, content ) {
29255		var tooltipData, tooltip, delayedShow, a11yContent,
29256			positionOption = $.extend( {}, this.options.position );
29257
29258		if ( !content ) {
29259			return;
29260		}
29261
29262		// Content can be updated multiple times. If the tooltip already
29263		// exists, then just update the content and bail.
29264		tooltipData = this._find( target );
29265		if ( tooltipData ) {
29266			tooltipData.tooltip.find( ".ui-tooltip-content" ).html( content );
29267			return;
29268		}
29269
29270		// If we have a title, clear it to prevent the native tooltip
29271		// we have to check first to avoid defining a title if none exists
29272		// (we don't want to cause an element to start matching [title])
29273		//
29274		// We use removeAttr only for key events, to allow IE to export the correct
29275		// accessible attributes. For mouse events, set to empty string to avoid
29276		// native tooltip showing up (happens only when removing inside mouseover).
29277		if ( target.is( "[title]" ) ) {
29278			if ( event && event.type === "mouseover" ) {
29279				target.attr( "title", "" );
29280			} else {
29281				target.removeAttr( "title" );
29282			}
29283		}
29284
29285		tooltipData = this._tooltip( target );
29286		tooltip = tooltipData.tooltip;
29287		this._addDescribedBy( target, tooltip.attr( "id" ) );
29288		tooltip.find( ".ui-tooltip-content" ).html( content );
29289
29290		// Support: Voiceover on OS X, JAWS on IE <= 9
29291		// JAWS announces deletions even when aria-relevant="additions"
29292		// Voiceover will sometimes re-read the entire log region's contents from the beginning
29293		this.liveRegion.children().hide();
29294		a11yContent = $( "<div>" ).html( tooltip.find( ".ui-tooltip-content" ).html() );
29295		a11yContent.removeAttr( "name" ).find( "[name]" ).removeAttr( "name" );
29296		a11yContent.removeAttr( "id" ).find( "[id]" ).removeAttr( "id" );
29297		a11yContent.appendTo( this.liveRegion );
29298
29299		function position( event ) {
29300			positionOption.of = event;
29301			if ( tooltip.is( ":hidden" ) ) {
29302				return;
29303			}
29304			tooltip.position( positionOption );
29305		}
29306		if ( this.options.track && event && /^mouse/.test( event.type ) ) {
29307			this._on( this.document, {
29308				mousemove: position
29309			} );
29310
29311			// trigger once to override element-relative positioning
29312			position( event );
29313		} else {
29314			tooltip.position( $.extend( {
29315				of: target
29316			}, this.options.position ) );
29317		}
29318
29319		tooltip.hide();
29320
29321		this._show( tooltip, this.options.show );
29322
29323		// Handle tracking tooltips that are shown with a delay (#8644). As soon
29324		// as the tooltip is visible, position the tooltip using the most recent
29325		// event.
29326		// Adds the check to add the timers only when both delay and track options are set (#14682)
29327		if ( this.options.track && this.options.show && this.options.show.delay ) {
29328			delayedShow = this.delayedShow = setInterval( function() {
29329				if ( tooltip.is( ":visible" ) ) {
29330					position( positionOption.of );
29331					clearInterval( delayedShow );
29332				}
29333			}, 13 );
29334		}
29335
29336		this._trigger( "open", event, { tooltip: tooltip } );
29337	},
29338
29339	_registerCloseHandlers: function( event, target ) {
29340		var events = {
29341			keyup: function( event ) {
29342				if ( event.keyCode === $.ui.keyCode.ESCAPE ) {
29343					var fakeEvent = $.Event( event );
29344					fakeEvent.currentTarget = target[ 0 ];
29345					this.close( fakeEvent, true );
29346				}
29347			}
29348		};
29349
29350		// Only bind remove handler for delegated targets. Non-delegated
29351		// tooltips will handle this in destroy.
29352		if ( target[ 0 ] !== this.element[ 0 ] ) {
29353			events.remove = function() {
29354				var targetElement = this._find( target );
29355				if ( targetElement ) {
29356					this._removeTooltip( targetElement.tooltip );
29357				}
29358			};
29359		}
29360
29361		if ( !event || event.type === "mouseover" ) {
29362			events.mouseleave = "close";
29363		}
29364		if ( !event || event.type === "focusin" ) {
29365			events.focusout = "close";
29366		}
29367		this._on( true, target, events );
29368	},
29369
29370	close: function( event ) {
29371		var tooltip,
29372			that = this,
29373			target = $( event ? event.currentTarget : this.element ),
29374			tooltipData = this._find( target );
29375
29376		// The tooltip may already be closed
29377		if ( !tooltipData ) {
29378
29379			// We set ui-tooltip-open immediately upon open (in open()), but only set the
29380			// additional data once there's actually content to show (in _open()). So even if the
29381			// tooltip doesn't have full data, we always remove ui-tooltip-open in case we're in
29382			// the period between open() and _open().
29383			target.removeData( "ui-tooltip-open" );
29384			return;
29385		}
29386
29387		tooltip = tooltipData.tooltip;
29388
29389		// Disabling closes the tooltip, so we need to track when we're closing
29390		// to avoid an infinite loop in case the tooltip becomes disabled on close
29391		if ( tooltipData.closing ) {
29392			return;
29393		}
29394
29395		// Clear the interval for delayed tracking tooltips
29396		clearInterval( this.delayedShow );
29397
29398		// Only set title if we had one before (see comment in _open())
29399		// If the title attribute has changed since open(), don't restore
29400		if ( target.data( "ui-tooltip-title" ) && !target.attr( "title" ) ) {
29401			target.attr( "title", target.data( "ui-tooltip-title" ) );
29402		}
29403
29404		this._removeDescribedBy( target );
29405
29406		tooltipData.hiding = true;
29407		tooltip.stop( true );
29408		this._hide( tooltip, this.options.hide, function() {
29409			that._removeTooltip( $( this ) );
29410		} );
29411
29412		target.removeData( "ui-tooltip-open" );
29413		this._off( target, "mouseleave focusout keyup" );
29414
29415		// Remove 'remove' binding only on delegated targets
29416		if ( target[ 0 ] !== this.element[ 0 ] ) {
29417			this._off( target, "remove" );
29418		}
29419		this._off( this.document, "mousemove" );
29420
29421		if ( event && event.type === "mouseleave" ) {
29422			$.each( this.parents, function( id, parent ) {
29423				$( parent.element ).attr( "title", parent.title );
29424				delete that.parents[ id ];
29425			} );
29426		}
29427
29428		tooltipData.closing = true;
29429		this._trigger( "close", event, { tooltip: tooltip } );
29430		if ( !tooltipData.hiding ) {
29431			tooltipData.closing = false;
29432		}
29433	},
29434
29435	_tooltip: function( element ) {
29436		var tooltip = $( "<div>" ).attr( "role", "tooltip" ),
29437			content = $( "<div>" ).appendTo( tooltip ),
29438			id = tooltip.uniqueId().attr( "id" );
29439
29440		this._addClass( content, "ui-tooltip-content" );
29441		this._addClass( tooltip, "ui-tooltip", "ui-widget ui-widget-content" );
29442
29443		tooltip.appendTo( this._appendTo( element ) );
29444
29445		return this.tooltips[ id ] = {
29446			element: element,
29447			tooltip: tooltip
29448		};
29449	},
29450
29451	_find: function( target ) {
29452		var id = target.data( "ui-tooltip-id" );
29453		return id ? this.tooltips[ id ] : null;
29454	},
29455
29456	_removeTooltip: function( tooltip ) {
29457
29458		// Clear the interval for delayed tracking tooltips
29459		clearInterval( this.delayedShow );
29460
29461		tooltip.remove();
29462		delete this.tooltips[ tooltip.attr( "id" ) ];
29463	},
29464
29465	_appendTo: function( target ) {
29466		var element = target.closest( ".ui-front, dialog" );
29467
29468		if ( !element.length ) {
29469			element = this.document[ 0 ].body;
29470		}
29471
29472		return element;
29473	},
29474
29475	_destroy: function() {
29476		var that = this;
29477
29478		// Close open tooltips
29479		$.each( this.tooltips, function( id, tooltipData ) {
29480
29481			// Delegate to close method to handle common cleanup
29482			var event = $.Event( "blur" ),
29483				element = tooltipData.element;
29484			event.target = event.currentTarget = element[ 0 ];
29485			that.close( event, true );
29486
29487			// Remove immediately; destroying an open tooltip doesn't use the
29488			// hide animation
29489			$( "#" + id ).remove();
29490
29491			// Restore the title
29492			if ( element.data( "ui-tooltip-title" ) ) {
29493
29494				// If the title attribute has changed since open(), don't restore
29495				if ( !element.attr( "title" ) ) {
29496					element.attr( "title", element.data( "ui-tooltip-title" ) );
29497				}
29498				element.removeData( "ui-tooltip-title" );
29499			}
29500		} );
29501		this.liveRegion.remove();
29502	}
29503} );
29504
29505// DEPRECATED
29506// TODO: Switch return back to widget declaration at top of file when this is removed
29507if ( $.uiBackCompat === true ) {
29508
29509	// Backcompat for tooltipClass option
29510	$.widget( "ui.tooltip", $.ui.tooltip, {
29511		options: {
29512			tooltipClass: null
29513		},
29514		_tooltip: function() {
29515			var tooltipData = this._superApply( arguments );
29516			if ( this.options.tooltipClass ) {
29517				tooltipData.tooltip.addClass( this.options.tooltipClass );
29518			}
29519			return tooltipData;
29520		}
29521	} );
29522}
29523
29524var widgetsTooltip = $.ui.tooltip;
29525
29526
29527
29528
29529} );;
29530/*!
29531 * jQuery Migrate - v3.0.1 - 2017-09-26
29532 * Copyright jQuery Foundation and other contributors
29533 */
29534;( function( factory ) {
29535	if ( typeof define === "function" && define.amd ) {
29536
29537		// AMD. Register as an anonymous module.
29538		define( [ "jquery" ], window, factory );
29539	} else if ( typeof module === "object" && module.exports ) {
29540
29541		// Node/CommonJS
29542		// eslint-disable-next-line no-undef
29543		module.exports = factory( require( "jquery" ), window );
29544	} else {
29545
29546		// Browser globals
29547		factory( jQuery, window );
29548	}
29549} )( function( jQuery, window ) {
29550"use strict";
29551
29552
29553jQuery.migrateVersion = "3.0.1";
29554
29555/* exported migrateWarn, migrateWarnFunc, migrateWarnProp */
29556
29557( function() {
29558
29559	var rbadVersions = /^[12]\./;
29560
29561	// Support: IE9 only
29562	// IE9 only creates console object when dev tools are first opened
29563	// IE9 console is a host object, callable but doesn't have .apply()
29564	if ( !window.console || !window.console.log ) {
29565		return;
29566	}
29567
29568	// Need jQuery 3.0.0+ and no older Migrate loaded
29569	if ( !jQuery || rbadVersions.test( jQuery.fn.jquery ) ) {
29570		window.console.log( "JQMIGRATE: jQuery 3.0.0+ REQUIRED" );
29571	}
29572	if ( jQuery.migrateWarnings ) {
29573		window.console.log( "JQMIGRATE: Migrate plugin loaded multiple times" );
29574	}
29575
29576	// Show a message on the console so devs know we're active
29577	window.console.log( "JQMIGRATE: Migrate is installed" +
29578		( jQuery.migrateMute ? "" : " with logging active" ) +
29579		", version " + jQuery.migrateVersion );
29580
29581} )();
29582
29583var warnedAbout = {};
29584
29585// List of warnings already given; public read only
29586jQuery.migrateWarnings = [];
29587
29588// Set to false to disable traces that appear with warnings
29589if ( jQuery.migrateTrace === undefined ) {
29590	jQuery.migrateTrace = true;
29591}
29592
29593// Forget any warnings we've already given; public
29594jQuery.migrateReset = function() {
29595	warnedAbout = {};
29596	jQuery.migrateWarnings.length = 0;
29597};
29598
29599function migrateWarn( msg ) {
29600	var console = window.console;
29601	if ( !warnedAbout[ msg ] ) {
29602		warnedAbout[ msg ] = true;
29603		jQuery.migrateWarnings.push( msg );
29604		if ( console && console.warn && !jQuery.migrateMute ) {
29605			console.warn( "JQMIGRATE: " + msg );
29606			if ( jQuery.migrateTrace && console.trace ) {
29607				console.trace();
29608			}
29609		}
29610	}
29611}
29612
29613function migrateWarnProp( obj, prop, value, msg ) {
29614	Object.defineProperty( obj, prop, {
29615		configurable: true,
29616		enumerable: true,
29617		get: function() {
29618			migrateWarn( msg );
29619			return value;
29620		},
29621		set: function( newValue ) {
29622			migrateWarn( msg );
29623			value = newValue;
29624		}
29625	} );
29626}
29627
29628function migrateWarnFunc( obj, prop, newFunc, msg ) {
29629	obj[ prop ] = function() {
29630		migrateWarn( msg );
29631		return newFunc.apply( this, arguments );
29632	};
29633}
29634
29635if ( window.document.compatMode === "BackCompat" ) {
29636
29637	// JQuery has never supported or tested Quirks Mode
29638	migrateWarn( "jQuery is not compatible with Quirks Mode" );
29639}
29640
29641
29642var oldInit = jQuery.fn.init,
29643	oldIsNumeric = jQuery.isNumeric,
29644	oldFind = jQuery.find,
29645	rattrHashTest = /\[(\s*[-\w]+\s*)([~|^$*]?=)\s*([-\w#]*?#[-\w#]*)\s*\]/,
29646	rattrHashGlob = /\[(\s*[-\w]+\s*)([~|^$*]?=)\s*([-\w#]*?#[-\w#]*)\s*\]/g;
29647
29648jQuery.fn.init = function( arg1 ) {
29649	var args = Array.prototype.slice.call( arguments );
29650
29651	if ( typeof arg1 === "string" && arg1 === "#" ) {
29652
29653		// JQuery( "#" ) is a bogus ID selector, but it returned an empty set before jQuery 3.0
29654		migrateWarn( "jQuery( '#' ) is not a valid selector" );
29655		args[ 0 ] = [];
29656	}
29657
29658	return oldInit.apply( this, args );
29659};
29660jQuery.fn.init.prototype = jQuery.fn;
29661
29662jQuery.find = function( selector ) {
29663	var args = Array.prototype.slice.call( arguments );
29664
29665	// Support: PhantomJS 1.x
29666	// String#match fails to match when used with a //g RegExp, only on some strings
29667	if ( typeof selector === "string" && rattrHashTest.test( selector ) ) {
29668
29669		// The nonstandard and undocumented unquoted-hash was removed in jQuery 1.12.0
29670		// First see if qS thinks it's a valid selector, if so avoid a false positive
29671		try {
29672			window.document.querySelector( selector );
29673		} catch ( err1 ) {
29674
29675			// Didn't *look* valid to qSA, warn and try quoting what we think is the value
29676			selector = selector.replace( rattrHashGlob, function( _, attr, op, value ) {
29677				return "[" + attr + op + "\"" + value + "\"]";
29678			} );
29679
29680			// If the regexp *may* have created an invalid selector, don't update it
29681			// Note that there may be false alarms if selector uses jQuery extensions
29682			try {
29683				window.document.querySelector( selector );
29684				migrateWarn( "Attribute selector with '#' must be quoted: " + args[ 0 ] );
29685				args[ 0 ] = selector;
29686			} catch ( err2 ) {
29687				migrateWarn( "Attribute selector with '#' was not fixed: " + args[ 0 ] );
29688			}
29689		}
29690	}
29691
29692	return oldFind.apply( this, args );
29693};
29694
29695// Copy properties attached to original jQuery.find method (e.g. .attr, .isXML)
29696var findProp;
29697for ( findProp in oldFind ) {
29698	if ( Object.prototype.hasOwnProperty.call( oldFind, findProp ) ) {
29699		jQuery.find[ findProp ] = oldFind[ findProp ];
29700	}
29701}
29702
29703// The number of elements contained in the matched element set
29704jQuery.fn.size = function() {
29705	migrateWarn( "jQuery.fn.size() is deprecated and removed; use the .length property" );
29706	return this.length;
29707};
29708
29709jQuery.parseJSON = function() {
29710	migrateWarn( "jQuery.parseJSON is deprecated; use JSON.parse" );
29711	return JSON.parse.apply( null, arguments );
29712};
29713
29714jQuery.isNumeric = function( val ) {
29715
29716	// The jQuery 2.2.3 implementation of isNumeric
29717	function isNumeric2( obj ) {
29718		var realStringObj = obj && obj.toString();
29719		return !jQuery.isArray( obj ) && ( realStringObj - parseFloat( realStringObj ) + 1 ) >= 0;
29720	}
29721
29722	var newValue = oldIsNumeric( val ),
29723		oldValue = isNumeric2( val );
29724
29725	if ( newValue !== oldValue ) {
29726		migrateWarn( "jQuery.isNumeric() should not be called on constructed objects" );
29727	}
29728
29729	return oldValue;
29730};
29731
29732migrateWarnFunc( jQuery, "holdReady", jQuery.holdReady,
29733	"jQuery.holdReady is deprecated" );
29734
29735migrateWarnFunc( jQuery, "unique", jQuery.uniqueSort,
29736	"jQuery.unique is deprecated; use jQuery.uniqueSort" );
29737
29738// Now jQuery.expr.pseudos is the standard incantation
29739migrateWarnProp( jQuery.expr, "filters", jQuery.expr.pseudos,
29740	"jQuery.expr.filters is deprecated; use jQuery.expr.pseudos" );
29741migrateWarnProp( jQuery.expr, ":", jQuery.expr.pseudos,
29742	"jQuery.expr[':'] is deprecated; use jQuery.expr.pseudos" );
29743
29744
29745var oldAjax = jQuery.ajax;
29746
29747jQuery.ajax = function( ) {
29748	var jQXHR = oldAjax.apply( this, arguments );
29749
29750	// Be sure we got a jQXHR (e.g., not sync)
29751	if ( jQXHR.promise ) {
29752		migrateWarnFunc( jQXHR, "success", jQXHR.done,
29753			"jQXHR.success is deprecated and removed" );
29754		migrateWarnFunc( jQXHR, "error", jQXHR.fail,
29755			"jQXHR.error is deprecated and removed" );
29756		migrateWarnFunc( jQXHR, "complete", jQXHR.always,
29757			"jQXHR.complete is deprecated and removed" );
29758	}
29759
29760	return jQXHR;
29761};
29762
29763
29764var oldRemoveAttr = jQuery.fn.removeAttr,
29765	oldToggleClass = jQuery.fn.toggleClass,
29766	rmatchNonSpace = /\S+/g;
29767
29768jQuery.fn.removeAttr = function( name ) {
29769	var self = this;
29770
29771	jQuery.each( name.match( rmatchNonSpace ), function( i, attr ) {
29772		if ( jQuery.expr.match.bool.test( attr ) ) {
29773			migrateWarn( "jQuery.fn.removeAttr no longer sets boolean properties: " + attr );
29774			self.prop( attr, false );
29775		}
29776	} );
29777
29778	return oldRemoveAttr.apply( this, arguments );
29779};
29780
29781jQuery.fn.toggleClass = function( state ) {
29782
29783	// Only deprecating no-args or single boolean arg
29784	if ( state !== undefined && typeof state !== "boolean" ) {
29785		return oldToggleClass.apply( this, arguments );
29786	}
29787
29788	migrateWarn( "jQuery.fn.toggleClass( boolean ) is deprecated" );
29789
29790	// Toggle entire class name of each element
29791	return this.each( function() {
29792		var className = this.getAttribute && this.getAttribute( "class" ) || "";
29793
29794		if ( className ) {
29795			jQuery.data( this, "__className__", className );
29796		}
29797
29798		// If the element has a class name or if we're passed `false`,
29799		// then remove the whole classname (if there was one, the above saved it).
29800		// Otherwise bring back whatever was previously saved (if anything),
29801		// falling back to the empty string if nothing was stored.
29802		if ( this.setAttribute ) {
29803			this.setAttribute( "class",
29804				className || state === false ?
29805				"" :
29806				jQuery.data( this, "__className__" ) || ""
29807			);
29808		}
29809	} );
29810};
29811
29812
29813var internalSwapCall = false;
29814
29815// If this version of jQuery has .swap(), don't false-alarm on internal uses
29816if ( jQuery.swap ) {
29817	jQuery.each( [ "height", "width", "reliableMarginRight" ], function( _, name ) {
29818		var oldHook = jQuery.cssHooks[ name ] && jQuery.cssHooks[ name ].get;
29819
29820		if ( oldHook ) {
29821			jQuery.cssHooks[ name ].get = function() {
29822				var ret;
29823
29824				internalSwapCall = true;
29825				ret = oldHook.apply( this, arguments );
29826				internalSwapCall = false;
29827				return ret;
29828			};
29829		}
29830	} );
29831}
29832
29833jQuery.swap = function( elem, options, callback, args ) {
29834	var ret, name,
29835		old = {};
29836
29837	if ( !internalSwapCall ) {
29838		migrateWarn( "jQuery.swap() is undocumented and deprecated" );
29839	}
29840
29841	// Remember the old values, and insert the new ones
29842	for ( name in options ) {
29843		old[ name ] = elem.style[ name ];
29844		elem.style[ name ] = options[ name ];
29845	}
29846
29847	ret = callback.apply( elem, args || [] );
29848
29849	// Revert the old values
29850	for ( name in options ) {
29851		elem.style[ name ] = old[ name ];
29852	}
29853
29854	return ret;
29855};
29856
29857var oldData = jQuery.data;
29858
29859jQuery.data = function( elem, name, value ) {
29860	var curData;
29861
29862	// Name can be an object, and each entry in the object is meant to be set as data
29863	if ( name && typeof name === "object" && arguments.length === 2 ) {
29864		curData = jQuery.hasData( elem ) && oldData.call( this, elem );
29865		var sameKeys = {};
29866		for ( var key in name ) {
29867			if ( key !== jQuery.camelCase( key ) ) {
29868				migrateWarn( "jQuery.data() always sets/gets camelCased names: " + key );
29869				curData[ key ] = name[ key ];
29870			} else {
29871				sameKeys[ key ] = name[ key ];
29872			}
29873		}
29874
29875		oldData.call( this, elem, sameKeys );
29876
29877		return name;
29878	}
29879
29880	// If the name is transformed, look for the un-transformed name in the data object
29881	if ( name && typeof name === "string" && name !== jQuery.camelCase( name ) ) {
29882		curData = jQuery.hasData( elem ) && oldData.call( this, elem );
29883		if ( curData && name in curData ) {
29884			migrateWarn( "jQuery.data() always sets/gets camelCased names: " + name );
29885			if ( arguments.length > 2 ) {
29886				curData[ name ] = value;
29887			}
29888			return curData[ name ];
29889		}
29890	}
29891
29892	return oldData.apply( this, arguments );
29893};
29894
29895var oldTweenRun = jQuery.Tween.prototype.run;
29896var linearEasing = function( pct ) {
29897		return pct;
29898	};
29899
29900jQuery.Tween.prototype.run = function( ) {
29901	if ( jQuery.easing[ this.easing ].length > 1 ) {
29902		migrateWarn(
29903			"'jQuery.easing." + this.easing.toString() + "' should use only one argument"
29904		);
29905
29906		jQuery.easing[ this.easing ] = linearEasing;
29907	}
29908
29909	oldTweenRun.apply( this, arguments );
29910};
29911
29912jQuery.fx.interval = jQuery.fx.interval || 13;
29913
29914// Support: IE9, Android <=4.4
29915// Avoid false positives on browsers that lack rAF
29916if ( window.requestAnimationFrame ) {
29917	migrateWarnProp( jQuery.fx, "interval", jQuery.fx.interval,
29918		"jQuery.fx.interval is deprecated" );
29919}
29920
29921var oldLoad = jQuery.fn.load,
29922	oldEventAdd = jQuery.event.add,
29923	originalFix = jQuery.event.fix;
29924
29925jQuery.event.props = [];
29926jQuery.event.fixHooks = {};
29927
29928migrateWarnProp( jQuery.event.props, "concat", jQuery.event.props.concat,
29929	"jQuery.event.props.concat() is deprecated and removed" );
29930
29931jQuery.event.fix = function( originalEvent ) {
29932	var event,
29933		type = originalEvent.type,
29934		fixHook = this.fixHooks[ type ],
29935		props = jQuery.event.props;
29936
29937	if ( props.length ) {
29938		migrateWarn( "jQuery.event.props are deprecated and removed: " + props.join() );
29939		while ( props.length ) {
29940			jQuery.event.addProp( props.pop() );
29941		}
29942	}
29943
29944	if ( fixHook && !fixHook._migrated_ ) {
29945		fixHook._migrated_ = true;
29946		migrateWarn( "jQuery.event.fixHooks are deprecated and removed: " + type );
29947		if ( ( props = fixHook.props ) && props.length ) {
29948			while ( props.length ) {
29949				jQuery.event.addProp( props.pop() );
29950			}
29951		}
29952	}
29953
29954	event = originalFix.call( this, originalEvent );
29955
29956	return fixHook && fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
29957};
29958
29959jQuery.event.add = function( elem, types ) {
29960
29961	// This misses the multiple-types case but that seems awfully rare
29962	if ( elem === window && types === "load" && window.document.readyState === "complete" ) {
29963		migrateWarn( "jQuery(window).on('load'...) called after load event occurred" );
29964	}
29965	return oldEventAdd.apply( this, arguments );
29966};
29967
29968jQuery.each( [ "load", "unload", "error" ], function( _, name ) {
29969
29970	jQuery.fn[ name ] = function() {
29971		var args = Array.prototype.slice.call( arguments, 0 );
29972
29973		// If this is an ajax load() the first arg should be the string URL;
29974		// technically this could also be the "Anything" arg of the event .load()
29975		// which just goes to show why this dumb signature has been deprecated!
29976		// jQuery custom builds that exclude the Ajax module justifiably die here.
29977		if ( name === "load" && typeof args[ 0 ] === "string" ) {
29978			return oldLoad.apply( this, args );
29979		}
29980
29981		migrateWarn( "jQuery.fn." + name + "() is deprecated" );
29982
29983		args.splice( 0, 0, name );
29984		if ( arguments.length ) {
29985			return this.on.apply( this, args );
29986		}
29987
29988		// Use .triggerHandler here because:
29989		// - load and unload events don't need to bubble, only applied to window or image
29990		// - error event should not bubble to window, although it does pre-1.7
29991		// See http://bugs.jquery.com/ticket/11820
29992		this.triggerHandler.apply( this, args );
29993		return this;
29994	};
29995
29996} );
29997
29998jQuery.each( ( "blur focus focusin focusout resize scroll click dblclick " +
29999	"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
30000	"change select submit keydown keypress keyup contextmenu" ).split( " " ),
30001	function( i, name ) {
30002
30003	// Handle event binding
30004	jQuery.fn[ name ] = function( data, fn ) {
30005		migrateWarn( "jQuery.fn." + name + "() event shorthand is deprecated" );
30006		return arguments.length > 0 ?
30007			this.on( name, null, data, fn ) :
30008			this.trigger( name );
30009	};
30010} );
30011
30012// Trigger "ready" event only once, on document ready
30013jQuery( function() {
30014	jQuery( window.document ).triggerHandler( "ready" );
30015} );
30016
30017jQuery.event.special.ready = {
30018	setup: function() {
30019		if ( this === window.document ) {
30020			migrateWarn( "'ready' event is deprecated" );
30021		}
30022	}
30023};
30024
30025jQuery.fn.extend( {
30026
30027	bind: function( types, data, fn ) {
30028		migrateWarn( "jQuery.fn.bind() is deprecated" );
30029		return this.on( types, null, data, fn );
30030	},
30031	unbind: function( types, fn ) {
30032		migrateWarn( "jQuery.fn.unbind() is deprecated" );
30033		return this.off( types, null, fn );
30034	},
30035	delegate: function( selector, types, data, fn ) {
30036		migrateWarn( "jQuery.fn.delegate() is deprecated" );
30037		return this.on( types, selector, data, fn );
30038	},
30039	undelegate: function( selector, types, fn ) {
30040		migrateWarn( "jQuery.fn.undelegate() is deprecated" );
30041		return arguments.length === 1 ?
30042			this.off( selector, "**" ) :
30043			this.off( types, selector || "**", fn );
30044	},
30045	hover: function( fnOver, fnOut ) {
30046		migrateWarn( "jQuery.fn.hover() is deprecated" );
30047		return this.on( "mouseenter", fnOver ).on( "mouseleave", fnOut || fnOver );
30048	}
30049} );
30050
30051
30052var oldOffset = jQuery.fn.offset;
30053
30054jQuery.fn.offset = function() {
30055	var docElem,
30056		elem = this[ 0 ],
30057		origin = { top: 0, left: 0 };
30058
30059	if ( !elem || !elem.nodeType ) {
30060		migrateWarn( "jQuery.fn.offset() requires a valid DOM element" );
30061		return origin;
30062	}
30063
30064	docElem = ( elem.ownerDocument || window.document ).documentElement;
30065	if ( !jQuery.contains( docElem, elem ) ) {
30066		migrateWarn( "jQuery.fn.offset() requires an element connected to a document" );
30067		return origin;
30068	}
30069
30070	return oldOffset.apply( this, arguments );
30071};
30072
30073
30074var oldParam = jQuery.param;
30075
30076jQuery.param = function( data, traditional ) {
30077	var ajaxTraditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
30078
30079	if ( traditional === undefined && ajaxTraditional ) {
30080
30081		migrateWarn( "jQuery.param() no longer uses jQuery.ajaxSettings.traditional" );
30082		traditional = ajaxTraditional;
30083	}
30084
30085	return oldParam.call( this, data, traditional );
30086};
30087
30088var oldSelf = jQuery.fn.andSelf || jQuery.fn.addBack;
30089
30090jQuery.fn.andSelf = function() {
30091	migrateWarn( "jQuery.fn.andSelf() is deprecated and removed, use jQuery.fn.addBack()" );
30092	return oldSelf.apply( this, arguments );
30093};
30094
30095
30096var oldDeferred = jQuery.Deferred,
30097	tuples = [
30098
30099		// Action, add listener, callbacks, .then handlers, final state
30100		[ "resolve", "done", jQuery.Callbacks( "once memory" ),
30101			jQuery.Callbacks( "once memory" ), "resolved" ],
30102		[ "reject", "fail", jQuery.Callbacks( "once memory" ),
30103			jQuery.Callbacks( "once memory" ), "rejected" ],
30104		[ "notify", "progress", jQuery.Callbacks( "memory" ),
30105			jQuery.Callbacks( "memory" ) ]
30106	];
30107
30108jQuery.Deferred = function( func ) {
30109	var deferred = oldDeferred(),
30110		promise = deferred.promise();
30111
30112	deferred.pipe = promise.pipe = function( /* fnDone, fnFail, fnProgress */ ) {
30113		var fns = arguments;
30114
30115		migrateWarn( "deferred.pipe() is deprecated" );
30116
30117		return jQuery.Deferred( function( newDefer ) {
30118			jQuery.each( tuples, function( i, tuple ) {
30119				var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
30120
30121				// Deferred.done(function() { bind to newDefer or newDefer.resolve })
30122				// deferred.fail(function() { bind to newDefer or newDefer.reject })
30123				// deferred.progress(function() { bind to newDefer or newDefer.notify })
30124				deferred[ tuple[ 1 ] ]( function() {
30125					var returned = fn && fn.apply( this, arguments );
30126					if ( returned && jQuery.isFunction( returned.promise ) ) {
30127						returned.promise()
30128							.done( newDefer.resolve )
30129							.fail( newDefer.reject )
30130							.progress( newDefer.notify );
30131					} else {
30132						newDefer[ tuple[ 0 ] + "With" ](
30133							this === promise ? newDefer.promise() : this,
30134							fn ? [ returned ] : arguments
30135						);
30136					}
30137				} );
30138			} );
30139			fns = null;
30140		} ).promise();
30141
30142	};
30143
30144	if ( func ) {
30145		func.call( deferred, deferred );
30146	}
30147
30148	return deferred;
30149};
30150
30151// Preserve handler of uncaught exceptions in promise chains
30152jQuery.Deferred.exceptionHook = oldDeferred.exceptionHook;
30153
30154return jQuery;
30155} );
30156;
30157/*!
30158 * Modernizr v2.8.3
30159 * www.modernizr.com
30160 *
30161 * Copyright (c) Faruk Ates, Paul Irish, Alex Sexton
30162 * Available under the BSD and MIT licenses: www.modernizr.com/license/
30163 */
30164
30165/*
30166 * Modernizr tests which native CSS3 and HTML5 features are available in
30167 * the current UA and makes the results available to you in two ways:
30168 * as properties on a global Modernizr object, and as classes on the
30169 * <html> element. This information allows you to progressively enhance
30170 * your pages with a granular level of control over the experience.
30171 *
30172 * Modernizr has an optional (not included) conditional resource loader
30173 * called Modernizr.load(), based on Yepnope.js (yepnopejs.com).
30174 * To get a build that includes Modernizr.load(), as well as choosing
30175 * which tests to include, go to www.modernizr.com/download/
30176 *
30177 * Authors        Faruk Ates, Paul Irish, Alex Sexton
30178 * Contributors   Ryan Seddon, Ben Alman
30179 */
30180
30181window.Modernizr = (function( window, document, undefined ) {
30182
30183    var version = '2.8.3',
30184
30185    Modernizr = {},
30186
30187    /*>>cssclasses*/
30188    // option for enabling the HTML classes to be added
30189    enableClasses = true,
30190    /*>>cssclasses*/
30191
30192    docElement = document.documentElement,
30193
30194    /**
30195     * Create our "modernizr" element that we do most feature tests on.
30196     */
30197    mod = 'modernizr',
30198    modElem = document.createElement(mod),
30199    mStyle = modElem.style,
30200
30201    /**
30202     * Create the input element for various Web Forms feature tests.
30203     */
30204    inputElem /*>>inputelem*/ = document.createElement('input') /*>>inputelem*/ ,
30205
30206    /*>>smile*/
30207    smile = ':)',
30208    /*>>smile*/
30209
30210    toString = {}.toString,
30211
30212    // TODO :: make the prefixes more granular
30213    /*>>prefixes*/
30214    // List of property values to set for css tests. See ticket #21
30215    prefixes = ' -webkit- -moz- -o- -ms- '.split(' '),
30216    /*>>prefixes*/
30217
30218    /*>>domprefixes*/
30219    // Following spec is to expose vendor-specific style properties as:
30220    //   elem.style.WebkitBorderRadius
30221    // and the following would be incorrect:
30222    //   elem.style.webkitBorderRadius
30223
30224    // Webkit ghosts their properties in lowercase but Opera & Moz do not.
30225    // Microsoft uses a lowercase `ms` instead of the correct `Ms` in IE8+
30226    //   erik.eae.net/archives/2008/03/10/21.48.10/
30227
30228    // More here: github.com/Modernizr/Modernizr/issues/issue/21
30229    omPrefixes = 'Webkit Moz O ms',
30230
30231    cssomPrefixes = omPrefixes.split(' '),
30232
30233    domPrefixes = omPrefixes.toLowerCase().split(' '),
30234    /*>>domprefixes*/
30235
30236    /*>>ns*/
30237    ns = {'svg': 'http://www.w3.org/2000/svg'},
30238    /*>>ns*/
30239
30240    tests = {},
30241    inputs = {},
30242    attrs = {},
30243
30244    classes = [],
30245
30246    slice = classes.slice,
30247
30248    featureName, // used in testing loop
30249
30250
30251    /*>>
vendor: 21,759 bytes, lines 30251-30860
30251teststyles*/
30252    // Inject element with style element and some CSS rules
30253    injectElementWithStyles = function( rule, callback, nodes, testnames ) {
30254
30255      var style, ret, node, docOverflow,
30256          div = document.createElement('div'),
30257          // After page load injecting a fake body doesn't work so check if body exists
30258          body = document.body,
30259          // IE6 and 7 won't return offsetWidth or offsetHeight unless it's in the body element, so we fake it.
30260          fakeBody = body || document.createElement('body');
30261
30262      if ( parseInt(nodes, 10) ) {
30263          // In order not to give false positives we create a node for each test
30264          // This also allows the method to scale for unspecified uses
30265          while ( nodes-- ) {
30266              node = document.createElement('div');
30267              node.id = testnames ? testnames[nodes] : mod + (nodes + 1);
30268              div.appendChild(node);
30269          }
30270      }
30271
30272      // <style> elements in IE6-9 are considered 'NoScope' elements and therefore will be removed
30273      // when injected with innerHTML. To get around this you need to prepend the 'NoScope' element
30274      // with a 'scoped' element, in our case the soft-hyphen entity as it won't mess with our measurements.
30275      // msdn.microsoft.com/en-us/library/ms533897%28VS.85%29.aspx
30276      // Documents served as xml will throw if using &shy; so use xml friendly encoded version. See issue #277
30277      style = ['&#173;','<style id="s', mod, '">', rule, '</style>'].join('');
30278      div.id = mod;
30279      // 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.
30280      // Opera will act all quirky when injecting elements in documentElement when page is served as xml, needs fakebody too. #270
30281      (body ? div : fakeBody).innerHTML += style;
30282      fakeBody.appendChild(div);
30283      if ( !body ) {
30284          //avoid crashing IE8, if background image is used
30285          fakeBody.style.background = '';
30286          //Safari 5.13/5.1.4 OSX stops loading if ::-webkit-scrollbar is used and scrollbars are visible
30287          fakeBody.style.overflow = 'hidden';
30288          docOverflow = docElement.style.overflow;
30289          docElement.style.overflow = 'hidden';
30290          docElement.appendChild(fakeBody);
30291      }
30292
30293      ret = callback(div, rule);
30294      // If this is done after page load we don't want to remove the body so check if body exists
30295      if ( !body ) {
30296          fakeBody.parentNode.removeChild(fakeBody);
30297          docElement.style.overflow = docOverflow;
30298      } else {
30299          div.parentNode.removeChild(div);
30300      }
30301
30302      return !!ret;
30303
30304    },
30305    /*>>teststyles*/
30306
30307    /*>>mq*/
30308    // adapted from matchMedia polyfill
30309    // by Scott Jehl and Paul Irish
30310    // gist.github.com/786768
30311    testMediaQuery = function( mq ) {
30312
30313      var matchMedia = window.matchMedia || window.msMatchMedia;
30314      if ( matchMedia ) {
30315        return matchMedia(mq) && matchMedia(mq).matches || false;
30316      }
30317
30318      var bool;
30319
30320      injectElementWithStyles('@media ' + mq + ' { #' + mod + ' { position: absolute; } }', function( node ) {
30321        bool = (window.getComputedStyle ?
30322                  getComputedStyle(node, null) :
30323                  node.currentStyle)['position'] == 'absolute';
30324      });
30325
30326      return bool;
30327
30328     },
30329     /*>>mq*/
30330
30331
30332    /*>>hasevent*/
30333    //
30334    // isEventSupported determines if a given element supports the given event
30335    // kangax.github.com/iseventsupported/
30336    //
30337    // The following results are known incorrects:
30338    //   Modernizr.hasEvent("webkitTransitionEnd", elem) // false negative
30339    //   Modernizr.hasEvent("textInput") // in Webkit. github.com/Modernizr/Modernizr/issues/333
30340    //   ...
30341    isEventSupported = (function() {
30342
30343      var TAGNAMES = {
30344        'select': 'input', 'change': 'input',
30345        'submit': 'form', 'reset': 'form',
30346        'error': 'img', 'load': 'img', 'abort': 'img'
30347      };
30348
30349      function isEventSupported( eventName, element ) {
30350
30351        element = element || document.createElement(TAGNAMES[eventName] || 'div');
30352        eventName = 'on' + eventName;
30353
30354        // When using `setAttribute`, IE skips "unload", WebKit skips "unload" and "resize", whereas `in` "catches" those
30355        var isSupported = eventName in element;
30356
30357        if ( !isSupported ) {
30358          // If it has no `setAttribute` (i.e. doesn't implement Node interface), try generic element
30359          if ( !element.setAttribute ) {
30360            element = document.createElement('div');
30361          }
30362          if ( element.setAttribute && element.removeAttribute ) {
30363            element.setAttribute(eventName, '');
30364            isSupported = is(element[eventName], 'function');
30365
30366            // If property was created, "remove it" (by setting value to `undefined`)
30367            if ( !is(element[eventName], 'undefined') ) {
30368              element[eventName] = undefined;
30369            }
30370            element.removeAttribute(eventName);
30371          }
30372        }
30373
30374        element = null;
30375        return isSupported;
30376      }
30377      return isEventSupported;
30378    })(),
30379    /*>>hasevent*/
30380
30381    // TODO :: Add flag for hasownprop ? didn't last time
30382
30383    // hasOwnProperty shim by kangax needed for Safari 2.0 support
30384    _hasOwnProperty = ({}).hasOwnProperty, hasOwnProp;
30385
30386    if ( !is(_hasOwnProperty, 'undefined') && !is(_hasOwnProperty.call, 'undefined') ) {
30387      hasOwnProp = function (object, property) {
30388        return _hasOwnProperty.call(object, property);
30389      };
30390    }
30391    else {
30392      hasOwnProp = function (object, property) { /* yes, this can give false positives/negatives, but most of the time we don't care about those */
30393        return ((property in object) && is(object.constructor.prototype[property], 'undefined'));
30394      };
30395    }
30396
30397    // Adapted from ES5-shim https://github.com/kriskowal/es5-shim/blob/master/es5-shim.js
30398    // es5.github.com/#x15.3.4.5
30399
30400    if (!Function.prototype.bind) {
30401      Function.prototype.bind = function bind(that) {
30402
30403        var target = this;
30404
30405        if (typeof target != "function") {
30406            throw new TypeError();
30407        }
30408
30409        var args = slice.call(arguments, 1),
30410            bound = function () {
30411
30412            if (this instanceof bound) {
30413
30414              var F = function(){};
30415              F.prototype = target.prototype;
30416              var self = new F();
30417
30418              var result = target.apply(
30419                  self,
30420                  args.concat(slice.call(arguments))
30421              );
30422              if (Object(result) === result) {
30423                  return result;
30424              }
30425              return self;
30426
30427            } else {
30428
30429              return target.apply(
30430                  that,
30431                  args.concat(slice.call(arguments))
30432              );
30433
30434            }
30435
30436        };
30437
30438        return bound;
30439      };
30440    }
30441
30442    /**
30443     * setCss applies given styles to the Modernizr DOM node.
30444     */
30445    function setCss( str ) {
30446        mStyle.cssText = str;
30447    }
30448
30449    /**
30450     * setCssAll extrapolates all vendor-specific css strings.
30451     */
30452    function setCssAll( str1, str2 ) {
30453        return setCss(prefixes.join(str1 + ';') + ( str2 || '' ));
30454    }
30455
30456    /**
30457     * is returns a boolean for if typeof obj is exactly type.
30458     */
30459    function is( obj, type ) {
30460        return typeof obj === type;
30461    }
30462
30463    /**
30464     * contains returns a boolean for if substr is found within str.
30465     */
30466    function contains( str, substr ) {
30467        return !!~('' + str).indexOf(substr);
30468    }
30469
30470    /*>>testprop*/
30471
30472    // testProps is a generic CSS / DOM property test.
30473
30474    // In testing support for a given CSS property, it's legit to test:
30475    //    `elem.style[styleName] !== undefined`
30476    // If the property is supported it will return an empty string,
30477    // if unsupported it will return undefined.
30478
30479    // We'll take advantage of this quick test and skip setting a style
30480    // on our modernizr element, but instead just testing undefined vs
30481    // empty string.
30482
30483    // Because the testing of the CSS property names (with "-", as
30484    // opposed to the camelCase DOM properties) is non-portable and
30485    // non-standard but works in WebKit and IE (but not Gecko or Opera),
30486    // we explicitly reject properties with dashes so that authors
30487    // developing in WebKit or IE first don't end up with
30488    // browser-specific content by accident.
30489
30490    function testProps( props, prefixed ) {
30491        for ( var i in props ) {
30492            var prop = props[i];
30493            if ( !contains(prop, "-") && mStyle[prop] !== undefined ) {
30494                return prefixed == 'pfx' ? prop : true;
30495            }
30496        }
30497        return false;
30498    }
30499    /*>>testprop*/
30500
30501    // TODO :: add testDOMProps
30502    /**
30503     * testDOMProps is a generic DOM property test; if a browser supports
30504     *   a certain property, it won't return undefined for it.
30505     */
30506    function testDOMProps( props, obj, elem ) {
30507        for ( var i in props ) {
30508            var item = obj[props[i]];
30509            if ( item !== undefined) {
30510
30511                // return the property name as a string
30512                if (elem === false) return props[i];
30513
30514                // let's bind a function
30515                if (is(item, 'function')){
30516                  // default to autobind unless override
30517                  return item.bind(elem || obj);
30518                }
30519
30520                // return the unbound function or obj or value
30521                return item;
30522            }
30523        }
30524        return false;
30525    }
30526
30527    /*>>testallprops*/
30528    /**
30529     * testPropsAll tests a list of DOM properties we want to check against.
30530     *   We specify literally ALL possible (known and/or likely) properties on
30531     *   the element including the non-vendor prefixed one, for forward-
30532     *   compatibility.
30533     */
30534    function testPropsAll( prop, prefixed, elem ) {
30535
30536        var ucProp  = prop.charAt(0).toUpperCase() + prop.slice(1),
30537            props   = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' ');
30538
30539        // did they call .prefixed('boxSizing') or are we just testing a prop?
30540        if(is(prefixed, "string") || is(prefixed, "undefined")) {
30541          return testProps(props, prefixed);
30542
30543        // otherwise, they called .prefixed('requestAnimationFrame', window[, elem])
30544        } else {
30545          props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' ');
30546          return testDOMProps(props, prefixed, elem);
30547        }
30548    }
30549    /*>>testallprops*/
30550
30551
30552    /**
30553     * Tests
30554     * -----
30555     */
30556
30557    // The *new* flexbox
30558    // dev.w3.org/csswg/css3-flexbox
30559
30560    tests['flexbox'] = function() {
30561      return testPropsAll('flexWrap');
30562    };
30563
30564    // The *old* flexbox
30565    // www.w3.org/TR/2009/WD-css3-flexbox-20090723/
30566
30567    tests['flexboxlegacy'] = function() {
30568        return testPropsAll('boxDirection');
30569    };
30570
30571    // On the S60 and BB Storm, getContext exists, but always returns undefined
30572    // so we actually have to call getContext() to verify
30573    // github.com/Modernizr/Modernizr/issues/issue/97/
30574
30575    tests['canvas'] = function() {
30576        var elem = document.createElement('canvas');
30577        return !!(elem.getContext && elem.getContext('2d'));
30578    };
30579
30580    tests['canvastext'] = function() {
30581        return !!(Modernizr['canvas'] && is(document.createElement('canvas').getContext('2d').fillText, 'function'));
30582    };
30583
30584    // webk.it/70117 is tracking a legit WebGL feature detect proposal
30585
30586    // We do a soft detect which may false positive in order to avoid
30587    // an expensive context creation: bugzil.la/732441
30588
30589    tests['webgl'] = function() {
30590        return !!window.WebGLRenderingContext;
30591    };
30592
30593    /*
30594     * The Modernizr.touch test only indicates if the browser supports
30595     *    touch events, which does not necessarily reflect a touchscreen
30596     *    device, as evidenced by tablets running Windows 7 or, alas,
30597     *    the Palm Pre / WebOS (touch) phones.
30598     *
30599     * Additionally, Chrome (desktop) used to lie about its support on this,
30600     *    but that has since been rectified: crbug.com/36415
30601     *
30602     * We also test for Firefox 4 Multitouch Support.
30603     *
30604     * For more info, see: modernizr.github.com/Modernizr/touch.html
30605     */
30606
30607    tests['touch'] = function() {
30608        var bool;
30609
30610        if(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) {
30611          bool = true;
30612        } else {
30613          injectElementWithStyles(['@media (',prefixes.join('touch-enabled),('),mod,')','{#modernizr{top:9px;position:absolute}}'].join(''), function( node ) {
30614            bool = node.offsetTop === 9;
30615          });
30616        }
30617
30618        return bool;
30619    };
30620
30621
30622    // geolocation is often considered a trivial feature detect...
30623    // Turns out, it's quite tricky to get right:
30624    //
30625    // Using !!navigator.geolocation does two things we don't want. It:
30626    //   1. Leaks memory in IE9: github.com/Modernizr/Modernizr/issues/513
30627    //   2. Disables page caching in WebKit: webk.it/43956
30628    //
30629    // Meanwhile, in Firefox < 8, an about:config setting could expose
30630    // a false positive that would throw an exception: bugzil.la/688158
30631
30632    tests['geolocation'] = function() {
30633        return 'geolocation' in navigator;
30634    };
30635
30636
30637    tests['postmessage'] = function() {
30638      return !!window.postMessage;
30639    };
30640
30641
30642    // Chrome incognito mode used to throw an exception when using openDatabase
30643    // It doesn't anymore.
30644    tests['websqldatabase'] = function() {
30645      return !!window.openDatabase;
30646    };
30647
30648    // Vendors had inconsistent prefixing with the experimental Indexed DB:
30649    // - Webkit's implementation is accessible through webkitIndexedDB
30650    // - Firefox shipped moz_indexedDB before FF4b9, but since then has been mozIndexedDB
30651    // For speed, we don't test the legacy (and beta-only) indexedDB
30652    tests['indexedDB'] = function() {
30653      return !!testPropsAll("indexedDB", window);
30654    };
30655
30656    // documentMode logic from YUI to filter out IE8 Compat Mode
30657    //   which false positives.
30658    tests['hashchange'] = function() {
30659      return isEventSupported('hashchange', window) && (document.documentMode === undefined || document.documentMode > 7);
30660    };
30661
30662    // Per 1.6:
30663    // This used to be Modernizr.historymanagement but the longer
30664    // name has been deprecated in favor of a shorter and property-matching one.
30665    // The old API is still available in 1.6, but as of 2.0 will throw a warning,
30666    // and in the first release thereafter disappear entirely.
30667    tests['history'] = function() {
30668      return !!(window.history && history.pushState);
30669    };
30670
30671    tests['draganddrop'] = function() {
30672        var div = document.createElement('div');
30673        return ('draggable' in div) || ('ondragstart' in div && 'ondrop' in div);
30674    };
30675
30676    // FF3.6 was EOL'ed on 4/24/12, but the ESR version of FF10
30677    // will be supported until FF19 (2/12/13), at which time, ESR becomes FF17.
30678    // FF10 still uses prefixes, so check for it until then.
30679    // for more ESR info, see: mozilla.org/en-US/firefox/organizations/faq/
30680    tests['websockets'] = function() {
30681        return 'WebSocket' in window || 'MozWebSocket' in window;
30682    };
30683
30684
30685    // css-tricks.com/rgba-browser-support/
30686    tests['rgba'] = function() {
30687        // Set an rgba() color and check the returned value
30688
30689        setCss('background-color:rgba(150,255,150,.5)');
30690
30691        return contains(mStyle.backgroundColor, 'rgba');
30692    };
30693
30694    tests['hsla'] = function() {
30695        // Same as rgba(), in fact, browsers re-map hsla() to rgba() internally,
30696        //   except IE9 who retains it as hsla
30697
30698        setCss('background-color:hsla(120,40%,100%,.5)');
30699
30700        return contains(mStyle.backgroundColor, 'rgba') || contains(mStyle.backgroundColor, 'hsla');
30701    };
30702
30703    tests['multiplebgs'] = function() {
30704        // Setting multiple images AND a color on the background shorthand property
30705        //  and then querying the style.background property value for the number of
30706        //  occurrences of "url(" is a reliable method for detecting ACTUAL support for this!
30707
30708        setCss('background:url(https://),url(https://),red url(https://)');
30709
30710        // If the UA supports multiple backgrounds, there should be three occurrences
30711        //   of the string "url(" in the return value for elemStyle.background
30712
30713        return (/(url\s*\(.*?){3}/).test(mStyle.background);
30714    };
30715
30716
30717
30718    // this will false positive in Opera Mini
30719    //   github.com/Modernizr/Modernizr/issues/396
30720
30721    tests['backgroundsize'] = function() {
30722        return testPropsAll('backgroundSize');
30723    };
30724
30725    tests['borderimage'] = function() {
30726        return testPropsAll('borderImage');
30727    };
30728
30729
30730    // Super comprehensive table about all the unique implementations of
30731    // border-radius: muddledramblings.com/table-of-css3-border-radius-compliance
30732
30733    tests['borderradius'] = function() {
30734        return testPropsAll('borderRadius');
30735    };
30736
30737    // WebOS unfortunately false positives on this test.
30738    tests['boxshadow'] = function() {
30739        return testPropsAll('boxShadow');
30740    };
30741
30742    // FF3.0 will false positive on this test
30743    tests['textshadow'] = function() {
30744        return document.createElement('div').style.textShadow === '';
30745    };
30746
30747
30748    tests['opacity'] = function() {
30749        // Browsers that actually have CSS Opacity implemented have done so
30750        //  according to spec, which means their return values are within the
30751        //  range of [0.0,1.0] - including the leading zero.
30752
30753        setCssAll('opacity:.55');
30754
30755        // The non-literal . in this regex is intentional:
30756        //   German Chrome returns this value as 0,55
30757        // github.com/Modernizr/Modernizr/issues/#issue/59/comment/516632
30758        return (/^0.55$/).test(mStyle.opacity);
30759    };
30760
30761
30762    // Note, Android < 4 will pass this test, but can only animate
30763    //   a single property at a time
30764    //   goo.gl/v3V4Gp
30765    tests['cssanimations'] = function() {
30766        return testPropsAll('animationName');
30767    };
30768
30769
30770    tests['csscolumns'] = function() {
30771        return testPropsAll('columnCount');
30772    };
30773
30774
30775    tests['cssgradients'] = function() {
30776        /**
30777         * For CSS Gradients syntax, please see:
30778         * webkit.org/blog/175/introducing-css-gradients/
30779         * developer.mozilla.org/en/CSS/-moz-linear-gradient
30780         * developer.mozilla.org/en/CSS/-moz-radial-gradient
30781         * dev.w3.org/csswg/css3-images/#gradients-
30782         */
30783
30784        var str1 = 'background-image:',
30785            str2 = 'gradient(linear,left top,right bottom,from(#9f9),to(white));',
30786            str3 = 'linear-gradient(left top,#9f9, white);';
30787
30788        setCss(
30789             // legacy webkit syntax (FIXME: remove when syntax not in use anymore)
30790              (str1 + '-webkit- '.split(' ').join(str2 + str1) +
30791             // standard syntax             // trailing 'background-image:'
30792              prefixes.join(str3 + str1)).slice(0, -str1.length)
30793        );
30794
30795        return contains(mStyle.backgroundImage, 'gradient');
30796    };
30797
30798
30799    tests['cssreflections'] = function() {
30800        return testPropsAll('boxReflect');
30801    };
30802
30803
30804    tests['csstransforms'] = function() {
30805        return !!testPropsAll('transform');
30806    };
30807
30808
30809    tests['csstransforms3d'] = function() {
30810
30811        var ret = !!testPropsAll('perspective');
30812
30813        // Webkit's 3D transforms are passed off to the browser's own graphics renderer.
30814        //   It works fine in Safari on Leopard and Snow Leopard, but not in Chrome in
30815        //   some conditions. As a result, Webkit typically recognizes the syntax but
30816        //   will sometimes throw a false positive, thus we must do a more thorough check:
30817        if ( ret && 'webkitPerspective' in docElement.style ) {
30818
30819          // Webkit allows this media query to succeed only if the feature is enabled.
30820          // `@media (transform-3d),(-webkit-transform-3d){ ... }`
30821          injectElementWithStyles('@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}', function( node, rule ) {
30822            ret = node.offsetLeft === 9 && node.offsetHeight === 3;
30823          });
30824        }
30825        return ret;
30826    };
30827
30828
30829    tests['csstransitions'] = function() {
30830        return testPropsAll('transition');
30831    };
30832
30833
30834    /*>>fontface*/
30835    // @font-face detection routine by Diego Perini
30836    // javascript.nwbox.com/CSSSupport/
30837
30838    // false positives:
30839    //   WebOS github.com/Modernizr/Modernizr/issues/342
30840    //   WP7   github.com/Modernizr/Modernizr/issues/538
30841    tests['fontface'] = function() {
30842        var bool;
30843
30844        injectElementWithStyles('@font-face {font-family:"font";src:url("https://")}', function( node, rule ) {
30845          var style = document.getElementById('smodernizr'),
30846              sheet = style.sheet || style.styleSheet,
30847              cssText = sheet ? (sheet.cssRules && sheet.cssRules[0] ? sheet.cssRules[0].cssText : sheet.cssText || '') : '';
30848
30849          bool = /src/i.test(cssText) && cssText.indexOf(rule.split(' ')[0]) === 0;
30850        });
30851
30852        return bool;
30853    };
30854    /*>>fontface*/
30855
30856    // CSS generated content detection
30857    tests['generatedcontent'] = function() {
30858        var bool;
30859
30860        injectElementWithStyles(['#',mod,'{font:0/0 a}
30860#',mod,':after{content:"',smile,'";visibility:hidden;font:3px/1 a}'].join(''), function( node ) {
30861          bool = node.offsetHeight >= 3;
30862        });
30863
30864        return bool;
30865    };
30866
30867
30868
30869    // These tests evaluate support of the video/audio elements, as well as
30870    // testing what types of content they support.
30871    //
30872    // We're using the Boolean constructor here, so that we can extend the value
30873    // e.g.  Modernizr.video     // true
30874    //       Modernizr.video.ogg // 'probably'
30875    //
30876    // Codec values from : github.com/NielsLeenheer/html5test/blob/9106a8/index.html#L845
30877    //                     thx to NielsLeenheer and zcorpan
30878
30879    // Note: in some older browsers, "no" was a return value instead of empty string.
30880    //   It was live in FF3.5.0 and 3.5.1, but fixed in 3.5.2
30881    //   It was also live in Safari 4.0.0 - 4.0.4, but fixed in 4.0.5
30882
30883    tests['video'] = function() {
30884        var elem = document.createElement('video'),
30885            bool = false;
30886
30887        // IE9 Running on Windows Server SKU can cause an exception to be thrown, bug #224
30888        try {
30889            if ( bool = !!elem.canPlayType ) {
30890                bool      = new Boolean(bool);
30891                bool.ogg  = elem.canPlayType('video/ogg; codecs="theora"')      .replace(/^no$/,'');
30892
vendor: 14,978 bytes, lines 30893-31267
30893                // Without QuickTime, this value will be `undefined`. github.com/Modernizr/Modernizr/issues/546
30894                bool.h264 = elem.canPlayType('video/mp4; codecs="avc1.42E01E"') .replace(/^no$/,'');
30895
30896                bool.webm = elem.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,'');
30897            }
30898
30899        } catch(e) { }
30900
30901        return bool;
30902    };
30903
30904    tests['audio'] = function() {
30905        var elem = document.createElement('audio'),
30906            bool = false;
30907
30908        try {
30909            if ( bool = !!elem.canPlayType ) {
30910                bool      = new Boolean(bool);
30911                bool.ogg  = elem.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,'');
30912                bool.mp3  = elem.canPlayType('audio/mpeg;')               .replace(/^no$/,'');
30913
30914                // Mimetypes accepted:
30915                //   developer.mozilla.org/En/Media_formats_supported_by_the_audio_and_video_elements
30916                //   bit.ly/iphoneoscodecs
30917                bool.wav  = elem.canPlayType('audio/wav; codecs="1"')     .replace(/^no$/,'');
30918                bool.m4a  = ( elem.canPlayType('audio/x-m4a;')            ||
30919                              elem.canPlayType('audio/aac;'))             .replace(/^no$/,'');
30920            }
30921        } catch(e) { }
30922
30923        return bool;
30924    };
30925
30926
30927    // In FF4, if disabled, window.localStorage should === null.
30928
30929    // Normally, we could not test that directly and need to do a
30930    //   `('localStorage' in window) && ` test first because otherwise Firefox will
30931    //   throw bugzil.la/365772 if cookies are disabled
30932
30933    // Also in iOS5 Private Browsing mode, attempting to use localStorage.setItem
30934    // will throw the exception:
30935    //   QUOTA_EXCEEDED_ERRROR DOM Exception 22.
30936    // Peculiarly, getItem and removeItem calls do not throw.
30937
30938    // Because we are forced to try/catch this, we'll go aggressive.
30939
30940    // Just FWIW: IE8 Compat mode supports these features completely:
30941    //   www.quirksmode.org/dom/html5.html
30942    // But IE8 doesn't support either with local files
30943
30944    tests['localstorage'] = function() {
30945        try {
30946            localStorage.setItem(mod, mod);
30947            localStorage.removeItem(mod);
30948            return true;
30949        } catch(e) {
30950            return false;
30951        }
30952    };
30953
30954    tests['sessionstorage'] = function() {
30955        try {
30956            sessionStorage.setItem(mod, mod);
30957            sessionStorage.removeItem(mod);
30958            return true;
30959        } catch(e) {
30960            return false;
30961        }
30962    };
30963
30964
30965    tests['webworkers'] = function() {
30966        return !!window.Worker;
30967    };
30968
30969
30970    tests['applicationcache'] = function() {
30971        return !!window.applicationCache;
30972    };
30973
30974
30975    // Thanks to Erik Dahlstrom
30976    tests['svg'] = function() {
30977        return !!document.createElementNS && !!document.createElementNS(ns.svg, 'svg').createSVGRect;
30978    };
30979
30980    // specifically for SVG inline in HTML, not within XHTML
30981    // test page: paulirish.com/demo/inline-svg
30982    tests['inlinesvg'] = function() {
30983      var div = document.createElement('div');
30984      div.innerHTML = '<svg/>';
30985      return (div.firstChild && div.firstChild.namespaceURI) == ns.svg;
30986    };
30987
30988    // SVG SMIL animation
30989    tests['smil'] = function() {
30990        return !!document.createElementNS && /SVGAnimate/.test(toString.call(document.createElementNS(ns.svg, 'animate')));
30991    };
30992
30993    // This test is only for clip paths in SVG proper, not clip paths on HTML content
30994    // demo: srufaculty.sru.edu/david.dailey/svg/newstuff/clipPath4.svg
30995
30996    // However read the comments to dig into applying SVG clippaths to HTML content here:
30997    //   github.com/Modernizr/Modernizr/issues/213#issuecomment-1149491
30998    tests['svgclippaths'] = function() {
30999        return !!document.createElementNS && /SVGClipPath/.test(toString.call(document.createElementNS(ns.svg, 'clipPath')));
31000    };
31001
31002    /*>>webforms*/
31003    // input features and input types go directly onto the ret object, bypassing the tests loop.
31004    // Hold this guy to execute in a moment.
31005    function webforms() {
31006        /*>>input*/
31007        // Run through HTML5's new input attributes to see if the UA understands any.
31008        // We're using f which is the <input> element created early on
31009        // Mike Taylr has created a comprehensive resource for testing these attributes
31010        //   when applied to all input types:
31011        //   miketaylr.com/code/input-type-attr.html
31012        // spec: www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary
31013
31014        // Only input placeholder is tested while textarea's placeholder is not.
31015        // Currently Safari 4 and Opera 11 have support only for the input placeholder
31016        // Both tests are available in feature-detects/forms-placeholder.js
31017        Modernizr['input'] = (function( props ) {
31018            for ( var i = 0, len = props.length; i < len; i++ ) {
31019                attrs[ props[i] ] = !!(props[i] in inputElem);
31020            }
31021            if (attrs.list){
31022              // safari false positive's on datalist: webk.it/74252
31023              // see also github.com/Modernizr/Modernizr/issues/146
31024              attrs.list = !!(document.createElement('datalist') && window.HTMLDataListElement);
31025            }
31026            return attrs;
31027        })('autocomplete autofocus list placeholder max min multiple pattern required step'.split(' '));
31028        /*>>input*/
31029
31030        /*>>inputtypes*/
31031        // Run through HTML5's new input types to see if the UA understands any.
31032        //   This is put behind the tests runloop because it doesn't return a
31033        //   true/false like all the other tests; instead, it returns an object
31034        //   containing each input type with its corresponding true/false value
31035
31036        // Big thanks to @miketaylr for the html5 forms expertise. miketaylr.com/
31037        Modernizr['inputtypes'] = (function(props) {
31038
31039            for ( var i = 0, bool, inputElemType, defaultView, len = props.length; i < len; i++ ) {
31040
31041                inputElem.setAttribute('type', inputElemType = props[i]);
31042                bool = inputElem.type !== 'text';
31043
31044                // We first check to see if the type we give it sticks..
31045                // If the type does, we feed it a textual value, which shouldn't be valid.
31046                // If the value doesn't stick, we know there's input sanitization which infers a custom UI
31047                if ( bool ) {
31048
31049                    inputElem.value         = smile;
31050                    inputElem.style.cssText = 'position:absolute;visibility:hidden;';
31051
31052                    if ( /^range$/.test(inputElemType) && inputElem.style.WebkitAppearance !== undefined ) {
31053
31054                      docElement.appendChild(inputElem);
31055                      defaultView = document.defaultView;
31056
31057                      // Safari 2-4 allows the smiley as a value, despite making a slider
31058                      bool =  defaultView.getComputedStyle &&
31059                              defaultView.getComputedStyle(inputElem, null).WebkitAppearance !== 'textfield' &&
31060                              // Mobile android web browser has false positive, so must
31061                              // check the height to see if the widget is actually there.
31062                              (inputElem.offsetHeight !== 0);
31063
31064                      docElement.removeChild(inputElem);
31065
31066                    } else if ( /^(search|tel)$/.test(inputElemType) ){
31067                      // Spec doesn't define any special parsing or detectable UI
31068                      //   behaviors so we pass these through as true
31069
31070                      // Interestingly, opera fails the earlier test, so it doesn't
31071                      //  even make it here.
31072
31073                    } else if ( /^(url|email)$/.test(inputElemType) ) {
31074                      // Real url and email support comes with prebaked validation.
31075                      bool = inputElem.checkValidity && inputElem.checkValidity() === false;
31076
31077                    } else {
31078                      // If the upgraded input compontent rejects the :) text, we got a winner
31079                      bool = inputElem.value != smile;
31080                    }
31081                }
31082
31083                inputs[ props[i] ] = !!bool;
31084            }
31085            return inputs;
31086        })('search tel url email datetime date month week time datetime-local number range color'.split(' '));
31087        /*>>inputtypes*/
31088    }
31089    /*>>webforms*/
31090
31091
31092    // End of test definitions
31093    // -----------------------
31094
31095
31096
31097    // Run through all tests and detect their support in the current UA.
31098    // todo: hypothetically we could be doing an array of tests and use a basic loop here.
31099    for ( var feature in tests ) {
31100        if ( hasOwnProp(tests, feature) ) {
31101            // run the test, throw the return value into the Modernizr,
31102            //   then based on that boolean, define an appropriate className
31103            //   and push it into an array of classes we'll join later.
31104            featureName  = feature.toLowerCase();
31105            Modernizr[featureName] = tests[feature]();
31106
31107            classes.push((Modernizr[featureName] ? '' : 'no-') + featureName);
31108        }
31109    }
31110
31111    /*>>webforms*/
31112    // input tests need to run.
31113    Modernizr.input || webforms();
31114    /*>>webforms*/
31115
31116
31117    /**
31118     * addTest allows the user to define their own feature tests
31119     * the result will be added onto the Modernizr object,
31120     * as well as an appropriate className set on the html element
31121     *
31122     * @param feature - String naming the feature
31123     * @param test - Function returning true if feature is supported, false if not
31124     */
31125     Modernizr.addTest = function ( feature, test ) {
31126       if ( typeof feature == 'object' ) {
31127         for ( var key in feature ) {
31128           if ( hasOwnProp( feature, key ) ) {
31129             Modernizr.addTest( key, feature[ key ] );
31130           }
31131         }
31132       } else {
31133
31134         feature = feature.toLowerCase();
31135
31136         if ( Modernizr[feature] !== undefined ) {
31137           // we're going to quit if you're trying to overwrite an existing test
31138           // if we were to allow it, we'd do this:
31139           //   var re = new RegExp("\\b(no-)?" + feature + "\\b");
31140           //   docElement.className = docElement.className.replace( re, '' );
31141           // but, no rly, stuff 'em.
31142           return Modernizr;
31143         }
31144
31145         test = typeof test == 'function' ? test() : test;
31146
31147         if (typeof enableClasses !== "undefined" && enableClasses) {
31148           docElement.className += ' ' + (test ? '' : 'no-') + feature;
31149         }
31150         Modernizr[feature] = test;
31151
31152       }
31153
31154       return Modernizr; // allow chaining.
31155     };
31156
31157
31158    // Reset modElem.cssText to nothing to reduce memory footprint.
31159    setCss('');
31160    modElem = inputElem = null;
31161
31162    /*>>shiv*/
31163    /**
31164     * @preserve HTML5 Shiv prev3.7.1 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
31165     */
31166    ;(function(window, document) {
31167        /*jshint evil:true */
31168        /** version */
31169        var version = '3.7.0';
31170
31171        /** Preset options */
31172        var options = window.html5 || {};
31173
31174        /** Used to skip problem elements */
31175        var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i;
31176
31177        /** Not all elements can be cloned in IE **/
31178        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;
31179
31180        /** Detect whether the browser supports default html5 styles */
31181        var supportsHtml5Styles;
31182
31183        /** Name of the expando, to work with multiple documents or to re-shiv one document */
31184        var expando = '_html5shiv';
31185
31186        /** The id for the the documents expando */
31187        var expanID = 0;
31188
31189        /** Cached data for each document */
31190        var expandoData = {};
31191
31192        /** Detect whether the browser supports unknown elements */
31193        var supportsUnknownElements;
31194
31195        (function() {
31196          try {
31197            var a = document.createElement('a');
31198            a.innerHTML = '<xyz></xyz>';
31199            //if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles
31200            supportsHtml5Styles = ('hidden' in a);
31201
31202            supportsUnknownElements = a.childNodes.length == 1 || (function() {
31203              // assign a false positive if unable to shiv
31204              (document.createElement)('a');
31205              var frag = document.createDocumentFragment();
31206              return (
31207                typeof frag.cloneNode == 'undefined' ||
31208                typeof frag.createDocumentFragment == 'undefined' ||
31209                typeof frag.createElement == 'undefined'
31210              );
31211            }());
31212          } catch(e) {
31213            // assign a false positive if detection fails => unable to shiv
31214            supportsHtml5Styles = true;
31215            supportsUnknownElements = true;
31216          }
31217
31218        }());
31219
31220        /*--------------------------------------------------------------------------*/
31221
31222        /**
31223         * Creates a style sheet with the given CSS text and adds it to the document.
31224         * @private
31225         * @param {Document} ownerDocument The document.
31226         * @param {String} cssText The CSS text.
31227         * @returns {StyleSheet} The style element.
31228         */
31229        function addStyleSheet(ownerDocument, cssText) {
31230          var p = ownerDocument.createElement('p'),
31231          parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement;
31232
31233          p.innerHTML = 'x<style>' + cssText + '</style>';
31234          return parent.insertBefore(p.lastChild, parent.firstChild);
31235        }
31236
31237        /**
31238         * Returns the value of `html5.elements` as an array.
31239         * @private
31240         * @returns {Array} An array of shived element node names.
31241         */
31242        function getElements() {
31243          var elements = html5.elements;
31244          return typeof elements == 'string' ? elements.split(' ') : elements;
31245        }
31246
31247        /**
31248         * Returns the data associated to the given document
31249         * @private
31250         * @param {Document} ownerDocument The document.
31251         * @returns {Object} An object of data.
31252         */
31253        function getExpandoData(ownerDocument) {
31254          var data = expandoData[ownerDocument[expando]];
31255          if (!data) {
31256            data = {};
31257            expanID++;
31258            ownerDocument[expando] = expanID;
31259            expandoData[expanID] = data;
31260          }
31261          return data;
31262        }
31263
31264        /**
31265         * returns a shived element for the given nodeName and document
31266         * @memberOf html5
31267         * @param {String}
vendor: 4,707 bytes, lines 31267-31378
31267 nodeName name of the element
31268         * @param {Document} ownerDocument The context document.
31269         * @returns {Object} The shived element.
31270         */
31271        function createElement(nodeName, ownerDocument, data){
31272          if (!ownerDocument) {
31273            ownerDocument = document;
31274          }
31275          if(supportsUnknownElements){
31276            return ownerDocument.createElement(nodeName);
31277          }
31278          if (!data) {
31279            data = getExpandoData(ownerDocument);
31280          }
31281          var node;
31282
31283          if (data.cache[nodeName]) {
31284            node = data.cache[nodeName].cloneNode();
31285          } else if (saveClones.test(nodeName)) {
31286            node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode();
31287          } else {
31288            node = data.createElem(nodeName);
31289          }
31290
31291          // Avoid adding some elements to fragments in IE < 9 because
31292          // * Attributes like `name` or `type` cannot be set/changed once an element
31293          //   is inserted into a document/fragment
31294          // * Link elements with `src` attributes that are inaccessible, as with
31295          //   a 403 response, will cause the tab/window to crash
31296          // * Script elements appended to fragments will execute when their `src`
31297          //   or `text` property is set
31298          return node.canHaveChildren && !reSkip.test(nodeName) && !node.tagUrn ? data.frag.appendChild(node) : node;
31299        }
31300
31301        /**
31302         * returns a shived DocumentFragment for the given document
31303         * @memberOf html5
31304         * @param {Document} ownerDocument The context document.
31305         * @returns {Object} The shived DocumentFragment.
31306         */
31307        function createDocumentFragment(ownerDocument, data){
31308          if (!ownerDocument) {
31309            ownerDocument = document;
31310          }
31311          if(supportsUnknownElements){
31312            return ownerDocument.createDocumentFragment();
31313          }
31314          data = data || getExpandoData(ownerDocument);
31315          var clone = data.frag.cloneNode(),
31316          i = 0,
31317          elems = getElements(),
31318          l = elems.length;
31319          for(;i<l;i++){
31320            clone.createElement(elems[i]);
31321          }
31322          return clone;
31323        }
31324
31325        /**
31326         * Shivs the `createElement` and `createDocumentFragment` methods of the document.
31327         * @private
31328         * @param {Document|DocumentFragment} ownerDocument The document.
31329         * @param {Object} data of the document.
31330         */
31331        function shivMethods(ownerDocument, data) {
31332          if (!data.cache) {
31333            data.cache = {};
31334            data.createElem = ownerDocument.createElement;
31335            data.createFrag = ownerDocument.createDocumentFragment;
31336            data.frag = data.createFrag();
31337          }
31338
31339
31340          ownerDocument.createElement = function(nodeName) {
31341            //abort shiv
31342            if (!html5.shivMethods) {
31343              return data.createElem(nodeName);
31344            }
31345            return createElement(nodeName, ownerDocument, data);
31346          };
31347
31348          ownerDocument.createDocumentFragment = Function('h,f', 'return function(){' +
31349                                                          'var n=f.cloneNode(),c=n.createElement;' +
31350                                                          'h.shivMethods&&(' +
31351                                                          // unroll the `createElement` calls
31352                                                          getElements().join().replace(/[\w\-]+/g, function(nodeName) {
31353            data.createElem(nodeName);
31354            data.frag.createElement(nodeName);
31355            return 'c("' + nodeName + '")';
31356          }) +
31357            ');return n}'
31358                                                         )(html5, data.frag);
31359        }
31360
31361        /*--------------------------------------------------------------------------*/
31362
31363        /**
31364         * Shivs the given document.
31365         * @memberOf html5
31366         * @param {Document} ownerDocument The document to shiv.
31367         * @returns {Document} The shived document.
31368         */
31369        function shivDocument(ownerDocument) {
31370          if (!ownerDocument) {
31371            ownerDocument = document;
31372          }
31373          var data = getExpandoData(ownerDocument);
31374
31375          if (html5.shivCSS && !supportsHtml5Styles && !data.hasCSS) {
31376            data.hasCSS = !!addStyleSheet(ownerDocument,
31377                                          // corrects block display not defined in IE6/7/8/9
31378                                          'article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{dis
31378play:block}' +
31379                                            // adds styling not present in IE6/7/8/9
31380                                            'mark{background:#FF0;color:#000}' +
31381                                            // hides non-rendered elements
31382                                            'template{display:none}'
31383                                         );
31384          }
31385          if (!supportsUnknownElements) {
31386            shivMethods(ownerDocument, data);
31387          }
31388          return ownerDocument;
31389        }
31390
31391        /*--------------------------------------------------------------------------*/
31392
31393        /**
31394         * The `html5` object is exposed so that more elements can be shived and
31395         * existing shiving can be detected on iframes.
31396         * @type Object
31397         * @example
31398         *
31399         * // options can be changed before the script is included
31400         * html5 = { 'elements': 'mark section', 'shivCSS': false, 'shivMethods': false };
31401         */
31402        var html5 = {
31403
31404          /**
31405           * An array or space separated string of node names of the elements to shiv.
31406           * @memberOf html5
31407           * @type Array|String
31408           */
31409          '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',
31410
31411          /**
31412           * current version of html5shiv
31413           */
31414          'version': version,
31415
31416          /**
31417           * A flag to indicate that the HTML5 style sheet should be inserted.
31418           * @memberOf html5
31419           * @type Boolean
31420           */
31421          'shivCSS': (options.shivCSS !== false),
31422
31423          /**
31424           * Is equal to true if a browser supports creating unknown/HTML5 elements
31425           * @memberOf html5
31426           * @type boolean
31427           */
31428          'supportsUnknownElements': supportsUnknownElements,
31429
31430          /**
31431           * A flag to indicate that the document's `createElement` and `createDocumentFragment`
31432           * methods should be overwritten.
31433           * @memberOf html5
31434           * @type Boolean
31435           */
31436          'shivMethods': (options.shivMethods !== false),
31437
31438          /**
31439           * A string to describe the type of `html5` object ("default" or "default print").
31440           * @memberOf html5
31441           * @type String
31442           */
31443          'type': 'default',
31444
31445          // shivs the document according to the specified `html5` object options
31446          'shivDocument': shivDocument,
31447
31448          //creates a shived element
31449          createElement: createElement,
31450
31451          //creates a shived documentFragment
31452          createDocumentFragment: createDocumentFragment
31453        };
31454
31455        /*--------------------------------------------------------------------------*/
31456
31457        // expose html5
31458        window.html5 = html5;
31459
31460        // shiv the document
31461        shivDocument(document);
31462
31463    }(this, document));
31464    /*>>shiv*/
31465
31466    // Assign private properties to the return object with prefix
31467    Modernizr._version      = version;
31468
31469    // expose these for the plugin API. Look in the source for how to join() them against your input
31470    /*>>prefixes*/
31471    Modernizr._prefixes     = prefixes;
31472    /*>>prefixes*/
31473    /*>>domprefixes*/
31474    Modernizr._domPrefixes  = domPrefixes;
31475    Modernizr._cssomPrefixes  = cssomPrefixes;
31476    /*>>domprefixes*/
31477
31478    /*>>mq*/
31479    // Modernizr.mq tests a given media query, live against the current state of the window
31480    // A few important notes:
31481    //   * If a browser does not support media queries at all (eg. oldIE) the mq() will always return false
31482    //   * A max-width or orientation query will be evaluated against the current state, which may change later.
31483    //   * You must specify values. Eg. If you are testing support for the min-width media query use:
31484    //       Modernizr.mq('(min-width:0)')
31485    // usage:
31486    // Modernizr.mq('only screen and (max-width:768)')
31487    Modernizr.mq            = testMediaQuery;
31488    /*>>mq*/
31489
31490    /*>>hasevent*/
31491    // Modernizr.hasEvent() detects support for a given event, with an optional element to test on
31492    // Modernizr.hasEvent('gesturestart', elem)
31493    Modernizr.hasEvent      = isEventSupported;
31494    /*>>hasevent*/
31495
31496    /*>>testprop*/
31497    // Modernizr.testProp() investigates whether a given style property is recognized
31498    // Note that the property names must be provided in the camelCase variant.
31499    // Modernizr.testProp('pointerEvents')
31500    Modernizr.testProp      = function(prop){
31501        return testProps([prop]);
31502    };
31503    /*>>testprop*/
31504
31505    /*>>testallprops*/
31506    // Modernizr.testAllProps() investigates whether a given style property,
31507    //   or any of its vendor-prefixed variants, is recognized
31508    // Note that the property names must be provided in the camelCase variant.
31509    // Modernizr.testAllProps('boxSizing')
31510    Modernizr.testAllProps  = testPropsAll;
31511    /*>>testallprops*/
31512
31513
31514    /*>>teststyles*/
31515    // Modernizr.testStyles() allows you to add custom styles to the document and test an element afterwards
31516    // Modernizr.testStyles('#modernizr { position:absolute }', function(elem, rule){ ... })
31517    Modernizr.testStyles    = injectElementWithStyles;
31518    /*>>teststyles*/
31519
31520
31521    /*>>prefixed*/
31522    // Modernizr.prefixed() returns the prefixed or nonprefixed property name variant of your input
31523    // Modernizr.prefixed('boxSizing') // 'MozBoxSizing'
31524
31525    // Properties must be passed as dom-style camelcase, rather than `box-sizing` hypentated style.
31526    // Return values will also be the camelCase variant, if you need to translate that to hypenated style use:
31527    //
31528    //     str.replace(/([A-Z])/g, function(str,m1){ return '-' + m1.toLowerCase(); }).replace(/^ms-/,'-ms-');
31529
31530    // If you're trying to ascertain which transition end event to bind to, you might do something like...
31531    //
31532    //     var transEndEventNames = {
31533    //       'WebkitTransition' : 'webkitTransitionEnd',
31534    //       'MozTransition'    : 'transitionend',
31535    //       'OTransition'      : 'oTransitionEnd',
31536    //       'msTransition'     : 'MSTransitionEnd',
31537    //       'transition'       : 'transitionend'
31538    //     },
31539    //     transEndEventName = transEndEventNames[ Modernizr.prefixed('transition') ];
31540
31541    Modernizr.prefixed      = function(prop, obj, elem){
31542      if(!obj) {
31543        return testPropsAll(prop, 'pfx');
31544      } else {
31545        // Testing DOM property e.g. Modernizr.prefixed('requestAnimationFrame', window) // 'mozRequestAnimationFrame'
31546        return testPropsAll(prop, obj, elem);
31547      }
31548    };
31549    /*>>prefixed*/
31550
31551
31552    /*>>cssclasses*/
31553    // Remove "no-js" class from <html> element, if it exists:
31554    docElement.className = docElement.className.replace(/(^|\s)no-js(\s|$)/, '$1$2') +
31555
31556                            // Add the new classes to the <html> element.
31557                            (enableClasses ? ' js ' + classes.join(' ') : '');
31558    /*>>cssclasses*/
31559
31560    return Modernizr;
31561
31562})(this, this.document);
31563;
31564
31565/*! Agility
31566*/
31567
31568
31569if (typeof (window.Agility) == "undefined") {
31570	window.Agility = new Object();	
31571}
31572(function(Agility) {
31573
31574	//handle ctrl and shift
31575	Agility.isCtrl = false; 
31576	Agility.isAlt = false; 
31577	Agility.isShift = false; 
31578
31579	$(document).keyup(function (e) { 
31580		switch (e.which) {
31581			case 16:
31582				Agility.isShift=false; 
31583				break;
31584			case 17:
31585				Agility.isCtrl=false; 
31586				break;
31587			case  18:
31588				Agility.isAlt=false; 	
31589				break;
31590		}
31591		
31592	}).keydown(function (e) { 
31593		switch (e.which) {
31594			case 16:
31595				Agility.isShift=true; 
31596				break;
31597			case 17:
31598				Agility.isCtrl=true; 
31599				break;
31600			case 18:
31601				Agility.isAlt=true; 	
31602				break;
31603		}
31604		
31605	});
31606	
31607
31608	Agility.RegisterNamespace = function(space) {
31609		/// <summary>
31610		/// Register a javascript namespace.
31611		/// </summary>
31612		/// <param name="space" type="String">The namespace (dot-separated) to register.</param>
31613		/// <returns type="object">Object representing the created namespace.</returns>
31614
31615		var spaces = space.split("."),
31616			root = window;
31617
31618		for (var i = 0; i < spaces.length; i++) {
31619			if (typeof (root[spaces[i]]) == "undefined") {
31620				root = root[spaces[i]] = {};
31621			} else {
31622				root = root[spaces[i]];
31623			}
31624		}
31625		
31626		return root;
31627	}
31628	
31629	var _sessionLevelCacheKey = null;
31630	Agility.SessionLevelCacheKey = function() {
31631		/// <summary>
31632		/// gets a string that is based on the date and time that this page was loaded.  Use this for Client Templating with urls.
31633		/// </summary>
31634		
31635		if (_sessionLevelCacheKey == null) {
31636			_sessionLevelCacheKey = (new Date()).toString("yyyyMMddHHmmss");
31637		}
31638		return _sessionLevelCacheKey;
31639		
31640	};
31641
31642	Agility.ResolveUrl = function(url) {
31643		/// <summary>
31644		/// Resolve "~/" to the application's base url. *Requires that global var "Edentity_BaseUrl" has been set.
31645		/// </summary>
31646		/// <param name="url" type="String">The URL whose path to resolve.</param>
31647		/// <returns type="string">String representing the resolved URL.</returns>
31648
31649		var baseUrl = window.Agility_BaseUrl || "/";
31650		return url.replace(/^~\//, baseUrl);
31651	}
31652	
31653	
31654	var _unique = {};
31655	var _uniqueIndex = 0;
31656	Agility.UniqueID = function(prePend){
31657		/// <summary>
31658		/// Build a Unique ID (unique to this instance).
31659		/// </summary>
31660		/// <param name="prePend" type="String">The value to prepend to the Unique portion.</param>
31661						
31662		if (prePend == undefined || prePend == null || prePend == "") {
31663			return _uniqueIndex++;
31664		} else {
31665			if (_unique[prePend] == undefined) _unique[prePend] = 0;
31666			return prePend + _unique[prePend]++;
31667		}				
31668	}
31669	
31670	Agility.CloneObject = function (what, serializationType) {
31671		/// <summary>
31672		/// Clones an object to preserve the original value.
31673		/// </summary>
31674		/// <param name="what" type="object">The object to clone.</param>
31675		
31676		if (serializationType != undefined && serializationType != null && serializationType != "") {
31677			this.__type = serializationType;	
31678		}
31679		
31680		for (i in what) {
31681			if (what[i] == null) {
31682				this[i] = null;
31683			} else {
31684			 
31685				if (typeof what[i] == 'object') {
31686					this[i] = new Agility.CloneObject(what[i]);
31687				} else {
31688					var val = what[i];				
31689					this[i] = val;				
31690				}
31691			}
31692		}
31693	}
31694
31695
31696	
31697	Agility.QueryString = function(name, url) {
31698		/// <summary>
31699		/// Gets a variable from the query string.  
31700		/// </summary>
31701		/// <param name="name" type="String">QueryString variable to retrieve.</param>
31702		/// <param name="url" type="String">(Optional) the url to take the querystring from.  If this is not present, the current url is used.</param>
31703		
31704		if (url == undefined || url == null || url == "") {
31705			url = location.href;
31706		}
31707		
31708		var index = url.indexOf("?");
31709		if (index < 1 && index == url.length - 2) return null;
31710		if (url.indexOf("#") != -1) {
31711			url = url.substring(0, url.indexOf("#"));
31712		}
31713		
31714		var qstr = url.substring(index + 1, url.length);
31715		
31716		var ary1 = qstr.split("&");
31717		var retValue = null;
31718		
31719		jQuery.each(ary1, function(index, q) {
31720			var ary2 = q.split("=");
31721			if (ary2.length == 2) {
31722				if (unescape(ary2[0]).toLowerCase() == name.toLowerCase()) {
31723				
31724					retValue = ary2[1];					
31725					retValue = retValue.replace(/\+/g, "%20");
31726					retValue = unescape(retValue);
31727					return false;
31728				}
31729			}
31730		});
31731		
31732		return retValue;
31733		
31734	}
31735	
31736	Agility.ToJSONDate = function(dateObj) {
31737		/// <summary>
31738		/// Converts a Date object to a JSON string, and it will account for the timezone offset (\/Date(000000000000)\/). 
31739		/// </summary>
31740		/// <param name="dateObj" type="Date">Date object to convert.</param>
31741				
31742		dateObj.setMinutes(dateObj.getMinutes() + dateObj.getTimezoneOffset());
31743				
31744		var dtStr = dateObj.getFullYear() + "-" + Agility.PadLeft(dateObj.getMonth() + 1, "0") + "-" + Agility.PadLeft(dateObj.getDate() + 1, "0") + " " + Agility.PadLeft(dateObj.getHours(), "0") + ":" + Agility.PadLeft(dateObj.getMinutes(), "0") + ":" + Agility.PadLeft(dateObj.getSeconds(), dateObj.getMilliseconds(), "0");
31745		
31746		return "\/Date("+ dtStr +")\/";	
31747	}
31748	
31749	Agility.PadLeft = function(str, padChar) {
31750		
31751		str = str + "";
31752		while (str.length < padChar) {
31753			str = padChar + str;
31754		}
31755		
31756		return str;
31757	}
31758	
31759	Agility.GetFlashVersion = function() {
31760		
31761	   var flashVersion = 0;
31762	   
31763		if (window.ActiveXObject) {   
31764			//ie
31765			var control = null;   
31766			try {   
31767				control = new ActiveXObject('ShockwaveFlash.ShockwaveFlash');   
31768				if (control) {					
31769					var version = control.GetVariable('$version').substring(4);   
31770					version = version.split(',');   
31771					flashVersion = parseInt(version[0]);
31772				}   
31773			} catch (e) {  				
31774			}   
31775			
31776		} else { 
31777	   
31778			//non ie
31779			if (navigator.plugins != null) {
31780				if (navigator.plugins.length > 0) {
31781					var flashPlugin = navigator.plugins['Shockwave Flash']; 
31782
31783						if (typeof flashPlugin == 'object') {
31784						if (flashPlugin.version) {
31785							var vstr = flashPlugin.version;
31786							if (vstr) flashVersion = parseInt(vstr.split(".")[0]);						
31787						} else {						
31788							var desc = flashPlugin.description;
31789							if (desc) flashVersion = parseInt(desc.replace("Shockwave Flash ", "").split(".")[0]);										
31790						}
31791					}
31792				}
31793			}
31794		}
31795		
31796		return flashVersion;
31797	}
31798
31799	
31800	
31801	Agility.SetCookie = function(name, value, expires, path, domain, secure ) {
31802	/// <summary>Sets a cookie based on the name and value provided.</summary>
31803	/// <param name="name" type="String">The name of the cookie to set the value of.</param>
31804	/// <param name="value" type="String">The value of the cookie to set.</param>
31805	/// <param name="expires" type="Date">(Optional) The date that the cookie should expire.</param>
31806	/// <param name="path" type="String">(Optional) The path of the cookie.</param>
31807	/// <param name="domain" type="String">(Optional) The domain of the cookie.</param>
31808	/// <param name="secure" type="Boolean">(Optional) Whether the cookie is secure or not.</param>
31809
31810		var expires_date = expires;
31811
31812		document.cookie = name + "=" +escape( value ) +
31813		( ( expires ) ? ";expires=" + expires_date.toGMTString() : "" ) +
31814		( ( path ) ? ";path=" + path : "" ) +
31815		( ( domain ) ? ";domain=" + domain : "" ) +
31816		( ( secure ) ? ";secure" : "" );
31817	}
31818
31819	
31820	
31821	Agility.GetCookie = function ( cookieName ) {
31822	/// <summary>Gets the value of the given cookieName from the current cookies collection.</summary>
31823	/// <param name="cookieName" type="String">The name of the cookie to return.</param>
31824
31825		// first we'll split this cookie up into name/value pairs
31826		// note: document.cookie only returns name=value, not the other components
31827		var a_all_cookies = document.cookie.split( ';' );
31828		var a_temp_cookie = '';
31829		var cookie_name = '';
31830		var cookie_value = '';
31831		var b_cookie_found = false; // set boolean t/f default f
31832
31833		for ( i = 0; i < a_all_cookies.length; i++ )
31834		{
31835			// now we'll split apart each name=value pair
31836			a_temp_cookie = a_all_cookies[i].split( '=' );
31837
31838
31839			// and trim left/right whitespace while we're at it
31840			cookie_name = a_temp_cookie[0].replace(/^\s+|\s+$/g, '');
31841
31842			// if the extracted name matches passed cookieName
31843			if ( cookie_name == cookieName )
31844			{
31845				b_cookie_found = true;
31846				// we need to handle case where cookie has no value but exists (no = sign, that is):
31847				if ( a_temp_cookie.length > 1 )
31848				{
31849					cookie_value = unescape( a_temp_cookie[1].replace(/^\s+|\s+$/g, '') );
31850				}
31851				// note that in cases where cookie is initialized but no value, null is returned
31852				return cookie_value;
31853				break;
31854			}
31855			a_temp_cookie = null;
31856			cookie_name = '';
31857		}
31858		if ( !b_cookie_found )
31859		{
31860			return null;
31861		}
31862	}
31863	
31864    Agility.DeleteCookie = function(name, path, domain, secure) {
31865    /// <summary>Delete a cookie based on the name provided.</summary>
31866	/// <param name="name" type="String">The name of the cookie to set the value of.</param>
31867	/// <param name="path" type="String">(Optional) The path of the cookie.</param>
31868	/// <param name="domain" type="String">(Optional) The domain of the cookie.</param>
31869	/// <param name="secure" type="Boolean">(Optional) Whether the cookie is secure or not.</param>
31870
31871        if (Agility.GetCookie(name)) {
31872            document.cookie = name + "=" + (path ? ";path=" + path : "") +
31873                (domain ? ";domain=" + domain : "" ) + (secure ? ";secure" : "") +
31874                ";expires=Thu, 01-Jan-1970 00:00:01 GMT";
31875        }
31876    };
31877
31878
31879    Agility.JSON = new function () {
31880
31881        /* Section: Methods - Public */
31882
31883        /*
31884        Method: decode
31885        decodes a valid JSON encoded string.
31886        
31887        Arguments:
31888        [String / Function] - Optional JSON string to decode or a filter function if method is a String prototype.
31889        [Function] - Optional filter function if first argument is a JSON string and this method is not a String prototype.
31890        
31891        Returns:
31892        Object - Generic JavaScript variable or undefined
31893        
31894        Example [Basic]:
31895        >var	arr = JSON.decode('[1,2,3]');
31896        >alert(arr);	// 1,2,3
31897        >
31898        >arr = JSON.decode('[1,2,3]', function(key, value){return key * value});
31899        >alert(arr);	// 0,2,6
31900        
31901        Example [Prototype]:
31902        >String.prototype.parseJSON = JSON.decode;
31903        >
31904        >alert('[1,2,3]'.parseJSON());	// 1,2,3
31905        >
31906        >try {
31907        >	alert('[1,2,3]'.parseJSON(function(key, value){return key * value}));
31908        >	// 0,2,6
31909        >}
31910        >catch(e) {
31911        >	alert(e.message);
31912        >}
31913        
31914        Note:
31915        Internet Explorer 5 and other old browsers should use a different regular expression to check if a JSON string is valid or not.
31916        This old browsers dedicated RegExp is not safe as native version is but it required for compatibility.
31917        */
31918        this.decode = function () {
31919            var filter, result, self, tmp;
31920            if ($$("toString")) {
31921                switch (arguments.length) {
31922                    case 2:
31923                        self = arguments[0];
31924                        filter = arguments[1];
31925                        break;
31926                    case 1:
31927                        if ($[typeof arguments[0]](arguments[0]) === Function) {
31928                            self = this;
31929                            filter = arguments[0];
31930                        }
31931                        else
31932                            self = arguments[0];
31933                        break;
31934                    default:
31935                        self = this;
31936                        break;
31937                };
31938                if (rc.test(self)) {
31939                    try {
31940                        result = e("(".concat(self, ")"));
31941                        if (filter && result !== null && (tmp = $[typeof result](result)) && (tmp === Array || tmp === Object)) {
31942                            for (self in result)
31943                                result[self] = v(self, result) ? filter(self, result[self]) : result[self];
31944                        }
31945                    }
31946                    catch (z) { }
31947                }
31948                else {
31949                    throw new JSONError("bad data");
31950                }
31951            };
31952            return result;
31953        };
31954
31955        /*
31956        Method: encode
31957        encode a generic JavaScript variable into a valid JSON string.
31958        
31959        Arguments:
31960        [Object] - Optional generic JavaScript variable to encode if method is not an Object prototype.
31961        
31962        Returns:
31963        String - Valid JSON string or undefined
31964        
31965        Example [Basic]:
31966        >var	s = Agility.JSON.encode([1,2,3]);
31967        >alert(s);	// [1,2,3]
31968        
31969        Example [Prototype]:
31970        >Object.prototype.toJSONString = Agility.JSON.encode;
31971        >
31972        >alert([1,2,3].toJSONString());	// [1,2,3]
31973        */
31974        this.encode = function () {
31975            var self = arguments.length ? arguments[0] : this,
31976                result, tmp;
31977            if (self === null)
31978                result = "null";
31979            else if (self !== undefined && (tmp = $[typeof self](self))) {
31980                switch (tmp) {
31981                    case Array:
31982                        result = [];
31983                        for (var i = 0, j = 0, k = self.length; j < k; j++) {
31984                            if (self[j] !== undefined && (tmp = Agility.JSON.encode(self[j])))
31985                                result[i++] = tmp;
31986                        };
31987                        result = "[".concat(result.join(","), "]");
31988                        break;
31989                    case Boolean:
31990                        result = String(self);
31991                        break;
31992                    case Date:
31993                        result = '"'.concat(self.getFullYear(), '-', d(self.getMonth() + 1), '-', d(self.getDate()), 'T', d(self.getHours()), ':', d(self.getMinutes()), ':', d(self.getSeconds()), '"');
31994                        break;
31995                    case Function:
31996                        break;
31997                    case Number:
31998                        result = isFinite(self) ? String(self) : "null";
31999                        break;
32000                    case String:
32001                        result = '"'.concat(self.replace(rs, s).replace(ru, u), '"');
32002                        break;
32003                    default:
32004                        var i = 0, key;
32005                        result = [];
32006                        for (key in self) {
32007                            if (self[key] !== undefined && (tmp = Agility.JSON.encode(self[key])))
32008                                result[i++] = '"'.concat(key.replace(rs, s).replace(ru, u), '":', tmp);
32009                        };
32010                        result = "{".concat(result.join(","), "}");
32011                        break;
32012                }
32013            };
32014            return result;
32015        };
32016
32017        /*
32018        Method: toDate
32019        transforms a JSON encoded Date string into a native Date object.
32020        
32021        Arguments:
32022        [String/Number] - Optional JSON Date string or server time if this method is not a String prototype. Server time should be an integer, based on seconds since 1970/01/01 or milliseconds / 1000 since 1970/01/01.
32023        
32024        Returns:
32025        Date - Date object or undefined if string is not a valid Date
32026        
32027        Example [Basic]:
32028        >var	serverDate = JSON.toDate("2007-04-05T08:36:46");
32029        >alert(serverDate.getMonth());	// 3 (months start from 0)
32030        
32031        Example [Prototype]:
32032        >String.prototype.parseDate = JSON.toDate;
32033        >
32034        >alert("2007-04-05T08:36:46".parseDate().getDate());	// 5
32035        
32036        Example [Server Time]:
32037        >var	phpServerDate = JSON.toDate(<?php echo time(); ?>);
32038        >var	csServerDate = JSON.toDate(<%=(DateTime.Now.Ticks/10000-62135596800000)%>/1000);
32039        
32040        Example [Server Time Prototype]:
32041        >Number.prototype.parseDate = JSON.toDate;
32042        >var	phpServerDate = (<?php echo time(); ?>).parseDate();
32043        >var	csServerDate = (<%=(DateTime.Now.Ticks/10000-62135596800000)%>/1000).parseDate();
32044        
32045        Note:
32046        This method accepts an integer or numeric string too to mantain compatibility with generic server side time() function.
32047        You can convert quickly mtime, ctime, time and other time based values.
32048        With languages that supports milliseconds you can send total milliseconds / 1000 (time is set as time * 1000)
32049        */
32050        this.toDate = function () {
32051            var self = arguments.length ? arguments[0] : this,
32052                result;
32053            if (rd.test(self)) {
32054                result = new Date;
32055                result.setHours(i(self, 11, 2));
32056                result.setMinutes(i(self, 14, 2));
32057                result.setSeconds(i(self, 17, 2));
32058                result.setMonth(i(self, 5, 2) - 1);
32059                result.setDate(i(self, 8, 2));
32060                result.setFullYear(i(self, 0, 4));
32061            }
32062            else if (rt.test(self))
32063                result = new Date(self * 1000);
32064            return result;
32065        };
32066
32067        /* Section: Properties - Private */
32068
32069        /*
32070        Property: Private
32071        
32072        List:
32073        Object - 'c' - a dictionary with useful keys / values for fast encode convertion
32074        Function - 'd' - returns decimal string rappresentation of a number ("14", "03", etc)
32075        Function - 'e' - safe and native code evaulation
32076        Function - 'i' - returns integer from string ("01" => 1, "15" => 15, etc)
32077        Array - 'p' - a list with different "0" strings for fast special chars escape convertion
32078        RegExp - 'rc' - regular expression to check JSON strings (different for IE5 or old browsers and new one)
32079        RegExp - 'rd' - regular expression to check a JSON Date string
32080        RegExp - 'rs' - regular expression to check string chars to modify using c (char) values
32081        RegExp - 'rt' - regular expression to check integer numeric string (for toDate time version evaluation)
32082        RegExp - 'ru' - regular expression to check string chars to escape using "\u" prefix
32083        Function - 's' - returns escaped string adding "\\" char as prefix ("\\" => "\\\\", etc.)
32084        Function - 'u' - returns escaped string, modifyng special chars using "\uNNNN" notation
32085        Function - 'v' - returns boolean value to skip object methods or prototyped parameters (length, others), used for optional decode filter function
32086        Function - '$' - returns object constructor if it was not cracked (someVar = {}; someVar.constructor = String <= ignore them)
32087        Function - '$$' - returns boolean value to check native Array and Object constructors before convertion
32088        */
32089        var c = { "\b": "b", "\t": "t", "\n": "n", "\f": "f", "\r": "r", '"': '"', "\\": "\\", "/": "/" },
32090            d = function (n) { return n < 10 ? "0".concat(n) : n },
32091            e = function (c, f, e) { e = eval; delete eval; if (typeof eval === "undefined") eval = e; f = eval("" + c); eval = e; return f },
32092            i = function (e, p, l) { return 1 * e.substr(p, l) },
32093            p = ["", "000", "00", "0", ""],
32094            rc = null,
32095            rd = /^[0-9]{4}\-[0-9]{2}\-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}$/,
32096            rs = /(\x5c|\x2F|\x22|[\x0c-\x0d]|[\x08-\x0a])/g,
32097            rt = /^([0-9]+|[0-9]+[,\.][0-9]{1,3})$/,
32098            ru = /([\x00-\x07]|\x0b|[\x0e-\x1f])/g,
32099            s = function (i, d) { return "\\".concat(c[d]) },
32100            u = function (i, d) {
32101                var n = d.charCodeAt(0).toString(16);
32102                return "\\u".concat(p[n.length], n)
32103            },
32104            v = function (k, v) { return $[typeof result](result) !== Function && (v.hasOwnProperty ? v.hasOwnProperty(k) : v.constructor.prototype[k] !== v[k]) },
32105            $ = {
32106                "boolean": function () { return Boolean },
32107                "function": function () { return Function },
32108                "number": function () { return Number },
32109                "object": function (o) { return o instanceof o.constructor ? o.constructor : null },
32110                "string": function () { return String },
32111                "undefined": function () { return null }
32112            },
32113            $$ = function (m) {
32114                function $(c, t) { t = c[m]; delete c[m]; try { e(c) } catch (z) { c[m] = t; return 1 } };
32115                return $(Array) && $(Object)
32116            };
32117        try { rc = new RegExp('^("(\\\\.|[^"\\\\\\n\\r])*?"|[,:{}\\[\\]0-9.\\-+Eaeflnr-u \\n\\r\\t])+?$') }
32118        catch (z) { rc = /^(true|false|null|\[.*\]|\{.*\}|".*"|\d+|\d+\.\d+)$/ }
32119    };
32120	
32121
32122})(Agility);
32123
32124
32125//include datejs here
32126var tryParseDate = Date.parse;
32127Date.CultureInfo={name:"en-US",englishName:"English (United States)",nativeName:"English (United States)",dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Frid
32127ay","Saturday"],abbreviatedDayNames:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],shortestDayNames:["Su","Mo","Tu","We","Th","Fr","Sa"],firstLetterDayNames:["S","M","T","W","T","F","S"],monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],abbreviatedMonthNames:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],amDesignator:"AM",pmDesignator:"PM",firstDayOfWeek:0,twoDigitYearMax:2029,dateElementOrder:"mdy",formatPatterns:{shortDate:"M/d/yyyy",longDate:"dddd, MMMM dd, yyyy",shortTime:"h:mm tt",longTime:"h:mm:ss tt",fullDateTime:"dddd, MMMM dd, yyyy h:mm:ss tt",sortableDateTime:"yyyy-MM-ddTHH:mm:ss",universalSortableDateTime:"yyyy-MM-dd HH:mm:ssZ",rfc1123:"ddd, dd MMM yyyy HH:mm:ss GMT",monthDay:"MMMM dd",yearMonth:"MMMM, yyyy"},regexPatterns:{jan:/^jan(uary)?/i,feb:/^feb(ruary)?/i,mar:/^mar(ch)?/i,apr:/^apr(il)?/i,may:/^may/i,jun:/^jun(e)?/i,jul:/^jul(y)?/i,aug:/^aug(ust)?/i,sep:/^sep(t(ember)?)?/i,oct:/^oct(ober)?/i,nov:/^nov(ember)?/i,dec:/^dec(ember)?/i,sun:/^su(n(day)?)?/i,mon:/^mo(n(day)?)?/i,tue:/^tu(e(s(day)?)?)?/i,wed:/^we(d(nesday)?)?/i,thu:/^th(u(r(s(day)?)?)?)?/i,fri:/^fr(i(day)?)?/i,sat:/^sa(t(urday)?)?/i,future:/^next/i,past:/^last|past|prev(ious)?/i,add:/^(\+|aft(er)?|from|hence)/i,subtract:/^(\-|bef(ore)?|ago)/i,yesterday:/^yes(terday)?/i,today:/^t(od(ay)?)?/i,tomorrow:/^tom(orrow)?/i,now:/^n(ow)?/i,millisecond:/^ms|milli(second)?s?/i,second:/^sec(ond)?s?/i,minute:/^mn|min(ute)?s?/i,hour:/^h(our)?s?/i,week:/^w(eek)?s?/i,month:/^m(onth)?s?/i,day:/^d(ay)?s?/i,year:/^y(ear)?s?/i,shortMeridian:/^(a|p)/i,longMeridian:/^(a\.?m?\.?|p\.?m?\.?)/i,timezone:/^((e(s|d)t|c(s|d)t|m(s|d)t|p(s|d)t)|((gmt)?\s*(\+|\-)\s*\d\d\d\d?)|gmt|utc)/i,ordinalSuffix:/^\s*(st|nd|rd|th)/i,timeContext:/^\s*(\:|a(?!u|p)|p)/i},timezones:[{name:"UTC",offset:"-000"},{name:"GMT",offset:"-000"},{name:"EST",offset:"-0500"},{name:"EDT",offset:"-0400"},{name:"CST",offset:"-0600"},{name:"CDT",offset:"-0500"},{name:"MST",offset:"-0700"},{name:"MDT",offset:"-0600"},{name:"PST",offset:"-0800"},{name:"PDT",offset:"-0700"}]};(function(){var $D=Date,$P=$D.prototype,$C=$D.CultureInfo,p=function(s,l){if(!l){l=2;}return("000"+s).slice(l*-1);};$P.clearTime=function(){this.setHours(0);this.setMinutes(0);this.setSeconds(0);this.setMilliseconds(0);return this;};$P.setTimeToNow=function(){var n=new Date();this.setHours(n.getHours());this.setMinutes(n.getMinutes());this.setSeconds(n.getSeconds());this.setMilliseconds(n.getMilliseconds());return this;};$D.today=function(){return new Date().clearTime();};$D.compare=function(date1,date2){if(isNaN(date1)||isNaN(date2)){throw new Error(date1+" - "+date2);}else{if(date1 instanceof Date&&date2 instanceof Date){return(date1<date2)?-1:(date1>date2)?1:0;}else{throw new TypeError(date1+" - "+date2);}}};$D.equals=function(date1,date2){return(date1.compareTo(date2)===0);};$D.getDayNumberFromName=function(name){var n=$C.dayNames,m=$C.abbreviatedDayNames,o=$C.shortestDayNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s||o[i].toLowerCase()==s){return i;}}return -1;};$D.getMonthNumberFromName=function(name){var n=$C.monthNames,m=$C.abbreviatedMonthNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}}return -1;};$D.isLeapYear=function(year){return((year%4===0&&year%100!==0)||year%400===0);};$D.getDaysInMonth=function(year,month){return[31,($D.isLeapYear(year)?29:28),31,30,31,30,31,31,30,31,30,31][month];};$D.getTimezoneAbbreviation=function(offset){var z=$C.timezones,p;for(var i=0;i<z.length;i++){if(z[i].offset===offset){return z[i].name;}}return null;};$D.getTimezoneOffset=function(name){var z=$C.timezones,p;for(var i=0;i<z.length;i++){if(z[i].name===name.toUpperCase()){return z[i].offset;}}return null;};$P.clone=function(){return new Date(this.getTime());};$P.compareTo=function(date){return Date.compare(this,date);};$P.equals=function(date){return Date.equals(this,date||new Date());};$P.between=function(start,end){return this.getTime()>=start.getTime()&&this.getTime()<=end.getTime();};$P.isAfter=function(date){return this.compareTo(date||new Date())===1;};$P.isBefore=function(date){return(this.compareTo(date||new Date())===-1);};$P.isToday=$P.isSameDay=function(date){return this.clone().clearTime().equals((date||new Date()).clone().clearTime());};$P.addMilliseconds=function(value){this.setMilliseconds(this.getMilliseconds()+value*1);return this;};$P.addSeconds=function(value){return this.addMilliseconds(value*1000);};$P.addMinutes=function(value){return this.addMilliseconds(value*60000);};$P.addHours=function(value){return this.addMilliseconds(value*3600000);};$P.addDays=function(value){this.setDate(this.getDate()+value*1);return this;};$P.addWeeks=function(value){return this.addDays(value*7);};$P.addMonths=function(value){var n=this.getDate();this.setDate(1);this.setMonth(this.getMonth()+value*1);this.setDate(Math.min(n,$D.getDaysInMonth(this.getFullYear(),this.getMonth())));return this;};$P.addYears=function(value){return this.addMonths(value*12);};$P.add=function(config){if(typeof config=="number"){this._orient=config;return this;}var x=config;if(x.milliseconds){this.addMilliseconds(x.milliseconds);}if(x.seconds){this.addSeconds(x.seconds);}if(x.minutes){this.addMinutes(x.minutes);}if(x.hours){this.addHours(x.hours);}if(x.weeks){this.addWeeks(x.weeks);}if(x.months){this.addMonths(x.months);}if(x.years){this.addYears(x.years);}if(x.days){this.addDays(x.days);}return this;};var $y,$m,$d;$P.getWeek=function(){var a,b,c,d,e,f,g,n,s,w;$y=(!$y)?this.getFullYear():$y;$m=(!$m)?this.getMonth()+1:$m;$d=(!$d)?this.getDate():$d;if($m<=2){a=$y-1;b=(a/4|0)-(a/100|0)+(a/400|0);c=((a-1)/4|0)-((a-1)/100|0)+((a-1)/400|0);s=b-c;e=0;f=$d-1+(31*($m-1));}else{a=$y;b=(a/4|0)-(a/100|0)+(a/400|0);c=((a-1)/4|0)-((a-1)/100|0)+((a-1)/400|0);s=b-c;e=s+1;f=$d+((153*($m-3)+2)/5)+58+s;}g=(a+b)%7;d=(f+g-e)%7;n=(f+3-d)|0;if(n<0){w=53-((g-s)/5|0);}else{if(n>364+s){w=1;}else{w=(n/7|0)+1;}}$y=$m=$d=null;return w;};$P.getISOWeek=function(){$y=this.getUTCFullYear();$m=this.getUTCMonth()+1;$d=this.getUTCDate();return p(this.getWeek());};
32127$P.setWeek=function(n){return this.moveToDayOfWeek(1).addWeeks(n-this.getWeek());};var validate=function(n,min,max,name){if(typeof n=="undefined"){return false;}else{if(typeof n!="number"){throw new TypeError(n+" is not a Number.");}else{if(n<min||n>max){throw new RangeError(n+" is not a valid value for "+name+".");}}}return true;};$D.validateMillisecond=function(value){return validate(value,0,999,"millisecond");};$D.validateSecond=function(value){return validate(value,0,59,"second");};$D.validateMinute=function(value){return validate(value,0,59,"minute");};$D.validateHour=function(value){return validate(value,0,23,"hour");};$D.validateDay=function(value,year,month){return validate(value,1,$D.getDaysInMonth(year,month),"day");};$D.validateMonth=function(value){return validate(value,0,11,"month");};$D.validateYear=function(value){return validate(value,0,9999,"year");};$P.set=function(config){if($D.validateMillisecond(config.millisecond)){this.addMilliseconds(config.millisecond-this.getMilliseconds());}if($D.validateSecond(config.second)){this.addSeconds(config.second-this.getSeconds());}if($D.validateMinute(config.minute)){this.addMinutes(config.minute-this.getMinutes());}if($D.validateHour(config.hour)){this.addHours(config.hour-this.getHours());}if($D.validateMonth(config.month)){this.addMonths(config.month-this.getMonth());}if($D.validateYear(config.year)){this.addYears(config.year-this.getFullYear());}if($D.validateDay(config.day,this.getFullYear(),this.getMonth())){this.addDays(config.day-this.getDate());}if(config.timezone){this.setTimezone(config.timezone);}if(config.timezoneOffset){this.setTimezoneOffset(config.timezoneOffset);}if(config.week&&validate(config.week,0,53,"week")){this.setWeek(config.week);}return this;};$P.moveToFirstDayOfMonth=function(){return this.set({day:1});};$P.moveToLastDayOfMonth=function(){return this.set({day:$D.getDaysInMonth(this.getFullYear(),this.getMonth())});};$P.moveToNthOccurrence=function(dayOfWeek,occurrence){var shift=0;if(occurrence>0){shift=occurrence-1;}else{if(occurrence===-1){this.moveToLastDayOfMonth();if(this.getDay()!==dayOfWeek){this.moveToDayOfWeek(dayOfWeek,-1);}return this;}}return this.moveToFirstDayOfMonth().addDays(-1).moveToDayOfWeek(dayOfWeek,+1).addWeeks(shift);};$P.moveToDayOfWeek=function(dayOfWeek,orient){var diff=(dayOfWeek-this.getDay()+7*(orient||+1))%7;return this.addDays((diff===0)?diff+=7*(orient||+1):diff);};$P.moveToMonth=function(month,orient){var diff=(month-this.getMonth()+12*(orient||+1))%12;return this.addMonths((diff===0)?diff+=12*(orient||+1):diff);};$P.getOrdinalNumber=function(){return Math.ceil((this.clone().clearTime()-new Date(this.getFullYear(),0,1))/86400000)+1;};$P.getTimezone=function(){return $D.getTimezoneAbbreviation(this.getUTCOffset());};$P.setTimezoneOffset=function(offset){var here=this.getTimezoneOffset(),there=Number(offset)*-6/10;return this.addMinutes(there-here);};$P.setTimezone=function(offset){return this.setTimezoneOffset($D.getTimezoneOffset(offset));};$P.hasDaylightSavingTime=function(){return(Date.today().set({month:0,day:1}).getTimezoneOffset()!==Date.today().set({month:6,day:1}).getTimezoneOffset());};$P.isDaylightSavingTime=function(){return Date.today().set({month:0,day:1}).getTimezoneOffset()!=this.getTimezoneOffset();};$P.getUTCOffset=function(){var n=this.getTimezoneOffset()*-10/6,r;if(n<0){r=(n-10000).toString();return r.charAt(0)+r.substr(2);}else{r=(n+10000).toString();return"+"+r.substr(1);}};$P.getElapsed=function(date){return(date||new Date())-this;};if(!$P.toISOString){$P.toISOString=function(){function f(n){return n<10?"0"+n:n;}return'"'+this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+'Z"';};}$P._toString=$P.toString;$P.toString=function(format){var x=this;if(format&&format.length==1){var c=$C.formatPatterns;x.t=x.toString;switch(format){case"d":return x.t(c.shortDate);case"D":return x.t(c.longDate);case"F":return x.t(c.fullDateTime);case"m":return x.t(c.monthDay);case"r":return x.t(c.rfc1123);case"s":return x.t(c.sortableDateTime);case"t":return x.t(c.shortTime);case"T":return x.t(c.longTime);case"u":return x.t(c.universalSortableDateTime);case"y":return x.t(c.yearMonth);}}var ord=function(n){switch(n*1){case 1:case 21:case 31:return"st";case 2:case 22:return"nd";case 3:case 23:return"rd";default:return"th";}};return format?format.replace(/(\\)?(dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|S)/g,function(m){if(m.charAt(0)==="\\"){return m.replace("\\","");}x.h=x.getHours;switch(m){case"hh":return p(x.h()<13?(x.h()===0?12:x.h()):(x.h()-12));case"h":return x.h()<13?(x.h()===0?12:x.h()):(x.h()-12);case"HH":return p(x.h());case"H":return x.h();case"mm":return p(x.getMinutes());case"m":return x.getMinutes();case"ss":return p(x.getSeconds());
32127case"s":return x.getSeconds();case"yyyy":return p(x.getFullYear(),4);case"yy":return p(x.getFullYear());case"dddd":return $C.dayNames[x.getDay()];case"ddd":return $C.abbreviatedDayNames[x.getDay()];case"dd":return p(x.getDate());case"d":return x.getDate();case"MMMM":return $C.monthNames[x.getMonth()];case"MMM":return $C.abbreviatedMonthNames[x.getMonth()];case"MM":return p((x.getMonth()+1));case"M":return x.getMonth()+1;case"t":return x.h()<12?$C.amDesignator.substring(0,1):$C.pmDesignator.substring(0,1);case"tt":return x.h()<12?$C.amDesignator:$C.pmDesignator;case"S":return ord(x.getDate());default:return m;}}):this._toString();};}());(function(){Date.Parsing={Exception:function(s){this.message="Parse error at '"+s.substring(0,10)+" ...'";}};var $P=Date.Parsing;var _=$P.Operators={rtoken:function(r){return function(s){var mx=s.match(r);if(mx){return([mx[0],s.substring(mx[0].length)]);}else{throw new $P.Exception(s);}};},token:function(s){return function(s){return _.rtoken(new RegExp("^s*"+s+"s*"))(s);};},stoken:function(s){return _.rtoken(new RegExp("^"+s));},until:function(p){return function(s){var qx=[],rx=null;while(s.length){try{rx=p.call(this,s);}catch(e){qx.push(rx[0]);s=rx[1];continue;}break;}return[qx,s];};},many:function(p){return function(s){var rx=[],r=null;while(s.length){try{r=p.call(this,s);}catch(e){return[rx,s];}rx.push(r[0]);s=r[1];}return[rx,s];};},optional:function(p){return function(s){var r=null;try{r=p.call(this,s);}catch(e){return[null,s];}return[r[0],r[1]];};},not:function(p){return function(s){try{p.call(this,s);}catch(e){return[null,s];}throw new $P.Exception(s);};},ignore:function(p){return p?function(s){var r=null;r=p.call(this,s);return[null,r[1]];}:null;},product:function(){var px=arguments[0],qx=Array.prototype.slice.call(arguments,1),rx=[];for(var i=0;i<px.length;i++){rx.push(_.each(px[i],qx));}return rx;},cache:function(rule){var cache={},r=null;return function(s){try{r=cache[s]=(cache[s]||rule.call(this,s));}catch(e){r=cache[s]=e;}if(r instanceof $P.Exception){throw r;}else{return r;}};},any:function(){var px=arguments;return function(s){var r=null;for(var i=0;i<px.length;i++){if(px[i]==null){continue;}try{r=(px[i].call(this,s));}catch(e){r=null;}if(r){return r;}}throw new $P.Exception(s);};},each:function(){var px=arguments;return function(s){var rx=[],r=null;for(var i=0;i<px.length;i++){if(px[i]==null){continue;}try{r=(px[i].call(this,s));}catch(e){throw new $P.Exception(s);}rx.push(r[0]);s=r[1];}return[rx,s];};},all:function(){var px=arguments,_=_;return _.each(_.optional(px));},sequence:function(px,d,c){d=d||_.rtoken(/^\s*/);c=c||null;if(px.length==1){return px[0];}return function(s){var r=null,q=null;var rx=[];for(var i=0;i<px.length;i++){try{r=px[i].call(this,s);}catch(e){break;}rx.push(r[0]);try{q=d.call(this,r[1]);}catch(ex){q=null;break;}s=q[1];}if(!r){throw new $P.Exception(s);}if(q){throw new $P.Exception(q[1]);}if(c){try{r=c.call(this,r[1]);}catch(ey){throw new $P.Exception(r[1]);}}return[rx,(r?r[1]:s)];};},between:function(d1,p,d2){d2=d2||d1;var _fn=_.each(_.ignore(d1),p,_.ignore(d2));return function(s){var rx=_fn.call(this,s);return[[rx[0][0],r[0][2]],rx[1]];};},list:function(p,d,c){d=d||_.rtoken(/^\s*/);c=c||null;return(p instanceof Array?_.each(_.product(p.slice(0,-1),_.ignore(d)),p.slice(-1),_.ignore(c)):_.each(_.many(_.each(p,_.ignore(d))),px,_.ignore(c)));},set:function(px,d,c){d=d||_.rtoken(/^\s*/);c=c||null;return function(s){var r=null,p=null,q=null,rx=null,best=[[],s],last=false;for(var i=0;i<px.length;i++){q=null;p=null;r=null;last=(px.length==1);try{r=px[i].call(this,s);}catch(e){continue;}rx=[[r[0]],r[1]];if(r[1].length>0&&!last){try{q=d.call(this,r[1]);}catch(ex){last=true;}}else{last=true;}if(!last&&q[1].length===0){last=true;}if(!last){var qx=[];for(var j=0;j<px.length;j++){if(i!=j){qx.push(px[j]);}}p=_.set(qx,d).call(this,q[1]);if(p[0].length>0){rx[0]=rx[0].concat(p[0]);rx[1]=p[1];}}if(rx[1].length<best[1].length){best=rx;}if(best[1].length===0){break;}}if(best[0].length===0){return best;}if(c){try{q=c.call(this,best[1]);}catch(ey){throw new $P.Exception(best[1]);}best[1]=q[1];}return best;};},forward:function(gr,fname){return function(s){return gr[fname].call(this,s);};},replace:function(rule,repl){return function(s){var r=rule.call(this,s);return[repl,r[1]];};},process:function(rule,fn){return function(s){var r=rule.call(this,s);return[fn.call(this,r[0]),r[1]];};},min:function(min,rule){return function(s){var rx=rule.call(this,s);if(rx[0].length<min){throw new $P.Exception(s);}return rx;};}};var _generator=function(op){return function(){var args=null,rx=[];if(arguments.length>1){args=Array.prototype.slice.call(arguments);}else{if(arguments[0] instanceof Array){args=arguments[0];}}if(args){for(var i=0,px=args.shift();i<px.length;i++){args.unshift(px[i]);rx.push(op.apply(null,args));args.shift();return rx;}}else{return op.apply(null,arguments);}};};var gx="optional not ignore cache".split(/\s/);for(var i=0;i<gx.length;i++){_[gx[i]]=_generator(_[gx[i]]);}var _vector=function(op){return function(){if(arguments[0] instanceof Array){return op.apply(null,arguments[0]);}else{return op.apply(null,arguments);}};};var vx="each any all".split(/\s/);for(var j=0;j<vx.length;j++){_[vx[j]]=_vector(_[vx[j]]);}}());(function(){var $D=Date,$P=$D.prototype,$C=$D.CultureInfo;var flattenAndCompact=function(ax){var rx=[];for(var i=0;i<ax.length;i++){if(ax[i] instanceof Array){rx=rx.concat(flattenAndCompact(ax[i])
32127);}else{if(ax[i]){rx.push(ax[i]);}}}return rx;};$D.Grammar={};$D.Translator={hour:function(s){return function(){this.hour=Number(s);};},minute:function(s){return function(){this.minute=Number(s);};},second:function(s){return function(){this.second=Number(s);};},meridian:function(s){return function(){this.meridian=s.slice(0,1).toLowerCase();};},timezone:function(s){return function(){var n=s.replace(/[^\d\+\-]/g,"");if(n.length){this.timezoneOffset=Number(n);}else{this.timezone=s.toLowerCase();}};},day:function(x){var s=x[0];return function(){this.day=Number(s.match(/\d+/)[0]);};},month:function(s){return function(){this.month=(s.length==3)?"jan feb mar apr may jun jul aug sep oct nov dec".indexOf(s)/4:Number(s)-1;};},year:function(s){return function(){var n=Number(s);this.year=((s.length>2)?n:(n+(((n+2000)<$C.twoDigitYearMax)?2000:1900)));};},rday:function(s){return function(){switch(s){case"yesterday":this.days=-1;break;case"tomorrow":this.days=1;break;case"today":this.days=0;break;case"now":this.days=0;this.now=true;break;}};},finishExact:function(x){x=(x instanceof Array)?x:[x];for(var i=0;i<x.length;i++){if(x[i]){x[i].call(this);}}var now=new Date();if((this.hour||this.minute)&&(!this.month&&!this.year&&!this.day)){this.day=now.getDate();}if(!this.year){this.year=now.getFullYear();}if(!this.month&&this.month!==0){this.month=now.getMonth();}if(!this.day){this.day=1;}if(!this.hour){this.hour=0;}if(!this.minute){this.minute=0;}if(!this.second){this.second=0;}if(this.meridian&&this.hour){if(this.meridian=="p"&&this.hour<12){this.hour=this.hour+12;}else{if(this.meridian=="a"&&this.hour==12){this.hour=0;}}}if(this.day>$D.getDaysInMonth(this.year,this.month)){throw new RangeError(this.day+" is not a valid value for days.");}var r=new Date(this.year,this.month,this.day,this.hour,this.minute,this.second);if(this.timezone){r.set({timezone:this.timezone});}else{if(this.timezoneOffset){r.set({timezoneOffset:this.timezoneOffset});}}return r;},finish:function(x){x=(x instanceof Array)?flattenAndCompact(x):[x];if(x.length===0){return null;}for(var i=0;i<x.length;i++){if(typeof x[i]=="function"){x[i].call(this);}}var today=$D.today();if(this.now&&!this.unit&&!this.operator){return new Date();}else{if(this.now){today=new Date();}}var expression=!!(this.days&&this.days!==null||this.orient||this.operator);var gap,mod,orient;orient=((this.orient=="past"||this.operator=="subtract")?-1:1);if(!this.now&&"hour minute second".indexOf(this.unit)!=-1){today.setTimeToNow();}if(this.month||this.month===0){if("year day hour minute second".indexOf(this.unit)!=-1){this.value=this.month+1;this.month=null;expression=true;}}if(!expression&&this.weekday&&!this.day&&!this.days){var temp=Date[this.weekday]();this.day=temp.getDate();if(!this.month){this.month=temp.getMonth();}this.year=temp.getFullYear();}if(expression&&this.weekday&&this.unit!="month"){this.unit="day";gap=($D.getDayNumberFromName(this.weekday)-today.getDay());mod=7;this.days=gap?((gap+(orient*mod))%mod):(orient*mod);}if(this.month&&this.unit=="day"&&this.operator){this.value=(this.month+1);this.month=null;}if(this.value!=null&&this.month!=null&&this.year!=null){this.day=this.value*1;}if(this.month&&!this.day&&this.value){today.set({day:this.value*1});if(!expression){this.day=this.value*1;}}if(!this.month&&this.value&&this.unit=="month"&&!this.now){this.month=this.value;expression=true;}if(expression&&(this.month||this.month===0)&&this.unit!="year"){this.unit="month";gap=(this.month-today.getMonth());mod=12;this.months=gap?((gap+(orient*mod))%mod):(orient*mod);this.month=null;}if(!this.unit){this.unit="day";}if(!this.value&&this.operator&&this.operator!==null&&this[this.unit+"s"]&&this[this.unit+"s"]!==null){this[this.unit+"s"]=this[this.unit+"s"]+((this.operator=="add")?1:-1)+(this.value||0)*orient;}else{if(this[this.unit+"s"]==null||this.operator!=null){if(!this.value){this.value=1;}this[this.unit+"s"]=this.value*orient;}}if(this.meridian&&this.hour){if(this.meridian=="p"&&this.hour<12){this.hour=this.hour+12;}else{if(this.meridian=="a"&&this.hour==12){this.hour=0;}}}if(this.weekday&&!this.day&&!this.days){var temp=Date[this.weekday]();this.day=temp.getDate();if(temp.getMonth()!==today.getMonth()){this.month=temp.getMonth();}}if((this.month||this.month===0)&&!this.day){this.day=1;}if(!this.orient&&!this.operator&&this.unit=="week"&&this.value&&!this.day&&!this.month){return Date.today().setWeek(this.value);}if(expression&&this.timezone&&this.day&&this.days){this.day=this.days;}return(expression)?today.add(this):today.set(this);}};var _=$D.Parsing.Operators,g=$D.Grammar,t=$D.Translator,_fn;g.datePartDelimiter=_.rtoken(/^([\s\-\.\,\/\x27]+)/);g.timePartDelimiter=_.stoken(":");g.whiteSpace=_.rtoken(/^\s*/);g.generalDelimiter=_.rtoken(/^(([\s\,]|at|@|on)+)/);var _C={};g.ctoken=function(keys){var fn=_C[keys];if(!fn){var c=$C.regexPatterns;var kx=keys.split(/\s+/),px=[];for(var i=0;i<kx.length;
32127i++){px.push(_.replace(_.rtoken(c[kx[i]]),kx[i]));}fn=_C[keys]=_.any.apply(null,px);}return fn;};g.ctoken2=function(key){return _.rtoken($C.regexPatterns[key]);};g.h=_.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2]|[1-9])/),t.hour));g.hh=_.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2])/),t.hour));g.H=_.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3]|[0-9])/),t.hour));g.HH=_.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3])/),t.hour));g.m=_.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/),t.minute));g.mm=_.cache(_.process(_.rtoken(/^[0-5][0-9]/),t.minute));g.s=_.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/),t.second));g.ss=_.cache(_.process(_.rtoken(/^[0-5][0-9]/),t.second));g.hms=_.cache(_.sequence([g.H,g.m,g.s],g.timePartDelimiter));g.t=_.cache(_.process(g.ctoken2("shortMeridian"),t.meridian));g.tt=_.cache(_.process(g.ctoken2("longMeridian"),t.meridian));g.z=_.cache(_.process(_.rtoken(/^((\+|\-)\s*\d\d\d\d)|((\+|\-)\d\d\:?\d\d)/),t.timezone));g.zz=_.cache(_.process(_.rtoken(/^((\+|\-)\s*\d\d\d\d)|((\+|\-)\d\d\:?\d\d)/),t.timezone));g.zzz=_.cache(_.process(g.ctoken2("timezone"),t.timezone));g.timeSuffix=_.each(_.ignore(g.whiteSpace),_.set([g.tt,g.zzz]));g.time=_.each(_.optional(_.ignore(_.stoken("T"))),g.hms,g.timeSuffix);g.d=_.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1]|\d)/),_.optional(g.ctoken2("ordinalSuffix"))),t.day));g.dd=_.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1])/),_.optional(g.ctoken2("ordinalSuffix"))),t.day));g.ddd=g.dddd=_.cache(_.process(g.ctoken("sun mon tue wed thu fri sat"),function(s){return function(){this.weekday=s;};}));g.M=_.cache(_.process(_.rtoken(/^(1[0-2]|0\d|\d)/),t.month));g.MM=_.cache(_.process(_.rtoken(/^(1[0-2]|0\d)/),t.month));g.MMM=g.MMMM=_.cache(_.process(g.ctoken("jan feb mar apr may jun jul aug sep oct nov dec"),t.month));g.y=_.cache(_.process(_.rtoken(/^(\d\d?)/),t.year));g.yy=_.cache(_.process(_.rtoken(/^(\d\d)/),t.year));g.yyy=_.cache(_.process(_.rtoken(/^(\d\d?\d?\d?)/),t.year));g.yyyy=_.cache(_.process(_.rtoken(/^(\d\d\d\d)/),t.year));_fn=function(){return _.each(_.any.apply(null,arguments),_.not(g.ctoken2("timeContext")));};g.day=_fn(g.d,g.dd);g.month=_fn(g.M,g.MMM);g.year=_fn(g.yyyy,g.yy);g.orientation=_.process(g.ctoken("past future"),function(s){return function(){this.orient=s;};});g.operator=_.process(g.ctoken("add subtract"),function(s){return function(){this.operator=s;};});g.rday=_.process(g.ctoken("yesterday tomorrow today now"),t.rday);g.unit=_.process(g.ctoken("second minute hour day week month year"),function(s){return function(){this.unit=s;};});g.value=_.process(_.rtoken(/^\d\d?(st|nd|rd|th)?/),function(s){return function(){this.value=s.replace(/\D/g,"");};});g.expression=_.set([g.rday,g.operator,g.value,g.unit,g.orientation,g.ddd,g.MMM]);_fn=function(){return _.set(arguments,g.datePartDelimiter);};g.mdy=_fn(g.ddd,g.month,g.day,g.year);g.ymd=_fn(g.ddd,g.year,g.month,g.day);g.dmy=_fn(g.ddd,g.day,g.month,g.year);g.date=function(s){return((g[$C.dateElementOrder]||g.mdy).call(this,s));};g.format=_.process(_.many(_.any(_.process(_.rtoken(/^(dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?)/),function(fmt){if(g[fmt]){return g[fmt];}else{throw $D.Parsing.Exception(fmt);}}),_.process(_.rtoken(/^[^dMyhHmstz]+/),function(s){return _.ignore(_.stoken(s));}))),function(rules){return _.process(_.each.apply(null,rules),t.finishExact);});var _F={};var _get=function(f){return _F[f]=(_F[f]||g.format(f)[0]);};g.formats=function(fx){if(fx instanceof Array){var rx=[];for(var i=0;i<fx.length;i++){rx.push(_get(fx[i]));}return _.any.apply(null,rx);}else{return _get(fx);}};g._formats=g.formats(['"yyyy-MM-ddTHH:mm:ssZ"',"yyyy-MM-ddTHH:mm:ssZ","yyyy-MM-ddTHH:mm:ssz","yyyy-MM-ddTHH:mm:ss","yyyy-MM-ddTHH:mmZ","yyyy-MM-ddTHH:mmz","yyyy-MM-ddTHH:mm","ddd, MMM dd, yyyy H:mm:ss tt","ddd MMM d yyyy HH:mm:ss zzz","MMddyyyy","ddMMyyyy","Mddyyyy","ddMyyyy","Mdyyyy","dMyyyy","yyyy","Mdyy","dMyy","d"]);g._start=_.process(_.set([g.date,g.time,g.expression],g.generalDelimiter,g.whiteSpace),t.finish);g.start=function(s){try{var r=g._formats.call({},s);if(r[1].length===0){return r;}}catch(e){}return g._start.call({},s);};$D._parse=$D.parse;$D.parse=function(s){var r=null;if(!s){return null;}if(s instanceof Date){return s;}try{r=$D.Grammar.start.call({},s.replace(/^\s*(\S*(\s+\S+)*)\s*$/,"$1"));}catch(e){return null;}try { return((r[1].length===0)?r[0]:Date._parse(s)); } catch (er1) {return tryParseDate(s);};};$D.getParseFunction=function(fx){var fn=$D.Grammar.formats(fx);return function(s){var r=null;try{r=fn.call({},s);}catch(e){return null;}return((r[1].length===0)?r[0]:null);};};$D.parseExact=function(s,fx){return $D.getParseFunction(fx)(s);};}());(function(){var $D=Date,$P=$D.prototype,$C=$D.CultureInfo,$N=Number.prototype;$P._orient=+1;$P._nth=null;$P._is=false;$P._same=false;$P._isSecond=false;$N._dateElement="day";$P.next=function(){this._orient=+1;return this;};$D.next=function(){return $D.today().next();};$P.last=$P.prev=$P.previous=function(){this._orient=-1;return this;};
32127$D.last=$D.prev=$D.previous=function(){return $D.today().last();};$P.is=function(){this._is=true;return this;};$P.same=function(){this._same=true;this._isSecond=false;return this;};$P.today=function(){return this.same().day();};$P.weekday=function(){if(this._is){this._is=false;return(!this.is().sat()&&!this.is().sun());}return false;};$P.at=function(time){return(typeof time==="string")?$D.parse(this.toString("d")+" "+time):this.set(time);};$N.fromNow=$N.after=function(date){var c={};c[this._dateElement]=this;return((!date)?new Date():date.clone()).add(c);};$N.ago=$N.before=function(date){var c={};c[this._dateElement]=this*-1;return((!date)?new Date():date.clone()).add(c);};var dx=("sunday monday tuesday wednesday thursday friday saturday").split(/\s/),mx=("january february march april may june july august september october november december").split(/\s/),px=("Millisecond Second Minute Hour Day Week Month Year").split(/\s/),pxf=("Milliseconds Seconds Minutes Hours Date Week Month FullYear").split(/\s/),nth=("final first second third fourth fifth").split(/\s/),de;$P.toObject=function(){var o={};for(var i=0;i<px.length;i++){o[px[i].toLowerCase()]=this["get"+pxf[i]]();}return o;};$D.fromObject=function(config){config.week=null;return Date.today().set(config);};var df=function(n){return function(){if(this._is){this._is=false;return this.getDay()==n;}if(this._nth!==null){if(this._isSecond){this.addSeconds(this._orient*-1);}this._isSecond=false;var ntemp=this._nth;this._nth=null;var temp=this.clone().moveToLastDayOfMonth();this.moveToNthOccurrence(n,ntemp);if(this>temp){throw new RangeError($D.getDayName(n)+" does not occur "+ntemp+" times in the month of "+$D.getMonthName(temp.getMonth())+" "+temp.getFullYear()+".");}return this;}return this.moveToDayOfWeek(n,this._orient);};};var sdf=function(n){return function(){var t=$D.today(),shift=n-t.getDay();if(n===0&&$C.firstDayOfWeek===1&&t.getDay()!==0){shift=shift+7;}return t.addDays(shift);};};for(var i=0;i<dx.length;i++){$D[dx[i].toUpperCase()]=$D[dx[i].toUpperCase().substring(0,3)]=i;$D[dx[i]]=$D[dx[i].substring(0,3)]=sdf(i);$P[dx[i]]=$P[dx[i].substring(0,3)]=df(i);}var mf=function(n){return function(){if(this._is){this._is=false;return this.getMonth()===n;}return this.moveToMonth(n,this._orient);};};var smf=function(n){return function(){return $D.today().set({month:n,day:1});};};for(var j=0;j<mx.length;j++){$D[mx[j].toUpperCase()]=$D[mx[j].toUpperCase().substring(0,3)]=j;$D[mx[j]]=$D[mx[j].substring(0,3)]=smf(j);$P[mx[j]]=$P[mx[j].substring(0,3)]=mf(j);}var ef=function(j){return function(){if(this._isSecond){this._isSecond=false;return this;}if(this._same){this._same=this._is=false;var o1=this.toObject(),o2=(arguments[0]||new Date()).toObject(),v="",k=j.toLowerCase();for(var m=(px.length-1);m>-1;m--){v=px[m].toLowerCase();if(o1[v]!=o2[v]){return false;}if(k==v){break;}}return true;}if(j.substring(j.length-1)!="s"){j+="s";}return this["add"+j](this._orient);};};var nf=function(n){return function(){this._dateElement=n;return this;};};for(var k=0;k<px.length;k++){de=px[k].toLowerCase();$P[de]=$P[de+"s"]=ef(px[k]);$N[de]=$N[de+"s"]=nf(de);}$P._ss=ef("Second");var nthfn=function(n){return function(dayOfWeek){if(this._same){return this._ss(arguments[0]);}if(dayOfWeek||dayOfWeek===0){return this.moveToNthOccurrence(dayOfWeek,n);}this._nth=n;if(n===2&&(dayOfWeek===undefined||dayOfWeek===null)){this._isSecond=true;return this.addSeconds(this._orient);}return this;};};for(var l=0;l<nth.length;l++){$P[nth[l]]=(l===0)?nthfn(-1):nthfn(l);}}());var TimeSpan=function(days,hours,minutes,seconds,milliseconds){var attrs="days hours minutes seconds milliseconds".split(/\s+/);var gFn=function(attr){return function(){return this[attr];};};var sFn=function(attr){return function(val){this[attr]=val;return this;};};for(var i=0;i<attrs.length;i++){var $a=attrs[i],$b=$a.slice(0,1).toUpperCase()+$a.slice(1);TimeSpan.prototype[$a]=0;TimeSpan.prototype["get"+$b]=gFn($a);TimeSpan.prototype["set"+$b]=sFn($a);}if(arguments.length==4){this.setDays(days);this.setHours(hours);this.setMinutes(minutes);this.setSeconds(seconds);}
32127else{if(arguments.length==5){this.setDays(days);this.setHours(hours);this.setMinutes(minutes);this.setSeconds(seconds);this.setMilliseconds(milliseconds);}else{if(arguments.length==1&&typeof days=="number"){var orient=(days<0)?-1:+1;this.setMilliseconds(Math.abs(days));this.setDays(Math.floor(this.getMilliseconds()/86400000)*orient);this.setMilliseconds(this.getMilliseconds()%86400000);this.setHours(Math.floor(this.getMilliseconds()/3600000)*orient);this.setMilliseconds(this.getMilliseconds()%3600000);this.setMinutes(Math.floor(this.getMilliseconds()/60000)*orient);this.setMilliseconds(this.getMilliseconds()%60000);this.setSeconds(Math.floor(this.getMilliseconds()/1000)*orient);this.setMilliseconds(this.getMilliseconds()%1000);this.setMilliseconds(this.getMilliseconds()*orient);}}}this.getTotalMilliseconds=function(){return(this.getDays()*86400000)+(this.getHours()*3600000)+(this.getMinutes()*60000)+(this.getSeconds()*1000);};this.compareTo=function(time){var t1=new Date(1970,1,1,this.getHours(),this.getMinutes(),this.getSeconds()),t2;if(time===null){t2=new Date(1970,1,1,0,0,0);}else{t2=new Date(1970,1,1,time.getHours(),time.getMinutes(),time.getSeconds());}return(t1<t2)?-1:(t1>t2)?1:0;};this.equals=function(time){return(this.compareTo(time)===0);};this.add=function(time){return(time===null)?this:this.addSeconds(time.getTotalMilliseconds()/1000);};this.subtract=function(time){return(time===null)?this:this.addSeconds(-time.getTotalMilliseconds()/1000);};this.addDays=function(n){return new TimeSpan(this.getTotalMilliseconds()+(n*86400000));};this.addHours=function(n){return new TimeSpan(this.getTotalMilliseconds()+(n*3600000));};this.addMinutes=function(n){return new TimeSpan(this.getTotalMilliseconds()+(n*60000));};this.addSeconds=function(n){return new TimeSpan(this.getTotalMilliseconds()+(n*1000));};this.addMilliseconds=function(n){return new TimeSpan(this.getTotalMilliseconds()+n);};this.get12HourHour=function(){return(this.getHours()>12)?this.getHours()-12:(this.getHours()===0)?12:this.getHours();};this.getDesignator=function(){return(this.getHours()<12)?Date.CultureInfo.amDesignator:Date.CultureInfo.pmDesignator;};this.toString=function(format){this._toString=function(){if(this.getDays()!==null&&this.getDays()>0){return this.getDays()+"."+this.getHours()+":"+this.p(this.getMinutes())+":"+this.p(this.getSeconds());}else{return this.getHours()+":"+this.p(this.getMinutes())+":"+this.p(this.getSeconds());}};this.p=function(s){return(s.toString().length<2)?"0"+s:s;};var me=this;return format?format.replace(/dd?|HH?|hh?|mm?|ss?|tt?/g,function(format){switch(format){case"d":return me.getDays();case"dd":return me.p(me.getDays());case"H":return me.getHours();case"HH":return me.p(me.getHours());case"h":return me.get12HourHour();case"hh":return me.p(me.get12HourHour());case"m":return me.getMinutes();case"mm":return me.p(me.getMinutes());case"s":return me.getSeconds();case"ss":return me.p(me.getSeconds());case"t":return((me.getHours()<12)?Date.CultureInfo.amDesignator:Date.CultureInfo.pmDesignator).substring(0,1);case"tt":return(me.getHours()<12)?Date.CultureInfo.amDesignator:Date.CultureInfo.pmDesignator;}}):this._toString();};return this;};Date.prototype.getTimeOfDay=function(){return new TimeSpan(0,this.getHours(),this.getMinutes(),this.getSeconds(),this.getMilliseconds());};var TimePeriod=function(years,months,days,hours,minutes,seconds,milliseconds){var attrs="years months days hours minutes seconds milliseconds".split(/\s+/);var gFn=function(attr){return function(){return this[attr];};};var sFn=function(attr){return function(val){this[attr]=val;return this;};};for(var i=0;i<attrs.length;i++){var $a=attrs[i],$b=$a.slice(0,1).toUpperCase()+$a.slice(1);TimePeriod.prototype[$a]=0;TimePeriod.prototype["get"+$b]=gFn($a);TimePeriod.prototype["set"+$b]=sFn($a);}if(arguments.length==7){this.years=years;this.months=months;this.setDays(days);this.setHours(hours);this.setMinutes(minutes);this.setSeconds(seconds);this.setMilliseconds(milliseconds);}else{if(arguments.length==2&&arguments[0] instanceof Date&&arguments[1] instanceof Date){var d1=years.clone();var d2=months.clone();var temp=d1.clone();var orient=(d1>d2)?-1:+1;this.years=d2.getFullYear()-d1.getFullYear();temp.addYears(this.years);if(orient==+1){if(temp>d2){if(this.years!==0){this.years--;}}}else{if(temp<d2){if(this.years!==0){this.years++;}}}d1.addYears(this.years);if(orient==+1){while(d1<d2&&d1.clone().addDays(Date.getDaysInMonth(d1.getYear(),d1.getMonth()))<d2){d1.addMonths(1);this.months++;}}else{while(d1>d2&&d1.clone().addDays(-d1.getDaysInMonth())>d2){d1.addMonths(-1);this.months--;}}var diff=d2-d1;if(diff!==0){var ts=new TimeSpan(diff);this.setDays(ts.getDays());this.setHours(ts.getHours());this.setMinutes(ts.getMinutes());this.setSeconds(ts.getSeconds());this.setMilliseconds(ts.getMilliseconds());}}}return this;};
32128
32129;
32130/*
32131 *  base64.js
32132 *
32133 *  Licensed under the BSD 3-Clause License.
32134 *    http://opensource.org/licenses/BSD-3-Clause
32135 *
32136 *  References:
32137 *    http://en.wikipedia.org/wiki/Base64
32138 */
32139;(function (global, factory) {
32140    typeof exports === 'object' && typeof module !== 'undefined'
32141        ? module.exports = factory(global)
32142        : typeof define === 'function' && define.amd
32143        ? define(factory) : factory(global)
32144}((
32145    typeof self !== 'undefined' ? self
32146        : typeof window !== 'undefined' ? window
32147        : typeof global !== 'undefined' ? global
32148: this
32149), function(global) {
32150    'use strict';
32151    // existing version for noConflict()
32152    global = global || {};
32153    var _Base64 = global.Base64;
32154    var version = "2.5.2";
32155    // if node.js and NOT React Native, we use Buffer
32156    var buffer;
32157    if (typeof module !== 'undefined' && module.exports) {
32158        try {
32159            buffer = eval("require('buffer').Buffer");
32160        } catch (err) {
32161            buffer = undefined;
32162        }
32163    }
32164    // constants
32165    var b64chars
32166        = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
32166+/';
32167    var b64tab = function(bin) {
32168        var t = {};
32169        for (var i = 0, l = bin.length; i < l; i++) t[bin.charAt(i)] = i;
32170        return t;
32171    }(b64chars);
32172    var fromCharCode = String.fromCharCode;
32173    // encoder stuff
32174    var cb_utob = function(c) {
32175        if (c.length < 2) {
32176            var cc = c.charCodeAt(0);
32177            return cc < 0x80 ? c
32178                : cc < 0x800 ? (fromCharCode(0xc0 | (cc >>> 6))
32179                                + fromCharCode(0x80 | (cc & 0x3f)))
32180                : (fromCharCode(0xe0 | ((cc >>> 12) & 0x0f))
32181                    + fromCharCode(0x80 | ((cc >>>  6) & 0x3f))
32182                    + fromCharCode(0x80 | ( cc         & 0x3f)));
32183        } else {
32184            var cc = 0x10000
32185                + (c.charCodeAt(0) - 0xD800) * 0x400
32186                + (c.charCodeAt(1) - 0xDC00);
32187            return (fromCharCode(0xf0 | ((cc >>> 18) & 0x07))
32188                    + fromCharCode(0x80 | ((cc >>> 12) & 0x3f))
32189                    + fromCharCode(0x80 | ((cc >>>  6) & 0x3f))
32190                    + fromCharCode(0x80 | ( cc         & 0x3f)));
32191        }
32192    };
32193    var re_utob = /[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g;
32194    var utob = function(u) {
32195        return u.replace(re_utob, cb_utob);
32196    };
32197    var cb_encode = function(ccc) {
32198        var padlen = [0, 2, 1][ccc.length % 3],
32199        ord = ccc.charCodeAt(0) << 16
32200            | ((ccc.length > 1 ? ccc.charCodeAt(1) : 0) << 8)
32201            | ((ccc.length > 2 ? ccc.charCodeAt(2) : 0)),
32202        chars = [
32203            b64chars.charAt( ord >>> 18),
32204            b64chars.charAt((ord >>> 12) & 63),
32205            padlen >= 2 ? '=' : b64chars.charAt((ord >>> 6) & 63),
32206            padlen >= 1 ? '=' : b64chars.charAt(ord & 63)
32207        ];
32208        return chars.join('');
32209    };
32210    var btoa = global.btoa ? function(b) {
32211        return global.btoa(b);
32212    } : function(b) {
32213        return b.replace(/[\s\S]{1,3}/g, cb_encode);
32214    };
32215    var _encode = function(u) {
32216        var isUint8Array = Object.prototype.toString.call(u) === '[object Uint8Array]';
32217        return isUint8Array ? u.toString('base64')
32218            : btoa(utob(String(u)));
32219    }
32220    var encode = function(u, urisafe) {
32221        return !urisafe
32222            ? _encode(u)
32223            : _encode(String(u)).replace(/[+\/]/g, function(m0) {
32224                return m0 == '+' ? '-' : '_';
32225            }).replace(/=/g, '');
32226    };
32227    var encodeURI = function(u) { return encode(u, true) };
32228    // decoder stuff
32229    var re_btou = /[\xC0-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF]{2}|[\xF0-\xF7][\x80-\xBF]{3}/g;
32230    var cb_btou = function(cccc) {
32231        switch(cccc.length) {
32232        case 4:
32233            var cp = ((0x07 & cccc.charCodeAt(0)) << 18)
32234                |    ((0x3f & cccc.charCodeAt(1)) << 12)
32235                |    ((0x3f & cccc.charCodeAt(2)) <<  6)
32236                |     (0x3f & cccc.charCodeAt(3)),
32237            offset = cp - 0x10000;
32238            return (fromCharCode((offset  >>> 10) + 0xD800)
32239                    + fromCharCode((offset & 0x3FF) + 0xDC00));
32240        case 3:
32241            return fromCharCode(
32242                ((0x0f & cccc.charCodeAt(0)) << 12)
32243                    | ((0x3f & cccc.charCodeAt(1)) << 6)
32244                    |  (0x3f & cccc.charCodeAt(2))
32245            );
32246        default:
32247            return  fromCharCode(
32248                ((0x1f & cccc.charCodeAt(0)) << 6)
32249                    |  (0x3f & cccc.charCodeAt(1))
32250            );
32251        }
32252    };
32253    var btou = function(b) {
32254        return b.replace(re_btou, cb_btou);
32255    };
32256    var cb_decode = function(cccc) {
32257        var len = cccc.length,
32258        padlen = len % 4,
32259        n = (len > 0 ? b64tab[cccc.charAt(0)] << 18 : 0)
32260            | (len > 1 ? b64tab[cccc.charAt(1)] << 12 : 0)
32261            | (len > 2 ? b64tab[cccc.charAt(2)] <<  6 : 0)
32262            | (len > 3 ? b64tab[cccc.charAt(3)]       : 0),
32263        chars = [
32264            fromCharCode( n >>> 16),
32265            fromCharCode((n >>>  8) & 0xff),
32266            fromCharCode( n         & 0xff)
32267        ];
32268        chars.length -= [0, 0, 2, 1][padlen];
32269        return chars.join('');
32270    };
32271    var _atob = global.atob ? function(a) {
32272        return global.atob(a);
32273    } : function(a){
32274        return a.replace(/\S{1,4}/g, cb_decode);
32275    };
32276    var atob = function(a) {
32277        return _atob(String(a).replace(/[^A-Za-z0-9\+\/]/g, ''));
32278    };
32279    var _decode = buffer ?
32280        buffer.from && Uint8Array && buffer.from !== Uint8Array.from
32281        ? function(a) {
32282            return (a.constructor === buffer.constructor
32283                    ? a : buffer.from(a, 'base64')).toString();
32284        }
32285        : function(a) {
32286            return (a.constructor === buffer.constructor
32287                    ? a : new buffer(a, 'base64')).toString();
32288        }
32289        : function(a) { return btou(_atob(a)) };
32290    var decode = function(a){
32291        return _decode(
32292            String(a).replace(/[-_]/g, function(m0) { return m0 == '-' ? '+' : '/' })
32293                .replace(/[^A-Za-z0-9\+\/]/g, '')
32294        );
32295    };
32296    var noConflict = function() {
32297        var Base64 = global.Base64;
32298        global.Base64 = _Base64;
32299        return Base64;
32300    };
32301    // export Base64
32302    global.Base64 = {
32303        VERSION: version,
32304        atob: atob,
32305        btoa: btoa,
32306        fromBase64: decode,
32307        toBase64: encode,
32308        utob: utob,
32309        encode: encode,
32310        encodeURI: encodeURI,
32311        btou: btou,
32312        decode: decode,
32313        noConflict: noConflict,
32314        __buffer__: buffer
32315    };
32316    // if ES5 is available, make Base64.extendString() available
32317    if (typeof Object.defineProperty === 'function') {
32318        var noEnum = function(v){
32319            return {value:v,enumerable:false,writable:true,configurable:true};
32320        };
32321        global.Base64.extendString = function () {
32322            Object.defineProperty(
32323                String.prototype, 'fromBase64', noEnum(function () {
32324                    return decode(this)
32325                }));
32326            Object.defineProperty(
32327                String.prototype, 'toBase64', noEnum(function (urisafe) {
32328                    return encode(this, urisafe)
32329                }));
32330            Object.defineProperty(
32331                String.prototype, 'toBase64URI', noEnum(function () {
32332                    return encode(this, true)
32333                }));
32334        };
32335    }
32336    //
32337    // export Base64 to the namespace
32338    //
32339    if (global['Meteor']) { // Meteor.js
32340        Base64 = global.Base64;
32341    }
32342    // module.exports and AMD are mutually exclusive.
32343    // module.exports has precedence.
32344    if (typeof module !== 'undefined' && module.exports) {
32345        module.exports.Base64 = global.Base64;
32346    }
32347    else if (typeof define === 'function' && define.amd) {
32348        // AMD. Register as an anonymous module.
32349        define([], function(){ return global.Base64 });
32350    }
32351    // that's it!
32352    return {Base64: global.Base64}
32353}));
32354
32355
32356Agility.RegisterNamespace('Agility.FormBuilder');
32357
32358(function (FormBuilder) {
32359
32360    FormBuilder.Bootstrap = '.agility-form-clearfix{clear: both;}.agility-form{clear: both;}.agility-form .agility-form-row{width:100%;margin-bottom: 5px;}.agility-form .agility-form-col-full,.agility-form .agility-form-col-half,.agility-form .agility-form-col-quarter,.agility-form .agility-form-col-third{position:relative;min-height:1px;padding-left:15px;padding-right:15px;width:100%}@media (min-width:768px){.agility-form .agility-form-col-full,.agility-form .agility-form-col-half,.agility-form .agility-form-col-quarter,.agility-form .agility-form-col-third{float:left}.agility-form .agility-form-col-full{width:100%}.agility-form .agility-form-col-half{width:50%}.agility-form .agility-form-col-third{width:33.33333333%}.agility-form .agility-form-col-quarter{width:25%}}.agility-form label,.agility-form input[type="text"],.agility-form input[type="email"],.agility-form input[type="number"],.agility-form input[type="date"],.agility-form input[type="file"],.agility-form select,.agility-form textarea{line-height:inherit;width:100%;}.agility-form textarea{min-height:150px;}.agility-form label.agility-form-checkbox-label{font-weight:normal;}.agility-form-checkbox-label span{margin-left: 5px;}.agility-form-submit-btn {margin-top: 5px;}';
32361    FormBuilder.Base64 = { encode: function (e) { return Base64.encode(e); }, decode: function (e) { return Base64.decode(e); } }
32362
32363    /// <summary>
32364    /// Gets/Sets HTML markup of the from
32365    /// </summary>
32366    /// <param name="textBlob">Text blob that stores additionaljson and fieldTypes</param>
32367    /// <param name="htmlContainerID">ID of the html element that the form will be injected to</param>
32368    /// <param name="callback" type="Function">The method to callback to. Has 1 parameter which is the html markup.</param>    
32369    FormBuilder.GetHTMLMarkup = function (textBlob, htmlContainerID, currentMode, callback) {
32370        var textBlobObj = JSON.parse(FormBuilder.Base64.decode(textBlob));
32371
32372        if (!window.FormBuilderValues) {
32373            window.FormBuilderValues = {};
32374        }
32375
32376        var values = textBlobObj.values;
32377
32378        window.FormBuilderValues[htmlContainerID] = values;
32379        window.FormBuilderContainerName = textBlobObj.uniqueID;
32380
32381
32382        var contentID = textBlobObj.contentID;
32383        var mode = parseInt(currentMode);
32384        var languageCode = textBlobObj.languageCode;
32385        var recordTypeID = values.RecordTypeID;
32386        var additionalJSON = values.AdditionalJSON;
32387        var fieldTypes = textBlobObj.fieldTypes;
32388        var formSelector = '#' + htmlContainerID + ' form';
32389
32390        var html = '<div><form class="agility-form" data-agility-form-content-id="' + contentID + '">';
32391
32392        //add bootstrap scoped
32393        html += '<style scoped>' + FormBuilder.Bootstrap + '</style>';
32394
32395        //there is additional styling
32396        if (values.ThemeID > 0) {
32397            html += FormBuilder.GetThemeStyleMarkup(values, formSelector);
32398        }
32399
32400        var rows = [];
32401        var currentRow = {
32402            columns: []
32403        };
32404
32405        var currentWidth = 0;
32406
32407        for (var i = 0; i < fieldTypes.length; i++) {
32408            var fieldType = fieldTypes[i];
32409
32410            if (fieldType.DataType === 9999 && fieldType.JSONFields.InlineCodeLanguage !== 'html') {
32411                if (fieldType.JSONFields.InlineCodeLanguage === 'javascript') {
32412                    html += '<script type="text/javascript">' + fieldType.JSONFields.InlineCode + '</script>';
32413                } else {
32414                    //css
32415                    html += '<style scoped>' + fieldType.JSONFields.InlineCode + '</style>';
32416                }
32417            } else {
32418                var width = FormBuilder.GetColumnWidth(fieldType.JSONFields.ColumnWidth);
32419
32420                if (currentWidth + width > 1.0) {
32421                    //clone the current row
32422                    rows.push(JSON.parse(JSON.stringify(currentRow)));
32423                    currentRow.columns = [];
32424                    currentWidth = 0;
32425                }
32426
32427                currentRow.columns.push({ width: fieldType.JSONFields.ColumnWidth, fieldType: fieldType });
32428                currentWidth += width;
32429            }
32430        }
32431
32432        rows.push(currentRow);
32433
32434        for (var i = 0; i < rows.length; i++) {
32435            var row = rows[i];
32436
32437            html += FormBuilder.GetRowMarkup(row.columns, contentID);
32438        }
32439
32440        html += FormBuilder.GetSubmitButtonMarkup(values.SubmitButtonLabel, formSelector, contentID, languageCode, mode, recordTypeID);
32441
32442        html += '<div class="agility-form-clearfix"><div>'
32443        html += '</form></div>';
32444        html += '<div class="agility-form-clearfix"><div>'
32445
32446        //return the html markup
32447        if (callback) {
32448            callback(html);
32449        } else if (htmlContainerID) {
32450            $('#' + htmlContainerID).html(html);
32451        }
32452
32453        if (window.Parsley) {
32454            FormBuilder.ConfigureParsley(formSelector);
32455        } else {
32456            $.getScript("https://media.agilitycms.com/form-builder/parsley.min.js", function () {
32457                FormBuilder.ConfigureParsley(formSelector);
32458            });
32459        }
32460    };
32461
32462    FormBuilder.ConfigureParsley = function (formSelector) {
32463        $(formSelector).parsley({
32464            excluded: 'input[type=button], input[type=submit], input[type=reset], input[type=hidden], .parsley-ignore',
32465        });
32466    };
32467
32468    FormBuilder.GetRowMarkup = function (columns, contentID) {
32469
32470        var html = '<div class="agility-form-row">';
32471
32472        for (var i = 0; i < columns.length; i++) {
32473            var column = columns[i];
32474
32475            if (column.fieldType.DataType === 9999) {
32476                html += '<div class="agility-form-col-full">' + column.fieldType.JSONFields.InlineCode + '</div>';
32477            } else {
32478                html += FormBuilder.GetColumnMarkup(column, contentID);
32479            }
32480        }
32481
32482        html += '<div class="agility-form-clearfix"></div>';
32483        html += '</div>';
32484
32485        return html;
32486    }
32487
32488    FormBuilder.GetThemeStyleMarkup = function (values, formSelector) {
32489        var html = "<style scoped>";
32490
32491        //form
32492        html += formSelector + '{'
32493            + FormBuilder.GetCSSRule('font-family', values.FormFontFamily)
32494            + FormBuilder.GetCSSRule('background-color', values.FormBackgroun
32494dColor)
32495            + FormBuilder.GetCSSRule('padding', values.FormPadding)
32496            + FormBuilder.GetCSSRule('margin', values.FormMargin)
32497            + FormBuilder.GetCSSRule('border', values.FormBorder)
32498            + '}';
32499
32500        //input
32501        html += formSelector + ' input:not([type=checkbox]), '
32502            + formSelector + ' select, '
32503            + formSelector + ' textarea '
32504            + '{'
32505            + FormBuilder.GetCSSRule('background-color', values.InputBackgroundColor)
32506            + FormBuilder.GetCSSRule('font-size', values.InputFontSize)
32507            + FormBuilder.GetCSSRule('color', values.InputFontColor)
32508            + FormBuilder.GetCSSRule('height', values.InputHeight)
32509            + FormBuilder.GetCSSRule('margin-top', values.InputMarginTop)
32510            + FormBuilder.GetCSSRule('margin-bottom', values.InputMarginBottom)
32511            + FormBuilder.GetCSSRule('outline', values.InputOutline)
32512            + FormBuilder.GetCSSRule('border', values.InputBorder)
32513            + FormBuilder.GetCSSRule('border-radius', values.InputBorderRadius)
32514            + FormBuilder.GetCSSRule('padding', values.InputPadding)
32515            + '}';
32516
32517        html += formSelector + ' input:not([type=checkbox]):focus, '
32518            + formSelector + ' select:focus,'
32519            + formSelector + ' textarea:focus'
32520            + '{'
32521            + FormBuilder.GetCSSRule('border', values.InputFocusedBorder)
32522            + '}';
32523
32524        //label
32525        html += formSelector + ' label{'
32526            + FormBuilder.GetCSSRule('font-size', values.LabelFontSize)
32527            + FormBuilder.GetCSSRule('color', values.LabelFontColor)
32528            + FormBuilder.GetCSSRule('font-weight', values.LabelFontWeight)
32529            + FormBuilder.GetCSSRule('margin', values.LabelMargin)
32530            + FormBuilder.GetCSSRule('padding', values.LabelPadding)
32531            + '}';
32532
32533        //button
32534        html += formSelector + ' button{'
32535            + FormBuilder.GetCSSRule('background-color', values.ButtonBackgroundColor)
32536            + FormBuilder.GetCSSRule('color', values.ButtonFontColor)
32537            + FormBuilder.GetCSSRule('font-size', values.ButtonFontSize)
32538            + FormBuilder.GetCSSRule('font-weight', values.ButtonFontWeight)
32539            + FormBuilder.GetCSSRule('height', values.ButtonHeight)
32540            + FormBuilder.GetCSSRule('width', values.ButtonWidth)
32541            + FormBuilder.GetCSSRule('margin', values.ButtonMargin)
32542            + FormBuilder.GetCSSRule('padding', values.ButtonPadding)
32543            + FormBuilder.GetCSSRule('border', values.ButtonBorder)
32544            + FormBuilder.GetCSSRule('border-radius', values.ButtonBorderRadius)
32545            + '}';
32546
32547        html += "</style>";
32548
32549        return html;
32550    };
32551
32552    FormBuilder.GetCSSRule = function (rule, value) {
32553        return rule + ':' + value + ';';
32554    };
32555
32556    FormBuilder.GetColumnMarkup = function (column, contentID) {
32557        var className = FormBuilder.GetBootsrapColumnClassName(column.width);
32558        var html = '<div class="' + className + '">'
32559
32560        html += FormBuilder.GetFieldTypeMarkup(column.fieldType, contentID);
32561
32562        html += '</div>';
32563
32564        return html;
32565    }
32566
32567    FormBuilder.GetFieldTypeMarkup = function (fieldType, contentID) {
32568        var html = '';
32569
32570        if (fieldType.DataType !== Agility.UGC.API.DataType.Boolean) {
32571            html = FormBuilder.GetLabelMarkup(fieldType, contentID);
32572        }
32573
32574        var basicFieldConfig = FormBuilder.GetBasicFieldConfig(fieldType, contentID);
32575
32576        switch (fieldType.DataType) {
32577            case Agility.UGC.API.DataType.String:
32578                html += FormBuilder.GetStringFieldTypeMarkup(fieldType, contentID, basicFieldConfig);
32579                break;
32580            case Agility.UGC.API.DataType.TextBlob:
32581            case Agility.UGC.API.DataType.HTML:
32582                html += FormBuilder.GetTextAreaFieldTypeMarkup(fieldType, contentID, basicFieldConfig);
32583                break;
32584            case Agility.UGC.API.DataType.Int:
32585                html += FormBuilder.GetIntFieldTypeMarkup(fieldType, contentID, basicFieldConfig);
32586                break;
32587            case Agility.UGC.API.DataType.Double:
32588                html += FormBuilder.GetDoubleFieldTypeMarkup(fieldType, contentID, basicFieldConfig);
32589                break;
32590            case Agility.UGC.API.DataType.DateTime:
32591                html += FormBuilder.GetDateTimeFieldTypeMarkup(fieldType, contentID, basicFieldConfig);
32592                break;
32593            case Agility.UGC.API.DataType.Email:
32594                html += FormBuilder.GetEmailFieldTypeMarkup(fieldType, contentID, basicFieldConfig);
32595                break;
32596            case Agility.UGC.API.DataType.Boolean:
32597                html += FormBuilder.GetBooleanFieldTypeMarkup(fieldType, contentID, basicFieldConfig);
32598                break;
32599            case Agility.UGC.API.DataType.Dropdown:
32600                html += FormBuilder.GetDropdownFieldTypeMarkup(fieldType, contentID, basicFieldConfig);
32601                break;
32602            case Agility.UGC.API.DataType.File:
32603                html += FormBuilder.GetFileFieldTypeMarkup(fieldType, contentID, basicFieldConfig);
32604                break;
32605            default:
32606        }
32607
32608        return html;
32609    };
32610
32611    FormBuilder.GetStringFieldTypeMarkup = function (fieldType, contentID, fieldConfig) {
32612        return '<input type="text"' + fieldConfig.id + fieldConfig.name + fieldConfig.value + fieldConfig.placeholder + fieldConfig.required + ' data-parsley-trigger="keyup"/>' + fieldConfig.description;
32613    };
32614
32615    FormBuilder.GetTextAreaFieldTypeMarkup = function (fieldType, contentID, fieldConfig) {
32616        return '<textarea' + fieldConfig.id + fieldConfig.name + fieldConfig.value + fieldConfig.placeholder + fieldConfig.required + ' data-parsley-trigger="keyup"></textarea>' + fieldConfig.description;
32617    };
32618
32619    FormBuilder.GetIntFieldTypeMarkup = function (fieldType, contentID, fieldConfig) {
32620        return '<input type="text"' + fieldConfig.id + fieldConfig.name + fieldConfig.value + fieldConfig.placeholder + fieldConfig.required + ' data-parsley-type="digits" max="2147483647" data-parsley-trigger="keyup"/>' + fieldConfig.description;
32621    };
32622
32623    FormBuilder.GetDoubleFieldTypeMarkup = function (fieldType, contentID, fieldConfig) {
32624        return '<input type="text"' + fieldConfig.id + fieldConfig.name + fieldConfig.value + fieldConfig.placeholder + fieldConfig.required + ' data-parsley-type="number" data-parsley-trigger="keyup"/>' + fieldConfig.description;
32625    };
32626
32627    FormBuilder.GetDateTimeFieldTypeMarkup = function (fieldType, contentID, fieldConfig) {
32628        return '<input type="date"' + fieldConfig.id + fieldConfig.name + fieldConfig.value + fieldConfig.placeholder + fieldConfig.required + ' data-date-format="YYYY-MM-DD" data-parsley-trigger="keyup"/>' + fieldConfig.description;
32629    };
32630
32631    FormBuilder.GetEmailFieldTypeMarkup = function (fieldType, contentID, fieldConfig) {
32632        return '<input type="email"' + fieldConfig.id + fieldConfig.name + fieldConfig.value + fieldConfig.placeholder + fieldConfig.required + ' data-date-format="YYYY-MM-DD" data-parsley-trigger="keyup"/>' + fieldConfig.description;
32633    };
32634
32635    FormBuilder.GetBooleanFieldTypeMarkup = function (fieldType, contentID, fieldConfig) {
32636        var html = '<label id="agility-form-checkbox-label-' + fieldType.Name + '-' + contentID + '" class="agility-form-checkbox-label" for="' + fieldType.Name + '-' + contentID + '">';
32637
32638        html += '<input type="checkbox"' + fieldConfig.id + fieldConfig.name + fieldConfig.value + fieldConfig.required + '/>';
32639
32640        html += '<span>' + fieldType.Label + '</span></label> ';
32641
32642        return html;
32643    };
32644
32645    FormBuilder.GetDropdownFieldTypeMarkup = function (fieldType, contentId, fieldConfig) {
32646        var html = '<select ' + fieldConfig.id + fieldConfig.name + fieldConfig.value + fieldConfig.required + '>';
32647
32648        html += '<option>' + fieldConfig.optionLabel + '</option>';
32649
32650        var options = [];
32651
32652        if (fieldType.AdditionalMetaData) {
32653            options = fieldType.AdditionalMetaData.split('\n');
32654
32655            for (var i = 0; i < options.length; i++) {
32656                var option = options[i];
32657
32658                var text = option.split('|')[0];
32659                var value = option.split('|')[1];
32660
32661                html += '<option value="' + value + '">
32661' + text + '</option>';
32662            }
32663        }
32664
32665        html += '</select>';
32666
32667        html += fieldConfig.description;
32668
32669        return html;
32670    };
32671
32672    FormBuilder.GetFileFieldTypeMarkup = function (fieldType, contentID, fieldConfig) {
32673        return '<input type="file"' + fieldConfig.id + fieldConfig.name + fieldConfig.required + '/>' + fieldConfig.description;
32674    };
32675
32676    FormBuilder.GetBasicFieldConfig = function (fieldType, contentID) {
32677        var value = fieldType.DefaultValue ? ' value="' + fieldType.DefaultValue + '" ' : '';
32678        var name = ' name="' + fieldType.Name + '" ';
32679        var required = fieldType.Required ? ' data-parsley-required="true" ' : '';
32680        var id = ' id="' + fieldType.Name + '-' + contentID + '" ';
32681        var description = fieldType.JSONFields.Description ? '<small class="agility-form-field-description">' + fieldType.JSONFields.Description + '</small>' : '';
32682        var placeholder = fieldType.JSONFields.PlaceholderText ? ' placeholder="' + fieldType.JSONFields.PlaceholderText + '" ' : '';
32683        var optionLabel = fieldType.JSONFields.PlaceholderText ? fieldType.JSONFields.PlaceholderText : '';
32684
32685        return {
32686            value: value,
32687            name: name,
32688            required: required,
32689            id: id,
32690            description: description,
32691            placeholder: placeholder,
32692            optionLabel: optionLabel
32693        }
32694    };
32695
32696    FormBuilder.GetLabelMarkup = function (fieldType, contentID) {
32697        var forID = ' for="' + fieldType.Name + '-' + contentID + '">';
32698        return '<label' + forID + fieldType.Label + '</label>';
32699    };
32700
32701    FormBuilder.GetBootsrapColumnClassName = function (width) {
32702        var className = 'agility-form-col-full';
32703
32704        switch (width) {
32705            case 'quarter':
32706                className = 'agility-form-col-quarter';
32707                break;
32708            case 'third':
32709                className = 'agility-form-col-third';
32710                break;
32711            case 'half':
32712                className = 'agility-form-col-half';
32713                break;
32714            case 'full':
32715                className = 'agility-form-col-full';
32716                break;
32717            default:
32718                className = 'agility-form-col-full';
32719        }
32720
32721        return className;
32722    };
32723
32724    FormBuilder.GetColumnWidth = function (widthStr) {
32725        var width = 0;
32726
32727        switch (widthStr) {
32728            case 'quarter':
32729                width = 0.25;
32730                break;
32731            case 'third':
32732                width = 0.33;
32733                break;
32734            case 'half':
32735                width = 0.5;
32736                break;
32737            case 'full':
32738                width = 1;
32739                break;
32740            default:
32741                width = 1;
32742        }
32743
32744        return width;
32745    };
32746
32747    FormBuilder.GetSubmitButtonMarkup = function (label, formSelector, contentID, languageCode, mode, recordTypeID) {
32748        var html = '<div class="agility-form-row"><div class="agility-form-col-full"><button id="agility-form-' + contentID + '-submit-btn" class="agility-form-submit-btn" type="button" onclick="Agility.FormBuilder.ValidateAndSubmitForm(\'' + formSelector + '\',' + contentID + ',\'' + languageCode + '\',' + mode + ',' + recordTypeID + ')">' + label + '</button></div></div>';
32749
32750        return html;
32751    };
32752
32753    FormBuilder.ValidateAndSubmitForm = function (formSelector, contentID, languageCode, mode, recordTypeID) {
32754        var formElement = $(formSelector);
32755
32756        //disable all inputs in form
32757        $('input, select, button, textarea', formElement).each(function () {
32758            $(this).attr('disabled', true);
32759        });
32760
32761        formElement.addClass('submitting');
32762
32763        if (formElement.parsley().validate()) {
32764            var data = {
32765                ContentID: contentID,
32766                LanguageCode: languageCode,
32767                Mode: mode,
32768                RecordTypeID: recordTypeID,
32769                Values: {}
32770            };
32771
32772            var values = {};
32773            $('input, select, textarea', formElement).each(function () {
32774            	var $elem = $(this);
32775            	var value = $elem.val();
32776
32777            	if ($elem.attr("type") == "checkbox") {
32778            		value = $elem.prop("checked");
32779            	}
32780
32781            	values[this.name] = value;
32782            });
32783
32784            data.Values = values;
32785
32786            //form is valid check if there are any files to be uploaded
32787            var fileInputs = $('input[type="file"]', formElement);
32788
32789            if (fileInputs.length > 0) {
32790                var filesToUpload = 0;
32791                var filesUploaded = 0;
32792
32793                for (var i = 0; i < fileInputs.length; i++) {
32794                    var fileInput = fileInputs[i];
32795                    if ($(fileInput).val()) {
32796                        filesToUpload++;
32797                    }
32798                }
32799
32800                if (filesToUpload === 0) {
32801                    _submitAndUpdateUI(data, formElement);
32802                } else {
32803                    var fileInputNameValuePairs = [];
32804                    for (var i = 0; i < fileInputs.length; i++) {
32805                        var fileInput = fileInputs[i];
32806
32807                        if ($(fileInput).val()) {
32808                            _uploadFile(fileInput,
32809                                function (resp) {
32810                                    //success
32811                                    if (resp && resp.ResponseType === Agility.UGC.API.ResponseType.Error) {
32812                                        return;
32813                                    }
32814
32815                                    filesUploaded++;
32816                                    fileInputNameValuePairs.push({ name: this.fileInput.name, value: resp });
32817
32818                                    if (filesToUpload === filesUploaded) {
32819                                        for (var i = 0; i < fileInputNameValuePairs.length; i++) {
32820                                            var fileInputNameValuePair = fileInputNameValuePairs[i];
32821                                            this.data.Values[fileInputNameValuePair.name] = fileInputNameValuePair.value;
32822                                        }
32823
32824                                        _submitAndUpdateUI(this.data, this.formElement);
32825                                    }
32826                                }.bind({ fileInput: fileInput, data: data, formElement: formElement }),
32827								function (err) {
32828									//err
32829									if (console)  console.log(err);
32830                                }, function () {
32831                                    //always
32832                                    $(this.fileInput).removeClass('uploading');
32833                                    $(this.formElement).removeClass('uploading');
32834                                }.bind({ fileInput: fileInput, formElement: formElement}), function (progress) {
32835                                    //progress
32836                                    $(this.fileInput).addClass('uploading');
32837                                    $(this.formElement).addClass('uploading');
32838                                    
32839                                	if (console) console.log("upload progress", progress);
32840                                }.bind({ fileInput: fileInput, formElement: formElement })
32841                            );
32842                        }
32843                    }
32844                }
32845
32846
32847            } else {
32848                //no need to upload anything, submit it
32849                _submitAndUpdateUI(data, formElement);
32850            }
32851
32852        } else {
32853            $('input, select, button, textarea', formElement).each(function () {
32854                $(this).removeAttr('disabled');
32855            });
32856
32857            formElement.removeClass('submitting');
32858        }
32859    }
32860
32861    function _submitAndUpdateUI(data, formElement) {
32862        FormBuilder.Submit(data, function (response) {
32863            var contentID = formElement.data('agility-form-content-id');
32864
32865            var htmlContainerID = 'agility-form-' + contentID;
32866            var htmlContainer = $('#' + htmlContainerID);
32867            var outerHeight = formElement.outerHeight();
32868
32869            var contentItemValues = window.FormBuilderValues[htmlContainerID];
32870
32871            if (!contentItemValues) {
32872                //calling from content manager
32873                htmlContainerID = window.FormBuilderContainerName;
32874                htmlContainer = $('#' + htmlContainerID);
32875                contentItemValues = window.FormBuilderValues[window.FormBuilderContainerName];
32876            }
32877
32878            formElement.hide();
32879
32880            if (response.ResponseType != Agility.UGC.API.ResponseType.OK) {
32881                htmlContainer.append('<div id="agility-form-msg">' + contentItemValues.ErrorCopy + '</div>');
32882            } else {
32883                htmlContainer.append('<div id="agility-form-msg">' + contentItemValues.SuccessCopy + '</div>');
32884            }
32885
32886            document.getElementById("agility-form-msg").scrollIntoView();
32887
32888        });
32889
32890    }
32891
32892    FormBuilder.Submit = function (data, callback) {
32893        if (!checkApiIntialized(callback)) return;
32894
32895        var postData = Agility.JSON.encode(data);
32896
32897        _performPost('SaveFormPost', { postData: postData }, callback);
32898    };
32899
32900    function _performPost(methodName, postData, callback) {
32901
32902        if (!postData) postData = {};
32903
32904        var url = Agility.UGC.API.APIUrl;
32905        if (url == '' || url == null) return null;
32906
32907        url = url.toLowerCase();
32908
32909        url = url.replace("http://", "https://");
32910        url = url.replace("/agility-ugc-api-jsonp.svc", "/ugc-api");
32911
32912        if (url.lastIndexOf('/') != url.length - 1) url += '/';
32913
32914        //create the base url for the call
32915        url += methodName;
32916
32917        //sanitize the post data
32918        if (postData.postData) {
32919            var postDataStr = postData.postData;
32920
32921            postData.postData = '__SANITIZED__' + postDataStr
32922                .replace(/&/g, '&amp;')
32923                .replace(/'/g, '&apos;')
32924                .replace(/</g, '&lt;')
32925                .replace(/>/g, '&gt;');
32926        }
32927
32928        //add the auth stuff into the postData
32929        postData.accessKey = Agility.UGC.API.APIAccessKey;
32930        postData.seconds = Agility.UGC.API.APISeconds;
32931        postData.randomNumber = Agility.UGC.API.APIRandomNumber;
32932        postData.hash = Agility.UGC.API.APIHash;
32933        postData.profileRecordID = Agility.UGC.API.APIProfileRecordID;
32934
32935        return $.ajax(url, {
32936            type: 'POST',
32937            data: postData,
32938            dataType: 'json',
32939            xhrFields: {
32940                withCredentials: true
32941            },
32942           crossDomain: true
32943        }).done(function (result) {
32944            callback(result);
32945        }).fail(function (err, status, errorMessage) {
32946
32947            if (status == 'abort') {
32948                //do nothing...
32949                return;
32950            }
32951
32952            callback({
32953                ResponseType: Agility.UGC.API.ResponseType.Error,
32954                Message: errorMessage
32955            });
32956        });
32957    };
32958
32959    function checkApiIntialized(callback) {
32960
32961        if (Agility.UGC.API.APIUrl == null || Agility.UGC.API.APIUrl == '' || Agility.UGC.API.APIAccessKey == undefined) {
32962            callback({
32963                ResponseType: Agility.UGC.API.ResponseType.Error,
32964                Message: 'The Agility UGC API has not been initialized.',
32965                ResponseData: null
32966            });
32967
32968            return false;
32969        }
32970
32971        return true;
32972    };
32973
32974    function _uploadFile(fileInputElem, callback, errorCallback, alwaysCallback, progressCallback) {
32975
32976        //TODO: check for files...
32977
32978        var fileToUpload = fileInputElem.files[0]
32979        var fileSize = fileToUpload.size;
32980        var fileName = fileToUpload.name;
32981
32982
32983
32984        var methodName = "Upload";
32985        var url = Agility.UGC.API.APIUrl;
32986        if (url == "" || url == null) return null;
32987        url = url.toLowerCase();
32988
32989        url = url.replace("http://", "https://");
32990        url = url.replace("/agility-ugc-api-jsonp.svc", "/ugc-api");
32991
32992        if (url.lastIndexOf("/") != url.length - 1) url += "/";
32993
32994        //create the base url for the call
32995        url += methodName;
32996
32997        if (url.indexOf("/") == 0) url = getBaseUrl() + url;
32998
32999        //add the auth stuff into the postData
33000        var formData = new FormData();
33001        formData.append("file", fileToUpload);
33002        formData.append("fileName", fileName);
33003        formData.append("accessKey", Agility.UGC.API.APIAccessKey);
33004        formData.append("seconds", Agility.UGC.API.APISeconds);
33005        formData.append("randomNumber", Agility.UGC.API.APIRandomNumber);
33006        formData.append("hash", Agility.UGC.API.APIHash);
33007        formData.append("profileRecordID", Agility.UGC.API.APIProfileRecordID);
33008
33009        return $.ajax({
33010            url: url,
33011            xhr: function () {  // Custom XMLHttpRequest
33012                var myXhr = $.ajaxSettings.xhr();
33013                if (myXhr.upload) { // Check if upload property exists
33014                    if ($.isFunction(progressCallback)) {
33015                        myXhr.upload.addEventListener('progress', progressCallback, false);
33016                    }
33017                }
33018                return myXhr;
33019            },
33020            type: 'POST',			
33021            data: formData,
33022            processData: false,
33023            contentType: false,
33024            xhrFields: {
33025                withCredentials: true
33026            },
33027            crossDomain: true
33028        }).done(function (result) {
33029
33030            if (result.IsError) {
33031                if (errorCallback != undefined && $.isFunction(errorCallback)) {
33032                    errorCallback(result.ErrorMessage);
33033                }
33034
33035            } else {
33036                //redirect to the return url		
33037                if (result.ResponseData) {
33038                    callback(result.ResponseData);
33039                } else {
33040                    callback(result);
33041                }
33042            }
33043
33044        }).fail(function (err, status, errorMessage) {
33045
33046            if (status == "abort") {
33047                //do nothing...
33048                return;
33049            }
33050
33051            if (errorCallback != undefined && $.isFunction(errorCallback)) {
33052                errorCallback(errorMessage, status);
33053            }
33054
33055        }).always(function () {
33056            if (alwaysCallback != undefined && $.isFunction(alwaysCallback)) {
33057                alwaysCallback();
33058            }
33059        });
33060    }
33061
33062
33063})(Agility.FormBuilder);;
33064/// <reference path="Agility.js" />
33065
33066Agility.RegisterNamespace("Agility.UGC.API");
33067
33068(function (API) {
33069
33070	//ENUMS
33071	API.DataType = {
33072		String: 0,
33073		TextBlob: 1,
33074		Int: 2,
33075		Double: 3,
33076		DateTime: 4,
33077		File: 5,
33078		GUID: 6,
33079		Encrypted: 7,
33080		Hashed: 8,
33081		Boolean: 9,
33082		Dropdown: 10,
33083		HTML: 11,
33084		Email: 12
33085	}
33086
33087	API.RecordState = {
33088		New: 0,
33089		Published: 1,
33090		Deleted: 2,
33091		Processing: 3,
33092		Declined: 4,
33093		Error: 5,
33094		Escalated: 6,
33095		AwaitingReview: 7,
33096		Draft: 8,
33097		All: -1
33098	}
33099
33100	API.Permission = {
33101		Read: 0,
33102		Create: 1,
33103		Edit: 2,
33104		Delete: 3,
33105		Moderate: 4,
33106		Administer: 5
33107	}
33108
33109	API.FileStorage = {
33110		RelativeURL: 0,
33111		BaseURL: 1,
33112		EdgeURL: 2
33113	}
33114
33115	API.SortDirection = {
33116		ASC: "ASC",
33117		DESC: "DESC"
33118	}
33119
33120	API.ResponseType = {
33121		OK: 0,
33122		Error: 1
33123	}
33124
33125	API.FileService = {
33126		AmazonS3: 0,
33127		YouTube: 1,
33128		Flickr: 2,
33129		Image: 3,
33130		Video: 4,
33131		Ooyala: 5,
33132		Brightcove: 6
33133	}
33134
33135	API.FileServiceState = {
33136		New: 0,
33137		Unprocessed: 1,
33138		Processed: 2,
33139		Error: 3
33140	}
33141
33142	API.RecordFlag = {
33143		Spam: "Spam",
33144		Flagged: "Flagged",
33145		Illegal: "Illegal",
33146		Abuse: "Abuse"
33147	}
33148
33149	API.AggregateTypes = {
33150		Count: 0,
33151		Sum: 1,
33152		Average: 2
33153	}
33154
33155	API.FeedbackContentType = {
33156		WCM: 0,
33157		UGC: 1,
33158		Custom: 2
33159	}
33160
33161	API.FeedbackSubmissionType = {
33162		Like: 0,
33163		Rating: 1,
33164		Vote: 2,
33165		ApproveDisapprove: 3,
33166		Custom: 4
33167	}
33168
33169	API.SubmissionInterval = {
33170		None: -1,
33171		Day: 0,
33172		Hour: 1,
33173		Week: 2,
33174		Month: 3,
33175		Minute: 4,
33176		SingleSubmissionOnly: 5
33177	}
33178
33179
33180	API.FileServiceMetaDataTypeName = "JSONPFileServiceMetaData:#Agility.UGC.API.ServiceObjects";
33181
33182	API.YouTubeMetaField = {
33183		OriginalFilePath: "OriginalFilePath",
33184		VideoID: "VideoID",
33185		Description: "Description",
33186		Category: "Category",
33187		Title: "Title",
33188		Keywords: "Keywords",
33189		Private: "Private",
33190		YouTubeState: "YouTubeState",
33191		Duration: "Duration"
33192	};
33193
33194	//from here: http://www.flickr.com/services/api/upload.api.html
33195
33196	API.FlickrMetaField = {
33197		OriginalFilePath: "OriginalFilePath",
33198		title: "title",
33199		description: "description",
33200		tags: "tags",
33201		is_public: "is_public",
33202		is_friend: "is_friend",
33203		is_family: "is_family",
33204		safety_level: "safety_level",
33205		hidden: "hidden",
33206		photo_id: "photo_id"
33207
33208		//other values are also appended as they are made available 
33209		/*
33210		secret
33211		photopage
33212		SquareImageUrl
33213		ThumbnailImageUrl
33214		SmallImageUrl
33215		MediumImageUrl
33216		LargeImageUrl
33217		*/
33218	};
33219
33220	API.OoyalaMetaField = {
33221		embedCode: "embedCode",
33222		title: "title",
33223		description: "description",
33224		status: "status"
33225
33226		//http://www.ooyala.com/support/docs/backlot_api#query
33227		//other metadata (plus any "generic" metadata) values are also appended as they are made available 
33228		/*
33229		thumbnailUrl
33230		hostedAt
33231		content_type
33232		uploadedAt
33233		length
33234		size
33235		updatedAt
33236		width
33237		height
33238		*/
33239	};
33240
33241	API.SearchArg = function () {
33242		///	<summary>
33243		///	The search object for the SearchRecords method.
33244		///	</summary>
33245		///<field name="PageSize" Type="Number">The number of records per page.</field>
33246		///<field name="RecordOffset" Type="Number"></field>
33247		///<field name="IncludeSpam" Type="Boolean"></field>
33248		///<field name="IncludeFlagged" Type="Boolean"></field>
33249		///<field name="IncludeIllegal" Type="Boolean"></field>
33250		///<field name="State" Type="API.RecordState"></field>
33251		///<field name="SortedField" Type="String"></field>
33252		///<field name="SortDirection" Type="String"></field>
33253		///<field name="RecordTypeName" Type="String"></field>
33254		///<field name="Search" Type="String">The search string.</field>
33255		///<field name="CacheKey" Type="String">A custom cache key that will be used instead of the record type id to cache the results with.</field>
33256		///<field name="Columns" Type="Array">A list of the field names that you want to be returned.</field>
33257
33258		PageSize = 20;
33259		RecordOffset = 0;
33260		IncludeSpam = false;
33261		IncludeFlagged = false;
33262		IncludeIllegal = false;
33263		State = API.RecordState.Published;
33264		SortedField = "";
33265		SortDirection = "";
33266		RecordTypeName = null;
33267		Search = "";
33268		CacheKey = null;
33269		Columns = [];
33270		FileStorage = API.FileStorage.RelativeURL;
33271		IncludeStatistics = false;
33272	}
33273
33274	API.CommentSearchArg = function () {
33275		///	<summary>
33276		///	The search object for the SearchComments method.
33277		///	</summary>
33278		///<field name="RelatedContentID" Type="Number">The ID of the Related Content Item</field>
33279		///<field name="PageSize" Type="Number">The number of records per page.</field>
33280		///<field name="RecordOffset" Type="Number"></field>
33281		///<field name="SortedField" Type="String"></field>
33282		///<field name="SortDirection" Type="String"></field>
33283		///<field name="RecordTypeName" Type="String"></field>
33284		///<field name="CacheKey" Type="String">A custom cache key that will be used instead of the record type id to cache the results with.</field>
33285		///<field name="OtherStates" Type="Array"></field>
33286		///<field name="State" Type="API.RecordState"></field>
33287		///<field name="FileStorage" Type="API.FileStorage"></field>
33288		///<field name="Columns" Type="Array">A list of the field names that you want to be returned.</field>
33289
33290
33291		RelatedContentID: -1;
33292		PageSize: 20;
33293		RecordOffset: 0;
33294		SortedField: "CreatedOn";
33295		SortDirection: "DESC";
33296		RecordTypeName: "";
33297		CacheKey = null;
33298		OtherStates = [];
33299		State = API.RecordState.Published;
33300		FileStorage = API.FileStorage.RelativeURL;
33301		Columns = [];
33302		IgnoreAbuse = true;
33303		IncludeFlagged = false;
33304		IncludeIllegal = false;
33305
33306	}
33307
33308	API.FeedbackSearchArg = function () {
33309		///	<summary>
33310		///	The search object for the GetFeedbackAggregate method.
33311		///	</summary>
33312		///<field name="ReferenceName" Type="String">The Reference name of the list the feedback refers to</field>
33313		///<field name="FeedbackContentType" Type="FeedbackContentType">The content type the reference name refers to (WCM/UGC/Custom)</field>
33314		///<field name="FeedbackSubmissionType" Type="FeedbackSubmissionType">The submission type the reference name refers to (Like/Vote/Rating/ApproveDisaprove/Custom)</field>
33315		///<field name="RelatedContentID" Type="int">The ID the item is related to</field>
33316		///<field name="StartDate" Type="Date"></field>
33317		///<field name="EndDate" Type="Date"></field>
33318		///<field name="IsPositive" Type="Boolean"></field>
33319		///<field name="Action" Type="AggregateTypes">The action to perform (Count/Sum/Average)</field>
33320
33321		ReferenceName = null;
33322		ContentType = -1;
33323		SubmissionType = -1;
33324		RelatedContentIDs = new Array();
33325		StartDate = null;
33326		EndDate = null;
33327		IsPositive = null;
33328		Action = null;
33329
33330	}
33331
33332
33333	API.BooleanFeedback = function () {
33334		BooleanFeedbackID = -1;
33335		FeedbackTypeID = -1;
33336		RelatedContentID = -1;
33337		ProfileRecordID = -1;
33338		ExternalProfileID = null;
33339		CreatedOn = null;
33340		IsPositive = null;
33341
33342		ReferenceName = null;
33343		ContentType = -1;
33344		SubmissionType = -1;
33345
33346		//Submission Rules
33347		RequiresAuthentication = false;
33348		SubmissionIntervalUnit = API.SubmissionInterval.None;
33349		SubmissionIntervalValue = 1;
33350	}
33351
33352	API.RatingFeedback = function () {
33353		RatingFeedbackID = -1;
33354		FeedbackTypeID = -1;
33355		RelatedContentID = -1;
33356		ProfileRecordID = -1;
33357		ExternalProfileID = null;
33358		CreatedOn = null;
33359		IsPositive = null;
33360		RatingValue = 0;
33361
33362		ReferenceName = null;
33363		ContentType = -1;
33364		SubmissionType = -1;
33365
33366		//Submission Rules
33367		RequiresAuthentication = false;
33368		SubmissionIntervalUnit = API.SubmissionInterval.None;
33369		SubmissionIntervalValue = 1;
33370	}
33371
33372	API.Record = function () {
33373		var ID = -1;
33374		var RecordTypeName;
33375		var CreatedOn;
33376		var ModifiedOn;
33377	}
33378
33379	API.Initialized = false;
33380
33381	API.APIUrl = "";
33382
33383	API.OnInit = function (API_Url, API_AccessKey, API_Seconds, API_RandomNumber, API_ProfileRecordID, API_Hash) {
33384		/// <summary>
33385		/// Initialize the Agility DataService API
33386		/// </summary>
33387		/// <param name="API_Url" type="String">The URL to the Agility DataService REST API.</param>        
33388		/// <param name="API_AccessKey" type="String">The API Key.</param>
33389		/// <param name="API_Seconds" type="String">The # of Seconds.</param>
33390		/// <param name="API_RandomNumber" type="String">A Random number.</param>        
33391		/// <param name="API_ProfileRecordID" type="String">The current user ID.</param>        
33392		/// <param name="API_Hash" type="String">The API Hash.</param>        
33393
33394		if (API_Url != undefined && API_Url != null) {
33395			API.APIUrl = API_Url;
33396		}
33397		API.APIAccessKey = API_AccessKey;
33398		API.APISeconds = API_Seconds;
33399		API.APIRandomNumber = API_RandomNumber;
33400		API.APIProfileRecordID = API_ProfileRecordID;
33401		API.APIHash = API_Hash;
33402		API.Initialized = true;
33403
33404	}
33405
33406
33407	function checkApiIntialized(callback) {
33408
33409		if (API.APIUrl == null || API.APIUrl == "" || API.APIAccessKey == undefined) {
33410			callback({
33411				ResponseType: API.ResponseType.Error,
33412				Message: "The Agility UGC API has not been initialized.",
33413				ResponseData: null
33414			});
33415
33416			return false;
33417		}
33418
33419		return true;
33420	}
33421
33422
33423
33424	API.GetAllRecordTypes = function (callback) {
33425		/// <summary>
33426		/// Get All Record Types.
33427		/// </summary>
33428		/// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      
33429
33430		if (!checkApiIntialized(callback)) return;
33431		var url = _buildAPIUrl("GetAllRecordTypes", null);
33432
33433
33434
33435		jQuery.getJSON(url, callback);
33436
33437	}
33438
33439	API.GetRecordType = function (recordTypeID, callback) {
33440		/// <summary>
33441		/// Get a record based on the record type id.
33442		/// </summary>
33443		/// <param name="recordTypeID">The ID of the record type to return.</param>      
33444		/// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      
33445		if (!checkApiIntialized(callback)) return;
33446		var url = _buildAPIUrl("GetRecordType", [recordTypeID]);
33447
33448		jQuery.getJSON(url, callback);
33449
33450	}
33451
33452	API.GetRecordTypeByName = function (recordTypeName, callback) {
33453		/// <summary>
33454		/// Get a record based on the record type name.
33455		/// </summary>
33456		/// <param name="recordTypeName">The name of the record type to return.</param>      
33457		/// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      
33458		if (!checkApiIntialized(callback)) return;
33459
33460		var url = _buildAPIUrl("GetRecordTypeByName", [recordTypeName]);
33461		jQuery.getJSON(url, callback);
33462	}
33463
33464	API.SaveRecordType = function (recordType, callback) {
33465		/// <summary>
33466		/// Saves a record type.
33467		/// </summary>
33468		/// <param name="recordType">The record type to save.</param>      
33469		/// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      
33470
33471		if (!checkApiIntialized(callback)) return;
33472		var postData = Agility.JSON.encode(recordType);
33473
33474		var url = _buildAPIUrl("SaveRecordType", null);
33475
33476		_submitPostData(url, postData, callback);
33477
33478	}
33479
33480	API.DeleteRecordType = function (recordTypeID, callback) {
33481		/// <summary>
33482		/// Get All Record Types.
33483		/// </summary>
33484		/// <param name="recordTypeID">The ID of the record type to return.</param>      
33485		/// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      
33486
33487		if (!checkApiIntialized(callback)) return;
33488
33489		var url = _buildAPIUrl("DeleteRecordType", [recordTypeID]);
33490
33491		jQuery.getJSON(url, callback);
33492
33493	}
33494
33495	API.GetRecord = function (recordID, fileStorage, callback) {
33496		/// <summary>
33497		/// Gets a Record.
33498		/// </summary>
33499		/// <param name="recordID" type="Number">The ID of the record to return.</param>      
33500		/// <param name="RelativeURL" type="Agility.UGC.API.FileStorage">(optional) The method to be used for building file field URLs that may be on this document.</param>      
33501		/// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      
33502
33503		if ($.isFunction(fileStorage)) {
33504			callback = fileStorage;
33505			fileStorage = null;
33506
33507		}
33508
33509		if (!checkApiIntialized(callback)) return;
33510
33511		var url = null;
33512		if (fileStorage == null) {
33513			url = _buildAPIUrl("GetRecord", [recordID]);
33514		} else {
33515			url = _buildAPIUrl("GetRecord", [recordID], "fileStorage=" + escape(fileStorage));
33516		}
33517
33518		jQuery.getJSON(url, callback);
33519
33520	}
33521
33522	API.GetRecordHistory = function (recordID, callback) {
33523		/// <summary>
33524		/// Gets a the Version Histor for a Record.  This method requires admin access.
33525		/// </summary>
33526		/// <param name="recordID">The ID of the record to return.</param>      
33527		/// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      
33528
33529		if (!checkApiIntialized(callback)) return;
33530
33531		var url = _buildAPIUrl("GetRecordHistory", [recordID]);
33532
33533		jQuery.getJSON(url, callback);
33534
33535	}
33536
33537
33538
33539	API.DeleteRecord = function (recordID, callback) {
33540		/// <summary>
33541		/// Deletes a Record.
33542		/// </summary>
33543		/// <param name="recordID">The ID of the record to return.</param>      
33544		/// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      
33545
33546		if (!checkApiIntialized(callback)) return;
33547
33548		var url = _buildAPIUrl("DeleteRecord", [recordID]);
33549
33550		jQuery.getJSON(url, callback);
33551
33552	}
33553
33554
33555	API.SetRecordFlag = function (recordID, flag, reason, callback) {
33556		/// <summary>
33557		/// Sets whether a record is flagged or not.
33558		/// </summary>
33559		/// <param name="recordID" type="Number">The ID of the record to return.</param>      
33560		/// <param name="flag" type="Agility.UGC.API.RecordFlag">
33560Whether the record is flagged or not.</param> 
33561		/// <param name="reason" type="String">Whether the record is flagged or not.</param> 		     		
33562		/// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      
33563
33564		if (!checkApiIntialized(callback)) return;
33565
33566		var query = null;
33567		if (reason != null && reason != "") {
33568			query = "reason=" + escape(reason);
33569		}
33570
33571		var url = _buildAPIUrl("SetRecordFlag", [recordID, flag], query);
33572
33573		jQuery.getJSON(url, callback);
33574
33575	}
33576
33577
33578	API.InsertRecordHistory = function (recordID, comment, callback) {
33579		/// <summary>
33580		/// Adds a comment to the record history.
33581		/// </summary>
33582		/// <param name="recordID">The ID of the record to return.</param>		
33583		/// <param name="comment">The comment.</param>      			
33584		/// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      
33585
33586		if (!checkApiIntialized(callback)) return;
33587
33588		var postData = comment;
33589
33590		var url = _buildAPIUrl("InsertRecordHistory", [recordID]);
33591
33592		_submitPostData(url, postData, callback);
33593
33594
33595	}
33596
33597	API.SetRecordState = function (recordID, recordState, reason, comment, callback) {
33598		/// <summary>
33599		/// Sets a record state.  Used for publish/decline, etc.
33600		/// </summary>
33601		/// <param name="recordID">The ID of the record to return.</param>      
33602		/// <param name="recordState">The State of the record (from enum)</param>      
33603		/// <param name="reason">The reason that the record is in this state.  May be null if not an Error state.</param>      			
33604		/// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      
33605		/// <param name="comment">The comment to send to the user with any notification, if any.</param>      			
33606
33607		if ($.isFunction(comment)) {
33608			callback = comment;
33609			comment = "";
33610		}
33611
33612		if (!checkApiIntialized(callback)) return;
33613
33614		//note - this method has been changed to a POST so that the reason can be as long as needed.
33615		if (reason == undefined || reason == null) reason = "";
33616		if (comment == undefined || comment == null) comment = "";
33617
33618		var postData = { reason: reason, comment: comment };
33619
33620
33621		var url = _buildAPIUrl("SetRecordStateEx", [recordID, recordState]);
33622
33623		_submitPostData(url, postData, callback);
33624
33625	}
33626
33627	API.SetRecordFileState = function (recordID, fieldName, fileServiceState, callback) {
33628		/// <summary>
33629		/// Sets the file service state on a given file service field.
33630		/// </summary>
33631		/// <param name="recordID">The ID of the record to return.</param>      
33632		/// <param name="fieldName">The name of the field the file is associated with on the record.</param>      
33633		/// <param name="fileServiceState">The fileServiceState to set the field to.  Normally this will be FileServiceState.Unprocessed.</param>      			
33634		/// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      
33635
33636		if (!checkApiIntialized(callback)) return;
33637
33638		var url = _buildAPIUrl("SetRecordFileState", [recordID, fieldName, fileServiceState]);
33639
33640		jQuery.getJSON(url, callback);
33641	}
33642
33643	API.UpdateRecordTypeAlert = function (recordTypeID, recordState, moderatorID, otherNotificationType, callback) {
33644		/// <summary>
33645		/// Inserts or updates a RecordTypeAlert.
33646		/// </summary>
33647		/// <param name="recordTypeID"></param>      
33648		/// <param name="recordState"></param>      
33649		/// <param name="moderatorID"></param>      	
33650		/// <param name="otherNotificationType"></param>		
33651		/// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      
33652
33653		if (!checkApiIntialized(callback)) return;
33654
33655		if (callback == undefined && jQuery.isFunction(otherNotificationType)) {
33656			callback = otherNotificationType;
33657			otherNotificationType = null;
33658		}
33659
33660		var query = null;
33661		if (otherNotificationType != null && otherNotificationType != "") {
33662			query = "otherNotificationType=" + escape(otherNotificationType);
33663		}
33664
33665		var url = _buildAPIUrl("UpdateRecordTypeAlert", [recordTypeID, recordState, moderatorID], query);
33666
33667		jQuery.getJSON(url, callback);
33668	}
33669
33670	API.DeleteRecordTypeAlert = function (recordTypeID, recordState, moderatorID, otherNotificationType, callback) {
33671		/// <summary>
33672		/// Deletes a RecordTypeAlert.
33673		/// </summary>
33674		/// <param name="recordTypeID"></param>      
33675		/// <param name="recordState"></param>      
33676		/// <param name="moderatorID"></param>      			
33677		/// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      
33678
33679		if (!checkApiIntialized(callback)) return;
33680
33681		if (callback == undefined && jQuery.isFunction(otherNotificationType)) {
33682			callback = otherNotificationType;
33683			otherNotificationType = null;
33684		}
33685
33686		var query = null;
33687		if (otherNotificationType != null && otherNotificationType != "") {
33688			query = "otherNotificationType=" + escape(otherNotificationType);
33689		}
33690
33691		var url = _buildAPIUrl("DeleteRecordTypeAlert", [recordTypeID, recordState, moderatorID], query);
33692
33693		jQuery.getJSON(url, callback);
33694	}
33695
33696	API.GetRecordTypeAlerts = function (recordTypeID, callback) {
33697		/// <summary>
33698		/// Gets the RecordTypeAlerts from a specific recordTypeID
33699		/// </summary>
33700		/// <param name="recordTypeID"></param>         			
33701		/// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      
33702
33703		if (!checkApiIntialized(callback)) return;
33704
33705		var url = _buildAPIUrl("GetRecordTypeAlerts", [recordTypeID]);
33706
33707		jQuery.getJSON(url, callback);
33708	}
33709
33710
33711	API.ClearCache = function (cacheKey, callback) {
33712		/// <summary>
33713		/// Clears the cache for a given cache key that was previously passed into the SearchRecords call in the SearchArg parameter.
33714		/// </summary>
33715		/// <param name="cacheKey">A cache key that was previously passed into the SearchRecords call in the SearchArg parameter.</param>         			
33716		/// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      
33717
33718		if (!checkApiIntialized(callback)) return;
33719
33720		var url = _buildAPIUrl("ClearCache", [cacheKey]);
33721
33722		jQuery.getJSON(url, callback);
33723	}
33724
33725
33726	API.SaveRecord = function (record, callback, cacheKey) {
33727		/// <summary>
33728		/// Saves a record.
33729		/// </summary>
33730		/// <param name="record">The record to save.</param>      
33731		/// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      
33732		/// <param name="cacheKey">Optional - the cacheKey to clear the cache for.  Use this in conjunction with the same cacheKey on calls to SearchRecords to control the cache.</param>      
33733
33734		if (!checkApiIntialized(callback)) return;
33735
33736		if (record == null) callback(API.ResponseType.Error, "The record object cannot be null.");
33737		if (record.RecordTypeName == undefined || record.RecordTypeName == null || record.RecordTypeName == "") {
33738			callback({
33739				ResponseType: API.ResponseType.Error,
33740				Message: "The RecordTypeName property cannot be null."
33741			});
33742			return;
33743		}
33744
33745
33746		//get the record type
33747		API.GetRecordTypeByName(record.RecordTypeName, function (response) {
33748
33749			if (response.ResponseType == API.ResponseType.Error) {
33750				callback(response);
33751				return;
33752			} else {
33753
33754				//check the record type
33755				var recordType = response.ResponseData;
33756				if (recordType == undefined || recordType == null) {
33757					callback({
33758						ResponseType: API.ResponseType.Error,
33759						Message: "The Record Type " + record.RecordTypeName + " could not be found."
33760					});
33761					return;
33762				}
33763
33764
33765				//validate the field types...
33766				var lstFieldErrors = [];
33767				for (var i = 0; i < recordType.FieldTypes.length; i++) {
33768					var fieldType = recordType.FieldTypes[i];
33769					var fieldValue = record[fieldType.Name];
33770
33771					if (fieldValue != undefined && fieldValue != null) {
33772						//check for a file value..
33773						if (fieldValue.OriginalFilePath != undefined) fieldValue = fieldValue.OriginalFilePath;
33774					}
33775
33776
33777					var fieldLabel = recordType.FieldTypes[i].Label;
33778
33779
33780
33781					if (fieldType.AllowNull == false) {
33782						//req field
33783						if (fieldValue == undefined || fieldValue == null || new String(fieldValue).length == 0) {
33784
33785							lstFieldErrors[lstFieldErrors.length] = {
33786								FieldType: fieldType,
33787								Message: "The " + fieldType.Label + " field is required."
33788							};
33789						}
33790					}
33791
33792					if (fieldValue == undefined || fieldValue == null || fieldValue == "") {
33793						//skip null vals if they are allowed...
33794						continue;
33795					}
33796
33797
33798					switch (fieldType.DataType) {
33799
33800						case API.DataType.Boolean:
33801							if (new String(fieldValue).toLowerCase() != "true"
33802								&& new String(fieldValue).toLowerCase() != "false") {
33803								lstFieldErrors[lstFieldErrors.length] = {
33804									FieldType: fieldType,
33805									Message: "Could not convert value " + fieldValue + " from field " + fieldType.Label + " to a boolean."
33806								};
33807							}
33808							break;
33809						case API.DataType.DateTime:
33810
33811							var dt = new Date(fieldValue);
33812							if (dt == null) {
33813								lstFieldErrors[lstFieldErrors.length] = {
33814									FieldType: fieldType,
33815									Message: "Could not convert value " + fieldValue + " from field " + fieldType.Label + " to a date/time."
33816								};
33817							}
33818							break;
33819						case API.DataType.Double:
33820
33821							if (isNaN(parseFloat(fieldValue))) {
33822								lstFieldErrors[lstFieldErrors.length] = {
33823									FieldType: fieldType,
33824									Message: "Could not convert value " + fieldValue + " from field " + fieldType.Label + " to a number."
33825								};
33826							}
33827							break;
33828						case API.DataType.Int:
33829							if (isNaN(parseInt(fieldValue))) {
33830								lstFieldErrors[lstFieldErrors.length] = {
33831									FieldType: fieldType,
33832									Message: "Could not convert value " + fieldValue + " from field " + fieldType.Label + " to a number."
33833								};
33834							}
33835							break;
33836						case API.DataType.String:
33837							//enforce max length...				
33838							if (fieldType.MaxLength == 0 && fieldValue.Length > 400) {
33839								lstFieldErrors[lstFieldErrors.length] = {
33840									FieldType: fieldType,
33841									Message: "The value from field " + fieldType.Label + " must be 400 characters or less."
33842								};
33843
33844							}
33845							else if (fieldType.MaxLength > 0 && fieldValue.Length > fieldType.MaxLength) {
33846								lstFieldErrors[lstFieldErrors.length] = {
33847									FieldType: fieldType,
33848									Message: "The value from field " + fieldType.Label + " must be " + fieldType.MaxLength + " characters or less."
33849								};
33850							}
33851
33852							var o1 = _enforceRegex(fieldType, fieldValue, fieldLabel);
33853							if (o1 != null) {
33854								lstFieldErrors[lstFieldErrors.length] = o1;
33855							}
33856
33857							break;
33858
33859						default:
33860							//textblob - enforce max length
33861
33862							if (fieldType.MaxLength > 0 && fieldValue.Length > fieldType.MaxLength) {
33863								lstFieldErrors[lstFieldErrors.length] = {
33864									FieldType: fieldType,
33865									Message: "The value from field " + fieldType.Label + " must be " + fieldType.MaxLength + " characters or less."
33866								};
33867							}
33868
33869							var o2 = _enforceRegex(fieldType, fieldValue, fieldLabel);
33870							if (o2 != null) {
33871								lstFieldErrors[lstFieldErrors.length] = o2;
33872							}
33873							break;
33874					}
33875
33876				}
33877
33878				//check for validation errors
33879				if (lstFieldErrors.length > 0) {
33880					var msg = "";
33881					for (var x = 0; x < lstFieldErrors.length; x++) {
33882						msg += " - " + lstFieldErrors[x].Message + "\n";
33883					}
33884
33885					callback({
33886						ResponseType: API.ResponseType.Error,
33887						Message: msg,
33888						ValidationErrors: lstFieldErrors
33889
33890					});
33891					return;
33892				}
33893
33894
33895
33896				//do the deed
33897				var postData = Agility.JSON.encode(record);
33898				if (cacheKey == undefined || cacheKey == null) cacheKey = "";
33899
33900				var url = _buildAPIUrl("SaveRecord", [], "cacheKey=" + escape(cacheKey));
33901
33902				_submitPostData(url, postData, callback);
33903			}
33904		});
33905
33906	}
33907
33908
33909	function _enforceRegex(fieldType, fieldValue, fieldLabel) {
33910		if (fieldValue == undefined || fieldValue == null || fieldValue == "" || typeof fieldValue != "string") return null;
33911
33912		//enfore regex
33913		if (fieldType.ValidationRegEx != null && fieldType.ValidationRegEx != "" && fieldType.ValidationRegEx != "Add comma separated file extensions. Eg: .pdf, .gif") {
33914			try {
33915				var rEx = new RegExp(fieldType.ValidationRegEx);
33916				rEx.ignoreCase = true;
33917
33918				if (fieldValue.search(rEx) == -1) {
33919
33920
33921					if (fieldType.ValidationMessage != null && fieldType.ValidationMessage != "" && fieldType.ValidationMessage != "Add the file type validation message.") {
33922						return {
33923							FieldType: fieldType,
33924							Message: fieldType.ValidationMessage
33925						};
33926					}
33927					else {
33928						return {
33929							FieldType: fieldType,
33930							Message: "The value from field " + fieldType.Label + " did not match the validation expression requirements."
33931						};
33932					}
33933				}
33934			} catch (Error) {
33935				//ignore regex errors...
33936			}
33937		}
33938	}
33939
33940	API.SearchRecords = function (searchArg, callback) {
33941		/// <summary>
33942		/// Searches for records based on a SearchArg object.
33943		/// </summary>
33944		/// <param name="searchArg" type="Agility.UGC.API.SearchArg">The search arg object.</param>      
33945		/// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      
33946
33947		if (!checkApiIntialized(callback)) return;
33948
33949		var argStr = Agility.JSON.encode(searchArg);
33950		var url = _buildAPIUrl("SearchRecords");
33951		url += "&s=" + escape(argStr);
33952
33953		jQuery.getJSON(url, callback);
33954
33955	}
33956
33957	API.SearchComments = function (commentSearchArg, callback) {
33958		/// <summary>
33959		/// Searches for records based on a SearchArg object.
33960		/// </summary>
33961		/// <param name="commentSearchArg" type="Agility.UGC.API.CommentSearchArg">The search arg object.</param>      
33962		/// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      
33963
33964		if (!checkApiIntialized(callback)) return;
33965
33966		var argStr = Agility.JSON.encode(commentSearchArg);
33967		var url = _buildAPIUrl("SearchComments");
33968		url += "&s=" + escape(argStr);
33969
33970		jQuery.getJSON(url, callback);
33971
33972	}
33973
33974	API.SearchCommentParentIDs = function (commentSearchArg, callback) {
33975		/// <summary>
33976		/// Searches for parent record ids for comments based on a SearchArg object.
33977		/// </summary>
33978		/// <param name="commentSearchArg" type="Agility.UGC.API.CommentSearchArg">The search arg object.</param>      
33979		/// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      
33980
33981		if (!checkApiIntialized(callback)) return;
33982
33983		var argStr = Agility.JSON.encode(commentSearchArg);
33984		var url = _buildAPIUrl("SearchCommentParentIDs");
33985		url += "&s=" + escape(argStr);
33986
33987		jQuery.getJSON(url, callback);
33988
33989	}
33990
33991	API.GetFeedbackAggregate = function (searchArg, callback) {
33992		/// <summary>
33993		/// Searches for records based on a SearchArg object.
33994		/// </summary>
33995		/// <param name="searchArg" type="Agility.UGC.API.SearchArg">The search arg object.</param>      
33996		/// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      
33997
33998		if (!checkApiIntialized(callback)) return;
33999
34000		var argStr = Agility.JSON.encode(searchArg);
34001		var url = _buildAPIUrl("GetFeedbackAggregate");
34002		url += "&s=" + escape(argStr);
34003
34004		jQuery.getJSON(url, callback);
34005
34006	}
34007
34008	API.SaveRating = function (ratingFeedback, callback) {
34009		var rating = ratingFeedback;
34010		rating.SubmissionType = API.FeedbackSubmissionType.Rating;
34011		API.SaveRatingFeedback(rating, callback);
34012	}
34013
34014	API.SaveLike = function (booleanFeedback, callback) {
34015		var like = booleanFeedback;
34016		like.SubmissionType = API.FeedbackSubmissionType.Like;
34017		like.IsPositive = true;
34018
34019		API.SaveBooleanFeedback(like, callback);
34020	}
34021
34022	API.SaveVote = function (booleanFeedback, callback) {
34023		var vote = booleanFeedback;
34024		vote.IsPositive = true;
34025		vote.SubmissionType = API.FeedbackSubmissionType.Vote;
34026
34027		API.SaveBooleanFeedback(vote, callback);
34028	}
34029
34030	API.SaveApproveDisapprove = function (booleanFeedback, IsApproved, callback) {
34031		var ap = booleanFeedback;
34032		ap.IsPositive = IsApproved;
34033		ap.SubmissionType = API.FeedbackSubmissionType.ApproveDisapprove;
34034
34035		API.SaveBooleanFeedback(ap, callback);
34036	}
34037
34038
34039	API.SaveRatingFeedback = function (ratingFeedback, callback) {
34040		/// <summary>
34041		/// Saves a Rating Feedback Object
34042		/// </summary>
34043		/// <param name="ratingFeedback">The rating feedback to save.</param>      
34044		/// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      
34045
34046		if (!checkApiIntialized(callback)) return;
34047
34048		if (API.APIProfileRecordID > 0) {
34049			ratingFeedback.ProfileRecordID = API.APIProfileRecordID;
34050		}
34051
34052		var postData = Agility.JSON.encode(ratingFeedback);
34053
34054		var url = _buildAPIUrl("SaveRatingFeedback", null);
34055
34056		_submitPostData(url, postData, callback);
34057
34058	}
34059
34060	API.SaveBooleanFeedback = function (booleanFeedback, callback) {
34061		/// <summary>
34062		/// Saves a boolean feedback object
34063		/// </summary>
34064		/// <param name="booleanFeedback">The boolean feedback to save.</param>      
34065		/// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      
34066
34067		if (!checkApiIntialized(callback)) return;
34068
34069		if (API.APIProfileRecordID > 0) {
34070			booleanFeedback.ProfileRecordID = API.APIProfileRecordID;
34071		}
34072
34073
34074
34075		var postData = Agility.JSON.encode(booleanFeedback);
34076
34077		var url = _buildAPIUrl("SaveBooleanFeedback", null);
34078
34079		_submitPostData(url, postData, callback);
34080
34081	}
34082
34083	var _settingsCache = null;
34084
34085	API.GetSettings = function (callback, ignoreCache) {
34086		/// <summary>
34087		/// Get the Settings.
34088		/// </summary>
34089		/// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      
34090		/// <param name="ignoreCache" type="Boolean">Whether to ignore the cached value and get the settings from the server every time.<param>
34091
34092		if (!checkApiIntialized(callback)) return;
34093
34094		if (_settingsCache == null || ignoreCache == false) {
34095
34096			var url = _buildAPIUrl("GetSettings", null);
34097
34098			jQuery.getJSON(url, function (data) {
34099				if (data.ResponseType != API.ResponseType.OK) {
34100					callback(data);
34101				} else {
34102					_settingsCache = data.ResponseData;
34103					callback(data);
34104				}
34105			});
34106		} else {
34107
34108			//use the cached value...
34109			callback({
34110				ResponseType: API.ResponseType.OK,
34111				ResponseData: _settingsCache
34112			});
34113		}
34114
34115	}
34116
34117	API.SaveSettings = function (settings, callback) {
34118		/// <summary>
34119		/// Saves the Settings
34120		/// </summary>
34121		/// <param name="settings">The settings to save.</param>      
34122		/// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      
34123
34124		if (!checkApiIntialized(callback)) return;
34125
34126		_settingsCache = null;
34127
34128		var postData = Agility.JSON.encode(settings);
34129
34130		var url = _buildAPIUrl("SaveSettings", null);
34131
34132		_submitPostData(url, postData, callback);
34133
34134	}
34135
34136	API.GetAllSyndicationServices = function (callback) {
34137		/// <summary>
34138		/// Gets all of the syndication services that have been configured.
34139		/// </summary>
34140		/// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      
34141
34142		if (!checkApiIntialized(callback)) return;
34143
34144		var url = _buildAPIUrl("GetAllSyndicationServices", null);
34145
34146		jQuery.getJSON(url, callback);
34147
34148	}
34149
34150	API.DeleteSyndicationService = function (syndicationServiceID, callback) {
34151		/// <summary>
34152		/// Deletes a syndication service.
34153		/// </summary>
34154		/// <param name="syndicationServiceID" type="Number">The ID of the syndication service</param>
34155		/// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      
34156
34157		if (!checkApiIntialized(callback)) return;
34158
34159		var url = _buildAPIUrl("DeleteSyndicationService", [syndicationServiceID]);
34160
34161		jQuery.getJSON(url, callback);
34162
34163	}
34164
34165
34166	API.SaveSyndicationService = function (syndicationService, callback) {
34167		/// <summary>
34168		/// Saves the Settings
34169		/// </summary>
34170		/// <param name="syndicationService">The settings to save.</param>      
34171		/// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      
34172
34173		if (!checkApiIntialized(callback)) return;
34174
34175		var postData = Agility.JSON.encode(syndicationService);
34176
34177		var url = _buildAPIUrl("SaveSyndicationService", null);
34178
34179		_submitPostData(url, postData, callback);
34180
34181	}
34182
34183
34184	API.GetAllSystemAccess = function (callback) {
34185		/// <summary>
34186		/// Gets all of the System Access names in the system/
34187		/// </summary>
34188		/// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      
34189
34190		if (!checkApiIntialized(callback)) return;
34191
34192		var url = _buildAPIUrl("GetAllSystemAccess", null);
34193
34194		jQuery.getJSON(url, callback);
34195
34196	}
34197
34198	API.GetGUID = function (callback) {
34199		/// <summary>
34200		/// Get a GUID.
34201		/// </summary>
34202		/// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      
34203
34204		if (!checkApiIntialized(callback)) return;
34205
34206		var url = _buildAPIUrl("GetGUID", null);
34207
34208		jQuery.getJSON(url, callback);
34209	}
34210
34211
34212
34213	API.GetAmazonS3Signature = function (policy, callback) {
34214		/// <summary>
34215		/// Gets a signature for an Amazon S3 call.
34216		/// </summary>
34217		/// <param name="policy" type="String"></param>      
34218		/// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>
34219
34220		if (!checkApiIntialized(callback)) return;
34221
34222		var url = _buildAPIUrl("GetAmazonS3Signature", null, "policy=" + escape(policy));
34223
34224		jQuery.getJSON(url, callback);
34225
34226	}
34227
34228	API.GetOoyalaSignature = function (queryString, callback) {
34229		/// <summary>
34230		/// Gets a signature for an Ooyala upload.
34231		/// </summary>
34232		/// <param name="queryString" type="String"></param>     
34233		/// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>
34234
34235		if (!checkApiIntialized(callback)) return;
34236
34237		var url = _buildAPIUrl("GetOoyalaSignature", null, "p=" + escape(queryString));
34238
34239		jQuery.getJSON(url, callback);
34240
34241	}
34242
34243	API.DeleteFile = function (key, callback) {
34244		/// <summary>
34245		/// Deletes a file from the Amazon S3 bucket
34246		/// </summary>
34247		/// <param name="key" type="String">The full key that points to the file in S3.</param>      
34248		/// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>
34249
34250		if (!checkApiIntialized(callback)) return;
34251
34252		var url = _buildAPIUrl("DeleteFile", null, "key=" + escape(key));
34253
34254		jQuery.getJSON(url, callback);
34255
34256	}
34257
34258	var _fileSizeCache = {};
34259
34260	API.GetFileSize = function (key, callback) {
34261		/// <summary>
34262		/// Get the file size from a file in the Amazon S3 bucket.
34263		/// </summary>
34264		/// <param name="key" type="String">The full key that points to the file in S3.</param>      
34265		/// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>
34266
34267		if (!checkApiIntialized(callback)) return;
34268
34269		var url = _buildAPIUrl("GetFileSize", null, "key=" + escape(key));
34270
34271		if (_fileSizeCache[key] == undefined) {
34272			jQuery.getJSON(url, function (data) {
34273				if (data.ResponseType == API.ResponseType.OK) {
34274					_fileSizeCache[key] = new Number(data.ResponseData);
34275				}
34276				callback(data);
34277			});
34278		} else {
34279			callback({
34280				ResponseType: API.ResponseType.OK,
34281				ResponseData: new Number(_fileSizeCache[key])
34282			});
34283		}
34284
34285	}
34286
34287
34288
34289	API.TestBrightcoveAuthenticationSettings = function (readToken, writeToken, callback) {
34290
34291		var url = API.APIUrl.toLowerCase().replace("agility-ugc-api-jsonp.svc", "TestBrightcoveAuth.ashx");
34292
34293		if ($.isFunction(writeToken)) {
34294
34295			var videoID = readToken;
34296			callback = writeToken;
34297
34298			url += "?accessKey=" + escape(API.APIAccessKey);
34299			url += "&seconds=" + escape(API.APISeconds);
34300			url += "&randomNumber=" + escape(API.APIRandomNumber);
34301			url += "&hash=" + escape(API.APIHash);
34302			url += "&profileRecordID=" + escape(API.APIProfileRecordID);
34303			url += "&videoID=" + videoID;
34304			url += "&method=?";
34305
34306		} else {
34307
34308			url = API.APIUrl.toLowerCase().replace("agility-ugc-api-jsonp.svc", "TestBrightcoveAuth.ashx");
34309			url += "?readToken=" + escape(readToken);
34310			url += "&writeToken=" + escape(writeToken);
34311			url += "&method=?";
34312		}
34313		jQuery.getJSON(url, function (retObj) {
34314			var isDisabled = false;
34315			if (retObj.videoIsDisabled != undefined && retObj.videoIsDisabled == true) isDisabled = true;
34316			callback(retObj.valid, retObj.videoExists, isDisabled);
34317		});
34318	};
34319
34320	API.TestYouTubeAuthenticationSettings = function (applicationName, apiKey, username, password, callback) {
34321
34322		var url = API.APIUrl.toLowerCase().replace("agility-ugc-api-jsonp.svc", "TestYouTubeAuth.ashx");
34323		url += "?applicationName=" + escape(applicationName);
34324		url += "&apiKey=" + escape(apiKey);
34325		url += "&username=" + escape(username);
34326		url += "&password=" + escape(password);
34327		url += "&method=?";
34328
34329		jQuery.getJSON(url, callback);
34330	};
34331
34332	API.TestAmazonS3AuthenticationSettings = function (bucket, apiKey, secretKey, callback) {
34333		var url = API.APIUrl.toLowerCase().replace("agility-ugc-api-jsonp.svc", "TestAmazonAuth.ashx");
34334		url += "?apiKey=" + escape(apiKey);
34335		url += "&bucket=" + escape(bucket);
34336		url += "&secretKey=" + escape(secretKey);
34337		url += "&method=?";
34338
34339		jQuery.getJSON(url, callback);
34340
34341	}
34342
34343	API.GenerateTwitterOauthRequestToken = function (key, secret, callback) {
34344
34345		var url = API.APIUrl.toLowerCase().replace("agility-ugc-api-jsonp.svc", "GenerateTwitterOauthRequestToken.ashx");
34346		url += "?accessKey=" + escape(API.APIAccessKey);
34347		url += "&seconds=" + escape(API.APISeconds);
34348		url += "&randomNumber=" + escape(API.APIRandomNumber);
34349		url += "&hash=" + escape(API.APIHash);
34350		url += "&profileRecordID=" + escape(API.APIProfileRecordID);
34351		url += "&appkey=" + escape(key);
34352		url += "&appsecret=" + escape(secret);
34353		url += "&method=?";
34354
34355
34356		jQuery.getJSON(url, callback);
34357
34358	}
34359
34360	API.GetAmazonS3Form = function (options) {
34361
34362		/// <summary>
34363		/// Builds the SWF form uploader that will upload data to Amazon S3.  The HTML will be appended to the jQuery element that is passed into the options argument (options.fieldPanel)
34364		/// </summary>
34365		/// <param name="options">The options for this input. Has the following properties: fieldName, inputID, fieldType  fieldPanel, swfUploadUrl, beforeUpload, uploadComplete, uploadError, uploadProgress, uploadButtonImageUrl, uploadButtonImageHeight, uploadButtonImageWidth, </param>        
34366
34367		if (options == undefined || options == null || typeof (options) == "string") {
34368			throw new Error("The Amazon S3 form parameters have not been set correctly.");
34369		}
34370
34371		var returnUrl = location.href;
34372		var inputID = options.inputID;
34373		var fieldPanel = options.fieldPanel;
34374		var fieldName = options.fieldName;
34375
34376		var fieldType = null;
34377
34378
34379		if (options.fieldType != undefined) fieldType = options.fieldType;
34380
34381		//get the settings...    
34382		API.GetSettings(function (data) {
34383
34384			var html = null;
34385
34386			if (data.ResponseType != API.ResponseType.OK) {
34387				html = jQuery("<span>There was an error building the " + options.fieldName + " input: " + data.Message + "</span>");
34388				html.appendTo(fieldPanel);
34389				return;
34390			} else {
34391
34392				var settings = data.ResponseData;
34393
34394				//if Amazon S3 is NOT enabled, just upload to UGC
34395				if (settings.AmazonS3Bucket == null || settings.AmazonS3Bucket == "") {
34396					API.GetUGCUploadForm(options);
34397					return;
34398				}
34399
34400				//get a new GUID
34401				API.GetGUID(function (dataGUID) {
34402
34403					if (dataGUID.ResponseType != API.ResponseType.OK) {
34404						html = jQuery("<span>There was an error building the " + options.fieldName + " input: " + dataGUID.Message + "</span>");
34405						html.appendTo(fieldPanel);
34406						return;
34407					} else {
34408
34409						var GUID = dataGUID.ResponseData;
34410
34411						//get the current filename stored in the field
34412						var currentFileKey = $("#" + inputID).val();
34413
34414						//build the unique ids
34415						var uniqueID = Agility.UniqueID("post_AmazonFileForm");
34416						var uniqueFormID = uniqueID + "_form";
34417						var uniqueFileUploadID = uniqueID + "_fileupload";
34418
34419						var uniqueSwfUploadID = uniqueID + "_swfupload";
34420						if (options.button_placeholder_id != undefined) {
34421							uniqueSwfUploadID = options.button_placeholder_id;
34422						}
34423						var uniqueIFrameID = uniqueID + "_iframe";
34424						var uniqueUploadProgressID = uniqueID + "_progress";
34425
34426						//check for flash version...						
34427						var flashVersion = Agility.GetFlashVersion();
34428
34429						//build the return url to come back to the blank.htm page
34430
34431						returnUrl = returnUrl.substring(0, returnUrl.indexOf("/", returnUrl.indexOf("//") + 2));
34432						returnUrl += Agility.ResolveUrl("~/AgilityRedirector.htm");
34433
34434						var blankUrl = Agility.ResolveUrl("~/AgilityRedirector.htm");
34435
34436
34437						var amazonS3Url = settings.AmazonS3BaseUrl;
34438						if (amazonS3Url == undefined || amazonS3Url == null || amazonS3Url == "") {
34439							html = jQuery("The Amazon S3 Base Url settings value has not be provided.");
34440							html.appendTo(fieldPanel);
34441							return;
34442						}
34443
34444						if (amazonS3Url.lastIndexOf("/") != amazonS3Url.length - 1) amazonS3Url += "/";
34445
34446						//yyyy-MM-dd\\THH:mm:ss.fff\\Z 
34447						var exDate = new Date();
34448						exDate.setDate(exDate.getDate() + 1);
34449						var expiration = exDate.getFullYear() + "-" + (exDate.getMonth() + 1) + "-" + exDate.getDate() + "T" + exDate.getHours() + ":" + exDate.getMinutes() + ":" + exDate.getSeconds() + "." + exDate.getTimezoneOffset() + "Z";
34450
34451						var baseDirectory = "AgilityUGC/" + GUID;
34452
34453						var contentLengthRangeMin = 0;
34454						var contentLengthRangeMax = 0;
34455						if (fieldType != null && fieldType.MaxLength > 0) {
34456							//convert from kb to bytes...
34457							contentLengthRangeMax = fieldType.MaxLength * 1024;
34458						}
34459
34460						var policy = '{ "expiration": "' + expiration + '", ';
34461						policy += '"conditions": [  ';
34462						policy += '	{"bucket": "' + settings.AmazonS3Bucket + '"}, ';
34463						policy += '	["starts-with", "$key", "' + baseDirectory + '"], ';
34464						policy += '	{"acl": "public-read"}, ';
34465						if (flashVersion <= 8) {
34466							policy += '	{"success_action_redirect": "' + returnUrl + '"}, ';
34467						} else {
34468							policy += '	{"success_action_status": "201"}, ';
34469
34470						}
34471						policy += '	 ["starts-with", "$Content-Type", ""], [ "starts-with", "$filename", "" ], ';
34472						if (contentLengthRangeMax > 0) {
34473							policy += ' ["content-length-range", ' + contentLengthRangeMin + ', ' + contentLengthRangeMax + '], ';
34474						}
34475
34476						policy += '] }';
34477
34478
34479
34480						//build the key
34481						var awsSecretKey = settings.AmazonS3SecretKey;
34482						var awskey = settings.AmazonS3AccessKey;
34483
34484						//get the signature from the UGC Server
34485						API.GetAmazonS3Signature(policy, function (data) {
34486							var policySig = data.ResponseData;
34487
34488
34489							var fileTypes = null;
34490							//assume that the file extensions are the validation.... eg: .*([\.jpg]|[\.gif]|[\.jpeg]|[\.png])						
34491							if (fieldType != null && fieldType.ValidationRegEx != undefined && fieldType.ValidationRegEx != "") {
34492
34493								var validExp = fieldType.ValidationRegEx;
34494								validExp = validExp.replace(".*([\\", "");
34495								validExp = validExp.replace("])", "");
34496
34497								while (validExp.indexOf("]|[\\") != -1) {
34498									validExp = validExp.replace("]|[\\", ";");
34499								}
34500								fileTypes = validExp.replace(/\./g, "*.");
34501
34502							}
34503
34504							//IF FLASH IS ENABLED AND swfUpload is defined...
34505							if (Agility.GetFlashVersion() > 8
34506								&& options.swfUploadUrl != undefined
34507								&& options.swfUploadUrl != null) {
34508								html = jQuery("<span id='" + uniqueSwfUploadID + "'></span>");
34509
34510								html.appendTo(fieldPanel);
34511
34512								var postParams = {
34513									"AWSAccessKeyId": awskey,
34514									"policy": policySig.PolicyBase64,
34515									"acl": "public-read",
34516									"Signature": policySig.Signature,
34517									"success_action_status": "201"
34518								};
34519
34520
34521								//build the upload swf
34522								var swfu = new SWFUpload({
34523									// Backend Settings
34524									upload_url: amazonS3Url,
34525									file_post_name: "file",
34526									post_params: postParams,
34527
34528									// File Upload Settings
34529									file_size_limit: contentLengthRangeMax / 1024,
34530									file_types: fileTypes,
34531									file_types_description: "Valid File Types",
34532									file_upload_limit: "0",    // Zero means unlimited
34533
34534
34535									// Event Handler Settings - these functions as defined in Handlers.js
34536									//  The handlers are not part of SWFUpload but are part of my website and control how
34537									//  my website reacts to the SWFUpload events.
34538									file_queue_error_handler: function (file, errorCode, message) {
34539										jQuery("#" + options.inputID).data("uploading", false);
34540										if (options.uploadError != undefined && jQuery.isFunction(options.uploadError)) {
34541											options.uploadError(file, errorCode, message);
34542										}
34543									},
34544									file_dialog_complete_handler: function (numFilesSelected, numFilesQueued) {
34545										if (numFilesQueued > 0) {
34546											var file = this.getFile();
34547											if (file == null) return;
34548
34549											var filename = file.name;
34550
34551											//get the mimetype
34552											var mimetype = API.GetMIMEtype(filename);
34553											this.addPostParam("Content-Type", API.GetMIMEtype(filename));
34554
34555											//set the key based on the filename, minus any invalid characters...
34556											var filenameStripped = filename.replace(/[^a-zA-Z0-9-_\.]/g, "");
34557											if (filenameStripped == "" || filenameStripped.lastIndexOf(".") == 0) {
34558
34559											}
34560
34561
34562											this.addPostParam("key", baseDirectory + "/" + filenameStripped);
34563
34564											if (options.beforeUpload != undefined && jQuery.isFunction(options.beforeUpload)) {
34565												if (options.beforeUpload(filename, mimetype, file.size, this) == false) {
34566													return;
34567												}
34568											}
34569
34570											jQuery("#" + options.inputID).data("uploading", true);
34571											this.startUpload();
34572										}
34573
34574									},
34575									upload_start_handler: function (file) {
34576										//check that the file name has SOME valid characters in it...
34577										var filenameStripped = file.name.replace(/[^a-zA-Z0-9-_\.]/g, "");
34578										if (filenameStripped == "" || filenameStripped.lastIndexOf(".") == 0) {
34579											return false;
34580										}
34581									},
34582									upload_progress_handler: function (file, bytesLoaded) {
34583										if (options.uploadProgress != undefined && jQuery.isFunction(options.uploadProgress)) {
34584											options.uploadProgress(file, bytesLoaded);
34585										}
34586									},
34587									upload_success_handler: function (file, serverData) {
34588
34589										if (jQuery.browser.msie) {
34590											var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
34591											xmlDoc.loadXML(serverData);
34592											serverData = xmlDoc;
34593										}
34594
34595										//success - set the value of the input and call the event.
34596										var uploadedKey = $(serverData).find("Key").text();
34597										if (uploadedKey == null || uploadedKey == "") {
34598											var filenameStripped = file.name.replace(/[^a-zA-Z0-9-_\.]/g, "");
34599											uploadedKey = baseDirectory + "/" + filenameStripped;
34600										}
34601
34602										jQuery("#" + options.inputID).val(uploadedKey);
34603										jQuery("#" + options.inputID).data("uploading", false);
34604										if (options.uploadComplete != undefined && jQuery.isFunction(options.uploadComplete)) {
34605											options.uploadComplete(uploadedKey, file.size);
34606										}
34607									},
34608									upload_complete_handler: function (file) {
34609										jQuery("#" + options.inputID).data("uploading", false);
34610									},
34611
34612									upload_error_handler: function uploadError(file, errorCode, message) {
34613										jQuery("#" + options.inputID).data("uploading", false);
34614										if (options.uploadError != undefined && jQuery.isFunction(options.uploadError)) {
34615											options.uploadError(file, errorCode, message);
34616										}
34617									},
34618									swfupload_loaded_handler: function () {
34619
34620									},
34621
34622									// Button settings
34623									button_image_url: options.uploadButtonImageUrl,
34624									button_placeholder_id: uniqueSwfUploadID,
34625									button_width: options.uploadButtonImageWidth,
34626									button_height: options.uploadButtonImageHeight,
34627									button_window_mode: SWFUpload.WINDOW_MODE.TRANSPARENT,
34628									button_action: SWFUpload.BUTTON_ACTION.SELECT_FILE,
34629									button_cursor: SWFUpload.CURSOR.HAND,
34630
34631
34632									// Flash Settings
34633									prevent_swf_caching: false,
34634									flash_url: options.swfUploadUrl, // Relative to this file
34635
34636									// Debug Settings
34637									debug: false
34638								});
34639
34640
34641
34642							} else {
34643
34644								//flash not enabled...
34645
34646								//build the html for the form and iframe
34647								var formHtml = "<form  enctype=\"multipart/form-data\" id=\"" + uniqueFormID + "\" method=\"post\" action=\"" + amazonS3Url + "\" target=\"" + uniqueIFrameID + "\"  style=\"display:inline\">";
34648								formHtml += "<input type=\"hidden\" name=\"key\" />";
34649								formHtml += "<input type=\"hidden\" name=\"AWSAccessKeyId\" />";
34650								formHtml += "<input type=\"hidden\" name=\"Content-Type\" value=\"\">";
34651								formHtml += "<input type=\"hidden\" name=\"success_action_redirect\" value=\"" + returnUrl + "\" />";
34652								formHtml += "<input type=\"hidden\" name=\"acl\" value=\"public-read\" />";
34653								formHtml += "<input type=\"hidden\" name=\"policy\" value=\"\" />";
34654								formHtml += "<input type=\"hidden\" name=\"filename\" value=\"\" />";
34655								formHtml += "<input type=\"hidden\" name=\"Signature\" size=\"100\" value=\"\" />";
34656								formHtml += "<input id='" + uniqueFileUploadID + "' type=\"file\" name=\"file\" />";
34657								formHtml += "</form>"
34658								formHtml += "<iframe id=\"" + uniqueIFrameID + "\" name=\"" + uniqueIFrameID + "\" src=\"" + blankUrl + "\" style='position:absolute; height:1px; width: 1px; top:-1px; left: -10000px; overflow:hidden'></iframe>";
34659
34660								//build the jQuery object for the form							
34661								html = jQuery(formHtml);
34662
34663								//add the form to the field panel..							
34664								html.appendTo(fieldPanel);
34665
34666								//set the field values...															
34667								jQuery("input[name='AWSAccessKeyId']", html).val(awskey);
34668								jQuery("input[name='policy']", html).val(policySig.PolicyBase64);
34669								jQuery("input[name='Signature']", html).val(policySig.Signature);
34670
34671
34672
34673								var uploadedFileName = null;
34674
34675								//listen to frame load events																			
34676								jQuery("#" + uniqueIFrameID).load(function () {
34677									//load event of the iframe...
34678
34679									jQuery("#" + uniqueFileUploadID).show();
34680
34681									var loc = null;
34682									try {
34683										loc = $(this.contentDocument.location)
34684									} catch (error) { }
34685
34686									try {
34687
34688										if (loc == undefined || loc == null) {
34689											loc = $(this.contentWindow.location)
34690										}
34691
34692										var href = loc.attr("href");
34693
34694										var key = Agility.QueryString("key", href);
34695										if (key != null && key != "") {
34696											var url = amazonS3Url + key;
34697
34698											//update the input file...
34699											jQuery("#" + inputID).val(key);
34700											$("#" + inputID).data("uploading", false);
34701
34702											//call the uploadComplete event, pass it the key
34703											if (options.uploadComplete != undefined && jQuery.isFunction(options.uploadComplete)) {
34704												options.uploadComplete(key, -1);
34705											}
34706										}
34707									} catch (Error) {
34708										$("#" + inputID).data("uploading", false);
34709
34710
34711										//call the uploadError event, pass it the Error object
34712										var errorMsg = "An error occurred while uploading."
34713										if (contentLengthRangeMax > 0) {
34714											errorMsg += " Please ensure the file is less than " + (contentLengthRangeMax / 1024) + "kb.";
34715										}
34716
34717										if (options.uploadError != undefined && jQuery.isFunction(options.uploadError)) {
34718											options.uploadError("", -1, errorMsg);
34719											throw Error;
34720										} else {
34721											alert(errorMsg);
34722											throw Error;
34723										}
34724									}
34725								});
34726
34727								//listen to file name changed events...							
34728								jQuery("input[name='file']", html).change(function () {
34729									uploadedFileName = $(this).val();
34730
34731									if (uploadedFileName != "") {
34732
34733										//check that filename is of the allowable types...
34734										if (fieldType != null) {
34735											try {
34736												if (!validateFileType(uploadedFileName, fieldType.ValidationRegEx)) {
34737
34738													if (options.uploadError != undefined && jQuery.isFunction(options.uploadError)) {
34739														options.uploadError(uploadedFileName, SWFUpload.QUEUE_ERROR.INVALID_FILETYPE, fieldType.ValidationMessage);
34740													}
34741
34742													$(this).val("");
34743													return;
34744												}
34745
34746											} catch (ex3) {
34747												return;
34748											}
34749										}
34750
34751										//ensure there are some valid characters in there...
34752										var unstrippedName = uploadedFileName;
34753										var uploadedFileName = uploadedFileName.replace(/[^a-zA-Z0-9-_\.]/g, "");
34754										if (uploadedFileName == "" || uploadedFileName.lastIndexOf(".") == 0) {
34755											if (options.uploadError != undefined && jQuery.isFunction(options.uploadError)) {
34756												options.uploadError(unstrippedName, SWFUpload.QUEUE_ERROR.INVALID_FILETYPE, fieldType.ValidationMessage);
34757											}
34758											$(this).val("");
34759											return;
34760										}
34761
34762										//set the "key" field value based on the stripped file name
34763										jQuery("input[name='key']", html).val(baseDirectory + "/" + uploadedFileName);
34764
34765										//get the mimeType of the file
34766										var mimeType = API.GetMIMEtype(uploadedFileName);
34767
34768										var filesize = -1;
34769
34770										try {
34771											if (this.files && this.files.length > 0) {
34772												filesize = this.files[0].size;
34773											}
34774										} catch (error) { }
34775
34776										//fire the beforeUpload event
34777										if (options.beforeUpload != undefined && jQuery.isFunction(options.beforeUpload)) {
34778											if (options.beforeUpload(uploadedFileName, mimeType, filesize, null) == false) {
34779												try {
34780													$(this).val("");
34781												} catch (ex2) { }
34782												return;
34783											}
34784										}
34785
34786
34787										//put a marker on the file to show that it has changed...
34788										$("#" + inputID).data("uploading", true);
34789										$("#" + uniqueFormID + " input[name='Content-Type']").val(mimeType);
34790
34791										//submit the form
34792										var f = jQuery("#" + uniqueFormID);
34793										$(this).hide();
34794										f.submit();
34795
34796										//clear out the input and hide it
34797										try {
34798											$(this).val("");
34799										} catch (ex1) { }
34800
34801									}
34802
34803								});
34804
34805							}
34806
34807						});
34808
34809					}
34810
34811				});
34812
34813			}
34814
34815		});
34816
34817
34818
34819
34820
34821		//bind a "live" event to the remove link (this will work for ANY remove link...);		
34822		if (API._liveAttachmentRemoveHandlerBound != true) {
34823
34824			API._liveAttachmentRemoveHandlerBound = true;
34825
34826			jQuery("form a.UploadedFileRemove").live("click", function () {
34827				if (confirm("Do you wish to delete this file?\n\nYou will not be able to recover this file, and any links to it will be broken")) {
34828
34829					//get the associated field ID from the <form> tag
34830					var associatedFieldID = jQuery(this).parents("form").data("associatedFieldID");
34831
34832					var elem = jQuery(this).parent("span.UploadedFileContainer")
34833					elem.html("Deleting file...");
34834
34835					var key = jQuery("#" + associatedFieldID).val();
34836					API.DeleteFile(key, function (data) {
34837						if (data.ResponseType != 0) {
34838							elem.html("An error occurred: " + data.Message);
34839						} else {
34840							elem.html("");
34841							jQuery("#" + associatedFieldID).val("");
34842						}
34843					});
34844				}
34845			});
34846		}
34847	}
34848
34849	function validateFileType(filepath, validExp) {
34850
34851		if (validExp == null || validExp == "") return true;
34852
34853		validExp = validExp.replace(".*([\\", "");
34854		validExp = validExp.replace("])", "");
34855
34856		while (validExp.indexOf("]|[\\") != -1) {
34857			validExp = validExp.replace("]|[\\", ";");
34858		}
34859		fileTypes = validExp.replace(/\./g, "*.");
34860
34861		var ary = fileTypes.split(";");
34862
34863		var selectedExt = filepath.substring(filepath.lastIndexOf(".")).toLowerCase();
34864		if (selectedExt.indexOf(".") != -1) {
34865			selectedExt = selectedExt.substring(selectedExt.lastIndexOf(".")).toLowerCase();
34866		}
34867
34868		for (var i in ary) {
34869			var ext = $.trim(ary[i]);
34870			if (ext == "" || ext.length < 2 || ext.indexOf("*") != 0) continue;
34871			ext = ext.substring(1).toLowerCase();
34872			if (ext == selectedExt) {
34873				return true;
34874			}
34875		}
34876
34877		return false;
34878
34879	}
34880
34881	API.GetUGCUploadForm = function (options) {
34882
34883		/// <summary>
34884		/// Builds the SWF form uploader that will upload data to UGC.  The HTML will be appended to the jQuery element that is passed into the options argument (options.fieldPanel)
34885		/// </summary>
34886		/// <param name="options">The options for this input. Has the following properties: fieldName, inputID, fieldType  fieldPanel, swfUploadUrl, beforeUpload, uploadComplete, uploadError, uploadProgress, uploadButtonImageUrl, uploadButtonImageHeight, uploadButtonImageWidth, </param>        
34887
34888		if (options == undefined || options == null || typeof (options) == "string") {
34889			throw new Error("The upload form parameters have not been set correctly.");
34890		}
34891
34892		var returnUrl = location.href;
34893		var inputID = options.inputID;
34894		var fieldPanel = options.fieldPanel;
34895		var fieldName = options.fieldName;
34896
34897		var fieldType = null;
34898
34899
34900		if (options.fieldType != undefined) fieldType = options.fieldType;
34901
34902		//get the current filename stored in the field
34903		var currentFileKey = $("#" + inputID).val();
34904
34905		//build the unique ids
34906		var uniqueID = Agility.UniqueID("post_UGCFileForm");
34907		var uniqueFormID = uniqueID + "_form";
34908		var uniqueFileUploadID = uniqueID + "_fileupload";
34909
34910
34911		var uniqueSwfUploadID = uniqueID + "_swfupload";
34912		if (options.button_placeholder_id != undefined) {
34913			uniqueSwfUploadID = options.button_placeholder_id;
34914		}
34915
34916		var uniqueIFrameID = uniqueID + "_iframe";
34917		var uniqueUploadProgressID = uniqueID + "_progress";
34918
34919		//check for flash version...						
34920		var flashVersion = Agility.GetFlashVersion();
34921
34922		//build the return url to come back to the blank.htm page
34923
34924		returnUrl = returnUrl.substring(0, returnUrl.indexOf("/", returnUrl.indexOf("//") + 2));
34925		returnUrl += Agility.ResolveUrl("~/AgilityRedirector.htm");
34926
34927		var blankUrl = Agility.ResolveUrl("~/AgilityRedirector.htm");
34928
34929
34930		var uploadUrl = API.APIUrl;
34931		uploadUrl = uploadUrl.substring(0, uploadUrl.toLowerCase().lastIndexOf("/")) + "/UploadFile.ashx";
34932
34933		//yyyy-MM-dd\\THH:mm:ss.fff\\Z 
34934		var exDate = new Date();
34935		exDate.setDate(exDate.getDate() + 1);
34936		var expiration = exDate.getFullYear() + "-" + (exDate.getMonth() + 1) + "-" + exDate.getDate() + "T" + exDate.getHours() + ":" + exDate.getMinutes() + ":" + exDate.getSeconds() + "." + exDate.getTimezoneOffset() + "Z";
34937
34938		var contentLengthRangeMin = 0;
34939		var contentLengthRangeMax = 0;
34940		if (fieldType != null && fieldType.MaxLength > 0) {
34941			//convert from kb to bytes...
34942			contentLengthRangeMax = fieldType.MaxLength * 1024;
34943		}
34944
34945		var fileTypes = null;
34946		//assume that the file extensions are the validation.... eg: .*([\.jpg]|[\.gif]|[\.jpeg]|[\.png])						
34947		if (fieldType != null && fieldType.ValidationRegEx != undefined && fieldType.ValidationRegEx != "") {
34948
34949			var validExp = fieldType.ValidationRegEx;
34950			validExp = validExp.replace(".*([\\", "");
34951			validExp = validExp.replace("])", "");
34952
34953			while (validExp.indexOf("]|[\\") != -1) {
34954				validExp = validExp.replace("]|[\\", ";");
34955			}
34956			fileTypes = validExp.replace(/\./g, "*.");
34957
34958		}
34959
34960		//IF FLASH IS ENABLED....
34961
34962		if (Agility.GetFlashVersion() > 8
34963			&& options.swfUploadUrl != undefined
34964			&& options.swfUploadUrl != null) {
34965
34966			if (options.button_placeholder_id == undefined) {
34967				html = jQuery("<span id='" + uniqueSwfUploadID + "'></span>");
34968				html.appendTo(fieldPanel);
34969			}
34970
34971			var button_window_mode = SWFUpload.WINDOW_MODE.TRANSPARENT;
34972			if (options.button_window_mode != undefined) button_window_mode = options.button_window_mode;
34973
34974
34975			var postParams = {
34976				"accessKey": API.APIAccessKey,
34977				"seconds": API.APISeconds,
34978				"randomNumber": API.APIRandomNumber,
34979				"hash": API.APIHash,
34980				"profileRecordID": API.APIProfileRecordID
34981			};
34982
34983
34984			//build the upload swf
34985			var swfu = new SWFUpload({
34986				// Backend Settings
34987				upload_url: uploadUrl,
34988				file_post_name: "file",
34989				post_params: postParams,
34990
34991				// File Upload Settings
34992				file_size_limit: contentLengthRangeMax / 1024,
34993				file_types: fileTypes,
34994				file_types_description: "Valid File Types",
34995				file_upload_limit: "0",    // Zero means unlimited
34996
34997
34998				// Event Handler Settings - these functions as defined in Handlers.js
34999				//  The handlers are not part of SWFUpload but are part of my website and control how
35000				//  my website reacts to the SWFUpload events.
35001				file_queue_error_handler: function (file, errorCode, message) {
35002					jQuery("#" + options.inputID).data("uploading", false);
35003					if (options.uploadError != undefined && jQuery.isFunction(options.uploadError)) {
35004						options.uploadError(file, errorCode, message);
35005					}
35006				},
35007				file_dialog_complete_handler: function (numFilesSelected, numFilesQueued) {
35008					if (numFilesQueued > 0) {
35009						var file = this.getFile();
35010						if (file == null) return;
35011
35012						var filename = file.name;
35013
35014						//get the mimetype
35015						var mimetype = API.GetMIMEtype(filename);
35016						this.addPostParam("Content-Type", API.GetMIMEtype(filename));
35017
35018						//set the key based on the filename, minus any invalid characters...
35019						var filenameStripped = filename.replace(/[^a-zA-Z0-9-_\.]/g, "");
35020						if (filenameStripped == "" || filenameStripped.lastIndexOf(".") == 0) {
35021
35022						}
35023
35024
35025						if (options.beforeUpload != undefined && jQuery.isFunction(options.beforeUpload)) {
35026							if (options.beforeUpload(filename, mimetype, file.size, this) == false) {
35027								return;
35028							}
35029						}
35030
35031						jQuery("#" + options.inputID).data("uploading", true);
35032						this.startUpload();
35033					}
35034
35035				},
35036				upload_start_handler: function (file) {
35037					//check that the file name has SOME valid characters in it...
35038					var filenameStripped = file.name.replace(/[^a-zA-Z0-9-_\.]/g, "");
35039					if (filenameStripped == "" || filenameStripped.lastIndexOf(".") == 0) {
35040						return false;
35041					}
35042				},
35043				upload_progress_handler: function (file, bytesLoaded) {
35044					if (options.uploadProgress != undefined && jQuery.isFunction(options.uploadProgress)) {
35045						options.uploadProgress(file, bytesLoaded);
35046					}
35047				},
35048				upload_success_handler: function (file, serverData) {
35049					jQuery("#" + options.inputID).data("uploading", false);
35050
35051					//try {
35052					var responseObj = Agility.JSON.decode(serverData);
35053					if (responseObj.ResponseType != API.ResponseType.OK) {
35054						//an error occurred...
35055						if (options.uploadError != undefined && jQuery.isFunction(options.uploadError)) {
35056							options.uploadError("", -1, responseObj.Message);
35057						}
35058					} else {
35059						//successful upload...
35060						var uploadedFileName = responseObj.ResponseData;
35061
35062						//update the input file...
35063						jQuery("#" + inputID).val(uploadedFileName);
35064
35065
35066						//call the uploadComplete event, pass it the key
35067						if (options.uploadComplete != undefined && jQuery.isFunction(options.uploadComplete)) {
35068							options.uploadComplete(uploadedFileName, -1);
35069						}
35070					}
35071
35072					/*
35073					} catch (error) {
35074						if (options.uploadError != undefined && jQuery.isFunction(options.uploadError)) {
35075							options.uploadError(file, 101, "An error occurred interpretting the results from the server.");
35076						}
35077					}	
35078					*/
35079				},
35080				upload_complete_handler: function (file) {
35081					jQuery("#" + options.inputID).data("uploading", false);
35082				},
35083
35084				upload_error_handler: function uploadError(file, errorCode, message) {
35085					jQuery("#" + options.inputID).data("uploading", false);
35086					if (options.uploadError != undefined && jQuery.isFunction(options.uploadError)) {
35087						options.uploadError(file, errorCode, message);
35088					}
35089				},
35090				swfupload_loaded_handler: function () {
35091
35092				},
35093
35094				// Button settings
35095				button_image_url: options.uploadButtonImageUrl,
35096				button_placeholder_id: uniqueSwfUploadID,
35097				button_width: options.uploadButtonImageWidth,
35098				button_height: options.uploadButtonImageHeight,
35099				button_window_mode: button_window_mode,
35100				button_action: SWFUpload.BUTTON_ACTION.SELECT_FILE,
35101				button_cursor: SWFUpload.CURSOR.HAND,
35102
35103
35104				// Flash Settings
35105				prevent_swf_caching: false,
35106				flash_url: options.swfUploadUrl, // Relative to this file
35107
35108				// Debug Settings
35109				debug: false
35110			});
35111
35112
35113
35114		}
35115		else {
35116
35117			//flash not enabled...
35118
35119			//build the html for the form and iframe
35120			var formHtml = "<form  enctype=\"multipart/form-data\" id=\"" + uniqueFormID + "\" method=\"post\" action=\"" + uploadUrl + "\" target=\"" + uniqueIFrameID + "\"  style=\"display:inline\">";
35121
35122			formHtml += "<input type=\"hidden\" name=\"accessKey\" />";
35123			formHtml += "<input type=\"hidden\" name=\"seconds\" />";
35124			formHtml += "<input type=\"hidden\" name=\"randomNumber\" />";
35125			formHtml += "<input type=\"hidden\" name=\"hash\" />";
35126			formHtml += "<input type=\"hidden\" name=\"profileRecordID\" />";
35127			formHtml += "<input type=\"hidden\" name=\"returnUrl\" />";
35128			formHtml += "<input id='" + uniqueFileUploadID + "' type=\"file\" name=\"file\" />";
35129			formHtml += "</form>"
35130			formHtml += "<iframe id=\"" + uniqueIFrameID + "\" name=\"" + uniqueIFrameID + "\" src=\"" + blankUrl + "\" style='position:absolute; height:1px; width: 1px; top:-1px; left: -10000px; overflow:hidden'></iframe>";
35131
35132			//build the jQuery object for the form							
35133			html = jQuery(formHtml);
35134
35135			//add the form to the field panel..							
35136			html.appendTo(fieldPanel);
35137
35138			//set the field values...															
35139			jQuery("input[name='accessKey']", html).val(API.APIAccessKey);
35140			jQuery("input[name='seconds']", html).val(API.APISeconds);
35141			jQuery("input[name='randomNumber']", html).val(API.APIRandomNumber);
35142			jQuery("input[name='hash']", html).val(API.APIHash);
35143			jQuery("input[name='profileRecordID']", html).val(API.APIProfileRecordID);
35144			jQuery("input[name='returnUrl']", html).val(returnUrl);
35145
35146			var uploadedFileName = null;
35147
35148			//listen to frame load events																			
35149			jQuery("#" + uniqueIFrameID).load(function () {
35150				//load event of the iframe...					
35151				jQuery("#" + uniqueFileUploadID).show();
35152
35153				var loc = null;
35154				try {
35155					loc = $(this.contentDocument.location)
35156				} catch (error) { }
35157
35158				try {
35159
35160					if (loc == undefined || loc == null) {
35161						loc = $(this.contentWindow.location)
35162					}
35163
35164					var href = loc.attr("href");
35165
35166					var responseType = Agility.QueryString("ResponseType", href);
35167					if (responseType == null) return;
35168
35169					if (responseType != API.ResponseType.OK) {
35170						//an error occurred...
35171						var errorMsg = Agility.QueryString("Message", href);
35172
35173						if (options.uploadError != undefined && jQuery.isFunction(options.uploadError)) {
35174							options.uploadError("", -1, errorMsg);
35175						}
35176					} else {
35177						//successful upload...
35178						var uploadedFileName = Agility.QueryString("ResponseData", href);
35179
35180						//update the input file...
35181						jQuery("#" + inputID).val(uploadedFileName);
35182						$("#" + inputID).data("uploading", false);
35183
35184						//call the uploadComplete event, pass it the key
35185						if (options.uploadComplete != undefined && jQuery.isFunction(options.uploadComplete)) {
35186							options.uploadComplete(uploadedFileName, -1);
35187						}
35188					}
35189
35190
35191				} catch (Error) {
35192					$("#" + inputID).data("uploading", false);
35193
35194
35195					//call the uploadError event, pass it the Error object
35196					var errorMsg = "An error occurred while uploading."
35197					if (contentLengthRangeMax > 0) {
35198						errorMsg += " Please ensure the file is less than " + (contentLengthRangeMax / 1024) + "kb.";
35199					}
35200
35201					if (options.uploadError != undefined && jQuery.isFunction(options.uploadError)) {
35202						options.uploadError("", -1, errorMsg);
35203						throw Error;
35204					} else {
35205						alert(errorMsg);
35206						throw Error;
35207					}
35208				}
35209			});
35210
35211			//listen to file name changed events...							
35212			jQuery("input[name='file']", html).change(function () {
35213				var fileElem = $(this);
35214				var fileDom = this;
35215				uploadedFileName = fileElem.val();
35216
35217				if (uploadedFileName != "") {
35218
35219
35220					//check that filename is of the allowable types...
35221					if (fieldType != null) {
35222						try {
35223							if (!validateFileType(uploadedFileName, fieldType.ValidationRegEx)) {
35224
35225								if (options.uploadError != undefined && jQuery.isFunction(options.uploadError)) {
35226									options.uploadError(uploadedFileName, SWFUpload.QUEUE_ERROR.INVALID_FILETYPE, fieldType.ValidationMessage);
35227								}
35228
35229								fileElem.val("");
35230								return;
35231							}
35232
35233						} catch (ex3) {
35234							return;
35235						}
35236					}
35237
35238					//ensure there are some valid characters in there...
35239					var unstrippedName = uploadedFileName;
35240					var uploadedFileName = uploadedFileName.replace(/[^a-zA-Z0-9-_\.]/g, "");
35241					if (uploadedFileName == "" || uploadedFileName.lastIndexOf(".") == 0) {
35242						if (options.uploadError != undefined && jQuery.isFunction(options.uploadError)) {
35243							options.uploadError(unstrippedName, SWFUpload.QUEUE_ERROR.INVALID_FILETYPE, fieldType.ValidationMessage);
35244						}
35245						fileElem.val("");
35246						return;
35247					}
35248
35249
35250					//get the mimeType of the file
35251					var mimeType = API.GetMIMEtype(uploadedFileName);
35252
35253					var uploaderObj = null;
35254					var filesize = -1;
35255
35256					try {
35257						if (fileDom.files && fileDom.files.length > 0) {
35258							filesize = fileDom.files[0].size;
35259						}
35260					} catch (error) { }
35261
35262					//fire the beforeUpload event
35263					if (options.beforeUpload != undefined && jQuery.isFunction(options.beforeUpload)) {
35264						if (options.beforeUpload(uploadedFileName, mimeType, filesize, uploaderObj) == false) {
35265							try {
35266								fileElem.val("");
35267							} catch (ex2) { }
35268							return;
35269						}
35270					}
35271
35272					//put a marker on the file to show that it has changed...
35273					$("#" + inputID).data("uploading", true);
35274					$("#" + uniqueFormID + " input[name='Content-Type']").val(mimeType);
35275
35276					//submit the form
35277					var f = jQuery("#" + uniqueFormID);
35278					fileElem.hide();
35279					f.submit();
35280
35281
35282					//clear out the input and hide it
35283					try {
35284						fileElem.val("");
35285					} catch (ex1) { }
35286
35287				}
35288
35289			});
35290
35291		}
35292
35293
35294
35295		//bind a "live" event to the remove link (this will work for ANY remove link...);		
35296		if (API._liveAttachmentRemoveHandlerBound != true) {
35297
35298			API._liveAttachmentRemoveHandlerBound = true;
35299
35300			jQuery("form a.UploadedFileRemove").live("click", function () {
35301				if (confirm("Do you wish to delete this file?\n\nYou will not be able to re
35301cover this file, and any links to it will be broken")) {
35302
35303					//get the associated field ID from the <form> tag
35304					var associatedFieldID = jQuery(this).parents("form").data("associatedFieldID");
35305
35306					var elem = jQuery(this).parent("span.UploadedFileContainer")
35307					elem.html("Deleting file...");
35308
35309					var key = jQuery("#" + associatedFieldID).val();
35310					API.DeleteFile(key, function (data) {
35311						if (data.ResponseType != 0) {
35312							elem.html("An error occurred: " + data.Message);
35313						} else {
35314							elem.html("");
35315							jQuery("#" + associatedFieldID).val("");
35316						}
35317					});
35318				}
35319			});
35320		}
35321	}
35322
35323
35324	//global variable used to track whether the  live attachment remove randler event has been bound
35325	API._liveAttachmentRemoveHandlerBound = false;
35326
35327
35328
35329	function _buildAPIUrl(methodName, args, query) {
35330		var url = API.APIUrl;
35331		if (url == "" || url == null) return null;
35332		//query should be in the form "q1=q1val&s2=s2val
35333
35334		//ensure the url ends with /
35335		if (url.lastIndexOf("/") != url.length - 1) url += "/";
35336
35337		//create the base url for the call
35338		url += methodName + "/" + API.APIAccessKey + "/" + API.APISeconds + "/" + API.APIRandomNumber + "/" + API.APIHash + "/" + API.APIProfileRecordID;
35339
35340		//add the arguments for call
35341		if (args != undefined && $.isArray(args) && args.length > 0) {
35342			jQuery.each(args, function (index, arg) {
35343				url += "/" + escape(arg);
35344			});
35345		}
35346
35347		//add the "method" param
35348		url += "?method=?";
35349
35350		//add the query strings
35351		if (query != undefined && query != "") {
35352			url += "&" + query;
35353		}
35354
35355		return url;
35356	}
35357
35358
35359
35360	function _submitPostData(url, postData, callback) {
35361
35362		//build the unique ids
35363		var uniqueID = Agility.UniqueID("postDataForm");
35364
35365		var uniqueFormID = uniqueID + "_form";
35366		var uniqueIFrameID = uniqueID + "_iframe";
35367
35368		//build the return url to come back to the AgilityRedirector.htm page
35369		var returnUrl = location.href;
35370		returnUrl = returnUrl.substring(0, returnUrl.indexOf("/", returnUrl.indexOf("//") + 2));
35371		returnUrl += Agility.ResolveUrl("~/AgilityRedirector.htm");
35372
35373		var blankUrl = Agility.ResolveUrl("~/AgilityRedirector.htm?empty=1");
35374
35375		//remove the method callback from the url
35376		url = url.replace("?method=?", "?method=post");
35377
35378		//build the html for the form and iframe
35379		var formHtml = "<div id=\"" + uniqueID + "\" style='display:inline'><form id=\"" + uniqueFormID + "\" method=\"post\" action=\"" + url + "\" target=\"" + uniqueIFrameID + "\">";
35380		if (typeof postData == "string") {
35381			formHtml += "<input type=\"text\" name=\"postdata\" />";
35382		} else {
35383			for (prop in postData) {
35384				formHtml += "<input type=\"text\" name=\"" + prop + "\" />";
35385			}
35386		}
35387		formHtml += "<input type=\"text\" name=\"url\" />";
35388		formHtml += "</form>"
35389		formHtml += "<iframe id=\"" + uniqueIFrameID + "\" name=\"" + uniqueIFrameID + "\" src=\"" + blankUrl + "\"></iframe>";
35390		formHtml += "</div>";
35391
35392
35393		//add the elements to the DOM
35394		var thisBody = jQuery(document.body);
35395		jQuery(thisBody).append(formHtml);
35396
35397		//create the actual DOM elements
35398		var div = jQuery("#" + uniqueID);
35399		var form = jQuery("#" + uniqueFormID);
35400		var iframe = jQuery("#" + uniqueIFrameID);
35401
35402		if (typeof postData == "string") {
35403			$("input[name=postdata]", form).val(postData);
35404		} else {
35405			for (prop in postData) {
35406				$("input[name=" + prop + "]", form).val(postData[prop]);
35407			}
35408		}
35409
35410
35411		$("input[name=url]", form).val(returnUrl);
35412
35413		//capture the load event of the form.
35414		jQuery(iframe).load(function () {
35415
35416			var frm = window.frames[uniqueIFrameID];
35417
35418			var responseType = responseType = API.ResponseType.Error;
35419
35420			var loc = frm.location;
35421
35422			if (loc != null) {
35423				var href = loc.href;
35424
35425				if (Agility.QueryString("empty", href) == "1") {
35426					//wait until the empty iframe has loaded...
35427					//submit the form		
35428					setTimeout(function () {
35429						form.submit();
35430					}, 0);
35431					return;
35432
35433				}
35434
35435				responseType = parseInt(Agility.QueryString("ResponseType", href));
35436				if (isNaN(responseType)) responseType = API.ResponseType.Error;
35437			}
35438
35439
35440			var data = {
35441				ResponseType: responseType,
35442				Message: Agility.QueryString("Message", href),
35443				ResponseData: Agility.QueryString("ResponseData", href)
35444			};
35445
35446			//call the callback
35447			setTimeout(function () {
35448				callback(data);
35449			}, 0);
35450
35451			//remove the elements...						
35452			setTimeout(function () {
35453				div.empty();
35454			}, 0);
35455
35456		});
35457
35458
35459	}
35460
35461
35462	var _authCookieName = null;
35463
35464	API.GetAuthCookieName = function () {
35465		/// <summary>Gets the name of the cookie that will be used for authentication.</summary>
35466		if (_authCookieName == null) _authCookieName = "UGC_AUTH_" + API.APIAccessKey;
35467		return _authCookieName;
35468	}
35469
35470	API.SetAuthCookieName = function (cookieName) {
35471		/// <summary>Gets the name of the cookie that will be used for authentication.</summary>
35472		return _authCookieName = cookieName;
35473	}
35474
35475
35476	API.Logout = function (websiteUserTypeName) {
35477		/// <summary>Logs a user out of the UGC system and removes their login cookie.</summary>
35478		/// <param name="websiteUserTypeName" type="String">The website user type reference name.</param>
35479
35480		//set the cookie based on the API Access Key
35481		var cookieName = API.GetAuthCookieName();
35482		if (websiteUserTypeName != null) cookieName += websiteUserTypeName;
35483		var cookieDate = Date.today().addMonths(-1);
35484		var cookieValue = null;
35485		Agility.SetCookie(cookieName, cookieValue, cookieDate, "/", null, true);
35486
35487	}
35488
35489	API.Authenticate = function (websiteUserTypeName, login, password, persist
35489Cookie, loginFieldName, callback) {
35490		/// <summary>Authenticates a user based on their login and password and their website user type reference name.  Returns the authentication token on success, empty string on failure.  This will also set a cookie that will keep the user logged in for this session, or persist the cookie if desired.</summary>
35491		/// <param name="websiteUserTypeName" type="String">The website user type reference name.</param>
35492		/// <param name="login" type="String">The login, usually a username or email address.</param>
35493		/// <param name="password" type="String">The password.</param>
35494		/// <param name="persistCookie" type="Boolean">(Optional) Whether or not to persist the authentication token in a cookie.</param>		
35495		/// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>
35496
35497		if (callback == undefined) {
35498			if (loginFieldName != undefined && $.isFunction(loginFieldName)) {
35499				callback = loginFieldName;
35500				loginFieldName = "";
35501			}
35502		}
35503
35504		if (callback == undefined) {
35505			if (persistCookie != undefined && $.isFunction(persistCookie)) {
35506				callback = persistCookie;
35507				persistCookie = false;
35508			}
35509		}
35510
35511		if (loginFieldName == undefined) loginFieldName = "";
35512
35513		if (!checkApiIntialized(callback)) return;
35514		var args = new Array();
35515		args.push(websiteUserTypeName);
35516		var argStr = Agility.JSON.encode(websiteUserTypeName);
35517		var url = _buildAPIUrl("Authenticate", args);
35518		url += "&l=" + escape(login) + "&p=" + escape(password) + "&fn=" + escape(loginFieldName);
35519
35520		$.getJSON(url, function (data) {
35521			if (_processOdataError(data, callback)) return;
35522			if (data != undefined) {
35523
35524				var token = data.ResponseData;
35525
35526				if (token != undefined && token != null && token != "") {
35527					//set the cookie based on the API Access Key
35528					var cookieName = API.GetAuthCookieName();
35529					if (websiteUserTypeName != null) cookieName += websiteUserTypeName;
35530
35531					var cookieValue = new String(token);
35532					var cookieDate = null;
35533					if (persistCookie) {
35534						cookieDate = Date.today().addMonths(1);
35535					}
35536					Agility.SetCookie(cookieName, cookieValue, cookieDate, "/", null, false);
35537				}
35538				//return the OK response and the authentication token
35539				callback({
35540					ResponseType: API.ResponseType.OK,
35541					ResponseData: token,
35542					Message: null
35543				});
35544			}
35545		});
35546
35547	}
35548
35549	API.IsAuthenticated = function (websiteUserTypeName, callback) {
35550		/// <summary>Determines if the current user is authenticated and returns the user ID if so.  If the profileRecordID returned is less than zero, the user is NOT authenticated.</summary>
35551		/// <param name="websiteUserTypeName" type="String">The website user type reference name to validate the current used based on.</param>
35552		/// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>
35553
35554		//grab the token the from the cookie
35555		var cookieName = API.GetAuthCookieName();
35556		if (websiteUserTypeName != null) cookieName += websiteUserTypeName;
35557
35558		var token = Agility.GetCookie(cookieName);
35559
35560
35561		if (token == null || token == "") {
35562			callback({
35563				ResponseType: API.ResponseType.OK,
35564				ResponseData: false,
35565				Message: null
35566			});
35567			return;
35568		}
35569
35570		if (!checkApiIntialized(callback)) return;
35571		var args = new Array();
35572		args.push(websiteUserTypeName);
35573
35574		var url = _buildAPIUrl("IsAuthenticated", args);
35575
35576		url += "&s=" + escape(token);
35577
35578		$.getJSON(url, function (data) {
35579			if (data != undefined && data.ResponseData != undefined && data.ResponseData != null) {
35580
35581
35582				var profileRecordID = data.ResponseData.ProfileRecordID;
35583				var seconds = data.ResponseData.Seconds;
35584				var randomNumber = data.ResponseData.RandomNumber;
35585				var hash = data.ResponseData.AccessHash;
35586				var accessKey = data.ResponseData.AccessKey;
35587
35588				//reset the API data for this session
35589				API.APIAccessKey = accessKey;
35590				API.APISeconds = seconds;
35591				API.APIRandomNumber = randomNumber;
35592				API.APIProfileRecordID = profileRecordID;
35593				API.APIHash = hash;
35594
35595				//send results to the user...
35596				callback({
35597					ResponseType: API.ResponseType.OK,
35598					ResponseData: profileRecordID,
35599					Message: null
35600				});
35601			}
35602		});
35603	}
35604
35605	API.ChangePassword = function (currentPassword, newPassword, callback) {
35606		/// <summary>Change the password for the current website user. The ResponseData parameter of the callback will be a true/false if the password change was successful.<summary>
35607		/// <param name="currentPassword" type="String">The user's current password.</param>
35608		/// <param name="newPassword" type="String">The user's new password.</param>
35609		/// <param name="newPassword" type="String">The user's new password.</param>
35610		/// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>
35611
35612		if (API.APIProfileRecordID < 1) {
35613			callback({
35614				ResponseType: API.ResponseType.Error,
35615				ResponseData: false,
35616				Message: "The user is not currently logged in."
35617			});
35618			return;
35619		}
35620
35621
35622
35623		if (!checkApiIntialized(callback)) return;
35624		var args = new Array();
35625
35626		var url = _buildAPIUrl("ChangePassword", args);
35627		url += "&c=" + escape(currentPassword);
35628		url += "&n=" + escape(newPassword);
35629
35630
35631		$.getJSON(url, function (data) {
35632
35633			callback(data);
35634
35635		});
35636	}
35637
35638	API.RetrievePassword = function (websiteUserTypeName, login, callback) {
35639		/// <summary>Retrieve the password for the profile login name and type. The ResponseData parameter of the callback will be a true/false if the password change was successful.<summary>
35640		/// <param name="websiteUserTypeName" type="String">The website user type reference name.</param>
35641		/// <param name="login" type="String">The user's login (usually username or email address).</param>
35642		/// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>
35643
35644
35645		if (!checkApiIntialized(callback)) return;
35646		var args = new Array();
35647		args.push(websiteUserTypeName);
35648
35649		var url = _buildAPIUrl("RetrievePassword", args);
35650		url += "&l=" + escape(login);
35651
35652
35653		$.getJSON(url, function (data) {
35654			if (data != undefined && data.ResponseData != undefined && data.ResponseData != null) {
35655
35656				//send results to the user...
35657				callback({
35658					ResponseType: API.ResponseType.OK,
35659					ResponseData: data.ResponseData,
35660					Message: null
35661				});
35662			}
35663		});
35664	}
35665
35666	API.GetODataMetaData = function (callback) {
35667		/// <summary>Gets the OData meta data for this service.</summary>
35668		var url = _getOdataUrl();
35669		url += "/?$format=json&$callback=?";
35670
35671		$.getJSON(url, function (data) {
35672			if (data != undefined && data.d != undefined && data.d != null) {
35673				if (_processOdataError(data, callback)) return;
35674
35675				if (data.d != undefined && data.d != null) {
35676					callback({
35677						ResponseType: API.ResponseType.OK,
35678						Message: null,
35679						ResponseData: data.d
35680					});
35681				}
35682			}
35683		});
35684
35685	}
35686
35687	API.GetODataFeed = function (recordTypeName, options, callback) {
35688
35689		var url = _getOdataUrl();
35690		url += "/" + recordTypeName + "/";
35691
35692		url += "?$format=json"
35693
35694		if (options != undefined && options != null) {
35695			if (options.filter != undefined && options.filter != null && options.filter != "") {
35696				url += "&$filter=" + escape(options.filter);
35697			}
35698		}
35699
35700		url += "&$callback=?";
35701
35702		$.getJSON(url, function (data) {
35703			if (_processOdataError(data, callback)) return;
35704
35705			if (data != undefined && data != null) {
35706				if (data.d != undefined && data.d != null && data.d.results != undefined && data.d.results != null) {
35707					callback({
35708						ResponseType: API.ResponseType.OK,
35709						Message: null,
35710						ResponseData: data.d.results
35711					});
35712				}
35713			}
35714		});
35715
35716	}
35717
35718
35719
35720	API.GetODataRecord = function (recordTypeName, recordID, callback) {
35721		var url = _getOdataUrl();
35722		url += "/" + recordTypeName + "(" + recordID + ")/";
35723		url += "?$format=json&$callback=?";
35724
35725
35726		$.getJSON(url, function (data) {
35727
35728			if (_processOdataError(data, callback)) return;
35729
35730			if (data != undefined && data != null) {
35731				if (data.d != undefined && data.d != null) {
35732					callback({
35733						ResponseType: API.ResponseType.OK,
35734						Message: null,
35735						ResponseData: data.d
35736					});
35737				}
35738			}
35739
35740		});
35741
35742	}
35743
35744
35745	API.ExecCustomProcedure = function (proc, paramArgs, callback) {
35746		var url = Agility.UGC.API.APIUrl;
35747		url = url.toLowerCase().replace("agility-ugc-api-jsonp.svc", "ExecCustomProcedure.ashx");
35748		url += "?proc=" + escape(proc);
35749
35750		if (paramArgs != undefined && paramArgs != null) {
35751			for (var propertyName in paramArgs) {
35752				var val = paramArgs[propertyName];
35753				if (val == undefined || val == null) continue;
35754				url += "&@" + escape(propertyName) + "=" + escape(paramArgs[propertyName]);
35755			}
35756		}
35757		url += "&method=?";
35758		url += "&format=json";
35759		url += "&accessKey=" + escape(API.APIAccessKey);
35760		url += "&seconds=" + escape(API.APISeconds);
35761		url += "&randomNumber=" + escape(API.APIRandomNumber);
35762		url += "&hash=" + escape(API.APIHash);
35763		url += "&profileRecordID=" + escape(API.APIProfileRecordID);
35764
35765		$.getJSON(url, function (data) {
35766
35767			if (data != undefined) {
35768
35769				var obj = {
35770					ResponseType: API.ResponseType.OK,
35771					Message: null
35772				};
35773
35774				if (data.ResonseData != undefined) {
35775					obj.ResponseData = data.ResonseData;
35776				} else {
35777					obj.ResponseData = data.ResponseData;
35778				}
35779
35780
35781				//send results to the user...
35782				callback(obj);
35783			}
35784		});
35785	}
35786
35787	function _getOdataUrl() {
35788		//url will look like this http://ugc.agilitycms.com/Agility-UGC-API-JSONP.svc
35789		//needs to be transformed to this http://ugc.agilitycms.com/Agility-UGC-API-ODATA.svc
35790		var url = API.APIUrl;
35791		url = url.substring(0, url.toLowerCase().lastIndexOf("/")) + "/Agility-UGC-API-ODATA.svc";
35792		return url;
35793	}
35794
35795	//does the error callback from OData and returns true if there was an error.
35796	function _processOdataError(data, callback) {
35797
35798		if (data != undefined && data != null) {
35799			if (data.error != undefined && data.error != null) {
35800				var message = "An error occurred.";
35801
35802				if (data.error.message != undefined && data.error.message.value != undefined) {
35803					message = data.error.message.value;
35804				}
35805				callback({
35806					ResponseType: API.ResponseType.Error,
35807					Message: message,
35808					ResponseData: null
35809				});
35810				return true;
35811			}
35812		}
35813	}
35814
35815
35816	API.GetMIMEtype = function (filename) {
35817		/// <summary>
35818		/// Gets the mime-type of a file based on a filename.
35819		/// </summary>
35820		/// <param name="filename" type="String">The file name (from a file upload...)</param>
35821
35822
35823		var fn = new String(filename);
35824		var fn1 = new String();
35825		fn1 = fn.match(/[\/\\][^\/\\]*$/);
35826		if (fn1 != null && fn1.length > 0) fn = fn1 + "";
35827
35828		fn = fn.toLowerCase();
35829
35830		if (fn.search(/^.*\.ai$/) >= 0) {
35831			return ("application/illustrator");
35832		}
35833		if (fn.search(/^.*\.bin$/) >= 0) {
35834			return ("application/octet-stream");
35835		}
35836		if (fn.search(/^.*\.pdf$/) >= 0) {
35837			return ("application/pdf");
35838		}
35839		if (fn.search(/^.*\.ps$/) >= 0) {
35840			return ("application/postscript");
35841		}
35842		if (fn.search(/^.*\.rtf$/) >= 0) {
35843			return ("application/rtf");
35844		}
35845		if (fn.search(/^.*\.sit$/) >= 0) {
35846			return ("application/stuffit");
35847		}
35848		if (fn.search(/^.*\.flv$/) >= 0) {
35849			return ("video/x-flv");
35850		}
35851		if (fn.search(/^.*\.mdb$/) >= 0) {
35852			return ("application/vnd.ms-access");
35853		}
35854		if (fn.search(/^.*\.xls$/) >= 0) {
35855			return ("application/vnd.ms-excel");
35856		}
35857		if (fn.search(/^.*\.ppt$/) >= 0) {
35858			return ("application/vnd.ms-powerpoint");
35859		}
35860		if (fn.search(/^.*\.pps$/) >= 0) {
35861			return ("application/vnd.ms-powerpoint");
35862		}
35863		if (fn.search(/^.*\.pot$/) >= 0) {
35864			return ("application/vnd.ms-powerpoint");
35865		}
35866		if (fn.search(/^.*\.xps$/) >= 0) {
35867			return ("application/vnd.ms-xpsdocument");
35868		}
35869		if (fn.search(/^.*\.doc$/) >= 0) {
35870			return ("application/msword");
35871		}
35872		if (fn.search(/^.*\.7z$/) >= 0) {
35873			return ("application/x-7z-compressed");
35874		}
35875		if (fn.search(/^.*\.torrent$/) >= 0) {
35876			return ("application/x-bittorrent");
35877		}
35878		if (fn.search(/^.*\.tar\.gz$/) >= 0) {
35879			return ("application/x-compressed-tar");
35880		}
35881		if (fn.search(/^.*\.tgz$/) >= 0) {
35882			return ("application/x-compressed-tar");
35883		}
35884		if (fn.search(/^.*\.ttf$/) >= 0) {
35885			return ("application/x-font-ttf");
35886		}
35887		if (fn.search(/^.*\.gz$/) >= 0) {
35888			return ("application/x-gzip");
35889		}
35890		if (fn.search(/^.*\.pdf\.gz$/) >= 0) {
35891			return ("application/x-gzpdf");
35892		}
35893		if (fn.search(/^.*\.ps\.gz$/) >= 0) {
35894			return ("application/x-gzpostscript");
35895		}
35896		if (fn.search(/^.*\.jar$/) >= 0) {
35897			return ("application/x-java-archive");
35898		}
35899		if (fn.search(/^.*\.js$/) >= 0) {
35900			return ("application/javascript");
35901		}
35902		if (fn.search(/^.*\.lzh$/) >= 0) {
35903			return ("application/x-lha");
35904		}
35905		if (fn.search(/^.*\.mkv$/) >= 0) {
35906			return ("video/x-matroska");
35907		}
35908		if (fn.search(/^.*\.exe$/) >= 0) {
35909			return ("application/x-ms-dos-executable");
35910		}
35911		if (fn.search(/^.*\.ogg$/) >= 0) {
35912			return ("application/ogg");
35913		}
35914		if (fn.search(/^.*\.ogx$/) >= 0) {
35915			return ("application/ogg");
35916		}
35917		if (fn.search(/^.*\.oga$/) >= 0) {
35918			return ("audio/ogg");
35919		}
35920		if (fn.search(/^.*\.ogv$/) >= 0) {
35921			return ("video/ogg");
35922		}
35923		if (fn.search(/^.*\.ogg$/) >= 0) {
35924			return ("audio/x-vorbis+ogg");
35925		}
35926		if (fn.search(/^.*\.ogg$/) >= 0) {
35927			return ("audio/x-flac+ogg");
35928		}
35929		if (fn.search(/^.*\.ogg$/) >= 0) {
35930			return ("audio/x-speex+ogg");
35931		}
35932		if (fn.search(/^.*\.spx$/) >= 0) {
35933			return ("audio/x-speex");
35934		}
35935		if (fn.search(/^.*\.ogg$/) >= 0) {
35936			return ("video/x-theora+ogg");
35937		}
35938		if (fn.search(/^.*\.ogm$/) >= 0) {
35939			return ("video/x-ogm+ogg");
35940		}
35941		if (fn.search(/^.*\.qtl$/) >= 0) {
35942			return ("application/x-quicktime-media-link");
35943		}
35944		if (fn.search(/^.*\.tar$/) >= 0) {
35945			return ("application/x-tar");
35946		}
35947		if (fn.search(/^.*\.theme$/) >= 0) {
35948			return ("application/x-theme");
35949		}
35950		if (fn.search(/^.*\.der$/) >= 0) {
35951			return ("application/x-x509-ca-cert");
35952		}
35953		if (fn.search(/^.*\.cer$/) >= 0) {
35954			return ("application/x-x509-ca-cert");
35955		}
35956		if (fn.search(/^.*\.crt$/) >= 0) {
35957			return ("application/x-x509-ca-cert");
35958		}
35959		if (fn.search(/^.*\.cert$/) >= 0) {
35960			return ("application/x-x509-ca-cert");
35961		}
35962		if (fn.search(/^.*\.pem$/) >= 0) {
35963			return ("application/x-x509-ca-cert");
35964		}
35965		if (fn.search(/^.*\.xhtml$/) >= 0) {
35966			return ("application/xhtml+xml");
35967		}
35968		if (fn.search(/^.*\.zip$/) >= 0) {
35969			return ("application/zip");
35970		}
35971		if (fn.search(/^.*\.ac3$/) >= 0) {
35972			return ("audio/ac3");
35973		}
35974		if (fn.search(/^.*\.aiff$/) >= 0) {
35975			return ("audio/x-aiff");
35976		}
35977		if (fn.search(/^.*\.aif$/) >= 0) {
35978			return ("audio/x-aiff");
35979		}
35980		if (fn.search(/^.*\.aifc$/) >= 0) {
35981			return ("audio/x-aiff");
35982		}
35983		if (fn.search(/^.*\.flac$/) >= 0) {
35984			return ("audio/x-flac");
35985		}
35986		if (fn.search(/^.*\.mid$/) >= 0) {
35987			return ("audio/midi");
35988		}
35989		if (fn.search(/^.*\.midi$/) >= 0) {
35990			return ("audio/midi");
35991		}
35992		if (fn.search(/^.*\.kar$/) >= 0) {
35993			return ("audio/midi");
35994		}
35995		if (fn.search(/^.*\.m4a$/) >= 0) {
35996			return ("audio/mp4");
35997		}
35998		if (fn.search(/^.*\.aac$/) >= 0) {
35999			return ("audio/mp4");
36000		}
36001		if (fn.search(/^.*\.mp4$/) >= 0) {
36002			return ("video/mp4");
36003		}
36004		if (fn.search(/^.*\.m4v$/) >= 0) {
36005			return ("video/mp4");
36006		}
36007		if (fn.search(/^.*\.m4b$/) >= 0) {
36008			return ("audio/x-m4b");
36009		}
36010		if (fn.search(/^.*\.3gp$/) >= 0) {
36011			return ("video/3gpp");
36012		}
36013		if (fn.search(/^.*\.3gpp$/) >= 0) {
36014			return ("video/3gpp");
36015		}
36016		if (fn.search(/^.*\.amr$/) >= 0) {
36017			return ("video/3gpp");
36018		}
36019		if (fn.search(/^.*\.mp2$/) >= 0) {
36020			return ("audio/mp2");
36021		}
36022		if (fn.search(/^.*\.mp3$/) >= 0) {
36023			return ("audio/mpeg");
36024		}
36025		if (fn.search(/^.*\.mpga$/) >= 0) {
36026			return ("audio/mpeg");
36027		}
36028		if (fn.search(/^.*\.m3u$/) >= 0) {
36029			return ("audio/x-mpegurl");
36030		}
36031		if (fn.search(/^.*\.vlc$/) >= 0) {
36032			return ("audio/x-mpegurl");
36033		}
36034		if (fn.search(/^.*\.asx$/) >= 0) {
36035			return ("audio/x-ms-asx");
36036		}
36037		if (fn.search(/^.*\.wax$/) >= 0) {
36038			return ("audio/x-ms-asx");
36039		}
36040		if (fn.search(/^.*\.wvx$/) >= 0) {
36041			return ("audio/x-ms-asx");
36042		}
36043		if (fn.search(/^.*\.wmx$/) >= 0) {
36044			return ("audio/x-ms-asx");
36045		}
36046		if (fn.search(/^.*\.psf$/) >= 0) {
36047			return ("audio/x-psf");
36048		}
36049		if (fn.search(/^.*\.wma$/) >= 0) {
36050			return ("audio/x-ms-wma");
36051		}
36052		if (fn.search(/^.*\.ra$/) >= 0) {
36053			return ("audio/vnd.rn-realaudio");
36054		}
36055		if (fn.search(/^.*\.rax$/) >= 0) {
36056			return ("audio/vnd.rn-realaudio");
36057		}
36058		if (fn.search(/^.*\.ram$/) >= 0) {
36059			return ("application/ram");
36060		}
36061		if (fn.search(/^.*\.rv$/) >= 0) {
36062			return ("video/vnd.rn-realvideo");
36063		}
36064		if (fn.search(/^.*\.rvx$/) >= 0) {
36065			return ("video/vnd.rn-realvideo");
36066		}
36067		if (fn.search(/^.*\.wav$/) >= 0) {
36068			return ("audio/x-wav");
36069		}
36070		if (fn.search(/^.*\.bmp$/) >= 0) {
36071			return ("image/bmp");
36072		}
36073		if (fn.search(/^.*\.wbmp$/) >= 0) {
36074			return ("image/vnd.wap.wbmp");
36075		}
36076		if (fn.search(/^.*\.gif$/) >= 0) {
36077			return ("image/gif");
36078		}
36079		if (fn.search(/^.*\.jpeg$/) >= 0) {
36080			return ("image/jpeg");
36081		}
36082		if (fn.search(/^.*\.jpg$/) >= 0) {
36083			return ("image/jpeg");
36084		}
36085		if (fn.search(/^.*\.jpe$/) >= 0) {
36086			return ("image/jpeg");
36087		}
36088		if (fn.search(/^.*\.png$/) >= 0) {
36089			return ("image/png");
36090		}
36091		if (fn.search(/^.*\.rle$/) >= 0) {
36092			return ("image/rle");
36093		}
36094		if (fn.search(/^.*\.svg$/) >= 0) {
36095			return ("image/svg+xml");
36096		}
36097		if (fn.search(/^.*\.svgz$/) >= 0) {
36098			return ("image/svg+xml-compressed");
36099		}
36100		if (fn.search(/^.*\.tif$/) >= 0) {
36101			return ("image/tiff");
36102		}
36103		if (fn.search(/^.*\.tiff$/) >= 0) {
36104			return ("image/tiff");
36105		}
36106		if (fn.search(/^.*\.eps$/) >= 0) {
36107			return ("image/x-eps");
36108		}
36109		if (fn.search(/^.*\.ico$/) >= 0) {
36110			return ("image/x-ico");
36111		}
36112		if (fn.search(/^.*\.psd$/) >= 0) {
36113			return ("image/x-psd");
36114		}
36115		if (fn.search(/^.*\.vcs$/) >= 0) {
36116			return ("text/calendar");
36117		}
36118		if (fn.search(/^.*\.ics$/) >= 0) {
36119			return ("text/calendar");
36120		}
36121		if (fn.search(/^.*\.css$/) >= 0) {
36122			return ("text/css");
36123		}
36124		if (fn.search(/^.*\.CSSL$/) >= 0) {
36125			return ("text/css");
36126		}
36127		if (fn.search(/^.*\.rtx$/) >= 0) {
36128			return ("text/richtext");
36129		}
36130		if (fn.search(/^.*\.rss$/) >= 0) {
36131			return ("application/rss+xml");
36132		}
36133		if (fn.search(/^.*\.atom$/) >= 0) {
36134			return ("application/atom+xml");
36135		}
36136		if (fn.search(/^.*\.opml$/) >= 0) {
36137			return ("text/x-opml+xml");
36138		}
36139		if (fn.search(/^.*\.sgml$/) >= 0) {
36140			return ("text/sgml");
36141		}
36142		if (fn.search(/^.*\.sgm$/) >= 0) {
36143			return ("text/sgml");
36144		}
36145		if (fn.search(/^.*\.dtd$/) >= 0) {
36146			return ("text/x-dtd");
36147		}
36148		if (fn.search(/^.*\.html$/) >= 0) {
36149			return ("text/html");
36150		}
36151		if (fn.search(/^.*\.htm$/) >= 0) {
36152			return ("text/html");
36153		}
36154		if (fn.search(/^.*\.log$/) >= 0) {
36155			return ("text/x-log");
36156		}
36157		if (fn.search(/^README*$/) >= 0) {
36158			return ("text/x-readme");
36159		}
36160		if (fn.search(/^.*\.uri$/) >= 0) {
36161			return ("text/x-uri");
36162		}
36163		if (fn.search(/^.*\.url$/) >= 0) {
36164			return ("text/x-uri");
36165		}
36166		if (fn.search(/^.*\.fo$/) >= 0) {
36167			return ("text/x-xslfo");
36168		}
36169		if (fn.search(/^.*\.xslfo$/) >= 0) {
36170			return ("text/x-xslfo");
36171		}
36172		if (fn.search(/^.*\.xml$/) >= 0) {
36173			return ("application/xml");
36174		}
36175		if (fn.search(/^.*\.xsl$/) >= 0) {
36176			return ("application/xml");
36177		}
36178		if (fn.search(/^.*\.xslt$/) >= 0) {
36179			return ("application/xml");
36180		}
36181		if (fn.search(/^.*\.xbl$/) >= 0) {
36182			return ("application/xml");
36183		}
36184		if (fn.search(/^.*\.mpeg$/) >= 0) {
36185			return ("video/mpeg");
36186		}
36187		if (fn.search(/^.*\.mpg$/) >= 0) {
36188			return ("video/mpeg");
36189		}
36190		if (fn.search(/^.*\.mp2$/) >= 0) {
36191			return ("video/mpeg");
36192		}
36193		if (fn.search(/^.*\.mpe$/) >= 0) {
36194			return ("video/mpeg");
36195		}
36196		if (fn.search(/^.*\.vob$/) >= 0) {
36197			return ("video/mpeg");
36198		}
36199		if (fn.search(/^.*\.m2t$/) >= 0) {
36200			return ("video/mpeg");
36201		}
36202		if (fn.search(/^.*\.qt$/) >= 0) {
36203			return ("video/quicktime");
36204		}
36205		if (fn.search(/^.*\.mov$/) >= 0) {
36206			return ("video/quicktime");
36207		}
36208		if (fn.search(/^.*\.moov$/) >= 0) {
36209			return ("video/quicktime");
36210		}
36211		if (fn.search(/^.*\.qtvr$/) >= 0) {
36212			return ("video/quicktime");
36213		}
36214		if (fn.search(/^.*\.qtif$/) >= 0) {
36215			return ("image/x-quicktime");
36216		}
36217		if (fn.search(/^.*\.qif$/) >= 0) {
36218			return ("image/x-quicktime");
36219		}
36220		if (fn.search(/^.*\.viv$/) >= 0) {
36221			return ("video/vivo");
36222		}
36223		if (fn.search(/^.*\.vivo$/) >= 0) {
36224			return ("video/vivo");
36225		}
36226		if (fn.search(/^.*\.anim[1-9j]$/) >= 0) {
36227			return ("video/x-anim");
36228		}
36229		if (fn.search(/^.*\.fli$/) >= 0) {
36230			return ("video/x-flic");
36231		}
36232		if (fn.search(/^.*\.flc$/) >= 0) {
36233			return ("video/x-flic");
36234		}
36235		if (fn.search(/^.*\.hwp$/) >= 0) {
36236			return ("application/x-hwp");
36237		}
36238		if (fn.search(/^.*\.hwt$/) >= 0) {
36239			return ("application/x-hwt");
36240		}
36241		if (fn.search(/^.*\.mng$/) >= 0) {
36242			return ("video/x-mng");
36243		}
36244		if (fn.search(/^.*\.asf$/) >= 0) {
36245			return ("video/x-ms-asf");
36246		}
36247		if (fn.search(/^.*\.nsc$/) >= 0) {
36248			return ("application/x-netshow-channel");
36249		}
36250		if (fn.search(
36250/^.*\.wmv$/) >= 0) {
36251			return ("video/x-ms-wmv");
36252		}
36253		if (fn.search(/^.*\.avi$/) >= 0) {
36254			return ("video/x-msvideo");
36255		}
36256		if (fn.search(/^.*\.divx$/) >= 0) {
36257			return ("video/x-msvideo");
36258		}
36259		return ("binary/octet-stream");
36260	}
36261
36262
36263
36264})(Agility.UGC.API);;
36265/*! Agility CMS API
36266*/
36267/// <reference path="Agility.js" />
36268
36269
36270Agility.RegisterNamespace("Agility.CMS.API");
36271
36272(function(API) {
36273
36274	//CONSTANTS
36275	API.EMPTY_GUID = "00000000-0000-0000-0000-000000000000";
36276	
36277	API.Initialized = false;
36278
36279	API.APIUrl = "";
36280
36281	API.OnInit = function(API_Url, API_WebsiteName) {
36282		/// <summary>
36283		/// Initialize the Agility Content Server API
36284		/// </summary>
36285		/// <param name="API_Url" type="String">The URL to the Agility Server REST API.</param>        
36286		/// <param name="API_WebsiteName" type="String">The Website Name.</param>        
36287        
36288		if (API_Url != undefined && API_Url != null) {
36289			API.APIUrl = API_Url;
36290		}
36291		API.APIWebsiteName = API_WebsiteName;		
36292		API.Initialized = true;
36293
36294	}
36295
36296	
36297
36298	function checkApiIntialized(callback) {
36299
36300		if (API.APIUrl == null || API.APIUrl == "" || API.APIWebsiteName == undefined) {
36301			callback({
36302				IsError: true,
36303				Message: "The Agility CMS API has not been initialized.",
36304				ResponseData: null
36305			});
36306
36307			return false;
36308		}
36309
36310		return true;
36311	}
36312
36313
36314	
36315
36316	API.SelectContentItems = function(searchArg, hash, callback) {
36317		/// <summary>
36318		/// Get a list of content items based on a search criteria.
36319		/// </summary>
36320		/// <param name="searchArg" type="Object">Object with the following: referenceName, pageSize, rowOffset, searchFilter, sortField, sortDirection.</param>
36321		/// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {IsError, ResponseData, Message}.</param>
36322		/*
36323			referenceName
36324			pageSize
36325			rowOffset
36326			searchFilter
36327			sortField
36328			sortDirection
36329		*/		
36330
36331		/*
36332		Filter syntax:
36333		To search for a field called "IntTest"
36334			x.xmlData.value('(CI/I/IntTest)[1]', 'int') > 1
36335		To search for Title:
36336			x.Title = 'this is a title'
36337		To search for TextBlob:
36338			x.TextBlob = 'this is a textblob'
36339		To search for state:
36340			state = 'Staging'
36341		
36342		*/
36343
36344
36345		if (!checkApiIntialized(callback)) return;
36346		searchArg.hash = hash;
36347		var url = _buildAPIUrl("SelectContentItems", searchArg);
36348
36349		jQuery.getJSON(url, callback);
36350	}
36351
36352	API.GetContentItem = function(arg, hash, callback) {
36353		/// <summary>
36354		/// Get a Content Item based on its ID and Language
36355		/// </summary>
36356		/// <param name="arg" type="Function">Object with: contentID, languageCode</param>
36357		/// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {IsError, ResponseData, Message}.</param>      
36358
36359		if (!checkApiIntialized(callback)) return;
36360
36361		/*
36362		
36363		*/
36364
36365		arg.hash = hash;
36366
36367		var url = _buildAPIUrl("GetContentItem", arg);
36368
36369		jQuery.getJSON(url, callback);
36370	}
36371
36372	API.RequestApproval = function(arg, hash, callback) {
36373		/// <summary>
36374		/// Request approval for a piece of content.
36375		/// </summary>
36376		/// <param name="arg" type="Function">Object with: contentID, languageCode</param>
36377		/// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {IsError, ResponseData, Message}.</param>      
36378
36379		if (!checkApiIntialized(callback)) return;
36380
36381		arg.hash = hash;
36382
36383		var url = _buildAPIUrl("RequestApproval",arg);
36384		jQuery.getJSON(url, callback);
36385	}
36386
36387
36388	API.GetThumbnailRootUrl = function(hash, callback) {
36389		if (!checkApiIntialized(callback)) return;
36390
36391		var arg = {hash: hash};
36392
36393		var url = _buildAPIUrl("GetThumbnailRootUrl", arg);
36394
36395		jQuery.getJSON(url, callback);
36396	}
36397
36398
36399	API.PublishContent = function(arg, hash, callback) {
36400		/// <summary>
36401		/// Publish a piece of content.
36402		/// </summary>
36403		/// <param name="arg" type="Function">Object with: contentID, languageCode</param>
36404		/// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {IsError, ResponseData, Message}.</param>      
36405
36406		if (!checkApiIntialized(callback)) return;
36407
36408		arg.hash = hash;
36409
36410		var url = _buildAPIUrl("PublishContent", arg);
36411
36412		jQuery.getJSON(url, callback);
36413	}
36414
36415	API.DeleteContent = function(arg, hash, callback) {
36416		/// <summary>
36417		/// Delete a piece of content.
36418		/// </summary>
36419		/// <param name="arg" type="Function">Object with: contentID, languageCode</param>
36420		/// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {IsError, ResponseData, Message}.</param>      
36421
36422		if (!checkApiIntialized(callback)) return;
36423
36424		arg.hash = hash;
36425
36426		var url = _buildAPIUrl("DeleteContent", arg);
36427
36428		jQuery.getJSON(url, callback);
36429	}
36430	
36431	API.SaveContentItem = function(arg, contentItem, attachments, hash, callback) {
36432		/// <summary>
36433		/// Saves a record type.
36434		/// </summary>
36435		/// <param name="contentID">The content ID to update (-1 if new).</param>      
36436		/// <param name="contentItem">The content Item to save.</param>      
36437		/// <param name="attachments">List of NEW attachments on this item (null if no new attachments).</param>      		
36438		/// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      
36439
36440		if (!checkApiIntialized(callback)) return;
36441
36442		var contentItemStr = Agility.JSON.encode(contentItem);
36443		var attachmentStr = null;
36444		if (attachments != null && attachments.length > 0) {
36445			attachmentStr = Agility.JSON.encode(attachments);
36446		}
36447
36448		arg.hash = hash;
36449
36450		var url = _buildAPIUrl("SaveContentItem", arg);
36451
36452		_submitPostData(url, {contentItem:contentItemStr, attachments:attachmentStr}, callback);
36453	}
36454
36455	function _buildAPIUrl(methodName, args) {
36456		var url = API.APIUrl;
36457		if (url == "" || url == null) return null;
36458		
36459		//ensure the url ends with /
36460		if (url.lastIndexOf("/") != url.length - 1) url += "/";
36461
36462		//create the base url for the call
36463		url += methodName + "?callback=?&website=" + escape(API.APIWebsiteName);
36464
36465
36466		for (var prop in args) {
36467			url += "&" + prop + "=" + escape(args[prop]);
36468	    }
36469
36470		return url;
36471	}
36472
36473
36474
36475	function _submitPostData(url, postData, callback) {
36476
36477		//build the unique ids
36478		var uniqueID = Agility.UniqueID("postDataForm");
36479
36480		var uniqueFormID = uniqueID + "_form";
36481		var uniqueIFrameID = uniqueID + "_iframe";
36482
36483		//build the return url to come back to the AgilityRedirector.htm page
36484		var returnUrl = location.href;
36485		returnUrl = returnUrl.substring(0, returnUrl.indexOf("/", returnUrl.indexOf("//") + 2));
36486		returnUrl += Agility.ResolveUrl("~/AgilityRedirector.htm");
36487
36488		var blankUrl = Agility.ResolveUrl("~/AgilityRedirector.htm");
36489
36490		//remove the method callback from the url
36491		url = url.replace("?callback=?", "?returnurl=" + escape(returnUrl));
36492
36493		//build the html for the form and iframe
36494		var formHtml = "<div id=\"" + uniqueID + "\" style='display:none'><form id=\"" + uniqueFormID + "\" method=\"post\" action=\"" + url + "\" target=\"" + uniqueIFrameID + "\">";
36495		if (typeof postData == "string") {
36496			formHtml += "<input type=\"text\" name=\"postdata\" />";
36497		} else {
36498			for(prop in postData)
36499			{
36500				formHtml += "<input type=\"text\" name=\""+prop+"\" />";
36501			}
36502		}
36503		formHtml += "<input type=\"text\" name=\"url\" />";
36504		formHtml += "</form>"
36505		formHtml += "<iframe id=\"" + uniqueIFrameID + "\" name=\"" + uniqueIFrameID + "\" src=\"" + blankUrl + "\"></iframe>";
36506		formHtml += "</div>";
36507
36508
36509		//add the elements to the DOM
36510		var thisBody = jQuery(document.body);
36511		jQuery(thisBody).append(formHtml);
36512
36513		//create the actual DOM elements
36514		var div = jQuery("#" + uniqueID);
36515		var form = jQuery("#" + uniqueFormID);
36516		var iframe = jQuery("#" + uniqueIFrameID);
36517
36518		if (typeof postData == "string") {
36519			$("input[name=postdata]", form).val(postData);
36520		} else {
36521			for(prop in postData)
36522			{
36523				$("input[name="+prop+"]", form).val(postData[prop]);			
36524			}
36525		}
36526
36527
36528		//capture the load event of the form.
36529		jQuery(iframe).load(function() {
36530
36531			var frm = window.frames[uniqueIFrameID];
36532
36533			var isError = true;
36534
36535			var loc = frm.location;
36536
36537			if (loc != null) {
36538				var href = loc.href;
36539				var errTest = Agility.QueryString("IsError", href);
36540				if (errTest == null) errTest = "true";
36541				isError = errTest.toLowerCase() == "true";				
36542			}
36543
36544
36545			var data = {
36546				IsError: isError,
36547				Message: Agility.QueryString("Message", href),
36548				ResponseData: Agility.QueryString("ResponseData", href)
36549			};
36550
36551			//call the callback
36552			setTimeout(function() {
36553				callback(data);
36554			}, 0);
36555
36556			//remove the elements...						
36557			setTimeout(function() {
36558				div.empty();
36559			}, 0);
36560
36561		});
36562
36563		//submit the form
36564		form.submit();
36565	}
36566
36567
36568
36569	
36570
36571})(Agility.CMS.API);;
36572// -- Sammy.js -- /sammy.js
36573// http://sammyjs.org
36574// Version: 0.7.6
36575// Built: 2014-08-26 10:45:34 +0300
36576(function (factory) { if (typeof define === "function" && define.amd) { define(["jquery"], factory) } else { jQuery.sammy = window.Sammy = factory(jQuery) } })(function ($) { var Sammy, PATH_REPLACER = "([^/]+)", PATH_NAME_MATCHER = /:([\w\d]+)/g, QUERY_STRING_MATCHER = /\?([^#]*)?$/, _makeArray = function (nonarray) { return Array.prototype.slice.call(nonarray) }, _isFunction = function (obj) { return Object.prototype.toString.call(obj) === "[object Function]" }, _isArray = function (obj) { return Object.prototype.toString.call(obj) === "[object Array]" }, _isRegExp = function (obj) { return Object.prototype.toString.call(obj) === "[object RegExp]" }, _decode = function (str) { return decodeURIComponent((str || "").replace(/\+/g, " ")) }, _encode = encodeURIComponent, _escapeHTML = function (s) { return String(s).replace(/&(?!\w+;)/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;") }, _routeWrapper = function (verb) { return function () { return this.route.apply(this, [verb].concat(Array.prototype.slice.call(arguments))) } }, _template_cache = {}, _has_history = !!(window.history && history.pushState), loggers = []; Sammy = function () { var args = _makeArray(arguments), app, selector; Sammy.apps = Sammy.apps || {}; if (args.length === 0 || args[0] && _isFunction(args[0])) { return Sammy.apply(Sammy, ["body"].concat(args)) } else if (typeof (selector = args.shift()) == "string") { app = Sammy.apps[selector] || new Sammy.Application; app.element_selector = selector; if (args.length > 0) { $.each(args, function (i, plugin) { app.use(plugin) }) } if (app.element_selector != selector) { delete Sammy.apps[selector] } Sammy.apps[app.element_selector] = app; return app } }; Sammy.VERSION = "0.7.6"; Sammy.addLogger = function (logger) { loggers.push(logger) }; Sammy.log = function () { var args = _makeArray(arguments); args.unshift("[" + Date() + "]"); $.each(loggers, function (i, logger) { logger.apply(Sammy, args) }) }; if (typeof window.console != "undefined") { if (typeof window.console.log === "function" && _isFunction(window.console.log.apply)) { Sammy.addLogger(function () { window.console.log.apply(window.console, arguments) }) } else { Sammy.addLogger(function () { window.console.log(arguments) }) } } else if (typeof console != "undefined") { Sammy.addLogger(function () { console.log.apply(console, arguments) }) } $.extend(Sammy, { makeArray: _makeArray, isFunction: _isFunction, isArray: _isArray }); Sammy.Object = function (obj) { return $.extend(this, obj || {}) }; $.extend(Sammy.Object.prototype, { escapeHTML: _escapeHTML, h: _escapeHTML, toHash: function () { var json = {};
36576 $.each(this, function (k, v) { if (!_isFunction(v)) { json[k] = v } }); return json }, toHTML: function () { var display = ""; $.each(this, function (k, v) { if (!_isFunction(v)) { display += "<strong>" + k + "</strong> " + v + "<br />" } }); return display }, keys: function (attributes_only) { var keys = []; for (var property in this) { if (!_isFunction(this[property]) || !attributes_only) { keys.push(property) } } return keys }, has: function (key) { return this[key] && $.trim(this[key].toString()) !== "" }, join: function () { var args = _makeArray(arguments); var delimiter = args.shift(); return args.join(delimiter) }, log: function () { Sammy.log.apply(Sammy, arguments) }, toString: function (include_functions) { var s = []; $.each(this, function (k, v) { if (!_isFunction(v) || include_functions) { s.push('"' + k + '": ' + v.toString()) } }); return "Sammy.Object: {" + s.join(",") + "}" } }); Sammy.targetIsThisWindow = function targetIsThisWindow(event, tagName) { var targetElement = $(event.target).closest(tagName); if (targetElement.length === 0) { return true } var targetWindow = targetElement.attr("target"); if (!targetWindow || targetWindow === window.name || targetWindow === "_self") { return true } if (targetWindow === "_blank") { return false } if (targetWindow === "top" && window === window.top) { return true } return false }; Sammy.DefaultLocationProxy = function (app, run_interval_every) { this.app = app; this.is_native = false; this.has_history = _has_history; this._startPolling(run_interval_every) }; Sammy.DefaultLocationProxy.fullPath = function (location_obj) { var matches = location_obj.toString().match(/^[^#]*(#.+)$/); var hash = matches ? matches[1] : ""; return [location_obj.pathname, location_obj.search, hash].join("") }; $.extend(Sammy.DefaultLocationProxy.prototype, { bind: function () { var proxy = this, app = this.app, lp = Sammy.DefaultLocationProxy; $(window).bind("hashchange." + this.app.eventNamespace(), function (e, non_native) { if (proxy.is_native === false && !non_native) { proxy.is_native = true; window.clearInterval(lp._interval); lp._interval = null } app.trigger("location-changed") }); if (_has_history && !app.disable_push_state) { $(window).bind("popstate." + this.app.eventNamespace(), function (e) { app.trigger("location-changed") }); $(document).delegate("a", "click.history-" + this.app.eventNamespace(), function (e) { if (e.isDefaultPrevented() || e.metaKey || e.ctrlKey) { return } var full_path = lp.fullPath(this), hostname = this.hostname ? this.hostname : function (a) { var l = document.createElement("a"); l.href = a.href; return l.hostname }(this); if (hostname == window.location.hostname && app.lookupRoute("get", full_path) && Sammy.targetIsThisWindow(e, "a")) { e.preventDefault(); proxy.setLocation(full_path); return false } }) } if (!lp._bindings) { lp._bindings = 0 } lp._bindings++ }, unbind: function () { $(window).unbind("hashchange." + this.app.eventNamespace()); $(window).unbind("popstate." + this.app.eventNamespace()); $(document).undelegate("a", "click.history-" + this.app.eventNamespace()); Sammy.DefaultLocationProxy._bindings--; if (Sammy.DefaultLocationProxy._bindings <= 0) { window.clearInterval(Sammy.DefaultLocationProxy._interval); Sammy.DefaultLocationProxy._interval = null } }, getLocation: function () { return Sammy.DefaultLocationProxy.fullPath(window.location) }, setLocation: function (new_location) { if (/^([^#\/]|$)/.test(new_location)) { if (_has_history && !this.app.disable_push_state) { new_location = "/" + new_location } else { new_location = "#!/" + new_location } } if (new_location != this.getLocation()) { if (_has_history && !this.app.disable_push_state && /^\//.test(new_location)) { history.pushState({ path: new_location }, window.title, new_location); this.app.trigger("location-changed") } else { return window.location = new_location } } }, _startPolling: function (every) { var proxy = this; if (!Sammy.DefaultLocationProxy._interval) { if (!every) { every = 10 } var hashCheck = function () { var current_location = proxy.getLocation(); if (typeof Sammy.DefaultLocationProxy._last_location == "undefined" || current_location != Sammy.DefaultLocationProxy._last_location) { window.setTimeout(function () { $(window).trigger("hashchange", [true]) }, 0) } Sammy.DefaultLocationProxy._last_location = current_location }; hashCheck(); Sammy.DefaultLocationProxy._interval = window.setInterval(hashCheck, every) } } }); Sammy.Application = function (app_function) { var app = this; this.routes = {}; this.listeners = new Sammy.Object({}); this.arounds = []; this.befores = []; this.namespace = (new Date).getTime() + "-" + parseInt(Math.random() * 1e3, 10); this.context_prototype = function () { Sammy.EventContext.apply(this, arguments) }; this.context_prototype.prototype = new Sammy.EventContext; if (_isFunction(app_function)) { app_function.apply(this, [this]) } if (!this._location_proxy) { this.setLocationProxy(new Sammy.DefaultLocationProxy(this, this.run_interval_every)) } if (this.debug) { this.bindToAllEvents(function (e, data) { app.log(app.toString(), e.cleaned_type, data || {}) }) } }; Sammy.Application.prototype = $.extend({}, Sammy.Object.prototype, { ROUTE_VERBS: ["get", "post", "put", "delete"], APP_EVENTS: ["run", "unload", "lookup-route", "run-route", "route-found", "event-context-before", "event-context-after", "changed", "error", "check-form-submission", "redirect", "location-changed"], _last_route: null, _location_proxy: null, _running: false, element_selector: "body", debug: false, raise_errors: false, run_interval_every: 50, disable_push_state: false, template_engine: null, toString: function () { return "Sammy.Application:" + this.element_selector }, $element: function (selector) { return selector ? $(this.element_selector).find(selector) : $(this.element_selector) }, use: function () { var args = _makeArray(arguments), plugin = args.shift(), plugin_name = plugin || ""; try { args.unshift(this); if (typeof plugin == "string") { plugin_name = "Sammy." + plugin; plugin = Sammy[plugin] } plugin.apply(this, args) } catch (e) { if (typeof plugin === "undefined") { this.error("Plugin Error: called use() but plugin (" + plugin_name.toString() + ") is not defined", e) }
36576 else if (!_isFunction(plugin)) { this.error("Plugin Error: called use() but '" + plugin_name.toString() + "' is not a function", e) } else { this.error("Plugin Error", e) } } return this }, setLocationProxy: function (new_proxy) { var original_proxy = this._location_proxy; this._location_proxy = new_proxy; if (this.isRunning()) { if (original_proxy) { original_proxy.unbind() } this._location_proxy.bind() } }, log: function () { Sammy.log.apply(Sammy, Array.prototype.concat.apply([this.element_selector], arguments)) }, route: function (verb, path) { var app = this, param_names = [], add_route, path_match, callback = Array.prototype.slice.call(arguments, 2); if (callback.length === 0 && _isFunction(path)) { callback = [path]; path = verb; verb = "any" } verb = verb.toLowerCase(); if (path.constructor == String) { PATH_NAME_MATCHER.lastIndex = 0; while ((path_match = PATH_NAME_MATCHER.exec(path)) !== null) { param_names.push(path_match[1]) } path = new RegExp(path.replace(PATH_NAME_MATCHER, PATH_REPLACER) + "$") } $.each(callback, function (i, cb) { if (typeof cb === "string") { callback[i] = app[cb] } }); add_route = function (with_verb) { var r = { verb: with_verb, path: path, callback: callback, param_names: param_names }; app.routes[with_verb] = app.routes[with_verb] || []; app.routes[with_verb].push(r) }; if (verb === "any") { $.each(this.ROUTE_VERBS, function (i, v) { add_route(v) }) } else { add_route(verb) } return this }, get: _routeWrapper("get"), post: _routeWrapper("post"), put: _routeWrapper("put"), del: _routeWrapper("delete"), any: _routeWrapper("any"), mapRoutes: function (route_array) { var app = this; $.each(route_array, function (i, route_args) { app.route.apply(app, route_args) }); return this }, eventNamespace: function () { return ["sammy-app", this.namespace].join("-") }, bind: function (name, data, callback) { var app = this; if (typeof callback == "undefined") { callback = data } var listener_callback = function () { var e, context, data; e = arguments[0]; data = arguments[1]; if (data && data.context) { context = data.context; delete data.context } else { context = new app.context_prototype(app, "bind", e.type, data, e.target) } e.cleaned_type = e.type.replace(app.eventNamespace(), ""); callback.apply(context, [e, data]) }; if (!this.listeners[name]) { this.listeners[name] = [] } this.listeners[name].push(listener_callback); if (this.isRunning()) { this._listen(name, listener_callback) } return this }, trigger: function (name, data) { this.$element().trigger([name, this.eventNamespace()].join("."), [data]); return this }, refresh: function () { this.last_location = null; this.trigger("location-changed"); return this }, before: function (options, callback) { if (_isFunction(options)) { callback = options; options = {} } this.befores.push([options, callback]); return this }, after: function (callback) { return this.bind("event-context-after", callback) }, around: function (callback) { this.arounds.push(callback); return this }, onComplete: function (callback) { this._onComplete = callback; return this }, isRunning: function () { return this._running }, helpers: function (extensions) { $.extend(this.context_prototype.prototype, extensions); return this }, helper: function (name, method) { this.context_prototype.prototype[name] = method; return this }, run: function (start_url) { if (this.isRunning()) { return false } var app = this; $.each(this.listeners.toHash(), function (name, callbacks) { $.each(callbacks, function (i, listener_callback) { app._listen(name, listener_callback) }) }); this.trigger("run", { start_url: start_url }); this._running = true; this.last_location = null; if (!/\#(.+)/.test(this.getLocation()) && typeof start_url != "undefined") { this.setLocation(start_url) } this._checkLocation(); this._location_proxy.bind(); this.bind("location-changed", function () { app._checkLocation() }); this.bind("submit", function (e) { if (!Sammy.targetIsThisWindow(e, "form")) { return true } var returned = app._checkFormSubmission($(e.target).closest("form")); return returned === false ? e.preventDefault() : false }); $(window).bind("unload", function () { app.unload() }); return this.trigger("changed") }, unload: function () { if (!this.isRunning()) { return false } var app = this; this.trigger("unload"); this._location_proxy.unbind(); this.$element().unbind("submit").removeClass(app.eventNamespace()); $.each(this.listeners.toHash(), function (name, listeners) { $.each(listeners, function (i, listener_callback) { app._unlisten(name, listener_callback) }) }); this._running = false; return this }, destroy: function () { this.unload(); delete Sammy.apps[this.element_selector]; return this }, bindToAllEvents: function (callback) { var app = this; $.each(this.APP_EVENTS, function (i, e) { app.bind(e, callback) }); $.each(this.listeners.keys(true), function (i, name) { if ($.inArray(name, app.APP_EVENTS) == -1) { app.bind(name, callback) } }); return this }, routablePath: function (path) { return path.replace(QUERY_STRING_MATCHER, "") }, lookupRoute: function (verb, path) { var app = this, routed = false, i = 0, l, route; if (typeof this.routes[verb] != "undefined") { l = this.routes[verb].length; for (; i < l; i++) { route = this.routes[verb][i]; if (app.routablePath(path).match(route.path)) { routed = route; break } } } return routed }, runRoute: function (verb, path, params, target) { var app = this, route = this.lookupRoute(verb, path), context, wrapped_route, arounds, around, befores, before, callback_args, path_params, final_returned; if (this.debug) { this.log("runRoute", [verb, path].join(" ")) } this.trigger("run-route", { verb: verb, path: path, params: params }); if (typeof params == "undefined") { params = {} } $.extend(params, this._parseQueryString(path)); if (route) { this.trigger("route-found", { route: route });
36576 if ((path_params = route.path.exec(this.routablePath(path))) !== null) { path_params.shift(); $.each(path_params, function (i, param) { if (route.param_names[i]) { params[route.param_names[i]] = _decode(param) } else { if (!params.splat) { params.splat = [] } params.splat.push(_decode(param)) } }) } context = new this.context_prototype(this, verb, path, params, target); arounds = this.arounds.slice(0); befores = this.befores.slice(0); callback_args = [context]; if (params.splat) { callback_args = callback_args.concat(params.splat) } wrapped_route = function () { var returned, i, nextRoute; while (befores.length > 0) { before = befores.shift(); if (app.contextMatchesOptions(context, before[0])) { returned = before[1].apply(context, [context]); if (returned === false) { return false } } } app.last_route = route; context.trigger("event-context-before", { context: context }); if (typeof route.callback === "function") { route.callback = [route.callback] } if (route.callback && route.callback.length) { i = -1; nextRoute = function () { i++; if (route.callback[i]) { returned = route.callback[i].apply(context, callback_args) } else if (app._onComplete && typeof (app._onComplete === "function")) { app._onComplete(context) } }; callback_args.push(nextRoute); nextRoute() } context.trigger("event-context-after", { context: context }); return returned }; $.each(arounds.reverse(), function (i, around) { var last_wrapped_route = wrapped_route; wrapped_route = function () { return around.apply(context, [last_wrapped_route]) } }); try { final_returned = wrapped_route() } catch (e) { this.error(["500 Error", verb, path].join(" "), e) } return final_returned } else { return this.notFound(verb, path) } }, contextMatchesOptions: function (context, match_options, positive) { var options = match_options; if (typeof options === "string" || _isRegExp(options)) { options = { path: options } } if (typeof positive === "undefined") { positive = true } if ($.isEmptyObject(options)) { return true } if (_isArray(options.path)) { var results, numopt, opts, len; results = []; for (numopt = 0, len = options.path.length; numopt < len; numopt += 1) { opts = $.extend({}, options, { path: options.path[numopt] }); results.push(this.contextMatchesOptions(context, opts)) } var matched = $.inArray(true, results) > -1 ? true : false; return positive ? matched : !matched } if (options.only) { return this.contextMatchesOptions(context, options.only, true) } else if (options.except) { return this.contextMatchesOptions(context, options.except, false) } var path_matched = true, verb_matched = true; if (options.path) { if (!_isRegExp(options.path)) { options.path = new RegExp(options.path.toString() + "$") } path_matched = options.path.test(context.path) } if (options.verb) { if (typeof options.verb === "string") { verb_matched = options.verb === context.verb } else { verb_matched = options.verb.indexOf(context.verb) > -1 } } return positive ? verb_matched && path_matched : !(verb_matched && path_matched) }, getLocation: function () { return this._location_proxy.getLocation() }, setLocation: function (new_location) { return this._location_proxy.setLocation(new_location) }, swap: function (content, callback) { var $el = this.$element().html(content); if (_isFunction(callback)) { callback(content) } return $el }, templateCache: function (key, value) { if (typeof value != "undefined") { return _template_cache[key] = value } else { return _template_cache[key] } }, clearTemplateCache: function () { return _template_cache = {} }, notFound: function (verb, path) { var ret = this.error(["404 Not Found", verb, path].join(" ")); return verb === "get" ? ret : true }, error: function (message, original_error) { if (!original_error) { original_error = new Error } original_error.message = [message, original_error.message].join(" "); this.trigger("error", { message: original_error.message, error: original_error }); if (this.raise_errors) { throw original_error } else { this.log(original_error.message, original_error) } }, _checkLocation: function () { var location, returned; location = this.getLocation(); if (!this.last_location || this.last_location[0] != "get" || this.last_location[1] != location) { this.last_location = ["get", location]; returned = this.runRoute("get", location) } return returned }, _getFormVerb: function (form) { var $form = $(form), verb, $_method; $_method = $form.find('input[name="_method"]'); if ($_method.length > 0) { verb = $_method.val() } if (!verb) { verb = $form[0].getAttribute("method") } if (!verb || verb === "") { verb = "get" } return $.trim(verb.toString().toLowerCase()) }, _checkFormSubmission: function (form) { var $form, path, verb, params, returned; this.trigger("check-form-submission", { form: form }); $form = $(form); path = $form.attr("action") || ""; verb = this._getFormVerb($form); if (this.debug) { this.log("_checkFormSubmission", $form, path, verb) } if (verb === "get") { params = this._serializeFormParams($form); if (params !== "") { path += "?" + params } this.setLocation(path); returned = false } else { params = $.extend({}, this._parseFormParams($form)); returned = this.runRoute(verb, path, params, form.get(0)) } return typeof returned == "undefined" ? false : returned }, _serializeFormParams: function ($form) { var queryString = "", fields = $form.serializeArray(), i; if (fields.length > 0) { queryString = this._encodeFormPair(fields[0].name, fields[0].value); for (i = 1; i < fields.length; i++) { queryString = queryString + "&" + this._encodeFormPair(fields[i].name, fields[i].value) } } return queryString }, _encodeFormPair: function (name, value) { return _encode(name) + "=" + _encode(value) }, _parseFormParams: function ($form) { var params = {}, form_fields = $form.serializeArray(), i; for (i = 0; i < form_fields.length; i++) { params = this._parseParamPair(params, form_fields[i].name, form_fields[i].value) } return params }, _parseQueryString: function (path) { var params = {}, parts, pairs, pair, i; parts = path.match(QUERY_STRING_MATCHER); if (parts && parts[1]) { pairs = parts[1].split("&"); for (i = 0; i < pairs.length; i++) { pair = pairs[i].split("="); params = this._parseParamPair(params, _decode(pair[0]), _decode(pair[1] || "")) } } return params }, _parseParamPair: function (params, key, value) { if (typeof params[key] !== "undefined") { if (_isArray(params[key])) { params[key].push(value) } else { params[key] = [params[key], value] } } else { params[key] = value } return params }, _listen: function (name, callback) { return this.$element().bind([name, this.eventNamespace()].join("."), callback) }, _unlisten: function (name, callback) { return this.$element().unbind([name, this.eventNamespace()].join("."), callback) } }); Sammy.RenderContext = function (event_context) { this.event_context = event_c
36576ontext; this.callbacks = []; this.previous_content = null; this.content = null; this.next_engine = false; this.waiting = false }; Sammy.RenderContext.prototype = $.extend({}, Sammy.Object.prototype, { then: function (callback) { if (!_isFunction(callback)) { if (typeof callback === "string" && callback in this.event_context) { var helper = this.event_context[callback]; callback = function (content) { return helper.apply(this.event_context, [content]) } } else { return this } } var context = this; if (this.waiting) { this.callbacks.push(callback) } else { this.wait(); window.setTimeout(function () { var returned = callback.apply(context, [context.content, context.previous_content]); if (returned !== false) { context.next(returned) } }, 0) } return this }, wait: function () { this.waiting = true }, next: function (content) { this.waiting = false; if (typeof content !== "undefined") { this.previous_content = this.content; this.content = content } if (this.callbacks.length > 0) { this.then(this.callbacks.shift()) } }, load: function (location, options, callback) { var context = this; return this.then(function () { var should_cache, cached, is_json, location_array; if (_isFunction(options)) { callback = options; options = {} } else { options = $.extend({}, options) } if (callback) { this.then(callback) } if (typeof location === "string") { is_json = location.match(/\.json(\?|$)/) || options.json; should_cache = is_json ? options.cache === true : options.cache !== false; context.next_engine = context.event_context.engineFor(location); delete options.cache; delete options.json; if (options.engine) { context.next_engine = options.engine; delete options.engine } if (should_cache && (cached = this.event_context.app.templateCache(location))) { return cached } this.wait(); $.ajax($.extend({ url: location, data: {}, dataType: is_json ? "json" : "text", type: "get", success: function (data) { if (should_cache) { context.event_context.app.templateCache(location, data) } context.next(data) } }, options)); return false } else { if (location.nodeType) { return location.innerHTML } if (location.selector) { context.next_engine = location.attr("data-engine"); if (options.clone === false) { return location.remove()[0].innerHTML.toString() } else { return location[0].innerHTML.toString() } } } }) }, loadPartials: function (partials) { var name; if (partials) { this.partials = this.partials || {}; for (name in partials) { (function (context, name) { context.load(partials[name]).then(function (template) { this.partials[name] = template }) })(this, name) } } return this }, render: function (location, data, callback, partials) { if (_isFunction(location) && !data) { return this.then(location) } else { if (_isFunction(data)) { partials = callback; callback = data; data = null } else if (callback && !_isFunction(callback)) { partials = callback; callback = null } return this.loadPartials(partials).load(location).interpolate(data, location).then(callback) } }, partial: function (location, data, callback, partials) { if (_isFunction(callback)) { return this.render(location, data, partials).swap(callback) } else if (_isFunction(data)) { return this.render(location, {}, callback).swap(data) } else { return this.render(location, data, callback).swap() } }, send: function () { var context = this, args = _makeArray(arguments), fun = args.shift(); if (_isArray(args[0])) { args = args[0] } return this.then(function (content) { args.push(function (response) { context.next(response) }); context.wait(); fun.apply(fun, args); return false }) }, collect: function (array, callback, now) { var context = this; var coll = function () { if (_isFunction(array)) { callback = array; array = this.content } var contents = [], doms = false; $.each(array, function (i, item) { var returned = callback.apply(context, [i, item]); if (returned.jquery && returned.length == 1) { returned = returned[0]; doms = true } contents.push(returned); return returned }); return doms ? contents : contents.join("") }; return now ? coll() : this.then(coll) }, renderEach: function (location, name, data, callback) { if (_isArray(name)) { callback = data; data = name; name = null } return this.load(location).then(function (content) { var rctx = this; if (!data) { data = _isArray(this.previous_content) ? this.previous_content : [] } if (callback) { $.each(data, function (i, value) { var idata = {}, engine = this.next_engine || location; if (name) { idata[name] = value } else { idata = value }
36576 callback(value, rctx.event_context.interpolate(content, idata, engine)) }) } else { return this.collect(data, function (i, value) { var idata = {}, engine = this.next_engine || location; if (name) { idata[name] = value } else { idata = value } return this.event_context.interpolate(content, idata, engine) }, true) } }) }, interpolate: function (data, engine, retain) { var context = this; return this.then(function (content, prev) { if (!data && prev) { data = prev } if (this.next_engine) { engine = this.next_engine; this.next_engine = false } var rendered = context.event_context.interpolate(content, data, engine, this.partials); return retain ? prev + rendered : rendered }) }, swap: function (callback) { return this.then(function (content) { this.event_context.swap(content, callback); return content }).trigger("changed", {}) }, appendTo: function (selector) { return this.then(function (content) { $(selector).append(content) }).trigger("changed", {}) }, prependTo: function (selector) { return this.then(function (content) { $(selector).prepend(content) }).trigger("changed", {}) }, replace: function (selector) { return this.then(function (content) { $(selector).html(content) }).trigger("changed", {}) }, trigger: function (name, data) { return this.then(function (content) { if (typeof data == "undefined") { data = { content: content } } this.event_context.trigger(name, data); return content }) } }); Sammy.EventContext = function (app, verb, path, params, target) { this.app = app; this.verb = verb; this.path = path; this.params = new Sammy.Object(params); this.target = target }; Sammy.EventContext.prototype = $.extend({}, Sammy.Object.prototype, { $element: function () { return this.app.$element(_makeArray(arguments).shift()) }, engineFor: function (engine) { var context = this, engine_match; if (_isFunction(engine)) { return engine } engine = (engine || context.app.template_engine).toString(); if (engine_match = engine.match(/\.([^\.\?\#]+)(\?|$)/)) { engine = engine_match[1] } if (engine && _isFunction(context[engine])) { return context[engine] } if (context.app.template_engine) { return this.engineFor(context.app.template_engine) } return function (content, data) { return content } }, interpolate: function (content, data, engine, partials) { return this.engineFor(engine).apply(this, [content, data, partials]) }, render: function (location, data, callback, partials) { return new Sammy.RenderContext(this).render(location, data, callback, partials) }, renderEach: function (location, name, data, callback) { return new Sammy.RenderContext(this).renderEach(location, name, data, callback) }, load: function (location, options, callback) { return new Sammy.RenderContext(this).load(location, options, callback) }, loadPartials: function (partials) { return new Sammy.RenderContext(this).loadPartials(partials) }, partial: function (location, data, callback, partials) { return new Sammy.RenderContext(this).partial(location, data, callback, partials) }, send: function () { var rctx = new Sammy.RenderContext(this); return rctx.send.apply(rctx, arguments) }, redirect: function () { var to, args = _makeArray(arguments), current_location = this.app.getLocation(), l = args.length; if (l > 1) { var i = 0, paths = [], pairs = [], params = {}, has_params = false; for (; i < l; i++) { if (typeof args[i] == "string") { paths.push(args[i]) } else { $.extend(params, args[i]); has_params = true } } to = paths.join("/"); if (has_params) { for (var k in params) { pairs.push(this.app._encodeFormPair(k, params[k])) } to += "?" + pairs.join("&") } } else { to = args[0] } this.trigger("redirect", { to: to }); this.app.last_location = [this.verb, this.path]; this.app.setLocation(to); if (new RegExp(to).test(current_location)) { this.app.trigger("location-changed") } }, trigger: function (name, data) { if (typeof data == "undefined") { data = {} } if (!data.context) { data.context = this } return this.app.trigger(name, data) }, eventNamespace: function () { return this.app.eventNamespace() }, swap: function (contents, callback) { return this.app.swap(contents, callback) }, notFound: function () { return this.app.notFound(this.verb, this.path) }, json: function (string) { return $.parseJSON(string) }, toString: function () { return "Sammy.EventContext: " + [this.verb, this.path, this.params].join(" ") } }); return Sammy });;
36577/*!
36578 * Knockout JavaScript library v3.5.1
36579 * (c) The Knockout.js team - http://knockoutjs.com/
36580 * License: MIT (http://www.opensource.org/licenses/mit-license.php)
36581 */
36582
36583(function() {(function(n){var A=this||(0,eval)("this"),w=A.document,R=A.navigator,v=A.jQuery,H=A.JSON;
vendor: 4,182 bytes, lines 36583-36591
36583v||"undefined"===typeof jQuery||(v=jQuery);(function(n){"function"===typeof define&&define.amd?define(["exports","require"],n):"object"===typeof exports&&"object"===typeof module?n(module.exports||exports):n(A.ko={})})(function(S,T){function K(a,c){return null===a||typeof a in W?a===c:!1}function X(b,c){var d;return function(){d||(d=a.a.setTimeout(function(){d=n;b()},c))}}function Y(b,c){var d;return function(){clearTimeout(d);
36584d=a.a.setTimeout(b,c)}}function Z(a,c){c&&"change"!==c?"beforeChange"===c?this.pc(a):this.gb(a,c):this.qc(a)}function aa(a,c){null!==c&&c.s&&c.s()}function ba(a,c){var d=this.qd,e=d[r];e.ra||(this.Qb&&this.mb[c]?(d.uc(c,a,this.mb[c]),this.mb[c]=null,--this.Qb):e.I[c]||d.uc(c,a,e.J?{da:a}:d.$c(a)),a.Ja&&a.gd())}var a="undefined"!==typeof S?S:{};a.b=function(b,c){for(var d=b.split("."),e=a,f=0;f<d.length-1;f++)e=e[d[f]];e[d[d.length-1]]=c};a.L=function(a,c,d){a[c]=d};a.version="3.5.1";a.b("version",
36585a.version);a.options={deferUpdates:!1,useOnlyNativeEvents:!1,foreachHidesDestroyed:!1};a.a=function(){function b(a,b){for(var c in a)f.call(a,c)&&b(c,a[c])}function c(a,b){if(b)for(var c in b)f.call(b,c)&&(a[c]=b[c]);return a}function d(a,b){a.__proto__=b;return a}function e(b,c,d,e){var l=b[c].match(q)||[];a.a.D(d.match(q),function(b){a.a.Na(l,b,e)});b[c]=l.join(" ")}var f=Object.prototype.hasOwnProperty,g={__proto__:[]}instanceof Array,h="function"===typeof Symbol,m={},k={};m[R&&/Firefox\/2/i.test(R.userAgent)?
36586"KeyboardEvent":"UIEvents"]=["keyup","keydown","keypress"];m.MouseEvents="click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave".split(" ");b(m,function(a,b){if(b.length)for(var c=0,d=b.length;c<d;c++)k[b[c]]=a});var l={propertychange:!0},p=w&&function(){for(var a=3,b=w.createElement("div"),c=b.getElementsByTagName("i");b.innerHTML="\x3c!--[if gt IE "+ ++a+"]><i></i><![endif]--\x3e",c[0];);return 4<a?a:n}(),q=/\S+/g,t;return{Jc:["authenticity_token",/^__RequestVerificationToken(_.*)?$/],
36587D:function(a,b,c){for(var d=0,e=a.length;d<e;d++)b.call(c,a[d],d,a)},A:"function"==typeof Array.prototype.indexOf?function(a,b){return Array.prototype.indexOf.call(a,b)}:function(a,b){for(var c=0,d=a.length;c<d;c++)if(a[c]===b)return c;return-1},Lb:function(a,b,c){for(var d=0,e=a.length;d<e;d++)if(b.call(c,a[d],d,a))return a[d];return n},Pa:function(b,c){var d=a.a.A(b,c);0<d?b.splice(d,1):0===d&&b.shift()},wc:function(b){var c=[];b&&a.a.D(b,function(b){0>a.a.A(c,b)&&c.push(b)});return c},Mb:function(a,
36588b,c){var d=[];if(a)for(var e=0,l=a.length;e<l;e++)d.push(b.call(c,a[e],e));return d},jb:function(a,b,c){var d=[];if(a)for(var e=0,l=a.length;e<l;e++)b.call(c,a[e],e)&&d.push(a[e]);return d},Nb:function(a,b){if(b instanceof Array)a.push.apply(a,b);else for(var c=0,d=b.length;c<d;c++)a.push(b[c]);return a},Na:function(b,c,d){var e=a.a.A(a.a.bc(b),c);0>e?d&&b.push(c):d||b.splice(e,1)},Ba:g,extend:c,setPrototypeOf:d,Ab:g?d:c,P:b,Ga:function(a,b,c){if(!a)return a;var d={},e;for(e in a)f.call(a,e)&&(d[e]=
36589b.call(c,a[e],e,a));return d},Tb:function(b){for(;b.firstChild;)a.removeNode(b.firstChild)},Yb:function(b){b=a.a.la(b);for(var c=(b[0]&&b[0].ownerDocument||w).createElement("div"),d=0,e=b.length;d<e;d++)c.appendChild(a.oa(b[d]));return c},Ca:function(b,c){for(var d=0,e=b.length,l=[];d<e;d++){var k=b[d].cloneNode(!0);l.push(c?a.oa(k):k)}return l},va:function(b,c){a.a.Tb(b);if(c)for(var d=0,e=c.length;d<e;d++)b.appendChild(c[d])},Xc:function(b,c){var d=b.nodeType?[b]:b;if(0<d.length){for(var e=d[0],
36590l=e.parentNode,k=0,f=c.length;k<f;k++)l.insertBefore(c[k],e);k=0;for(f=d.length;k<f;k++)a.removeNode(d[k])}},Ua:function(a,b){if(a.length){for(b=8===b.nodeType&&b.parentNode||b;a.length&&a[0].parentNode!==b;)a.splice(0,1);for(;1<a.length&&a[a.length-1].parentNode!==b;)a.length--;if(1<a.length){var c=a[0],d=a[a.length-1];for(a.length=0;c!==d;)a.push(c),c=c.nextSibling;a.push(d)}}return a},Zc:function(a,b){7>p?a.setAttribute("selected",b):a.selected=b},Db:function(a){return null===a||a===n?"":a.trim?
36591a.trim():a.toString().replace(/^[\s\xa0]+|[\s\xa0]+$/g,"")},Ud:function(a,b){a=a||"";return b.length>a.length?!1:a.substring(0,b.length)===b},vd:function(a,b){if(a===b)return!0;
vendor: 63,735 bytes, lines 36591-36715
36591if(11===a.nodeType)return!1;if(b.contains)return b.contains(1!==a.nodeType?a.parentNode:a);if(b.compareDocumentPosition)return 16==(b.compareDocumentPosition(a)&16);for(;a&&a!=b;)a=a.parentNode;return!!a},Sb:function(b){return a.a.vd(b,b.ownerDocument.documentElement)},kd:function(b){return!!a.a.Lb(b,a.a.Sb)},R:function(a){return a&&
36592a.tagName&&a.tagName.toLowerCase()},Ac:function(b){return a.onError?function(){try{return b.apply(this,arguments)}catch(c){throw a.onError&&a.onError(c),c;}}:b},setTimeout:function(b,c){return setTimeout(a.a.Ac(b),c)},Gc:function(b){setTimeout(function(){a.onError&&a.onError(b);throw b;},0)},B:function(b,c,d){var e=a.a.Ac(d);d=l[c];if(a.options.useOnlyNativeEvents||d||!v)if(d||"function"!=typeof b.addEventListener)if("undefined"!=typeof b.attachEvent){var k=function(a){e.call(b,a)},f="on"+c;b.attachEvent(f,
36593k);a.a.K.za(b,function(){b.detachEvent(f,k)})}else throw Error("Browser doesn't support addEventListener or attachEvent");else b.addEventListener(c,e,!1);else t||(t="function"==typeof v(b).on?"on":"bind"),v(b)[t](c,e)},Fb:function(b,c){if(!b||!b.nodeType)throw Error("element must be a DOM node when calling triggerEvent");var d;"input"===a.a.R(b)&&b.type&&"click"==c.toLowerCase()?(d=b.type,d="checkbox"==d||"radio"==d):d=!1;if(a.options.useOnlyNativeEvents||!v||d)if("function"==typeof w.createEvent)if("function"==
36594typeof b.dispatchEvent)d=w.createEvent(k[c]||"HTMLEvents"),d.initEvent(c,!0,!0,A,0,0,0,0,0,!1,!1,!1,!1,0,b),b.dispatchEvent(d);else throw Error("The supplied element doesn't support dispatchEvent");else 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");else v(b).trigger(c)},f:function(b){return a.O(b)?b():b},bc:function(b){return a.O(b)?b.v():b},Eb:function(b,c,d){var l;c&&("object"===typeof b.classList?
36595(l=b.classList[d?"add":"remove"],a.a.D(c.match(q),function(a){l.call(b.classList,a)})):"string"===typeof b.className.baseVal?e(b.className,"baseVal",c,d):e(b,"className",c,d))},Bb:function(b,c){var d=a.a.f(c);if(null===d||d===n)d="";var e=a.h.firstChild(b);!e||3!=e.nodeType||a.h.nextSibling(e)?a.h.va(b,[b.ownerDocument.createTextNode(d)]):e.data=d;a.a.Ad(b)},Yc:function(a,b){a.name=b;if(7>=p)try{var c=a.name.replace(/[&<>'"]/g,function(a){return"&#"+a.charCodeAt(0)+";"});a.mergeAttributes(w.createElement("<input name='"+
36596c+"'/>"),!1)}catch(d){}},Ad:function(a){9<=p&&(a=1==a.nodeType?a:a.parentNode,a.style&&(a.style.zoom=a.style.zoom))},wd:function(a){if(p){var b=a.style.width;a.style.width=0;a.style.width=b}},Pd:function(b,c){b=a.a.f(b);c=a.a.f(c);for(var d=[],e=b;e<=c;e++)d.push(e);return d},la:function(a){for(var b=[],c=0,d=a.length;c<d;c++)b.push(a[c]);return b},Da:function(a){return h?Symbol(a):a},Zd:6===p,$d:7===p,W:p,Lc:function(b,c){for(var d=a.a.la(b.getElementsByTagName("input")).concat(a.a.la(b.getElementsByTagName("textarea"))),
36597e="string"==typeof c?function(a){return a.name===c}:function(a){return c.test(a.name)},l=[],k=d.length-1;0<=k;k--)e(d[k])&&l.push(d[k]);return l},Nd:function(b){return"string"==typeof b&&(b=a.a.Db(b))?H&&H.parse?H.parse(b):(new Function("return "+b))():null},hc:function(b,c,d){if(!H||!H.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");
36598return H.stringify(a.a.f(b),c,d)},Od:function(c,d,e){e=e||{};var l=e.params||{},k=e.includeFields||this.Jc,f=c;if("object"==typeof c&&"form"===a.a.R(c))for(var f=c.action,h=k.length-1;0<=h;h--)for(var g=a.a.Lc(c,k[h]),m=g.length-1;0<=m;m--)l[g[m].name]=g[m].value;d=a.a.f(d);var p=w.createElement("form");p.style.display="none";p.action=f;p.method="post";for(var q in d)c=w.createElement("input"),c.type="hidden",c.name=q,c.value=a.a.hc(a.a.f(d[q])),p.appendChild(c);b(l,function(a,b){var c=w.createElement("input");
36599c.type="hidden";c.name=a;c.value=b;p.appendChild(c)});w.body.appendChild(p);e.submitter?e.submitter(p):p.submit();setTimeout(function(){p.parentNode.removeChild(p)},0)}}}();a.b("utils",a.a);a.b("utils.arrayForEach",a.a.D);a.b("utils.arrayFirst",a.a.Lb);a.b("utils.arrayFilter",a.a.jb);a.b("utils.arrayGetDistinctValues",a.a.wc);a.b("utils.arrayIndexOf",a.a.A);a.b("utils.arrayMap",a.a.Mb);a.b("utils.arrayPushAll",a.a.Nb);a.b("utils.arrayRemoveItem",a.a.Pa);a.b("utils.cloneNodes",a.a.Ca);a.b("utils.createSymbolOrString",
36600a.a.Da);a.b("utils.extend",a.a.extend);a.b("utils.fieldsIncludedWithJsonPost",a.a.Jc);a.b("utils.getFormFields",a.a.Lc);a.b("utils.objectMap",a.a.Ga);a.b("utils.peekObservable",a.a.bc);a.b("utils.postJson",a.a.Od);a.b("utils.parseJson",a.a.Nd);a.b("utils.registerEventHandler",a.a.B);a.b("utils.stringifyJson",a.a.hc);a.b("utils.range",a.a.Pd);a.b("utils.toggleDomNodeCssClass",a.a.Eb);a.b("utils.triggerEvent",a.a.Fb);a.b("utils.unwrapObservable",a.a.f);a.b("utils.objectForEach",a.a.P);a.b("utils.addOrRemoveItem",
36601a.a.Na);a.b("utils.setTextContent",a.a.Bb);a.b("unwrap",a.a.f);Function.prototype.bind||(Function.prototype.bind=function(a){var c=this;if(1===arguments.length)return function(){return c.apply(a,arguments)};var d=Array.prototype.slice.call(arguments,1);return function(){var e=d.slice(0);e.push.apply(e,arguments);return c.apply(a,e)}});a.a.g=new function(){var b=0,c="__ko__"+(new Date).getTime(),d={},e,f;a.a.W?(e=function(a,e){var f=a[c];if(!f||"null"===f||!d[f]){if(!e)return n;f=a[c]="ko"+b++;d[f]=
36602{}}return d[f]},f=function(a){var b=a[c];return b?(delete d[b],a[c]=null,!0):!1}):(e=function(a,b){var d=a[c];!d&&b&&(d=a[c]={});return d},f=function(a){return a[c]?(delete a[c],!0):!1});return{get:function(a,b){var c=e(a,!1);return c&&c[b]},set:function(a,b,c){(a=e(a,c!==n))&&(a[b]=c)},Ub:function(a,b,c){a=e(a,!0);return a[b]||(a[b]=c)},clear:f,Z:function(){return b++ +c}}};a.b("utils.domData",a.a.g);a.b("utils.domData.clear",a.a.g.clear);a.a.K=new function(){function b(b,c){var d=a.a.g.get(b,e);
36603d===n&&c&&(d=[],a.a.g.set(b,e,d));return d}function c(c){var e=b(c,!1);if(e)for(var e=e.slice(0),k=0;k<e.length;k++)e[k](c);a.a.g.clear(c);a.a.K.cleanExternalData(c);g[c.nodeType]&&d(c.childNodes,!0)}function d(b,d){for(var e=[],l,f=0;f<b.length;f++)if(!d||8===b[f].nodeType)if(c(e[e.length]=l=b[f]),b[f]!==l)for(;f--&&-1==a.a.A(e,b[f]););}var e=a.a.g.Z(),f={1:!0,8:!0,9:!0},g={1:!0,9:!0};return{za:function(a,c){if("function"!=typeof c)throw Error("Callback must be a function");b(a,!0).push(c)},yb:function(c,
36604d){var f=b(c,!1);f&&(a.a.Pa(f,d),0==f.length&&a.a.g.set(c,e,n))},oa:function(b){a.u.G(function(){f[b.nodeType]&&(c(b),g[b.nodeType]&&d(b.getElementsByTagName("*")))});return b},removeNode:function(b){a.oa(b);b.parentNode&&b.parentNode.removeChild(b)},cleanExternalData:function(a){v&&"function"==typeof v.cleanData&&v.cleanData([a])}}};a.oa=a.a.K.oa;a.removeNode=a.a.K.removeNode;a.b("cleanNode",a.oa);a.b("removeNode",a.removeNode);a.b("utils.domNodeDisposal",a.a.K);a.b("utils.domNodeDisposal.addDisposeCallback",
36605a.a.K.za);a.b("utils.domNodeDisposal.removeDisposeCallback",a.a.K.yb);(function(){var b=[0,"",""],c=[1,"<table>","</table>"],d=[3,"<table><tbody><tr>","</tr></tbody></table>"],e=[1,"<select multiple='multiple'>","</select>"],f={thead:c,tbody:c,tfoot:c,tr:[2,"<table><tbody>","</tbody></table>"],td:d,th:d,option:e,optgroup:e},g=8>=a.a.W;a.a.ua=function(c,d){var e;if(v)if(v.parseHTML)e=v.parseHTML(c,d)||[];else{if((e=v.clean([c],d))&&e[0]){for(var l=e[0];l.parentNode&&11!==l.parentNode.nodeType;)l=l.parentNode;
36606l.parentNode&&l.parentNode.removeChild(l)}}else{(e=d)||(e=w);var l=e.parentWindow||e.defaultView||A,p=a.a.Db(c).toLowerCase(),q=e.createElement("div"),t;t=(p=p.match(/^(?:\x3c!--.*?--\x3e\s*?)*?<([a-z]+)[\s>]/))&&f[p[1]]||b;p=t[0];t="ignored<div>"+t[1]+c+t[2]+"</div>";"function"==typeof l.innerShiv?q.appendChild(l.innerShiv(t)):(g&&e.body.appendChild(q),q.innerHTML=t,g&&q.parentNode.removeChild(q));for(;p--;)q=q.lastChild;e=a.a.la(q.lastChild.childNodes)}return e};a.a.Md=function(b,c){var d=a.a.ua(b,
36607c);return d.length&&d[0].parentElement||a.a.Yb(d)};a.a.fc=function(b,c){a.a.Tb(b);c=a.a.f(c);if(null!==c&&c!==n)if("string"!=typeof c&&(c=c.toString()),v)v(b).html(c);else for(var d=a.a.ua(c,b.ownerDocument),e=0;e<d.length;e++)b.appendChild(d[e])}})();a.b("utils.parseHtmlFragment",a.a.ua);a.b("utils.setHtml",a.a.fc);a.aa=function(){function b(c,e){if(c)if(8==c.nodeType){var f=a.aa.Uc(c.nodeValue);null!=f&&e.push({ud:c,Kd:f})}else if(1==c.nodeType)for(var f=0,g=c.childNodes,h=g.length;f<h;f++)b(g[f],
36608e)}var c={};return{Xb: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);c[b]=a;return"\x3c!--[ko_memo:"+b+"]--\x3e"},bd:function(a,b){var f=c[a];if(f===n)throw Error("Couldn't find any memo with ID "+a+". Perhaps it's already been unmemoized.");try{return f.apply(null,b||[]),!0}finally{delete c[a]}},cd:function(c,e){var f=
36609[];b(c,f);for(var g=0,h=f.length;g<h;g++){var m=f[g].ud,k=[m];e&&a.a.Nb(k,e);a.aa.bd(f[g].Kd,k);m.nodeValue="";m.parentNode&&m.parentNode.removeChild(m)}},Uc:function(a){return(a=a.match(/^\[ko_memo\:(.*?)\]$/))?a[1]:null}}}();a.b("memoization",a.aa);a.b("memoization.memoize",a.aa.Xb);a.b("memoization.unmemoize",a.aa.bd);a.b("memoization.parseMemoText",a.aa.Uc);a.b("memoization.unmemoizeDomNodeAndDescendants",a.aa.cd);a.na=function(){function b(){if(f)for(var b=f,c=0,d;h<f;)if(d=e[h++]){if(h>b){if(5E3<=
36610++c){h=f;a.a.Gc(Error("'Too much recursion' after processing "+c+" task groups."));break}b=f}try{d()}catch(p){a.a.Gc(p)}}}function c(){b();h=f=e.length=0}var d,e=[],f=0,g=1,h=0;A.MutationObserver?d=function(a){var b=w.createElement("div");(new MutationObserver(a)).observe(b,{attributes:!0});return function(){b.classList.toggle("foo")}}(c):d=w&&"onreadystatechange"in w.createElement("script")?function(a){var b=w.createElement("script");b.onreadystatechange=function(){b.onreadystatechange=null;w.documentElement.removeChild(b);
36611b=null;a()};w.documentElement.appendChild(b)}:function(a){setTimeout(a,0)};return{scheduler:d,zb:function(b){f||a.na.scheduler(c);e[f++]=b;return g++},cancel:function(a){a=a-(g-f);a>=h&&a<f&&(e[a]=null)},resetForTesting:function(){var a=f-h;h=f=e.length=0;return a},Sd:b}}();a.b("tasks",a.na);a.b("tasks.schedule",a.na.zb);a.b("tasks.runEarly",a.na.Sd);a.Ta={throttle:function(b,c){b.throttleEvaluation=c;var d=null;return a.$({read:b,write:function(e){clearTimeout(d);d=a.a.setTimeout(function(){b(e)},
36612c)}})},rateLimit:function(a,c){var d,e,f;"number"==typeof c?d=c:(d=c.timeout,e=c.method);a.Hb=!1;f="function"==typeof e?e:"notifyWhenChangesStop"==e?Y:X;a.ub(function(a){return f(a,d,c)})},deferred:function(b,c){if(!0!==c)throw Error("The 'deferred' extender only accepts the value 'true', because it is not supported to turn deferral off once enabled.");b.Hb||(b.Hb=!0,b.ub(function(c){var e,f=!1;return function(){if(!f){a.na.cancel(e);e=a.na.zb(c);try{f=!0,b.notifySubscribers(n,"dirty")}finally{f=
36613!1}}}}))},notify:function(a,c){a.equalityComparer="always"==c?null:K}};var W={undefined:1,"boolean":1,number:1,string:1};a.b("extenders",a.Ta);a.ic=function(b,c,d){this.da=b;this.lc=c;this.mc=d;this.Ib=!1;this.fb=this.Jb=null;a.L(this,"dispose",this.s);a.L(this,"disposeWhenNodeIsRemoved",this.l)};a.ic.prototype.s=function(){this.Ib||(this.fb&&a.a.K.yb(this.Jb,this.fb),this.Ib=!0,this.mc(),this.da=this.lc=this.mc=this.Jb=this.fb=null)};a.ic.prototype.l=function(b){this.Jb=b;a.a.K.za(b,this.fb=this.s.bind(this))};
36614a.T=function(){a.a.Ab(this,D);D.qb(this)};var D={qb:function(a){a.U={change:[]};a.sc=1},subscribe:function(b,c,d){var e=this;d=d||"change";var f=new a.ic(e,c?b.bind(c):b,function(){a.a.Pa(e.U[d],f);e.hb&&e.hb(d)});e.Qa&&e.Qa(d);e.U[d]||(e.U[d]=[]);e.U[d].push(f);return f},notifySubscribers:function(b,c){c=c||"change";"change"===c&&this.Gb();if(this.Wa(c)){var d="change"===c&&this.ed||this.U[c].slice(0);try{a.u.xc();for(var e=0,f;f=d[e];++e)f.Ib||f.lc(b)}finally{a.u.end()}}},ob:function(){return this.sc},
36615Dd:function(a){return this.ob()!==a},Gb:function(){++this.sc},ub:function(b){var c=this,d=a.O(c),e,f,g,h,m;c.gb||(c.gb=c.notifySubscribers,c.notifySubscribers=Z);var k=b(function(){c.Ja=!1;d&&h===c&&(h=c.nc?c.nc():c());var a=f||m&&c.sb(g,h);m=f=e=!1;a&&c.gb(g=h)});c.qc=function(a,b){b&&c.Ja||(m=!b);c.ed=c.U.change.slice(0);c.Ja=e=!0;h=a;k()};c.pc=function(a){e||(g=a,c.gb(a,"beforeChange"))};c.rc=function(){m=!0};c.gd=function(){c.sb(g,c.v(!0))&&(f=!0)}},Wa:function(a){return this.U[a]&&this.U[a].length},
36616Bd:function(b){if(b)return this.U[b]&&this.U[b].length||0;var c=0;a.a.P(this.U,function(a,b){"dirty"!==a&&(c+=b.length)});return c},sb:function(a,c){return!this.equalityComparer||!this.equalityComparer(a,c)},toString:function(){return"[object Object]"},extend:function(b){var c=this;b&&a.a.P(b,function(b,e){var f=a.Ta[b];"function"==typeof f&&(c=f(c,e)||c)});return c}};a.L(D,"init",D.qb);a.L(D,"subscribe",D.subscribe);a.L(D,"extend",D.extend);a.L(D,"getSubscriptionsCount",D.Bd);a.a.Ba&&a.a.setPrototypeOf(D,
36617Function.prototype);a.T.fn=D;a.Qc=function(a){return null!=a&&"function"==typeof a.subscribe&&"function"==typeof a.notifySubscribers};a.b("subscribable",a.T);a.b("isSubscribable",a.Qc);a.S=a.u=function(){function b(a){d.push(e);e=a}function c(){e=d.pop()}var d=[],e,f=0;return{xc:b,end:c,cc:function(b){if(e){if(!a.Qc(b))throw Error("Only subscribable things can act as dependencies");e.od.call(e.pd,b,b.fd||(b.fd=++f))}},G:function(a,d,e){try{return b(),a.apply(d,e||[])}finally{c()}},qa:function(){if(e)return e.o.qa()},
36618Va:function(){if(e)return e.o.Va()},Ya:function(){if(e)return e.Ya},o:function(){if(e)return e.o}}}();a.b("computedContext",a.S);a.b("computedContext.getDependenciesCount",a.S.qa);a.b("computedContext.getDependencies",a.S.Va);a.b("computedContext.isInitial",a.S.Ya);a.b("computedContext.registerDependency",a.S.cc);a.b("ignoreDependencies",a.Yd=a.u.G);var I=a.a.Da("_latestValue");a.ta=function(b){function c(){if(0<arguments.length)return c.sb(c[I],arguments[0])&&(c.ya(),c[I]=arguments[0],c.xa()),this;
36619a.u.cc(c);return c[I]}c[I]=b;a.a.Ba||a.a.extend(c,a.T.fn);a.T.fn.qb(c);a.a.Ab(c,F);a.options.deferUpdates&&a.Ta.deferred(c,!0);return c};var F={equalityComparer:K,v:function(){return this[I]},xa:function(){this.notifySubscribers(this[I],"spectate");this.notifySubscribers(this[I])},ya:function(){this.notifySubscribers(this[I],"beforeChange")}};a.a.Ba&&a.a.setPrototypeOf(F,a.T.fn);var G=a.ta.Ma="__ko_proto__";F[G]=a.ta;a.O=function(b){if((b="function"==typeof b&&b[G])&&b!==F[G]&&b!==a.o.fn[G])throw Error("Invalid object that looks like an observable; possibly from another Knockout instance");
36620return!!b};a.Za=function(b){return"function"==typeof b&&(b[G]===F[G]||b[G]===a.o.fn[G]&&b.Nc)};a.b("observable",a.ta);a.b("isObservable",a.O);a.b("isWriteableObservable",a.Za);a.b("isWritableObservable",a.Za);a.b("observable.fn",F);a.L(F,"peek",F.v);a.L(F,"valueHasMutated",F.xa);a.L(F,"valueWillMutate",F.ya);a.Ha=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.ta(b);a.a.Ab(b,
36621a.Ha.fn);return b.extend({trackArrayChanges:!0})};a.Ha.fn={remove:function(b){for(var c=this.v(),d=[],e="function"!=typeof b||a.O(b)?function(a){return a===b}:b,f=0;f<c.length;f++){var g=c[f];if(e(g)){0===d.length&&this.ya();if(c[f]!==g)throw Error("Array modified during remove; cannot remove item");d.push(g);c.splice(f,1);f--}}d.length&&this.xa();return d},removeAll:function(b){if(b===n){var c=this.v(),d=c.slice(0);this.ya();c.splice(0,c.length);this.xa();return d}return b?this.remove(function(c){return 0<=
36622a.a.A(b,c)}):[]},destroy:function(b){var c=this.v(),d="function"!=typeof b||a.O(b)?function(a){return a===b}:b;this.ya();for(var e=c.length-1;0<=e;e--){var f=c[e];d(f)&&(f._destroy=!0)}this.xa()},destroyAll:function(b){return b===n?this.destroy(function(){return!0}):b?this.destroy(function(c){return 0<=a.a.A(b,c)}):[]},indexOf:function(b){var c=this();return a.a.A(c,b)},replace:function(a,c){var d=this.indexOf(a);0<=d&&(this.ya(),this.v()[d]=c,this.xa())},sorted:function(a){var c=this().slice(0);
36623return a?c.sort(a):c.sort()},reversed:function(){return this().slice(0).reverse()}};a.a.Ba&&a.a.setPrototypeOf(a.Ha.fn,a.ta.fn);a.a.D("pop push reverse shift sort splice unshift".split(" "),function(b){a.Ha.fn[b]=function(){var a=this.v();this.ya();this.zc(a,b,arguments);var d=a[b].apply(a,arguments);this.xa();return d===a?this:d}});a.a.D(["slice"],function(b){a.Ha.fn[b]=function(){var a=this();return a[b].apply(a,arguments)}});a.Pc=function(b){return a.O(b)&&"function"==typeof b.remove&&"function"==
36624typeof b.push};a.b("observableArray",a.Ha);a.b("isObservableArray",a.Pc);a.Ta.trackArrayChanges=function(b,c){function d(){function c(){if(m){var d=[].concat(b.v()||[]),e;if(b.Wa("arrayChange")){if(!f||1<m)f=a.a.Pb(k,d,b.Ob);e=f}k=d;f=null;m=0;e&&e.length&&b.notifySubscribers(e,"arrayChange")}}e?c():(e=!0,h=b.subscribe(function(){++m},null,"spectate"),k=[].concat(b.v()||[]),f=null,g=b.subscribe(c))}b.Ob={};c&&"object"==typeof c&&a.a.extend(b.Ob,c);b.Ob.sparse=!0;if(!b.zc){var e=!1,f=null,g,h,m=0,
36625k,l=b.Qa,p=b.hb;b.Qa=function(a){l&&l.call(b,a);"arrayChange"===a&&d()};b.hb=function(a){p&&p.call(b,a);"arrayChange"!==a||b.Wa("arrayChange")||(g&&g.s(),h&&h.s(),h=g=null,e=!1,k=n)};b.zc=function(b,c,d){function l(a,b,c){return k[k.length]={status:a,value:b,index:c}}if(e&&!m){var k=[],p=b.length,g=d.length,h=0;switch(c){case "push":h=p;case "unshift":for(c=0;c<g;c++)l("added",d[c],h+c);break;case "pop":h=p-1;case "shift":p&&l("deleted",b[h],h);break;case "splice":c=Math.min(Math.max(0,0>d[0]?p+d[0]:
36626d[0]),p);for(var p=1===g?p:Math.min(c+(d[1]||0),p),g=c+g-2,h=Math.max(p,g),U=[],L=[],n=2;c<h;++c,++n)c<p&&L.push(l("deleted",b[c],c)),c<g&&U.push(l("added",d[n],c));a.a.Kc(L,U);break;default:return}f=k}}}};var r=a.a.Da("_state");a.o=a.$=function(b,c,d){function e(){if(0<arguments.length){if("function"===typeof f)f.apply(g.nb,arguments);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}g.ra||
36627a.u.cc(e);(g.ka||g.J&&e.Xa())&&e.ha();return g.X}"object"===typeof b?d=b:(d=d||{},b&&(d.read=b));if("function"!=typeof d.read)throw Error("Pass a function that returns the value of the ko.computed");var f=d.write,g={X:n,sa:!0,ka:!0,rb:!1,jc:!1,ra:!1,wb:!1,J:!1,Wc:d.read,nb:c||d.owner,l:d.disposeWhenNodeIsRemoved||d.l||null,Sa:d.disposeWhen||d.Sa,Rb:null,I:{},V:0,Ic:null};e[r]=g;e.Nc="function"===typeof f;a.a.Ba||a.a.extend(e,a.T.fn);a.T.fn.qb(e);a.a.Ab(e,C);d.pure?(g.wb=!0,g.J=!0,a.a.extend(e,da)):
36628d.deferEvaluation&&a.a.extend(e,ea);a.options.deferUpdates&&a.Ta.deferred(e,!0);g.l&&(g.jc=!0,g.l.nodeType||(g.l=null));g.J||d.deferEvaluation||e.ha();g.l&&e.ja()&&a.a.K.za(g.l,g.Rb=function(){e.s()});return e};var C={equalityComparer:K,qa:function(){return this[r].V},Va:function(){var b=[];a.a.P(this[r].I,function(a,d){b[d.Ka]=d.da});return b},Vb:function(b){if(!this[r].V)return!1;var c=this.Va();return-1!==a.a.A(c,b)?!0:!!a.a.Lb(c,function(a){return a.Vb&&a.Vb(b)})},uc:function(a,c,d){if(this[r].wb&&
36629c===this)throw Error("A 'pure' computed must not be called recursively");this[r].I[a]=d;d.Ka=this[r].V++;d.La=c.ob()},Xa:function(){var a,c,d=this[r].I;for(a in d)if(Object.prototype.hasOwnProperty.call(d,a)&&(c=d[a],this.Ia&&c.da.Ja||c.da.Dd(c.La)))return!0},Jd:function(){this.Ia&&!this[r].rb&&this.Ia(!1)},ja:function(){var a=this[r];return a.ka||0<a.V},Rd:function(){this.Ja?this[r].ka&&(this[r].sa=!0):this.Hc()},$c:function(a){if(a.Hb){var c=a.subscribe(this.Jd,this,"dirty"),d=a.subscribe(this.Rd,
36630this);return{da:a,s:function(){c.s();d.s()}}}return a.subscribe(this.Hc,this)},Hc:function(){var b=this,c=b.throttleEvaluation;c&&0<=c?(clearTimeout(this[r].Ic),this[r].Ic=a.a.setTimeout(function(){b.ha(!0)},c)):b.Ia?b.Ia(!0):b.ha(!0)},ha:function(b){var c=this[r],d=c.Sa,e=!1;if(!c.rb&&!c.ra){if(c.l&&!a.a.Sb(c.l)||d&&d()){if(!c.jc){this.s();return}}else c.jc=!1;c.rb=!0;try{e=this.zd(b)}finally{c.rb=!1}return e}},zd:function(b){var c=this[r],d=!1,e=c.wb?n:!c.V,d={qd:this,mb:c.I,Qb:c.V};a.u.xc({pd:d,
36631od:ba,o:this,Ya:e});c.I={};c.V=0;var f=this.yd(c,d);c.V?d=this.sb(c.X,f):(this.s(),d=!0);d&&(c.J?this.Gb():this.notifySubscribers(c.X,"beforeChange"),c.X=f,this.notifySubscribers(c.X,"spectate"),!c.J&&b&&this.notifySubscribers(c.X),this.rc&&this.rc());e&&this.notifySubscribers(c.X,"awake");return d},yd:function(b,c){try{var d=b.Wc;return b.nb?d.call(b.nb):d()}finally{a.u.end(),c.Qb&&!b.J&&a.a.P(c.mb,aa),b.sa=b.ka=!1}},v:function(a){var c=this[r];(c.ka&&(a||!c.V)||c.J&&this.Xa())&&this.ha();return c.X},
36632ub:function(b){a.T.fn.ub.call(this,b);this.nc=function(){this[r].J||(this[r].sa?this.ha():this[r].ka=!1);return this[r].X};this.Ia=function(a){this.pc(this[r].X);this[r].ka=!0;a&&(this[r].sa=!0);this.qc(this,!a)}},s:function(){var b=this[r];!b.J&&b.I&&a.a.P(b.I,function(a,b){b.s&&b.s()});b.l&&b.Rb&&a.a.K.yb(b.l,b.Rb);b.I=n;b.V=0;b.ra=!0;b.sa=!1;b.ka=!1;b.J=!1;b.l=n;b.Sa=n;b.Wc=n;this.Nc||(b.nb=n)}},da={Qa:function(b){var c=this,d=c[r];if(!d.ra&&d.J&&"change"==b){d.J=!1;if(d.sa||c.Xa())d.I=null,d.V=
366330,c.ha()&&c.Gb();else{var e=[];a.a.P(d.I,function(a,b){e[b.Ka]=a});a.a.D(e,function(a,b){var e=d.I[a],m=c.$c(e.da);m.Ka=b;m.La=e.La;d.I[a]=m});c.Xa()&&c.ha()&&c.Gb()}d.ra||c.notifySubscribers(d.X,"awake")}},hb:function(b){var c=this[r];c.ra||"change"!=b||this.Wa("change")||(a.a.P(c.I,function(a,b){b.s&&(c.I[a]={da:b.da,Ka:b.Ka,La:b.La},b.s())}),c.J=!0,this.notifySubscribers(n,"asleep"))},ob:function(){var b=this[r];b.J&&(b.sa||this.Xa())&&this.ha();return a.T.fn.ob.call(this)}},ea={Qa:function(a){"change"!=
36634a&&"beforeChange"!=a||this.v()}};a.a.Ba&&a.a.setPrototypeOf(C,a.T.fn);var N=a.ta.Ma;C[N]=a.o;a.Oc=function(a){return"function"==typeof a&&a[N]===C[N]};a.Fd=function(b){return a.Oc(b)&&b[r]&&b[r].wb};a.b("computed",a.o);a.b("dependentObservable",a.o);a.b("isComputed",a.Oc);a.b("isPureComputed",a.Fd);a.b("computed.fn",C);a.L(C,"peek",C.v);a.L(C,"dispose",C.s);a.L(C,"isActive",C.ja);a.L(C,"getDependenciesCount",C.qa);a.L(C,"getDependencies",C.Va);a.xb=function(b,c){if("function"===typeof b)return a.o(b,
36635c,{pure:!0});b=a.a.extend({},b);b.pure=!0;return a.o(b,c)};a.b("pureComputed",a.xb);(function(){function b(a,f,g){g=g||new d;a=f(a);if("object"!=typeof a||null===a||a===n||a instanceof RegExp||a instanceof Date||a instanceof String||a instanceof Number||a instanceof Boolean)return a;var h=a instanceof Array?[]:{};g.save(a,h);c(a,function(c){var d=f(a[c]);switch(typeof d){case "boolean":case "number":case "string":case "function":h[c]=d;break;case "object":case "undefined":var l=g.get(d);h[c]=l!==
36636n?l:b(d,f,g)}});return h}function c(a,b){if(a instanceof Array){for(var c=0;c<a.length;c++)b(c);"function"==typeof a.toJSON&&b("toJSON")}else for(c in a)b(c)}function d(){this.keys=[];this.values=[]}a.ad=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.O(b)&&10>c;c++)b=b();return b})};a.toJSON=function(b,c,d){b=a.ad(b);return a.a.hc(b,c,d)};d.prototype={constructor:d,save:function(b,c){var d=a.a.A(this.keys,
36637b);0<=d?this.values[d]=c:(this.keys.push(b),this.values.push(c))},get:function(b){b=a.a.A(this.keys,b);return 0<=b?this.values[b]:n}}})();a.b("toJS",a.ad);a.b("toJSON",a.toJSON);a.Wd=function(b,c,d){function e(c){var e=a.xb(b,d).extend({ma:"always"}),h=e.subscribe(function(a){a&&(h.s(),c(a))});e.notifySubscribers(e.v());return h}return"function"!==typeof Promise||c?e(c.bind(d)):new Promise(e)};a.b("when",a.Wd);(function(){a.w={M:function(b){switch(a.a.R(b)){case "option":return!0===b.__ko__hasDomDataOptionValue__?
36638a.a.g.get(b,a.c.options.$b):7>=a.a.W?b.getAttributeNode("value")&&b.getAttributeNode("value").specified?b.value:b.text:b.value;case "select":return 0<=b.selectedIndex?a.w.M(b.options[b.selectedIndex]):n;default:return b.value}},cb:function(b,c,d){switch(a.a.R(b)){case "option":"string"===typeof c?(a.a.g.set(b,a.c.options.$b,n),"__ko__hasDomDataOptionValue__"in b&&delete b.__ko__hasDomDataOptionValue__,b.value=c):(a.a.g.set(b,a.c.options.$b,c),b.__ko__hasDomDataOptionValue__=!0,b.value="number"===
36639typeof c?c:"");break;case "select":if(""===c||null===c)c=n;for(var e=-1,f=0,g=b.options.length,h;f<g;++f)if(h=a.w.M(b.options[f]),h==c||""===h&&c===n){e=f;break}if(d||0<=e||c===n&&1<b.size)b.selectedIndex=e,6===a.a.W&&a.a.setTimeout(function(){b.selectedIndex=e},0);break;default:if(null===c||c===n)c="";b.value=c}}}})();a.b("selectExtensions",a.w);a.b("selectExtensions.readValue",a.w.M);a.b("selectExtensions.writeValue",a.w.cb);a.m=function(){function b(b){b=a.a.Db(b);123===b.charCodeAt(0)&&(b=b.slice(1,
36640-1));b+="\n,";var c=[],d=b.match(e),p,q=[],h=0;if(1<d.length){for(var x=0,B;B=d[x];++x){var u=B.charCodeAt(0);if(44===u){if(0>=h){c.push(p&&q.length?{key:p,value:q.join("")}:{unknown:p||q.join("")});p=h=0;q=[];continue}}else if(58===u){if(!h&&!p&&1===q.length){p=q.pop();continue}}else if(47===u&&1<B.length&&(47===B.charCodeAt(1)||42===B.charCodeAt(1)))continue;else 47===u&&x&&1<B.length?(u=d[x-1].match(f))&&!g[u[0]]&&(b=b.substr(b.indexOf(B)+1),d=b.match(e),x=-1,B="/"):40===u||123===u||91===u?++h:
3664141===u||125===u||93===u?--h:p||q.length||34!==u&&39!==u||(B=B.slice(1,-1));q.push(B)}if(0<h)throw Error("Unbalanced parentheses, braces, or brackets");}return c}var c=["true","false","null","undefined"],d=/^(?:[$_a-z][$\w]*|(.+)(\.\s*[$_a-z][$\w]*|\[.+\]))$/i,e=RegExp("\"(?:\\\\.|[^\"])*\"|'(?:\\\\.|[^'])*'|`(?:\\\\.|[^`])*`|/\\*(?:[^*]|\\*+[^*/])*\\*+/|//.*\n|/(?:\\\\.|[^/])+/w*|[^\\s:,/][^,\"'`{}()/:[\\]]*[^\\s,\"'`{}()/:[\\]]|[^\\s]","g"),f=/[\])"'A-Za-z0-9_$]+$/,g={"in":1,"return":1,"typeof":1},
36642h={};return{Ra:[],wa:h,ac:b,vb:function(e,f){function l(b,e){var f;if(!x){var k=a.getBindingHandler(b);if(k&&k.preprocess&&!(e=k.preprocess(e,b,l)))return;if(k=h[b])f=e,0<=a.a.A(c,f)?f=!1:(k=f.match(d),f=null===k?!1:k[1]?"Object("+k[1]+")"+k[2]:f),k=f;k&&q.push("'"+("string"==typeof h[b]?h[b]:b)+"':function(_z){"+f+"=_z}")}g&&(e="function(){return "+e+" }");p.push("'"+b+"':"+e)}f=f||{};var p=[],q=[],g=f.valueAccessors,x=f.bindingParams,B="string"===typeof e?b(e):e;a.a.D(B,function(a){l(a.key||a.unknown,
36643a.value)});q.length&&l("_ko_property_writers","{"+q.join(",")+" }");return p.join(",")},Id:function(a,b){for(var c=0;c<a.length;c++)if(a[c].key==b)return!0;return!1},eb:function(b,c,d,e,f){if(b&&a.O(b))!a.Za(b)||f&&b.v()===e||b(e);else if((b=c.get("_ko_property_writers"))&&b[d])b[d](e)}}}();a.b("expressionRewriting",a.m);a.b("expressionRewriting.bindingRewriteValidators",a.m.Ra);a.b("expressionRewriting.parseObjectLiteral",a.m.ac);a.b("expressionRewriting.preProcessBindings",a.m.vb);a.b("expressionRewriting._twoWayBindings",
36644a.m.wa);a.b("jsonExpressionRewriting",a.m);a.b("jsonExpressionRewriting.insertPropertyAccessorsIntoJson",a.m.vb);(function(){function b(a){return 8==a.nodeType&&g.test(f?a.text:a.nodeValue)}function c(a){return 8==a.nodeType&&h.test(f?a.text:a.nodeValue)}function d(d,e){for(var f=d,h=1,g=[];f=f.nextSibling;){if(c(f)&&(a.a.g.set(f,k,!0),h--,0===h))return g;g.push(f);b(f)&&h++}if(!e)throw Error("Cannot find closing comment tag to match: "+d.nodeValue);return null}function e(a,b){var c=d(a,b);return c?
366450<c.length?c[c.length-1].nextSibling:a.nextSibling:null}var f=w&&"\x3c!--test--\x3e"===w.createComment("test").text,g=f?/^\x3c!--\s*ko(?:\s+([\s\S]+))?\s*--\x3e$/:/^\s*ko(?:\s+([\s\S]+))?\s*$/,h=f?/^\x3c!--\s*\/ko\s*--\x3e$/:/^\s*\/ko\s*$/,m={ul:!0,ol:!0},k="__ko_matchedEndComment__";a.h={ea:{},childNodes:function(a){return b(a)?d(a):a.childNodes},Ea:function(c){if(b(c)){c=a.h.childNodes(c);for(var d=0,e=c.length;d<e;d++)a.removeNode(c[d])}else a.a.Tb(c)},va:function(c,d){if(b(c)){a.h.Ea(c);for(var e=
36646c.nextSibling,f=0,k=d.length;f<k;f++)e.parentNode.insertBefore(d[f],e)}else a.a.va(c,d)},Vc:function(a,c){var d;b(a)?(d=a.nextSibling,a=a.parentNode):d=a.firstChild;d?c!==d&&a.insertBefore(c,d):a.appendChild(c)},Wb:function(c,d,e){e?(e=e.nextSibling,b(c)&&(c=c.parentNode),e?d!==e&&c.insertBefore(d,e):c.appendChild(d)):a.h.Vc(c,d)},firstChild:function(a){if(b(a))return!a.nextSibling||c(a.nextSibling)?null:a.nextSibling;if(a.firstChild&&c(a.firstChild))throw Error("Found invalid end comment, as the first child of "+
36647a);return a.firstChild},nextSibling:function(d){b(d)&&(d=e(d));if(d.nextSibling&&c(d.nextSibling)){var f=d.nextSibling;if(c(f)&&!a.a.g.get(f,k))throw Error("Found end comment without a matching opening comment, as child of "+d);return null}return d.nextSibling},Cd:b,Vd:function(a){return(a=(f?a.text:a.nodeValue).match(g))?a[1]:null},Sc:function(d){if(m[a.a.R(d)]){var f=d.firstChild;if(f){do if(1===f.nodeType){var k;k=f.firstChild;var h=null;if(k){do if(h)h.push(k);else if(b(k)){var g=e(k,!0);g?k=
36648g:h=[k]}else c(k)&&(h=[k]);while(k=k.nextSibling)}if(k=h)for(h=f.nextSibling,g=0;g<k.length;g++)h?d.insertBefore(k[g],h):d.appendChild(k[g])}while(f=f.nextSibling)}}}}})();a.b("virtualElements",a.h);a.b("virtualElements.allowedBindings",a.h.ea);a.b("virtualElements.emptyNode",a.h.Ea);a.b("virtualElements.insertAfter",a.h.Wb);a.b("virtualElements.prepend",a.h.Vc);a.b("virtualElements.setDomNodeChildren",a.h.va);(function(){a.ga=function(){this.nd={}};a.a.extend(a.ga.prototype,{nodeHasBindings:function(b){switch(b.nodeType){case 1:return null!=
36649b.getAttribute("data-bind")||a.j.getComponentNameForNode(b);case 8:return a.h.Cd(b);default:return!1}},getBindings:function(b,c){var d=this.getBindingsString(b,c),d=d?this.parseBindingsString(d,c,b):null;return a.j.tc(d,b,c,!1)},getBindingAccessors:function(b,c){var d=this.getBindingsString(b,c),d=d?this.parseBindingsString(d,c,b,{valueAccessors:!0}):null;return a.j.tc(d,b,c,!0)},getBindingsString:function(b){switch(b.nodeType){case 1:return b.getAttribute("data-bind");case 8:return a.h.Vd(b);default:return null}},
36650parseBindingsString:function(b,c,d,e){try{var f=this.nd,g=b+(e&&e.valueAccessors||""),h;if(!(h=f[g])){var m,k="with($context){with($data||{}){return{"+a.m.vb(b,e)+"}}}";m=new Function("$context","$element",k);h=f[g]=m}return h(c,d)}catch(l){throw l.message="Unable to parse bindings.\nBindings value: "+b+"\nMessage: "+l.message,l;}}});a.ga.instance=new a.ga})();a.b("bindingProvider",a.ga);(function(){function b(b){var c=(b=a.a.g.get(b,z))&&b.N;c&&(b.N=null,c.Tc())}function c(c,d,e){this.node=c;this.yc=
36651d;this.kb=[];this.H=!1;d.N||a.a.K.za(c,b);e&&e.N&&(e.N.kb.push(c),this.Kb=e)}function d(a){return function(){return a}}function e(a){return a()}function f(b){return a.a.Ga(a.u.G(b),function(a,c){return function(){return b()[c]}})}function g(b,c,e){return"function"===typeof b?f(b.bind(null,c,e)):a.a.Ga(b,d)}function h(a,b){return f(this.getBindings.bind(this,a,b))}function m(b,c){var d=a.h.firstChild(c);if(d){var e,f=a.ga.instance,l=f.preprocessNode;if(l){for(;e=d;)d=a.h.nextSibling(e),l.call(f,e);
36652d=a.h.firstChild(c)}for(;e=d;)d=a.h.nextSibling(e),k(b,e)}a.i.ma(c,a.i.H)}function k(b,c){var d=b,e=1===c.nodeType;e&&a.h.Sc(c);if(e||a.ga.instance.nodeHasBindings(c))d=p(c,null,b).bindingContextForDescendants;d&&!u[a.a.R(c)]&&m(d,c)}function l(b){var c=[],d={},e=[];a.a.P(b,function ca(f){if(!d[f]){var k=a.getBindingHandler(f);k&&(k.after&&(e.push(f),a.a.D(k.after,function(c){if(b[c]){if(-1!==a.a.A(e,c))throw Error("Cannot combine the following bindings, because they have a cyclic dependency: "+e.join(", "));
36653ca(c)}}),e.length--),c.push({key:f,Mc:k}));d[f]=!0}});return c}function p(b,c,d){var f=a.a.g.Ub(b,z,{}),k=f.hd;if(!c){if(k)throw Error("You cannot apply bindings multiple times to the same element.");f.hd=!0}k||(f.context=d);f.Zb||(f.Zb={});var g;if(c&&"function"!==typeof c)g=c;else{var p=a.ga.instance,q=p.getBindingAccessors||h,m=a.$(function(){if(g=c?c(d,b):q.call(p,b,d)){if(d[t])d[t]();if(d[B])d[B]()}return g},null,{l:b});g&&m.ja()||(m=null)}var x=d,u;if(g){var J=function(){return a.a.Ga(m?m():
36654g,e)},r=m?function(a){return function(){return e(m()[a])}}:function(a){return g[a]};J.get=function(a){return g[a]&&e(r(a))};J.has=function(a){return a in g};a.i.H in g&&a.i.subscribe(b,a.i.H,function(){var c=(0,g[a.i.H])();if(c){var d=a.h.childNodes(b);d.length&&c(d,a.Ec(d[0]))}});a.i.pa in g&&(x=a.i.Cb(b,d),a.i.subscribe(b,a.i.pa,function(){var c=(0,g[a.i.pa])();c&&a.h.firstChild(b)&&c(b)}));f=l(g);a.a.D(f,function(c){var d=c.Mc.init,e=c.Mc.update,f=c.key;if(8===b.nodeType&&!a.h.ea[f])throw Error("The binding '"+
36655f+"' cannot be used with virtual elements");try{"function"==typeof d&&a.u.G(function(){var a=d(b,r(f),J,x.$data,x);if(a&&a.controlsDescendantBindings){if(u!==n)throw Error("Multiple bindings ("+u+" and "+f+") are trying to control descendant bindings of the same element. You cannot use these bindings together on the same element.");u=f}}),"function"==typeof e&&a.$(function(){e(b,r(f),J,x.$data,x)},null,{l:b})}catch(k){throw k.message='Unable to process binding "'+f+": "+g[f]+'"\nMessage: '+k.message,
36656k;}})}f=u===n;return{shouldBindDescendants:f,bindingContextForDescendants:f&&x}}function q(b,c){return b&&b instanceof a.fa?b:new a.fa(b,n,n,c)}var t=a.a.Da("_subscribable"),x=a.a.Da("_ancestorBindingInfo"),B=a.a.Da("_dataDependency");a.c={};var u={script:!0,textarea:!0,template:!0};a.getBindingHandler=function(b){return a.c[b]};var J={};a.fa=function(b,c,d,e,f){function k(){var b=p?h():h,f=a.a.f(b);c?(a.a.extend(l,c),x in c&&(l[x]=c[x])):(l.$parents=[],l.$root=f,l.ko=a);l[t]=q;g?f=l.$data:(l.$rawData=
36657b,l.$data=f);d&&(l[d]=f);e&&e(l,c,f);if(c&&c[t]&&!a.S.o().Vb(c[t]))c[t]();m&&(l[B]=m);return l.$data}var l=this,g=b===J,h=g?n:b,p="function"==typeof h&&!a.O(h),q,m=f&&f.dataDependency;f&&f.exportDependencies?k():(q=a.xb(k),q.v(),q.ja()?q.equalityComparer=null:l[t]=n)};a.fa.prototype.createChildContext=function(b,c,d,e){!e&&c&&"object"==typeof c&&(e=c,c=e.as,d=e.extend);if(c&&e&&e.noChildContext){var f="function"==typeof b&&!a.O(b);return new a.fa(J,this,null,function(a){d&&d(a);a[c]=f?b():b},e)}return new a.fa(b,
36658this,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)},e)};a.fa.prototype.extend=function(b,c){return new a.fa(J,this,null,function(c){a.a.extend(c,"function"==typeof b?b(c):b)},c)};var z=a.a.g.Z();c.prototype.Tc=function(){this.Kb&&this.Kb.N&&this.Kb.N.sd(this.node)};c.prototype.sd=function(b){a.a.Pa(this.kb,b);!this.kb.length&&this.H&&this.Cc()};c.prototype.Cc=function(){this.H=!0;this.yc.N&&!this.kb.length&&(this.yc.N=
36659null,a.a.K.yb(this.node,b),a.i.ma(this.node,a.i.pa),this.Tc())};a.i={H:"childrenComplete",pa:"descendantsComplete",subscribe:function(b,c,d,e,f){var k=a.a.g.Ub(b,z,{});k.Fa||(k.Fa=new a.T);f&&f.notifyImmediately&&k.Zb[c]&&a.u.G(d,e,[b]);return k.Fa.subscribe(d,e,c)},ma:function(b,c){var d=a.a.g.get(b,z);if(d&&(d.Zb[c]=!0,d.Fa&&d.Fa.notifySubscribers(b,c),c==a.i.H))if(d.N)d.N.Cc();else if(d.N===n&&d.Fa&&d.Fa.Wa(a.i.pa))throw Error("descendantsComplete event not supported for bindings on this node");
36660},Cb:function(b,d){var e=a.a.g.Ub(b,z,{});e.N||(e.N=new c(b,e,d[x]));return d[x]==e?d:d.extend(function(a){a[x]=e})}};a.Td=function(b){return(b=a.a.g.get(b,z))&&b.context};a.ib=function(b,c,d){1===b.nodeType&&a.h.Sc(b);return p(b,c,q(d))};a.ld=function(b,c,d){d=q(d);return a.ib(b,g(c,d,b),d)};a.Oa=function(a,b){1!==b.nodeType&&8!==b.nodeType||m(q(a),b)};a.vc=function(a,b,c){!v&&A.jQuery&&(v=A.jQuery);if(2>arguments.length){if(b=w.body,!b)throw Error("ko.applyBindings: could not find document.body; has the document been loaded?");
36661}else 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");k(q(a,c),b)};a.Dc=function(b){return!b||1!==b.nodeType&&8!==b.nodeType?n:a.Td(b)};a.Ec=function(b){return(b=a.Dc(b))?b.$data:n};a.b("bindingHandlers",a.c);a.b("bindingEvent",a.i);a.b("bindingEvent.subscribe",a.i.subscribe);a.b("bindingEvent.startPossiblyAsyncContentBinding",a.i.Cb);a.b("applyBindings",a.vc);a.b("applyBindingsToDescendants",a.Oa);
36662a.b("applyBindingAccessorsToNode",a.ib);a.b("applyBindingsToNode",a.ld);a.b("contextFor",a.Dc);a.b("dataFor",a.Ec)})();(function(b){function c(c,e){var k=Object.prototype.hasOwnProperty.call(f,c)?f[c]:b,l;k?k.subscribe(e):(k=f[c]=new a.T,k.subscribe(e),d(c,function(b,d){var e=!(!d||!d.synchronous);g[c]={definition:b,Gd:e};delete f[c];l||e?k.notifySubscribers(b):a.na.zb(function(){k.notifySubscribers(b)})}),l=!0)}function d(a,b){e("getConfig",[a],function(c){c?e("loadComponent",[a,c],function(a){b(a,
36663c)}):b(null,null)})}function e(c,d,f,l){l||(l=a.j.loaders.slice(0));var g=l.shift();if(g){var q=g[c];if(q){var t=!1;if(q.apply(g,d.concat(function(a){t?f(null):null!==a?f(a):e(c,d,f,l)}))!==b&&(t=!0,!g.suppressLoaderExceptions))throw Error("Component loaders must supply values by invoking the callback, not by returning values synchronously.");}else e(c,d,f,l)}else f(null)}var f={},g={};a.j={get:function(d,e){var f=Object.prototype.hasOwnProperty.call(g,d)?g[d]:b;f?f.Gd?a.u.G(function(){e(f.definition)}):
36664a.na.zb(function(){e(f.definition)}):c(d,e)},Bc:function(a){delete g[a]},oc:e};a.j.loaders=[];a.b("components",a.j);a.b("components.get",a.j.get);a.b("components.clearCachedDefinition",a.j.Bc)})();(function(){function b(b,c,d,e){function g(){0===--B&&e(h)}var h={},B=2,u=d.template;d=d.viewModel;u?f(c,u,function(c){a.j.oc("loadTemplate",[b,c],function(a){h.template=a;g()})}):g();d?f(c,d,function(c){a.j.oc("loadViewModel",[b,c],function(a){h[m]=a;g()})}):g()}function c(a,b,d){if("function"===typeof b)d(function(a){return new b(a)});
36665else if("function"===typeof b[m])d(b[m]);else if("instance"in b){var e=b.instance;d(function(){return e})}else"viewModel"in b?c(a,b.viewModel,d):a("Unknown viewModel value: "+b)}function d(b){switch(a.a.R(b)){case "script":return a.a.ua(b.text);case "textarea":return a.a.ua(b.value);case "template":if(e(b.content))return a.a.Ca(b.content.childNodes)}return a.a.Ca(b.childNodes)}function e(a){return A.DocumentFragment?a instanceof DocumentFragment:a&&11===a.nodeType}function f(a,b,c){"string"===typeof b.require?
36666T||A.require?(T||A.require)([b.require],function(a){a&&"object"===typeof a&&a.Xd&&a["default"]&&(a=a["default"]);c(a)}):a("Uses require, but no AMD loader is present"):c(b)}function g(a){return function(b){throw Error("Component '"+a+"': "+b);}}var h={};a.j.register=function(b,c){if(!c)throw Error("Invalid configuration for "+b);if(a.j.tb(b))throw Error("Component "+b+" is already registered");h[b]=c};a.j.tb=function(a){return Object.prototype.hasOwnProperty.call(h,a)};a.j.unregister=function(b){delete h[b];
36667a.j.Bc(b)};a.j.Fc={getConfig:function(b,c){c(a.j.tb(b)?h[b]:null)},loadComponent:function(a,c,d){var e=g(a);f(e,c,function(c){b(a,e,c,d)})},loadTemplate:function(b,c,f){b=g(b);if("string"===typeof c)f(a.a.ua(c));else if(c instanceof Array)f(c);else if(e(c))f(a.a.la(c.childNodes));else if(c.element)if(c=c.element,A.HTMLElement?c instanceof HTMLElement:c&&c.tagName&&1===c.nodeType)f(d(c));else if("string"===typeof c){var h=w.getElementById(c);h?f(d(h)):b("Cannot find element with ID "+c)}else b("Unknown element type: "+
36668c);else b("Unknown template value: "+c)},loadViewModel:function(a,b,d){c(g(a),b,d)}};var m="createViewModel";a.b("components.register",a.j.register);a.b("components.isRegistered",a.j.tb);a.b("components.unregister",a.j.unregister);a.b("components.defaultLoader",a.j.Fc);a.j.loaders.push(a.j.Fc);a.j.dd=h})();(function(){function b(b,e){var f=b.getAttribute("params");if(f){var f=c.parseBindingsString(f,e,b,{valueAccessors:!0,bindingParams:!0}),f=a.a.Ga(f,function(c){return a.o(c,null,{l:b})}),g=a.a.Ga(f,
36669function(c){var e=c.v();return c.ja()?a.o({read:function(){return a.a.f(c())},write:a.Za(e)&&function(a){c()(a)},l:b}):e});Object.prototype.hasOwnProperty.call(g,"$raw")||(g.$raw=f);return g}return{$raw:{}}}a.j.getComponentNameForNode=function(b){var c=a.a.R(b);if(a.j.tb(c)&&(-1!=c.indexOf("-")||"[object HTMLUnknownElement]"==""+b||8>=a.a.W&&b.tagName===c))return c};a.j.tc=function(c,e,f,g){if(1===e.nodeType){var h=a.j.getComponentNameForNode(e);if(h){c=c||{};if(c.component)throw Error('Cannot use the "component" binding on a custom element matching a component');
36670var m={name:h,params:b(e,f)};c.component=g?function(){return m}:m}}return c};var c=new a.ga;9>a.a.W&&(a.j.register=function(a){return function(b){return a.apply(this,arguments)}}(a.j.register),w.createDocumentFragment=function(b){return function(){var c=b(),f=a.j.dd,g;for(g in f);return c}}(w.createDocumentFragment))})();(function(){function b(b,c,d){c=c.template;if(!c)throw Error("Component '"+b+"' has no template");b=a.a.Ca(c);a.h.va(d,b)}function c(a,b,c){var d=a.createViewModel;return d?d.call(a,
36671b,c):b}var d=0;a.c.component={init:function(e,f,g,h,m){function k(){var a=l&&l.dispose;"function"===typeof a&&a.call(l);q&&q.s();p=l=q=null}var l,p,q,t=a.a.la(a.h.childNodes(e));a.h.Ea(e);a.a.K.za(e,k);a.o(function(){var g=a.a.f(f()),h,u;"string"===typeof g?h=g:(h=a.a.f(g.name),u=a.a.f(g.params));if(!h)throw Error("No component name specified");var n=a.i.Cb(e,m),z=p=++d;a.j.get(h,function(d){if(p===z){k();if(!d)throw Error("Unknown component '"+h+"'");b(h,d,e);var f=c(d,u,{element:e,templateNodes:t});
36672d=n.createChildContext(f,{extend:function(a){a.$component=f;a.$componentTemplateNodes=t}});f&&f.koDescendantsComplete&&(q=a.i.subscribe(e,a.i.pa,f.koDescendantsComplete,f));l=f;a.Oa(d,e)}})},null,{l:e});return{controlsDescendantBindings:!0}}};a.h.ea.component=!0})();var V={"class":"className","for":"htmlFor"};a.c.attr={update:function(b,c){var d=a.a.f(c())||{};a.a.P(d,function(c,d){d=a.a.f(d);var g=c.indexOf(":"),g="lookupNamespaceURI"in b&&0<g&&b.lookupNamespaceURI(c.substr(0,g)),h=!1===d||null===
36673d||d===n;h?g?b.removeAttributeNS(g,c):b.removeAttribute(c):d=d.toString();8>=a.a.W&&c in V?(c=V[c],h?b.removeAttribute(c):b[c]=d):h||(g?b.setAttributeNS(g,c,d):b.setAttribute(c,d));"name"===c&&a.a.Yc(b,h?"":d)})}};(function(){a.c.checked={after:["value","attr"],init:function(b,c,d){function e(){var e=b.checked,f=g();if(!a.S.Ya()&&(e||!m&&!a.S.qa())){var k=a.u.G(c);if(l){var q=p?k.v():k,z=t;t=f;z!==f?e&&(a.a.Na(q,f,!0),a.a.Na(q,z,!1)):a.a.Na(q,f,e);p&&a.Za(k)&&k(q)}else h&&(f===n?f=e:e||(f=n)),a.m.eb(k,
36674d,"checked",f,!0)}}function f(){var d=a.a.f(c()),e=g();l?(b.checked=0<=a.a.A(d,e),t=e):b.checked=h&&e===n?!!d:g()===d}var g=a.xb(function(){if(d.has("checkedValue"))return a.a.f(d.get("checkedValue"));if(q)return d.has("value")?a.a.f(d.get("value")):b.value}),h="checkbox"==b.type,m="radio"==b.type;if(h||m){var k=c(),l=h&&a.a.f(k)instanceof Array,p=!(l&&k.push&&k.splice),q=m||l,t=l?g():n;m&&!b.name&&a.c.uniqueName.init(b,function(){return!0});a.o(e,null,{l:b});a.a.B(b,"click",e);a.o(f,null,{l:b});
36675k=n}}};a.m.wa.checked=!0;a.c.checkedValue={update:function(b,c){b.value=a.a.f(c())}}})();a.c["class"]={update:function(b,c){var d=a.a.Db(a.a.f(c()));a.a.Eb(b,b.__ko__cssValue,!1);b.__ko__cssValue=d;a.a.Eb(b,d,!0)}};a.c.css={update:function(b,c){var d=a.a.f(c());null!==d&&"object"==typeof d?a.a.P(d,function(c,d){d=a.a.f(d);a.a.Eb(b,c,d)}):a.c["class"].update(b,c)}};a.c.enable={update:function(b,c){var d=a.a.f(c());d&&b.disabled?b.removeAttribute("disabled"):d||b.disabled||(b.disabled=!0)}};a.c.disable=
36676{update:function(b,c){a.c.enable.update(b,function(){return!a.a.f(c())})}};a.c.event={init:function(b,c,d,e,f){var g=c()||{};a.a.P(g,function(g){"string"==typeof g&&a.a.B(b,g,function(b){var k,l=c()[g];if(l){try{var p=a.a.la(arguments);e=f.$data;p.unshift(e);k=l.apply(e,p)}finally{!0!==k&&(b.preventDefault?b.preventDefault():b.returnValue=!1)}!1===d.get(g+"Bubble")&&(b.cancelBubble=!0,b.stopPropagation&&b.stopPropagation())}})})}};a.c.foreach={Rc:function(b){return function(){var c=b(),d=a.a.bc(c);
36677if(!d||"number"==typeof d.length)return{foreach:c,templateEngine:a.ba.Ma};a.a.f(c);return{foreach:d.data,as:d.as,noChildContext:d.noChildContext,includeDestroyed:d.includeDestroyed,afterAdd:d.afterAdd,beforeRemove:d.beforeRemove,afterRender:d.afterRender,beforeMove:d.beforeMove,afterMove:d.afterMove,templateEngine:a.ba.Ma}}},init:function(b,c){return a.c.template.init(b,a.c.foreach.Rc(c))},update:function(b,c,d,e,f){return a.c.template.update(b,a.c.foreach.Rc(c),d,e,f)}};a.m.Ra.foreach=!1;a.h.ea.foreach=
36678!0;a.c.hasfocus={init:function(b,c,d){function e(e){b.__ko_hasfocusUpdating=!0;var f=b.ownerDocument;if("activeElement"in f){var g;try{g=f.activeElement}catch(l){g=f.body}e=g===b}f=c();a.m.eb(f,d,"hasfocus",e,!0);b.__ko_hasfocusLastValue=e;b.__ko_hasfocusUpdating=!1}var f=e.bind(null,!0),g=e.bind(null,!1);a.a.B(b,"focus",f);a.a.B(b,"focusin",f);a.a.B(b,"blur",g);a.a.B(b,"focusout",g);b.__ko_hasfocusLastValue=!1},update:function(b,c){var d=!!a.a.f(c());b.__ko_hasfocusUpdating||b.__ko_hasfocusLastValue===
36679d||(d?b.focus():b.blur(),!d&&b.__ko_hasfocusLastValue&&b.ownerDocument.body.focus(),a.u.G(a.a.Fb,null,[b,d?"focusin":"focusout"]))}};a.m.wa.hasfocus=!0;a.c.hasFocus=a.c.hasfocus;a.m.wa.hasFocus="hasfocus";a.c.html={init:function(){return{controlsDescendantBindings:!0}},update:function(b,c){a.a.fc(b,c())}};(function(){function b(b,d,e){a.c[b]={init:function(b,c,h,m,k){var l,p,q={},t,x,n;if(d){m=h.get("as");var u=h.get("noChildContext");n=!(m&&u);q={as:m,noChildContext:u,exportDependencies:n}}x=(t=
36680"render"==h.get("completeOn"))||h.has(a.i.pa);a.o(function(){var h=a.a.f(c()),m=!e!==!h,u=!p,r;if(n||m!==l){x&&(k=a.i.Cb(b,k));if(m){if(!d||n)q.dataDependency=a.S.o();r=d?k.createChildContext("function"==typeof h?h:c,q):a.S.qa()?k.extend(null,q):k}u&&a.S.qa()&&(p=a.a.Ca(a.h.childNodes(b),!0));m?(u||a.h.va(b,a.a.Ca(p)),a.Oa(r,b)):(a.h.Ea(b),t||a.i.ma(b,a.i.H));l=m}},null,{l:b});return{controlsDescendantBindings:!0}}};a.m.Ra[b]=!1;a.h.ea[b]=!0}b("if");b("ifnot",!1,!0);b("with",!0)})();a.c.let={init:function(b,
36681c,d,e,f){c=f.extend(c);a.Oa(c,b);return{controlsDescendantBindings:!0}}};a.h.ea.let=!0;var Q={};a.c.options={init:function(b){if("select"!==a.a.R(b))throw Error("options binding applies only to SELECT elements");for(;0<b.length;)b.remove(0);return{controlsDescendantBindings:!0}},update:function(b,c,d){function e(){return a.a.jb(b.options,function(a){return a.selected})}function f(a,b,c){var d=typeof b;return"function"==d?b(a):"string"==d?a[b]:c}function g(c,d){if(x&&l)a.i.ma(b,a.i.H);else if(t.length){var e=
366820<=a.a.A(t,a.w.M(d[0]));a.a.Zc(d[0],e);x&&!e&&a.u.G(a.a.Fb,null,[b,"change"])}}var h=b.multiple,m=0!=b.length&&h?b.scrollTop:null,k=a.a.f(c()),l=d.get("valueAllowUnset")&&d.has("value"),p=d.get("optionsIncludeDestroyed");c={};var q,t=[];l||(h?t=a.a.Mb(e(),a.w.M):0<=b.selectedIndex&&t.push(a.w.M(b.options[b.selectedIndex])));k&&("undefined"==typeof k.length&&(k=[k]),q=a.a.jb(k,function(b){return p||b===n||null===b||!a.a.f(b._destroy)}),d.has("optionsCaption")&&(k=a.a.f(d.get("optionsCaption")),null!==
36683k&&k!==n&&q.unshift(Q)));var x=!1;c.beforeRemove=function(a){b.removeChild(a)};k=g;d.has("optionsAfterRender")&&"function"==typeof d.get("optionsAfterRender")&&(k=function(b,c){g(0,c);a.u.G(d.get("optionsAfterRender"),null,[c[0],b!==Q?b:n])});a.a.ec(b,q,function(c,e,g){g.length&&(t=!l&&g[0].selected?[a.w.M(g[0])]:[],x=!0);e=b.ownerDocument.createElement("option");c===Q?(a.a.Bb(e,d.get("optionsCaption")),a.w.cb(e,n)):(g=f(c,d.get("optionsValue"),c),a.w.cb(e,a.a.f(g)),c=f(c,d.get("optionsText"),g),
36684a.a.Bb(e,c));return[e]},c,k);if(!l){var B;h?B=t.length&&e().length<t.length:B=t.length&&0<=b.selectedIndex?a.w.M(b.options[b.selectedIndex])!==t[0]:t.length||0<=b.selectedIndex;B&&a.u.G(a.a.Fb,null,[b,"change"])}(l||a.S.Ya())&&a.i.ma(b,a.i.H);a.a.wd(b);m&&20<Math.abs(m-b.scrollTop)&&(b.scrollTop=m)}};a.c.options.$b=a.a.g.Z();a.c.selectedOptions={init:function(b,c,d){function e(){var e=c(),f=[];a.a.D(b.getElementsByTagName("option"),function(b){b.selected&&f.push(a.w.M(b))});a.m.eb(e,d,"selectedOptions",
36685f)}function f(){var d=a.a.f(c()),e=b.scrollTop;d&&"number"==typeof d.length&&a.a.D(b.getElementsByTagName("option"),function(b){var c=0<=a.a.A(d,a.w.M(b));b.selected!=c&&a.a.Zc(b,c)});b.scrollTop=e}if("select"!=a.a.R(b))throw Error("selectedOptions binding applies only to SELECT elements");var g;a.i.subscribe(b,a.i.H,function(){g?e():(a.a.B(b,"change",e),g=a.o(f,null,{l:b}))},null,{notifyImmediately:!0})},update:function(){}};a.m.wa.selectedOptions=!0;a.c.style={update:function(b,c){var d=a.a.f(c()||
36686{});a.a.P(d,function(c,d){d=a.a.f(d);if(null===d||d===n||!1===d)d="";if(v)v(b).css(c,d);else if(/^--/.test(c))b.style.setProperty(c,d);else{c=c.replace(/-(\w)/g,function(a,b){return b.toUpperCase()});var g=b.style[c];b.style[c]=d;d===g||b.style[c]!=g||isNaN(d)||(b.style[c]=d+"px")}})}};a.c.submit={init:function(b,c,d,e,f){if("function"!=typeof c())throw Error("The value for a submit binding must be a function");a.a.B(b,"submit",function(a){var d,e=c();try{d=e.call(f.$data,b)}finally{!0!==d&&(a.preventDefault?
36687a.preventDefault():a.returnValue=!1)}})}};a.c.text={init:function(){return{controlsDescendantBindings:!0}},update:function(b,c){a.a.Bb(b,c())}};a.h.ea.text=!0;(function(){if(A&&A.navigator){var b=function(a){if(a)return parseFloat(a[1])},c=A.navigator.userAgent,d,e,f,g,h;(d=A.opera&&A.opera.version&&parseInt(A.opera.version()))||(h=b(c.match(/Edge\/([^ ]+)$/)))||b(c.match(/Chrome\/([^ ]+)/))||(e=b(c.match(/Version\/([^ ]+) Safari/)))||(f=b(c.match(/Firefox\/([^ ]+)/)))||(g=a.a.W||b(c.match(/MSIE ([^ ]+)/)))||
36688(g=b(c.match(/rv:([^ )]+)/)))}if(8<=g&&10>g)var m=a.a.g.Z(),k=a.a.g.Z(),l=function(b){var c=this.activeElement;(c=c&&a.a.g.get(c,k))&&c(b)},p=function(b,c){var d=b.ownerDocument;a.a.g.get(d,m)||(a.a.g.set(d,m,!0),a.a.B(d,"selectionchange",l));a.a.g.set(b,k,c)};a.c.textInput={init:function(b,c,k){function l(c,d){a.a.B(b,c,d)}function m(){var d=a.a.f(c());if(null===d||d===n)d="";L!==n&&d===L?a.a.setTimeout(m,4):b.value!==d&&(y=!0,b.value=d,y=!1,v=b.value)}function r(){w||(L=b.value,w=a.a.setTimeout(z,
366894))}function z(){clearTimeout(w);L=w=n;var d=b.value;v!==d&&(v=d,a.m.eb(c(),k,"textInput",d))}var v=b.value,w,L,A=9==a.a.W?r:z,y=!1;g&&l("keypress",z);11>g&&l("propertychange",function(a){y||"value"!==a.propertyName||A(a)});8==g&&(l("keyup",z),l("keydown",z));p&&(p(b,A),l("dragend",r));(!g||9<=g)&&l("input",A);5>e&&"textarea"===a.a.R(b)?(l("keydown",r),l("paste",r),l("cut",r)):11>d?l("keydown",r):4>f?(l("DOMAutoComplete",z),l("dragdrop",z),l("drop",z)):h&&"number"===b.type&&l("keydown",r);l("change",
36690z);l("blur",z);a.o(m,null,{l:b})}};a.m.wa.textInput=!0;a.c.textinput={preprocess:function(a,b,c){c("textInput",a)}}})();a.c.uniqueName={init:function(b,c){if(c()){var d="ko_unique_"+ ++a.c.uniqueName.rd;a.a.Yc(b,d)}}};a.c.uniqueName.rd=0;a.c.using={init:function(b,c,d,e,f){var g;d.has("as")&&(g={as:d.get("as"),noChildContext:d.get("noChildContext")});c=f.createChildContext(c,g);a.Oa(c,b);return{controlsDescendantBindings:!0}}};a.h.ea.using=!0;a.c.value={init:function(b,c,d){var e=a.a.R(b),f="input"==
36691e;if(!f||"checkbox"!=b.type&&"radio"!=b.type){var g=[],h=d.get("valueUpdate"),m=!1,k=null;h&&("string"==typeof h?g=[h]:g=a.a.wc(h),a.a.Pa(g,"change"));var l=function(){k=null;m=!1;var e=c(),f=a.w.M(b);a.m.eb(e,d,"value",f)};!a.a.W||!f||"text"!=b.type||"off"==b.autocomplete||b.form&&"off"==b.form.autocomplete||-1!=a.a.A(g,"propertychange")||(a.a.B(b,"propertychange",function(){m=!0}),a.a.B(b,"focus",function(){m=!1}),a.a.B(b,"blur",function(){m&&l()}));a.a.D(g,function(c){var d=l;a.a.Ud(c,"after")&&
36692(d=function(){k=a.w.M(b);a.a.setTimeout(l,0)},c=c.substring(5));a.a.B(b,c,d)});var p;p=f&&"file"==b.type?function(){var d=a.a.f(c());null===d||d===n||""===d?b.value="":a.u.G(l)}:function(){var f=a.a.f(c()),g=a.w.M(b);if(null!==k&&f===k)a.a.setTimeout(p,0);else if(f!==g||g===n)"select"===e?(g=d.get("valueAllowUnset"),a.w.cb(b,f,g),g||f===a.w.M(b)||a.u.G(l)):a.w.cb(b,f)};if("select"===e){var q;a.i.subscribe(b,a.i.H,function(){q?d.get("valueAllowUnset")?p():l():(a.a.B(b,"change",l),q=a.o(p,null,{l:b}))},
36693null,{notifyImmediately:!0})}else a.a.B(b,"change",l),a.o(p,null,{l:b})}else a.ib(b,{checkedValue:c})},update:function(){}};a.m.wa.value=!0;a.c.visible={update:function(b,c){var d=a.a.f(c()),e="none"!=b.style.display;d&&!e?b.style.display="":!d&&e&&(b.style.display="none")}};a.c.hidden={update:function(b,c){a.c.visible.update(b,function(){return!a.a.f(c())})}};(function(b){a.c[b]={init:function(c,d,e,f,g){return a.c.event.init.call(this,c,function(){var a={};a[b]=d();return a},e,f,g)}}})("click");
36694a.ca=function(){};a.ca.prototype.renderTemplateSource=function(){throw Error("Override renderTemplateSource");};a.ca.prototype.createJavaScriptEvaluatorBlock=function(){throw Error("Override createJavaScriptEvaluatorBlock");};a.ca.prototype.makeTemplateSource=function(b,c){if("string"==typeof b){c=c||w;var d=c.getElementById(b);if(!d)throw Error("Cannot find template with ID "+b);return new a.C.F(d)}if(1==b.nodeType||8==b.nodeType)return new a.C.ia(b);throw Error("Unknown template type: "+b);};a.ca.prototype.renderTemplate=
36695function(a,c,d,e){a=this.makeTemplateSource(a,e);return this.renderTemplateSource(a,c,d,e)};a.ca.prototype.isTemplateRewritten=function(a,c){return!1===this.allowTemplateRewriting?!0:this.makeTemplateSource(a,c).data("isRewritten")};a.ca.prototype.rewriteTemplate=function(a,c,d){a=this.makeTemplateSource(a,d);c=c(a.text());a.text(c);a.data("isRewritten",!0)};a.b("templateEngine",a.ca);a.kc=function(){function b(b,c,d,h){b=a.m.ac(b);for(var m=a.m.Ra,k=0;k<b.length;k++){var l=b[k].key;if(Object.prototype.hasOwnProperty.call(m,
36696l)){var p=m[l];if("function"===typeof p){if(l=p(b[k].value))throw Error(l);}else if(!p)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.m.vb(b,{valueAccessors:!0})+" } })()},'"+d.toLowerCase()+"')";return h.createJavaScriptEvaluatorBlock(d)+c}var c=/(<([a-z]+\d*)(?:\s+(?!data-bind\s*=\s*)[a-z0-9\-]+(?:=(?:\"[^\"]*\"|\'[^\']*\'|[^>]*))?)*\s+)data-bind\s*=\s*(["'])([\s\S]*?)\3/gi,
36697d=/\x3c!--\s*ko\b\s*([\s\S]*?)\s*--\x3e/g;return{xd:function(b,c,d){c.isTemplateRewritten(b,d)||c.rewriteTemplate(b,function(b){return a.kc.Ld(b,c)},d)},Ld:function(a,f){return a.replace(c,function(a,c,d,e,l){return b(l,c,d,f)}).replace(d,function(a,c){return b(c,"\x3c!-- ko --\x3e","#comment",f)})},md:function(b,c){return a.aa.Xb(function(d,h){var m=d.nextSibling;m&&m.nodeName.toLowerCase()===c&&a.ib(m,b,h)})}}}();a.b("__tr_ambtns",a.kc.md);(function(){a.C={};a.C.F=function(b){if(this.F=b){var c=
36698a.a.R(b);this.ab="script"===c?1:"textarea"===c?2:"template"==c&&b.content&&11===b.content.nodeType?3:4}};a.C.F.prototype.text=function(){var b=1===this.ab?"text":2===this.ab?"value":"innerHTML";if(0==arguments.length)return this.F[b];var c=arguments[0];"innerHTML"===b?a.a.fc(this.F,c):this.F[b]=c};var b=a.a.g.Z()+"_";a.C.F.prototype.data=function(c){if(1===arguments.length)return a.a.g.get(this.F,b+c);a.a.g.set(this.F,b+c,arguments[1])};var c=a.a.g.Z();a.C.F.prototype.nodes=function(){var b=this.F;
36699if(0==arguments.length){var e=a.a.g.get(b,c)||{},f=e.lb||(3===this.ab?b.content:4===this.ab?b:n);if(!f||e.jd){var g=this.text();g&&g!==e.bb&&(f=a.a.Md(g,b.ownerDocument),a.a.g.set(b,c,{lb:f,bb:g,jd:!0}))}return f}e=arguments[0];this.ab!==n&&this.text("");a.a.g.set(b,c,{lb:e})};a.C.ia=function(a){this.F=a};a.C.ia.prototype=new a.C.F;a.C.ia.prototype.constructor=a.C.ia;a.C.ia.prototype.text=function(){if(0==arguments.length){var b=a.a.g.get(this.F,c)||{};b.bb===n&&b.lb&&(b.bb=b.lb.innerHTML);return b.bb}a.a.g.set(this.F,
36700c,{bb:arguments[0]})};a.b("templateSources",a.C);a.b("templateSources.domElement",a.C.F);a.b("templateSources.anonymousTemplate",a.C.ia)})();(function(){function b(b,c,d){var e;for(c=a.h.nextSibling(c);b&&(e=b)!==c;)b=a.h.nextSibling(e),d(e,b)}function c(c,d){if(c.length){var e=c[0],f=c[c.length-1],g=e.parentNode,h=a.ga.instance,m=h.preprocessNode;if(m){b(e,f,function(a,b){var c=a.previousSibling,d=m.call(h,a);d&&(a===e&&(e=d[0]||b),a===f&&(f=d[d.length-1]||c))});c.length=0;if(!e)return;e===f?c.push(e):
36701(c.push(e,f),a.a.Ua(c,g))}b(e,f,function(b){1!==b.nodeType&&8!==b.nodeType||a.vc(d,b)});b(e,f,function(b){1!==b.nodeType&&8!==b.nodeType||a.aa.cd(b,[d])});a.a.Ua(c,g)}}function d(a){return a.nodeType?a:0<a.length?a[0]:null}function e(b,e,f,h,m){m=m||{};var n=(b&&d(b)||f||{}).ownerDocument,B=m.templateEngine||g;a.kc.xd(f,B,n);f=B.renderTemplate(f,h,m,n);if("number"!=typeof f.length||0<f.length&&"number"!=typeof f[0].nodeType)throw Error("Template engine must return an array of DOM nodes");n=!1;switch(e){case "replaceChildren":a.h.va(b,
36702f);n=!0;break;case "replaceNode":a.a.Xc(b,f);n=!0;break;case "ignoreTargetNode":break;default:throw Error("Unknown renderMode: "+e);}n&&(c(f,h),m.afterRender&&a.u.G(m.afterRender,null,[f,h[m.as||"$data"]]),"replaceChildren"==e&&a.i.ma(b,a.i.H));return f}function f(b,c,d){return a.O(b)?b():"function"===typeof b?b(c,d):b}var g;a.gc=function(b){if(b!=n&&!(b instanceof a.ca))throw Error("templateEngine must inherit from ko.templateEngine");g=b};a.dc=function(b,c,h,m,t){h=h||{};if((h.templateEngine||g)==
36703n)throw Error("Set a template engine before calling renderTemplate");t=t||"replaceChildren";if(m){var x=d(m);return a.$(function(){var g=c&&c instanceof a.fa?c:new a.fa(c,null,null,null,{exportDependencies:!0}),n=f(b,g.$data,g),g=e(m,t,n,g,h);"replaceNode"==t&&(m=g,x=d(m))},null,{Sa:function(){return!x||!a.a.Sb(x)},l:x&&"replaceNode"==t?x.parentNode:x})}return a.aa.Xb(function(d){a.dc(b,c,h,d,"replaceNode")})};a.Qd=function(b,d,g,h,m){function x(b,c){a.u.G(a.a.ec,null,[h,b,u,g,r,c]);a.i.ma(h,a.i.H)}
36704function r(a,b){c(b,v);g.afterRender&&g.afterRender(b,a);v=null}function u(a,c){v=m.createChildContext(a,{as:z,noChildContext:g.noChildContext,extend:function(a){a.$index=c;z&&(a[z+"Index"]=c)}});var d=f(b,a,v);return e(h,"ignoreTargetNode",d,v,g)}var v,z=g.as,w=!1===g.includeDestroyed||a.options.foreachHidesDestroyed&&!g.includeDestroyed;if(w||g.beforeRemove||!a.Pc(d))return a.$(function(){var b=a.a.f(d)||[];"undefined"==typeof b.length&&(b=[b]);w&&(b=a.a.jb(b,function(b){return b===n||null===b||
36705!a.a.f(b._destroy)}));x(b)},null,{l:h});x(d.v());var A=d.subscribe(function(a){x(d(),a)},null,"arrayChange");A.l(h);return A};var h=a.a.g.Z(),m=a.a.g.Z();a.c.template={init:function(b,c){var d=a.a.f(c());if("string"==typeof d||"name"in d)a.h.Ea(b);else if("nodes"in d){d=d.nodes||[];if(a.O(d))throw Error('The "nodes" option must be a plain, non-observable array.');var e=d[0]&&d[0].parentNode;e&&a.a.g.get(e,m)||(e=a.a.Yb(d),a.a.g.set(e,m,!0));(new a.C.ia(b)).nodes(e)}else if(d=a.h.childNodes(b),0<d.length)e=
36706a.a.Yb(d),(new a.C.ia(b)).nodes(e);else throw Error("Anonymous template defined, but no template content was provided");return{controlsDescendantBindings:!0}},update:function(b,c,d,e,f){var g=c();c=a.a.f(g);d=!0;e=null;"string"==typeof c?c={}:(g="name"in c?c.name:b,"if"in c&&(d=a.a.f(c["if"])),d&&"ifnot"in c&&(d=!a.a.f(c.ifnot)),d&&!g&&(d=!1));"foreach"in c?e=a.Qd(g,d&&c.foreach||[],c,b,f):d?(d=f,"data"in c&&(d=f.createChildContext(c.data,{as:c.as,noChildContext:c.noChildContext,exportDependencies:!0})),
36707e=a.dc(g,d,c,b)):a.h.Ea(b);f=e;(c=a.a.g.get(b,h))&&"function"==typeof c.s&&c.s();a.a.g.set(b,h,!f||f.ja&&!f.ja()?n:f)}};a.m.Ra.template=function(b){b=a.m.ac(b);return 1==b.length&&b[0].unknown||a.m.Id(b,"name")?null:"This template engine does not support anonymous templates nested within its templates"};a.h.ea.template=!0})();a.b("setTemplateEngine",a.gc);a.b("renderTemplate",a.dc);a.a.Kc=function(a,c,d){if(a.length&&c.length){var e,f,g,h,m;for(e=f=0;(!d||e<d)&&(h=a[f]);++f){for(g=0;m=c[g];++g)if(h.value===
36708m.value){h.moved=m.index;m.moved=h.index;c.splice(g,1);e=g=0;break}e+=g}}};a.a.Pb=function(){function b(b,d,e,f,g){var h=Math.min,m=Math.max,k=[],l,p=b.length,q,n=d.length,r=n-p||1,v=p+n+1,u,w,z;for(l=0;l<=p;l++)for(w=u,k.push(u=[]),z=h(n,l+r),q=m(0,l-1);q<=z;q++)u[q]=q?l?b[l-1]===d[q-1]?w[q-1]:h(w[q]||v,u[q-1]||v)+1:q+1:l+1;h=[];m=[];r=[];l=p;for(q=n;l||q;)n=k[l][q]-1,q&&n===k[l][q-1]?m.push(h[h.length]={status:e,value:d[--q],index:q}):l&&n===k[l-1][q]?r.push(h[h.length]={status:f,value:b[--l],index:l}):
36709(--q,--l,g.sparse||h.push({status:"retained",value:d[q]}));a.a.Kc(r,m,!g.dontLimitMoves&&10*p);return h.reverse()}return function(a,d,e){e="boolean"===typeof e?{dontLimitMoves:e}:e||{};a=a||[];d=d||[];return a.length<d.length?b(a,d,"added","deleted",e):b(d,a,"deleted","added",e)}}();a.b("utils.compareArrays",a.a.Pb);(function(){function b(b,c,d,h,m){var k=[],l=a.$(function(){var l=c(d,m,a.a.Ua(k,b))||[];0<k.length&&(a.a.Xc(k,l),h&&a.u.G(h,null,[d,l,m]));k.length=0;a.a.Nb(k,l)},null,{l:b,Sa:function(){return!a.a.kd(k)}});
36710return{Y:k,$:l.ja()?l:n}}var c=a.a.g.Z(),d=a.a.g.Z();a.a.ec=function(e,f,g,h,m,k){function l(b){y={Aa:b,pb:a.ta(w++)};v.push(y);r||F.push(y)}function p(b){y=t[b];w!==y.pb.v()&&D.push(y);y.pb(w++);a.a.Ua(y.Y,e);v.push(y)}function q(b,c){if(b)for(var d=0,e=c.length;d<e;d++)a.a.D(c[d].Y,function(a){b(a,d,c[d].Aa)})}f=f||[];"undefined"==typeof f.length&&(f=[f]);h=h||{};var t=a.a.g.get(e,c),r=!t,v=[],u=0,w=0,z=[],A=[],C=[],D=[],F=[],y,I=0;if(r)a.a.D(f,l);else{if(!k||t&&t._countWaitingForRemove){var E=
36711a.a.Mb(t,function(a){return a.Aa});k=a.a.Pb(E,f,{dontLimitMoves:h.dontLimitMoves,sparse:!0})}for(var E=0,G,H,K;G=k[E];E++)switch(H=G.moved,K=G.index,G.status){case "deleted":for(;u<K;)p(u++);H===n&&(y=t[u],y.$&&(y.$.s(),y.$=n),a.a.Ua(y.Y,e).length&&(h.beforeRemove&&(v.push(y),I++,y.Aa===d?y=null:C.push(y)),y&&z.push.apply(z,y.Y)));u++;break;case "added":for(;w<K;)p(u++);H!==n?(A.push(v.length),p(H)):l(G.value)}for(;w<f.length;)p(u++);v._countWaitingForRemove=I}a.a.g.set(e,c,v);q(h.beforeMove,D);a.a.D(z,
36712h.beforeRemove?a.oa:a.removeNode);var M,O,P;try{P=e.ownerDocument.activeElement}catch(N){}if(A.length)for(;(E=A.shift())!=n;){y=v[E];for(M=n;E;)if((O=v[--E].Y)&&O.length){M=O[O.length-1];break}for(f=0;u=y.Y[f];M=u,f++)a.h.Wb(e,u,M)}for(E=0;y=v[E];E++){y.Y||a.a.extend(y,b(e,g,y.Aa,m,y.pb));for(f=0;u=y.Y[f];M=u,f++)a.h.Wb(e,u,M);!y.Ed&&m&&(m(y.Aa,y.Y,y.pb),y.Ed=!0,M=y.Y[y.Y.length-1])}P&&e.ownerDocument.activeElement!=P&&P.focus();q(h.beforeRemove,C);for(E=0;E<C.length;++E)C[E].Aa=d;q(h.afterMove,D);
36713q(h.afterAdd,F)}})();a.b("utils.setDomNodeChildrenFromArrayMapping",a.a.ec);a.ba=function(){this.allowTemplateRewriting=!1};a.ba.prototype=new a.ca;a.ba.prototype.constructor=a.ba;a.ba.prototype.renderTemplateSource=function(b,c,d,e){if(c=(9>a.a.W?0:b.nodes)?b.nodes():null)return a.a.la(c.cloneNode(!0).childNodes);b=b.text();return a.a.ua(b,e)};a.ba.Ma=new a.ba;a.gc(a.ba.Ma);a.b("nativeTemplateEngine",a.ba);(function(){a.$a=function(){var a=this.Hd=function(){if(!v||!v.tmpl)return 0;try{if(0<=v.tmpl.tag.tmpl.open.toString().indexOf("__"))return 2}catch(a){}return 1}();
36714this.renderTemplateSource=function(b,e,f,g){g=g||w;f=f||{};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=v.template(null,"{{ko_with $item.koBindingContext}}"+h+"{{/ko_with}}"),b.data("precompiled",h));b=[e.$data];e=v.extend({koBindingContext:e},f.templateOptions);e=v.tmpl(h,b,e);e.appendTo(g.createElement("div"));v.fragments={};return e};this.createJavaScriptEvaluatorBlock=function(a){return"{{ko_code ((function() { return "+
36715a+" })()) }}"};this.addTemplate=function(a,b){w.write("<script type='text/html' id='"+a+"'>"+b+"\x3c/script>")};0<a&&(v.tmpl.tag.ko_code={open:"__.push($1 || '');"}
36715,v.tmpl.tag.ko_with={open:"with($1) {",close:"} "})};a.$a.prototype=new a.ca;a.$a.prototype.constructor=a.$a;var b=new a.$a;0<b.Hd&&a.gc(b);a.b("jqueryTmplTemplateEngine",a.$a)})()})})();})();
36716;
36717/// Knockout Mapping plugin v2.4.1
36718/// (c) 2013 Steven Sanderson, Roy Jacobs - http://knockoutjs.com/
36719/// License: MIT (http://www.opensource.org/licenses/mit-license.php)
36720(function(e){"function"===typeof require&&"object"===typeof exports&&"object"===typeof module?e(require("knockout"),exports):"function"===typeof define&&define.amd?define(["knockout","exports"],e):e(ko,ko.mapping={})})(function(e,f){function y(b,c){var a,d;for(d in c)if(c.hasOwnProperty(d)&&c[d])if(a=f.getType(b[d]),d&&b[d]&&"array"!==a&&"string"!==a)y(b[d],c[d]);else if("array"===f.getType(b[d])&&"array"===f.getType(c[d])){a=b;for(var e=d,l=b[d],n=c[d],t={},g=l.length-1;0<=g;--g)t[l[g]]=l[g];for(g=
36721n.length-1;0<=g;--g)t[n[g]]=n[g];l=[];n=void 0;for(n in t)l.push(t[n]);a[e]=l}else b[d]=c[d]}function E(b,c){var a={};y(a,b);y(a,c);return a}function z(b,c){for(var a=E({},b),e=L.length-1;0<=e;e--){var f=L[e];a[f]&&(a[""]instanceof Object||(a[""]={}),a[""][f]=a[f],delete a[f])}c&&(a.ignore=h(c.ignore,a.ignore),a.include=h(c.include,a.include),a.copy=h(c.copy,a.copy),a.observe=h(c.observe,a.observe));a.ignore=h(a.ignore,j.ignore);a.include=h(a.include,j.include);a.copy=h(a.copy,j.copy);a.observe=h(a.observe,
36722j.observe);a.mappedProperties=a.mappedProperties||{};a.copiedProperties=a.copiedProperties||{};return a}function h(b,c){"array"!==f.getType(b)&&(b="undefined"===f.getType(b)?[]:[b]);"array"!==f.getType(c)&&(c="undefined"===f.getType(c)?[]:[c]);return e.utils.arrayGetDistinctValues(b.concat(c))}function F(b,c,a,d,k,l,n){var t="array"===f.getType(e.utils.unwrapObservable(c));l=l||"";if(f.isMapped(b)){var g=e.utils.unwrapObservable(b)[p];a=E(g,a)}var j=n||k,h=function(){return a[d]&&a[d].create instanceof
36723Function},x=function(b){var f=G,g=e.dependentObservable;e.dependentObservable=function(a,b,c){c=c||{};a&&"object"==typeof a&&(c=a);var d=c.deferEvaluation,M=!1;c.deferEvaluation=!0;a=new H(a,b,c);if(!d){var g=a,d=e.dependentObservable;e.dependentObservable=H;a=e.isWriteableObservable(g);e.dependentObservable=d;d=H({read:function(){M||(e.utils.arrayRemoveItem(f,g),M=!0);return g.apply(g,arguments)},write:a&&function(a){return g(a)},deferEvaluation:!0});d.__DO=g;a=d;f.push(a)}return a};e.dependentObservable.fn=
36724H.fn;e.computed=e.dependentObservable;b=e.utils.unwrapObservable(k)instanceof Array?a[d].create({data:b||c,parent:j,skip:N}):a[d].create({data:b||c,parent:j});e.dependentObservable=g;e.computed=e.dependentObservable;return b},u=function(){return a[d]&&a[d].update instanceof Function},v=function(b,f){var g={data:f||c,parent:j,target:e.utils.unwrapObservable(b)};e.isWriteableObservable(b)&&(g.observable=b);return a[d].update(g)};if(n=I.get(c))return n;d=d||"";if(t){var t=[],s=!1,m=function(a){return a};
36725a[d]&&a[d].key&&(m=a[d].key,s=!0);e.isObservable(b)||(b=e.observableArray([]),b.mappedRemove=function(a){var c="function"==typeof a?a:function(b){return b===m(a)};return b.remove(function(a){return c(m(a))})},b.mappedRemoveAll=function(a){var c=C(a,m);return b.remove(function(a){return-1!=e.utils.arrayIndexOf(c,m(a))})},b.mappedDestroy=function(a){var c="function"==typeof a?a:function(b){return b===m(a)};return b.destroy(function(a){return c(m(a))})},b.mappedDestroyAll=function(a){var c=C(a,m);return b.destroy(function(a){return-1!=
36726e.utils.arrayIndexOf(c,m(a))})},b.mappedIndexOf=function(a){var c=C(b(),m);a=m(a);return e.utils.arrayIndexOf(c,a)},b.mappedGet=function(a){return b()[b.mappedIndexOf(a)]},b.mappedCreate=function(a){if(-1!==b.mappedIndexOf(a))throw Error("There already is an object with the key that you specified.");var c=h()?x(a):a;u()&&(a=v(c,a),e.isWriteableObservable(c)?c(a):c=a);b.push(c);return c});n=C(e.utils.unwrapObservable(b),m).sort();g=C(c,m);s&&g.sort();s=e.utils.compareArrays(n,g);n={};var J,A=e.utils.unwrapObservable(c),
36727y={},z=!0,g=0;for(J=A.length;g<J;g++){var r=m(A[g]);if(void 0===r||r instanceof Object){z=!1;break}y[r]=A[g]}var A=[],B=0,g=0;for(J=s.length;g<J;g++){var r=s[g],q,w=l+"["+g+"]";switch(r.status){case "added":var D=z?y[r.value]:K(e.utils.unwrapObservable(c),r.value,m);q=F(void 0,D,a,d,b,w,k);h()||(q=e.utils.unwrapObservable(q));w=O(e.utils.unwrapObservable(c),D,n);q===N?B++:A[w-B]=q;n[w]=!0;break;case "retained":D=z?y[r.value]:K(e.utils.unwrapObservable(c),r.value,m);q=K(b,r.value,m);F(q,D,a,d,b,w,
36728k);w=O(e.utils.unwrapObservable(c),D,n);A[w]=q;n[w]=!0;break;case "deleted":q=K(b,r.value,m)}t.push({event:r.status,item:q})}b(A);a[d]&&a[d].arrayChanged&&e.utils.arrayForEach(t,function(b){a[d].arrayChanged(b.event,b.item)})}else if(P(c)){b=e.utils.unwrapObservable(b);if(!b){if(h())return s=x(),u()&&(s=v(s)),s;if(u())return v(s);b={}}u()&&(b=v(b));I.save(c,b);
36728if(u())return b;Q(c,function(d){var f=l.length?l+"."+d:d;if(-1==e.utils.arrayIndexOf(a.ignore,f))if(-1!=e.utils.arrayIndexOf(a.copy,f))b[d]=
36729c[d];else if("object"!=typeof c[d]&&"array"!=typeof c[d]&&0<a.observe.length&&-1==e.utils.arrayIndexOf(a.observe,f))b[d]=c[d],a.copiedProperties[f]=!0;else{var g=I.get(c[d]),k=F(b[d],c[d],a,d,b,f,b),g=g||k;if(0<a.observe.length&&-1==e.utils.arrayIndexOf(a.observe,f))b[d]=g(),a.copiedProperties[f]=!0;else{if(e.isWriteableObservable(b[d])){if(g=e.utils.unwrapObservable(g),b[d]()!==g)b[d](g)}else g=void 0===b[d]?g:e.utils.unwrapObservable(g),b[d]=g;a.mappedProperties[f]=!0}}})}else switch(f.getType(c)){case "function":u()?
36730e.isWriteableObservable(c)?(c(v(c)),b=c):b=v(c):b=c;break;default:if(e.isWriteableObservable(b))return q=u()?v(b):e.utils.unwrapObservable(c),b(q),q;h()||u();b=h()?x():e.observable(e.utils.unwrapObservable(c));u()&&b(v(b))}return b}function O(b,c,a){for(var d=0,e=b.length;d<e;d++)if(!0!==a[d]&&b[d]===c)return d;return null}function R(b,c){var a;c&&(a=c(b));"undefined"===f.getType(a)&&(a=b);return e.utils.unwrapObservable(a)}function K(b,c,a){b=e.utils.unwrapObservable(b);for(var d=0,f=b.length;d<
36731f;d++){var l=b[d];if(R(l,a)===c)return l}throw Error("When calling ko.update*, the key '"+c+"' was not found!");}function C(b,c){return e.utils.arrayMap(e.utils.unwrapObservable(b),function(a){return c?R(a,c):a})}function Q(b,c){if("array"===f.getType(b))for(var a=0;a<b.length;a++)c(a);else for(a in b)c(a)}function P(b){var c=f.getType(b);return("object"===c||"array"===c)&&null!==b}function T(){var b=[],c=[];this.save=function(a,d){var f=e.utils.arrayIndexOf(b,a);0<=f?c[f]=d:(b.push(a),c.push(d))};
36732this.get=function(a){a=e.utils.arrayIndexOf(b,a);return 0<=a?c[a]:void 0}}function S(){var b={},c=function(a){var c;try{c=a}catch(e){c="$$$"}a=b[c];void 0===a&&(a=new T,b[c]=a);return a};this.save=function(a,b){c(a).save(a,b)};this.get=function(a){return c(a).get(a)}}var p="__ko_mapping__",H=e.dependentObservable,B=0,G,I,L=["create","update","key","arrayChanged"],N={},x={include:["_destroy"],ignore:[],copy:[],observe:[]},j=x;f.isMapped=function(b){return(b=e.utils.unwrapObservable(b))&&b[p]};f.fromJS=
36733function(b){if(0==arguments.length)throw Error("When calling ko.fromJS, pass the object you want to convert.");try{B++||(G=[],I=new S);var c,a;2==arguments.length&&(arguments[1][p]?a=arguments[1]:c=arguments[1]);3==arguments.length&&(c=arguments[1],a=arguments[2]);a&&(c=E(c,a[p]));c=z(c);var d=F(a,b,c);a&&(d=a);if(!--B)for(;G.length;){var e=G.pop();e&&(e(),e.__DO.throttleEvaluation=e.throttleEvaluation)}d[p]=E(d[p],c);return d}catch(f){throw B=0,f;}};f.fromJSON=function(b){var c=e.utils.parseJson(b);
36734arguments[0]=c;return f.fromJS.apply(this,arguments)};f.updateFromJS=function(){throw Error("ko.mapping.updateFromJS, use ko.mapping.fromJS instead. Please note that the order of parameters is different!");};f.updateFromJSON=function(){throw Error("ko.mapping.updateFromJSON, use ko.mapping.fromJSON instead. Please note that the order of parameters is different!");};f.toJS=function(b,c){j||f.resetDefaultOptions();if(0==arguments.length)throw Error("When calling ko.mapping.toJS, pass the object you want to convert.");
36735if("array"!==f.getType(j.ignore))throw Error("ko.mapping.defaultOptions().ignore should be an array.");if("array"!==f.getType(j.include))throw Error("ko.mapping.defaultOptions().include should be an array.");if("array"!==f.getType(j.copy))throw Error("ko.mapping.defaultOptions().copy should be an array.");c=z(c,b[p]);return f.visitModel(b,function(a){return e.utils.unwrapObservable(a)},c)};f.toJSON=function(b,c){var a=f.toJS(b,c);return e.utils.stringifyJson(a)};f.defaultOptions=function(){if(0<arguments.length)j=
36736arguments[0];else return j};f.resetDefaultOptions=function(){j={include:x.include.slice(0),ignore:x.ignore.slice(0),copy:x.copy.slice(0)}};f.getType=function(b){if(b&&"object"===typeof b){if(b.constructor===Date)return"date";if(b.constructor===Array)return"array"}return typeof b};f.visitModel=function(b,c,a){a=a||{};a.visitedObjects=a.visitedObjects||new S;var d,k=e.utils.unwrapObservable(b);if(P(k))a=z(a,k[p]),c(b,a.parentName),d="array"===f.getType(k)?[]:{};else return c(b,a.parentName);a.visitedObjects.save(b,
36737d);var l=a.parentName;Q(k,function(b){if(!(a.ignore&&-1!=e.utils.arrayIndexOf(a.ignore,b))){var j=k[b],g=a,h=l||"";"array"===f.getType(k)?l&&(h+="["+b+"]"):(l&&(h+="."),h+=b);g.parentName=h;if(!(-1===e.utils.arrayIndexOf(a.copy,b)&&-1===e.utils.arrayIndexOf(a.include,b)&&k[p]&&k[p].mappedProperties&&!k[p].mappedProperties[b]&&k[p].copiedProperties&&!k[p].copiedProperties[b]&&"array"!==f.getType(k)))switch(f.getType(e.utils.unwrapObservable(j))){case "object":case "array":case "undefined":g=a.visitedObjects.get(j);
36738d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.parentName)}}});return d}});
36739;
36740;
36741!function(i){"use strict";"function"==typeof define&&define.amd?define(["jquery"],i):"undefined"!=typeof exports?module.exports=i(require("jquery")):i(jQuery)}(function(i){"use strict";var e=window.Slick||{};(e=function(){var e=0;return function(t,o){var s,n=this;n.defaults={accessibility:!0,adaptiveHeight:!1,appendArrows:i(t),appendDots:i(t),arrows:!0,asNavFor:null,prevArrow:'<button class="slick-prev" aria-label="Previous" type="button">Previous</button>',nextArrow:'<button class="slick-next" aria-label="Next" type="button">Next</button>',autoplay:!1,autoplaySpeed:3e3,centerMode:!1,centerPadding:"50px",cssEase:"ease",customPaging:function(e,t){return i('<button type="button" />').text(t+1)},dots:!1,dotsClass:"slick-dots",draggable:!0,easing:"linear",edgeFriction:.35,fade:!1,focusOnSelect:!1,focusOnChange:!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},n.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,scrolling:!1,slideCount:null,slideWidth:null,$slideTrack:null,$slides:null,
vendor: 6,594 bytes, line 36741
36741sliding:!1,slideOffset:0,swipeLeft:null,swiping:!1,$list:null,touchObject:{},transformsEnabled:!1,unslicked:!1},i.extend(n,n.initials),n.activeBreakpoint=null,n.animType=null,n.animProp=null,n.breakpoints=[],n.breakpointSettings=[],n.cssTransitions=!1,n.focussed=!1,n.interrupted=!1,n.hidden="hidden",n.paused=!0,n.positionProp=null,n.respondTo=null,n.rowCount=1,n.shouldClick=!0,n.$slider=i(t),n.$slidesCache=null,n.transformType=null,n.transitionType=null,n.visibilityChange="visibilitychange",n.windowWidth=0,n.windowTimer=null,s=i(t).data("slick")||{},n.options=i.extend({},n.defaults,o,s),n.currentSlide=n.options.initialSlide,n.originalSettings=n.options,void 0!==document.mozHidden?(n.hidden="mozHidden",n.visibilityChange="mozvisibilitychange"):void 0!==document.webkitHidden&&(n.hidden="webkitHidden",n.visibilityChange="webkitvisibilitychange"),n.autoPlay=i.proxy(n.autoPlay,n),n.autoPlayClear=i.proxy(n.autoPlayClear,n),n.autoPlayIterator=i.proxy(n.autoPlayIterator,n),n.changeSlide=i.proxy(n.changeSlide,n),n.clickHandler=i.proxy(n.clickHandler,n),n.selectHandler=i.proxy(n.selectHandler,n),n.setPosition=i.proxy(n.setPosition,n),n.swipeHandler=i.proxy(n.swipeHandler,n),n.dragHandler=i.proxy(n.dragHandler,n),n.keyHandler=i.proxy(n.keyHandler,n),n.instanceUid=e++,n.htmlExpr=/^(?:\s*(<[\w\W]+>)[^>]*)$/,n.registerBreakpoints(),n.init(!0)}}()).prototype.activateADA=function(){this.$slideTrack.find(".slick-active").attr({"aria-hidden":"false"}).find("a, input, button, select").attr({tabindex:"0"})},e.prototype.addSlide=e.prototype.slickAdd=function(e,t,o){var s=this;if("boolean"==typeof t)o=t,t=null;else if(t<0||t>=s.slideCount)return!1;s.unload(),"number"==typeof t?0===t&&0===s.$slides.length?i(e).appendTo(s.$slideTrack):o?i(e).insertBefore(s.$slides.eq(t)):i(e).insertAfter(s.$slides.eq(t)):!0===o?i(e).prependTo(s.$slideTrack):i(e).appendTo(s.$slideTrack),s.$slides=s.$slideTrack.children(this.options.slide),s.$slideTrack.children(this.options.slide).detach(),s.$slideTrack.append(s.$slides),s.$slides.each(function(e,t){i(t).attr("data-slick-index",e)}),s.$slidesCache=s.$slides,s.reinit()},e.prototype.animateHeight=function(){var i=this;if(1===i.options.slidesToShow&&!0===i.options.adaptiveHeight&&!1===i.options.vertical){var e=i.$slides.eq(i.currentSlide).outerHeight(!0);i.$list.animate({height:e},i.options.speed)}},e.prototype.animateSlide=function(e,t){var o={},s=this;s.animateHeight(),!0===s.options.rtl&&!1===s.options.vertical&&(e=-e),!1===s.transformsEnabled?!1===s.options.vertical?s.$slideTrack.animate({left:e},s.options.speed,s.options.easing,t):s.$slideTrack.animate({top:e},s.options.speed,s.options.easing,t):!1===s.cssTransitions?(!0===s.options.rtl&&(s.currentLeft=-s.currentLeft),i({animStart:s.currentLeft}).animate({animStart:e},{duration:s.options.speed,easing:s.options.easing,step:function(i){i=Math.ceil(i),!1===s.options.vertical?(o[s.animType]="translate("+i+"px, 0px)",s.$slideTrack.css(o)):(o[s.animType]="translate(0px,"+i+"px)",s.$slideTrack.css(o))},complete:function(){t&&t.call()}})):(s.applyTransition(),e=Math.ceil(e),!1===s.options.vertical?o[s.animType]="translate3d("+e+"px, 0px, 0px)":o[s.animType]="translate3d(0px,"+e+"px, 0px)",s.$slideTrack.css(o),t&&setTimeout(function(){s.disableTransition(),t.call()},s.options.speed))},e.prototype.getNavTarget=function(){var e=this,t=e.options.asNavFor;return t&&null!==t&&(t=i(t).not(e.$slider)),t},e.prototype.asNavFor=function(e){var t=this.getNavTarget();null!==t&&"object"==typeof t&&t.each(function(){var t=i(this).slick("getSlick");t.unslicked||t.slideHandler(e,!0)})},e.prototype.applyTransition=function(i){var e=this,t={};!1===e.options.fade?t[e.transitionType]=e.transformType+" "+e.options.speed+"ms "+e.options.cssEase:t[e.transitionType]="opacity "+e.options.speed+"ms "+e.options.cssEase,!1===e.options.fade?e.$slideTrack.css(t):e.$slides.eq(i).css(t)},e.prototype.autoPlay=function(){var i=this;i.autoPlayClear(),i.slideCount>i.options.slidesToShow&&(i.autoPlayTimer=setInterval(i.autoPlayIterator,i.options.autoplaySpeed))},e.prototype.autoPlayClear=function(){var i=this;i.autoPlayTimer&&clearInterval(i.autoPlayTimer)},e.prototype.autoPlayIterator=function(){var i=this,e=i.currentSlide+i.options.slidesToScroll;i.paused||i.interrupted||i.focussed||(!1===i.options.infinite&&(1===i.direction&&i.currentSlide+1===i.slideCount-1?i.direction=0:0===i.direction&&(e=i.currentSlide-i.options.slidesToScroll,i.currentSlide-1==0&&(i.direction=1))),i.slideHandler(e))},e.prototype.buildArrows=function(){var e=this;!0===e.options.arrows&&(e.$prevArrow=i(e.options.prevArrow).addClass("slick-arrow"),e.$nextArrow=i(e.options.nextArrow).addClass("slick-arrow"),e.slideCount>e.options.slidesToShow?(e.$prevArrow.removeClass("slick-hidden").removeAttr("aria-hidden tabindex"),e.$nextArrow.removeClass("slick-hidden").removeAttr("aria-hidden tabindex"),e.htmlExpr.test(e.options.prevArrow)&&e.$prevArrow.prependTo(e.options.appendArrows),e.htmlExpr.test(e.options.nextArrow)&&e.$nextArrow.appendTo(e.options.appendArrows),!0!==e.options.infinite&&e.$prevArrow.addClass("slick-disabled").attr("aria-disabled","true")):e.$prevArrow.add(e.$nextArrow).addClass("slick-hidden").attr({"aria-disabled":"true",tabindex:"-1"}))},e.prototype.buildDots=function(){var e,t,o=this;if(!0===o.options.dots){for(o.$slider.addClass("slick-dotted"),t=i("<ul />").addClass(o.options.dotsClass),e=0;e<=o.getDotCount();e+=1)t.append(i("<li />").append(o.options.customPaging.call(this,o,e)));o.$dots=t.appendTo(o.options.appendDots),o.$dots.find("li").first().addClass("slick-active")}},e.prototype.buildOut=function(){var e=this;e.$slides=e.$slider.children(e.options.slide+":not(.slick-cloned)").addClass("slick-slide"),e.slideCount=e.$slides.length,e.$slides.each(function(e,t){i(t).attr("data-slick-index",e).data("originalStyling",i(t).attr("style")||"")}),e.$slider.addClass("slick-slider"),e.$slideTrack=0===e.slideCount?i('<div class="slick-track"/>').appendTo(e.$slider):e.$slides.wrapAll('<div class="slick-track"/>').parent(),e.$list=e.$slideTrack.wrap('<div class="slick-list"/>').parent(),e.$slideTrack.css("opacity",0),!0!==e.options.centerMode&&!0!==e.options.swipeToSlide||(e.options.slidesToScroll=1),i("img[data-lazy]",e.$slider).not("[src]").addClass("slick-loading"),e.setupInfinite(),e.buildArrows(),e.buildDots(),e.updateDots(),e.setSlideClasses("number"==typeof e.currentSlide?e.currentSlide:0),!0===e.options.draggable&&e.$list.addClass("draggable")},e.prototype.buildRows=function(){var i,e,t,o,s,n,r,l=this;if(o=document.createDocumentFragment(),n=l.$slider.children(),l.o
vendor: 3,442 bytes, line 36741
36741ptions.rows>1){for(r=l.options.slidesPerRow*l.options.rows,s=Math.ceil(n.length/r),i=0;i<s;i++){var d=document.createElement("div");for(e=0;e<l.options.rows;e++){var a=document.createElement("div");for(t=0;t<l.options.slidesPerRow;t++){var c=i*r+(e*l.options.slidesPerRow+t);n.get(c)&&a.appendChild(n.get(c))}d.appendChild(a)}o.appendChild(d)}l.$slider.empty().append(o),l.$slider.children().children().children().css({width:100/l.options.slidesPerRow+"%",display:"inline-block"})}},e.prototype.checkResponsive=function(e,t){var o,s,n,r=this,l=!1,d=r.$slider.width(),a=window.innerWidth||i(window).width();if("window"===r.respondTo?n=a:"slider"===r.respondTo?n=d:"min"===r.respondTo&&(n=Math.min(a,d)),r.options.responsive&&r.options.responsive.length&&null!==r.options.responsive){s=null;for(o in r.breakpoints)r.breakpoints.hasOwnProperty(o)&&(!1===r.originalSettings.mobileFirst?n<r.breakpoints[o]&&(s=r.breakpoints[o]):n>r.breakpoints[o]&&(s=r.breakpoints[o]));null!==s?null!==r.activeBreakpoint?(s!==r.activeBreakpoint||t)&&(r.activeBreakpoint=s,"unslick"===r.breakpointSettings[s]?r.unslick(s):(r.options=i.extend({},r.originalSettings,r.breakpointSettings[s]),!0===e&&(r.currentSlide=r.options.initialSlide),r.refresh(e)),l=s):(r.activeBreakpoint=s,"unslick"===r.breakpointSettings[s]?r.unslick(s):(r.options=i.extend({},r.originalSettings,r.breakpointSettings[s]),!0===e&&(r.currentSlide=r.options.initialSlide),r.refresh(e)),l=s):null!==r.activeBreakpoint&&(r.activeBreakpoint=null,r.options=r.originalSettings,!0===e&&(r.currentSlide=r.options.initialSlide),r.refresh(e),l=s),e||!1===l||r.$slider.trigger("breakpoint",[r,l])}},e.prototype.changeSlide=function(e,t){var o,s,n,r=this,l=i(e.currentTarget);switch(l.is("a")&&e.preventDefault(),l.is("li")||(l=l.closest("li")),n=r.slideCount%r.options.slidesToScroll!=0,o=n?0:(r.slideCount-r.currentSlide)%r.options.slidesToScroll,e.data.message){case"previous":s=0===o?r.options.slidesToScroll:r.options.slidesToShow-o,r.slideCount>r.options.slidesToShow&&r.slideHandler(r.currentSlide-s,!1,t);break;case"next":s=0===o?r.options.slidesToScroll:o,r.slideCount>r.options.slidesToShow&&r.slideHandler(r.currentSlide+s,!1,t);break;case"index":var d=0===e.data.index?0:e.data.index||l.index()*r.options.slidesToScroll;r.slideHandler(r.checkNavigable(d),!1,t),l.children().trigger("focus");break;default:return}},e.prototype.checkNavigable=function(i){var e,t;if(e=this.getNavigableIndexes(),t=0,i>e[e.length-1])i=e[e.length-1];else for(var o in e){if(i<e[o]){i=t;break}t=e[o]}return i},e.prototype.cleanUpEvents=function(){var e=this;e.options.dots&&null!==e.$dots&&(i("li",e.$dots).off("click.slick",e.changeSlide).off("mouseenter.slick",i.proxy(e.interrupt,e,!0)).off("mouseleave.slick",i.proxy(e.interrupt,e,!1)),!0===e.options.accessibility&&e.$dots.off("keydown.slick",e.keyHandler)),e.$slider.off("focus.slick blur.slick"),!0===e.options.arrows&&e.slideCount>e.options.slidesToShow&&(e.$prevArrow&&e.$prevArrow.off("click.slick",e.changeSlide),e.$nextArrow&&e.$nextArrow.off("click.slick",e.changeSlide),!0===e.options.accessibility&&(e.$prevArrow&&e.$prevArrow.off("keydown.slick",e.keyHandler),e.$nextArrow&&e.$nextArrow.off("keydown.slick",e.keyHandler))),e.$list.off("touchstart.slick mousedown.slick",e.swipeHandler),e.$list.off("touchmove.slick mousemove.slick",e.swipeHandler),e.$list.off("touchend.slick mouseup.slick",e.swipeHandler),e.$list.off("touchcancel.slick mouseleave.
36741slick",e.swipeHandler),e.$list.off("click.slick",e.clickHandler),i(document).off(e.visibilityChange,e.visibility),e.cleanUpSlideEvents(),!0===e.options.accessibility&&e.$list.off("keydown.slick",e.keyHandler),!0===e.options.focusOnSelect&&i(e.$slideTrack).children().off("click.slick",e.selectHandler),i(window).off("orientationchange.slick.slick-"+e.instanceUid,e.orientationChange),i(window).off("resize.slick.slick-"+e.instanceUid,e.resize),i("[draggable!=true]",e.$slideTrack).off("dragstart",e.preventDefault),i(window).off("load.slick.slick-"+e.instanceUid,e.setPosition)},e.prototype.cleanUpSlideEvents=function(){var e=this;e.$list.off("mouseenter.slick",i.proxy(e.interrupt,e,!0)),e.$list.off("mouseleave.slick",i.proxy(e.interrupt,e,!1))},e.prototype.cleanUpRows=function(){var i,e=this;e.options.rows>1&&((i=e.$slides.children().children()).removeAttr("style"),e.$slider.empty().append(i))},e.prototype.clickHandler=function(i){!1===this.shouldClick&&(i.stopImmediatePropagation(),i.stopPropagation(),i.preventDefault())},e.prototype.destroy=function(e){var t=this;t.autoPlayClear(),t.touchObject={},t.cleanUpEvents(),i(".slick-cloned",t.$slider).detach(),t.$dots&&t.$dots.remove(),t.$prevArrow&&t.$prevArrow.length&&(t.$prevArrow.removeClass("slick-disabled slick-arrow slick-hidden").removeAttr("aria-hidden aria-disabled tabindex").css("display",""),t.htmlExpr.test(t.options.prevArrow)&&t.$prevArrow.remove()),t.$nextArrow&&t.$nextArrow.length&&(t.$nextArrow.removeClass("slick-disabled slick-arrow slick-hidden").removeAttr("aria-hidden aria-disabled tabindex").css("display",""),t.htmlExpr.test(t.options.nextArrow)&&t.$nextArrow.remove()),t.$slides&&(t.$slides.removeClass("slick-slide slick-active slick-center slick-visible slick-current").removeAttr("aria-hidden").removeAttr("data-slick-index").each(function(){i(this).attr("style",i(this).data("originalStyling"))}),t.$slideTrack.children(this.options.slide).detach(),t.$slideTrack.detach(),t.$list.detach(),t.$slider.append(t.$slides)),t.cleanUpRows(),t.$slider.removeClass("slick-slider"),t.$slider.removeClass("slick-initialized"),t.$slider.removeClass("slick-dotted"),t.unslicked=!0,e||t.$slider.trigger("destroy",[t])},e.prototype.disableTransition=function(i){var e=this,t={};t[e.transitionType]="",!1===e.options.fade?e.$slideTrack.css(t):e.$slides.eq(i).css(t)},e.prototype.fadeSlide=function(i,e){var t=this;!1===t.cssTransitions?(t.$slides.eq(i).css({zIndex:t.options.zIndex}),t.$slides.eq(i).animate({opacity:1},t.options.speed,t.options.easing,e)):(t.applyTransition(i),t.$slides.eq(i).css({opacity:1,zIndex:t.options.zIndex}),e&&setTimeout(function(){t.disableTransition(i),e.call()},t.options.speed))},e.prototype.fadeSlideOut=function(i){var e=this;!1===e.cssTransitions?e.$slides.eq(i).animate({opacity:0,zIndex:e.options.zIndex-2},e.options.speed,e.options.easing):(e.applyTransition(i),e.$slides.eq(i).css({opacity:0,zIndex:e.options.zIndex-2}))},e.prototype.filterSlides=e.prototype.slickFilter=function(i){var e=this;null!==i&&(e.$slidesCache=e.$slides,e.unload(),e.$slideTrack.children(this.options.slide).detach(),e.$slidesCache.filter(i).appendTo(e.$slideTrack),e.reinit())},e.prototype.focusHandler=function(){var e=this;e.$slider.off("focus.slick blur.slick").on("focus.slick blur.slick","*",function(t){t.stopImmediatePropagation();var o=i(this);setTimeout(function(){e.options.pauseOnFocus&&(e.focussed=o.is(":focus"),e.autoPlay())},0)})},e.prototype.getCurrent=e.prototype.slickCurrentSlide=function(){return this.currentSlide},e.prototype.getDotCount=function(){var i=this,e=0,t=0,o=0;if(!0===i.options.infinite)if(i.slideCount<=i.options.slidesToShow)++o;else for(;e<i.slideCount;)++o,e=t+i.options.slidesToScroll,t+=i.options.slidesToScroll<=i.options.slidesToShow?i.options.slidesToScroll:i.options.slidesToShow;else if(!0===i.options.centerMode)o=i.slideCount;else if(i.options.asNavFor)for(;e<i.slideCount;)++o,e=t+i.options.slidesToScroll,t+=i.options.slidesToScroll<=i.options.slidesToShow?i.options.slidesToScroll:i.options.slidesToShow;else o=1+Math.ceil((i.slideCount-i.options.slidesToShow)/i.options.slidesToScroll);return o-1},e.prototype.getLeft=function(i){var e,t,o,s,n=this,r=0;return n.slideOffset=0,t=n.$slides.first().outerHeight(!0),!0===n.options.infinite?(n.slideCount>n.options.slidesToShow&&(n.slideOffset=n.slideWidth*n.options.slidesToShow*-1,s=-1,!0===n.options.vertical&&!0===n.options.centerMode&&(2===n.options.slidesToShow?s=-1.5:1===n.options.slidesToShow&&(s=-2)),r=t*n.options.slidesToShow*s),n.slideCount%n.options.slidesToScroll!=0&&i+n.options.slidesToScroll>n.slideCount&&n.slideCount>n.options.slidesToShow&&(i>n.slideCount?(n.slideOffset=(n.options.slidesToShow-(i-n.slideCount))*n.slideWidth*-1,r=(n.options.slidesToShow-(i-n.slideCount))*t*-1):(n.slideOffset=n.slideCount%n.options.slidesToScroll*n.slideWidth*-1,r=n.slideCount%n.options.slidesToScroll*t*-1))):i+n.options.slidesToShow>n.slideCount&&(n.slideOffset=(i+n.options.slidesToShow-n.slideCount)*n.slideWidth,r=(i+n.options.slidesToShow-n.slideCount)*t),n.slideCount<=n.options.slidesToShow&&(n.slideOffset=0,r=0),!0===n.options.centerMode&&n.slideCount<=n.options.slidesToShow?n.slideOffset=n.slideWidth*Math.floor(n.options.slidesToShow)/2-n.slideWidth*n.slideCount/2:!0===n.options.centerMode&&!0===n.options.infinite?n.slideOffset+=n.slideWidth*Math.floor(n.options.slidesToShow/2)-n.slideWidth:!0===n.options.centerMode&&(n.slideOffset=0,n.slideOffset+=n.slideWidth*Math.floor(n.options.slidesToShow/2)),e=!1===n.options.vertical?i*n.slideWidth*-1+n.slideOffset:i*t*-1+r,!0===n.options.variableWidth&&(o=n.slideCount<=n.options.slidesToShow||!1===n.options.infinite?n.$slideTrack.children(".slick-slide").eq(i):n.$slideTrack.children(".slick-slide").eq(i+n.options.slidesToShow),e=!0===n.options.rtl?o[0]?-1*(n.$slideTrack.width()-o[0].offsetLeft-o.width()):0:o[0]?-1*o[0].offsetLeft:0,!0===n.options.centerMode&&(o=n.slideCount<=n.options.slidesToShow||!1===n.options.infinite?n.$slideTrack.children(".slick-slide").eq(i):n.$slideTrack.children(".slick-slide").eq(i+n.options.slidesToShow+1),e=!0===n.options.rtl?o[0]?-1*(n.$slideTrack.width()-o[0].offsetLeft-o.width()):0:o[0]?-1*o[0].offsetLeft:0,e+=(n.$list.width()-o.outerWidth())/2)),e},e.prototype.getOption=e.prototype.slickGetOption=function(i){return this.options[i]},e.prototype.getNavigableIndexes=function(){var i,e=this,t=0,o=0,s=[];for(!1===e.options.infinite?i=e.slideCount:(t=-1*e.options.slidesToScroll,o=-1*e.options.slidesToScroll,i=2*e.slideCount);t<i;)s.push(t),t=o+e.options.slidesToScroll,o+=e.options.slidesToScroll<=e.options.slidesToShow?e.options.slidesToScroll:e.options.slidesToShow;return s},e.prototype.getSlick=function(){return this},e.prototype.getSlideCount=function(){var e,t,o=this;return t=!0===o.options.centerMode?o.slideWidth*Math.floor(o.options.slidesToShow/2):0,!0===o.options.swipeToSlide?(o.$slideTrack.find(".slick-slide").each(function(s,n){if(n.offsetLeft-t+i(n).outerWidth()/2>-1*o.swipeLeft)return e=n,!1}),Math.abs(i(e).attr("data-slick-index")-o.currentSlide)||1):o.options.slidesToScroll},e.prototype.goTo=e.prototype.slickGoTo=function(i,e){this.changeSlide({data:{message:"index",index:
36741parseInt(i)}},e)},e.prototype.init=function(e){var t=this;i(t.$slider).hasClass("slick-initialized")||(i(t.$slider).addClass("slick-initialized"),t.buildRows(),t.buildOut(),t.setProps(),t.startLoad(),t.loadSlider(),t.initializeEvents(),t.updateArrows(),t.updateDots(),t.checkResponsive(!0),t.focusHandler()),e&&t.$slider.trigger("init",[t]),!0===t.options.accessibility&&t.initADA(),t.options.autoplay&&(t.paused=!1,t.autoPlay())},e.prototype.initADA=function(){var e=this,t=Math.ceil(e.slideCount/e.options.slidesToShow),o=e.getNavigableIndexes().filter(function(i){return i>=0&&i<e.slideCount});e.$slides.add(e.$slideTrack.find(".slick-cloned")).attr({"aria-hidden":"true",tabindex:"-1"}).find("a, input, button, select").attr({tabindex:"-1"}),null!==e.$dots&&(e.$slides.not(e.$slideTrack.find(".slick-cloned")).each(function(t){var s=o.indexOf(t);i(this).attr({role:"tabpanel",id:"slick-slide"+e.instanceUid+t,tabindex:-1}),-1!==s&&i(this).attr({"aria-describedby":"slick-slide-control"+e.instanceUid+s})}),e.$dots.attr("role","tablist").find("li").each(function(s){var n=o[s];i(this).attr({role:"presentation"}),i(this).find("button").first().attr({role:"tab",id:"slick-slide-control"+e.instanceUid+s,"aria-controls":"slick-slide"+e.instanceUid+n,"aria-label":s+1+" of "+t,"aria-selected":null,tabindex:"-1"})}).eq(e.currentSlide).find("button").attr({"aria-selected":"true",tabindex:"0"}).end());for(var s=e.currentSlide,n=s+e.options.slidesToShow;s<n;s++)e.$slides.eq(s).attr("tabindex",0);e.activateADA()},e.prototype.initArrowEvents=function(){var i=this;!0===i.options.arrows&&i.slideCount>i.options.slidesToShow&&(i.$prevArrow.off("click.slick").on("click.slick",{message:"previous"},i.changeSlide),i.$nextArrow.off("click.slick").on("click.slick",{message:"next"},i.changeSlide),!0===i.options.accessibility&&(i.$prevArrow.on("keydown.slick",i.keyHandler),i.$nextArrow.on("keydown.slick",i.keyHandler)))},e.prototype.initDotEvents=function(){var e=this;!0===e.options.dots&&(i("li",e.$dots).on("click.slick",{message:"index"},e.changeSlide),!0===e.options.accessibility&&e.$dots.on("keydown.slick",e.keyHandler)),!0===e.options.dots&&!0===e.options.pauseOnDotsHover&&i("li",e.$dots).on("mouseenter.slick",i.proxy(e.interrupt,e,!0)).on("mouseleave.slick",i.proxy(e.interrupt,e,!1))},e.prototype.initSlideEvents=function(){var e=this;e.options.pauseOnHover&&(e.$list.on("mouseenter.slick",i.proxy(e.interrupt,e,!0)),e.$list.on("mouseleave.slick",i.proxy(e.interrupt,e,!1)))},e.prototype.initializeEvents=function(){var e=this;e.initArrowEvents(),e.initDotEvents(),e.initSlideEvents(),e.$list.on("touchstart.slick mousedown.slick",{action:"start"},e.swipeHandler),e.$list.on("touchmove.slick mousemove.slick",{action:"move"},e.swipeHandler),e.$list.on("touchend.slick mouseup.slick",{action:"end"}
36741,e.swipeHandler),e.$list.on("touchcancel.slick mouseleave.slick",{action:"end"},e.swipeHandler),e.$list.on("click.slick",e.clickHandler),i(document).on(e.visibilityChange,i.proxy(e.visibility,e)),!0===e.options.accessibility&&e.$list.on("keydown.slick",e.keyHandler),!0===e.options.focusOnSelect&&i(e.$slideTrack).children().on("click.slick",e.selectHandler),i(window).on("orientationchange.slick.slick-"+e.instanceUid,i.proxy(e.orientationChange,e)),i(window).on("resize.slick.slick-"+e.instanceUid,i.proxy(e.resize,e)),i("[draggable!=true]",e.$slideTrack).on("dragstart",e.preventDefault),i(window).on("load.slick.slick-"+e.instanceUid,e.setPosition),i(e.setPosition)},e.prototype.initUI=function(){var i=this;!0===i.options.arrows&&i.slideCount>i.options.slidesToShow&&(i.$prevArrow.show(),i.$nextArrow.show()),!0===i.options.dots&&i.slideCount>i.options.slidesToShow&&i.$dots.show()},e.prototype.keyHandler=function(i){var e=this;i.target.tagName.match("TEXTAREA|INPUT|SELECT")||(37===i.keyCode&&!0===e.options.accessibility?e.changeSlide({data:{message:!0===e.options.rtl?"next":"previous"}}):39===i.keyCode&&!0===e.options.accessibility&&e.changeSlide({data:{message:!0===e.options.rtl?"previous":"next"}}))},e.prototype.lazyLoad=function(){function e(e){i("img[data-lazy]",e).each(function(){var e=i(this),t=i(this).attr("data-lazy"),o=i(this).attr("data-srcset"),s=i(this).attr("data-sizes")||n.$slider.attr("data-sizes"),r=document.createElement("img");r.onload=function(){e.animate({opacity:0}
vendor: 5,619 bytes, line 36741
36741,100,function(){o&&(e.attr("srcset",o),s&&e.attr("sizes",s)),e.attr("src",t).animate({opacity:1},200,function(){e.removeAttr("data-lazy data-srcset data-sizes").removeClass("slick-loading")}),n.$slider.trigger("lazyLoaded",[n,e,t])})},r.onerror=function(){e.removeAttr("data-lazy").removeClass("slick-loading").addClass("slick-lazyload-error"),n.$slider.trigger("lazyLoadError",[n,e,t])},r.src=t})}var t,o,s,n=this;if(!0===n.options.centerMode?!0===n.options.infinite?s=(o=n.currentSlide+(n.options.slidesToShow/2+1))+n.options.slidesToShow+2:(o=Math.max(0,n.currentSlide-(n.options.slidesToShow/2+1)),s=n.options.slidesToShow/2+1+2+n.currentSlide):(o=n.options.infinite?n.options.slidesToShow+n.currentSlide:n.currentSlide,s=Math.ceil(o+n.options.slidesToShow),!0===n.options.fade&&(o>0&&o--,s<=n.slideCount&&s++)),t=n.$slider.find(".slick-slide").slice(o,s),"anticipated"===n.options.lazyLoad)for(var r=o-1,l=s,d=n.$slider.find(".slick-slide"),a=0;a<n.options.slidesToScroll;a++)r<0&&(r=n.slideCount-1),t=(t=t.add(d.eq(r))).add(d.eq(l)),r--,l++;e(t),n.slideCount<=n.options.slidesToShow?e(n.$slider.find(".slick-slide")):n.currentSlide>=n.slideCount-n.options.slidesToShow?e(n.$slider.find(".slick-cloned").slice(0,n.options.slidesToShow)):0===n.currentSlide&&e(n.$slider.find(".slick-cloned").slice(-1*n.options.slidesToShow))},e.prototype.loadSlider=function(){var i=this;i.setPosition(),i.$slideTrack.css({opacity:1}),i.$slider.removeClass("slick-loading"),i.initUI(),"progressive"===i.options.lazyLoad&&i.progressiveLazyLoad()},e.prototype.next=e.prototype.slickNext=function(){this.changeSlide({data:{message:"next"}})},e.prototype.orientationChange=function(){var i=this;i.checkResponsive(),i.setPosition()},e.prototype.pause=e.prototype.slickPause=function(){var i=this;i.autoPlayClear(),i.paused=!0},e.prototype.play=e.prototype.slickPlay=function(){var i=this;i.autoPlay(),i.options.autoplay=!0,i.paused=!1,i.focussed=!1,i.interrupted=!1},e.prototype.postSlide=function(e){var t=this;t.unslicked||(t.$slider.trigger("afterChange",[t,e]),t.animating=!1,t.slideCount>t.options.slidesToShow&&t.setPosition(),t.swipeLeft=null,t.options.autoplay&&t.autoPlay(),!0===t.options.accessibility&&(t.initADA(),t.options.focusOnChange&&i(t.$slides.get(t.currentSlide)).attr("tabindex",0).focus()))},e.prototype.prev=e.prototype.slickPrev=function(){this.changeSlide({data:{message:"previous"}})},e.prototype.preventDefault=function(i){i.preventDefault()},e.prototype.progressiveLazyLoad=function(e){e=e||1;var t,o,s,n,r,l=this,d=i("img[data-lazy]",l.$slider);d.length?(t=d.first(),o=t.attr("data-lazy"),s=t.attr("data-srcset"),n=t.attr("data-sizes")||l.$slider.attr("data-sizes"),(r=document.createElement("img")).onload=function(){s&&(t.attr("srcset",s),n&&t.attr("sizes",n)),t.attr("src",o).removeAttr("data-lazy data-srcset data-sizes").removeClass("slick-loading"),!0===l.options.adaptiveHeight&&l.setPosition(),l.$slider.trigger("lazyLoaded",[l,t,o]),l.progressiveLazyLoad()},r.onerror=function(){e<3?setTimeout(function(){l.progressiveLazyLoad(e+1)},500):(t.removeAttr("data-lazy").removeClass("slick-loading").addClass("slick-lazyload-error"),l.$slider.trigger("lazyLoadError",[l,t,o]),l.progressiveLazyLoad())},r.src=o):l.$slider.trigger("allImagesLoaded",[l])},e.prototype.refresh=function(e){var t,o,s=this;o=s.slideCount-s.options.slidesToShow,!s.options.infinite&&s.currentSlide>o&&(s.currentSlide=o),s.slideCount<=s.options.slidesToShow&&(s.currentSlide=0),t=s.currentSlide,s.destroy(!0),i.extend(s,s.initials,{currentSlide:t}),s.init(),e||s.changeSlide({data:{message:"index",index:t}},!1)},e.prototype.registerBreakpoints=function(){var e,t,o,s=this,n=s.options.responsive||null;if("array"===i.type(n)&&n.length){s.respondTo=s.options.respondTo||"window";for(e in n)if(o=s.breakpoints.length-1,n.hasOwnProperty(e)){for(t=n[e].breakpoint;o>=0;)s.breakpoints[o]&&s.breakpoints[o]===t&&s.breakpoints.splice(o,1),o--;s.breakpoints.push(t),s.breakpointSettings[t]=n[e].settings}s.breakpoints.sort(function(i,e){return s.options.mobileFirst?i-e:e-i})}},e.prototype.reinit=function(){var e=this;e.$slides=e.$slideTrack.children(e.options.slide).addClass("slick-slide"),e.slideCount=e.$slides.length,e.currentSlide>=e.slideCount&&0!==e.currentSlide&&(e.currentSlide=e.currentSlide-e.options.slidesToScroll),e.slideCount<=e.options.slidesToShow&&(e.currentSlide=0),e.registerBreakpoints(),e.setProps(),e.setupInfinite(),e.buildArrows(),e.updateArrows(),e.initArrowEvents(),e.buildDots(),e.updateDots(),e.initDotEvents(),e.cleanUpSlideEvents(),e.initSlideEvents(),e.checkResponsive(!1,!0),!0===e.options.focusOnSelect&&i(e.$slideTrack).children().on("click.slick",e.selectHandler),e.setSlideClasses("number"==typeof e.currentSlide?e.currentSlide:0),e.setPosition(),e.focusHandler(),e.paused=!e.options.autoplay,e.autoPlay(),e.$slider.trigger("reInit",[e])},e.prototype.resize=function(){var e=this;i(window).width()!==e.windowWidth&&(clearTimeout(e.windowDelay),e.windowDelay=window.setTimeout(function(){e.windowWidth=i(window).width(),e.checkResponsive(),e.unslicked||e.setPosition()},50))},e.prototype.removeSlide=e.prototype.slickRemove=function(i,e,t){var o=this;if(i="boolean"==typeof i?!0===(e=i)?0:o.slideCount-1:!0===e?--i:i,o.slideCount<1||i<0||i>o.slideCount-1)return!1;o.unload(),!0===t?o.$slideTrack.children().remove():o.$slideTrack.children(this.options.slide).eq(i).remove(),o.$slides=o.$slideTrack.children(this.options.slide),o.$slideTrack.children(this.options.slide).detach(),o.$slideTrack.append(o.$slides),o.$slidesCache=o.$slides,o.reinit()},e.prototype.setCSS=function(i){var e,t,o=this,s={};
36741!0===o.options.rtl&&(i=-i),e="left"==o.positionProp?Math.ceil(i)+"px":"0px",t="top"==o.positionProp?Math.ceil(i)+"px":"0px",s[o.positionProp]=i,!1===o.transformsEnabled?o.$slideTrack.css(s):(s={},!1===o.cssTransitions?(s[o.animType]="translate("+e+", "+t+")",o.$slideTrack.css(s)):(s[o.animType]="translate3d("+e+", "+t+", 0px)",o.$slideTrack.css(s)))},e.prototype.setDimensions=function(){var i=this;!1===i.options.vertical?!0===i.options.centerMode&&i.$list.css({padding:"0px "+i.options.centerPadding}):(i.$list.height(i.$slides.first().outerHeight(!0)*i.options.slidesToShow),!0===i.options.centerMode&&i.$list.css({padding:i.options.centerPadding+" 0px"})),i.listWidth=i.$list.width(),i.listHeight=i.$list.height(),!1===i.options.vertical&&!1===i.options.variableWidth?(i.slideWidth=Math.ceil(i.listWidth/i.options.slidesToShow),i.$slideTrack.width(Math.ceil(i.slideWidth*i.$slideTrack.children(".slick-slide").length))):!0===i.options.variableWidth?i.$slideTrack.width(5e3*i.slideCount):(i.slideWidth=Math.ceil(i.listWidth),i.$slideTrack.height(Math.ceil(i.$slides.first().outerHeight(!0)*i.$slideTrack.children(".slick-slide").length)));var e=i.$slides.first().outerWidth(!0)-i.$slides.first().width();!1===i.options.variableWidth&&i.$slideTrack.children(".slick-slide").width(i.slideWidth-e)},e.prototype.setFade=function(){var e,t=this;t.$slides.each(function(o,s){e=t.slideWidth*o*-1,!0===t.options.rtl?i(s).css({position:"relative",right:e,top:0,zIndex:t.options.zIndex-2,opacity:0}
36741):i(s).css({position:"relative",left:e,top:0,zIndex:t.options.zIndex-2,opacity:0})}),t.$slides.eq(t.currentSlide).css({zIndex:t.options.zIndex-1,opacity:1})},e.prototype.setHeight=function(){var i=this;if(1===i.options.slidesToShow&&!0===i.options.adaptiveHeight&&!1===i.options.vertical){var e=i.$slides.eq(i.currentSlide).outerHeight(!0);i.$list.css("height",e)}},e.prototype.setOption=e.prototype.slickSetOption=function(){var e,t,o,s,n,r=this,l=!1;if("object"===i.type(arguments[0])?(o=arguments[0],l=arguments[1],n="multiple"):"string"===i.type(arguments[0])&&(o=arguments[0],s=arguments[1],l=arguments[2],"responsive"===arguments[0]&&"array"===i.type(arguments[1])?n="responsive":void 0!==arguments[1]&&(n="single")),"single"===n)r.options[o]=s;else if("multiple"===n)i.each(o,function(i,e){r.options[i]=e});else if("responsive"===n)for(t in s)if("array"!==i.type(r.options.responsive))r.options.responsive=[s[t]];else{for(e=r.options.responsive.length-1;e>=0;)r.options.responsive[e].breakpoint===s[t].breakpoint&&r.options.responsive.splice(e,1),e--;r.options.responsive.push(s[t])}l&&(r.unload(),r.reinit())},e.prototype.setPosition=function(){var i=this;i.setDimensions(),i.setHeight(),!1===i.options.fade?i.setCSS(i.getLeft(i.currentSlide)):i.setFade(),i.$slider.trigger("setPosition",[i])},e.prototype.setProps=function(){var i=this,e=document.body.style;i.positionProp=!0===i.options.vertical?"top":"left","top"===i.positionProp?i.$slider.addClass("slick-vertical"):i.$slider.removeClass("slick-vertical"),void 0===e.WebkitTransition&&void 0===e.MozTransition&&void 0===e.msTransition||!0===i.options.useCSS&&(i.cssTransitions=!0),i.options.fade&&("number"==typeof i.options.zIndex?i.options.zIndex<3&&(i.options.zIndex=3):i.options.zIndex=i.defaults.zIndex),void 0!==e.OTransform&&(i.animType="OTransform",i.transformType="-o-transform",i.transitionType="OTransition",void 0===e.perspectiveProperty&&void 0===e.webkitPerspective&&(i.animType=!1)),void 0!==e.MozTransform&&(i.animType="MozTransform",i.transformType="-moz-transform",i.transitionType="MozTransition",void 0===e.perspectiveProperty&&void 0===e.MozPerspective&&(i.animType=!1)),void 0!==e.webkitTransform&&(i.animType="webkitTransform",i.transformType="-webkit-transform",i.transitionType="webkitTransition",void 0===e.perspectiveProperty&&void 0===e.webkitPerspective&&(i.animType=!1)),void 0!==e.msTransform&&(i.animType="msTransform",i.transformType="-ms-transform",i.transitionType="msTransition",void 0===e.msTransform&&(i.animType=!1)),void 0!==e.transform&&!1!==i.animType&&(i.animType="transform",i.transformType="transform",i.transitionType="transition"),i.transformsEnabled=i.options.useTransform&&null!==i.animType&&!1!==i.animType},e.prototype.setSlideClasses=function(i){var e,t,o,s,n=this;if(t=n.$slider.find(".slick-slide").removeClass("slick-active slick-center slick-current").attr("aria-hidden","true"),n.$slides.eq(i).addClass("slick-current"),!0===n.options.centerMode){var r=n.options.slidesToShow%2==0?1:0;e=Math.floor(n.options.slidesToShow/2),!0===n.options.infinite&&(i>=e&&i<=n.slideCount-1-e?n.$slides.slice(i-e+r,i+e+1).addClass("slick-active").attr("aria-hidden","false"):(o=n.options.slidesToShow+i,t.slice(o-e+1+r,o+e+2).addClass("slick-active").attr("aria-hidden","false")),0===i?t.eq(t.length-1-n.options.slidesToShow).addClass("slick-center"):i===n.slideCount-1&&t.eq(n.options.slidesToShow).addClass("slick-center")),n.$slides.eq(i).addClass("slick-center")}else i>=0&&i<=n.slideCount-n.options.slidesToShow?n.$slides.slice(i,i+n.options.slidesToShow).addClass("slick-active").attr("aria-hidden","false"):t.length<=n.options.slidesToShow?t.addClass("slick-active").attr("aria-hidden","false"):(s=n.slideCount%n.options.slidesToShow,o=!0===n.options.infinite?n.options.slidesToShow+i:i,n.options.slidesToShow==n.options.slidesToScroll&&n.slideCount-i<n.options.slidesToShow?t.slice(o-(n.options.slidesToShow-s),o+s).addClass("slick-active").attr("aria-hidden","false"):t.slice(o,o+n.options.slidesToShow).addClass("slick-active").attr("aria-hidden","false"));"ondemand"!==n.options.lazyLoad&&"anticipated"!==n.options.lazyLoad||n.lazyLoad()},e.prototype.setupInfinite=function(){var e,t,o,s=this;if(!0===s.options.fade&&(s.options.centerMode=!1),!0===s.options.infinite&&!1===s.options.fade&&(t=null,s.slideCount>s.options.slidesToShow)){for(o=!0===s.options.centerMode?s.options.slidesToShow+1:s.options.slidesToShow,e=s.slideCount;e>s.slideCount-o;e-=1)t=e-1,i(s.$slides[t]).clone(!0).attr("id","").attr("data-slick-index",t-s.slideCount).prependTo(s.$slideTrack).addClass("slick-cloned");for(e=0;e<o+s.slideCount;e+=1)t=e,i(s.$slides[t]).clone(!0).attr("id","").attr("data-slick-index",t+s.slideCount).appendTo(s.$slideTrack).addClass("slick-cloned");s.$slideTrack.find(".slick-cloned").find("[id]").each(function(){i(this).attr("id","")})}},e.prototype.interrupt=function(i){var e=this;i||e.autoPlay(),e.interrupted=i},e.prototype.selectHandler=function(e){var t=this,o=i(e.target).is(".slick-slide")?i(e.target):i(e.target).parents(".slick-slide"),s=parseInt(o.attr("data-slick-index"));s||(s=0),t.slideCount<=t.options.slidesToShow?t.slideHandler(s,!1,!0):t.slideHandler(s)},e.prototype.slideHandler=function(i,e,t){var o,s,n,r,l,d=null,a=this;if(e=e||!1,!(!0===a.animating&&!0===a.options.waitForAnimate||!0===a.options.fade&&a.currentSlide===i))if(!1===e&&a.asNavFor(i),o=i,d=a.getLeft(o),r=a.getLeft(a.currentSlide),a.currentLeft=null===a.swipeLeft?r:a.swipeLeft,!1===a.options.infinite&&!1===a.options.centerMode&&(i<0||i>a.getDotCount()*a.options.slidesToScroll))!1===a.options.fade&&(o=a.currentSlide,!0!==t?a.animateSlide(r,function(){a.postSlide(o)}):a.postSlide(o));else if(!1===a.options.infinite&&!0===a.options.centerMode&&(i<0||i>a.slideCount-a.options.slidesToScroll))!1===a.options.fade&&(o=a.currentSlide,!0!==t?a.animateSlide(r,function(){a.postSlide(o)}):a.postSlide(o));else{if(a.options.autoplay&&clearInterval(a.autoPlayTimer),s=o<0?a.slideCount%a.options.slidesToScroll!=0?a.slideCount-a.slideCount%a.options.slidesToScroll:a.slideCount+
36741o:o>=a.slideCount?a.slideCount%a.options.slidesToScroll!=0?0:o-a.slideCount:o,a.animating=!0,a.$slider.trigger("beforeChange",[a,a.currentSlide,s]),n=a.currentSlide,a.currentSlide=s,a.setSlideClasses(a.currentSlide),a.options.asNavFor&&(l=(l=a.getNavTarget()).slick("getSlick")).slideCount<=l.options.slidesToShow&&l.setSlideClasses(a.currentSlide),a.updateDots(),a.updateArrows(),!0===a.options.fade)return!0!==t?(a.fadeSlideOut(n),a.fadeSlide(s,function(){a.postSlide(s)})):a.postSlide(s),void a.animateHeight();!0!==t?a.animateSlide(d,function(){a.postSlide(s)}):a.postSlide(s)}},e.prototype.startLoad=function(){var i=this;!0===i.options.arrows&&i.slideCount>i.options.slidesToShow&&(i.$prevArrow.hide(),i.$nextArrow.hide()),!0===i.options.dots&&i.slideCount>i.options.slidesToShow&&i.$dots.hide(),i.$slider.addClass("slick-loading")},e.prototype.swipeDirection=function(){var i,e,t,o,s=this;return i=s.touchObject.startX-s.touchObject.curX,e=s.touchObject.startY-s.touchObject.curY,t=Math.atan2(e,i),(o=Math.round(180*t/Math.PI))<0&&(o=360-Math.abs(o)),o<=45&&o>=0?!1===s.options.rtl?"left":"right":o<=360&&o>=315?!1===s.options.rtl?"left":"right":o>=135&&o<=225?!1===s.options.rtl?"right":"left":!0===s.options.verticalSwiping?o>=35&&o<=135?"down":"up":"vertical"},e.prototype.swipeEnd=function(i){var e,t,o=this;if(o.dragging=!1,o.swiping=!1,o.scrolling)return o.scrolling=!1,!1;if(o.interrupted=!1,o.shouldClick=!(o.touchObject.swipeLength>10),void 0===o.touchObject.curX)return!1;if(!0===o.touchObject.edgeHit&&o.$slider.trigger("edge",[o,o.swipeDirection()]),o.touchObject.swipeLength>=o.touchObject.minSwipe){switch(t=o.swipeDirection()){case"left":case"down":e=o.options.swipeToSlide?o.checkNavigable(o.currentSlide+o.getSlideCount()):o.currentSlide+o.getSlideCount(),o.currentDirection=0;break;case"right":case"up":e=o.options.swipeToSlide?o.checkNavigable(o.currentSlide-o.getSlideCount()):o.currentSlide-o.getSlideCount(),o.currentDirection=1}"vertical"!=t&&(o.slideHandler(e),o.touchObject={},o.$slider.trigger("swipe",[o,t]))}else o.touchObject.startX!==o.touchObject.curX&&(o.slideHandler(o.currentSlide),o.touchObject={})},e.prototype.swipeHandler=function(i){var e=this;if(!(!1===e.options.swipe||"ontouchend"in document&&!1===e.options.swipe||!1===e.options.draggable&&-1!==i.type.indexOf("mouse")))switch(e.touchObject.fingerCount=i.originalEvent&&void 0!==i.originalEvent.touches?i.originalEvent.touches.length:1,e.touchObject.minSwipe=e.listWidth/e.options.touchThreshold,!0===e.options.verticalSwiping&&(e.touchObject.minSwipe=e.listHeight/e.options.touchThreshold),i.data.action){case"start":e.swipeStart(i);break;case"move":e.swipeMove(i);break;case"end":e.swipeEnd(i)}},e.prototype.swipeMove=function(i){var e,t,o,s,n,r,l=this;return n=void 0!==i.originalEvent?i.originalEvent.touches:null,!(!l.dragging||l.scrolling||n&&1!==n.length)&&(e=l.getLeft(l.currentSlide),l.touchObject.curX=void 0!==n?n[0].pageX:i.clientX,l.touchObject.curY=void 0!==n?n[0].pageY:i.clientY,l.touchObject.swipeLength=Math.round(Math.sqrt(Math.pow(l.touchObject.curX-l.touchObject.startX,2))),r=Math.round(Math.sqrt(Math.pow(l.touchObject.curY-l.touchObject.startY,2))),!l.options.verticalSwiping&&!l.swiping&&r>4?(l.scrolling=!0,!1):(!0===l.options.verticalSwiping&&(l.touchObject.swipeLength=r),t=l.swipeDirection(),void 0!==i.originalEvent&&l.touchObject.swipeLength>4&&(l.swiping=!0,i.preventDefault()),s=(!1===l.options.rtl?1:-1)*(l.touchObject.curX>l.touchObject.startX?1:-1),!0===l.options.verticalSwiping&&(s=l.touchObject.curY>l.touchObject.startY?1:-1),o=l.touchObject.swipeLength,l.touchObject.edgeHit=!1,!1===l.options.infinite&&(0===l.currentSlide&&"right"===t||l.currentSlide>=l.getDotCount()&&"left"===t)&&(o=l.touchObject.swipeLength*l.options.edgeFriction,l.touchObject.edgeHit=!0),!1===l.options.vertical?l.swipeLeft=e+o*s:l.swipeLeft=e+o*(l.$list.height()/l.listWidth)*s,!0===l.options.verticalSwiping&&(l.swipeLeft=e+o*s),!0!==l.options.fade&&!1!==l.options.touchMove&&(!0===l.animating?(l.swipeLeft=null,!1):void l.setCSS(l.swipeLeft))))},e.prototype.swipeStart=function(i){var e,t=this;if(t.interrupted=!0,1!==t.touchObject.fingerCount||t.slideCount<=t.options.slidesToShow)return t.touchObject={},!1;void 0!==i.originalEvent&&void 0!==i.originalEvent.touches&&(e=i.originalEvent.touches[0]),t.touchObject.startX=t.touchObject.curX=void 0!==e?e.pageX:i.clientX,t.touchObject.startY=t.touchObject.curY=void 0!==e?e.pageY:i.clientY,t.dragging=!0},e.prototype.unfilterSlides=e.prototype.slickUnfilter=function(){var i=this;null!==i.$slidesCache&&(i.unload(),i.$slideTrack.children(this.options.slide).detach(),i.$slidesCache.appendTo(i.$slideTrack),i.reinit())},e.prototype.unload=function(){var e=this;i(".slick-cloned",e.$slider).remove(),e.$dots&&e.$dots.remove(),e.$prevArrow&&e.htmlExpr.test(e.options.prevArrow)&&e.$prevArrow.remove(),e.$nextArrow&&e.htmlExpr.test(e.options.nextArrow)&&e.$nextArrow.remove(),e.$slides.removeClass("slick-slide slick-active slick-visible slick-current").attr("aria-hidden","true").css("width","")}
36741,e.prototype.unslick=function(i){var e=this;e.$slider.trigger("unslick",[e,i]),e.destroy()},e.prototype.updateArrows=function(){var i=this;Math.floor(i.options.slidesToShow/2),!0===i.options.arrows&&i.slideCount>i.options.slidesToShow&&!i.options.infinite&&(i.$prevArrow.removeClass("slick-disabled").attr("aria-disabled","false"),i.$nextArrow.removeClass("slick-disabled").attr("aria-disabled","false"),0===i.currentSlide?(i.$prevArrow.addClass("slick-disabled").attr("aria-disabled","true"),i.$nextArrow.removeClass("slick-disabled").attr("aria-disabled","false")):i.currentSlide>=i.slideCount-i.options.slidesToShow&&!1===i.options.centerMode?(i.$nextArrow.addClass("slick-disabled").attr("aria-disabled","true"),i.$prevArrow.removeClass("slick-disabled").attr("aria-disabled","false")):i.currentSlide>=i.slideCount-1&&!0===i.options.centerMode&&(i.$nextArrow.addClass("slick-disabled").attr("aria-disabled","true"),i.$prevArrow.removeClass("slick-disabled").attr("aria-disabled","false")))},e.prototype.updateDots=function(){var i=this;null!==i.$dots&&(i.$dots.find("li").removeClass("slick-active").end(),i.$dots.find("li").eq(Math.floor(i.currentSlide/i.options.slidesToScroll)).addClass("slick-active"))},e.prototype.visibility=function(){var i=this;i.options.autoplay&&(document[i.hidden]?i.interrupted=!0:i.interrupted=!1)},i.fn.slick=function(){var i,t,o=this,s=arguments[0],n=Array.prototype.slice.call(arguments,1),r=o.length;for(i=0;i<r;i++)if("object"==typeof s||void 0===s?o[i].slick=new e(o[i],s):t=o[i].slick[s].apply(o[i].slick,n),void 0!==t)return t;return o}});
36742;
36743/*!
36744	Modaal - accessible modals - v0.3.1
36745	by Humaan, for all humans.
36746	http://humaan.com
36747 */
36748/**
36749	Modaal jQuery Plugin : Accessible Modals
36750
36751	==== General Options ===
36752	type (string) 					: ajax, inline, image, iframe, confirm. Defaults to 'inline'
36753	animation (string) 				: Fade, expand, down, up. Defaults to 'fade'
36754	after_callback_delay (integer)	: Specify a delay value for the after open callbacks. This is necessary because with the bundled animations
36755										have a set duration in the bundled CSS. Specify a delay of the same amount as the animation duration in so
36756										more accurately fire the after open/close callbacks. Defaults 350, does not apply if animation is 'none',
36757										after open callbacks are dispatched immediately
36758
36759	is_locked (boolean)				: Set this to true to disable closing the modal via keypress or clicking the background. Beware that if
36760										type != 'confirm' there will be no interface to dismiss the modal if is_locked = true, you'd have to
36761										programmatically arrange to dismiss the modal. Confirm modals are always locked regardless of this option
36762										Defaults to false
36763
36764	hide_close (boolean)			: Set this to true to hide the close modal button. Key press and overlay click will still close the modal.
36765										This method is best used when you want to put a custom close button inside the modal container space.
36766
36767	background (string)				: Background overlay style. Defaults to '#000'
36768	overlay_opacity (float) 		: Background overlay transparency. Defaults to 0.8
36769	overlay_close (boolean)			: Set this to false if you want to disable click to close on overlay background.
36770
36771	accessible_title (string)		: Accessible title. Default 'Dialog Window'
36772	start_open (boolean)			: Set this to true to launch the Modaal window immediately on page open
36773	fullscreen (boolean)			: Set this to true to make the modaal fill the entire screen, false will default to own width/height attributes.
36774	custom_class (string)			: Fill in this string with a custom class that will be applied to the outer most modal wrapper.
36775
36776	width (integer)					: Desired width of the modal. Required for iframe type. Defaults to undefined //TODO
36777	height (integer)				: Desired height of the modal. Required for iframe type. Defaults to undefined //TODO
36778
36779	background_scroll (boolean)		: Set this to true to enable the page to scroll behind the open modal.
36780
36781    should_open (boolean|function)  : Boolean or closure that returns a boolean to determine whether to open the modal or not.
36782
36783	close_text						: String for close button text. Available for localisation and alternative languages to be used.
36784	close_aria_label				: String for close button aria-label attribute (value that screen readers will read out). Available for localisation and alternative languages to be used.
36785
36786	=== Events ===
36787	before_open (function) 			: Callback function executed before modal is opened
36788	after_open (function)			: Callback function executed after modal is opened
36789	before_close (function)			: Callback function executed before modal is closed
36790	after_close (function)			: Callback function executed after modal is closed
36791	source (function(element, src))	: Callback function executed on the default source, it is intended to transform the
36792										source (href in an AJAX modal or iframe). The function passes in the triggering element
36793										as well as the default source depending of the modal type. The default output of the
36794										function is an untransformed default source.
36795
36796
36797	=== Confirm Options & Events ===
36798	confirm_button_text (string)	: Text on the confirm button. Defaults to 'Confirm'
36799	confirm_cancel_button_text (string) : Text on the confirm modal cancel button. Defaults to 'Cancel'
36800	confirm_title (string)			: Title for confirm modal. Default 'Confirm Title'
36801	confirm_content (string)		: HTML content for confirm message
36802	confirm_callback (function)		: Callback function for when the confirm button is pressed as opposed to cancel
36803	confirm_cancel_callback (function) : Callback function for when the cancel button is pressed
36804
36805
36806	=== Gallery Options & Events ===
36807	gallery_active_class (string)	: Active class applied to the currently active image or image slide in a gallery 'gallery_active_item'
36808	before_image_change (function)	: Callback function executed before the image slide changes in a gallery modal. Default function( current_item, incoming_item )
36809	after_image_change (function)	: Callback function executed after the image slide changes in a gallery modal. Default function ( current_item )
36810
36811
36812	=== AJAX Options & Events ===
36813	loading_content (string)		: HTML content for loading message. Default 'Loading &hellip;'
36814	loading_class (string)			: Class name to be applied while content is loaded via AJAX. Default 'is_loading'
36815	ajax_error_class (string)		: Class name to be applied when content has failed to load. Default is 'modaal-error'
36816	ajax_success (function)		 	: Callback for when AJAX content is loaded in
36817
36818
36819	=== SOCIAL CONTENT ===
vendor: 13,074 bytes, lines 36820-37225
36820	instagram_id (string)			: Unique photo ID for an Instagram photo.
36821
36822*/
36823( function( $ ) {
36824
36825	var modaal_loading_spinner = '<div class="modaal-loading-spinner"><div><div></div></div><div><div></div></div><div><div></div></div><div><div></div></div><div><div></div></div><div><div></div></div><div><div></div></div><div><div></div></div></div>'
36826
36827	var Modaal = {
36828		init : function(options, elem) {
36829			var self = this;
36830
36831			self.dom = $('body');
36832
36833			self.$elem = $(elem);
36834			self.options = $.extend({}, $.fn.modaal.options, self.$elem.data(), options);
36835			self.xhr = null;
36836
36837			// set up the scope
36838			self.scope = {
36839				is_open: false,
36840				id: 'modaal_' + ( new Date().getTime() ) + ( Math.random().toString(16).substring(2) )
36841			};
36842
36843			// add scope attribute to trigger element
36844			self.$elem.attr('data-modaal-scope', self.scope.id);
36845
36846			// private options
36847			self.private_options = {
36848				active_class: 'is_active'
36849			};
36850
36851			self.lastFocus = null;
36852
36853			// if is_locked
36854			if ( self.options.is_locked || self.options.type == 'confirm' || self.options.hide_close ) {
36855				self.scope.close_btn = '';
36856			} else {
36857				self.scope.close_btn = '<button type="button" class="modaal-close" id="modaal-close" aria-label="' + self.options.close_aria_label + '"><span>' + self.options.close_text + '</span></button>';
36858			}
36859
36860			// reset animation_speed
36861			if (self.options.animation === 'none' ){
36862				self.options.animation_speed = 0;
36863				self.options.after_callback_delay = 0;
36864			}
36865
36866			// On click to open modal
36867			$(elem).on('click.Modaal', function(e) {
36868				e.preventDefault();
36869
36870				var source;
36871
36872				// Save last active state before modal
36873				self.lastFocus = document.activeElement;
36874
36875				if ( self.options.should_open === false || ( typeof self.options.should_open === 'function' && self.options.should_open() === false ) ) {
36876					return;
36877				}
36878
36879				// CB: before_open
36880				self.options.before_open.call(self, e);
36881
36882				switch (self.options.type) {
36883					case 'inline':
36884						self.create_basic();
36885						break;
36886
36887					case 'ajax':
36888						source = self.options.source( self.$elem, self.$elem.attr('href') );
36889						self.fetch_ajax( source );
36890						break;
36891
36892					case 'confirm':
36893						self.options.is_locked = true;
36894						self.create_confirm();
36895						break;
36896
36897					case 'image':
36898						self.create_image();
36899						break;
36900
36901					case 'iframe':
36902						source = self.options.source( self.$elem, self.$elem.attr('href') );
36903						self.create_iframe( source );
36904						break;
36905
36906					case 'video':
36907						self.create_video(self.$elem.attr('href'));
36908						break;
36909
36910					case 'instagram':
36911						self.create_instagram();
36912						break;
36913				}
36914
36915				// call events to be watched (click, tab, keyup, keydown etc.)
36916				self.watch_events();
36917
36918			});
36919
36920
36921			// Check for start_open
36922			if (self.options.start_open === true ){
36923				$(elem).click();
36924			}
36925		},
36926
36927		// Watching Modal
36928		// ----------------------------------------------------------------
36929		watch_events : function() {
36930			var self = this;
36931
36932			self.dom.off('click.Modaal keyup.Modaal keydown.Modaal');
36933
36934			// Body keydown
36935			self.dom.on('keydown.Modaal', function(e) {
36936				var key = e.keyCode;
36937				var target = e.target;
36938
36939				// look for tab change and reset focus to modal window
36940				// done in keydown so the check fires repeatedly when you hold the tab key down
36941				if (key == 9 && self.scope.is_open) {
36942					if (!$.contains(document.getElementById(self.scope.id), target) ) {
36943						$('#' + self.scope.id).find('*[tabindex="0"]').focus();
36944					}
36945				}
36946			});
36947
36948			// Body keyup
36949			self.dom.on('keyup.Modaal', function(e) {
36950				var key = e.keyCode;
36951				var target = e.target;
36952
36953				if ( (e.shiftKey && e.keyCode == 9) && self.scope.is_open) {
36954					// Watch for shift + tab key press. if open shift focus to close button.
36955					if (!$.contains(document.getElementById(self.scope.id), target) ) {
36956						$('#' + self.scope.id).find('.modaal-close').focus();
36957					}
36958				}
36959
36960				if ( !self.options.is_locked ){
36961					// On escape key press close modal
36962					if (key == 27 && self.scope.is_open ) {
36963						if ( $(document.activeElement).is('input:not(:checkbox):not(:radio)') ) {
36964							return false;
36965						}
36966
36967						self.modaal_close();
36968						return;
36969					}
36970				}
36971
36972				// is gallery open and images length is > 1
36973				if ( self.options.type == 'image' ) {
36974					// arrow left for back
36975					if (key == 37 && self.scope.is_open && (!$('#' + self.scope.id + ' .modaal-gallery-prev').hasClass('is_hidden')) ) {
36976						self.gallery_update('prev');
36977					}
36978					// arrow right for next
36979					if (key == 39 && self.scope.is_open && (!$('#' + self.scope.id + ' .modaal-gallery-next').hasClass('is_hidden')) ) {
36980						self.gallery_update('next');
36981					}
36982					return;
36983				}
36984			});
36985
36986			// Body click
36987			self.dom.on('click.Modaal', function(e) {
36988				var trigger = $(e.target);
36989
36990				// General Controls: If it's not locked allow greedy close
36991				if ( !self.options.is_locked ){
36992					if ( (self.options.overlay_close && trigger.is('.modaal-inner-wrapper')) || trigger.is('.modaal-close') || trigger.closest('.modaal-close').length ) {
36993						self.modaal_close();
36994						return;
36995					}
36996				}
36997
36998				//Confirm Controls
36999				if ( trigger.is('.modaal-confirm-btn' ) ){
37000					// if 'OK' button is clicked, run confirm_callback()
37001					if ( trigger.is('.modaal-ok') ) {
37002						self.options.confirm_callback.call(self, self.lastFocus);
37003					}
37004
37005					if ( trigger.is('.modaal-cancel') ) {
37006						self.options.confirm_cancel_callback.call(self, self.lastFocus);
37007					}
37008					self.modaal_close();
37009					return;
37010				}
37011
37012				// Gallery Controls
37013				if ( trigger.is( '.modaal-gallery-control' ) ){
37014					// it not active, don't do nuthin!
37015					if ( trigger.hasClass('is_hidden') ) {
37016						return;
37017					}
37018
37019					// trigger previous
37020					if ( trigger.is('.modaal-gallery-prev') ) {
37021						self.gallery_update('prev');
37022					}
37023					// trigger next
37024					if ( trigger.is('.modaal-gallery-next') ) {
37025						self.gallery_update('next');
37026					}
37027					return;
37028				}
37029			});
37030		},
37031
37032		// Append markup into DOM
37033		build_modal : function(content) {
37034			var self = this;
37035
37036			// if is instagram
37037			var igClass = '';
37038			if ( self.options.type == 'instagram' ) {
37039				igClass = ' modaal-instagram';
37040			}
37041
37042			var wrap_class = (self.options.type == 'video') ? 'modaal-video-wrap' : 'modaal-content';
37043
37044			/*
37045				modaal-start_none : fully hidden via display:none;
37046				modaal-start_fade : hidden via opacity:0
37047				modaal-start_slidedown : ...
37048
37049			*/
37050			var animation_class;
37051			switch ( self.options.animation ) {
37052				case 'fade' :
37053					animation_class = ' modaal-start_fade';
37054					break;
37055				case 'slide-down' :
37056					animation_class = ' modaal-start_slidedown';
37057					break;
37058				default :
37059					animation_class = ' modaal-start_none'
37060			}
37061
37062			// fullscreen check
37063			var fullscreen_class = '';
37064			if ( self.options.fullscreen ) {
37065				fullscreen_class = ' modaal-fullscreen';
37066			}
37067
37068			// custom class check
37069			if ( self.options.custom_class !== '' || typeof(self.options.custom_class) !== 'undefined' ) {
37070				self.options.custom_class = ' ' + self.options.custom_class;
37071			}
37072
37073			// if width and heights exists and is typeof number
37074			var dimensionsStyle = '';
37075			if ( self.options.width && self.options.height && typeof self.options.width == 'number' && typeof self.options.height == 'number' ) {
37076				// if width and height exist, and they are both numbers
37077				dimensionsStyle = ' style="max-width:' + self.options.width + 'px;height:' + self.options.height + 'px;overflow:auto;"';
37078			} else if ( self.options.width && typeof self.options.width == 'number' ) {
37079				// if only width
37080				dimensionsStyle = ' style="max-width:' + self.options.width + 'px;"';
37081			} else if ( self.options.height && typeof self.options.height == 'number' ) {
37082				// if only height
37083				dimensionsStyle = ' style="height:' + self.options.height + 'px;overflow:auto;"';
37084			}
37085
37086			// Reset dimensions style (width and height) for certain types
37087			if ( self.options.type == 'image' || self.options.type == 'video' || self.options.type == 'instagram' || self.options.fullscreen ) {
37088				dimensionsStyle = '';
37089			}
37090
37091			//var build_markup = '<div class="modaal-wrapper modaal-start_fade' + igClass + '" id="' + self.scope.id + '"><div class="modaal-outer-wrapper"><div class="modaal-inner-wrapper">';
37092			var build_markup = '<div class="modaal-wrapper modaal-' + self.options.type + animation_class + igClass + fullscreen_class + self.options.custom_class + '" id="' + self.scope.id + '"><div class="modaal-outer-wrapper"><div class="modaal-inner-wrapper">';
37093
37094					// hide if video
37095					if (self.options.type != 'video') {
37096						build_markup += '<div class="modaal-container"' + dimensionsStyle + '>';
37097					}
37098
37099					// add the guts of the content
37100					build_markup +=	'<div class="' + wrap_class + ' modaal-focus" aria-hidden="false" aria-label="' + self.options.accessible_title + ' (Press escape to close)" role="dialog">';
37101
37102							// If it's inline type, we want to clone content instead of dropping it straight in
37103							if (self.options.type == 'inline') {
37104								build_markup += '<div class="modaal-content-container"></div>';
37105							} else {
37106								// Drop in the content if it's not inline
37107								build_markup +=	content;
37108							}
37109
37110					// close wrap_class
37111					build_markup += '</div>' + self.scope.close_btn;
37112
37113					// hide if video
37114					if (self.options.type != 'video') {
37115						build_markup += '</div>';
37116					}
37117
37118			// close off modaal-wrapper
37119			build_markup +=	'</div></div></div>';
37120
37121			// append ajax modal markup to dom
37122			self.dom.append(build_markup);
37123
37124			// if inline, clone content into space
37125			if (self.options.type == 'inline') {
37126				content.appendTo('#' + self.scope.id + ' .modaal-content-container');
37127			}
37128
37129			// Trigger overlay show (which triggers modal show)
37130			self.modaal_overlay('show');
37131		},
37132
37133		// Create Basic Inline Modal
37134		// ----------------------------------------------------------------
37135		create_basic : function() {
37136			var self = this;
37137			// if $elem is a link, then href points to the target, otherwise assume target was passed in initially
37138			var target = (self.$elem.is('[href]')) ? $(self.$elem.attr('href')) : self.$elem;
37139			var content = '';
37140
37141			if (target.length) {
37142				content = target.contents().clone(true,true);
37143				target.empty();
37144			} else {
37145				content = 'Content could not be loaded. Please check the source and try again.';
37146			}
37147
37148			// now push content into markup
37149			self.build_modal(content);
37150		},
37151
37152		// Create Instagram Modal
37153		// ----------------------------------------------------------------
37154		create_instagram : function() {
37155			var self = this;
37156			var id = self.options.instagram_id;
37157			var content = '';
37158
37159			var error_msg = 'Instagram photo couldn\'t be loaded, please check the embed code and try again.';
37160
37161			self.build_modal('<div class="modaal-content-container' + ( self.options.loading_class != '' ? ' ' + self.options.loading_class : '' ) + '">' + self.options.loading_content + '</div>' );
37162
37163			// ID exists, is not empty null or undefined.
37164			if ( id != '' && id !== null && id !== undefined ) {
37165				// set up oembed url
37166				var ig_url = 'https://api.instagram.com/oembed?url=http://instagr.am/p/' + id + '/';
37167
37168				$.ajax({
37169					url: ig_url,
37170					dataType: "jsonp",
37171					cache: false,
37172					success: function (data) {
37173						// set up the new content
37174						content = data.html;
37175
37176						// now set location for new content
37177						var target = $('#' + self.scope.id + ' .modaal-content-container');
37178						if ( target.length > 0) {
37179							// add HTML into target region
37180							target.removeClass( self.options.loading_class );
37181							target.html(content);
37182
37183							// now trigger an instagram refresh
37184							window.instgrm.Embeds.process();
37185						}
37186					},
37187					error: function() {
37188						content = error_msg;
37189
37190						// now set location for new content
37191						var target = $('#' + self.scope.id + ' .modaal-content-container');
37192						if ( target.length > 0) {
37193							target.removeClass( self.options.loading_class ).addClass( self.options.ajax_error_class );
37194							target.html(content);
37195						}
37196					}
37197				});
37198
37199			} else {
37200				content = error_msg;
37201			}
37202
37203			return false;
37204		},
37205
37206		// Fetch Ajax Data
37207		// ----------------------------------------------------------------
37208		fetch_ajax : function(url) {
37209			var self = this;
37210			var content = '';
37211
37212			// If no accessible title, set it to 'Dialog Window'
37213			if ( self.options.accessible_title == null ) {
37214				self.options.accessible_title = 'Dialog Window'
37215			}
37216
37217			if ( self.xhr !== null ){
37218				self.xhr.abort();
37219				self.xhr = null;
37220			}
37221
37222			self.build_modal('<div class="modaal-content-container' + ( self.options.loading_class != '' ? ' ' + self.options.loading_class : '' ) + '">' + self.options.loading_content + '</div>' );
37223
37224			self.xhr = $.ajax(url, {
37225				success: function(data) {
37226					// content fetch is successful so push it into markup
37227					var target = $('#' + self.scope.id).find('.modaal-content-container');
37228					if ( target.length > 0){
37229						target.removeClass( self.options.loading_class );
37230						target.html( data );
37231
37232						self.options.ajax_success.call(self, target);
37233					}
37234				},
37235				error: function( xhr ) {
37236					// There were some errors so return an error message
37237					if ( xhr.statusText == 'abort' ){
37238						return;
37239					}
37240
37241					var target = $('#' + self.scope.id + ' .modaal-content-container');
37242					if ( target.length > 0){
37243						target.removeClass( self.options.loading_class ).addClass( self.options.ajax_error_class );
37244						target.html( 'Content could not be loaded. Please check the source and try again.' );
37245					}
37246				}
37247			});
37248		},
37249
37250		// Create Confirm Modal
37251		// ----------------------------------------------------------------
37252		create_confirm : function() {
37253			var self = this;
37254			var content;
37255
37256			content = '<div class="modaal-content-container">' +
37257					'<h1 id="modaal-title">' + self.options.confirm_title + '</h1>' +
37258					'<div class="modaal-confirm-content">' + self.options.confirm_content + '</div>' +
37259						'<div class="modaal-confirm-wrap">' +
37260							'<button type="button" class="modaal-confirm-btn modaal-ok" aria-label="Confirm">' + self.options.confirm_button_text + '</button>' +
37261							'<button type="button" class="modaal-confirm-btn modaal-cancel" aria-label="Cancel">' + self.options.confirm_cancel_button_text + '</button>' +
37262						'</div>' +
37263					'</div>' +
37264				'</div>';
37265
37266			// now push content into markup
37267			self.build_modal(content);
37268		},
37269
37270		// Create Image/Gallery Modal
37271		// ----------------------------------------------------------------
37272		create_image : function() {
37273			var self = this;
37274			var content;
37275
37276			var modaal_image_markup = '';
37277			var gallery_total;
37278			var prev_btn = '<button type="button" class="modaal-gallery-control modaal-gallery-prev" id="modaal-gallery-prev" aria-label="Previous image (use left arrow to change)"><span>Previous Image</span></button>';
37279			var next_btn = '<button type="button" class="modaal-gallery-control modaal-gallery-next" id="modaal-gallery-next" aria-label="Next image (use right arrow to change)"><span>Next Image</span></button>';
37280
37281			// If has rel attribute
37282			if ( self.$elem.is('[rel]') ) {
37283				// find gallery rel
37284				var gallery_group = self.$elem.attr('rel');
37285				var gallery_group_items = $('[rel="' + gallery_group + '"]');
37286
37287				// remove any previous active attribute to any in the group
37288				gallery_group_items.removeAttr('data-gallery-active', 'is_active');
37289				// add active attribute to the item clicked
37290				self.$elem.attr('data-gallery-active', 'is_active');
37291
37292				// how many in the rel grouping are there (-1 to connect with each function starting with 0)
37293				gallery_total = gallery_group_items.length - 1;
37294
37295				// prepare array for gallery data
37296				var gallery = [];
37297
37298				// start preparing markup
37299				modaal_image_markup = '<div class="modaal-gallery-item-wrap">';
37300
37301				// loop each grouping item and push it into our gallery array
37302				gallery_group_items.each(function(i, item) {
37303					// setup default content
37304					var img_src = '';
37305					var img_alt = '';
37306					var img_description = '';
37307					var img_active = false;
37308
37309					var data_modaal_desc = item.getAttribute('data-modaal-desc');
37310					var data_item_active = item.getAttribute('data-gallery-active');
37311
37312					// is it an img SRC or link HREF value
37313					if ( item.href !== '' || item.href !== undefined ) {
37314						img_src = item.href;
37315					} else if ( item.src !== '' || item.src !== undefined ) {
37316						img_src = item.src;
37317					}
37318
37319					// Does it have a modaal description
37320					if ( data_modaal_desc != '' && data_modaal_desc !== null && data_modaal_desc !== undefined ) {
37321						img_alt = data_modaal_desc;
37322						img_description = '<div class="modaal-gallery-label"><span class="modaal-accessible-hide">Image ' + (i+1) + ' - </span>' + data_modaal_desc + '</div>'
37323					} else {
37324						img_description = '<div class="modaal-gallery-label"><span class="modaal-accessible-hide">Image ' + (i+1) + '</span></div>';
37325					}
37326
37327					// is it the active item
37328					if ( data_item_active ) {
37329						img_active = true
37330					}
37331
37332					// set new object for values we want
37333					var gallery_item = {
37334						'url': img_src,
37335						'alt': img_alt,
37336						'rawdesc': data_modaal_desc,
37337						'desc': img_description,
37338						'active': img_active
37339					};
37340
37341					// push object into gallery array
37342					gallery.push( gallery_item );
37343				});
37344
37345				// now loop through all items in the gallery and build up the markup
37346				for (var i = 0; i < gallery.length; i++) {
37347					// Set default active class, then check if array item active is true and update string for class
37348					var is_active = '';
37349					var aria_label = gallery[i].rawdesc ? 'Image: ' + gallery[i].rawdesc : 'Image ' + i + ' no description';
37350
37351					if ( gallery[i].active ) {
37352						is_active = ' ' + self.private_options.active_class;
37353					}
37354
37355					// for each item build up the markup
37356					modaal_image_markup += '<div class="modaal-gallery-item gallery-item-' + i + is_active + '" aria-label="' + aria_label + '">' +
37357						'<img src="' + gallery[i].url + '" alt=" " style="width:100%">' +
37358						gallery[i].desc +
37359					'</div>';
37360				}
37361
37362				// close off the markup for the gallery and add next/previous buttons
37363				modaal_image_markup += '</div>' + prev_btn + next_btn;
37364			} else {
37365				// This is only a single gallery item so let's grab the necessary values
37366
37367				// Setup selected image
37368				var this_img_src = self.$elem.attr('href');
37369				var this_img_alt_txt = '';
37370				var this_img_alt = '';
37371				var aria_label = '';
37372
37373				if ( self.$elem.attr('data-modaal-desc') ) {
37374					aria_label = self.$elem.attr('data-modaal-desc');
37375					this_img_alt_txt = self.$elem.attr('data-modaal-desc');
37376					this_img_alt = '<div class="modaal-gallery-label"><span class="modaal-accessible-hide">Image - </span>' + this_img_alt_txt + '</div>';
37377				} else {
37378					aria_label = "Image with no description";
37379				}
37380
37381				// build up the html
37382				modaal_image_markup = '<div class="modaal-gallery-item is_active" aria-label="' + aria_label + '">' +
37383					'<img src="' + this_img_src + '" alt=" " style="width:100%">' +
37384					this_img_alt +
37385				'</div>';
37386			}
37387
37388			// Update content variable
37389			content = modaal_image_markup;
37390
37391			// now push content into markup
37392			self.build_modal(content);
37393
37394			// setup next & prev buttons
37395			if ( $('.modaal-gallery-item.is_active').is('.gallery-item-0') ) {
37396				$('.modaal-gallery-prev').hide();
37397			}
37398			if ( $('.modaal-gallery-item.is_active').is('.gallery-item-' + gallery_total) ) {
37399				$('.modaal-gallery-next').hide();
37400			}
37401		},
37402
37403		// Gallery Change Image
37404		// ----------------------------------------------------------------
37405		gallery_update : function(direction) {
37406			var self = this;
37407			var this_gallery = $('#' + self.scope.id);
37408			var this_gallery_item = this_gallery.find('.modaal-gallery-item');
37409			var this_gallery_total = this_gallery_item.length - 1;
37410
37411			// if single item, don't proceed
37412			if ( this_gallery_total == 0 ) {
37413				return false;
37414			}
37415
37416			var prev_btn = this_gallery.find('.modaal-gallery-prev'),
37417				next_btn = this_gallery.find('.modaal-gallery-next');
37418
37419			var duration = 250;
37420
37421			var new_img_w = 0,
37422				new_img_h = 0;
37423
vendor: 8,985 bytes, lines 37424-37686
37424			// CB: Before image change
37425			var current_item = this_gallery.find( '.modaal-gallery-item.' + self.private_options.active_class ),
37426				incoming_item = ( direction == 'next' ? current_item.next( '.modaal-gallery-item' ) : current_item.prev( '.modaal-gallery-item' ) );
37427			self.options.before_image_change.call(self, current_item, incoming_item);
37428
37429			// stop change if at start of end
37430			if ( direction == 'prev' && this_gallery.find('.gallery-item-0').hasClass('is_active') ) {
37431				return false;
37432			} else if ( direction == 'next' && this_gallery.find('.gallery-item-' + this_gallery_total).hasClass('is_active') ) {
37433				return false;
37434			}
37435
37436
37437			// lock dimensions
37438			current_item.stop().animate({
37439				opacity: 0
37440			}, duration, function(){
37441				// Move to appropriate image
37442				incoming_item.addClass('is_next').css({
37443					'position': 'absolute',
37444					'display': 'block',
37445					'opacity': 0
37446				});
37447
37448				// Collect doc width
37449				var doc_width = $(document).width();
37450				var width_threshold = doc_width > 1140 ? 280 : 50;
37451
37452				// start toggle to 'is_next'
37453				new_img_w = this_gallery.find('.modaal-gallery-item.is_next').width();
37454				new_img_h = this_gallery.find('.modaal-gallery-item.is_next').height();
37455
37456				var new_natural_w = this_gallery.find('.modaal-gallery-item.is_next img').prop('naturalWidth');
37457				var new_natural_h = this_gallery.find('.modaal-gallery-item.is_next img').prop('naturalHeight');
37458
37459				// if new image is wider than doc width
37460				if ( new_natural_w > (doc_width - width_threshold) ) {
37461					// set new width just below doc width
37462					new_img_w = doc_width - width_threshold;
37463
37464					// Set temp widths so we can calulate the correct height;
37465					this_gallery.find('.modaal-gallery-item.is_next').css({ 'width': new_img_w });
37466					this_gallery.find('.modaal-gallery-item.is_next img').css({ 'width': new_img_w });
37467
37468					// Set new height variable
37469					new_img_h = this_gallery.find('.modaal-gallery-item.is_next').find('img').height();
37470				} else {
37471					// new img is not wider than screen, so let's set the new dimensions
37472					new_img_w = new_natural_w;
37473					new_img_h = new_natural_h;
37474				}
37475
37476				// resize gallery region
37477				this_gallery.find('.modaal-gallery-item-wrap').stop().animate({
37478					'width': new_img_w,
37479					'height': new_img_h
37480				}, duration, function() {
37481					// hide old active image
37482					current_item.removeClass(self.private_options.active_class + ' ' + self.options.gallery_active_class).removeAttr('style');
37483					current_item.find('img').removeAttr('style');
37484
37485					// show new image
37486					incoming_item.addClass(self.private_options.active_class + ' ' + self.options.gallery_active_class).removeClass('is_next').css('position','');
37487
37488					// animate in new image (now has the normal is_active class
37489					incoming_item.stop().animate({
37490						opacity: 1
37491					}, duration, function(){
37492						$(this).removeAttr('style').css({
37493							'width': '100%'
37494						});
37495						$(this).find('img').css('width', '100%');
37496
37497						// remove dimension lock
37498						this_gallery.find('.modaal-gallery-item-wrap').removeAttr('style');
37499
37500						// CB: After image change
37501						self.options.after_image_change.call( self, incoming_item );
37502					});
37503
37504					// Focus on the new gallery item
37505					this_gallery.find('.modaal-gallery-item').removeAttr('tabindex');
37506					this_gallery.find('.modaal-gallery-item.' + self.private_options.active_class + '').attr('tabindex', '0').focus();
37507
37508					// hide/show next/prev
37509					if ( this_gallery.find('.modaal-gallery-item.' + self.private_options.active_class).is('.gallery-item-0') ) {
37510						prev_btn.stop().animate({
37511							opacity: 0
37512						}, 150, function(){
37513							$(this).hide();
37514						});
37515					} else {
37516						prev_btn.stop().css({
37517							'display': 'block',
37518							'opacity': prev_btn.css('opacity')
37519						}).animate({
37520							opacity: 1
37521						}, 150);
37522					}
37523					if ( this_gallery.find('.modaal-gallery-item.' + self.private_options.active_class).is('.gallery-item-' + this_gallery_total) ) {
37524						next_btn.stop().animate({
37525							opacity: 0
37526						}, 150, function(){
37527							$(this).hide();
37528						});
37529					} else {
37530						next_btn.stop().css({
37531							'display': 'block',
37532							'opacity': prev_btn.css('opacity')
37533						}).animate({
37534							opacity: 1
37535						}, 150);
37536					}
37537				});
37538			});
37539		},
37540
37541		// Create Video Modal
37542		// ----------------------------------------------------------------
37543		create_video : function(url) {
37544			var self = this;
37545			var content;
37546
37547			// video markup
37548			content = '<iframe src="' + url + '" class="modaal-video-frame" frameborder="0" allowfullscreen></iframe>';
37549
37550			// now push content into markup
37551			self.build_modal('<div class="modaal-video-container">' + content + '</div>');
37552		},
37553
37554		// Create iFrame Modal
37555		// ----------------------------------------------------------------
37556		create_iframe : function(url) {
37557			var self = this;
37558			var content;
37559
37560			if ( self.options.width !== null || self.options.width !== undefined || self.options.height !== null || self.options.height !== undefined ) {
37561				// video markup
37562				content = '<iframe src="' + url + '" class="modaal-iframe-elem" frameborder="0" allowfullscreen></iframe>';
37563			} else {
37564				content = '<div class="modaal-content-container">Please specify a width and height for your iframe</div>';
37565			}
37566
37567			// now push content into markup
37568			self.build_modal(content);
37569		},
37570
37571		// Open Modaal
37572		// ----------------------------------------------------------------
37573		modaal_open : function() {
37574			var self = this;
37575			var modal_wrapper = $( '#' + self.scope.id );
37576			var animation_type = self.options.animation;
37577
37578			if (animation_type === 'none' ){
37579				modal_wrapper.removeClass('modaal-start_none');
37580				self.options.after_open.call(self, modal_wrapper);
37581			}
37582
37583			// Open with fade
37584			if (animation_type === 'fade') {
37585				modal_wrapper.removeClass('modaal-start_fade');
37586			}
37587
37588			// Open with slide down
37589			if (animation_type === 'slide-down') {
37590				modal_wrapper.removeClass('modaal-start_slide_down');
37591			}
37592
37593			var focusTarget = modal_wrapper;
37594
37595			// Switch focusTarget tabindex (switch from other modal if exists)
37596			$('.modaal-wrapper *[tabindex=0]').removeAttr('tabindex');
37597
37598			if ( self.options.type == 'image' ) {
37599				focusTarget = $('#' + self.scope.id).find('.modaal-gallery-item.' + self.private_options.active_class);
37600
37601			} else if ( modal_wrapper.find('.modaal-iframe-elem').length ) {
37602				focusTarget = modal_wrapper.find('.modaal-iframe-elem');
37603
37604			} else if ( modal_wrapper.find('.modaal-video-wrap').length ) {
37605				focusTarget = modal_wrapper.find('.modaal-video-wrap');
37606
37607			} else {
37608				focusTarget = modal_wrapper.find('.modaal-focus');
37609
37610			}
37611
37612			// now set the focus
37613			focusTarget.attr('tabindex', '0').focus();
37614
37615			// Run after_open
37616			if (animation_type !== 'none') {
37617				// CB: after_open
37618				setTimeout(function() {
37619					self.options.after_open.call(self, modal_wrapper)
37620				}, self.options.after_callback_delay);
37621			}
37622		},
37623
37624		// Close Modal
37625		// ----------------------------------------------------------------
37626		modaal_close : function() {
37627			var self = this;
37628			var modal_wrapper = $( '#' + self.scope.id );
37629
37630			// CB: before_close
37631			self.options.before_close.call(self, modal_wrapper);
37632
37633			if (self.xhr !== null){
37634				self.xhr.abort();
37635				self.xhr = null;
37636			}
37637
37638			// Now we close the modal
37639			if (self.options.animation === 'none' ){
37640				modal_wrapper.addClass('modaal-start_none');
37641			}
37642
37643			// Close with fade
37644			if (self.options.animation === 'fade') {
37645				modal_wrapper.addClass('modaal-start_fade');
37646			}
37647
37648			// Close with slide up (using initial slide down)
37649			if (self.options.animation === 'slide-down') {
37650				modal_wrapper.addClass('modaal-start_slide_down');
37651			}
37652
37653			// CB: after_close and remove
37654			setTimeout(function() {
37655				// clone inline content back to origin place
37656				if (self.options.type == 'inline') {
37657					$('#' + self.scope.id + ' .modaal-content-container').contents().clone(true,true).appendTo( self.$elem.attr('href') )
37658				}
37659				// remove markup from dom
37660				modal_wrapper.remove();
37661				// CB: after_close
37662				self.options.after_close.call(self);
37663				// scope is now closed
37664				self.scope.is_open = false;
37665
37666			}, self.options.after_callback_delay);
37667
37668			// Call overlay hide
37669			self.modaal_overlay('hide');
37670
37671			// Roll back to last focus state before modal open. If was closed programmatically, this might not be set
37672			if (self.lastFocus != null) {
37673				self.lastFocus.focus();
37674			}
37675		},
37676
37677		// Overlay control (accepts action for show or hide)
37678		// ----------------------------------------------------------------
37679		modaal_overlay : function(action) {
37680			var self = this;
37681
37682			if (action == 'show') {
37683				// Modal is open so update scope
37684				self.scope.is_open = true;
37685
37686				// set body to overflow hidden if background_scroll is false
37687				if (! self.options.background_scroll) {
37688					self.dom.addClass('modaal-noscroll');
37689				}
37690
37691				// append modaal overlay
37692				self.dom.append('<div class="modaal-overlay" id="' + self.scope.id + '_overlay"></div>');
37693
37694				// now show
37695				$('#' + self.scope.id + '_overlay').css('background', self.options.background).stop().animate({
37696					opacity: self.options.overlay_opacity
37697				}, self.options.animation_speed, function(){
37698					// now open the modal
37699					self.modaal_open();
37700				});
37701
37702			} else if (action == 'hide') {
37703				// remove body overflow lock
37704				self.dom.removeClass('modaal-noscroll');
37705
37706				// now hide the overlay
37707				$('#' + self.scope.id + '_overlay').stop().animate({
37708					opacity: 0
37709				}, self.options.animation_speed, function(){
37710					// remove overlay from dom
37711					$(this).remove();
37712				});
37713			}
37714		}
37715	};
37716
37717	// Declare the modaal jQuery method
37718	// ------------------------------------------------------------
37719	$.fn.modaal = function(options) {
37720		return this.each(function () {
37721			var existing_modaal = $(this).data('modaal');
37722
37723			if ( existing_modaal ){
37724				// Checking for string value, used for methods
37725				if (typeof(options) == 'string'){
37726					switch (options) {
37727						case 'close':
37728							existing_modaal.modaal_close();
37729							break;
37730					}
37731				}
37732			} else {
37733				// Not a string, so let's setup the modal ready to use
37734				var modaal = Object.create(Modaal);
37735				modaal.init(options, this);
37736				$.data(this, "modaal", modaal);
37737			}
37738		});
37739	};
37740
37741	// Default options
37742	// ------------------------------------------------------------
37743	$.fn.modaal.options = {
37744
37745		//General
37746		type : 'inline',
37747		animation : 'fade',
37748		animation_speed : 300,
37749		after_callback_delay : 350,
37750		is_locked : false,
37751		hide_close: false,
37752		background: '#000',
37753		overlay_opacity: '0.8',
37754		overlay_close: true,
37755		accessible_title: 'Dialog Window',
37756		start_open: false,
37757		fullscreen: false,
37758		custom_class: '',
37759		background_scroll: false,
37760		should_open: true,
37761		close_text: 'Close',
37762		close_aria_label: 'Close (Press escape to close)',
37763		width: null,
37764		height: null,
37765
37766		//Events
37767		before_open : function(){},
37768		after_open : function(){},
37769		before_close : function(){},
37770		after_close : function(){},
37771		source : function( element, src ){
37772			return src;
37773		},
37774
37775		//Confirm Modal
37776		confirm_button_text: 'Confirm', // text on confirm button
37777		confirm_cancel_button_text: 'Cancel',
37778		confirm_title: 'Confirm Title', // title for confirm modal
37779		confirm_content: '<p>This is the default confirm dialog content. Replace me through the options</p>', // html for confirm message
37780		confirm_callback: function() {},
37781		confirm_cancel_callback: function() {},
37782
37783
37784		//Gallery Modal
37785		gallery_active_class: 'gallery_active_item',
37786		before_image_change: function( current_item, incoming_item ) {},
37787		after_image_change: function( current_item ) {},
37788
37789		//Ajax Modal
37790		loading_content : modaal_loading_spinner,
37791		loading_class : 'is_loading',
37792		ajax_error_class : 'modaal-error',
37793		ajax_success : function(){},
37794
37795		//Instagram
37796		instagram_id : null
37797	};
37798
37799	// On body load (or now, if already loaded), init any modaals defined inline
37800	// Ensure this is done after $.fn.modaal and default options are declared
37801	// ----------------------------------------------------------------
37802	$(function(){
37803		var single_modaal = $('.modaal');
37804
37805		if ( single_modaal.length ) {
37806			single_modaal.each(function() {
37807				var self = $(this);
37808
37809				// new empty options
37810				var options = {};
37811				var inline_options = false;
37812
37813				// option: type
37814				if ( self.attr('data-modaal-type') ) {
37815					inline_options = true;
37816					options.type = self.attr('data-modaal-type');
37817				}
37818
37819				// option: animation
37820				if ( self.attr('data-modaal-animation') ) {
37821					inline_options = true;
37822					options.animation = self.attr('data-modaal-animation');
37823				}
37824
37825				// option: animation_speed
37826				if ( self.attr('data-modaal-animation-speed') ) {
37827					inline_options = true;
37828					options.animation_speed = self.attr('data-modaal-animation-speed');
37829				}
37830
37831				// option: after_callback_delay
37832				if ( self.attr('data-modaal-after-callback-delay') ) {
37833					inline_options = true;
37834					options.after_callback_delay = self.attr('data-modaal-after-callback-delay');
37835				}
37836
37837				// option: after_callback_delay
37838				if ( self.attr('data-modaal-is-locked') ) {
37839					inline_options = true;
37840					options.is_locked = (self.attr('data-modaal-is-locked') === 'true' ? true : false);
37841				}
37842
37843				// option: hide_close
37844				if ( self.attr('data-modaal-hide-close') ) {
37845					inline_options = true;
37846					options.hide_close = (self.attr('data-modaal-hide-close') === 'true' ? true : false);
37847				}
37848
37849				// option: background
37850				if ( self.attr('data-modaal-background') ) {
37851					inline_options = true;
37852					options.background = self.attr('data-modaal-background');
37853				}
37854
37855				// option: overlay_opacity
37856				if ( self.attr('data-modaal-overlay-opacity') ) {
37857					inline_options = true;
37858					options.overlay_opacity = self.attr('data-modaal-overlay-opacity');
37859				}
37860
37861				// option: overlay_close
37862				if ( self.attr('data-modaal-overlay-close') ) {
37863					inline_options = true;
37864					options.overlay_close = (self.attr('data-modaal-overlay-close') === 'false' ? false : true);
37865				}
37866
37867				// option: accessible_title
37868				if ( self.attr('data-modaal-accessible-title') ) {
37869					inline_options = true;
37870					options.accessible_title = self.attr('data-modaal-accessible-title');
37871				}
37872
37873				// option: start_open
37874				if ( self.attr('data-modaal-start-open') ) {
37875					inline_options = true;
37876					options.start_open = (self.attr('data-modaal-start-open') === 'true' ? true : false);
37877				}
37878
37879				// option: fullscreen
37880				if ( self.attr('data-modaal-fullscreen') ) {
37881					inline_options = true;
37882					options.fullscreen = (self.attr('data-modaal-fullscreen') === 'true' ? true : false);
37883				}
37884
37885				// option: custom_class
37886				if ( self.attr('data-modaal-custom-class') ) {
37887					inline_options = true;
37888					options.custom_class = self.attr('data-modaal-custom-class');
37889				}
37890
37891				// option: close_text
37892				if ( self.attr('data-modaal-close-text') ) {
37893					inline_options = true;
37894					options.close_text = self.attr('data-modaal-close-text');
37895				}
37896
37897				// option: close_aria_label
37898				if ( self.attr('data-modaal-close-aria-label') ) {
37899					inline_options = true;
37900					options.close_aria_label = self.attr('data-modaal-close-aria-label');
37901				}
37902
37903				// option: background_scroll
37904				if ( self.attr('data-modaal-background-scroll') ) {
37905					inline_options = true;
37906					options.background_scroll = (self.attr('data-modaal-background-scroll') === 'true' ? true : false);
37907				}
37908
37909				// option: width
37910				if ( self.attr('data-modaal-width') ) {
37911					inline_options = true;
37912					options.width = parseInt( self.attr('data-modaal-width') );
37913				}
37914
37915				// option: height
37916				if ( self.attr('data-modaal-height') ) {
37917					inline_options = true;
37918					options.height = parseInt( self.attr('data-modaal-height') );
37919				}
37920
37921				// option: confirm_button_text
37922				if ( self.attr('data-modaal-confirm-button-text') ) {
37923					inline_options = true;
37924					options.confirm_button_text = self.attr('data-modaal-confirm-button-text');
37925				}
37926
37927				// option: confirm_cancel_button_text
37928				if ( self.attr('data-modaal-confirm-cancel-button-text') ) {
37929					inline_options = true;
37930					options.confirm_cancel_button_text = self.attr('data-modaal-confirm-cancel-button-text');
37931				}
37932
37933				// option: confirm_title
37934				if ( self.attr('data-modaal-confirm-title') ) {
37935					inline_options = true;
37936					options.confirm_title = self.attr('data-modaal-confirm-title');
37937				}
37938
37939				// option: confirm_content
37940				if ( self.attr('data-modaal-confirm-content') ) {
37941					inline_options = true;
37942					options.confirm_content = self.attr('data-modaal-confirm-content');
37943				}
37944
37945				// option: gallery_active_class
37946				if ( self.attr('data-modaal-gallery-active-class') ) {
37947					inline_options = true;
37948					options.gallery_active_class = self.attr('data-modaal-gallery-active-class');
37949				}
37950
37951				// option: loading_content
37952				if ( self.attr('data-modaal-loading-content') ) {
37953					inline_options = true;
37954					options.loading_content = self.attr('data-modaal-loading-content');
37955				}
37956
37957				// option: loading_class
37958				if ( self.attr('data-modaal-loading-class') ) {
37959					inline_options = true;
37960					options.loading_class = self.attr('data-modaal-loading-class');
37961				}
37962
37963				// option: ajax_error_class
37964				if ( self.attr('data-modaal-ajax-error-class') ) {
37965					inline_options = true;
37966					options.ajax_error_class = self.attr('data-modaal-ajax-error-class');
37967				}
37968
37969				// option: start_open
37970				if ( self.attr('data-modaal-instagram-id') ) {
37971					inline_options = true;
37972					options.instagram_id = self.attr('data-modaal-instagram-id');
37973				}
37974
37975				// now set it up for the trigger, but only if inline_options is true
37976				if ( inline_options ) {
37977					self.modaal(options);
37978				}
37979			});
37980		}
37981	});
37982
37983} ( jQuery, window, document ) );
37984;
37985/// <reference path="../_references.js" />
37986
37987Agility.RegisterNamespace("APP.Core");
37988Agility.RegisterNamespace("APP.Data");
37989Agility.RegisterNamespace("APP.ViewModels");
37990Agility.RegisterNamespace("APP.Router");
37991
37992var CORE = APP.Core,
37993    VM = APP.ViewModels,
37994    DATA = APP.Data
37995
37996/////////////////////////
37997//UTILITIES
37998/////////////////////////
37999
38000
38001CORE.Keys = {
38002    AgilityPageAPIBasePath: '/AgilityPage/GetPage?path='
38003};
38004
38005CORE.DateFormatString = {
38006    //DateWithTime: 'MMMM Do YYYY, h:mm:ss a', // August 4th 2016, 8:29:34 am,
38007    //DateOnly: "MMM Do YY", // Aug 4th 16 
38008    //DateTimeCompact: 'MM/DD/YY h:mm a' //08/04/2016 8:29 am
38009};
38010
38011CORE.RegEx = {
38012    //FirstAndLastName: /^[a-z ,.'-]+$/i,
38013    //PostalZipCode: /^[ABCEGHJKLMNPRSTVXY][0-9][ABCEGHJKLMNPRSTVWXYZ][0-9][ABCEGHJKLMNPRSTVWXYZ][0-9]$|^\d{5}(?:[-\s]\d{4})?$/i
38014};
38015
38016CORE.MakeFriendlyString = function (s) {
38017    if (s) {
38018        var r = s.toLowerCase();
38019        r = r.replace(new RegExp("\\s", 'g'), "-");
38020        r = r.replace(new RegExp("[àáâãäå]", 'g'), "a");
38021        r = r.replace(new RegExp("æ", 'g'), "ae");
38022        r = r.replace(new RegExp("ç", 'g'), "c");
38023        r = r.replace(new RegExp("[èéêë]", 'g'), "e");
38024        r = r.replace(new RegExp("[ìíîï]", 'g'), "i");
38025        r = r.replace(new RegExp("ñ", 'g'), "n");
38026        r = r.replace(new RegExp("[òóôõö]", 'g'), "o");
38027        r = r.replace(new RegExp("œ", 'g'), "oe");
38028        r = r.replace(new RegExp("[ùúûü]", 'g'), "u");
38029        r = r.replace(new RegExp("[ýÿ]", 'g'), "y");
38030
38031        r = r.replace(new RegExp("[^\\w\\-@-]", 'g'), "-");
38032        r = r.replace(new RegExp("--+", 'g'), "-");
38033
38034
38035        if (r.lastIndexOf("-") > 0 && r.lastIndexOf("-") == r.length - 1) {
38036            r = r.substring(0, r.length - 1);
38037        }
38038    }
38039
38040    return r;
38041};
38042
38043
38044CORE.GetQueryVariable = function (variable) {
38045    var query = window.location.search.substring(1);
38046    var vars = query.split("&");
38047    for (var i = 0; i < vars.length; i++) {
38048        var pair = vars[i].split("=");
38049        if (pair[0] == variable) { return pair[1]; }
38050    }
38051    return (false);
38052}
38053
38054CORE.Post = function (url, data, callback, errorCallback, alwaysCallback) {
38055    return $.post(url, data, null, "json")
38056		.success(function (result) {
38057		    if (callback)
38058		        callback(result);
38059		})
38060		.fail(function (err, status, errorMessage) {
38061		    if (errorCallback != undefined && $.isFunction(errorCallback)) {
38062		        errorCallback(err, status, errorMessage);
38063		    }
38064		})
38065		.always(function () {
38066		    if (alwaysCallback != undefined && $.isFunction(alwaysCallback)) {
38067		        alwaysCallback();
38068		    }
38069		});
38070};
38071
38072CORE.Get = function (url, data, callback, errorCallback, alwaysCallback) {
38073    return $.get(url, data, null, "json")
38074		.success(function (result) {
38075		    if (callback)
38076		        callback(result);
38077		})
38078		.fail(function (err, status, errorMessage) {
38079		    if (errorCallback != undefined && $.isFunction(errorCallback)) {
38080		        errorCallback(err, status, errorMessage);
38081		    }
38082		})
38083		.always(function () {
38084		    if (alwaysCallback != undefined && $.isFunction(alwaysCallback)) {
38085		        alwaysCallback();
38086		    }
38087		});
38088};
38089
38090CORE.ValidateForm = function (formElem) {
38091    var $form;
38092
38093    $form = (formElem instanceof jQuery) ? formElem : $(formElem);
38094
38095    if (!$form.parsley().validate()) {
38096        return false;
38097    }
38098
38099    return true;
38100}
38101
38102;
38103/// <reference path="../_references.js" />
38104var CORE = APP.Core,
38105    VM = APP.ViewModels,
38106    DATA = APP.Data;
38107
38108DATA.Sample = {
38109    GetSomething: function (callback) {
38110        var postData = {
38111            something: 'something'
38112        }
38113        APP.Core.Post('/some-url', postData, function () {
38114            //on success
38115        },
38116            function () {
38117                //on error
38118            },
38119            function () {
38120                //always do this...
38121
38122                if ($.isFunction(callback)) {
38123                    callback();
38124                }
38125            });
38126    }
38127}
38128
38129DATA.Agility = {
38130    GetPage: function (pagePath) {
38131
38132        APP.clientPageRequest(pagePath);
38133
38134    }
38135}
38136
38137
38138
38139
38140;
38141var VM = APP.ViewModels;
38142
38143VM.RouterModel = function () {
38144    var self = this;
38145
38146    self.sammyApp = null;
38147    self.maxRedirectCount = 3;
38148    self.redirectCount = 0;
38149    self.languageCodeInPath = true;
38150    self.allLanguages = _serverContext.AllLanguages;
38151    self.currentLanguageCode = _serverContext.LanguageCode;
38152    self.initialLoad = true;
38153    self.forceUpdate = false;
38154    self.lastPath = ko.observable(null);
38155    self.modals = _serverContext.Modals;
38156    self.pages = _serverContext.Pages;
38157
38158    self.scheduledTimerID = ko.observable(0);
38159
38160    self.RouteNames = {
38161        //Checkout: {
38162        //    Checkout: 'Checkout-Checkout',
38163        //    Shipping: 'Checkout-Shipping',
38164        //    Review: 'Checkout-Review',
38165        //    Payment: 'Checkout-Payment',
38166        //    Confirmation: 'Checkout-Confirmation'
38167        //},
38168        //MyAccount: {
38169        //    Manager: 'MyAccount-Manager',
38170        //    Contact: 'MyAccount-Contact',
38171        //    Billing: 'MyAccount-Billing',
38172        //    Orders: 'MyAccount-Orders',
38173        //    Security: 'MyAccount-Security'
38174        //}
38175    };
38176};
38177
38178///
38179//proto
38180///
38181ko.utils.extend(VM.RouterModel.prototype, {
38182    redirect: function (path) {
38183        var ROUTER = this;
38184        //ensure there isn't too many redirects accidentally
38185        if (ROUTER.redirectCount < ROUTER.maxRedirectCount) {
38186            ROUTER.redirectCount++;
38187
38188            ROUTER.sammyApp.setLocation(path);
38189        }
38190    },
38191    setupRoutes: function () {
38192
38193        var ROUTER = this;
38194
38195        ROUTER.sammyApp = new Sammy(function() {
38196
38197            ////////////////////////////////////////////////////////////////////////////////////////////////////////
38198            /// BEFORE
38199            ////////////////////////////////////////////////////////////////////////////////////////////////////////
38200
38201
38202            //MATCH all get requests = /.*/
38203            this.before(/.*/,
38204                function(context) {
38205
38206                    if (ROUTER.forceUpdate) {
38207                        ROUTER.forceUpdate = false;
38208                        return;
38209                    }
38210
38211                    if (ROUTER.lastPath() != null) {
38212
38213                        var incomingPath = context.path;
38214                        var incomingParts = incomingPath.split('/');
38215                        var lastPath = ROUTER.lastPath.peek();
38216
38217                        ///////////////////////////////////////////////////////////////////////////////////////////////////
38218                        /// KEEP LANGUAGE CODE IN PATH
38219                        ///////////////////////////////////////////////////////////////////////////////////////////////////
38220
38221                        //HACK: don't handle the language code because it messes up the "History" of the user and they can't press back...
38222                        //if (ROUTER.languageCodeInPath) {
38223                        //    //ensure we keep the language code in the path at all times
38224
38225                        //    //look for /en-ca/{path}
38226                        //    var langCodePart = incomingParts[1];
38227
38228                        //    if (langCodePart != ROUTER.currentLanguageCode) {
38229                        //        //there is no language code in the incoming path, add it and redirect!
38230                        //        var incomingPathWithLanguageCode = "/" + ROUTER.currentLanguageCode + incomingPath;
38231                        //        ROUTER.redirect(incomingPathWithLanguageCode);
38232                        //        return false;
38233                        //    }
38234                        //}
38235
38236                        ////////////////////////////////////////////////////////////////////////////////////////////////////
38237                        /// KEEP PATH ON # ANCHOR 
38238                        /// if the incoming route is just a variation of a hash with the same path then don't reload the page
38239                        ////////////////////////////////////////////////////////////////////////////////////////////////////
38240
38241                        //let modals go through
38242                        if (incomingPath.indexOf('#/m/') > -1) {
38243                            return;
38244                        }
38245
38246                        var incomingPathNoHash = incomingPath;
38247                        var lastPathNoHash = lastPath;
38248
38249                        if (incomingPath.indexOf('#') > -1) {
38250                            incomingPathNoHash = incomingPath.substr(0, incomingPath.indexOf('#'));
38251                        }
38252
38253                        if (lastPath.indexOf('#') > -1) {
38254                            lastPathNoHash = lastPath.substr(0, lastPath.indexOf('#'));
38255                        }
38256
38257                        if (incomingPathNoHash == lastPathNoHash) {
38258                            return false;
38259                        }
38260
38261                    }
38262
38263                });
38264
38265            //////////////////////////////////////////////////////////////////////////////////////////////////////
38266            /// HANDLE ROUTES
38267            //////////////////////////////////////////////////////////////////////////////////////////////////////
38268
38269            //MODALS
38270            // -- Offers
38271            //this.get(ROUTER.modals.OfferDetailsPath + ':code', function (context) {
38272
38273            //    if (context.params.code) {
38274            //        ROUTER.getModal.Offer(context.params.code);
38275            //    }
38276
38277            //});
38278
38279            //CATCH ALL
38280            this.get(/.*/,
38281                function(context) {
38282
38283                    if (!ROUTER.initialLoad) {
38284
38285                        ROUTER.getPage(context.path);
38286                    }
38287
38288                    //reset the redirect count
38289                    ROUTER.redirectCount = 0;
38290
38291                });
38292
38293            // Override this function so that Sammy doesn't mess with forms
38294            this._checkFormSubmission = function(form) {
38295                return true;
38296            };
38297
38298            //404
38299            this.notFound = function(verb, path) {
38300                //route not matched
38301            }
38302
38303            //Run after every update
38304            this.after(function() {
38305                ROUTER.routeChanged();
38306                APP.closeAllGlobalElements();
38307                APP.mobileMenu.open(false);
38308            });
38309        });
38310
38311        ROUTER.sammyApp.debug = false;
38312
38313        ROUTER.sammyApp.run();
38314
38315    },
38316    routeChanged: function () {
38317        var ROUTER = this;
38318        ROUTER.initialLoad = false;
38319        var path = location.pathname + location.search;
38320        ROUTER.lastPath(path);
38321    },
38322    addRoute: function (routeName, regexPath, callback) {
38323        var ROUTER = this;
38324        var existingRoutes = ROUTER.sammyApp.routes.get;
38325        var routeExists = false;
38326
38327        for (var i in existingRoutes) {
38328            var route = existingRoutes[i];
38329            if (route.name && route.name == routeName) {
38330                routeExists = true;
38331            }
38332        }
38333
38334        if (!routeExists) {
38335            //add the route
38336            ROUTER.sammyApp.get(regexPath, function (context) {
38337                ROUTER.lastPath(context.path);
38338                callback(context);
38339                ROUTER.routeChanged();
38340            });
38341            //move it to the top of the list
38342            ROUTER.sammyApp.routes.get.unshift(ROUTER.sammyApp.routes.get.pop())
38343            //set the custom route name/id
38344            ROUTER.sammyApp.routes.get[0].name = routeName;
38345        }
38346    },
38347    removeRoute: function (routeName) {
38348        var ROUTER = this;
38349        var existingRoutes = ROUTER.sammyApp.routes.get;
38350        var routeExistsIndex = -1;
38351
38352        for (var i in existingRoutes) {
38353            var route = existingRoutes[i];
38354            if (route.name && route.name == routeName) {
38355                routeExistsIndex = i;
38356            }
38357        }
38358
38359        if (routeExistsIndex > -1) {
38360            //remove the route
38361            ROUTER.sammyApp.routes.get.splice(routeExistsIndex, 1);
38362        }
38363    },
38364    reRun: function () {
38365        var ROUTER = this;
38366        //need to re-evaluate the routes now that we've added them
38367        ROUTER.forceUpdate = true;
38368        ROUTER.sammyApp.runRoute('get', location.pathname + location.search);
38369    },
38370    getPage: function (path) {
38371
38372        var ROUTER = this;
38373
38374        if (ROUTER.scheduledTimerID() > 0) {
38375            window.clearTimeout(ROUTER.scheduledTimerID());
38376        }
38377
38378        APP.Data.Agility.GetPage(path);
38379    },
38380    getPageTimeout: function (path, timeout) {
38381
38382        var ROUTER = this;
38383
38384        var timerID = window.setTimeout(function () {
38385
38386            APP.Data.Agility.GetPage(path);
38387
38388        }, timeout);
38389
38390        ROUTER.scheduledTimerID(timerID);
38391    },
38392    getModal: {
38393        //Offer: function (code) {
38394        //    var req = new DATA.CMSAPI.Offers.Details();
38395        //    req.args.LanguageCode = _serverContext.LanguageCode;
38396        //    req.args.Code = code;
38397
38398        //    req.onSuccess = function (res) {
38399        //        if (res.Offer) {
38400        //            var modal = new App.ViewModels.Modal('offer-details', code, 'offer-details-modal-tmpl')
38401        //            modal.viewModelForTemplate = new App.ViewModels.OfferDetailsModel(res.Offer);
38402        //            modal.open();
38403        //        }
38404        //    }
38405
38406        //    req.execute();
38407
38408        //},
38409        //MyCard: function () {
38410        //    var modal = new App.ViewModels.Modal('my-card', 'my-card', 'my-card-tmpl').open();
38411        //}
38412    },
38413    navigateHome: function () {
38414        var ROUTER = this;
38415        ROUTER.navigate('/');
38416    },
38417    //redirectToLogin: function () {
38418    //    var ROUTER = this;
38419    //    var qs = [
38420    //            { key: APP.Core.Keys.ReturnUrl, value: window.location.pathname }
38421    //    ];
38422
38423    //    ROUTER.navigate(ROUTER.pages.Login, qs);
38424    //},
38425
38426    //redirectToLogout: function () {
38427    //    var ROUTER = this;
38428    //    var qs = [
38429    //            { key: APP.Core.Keys.ReturnUrl, value: window.location.pathname }
38430    //    ];
38431
38432    //    ROUTER.navigate(ROUTER.pages.Logout, qs);
38433    //},
38434    navigate: function (url, params) {
38435        var ROUTER = this;
38436
38437        //params: [ { key: 'k', value: 'v } ]
38438        if (params) {
38439            for (var i in params) {
38440                if (i == 0) {
38441                    url += "?";
38442                } else {
38443                    url += "&";
38444                }
38445                url += params[i].key;
38446                url += "=";
38447                url += params[i].value;
38448            }
38449        }
38450
38451
38452        //absolute
38453        if (url.indexOf('http') > -1) {
38454            window.location.href = url;
38455        } else {
38456            //relative
38457            ROUTER.sammyApp.setLocation(url);
38458        }
38459    },
38460    afterPageLoaded: function () {
38461        //do something after the next page has loaded
38462    }
38463});
38464
38465;
38466/// <reference path="../_references.js" />
38467
38468//toggleable observable
38469ko.observable.fn.toggleable = function () {
38470    var self = this;
38471    self.toggle = function () {
38472        self(!self());
38473    };
38474
38475    return self;
38476};;
38477if (typeof (window.Agility) == "undefined") {
38478    window.Agility = new Object();
38479}
38480
38481if (typeof (window.Agility.Search) == "undefined") {
38482    window.Agility.Search = new Object();
38483}
38484
38485(function (S, $) {
38486
38487    ///GLOBAL VARIABLES - set in the init
38488    S.SearchUrl = null;
38489    S.WebsiteName = null;
38490    S.AuthKey = null;
38491    S.LanguageCode = null;
38492
38493
38494    _postCORS = function (url, data) {
38495
38496        url = S.SearchUrl + url;
38497
38498        var authHeaders = {};
38499        authHeaders["as-WebsiteName"] = S.WebsiteName;
38500        authHeaders["as-AuthKey"] = S.AuthKey;
38501
38502        return $.ajax(url, {
38503            type: "POST",
38504            data: data,
38505            dataType: "json",
38506            headers: authHeaders,
38507            xhrFields: {
38508                withCredentials: true
38509            },
38510            crossDomain: true
38511        });
38512    };
38513
38514
38515    /**
38516     * A Config object to initialize the Search API.
38517     * @typedef {object} APIConfig
38518     * @property {String} url the search service url
38519     * @property {String} websiteName the website name
38520     * @property {String} authKey the authorization key
38521   * @property {String} lang the default language code	
38522     */
38523    /**
38524     * Initialize the Agility Search API.
38525     * @param {APIConfig} config The API Config object.
38526     */
38527    S.Init = function (config) {
38528        S.SearchUrl = config.url;
38529        S.WebsiteName = config.websiteName;
38530        S.AuthKey = config.authKey;
38531        S.LanguageCode = config.lang;
38532
38533
38534        try {
38535            //try to get the current language code if one wasn't provided
38536            if (!S.LanguageCode || S.LanguageCode == "") {
38537                var attr = $('meta[name=agility_attributes]').attr("content");
38538
38539                if (attr && attr != "") {
38540                    var ary = attr.split(", ");
38541                    for (var i = 0; i < ary.length; i++) {
38542                        if (ary[i].indexOf("Language=") != -1) {
38543                            var languageCode = ary[i].substring("Language=".length);
38544                            S.LanguageCode = languageCode;
38545                        }
38546                    }
38547                }
38548
38549            }
38550        } catch (err) { }
38551
38552        var builtIn = new S.BuiltInSearch();
38553        var builtInGrouped = new S.BuiltInGroupedSearch();
38554
38555        $(function () {
38556
38557            //TODO: when we release Personalization, make this work with the personalization event
38558            builtIn.Init();
38559            builtInGrouped.Init();
38560        });
38561    };
38562
38563
38564    /**
38565     * A Search Query object
38566     * @typedef {object} Query
38567     * @property {String} query
38568     * @property {String} languageCode (optional)
38569   * @property {String} category (optional)
38570   * @property {String} domain (optional)
38571   * @property {Number} top (optional)
38572     * @property {Number} skip (option)
38573     */
38574    /**
38575     * Execute a Search query
38576     * @param {Query} arg The search query object.
38577   * @returns a deferred object
38578     */
38579    S.Query = function (arg) {
38580        if (arg == undefined
38581            || arg == null) {
38582            return;
38583        }
38584
38585        var url = "/search";
38586
38587        if (arg.languageCode === undefined) {
38588            arg.languageCode = S.LanguageCode;
38589        }
38590
38591        return _postCORS(url, arg);
38592    };
38593
38594    /**
38595     * A Grouped Query object
38596     * @typedef {object} GroupedQuery
38597     * @property {String} query
38598     * @property {String} languageCode (optional)
38599     * @property {String} domain (optional)
38600   * @property {Number} top (optional) - Max number of returned items in each category
38601     */
38602    /**
38603     * Execute a Grouped Search query
38604     * @param {GroupedQuery} arg The group search query object.
38605   * @returns a deferred object
38606     */
38607    S.GroupedQuery = function (arg) {
38608        if (arg == undefined
38609            || arg == null) {
38610            return;
38611        }
38612
38613        var url = "/GroupedQuery";
38614
38615        if (arg.languageCode === undefined) {
38616            arg.languageCode = S.LanguageCode;
38617        }
38618
38619        return _postCORS(url, arg);
38620    };
38621
38622
38623    /**
38624     * An AutoComplete object
38625     * @typedef {object} AutoComplete
38626     * @property {String} query
38627     * @property {String} languageCode (optional)
38628   * @property {String} category (optional)
38629   * @property {Number} top (optional)
38630     * @property {Boolean} fuzzy (option)
38631     */
38632    /**
38633     * Execute an Autocomplete query
38634     * @param {AutoComplete} arg The search query object.
38635   * @returns a deferred object
38636     */
38637    S.AutoComplete = function (arg) {
38638        if (arg == undefined
38639            || arg == null) {
38640            return;
38641        }
38642
38643        var url = "/autocomplete";
38644
38645        if (!arg.languageCode) {
38646            arg.languageCode = S.LanguageCode;
38647        }
38648
38649        return _postCORS(url, arg);
38650    };
38651
38652    /**
38653     * A Conversion object
38654     * @typedef {object} Conversion
38655     * @property {String} url    
38656     */
38657    /**
38658     * Record a conversion
38659     * @param {Conversion} arg The conversion object
38660   * @returns a deferred object
38661     */
38662    S.Conversion = function (arg) {
38663        if (arg == undefined
38664            || arg == null) {
38665            return;
38666        }
38667
38668        var url = "/conversion";
38669
38670        return _postCORS(url, arg);
38671    };
38672
38673    var _injectStyle = function () {
38674
38675        var cssUrl = S.SearchUrl + "/Content/Public.min.css";
38676        var autoCompleteUrl = S.SearchUrl + "/scripts/jquery.auto-complete.min.js";
38677
38678        $("<link/>", {
38679            rel: "stylesheet",
38680            type: "text/css",
38681            href: cssUrl
38682        }).appendTo("head");
38683
38684
38685        _scriptLoader = $.getScript(autoCompleteUrl);
38686
38687    };
38688
38689
38690
38691    S.BuiltInGroupedSearch = function () {
38692
38693        var self = this;
38694
38695        self.Init = function () {
38696            //_injectStyle();
38697            $(".agility-grouped-search-panel").each(function () {
38698                _createGroupedSearchField(this);
38699            });
38700        };
38701
38702        _scriptLoader = null;
38703
38704        var _ajaxRequestQuery = null;
38705        var skip = 0;
38706
38707        _createGroupedSearchField = function (elem) {
38708
38709            var $elem = $(elem);
38710
38711            var top = $elem.data('top') || 5;
38712            var redirectPath = $elem.data('redirect-path');
38713            var delay = $elem.data('delay') || 500;
38714            var groupCount = $elem.data('group-count') || 0;
38715            var isPopOver = $elem.data('pop-over') == null || $elem.data('pop-over') == true;
38716
38717            var html = "<form action='' method='post' class='agility-grouped-search-form'><input type='search' placeholder='Search' /><button type='submit'>Search</button>";
38718            html += '<div class="agility-grouped-search-results hidden-panel"><div class="agility-grouped-search-results-inner"></div></div></form>';
38719
38720            $(html).appendTo($elem);
38721
38722            var searchForm = $(".agility-grouped-search-form", $elem);
38723            var searchField = $("input", searchForm);
38724            var resultsPanel = $(".agility-grouped-search-results-inner", $elem);
38725            var resultsPanelOuter = $('.agility-grouped-search-results', $elem);
38726
38727            if (isPopOver) {
38728                resultsPanelOuter.addClass('popOver');
38729
38730                $(document).mouseup(function (e) {
38731                    var container = resultsPanelOuter;
38732
38733                    // if the target of the click isn't the container nor a descendant of the container
38734                    if (!container.is(e.target) && container.has(e.target).length === 0) {
38735                        var lists = $('ul', container);
38736
38737                        if (lists && lists.length > 0) {
38738                            container.addClass('hidden-panel');
38739                        }
38740                    }
38741                });
38742            } else {
38743                resultsPanelOuter.addClass('inline');
38744            }
38745
38746            var scriptLoaded = function () {
38747                var wto;
38748
38749                $('.agility-grouped-search-form input', $elem).on('input', function (e) {
38750                    if (_ajaxRequestQuery) _ajaxRequestQuery.abort();
38751
38752                    var term = $(this).val();
38753
38754                    if (term.length >= 3) {
38755                        _clearTimeoutAndStartLoading(wto, resultsPanel, true);
38756
38757                        wto = setTimeout(function () {
38758
38759                            term = term.toLowerCase();
38760
38761
38762                            _ajaxRequestQuery = S.GroupedQuery({
38763                                query: term,
38764                                top: top,
38765                                groupCount: groupCount
38766                            }).done(function (res) {
38767                                if (!res.IsError) {
38768                                    _renderGroupedResults(res.ResponseData, resultsPanel);
38769
38770                                    if (res.Count > 0) {
38771                                        hasResults = true;
38772                                    } else {
38773                                        hasResults = false;
38774                                    }
38775                                }
38776                            }).always(function () {
38777                                resultsPanel.removeClass('loading');
38778                            });
38779                        }, delay);
38780                    } else {
38781                        _clearTimeoutAndStartLoading(wto, resultsPanel, false);
38782                    }
38783                });
38784
38785                $('.agility-grouped-search-form input', $elem).keydown(function (event) {
38786                    if (event.keyCode === 40) {
38787                        //down arrow key
38788                        var firstGroup = $('.agility-grouped-result', resultsPanel).first();
38789
38790                        if (firstGroup) {
38791                            var firstResult = $('ul li', firstGroup).first();
38792
38793                            firstResult.addClass('selected');
38794
38795                            firstResult.focus();
38796
38797                            return false;
38798                        }
38799                    } else if (event.keyCode === 38) {
38800                        //up arrow key
38801                        var lastGroup = $('.agility-grouped-result', resultsPanel).last();
38802
38803                        if (lastGroup) {
38804                            var lastResult = $('ul li', lastGroup).last(
38804);
38805
38806                            lastResult.addClass('selected');
38807
38808                            lastResult.focus();
38809
38810                            return false;
38811                        }
38812                    } else {
38813                        return true;
38814                    }
38815                });
38816            };
38817
38818
38819            var _clearTimeoutAndStartLoading = function (wto, resultsPanel, startLoading) {
38820                clearTimeout(wto);
38821
38822                resultsPanel.empty();
38823                resultsPanel.parent().removeClass('hidden-panel');
38824
38825                if (startLoading) {
38826                    resultsPanel.addClass('loading');
38827                } else {
38828                    resultsPanel.removeClass('loading');
38829                }
38830            };
38831
38832            var _renderGroupedResults = function (response, resultsPanel) {
38833                for (var i = 0; i < response.GroupedResults.length; i++) {
38834                    resultsPanel.append(_getGroupHTML(response.GroupedResults[i]));
38835                }
38836
38837                $('ul li', resultsPanel).keydown(function () {
38838                    if (event.keyCode === 40) {
38839                        //down arrow key
38840                        var nextResult = $(this).next();
38841
38842                        if (nextResult && nextResult.length != 0) {
38843                            $(this).removeClass('selected');
38844                            nextResult.addClass('selected');
38845                            nextResult.focus();
38846
38847                        } else {
38848                            //go to the next group
38849                            var nextGroup = $(this).parent().parent().next();
38850
38851                            if (nextGroup && nextGroup.length != 0) {
38852                                var firstResultOfNextGroup = $('li', nextGroup).first();
38853
38854                                //result in next group
38855                                $(this).removeClass('selected');
38856                                firstResultOfNextGroup.addClass('selected');
38857                                firstResultOfNextGroup.focus();
38858                            } else {
38859                                //go back to input
38860                                $(this).removeClass('selected');
38861                                searchField.focus();
38862                            }
38863
38864                        }
38865
38866                        return false;
38867                    } else if (event.keyCode === 38) {
38868                        //up arrow key
38869                        var previousResult = $(this).prev();
38870
38871                        if (previousResult && previousResult.length != 0) {
38872                            $(this).removeClass('selected');
38873                            previousResult.addClass('selected');
38874                            previousResult.focus();
38875
38876                        } else {
38877                            //go to the previous group
38878                            var previousGroup = $(this).parent().parent().prev();
38879
38880                            if (previousGroup && previousGroup.length != 0) {
38881                                var lastResultOfPreviousGroup = $('li', previousGroup).last();
38882
38883                                //result in next group
38884                                $(this).removeClass('selected');
38885                                lastResultOfPreviousGroup.addClass('selected');
38886                                lastResultOfPreviousGroup.focus();
38887                            } else {
38888                                //go back to input
38889                                $(this).removeClass('selected');
38890                                searchField.focus();
38891                            }
38892                        }
38893
38894                        return false;
38895                    } else if (event.keyCode === 13) {
38896                        window.location.href = $('a', $(this)).attr('href');
38897
38898                        return false;
38899                    } else {
38900                        return true;
38901                    }
38902                });
38903            };
38904
38905            var _getGroupHTML = function (group) {
38906                var html = '<div class="agility-grouped-result">';
38907                html += '<h3 class="agility-grouped-result-name">';
38908                html += group.Name;
38909                html += '</h3>';
38910
38911                html += '<ul class="agility-grouped-search-list">';
38912
38913                var flags = [], output = [], l = group.Results.length, i;
38914                for (i = 0; i < l; i++) {
38915                    if (flags[group.Results[i].Title]) continue;
38916                    flags[group.Results[i].Title] = true;
38917                    output.push(group.Results[i]);
38918                }
38919
38920                for (var i = 0; i < output.length; i++) {
38921                    var result = output[i];
38922
38923                    html += '<li tabindex="-1">';
38924
38925                    html += '<a href="' + result.Url + '" target="_self">';
38926                    html += result.Title;
38927                    html += '</a>';
38928
38929                    html += '</li>';
38930                }
38931
38932                html += '</ul>';
38933                html += '</div>';
38934
38935                return html;
38936            };
38937
38938            _scriptLoader.done(scriptLoaded.bind(searchField));
38939
38940            searchForm.submit(function (event) {
38941                //redirect to search url
38942                event.preventDefault();
38943
38944                window.location.href = redirectPath + '?q=' + searchField.val();
38945
38946                return false;
38947            });
38948        };
38949    };
38950
38951    S.BuiltInSearch = function () {
38952
38953        var self = this;
38954
38955        self.Init = function () {
38956            _injectStyle();
38957
38958            $(".agility-search-panel").each(function () {
38959                _createSearchField(this);
38960            });
38961        };
38962
38963        _scriptLoader = null;
38964
38965        var ajaxRequestAutoComplete = null;
38966        var _ajaxRequestQuery = null;
38967        var skip = 0;
38968
38969        _createSearchField = function (elem) {
38970
38971            var $elem = $(elem);
38972
38973            var currentQuery = S.GetQueryString("q");
38974            var currentSkip = parseInt(S.GetQueryString("s"));
38975
38976            var html = "<form action='' method='post' class='agility-search-form'><input type='search' placeholder='Search' /><button type='submit'>Search</button></form>";
38977            html += "<div class='agility-search-results'></div>";
38978
38979            $(html).appendTo($elem);
38980
38981            var searchForm = $(".agility-search-form", $elem);
38982            var searchField = $("input", searchForm);
38983            var resultsPanel = $(".agility-search-results", $elem);
38984
38985            searchField.val(currentQuery);
38986
38987            var scriptLoaded = function () {
38988
38989                $(this).autoComplete({
38990                    minChars: 3,
38991                    source: function (term, response) {
38992
38993                        try {
38994                            if (ajaxRequestAutoComplete) ajaxRequestAutoComplete.abort();
38995                        } catch (e) { }
38996
38997                        term = term.toLowerCase();
38998
38999
39000                        var timeout = setTimeout(function () {
39001                            response(["Loading..."]);
39002                        }, 250);
39003
39004                        ajaxRequestAutoComplete = S.AutoComplete({
39005                            query: term
39006                        }).done(function (res) {
39007                            if (!res.IsError) {
39008                                response(res.ResponseData);
39009                            }
39010                        }).always(function () {
39011                            clearTimeout(timeout);
39012                        });
39013
39014                    },
39015                    onSelect: function (e, term, item) {
39016                        if (e.type == "mousedown") {
39017                            searchForm.submit();
39018                        }
39019                    }
39020                });
39021            };
39022            _scriptLoader.done(scriptLoaded.bind(searchField));
39023
39024            searchForm.submit(function (event) {
39025
39026                event.preventDefault();
39027
39028                var query = $.trim(searchField.val());
39029                skip = 0;
39030                if (query.length > 2) {
39031                    S.SetQueryString("q", query);
39032                    S.SetQueryString("s", null);
39033
39034                    _performSearch(query, resultsPanel);
39035
39036                    searchField.blur();
39037                    setTimeout(function () {
39038                        searchField.focus();
39039                    }, 50);
39040
39041
39042                }
39043
39044                return false;
39045            });
39046
39047            if (currentQuery && currentQuery.length > 2) {
39048
39049                if (currentSkip > 0) skip = currentSkip;
39050                _performSearch(currentQuery, resultsPanel);
39051            }
39052
39053        };
39054
39055
39056        var _performSearch = function (query, resultsPanel) {
39057
39058            if (_ajaxRequestQuery != null) {
39059                _ajaxRequestQuery.abort();
39060            }
39061
39062            var panelHeight = resultsPanel.height();
39063            resultsPanel.css("minHeight", panelHeight + "px");
39064
39065            var timeout = setTimeout(function () {
39066                resultsPanel.html("<div class='agility-search-loader'>Loading...</div>");
39067            }, 300);
39068
39069
39070            _ajaxRequestQuery = S.Query({
39071                query: query,
39072                top: 10,
39073                skip: skip,
39074            }).done(function (res) {
39075                _renderResults(res, resultsPanel);
39076
39077            }).fail(function (err) {
39078                _renderResults({ IsError: true, ErrorMessage: err }, resultsPanel);
39079
39080            }).always(function () {
39081                clearTimeout(timeout);
39082                resultsPanel.css("min-height", "");
39083            });;
39084
39085        };
39086
39087        _renderResults = function (res, resultsPanel) {
39088
39089            var html = "<div class='agility-results-header'></div>";
39090            html += "<div class='agility-results-listing'></div>";
39091            html += "<div class='agility-results-pager'></div>";
39092
39093            resultsPanel.html(html);
39094            var header = $(".agility-results-header", resultsPanel);
39095            var listing = $(".agility-results-listing", resultsPanel);
39096
39097            var pagers = $(".agility-results-pager", resultsPanel);
39098
39099            if (res.IsError) {
39100                header.text("An error occurred.");
39101
39102                if (console) console.warn(res.ErrorMessage);
39103                return;
39104            }
39105
39106            var result = res.ResponseData;
39107            if (!result) {
39108                header.text("No results.");
39109            } else if (result.Count == 0 || !result.Results) {
39110                header.text("No results for " + result.Query);
39111            } else {
39112                header.text("Showing result " + result.FromNumber + " to " + result.ToNumber + " of " + result.Count + " for " + result.Query);
39113
39114                var itemHtml = "<div class='agility-result-item'>"
39115                itemHtml += "<a class='agility-result-title'></a>"
39116                itemHtml += "<div class='agility-result-link'></div>"
39117                itemHtml += "<div class='agility-result-description'></div>"
39118                itemHtml += "</div>"
39119
39120                for (var i = 0; i < result.Results.length; i++) {
39121
39122                    var item = result.Results[i];
39123
39124                    var itemObj = $(itemHtml);
39125                    itemObj.appendTo(listing);
39126
39127                    var itemTitle = $(".agility-result-title", itemObj);
39128                    var itemLink = $(".agility-result-link", itemObj);
39129                    var itemDesc = $(".agility-result-description", itemObj);
39130
39131                    if (item.Category) {
39132                        $("<div class='agility-result-category'></div>").prependTo(itemObj);
39133                        var itemCat = $(".agility-result-category", itemObj);
39134                        itemCat.text(item.Category);
39135                    }
39136
39137
39138                    if (item.ImageUrl) {
39139                        $("<div class='agility-result-image'></div>").prependTo(itemObj);
39140                        var itemImage = $(".agility-result-image", itemObj);
39141                        itemImage.css("background-image", "url('" + item.ImageUrl + "')");
39142                    }
39143
39144
39145
39146                    itemTitle.text(item.Title).attr("href", item.Url);
39147                    itemLink.text(item.Url);
39148
39149                    itemDesc.html(item.Highlight);
39150
39151                }
39152
39153                var pHtml = "";
39154
39155                if (result.FromNumber > 1) {
39156                    pHtml += "<a class='prev-link' href='#'>Previous</a>";
39157                }
39158
39159                if (result.ToNumber < result.Count) {
39160                    if (pHtml != "") {
39161                        pHtml += "&nbsp;|&nbsp;"
39162                    }
39163                    pHtml += "<a class='next-link' href='#'>Next</a>";
39164                }
39165
39166
39167
39168                if (pHtml != "") {
39169                    pagers.html(pHtml);
39170                    pagers.css("display", "block");
39171                }
39172
39173                $(".agility-result-title", resultsPanel).click(function () {
39174
39175                    var url = $(this).attr("href");
39176                    S.Conversion({ url: url });
39177                });
39178                $(".next-link", pagers).click(function () {
39179                    skip = result.ToNumber;
39180                    S.SetQueryString("s", skip);
39181                    //_performSearch(result.Query, resultsPanel);
39182
39183                    return false;
39184                });
39185
39186                $(".prev-link", pagers).click(function () {
39187                    var pageSize = result.ToNumber - result.FromNumber + 1;
39188                    skip = result.FromNumber - pageSize - 1;
39189                    if (skip < 0) skip = 0;
39190                    S.SetQueryString("s", skip);
39191                    //_performSearch(result.Query, resultsPanel);
39192
39193                    return false;
39194
39195                });
39196
39197
39198
39199            }
39200
39201
39202
39203
39204        };
39205    };
39206
39207    S.SetQueryString = function (name, value, url) {
39208        if (url == undefined || url == null || url == "") {
39209            url = location.href;
39210        }
39211
39212        if (url.indexOf("#") != -1) {
39213            url = url.substring(0, url.indexOf("#"));
39214        }
39215
39216        var queryObj = {};
39217
39218        var urlNoQuery = url;
39219
39220        var index = url.indexOf("?");
39221        if (index > 1) {
39222
39223            urlNoQuery = url.substring(0, index);
39224
39225            //get the current query strings...
39226            var qstr = url.substring(index + 1, url.length);
39227            var ary1 = qstr.split("&");
39228
39229            for (var i = 0; i < ary1.length; i++) {
39230                var q = ary1[i];
39231                var ary2 = q.split("=");
39232                if (ary2.length == 2) {
39233                    var qName = decodeURIComponent(ary2[0]);
39234
39235                    var qValue = ary2[1];
39236                    qValue = qValue.replace(/\+/g, "%20");
39237                    qValue = decodeURIComponent(qValue);
39238
39239
39240                    queryObj[qName] = qValue;
39241                }
39242            }
39243        }
39244
39245        if (value) {
39246            queryObj[name] = value;
39247        } else {
39248            delete queryObj[name];
39249        }
39250
39251
39252
39253        var newUrl = "";
39254        for (var qn in queryObj) {
39255            var qv = queryObj[qn];
39256
39257            if (newUrl == "") {
39258                newUrl += "?";
39259            } else {
39260                newUrl += "&";
39261            }
39262            newUrl += encodeURIComponent(qn) + "=" + encodeURIComponent(qv);
39263        }
39264
39265        //push this to the address bar...
39266        newUrl = urlNoQuery + newUrl;
39267
39268        history.pushState({}, document.title, newUrl);
39269
39270    }
39271
39272    S.GetQueryString = function (name, url) {
39273        /// <summary>
39274        /// Gets a variable from the query string.  
39275        /// </summary>
39276        /// <param name="name" type="String">QueryString variable to retrieve.</param>
39277        /// <param name="url" type="String">(Optional) the url to take the querystring from.  If this is not present, the current url is used.</param>
39278
39279        if (url == undefined || url == null || url == "") {
39280            url = location.href;
39281        }
39282
39283        //strip off the hash
39284        if (url.indexOf("#") != -1) {
39285            url = url.substring(0, url.indexOf("#"));
39286        }
39287
39288        var index = url.indexOf("?");
39289        if (index < 1) return null;
39290
39291        var qstr = url.substring(index + 1, url.length);
39292
39293        var ary1 = qstr.split("&");
39294        var retValue = null;
39295
39296        for (var i = 0; i < ary1.length; i++) {
39297            var q = ary1[i];
39298            var ary2 = q.split("=");
39299            if (ary2.length == 2) {
39300                if (decodeURIComponent(ary2[0]).toLowerCase() == name.toLowerCase()) {
39301                    var retValue = ary2[1];
39302                    retValue = retValue.replace(/\+/g, "%20");
39303                    return decodeURIComponent(retValue);
39304                }
39305            }
39306        }
39307
39308        return null;
39309
39310    }
39311
39312
39313
39314
39315
39316
39317
39318})(Agility.Search, jQuery);;
39319/// <reference path="../_references.js" />
39320
39321ko.bindingHandlers.articleGallery = {
39322    init: function (element, valueAccessor, allBindings, viewModel) {
39323        $('.news-details__gallery-main').slick({
39324            slidesToShow: 1,
39325            slidesToScroll: 1,
39326            arrows: false,
39327            fade: true,
39328            asNavFor: '.news-details__gallery-nav'
39329        });
39330
39331        $('.news-details__gallery-nav').slick({
39332            slidesToShow: 2,
39333            slidesToScroll: 1,
39334            asNavFor: '.news-details__gallery-main',
39335            centerMode: true,
39336            focusOnSelect: true
39337        });
39338    }
39339};
39340;
39341/// <reference path="../../_references.js" />
39342
39343// Found on https://stackoverflow.com/questions/20817710/knockout-custom-html-binding
39344
39345ko.bindingHandlers.bindHTML = {
39346    init: function () {
39347        return { 'controlsDescendantBindings': true };
39348    },
39349    update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
39350        // setHtml will unwrap the value if needed
39351        ko.utils.setHtml(element, valueAccessor());
39352
39353        var elementsToAdd = element.children;
39354
39355        for (var i = 0; i < elementsToAdd.length; i++) {
39356            ko.cleanNode(elementsToAdd[i]); //Clean node from Knockout bindings
39357            ko.applyBindings(bindingContext, elementsToAdd[i]);
39358        }
39359    }
39360};;
39361/// <reference path="../../_references.js" />
39362
39363ko.bindingHandlers.clientFrameLoader = {
39364    update: function (element, valueAccessor, allBindings, viewModel) {
39365
39366        //function that runs when any dependency in the valueAccessor changes
39367        var clientPageRequest = ko.unwrap(valueAccessor());
39368        var $frame = $(element);
39369
39370        var getHash = function (url) {
39371            var tag = document.createElement("a");
39372
39373            var hash = "";
39374
39375            tag.href = url;
39376
39377            if (!!tag.hash && tag.hash.length > 1) {
39378                hash = tag.hash.substring(1);
39379            }
39380
39381            return hash;
39382        };
39383
39384        var getUrl = function (url) {
39385            var tag = document.createElement("a");
39386
39387            var href = "";
39388
39389            tag.href = url;
39390
39391            if (!!tag.pathname) {
39392                href = tag.pathname + tag.search;
39393            }
39394
39395            return href;
39396        };
39397
39398        if (clientPageRequest != null) {
39399
39400            $frame.attr('src', APP.Core.Keys.AgilityPageAPIBasePath + encodeURIComponent(getUrl(clientPageRequest)));
39401            $frame.on('load', function (data) {
39402				
39403                var contentsText = $(this).contents().find('body').text();
39404                var resultJSON = $.parseJSON(contentsText);
39405
39406                if (resultJSON.isError) {
39407                    //got a problem? hard redirect...
39408                    window.location.href = clientPageRequest;
39409                } else if (resultJSON.redirect_location != null) {
39410                    //this is a redirect
39411                    APP.Router.sammyApp.setLocation(resultJSON.redirect_location);
39412                }
39413                else {
39414					
39415                    //set a unique ID
39416                    resultJSON.page.id = APP.newPageID();
39417
39418                    // set the hash, if we have one
39419                    resultJSON.page.hash = getHash(clientPageRequest);
39420
39421                    //set the new page
39422                    APP.page(resultJSON.page);
39423
39424                    //remove the load event - won't need it again
39425                    $frame.unbind('load');
39426
39427                    //clear the frame - this so that the frame doesn't remain the same in the dom and doesn't mess with the back/forward browser behaviour
39428                    APP.clientPageRequest(null);
39429
39430                    //Reattach search:
39431                    Agility.Search.Init({ url: "https://search.agilitycms.com", websiteName: "EMSB", lang: "", authKey: "9fLju8eeNyfB1i5ZjB7drTfY7UEIu6y8V4lGbTF7K60" });
39432
39433                }
39434
39435
39436
39437            });
39438
39439
39440        }
39441
39442
39443    }
39444};
39445;
39446/// <reference path="../_references.js" />
39447
39448ko.bindingHandlers.documentList = {
39449    init: function (element, valueAccessor, allBindings, viewModel) {
39450        $(element).click(function () {
39451            $(element).toggleClass('open');
39452            $(element).children().first().next().slideToggle();
39453        })
39454
39455    }
39456};
39457;
39458/// <reference path="../_references.js" />
39459
39460ko.bindingHandlers.dropdownMenu = {
39461
39462    init: function (element, valueAccessor, allBindings, viewModel) {
39463        var options = valueAccessor() || [],
39464            linkClass = options.linkClass || "",
39465            activeClass = options.activeClass || linkClass + "--open",
39466            dropdownClass = options.dropdownClass || linkClass + "__dropdown",
39467            dropdownActiveClass = options.dropdownActiveClass || dropdownClass + "--open";
39468
39469        if (linkClass != "") {
39470            var links = document.getElementsByClassName(linkClass);
39471            console.log(links);
39472
39473            for (i = 0; i < links.length; i++) {
39474                links[i].addEventListener('focus', function (e) {
39475                }, true);  
39476
39477                links[i].addEventListener('blur', function (e) {
39478                    let self = this;
39479                }, true);    
39480                
39481            }
39482        }
39483    }
39484};
39485;
39486/// <reference path="../_references.js" />
39487
39488ko.bindingHandlers.employmentExpand = {
39489    init: function (element, valueAccessor, allBindings, viewModel) {
39490        //function runs when element is added to the DOM
39491        $(element).click(function () {
39492            console.log(this)
39493            var elParent = $(this).parent();
39494            console.log(elParent);
39495            var grandParent = elParent.parent();
39496            console.log(grandParent)
39497            var target = grandParent.children();
39498            console.log(target);
39499            target.toggleClass('open');
39500        })
39501        $(element).keydown(function (e) {
39502            if (e.which === 13) {
39503                var elParent = $(this).parent();
39504                console.log(elParent);
39505                var grandParent = elParent.parent();
39506                console.log(grandParent)
39507                var target = grandParent.children();
39508                console.log(target);
39509                target.toggleClass('open');
39510            }
39511           
39512        })
39513    },
39514};
39515;
39516ko.bindingHandlers.globalLoading = {
39517    update: function (element, valueAccessor, allBindings, viewModel) {
39518        //function that runs when any dependency in the valueAccessor changes
39519        var isLoading = ko.unwrap(valueAccessor());
39520
39521        if (isLoading) {
39522            $(element).addClass('global-loading');
39523            $(element).removeClass('global-loading-done');
39524        } else {
39525            $(element).addClass('global-loading-done');
39526        }
39527    }
39528};;
39529/// <reference path="../../_references.js" />
39530
39531ko.bindingHandlers.googleMap = {
39532    init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
39533        var options = valueAccessor(),
39534            latitude = options.lat || null,
39535            longtitude = options.long || null;
39536
39537        var mapCenter = {
39538            lat: latitude, lng: longtitude
39539        };
39540
39541        var map = new google.maps.Map(element, {
39542            zoom: 16,
39543            center: mapCenter,
39544            disableDefaultUI: true
39545        });
39546
39547        var marker = new google.maps.Marker({
39548            position: mapCenter
39549        });
39550
39551        marker.setMap(map);
39552    }
39553
39554};;
39555/// <reference path="../../_references.js" />
39556
39557/*jslint this:true */
39558(function (window) {
39559
39560    var ko = window.ko;
39561
39562    var _serverContext = window._serverContext;
39563
39564    var $ = window.jQuery;
39565
39566    ko.bindingHandlers.languageSwitcher = {
39567
39568        init: function (element, valueAccessor) {
39569
39570            var thisLang = valueAccessor();
39571
39572            var switcherURL = "/languageswitcher/" + thisLang;
39573
39574            if (thisLang === _serverContext.LanguageCode) {
39575
39576                if ($(element).data("active-hide")) {
39577                    $(element).hide();
39578                } else {
39579                    $(element).addClass("header__right-language-link--active");
39580                    $(element).attr("disabled", "disabled");
39581                }
39582            } else {
39583
39584                $(element).click(function () {
39585                    window.location.href = switcherURL + "?url=" + window.location.pathname + encodeURIComponent(window.location.search);
39586                });
39587            }
39588
39589        }
39590    };
39591
39592}(this));;
39593/// <reference path="../_references.js" />
39594
39595ko.bindingHandlers.levelTabsSections = {
39596    init: function (element, valueAccessor, allBindings, viewModel) {
39597        var $elem = $(element),
39598            options = valueAccessor(),
39599            $container = options.container != null ? $(container) : $elem,
39600            children = options.children || "",
39601            classToAdd = options.classToAdd || "modified";
39602
39603        $container.children(children).find(".article-listing__header").parents(children).siblings().addClass(classToAdd);
39604    }
39605};
39606;
39607/// <reference path="../../_references.js" />
39608
39609ko.bindingHandlers.main = {
39610    update: function (element, valueAccessor, allBindings, viewModel) {
39611        //function that runs when any dependency in the valueAccessor changes
39612
39613        var page = ko.unwrap(valueAccessor());
39614        var $main = $(element);
39615        var templateContainerClass = 'template-container';
39616
39617        var scrollTo = function (elementID) {
39618
39619            var headerHeight = $("header").outerHeight();
39620
39621            var element = $("a[name='" + elementID + "'], #" + elementID);
39622
39623            var scroll = function () {
39624                $('html, body').animate({
39625                    scrollTop: element.offset().top - headerHeight + 'px'
39626                }, 0);
39627            };
39628
39629            if (element.length > 0) {
39630                scroll();
39631            }
39632        };
39633
39634        //if this is the server page, kick out
39635        if (page.serverPage !== true) {
39636
39637            var addPage = function () {
39638                //setup the new template container
39639                //var $tmplCnt = $('<div>').addClass(templateContainerClass).attr('id', page.id).delay(500).addClass('fade-in');
39640                var $tmplCnt = $('<div>').addClass(templateContainerClass).attr('id', page.id);
39641
39642                //add the html from the new page
39643                $tmplCnt.html(page.html);
39644
39645                //start fading out the previous page
39646                //$main.children('.' + templateContainerClass).eq(0).addClass('fade-out');
39647
39648                //add the new page to the DOM!
39649                $main.append($tmplCnt);
39650
39651                //scroll to top, if we don't have a hash
39652                if (!page.hash) {
39653                    window.scrollTo(0, 0);
39654                } else {
39655                    scrollTo(page.hash);
39656                }
39657
39658                //add combined scripts
39659                var $scripts = $('<div/>').attr('id', 'script-zone-for--' + page.id).html(page.scripts_combined);
39660                $tmplCnt.append($scripts);
39661
39662
39663                //apply the global viewmodel bindings to the new page
39664               ko.applyBindings(APP, document.getElementById(page.id))
39665
39666                //wait 1s, until some animations finish, then remove the old page from the DOM
39667                //setTimeout(function () {
39668                var $disposedPage = $main.children('.' + templateContainerClass).eq(0)
39669                ko.cleanNode($disposedPage[0]);
39670                ko.removeNode($disposedPage[0]);
39671                //}, 1000);
39672
39673                APP.Router.afterPageLoaded();
39674            };
39675
39676            //if there is still two templates, wait till it's gone
39677            if ($main.children('.' + templateContainerClass).length > 1) {
39678
39679                //check every 100ms
39680                var interval = setInterval(function () {
39681
39682                    if ($main.children('.' + templateContainerClass).length < 2) {
39683                        addPage();
39684                        clearInterval(interval);
39685                    }
39686                }, 100)
39687            } else {
39688                addPage();
39689            }
39690
39691        }
39692
39693    }
39694
39695};
39696;
39697/// <reference path="../_references.js" />
39698
39699ko.bindingHandlers.mobileMenuExpand = {
39700    init: function (element, valueAccessor, allBindings, viewModel) {
39701        //function runs when element is added to the DOM
39702        $(element).click(function () {
39703            $('.mobile-menu').toggleClass('open');
39704        })
39705        $('#nav-icon').click(function () {
39706            $(this).toggleClass('open');
39707            $('.menu').toggleClass('show');
39708        });
39709    },
39710
39711};
39712
39713ko.bindingHandlers.mobileSublistExpand = {
39714    init: function (element, valueAccessor, allBindings, viewModel) {
39715        //function runs when element is added to the DOM
39716        $(element).click(function () {
39717            $(element).toggleClass('expanded')
39718            var elParent = $(this).parent();
39719            var grandParent = elParent.parent();
39720            grandParent.children().toggleClass('open');
39721        })
39722    },
39723
39724};
39725;
39726/// <reference path="../_references.js" />
39727
39728ko.bindingHandlers.mobileMenuTabindex = {
39729    update: function (element, valueAccessor, allBindings, viewModel) {
39730        var $elem = $(element),
39731            options = valueAccessor();
39732
39733        if (options) {
39734            $elem.find('a').attr('tabindex', '0')
39735        } else {
39736            $elem.find('a').attr('tabindex', '-1')
39737        }
39738    }
39739};
39740;
39741/// <reference path="../_references.js" />
39742
39743ko.bindingHandlers.mobileSubNavExpand = {
39744    init: function (element, valueAccessor, allBindings, viewModel) {
39745        //function runs when element is added to the DOM
39746        $(element).click(function () {
39747            $('.subNav-container').toggleClass('open');
39748            $(this).toggleClass('open');
39749        })
39750    },
39751};
39752
39753ko.bindingHandlers.mobileSubNavCollapse = {
39754    init: function (element, valueAccessor, allBindings, viewModel) {
39755        //function runs when element is added to the DOM
39756        var lastButton = null;
39757
39758        $(element).click(function () {
39759            $('.subNav-container').removeClass('open');
39760            $('button').removeClass('open');
39761        })
39762        $(element).keydown(function (e) {
39763            if (e.which === 40) {
39764                $('.news--header__link').focus();
39765                //create variable to remember last tabbed item here.
39766                lastButton = e.target;
39767                console.log(lastButton);
39768                $('.badge-link').blur(function () {
39769                    lastButton.focus();
39770                })
39771            }
39772        })
39773        $('.badge-link').keydown(function (e) {
39774            if (e.which === 40) {
39775                $('.event-details-title').filter(":first").focus();
39776
39777            }
39778        })
39779    },
39780    
39781};
39782
39783
39784;
39785/// <reference path="../_references.js" />
39786
39787ko.bindingHandlers.openModaal = {
39788    init: function (element, valueAccessor, allBindings, viewModel) {
39789        var $elem = $(element),
39790            target = valueAccessor();
39791
39792        $elem.modaal();
39793    }
39794};
39795;
39796/// <reference path="../_references.js" />
39797
39798ko.bindingHandlers.search = {
39799    init: function (element, valueAccessor, allBindings, viewModel) {
39800        //function runs when element is added to the DOM
39801        //console.log(element)
39802        $(element).click(function () {
39803            $(".logo__container").toggleClass("hide");
39804            $(".header-functions__contact").toggleClass("hide")
39805            $(this).toggleClass("open");
39806            $('input.search').val('Search');
39807            $('.header-functions__search').css('max-width', 'unset');
39808            var classState = $(this).attr('class');
39809            if (classState === "header-functions__search") {
39810                $('input.search').val('');
39811
39812            }
39813
39814            ///when the element is closed, remove search value
39815        })
39816    }
39817   
39818};
39819
39820;
39821/// <reference path="../_references.js" />
39822
39823ko.bindingHandlers.selectize = {
39824    init: function (element, valueAccessor, allBindings, viewModel) {
39825        var $elem = $(element),
39826            options = valueAccessor(),
39827            items = options.items || null;
39828
39829        $elem.selectize({
39830            valueField: 'TabIndex',
39831            labelField: 'Title',
39832            hideSelected: true,
39833            options: items,
39834            render: {
39835                option: function (data, escape) {
39836                    return '<div class="option">'
39837                        + (data.Icon !== null ? '<span class="option__icon ' + escape(data.Icon) + '"></span>' : "")
39838                        + '<span class="option__title title">' + escape(data.Title) + '</span>'
39839                    + '</div>';
39840                }
39841            },
39842            onInitialize: function () {
39843                var self = this;
39844
39845                self.$control_input.attr('readonly', true);                
39846                self.setValue(1);
39847            },
39848            onChange: function (value, $item) {
39849                //HACK - I'm so sorry
39850                //TODO: Make this work with the binding. Instead of changing the classes change an observable
39851				$('[data-toggle-click-index="tab-' + value + '"]').click();
39852            }
39853        })
39854
39855    }
39856};
39857;
39858/// <reference path="../_references.js" />
39859
39860/*jslint this:true */
39861(function (window) {
39862
39863    var ko = window.ko;
39864
39865    var $ = window.jQuery;
39866
39867    var defaultSlider = "slick";
39868
39869    var swiperAdapter = {
39870
39871        createSlider: function (element, options) {
39872
39873            var self = this;
39874
39875            var selectorClass = $(element).attr("class");
39876
39877            var sliderID = $(element).attr("id");
39878
39879            var swiperSelector = !!sliderID
39880                ? "#" + sliderID
39881                : "";
39882
39883            swiperSelector += !!selectorClass
39884                ? "." + selectorClass.replace(/\s+/gi, ".")
39885                : "";
39886
39887            var swiperOptions = {};
39888
39889            var registerParentCallback = function (options, eventCallback) {
39890
39891                var eventHandler = function () {
39892
39893                    var newSlideIndex = !parentInstance
39894                        ? -1
39895                        : parentInstance.realIndex + 1;
39896
39897                    eventCallback(parentInstance, newSlideIndex);
39898
39899                    return true;
39900                };
39901
39902                if (!!options.parentSliderID) {
39903
39904                    var parentSliderElem = $("#" + options.parentSliderID);
39905
39906                    var parentInstance = parentSliderElem[0].swiper;
39907
39908                    parentInstance.on("slideChangeStart", eventHandler);
39909                }
39910            };
39911
39912            var slider = null;
39913
39914            if (!!swiperSelector) {
39915
39916                swiperOptions.preventClicks = false;
39917                swiperOptions.paginationClickable = true;
39918                swiperOptions.slidesPerView = options.slidesPerView;
39919                swiperOptions.spaceBetween = options.spaceBetween;
39920                swiperOptions.effect = options.effect;
39921                swiperOptions.centeredSlides = "centeredSlides" in o
39921ptions ? options.centeredSlides : false;
39922
39923                if (options.speed > 0) {
39924                    swiperOptions.autoplay = options.speed;
39925                    swiperOptions.autoplayDisableOnInteraction = false;
39926                    swiperOptions.lazyLoading = true;
39927                }
39928
39929                registerParentCallback(options, function (instance, newSlideIndex) {
39930
39931                    console.log(newSlideIndex);
39932
39933                    self.sliderGoTo(swiperSelector, newSlideIndex);
39934                });
39935
39936                swiperOptions.loop = "loop" in options ? options.loop : true;
39937
39938                slider = new window.Swiper(swiperSelector, swiperOptions);
39939
39940            } else {
39941                slider = null;
39942            }
39943        },
39944
39945        sliderGoTo: function (sliderSelector, slideIndex) {
39946
39947            var sliderElem = $(sliderSelector);
39948
39949            var instance = sliderElem[0].swiper;
39950
39951            instance.slideTo(slideIndex);
39952        },
39953
39954        sliderNext: function (sliderSelector) {
39955
39956            var sliderElem = $(sliderSelector);
39957
39958            var instance = sliderElem[0].swiper;
39959
39960            instance.slideNext();
39961        },
39962
39963        sliderPrevious: function (sliderSelector) {
39964
39965            var sliderElem = $(sliderSelector);
39966
39967            var instance = sliderElem[0].swiper;
39968
39969            instance.slidePrev();
39970        },
39971
39972        registerEventHandlers: function (sliderSelector, eventCallback) {
39973
39974            var sliderElem = $(sliderSelector);
39975
39976            var instance = sliderElem[0].swiper;
39977
39978            var eventHandler = function () {
39979
39980                var newSlideIndex = !instance
39981                    ? -1
39982                    : instance.realIndex + 1;
39983
39984                eventCallback(instance, newSlideIndex);
39985
39986                return true;
39987            };
39988
39989            instance.on("slideChangeStart", eventHandler);
39990
39991            eventHandler();
39992        }
39993    };
39994
39995    var slickAdapter = {
39996
39997        createSlider: function (element, options) {
39998
39999            var $elem = $(element);
40000
40001            var slickOptions = {};
40002
40003            //var registerParentCallback = function (options, eventCallback) {
40004
40005            //    var eventHandler = function () {
40006
40007            //        var newSlideIndex = !parentInstance
40008            //            ? -1
40009            //            : parentInstance.realIndex + 1;
40010
40011            //        eventCallback(parentInstance, newSlideIndex);
40012
40013            //        return true;
40014            //    };
40015
40016            //    if (!!options.parentSliderID) {
40017
40018            //        var parentSliderElem = $("#" + options.parentSliderID);
40019
40020            //        var parentInstance = parentSliderElem[0].swiper;
40021
40022            //        parentInstance.on("afterChange", eventHandler);
40023            //    }
40024            //};
40025
40026            if (options.speed > 0) {
40027                slickOptions.autoplay = true;
40028                slickOptions.autoplaySpeed = options.speed;
40029            }
40030
40031            slickOptions.lazyLoad = "ondemand";
40032            slickOptions.prevArrow = "";
40033            slickOptions.nextArrow = "";
40034            slickOptions.dots = options.dots;
40035
40036            $($elem).slick(slickOptions);
40037
40038            //registerParentCallback(options, function (instance, newSlideIndex) {
40039
40040            //    console.log(newSlideIndex);
40041
40042            //    self.sliderGoTo(swiperSelector, newSlideIndex);
40043            //});
40044        },
40045
40046        sliderGoTo: function (sliderSelector, slideIndex) {
40047
40048            var sliderElem = $(sliderSelector);
40049
40050            sliderElem.slick("slickGoTo", slideIndex - 1);
40051        },
40052
40053        sliderNext: function (sliderSelector, slideIndex) {
40054
40055            // TODO: implement this
40056        },
40057
40058        sliderPrevious: function (sliderSelector, slideIndex) {
40059
40060            // TODO: implement this
40061        },
40062
40063        registerEventHandlers: function (sliderSelector, eventCallback) {
40064
40065            // TODO: implement on slick
40066            eventCallback(null, -1);
40067        }
40068    };
40069
40070    var owlcarouselAdapter = {
40071
40072        createSlider: function (element, options) {
40073
40074            var $elem = $(element);
40075
40076            var carouselElem = $(".owl-carousel", $elem);
40077
40078            var owlOptions = {};
40079
40080            if (!$.fn.owlCarousel) {
40081
40082                return;
40083            }
40084
40085            var numOfSlides = $('.owl-carousel > div', $(element)).length;
40086
40087            if (numOfSlides > 1) {
40088                owlOptions.loop = true;
40089            } else {
40090                owlOptions.mouseDrag = false;
40091                owlOptions.touchDrag = false;
40092                owlOptions.pullDrag = false;
40093            }
40094
40095            owlOptions.autoplay = true;
40096            owlOptions.navigation = false;
40097            owlOptions.autoplayTimeout = options.speed;
40098            owlOptions.paginationSpeed = 400;
40099            owlOptions.items = 1;
40100            owlOptions.lazyLoad = true;
40101
40102            carouselElem.owlCarousel(owlOptions);
40103        },
40104
40105        sliderGoTo: function (sliderSelector, slideIndex) {
40106
40107            var sliderElem = $(".owl-carousel", sliderSelector).data("owlCarousel");
40108
40109            sliderElem.to(slideIndex - 1);
40110        },
40111
40112        sliderNext: function (sliderSelector, slideIndex) {
40113
40114            var sliderElem = $(sliderSelector);
40115
40116            sliderElem = $(".owl-carousel", sliderSelector).data("owlCarousel");
40117
40118            sliderElem.next();
40119        },
40120
40121        sliderPrevious: function (sliderSelector, slideIndex) {
40122
40123            var sliderElem = $(sliderSelector);
40124
40125            sliderElem = $(".owl-carousel", sliderSelector).data("owlCarousel");
40126
40127            sliderElem.prev();
40128        },
40129
40130        registerEventHandlers: function (sliderSelector, eventCallback) {
40131
40132            var sliderElem = $(".owl-carousel", sliderSelector).data("owlCarousel");
40133
40134            $(".owl-carousel", sliderSelector).on("changed.owl.carousel", function (evt) {
40135
40136                var newSlideIndex = evt.item.index - 1;
40137
40138                eventCallback(null, newSlideIndex);
40139            });
40140        }
40141    };
40142
40143    var sliders = {
40144
40145        "swiper": swiperAdapter,
40146
40147        "slick": slickAdapter,
40148
40149        "owlcarousel2": owlcarouselAdapter
40150    };
40151
40152    ko.bindingHandlers.slider = {
40153
40154        init: function (element, valueAccessor) {
40155
40156            var $ = window.jQuery;
40157
40158            var options = ko.unwrap(valueAccessor()) || {};
40159
40160            if (sliders.hasOwnProperty(defaultSlider)) {
40161
40162                sliders[defaultSlider].createSlider(element, options);
40163            }
40164        }
40165    };
40166
40167    ko.bindingHandlers.sliderGoTo = {
40168
40169        init: function (element, valueAccessor, allBindings) {
40170
40171            var $ = window.jQuery;
40172
40173            var $elem = $(element);
40174
40175            var sliderSelector = ko.unwrap(valueAccessor());
40176
40177            var sliderElem = null;
40178
40179            var addActiveClass = function (classToAdd) {
40180
40181                $($elem.siblings()).removeClass(classToAdd);
40182
40183                $elem.addClass(classToAdd);
40184            };
40185
40186            var slideGoToOptions = allBindings.get("sliderGoToOptions");
40187
40188            var slideIndex = parseInt(slideGoToOptions.slideIndex, 10);
40189
40190            $elem.on("click", function (evt) {
40191                evt.preventDefault();
40192
40193                if (sliders.hasOwnProperty(defaultSlider)) {
40194                    sliders[defaultSlider].sliderGoTo(sliderSelector, slideIndex);
40195                }
40196
40197                addActiveClass(slideGoToOptions.classToAdd);
40198            });
40199
40200            if (sliders.hasOwnProperty(defaultSlider)) {
40201
40202                if (sliders[defaultSlider].hasOwnProperty("registerEventHandlers")) {
40203
40204                    sliders[defaultSlider].registerEventHandlers(sliderSelector, function (instance, newSlideIndex) {
40205
40206                        if (newSlideIndex === slideIndex) {
40207
40208                            addActiveClass(slideGoToOptions.classToAdd);
40209                        }
40210                    });
40211                }
40212            }
40213        }
40214    };
40215
40216    ko.bindingHandlers.sliderNext = {
40217
40218        init: function (element, valueAccessor, allBindings) {
40219
40220            var sliderSelector = ko.unwrap(valueAccessor());
40221
40222            var $elem = $(element);
40223
40224            var sliderElem = null;
40225
40226            $elem.on("click", function (evt) {
40227
40228                evt.preventDefault();
40229
40230                if (sliders.hasOwnProperty(defaultSlider)) {
40231                    sliders[defaultSlider].sliderNext(sliderSelector);
40232                }
40233            });
40234        }
40235    };
40236
40237    ko.bindingHandlers.sliderPrevious = {
40238
40239        init: function (element, valueAccessor, allBindings) {
40240
40241            var sliderSelector = ko.unwrap(valueAccessor());
40242
40243            var $elem = $(element);
40244
40245            var sliderElem = null;
40246
40247            $elem.on("click", function (evt) {
40248                evt.preventDefault();
40249
40250                if (sliders.hasOwnProperty(defaultSlider)) {
40251                    sliders[defaultSlider].sliderPrevious(sliderSelector);
40252                }
40253            });
40254        }
40255    };
40256
40257}(this));;
40258/// <reference path="../_references.js" />
40259
40260ko.bindingHandlers.showSpotlightSection = {
40261    init: function (element, valueAccessor, allBindings, viewModel) {
40262        //function runs when element is added to the DO
40263
40264        $(element).click(function (e) {
40265            function showSection(n) {
40266                console.log(clicked)
40267                var sections = $('.spotlight-flex-container');
40268                var tabs = $('.tab-desk');
40269                if (n > sections.length) {
40270                    sectionIndex = 1;
40271                }
40272                if (n < 1) {
40273                    sectionIndex = sections.length;
40274                }
40275                for (var i = 0; i < sections.length; i++) {
40276                    sections[i].style.display = "none";
40277                }
40278                for (var i = 0; i < tabs.length; i++) {
40279                    tabs[i].className = tabs[i].className.replace(' tab-open', 'tab-desk');
40280                }
40281                sections[sectionIndex - 1].style.display = "flex";
40282                tabs[sectionIndex - 1].className += " tab-open";
40283
40284            }
40285                var clicked = e.target.className
40286                $(this).toggleClass("");
40287                if (clicked === "spotlight-tab") {
40288                    sectionIndex = 1;
40289                }
40290                if (clicked === "schools-tab") {
40291                    sectionIndex = 2;
40292                }
40293                if (clicked === "parents-tab") {
40294                    sectionIndex =3;
40295                }
40296                if (clicked === "special-tab") {
40297                    sectionIndex = 4;
40298                }
40299                if (clicked === "public-tab") {
40300                    sectionIndex = 5;
40301                }
40302                if (clicked === "employees-tab") {
40303                    sectionIndex = 6;
40304                }
40305                if (clicked === "facebook-tab") {
40306                    sectionIndex = 7;
40307                }
40308                if (clicked === "fa fa-facebook") {
40309                    sectionIndex = 7;
40310                }
40311                if (clicked === "twitter-tab") {
40312                    sectionIndex = 8;
40313                }
40314                if (clicked === "fa fa-twitter") {
40315                    sectionIndex = 8;
40316                }
40317                showSection(sectionIndex);
40318    
40319            })
40320
40321            var sectionIndex = 1;
40322            showSection(sectionIndex);
40323       
40324
40325        function showSection(n) {
40326            var sections = $('.spotlight-flex-container');
40327            var tabs = $('.tab-desk');
40328            if (n > sections.length) {
40329                sectionIndex = 1;
40330            }
40331            if (n < 1) {
40332                sectionIndex = sections.length;
40333            }
40334            for (var i = 0; i < sections.length; i++) {
40335                sections[i].style.display = "none";
40336            }
40337            for (var i = 0; i < tabs.length; i++) {
40338                tabs[i].className = tabs[i].className.replace(' tab-open', 'tab-desk');
40339            }
40340            sections[sectionIndex - 1].style.display = "flex";
40341            tabs[sectionIndex - 1].className += " tab-open";
40342
40343        }
40344    }
40345    
40346};
40347;
40348/// <reference path="../_references.js" />
40349
40350ko.bindingHandlers.tabletMenu = {
40351    init: function (element, valueAccessor, allBindings, viewModel) {
40352        //function runs when element is added to the DOM
40353        //console.log(element)
40354        $(element).click(function () {
40355            $(this).toggleClass("open");
40356        });
40357    }
40358};
40359;
40360/// <reference path="../_references.js" />
40361
40362/*jslint this:true */
40363(function (window) {
40364
40365    var ko = window.ko;
40366
40367    var $ = window.jQuery;
40368
40369    ko.bindingHandlers.toggleOnClick = {
40370
40371        init: function (element, valueAccessor) {
40372
40373            var $elem = $(element);
40374
40375            var options = ko.unwrap(valueAccessor());
40376
40377            var keepActive = options.keepActive || false;
40378
40379            var tabClassToAdd = options.tabClassToAdd || "active";
40380
40381            var tabContentClassToAdd = options.tabContentClassToAdd || options.tabClassToAdd || "active";
40382
40383            var containerClassToAdd = options.containerClassToAdd || "";
40384
40385            var tabGroup = options.tabGroup || "";
40386
40387            var showFirst = "showFirst" in options
40388                ? options.showFirst
40389                : false;
40390
40391            var tabsFilter = !!tabGroup
40392                ? "[data-toggle-click='true'][data-toggle-click-group='" + tabGroup + "']"
40393                : "[data-toggle-click='true']";
40394
40395            var tabs = $(tabsFilter, $elem);
40396
40397            var hideTab = function (tabName) {
40398
40399                //hide all tab contents
40400                $("[data-toggle-click-content='true']", $elem).removeClass(tabContentClassToAdd); //content
40401                $("[data-toggle-click='true']", $elem).removeClass(tabClassToAdd); //tab
40402
40403                var $tabContentToActivate = $("[data-toggle-click-content='true'][data-toggle-click-index='" + tabName + "']");
40404                var $tabToActive = $("[data-toggle-click='true'][data-toggle-click-index='" + tabName + "']");
40405
40406                //show active
40407                $tabContentToActivate.removeClass(tabContentClassToAdd); //content
40408
40409                //tab
40410                $tabToActive.removeClass(tabClassToAdd);
40411
40412                if (!!containerClassToAdd) {
40413                    $elem.removeClass(containerClassToAdd);
40414                }
40415            };
40416
40417            var showTab = function (tabName) {
40418
40419                //hide all tab contents
40420                $("[data-toggle-click-content='true']", $elem).removeClass(tabContentClassToAdd); //content
40421                $("[data-toggle-click='true']", $elem).removeClass(tabClassToAdd); //tab
40422
40423                var $tabContentToActivate = $("[data-toggle-click-content='true'][data-toggle-click-index='" + tabName + "']");
40424                var $tabToActive = $("[data-toggle-click='true'][data-toggle-click-index='" + tabName + "']");
40425
40426                //show active
40427                $tabContentToActivate.addClass(tabContentClassToAdd); //content
40428
40429                //tab
40430                $tabToActive.addClass(tabClassToAdd);
40431
40432                if (!!containerClassToAdd) {
40433                    $elem.addClass(containerClassToAdd);
40434                }
40435            };
40436
40437            tabs.click(function (evt) {
40438                evt.preventDefault();
40439                var tabName = $(this).attr("data-toggle-click-index");
40440
40441                if ($(this).hasClass(tabClassToAdd)) {
40442
40443                    if (!keepActive) {
40444                        hideTab(tabName);
40445                    }
40446                } else {
40447                    showTab(tabName);
40448                }
40449
40450            });
40451
40452            if (!!showFirst) {
40453
40454                var firstContent = $("[data-toggle-click-content='true']:first-child", $elem);
40455
40456                var firstTabName = "";
40457
40458                if (firstContent.length > 0) {
40459
40460                    firstTabName = firstContent.data("toggle-click-index");
40461
40462                    showTab(firstTabName);
40463                }
40464            }
40465        }
40466    };
40467
40468}(this));;
40469/// <reference path="../_references.js" />
40470
40471ko.bindingHandlers.warningModal = {
40472    init: function (element, valueAccessor, allBindings, viewModel) {
40473        //function runs when element is added to the DOM
40474
40475        $(element).on('click', function (event) {
40476            event.preventDefault();
40477            $('#warning-modal').iziModal('open', {
40478                //transitionIn: 'fadeInDown',
40479                //transitionOut: 'flipOutX'
40480            });
40481        });
40482
40483        $("#warning-modal").iziModal();
40484
40485    }
40486};
40487;
40488/// <reference path="../_references.js" />
40489var VM = APP.ViewModels;
40490
40491VM.AppModel = function () {
40492    var self = this;
40493
40494    self.page = ko.observable(window._serverContext.Page);
40495
40496    self.sections = ko.observableArray([]);
40497
40498    self.slideInView = null;
40499    self.routeScrollInProgress = false;
40500
40501    self.section = ko.observable("");
40502    self.updatedSection = ko.pureComputed(function () {
40503        return self.section();
40504    });
40505
40506    self.clientPageRequest = ko.observable(null);
40507
40508    //close all the global elements like searchbar or modals
40509    self.closeAllGlobalElements = function () {
40510        //self.open.searchbar(false);
40511        //self.open.splashSearch(false);
40512    }
40513
40514    //function called to check if the page requires authentication
40515    self.checkPageAuthentication = function (page) {
40516
40517        if (!page) {
40518            page = self.page();
40519        }
40520
40521        if (page.requiresAuth) {
40522            self.Router.RedirectToLogin();
40523            return true;
40524        }
40525
40526        return false;
40527    }
40528
40529    self.globalLoading = ko.pureComputed({
40530        read: function () {
40531
40532            var clientPageRequest = ko.unwrap(self.clientPageRequest);
40533            var ready = ko.unwrap(self.appReady);
40534
40535            return clientPageRequest != null || !ready;
40536        },
40537        owner: this
40538    });
40539
40540    self.pageIndex = 0;
40541
40542    self.newPageID = function () {
40543        self.pageIndex++;
40544        return 'page-' + self.pageIndex;
40545    }
40546
40547    self.initialLoading = ko.pureComputed({
40548        read: function () {
40549            var ready = ko.unwrap(self.appReady);
40550            return !ready;
40551        },
40552        owner: this
40553    });
40554
40555    ///
40556    //on ready
40557    ///
40558    self.appReady = ko.observable(false);
40559    self.onReady = function () {
40560        APP.Router.setupRoutes();
40561
40562        //APP.Account.Initialize(function () {
40563        //    self.appReady(true);
40564        //});
40565
40566        self.appReady(true);
40567    };
40568
40569    // Menu variable
40570    self.mobileMenu = {
40571        open: ko.observable(false).toggleable()
40572    };
40573
40574    self.mobileSearch = {
40575        open: ko.observable(false).toggleable()
40576    };
40577
40578};
40579
40580;
40581ko.components.register('contact-us', {
40582    viewModel: function (params) {
40583        function ContactUs(params) {
40584            var self = this;
40585
40586            self.state = {
40587                loading: ko.observable(false),
40588                ready: ko.observable(false),
40589                error: ko.observable(false),
40590                submitted: ko.observable(false),
40591                reset: function () {
40592                    self.state.loading(false);
40593                    self.state.ready(false);
40594                    self.state.error(false);
40595                    self.state.submitted(false);
40596                }
40597            };
40598
40599            self.data = {
40600                referenceName: params.referenceName || "ContactUs"
40601            }
40602
40603            self.form = {
40604                firstName: ko.observable(""),
40605                lastName: ko.observable(""),
40606                emailAddress: ko.observable(""),
40607                departmentOrTopic: ko.observable(""),
40608                message: ko.observable(""),
40609                submit: self.submitForm,
40610                error: ko.observable()
40611            };
40612
40613            self.init(params);
40614        };
40615
40616        ko.utils.extend(ContactUs.prototype, {
40617            init: function (params) {
40618                var self = this;
40619
40620                self.state.loading(true);
40621
40622                //Do something
40623
40624                self.state.loading(false);
40625
40626            },
40627            submitForm: function () {
40628                var self = this;
40629
40630                self.state.loading(true);
40631
40632                self.state.error(false);
40633
40634                var contactUsForm = new Agility.UGC.API.BooleanFeedback();
40635
40636                contactUsForm.RecordTypeName = self.data.referenceName;
40637
40638                contactUsForm.FirstName = ko.unwrap(self.form.firstName);
40639                contactUsForm.LastName = ko.unwrap(self.form.lastName);
40640                contactUsForm.EmailAddress = ko.unwrap(self.form.emailAddress);
40641                contactUsForm.Message = ko.unwrap(self.form.message);
40642                contactUsForm.DepartmentOrTopic = ko.unwrap(self.form.departmentOrTopic);
40643
40644                Agility.UGC.API.SaveRecord(contactUsForm, function (data) {
40645
40646                    if (data.ResponseType != Agility.UGC.API.ResponseType.OK) {
40647                        //error occurred                        
40648                        self.form.error(data.Message);
40649                        self.state.error(true);
40650                    } else {
40651                        console.log("Form submitted sucessfully." + data.Message);
40652                        self.state.submitted(true);
40653                    }
40654
40655                    self.state.loading(false);
40656
40657                });
40658
40659            },
40660            dispose: function () {
40661                var self = this;
40662            }
40663
40664        });
40665
40666        return new ContactUs(params);
40667
40668    },
40669    template: {
40670        element: 'contact-us-tmpl'
40671    }
40672});;
40673ko.components.register('event-details', {
40674    viewModel: function (params) {
40675        function EventDetails(params) {
40676            var self = this;
40677
40678            self.state = {
40679                loading: ko.observable(false),
40680                ready: ko.observable(false),
40681                error: ko.observable(false),
40682                submitted: ko.observable(false),
40683                reset: function () {
40684                    self.state.loading(false);
40685                    self.state.ready(false);
40686                    self.state.error(false);
40687                    self.state.submitted(false);
40688                }
40689            };
40690
40691            self.data = {
40692                locationTerm: params.location
40693            }
40694
40695            self.searchHTML5 = "HTML5";
40696            self.searchGoogleMaps = "Google";
40697            self.searchType = ko.observable(self.searchHTML5);
40698            self.geocoder = null;
40699            self.locations = ko.observableArray([]);            
40700            self.longitude = ko.observable(null);
40701            self.latitude = ko.observable(null);
40702
40703            self.searchByLocationTerm = function (onSuccess) {
40704
40705                self.searchType(self.searchGoogleMaps);
40706
40707                if (self.geocoder == null) {
40708                    self.geocoder = new google.maps.Geocoder();
40709                }
40710
40711                self.geocoder.geocode({
40712                    'address': self.data.locationTerm
40713                }, function (results, status) {
40714                    if (status == google.maps.GeocoderStatus.OK && results != null && results.length > 0) {
40715
40716                        self.searchByLatLng(results[0].geometry.location.lat(), results[0].geometry.location.lng())
40717
40718                        if (onSuccess)
40719                            onSuccess();
40720                    }
40721                });
40722            };
40723
40724            self.searchByLatLng = function (latitude, longitude) {                
40725                self.latitude(latitude)
40726                self.longitude(longitude)                
40727            };
40728
40729            self.init(params);
40730        };
40731
40732        ko.utils.extend(EventDetails.prototype, {
40733
40734            init: function (params) {
40735                var self = this;
40736
40737                self.state.loading(true);
40738
40739                //Do something
40740                self.searchByLocationTerm(function () {                    
40741                    self.state.loading(false);
40742                    self.state.ready(true);
40743                });
40744                
40745            },
40746
40747            dispose: function () {
40748                var self = this;
40749            }
40750
40751        });
40752
40753        return new EventDetails(params);
40754
40755    },
40756    template: {
40757        element: 'event-details-tmpl'
40758    }
40759});;
40760ko.components.register('school-search', {
40761	viewModel: function (params) {
40762		function SchoolSearch(params) {
40763			var self = this;
40764
40765			self.state = {
40766				loading: ko.observable(false),
40767				ready: ko.observable(false),
40768				error: ko.observable(false),
40769				noSchoolsResult: ko.observable(false),
40770				reset: function () {
40771					self.state.loading(false);
40772					self.state.ready(false);
40773					self.state.error(false);
40774					self.state.noSchoolsResult(false);
40775				}
40776			};
40777
40778			self.data = {
40779				programs: ko.observableArray(JSON.parse(params.programs)),
40780				schoolResults: ko.observableArray([])
40781			}
40782
40783			self.form = {
40784				selectedProgram: ko.observable(params.preSelectionProgramsIDs || null),
40785				selectedLevel: ko.observable(params.preSelectionLevelsIDs || null),
40786				selectedBorough: ko.observable(params.preSelectionBoroughsIDs || null)
40787			};
40788
40789			//self.form.selectedProgram.subscribe(function(newvalue) {
40790			//    return self.searchFilterChange();
40791			//});
40792
40793			self.init(params);
40794		};
40795
40796		ko.utils.extend(SchoolSearch.prototype, {
40797			init: function (params) {
40798				var self = this;
40799
40800				self.getSchools();
40801
40802	            self.filterPrograms();
40803				
40804            },
40805            search: function() {
40806                var self = this;
40807                
40808                self.searchFilterChange();
40809            },
40810            searchFilterChange: function () {
40811
40812				var self = this;
40813
40814				self.getSchools();
40815				
40816                self.state.loading(true);
40817
40818				self.state.error(false);
40819
40820			},
40821
40822			filterPrograms: function () {
40823				var self = this;
40824
40825				self.state.loading(true);
40826
40827				var url = "/SchoolSearch/GetSchoolPrograms";
40828
40829				var data = {
40830					academicLevelId: ko.unwrap(self.form.selectedLevel)
40831				};
40832
40833				self.ajaxRequest = CORE.Get(url, data,
40834					function (result) {
40835
40836						if (!result.IsError) {
40837							self.data.programs(result);
40838						}
40839					},
40840					function (err, status, errorMessage) { },
40841					function () {
40842						self.state.loading(false);
40843					});
40844
40845				return self.ajaxRequest;
40846			},
40847
40848			getSchools: function () {
40849				var self = this;
40850
40851                self.state.reset();
40852                self.state.loading(true);
40853	            
40854                if (!ko.unwrap(self.form.selectedBorough) &&
40855                    !ko.unwrap(self.form.selectedProgram) &&
40856                    !ko.unwrap(self.form.selectedLevel)) {
40857                    self.data.schoolResults([]);
40858                }
40859                else {
40860
40861					var url = '/SchoolSearch/GetSchools';
40862
40863					var prog = ko.unwrap(self.form.selectedProgram);
40864
40865					if (prog) {
40866						prog = prog.Value;
40867					}
40868
40869					var data = {
40870						boroughId: ko.unwrap(self.form.selectedBorough),
40871						programId: prog,
40872						academicLevelId: ko.unwrap(self.form.selectedLevel)
40873					};
40874
40875					self.ajaxRequest = CORE.Get(url, data,
40876						function (result) {
40877
40878							if (!result.IsError) {
40879
40880								self.data.schoolResults(result.AcademicLevel);
40881
40882								if (ko.unwrap(self.data.schoolResults).length === 0) {
40883									self.state.noSchoolsResult(true);
40884								}
40885
40886							} else {
40887								self.state.noSchoolsResult(true);
40888							}
40889
40890						},
40891						function (err, status, errorMessage) { },
40892						function () {
40893							self.state.loading(false);
40894						});
40895
40896					return self.ajaxRequest;
40897				}
40898			},
40899
40900			formatSchoolAddress: function (school) {
40901
40902				var schoolAddress = "";
40903
40904				if (this.hasAddress(school)) {
40905					schoolAddress += school.StreetAddress1 + "<br/>" + school.City + " " + school.PostalCode;
40906				}
40907
40908				return schoolAddress;
40909
40910			},
40911
40912			hasAddress: function (school) {
40913
40914				var hasAddress = false;
40915
40916				if (school) {
40917					hasAddress = true;
40918				}
40919
40920				return hasAddress;
40921
40922			},
40923
40924			dispose: function () {
40925				var self = this;
40926			}
40927
40928		});
40929
40930		return new SchoolSearch(params);
40931
40932	},
40933	template: {
40934		element: 'school-search-tmpl'
40935	}
40936});;
40937/// <reference path="../_references.js" />
40938
40939var CORE = APP.Core,
40940    VM = APP.ViewModels,
40941    ROUTER = APP.Router;
40942
40943/////////////////////////
40944// DOM READY
40945/////////////////////////
40946var $win = $(window);
40947
40948$(function () {
40949
40950    //////////////////////////////////////////////////////////////////////////////
40951    // INIT UGC
40952    //////////////////////////////////////////////////////////////////////////////
40953    window.InitUGC();
40954
40955
40956    //////////////////////////////////////////////////////////////////////////////
40957    // INIT KNOCKOUT
40958    //////////////////////////////////////////////////////////////////////////////
40959    ko.options.deferUpdates = true;
40960
40961
40962    APP.Router = new VM.RouterModel();
40963
40964    //kickoff knockout binding
40965    ko.utils.extend(APP, new VM.AppModel()); //store bound instance of APP model in global var
40966    ko.applyBindings(APP, document.getElementById('html'));
40967
40968    //let's go!
40969    APP.onReady();
40970
40971
40972});;
40973Agility.RegisterNamespace("RegistrationForm");
40974
40975const PRF = (function (PreregForm, $) {
40976
40977    PreregForm.Init = function (arg) {
40978        // $("#btnCreateAccount").click(createProfile);
40979    }
40980
40981    // 30th september current year
40982    const cutoff = new Date(new Date().getFullYear(), 8, 30);
40983    $("[js-datepicker]").datepicker({
40984        minDate: "-18y",
40985        changeYear: true,
40986        changeMonth: true,
40987        yearRange: "-21:+0",
40988        onSelect: function () {
40989            $("[js-registration-type]").prop("selectedIndex", 0);
40990            $("[js-registration-type]").trigger("change");
40991        }
40992    }).focus(function () {
40993        $(".ui-datepicker-next").hide();
40994        $(".ui-datepicker-prev").hide();
40995    });
40996
40997    $("[js-next-step]").on("click", function () {
40998        let nextStep = $(this).data("next-step");
40999        if ($(".registration-form").valid()) {
41000            $("[data-step=" + (nextStep - 1) + "]").hide();
41001            $("[data-step=" + nextStep + "]").show();
41002        }
41003        
41004    });
41005
41006    $("[js-prev-step]").on("click", function () {
41007        let prevStep = $(this).data("prev-step");
41008        $("[data-step=" + (prevStep + 1) + "]").hide();
41009        $("[data-step=" + prevStep + "]").show();
41010    });
41011
41012    // https://stackoverflow.com/questions/4060004/calculate-age-given-the-birth-date-in-the-format-yyyymmdd
41013    $("[js-registration-type]").on("change", function () {
41014        let childDob = new Date($("[js-child-dob]").val());
41015        var ageDifMs = cutoff.getTime() - childDob.getTime();
41016        var ageDate = new Date(ageDifMs); // miliseconds from epoch
41017        let age = Math.abs(ageDate.getUTCFullYear() - 1970)
41018
41019        // reset all elements
41020        $("[js-kindergarten-sister-name]").find("input[type=text]").val("");
41021        $("[js-derogation-gradeone]").find("input[type=checkbox]").prop("checked", false);
41022        $("[js-derogation-kindergarten]").find("input[type=checkbox]").prop("checked", false);
41023        $($("[js-kindergarten-sister]")[1]).trigger("click"); // set to no.
41024        $("[js-derogation-gradeone]").hide();
41025        $("[js-derogation-kindergarten]").hide();
41026        $("[js-kindergarten]").hide();
41027
41028        if ($("[js-registration-type]").val() == "Kindergarten" && age < 5) { // if the child is less than 5 and they have chosen kindergarten show derogation
41029            $("[js-derogation-kindergarten]").show();
41030        }
41031        if ($("[js-registration-type]").val() == "Kindergarten") { // but always show this if they chose kindergarten
41032            $("[js-kindergarten]").show();
41033        }
41034
41035        if ($("[js-registration-type]").val() == "Grade 1" && age < 6) { // if they chose grade 1 and the child is greater than 7
41036            $("[js-derogation-gradeone]").show();
41037        }
41038
41039    });
41040
41041    $("[js-kindergarten-sister]").on("click", function () {
41042
41043        if (parseInt($(this).val()) == 1) { // yes
41044            $("[js-kindergarten-sister-name]").show();
41045        }
41046        if (parseInt($(this).val()) == 0) { // no
41047            $("[js-kindergarten-sister-name]").hide();
41048        }
41049
41050    });
41051
41052    $("[js-english-eligibility]").on("click", function () {
41053
41054        $("[js-english-eligibility-no]").hide();
41055        $("[js-english-eligibility-yes]").hide();
41056
41057        if (parseInt($(this).val()) == 1) { // yes
41058            $("[js-english-eligibility-yes]").show();
41059            $(".form__group[data-step='2']").find("[js-next-step]").show();
41060        }
41061        if (parseInt($(this).val()) == 0) { // no
41062            $("[js-english-eligibility-no]").show();
41063            $(".form__group[data-step='2']").find("[js-next-step]").show();
41064        }
41065
41066    });
41067
41068    $("[js-assessment]").on("click", function () {
41069        
41070        if (parseInt($(this).val()) == 1) { // yes
41071            $("[js-assement-yes]").show();
41072        }
41073        if (parseInt($(this).val()) == 0) { // no
41074            $("[js-assement-yes]").hide();    
41075        }
41076    });
41077
41078    $("[js-same-as-parent1]").on("click", function () {
41079
41080        $(this).parents("fieldset").find("input[type=text]").prop("disabled", false);
41081        if ($(this).prop("checked")) {
41082            $(this).parents("fieldset").find("input[type=text]").val("");
41083            $(this).parents("fieldset").find("input[type=text]").prop("disabled", true);
41084        }
41085
41086    });
41087
41088    var recaptchaTicked = false;
41089    $("[js-submit]").on("click", function (e) {
41090
41091        e.preventDefault();
41092
41093        let $form = $(this).parents("form");
41094        let captcha = $form.find("[js-google-captcha]");
41095        captcha.attr("class", "");
41096
41097        if (!recaptchaTicked) {
41098            captcha.addClass("field-validation-error--centered");
41099        }
41100        else {
41101            captcha.addClass("field-validation-valid");
41102        }
41103
41104        if (recaptchaTicked && $(".registration-form").valid()) {
41105            saveRegistrationForm() // save form to Agility
41106                        .then(function (submission) {
41107                            if (submission !== null) {
41108                                // now post back to our controller in order for the webhook to happen
41109                                $.post("/PreregistrationForm/ProcessPreregistration", submission, function (response) {
41110                                    if (!response.Success) {
41111                                        $("[js-error]").show();
41112                                    }
41113                                    else {
41114                                        // hide form, show error message
41115                                        $("#registrationForm").hide();
41116                                        $("[js-success]").show();
41117                                    }
41118                                });
41119                            }
41120
41121                        }, function () {
41122                            return null;
41123                        });
41124        }
41125    });
41126
41127    function recaptchaCallback() {
41128        recaptchaTicked = true;
41129    }
41130
41131    function saveRegistrationForm() {
41132
41133        var serialise = $(".registration-form").serializeArray();
41134        var submission = {
41135            RecordTypeName: "RegistrationForm"
41136        };
41137
41138        // apply fields.
41139        for (iii = 0; iii < serialise.length; iii += 1) {
41140            if (serialise[iii].name === "g-recaptcha-response") {
41141                submission["RecaptchResponse"] = "true";
41142            }
41143            else {
41144                submission[serialise[iii].name] = serialise[iii].value;
41145            }
41146        }
41147
41148        // fix the date
41149        var dob = new Date($("[js-child-dob]").val());
41150        submission["ChildDOB"] = dob.getFullYear() + "-" + (dob.getMonth() + 1) + "-" + dob.getDate();
41151
41152        // fix the complete bool.
41153        submission["AttendSisterKindergarten"] = !!parseInt(submission["AttendSisterKindergarten"]);
41154        submission["EnglishEducationEligibility"] = !!parseInt(submission["EnglishEducationEligibility"]);
41155        submission["HasAssessment"] = !!parseInt(submission["HasAssessment"]);
41156
41157        return saveRecordToAgility(submission);
41158    }
41159
41160    $(document).ready(function () {
41161        // Adds the booleanrequired attribute defined in the Helpers folder.
41162        $.validator.unobtrusive.adapters.addBool("booleanrequired", "required");
41163    })
41164
41165
41166    return {
41167        RecaptchaCallback: recaptchaCallback
41168    };
41169
41170
41171    function saveRecordToAgility(submission) {
41172        return new Promise(function (resolve, reject) {
41173
41174            Agility.UGC.API.SaveRecord(submission, function (data) {
41175                if (data.ResponseType != Agility.UGC.API.ResponseType.OK) {
41176                    reject(null);
41177                }
41178                else
41179                {
41180                    resolve(submission);
41181                }
41182            });
41183
41184            
41185        });
41186    }
41187
41188
41189})(RegistrationForm, window.jQuery);
41190
41191function recaptchaCallbackConfactForm() {
41192    PRF.RecaptchaCallback();
41193};

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.