PageSourceSearch

https://www.cloudhq.net/javascripts/main_jquery_3_7_1_packaged.js?ed39c42136b17294d50f289a32b24e8d

js cloudhq.net collected 2026-09-24 08:49:00 UTC 1,271,992 bytes, 41,656 lines download raw bytes

vendor: 113,357 bytes, lines 1-4077
1/*!
2 * jQuery JavaScript Library v3.7.1
3 * https://jquery.com/
4 *
5 * Copyright OpenJS Foundation and other contributors
6 * Released under the MIT license
7 * https://jquery.org/license
8 *
9 * Date: 2023-08-28T13:37Z
10 */
11( function( global, factory ) {
12
13	"use strict";
14
15	if ( typeof module === "object" && typeof module.exports === "object" ) {
16
17		// For CommonJS and CommonJS-like environments where a proper `window`
18		// is present, execute the factory and get jQuery.
19		// For environments that do not have a `window` with a `document`
20		// (such as Node.js), expose a factory as module.exports.
21		// This accentuates the need for the creation of a real `window`.
22		// e.g. var jQuery = require("jquery")(window);
23		// See ticket trac-14549 for more info.
24		module.exports = global.document ?
25			factory( global, true ) :
26			function( w ) {
27				if ( !w.document ) {
28					throw new Error( "jQuery requires a window with a document" );
29				}
30				return factory( w );
31			};
32	} else {
33		factory( global );
34	}
35
36// Pass this if window is not defined yet
37} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
38
39// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1
40// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode
41// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common
42// enough that all such attempts are guarded in a try block.
43"use strict";
44
45var arr = [];
46
47var getProto = Object.getPrototypeOf;
48
49var slice = arr.slice;
50
51var flat = arr.flat ? function( array ) {
52	return arr.flat.call( array );
53} : function( array ) {
54	return arr.concat.apply( [], array );
55};
56
57
58var push = arr.push;
59
60var indexOf = arr.indexOf;
61
62var class2type = {};
63
64var toString = class2type.toString;
65
66var hasOwn = class2type.hasOwnProperty;
67
68var fnToString = hasOwn.toString;
69
70var ObjectFunctionString = fnToString.call( Object );
71
72var support = {};
73
74var isFunction = function isFunction( obj ) {
75
76		// Support: Chrome <=57, Firefox <=52
77		// In some browsers, typeof returns "function" for HTML <object> elements
78		// (i.e., `typeof document.createElement( "object" ) === "function"`).
79		// We don't want to classify *any* DOM node as a function.
80		// Support: QtWeb <=3.8.5, WebKit <=534.34, wkhtmltopdf tool <=0.12.5
81		// Plus for old WebKit, typeof returns "function" for HTML collections
82		// (e.g., `typeof document.getElementsByTagName("div") === "function"`). (gh-4756)
83		return typeof obj === "function" && typeof obj.nodeType !== "number" &&
84			typeof obj.item !== "function";
85	};
86
87
88var isWindow = function isWindow( obj ) {
89		return obj != null && obj === obj.window;
90	};
91
92
93var document = window.document;
94
95
96
97	var preservedScriptAttributes = {
98		type: true,
99		src: true,
100		nonce: true,
101		noModule: true
102	};
103
104	function DOMEval( code, node, doc ) {
105		doc = doc || document;
106
107		var i, val,
108			script = doc.createElement( "script" );
109
110		script.text = code;
111		if ( node ) {
112			for ( i in preservedScriptAttributes ) {
113
114				// Support: Firefox 64+, Edge 18+
115				// Some browsers don't support the "nonce" property on scripts.
116				// On the other hand, just using `getAttribute` is not enough as
117				// the `nonce` attribute is reset to an empty string whenever it
118				// becomes browsing-context connected.
119				// See https://github.com/whatwg/html/issues/2369
120				// See https://html.spec.whatwg.org/#nonce-attributes
121				// The `node.getAttribute` check was added for the sake of
122				// `jQuery.globalEval` so that it can fake a nonce-containing node
123				// via an object.
124				val = node[ i ] || node.getAttribute && node.getAttribute( i );
125				if ( val ) {
126					script.setAttribute( i, val );
127				}
128			}
129		}
130		doc.head.appendChild( script ).parentNode.removeChild( script );
131	}
132
133
134function toType( obj ) {
135	if ( obj == null ) {
136		return obj + "";
137	}
138
139	// Support: Android <=2.3 only (functionish RegExp)
140	return typeof obj === "object" || typeof obj === "function" ?
141		class2type[ toString.call( obj ) ] || "object" :
142		typeof obj;
143}
144/* global Symbol */
145// Defining this global in .eslintrc.json would create a danger of using the global
146// unguarded in another place, it seems safer to define global only for this module
147
148
149
150var version = "3.7.1",
151
152	rhtmlSuffix = /HTML$/i,
153
154	// Define a local copy of jQuery
155	jQuery = function( selector, context ) {
156
157		// The jQuery object is actually just the init constructor 'enhanced'
158		// Need init if jQuery is called (just allow error to be thrown if not included)
159		return new jQuery.fn.init( selector, context );
160	};
161
162jQuery.fn = jQuery.prototype = {
163
164	// The current version of jQuery being used
165	jquery: version,
166
167	constructor: jQuery,
168
169	// The default length of a jQuery object is 0
170	length: 0,
171
172	toArray: function() {
173		return slice.call( this );
174	},
175
176	// Get the Nth element in the matched element set OR
177	// Get the whole matched element set as a clean array
178	get: function( num ) {
179
180		// Return all the elements in a clean array
181		if ( num == null ) {
182			return slice.call( this );
183		}
184
185		// Return just the one element from the set
186		return num < 0 ? this[ num + this.length ] : this[ num ];
187	},
188
189	// Take an array of elements and push it onto the stack
190	// (returning the new matched element set)
191	pushStack: function( elems ) {
192
193		// Build a new jQuery matched element set
194		var ret = jQuery.merge( this.constructor(), elems );
195
196		// Add the old object onto the stack (as a reference)
197		ret.prevObject = this;
198
199		// Return the newly-formed element set
200		return ret;
201	},
202
203	// Execute a callback for every element in the matched set.
204	each: function( callback ) {
205		return jQuery.each( this, callback );
206	},
207
208	map: function( callback ) {
209		return this.pushStack( jQuery.map( this, function( elem, i ) {
210			return callback.call( elem, i, elem );
211		} ) );
212	},
213
214	slice: function() {
215		return this.pushStack( slice.apply( this, arguments ) );
216	},
217
218	first: function() {
219		return this.eq( 0 );
220	},
221
222	last: function() {
223		return this.eq( -1 );
224	},
225
226	even: function() {
227		return this.pushStack( jQuery.grep( this, function( _elem, i ) {
228			return ( i + 1 ) % 2;
229		} ) );
230	},
231
232	odd: function() {
233		return this.pushStack( jQuery.grep( this, function( _elem, i ) {
234			return i % 2;
235		} ) );
236	},
237
238	eq: function( i ) {
239		var len = this.length,
240			j = +i + ( i < 0 ? len : 0 );
241		return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] );
242	},
243
244	end: function() {
245		return this.prevObject || this.constructor();
246	},
247
248	// For internal use only.
249	// Behaves like an Array's method, not like a jQuery method.
250	push: push,
251	sort: arr.sort,
252	splice: arr.splice
253};
254
255jQuery.extend = jQuery.fn.extend = function() {
256	var options, name, src, copy, copyIsArray, clone,
257		target = arguments[ 0 ] || {},
258		i = 1,
259		length = arguments.length,
260		deep = false;
261
262	// Handle a deep copy situation
263	if ( typeof target === "boolean" ) {
264		deep = target;
265
266		// Skip the boolean and the target
267		target = arguments[ i ] || {};
268		i++;
269	}
270
271	// Handle case when target is a string or something (possible in deep copy)
272	if ( typeof target !== "object" && !isFunction( target ) ) {
273		target = {};
274	}
275
276	// Extend jQuery itself if only one argument is passed
277	if ( i === length ) {
278		target = this;
279		i--;
280	}
281
282	for ( ; i < length; i++ ) {
283
284		// Only deal with non-null/undefined values
285		if ( ( options = arguments[ i ] ) != null ) {
286
287			// Extend the base object
288			for ( name in options ) {
289				copy = options[ name ];
290
291				// Prevent Object.prototype pollution
292				// Prevent never-ending loop
293				if ( name === "__proto__" || target === copy ) {
294					continue;
295				}
296
297				// Recurse if we're merging plain objects or arrays
298				if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
299					( copyIsArray = Array.isArray( copy ) ) ) ) {
300					src = target[ name ];
301
302					// Ensure proper type for the source value
303					if ( copyIsArray && !Array.isArray( src ) ) {
304						clone = [];
305					} else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) {
306						clone = {};
307					} else {
308						clone = src;
309					}
310					copyIsArray = false;
311
312					// Never move original objects, clone them
313					target[ name ] = jQuery.extend( deep, clone, copy );
314
315				// Don't bring in undefined values
316				} else if ( copy !== undefined ) {
317					target[ name ] = copy;
318				}
319			}
320		}
321	}
322
323	// Return the modified object
324	return target;
325};
326
327jQuery.extend( {
328
329	// Unique for each copy of jQuery on the page
330	expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
331
332	// Assume jQuery is ready without the ready module
333	isReady: true,
334
335	error: function( msg ) {
336		throw new Error( msg );
337	},
338
339	noop: function() {},
340
341	isPlainObject: function( obj ) {
342		var proto, Ctor;
343
344		// Detect obvious negatives
345		// Use toString instead of jQuery.type to catch host objects
346		if ( !obj || toString.call( obj ) !== "[object Object]" ) {
347			return false;
348		}
349
350		proto = getProto( obj );
351
352		// Objects with no prototype (e.g., `Object.create( null )`) are plain
353		if ( !proto ) {
354			return true;
355		}
356
357		// Objects with prototype are plain iff they were constructed by a global Object function
358		Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor;
359		return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString;
360	},
361
362	isEmptyObject: function( obj ) {
363		var name;
364
365		for ( name in obj ) {
366			return false;
367		}
368		return true;
369	},
370
371	// Evaluates a script in a provided context; falls back to the global one
372	// if not specified.
373	globalEval: function( code, options, doc ) {
374		DOMEval( code, { nonce: options && options.nonce }, doc );
375	},
376
377	each: function( obj, callback ) {
378		var length, i = 0;
379
380		if ( isArrayLike( obj ) ) {
381			length = obj.length;
382			for ( ; i < length; i++ ) {
383				if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
384					break;
385				}
386			}
387		} else {
388			for ( i in obj ) {
389				if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
390					break;
391				}
392			}
393		}
394
395		return obj;
396	},
397
398
399	// Retrieve the text value of an array of DOM nodes
400	text: function( elem ) {
401		var node,
402			ret = "",
403			i = 0,
404			nodeType = elem.nodeType;
405
406		if ( !nodeType ) {
407
408			// If no nodeType, this is expected to be an array
409			while ( ( node = elem[ i++ ] ) ) {
410
411				// Do not traverse comment nodes
412				ret += jQuery.text( node );
413			}
414		}
415		if ( nodeType === 1 || nodeType === 11 ) {
416			return elem.textContent;
417		}
418		if ( nodeType === 9 ) {
419			return elem.documentElement.textContent;
420		}
421		if ( nodeType === 3 || nodeType === 4 ) {
422			return elem.nodeValue;
423		}
424
425		// Do not include comment or processing instruction nodes
426
427		return ret;
428	},
429
430	// results is for internal usage only
431	makeArray: function( arr, results ) {
432		var ret = results || [];
433
434		if ( arr != null ) {
435			if ( isArrayLike( Object( arr ) ) ) {
436				jQuery.merge( ret,
437					typeof arr === "string" ?
438						[ arr ] : arr
439				);
440			} else {
441				push.call( ret, arr );
442			}
443		}
444
445		return ret;
446	},
447
448	inArray: function( elem, arr, i ) {
449		return arr == null ? -1 : indexOf.call( arr, elem, i );
450	},
451
452	isXMLDoc: function( elem ) {
453		var namespace = elem && elem.namespaceURI,
454			docElem = elem && ( elem.ownerDocument || elem ).documentElement;
455
456		// Assume HTML when documentElement doesn't yet exist, such as inside
457		// document fragments.
458		return !rhtmlSuffix.test( namespace || docElem && docElem.nodeName || "HTML" );
459	},
460
461	// Support: Android <=4.0 only, PhantomJS 1 only
462	// push.apply(_, arraylike) throws on ancient WebKit
463	merge: function( first, second ) {
464		var len = +second.length,
465			j = 0,
466			i = first.length;
467
468		for ( ; j < len; j++ ) {
469			first[ i++ ] = second[ j ];
470		}
471
472		first.length = i;
473
474		return first;
475	},
476
477	grep: function( elems, callback, invert ) {
478		var callbackInverse,
479			matches = [],
480			i = 0,
481			length = elems.length,
482			callbackExpect = !invert;
483
484		// Go through the array, only saving the items
485		// that pass the validator function
486		for ( ; i < length; i++ ) {
487			callbackInverse = !callback( elems[ i ], i );
488			if ( callbackInverse !== callbackExpect ) {
489				matches.push( elems[ i ] );
490			}
491		}
492
493		return matches;
494	},
495
496	// arg is for internal usage only
497	map: function( elems, callback, arg ) {
498		var length, value,
499			i = 0,
500			ret = [];
501
502		// Go through the array, translating each of the items to their new values
503		if ( isArrayLike( elems ) ) {
504			length = elems.length;
505			for ( ; i < length; i++ ) {
506				value = callback( elems[ i ], i, arg );
507
508				if ( value != null ) {
509					ret.push( value );
510				}
511			}
512
513		// Go through every key on the object,
514		} else {
515			for ( i in elems ) {
516				value = callback( elems[ i ], i, arg );
517
518				if ( value != null ) {
519					ret.push( value );
520				}
521			}
522		}
523
524		// Flatten any nested arrays
525		return flat( ret );
526	},
527
528	// A global GUID counter for objects
529	guid: 1,
530
531	// jQuery.support is not used in Core but other projects attach their
532	// properties to it so it needs to exist.
533	support: support
534} );
535
536if ( typeof Symbol === "function" ) {
537	jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ];
538}
539
540// Populate the class2type map
541jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
542	function( _i, name ) {
543		class2type[ "[object " + name + "]" ] = name.toLowerCase();
544	} );
545
546function isArrayLike( obj ) {
547
548	// Support: real iOS 8.2 only (not reproducible in simulator)
549	// `in` check used to prevent JIT error (gh-2145)
550	// hasOwn isn't used here due to false negatives
551	// regarding Nodelist length in IE
552	var length = !!obj && "length" in obj && obj.length,
553		type = toType( obj );
554
555	if ( isFunction( obj ) || isWindow( obj ) ) {
556		return false;
557	}
558
559	return type === "array" || length === 0 ||
560		typeof length === "number" && length > 0 && ( length - 1 ) in obj;
561}
562
563
564function nodeName( elem, name ) {
565
566	return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
567
568}
569var pop = arr.pop;
570
571
572var sort = arr.sort;
573
574
575var splice = arr.splice;
576
577
578var whitespace = "[\\x20\\t\\r\\n\\f]";
579
580
581var rtrimCSS = new RegExp(
582	"^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$",
583	"g"
584);
585
586
587
588
589// Note: an element does not contain itself
590jQuery.contains = function( a, b ) {
591	var bup = b && b.parentNode;
592
593	return a === bup || !!( bup && bup.nodeType === 1 && (
594
595		// Support: IE 9 - 11+
596		// IE doesn't have `contains` on SVG.
597		a.contains ?
598			a.contains( bup ) :
599			a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
600	) );
601};
602
603
604
605
606// CSS string/identifier serialization
607// https://drafts.csswg.org/cssom/#common-serializing-idioms
608var rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g;
609
610function fcssescape( ch, asCodePoint ) {
611	if ( asCodePoint ) {
612
613		// U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER
614		if ( ch === "\0" ) {
615			return "\uFFFD";
616		}
617
618		// Control characters and (dependent upon position) numbers get escaped as code points
619		return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " ";
620	}
621
622	// Other potentially-special ASCII characters get backslash-escaped
623	return "\\" + ch;
624}
625
626jQuery.escapeSelector = function( sel ) {
627	return ( sel + "" ).replace( rcssescape, fcssescape );
628};
629
630
631
632
633var preferredDoc = document,
634	pushNative = push;
635
636( function() {
637
638var i,
639	Expr,
640	outermostContext,
641	sortInput,
642	hasDuplicate,
643	push = pushNative,
644
645	// Local document vars
646	document,
647	documentElement,
648	documentIsHTML,
649	rbuggyQSA,
650	matches,
651
652	// Instance-specific data
653	expando = jQuery.expando,
654	dirruns = 0,
655	done = 0,
656	classCache = createCache(),
657	tokenCache = createCache(),
658	compilerCache = createCache(),
659	nonnativeSelectorCache = createCache(),
660	sortOrder = function( a, b ) {
661		if ( a === b ) {
662			hasDuplicate = true;
663		}
664		return 0;
665	},
666
667	booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|" +
668		"loop|multiple|open|readonly|required|scoped",
669
670	// Regular expressions
671
672	// https://www.w3.org/TR/css-syntax-3/#ident-token-diagram
673	identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace +
674		"?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+",
675
676	// Attribute selectors: https://www.w3.org/TR/selectors/#attribute-selectors
677	attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace +
678
679		// Operator (capture 2)
680		"*([*^$|!~]?=)" + whitespace +
681
682		// "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
683		"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" +
684		whitespace + "*\\]",
685
686	pseudos = ":(" + identifier + ")(?:\\((" +
687
688		// To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
689		// 1. quoted (capture 3; capture 4 or capture 5)
690		"('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
691
692		// 2. simple (capture 6)
693		"((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
694
695		// 3. anything else (capture 2)
696		".*" +
697		")\\)|)",
698
699	// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
700	rwhitespace = new RegExp( whitespace + "+", "g" ),
701
702	rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
703	rleadingCombinator = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" +
704		whitespace + "*" ),
705	rdescend = new RegExp( whitespace + "|>" ),
706
707	rpseudo = new RegExp( pseudos ),
708	ridentifier = new RegExp( "^" + identifier + "$" ),
709
710	matchExpr = {
711		ID: new RegExp( "^#(" + identifier + ")" ),
712		CLASS: new RegExp( "^\\.(" + identifier + ")" ),
713		TAG: new RegExp( "^(" + identifier + "|[*])" ),
714		ATTR: new RegExp( "^" + attributes ),
715		PSEUDO: new RegExp( "^" + pseudos ),
716		CHILD: new RegExp(
717			"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" +
718				whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" +
719				whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
720		bool: new RegExp( "^(?:" + booleans + ")$", "i" ),
721
722		// For use in libraries implementing .is()
723		// We use this for POS matching in `select`
724		needsContext: new RegExp( "^" + whitespace +
725			"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace +
726			"*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
727	},
728
729	rinputs = /^(?:input|select|textarea|button)$/i,
730	rheader = /^h\d$/i,
731
732	// Easily-parseable/retrievable ID or TAG or CLASS selectors
733	rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
734
735	rsibling = /[+~]/,
736
737	// CSS escapes
738	// https://www.w3.org/TR/CSS21/syndata.html#escaped-characters
739	runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace +
740		"?|\\\\([^\\r\\n\\f])", "g" ),
741	funescape = function( escape, nonHex ) {
742		var high = "0x" + escape.slice( 1 ) - 0x10000;
743
744		if ( nonHex ) {
745
746			// Strip the backslash prefix from a non-hex escape sequence
747			return nonHex;
748		}
749
750		// Replace a hexadecimal escape sequence with the encoded Unicode code point
751		// Support: IE <=11+
752		// For values outside the Basic Multilingual Plane (BMP), manually construct a
753		// surrogate pair
754		return high < 0 ?
755			String.fromCharCode( high + 0x10000 ) :
756			String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
757	},
758
759	// Used for iframes; see `setDocument`.
760	// Support: IE 9 - 11+, Edge 12 - 18+
761	// Removing the function wrapper causes a "Permission Denied"
762	// error in IE/Edge.
763	unloadHandler = function() {
764		setDocument();
765	},
766
767	inDisabledFieldset = addCombinator(
768		function( elem ) {
769			return elem.disabled === true && nodeName( elem, "fieldset" );
770		},
771		{ dir: "parentNode", next: "legend" }
772	);
773
774// Support: IE <=9 only
775// Accessing document.activeElement can throw unexpectedly
776// https://bugs.jquery.com/ticket/13393
777function safeActiveElement() {
778	try {
779		return document.activeElement;
780	} catch ( err ) { }
781}
782
783// Optimize for push.apply( _, NodeList )
784try {
785	push.apply(
786		( arr = slice.call( preferredDoc.childNodes ) ),
787		preferredDoc.childNodes
788	);
789
790	// Support: Android <=4.0
791	// Detect silently failing push.apply
792	// eslint-disable-next-line no-unused-expressions
793	arr[ preferredDoc.childNodes.length ].nodeType;
794} catch ( e ) {
795	push = {
796		apply: function( target, els ) {
797			pushNative.apply( target, slice.call( els ) );
798		},
799		call: function( target ) {
800			pushNative.apply( target, slice.call( arguments, 1 ) );
801		}
802	};
803}
804
805function find( selector, context, results, seed ) {
806	var m, i, elem, nid, match, groups, newSelector,
807		newContext = context && context.ownerDocument,
808
809		// nodeType defaults to 9, since context defaults to document
810		nodeType = context ? context.nodeType : 9;
811
812	results = results || [];
813
814	// Return early from calls with invalid selector or context
815	if ( typeof selector !== "string" || !selector ||
816		nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
817
818		return results;
819	}
820
821	// Try to shortcut find operations (as opposed to filters) in HTML documents
822	if ( !seed ) {
823		setDocument( context );
824		context = context || document;
825
826		if ( documentIsHTML ) {
827
828			// If the selector is sufficiently simple, try using a "get*By*" DOM method
829			// (excepting DocumentFragment context, where the methods don't exist)
830			if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) {
831
832				// ID selector
833				if ( ( m = match[ 1 ] ) ) {
834
835					// Document context
836					if ( nodeType === 9 ) {
837						if ( ( elem = context.getElementById( m ) ) ) {
838
839							// Support: IE 9 only
840							// getElementById can match elements by name instead of ID
841							if ( elem.id === m ) {
842								push.call( results, elem );
843								return results;
844							}
845						} else {
846							return results;
847						}
848
849					// Element context
850					} else {
851
852						// Support: IE 9 only
853						// getElementById can match elements by name instead of ID
854						if ( newContext && ( elem = newContext.getElementById( m ) ) &&
855							find.contains( context, elem ) &&
856							elem.id === m ) {
857
858							push.call( results, elem );
859							return results;
860						}
861					}
862
863				// Type selector
864				} else if ( match[ 2 ] ) {
865					push.apply( results, context.getElementsByTagName( selector ) );
866					return results;
867
868				// Class selector
869				} else if ( ( m = match[ 3 ] ) && context.getElementsByClassName ) {
870					push.apply( results, context.getElementsByClassName( m ) );
871					return results;
872				}
873			}
874
875			// Take advantage of querySelectorAll
876			if ( !nonnativeSelectorCache[ selector + " " ] &&
877				( !rbuggyQSA || !rbuggyQSA.test( selector ) ) ) {
878
879				newSelector = selector;
880				newContext = context;
881
882				// qSA considers elements outside a scoping root when evaluating child or
883				// descendant combinators, which is not what we want.
884				// In such cases, we work around the behavior by prefixing every selector in the
885				// list with an ID selector referencing the scope context.
886				// The technique has to be used as well when a leading combinator is used
887				// as such selectors are not recognized by querySelectorAll.
888				// Thanks to Andrew Dupont for this technique.
889				if ( nodeType === 1 &&
890					( rdescend.test( selector ) || rleadingCombinator.test( selector ) ) ) {
891
892					// Expand context for sibling selectors
893					newContext = rsibling.test( selector ) && testContext( context.parentNode ) ||
894						context;
895
896					// We can use :scope instead of the ID hack if the browser
897					// supports it & if we're not changing the context.
898					// Support: IE 11+, Edge 17 - 18+
899					// IE/Edge sometimes throw a "Permission denied" error when
900					// strict-comparing two documents; shallow comparisons work.
901					// eslint-disable-next-line eqeqeq
902					if ( newContext != context || !support.scope ) {
903
904						// Capture the context ID, setting it first if necessary
905						if ( ( nid = context.getAttribute( "id" ) ) ) {
906							nid = jQuery.escapeSelector( nid );
907						} else {
908							context.setAttribute( "id", ( nid = expando ) );
909						}
910					}
911
912					// Prefix every selector in the list
913					groups = tokenize( selector );
914					i = groups.length;
915					while ( i-- ) {
916						groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " +
917							toSelector( groups[ i ] );
918					}
919					newSelector = groups.join( "," );
920				}
921
922				try {
923					push.apply( results,
924						newContext.querySelectorAll( newSelector )
925					);
926					return results;
927				} catch ( qsaError ) {
928					nonnativeSelectorCache( selector, true );
929				} finally {
930					if ( nid === expando ) {
931						context.removeAttribute( "id" );
932					}
933				}
934			}
935		}
936	}
937
938	// All others
939	return select( selector.replace( rtrimCSS, "$1" ), context, results, seed );
940}
941
942/**
943 * Create key-value caches of limited size
944 * @returns {function(string, object)} Returns the Object data after storing it on itself with
945 *	property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
946 *	deleting the oldest entry
947 */
948function createCache() {
949	var keys = [];
950
951	function cache( key, value ) {
952
953		// Use (key + " ") to avoid collision with native prototype properties
954		// (see https://github.com/jquery/sizzle/issues/157)
955		if ( keys.push( key + " " ) > Expr.cacheLength ) {
956
957			// Only keep the most recent entries
958			delete cache[ keys.shift() ];
959		}
960		return ( cache[ key + " " ] = value );
961	}
962	return cache;
963}
964
965/**
966 * Mark a function for special use by jQuery selector module
967 * @param {Function} fn The function to mark
968 */
969function markFunction( fn ) {
970	fn[ expando ] = true;
971	return fn;
972}
973
974/**
975 * Support testing using an element
976 * @param {Function} fn Passed the created element and returns a boolean result
977 */
978function assert( fn ) {
979	var el = document.createElement( "fieldset" );
980
981	try {
982		return !!fn( el );
983	} catch ( e ) {
984		return false;
985	} finally {
986
987		// Remove from its parent by default
988		if ( el.parentNode ) {
989			el.parentNode.removeChild( el );
990		}
991
992		// release memory in IE
993		el = null;
994	}
995}
996
997/**
998 * Returns a function to use in pseudos for input types
999 * @param {String} type
1000 */
1001function createInputPseudo( type ) {
1002	return function( elem ) {
1003		return nodeName( elem, "input" ) && elem.type === type;
1004	};
1005}
1006
1007/**
1008 * Returns a function to use in pseudos for buttons
1009 * @param {String} type
1010 */
1011function createButtonPseudo( type ) {
1012	return function( elem ) {
1013		return ( nodeName( elem, "input" ) || nodeName( elem, "button" ) ) &&
1014			elem.type === type;
1015	};
1016}
1017
1018/**
1019 * Returns a function to use in pseudos for :enabled/:disabled
1020 * @param {Boolean} disabled true for :disabled; false for :enabled
1021 */
1022function createDisabledPseudo( disabled ) {
1023
1024	// Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable
1025	return function( elem ) {
1026
1027		// Only certain elements can match :enabled or :disabled
1028		// https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled
1029		// https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled
1030		if ( "form" in elem ) {
1031
1032			// Check for inherited disabledness on relevant non-disabled elements:
1033			// * listed form-associated elements in a disabled fieldset
1034			//   https://html.spec.whatwg.org/multipage/forms.html#category-listed
1035			//   https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled
1036			// * option elements in a disabled optgroup
1037			//   https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled
1038			// All such elements have a "form" property.
1039			if ( elem.parentNode && elem.disabled === false ) {
1040
1041				// Option elements defer to a parent optgroup if present
1042				if ( "label" in elem ) {
1043					if ( "label" in elem.parentNode ) {
1044						return elem.parentNode.disabled === disabled;
1045					} else {
1046						return elem.disabled === disabled;
1047					}
1048				}
1049
1050				// Support: IE 6 - 11+
1051				// Use the isDisabled shortcut property to check for disabled fieldset ancestors
1052				return elem.isDisabled === disabled ||
1053
1054					// Where there is no isDisabled, check manually
1055					elem.isDisabled !== !disabled &&
1056						inDisabledFieldset( elem ) === disabled;
1057			}
1058
1059			return elem.disabled === disabled;
1060
1061		// Try to winnow out elements that can't be disabled before trusting the disabled property.
1062		// Some victims get caught in our net (label, legend, menu, track), but it shouldn't
1063		// even exist on them, let alone have a boolean value.
1064		} else if ( "label" in elem ) {
1065			return elem.disabled === disabled;
1066		}
1067
1068		// Remaining elements are neither :enabled nor :disabled
1069		return false;
1070	};
1071}
1072
1073/**
1074 * Returns a function to use in pseudos for positionals
1075 * @param {Function} fn
1076 */
1077function createPositionalPseudo( fn ) {
1078	return markFunction( function( argument ) {
1079		argument = +argument;
1080		return markFunction( function( seed, matches ) {
1081			var j,
1082				matchIndexes = fn( [], seed.length, argument ),
1083				i = matchIndexes.length;
1084
1085			// Match elements found at the specified indexes
1086			while ( i-- ) {
1087				if ( seed[ ( j = matchIndexes[ i ] ) ] ) {
1088					seed[ j ] = !( matches[ j ] = seed[ j ] );
1089				}
1090			}
1091		} );
1092	} );
1093}
1094
1095/**
1096 * Checks a node for validity as a jQuery selector context
1097 * @param {Element|Object=} context
1098 * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
1099 */
1100function testContext( context ) {
1101	return context && typeof context.getElementsByTagName !== "undefined" && context;
1102}
1103
1104/**
1105 * Sets document-related variables once based on the current document
1106 * @param {Element|Object} [node] An element or document object to use to set the document
1107 * @returns {Object} Returns the current document
1108 */
1109function setDocument( node ) {
1110	var subWindow,
1111		doc = node ? node.ownerDocument || node : preferredDoc;
1112
1113	// Return early if doc is invalid or already selected
1114	// Support: IE 11+, Edge 17 - 18+
1115	// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
1116	// two documents; shallow comparisons work.
1117	// eslint-disable-next-line eqeqeq
1118	if ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) {
1119		return document;
1120	}
1121
1122	// Update global variables
1123	document = doc;
1124	documentElement = document.documentElement;
1125	documentIsHTML = !jQuery.isXMLDoc( document );
1126
1127	// Support: iOS 7 only, IE 9 - 11+
1128	// Older browsers didn't support unprefixed `matches`.
1129	matches = documentElement.matches ||
1130		documentElement.webkitMatchesSelector ||
1131		documentElement.msMatchesSelector;
1132
1133	// Support: IE 9 - 11+, Edge 12 - 18+
1134	// Accessing iframe documents after unload throws "permission denied" errors
1135	// (see trac-13936).
1136	// Limit the fix to IE & Edge Legacy; despite Edge 15+ implementing `matches`,
1137	// all IE 9+ and Edge Legacy versions implement `msMatchesSelector` as well.
1138	if ( documentElement.msMatchesSelector &&
1139
1140		// Support: IE 11+, Edge 17 - 18+
1141		// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
1142		// two documents; shallow comparisons work.
1143		// eslint-disable-next-line eqeqeq
1144		preferredDoc != document &&
1145		( subWindow = document.defaultView ) && subWindow.top !== subWindow ) {
1146
1147		// Support: IE 9 - 11+, Edge 12 - 18+
1148		subWindow.addEventListener( "unload", unloadHandler );
1149	}
1150
1151	// Support: IE <10
1152	// Check if getElementById returns elements by name
1153	// The broken getElementById methods don't pick up programmatically-set names,
1154	// so use a roundabout getElementsByName test
1155	support.getById = assert( function( el ) {
1156		documentElement.appendChild( el ).id = jQuery.expando;
1157		return !document.getElementsByName ||
1158			!document.getElementsByName( jQuery.expando ).length;
1159	} );
1160
1161	// Support: IE 9 only
1162	// Check to see if it's possible to do matchesSelector
1163	// on a disconnected node.
1164	support.disconnectedMatch = assert( function( el ) {
1165		return matches.call( el, "*" );
1166	} );
1167
1168	// Support: IE 9 - 11+, Edge 12 - 18+
1169	// IE/Edge don't support the :scope pseudo-class.
1170	support.scope = assert( function() {
1171		return document.querySelectorAll( ":scope" );
1172	} );
1173
1174	// Support: Chrome 105 - 111 only, Safari 15.4 - 16.3 only
1175	// Make sure the `:has()` argument is parsed unforgivingly.
1176	// We include `*` in the test to detect buggy implementations that are
1177	// _selectively_ forgiving (specifically when the list includes at least
1178	// one valid selector).
1179	// Note that we treat complete lack of support for `:has()` as if it were
1180	// spec-compliant support, which is fine because use of `:has()` in such
1181	// environments will fail in the qSA path and fall back to jQuery traversal
1182	// anyway.
1183	support.cssHas = assert( function() {
1184		try {
1185			document.querySelector( ":has(*,:jqfake)" );
1186			return false;
1187		} catch ( e ) {
1188			return true;
1189		}
1190	} );
1191
1192	// ID filter and find
1193	if ( support.getById ) {
1194		Expr.filter.ID = function( id ) {
1195			var attrId = id.replace( runescape, funescape );
1196			return function( elem ) {
1197				return elem.getAttribute( "id" ) === attrId;
1198			};
1199		};
1200		Expr.find.ID = function( id, context ) {
1201			if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
1202				var elem = context.getElementById( id );
1203				return elem ? [ elem ] : [];
1204			}
1205		};
1206	} else {
1207		Expr.filter.ID =  function( id ) {
1208			var attrId = id.replace( runescape, funescape );
1209			return function( elem ) {
1210				var node = typeof elem.getAttributeNode !== "undefined" &&
1211					elem.getAttributeNode( "id" );
1212				return node && node.value === attrId;
1213			};
1214		};
1215
1216		// Support: IE 6 - 7 only
1217		// getElementById is not reliable as a find shortcut
1218		Expr.find.ID = function( id, context ) {
1219			if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
1220				var node, i, elems,
1221					elem = context.getElementById( id );
1222
1223				if ( elem ) {
1224
1225					// Verify the id attribute
1226					node = elem.getAttributeNode( "id" );
1227					if ( node && node.value === id ) {
1228						return [ elem ];
1229					}
1230
1231					// Fall back on getElementsByName
1232					elems = context.getElementsByName( id );
1233					i = 0;
1234					while ( ( elem = elems[ i++ ] ) ) {
1235						node = elem.getAttributeNode( "id" );
1236						if ( node && node.value === id ) {
1237							return [ elem ];
1238						}
1239					}
1240				}
1241
1242				return [];
1243			}
1244		};
1245	}
1246
1247	// Tag
1248	Expr.find.TAG = function( tag, context ) {
1249		if ( typeof context.getElementsByTagName !== "undefined" ) {
1250			return context.getElementsByTagName( tag );
1251
1252		// DocumentFragment nodes don't have gEBTN
1253		} else {
1254			return context.querySelectorAll( tag );
1255		}
1256	};
1257
1258	// Class
1259	Expr.find.CLASS = function( className, context ) {
1260		if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) {
1261			return context.getElementsByClassName( className );
1262		}
1263	};
1264
1265	/* QSA/matchesSelector
1266	---------------------------------------------------------------------- */
1267
1268	// QSA and matchesSelector support
1269
1270	rbuggyQSA = [];
1271
1272	// Build QSA regex
1273	// Regex strategy adopted from Diego Perini
1274	assert( function( el ) {
1275
1276		var input;
1277
1278		documentElement.appendChild( el ).innerHTML =
1279			"<a id='" + expando + "' href='' disabled='disabled'></a>" +
1280			"<select id='" + expando + "-\r\\' disabled='disabled'>" +
1281			"<option selected=''></option></select>";
1282
1283		// Support: iOS <=7 - 8 only
1284		// Boolean attributes and "value" are not treated correctly in some XML documents
1285		if ( !el.querySelectorAll( "[selected]" ).length ) {
1286			rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
1287		}
1288
1289		// Support: iOS <=7 - 8 only
1290		if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
1291			rbuggyQSA.push( "~=" );
1292		}
1293
1294		// Support: iOS 8 only
1295		// https://bugs.webkit.org/show_bug.cgi?id=136851
1296		// In-page `selector#id sibling-combinator selector` fails
1297		if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) {
1298			rbuggyQSA.push( ".#.+[+~]" );
1299		}
1300
1301		// Support: Chrome <=105+, Firefox <=104+, Safari <=15.4+
1302		// In some of the document kinds, these selectors wouldn't work natively.
1303		// This is probably OK but for backwards compatibility we want to maintain
1304		// handling them through jQuery traversal in jQuery 3.x.
1305		if ( !el.querySelectorAll( ":checked" ).length ) {
1306			rbuggyQSA.push( ":checked" );
1307		}
1308
1309		// Support: Windows 8 Native Apps
1310		// The type and name attributes are restricted during .innerHTML assignment
1311		input = document.createElement( "input" );
1312		input.setAttribute( "type", "hidden" );
1313		el.appendChild( input ).setAttribute( "name", "D" );
1314
1315		// Support: IE 9 - 11+
1316		// IE's :disabled selector does not pick up the children of disabled fieldsets
1317		// Support: Chrome <=105+, Firefox <=104+, Safari <=15.4+
1318		// In some of the document kinds, these selectors wouldn't work natively.
1319		// This is probably OK but for backwards compatibility we want to maintain
1320		// handling them through jQuery traversal in jQuery 3.x.
1321		documentElement.appendChild( el ).disabled = true;
1322		if ( el.querySelectorAll( ":disabled" ).length !== 2 ) {
1323			rbuggyQSA.push( ":enabled", ":disabled" );
1324		}
1325
1326		// Support: IE 11+, Edge 15 - 18+
1327		// IE 11/Edge don't find elements on a `[name='']` query in some cases.
1328		// Adding a temporary attribute to the document before the selection works
1329		// around the issue.
1330		// Interestingly, IE 10 & older don't seem to have the issue.
1331		input = document.createElement( "input" );
1332		input.setAttribute( "name", "" );
1333		el.appendChild( input );
1334		if ( !el.querySelectorAll( "[name='']" ).length ) {
1335			rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" +
1336				whitespace + "*(?:''|\"\")" );
1337		}
1338	} );
1339
1340	if ( !support.cssHas ) {
1341
1342		// Support: Chrome 105 - 110+, Safari 15.4 - 16.3+
1343		// Our regular `try-catch` mechanism fails to detect natively-unsupported
1344		// pseudo-classes inside `:has()` (such as `:has(:contains("Foo"))`)
1345		// in browsers that parse the `:has()` argument as a forgiving selector list.
1346		// https://drafts.csswg.org/selectors/#relational now requires the argument
1347		// to be parsed unforgivingly, but browsers have not yet fully adjusted.
1348		rbuggyQSA.push( ":has" );
1349	}
1350
1351	rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) );
1352
1353	/* Sorting
1354	---------------------------------------------------------------------- */
1355
1356	// Document order sorting
1357	sortOrder = function( a, b ) {
1358
1359		// Flag for duplicate removal
1360		if ( a === b ) {
1361			hasDuplicate = true;
1362			return 0;
1363		}
1364
1365		// Sort on method existence if only one input has compareDocumentPosition
1366		var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
1367		if ( compare ) {
1368			return compare;
1369		}
1370
1371		// Calculate position if both inputs belong to the same document
1372		// Support: IE 11+, Edge 17 - 18+
1373		// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
1374		// two documents; shallow comparisons work.
1375		// eslint-disable-next-line eqeqeq
1376		compare = ( a.ownerDocument || a ) == ( b.ownerDocument || b ) ?
1377			a.compareDocumentPosition( b ) :
1378
1379			// Otherwise we know they are disconnected
1380			1;
1381
1382		// Disconnected nodes
1383		if ( compare & 1 ||
1384			( !support.sortDetached && b.compareDocumentPosition( a ) === compare ) ) {
1385
1386			// Choose the first element that is related to our preferred document
1387			// Support: IE 11+, Edge 17 - 18+
1388			// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
1389			// two documents; shallow comparisons work.
1390			// eslint-disable-next-line eqeqeq
1391			if ( a === document || a.ownerDocument == preferredDoc &&
1392				find.contains( preferredDoc, a ) ) {
1393				return -1;
1394			}
1395
1396			// Support: IE 11+, Edge 17 - 18+
1397			// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
1398			// two documents; shallow comparisons work.
1399			// eslint-disable-next-line eqeqeq
1400			if ( b === document || b.ownerDocument == preferredDoc &&
1401				find.contains( preferredDoc, b ) ) {
1402				return 1;
1403			}
1404
1405			// Maintain original order
1406			return sortInput ?
1407				( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
1408				0;
1409		}
1410
1411		return compare & 4 ? -1 : 1;
1412	};
1413
1414	return document;
1415}
1416
1417find.matches = function( expr, elements ) {
1418	return find( expr, null, null, elements );
1419};
1420
1421find.matchesSelector = function( elem, expr ) {
1422	setDocument( elem );
1423
1424	if ( documentIsHTML &&
1425		!nonnativeSelectorCache[ expr + " " ] &&
1426		( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) {
1427
1428		try {
1429			var ret = matches.call( elem, expr );
1430
1431			// IE 9's matchesSelector returns false on disconnected nodes
1432			if ( ret || support.disconnectedMatch ||
1433
1434					// As well, disconnected nodes are said to be in a document
1435					// fragment in IE 9
1436					elem.document && elem.document.nodeType !== 11 ) {
1437				return ret;
1438			}
1439		} catch ( e ) {
1440			nonnativeSelectorCache( expr, true );
1441		}
1442	}
1443
1444	return find( expr, document, null, [ elem ] ).length > 0;
1445};
1446
1447find.contains = function( context, elem ) {
1448
1449	// Set document vars if needed
1450	// Support: IE 11+, Edge 17 - 18+
1451	// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
1452	// two documents; shallow comparisons work.
1453	// eslint-disable-next-line eqeqeq
1454	if ( ( context.ownerDocument || context ) != document ) {
1455		setDocument( context );
1456	}
1457	return jQuery.contains( context, elem );
1458};
1459
1460
1461find.attr = function( elem, name ) {
1462
1463	// Set document vars if needed
1464	// Support: IE 11+, Edge 17 - 18+
1465	// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
1466	// two documents; shallow comparisons work.
1467	// eslint-disable-next-line eqeqeq
1468	if ( ( elem.ownerDocument || elem ) != document ) {
1469		setDocument( elem );
1470	}
1471
1472	var fn = Expr.attrHandle[ name.toLowerCase() ],
1473
1474		// Don't get fooled by Object.prototype properties (see trac-13807)
1475		val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
1476			fn( elem, name, !documentIsHTML ) :
1477			undefined;
1478
1479	if ( val !== undefined ) {
1480		return val;
1481	}
1482
1483	return elem.getAttribute( name );
1484};
1485
1486find.error = function( msg ) {
1487	throw new Error( "Syntax error, unrecognized expression: " + msg );
1488};
1489
1490/**
1491 * Document sorting and removing duplicates
1492 * @param {ArrayLike} results
1493 */
1494jQuery.uniqueSort = function( results ) {
1495	var elem,
1496		duplicates = [],
1497		j = 0,
1498		i = 0;
1499
1500	// Unless we *know* we can detect duplicates, assume their presence
1501	//
1502	// Support: Android <=4.0+
1503	// Testing for detecting duplicates is unpredictable so instead assume we can't
1504	// depend on duplicate detection in all browsers without a stable sort.
1505	hasDuplicate = !support.sortStable;
1506	sortInput = !support.sortStable && slice.call( results, 0 );
1507	sort.call( results, sortOrder );
1508
1509	if ( hasDuplicate ) {
1510		while ( ( elem = results[ i++ ] ) ) {
1511			if ( elem === results[ i ] ) {
1512				j = duplicates.push( i );
1513			}
1514		}
1515		while ( j-- ) {
1516			splice.call( results, duplicates[ j ], 1 );
1517		}
1518	}
1519
1520	// Clear input after sorting to release objects
1521	// See https://github.com/jquery/sizzle/pull/225
1522	sortInput = null;
1523
1524	return results;
1525};
1526
1527jQuery.fn.uniqueSort = function() {
1528	return this.pushStack( jQuery.uniqueSort( slice.apply( this ) ) );
1529};
1530
1531Expr = jQuery.expr = {
1532
1533	// Can be adjusted by the user
1534	cacheLength: 50,
1535
1536	createPseudo: markFunction,
1537
1538	match: matchExpr,
1539
1540	attrHandle: {},
1541
1542	find: {},
1543
1544	relative: {
1545		">": { dir: "parentNode", first: true },
1546		" ": { dir: "parentNode" },
1547		"+": { dir: "previousSibling", first: true },
1548		"~": { dir: "previousSibling" }
1549	},
1550
1551	preFilter: {
1552		ATTR: function( match ) {
1553			match[ 1 ] = match[ 1 ].replace( runescape, funescape );
1554
1555			// Move the given value to match[3] whether quoted or unquoted
1556			match[ 3 ] = ( match[ 3 ] || match[ 4 ] || match[ 5 ] || "" )
1557				.replace( runescape, funescape );
1558
1559			if ( match[ 2 ] === "~=" ) {
1560				match[ 3 ] = " " + match[ 3 ] + " ";
1561			}
1562
1563			return match.slice( 0, 4 );
1564		},
1565
1566		CHILD: function( match ) {
1567
1568			/* matches from matchExpr["CHILD"]
1569				1 type (only|nth|...)
1570				2 what (child|of-type)
1571				3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
1572				4 xn-component of xn+y argument ([+-]?\d*n|)
1573				5 sign of xn-component
1574				6 x of xn-component
1575				7 sign of y-component
1576				8 y of y-component
1577			*/
1578			match[ 1 ] = match[ 1 ].toLowerCase();
1579
1580			if ( match[ 1 ].slice( 0, 3 ) === "nth" ) {
1581
1582				// nth-* requires argument
1583				if ( !match[ 3 ] ) {
1584					find.error( match[ 0 ] );
1585				}
1586
1587				// numeric x and y parameters for Expr.filter.CHILD
1588				// remember that false/true cast respectively to 0/1
1589				match[ 4 ] = +( match[ 4 ] ?
1590					match[ 5 ] + ( match[ 6 ] || 1 ) :
1591					2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" )
1592				);
1593				match[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === "odd" );
1594
1595			// other types prohibit arguments
1596			} else if ( match[ 3 ] ) {
1597				find.error( match[ 0 ] );
1598			}
1599
1600			return match;
1601		},
1602
1603		PSEUDO: function( match ) {
1604			var excess,
1605				unquoted = !match[ 6 ] && match[ 2 ];
1606
1607			if ( matchExpr.CHILD.test( match[ 0 ] ) ) {
1608				return null;
1609			}
1610
1611			// Accept quoted arguments as-is
1612			if ( match[ 3 ] ) {
1613				match[ 2 ] = match[ 4 ] || match[ 5 ] || "";
1614
1615			// Strip excess characters from unquoted arguments
1616			} else if ( unquoted && rpseudo.test( unquoted ) &&
1617
1618				// Get excess from tokenize (recursively)
1619				( excess = tokenize( unquoted, true ) ) &&
1620
1621				// advance to the next closing parenthesis
1622				( excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length ) ) {
1623
1624				// excess is a negative index
1625				match[ 0 ] = match[ 0 ].slice( 0, excess );
1626				match[ 2 ] = unquoted.slice( 0, excess );
1627			}
1628
1629			// Return only captures needed by the pseudo filter method (type and argument)
1630			return match.slice( 0, 3 );
1631		}
1632	},
1633
1634	filter: {
1635
1636		TAG: function( nodeNameSelector ) {
1637			var expectedNodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
1638			return nodeNameSelector === "*" ?
1639				function() {
1640					return true;
1641				} :
1642				function( elem ) {
1643					return nodeName( elem, expectedNodeName );
1644				};
1645		},
1646
1647		CLASS: function( className ) {
1648			var pattern = classCache[ className + " " ];
1649
1650			return pattern ||
1651				( pattern = new RegExp( "(^|" + whitespace + ")" + className +
1652					"(" + whitespace + "|$)" ) ) &&
1653				classCache( className, function( elem ) {
1654					return pattern.test(
1655						typeof elem.className === "string" && elem.className ||
1656							typeof elem.getAttribute !== "undefined" &&
1657								elem.getAttribute( "class" ) ||
1658							""
1659					);
1660				} );
1661		},
1662
1663		ATTR: function( name, operator, check ) {
1664			return function( elem ) {
1665				var result = find.attr( elem, name );
1666
1667				if ( result == null ) {
1668					return operator === "!=";
1669				}
1670				if ( !operator ) {
1671					return true;
1672				}
1673
1674				result += "";
1675
1676				if ( operator === "=" ) {
1677					return result === check;
1678				}
1679				if ( operator === "!=" ) {
1680					return result !== check;
1681				}
1682				if ( operator === "^=" ) {
1683					return check && result.indexOf( check ) === 0;
1684				}
1685				if ( operator === "*=" ) {
1686					return check && result.indexOf( check ) > -1;
1687				}
1688				if ( operator === "$=" ) {
1689					return check && result.slice( -check.length ) === check;
1690				}
1691				if ( operator === "~=" ) {
1692					return ( " " + result.replace( rwhitespace, " " ) + " " )
1693						.indexOf( check ) > -1;
1694				}
1695				if ( operator === "|=" ) {
1696					return result === check || result.slice( 0, check.length + 1 ) === check + "-";
1697				}
1698
1699				return false;
1700			};
1701		},
1702
1703		CHILD: function( type, what, _argument, first, last ) {
1704			var simple = type.slice( 0, 3 ) !== "nth",
1705				forward = type.slice( -4 ) !== "last",
1706				ofType = what === "of-type";
1707
1708			return first === 1 && last === 0 ?
1709
1710				// Shortcut for :nth-*(n)
1711				function( elem ) {
1712					return !!elem.parentNode;
1713				} :
1714
1715				function( elem, _context, xml ) {
1716					var cache, outerCache, node, nodeIndex, start,
1717						dir = simple !== forward ? "nextSibling" : "previousSibling",
1718						parent = elem.parentNode,
1719						name = ofType && elem.nodeName.toLowerCase(),
1720						useCache = !xml && !ofType,
1721						diff = false;
1722
1723					if ( parent ) {
1724
1725						// :(first|last|only)-(child|of-type)
1726						if ( simple ) {
1727							while ( dir ) {
1728								node = elem;
1729								while ( ( node = node[ dir ] ) ) {
1730									if ( ofType ?
1731										nodeName( node, name ) :
1732										node.nodeType === 1 ) {
1733
1734										return false;
1735									}
1736								}
1737
1738								// Reverse direction for :only-* (if we haven't yet done so)
1739								start = dir = type === "only" && !start && "nextSibling";
1740							}
1741							return true;
1742						}
1743
1744						start = [ forward ? parent.firstChild : parent.lastChild ];
1745
1746						// non-xml :nth-child(...) stores cache data on `parent`
1747						if ( forward && useCache ) {
1748
1749							// Seek `elem` from a previously-cached index
1750							outerCache = parent[ expando ] || ( parent[ expando ] = {} );
1751							cache = outerCache[ type ] || [];
1752							nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
1753							diff = nodeIndex && cache[ 2 ];
1754							node = nodeIndex && parent.childNodes[ nodeIndex ];
1755
1756							while ( ( node = ++nodeIndex && node && node[ dir ] ||
1757
1758								// Fallback to seeking `elem` from the start
1759								( diff = nodeIndex = 0 ) || start.pop() ) ) {
1760
1761								// When found, cache indexes on `parent` and break
1762								if ( node.nodeType === 1 && ++diff && node === elem ) {
1763									outerCache[ type ] = [ dirruns, nodeIndex, diff ];
1764									break;
1765								}
1766							}
1767
1768						} else {
1769
1770							// Use previously-cached element index if available
1771							if ( useCache ) {
1772								outerCache = elem[ expando ] || ( elem[ expando ] = {} );
1773								cache = outerCache[ type ] || [];
1774								nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
1775								diff = nodeIndex;
1776							}
1777
1778							// xml :nth-child(...)
1779							// or :nth-last-child(...) or :nth(-last)?-of-type(...)
1780							if ( diff === false ) {
1781
1782								// Use the same loop as above to seek `elem` from the start
1783								while ( ( node = ++nodeIndex && node && node[ dir ] ||
1784									( diff = nodeIndex = 0 ) || start.pop() ) ) {
1785
1786									if ( ( ofType ?
1787										nodeName( node, name ) :
1788										node.nodeType === 1 ) &&
1789										++diff ) {
1790
1791										// Cache the index of each encountered element
1792										if ( useCache ) {
1793											outerCache = node[ expando ] ||
1794												( node[ expando ] = {} );
1795											outerCache[ type ] = [ dirruns, diff ];
1796										}
1797
1798										if ( node === elem ) {
1799											break;
1800										}
1801									}
1802								}
1803							}
1804						}
1805
1806						// Incorporate the offset, then check against cycle size
1807						diff -= last;
1808						return diff === first || ( diff % first === 0 && diff / first >= 0 );
1809					}
1810				};
1811		},
1812
1813		PSEUDO: function( pseudo, argument ) {
1814
1815			// pseudo-class names are case-insensitive
1816			// https://www.w3.org/TR/selectors/#pseudo-classes
1817			// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
1818			// Remember that setFilters inherits from pseudos
1819			var args,
1820				fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
1821					find.error( "unsupported pseudo: " + pseudo );
1822
1823			// The user may use createPseudo to indicate that
1824			// arguments are needed to create the filter function
1825			// just as jQuery does
1826			if ( fn[ expando ] ) {
1827				return fn( argument );
1828			}
1829
1830			// But maintain support for old signatures
1831			if ( fn.length > 1 ) {
1832				args = [ pseudo, pseudo, "", argument ];
1833				return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
1834					markFunction( function( seed, matches ) {
1835						var idx,
1836							matched = fn( seed, argument ),
1837							i = matched.length;
1838						while ( i-- ) {
1839							idx = indexOf.call( seed, matched[ i ] );
1840							seed[ idx ] = !( matches[ idx ] = matched[ i ] );
1841						}
1842					} ) :
1843					function( elem ) {
1844						return fn( elem, 0, args );
1845					};
1846			}
1847
1848			return fn;
1849		}
1850	},
1851
1852	pseudos: {
1853
1854		// Potentially complex pseudos
1855		not: markFunction( function( selector ) {
1856
1857			// Trim the selector passed to compile
1858			// to avoid treating leading and trailing
1859			// spaces as combinators
1860			var input = [],
1861				results = [],
1862				matcher = compile( selector.replace( rtrimCSS, "$1" ) );
1863
1864			return matcher[ expando ] ?
1865				markFunction( function( seed, matches, _context, xml ) {
1866					var elem,
1867						unmatched = matcher( seed, null, xml, [] ),
1868						i = seed.length;
1869
1870					// Match elements unmatched by `matcher`
1871					while ( i-- ) {
1872						if ( ( elem = unmatched[ i ] ) ) {
1873							seed[ i ] = !( matches[ i ] = elem );
1874						}
1875					}
1876				} ) :
1877				function( elem, _context, xml ) {
1878					input[ 0 ] = elem;
1879					matcher( input, null, xml, results );
1880
1881					// Don't keep the element
1882					// (see https://github.com/jquery/sizzle/issues/299)
1883					input[ 0 ] = null;
1884					return !results.pop();
1885				};
1886		} ),
1887
1888		has: markFunction( function( selector ) {
1889			return function( elem ) {
1890				return find( selector, elem ).length > 0;
1891			};
1892		} ),
1893
1894		contains: markFunction( function( text ) {
1895			text = text.replace( runescape, funescape );
1896			return function( elem ) {
1897				return ( elem.textContent || jQuery.text( elem ) ).indexOf( text ) > -1;
1898			};
1899		} ),
1900
1901		// "Whether an element is represented by a :lang() selector
1902		// is based solely on the element's language value
1903		// being equal to the identifier C,
1904		// or beginning with the identifier C immediately followed by "-".
1905		// The matching of C against the element's language value is performed case-insensitively.
1906		// The identifier C does not have to be a valid language name."
1907		// https://www.w3.org/TR/selectors/#lang-pseudo
1908		lang: markFunction( function( lang ) {
1909
1910			// lang value must be a valid identifier
1911			if ( !ridentifier.test( lang || "" ) ) {
1912				find.error( "unsupported lang: " + lang );
1913			}
1914			lang = lang.replace( runescape, funescape ).toLowerCase();
1915			return function( elem ) {
1916				var elemLang;
1917				do {
1918					if ( ( elemLang = documentIsHTML ?
1919						elem.lang :
1920						elem.getAttribute( "xml:lang" ) || elem.getAttribute( "lang" ) ) ) {
1921
1922						elemLang = elemLang.toLowerCase();
1923						return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
1924					}
1925				} while ( ( elem = elem.parentNode ) && elem.nodeType === 1 );
1926				return false;
1927			};
1928		} ),
1929
1930		// Miscellaneous
1931		target: function( elem ) {
1932			var hash = window.location && window.location.hash;
1933			return hash && hash.slice( 1 ) === elem.id;
1934		},
1935
1936		root: function( elem ) {
1937			return elem === documentElement;
1938		},
1939
1940		focus: function( elem ) {
1941			return elem === safeActiveElement() &&
1942				document.hasFocus() &&
1943				!!( elem.type || elem.href || ~elem.tabIndex );
1944		},
1945
1946		// Boolean properties
1947		enabled: createDisabledPseudo( false ),
1948		disabled: createDisabledPseudo( true ),
1949
1950		checked: function( elem ) {
1951
1952			// In CSS3, :checked should return both checked and selected elements
1953			// https://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
1954			return ( nodeName( elem, "input" ) && !!elem.checked ) ||
1955				( nodeName( elem, "option" ) && !!elem.selected );
1956		},
1957
1958		selected: function( elem ) {
1959
1960			// Support: IE <=11+
1961			// Accessing the selectedIndex property
1962			// forces the browser to treat the default option as
1963			// selected when in an optgroup.
1964			if ( elem.parentNode ) {
1965				// eslint-disable-next-line no-unused-expressions
1966				elem.parentNode.selectedIndex;
1967			}
1968
1969			return elem.selected === true;
1970		},
1971
1972		// Contents
1973		empty: function( elem ) {
1974
1975			// https://www.w3.org/TR/selectors/#empty-pseudo
1976			// :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
1977			//   but not by others (comment: 8; processing instruction: 7; etc.)
1978			// nodeType < 6 works because attributes (2) do not appear as children
1979			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
1980				if ( elem.nodeType < 6 ) {
1981					return false;
1982				}
1983			}
1984			return true;
1985		},
1986
1987		parent: function( elem ) {
1988			return !Expr.pseudos.empty( elem );
1989		},
1990
1991		// Element/input types
1992		header: function( elem ) {
1993			return rheader.test( elem.nodeName );
1994		},
1995
1996		input: function( elem ) {
1997			return rinputs.test( elem.nodeName );
1998		},
1999
2000		button: function( elem ) {
2001			return nodeName( elem, "input" ) && elem.type === "button" ||
2002				nodeName( elem, "button" );
2003		},
2004
2005		text: function( elem ) {
2006			var attr;
2007			return nodeName( elem, "input" ) && elem.type === "text" &&
2008
2009				// Support: IE <10 only
2010				// New HTML5 attribute values (e.g., "search") appear
2011				// with elem.type === "text"
2012				( ( attr = elem.getAttribute( "type" ) ) == null ||
2013					attr.toLowerCase() === "text" );
2014		},
2015
2016		// Position-in-collection
2017		first: createPositionalPseudo( function() {
2018			return [ 0 ];
2019		} ),
2020
2021		last: createPositionalPseudo( function( _matchIndexes, length ) {
2022			return [ length - 1 ];
2023		} ),
2024
2025		eq: createPositionalPseudo( function( _matchIndexes, length, argument ) {
2026			return [ argument < 0 ? argument + length : argument ];
2027		} ),
2028
2029		even: createPositionalPseudo( function( matchIndexes, length ) {
2030			var i = 0;
2031			for ( ; i < length; i += 2 ) {
2032				matchIndexes.push( i );
2033			}
2034			return matchIndexes;
2035		} ),
2036
2037		odd: createPositionalPseudo( function( matchIndexes, length ) {
2038			var i = 1;
2039			for ( ; i < length; i += 2 ) {
2040				matchIndexes.push( i );
2041			}
2042			return matchIndexes;
2043		} ),
2044
2045		lt: createPositionalPseudo( function( matchIndexes, length, argument ) {
2046			var i;
2047
2048			if ( argument < 0 ) {
2049				i = argument + length;
2050			} else if ( argument > length ) {
2051				i = length;
2052			} else {
2053				i = argument;
2054			}
2055
2056			for ( ; --i >= 0; ) {
2057				matchIndexes.push( i );
2058			}
2059			return matchIndexes;
2060		} ),
2061
2062		gt: createPositionalPseudo( function( matchIndexes, length, argument ) {
2063			var i = argument < 0 ? argument + length : argument;
2064			for ( ; ++i < length; ) {
2065				matchIndexes.push( i );
2066			}
2067			return matchIndexes;
2068		} )
2069	}
2070};
2071
2072Expr.pseudos.nth = Expr.pseudos.eq;
2073
2074// Add button/input type pseudos
2075for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
2076	Expr.pseudos[ i ] = createInputPseudo( i );
2077}
2078for ( i in { submit: true, reset: true } ) {
2079	Expr.pseudos[ i ] = createButtonPseudo( i );
2080}
2081
2082// Easy API for creating new setFilters
2083function setFilters() {}
2084setFilters.prototype = Expr.filters = Expr.pseudos;
2085Expr.setFilters = new setFilters();
2086
2087function tokenize( selector, parseOnly ) {
2088	var matched, match, tokens, type,
2089		soFar, groups, preFilters,
2090		cached = tokenCache[ selector + " " ];
2091
2092	if ( cached ) {
2093		return parseOnly ? 0 : cached.slice( 0 );
2094	}
2095
2096	soFar = selector;
2097	groups = [];
2098	preFilters = Expr.preFilter;
2099
2100	while ( soFar ) {
2101
2102		// Comma and first run
2103		if ( !matched || ( match = rcomma.exec( soFar ) ) ) {
2104			if ( match ) {
2105
2106				// Don't consume trailing commas as valid
2107				soFar = soFar.slice( match[ 0 ].length ) || soFar;
2108			}
2109			groups.push( ( tokens = [] ) );
2110		}
2111
2112		matched = false;
2113
2114		// Combinators
2115		if ( ( match = rleadingCombinator.exec( soFar ) ) ) {
2116			matched = match.shift();
2117			tokens.push( {
2118				value: matched,
2119
2120				// Cast descendant combinators to space
2121				type: match[ 0 ].replace( rtrimCSS, " " )
2122			} );
2123			soFar = soFar.slice( matched.length );
2124		}
2125
2126		// Filters
2127		for ( type in Expr.filter ) {
2128			if ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] ||
2129				( match = preFilters[ type ]( match ) ) ) ) {
2130				matched = match.shift();
2131				tokens.push( {
2132					value: matched,
2133					type: type,
2134					matches: match
2135				} );
2136				soFar = soFar.slice( matched.length );
2137			}
2138		}
2139
2140		if ( !matched ) {
2141			break;
2142		}
2143	}
2144
2145	// Return the length of the invalid excess
2146	// if we're just parsing
2147	// Otherwise, throw an error or return tokens
2148	if ( parseOnly ) {
2149		return soFar.length;
2150	}
2151
2152	return soFar ?
2153		find.error( selector ) :
2154
2155		// Cache the tokens
2156		tokenCache( selector, groups ).slice( 0 );
2157}
2158
2159function toSelector( tokens ) {
2160	var i = 0,
2161		len = tokens.length,
2162		selector = "";
2163	for ( ; i < len; i++ ) {
2164		selector += tokens[ i ].value;
2165	}
2166	return selector;
2167}
2168
2169function addCombinator( matcher, combinator, base ) {
2170	var dir = combinator.dir,
2171		skip = combinator.next,
2172		key = skip || dir,
2173		checkNonElements = base && key === "parentNode",
2174		doneName = done++;
2175
2176	return combinator.first ?
2177
2178		// Check against closest ancestor/preceding element
2179		function( elem, context, xml ) {
2180			while ( ( elem = elem[ dir ] ) ) {
2181				if ( elem.nodeType === 1 || checkNonElements ) {
2182					return matcher( elem, context, xml );
2183				}
2184			}
2185			return false;
2186		} :
2187
2188		// Check against all ancestor/preceding elements
2189		function( elem, context, xml ) {
2190			var oldCache, outerCache,
2191				newCache = [ dirruns, doneName ];
2192
2193			// We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching
2194			if ( xml ) {
2195				while ( ( elem = elem[ dir ] ) ) {
2196					if ( elem.nodeType === 1 || checkNonElements ) {
2197						if ( matcher( elem, context, xml ) ) {
2198							return true;
2199						}
2200					}
2201				}
2202			} else {
2203				while ( ( elem = elem[ dir ] ) ) {
2204					if ( elem.nodeType === 1 || checkNonElements ) {
2205						outerCache = elem[ expando ] || ( elem[ expando ] = {} );
2206
2207						if ( skip && nodeName( elem, skip ) ) {
2208							elem = elem[ dir ] || elem;
2209						} else if ( ( oldCache = outerCache[ key ] ) &&
2210							oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
2211
2212							// Assign to newCache so results back-propagate to previous elements
2213							return ( newCache[ 2 ] = oldCache[ 2 ] );
2214						} else {
2215
2216							// Reuse newcache so results back-propagate to previous elements
2217							outerCache[ key ] = newCache;
2218
2219							// A match means we're done; a fail means we have to keep checking
2220							if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) {
2221								return true;
2222							}
2223						}
2224					}
2225				}
2226			}
2227			return false;
2228		};
2229}
2230
2231function elementMatcher( matchers ) {
2232	return matchers.length > 1 ?
2233		function( elem, context, xml ) {
2234			var i = matchers.length;
2235			while ( i-- ) {
2236				if ( !matchers[ i ]( elem, context, xml ) ) {
2237					return false;
2238				}
2239			}
2240			return true;
2241		} :
2242		matchers[ 0 ];
2243}
2244
2245function multipleContexts( selector, contexts, results ) {
2246	var i = 0,
2247		len = contexts.length;
2248	for ( ; i < len; i++ ) {
2249		find( selector, contexts[ i ], results );
2250	}
2251	return results;
2252}
2253
2254function condense( unmatched, map, filter, context, xml ) {
2255	var elem,
2256		newUnmatched = [],
2257		i = 0,
2258		len = unmatched.length,
2259		mapped = map != null;
2260
2261	for ( ; i < len; i++ ) {
2262		if ( ( elem = unmatched[ i ] ) ) {
2263			if ( !filter || filter( elem, context, xml ) ) {
2264				newUnmatched.push( elem );
2265				if ( mapped ) {
2266					map.push( i );
2267				}
2268			}
2269		}
2270	}
2271
2272	return newUnmatched;
2273}
2274
2275function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
2276	if ( postFilter && !postFilter[ expando ] ) {
2277		postFilter = setMatcher( postFilter );
2278	}
2279	if ( postFinder && !postFinder[ expando ] ) {
2280		postFinder = setMatcher( postFinder, postSelector );
2281	}
2282	return markFunction( function( seed, results, context, xml ) {
2283		var temp, i, elem, matcherOut,
2284			preMap = [],
2285			postMap = [],
2286			preexisting = results.length,
2287
2288			// Get initial elements from seed or context
2289			elems = seed ||
2290				multipleContexts( selector || "*",
2291					context.nodeType ? [ context ] : context, [] ),
2292
2293			// Prefilter to get matcher input, preserving a map for seed-results synchronization
2294			matcherIn = preFilter && ( seed || !selector ) ?
2295				condense( elems, preMap, preFilter, context, xml ) :
2296				elems;
2297
2298		if ( matcher ) {
2299
2300			// If we have a postFinder, or filtered seed, or non-seed postFilter
2301			// or preexisting results,
2302			matcherOut = postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
2303
2304				// ...intermediate processing is necessary
2305				[] :
2306
2307				// ...otherwise use results directly
2308				results;
2309
2310			// Find primary matches
2311			matcher( matcherIn, matcherOut, context, xml );
2312		} else {
2313			matcherOut = matcherIn;
2314		}
2315
2316		// Apply postFilter
2317		if ( postFilter ) {
2318			temp = condense( matcherOut, postMap );
2319			postFilter( temp, [], context, xml );
2320
2321			// Un-match failing elements by moving them back to matcherIn
2322			i = temp.length;
2323			while ( i-- ) {
2324				if ( ( elem = temp[ i ] ) ) {
2325					matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem );
2326				}
2327			}
2328		}
2329
2330		if ( seed ) {
2331			if ( postFinder || preFilter ) {
2332				if ( postFinder ) {
2333
2334					// Get the final matcherOut by condensing this intermediate into postFinder contexts
2335					temp = [];
2336					i = matcherOut.length;
2337					while ( i-- ) {
2338						if ( ( elem = matcherOut[ i ] ) ) {
2339
2340							// Restore matcherIn since elem is not yet a final match
2341							temp.push( ( matcherIn[ i ] = elem ) );
2342						}
2343					}
2344					postFinder( null, ( matcherOut = [] ), temp, xml );
2345				}
2346
2347				// Move matched elements from seed to results to keep them synchronized
2348				i = matcherOut.length;
2349				while ( i-- ) {
2350					if ( ( elem = matcherOut[ i ] ) &&
2351						( temp = postFinder ? indexOf.call( seed, elem ) : preMap[ i ] ) > -1 ) {
2352
2353						seed[ temp ] = !( results[ temp ] = elem );
2354					}
2355				}
2356			}
2357
2358		// Add elements to results, through postFinder if defined
2359		} else {
2360			matcherOut = condense(
2361				matcherOut === results ?
2362					matcherOut.splice( preexisting, matcherOut.length ) :
2363					matcherOut
2364			);
2365			if ( postFinder ) {
2366				postFinder( null, results, matcherOut, xml );
2367			} else {
2368				push.apply( results, matcherOut );
2369			}
2370		}
2371	} );
2372}
2373
2374function matcherFromTokens( tokens ) {
2375	var checkContext, matcher, j,
2376		len = tokens.length,
2377		leadingRelative = Expr.relative[ tokens[ 0 ].type ],
2378		implicitRelative = leadingRelative || Expr.relative[ " " ],
2379		i = leadingRelative ? 1 : 0,
2380
2381		// The foundational matcher ensures that elements are reachable from top-level context(s)
2382		matchContext = addCombinator( function( elem ) {
2383			return elem === checkContext;
2384		}, implicitRelative, true ),
2385		matchAnyContext = addCombinator( function( elem ) {
2386			return indexOf.call( checkContext, elem ) > -1;
2387		}, implicitRelative, true ),
2388		matchers = [ function( elem, context, xml ) {
2389
2390			// Support: IE 11+, Edge 17 - 18+
2391			// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
2392			// two documents; shallow comparisons work.
2393			// eslint-disable-next-line eqeqeq
2394			var ret = ( !leadingRelative && ( xml || context != outermostContext ) ) || (
2395				( checkContext = context ).nodeType ?
2396					matchContext( elem, context, xml ) :
2397					matchAnyContext( elem, context, xml ) );
2398
2399			// Avoid hanging onto element
2400			// (see https://github.com/jquery/sizzle/issues/299)
2401			checkContext = null;
2402			return ret;
2403		} ];
2404
2405	for ( ; i < len; i++ ) {
2406		if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) {
2407			matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ];
2408		} else {
2409			matcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches );
2410
2411			// Return special upon seeing a positional matcher
2412			if ( matcher[ expando ] ) {
2413
2414				// Find the next relative operator (if any) for proper handling
2415				j = ++i;
2416				for ( ; j < len; j++ ) {
2417					if ( Expr.relative[ tokens[ j ].type ] ) {
2418						break;
2419					}
2420				}
2421				return setMatcher(
2422					i > 1 && elementMatcher( matchers ),
2423					i > 1 && toSelector(
2424
2425						// If the preceding token was a descendant combinator, insert an implicit any-element `*`
2426						tokens.slice( 0, i - 1 )
2427							.concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } )
2428					).replace( rtrimCSS, "$1" ),
2429					matcher,
2430					i < j && matcherFromTokens( tokens.slice( i, j ) ),
2431					j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ),
2432					j < len && toSelector( tokens )
2433				);
2434			}
2435			matchers.push( matcher );
2436		}
2437	}
2438
2439	return elementMatcher( matchers );
2440}
2441
2442function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
2443	var bySet = setMatchers.length > 0,
2444		byElement = elementMatchers.length > 0,
2445		superMatcher = function( seed, context, xml, results, outermost ) {
2446			var elem, j, matcher,
2447				matchedCount = 0,
2448				i = "0",
2449				unmatched = seed && [],
2450				setMatched = [],
2451				contextBackup = outermostContext,
2452
2453				// We must always have either seed elements or outermost context
2454				elems = seed || byElement && Expr.find.TAG( "*", outermost ),
2455
2456				// Use integer dirruns iff this is the outermost matcher
2457				dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ),
2458				len = elems.length;
2459
2460			if ( outermost ) {
2461
2462				// Support: IE 11+, Edge 17 - 18+
2463				// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
2464				// two documents; shallow comparisons work.
2465				// eslint-disable-next-line eqeqeq
2466				outermostContext = context == document || context || outermost;
2467			}
2468
2469			// Add elements passing elementMatchers directly to results
2470			// Support: iOS <=7 - 9 only
2471			// Tolerate NodeList properties (IE: "length"; Safari: <number>) matching
2472			// elements by id. (see trac-14142)
2473			for ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) {
2474				if ( byElement && elem ) {
2475					j = 0;
2476
2477					// Support: IE 11+, Edge 17 - 18+
2478					// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
2479					// two documents; shallow comparisons work.
2480					// eslint-disable-next-line eqeqeq
2481					if ( !context && elem.ownerDocument != document ) {
2482						setDocument( elem );
2483						xml = !documentIsHTML;
2484					}
2485					while ( ( matcher = elementMatchers[ j++ ] ) ) {
2486						if ( matcher( elem, context || document, xml ) ) {
2487							push.call( results, elem );
2488							break;
2489						}
2490					}
2491					if ( outermost ) {
2492						dirruns = dirrunsUnique;
2493					}
2494				}
2495
2496				// Track unmatched elements for set filters
2497				if ( bySet ) {
2498
2499					// They will have gone through all possible matchers
2500					if ( ( elem = !matcher && elem ) ) {
2501						matchedCount--;
2502					}
2503
2504					// Lengthen the array for every element, matched or not
2505					if ( seed ) {
2506						unmatched.push( elem );
2507					}
2508				}
2509			}
2510
2511			// `i` is now the count of elements visited above, and adding it to `matchedCount`
2512			// makes the latter nonnegative.
2513			matchedCount += i;
2514
2515			// Apply set filters to unmatched elements
2516			// NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`
2517			// equals `i`), unless we didn't visit _any_ elements in the above loop because we have
2518			// no element matchers and no seed.
2519			// Incrementing an initially-string "0" `i` allows `i` to remain a string only in that
2520			// case, which will result in a "00" `matchedCount` that differs from `i` but is also
2521			// numerically zero.
2522			if ( bySet && i !== matchedCount ) {
2523				j = 0;
2524				while ( ( matcher = setMatchers[ j++ ] ) ) {
2525					matcher( unmatched, setMatched, context, xml );
2526				}
2527
2528				if ( seed ) {
2529
2530					// Reintegrate element matches to eliminate the need for sorting
2531					if ( matchedCount > 0 ) {
2532						while ( i-- ) {
2533							if ( !( unmatched[ i ] || setMatched[ i ] ) ) {
2534								setMatched[ i ] = pop.call( results );
2535							}
2536						}
2537					}
2538
2539					// Discard index placeholder values to get only actual matches
2540					setMatched = condense( setMatched );
2541				}
2542
2543				// Add matches to results
2544				push.apply( results, setMatched );
2545
2546				// Seedless set matches succeeding multiple successful matchers stipulate sorting
2547				if ( outermost && !seed && setMatched.length > 0 &&
2548					( matchedCount + setMatchers.length ) > 1 ) {
2549
2550					jQuery.uniqueSort( results );
2551				}
2552			}
2553
2554			// Override manipulation of globals by nested matchers
2555			if ( outermost ) {
2556				dirruns = dirrunsUnique;
2557				outermostContext = contextBackup;
2558			}
2559
2560			return unmatched;
2561		};
2562
2563	return bySet ?
2564		markFunction( superMatcher ) :
2565		superMatcher;
2566}
2567
2568function compile( selector, match /* Internal Use Only */ ) {
2569	var i,
2570		setMatchers = [],
2571		elementMatchers = [],
2572		cached = compilerCache[ selector + " " ];
2573
2574	if ( !cached ) {
2575
2576		// Generate a function of recursive functions that can be used to check each element
2577		if ( !match ) {
2578			match = tokenize( selector );
2579		}
2580		i = match.length;
2581		while ( i-- ) {
2582			cached = matcherFromTokens( match[ i ] );
2583			if ( cached[ expando ] ) {
2584				setMatchers.push( cached );
2585			} else {
2586				elementMatchers.push( cached );
2587			}
2588		}
2589
2590		// Cache the compiled function
2591		cached = compilerCache( selector,
2592			matcherFromGroupMatchers( elementMatchers, setMatchers ) );
2593
2594		// Save selector and tokenization
2595		cached.selector = selector;
2596	}
2597	return cached;
2598}
2599
2600/**
2601 * A low-level selection function that works with jQuery's compiled
2602 *  selector functions
2603 * @param {String|Function} selector A selector or a pre-compiled
2604 *  selector function built with jQuery selector compile
2605 * @param {Element} context
2606 * @param {Array} [results]
2607 * @param {Array} [seed] A set of elements to match against
2608 */
2609function select( selector, context, results, seed ) {
2610	var i, tokens, token, type, find,
2611		compiled = typeof selector === "function" && selector,
2612		match = !seed && tokenize( ( selector = compiled.selector || selector ) );
2613
2614	results = results || [];
2615
2616	// Try to minimize operations if there is only one selector in the list and no seed
2617	// (the latter of which guarantees us context)
2618	if ( match.length === 1 ) {
2619
2620		// Reduce context if the leading compound selector is an ID
2621		tokens = match[ 0 ] = match[ 0 ].slice( 0 );
2622		if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" &&
2623				context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) {
2624
2625			context = ( Expr.find.ID(
2626				token.matches[ 0 ].replace( runescape, funescape ),
2627				context
2628			) || [] )[ 0 ];
2629			if ( !context ) {
2630				return results;
2631
2632			// Precompiled matchers will still verify ancestry, so step up a level
2633			} else if ( compiled ) {
2634				context = context.parentNode;
2635			}
2636
2637			selector = selector.slice( tokens.shift().value.length );
2638		}
2639
2640		// Fetch a seed set for right-to-left matching
2641		i = matchExpr.needsContext.test( selector ) ? 0 : tokens.length;
2642		while ( i-- ) {
2643			token = tokens[ i ];
2644
2645			// Abort if we hit a combinator
2646			if ( Expr.relative[ ( type = token.type ) ] ) {
2647				break;
2648			}
2649			if ( ( find = Expr.find[ type ] ) ) {
2650
2651				// Search, expanding context for leading sibling combinators
2652				if ( ( seed = find(
2653					token.matches[ 0 ].replace( runescape, funescape ),
2654					rsibling.test( tokens[ 0 ].type ) &&
2655						testContext( context.parentNode ) || context
2656				) ) ) {
2657
2658					// If seed is empty or no tokens remain, we can return early
2659					tokens.splice( i, 1 );
2660					selector = seed.length && toSelector( tokens );
2661					if ( !selector ) {
2662						push.apply( results, seed );
2663						return results;
2664					}
2665
2666					break;
2667				}
2668			}
2669		}
2670	}
2671
2672	// Compile and execute a filtering function if one is not provided
2673	// Provide `match` to avoid retokenization if we modified the selector above
2674	( compiled || compile( selector, match ) )(
2675		seed,
2676		context,
2677		!documentIsHTML,
2678		results,
2679		!context || rsibling.test( selector ) && testContext( context.parentNode ) || context
2680	);
2681	return results;
2682}
2683
2684// One-time assignments
2685
2686// Support: Android <=4.0 - 4.1+
2687// Sort stability
2688support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando;
2689
2690// Initialize against the default document
2691setDocument();
2692
2693// Support: Android <=4.0 - 4.1+
2694// Detached nodes confoundingly follow *each other*
2695support.sortDetached = assert( function( el ) {
2696
2697	// Should return 1, but returns 4 (following)
2698	return el.compareDocumentPosition( document.createElement( "fieldset" ) ) & 1;
2699} );
2700
2701jQuery.find = find;
2702
2703// Deprecated
2704jQuery.expr[ ":" ] = jQuery.expr.pseudos;
2705jQuery.unique = jQuery.uniqueSort;
2706
2707// These have always been private, but they used to be documented as part of
2708// Sizzle so let's maintain them for now for backwards compatibility purposes.
2709find.compile = compile;
2710find.select = select;
2711find.setDocument = setDocument;
2712find.tokenize = tokenize;
2713
2714find.escape = jQuery.escapeSelector;
2715find.getText = jQuery.text;
2716find.isXML = jQuery.isXMLDoc;
2717find.selectors = jQuery.expr;
2718find.support = jQuery.support;
2719find.uniqueSort = jQuery.uniqueSort;
2720
2721	/* eslint-enable */
2722
2723} )();
2724
2725
2726var dir = function( elem, dir, until ) {
2727	var matched = [],
2728		truncate = until !== undefined;
2729
2730	while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) {
2731		if ( elem.nodeType === 1 ) {
2732			if ( truncate && jQuery( elem ).is( until ) ) {
2733				break;
2734			}
2735			matched.push( elem );
2736		}
2737	}
2738	return matched;
2739};
2740
2741
2742var siblings = function( n, elem ) {
2743	var matched = [];
2744
2745	for ( ; n; n = n.nextSibling ) {
2746		if ( n.nodeType === 1 && n !== elem ) {
2747			matched.push( n );
2748		}
2749	}
2750
2751	return matched;
2752};
2753
2754
2755var rneedsContext = jQuery.expr.match.needsContext;
2756
2757var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i );
2758
2759
2760
2761// Implement the identical functionality for filter and not
2762function winnow( elements, qualifier, not ) {
2763	if ( isFunction( qualifier ) ) {
2764		return jQuery.grep( elements, function( elem, i ) {
2765			return !!qualifier.call( elem, i, elem ) !== not;
2766		} );
2767	}
2768
2769	// Single element
2770	if ( qualifier.nodeType ) {
2771		return jQuery.grep( elements, function( elem ) {
2772			return ( elem === qualifier ) !== not;
2773		} );
2774	}
2775
2776	// Arraylike of elements (jQuery, arguments, Array)
2777	if ( typeof qualifier !== "string" ) {
2778		return jQuery.grep( elements, function( elem ) {
2779			return ( indexOf.call( qualifier, elem ) > -1 ) !== not;
2780		} );
2781	}
2782
2783	// Filtered directly for both simple and complex selectors
2784	return jQuery.filter( qualifier, elements, not );
2785}
2786
2787jQuery.filter = function( expr, elems, not ) {
2788	var elem = elems[ 0 ];
2789
2790	if ( not ) {
2791		expr = ":not(" + expr + ")";
2792	}
2793
2794	if ( elems.length === 1 && elem.nodeType === 1 ) {
2795		return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [];
2796	}
2797
2798	return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
2799		return elem.nodeType === 1;
2800	} ) );
2801};
2802
2803jQuery.fn.extend( {
2804	find: function( selector ) {
2805		var i, ret,
2806			len = this.length,
2807			self = this;
2808
2809		if ( typeof selector !== "string" ) {
2810			return this.pushStack( jQuery( selector ).filter( function() {
2811				for ( i = 0; i < len; i++ ) {
2812					if ( jQuery.contains( self[ i ], this ) ) {
2813						return true;
2814					}
2815				}
2816			} ) );
2817		}
2818
2819		ret = this.pushStack( [] );
2820
2821		for ( i = 0; i < len; i++ ) {
2822			jQuery.find( selector, self[ i ], ret );
2823		}
2824
2825		return len > 1 ? jQuery.uniqueSort( ret ) : ret;
2826	},
2827	filter: function( selector ) {
2828		return this.pushStack( winnow( this, selector || [], false ) );
2829	},
2830	not: function( selector ) {
2831		return this.pushStack( winnow( this, selector || [], true ) );
2832	},
2833	is: function( selector ) {
2834		return !!winnow(
2835			this,
2836
2837			// If this is a positional/relative selector, check membership in the returned set
2838			// so $("p:first").is("p:last") won't return true for a doc with two "p".
2839			typeof selector === "string" && rneedsContext.test( selector ) ?
2840				jQuery( selector ) :
2841				selector || [],
2842			false
2843		).length;
2844	}
2845} );
2846
2847
2848// Initialize a jQuery object
2849
2850
2851// A central reference to the root jQuery(document)
2852var rootjQuery,
2853
2854	// A simple way to check for HTML strings
2855	// Prioritize #id over <tag> to avoid XSS via location.hash (trac-9521)
2856	// Strict HTML recognition (trac-11290: must start with <)
2857	// Shortcut simple #id case for speed
2858	rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,
2859
2860	init = jQuery.fn.init = function( selector, context, root ) {
2861		var match, elem;
2862
2863		// HANDLE: $(""), $(null), $(undefined), $(false)
2864		if ( !selector ) {
2865			return this;
2866		}
2867
2868		// Method init() accepts an alternate rootjQuery
2869		// so migrate can support jQuery.sub (gh-2101)
2870		root = root || rootjQuery;
2871
2872		// Handle HTML strings
2873		if ( typeof selector === "string" ) {
2874			if ( selector[ 0 ] === "<" &&
2875				selector[ selector.length - 1 ] === ">" &&
2876				selector.length >= 3 ) {
2877
2878				// Assume that strings that start and end with <> are HTML and skip the regex check
2879				match = [ null, selector, null ];
2880
2881			} else {
2882				match = rquickExpr.exec( selector );
2883			}
2884
2885			// Match html or make sure no context is specified for #id
2886			if ( match && ( match[ 1 ] || !context ) ) {
2887
2888				// HANDLE: $(html) -> $(array)
2889				if ( match[ 1 ] ) {
2890					context = context instanceof jQuery ? context[ 0 ] : context;
2891
2892					// Option to run scripts is true for back-compat
2893					// Intentionally let the error be thrown if parseHTML is not present
2894					jQuery.merge( this, jQuery.parseHTML(
2895						match[ 1 ],
2896						context && context.nodeType ? context.ownerDocument || context : document,
2897						true
2898					) );
2899
2900					// HANDLE: $(html, props)
2901					if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) {
2902						for ( match in context ) {
2903
2904							// Properties of context are called as methods if possible
2905							if ( isFunction( this[ match ] ) ) {
2906								this[ match ]( context[ match ] );
2907
2908							// ...and otherwise set as attributes
2909							} else {
2910								this.attr( match, context[ match ] );
2911							}
2912						}
2913					}
2914
2915					return this;
2916
2917				// HANDLE: $(#id)
2918				} else {
2919					elem = document.getElementById( match[ 2 ] );
2920
2921					if ( elem ) {
2922
2923						// Inject the element directly into the jQuery object
2924						this[ 0 ] = elem;
2925						this.length = 1;
2926					}
2927					return this;
2928				}
2929
2930			// HANDLE: $(expr, $(...))
2931			} else if ( !context || context.jquery ) {
2932				return ( context || root ).find( selector );
2933
2934			// HANDLE: $(expr, context)
2935			// (which is just equivalent to: $(context).find(expr)
2936			} else {
2937				return this.constructor( context ).find( selector );
2938			}
2939
2940		// HANDLE: $(DOMElement)
2941		} else if ( selector.nodeType ) {
2942			this[ 0 ] = selector;
2943			this.length = 1;
2944			return this;
2945
2946		// HANDLE: $(function)
2947		// Shortcut for document ready
2948		} else if ( isFunction( selector ) ) {
2949			return root.ready !== undefined ?
2950				root.ready( selector ) :
2951
2952				// Execute immediately if ready is not present
2953				selector( jQuery );
2954		}
2955
2956		return jQuery.makeArray( selector, this );
2957	};
2958
2959// Give the init function the jQuery prototype for later instantiation
2960init.prototype = jQuery.fn;
2961
2962// Initialize central reference
2963rootjQuery = jQuery( document );
2964
2965
2966var rparentsprev = /^(?:parents|prev(?:Until|All))/,
2967
2968	// Methods guaranteed to produce a unique set when starting from a unique set
2969	guaranteedUnique = {
2970		children: true,
2971		contents: true,
2972		next: true,
2973		prev: true
2974	};
2975
2976jQuery.fn.extend( {
2977	has: function( target ) {
2978		var targets = jQuery( target, this ),
2979			l = targets.length;
2980
2981		return this.filter( function() {
2982			var i = 0;
2983			for ( ; i < l; i++ ) {
2984				if ( jQuery.contains( this, targets[ i ] ) ) {
2985					return true;
2986				}
2987			}
2988		} );
2989	},
2990
2991	closest: function( selectors, context ) {
2992		var cur,
2993			i = 0,
2994			l = this.length,
2995			matched = [],
2996			targets = typeof selectors !== "string" && jQuery( selectors );
2997
2998		// Positional selectors never match, since there's no _selection_ context
2999		if ( !rneedsContext.test( selectors ) ) {
3000			for ( ; i < l; i++ ) {
3001				for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) {
3002
3003					// Always skip document fragments
3004					if ( cur.nodeType < 11 && ( targets ?
3005						targets.index( cur ) > -1 :
3006
3007						// Don't pass non-elements to jQuery#find
3008						cur.nodeType === 1 &&
3009							jQuery.find.matchesSelector( cur, selectors ) ) ) {
3010
3011						matched.push( cur );
3012						break;
3013					}
3014				}
3015			}
3016		}
3017
3018		return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched );
3019	},
3020
3021	// Determine the position of an element within the set
3022	index: function( elem ) {
3023
3024		// No argument, return index in parent
3025		if ( !elem ) {
3026			return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
3027		}
3028
3029		// Index in selector
3030		if ( typeof elem === "string" ) {
3031			return indexOf.call( jQuery( elem ), this[ 0 ] );
3032		}
3033
3034		// Locate the position of the desired element
3035		return indexOf.call( this,
3036
3037			// If it receives a jQuery object, the first element is used
3038			elem.jquery ? elem[ 0 ] : elem
3039		);
3040	},
3041
3042	add: function( selector, context ) {
3043		return this.pushStack(
3044			jQuery.uniqueSort(
3045				jQuery.merge( this.get(), jQuery( selector, context ) )
3046			)
3047		);
3048	},
3049
3050	addBack: function( selector ) {
3051		return this.add( selector == null ?
3052			this.prevObject : this.prevObject.filter( selector )
3053		);
3054	}
3055} );
3056
3057function sibling( cur, dir ) {
3058	while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {}
3059	return cur;
3060}
3061
3062jQuery.each( {
3063	parent: function( elem ) {
3064		var parent = elem.parentNode;
3065		return parent && parent.nodeType !== 11 ? parent : null;
3066	},
3067	parents: function( elem ) {
3068		return dir( elem, "parentNode" );
3069	},
3070	parentsUntil: function( elem, _i, until ) {
3071		return dir( elem, "parentNode", until );
3072	},
3073	next: function( elem ) {
3074		return sibling( elem, "nextSibling" );
3075	},
3076	prev: function( elem ) {
3077		return sibling( elem, "previousSibling" );
3078	},
3079	nextAll: function( elem ) {
3080		return dir( elem, "nextSibling" );
3081	},
3082	prevAll: function( elem ) {
3083		return dir( elem, "previousSibling" );
3084	},
3085	nextUntil: function( elem, _i, until ) {
3086		return dir( elem, "nextSibling", until );
3087	},
3088	prevUntil: function( elem, _i, until ) {
3089		return dir( elem, "previousSibling", until );
3090	},
3091	siblings: function( elem ) {
3092		return siblings( ( elem.parentNode || {} ).firstChild, elem );
3093	},
3094	children: function( elem ) {
3095		return siblings( elem.firstChild );
3096	},
3097	contents: function( elem ) {
3098		if ( elem.contentDocument != null &&
3099
3100			// Support: IE 11+
3101			// <object> elements with no `data` attribute has an object
3102			// `contentDocument` with a `null` prototype.
3103			getProto( elem.contentDocument ) ) {
3104
3105			return elem.contentDocument;
3106		}
3107
3108		// Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only
3109		// Treat the template element as a regular one in browsers that
3110		// don't support it.
3111		if ( nodeName( elem, "template" ) ) {
3112			elem = elem.content || elem;
3113		}
3114
3115		return jQuery.merge( [], elem.childNodes );
3116	}
3117}, function( name, fn ) {
3118	jQuery.fn[ name ] = function( until, selector ) {
3119		var matched = jQuery.map( this, fn, until );
3120
3121		if ( name.slice( -5 ) !== "Until" ) {
3122			selector = until;
3123		}
3124
3125		if ( selector && typeof selector === "string" ) {
3126			matched = jQuery.filter( selector, matched );
3127		}
3128
3129		if ( this.length > 1 ) {
3130
3131			// Remove duplicates
3132			if ( !guaranteedUnique[ name ] ) {
3133				jQuery.uniqueSort( matched );
3134			}
3135
3136			// Reverse order for parents* and prev-derivatives
3137			if ( rparentsprev.test( name ) ) {
3138				matched.reverse();
3139			}
3140		}
3141
3142		return this.pushStack( matched );
3143	};
3144} );
3145var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g );
3146
3147
3148
3149// Convert String-formatted options into Object-formatted ones
3150function createOptions( options ) {
3151	var object = {};
3152	jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) {
3153		object[ flag ] = true;
3154	} );
3155	return object;
3156}
3157
3158/*
3159 * Create a callback list using the following parameters:
3160 *
3161 *	options: an optional list of space-separated options that will change how
3162 *			the callback list behaves or a more traditional option object
3163 *
3164 * By default a callback list will act like an event callback list and can be
3165 * "fired" multiple times.
3166 *
3167 * Possible options:
3168 *
3169 *	once:			will ensure the callback list can only be fired once (like a Deferred)
3170 *
3171 *	memory:			will keep track of previous values and will call any callback added
3172 *					after the list has been fired right away with the latest "memorized"
3173 *					values (like a Deferred)
3174 *
3175 *	unique:			will ensure a callback can only be added once (no duplicate in the list)
3176 *
3177 *	stopOnFalse:	interrupt callings when a callback returns false
3178 *
3179 */
3180jQuery.Callbacks = function( options ) {
3181
3182	// Convert options from String-formatted to Object-formatted if needed
3183	// (we check in cache first)
3184	options = typeof options === "string" ?
3185		createOptions( options ) :
3186		jQuery.extend( {}, options );
3187
3188	var // Flag to know if list is currently firing
3189		firing,
3190
3191		// Last fire value for non-forgettable lists
3192		memory,
3193
3194		// Flag to know if list was already fired
3195		fired,
3196
3197		// Flag to prevent firing
3198		locked,
3199
3200		// Actual callback list
3201		list = [],
3202
3203		// Queue of execution data for repeatable lists
3204		queue = [],
3205
3206		// Index of currently firing callback (modified by add/remove as needed)
3207		firingIndex = -1,
3208
3209		// Fire callbacks
3210		fire = function() {
3211
3212			// Enforce single-firing
3213			locked = locked || options.once;
3214
3215			// Execute callbacks for all pending executions,
3216			// respecting firingIndex overrides and runtime changes
3217			fired = firing = true;
3218			for ( ; queue.length; firingIndex = -1 ) {
3219				memory = queue.shift();
3220				while ( ++firingIndex < list.length ) {
3221
3222					// Run callback and check for early termination
3223					if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false &&
3224						options.stopOnFalse ) {
3225
3226						// Jump to end and forget the data so .add doesn't re-fire
3227						firingIndex = list.length;
3228						memory = false;
3229					}
3230				}
3231			}
3232
3233			// Forget the data if we're done with it
3234			if ( !options.memory ) {
3235				memory = false;
3236			}
3237
3238			firing = false;
3239
3240			// Clean up if we're done firing for good
3241			if ( locked ) {
3242
3243				// Keep an empty list if we have data for future add calls
3244				if ( memory ) {
3245					list = [];
3246
3247				// Otherwise, this object is spent
3248				} else {
3249					list = "";
3250				}
3251			}
3252		},
3253
3254		// Actual Callbacks object
3255		self = {
3256
3257			// Add a callback or a collection of callbacks to the list
3258			add: function() {
3259				if ( list ) {
3260
3261					// If we have memory from a past run, we should fire after adding
3262					if ( memory && !firing ) {
3263						firingIndex = list.length - 1;
3264						queue.push( memory );
3265					}
3266
3267					( function add( args ) {
3268						jQuery.each( args, function( _, arg ) {
3269							if ( isFunction( arg ) ) {
3270								if ( !options.unique || !self.has( arg ) ) {
3271									list.push( arg );
3272								}
3273							} else if ( arg && arg.length && toType( arg ) !== "string" ) {
3274
3275								// Inspect recursively
3276								add( arg );
3277							}
3278						} );
3279					} )( arguments );
3280
3281					if ( memory && !firing ) {
3282						fire();
3283					}
3284				}
3285				return this;
3286			},
3287
3288			// Remove a callback from the list
3289			remove: function() {
3290				jQuery.each( arguments, function( _, arg ) {
3291					var index;
3292					while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
3293						list.splice( index, 1 );
3294
3295						// Handle firing indexes
3296						if ( index <= firingIndex ) {
3297							firingIndex--;
3298						}
3299					}
3300				} );
3301				return this;
3302			},
3303
3304			// Check if a given callback is in the list.
3305			// If no argument is given, return whether or not list has callbacks attached.
3306			has: function( fn ) {
3307				return fn ?
3308					jQuery.inArray( fn, list ) > -1 :
3309					list.length > 0;
3310			},
3311
3312			// Remove all callbacks from the list
3313			empty: function() {
3314				if ( list ) {
3315					list = [];
3316				}
3317				return this;
3318			},
3319
3320			// Disable .fire and .add
3321			// Abort any current/pending executions
3322			// Clear all callbacks and values
3323			disable: function() {
3324				locked = queue = [];
3325				list = memory = "";
3326				return this;
3327			},
3328			disabled: function() {
3329				return !list;
3330			},
3331
3332			// Disable .fire
3333			// Also disable .add unless we have memory (since it would have no effect)
3334			// Abort any pending executions
3335			lock: function() {
3336				locked = queue = [];
3337				if ( !memory && !firing ) {
3338					list = memory = "";
3339				}
3340				return this;
3341			},
3342			locked: function() {
3343				return !!locked;
3344			},
3345
3346			// Call all callbacks with the given context and arguments
3347			fireWith: function( context, args ) {
3348				if ( !locked ) {
3349					args = args || [];
3350					args = [ context, args.slice ? args.slice() : args ];
3351					queue.push( args );
3352					if ( !firing ) {
3353						fire();
3354					}
3355				}
3356				return this;
3357			},
3358
3359			// Call all the callbacks with the given arguments
3360			fire: function() {
3361				self.fireWith( this, arguments );
3362				return this;
3363			},
3364
3365			// To know if the callbacks have already been called at least once
3366			fired: function() {
3367				return !!fired;
3368			}
3369		};
3370
3371	return self;
3372};
3373
3374
3375function Identity( v ) {
3376	return v;
3377}
3378function Thrower( ex ) {
3379	throw ex;
3380}
3381
3382function adoptValue( value, resolve, reject, noValue ) {
3383	var method;
3384
3385	try {
3386
3387		// Check for promise aspect first to privilege synchronous behavior
3388		if ( value && isFunction( ( method = value.promise ) ) ) {
3389			method.call( value ).done( resolve ).fail( reject );
3390
3391		// Other thenables
3392		} else if ( value && isFunction( ( method = value.then ) ) ) {
3393			method.call( value, resolve, reject );
3394
3395		// Other non-thenables
3396		} else {
3397
3398			// Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer:
3399			// * false: [ value ].slice( 0 ) => resolve( value )
3400			// * true: [ value ].slice( 1 ) => resolve()
3401			resolve.apply( undefined, [ value ].slice( noValue ) );
3402		}
3403
3404	// For Promises/A+, convert exceptions into rejections
3405	// Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in
3406	// Deferred#then to conditionally suppress rejection.
3407	} catch ( value ) {
3408
3409		// Support: Android 4.0 only
3410		// Strict mode functions invoked without .call/.apply get global-object context
3411		reject.apply( undefined, [ value ] );
3412	}
3413}
3414
3415jQuery.extend( {
3416
3417	Deferred: function( func ) {
3418		var tuples = [
3419
3420				// action, add listener, callbacks,
3421				// ... .then handlers, argument index, [final state]
3422				[ "notify", "progress", jQuery.Callbacks( "memory" ),
3423					jQuery.Callbacks( "memory" ), 2 ],
3424				[ "resolve", "done", jQuery.Callbacks( "once memory" ),
3425					jQuery.Callbacks( "once memory" ), 0, "resolved" ],
3426				[ "reject", "fail", jQuery.Callbacks( "once memory" ),
3427					jQuery.Callbacks( "once memory" ), 1, "rejected" ]
3428			],
3429			state = "pending",
3430			promise = {
3431				state: function() {
3432					return state;
3433				},
3434				always: function() {
3435					deferred.done( arguments ).fail( arguments );
3436					return this;
3437				},
3438				"catch": function( fn ) {
3439					return promise.then( null, fn );
3440				},
3441
3442				// Keep pipe for back-compat
3443				pipe: function( /* fnDone, fnFail, fnProgress */ ) {
3444					var fns = arguments;
3445
3446					return jQuery.Deferred( function( newDefer ) {
3447						jQuery.each( tuples, function( _i, tuple ) {
3448
3449							// Map tuples (progress, done, fail) to arguments (done, fail, progress)
3450							var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ];
3451
3452							// deferred.progress(function() { bind to newDefer or newDefer.notify })
3453							// deferred.done(function() { bind to newDefer or newDefer.resolve })
3454							// deferred.fail(function() { bind to newDefer or newDefer.reject })
3455							deferred[ tuple[ 1 ] ]( function() {
3456								var returned = fn && fn.apply( this, arguments );
3457								if ( returned && isFunction( returned.promise ) ) {
3458									returned.promise()
3459										.progress( newDefer.notify )
3460										.done( newDefer.resolve )
3461										.fail( newDefer.reject );
3462								} else {
3463									newDefer[ tuple[ 0 ] + "With" ](
3464										this,
3465										fn ? [ returned ] : arguments
3466									);
3467								}
3468							} );
3469						} );
3470						fns = null;
3471					} ).promise();
3472				},
3473				then: function( onFulfilled, onRejected, onProgress ) {
3474					var maxDepth = 0;
3475					function resolve( depth, deferred, handler, special ) {
3476						return function() {
3477							var that = this,
3478								args = arguments,
3479								mightThrow = function() {
3480									var returned, then;
3481
3482									// Support: Promises/A+ section 2.3.3.3.3
3483									// https://promisesaplus.com/#point-59
3484									// Ignore double-resolution attempts
3485									if ( depth < maxDepth ) {
3486										return;
3487									}
3488
3489									returned = handler.apply( that, args );
3490
3491									// Support: Promises/A+ section 2.3.1
3492									// https://promisesaplus.com/#point-48
3493									if ( returned === deferred.promise() ) {
3494										throw new TypeError( "Thenable self-resolution" );
3495									}
3496
3497									// Support: Promises/A+ sections 2.3.3.1, 3.5
3498									// https://promisesaplus.com/#point-54
3499									// https://promisesaplus.com/#point-75
3500									// Retrieve `then` only once
3501									then = returned &&
3502
3503										// Support: Promises/A+ section 2.3.4
3504										// https://promisesaplus.com/#point-64
3505										// Only check objects and functions for thenability
3506										( typeof returned === "object" ||
3507											typeof returned === "function" ) &&
3508										returned.then;
3509
3510									// Handle a returned thenable
3511									if ( isFunction( then ) ) {
3512
3513										// Special processors (notify) just wait for resolution
3514										if ( special ) {
3515											then.call(
3516												returned,
3517												resolve( maxDepth, deferred, Identity, special ),
3518												resolve( maxDepth, deferred, Thrower, special )
3519											);
3520
3521										// Normal processors (resolve) also hook into progress
3522										} else {
3523
3524											// ...and disregard older resolution values
3525											maxDepth++;
3526
3527											then.call(
3528												returned,
3529												resolve( maxDepth, deferred, Identity, special ),
3530												resolve( maxDepth, deferred, Thrower, special ),
3531												resolve( maxDepth, deferred, Identity,
3532													deferred.notifyWith )
3533											);
3534										}
3535
3536									// Handle all other returned values
3537									} else {
3538
3539										// Only substitute handlers pass on context
3540										// and multiple values (non-spec behavior)
3541										if ( handler !== Identity ) {
3542											that = undefined;
3543											args = [ returned ];
3544										}
3545
3546										// Process the value(s)
3547										// Default process is resolve
3548										( special || deferred.resolveWith )( that, args );
3549									}
3550								},
3551
3552								// Only normal processors (resolve) catch and reject exceptions
3553								process = special ?
3554									mightThrow :
3555									function() {
3556										try {
3557											mightThrow();
3558										} catch ( e ) {
3559
3560											if ( jQuery.Deferred.exceptionHook ) {
3561												jQuery.Deferred.exceptionHook( e,
3562													process.error );
3563											}
3564
3565											// Support: Promises/A+ section 2.3.3.3.4.1
3566											// https://promisesaplus.com/#point-61
3567											// Ignore post-resolution exceptions
3568											if ( depth + 1 >= maxDepth ) {
3569
3570												// Only substitute handlers pass on context
3571												// and multiple values (non-spec behavior)
3572												if ( handler !== Thrower ) {
3573													that = undefined;
3574													args = [ e ];
3575												}
3576
3577												deferred.rejectWith( that, args );
3578											}
3579										}
3580									};
3581
3582							// Support: Promises/A+ section 2.3.3.3.1
3583							// https://promisesaplus.com/#point-57
3584							// Re-resolve promises immediately to dodge false rejection from
3585							// subsequent errors
3586							if ( depth ) {
3587								process();
3588							} else {
3589
3590								// Call an optional hook to record the error, in case of exception
3591								// since it's otherwise lost when execution goes async
3592								if ( jQuery.Deferred.getErrorHook ) {
3593									process.error = jQuery.Deferred.getErrorHook();
3594
3595								// The deprecated alias of the above. While the name suggests
3596								// returning the stack, not an error instance, jQuery just passes
3597								// it directly to `console.warn` so both will work; an instance
3598								// just better cooperates with source maps.
3599								} else if ( jQuery.Deferred.getStackHook ) {
3600									process.error = jQuery.Deferred.getStackHook();
3601								}
3602								window.setTimeout( process );
3603							}
3604						};
3605					}
3606
3607					return jQuery.Deferred( function( newDefer ) {
3608
3609						// progress_handlers.add( ... )
3610						tuples[ 0 ][ 3 ].add(
3611							resolve(
3612								0,
3613								newDefer,
3614								isFunction( onProgress ) ?
3615									onProgress :
3616									Identity,
3617								newDefer.notifyWith
3618							)
3619						);
3620
3621						// fulfilled_handlers.add( ... )
3622						tuples[ 1 ][ 3 ].add(
3623							resolve(
3624								0,
3625								newDefer,
3626								isFunction( onFulfilled ) ?
3627									onFulfilled :
3628									Identity
3629							)
3630						);
3631
3632						// rejected_handlers.add( ... )
3633						tuples[ 2 ][ 3 ].add(
3634							resolve(
3635								0,
3636								newDefer,
3637								isFunction( onRejected ) ?
3638									onRejected :
3639									Thrower
3640							)
3641						);
3642					} ).promise();
3643				},
3644
3645				// Get a promise for this deferred
3646				// If obj is provided, the promise aspect is added to the object
3647				promise: function( obj ) {
3648					return obj != null ? jQuery.extend( obj, promise ) : promise;
3649				}
3650			},
3651			deferred = {};
3652
3653		// Add list-specific methods
3654		jQuery.each( tuples, function( i, tuple ) {
3655			var list = tuple[ 2 ],
3656				stateString = tuple[ 5 ];
3657
3658			// promise.progress = list.add
3659			// promise.done = list.add
3660			// promise.fail = list.add
3661			promise[ tuple[ 1 ] ] = list.add;
3662
3663			// Handle state
3664			if ( stateString ) {
3665				list.add(
3666					function() {
3667
3668						// state = "resolved" (i.e., fulfilled)
3669						// state = "rejected"
3670						state = stateString;
3671					},
3672
3673					// rejected_callbacks.disable
3674					// fulfilled_callbacks.disable
3675					tuples[ 3 - i ][ 2 ].disable,
3676
3677					// rejected_handlers.disable
3678					// fulfilled_handlers.disable
3679					tuples[ 3 - i ][ 3 ].disable,
3680
3681					// progress_callbacks.lock
3682					tuples[ 0 ][ 2 ].lock,
3683
3684					// progress_handlers.lock
3685					tuples[ 0 ][ 3 ].lock
3686				);
3687			}
3688
3689			// progress_handlers.fire
3690			// fulfilled_handlers.fire
3691			// rejected_handlers.fire
3692			list.add( tuple[ 3 ].fire );
3693
3694			// deferred.notify = function() { deferred.notifyWith(...) }
3695			// deferred.resolve = function() { deferred.resolveWith(...) }
3696			// deferred.reject = function() { deferred.rejectWith(...) }
3697			deferred[ tuple[ 0 ] ] = function() {
3698				deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments );
3699				return this;
3700			};
3701
3702			// deferred.notifyWith = list.fireWith
3703			// deferred.resolveWith = list.fireWith
3704			// deferred.rejectWith = list.fireWith
3705			deferred[ tuple[ 0 ] + "With" ] = list.fireWith;
3706		} );
3707
3708		// Make the deferred a promise
3709		promise.promise( deferred );
3710
3711		// Call given func if any
3712		if ( func ) {
3713			func.call( deferred, deferred );
3714		}
3715
3716		// All done!
3717		return deferred;
3718	},
3719
3720	// Deferred helper
3721	when: function( singleValue ) {
3722		var
3723
3724			// count of uncompleted subordinates
3725			remaining = arguments.length,
3726
3727			// count of unprocessed arguments
3728			i = remaining,
3729
3730			// subordinate fulfillment data
3731			resolveContexts = Array( i ),
3732			resolveValues = slice.call( arguments ),
3733
3734			// the primary Deferred
3735			primary = jQuery.Deferred(),
3736
3737			// subordinate callback factory
3738			updateFunc = function( i ) {
3739				return function( value ) {
3740					resolveContexts[ i ] = this;
3741					resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
3742					if ( !( --remaining ) ) {
3743						primary.resolveWith( resolveContexts, resolveValues );
3744					}
3745				};
3746			};
3747
3748		// Single- and empty arguments are adopted like Promise.resolve
3749		if ( remaining <= 1 ) {
3750			adoptValue( singleValue, primary.done( updateFunc( i ) ).resolve, primary.reject,
3751				!remaining );
3752
3753			// Use .then() to unwrap secondary thenables (cf. gh-3000)
3754			if ( primary.state() === "pending" ||
3755				isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) {
3756
3757				return primary.then();
3758			}
3759		}
3760
3761		// Multiple arguments are aggregated like Promise.all array elements
3762		while ( i-- ) {
3763			adoptValue( resolveValues[ i ], updateFunc( i ), primary.reject );
3764		}
3765
3766		return primary.promise();
3767	}
3768} );
3769
3770
3771// These usually indicate a programmer mistake during development,
3772// warn about them ASAP rather than swallowing them by default.
3773var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;
3774
3775// If `jQuery.Deferred.getErrorHook` is defined, `asyncError` is an error
3776// captured before the async barrier to get the original error cause
3777// which may otherwise be hidden.
3778jQuery.Deferred.exceptionHook = function( error, asyncError ) {
3779
3780	// Support: IE 8 - 9 only
3781	// Console exists when dev tools are open, which can happen at any time
3782	if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) {
3783		window.console.warn( "jQuery.Deferred exception: " + error.message,
3784			error.stack, asyncError );
3785	}
3786};
3787
3788
3789
3790
3791jQuery.readyException = function( error ) {
3792	window.setTimeout( function() {
3793		throw error;
3794	} );
3795};
3796
3797
3798
3799
3800// The deferred used on DOM ready
3801var readyList = jQuery.Deferred();
3802
3803jQuery.fn.ready = function( fn ) {
3804
3805	readyList
3806		.then( fn )
3807
3808		// Wrap jQuery.readyException in a function so that the lookup
3809		// happens at the time of error handling instead of callback
3810		// registration.
3811		.catch( function( error ) {
3812			jQuery.readyException( error );
3813		} );
3814
3815	return this;
3816};
3817
3818jQuery.extend( {
3819
3820	// Is the DOM ready to be used? Set to true once it occurs.
3821	isReady: false,
3822
3823	// A counter to track how many items to wait for before
3824	// the ready event fires. See trac-6781
3825	readyWait: 1,
3826
3827	// Handle when the DOM is ready
3828	ready: function( wait ) {
3829
3830		// Abort if there are pending holds or we're already ready
3831		if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
3832			return;
3833		}
3834
3835		// Remember that the DOM is ready
3836		jQuery.isReady = true;
3837
3838		// If a normal DOM Ready event fired, decrement, and wait if need be
3839		if ( wait !== true && --jQuery.readyWait > 0 ) {
3840			return;
3841		}
3842
3843		// If there are functions bound, to execute
3844		readyList.resolveWith( document, [ jQuery ] );
3845	}
3846} );
3847
3848jQuery.ready.then = readyList.then;
3849
3850// The ready event handler and self cleanup method
3851function completed() {
3852	document.removeEventListener( "DOMContentLoaded", completed );
3853	window.removeEventListener( "load", completed );
3854	jQuery.ready();
3855}
3856
3857// Catch cases where $(document).ready() is called
3858// after the browser event has already occurred.
3859// Support: IE <=9 - 10 only
3860// Older IE sometimes signals "interactive" too soon
3861if ( document.readyState === "complete" ||
3862	( document.readyState !== "loading" && !document.documentElement.doScroll ) ) {
3863
3864	// Handle it asynchronously to allow scripts the opportunity to delay ready
3865	window.setTimeout( jQuery.ready );
3866
3867} else {
3868
3869	// Use the handy event callback
3870	document.addEventListener( "DOMContentLoaded", completed );
3871
3872	// A fallback to window.onload, that will always work
3873	window.addEventListener( "load", completed );
3874}
3875
3876
3877
3878
3879// Multifunctional method to get and set values of a collection
3880// The value/s can optionally be executed if it's a function
3881var access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
3882	var i = 0,
3883		len = elems.length,
3884		bulk = key == null;
3885
3886	// Sets many values
3887	if ( toType( key ) === "object" ) {
3888		chainable = true;
3889		for ( i in key ) {
3890			access( elems, fn, i, key[ i ], true, emptyGet, raw );
3891		}
3892
3893	// Sets one value
3894	} else if ( value !== undefined ) {
3895		chainable = true;
3896
3897		if ( !isFunction( value ) ) {
3898			raw = true;
3899		}
3900
3901		if ( bulk ) {
3902
3903			// Bulk operations run against the entire set
3904			if ( raw ) {
3905				fn.call( elems, value );
3906				fn = null;
3907
3908			// ...except when executing function values
3909			} else {
3910				bulk = fn;
3911				fn = function( elem, _key, value ) {
3912					return bulk.call( jQuery( elem ), value );
3913				};
3914			}
3915		}
3916
3917		if ( fn ) {
3918			for ( ; i < len; i++ ) {
3919				fn(
3920					elems[ i ], key, raw ?
3921						value :
3922						value.call( elems[ i ], i, fn( elems[ i ], key ) )
3923				);
3924			}
3925		}
3926	}
3927
3928	if ( chainable ) {
3929		return elems;
3930	}
3931
3932	// Gets
3933	if ( bulk ) {
3934		return fn.call( elems );
3935	}
3936
3937	return len ? fn( elems[ 0 ], key ) : emptyGet;
3938};
3939
3940
3941// Matches dashed string for camelizing
3942var rmsPrefix = /^-ms-/,
3943	rdashAlpha = /-([a-z])/g;
3944
3945// Used by camelCase as callback to replace()
3946function fcamelCase( _all, letter ) {
3947	return letter.toUpperCase();
3948}
3949
3950// Convert dashed to camelCase; used by the css and data modules
3951// Support: IE <=9 - 11, Edge 12 - 15
3952// Microsoft forgot to hump their vendor prefix (trac-9572)
3953function camelCase( string ) {
3954	return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
3955}
3956var acceptData = function( owner ) {
3957
3958	// Accepts only:
3959	//  - Node
3960	//    - Node.ELEMENT_NODE
3961	//    - Node.DOCUMENT_NODE
3962	//  - Object
3963	//    - Any
3964	return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );
3965};
3966
3967
3968
3969
3970function Data() {
3971	this.expando = jQuery.expando + Data.uid++;
3972}
3973
3974Data.uid = 1;
3975
3976Data.prototype = {
3977
3978	cache: function( owner ) {
3979
3980		// Check if the owner object already has a cache
3981		var value = owner[ this.expando ];
3982
3983		// If not, create one
3984		if ( !value ) {
3985			value = {};
3986
3987			// We can accept data for non-element nodes in modern browsers,
3988			// but we should not, see trac-8335.
3989			// Always return an empty object.
3990			if ( acceptData( owner ) ) {
3991
3992				// If it is a node unlikely to be stringify-ed or looped over
3993				// use plain assignment
3994				if ( owner.nodeType ) {
3995					owner[ this.expando ] = value;
3996
3997				// Otherwise secure it in a non-enumerable property
3998				// configurable must be true to allow the property to be
3999				// deleted when data is removed
4000				} else {
4001					Object.defineProperty( owner, this.expando, {
4002						value: value,
4003						configurable: true
4004					} );
4005				}
4006			}
4007		}
4008
4009		return value;
4010	},
4011	set: function( owner, data, value ) {
4012		var prop,
4013			cache = this.cache( owner );
4014
4015		// Handle: [ owner, key, value ] args
4016		// Always use camelCase key (gh-2257)
4017		if ( typeof data === "string" ) {
4018			cache[ camelCase( data ) ] = value;
4019
4020		// Handle: [ owner, { properties } ] args
4021		} else {
4022
4023			// Copy the properties one-by-one to the cache object
4024			for ( prop in data ) {
4025				cache[ camelCase( prop ) ] = data[ prop ];
4026			}
4027		}
4028		return cache;
4029	},
4030	get: function( owner, key ) {
4031		return key === undefined ?
4032			this.cache( owner ) :
4033
4034			// Always use camelCase key (gh-2257)
4035			owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ];
4036	},
4037	access: function( owner, key, value ) {
4038
4039		// In cases where either:
4040		//
4041		//   1. No key was specified
4042		//   2. A string key was specified, but no value provided
4043		//
4044		// Take the "read" path and allow the get method to determine
4045		// which value to return, respectively either:
4046		//
4047		//   1. The entire cache object
4048		//   2. The data stored at the key
4049		//
4050		if ( key === undefined ||
4051				( ( key && typeof key === "string" ) && value === undefined ) ) {
4052
4053			return this.get( owner, key );
4054		}
4055
4056		// When the key is not a string, or both a key and value
4057		// are specified, set or extend (existing objects) with either:
4058		//
4059		//   1. An object of properties
4060		//   2. A key and value
4061		//
4062		this.set( owner, key, value );
4063
4064		// Since the "set" path can have two possible entry points
4065		// return the expected data based on which path was taken[*]
4066		return value !== undefined ? value : key;
4067	},
4068	remove: function( owner, key ) {
4069		var i,
4070			cache = owner[ this.expando ];
4071
4072		if ( cache === undefined ) {
4073			return;
4074		}
4075
4076		if ( key !== undefined ) {
4077
vendor: 4,799 bytes, lines 4078-4260
4078			// Support array or space separated string of keys
4079			if ( Array.isArray( key ) ) {
4080
4081				// If key is an array of keys...
4082				// We always set camelCase keys, so remove that.
4083				key = key.map( camelCase );
4084			} else {
4085				key = camelCase( key );
4086
4087				// If a key with the spaces exists, use it.
4088				// Otherwise, create an array by matching non-whitespace
4089				key = key in cache ?
4090					[ key ] :
4091					( key.match( rnothtmlwhite ) || [] );
4092			}
4093
4094			i = key.length;
4095
4096			while ( i-- ) {
4097				delete cache[ key[ i ] ];
4098			}
4099		}
4100
4101		// Remove the expando if there's no more data
4102		if ( key === undefined || jQuery.isEmptyObject( cache ) ) {
4103
4104			// Support: Chrome <=35 - 45
4105			// Webkit & Blink performance suffers when deleting properties
4106			// from DOM nodes, so set to undefined instead
4107			// https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted)
4108			if ( owner.nodeType ) {
4109				owner[ this.expando ] = undefined;
4110			} else {
4111				delete owner[ this.expando ];
4112			}
4113		}
4114	},
4115	hasData: function( owner ) {
4116		var cache = owner[ this.expando ];
4117		return cache !== undefined && !jQuery.isEmptyObject( cache );
4118	}
4119};
4120var dataPriv = new Data();
4121
4122var dataUser = new Data();
4123
4124
4125
4126//	Implementation Summary
4127//
4128//	1. Enforce API surface and semantic compatibility with 1.9.x branch
4129//	2. Improve the module's maintainability by reducing the storage
4130//		paths to a single mechanism.
4131//	3. Use the same single mechanism to support "private" and "user" data.
4132//	4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData)
4133//	5. Avoid exposing implementation details on user objects (eg. expando properties)
4134//	6. Provide a clear path for implementation upgrade to WeakMap in 2014
4135
4136var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
4137	rmultiDash = /[A-Z]/g;
4138
4139function getData( data ) {
4140	if ( data === "true" ) {
4141		return true;
4142	}
4143
4144	if ( data === "false" ) {
4145		return false;
4146	}
4147
4148	if ( data === "null" ) {
4149		return null;
4150	}
4151
4152	// Only convert to a number if it doesn't change the string
4153	if ( data === +data + "" ) {
4154		return +data;
4155	}
4156
4157	if ( rbrace.test( data ) ) {
4158		return JSON.parse( data );
4159	}
4160
4161	return data;
4162}
4163
4164function dataAttr( elem, key, data ) {
4165	var name;
4166
4167	// If nothing was found internally, try to fetch any
4168	// data from the HTML5 data-* attribute
4169	if ( data === undefined && elem.nodeType === 1 ) {
4170		name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase();
4171		data = elem.getAttribute( name );
4172
4173		if ( typeof data === "string" ) {
4174			try {
4175				data = getData( data );
4176			} catch ( e ) {}
4177
4178			// Make sure we set the data so it isn't changed later
4179			dataUser.set( elem, key, data );
4180		} else {
4181			data = undefined;
4182		}
4183	}
4184	return data;
4185}
4186
4187jQuery.extend( {
4188	hasData: function( elem ) {
4189		return dataUser.hasData( elem ) || dataPriv.hasData( elem );
4190	},
4191
4192	data: function( elem, name, data ) {
4193		return dataUser.access( elem, name, data );
4194	},
4195
4196	removeData: function( elem, name ) {
4197		dataUser.remove( elem, name );
4198	},
4199
4200	// TODO: Now that all calls to _data and _removeData have been replaced
4201	// with direct calls to dataPriv methods, these can be deprecated.
4202	_data: function( elem, name, data ) {
4203		return dataPriv.access( elem, name, data );
4204	},
4205
4206	_removeData: function( elem, name ) {
4207		dataPriv.remove( elem, name );
4208	}
4209} );
4210
4211jQuery.fn.extend( {
4212	data: function( key, value ) {
4213		var i, name, data,
4214			elem = this[ 0 ],
4215			attrs = elem && elem.attributes;
4216
4217		// Gets all values
4218		if ( key === undefined ) {
4219			if ( this.length ) {
4220				data = dataUser.get( elem );
4221
4222				if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) {
4223					i = attrs.length;
4224					while ( i-- ) {
4225
4226						// Support: IE 11 only
4227						// The attrs elements can be null (trac-14894)
4228						if ( attrs[ i ] ) {
4229							name = attrs[ i ].name;
4230							if ( name.indexOf( "data-" ) === 0 ) {
4231								name = camelCase( name.slice( 5 ) );
4232								dataAttr( elem, name, data[ name ] );
4233							}
4234						}
4235					}
4236					dataPriv.set( elem, "hasDataAttrs", true );
4237				}
4238			}
4239
4240			return data;
4241		}
4242
4243		// Sets multiple values
4244		if ( typeof key === "object" ) {
4245			return this.each( function() {
4246				dataUser.set( this, key );
4247			} );
4248		}
4249
4250		return access( this, function( value ) {
4251			var data;
4252
4253			// The calling jQuery object (element matches) is not empty
4254			// (and therefore has an element appears at this[ 0 ]) and the
4255			// `value` parameter was not undefined. An empty jQuery object
4256			// will result in `undefined` for elem = this[ 0 ] which will
4257			// throw an exception if an attempt to read a data cache is made.
4258			if ( elem && value === undefined ) {
4259
4260				// Attempt to get data from the cache
vendor: 20,334 bytes, lines 4261-5034
4261				// The key will always be camelCased in Data
4262				data = dataUser.get( elem, key );
4263				if ( data !== undefined ) {
4264					return data;
4265				}
4266
4267				// Attempt to "discover" the data in
4268				// HTML5 custom data-* attrs
4269				data = dataAttr( elem, key );
4270				if ( data !== undefined ) {
4271					return data;
4272				}
4273
4274				// We tried really hard, but the data doesn't exist.
4275				return;
4276			}
4277
4278			// Set the data...
4279			this.each( function() {
4280
4281				// We always store the camelCased key
4282				dataUser.set( this, key, value );
4283			} );
4284		}, null, value, arguments.length > 1, null, true );
4285	},
4286
4287	removeData: function( key ) {
4288		return this.each( function() {
4289			dataUser.remove( this, key );
4290		} );
4291	}
4292} );
4293
4294
4295jQuery.extend( {
4296	queue: function( elem, type, data ) {
4297		var queue;
4298
4299		if ( elem ) {
4300			type = ( type || "fx" ) + "queue";
4301			queue = dataPriv.get( elem, type );
4302
4303			// Speed up dequeue by getting out quickly if this is just a lookup
4304			if ( data ) {
4305				if ( !queue || Array.isArray( data ) ) {
4306					queue = dataPriv.access( elem, type, jQuery.makeArray( data ) );
4307				} else {
4308					queue.push( data );
4309				}
4310			}
4311			return queue || [];
4312		}
4313	},
4314
4315	dequeue: function( elem, type ) {
4316		type = type || "fx";
4317
4318		var queue = jQuery.queue( elem, type ),
4319			startLength = queue.length,
4320			fn = queue.shift(),
4321			hooks = jQuery._queueHooks( elem, type ),
4322			next = function() {
4323				jQuery.dequeue( elem, type );
4324			};
4325
4326		// If the fx queue is dequeued, always remove the progress sentinel
4327		if ( fn === "inprogress" ) {
4328			fn = queue.shift();
4329			startLength--;
4330		}
4331
4332		if ( fn ) {
4333
4334			// Add a progress sentinel to prevent the fx queue from being
4335			// automatically dequeued
4336			if ( type === "fx" ) {
4337				queue.unshift( "inprogress" );
4338			}
4339
4340			// Clear up the last queue stop function
4341			delete hooks.stop;
4342			fn.call( elem, next, hooks );
4343		}
4344
4345		if ( !startLength && hooks ) {
4346			hooks.empty.fire();
4347		}
4348	},
4349
4350	// Not public - generate a queueHooks object, or return the current one
4351	_queueHooks: function( elem, type ) {
4352		var key = type + "queueHooks";
4353		return dataPriv.get( elem, key ) || dataPriv.access( elem, key, {
4354			empty: jQuery.Callbacks( "once memory" ).add( function() {
4355				dataPriv.remove( elem, [ type + "queue", key ] );
4356			} )
4357		} );
4358	}
4359} );
4360
4361jQuery.fn.extend( {
4362	queue: function( type, data ) {
4363		var setter = 2;
4364
4365		if ( typeof type !== "string" ) {
4366			data = type;
4367			type = "fx";
4368			setter--;
4369		}
4370
4371		if ( arguments.length < setter ) {
4372			return jQuery.queue( this[ 0 ], type );
4373		}
4374
4375		return data === undefined ?
4376			this :
4377			this.each( function() {
4378				var queue = jQuery.queue( this, type, data );
4379
4380				// Ensure a hooks for this queue
4381				jQuery._queueHooks( this, type );
4382
4383				if ( type === "fx" && queue[ 0 ] !== "inprogress" ) {
4384					jQuery.dequeue( this, type );
4385				}
4386			} );
4387	},
4388	dequeue: function( type ) {
4389		return this.each( function() {
4390			jQuery.dequeue( this, type );
4391		} );
4392	},
4393	clearQueue: function( type ) {
4394		return this.queue( type || "fx", [] );
4395	},
4396
4397	// Get a promise resolved when queues of a certain type
4398	// are emptied (fx is the type by default)
4399	promise: function( type, obj ) {
4400		var tmp,
4401			count = 1,
4402			defer = jQuery.Deferred(),
4403			elements = this,
4404			i = this.length,
4405			resolve = function() {
4406				if ( !( --count ) ) {
4407					defer.resolveWith( elements, [ elements ] );
4408				}
4409			};
4410
4411		if ( typeof type !== "string" ) {
4412			obj = type;
4413			type = undefined;
4414		}
4415		type = type || "fx";
4416
4417		while ( i-- ) {
4418			tmp = dataPriv.get( elements[ i ], type + "queueHooks" );
4419			if ( tmp && tmp.empty ) {
4420				count++;
4421				tmp.empty.add( resolve );
4422			}
4423		}
4424		resolve();
4425		return defer.promise( obj );
4426	}
4427} );
4428var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source;
4429
4430var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" );
4431
4432
4433var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
4434
4435var documentElement = document.documentElement;
4436
4437
4438
4439	var isAttached = function( elem ) {
4440			return jQuery.contains( elem.ownerDocument, elem );
4441		},
4442		composed = { composed: true };
4443
4444	// Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only
4445	// Check attachment across shadow DOM boundaries when possible (gh-3504)
4446	// Support: iOS 10.0-10.2 only
4447	// Early iOS 10 versions support `attachShadow` but not `getRootNode`,
4448	// leading to errors. We need to check for `getRootNode`.
4449	if ( documentElement.getRootNode ) {
4450		isAttached = function( elem ) {
4451			return jQuery.contains( elem.ownerDocument, elem ) ||
4452				elem.getRootNode( composed ) === elem.ownerDocument;
4453		};
4454	}
4455var isHiddenWithinTree = function( elem, el ) {
4456
4457		// isHiddenWithinTree might be called from jQuery#filter function;
4458		// in that case, element will be second argument
4459		elem = el || elem;
4460
4461		// Inline style trumps all
4462		return elem.style.display === "none" ||
4463			elem.style.display === "" &&
4464
4465			// Otherwise, check computed style
4466			// Support: Firefox <=43 - 45
4467			// Disconnected elements can have computed display: none, so first confirm that elem is
4468			// in the document.
4469			isAttached( elem ) &&
4470
4471			jQuery.css( elem, "display" ) === "none";
4472	};
4473
4474
4475
4476function adjustCSS( elem, prop, valueParts, tween ) {
4477	var adjusted, scale,
4478		maxIterations = 20,
4479		currentValue = tween ?
4480			function() {
4481				return tween.cur();
4482			} :
4483			function() {
4484				return jQuery.css( elem, prop, "" );
4485			},
4486		initial = currentValue(),
4487		unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
4488
4489		// Starting value computation is required for potential unit mismatches
4490		initialInUnit = elem.nodeType &&
4491			( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) &&
4492			rcssNum.exec( jQuery.css( elem, prop ) );
4493
4494	if ( initialInUnit && initialInUnit[ 3 ] !== unit ) {
4495
4496		// Support: Firefox <=54
4497		// Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144)
4498		initial = initial / 2;
4499
4500		// Trust units reported by jQuery.css
4501		unit = unit || initialInUnit[ 3 ];
4502
4503		// Iteratively approximate from a nonzero starting point
4504		initialInUnit = +initial || 1;
4505
4506		while ( maxIterations-- ) {
4507
4508			// Evaluate and update our best guess (doubling guesses that zero out).
4509			// Finish if the scale equals or crosses 1 (making the old*new product non-positive).
4510			jQuery.style( elem, prop, initialInUnit + unit );
4511			if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) {
4512				maxIterations = 0;
4513			}
4514			initialInUnit = initialInUnit / scale;
4515
4516		}
4517
4518		initialInUnit = initialInUnit * 2;
4519		jQuery.style( elem, prop, initialInUnit + unit );
4520
4521		// Make sure we update the tween properties later on
4522		valueParts = valueParts || [];
4523	}
4524
4525	if ( valueParts ) {
4526		initialInUnit = +initialInUnit || +initial || 0;
4527
4528		// Apply relative offset (+=/-=) if specified
4529		adjusted = valueParts[ 1 ] ?
4530			initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] :
4531			+valueParts[ 2 ];
4532		if ( tween ) {
4533			tween.unit = unit;
4534			tween.start = initialInUnit;
4535			tween.end = adjusted;
4536		}
4537	}
4538	return adjusted;
4539}
4540
4541
4542var defaultDisplayMap = {};
4543
4544function getDefaultDisplay( elem ) {
4545	var temp,
4546		doc = elem.ownerDocument,
4547		nodeName = elem.nodeName,
4548		display = defaultDisplayMap[ nodeName ];
4549
4550	if ( display ) {
4551		return display;
4552	}
4553
4554	temp = doc.body.appendChild( doc.createElement( nodeName ) );
4555	display = jQuery.css( temp, "display" );
4556
4557	temp.parentNode.removeChild( temp );
4558
4559	if ( display === "none" ) {
4560		display = "block";
4561	}
4562	defaultDisplayMap[ nodeName ] = display;
4563
4564	return display;
4565}
4566
4567function showHide( elements, show ) {
4568	var display, elem,
4569		values = [],
4570		index = 0,
4571		length = elements.length;
4572
4573	// Determine new display value for elements that need to change
4574	for ( ; index < length; index++ ) {
4575		elem = elements[ index ];
4576		if ( !elem.style ) {
4577			continue;
4578		}
4579
4580		display = elem.style.display;
4581		if ( show ) {
4582
4583			// Since we force visibility upon cascade-hidden elements, an immediate (and slow)
4584			// check is required in this first loop unless we have a nonempty display value (either
4585			// inline or about-to-be-restored)
4586			if ( display === "none" ) {
4587				values[ index ] = dataPriv.get( elem, "display" ) || null;
4588				if ( !values[ index ] ) {
4589					elem.style.display = "";
4590				}
4591			}
4592			if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) {
4593				values[ index ] = getDefaultDisplay( elem );
4594			}
4595		} else {
4596			if ( display !== "none" ) {
4597				values[ index ] = "none";
4598
4599				// Remember what we're overwriting
4600				dataPriv.set( elem, "display", display );
4601			}
4602		}
4603	}
4604
4605	// Set the display of the elements in a second loop to avoid constant reflow
4606	for ( index = 0; index < length; index++ ) {
4607		if ( values[ index ] != null ) {
4608			elements[ index ].style.display = values[ index ];
4609		}
4610	}
4611
4612	return elements;
4613}
4614
4615jQuery.fn.extend( {
4616	show: function() {
4617		return showHide( this, true );
4618	},
4619	hide: function() {
4620		return showHide( this );
4621	},
4622	toggle: function( state ) {
4623		if ( typeof state === "boolean" ) {
4624			return state ? this.show() : this.hide();
4625		}
4626
4627		return this.each( function() {
4628			if ( isHiddenWithinTree( this ) ) {
4629				jQuery( this ).show();
4630			} else {
4631				jQuery( this ).hide();
4632			}
4633		} );
4634	}
4635} );
4636var rcheckableType = ( /^(?:checkbox|radio)$/i );
4637
4638var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]*)/i );
4639
4640var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i );
4641
4642
4643
4644( function() {
4645	var fragment = document.createDocumentFragment(),
4646		div = fragment.appendChild( document.createElement( "div" ) ),
4647		input = document.createElement( "input" );
4648
4649	// Support: Android 4.0 - 4.3 only
4650	// Check state lost if the name is set (trac-11217)
4651	// Support: Windows Web Apps (WWA)
4652	// `name` and `type` must use .setAttribute for WWA (trac-14901)
4653	input.setAttribute( "type", "radio" );
4654	input.setAttribute( "checked", "checked" );
4655	input.setAttribute( "name", "t" );
4656
4657	div.appendChild( input );
4658
4659	// Support: Android <=4.1 only
4660	// Older WebKit doesn't clone checked state correctly in fragments
4661	support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
4662
4663	// Support: IE <=11 only
4664	// Make sure textarea (and checkbox) defaultValue is properly cloned
4665	div.innerHTML = "<textarea>x</textarea>";
4666	support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
4667
4668	// Support: IE <=9 only
4669	// IE <=9 replaces <option> tags with their contents when inserted outside of
4670	// the select element.
4671	div.innerHTML = "<option></option>";
4672	support.option = !!div.lastChild;
4673} )();
4674
4675
4676// We have to close these tags to support XHTML (trac-13200)
4677var wrapMap = {
4678
4679	// XHTML parsers do not magically insert elements in the
4680	// same way that tag soup parsers do. So we cannot shorten
4681	// this by omitting <tbody> or other required elements.
4682	thead: [ 1, "<table>", "</table>" ],
4683	col: [ 2, "<table><colgroup>", "</colgroup></table>" ],
4684	tr: [ 2, "<table><tbody>", "</tbody></table>" ],
4685	td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
4686
4687	_default: [ 0, "", "" ]
4688};
4689
4690wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
4691wrapMap.th = wrapMap.td;
4692
4693// Support: IE <=9 only
4694if ( !support.option ) {
4695	wrapMap.optgroup = wrapMap.option = [ 1, "<select multiple='multiple'>", "</select>" ];
4696}
4697
4698
4699function getAll( context, tag ) {
4700
4701	// Support: IE <=9 - 11 only
4702	// Use typeof to avoid zero-argument method invocation on host objects (trac-15151)
4703	var ret;
4704
4705	if ( typeof context.getElementsByTagName !== "undefined" ) {
4706		ret = context.getElementsByTagName( tag || "*" );
4707
4708	} else if ( typeof context.querySelectorAll !== "undefined" ) {
4709		ret = context.querySelectorAll( tag || "*" );
4710
4711	} else {
4712		ret = [];
4713	}
4714
4715	if ( tag === undefined || tag && nodeName( context, tag ) ) {
4716		return jQuery.merge( [ context ], ret );
4717	}
4718
4719	return ret;
4720}
4721
4722
4723// Mark scripts as having already been evaluated
4724function setGlobalEval( elems, refElements ) {
4725	var i = 0,
4726		l = elems.length;
4727
4728	for ( ; i < l; i++ ) {
4729		dataPriv.set(
4730			elems[ i ],
4731			"globalEval",
4732			!refElements || dataPriv.get( refElements[ i ], "globalEval" )
4733		);
4734	}
4735}
4736
4737
4738var rhtml = /<|&#?\w+;/;
4739
4740function buildFragment( elems, context, scripts, selection, ignored ) {
4741	var elem, tmp, tag, wrap, attached, j,
4742		fragment = context.createDocumentFragment(),
4743		nodes = [],
4744		i = 0,
4745		l = elems.length;
4746
4747	for ( ; i < l; i++ ) {
4748		elem = elems[ i ];
4749
4750		if ( elem || elem === 0 ) {
4751
4752			// Add nodes directly
4753			if ( toType( elem ) === "object" ) {
4754
4755				// Support: Android <=4.0 only, PhantomJS 1 only
4756				// push.apply(_, arraylike) throws on ancient WebKit
4757				jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
4758
4759			// Convert non-html into a text node
4760			} else if ( !rhtml.test( elem ) ) {
4761				nodes.push( context.createTextNode( elem ) );
4762
4763			// Convert html into DOM nodes
4764			} else {
4765				tmp = tmp || fragment.appendChild( context.createElement( "div" ) );
4766
4767				// Deserialize a standard representation
4768				tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase();
4769				wrap = wrapMap[ tag ] || wrapMap._default;
4770				tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ];
4771
4772				// Descend through wrappers to the right content
4773				j = wrap[ 0 ];
4774				while ( j-- ) {
4775					tmp = tmp.lastChild;
4776				}
4777
4778				// Support: Android <=4.0 only, PhantomJS 1 only
4779				// push.apply(_, arraylike) throws on ancient WebKit
4780				jQuery.merge( nodes, tmp.childNodes );
4781
4782				// Remember the top-level container
4783				tmp = fragment.firstChild;
4784
4785				// Ensure the created nodes are orphaned (trac-12392)
4786				tmp.textContent = "";
4787			}
4788		}
4789	}
4790
4791	// Remove wrapper from fragment
4792	fragment.textContent = "";
4793
4794	i = 0;
4795	while ( ( elem = nodes[ i++ ] ) ) {
4796
4797		// Skip elements already in the context collection (trac-4087)
4798		if ( selection && jQuery.inArray( elem, selection ) > -1 ) {
4799			if ( ignored ) {
4800				ignored.push( elem );
4801			}
4802			continue;
4803		}
4804
4805		attached = isAttached( elem );
4806
4807		// Append to fragment
4808		tmp = getAll( fragment.appendChild( elem ), "script" );
4809
4810		// Preserve script evaluation history
4811		if ( attached ) {
4812			setGlobalEval( tmp );
4813		}
4814
4815		// Capture executables
4816		if ( scripts ) {
4817			j = 0;
4818			while ( ( elem = tmp[ j++ ] ) ) {
4819				if ( rscriptType.test( elem.type || "" ) ) {
4820					scripts.push( elem );
4821				}
4822			}
4823		}
4824	}
4825
4826	return fragment;
4827}
4828
4829
4830var rtypenamespace = /^([^.]*)(?:\.(.+)|)/;
4831
4832function returnTrue() {
4833	return true;
4834}
4835
4836function returnFalse() {
4837	return false;
4838}
4839
4840function on( elem, types, selector, data, fn, one ) {
4841	var origFn, type;
4842
4843	// Types can be a map of types/handlers
4844	if ( typeof types === "object" ) {
4845
4846		// ( types-Object, selector, data )
4847		if ( typeof selector !== "string" ) {
4848
4849			// ( types-Object, data )
4850			data = data || selector;
4851			selector = undefined;
4852		}
4853		for ( type in types ) {
4854			on( elem, type, selector, data, types[ type ], one );
4855		}
4856		return elem;
4857	}
4858
4859	if ( data == null && fn == null ) {
4860
4861		// ( types, fn )
4862		fn = selector;
4863		data = selector = undefined;
4864	} else if ( fn == null ) {
4865		if ( typeof selector === "string" ) {
4866
4867			// ( types, selector, fn )
4868			fn = data;
4869			data = undefined;
4870		} else {
4871
4872			// ( types, data, fn )
4873			fn = data;
4874			data = selector;
4875			selector = undefined;
4876		}
4877	}
4878	if ( fn === false ) {
4879		fn = returnFalse;
4880	} else if ( !fn ) {
4881		return elem;
4882	}
4883
4884	if ( one === 1 ) {
4885		origFn = fn;
4886		fn = function( event ) {
4887
4888			// Can use an empty set, since event contains the info
4889			jQuery().off( event );
4890			return origFn.apply( this, arguments );
4891		};
4892
4893		// Use same guid so caller can remove using origFn
4894		fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
4895	}
4896	return elem.each( function() {
4897		jQuery.event.add( this, types, fn, data, selector );
4898	} );
4899}
4900
4901/*
4902 * Helper functions for managing events -- not part of the public interface.
4903 * Props to Dean Edwards' addEvent library for many of the ideas.
4904 */
4905jQuery.event = {
4906
4907	global: {},
4908
4909	add: function( elem, types, handler, data, selector ) {
4910
4911		var handleObjIn, eventHandle, tmp,
4912			events, t, handleObj,
4913			special, handlers, type, namespaces, origType,
4914			elemData = dataPriv.get( elem );
4915
4916		// Only attach events to objects that accept data
4917		if ( !acceptData( elem ) ) {
4918			return;
4919		}
4920
4921		// Caller can pass in an object of custom data in lieu of the handler
4922		if ( handler.handler ) {
4923			handleObjIn = handler;
4924			handler = handleObjIn.handler;
4925			selector = handleObjIn.selector;
4926		}
4927
4928		// Ensure that invalid selectors throw exceptions at attach time
4929		// Evaluate against documentElement in case elem is a non-element node (e.g., document)
4930		if ( selector ) {
4931			jQuery.find.matchesSelector( documentElement, selector );
4932		}
4933
4934		// Make sure that the handler has a unique ID, used to find/remove it later
4935		if ( !handler.guid ) {
4936			handler.guid = jQuery.guid++;
4937		}
4938
4939		// Init the element's event structure and main handler, if this is the first
4940		if ( !( events = elemData.events ) ) {
4941			events = elemData.events = Object.create( null );
4942		}
4943		if ( !( eventHandle = elemData.handle ) ) {
4944			eventHandle = elemData.handle = function( e ) {
4945
4946				// Discard the second event of a jQuery.event.trigger() and
4947				// when an event is called after a page has unloaded
4948				return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ?
4949					jQuery.event.dispatch.apply( elem, arguments ) : undefined;
4950			};
4951		}
4952
4953		// Handle multiple events separated by a space
4954		types = ( types || "" ).match( rnothtmlwhite ) || [ "" ];
4955		t = types.length;
4956		while ( t-- ) {
4957			tmp = rtypenamespace.exec( types[ t ] ) || [];
4958			type = origType = tmp[ 1 ];
4959			namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
4960
4961			// There *must* be a type, no attaching namespace-only handlers
4962			if ( !type ) {
4963				continue;
4964			}
4965
4966			// If event changes its type, use the special event handlers for the changed type
4967			special = jQuery.event.special[ type ] || {};
4968
4969			// If selector defined, determine special event api type, otherwise given type
4970			type = ( selector ? special.delegateType : special.bindType ) || type;
4971
4972			// Update special based on newly reset type
4973			special = jQuery.event.special[ type ] || {};
4974
4975			// handleObj is passed to all event handlers
4976			handleObj = jQuery.extend( {
4977				type: type,
4978				origType: origType,
4979				data: data,
4980				handler: handler,
4981				guid: handler.guid,
4982				selector: selector,
4983				needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
4984				namespace: namespaces.join( "." )
4985			}, handleObjIn );
4986
4987			// Init the event handler queue if we're the first
4988			if ( !( handlers = events[ type ] ) ) {
4989				handlers = events[ type ] = [];
4990				handlers.delegateCount = 0;
4991
4992				// Only use addEventListener if the special events handler returns false
4993				if ( !special.setup ||
4994					special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
4995
4996					if ( elem.addEventListener ) {
4997						elem.addEventListener( type, eventHandle );
4998					}
4999				}
5000			}
5001
5002			if ( special.add ) {
5003				special.add.call( elem, handleObj );
5004
5005				if ( !handleObj.handler.guid ) {
5006					handleObj.handler.guid = handler.guid;
5007				}
5008			}
5009
5010			// Add to the element's handler list, delegates in front
5011			if ( selector ) {
5012				handlers.splice( handlers.delegateCount++, 0, handleObj );
5013			} else {
5014				handlers.push( handleObj );
5015			}
5016
5017			// Keep track of which events have ever been used, for event optimization
5018			jQuery.event.global[ type ] = true;
5019		}
5020
5021	},
5022
5023	// Detach an event or set of events from an element
5024	remove: function( elem, types, handler, selector, mappedTypes ) {
5025
5026		var j, origCount, tmp,
5027			events, t, handleObj,
5028			special, handlers, type, namespaces, origType,
5029			elemData = dataPriv.hasData( elem ) && dataPriv.get( elem );
5030
5031		if ( !elemData || !( events = elemData.events ) ) {
5032			return;
5033		}
5034
vendor: 4,336 bytes, lines 5035-5173
5035		// Once for each type.namespace in types; type may be omitted
5036		types = ( types || "" ).match( rnothtmlwhite ) || [ "" ];
5037		t = types.length;
5038		while ( t-- ) {
5039			tmp = rtypenamespace.exec( types[ t ] ) || [];
5040			type = origType = tmp[ 1 ];
5041			namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
5042
5043			// Unbind all events (on this namespace, if provided) for the element
5044			if ( !type ) {
5045				for ( type in events ) {
5046					jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
5047				}
5048				continue;
5049			}
5050
5051			special = jQuery.event.special[ type ] || {};
5052			type = ( selector ? special.delegateType : special.bindType ) || type;
5053			handlers = events[ type ] || [];
5054			tmp = tmp[ 2 ] &&
5055				new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" );
5056
5057			// Remove matching events
5058			origCount = j = handlers.length;
5059			while ( j-- ) {
5060				handleObj = handlers[ j ];
5061
5062				if ( ( mappedTypes || origType === handleObj.origType ) &&
5063					( !handler || handler.guid === handleObj.guid ) &&
5064					( !tmp || tmp.test( handleObj.namespace ) ) &&
5065					( !selector || selector === handleObj.selector ||
5066						selector === "**" && handleObj.selector ) ) {
5067					handlers.splice( j, 1 );
5068
5069					if ( handleObj.selector ) {
5070						handlers.delegateCount--;
5071					}
5072					if ( special.remove ) {
5073						special.remove.call( elem, handleObj );
5074					}
5075				}
5076			}
5077
5078			// Remove generic event handler if we removed something and no more handlers exist
5079			// (avoids potential for endless recursion during removal of special event handlers)
5080			if ( origCount && !handlers.length ) {
5081				if ( !special.teardown ||
5082					special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
5083
5084					jQuery.removeEvent( elem, type, elemData.handle );
5085				}
5086
5087				delete events[ type ];
5088			}
5089		}
5090
5091		// Remove data and the expando if it's no longer used
5092		if ( jQuery.isEmptyObject( events ) ) {
5093			dataPriv.remove( elem, "handle events" );
5094		}
5095	},
5096
5097	dispatch: function( nativeEvent ) {
5098
5099		var i, j, ret, matched, handleObj, handlerQueue,
5100			args = new Array( arguments.length ),
5101
5102			// Make a writable jQuery.Event from the native event object
5103			event = jQuery.event.fix( nativeEvent ),
5104
5105			handlers = (
5106				dataPriv.get( this, "events" ) || Object.create( null )
5107			)[ event.type ] || [],
5108			special = jQuery.event.special[ event.type ] || {};
5109
5110		// Use the fix-ed jQuery.Event rather than the (read-only) native event
5111		args[ 0 ] = event;
5112
5113		for ( i = 1; i < arguments.length; i++ ) {
5114			args[ i ] = arguments[ i ];
5115		}
5116
5117		event.delegateTarget = this;
5118
5119		// Call the preDispatch hook for the mapped type, and let it bail if desired
5120		if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
5121			return;
5122		}
5123
5124		// Determine handlers
5125		handlerQueue = jQuery.event.handlers.call( this, event, handlers );
5126
5127		// Run delegates first; they may want to stop propagation beneath us
5128		i = 0;
5129		while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) {
5130			event.currentTarget = matched.elem;
5131
5132			j = 0;
5133			while ( ( handleObj = matched.handlers[ j++ ] ) &&
5134				!event.isImmediatePropagationStopped() ) {
5135
5136				// If the event is namespaced, then each handler is only invoked if it is
5137				// specially universal or its namespaces are a superset of the event's.
5138				if ( !event.rnamespace || handleObj.namespace === false ||
5139					event.rnamespace.test( handleObj.namespace ) ) {
5140
5141					event.handleObj = handleObj;
5142					event.data = handleObj.data;
5143
5144					ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle ||
5145						handleObj.handler ).apply( matched.elem, args );
5146
5147					if ( ret !== undefined ) {
5148						if ( ( event.result = ret ) === false ) {
5149							event.preventDefault();
5150							event.stopPropagation();
5151						}
5152					}
5153				}
5154			}
5155		}
5156
5157		// Call the postDispatch hook for the mapped type
5158		if ( special.postDispatch ) {
5159			special.postDispatch.call( this, event );
5160		}
5161
5162		return event.result;
5163	},
5164
5165	handlers: function( event, handlers ) {
5166		var i, handleObj, sel, matchedHandlers, matchedSelectors,
5167			handlerQueue = [],
5168			delegateCount = handlers.delegateCount,
5169			cur = event.target;
5170
5171		// Find delegate handlers
5172		if ( delegateCount &&
5173
vendor: 26,293 bytes, lines 5174-6050
5174			// Support: IE <=9
5175			// Black-hole SVG <use> instance trees (trac-13180)
5176			cur.nodeType &&
5177
5178			// Support: Firefox <=42
5179			// Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861)
5180			// https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click
5181			// Support: IE 11 only
5182			// ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343)
5183			!( event.type === "click" && event.button >= 1 ) ) {
5184
5185			for ( ; cur !== this; cur = cur.parentNode || this ) {
5186
5187				// Don't check non-elements (trac-13208)
5188				// Don't process clicks on disabled elements (trac-6911, trac-8165, trac-11382, trac-11764)
5189				if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) {
5190					matchedHandlers = [];
5191					matchedSelectors = {};
5192					for ( i = 0; i < delegateCount; i++ ) {
5193						handleObj = handlers[ i ];
5194
5195						// Don't conflict with Object.prototype properties (trac-13203)
5196						sel = handleObj.selector + " ";
5197
5198						if ( matchedSelectors[ sel ] === undefined ) {
5199							matchedSelectors[ sel ] = handleObj.needsContext ?
5200								jQuery( sel, this ).index( cur ) > -1 :
5201								jQuery.find( sel, this, null, [ cur ] ).length;
5202						}
5203						if ( matchedSelectors[ sel ] ) {
5204							matchedHandlers.push( handleObj );
5205						}
5206					}
5207					if ( matchedHandlers.length ) {
5208						handlerQueue.push( { elem: cur, handlers: matchedHandlers } );
5209					}
5210				}
5211			}
5212		}
5213
5214		// Add the remaining (directly-bound) handlers
5215		cur = this;
5216		if ( delegateCount < handlers.length ) {
5217			handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } );
5218		}
5219
5220		return handlerQueue;
5221	},
5222
5223	addProp: function( name, hook ) {
5224		Object.defineProperty( jQuery.Event.prototype, name, {
5225			enumerable: true,
5226			configurable: true,
5227
5228			get: isFunction( hook ) ?
5229				function() {
5230					if ( this.originalEvent ) {
5231						return hook( this.originalEvent );
5232					}
5233				} :
5234				function() {
5235					if ( this.originalEvent ) {
5236						return this.originalEvent[ name ];
5237					}
5238				},
5239
5240			set: function( value ) {
5241				Object.defineProperty( this, name, {
5242					enumerable: true,
5243					configurable: true,
5244					writable: true,
5245					value: value
5246				} );
5247			}
5248		} );
5249	},
5250
5251	fix: function( originalEvent ) {
5252		return originalEvent[ jQuery.expando ] ?
5253			originalEvent :
5254			new jQuery.Event( originalEvent );
5255	},
5256
5257	special: {
5258		load: {
5259
5260			// Prevent triggered image.load events from bubbling to window.load
5261			noBubble: true
5262		},
5263		click: {
5264
5265			// Utilize native event to ensure correct state for checkable inputs
5266			setup: function( data ) {
5267
5268				// For mutual compressibility with _default, replace `this` access with a local var.
5269				// `|| data` is dead code meant only to preserve the variable through minification.
5270				var el = this || data;
5271
5272				// Claim the first handler
5273				if ( rcheckableType.test( el.type ) &&
5274					el.click && nodeName( el, "input" ) ) {
5275
5276					// dataPriv.set( el, "click", ... )
5277					leverageNative( el, "click", true );
5278				}
5279
5280				// Return false to allow normal processing in the caller
5281				return false;
5282			},
5283			trigger: function( data ) {
5284
5285				// For mutual compressibility with _default, replace `this` access with a local var.
5286				// `|| data` is dead code meant only to preserve the variable through minification.
5287				var el = this || data;
5288
5289				// Force setup before triggering a click
5290				if ( rcheckableType.test( el.type ) &&
5291					el.click && nodeName( el, "input" ) ) {
5292
5293					leverageNative( el, "click" );
5294				}
5295
5296				// Return non-false to allow normal event-path propagation
5297				return true;
5298			},
5299
5300			// For cross-browser consistency, suppress native .click() on links
5301			// Also prevent it if we're currently inside a leveraged native-event stack
5302			_default: function( event ) {
5303				var target = event.target;
5304				return rcheckableType.test( target.type ) &&
5305					target.click && nodeName( target, "input" ) &&
5306					dataPriv.get( target, "click" ) ||
5307					nodeName( target, "a" );
5308			}
5309		},
5310
5311		beforeunload: {
5312			postDispatch: function( event ) {
5313
5314				// Support: Firefox 20+
5315				// Firefox doesn't alert if the returnValue field is not set.
5316				if ( event.result !== undefined && event.originalEvent ) {
5317					event.originalEvent.returnValue = event.result;
5318				}
5319			}
5320		}
5321	}
5322};
5323
5324// Ensure the presence of an event listener that handles manually-triggered
5325// synthetic events by interrupting progress until reinvoked in response to
5326// *native* events that it fires directly, ensuring that state changes have
5327// already occurred before other listeners are invoked.
5328function leverageNative( el, type, isSetup ) {
5329
5330	// Missing `isSetup` indicates a trigger call, which must force setup through jQuery.event.add
5331	if ( !isSetup ) {
5332		if ( dataPriv.get( el, type ) === undefined ) {
5333			jQuery.event.add( el, type, returnTrue );
5334		}
5335		return;
5336	}
5337
5338	// Register the controller as a special universal handler for all event namespaces
5339	dataPriv.set( el, type, false );
5340	jQuery.event.add( el, type, {
5341		namespace: false,
5342		handler: function( event ) {
5343			var result,
5344				saved = dataPriv.get( this, type );
5345
5346			if ( ( event.isTrigger & 1 ) && this[ type ] ) {
5347
5348				// Interrupt processing of the outer synthetic .trigger()ed event
5349				if ( !saved ) {
5350
5351					// Store arguments for use when handling the inner native event
5352					// There will always be at least one argument (an event object), so this array
5353					// will not be confused with a leftover capture object.
5354					saved = slice.call( arguments );
5355					dataPriv.set( this, type, saved );
5356
5357					// Trigger the native event and capture its result
5358					this[ type ]();
5359					result = dataPriv.get( this, type );
5360					dataPriv.set( this, type, false );
5361
5362					if ( saved !== result ) {
5363
5364						// Cancel the outer synthetic event
5365						event.stopImmediatePropagation();
5366						event.preventDefault();
5367
5368						return result;
5369					}
5370
5371				// If this is an inner synthetic event for an event with a bubbling surrogate
5372				// (focus or blur), assume that the surrogate already propagated from triggering
5373				// the native event and prevent that from happening again here.
5374				// This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the
5375				// bubbling surrogate propagates *after* the non-bubbling base), but that seems
5376				// less bad than duplication.
5377				} else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) {
5378					event.stopPropagation();
5379				}
5380
5381			// If this is a native event triggered above, everything is now in order
5382			// Fire an inner synthetic event with the original arguments
5383			} else if ( saved ) {
5384
5385				// ...and capture the result
5386				dataPriv.set( this, type, jQuery.event.trigger(
5387					saved[ 0 ],
5388					saved.slice( 1 ),
5389					this
5390				) );
5391
5392				// Abort handling of the native event by all jQuery handlers while allowing
5393				// native handlers on the same element to run. On target, this is achieved
5394				// by stopping immediate propagation just on the jQuery event. However,
5395				// the native event is re-wrapped by a jQuery one on each level of the
5396				// propagation so the only way to stop it for jQuery is to stop it for
5397				// everyone via native `stopPropagation()`. This is not a problem for
5398				// focus/blur which don't bubble, but it does also stop click on checkboxes
5399				// and radios. We accept this limitation.
5400				event.stopPropagation();
5401				event.isImmediatePropagationStopped = returnTrue;
5402			}
5403		}
5404	} );
5405}
5406
5407jQuery.removeEvent = function( elem, type, handle ) {
5408
5409	// This "if" is needed for plain objects
5410	if ( elem.removeEventListener ) {
5411		elem.removeEventListener( type, handle );
5412	}
5413};
5414
5415jQuery.Event = function( src, props ) {
5416
5417	// Allow instantiation without the 'new' keyword
5418	if ( !( this instanceof jQuery.Event ) ) {
5419		return new jQuery.Event( src, props );
5420	}
5421
5422	// Event object
5423	if ( src && src.type ) {
5424		this.originalEvent = src;
5425		this.type = src.type;
5426
5427		// Events bubbling up the document may have been marked as prevented
5428		// by a handler lower down the tree; reflect the correct value.
5429		this.isDefaultPrevented = src.defaultPrevented ||
5430				src.defaultPrevented === undefined &&
5431
5432				// Support: Android <=2.3 only
5433				src.returnValue === false ?
5434			returnTrue :
5435			returnFalse;
5436
5437		// Create target properties
5438		// Support: Safari <=6 - 7 only
5439		// Target should not be a text node (trac-504, trac-13143)
5440		this.target = ( src.target && src.target.nodeType === 3 ) ?
5441			src.target.parentNode :
5442			src.target;
5443
5444		this.currentTarget = src.currentTarget;
5445		this.relatedTarget = src.relatedTarget;
5446
5447	// Event type
5448	} else {
5449		this.type = src;
5450	}
5451
5452	// Put explicitly provided properties onto the event object
5453	if ( props ) {
5454		jQuery.extend( this, props );
5455	}
5456
5457	// Create a timestamp if incoming event doesn't have one
5458	this.timeStamp = src && src.timeStamp || Date.now();
5459
5460	// Mark it as fixed
5461	this[ jQuery.expando ] = true;
5462};
5463
5464// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
5465// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
5466jQuery.Event.prototype = {
5467	constructor: jQuery.Event,
5468	isDefaultPrevented: returnFalse,
5469	isPropagationStopped: returnFalse,
5470	isImmediatePropagationStopped: returnFalse,
5471	isSimulated: false,
5472
5473	preventDefault: function() {
5474		var e = this.originalEvent;
5475
5476		this.isDefaultPrevented = returnTrue;
5477
5478		if ( e && !this.isSimulated ) {
5479			e.preventDefault();
5480		}
5481	},
5482	stopPropagation: function() {
5483		var e = this.originalEvent;
5484
5485		this.isPropagationStopped = returnTrue;
5486
5487		if ( e && !this.isSimulated ) {
5488			e.stopPropagation();
5489		}
5490	},
5491	stopImmediatePropagation: function() {
5492		var e = this.originalEvent;
5493
5494		this.isImmediatePropagationStopped = returnTrue;
5495
5496		if ( e && !this.isSimulated ) {
5497			e.stopImmediatePropagation();
5498		}
5499
5500		this.stopPropagation();
5501	}
5502};
5503
5504// Includes all common event props including KeyEvent and MouseEvent specific props
5505jQuery.each( {
5506	altKey: true,
5507	bubbles: true,
5508	cancelable: true,
5509	changedTouches: true,
5510	ctrlKey: true,
5511	detail: true,
5512	eventPhase: true,
5513	metaKey: true,
5514	pageX: true,
5515	pageY: true,
5516	shiftKey: true,
5517	view: true,
5518	"char": true,
5519	code: true,
5520	charCode: true,
5521	key: true,
5522	keyCode: true,
5523	button: true,
5524	buttons: true,
5525	clientX: true,
5526	clientY: true,
5527	offsetX: true,
5528	offsetY: true,
5529	pointerId: true,
5530	pointerType: true,
5531	screenX: true,
5532	screenY: true,
5533	targetTouches: true,
5534	toElement: true,
5535	touches: true,
5536	which: true
5537}, jQuery.event.addProp );
5538
5539jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) {
5540
5541	function focusMappedHandler( nativeEvent ) {
5542		if ( document.documentMode ) {
5543
5544			// Support: IE 11+
5545			// Attach a single focusin/focusout handler on the document while someone wants
5546			// focus/blur. This is because the former are synchronous in IE while the latter
5547			// are async. In other browsers, all those handlers are invoked synchronously.
5548
5549			// `handle` from private data would already wrap the event, but we need
5550			// to change the `type` here.
5551			var handle = dataPriv.get( this, "handle" ),
5552				event = jQuery.event.fix( nativeEvent );
5553			event.type = nativeEvent.type === "focusin" ? "focus" : "blur";
5554			event.isSimulated = true;
5555
5556			// First, handle focusin/focusout
5557			handle( nativeEvent );
5558
5559			// ...then, handle focus/blur
5560			//
5561			// focus/blur don't bubble while focusin/focusout do; simulate the former by only
5562			// invoking the handler at the lower level.
5563			if ( event.target === event.currentTarget ) {
5564
5565				// The setup part calls `leverageNative`, which, in turn, calls
5566				// `jQuery.event.add`, so event handle will already have been set
5567				// by this point.
5568				handle( event );
5569			}
5570		} else {
5571
5572			// For non-IE browsers, attach a single capturing handler on the document
5573			// while someone wants focusin/focusout.
5574			jQuery.event.simulate( delegateType, nativeEvent.target,
5575				jQuery.event.fix( nativeEvent ) );
5576		}
5577	}
5578
5579	jQuery.event.special[ type ] = {
5580
5581		// Utilize native event if possible so blur/focus sequence is correct
5582		setup: function() {
5583
5584			var attaches;
5585
5586			// Claim the first handler
5587			// dataPriv.set( this, "focus", ... )
5588			// dataPriv.set( this, "blur", ... )
5589			leverageNative( this, type, true );
5590
5591			if ( document.documentMode ) {
5592
5593				// Support: IE 9 - 11+
5594				// We use the same native handler for focusin & focus (and focusout & blur)
5595				// so we need to coordinate setup & teardown parts between those events.
5596				// Use `delegateType` as the key as `type` is already used by `leverageNative`.
5597				attaches = dataPriv.get( this, delegateType );
5598				if ( !attaches ) {
5599					this.addEventListener( delegateType, focusMappedHandler );
5600				}
5601				dataPriv.set( this, delegateType, ( attaches || 0 ) + 1 );
5602			} else {
5603
5604				// Return false to allow normal processing in the caller
5605				return false;
5606			}
5607		},
5608		trigger: function() {
5609
5610			// Force setup before trigger
5611			leverageNative( this, type );
5612
5613			// Return non-false to allow normal event-path propagation
5614			return true;
5615		},
5616
5617		teardown: function() {
5618			var attaches;
5619
5620			if ( document.documentMode ) {
5621				attaches = dataPriv.get( this, delegateType ) - 1;
5622				if ( !attaches ) {
5623					this.removeEventListener( delegateType, focusMappedHandler );
5624					dataPriv.remove( this, delegateType );
5625				} else {
5626					dataPriv.set( this, delegateType, attaches );
5627				}
5628			} else {
5629
5630				// Return false to indicate standard teardown should be applied
5631				return false;
5632			}
5633		},
5634
5635		// Suppress native focus or blur if we're currently inside
5636		// a leveraged native-event stack
5637		_default: function( event ) {
5638			return dataPriv.get( event.target, type );
5639		},
5640
5641		delegateType: delegateType
5642	};
5643
5644	// Support: Firefox <=44
5645	// Firefox doesn't have focus(in | out) events
5646	// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787
5647	//
5648	// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1
5649	// focus(in | out) events fire after focus & blur events,
5650	// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order
5651	// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857
5652	//
5653	// Support: IE 9 - 11+
5654	// To preserve relative focusin/focus & focusout/blur event order guaranteed on the 3.x branch,
5655	// attach a single handler for both events in IE.
5656	jQuery.event.special[ delegateType ] = {
5657		setup: function() {
5658
5659			// Handle: regular nodes (via `this.ownerDocument`), window
5660			// (via `this.document`) & document (via `this`).
5661			var doc = this.ownerDocument || this.document || this,
5662				dataHolder = document.documentMode ? this : doc,
5663				attaches = dataPriv.get( dataHolder, delegateType );
5664
5665			// Support: IE 9 - 11+
5666			// We use the same native handler for focusin & focus (and focusout & blur)
5667			// so we need to coordinate setup & teardown parts between those events.
5668			// Use `delegateType` as the key as `type` is already used by `leverageNative`.
5669			if ( !attaches ) {
5670				if ( document.documentMode ) {
5671					this.addEventListener( delegateType, focusMappedHandler );
5672				} else {
5673					doc.addEventListener( type, focusMappedHandler, true );
5674				}
5675			}
5676			dataPriv.set( dataHolder, delegateType, ( attaches || 0 ) + 1 );
5677		},
5678		teardown: function() {
5679			var doc = this.ownerDocument || this.document || this,
5680				dataHolder = document.documentMode ? this : doc,
5681				attaches = dataPriv.get( dataHolder, delegateType ) - 1;
5682
5683			if ( !attaches ) {
5684				if ( document.documentMode ) {
5685					this.removeEventListener( delegateType, focusMappedHandler );
5686				} else {
5687					doc.removeEventListener( type, focusMappedHandler, true );
5688				}
5689				dataPriv.remove( dataHolder, delegateType );
5690			} else {
5691				dataPriv.set( dataHolder, delegateType, attaches );
5692			}
5693		}
5694	};
5695} );
5696
5697// Create mouseenter/leave events using mouseover/out and event-time checks
5698// so that event delegation works in jQuery.
5699// Do the same for pointerenter/pointerleave and pointerover/pointerout
5700//
5701// Support: Safari 7 only
5702// Safari sends mouseenter too often; see:
5703// https://bugs.chromium.org/p/chromium/issues/detail?id=470258
5704// for the description of the bug (it existed in older Chrome versions as well).
5705jQuery.each( {
5706	mouseenter: "mouseover",
5707	mouseleave: "mouseout",
5708	pointerenter: "pointerover",
5709	pointerleave: "pointerout"
5710}, function( orig, fix ) {
5711	jQuery.event.special[ orig ] = {
5712		delegateType: fix,
5713		bindType: fix,
5714
5715		handle: function( event ) {
5716			var ret,
5717				target = this,
5718				related = event.relatedTarget,
5719				handleObj = event.handleObj;
5720
5721			// For mouseenter/leave call the handler if related is outside the target.
5722			// NB: No relatedTarget if the mouse left/entered the browser window
5723			if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) {
5724				event.type = handleObj.origType;
5725				ret = handleObj.handler.apply( this, arguments );
5726				event.type = fix;
5727			}
5728			return ret;
5729		}
5730	};
5731} );
5732
5733jQuery.fn.extend( {
5734
5735	on: function( types, selector, data, fn ) {
5736		return on( this, types, selector, data, fn );
5737	},
5738	one: function( types, selector, data, fn ) {
5739		return on( this, types, selector, data, fn, 1 );
5740	},
5741	off: function( types, selector, fn ) {
5742		var handleObj, type;
5743		if ( types && types.preventDefault && types.handleObj ) {
5744
5745			// ( event )  dispatched jQuery.Event
5746			handleObj = types.handleObj;
5747			jQuery( types.delegateTarget ).off(
5748				handleObj.namespace ?
5749					handleObj.origType + "." + handleObj.namespace :
5750					handleObj.origType,
5751				handleObj.selector,
5752				handleObj.handler
5753			);
5754			return this;
5755		}
5756		if ( typeof types === "object" ) {
5757
5758			// ( types-object [, selector] )
5759			for ( type in types ) {
5760				this.off( type, selector, types[ type ] );
5761			}
5762			return this;
5763		}
5764		if ( selector === false || typeof selector === "function" ) {
5765
5766			// ( types [, fn] )
5767			fn = selector;
5768			selector = undefined;
5769		}
5770		if ( fn === false ) {
5771			fn = returnFalse;
5772		}
5773		return this.each( function() {
5774			jQuery.event.remove( this, types, fn, selector );
5775		} );
5776	}
5777} );
5778
5779
5780var
5781
5782	// Support: IE <=10 - 11, Edge 12 - 13 only
5783	// In IE/Edge using regex groups here causes severe slowdowns.
5784	// See https://connect.microsoft.com/IE/feedback/details/1736512/
5785	rnoInnerhtml = /<script|<style|<link/i,
5786
5787	// checked="checked" or checked
5788	rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
5789
5790	rcleanScript = /^\s*<!\[CDATA\[|\]\]>\s*$/g;
5791
5792// Prefer a tbody over its parent table for containing new rows
5793function manipulationTarget( elem, content ) {
5794	if ( nodeName( elem, "table" ) &&
5795		nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) {
5796
5797		return jQuery( elem ).children( "tbody" )[ 0 ] || elem;
5798	}
5799
5800	return elem;
5801}
5802
5803// Replace/restore the type attribute of script elements for safe DOM manipulation
5804function disableScript( elem ) {
5805	elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type;
5806	return elem;
5807}
5808function restoreScript( elem ) {
5809	if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) {
5810		elem.type = elem.type.slice( 5 );
5811	} else {
5812		elem.removeAttribute( "type" );
5813	}
5814
5815	return elem;
5816}
5817
5818function cloneCopyEvent( src, dest ) {
5819	var i, l, type, pdataOld, udataOld, udataCur, events;
5820
5821	if ( dest.nodeType !== 1 ) {
5822		return;
5823	}
5824
5825	// 1. Copy private data: events, handlers, etc.
5826	if ( dataPriv.hasData( src ) ) {
5827		pdataOld = dataPriv.get( src );
5828		events = pdataOld.events;
5829
5830		if ( events ) {
5831			dataPriv.remove( dest, "handle events" );
5832
5833			for ( type in events ) {
5834				for ( i = 0, l = events[ type ].length; i < l; i++ ) {
5835					jQuery.event.add( dest, type, events[ type ][ i ] );
5836				}
5837			}
5838		}
5839	}
5840
5841	// 2. Copy user data
5842	if ( dataUser.hasData( src ) ) {
5843		udataOld = dataUser.access( src );
5844		udataCur = jQuery.extend( {}, udataOld );
5845
5846		dataUser.set( dest, udataCur );
5847	}
5848}
5849
5850// Fix IE bugs, see support tests
5851function fixInput( src, dest ) {
5852	var nodeName = dest.nodeName.toLowerCase();
5853
5854	// Fails to persist the checked state of a cloned checkbox or radio button.
5855	if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
5856		dest.checked = src.checked;
5857
5858	// Fails to return the selected option to the default selected state when cloning options
5859	} else if ( nodeName === "input" || nodeName === "textarea" ) {
5860		dest.defaultValue = src.defaultValue;
5861	}
5862}
5863
5864function domManip( collection, args, callback, ignored ) {
5865
5866	// Flatten any nested arrays
5867	args = flat( args );
5868
5869	var fragment, first, scripts, hasScripts, node, doc,
5870		i = 0,
5871		l = collection.length,
5872		iNoClone = l - 1,
5873		value = args[ 0 ],
5874		valueIsFunction = isFunction( value );
5875
5876	// We can't cloneNode fragments that contain checked, in WebKit
5877	if ( valueIsFunction ||
5878			( l > 1 && typeof value === "string" &&
5879				!support.checkClone && rchecked.test( value ) ) ) {
5880		return collection.each( function( index ) {
5881			var self = collection.eq( index );
5882			if ( valueIsFunction ) {
5883				args[ 0 ] = value.call( this, index, self.html() );
5884			}
5885			domManip( self, args, callback, ignored );
5886		} );
5887	}
5888
5889	if ( l ) {
5890		fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored );
5891		first = fragment.firstChild;
5892
5893		if ( fragment.childNodes.length === 1 ) {
5894			fragment = first;
5895		}
5896
5897		// Require either new content or an interest in ignored elements to invoke the callback
5898		if ( first || ignored ) {
5899			scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
5900			hasScripts = scripts.length;
5901
5902			// Use the original fragment for the last item
5903			// instead of the first because it can end up
5904			// being emptied incorrectly in certain situations (trac-8070).
5905			for ( ; i < l; i++ ) {
5906				node = fragment;
5907
5908				if ( i !== iNoClone ) {
5909					node = jQuery.clone( node, true, true );
5910
5911					// Keep references to cloned scripts for later restoration
5912					if ( hasScripts ) {
5913
5914						// Support: Android <=4.0 only, PhantomJS 1 only
5915						// push.apply(_, arraylike) throws on ancient WebKit
5916						jQuery.merge( scripts, getAll( node, "script" ) );
5917					}
5918				}
5919
5920				callback.call( collection[ i ], node, i );
5921			}
5922
5923			if ( hasScripts ) {
5924				doc = scripts[ scripts.length - 1 ].ownerDocument;
5925
5926				// Re-enable scripts
5927				jQuery.map( scripts, restoreScript );
5928
5929				// Evaluate executable scripts on first document insertion
5930				for ( i = 0; i < hasScripts; i++ ) {
5931					node = scripts[ i ];
5932					if ( rscriptType.test( node.type || "" ) &&
5933						!dataPriv.access( node, "globalEval" ) &&
5934						jQuery.contains( doc, node ) ) {
5935
5936						if ( node.src && ( node.type || "" ).toLowerCase()  !== "module" ) {
5937
5938							// Optional AJAX dependency, but won't run scripts if not present
5939							if ( jQuery._evalUrl && !node.noModule ) {
5940								jQuery._evalUrl( node.src, {
5941									nonce: node.nonce || node.getAttribute( "nonce" )
5942								}, doc );
5943							}
5944						} else {
5945
5946							// Unwrap a CDATA section containing script contents. This shouldn't be
5947							// needed as in XML documents they're already not visible when
5948							// inspecting element contents and in HTML documents they have no
5949							// meaning but we're preserving that logic for backwards compatibility.
5950							// This will be removed completely in 4.0. See gh-4904.
5951							DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc );
5952						}
5953					}
5954				}
5955			}
5956		}
5957	}
5958
5959	return collection;
5960}
5961
5962function remove( elem, selector, keepData ) {
5963	var node,
5964		nodes = selector ? jQuery.filter( selector, elem ) : elem,
5965		i = 0;
5966
5967	for ( ; ( node = nodes[ i ] ) != null; i++ ) {
5968		if ( !keepData && node.nodeType === 1 ) {
5969			jQuery.cleanData( getAll( node ) );
5970		}
5971
5972		if ( node.parentNode ) {
5973			if ( keepData && isAttached( node ) ) {
5974				setGlobalEval( getAll( node, "script" ) );
5975			}
5976			node.parentNode.removeChild( node );
5977		}
5978	}
5979
5980	return elem;
5981}
5982
5983jQuery.extend( {
5984	htmlPrefilter: function( html ) {
5985		return html;
5986	},
5987
5988	clone: function( elem, dataAndEvents, deepDataAndEvents ) {
5989		var i, l, srcElements, destElements,
5990			clone = elem.cloneNode( true ),
5991			inPage = isAttached( elem );
5992
5993		// Fix IE cloning issues
5994		if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&
5995				!jQuery.isXMLDoc( elem ) ) {
5996
5997			// We eschew jQuery#find here for performance reasons:
5998			// https://jsperf.com/getall-vs-sizzle/2
5999			destElements = getAll( clone );
6000			srcElements = getAll( elem );
6001
6002			for ( i = 0, l = srcElements.length; i < l; i++ ) {
6003				fixInput( srcElements[ i ], destElements[ i ] );
6004			}
6005		}
6006
6007		// Copy the events from the original to the clone
6008		if ( dataAndEvents ) {
6009			if ( deepDataAndEvents ) {
6010				srcElements = srcElements || getAll( elem );
6011				destElements = destElements || getAll( clone );
6012
6013				for ( i = 0, l = srcElements.length; i < l; i++ ) {
6014					cloneCopyEvent( srcElements[ i ], destElements[ i ] );
6015				}
6016			} else {
6017				cloneCopyEvent( elem, clone );
6018			}
6019		}
6020
6021		// Preserve script evaluation history
6022		destElements = getAll( clone, "script" );
6023		if ( destElements.length > 0 ) {
6024			setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
6025		}
6026
6027		// Return the cloned set
6028		return clone;
6029	},
6030
6031	cleanData: function( elems ) {
6032		var data, elem, type,
6033			special = jQuery.event.special,
6034			i = 0;
6035
6036		for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) {
6037			if ( acceptData( elem ) ) {
6038				if ( ( data = elem[ dataPriv.expando ] ) ) {
6039					if ( data.events ) {
6040						for ( type in data.events ) {
6041							if ( special[ type ] ) {
6042								jQuery.event.remove( elem, type );
6043
6044							// This is a shortcut to avoid jQuery.event.remove's overhead
6045							} else {
6046								jQuery.removeEvent( elem, type, data.handle );
6047							}
6048						}
6049					}
6050
vendor: 4,139 bytes, lines 6051-6215
6051					// Support: Chrome <=35 - 45+
6052					// Assign undefined instead of using delete, see Data#remove
6053					elem[ dataPriv.expando ] = undefined;
6054				}
6055				if ( elem[ dataUser.expando ] ) {
6056
6057					// Support: Chrome <=35 - 45+
6058					// Assign undefined instead of using delete, see Data#remove
6059					elem[ dataUser.expando ] = undefined;
6060				}
6061			}
6062		}
6063	}
6064} );
6065
6066jQuery.fn.extend( {
6067	detach: function( selector ) {
6068		return remove( this, selector, true );
6069	},
6070
6071	remove: function( selector ) {
6072		return remove( this, selector );
6073	},
6074
6075	text: function( value ) {
6076		return access( this, function( value ) {
6077			return value === undefined ?
6078				jQuery.text( this ) :
6079				this.empty().each( function() {
6080					if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
6081						this.textContent = value;
6082					}
6083				} );
6084		}, null, value, arguments.length );
6085	},
6086
6087	append: function() {
6088		return domManip( this, arguments, function( elem ) {
6089			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
6090				var target = manipulationTarget( this, elem );
6091				target.appendChild( elem );
6092			}
6093		} );
6094	},
6095
6096	prepend: function() {
6097		return domManip( this, arguments, function( elem ) {
6098			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
6099				var target = manipulationTarget( this, elem );
6100				target.insertBefore( elem, target.firstChild );
6101			}
6102		} );
6103	},
6104
6105	before: function() {
6106		return domManip( this, arguments, function( elem ) {
6107			if ( this.parentNode ) {
6108				this.parentNode.insertBefore( elem, this );
6109			}
6110		} );
6111	},
6112
6113	after: function() {
6114		return domManip( this, arguments, function( elem ) {
6115			if ( this.parentNode ) {
6116				this.parentNode.insertBefore( elem, this.nextSibling );
6117			}
6118		} );
6119	},
6120
6121	empty: function() {
6122		var elem,
6123			i = 0;
6124
6125		for ( ; ( elem = this[ i ] ) != null; i++ ) {
6126			if ( elem.nodeType === 1 ) {
6127
6128				// Prevent memory leaks
6129				jQuery.cleanData( getAll( elem, false ) );
6130
6131				// Remove any remaining nodes
6132				elem.textContent = "";
6133			}
6134		}
6135
6136		return this;
6137	},
6138
6139	clone: function( dataAndEvents, deepDataAndEvents ) {
6140		dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
6141		deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
6142
6143		return this.map( function() {
6144			return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
6145		} );
6146	},
6147
6148	html: function( value ) {
6149		return access( this, function( value ) {
6150			var elem = this[ 0 ] || {},
6151				i = 0,
6152				l = this.length;
6153
6154			if ( value === undefined && elem.nodeType === 1 ) {
6155				return elem.innerHTML;
6156			}
6157
6158			// See if we can take a shortcut and just use innerHTML
6159			if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
6160				!wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) {
6161
6162				value = jQuery.htmlPrefilter( value );
6163
6164				try {
6165					for ( ; i < l; i++ ) {
6166						elem = this[ i ] || {};
6167
6168						// Remove element nodes and prevent memory leaks
6169						if ( elem.nodeType === 1 ) {
6170							jQuery.cleanData( getAll( elem, false ) );
6171							elem.innerHTML = value;
6172						}
6173					}
6174
6175					elem = 0;
6176
6177				// If using innerHTML throws an exception, use the fallback method
6178				} catch ( e ) {}
6179			}
6180
6181			if ( elem ) {
6182				this.empty().append( value );
6183			}
6184		}, null, value, arguments.length );
6185	},
6186
6187	replaceWith: function() {
6188		var ignored = [];
6189
6190		// Make the changes, replacing each non-ignored context element with the new content
6191		return domManip( this, arguments, function( elem ) {
6192			var parent = this.parentNode;
6193
6194			if ( jQuery.inArray( this, ignored ) < 0 ) {
6195				jQuery.cleanData( getAll( this ) );
6196				if ( parent ) {
6197					parent.replaceChild( elem, this );
6198				}
6199			}
6200
6201		// Force callback invocation
6202		}, ignored );
6203	}
6204} );
6205
6206jQuery.each( {
6207	appendTo: "append",
6208	prependTo: "prepend",
6209	insertBefore: "before",
6210	insertAfter: "after",
6211	replaceAll: "replaceWith"
6212}, function( name, original ) {
6213	jQuery.fn[ name ] = function( selector ) {
6214		var elems,
6215			ret = [],
vendor: 31,588 bytes, lines 6216-7278
6216			insert = jQuery( selector ),
6217			last = insert.length - 1,
6218			i = 0;
6219
6220		for ( ; i <= last; i++ ) {
6221			elems = i === last ? this : this.clone( true );
6222			jQuery( insert[ i ] )[ original ]( elems );
6223
6224			// Support: Android <=4.0 only, PhantomJS 1 only
6225			// .get() because push.apply(_, arraylike) throws on ancient WebKit
6226			push.apply( ret, elems.get() );
6227		}
6228
6229		return this.pushStack( ret );
6230	};
6231} );
6232var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
6233
6234var rcustomProp = /^--/;
6235
6236
6237var getStyles = function( elem ) {
6238
6239		// Support: IE <=11 only, Firefox <=30 (trac-15098, trac-14150)
6240		// IE throws on elements created in popups
6241		// FF meanwhile throws on frame elements through "defaultView.getComputedStyle"
6242		var view = elem.ownerDocument.defaultView;
6243
6244		if ( !view || !view.opener ) {
6245			view = window;
6246		}
6247
6248		return view.getComputedStyle( elem );
6249	};
6250
6251var swap = function( elem, options, callback ) {
6252	var ret, name,
6253		old = {};
6254
6255	// Remember the old values, and insert the new ones
6256	for ( name in options ) {
6257		old[ name ] = elem.style[ name ];
6258		elem.style[ name ] = options[ name ];
6259	}
6260
6261	ret = callback.call( elem );
6262
6263	// Revert the old values
6264	for ( name in options ) {
6265		elem.style[ name ] = old[ name ];
6266	}
6267
6268	return ret;
6269};
6270
6271
6272var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" );
6273
6274
6275
6276( function() {
6277
6278	// Executing both pixelPosition & boxSizingReliable tests require only one layout
6279	// so they're executed at the same time to save the second computation.
6280	function computeStyleTests() {
6281
6282		// This is a singleton, we need to execute it only once
6283		if ( !div ) {
6284			return;
6285		}
6286
6287		container.style.cssText = "position:absolute;left:-11111px;width:60px;" +
6288			"margin-top:1px;padding:0;border:0";
6289		div.style.cssText =
6290			"position:relative;display:block;box-sizing:border-box;overflow:scroll;" +
6291			"margin:auto;border:1px;padding:1px;" +
6292			"width:60%;top:1%";
6293		documentElement.appendChild( container ).appendChild( div );
6294
6295		var divStyle = window.getComputedStyle( div );
6296		pixelPositionVal = divStyle.top !== "1%";
6297
6298		// Support: Android 4.0 - 4.3 only, Firefox <=3 - 44
6299		reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12;
6300
6301		// Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3
6302		// Some styles come back with percentage values, even though they shouldn't
6303		div.style.right = "60%";
6304		pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36;
6305
6306		// Support: IE 9 - 11 only
6307		// Detect misreporting of content dimensions for box-sizing:border-box elements
6308		boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36;
6309
6310		// Support: IE 9 only
6311		// Detect overflow:scroll screwiness (gh-3699)
6312		// Support: Chrome <=64
6313		// Don't get tricked when zoom affects offsetWidth (gh-4029)
6314		div.style.position = "absolute";
6315		scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12;
6316
6317		documentElement.removeChild( container );
6318
6319		// Nullify the div so it wouldn't be stored in the memory and
6320		// it will also be a sign that checks already performed
6321		div = null;
6322	}
6323
6324	function roundPixelMeasures( measure ) {
6325		return Math.round( parseFloat( measure ) );
6326	}
6327
6328	var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal,
6329		reliableTrDimensionsVal, reliableMarginLeftVal,
6330		container = document.createElement( "div" ),
6331		div = document.createElement( "div" );
6332
6333	// Finish early in limited (non-browser) environments
6334	if ( !div.style ) {
6335		return;
6336	}
6337
6338	// Support: IE <=9 - 11 only
6339	// Style of cloned element affects source element cloned (trac-8908)
6340	div.style.backgroundClip = "content-box";
6341	div.cloneNode( true ).style.backgroundClip = "";
6342	support.clearCloneStyle = div.style.backgroundClip === "content-box";
6343
6344	jQuery.extend( support, {
6345		boxSizingReliable: function() {
6346			computeStyleTests();
6347			return boxSizingReliableVal;
6348		},
6349		pixelBoxStyles: function() {
6350			computeStyleTests();
6351			return pixelBoxStylesVal;
6352		},
6353		pixelPosition: function() {
6354			computeStyleTests();
6355			return pixelPositionVal;
6356		},
6357		reliableMarginLeft: function() {
6358			computeStyleTests();
6359			return reliableMarginLeftVal;
6360		},
6361		scrollboxSize: function() {
6362			computeStyleTests();
6363			return scrollboxSizeVal;
6364		},
6365
6366		// Support: IE 9 - 11+, Edge 15 - 18+
6367		// IE/Edge misreport `getComputedStyle` of table rows with width/height
6368		// set in CSS while `offset*` properties report correct values.
6369		// Behavior in IE 9 is more subtle than in newer versions & it passes
6370		// some versions of this test; make sure not to make it pass there!
6371		//
6372		// Support: Firefox 70+
6373		// Only Firefox includes border widths
6374		// in computed dimensions. (gh-4529)
6375		reliableTrDimensions: function() {
6376			var table, tr, trChild, trStyle;
6377			if ( reliableTrDimensionsVal == null ) {
6378				table = document.createElement( "table" );
6379				tr = document.createElement( "tr" );
6380				trChild = document.createElement( "div" );
6381
6382				table.style.cssText = "position:absolute;left:-11111px;border-collapse:separate";
6383				tr.style.cssText = "box-sizing:content-box;border:1px solid";
6384
6385				// Support: Chrome 86+
6386				// Height set through cssText does not get applied.
6387				// Computed height then comes back as 0.
6388				tr.style.height = "1px";
6389				trChild.style.height = "9px";
6390
6391				// Support: Android 8 Chrome 86+
6392				// In our bodyBackground.html iframe,
6393				// display for all div elements is set to "inline",
6394				// which causes a problem only in Android 8 Chrome 86.
6395				// Ensuring the div is `display: block`
6396				// gets around this issue.
6397				trChild.style.display = "block";
6398
6399				documentElement
6400					.appendChild( table )
6401					.appendChild( tr )
6402					.appendChild( trChild );
6403
6404				trStyle = window.getComputedStyle( tr );
6405				reliableTrDimensionsVal = ( parseInt( trStyle.height, 10 ) +
6406					parseInt( trStyle.borderTopWidth, 10 ) +
6407					parseInt( trStyle.borderBottomWidth, 10 ) ) === tr.offsetHeight;
6408
6409				documentElement.removeChild( table );
6410			}
6411			return reliableTrDimensionsVal;
6412		}
6413	} );
6414} )();
6415
6416
6417function curCSS( elem, name, computed ) {
6418	var width, minWidth, maxWidth, ret,
6419		isCustomProp = rcustomProp.test( name ),
6420
6421		// Support: Firefox 51+
6422		// Retrieving style before computed somehow
6423		// fixes an issue with getting wrong values
6424		// on detached elements
6425		style = elem.style;
6426
6427	computed = computed || getStyles( elem );
6428
6429	// getPropertyValue is needed for:
6430	//   .css('filter') (IE 9 only, trac-12537)
6431	//   .css('--customProperty) (gh-3144)
6432	if ( computed ) {
6433
6434		// Support: IE <=9 - 11+
6435		// IE only supports `"float"` in `getPropertyValue`; in computed styles
6436		// it's only available as `"cssFloat"`. We no longer modify properties
6437		// sent to `.css()` apart from camelCasing, so we need to check both.
6438		// Normally, this would create difference in behavior: if
6439		// `getPropertyValue` returns an empty string, the value returned
6440		// by `.css()` would be `undefined`. This is usually the case for
6441		// disconnected elements. However, in IE even disconnected elements
6442		// with no styles return `"none"` for `getPropertyValue( "float" )`
6443		ret = computed.getPropertyValue( name ) || computed[ name ];
6444
6445		if ( isCustomProp && ret ) {
6446
6447			// Support: Firefox 105+, Chrome <=105+
6448			// Spec requires trimming whitespace for custom properties (gh-4926).
6449			// Firefox only trims leading whitespace. Chrome just collapses
6450			// both leading & trailing whitespace to a single space.
6451			//
6452			// Fall back to `undefined` if empty string returned.
6453			// This collapses a missing definition with property defined
6454			// and set to an empty string but there's no standard API
6455			// allowing us to differentiate them without a performance penalty
6456			// and returning `undefined` aligns with older jQuery.
6457			//
6458			// rtrimCSS treats U+000D CARRIAGE RETURN and U+000C FORM FEED
6459			// as whitespace while CSS does not, but this is not a problem
6460			// because CSS preprocessing replaces them with U+000A LINE FEED
6461			// (which *is* CSS whitespace)
6462			// https://www.w3.org/TR/css-syntax-3/#input-preprocessing
6463			ret = ret.replace( rtrimCSS, "$1" ) || undefined;
6464		}
6465
6466		if ( ret === "" && !isAttached( elem ) ) {
6467			ret = jQuery.style( elem, name );
6468		}
6469
6470		// A tribute to the "awesome hack by Dean Edwards"
6471		// Android Browser returns percentage for some values,
6472		// but width seems to be reliably pixels.
6473		// This is against the CSSOM draft spec:
6474		// https://drafts.csswg.org/cssom/#resolved-values
6475		if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) {
6476
6477			// Remember the original values
6478			width = style.width;
6479			minWidth = style.minWidth;
6480			maxWidth = style.maxWidth;
6481
6482			// Put in the new values to get a computed value out
6483			style.minWidth = style.maxWidth = style.width = ret;
6484			ret = computed.width;
6485
6486			// Revert the changed values
6487			style.width = width;
6488			style.minWidth = minWidth;
6489			style.maxWidth = maxWidth;
6490		}
6491	}
6492
6493	return ret !== undefined ?
6494
6495		// Support: IE <=9 - 11 only
6496		// IE returns zIndex value as an integer.
6497		ret + "" :
6498		ret;
6499}
6500
6501
6502function addGetHookIf( conditionFn, hookFn ) {
6503
6504	// Define the hook, we'll check on the first run if it's really needed.
6505	return {
6506		get: function() {
6507			if ( conditionFn() ) {
6508
6509				// Hook not needed (or it's not possible to use it due
6510				// to missing dependency), remove it.
6511				delete this.get;
6512				return;
6513			}
6514
6515			// Hook needed; redefine it so that the support test is not executed again.
6516			return ( this.get = hookFn ).apply( this, arguments );
6517		}
6518	};
6519}
6520
6521
6522var cssPrefixes = [ "Webkit", "Moz", "ms" ],
6523	emptyStyle = document.createElement( "div" ).style,
6524	vendorProps = {};
6525
6526// Return a vendor-prefixed property or undefined
6527function vendorPropName( name ) {
6528
6529	// Check for vendor prefixed names
6530	var capName = name[ 0 ].toUpperCase() + name.slice( 1 ),
6531		i = cssPrefixes.length;
6532
6533	while ( i-- ) {
6534		name = cssPrefixes[ i ] + capName;
6535		if ( name in emptyStyle ) {
6536			return name;
6537		}
6538	}
6539}
6540
6541// Return a potentially-mapped jQuery.cssProps or vendor prefixed property
6542function finalPropName( name ) {
6543	var final = jQuery.cssProps[ name ] || vendorProps[ name ];
6544
6545	if ( final ) {
6546		return final;
6547	}
6548	if ( name in emptyStyle ) {
6549		return name;
6550	}
6551	return vendorProps[ name ] = vendorPropName( name ) || name;
6552}
6553
6554
6555var
6556
6557	// Swappable if display is none or starts with table
6558	// except "table", "table-cell", or "table-caption"
6559	// See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
6560	rdisplayswap = /^(none|table(?!-c[ea]).+)/,
6561	cssShow = { position: "absolute", visibility: "hidden", display: "block" },
6562	cssNormalTransform = {
6563		letterSpacing: "0",
6564		fontWeight: "400"
6565	};
6566
6567function setPositiveNumber( _elem, value, subtract ) {
6568
6569	// Any relative (+/-) values have already been
6570	// normalized at this point
6571	var matches = rcssNum.exec( value );
6572	return matches ?
6573
6574		// Guard against undefined "subtract", e.g., when used as in cssHooks
6575		Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) :
6576		value;
6577}
6578
6579function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) {
6580	var i = dimension === "width" ? 1 : 0,
6581		extra = 0,
6582		delta = 0,
6583		marginDelta = 0;
6584
6585	// Adjustment may not be necessary
6586	if ( box === ( isBorderBox ? "border" : "content" ) ) {
6587		return 0;
6588	}
6589
6590	for ( ; i < 4; i += 2 ) {
6591
6592		// Both box models exclude margin
6593		// Count margin delta separately to only add it after scroll gutter adjustment.
6594		// This is needed to make negative margins work with `outerHeight( true )` (gh-3982).
6595		if ( box === "margin" ) {
6596			marginDelta += jQuery.css( elem, box + cssExpand[ i ], true, styles );
6597		}
6598
6599		// If we get here with a content-box, we're seeking "padding" or "border" or "margin"
6600		if ( !isBorderBox ) {
6601
6602			// Add padding
6603			delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
6604
6605			// For "border" or "margin", add border
6606			if ( box !== "padding" ) {
6607				delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
6608
6609			// But still keep track of it otherwise
6610			} else {
6611				extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
6612			}
6613
6614		// If we get here with a border-box (content + padding + border), we're seeking "content" or
6615		// "padding" or "margin"
6616		} else {
6617
6618			// For "content", subtract padding
6619			if ( box === "content" ) {
6620				delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
6621			}
6622
6623			// For "content" or "padding", subtract border
6624			if ( box !== "margin" ) {
6625				delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
6626			}
6627		}
6628	}
6629
6630	// Account for positive content-box scroll gutter when requested by providing computedVal
6631	if ( !isBorderBox && computedVal >= 0 ) {
6632
6633		// offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border
6634		// Assuming integer scroll gutter, subtract the rest and round down
6635		delta += Math.max( 0, Math.ceil(
6636			elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] -
6637			computedVal -
6638			delta -
6639			extra -
6640			0.5
6641
6642		// If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter
6643		// Use an explicit zero to avoid NaN (gh-3964)
6644		) ) || 0;
6645	}
6646
6647	return delta + marginDelta;
6648}
6649
6650function getWidthOrHeight( elem, dimension, extra ) {
6651
6652	// Start with computed style
6653	var styles = getStyles( elem ),
6654
6655		// To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322).
6656		// Fake content-box until we know it's needed to know the true value.
6657		boxSizingNeeded = !support.boxSizingReliable() || extra,
6658		isBorderBox = boxSizingNeeded &&
6659			jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
6660		valueIsBorderBox = isBorderBox,
6661
6662		val = curCSS( elem, dimension, styles ),
6663		offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 );
6664
6665	// Support: Firefox <=54
6666	// Return a confounding non-pixel value or feign ignorance, as appropriate.
6667	if ( rnumnonpx.test( val ) ) {
6668		if ( !extra ) {
6669			return val;
6670		}
6671		val = "auto";
6672	}
6673
6674
6675	// Support: IE 9 - 11 only
6676	// Use offsetWidth/offsetHeight for when box sizing is unreliable.
6677	// In those cases, the computed value can be trusted to be border-box.
6678	if ( ( !support.boxSizingReliable() && isBorderBox ||
6679
6680		// Support: IE 10 - 11+, Edge 15 - 18+
6681		// IE/Edge misreport `getComputedStyle` of table rows with width/height
6682		// set in CSS while `offset*` properties report correct values.
6683		// Interestingly, in some cases IE 9 doesn't suffer from this issue.
6684		!support.reliableTrDimensions() && nodeName( elem, "tr" ) ||
6685
6686		// Fall back to offsetWidth/offsetHeight when value is "auto"
6687		// This happens for inline elements with no explicit setting (gh-3571)
6688		val === "auto" ||
6689
6690		// Support: Android <=4.1 - 4.3 only
6691		// Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602)
6692		!parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) &&
6693
6694		// Make sure the element is visible & connected
6695		elem.getClientRects().length ) {
6696
6697		isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
6698
6699		// Where available, offsetWidth/offsetHeight approximate border box dimensions.
6700		// Where not available (e.g., SVG), assume unreliable box-sizing and interpret the
6701		// retrieved value as a content box dimension.
6702		valueIsBorderBox = offsetProp in elem;
6703		if ( valueIsBorderBox ) {
6704			val = elem[ offsetProp ];
6705		}
6706	}
6707
6708	// Normalize "" and auto
6709	val = parseFloat( val ) || 0;
6710
6711	// Adjust for the element's box model
6712	return ( val +
6713		boxModelAdjustment(
6714			elem,
6715			dimension,
6716			extra || ( isBorderBox ? "border" : "content" ),
6717			valueIsBorderBox,
6718			styles,
6719
6720			// Provide the current computed size to request scroll gutter calculation (gh-3589)
6721			val
6722		)
6723	) + "px";
6724}
6725
6726jQuery.extend( {
6727
6728	// Add in style property hooks for overriding the default
6729	// behavior of getting and setting a style property
6730	cssHooks: {
6731		opacity: {
6732			get: function( elem, computed ) {
6733				if ( computed ) {
6734
6735					// We should always get a number back from opacity
6736					var ret = curCSS( elem, "opacity" );
6737					return ret === "" ? "1" : ret;
6738				}
6739			}
6740		}
6741	},
6742
6743	// Don't automatically add "px" to these possibly-unitless properties
6744	cssNumber: {
6745		animationIterationCount: true,
6746		aspectRatio: true,
6747		borderImageSlice: true,
6748		columnCount: true,
6749		flexGrow: true,
6750		flexShrink: true,
6751		fontWeight: true,
6752		gridArea: true,
6753		gridColumn: true,
6754		gridColumnEnd: true,
6755		gridColumnStart: true,
6756		gridRow: true,
6757		gridRowEnd: true,
6758		gridRowStart: true,
6759		lineHeight: true,
6760		opacity: true,
6761		order: true,
6762		orphans: true,
6763		scale: true,
6764		widows: true,
6765		zIndex: true,
6766		zoom: true,
6767
6768		// SVG-related
6769		fillOpacity: true,
6770		floodOpacity: true,
6771		stopOpacity: true,
6772		strokeMiterlimit: true,
6773		strokeOpacity: true
6774	},
6775
6776	// Add in properties whose names you wish to fix before
6777	// setting or getting the value
6778	cssProps: {},
6779
6780	// Get and set the style property on a DOM Node
6781	style: function( elem, name, value, extra ) {
6782
6783		// Don't set styles on text and comment nodes
6784		if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
6785			return;
6786		}
6787
6788		// Make sure that we're working with the right name
6789		var ret, type, hooks,
6790			origName = camelCase( name ),
6791			isCustomProp = rcustomProp.test( name ),
6792			style = elem.style;
6793
6794		// Make sure that we're working with the right name. We don't
6795		// want to query the value if it is a CSS custom property
6796		// since they are user-defined.
6797		if ( !isCustomProp ) {
6798			name = finalPropName( origName );
6799		}
6800
6801		// Gets hook for the prefixed version, then unprefixed version
6802		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
6803
6804		// Check if we're setting a value
6805		if ( value !== undefined ) {
6806			type = typeof value;
6807
6808			// Convert "+=" or "-=" to relative numbers (trac-7345)
6809			if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) {
6810				value = adjustCSS( elem, name, ret );
6811
6812				// Fixes bug trac-9237
6813				type = "number";
6814			}
6815
6816			// Make sure that null and NaN values aren't set (trac-7116)
6817			if ( value == null || value !== value ) {
6818				return;
6819			}
6820
6821			// If a number was passed in, add the unit (except for certain CSS properties)
6822			// The isCustomProp check can be removed in jQuery 4.0 when we only auto-append
6823			// "px" to a few hardcoded values.
6824			if ( type === "number" && !isCustomProp ) {
6825				value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" );
6826			}
6827
6828			// background-* props affect original clone's values
6829			if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) {
6830				style[ name ] = "inherit";
6831			}
6832
6833			// If a hook was provided, use that value, otherwise just set the specified value
6834			if ( !hooks || !( "set" in hooks ) ||
6835				( value = hooks.set( elem, value, extra ) ) !== undefined ) {
6836
6837				if ( isCustomProp ) {
6838					style.setProperty( name, value );
6839				} else {
6840					style[ name ] = value;
6841				}
6842			}
6843
6844		} else {
6845
6846			// If a hook was provided get the non-computed value from there
6847			if ( hooks && "get" in hooks &&
6848				( ret = hooks.get( elem, false, extra ) ) !== undefined ) {
6849
6850				return ret;
6851			}
6852
6853			// Otherwise just get the value from the style object
6854			return style[ name ];
6855		}
6856	},
6857
6858	css: function( elem, name, extra, styles ) {
6859		var val, num, hooks,
6860			origName = camelCase( name ),
6861			isCustomProp = rcustomProp.test( name );
6862
6863		// Make sure that we're working with the right name. We don't
6864		// want to modify the value if it is a CSS custom property
6865		// since they are user-defined.
6866		if ( !isCustomProp ) {
6867			name = finalPropName( origName );
6868		}
6869
6870		// Try prefixed name followed by the unprefixed name
6871		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
6872
6873		// If a hook was provided get the computed value from there
6874		if ( hooks && "get" in hooks ) {
6875			val = hooks.get( elem, true, extra );
6876		}
6877
6878		// Otherwise, if a way to get the computed value exists, use that
6879		if ( val === undefined ) {
6880			val = curCSS( elem, name, styles );
6881		}
6882
6883		// Convert "normal" to computed value
6884		if ( val === "normal" && name in cssNormalTransform ) {
6885			val = cssNormalTransform[ name ];
6886		}
6887
6888		// Make numeric if forced or a qualifier was provided and val looks numeric
6889		if ( extra === "" || extra ) {
6890			num = parseFloat( val );
6891			return extra === true || isFinite( num ) ? num || 0 : val;
6892		}
6893
6894		return val;
6895	}
6896} );
6897
6898jQuery.each( [ "height", "width" ], function( _i, dimension ) {
6899	jQuery.cssHooks[ dimension ] = {
6900		get: function( elem, computed, extra ) {
6901			if ( computed ) {
6902
6903				// Certain elements can have dimension info if we invisibly show them
6904				// but it must have a current display style that would benefit
6905				return rdisplayswap.test( jQuery.css( elem, "display" ) ) &&
6906
6907					// Support: Safari 8+
6908					// Table columns in Safari have non-zero offsetWidth & zero
6909					// getBoundingClientRect().width unless display is changed.
6910					// Support: IE <=11 only
6911					// Running getBoundingClientRect on a disconnected node
6912					// in IE throws an error.
6913					( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ?
6914					swap( elem, cssShow, function() {
6915						return getWidthOrHeight( elem, dimension, extra );
6916					} ) :
6917					getWidthOrHeight( elem, dimension, extra );
6918			}
6919		},
6920
6921		set: function( elem, value, extra ) {
6922			var matches,
6923				styles = getStyles( elem ),
6924
6925				// Only read styles.position if the test has a chance to fail
6926				// to avoid forcing a reflow.
6927				scrollboxSizeBuggy = !support.scrollboxSize() &&
6928					styles.position === "absolute",
6929
6930				// To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991)
6931				boxSizingNeeded = scrollboxSizeBuggy || extra,
6932				isBorderBox = boxSizingNeeded &&
6933					jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
6934				subtract = extra ?
6935					boxModelAdjustment(
6936						elem,
6937						dimension,
6938						extra,
6939						isBorderBox,
6940						styles
6941					) :
6942					0;
6943
6944			// Account for unreliable border-box dimensions by comparing offset* to computed and
6945			// faking a content-box to get border and padding (gh-3699)
6946			if ( isBorderBox && scrollboxSizeBuggy ) {
6947				subtract -= Math.ceil(
6948					elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] -
6949					parseFloat( styles[ dimension ] ) -
6950					boxModelAdjustment( elem, dimension, "border", false, styles ) -
6951					0.5
6952				);
6953			}
6954
6955			// Convert to pixels if value adjustment is needed
6956			if ( subtract && ( matches = rcssNum.exec( value ) ) &&
6957				( matches[ 3 ] || "px" ) !== "px" ) {
6958
6959				elem.style[ dimension ] = value;
6960				value = jQuery.css( elem, dimension );
6961			}
6962
6963			return setPositiveNumber( elem, value, subtract );
6964		}
6965	};
6966} );
6967
6968jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft,
6969	function( elem, computed ) {
6970		if ( computed ) {
6971			return ( parseFloat( curCSS( elem, "marginLeft" ) ) ||
6972				elem.getBoundingClientRect().left -
6973					swap( elem, { marginLeft: 0 }, function() {
6974						return elem.getBoundingClientRect().left;
6975					} )
6976			) + "px";
6977		}
6978	}
6979);
6980
6981// These hooks are used by animate to expand properties
6982jQuery.each( {
6983	margin: "",
6984	padding: "",
6985	border: "Width"
6986}, function( prefix, suffix ) {
6987	jQuery.cssHooks[ prefix + suffix ] = {
6988		expand: function( value ) {
6989			var i = 0,
6990				expanded = {},
6991
6992				// Assumes a single number if not a string
6993				parts = typeof value === "string" ? value.split( " " ) : [ value ];
6994
6995			for ( ; i < 4; i++ ) {
6996				expanded[ prefix + cssExpand[ i ] + suffix ] =
6997					parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
6998			}
6999
7000			return expanded;
7001		}
7002	};
7003
7004	if ( prefix !== "margin" ) {
7005		jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
7006	}
7007} );
7008
7009jQuery.fn.extend( {
7010	css: function( name, value ) {
7011		return access( this, function( elem, name, value ) {
7012			var styles, len,
7013				map = {},
7014				i = 0;
7015
7016			if ( Array.isArray( name ) ) {
7017				styles = getStyles( elem );
7018				len = name.length;
7019
7020				for ( ; i < len; i++ ) {
7021					map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
7022				}
7023
7024				return map;
7025			}
7026
7027			return value !== undefined ?
7028				jQuery.style( elem, name, value ) :
7029				jQuery.css( elem, name );
7030		}, name, value, arguments.length > 1 );
7031	}
7032} );
7033
7034
7035function Tween( elem, options, prop, end, easing ) {
7036	return new Tween.prototype.init( elem, options, prop, end, easing );
7037}
7038jQuery.Tween = Tween;
7039
7040Tween.prototype = {
7041	constructor: Tween,
7042	init: function( elem, options, prop, end, easing, unit ) {
7043		this.elem = elem;
7044		this.prop = prop;
7045		this.easing = easing || jQuery.easing._default;
7046		this.options = options;
7047		this.start = this.now = this.cur();
7048		this.end = end;
7049		this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
7050	},
7051	cur: function() {
7052		var hooks = Tween.propHooks[ this.prop ];
7053
7054		return hooks && hooks.get ?
7055			hooks.get( this ) :
7056			Tween.propHooks._default.get( this );
7057	},
7058	run: function( percent ) {
7059		var eased,
7060			hooks = Tween.propHooks[ this.prop ];
7061
7062		if ( this.options.duration ) {
7063			this.pos = eased = jQuery.easing[ this.easing ](
7064				percent, this.options.duration * percent, 0, 1, this.options.duration
7065			);
7066		} else {
7067			this.pos = eased = percent;
7068		}
7069		this.now = ( this.end - this.start ) * eased + this.start;
7070
7071		if ( this.options.step ) {
7072			this.options.step.call( this.elem, this.now, this );
7073		}
7074
7075		if ( hooks && hooks.set ) {
7076			hooks.set( this );
7077		} else {
7078			Tween.propHooks._default.set( this );
7079		}
7080		return this;
7081	}
7082};
7083
7084Tween.prototype.init.prototype = Tween.prototype;
7085
7086Tween.propHooks = {
7087	_default: {
7088		get: function( tween ) {
7089			var result;
7090
7091			// Use a property on the element directly when it is not a DOM element,
7092			// or when there is no matching style property that exists.
7093			if ( tween.elem.nodeType !== 1 ||
7094				tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) {
7095				return tween.elem[ tween.prop ];
7096			}
7097
7098			// Passing an empty string as a 3rd parameter to .css will automatically
7099			// attempt a parseFloat and fallback to a string if the parse fails.
7100			// Simple values such as "10px" are parsed to Float;
7101			// complex values such as "rotate(1rad)" are returned as-is.
7102			result = jQuery.css( tween.elem, tween.prop, "" );
7103
7104			// Empty strings, null, undefined and "auto" are converted to 0.
7105			return !result || result === "auto" ? 0 : result;
7106		},
7107		set: function( tween ) {
7108
7109			// Use step hook for back compat.
7110			// Use cssHook if its there.
7111			// Use .style if available and use plain properties where available.
7112			if ( jQuery.fx.step[ tween.prop ] ) {
7113				jQuery.fx.step[ tween.prop ]( tween );
7114			} else if ( tween.elem.nodeType === 1 && (
7115				jQuery.cssHooks[ tween.prop ] ||
7116					tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) {
7117				jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
7118			} else {
7119				tween.elem[ tween.prop ] = tween.now;
7120			}
7121		}
7122	}
7123};
7124
7125// Support: IE <=9 only
7126// Panic based approach to setting things on disconnected nodes
7127Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
7128	set: function( tween ) {
7129		if ( tween.elem.nodeType && tween.elem.parentNode ) {
7130			tween.elem[ tween.prop ] = tween.now;
7131		}
7132	}
7133};
7134
7135jQuery.easing = {
7136	linear: function( p ) {
7137		return p;
7138	},
7139	swing: function( p ) {
7140		return 0.5 - Math.cos( p * Math.PI ) / 2;
7141	},
7142	_default: "swing"
7143};
7144
7145jQuery.fx = Tween.prototype.init;
7146
7147// Back compat <1.8 extension point
7148jQuery.fx.step = {};
7149
7150
7151
7152
7153var
7154	fxNow, inProgress,
7155	rfxtypes = /^(?:toggle|show|hide)$/,
7156	rrun = /queueHooks$/;
7157
7158function schedule() {
7159	if ( inProgress ) {
7160		if ( document.hidden === false && window.requestAnimationFrame ) {
7161			window.requestAnimationFrame( schedule );
7162		} else {
7163			window.setTimeout( schedule, jQuery.fx.interval );
7164		}
7165
7166		jQuery.fx.tick();
7167	}
7168}
7169
7170// Animations created synchronously will run synchronously
7171function createFxNow() {
7172	window.setTimeout( function() {
7173		fxNow = undefined;
7174	} );
7175	return ( fxNow = Date.now() );
7176}
7177
7178// Generate parameters to create a standard animation
7179function genFx( type, includeWidth ) {
7180	var which,
7181		i = 0,
7182		attrs = { height: type };
7183
7184	// If we include width, step value is 1 to do all cssExpand values,
7185	// otherwise step value is 2 to skip over Left and Right
7186	includeWidth = includeWidth ? 1 : 0;
7187	for ( ; i < 4; i += 2 - includeWidth ) {
7188		which = cssExpand[ i ];
7189		attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
7190	}
7191
7192	if ( includeWidth ) {
7193		attrs.opacity = attrs.width = type;
7194	}
7195
7196	return attrs;
7197}
7198
7199function createTween( value, prop, animation ) {
7200	var tween,
7201		collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ),
7202		index = 0,
7203		length = collection.length;
7204	for ( ; index < length; index++ ) {
7205		if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) {
7206
7207			// We're done with this property
7208			return tween;
7209		}
7210	}
7211}
7212
7213function defaultPrefilter( elem, props, opts ) {
7214	var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display,
7215		isBox = "width" in props || "height" in props,
7216		anim = this,
7217		orig = {},
7218		style = elem.style,
7219		hidden = elem.nodeType && isHiddenWithinTree( elem ),
7220		dataShow = dataPriv.get( elem, "fxshow" );
7221
7222	// Queue-skipping animations hijack the fx hooks
7223	if ( !opts.queue ) {
7224		hooks = jQuery._queueHooks( elem, "fx" );
7225		if ( hooks.unqueued == null ) {
7226			hooks.unqueued = 0;
7227			oldfire = hooks.empty.fire;
7228			hooks.empty.fire = function() {
7229				if ( !hooks.unqueued ) {
7230					oldfire();
7231				}
7232			};
7233		}
7234		hooks.unqueued++;
7235
7236		anim.always( function() {
7237
7238			// Ensure the complete handler is called before this completes
7239			anim.always( function() {
7240				hooks.unqueued--;
7241				if ( !jQuery.queue( elem, "fx" ).length ) {
7242					hooks.empty.fire();
7243				}
7244			} );
7245		} );
7246	}
7247
7248	// Detect show/hide animations
7249	for ( prop in props ) {
7250		value = props[ prop ];
7251		if ( rfxtypes.test( value ) ) {
7252			delete props[ prop ];
7253			toggle = toggle || value === "toggle";
7254			if ( value === ( hidden ? "hide" : "show" ) ) {
7255
7256				// Pretend to be hidden if this is a "show" and
7257				// there is still data from a stopped show/hide
7258				if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
7259					hidden = true;
7260
7261				// Ignore all other no-op show/hide data
7262				} else {
7263					continue;
7264				}
7265			}
7266			orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
7267		}
7268	}
7269
7270	// Bail out if this is a no-op like .hide().hide()
7271	propTween = !jQuery.isEmptyObject( props );
7272	if ( !propTween && jQuery.isEmptyObject( orig ) ) {
7273		return;
7274	}
7275
7276	// Restrict "overflow" and "display" styles during box animations
7277	if ( isBox && elem.nodeType === 1 ) {
7278
vendor: 4,381 bytes, lines 7279-7438
7279		// Support: IE <=9 - 11, Edge 12 - 15
7280		// Record all 3 overflow attributes because IE does not infer the shorthand
7281		// from identically-valued overflowX and overflowY and Edge just mirrors
7282		// the overflowX value there.
7283		opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
7284
7285		// Identify a display type, preferring old show/hide data over the CSS cascade
7286		restoreDisplay = dataShow && dataShow.display;
7287		if ( restoreDisplay == null ) {
7288			restoreDisplay = dataPriv.get( elem, "display" );
7289		}
7290		display = jQuery.css( elem, "display" );
7291		if ( display === "none" ) {
7292			if ( restoreDisplay ) {
7293				display = restoreDisplay;
7294			} else {
7295
7296				// Get nonempty value(s) by temporarily forcing visibility
7297				showHide( [ elem ], true );
7298				restoreDisplay = elem.style.display || restoreDisplay;
7299				display = jQuery.css( elem, "display" );
7300				showHide( [ elem ] );
7301			}
7302		}
7303
7304		// Animate inline elements as inline-block
7305		if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) {
7306			if ( jQuery.css( elem, "float" ) === "none" ) {
7307
7308				// Restore the original display value at the end of pure show/hide animations
7309				if ( !propTween ) {
7310					anim.done( function() {
7311						style.display = restoreDisplay;
7312					} );
7313					if ( restoreDisplay == null ) {
7314						display = style.display;
7315						restoreDisplay = display === "none" ? "" : display;
7316					}
7317				}
7318				style.display = "inline-block";
7319			}
7320		}
7321	}
7322
7323	if ( opts.overflow ) {
7324		style.overflow = "hidden";
7325		anim.always( function() {
7326			style.overflow = opts.overflow[ 0 ];
7327			style.overflowX = opts.overflow[ 1 ];
7328			style.overflowY = opts.overflow[ 2 ];
7329		} );
7330	}
7331
7332	// Implement show/hide animations
7333	propTween = false;
7334	for ( prop in orig ) {
7335
7336		// General show/hide setup for this element animation
7337		if ( !propTween ) {
7338			if ( dataShow ) {
7339				if ( "hidden" in dataShow ) {
7340					hidden = dataShow.hidden;
7341				}
7342			} else {
7343				dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } );
7344			}
7345
7346			// Store hidden/visible for toggle so `.stop().toggle()` "reverses"
7347			if ( toggle ) {
7348				dataShow.hidden = !hidden;
7349			}
7350
7351			// Show elements before animating them
7352			if ( hidden ) {
7353				showHide( [ elem ], true );
7354			}
7355
7356			/* eslint-disable no-loop-func */
7357
7358			anim.done( function() {
7359
7360				/* eslint-enable no-loop-func */
7361
7362				// The final step of a "hide" animation is actually hiding the element
7363				if ( !hidden ) {
7364					showHide( [ elem ] );
7365				}
7366				dataPriv.remove( elem, "fxshow" );
7367				for ( prop in orig ) {
7368					jQuery.style( elem, prop, orig[ prop ] );
7369				}
7370			} );
7371		}
7372
7373		// Per-property setup
7374		propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
7375		if ( !( prop in dataShow ) ) {
7376			dataShow[ prop ] = propTween.start;
7377			if ( hidden ) {
7378				propTween.end = propTween.start;
7379				propTween.start = 0;
7380			}
7381		}
7382	}
7383}
7384
7385function propFilter( props, specialEasing ) {
7386	var index, name, easing, value, hooks;
7387
7388	// camelCase, specialEasing and expand cssHook pass
7389	for ( index in props ) {
7390		name = camelCase( index );
7391		easing = specialEasing[ name ];
7392		value = props[ index ];
7393		if ( Array.isArray( value ) ) {
7394			easing = value[ 1 ];
7395			value = props[ index ] = value[ 0 ];
7396		}
7397
7398		if ( index !== name ) {
7399			props[ name ] = value;
7400			delete props[ index ];
7401		}
7402
7403		hooks = jQuery.cssHooks[ name ];
7404		if ( hooks && "expand" in hooks ) {
7405			value = hooks.expand( value );
7406			delete props[ name ];
7407
7408			// Not quite $.extend, this won't overwrite existing keys.
7409			// Reusing 'index' because we have the correct "name"
7410			for ( index in value ) {
7411				if ( !( index in props ) ) {
7412					props[ index ] = value[ index ];
7413					specialEasing[ index ] = easing;
7414				}
7415			}
7416		} else {
7417			specialEasing[ name ] = easing;
7418		}
7419	}
7420}
7421
7422function Animation( elem, properties, options ) {
7423	var result,
7424		stopped,
7425		index = 0,
7426		length = Animation.prefilters.length,
7427		deferred = jQuery.Deferred().always( function() {
7428
7429			// Don't match elem in the :animated selector
7430			delete tick.elem;
7431		} ),
7432		tick = function() {
7433			if ( stopped ) {
7434				return false;
7435			}
7436			var currentTime = fxNow || createFxNow(),
7437				remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
7438
vendor: 39,713 bytes, lines 7439-8989
7439				// Support: Android 2.3 only
7440				// Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (trac-12497)
7441				temp = remaining / animation.duration || 0,
7442				percent = 1 - temp,
7443				index = 0,
7444				length = animation.tweens.length;
7445
7446			for ( ; index < length; index++ ) {
7447				animation.tweens[ index ].run( percent );
7448			}
7449
7450			deferred.notifyWith( elem, [ animation, percent, remaining ] );
7451
7452			// If there's more to do, yield
7453			if ( percent < 1 && length ) {
7454				return remaining;
7455			}
7456
7457			// If this was an empty animation, synthesize a final progress notification
7458			if ( !length ) {
7459				deferred.notifyWith( elem, [ animation, 1, 0 ] );
7460			}
7461
7462			// Resolve the animation and report its conclusion
7463			deferred.resolveWith( elem, [ animation ] );
7464			return false;
7465		},
7466		animation = deferred.promise( {
7467			elem: elem,
7468			props: jQuery.extend( {}, properties ),
7469			opts: jQuery.extend( true, {
7470				specialEasing: {},
7471				easing: jQuery.easing._default
7472			}, options ),
7473			originalProperties: properties,
7474			originalOptions: options,
7475			startTime: fxNow || createFxNow(),
7476			duration: options.duration,
7477			tweens: [],
7478			createTween: function( prop, end ) {
7479				var tween = jQuery.Tween( elem, animation.opts, prop, end,
7480					animation.opts.specialEasing[ prop ] || animation.opts.easing );
7481				animation.tweens.push( tween );
7482				return tween;
7483			},
7484			stop: function( gotoEnd ) {
7485				var index = 0,
7486
7487					// If we are going to the end, we want to run all the tweens
7488					// otherwise we skip this part
7489					length = gotoEnd ? animation.tweens.length : 0;
7490				if ( stopped ) {
7491					return this;
7492				}
7493				stopped = true;
7494				for ( ; index < length; index++ ) {
7495					animation.tweens[ index ].run( 1 );
7496				}
7497
7498				// Resolve when we played the last frame; otherwise, reject
7499				if ( gotoEnd ) {
7500					deferred.notifyWith( elem, [ animation, 1, 0 ] );
7501					deferred.resolveWith( elem, [ animation, gotoEnd ] );
7502				} else {
7503					deferred.rejectWith( elem, [ animation, gotoEnd ] );
7504				}
7505				return this;
7506			}
7507		} ),
7508		props = animation.props;
7509
7510	propFilter( props, animation.opts.specialEasing );
7511
7512	for ( ; index < length; index++ ) {
7513		result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts );
7514		if ( result ) {
7515			if ( isFunction( result.stop ) ) {
7516				jQuery._queueHooks( animation.elem, animation.opts.queue ).stop =
7517					result.stop.bind( result );
7518			}
7519			return result;
7520		}
7521	}
7522
7523	jQuery.map( props, createTween, animation );
7524
7525	if ( isFunction( animation.opts.start ) ) {
7526		animation.opts.start.call( elem, animation );
7527	}
7528
7529	// Attach callbacks from options
7530	animation
7531		.progress( animation.opts.progress )
7532		.done( animation.opts.done, animation.opts.complete )
7533		.fail( animation.opts.fail )
7534		.always( animation.opts.always );
7535
7536	jQuery.fx.timer(
7537		jQuery.extend( tick, {
7538			elem: elem,
7539			anim: animation,
7540			queue: animation.opts.queue
7541		} )
7542	);
7543
7544	return animation;
7545}
7546
7547jQuery.Animation = jQuery.extend( Animation, {
7548
7549	tweeners: {
7550		"*": [ function( prop, value ) {
7551			var tween = this.createTween( prop, value );
7552			adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween );
7553			return tween;
7554		} ]
7555	},
7556
7557	tweener: function( props, callback ) {
7558		if ( isFunction( props ) ) {
7559			callback = props;
7560			props = [ "*" ];
7561		} else {
7562			props = props.match( rnothtmlwhite );
7563		}
7564
7565		var prop,
7566			index = 0,
7567			length = props.length;
7568
7569		for ( ; index < length; index++ ) {
7570			prop = props[ index ];
7571			Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || [];
7572			Animation.tweeners[ prop ].unshift( callback );
7573		}
7574	},
7575
7576	prefilters: [ defaultPrefilter ],
7577
7578	prefilter: function( callback, prepend ) {
7579		if ( prepend ) {
7580			Animation.prefilters.unshift( callback );
7581		} else {
7582			Animation.prefilters.push( callback );
7583		}
7584	}
7585} );
7586
7587jQuery.speed = function( speed, easing, fn ) {
7588	var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
7589		complete: fn || !fn && easing ||
7590			isFunction( speed ) && speed,
7591		duration: speed,
7592		easing: fn && easing || easing && !isFunction( easing ) && easing
7593	};
7594
7595	// Go to the end state if fx are off
7596	if ( jQuery.fx.off ) {
7597		opt.duration = 0;
7598
7599	} else {
7600		if ( typeof opt.duration !== "number" ) {
7601			if ( opt.duration in jQuery.fx.speeds ) {
7602				opt.duration = jQuery.fx.speeds[ opt.duration ];
7603
7604			} else {
7605				opt.duration = jQuery.fx.speeds._default;
7606			}
7607		}
7608	}
7609
7610	// Normalize opt.queue - true/undefined/null -> "fx"
7611	if ( opt.queue == null || opt.queue === true ) {
7612		opt.queue = "fx";
7613	}
7614
7615	// Queueing
7616	opt.old = opt.complete;
7617
7618	opt.complete = function() {
7619		if ( isFunction( opt.old ) ) {
7620			opt.old.call( this );
7621		}
7622
7623		if ( opt.queue ) {
7624			jQuery.dequeue( this, opt.queue );
7625		}
7626	};
7627
7628	return opt;
7629};
7630
7631jQuery.fn.extend( {
7632	fadeTo: function( speed, to, easing, callback ) {
7633
7634		// Show any hidden elements after setting opacity to 0
7635		return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show()
7636
7637			// Animate to the value specified
7638			.end().animate( { opacity: to }, speed, easing, callback );
7639	},
7640	animate: function( prop, speed, easing, callback ) {
7641		var empty = jQuery.isEmptyObject( prop ),
7642			optall = jQuery.speed( speed, easing, callback ),
7643			doAnimation = function() {
7644
7645				// Operate on a copy of prop so per-property easing won't be lost
7646				var anim = Animation( this, jQuery.extend( {}, prop ), optall );
7647
7648				// Empty animations, or finishing resolves immediately
7649				if ( empty || dataPriv.get( this, "finish" ) ) {
7650					anim.stop( true );
7651				}
7652			};
7653
7654		doAnimation.finish = doAnimation;
7655
7656		return empty || optall.queue === false ?
7657			this.each( doAnimation ) :
7658			this.queue( optall.queue, doAnimation );
7659	},
7660	stop: function( type, clearQueue, gotoEnd ) {
7661		var stopQueue = function( hooks ) {
7662			var stop = hooks.stop;
7663			delete hooks.stop;
7664			stop( gotoEnd );
7665		};
7666
7667		if ( typeof type !== "string" ) {
7668			gotoEnd = clearQueue;
7669			clearQueue = type;
7670			type = undefined;
7671		}
7672		if ( clearQueue ) {
7673			this.queue( type || "fx", [] );
7674		}
7675
7676		return this.each( function() {
7677			var dequeue = true,
7678				index = type != null && type + "queueHooks",
7679				timers = jQuery.timers,
7680				data = dataPriv.get( this );
7681
7682			if ( index ) {
7683				if ( data[ index ] && data[ index ].stop ) {
7684					stopQueue( data[ index ] );
7685				}
7686			} else {
7687				for ( index in data ) {
7688					if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
7689						stopQueue( data[ index ] );
7690					}
7691				}
7692			}
7693
7694			for ( index = timers.length; index--; ) {
7695				if ( timers[ index ].elem === this &&
7696					( type == null || timers[ index ].queue === type ) ) {
7697
7698					timers[ index ].anim.stop( gotoEnd );
7699					dequeue = false;
7700					timers.splice( index, 1 );
7701				}
7702			}
7703
7704			// Start the next in the queue if the last step wasn't forced.
7705			// Timers currently will call their complete callbacks, which
7706			// will dequeue but only if they were gotoEnd.
7707			if ( dequeue || !gotoEnd ) {
7708				jQuery.dequeue( this, type );
7709			}
7710		} );
7711	},
7712	finish: function( type ) {
7713		if ( type !== false ) {
7714			type = type || "fx";
7715		}
7716		return this.each( function() {
7717			var index,
7718				data = dataPriv.get( this ),
7719				queue = data[ type + "queue" ],
7720				hooks = data[ type + "queueHooks" ],
7721				timers = jQuery.timers,
7722				length = queue ? queue.length : 0;
7723
7724			// Enable finishing flag on private data
7725			data.finish = true;
7726
7727			// Empty the queue first
7728			jQuery.queue( this, type, [] );
7729
7730			if ( hooks && hooks.stop ) {
7731				hooks.stop.call( this, true );
7732			}
7733
7734			// Look for any active animations, and finish them
7735			for ( index = timers.length; index--; ) {
7736				if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
7737					timers[ index ].anim.stop( true );
7738					timers.splice( index, 1 );
7739				}
7740			}
7741
7742			// Look for any animations in the old queue and finish them
7743			for ( index = 0; index < length; index++ ) {
7744				if ( queue[ index ] && queue[ index ].finish ) {
7745					queue[ index ].finish.call( this );
7746				}
7747			}
7748
7749			// Turn off finishing flag
7750			delete data.finish;
7751		} );
7752	}
7753} );
7754
7755jQuery.each( [ "toggle", "show", "hide" ], function( _i, name ) {
7756	var cssFn = jQuery.fn[ name ];
7757	jQuery.fn[ name ] = function( speed, easing, callback ) {
7758		return speed == null || typeof speed === "boolean" ?
7759			cssFn.apply( this, arguments ) :
7760			this.animate( genFx( name, true ), speed, easing, callback );
7761	};
7762} );
7763
7764// Generate shortcuts for custom animations
7765jQuery.each( {
7766	slideDown: genFx( "show" ),
7767	slideUp: genFx( "hide" ),
7768	slideToggle: genFx( "toggle" ),
7769	fadeIn: { opacity: "show" },
7770	fadeOut: { opacity: "hide" },
7771	fadeToggle: { opacity: "toggle" }
7772}, function( name, props ) {
7773	jQuery.fn[ name ] = function( speed, easing, callback ) {
7774		return this.animate( props, speed, easing, callback );
7775	};
7776} );
7777
7778jQuery.timers = [];
7779jQuery.fx.tick = function() {
7780	var timer,
7781		i = 0,
7782		timers = jQuery.timers;
7783
7784	fxNow = Date.now();
7785
7786	for ( ; i < timers.length; i++ ) {
7787		timer = timers[ i ];
7788
7789		// Run the timer and safely remove it when done (allowing for external removal)
7790		if ( !timer() && timers[ i ] === timer ) {
7791			timers.splice( i--, 1 );
7792		}
7793	}
7794
7795	if ( !timers.length ) {
7796		jQuery.fx.stop();
7797	}
7798	fxNow = undefined;
7799};
7800
7801jQuery.fx.timer = function( timer ) {
7802	jQuery.timers.push( timer );
7803	jQuery.fx.start();
7804};
7805
7806jQuery.fx.interval = 13;
7807jQuery.fx.start = function() {
7808	if ( inProgress ) {
7809		return;
7810	}
7811
7812	inProgress = true;
7813	schedule();
7814};
7815
7816jQuery.fx.stop = function() {
7817	inProgress = null;
7818};
7819
7820jQuery.fx.speeds = {
7821	slow: 600,
7822	fast: 200,
7823
7824	// Default speed
7825	_default: 400
7826};
7827
7828
7829// Based off of the plugin by Clint Helfers, with permission.
7830jQuery.fn.delay = function( time, type ) {
7831	time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
7832	type = type || "fx";
7833
7834	return this.queue( type, function( next, hooks ) {
7835		var timeout = window.setTimeout( next, time );
7836		hooks.stop = function() {
7837			window.clearTimeout( timeout );
7838		};
7839	} );
7840};
7841
7842
7843( function() {
7844	var input = document.createElement( "input" ),
7845		select = document.createElement( "select" ),
7846		opt = select.appendChild( document.createElement( "option" ) );
7847
7848	input.type = "checkbox";
7849
7850	// Support: Android <=4.3 only
7851	// Default value for a checkbox should be "on"
7852	support.checkOn = input.value !== "";
7853
7854	// Support: IE <=11 only
7855	// Must access selectedIndex to make default options select
7856	support.optSelected = opt.selected;
7857
7858	// Support: IE <=11 only
7859	// An input loses its value after becoming a radio
7860	input = document.createElement( "input" );
7861	input.value = "t";
7862	input.type = "radio";
7863	support.radioValue = input.value === "t";
7864} )();
7865
7866
7867var boolHook,
7868	attrHandle = jQuery.expr.attrHandle;
7869
7870jQuery.fn.extend( {
7871	attr: function( name, value ) {
7872		return access( this, jQuery.attr, name, value, arguments.length > 1 );
7873	},
7874
7875	removeAttr: function( name ) {
7876		return this.each( function() {
7877			jQuery.removeAttr( this, name );
7878		} );
7879	}
7880} );
7881
7882jQuery.extend( {
7883	attr: function( elem, name, value ) {
7884		var ret, hooks,
7885			nType = elem.nodeType;
7886
7887		// Don't get/set attributes on text, comment and attribute nodes
7888		if ( nType === 3 || nType === 8 || nType === 2 ) {
7889			return;
7890		}
7891
7892		// Fallback to prop when attributes are not supported
7893		if ( typeof elem.getAttribute === "undefined" ) {
7894			return jQuery.prop( elem, name, value );
7895		}
7896
7897		// Attribute hooks are determined by the lowercase version
7898		// Grab necessary hook if one is defined
7899		if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
7900			hooks = jQuery.attrHooks[ name.toLowerCase() ] ||
7901				( jQuery.expr.match.bool.test( name ) ? boolHook : undefined );
7902		}
7903
7904		if ( value !== undefined ) {
7905			if ( value === null ) {
7906				jQuery.removeAttr( elem, name );
7907				return;
7908			}
7909
7910			if ( hooks && "set" in hooks &&
7911				( ret = hooks.set( elem, value, name ) ) !== undefined ) {
7912				return ret;
7913			}
7914
7915			elem.setAttribute( name, value + "" );
7916			return value;
7917		}
7918
7919		if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
7920			return ret;
7921		}
7922
7923		ret = jQuery.find.attr( elem, name );
7924
7925		// Non-existent attributes return null, we normalize to undefined
7926		return ret == null ? undefined : ret;
7927	},
7928
7929	attrHooks: {
7930		type: {
7931			set: function( elem, value ) {
7932				if ( !support.radioValue && value === "radio" &&
7933					nodeName( elem, "input" ) ) {
7934					var val = elem.value;
7935					elem.setAttribute( "type", value );
7936					if ( val ) {
7937						elem.value = val;
7938					}
7939					return value;
7940				}
7941			}
7942		}
7943	},
7944
7945	removeAttr: function( elem, value ) {
7946		var name,
7947			i = 0,
7948
7949			// Attribute names can contain non-HTML whitespace characters
7950			// https://html.spec.whatwg.org/multipage/syntax.html#attributes-2
7951			attrNames = value && value.match( rnothtmlwhite );
7952
7953		if ( attrNames && elem.nodeType === 1 ) {
7954			while ( ( name = attrNames[ i++ ] ) ) {
7955				elem.removeAttribute( name );
7956			}
7957		}
7958	}
7959} );
7960
7961// Hooks for boolean attributes
7962boolHook = {
7963	set: function( elem, value, name ) {
7964		if ( value === false ) {
7965
7966			// Remove boolean attributes when set to false
7967			jQuery.removeAttr( elem, name );
7968		} else {
7969			elem.setAttribute( name, name );
7970		}
7971		return name;
7972	}
7973};
7974
7975jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( _i, name ) {
7976	var getter = attrHandle[ name ] || jQuery.find.attr;
7977
7978	attrHandle[ name ] = function( elem, name, isXML ) {
7979		var ret, handle,
7980			lowercaseName = name.toLowerCase();
7981
7982		if ( !isXML ) {
7983
7984			// Avoid an infinite loop by temporarily removing this function from the getter
7985			handle = attrHandle[ lowercaseName ];
7986			attrHandle[ lowercaseName ] = ret;
7987			ret = getter( elem, name, isXML ) != null ?
7988				lowercaseName :
7989				null;
7990			attrHandle[ lowercaseName ] = handle;
7991		}
7992		return ret;
7993	};
7994} );
7995
7996
7997
7998
7999var rfocusable = /^(?:input|select|textarea|button)$/i,
8000	rclickable = /^(?:a|area)$/i;
8001
8002jQuery.fn.extend( {
8003	prop: function( name, value ) {
8004		return access( this, jQuery.prop, name, value, arguments.length > 1 );
8005	},
8006
8007	removeProp: function( name ) {
8008		return this.each( function() {
8009			delete this[ jQuery.propFix[ name ] || name ];
8010		} );
8011	}
8012} );
8013
8014jQuery.extend( {
8015	prop: function( elem, name, value ) {
8016		var ret, hooks,
8017			nType = elem.nodeType;
8018
8019		// Don't get/set properties on text, comment and attribute nodes
8020		if ( nType === 3 || nType === 8 || nType === 2 ) {
8021			return;
8022		}
8023
8024		if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
8025
8026			// Fix name and attach hooks
8027			name = jQuery.propFix[ name ] || name;
8028			hooks = jQuery.propHooks[ name ];
8029		}
8030
8031		if ( value !== undefined ) {
8032			if ( hooks && "set" in hooks &&
8033				( ret = hooks.set( elem, value, name ) ) !== undefined ) {
8034				return ret;
8035			}
8036
8037			return ( elem[ name ] = value );
8038		}
8039
8040		if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
8041			return ret;
8042		}
8043
8044		return elem[ name ];
8045	},
8046
8047	propHooks: {
8048		tabIndex: {
8049			get: function( elem ) {
8050
8051				// Support: IE <=9 - 11 only
8052				// elem.tabIndex doesn't always return the
8053				// correct value when it hasn't been explicitly set
8054				// Use proper attribute retrieval (trac-12072)
8055				var tabindex = jQuery.find.attr( elem, "tabindex" );
8056
8057				if ( tabindex ) {
8058					return parseInt( tabindex, 10 );
8059				}
8060
8061				if (
8062					rfocusable.test( elem.nodeName ) ||
8063					rclickable.test( elem.nodeName ) &&
8064					elem.href
8065				) {
8066					return 0;
8067				}
8068
8069				return -1;
8070			}
8071		}
8072	},
8073
8074	propFix: {
8075		"for": "htmlFor",
8076		"class": "className"
8077	}
8078} );
8079
8080// Support: IE <=11 only
8081// Accessing the selectedIndex property
8082// forces the browser to respect setting selected
8083// on the option
8084// The getter ensures a default option is selected
8085// when in an optgroup
8086// eslint rule "no-unused-expressions" is disabled for this code
8087// since it considers such accessions noop
8088if ( !support.optSelected ) {
8089	jQuery.propHooks.selected = {
8090		get: function( elem ) {
8091
8092			/* eslint no-unused-expressions: "off" */
8093
8094			var parent = elem.parentNode;
8095			if ( parent && parent.parentNode ) {
8096				parent.parentNode.selectedIndex;
8097			}
8098			return null;
8099		},
8100		set: function( elem ) {
8101
8102			/* eslint no-unused-expressions: "off" */
8103
8104			var parent = elem.parentNode;
8105			if ( parent ) {
8106				parent.selectedIndex;
8107
8108				if ( parent.parentNode ) {
8109					parent.parentNode.selectedIndex;
8110				}
8111			}
8112		}
8113	};
8114}
8115
8116jQuery.each( [
8117	"tabIndex",
8118	"readOnly",
8119	"maxLength",
8120	"cellSpacing",
8121	"cellPadding",
8122	"rowSpan",
8123	"colSpan",
8124	"useMap",
8125	"frameBorder",
8126	"contentEditable"
8127], function() {
8128	jQuery.propFix[ this.toLowerCase() ] = this;
8129} );
8130
8131
8132
8133
8134	// Strip and collapse whitespace according to HTML spec
8135	// https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace
8136	function stripAndCollapse( value ) {
8137		var tokens = value.match( rnothtmlwhite ) || [];
8138		return tokens.join( " " );
8139	}
8140
8141
8142function getClass( elem ) {
8143	return elem.getAttribute && elem.getAttribute( "class" ) || "";
8144}
8145
8146function classesToArray( value ) {
8147	if ( Array.isArray( value ) ) {
8148		return value;
8149	}
8150	if ( typeof value === "string" ) {
8151		return value.match( rnothtmlwhite ) || [];
8152	}
8153	return [];
8154}
8155
8156jQuery.fn.extend( {
8157	addClass: function( value ) {
8158		var classNames, cur, curValue, className, i, finalValue;
8159
8160		if ( isFunction( value ) ) {
8161			return this.each( function( j ) {
8162				jQuery( this ).addClass( value.call( this, j, getClass( this ) ) );
8163			} );
8164		}
8165
8166		classNames = classesToArray( value );
8167
8168		if ( classNames.length ) {
8169			return this.each( function() {
8170				curValue = getClass( this );
8171				cur = this.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " );
8172
8173				if ( cur ) {
8174					for ( i = 0; i < classNames.length; i++ ) {
8175						className = classNames[ i ];
8176						if ( cur.indexOf( " " + className + " " ) < 0 ) {
8177							cur += className + " ";
8178						}
8179					}
8180
8181					// Only assign if different to avoid unneeded rendering.
8182					finalValue = stripAndCollapse( cur );
8183					if ( curValue !== finalValue ) {
8184						this.setAttribute( "class", finalValue );
8185					}
8186				}
8187			} );
8188		}
8189
8190		return this;
8191	},
8192
8193	removeClass: function( value ) {
8194		var classNames, cur, curValue, className, i, finalValue;
8195
8196		if ( isFunction( value ) ) {
8197			return this.each( function( j ) {
8198				jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) );
8199			} );
8200		}
8201
8202		if ( !arguments.length ) {
8203			return this.attr( "class", "" );
8204		}
8205
8206		classNames = classesToArray( value );
8207
8208		if ( classNames.length ) {
8209			return this.each( function() {
8210				curValue = getClass( this );
8211
8212				// This expression is here for better compressibility (see addClass)
8213				cur = this.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " );
8214
8215				if ( cur ) {
8216					for ( i = 0; i < classNames.length; i++ ) {
8217						className = classNames[ i ];
8218
8219						// Remove *all* instances
8220						while ( cur.indexOf( " " + className + " " ) > -1 ) {
8221							cur = cur.replace( " " + className + " ", " " );
8222						}
8223					}
8224
8225					// Only assign if different to avoid unneeded rendering.
8226					finalValue = stripAndCollapse( cur );
8227					if ( curValue !== finalValue ) {
8228						this.setAttribute( "class", finalValue );
8229					}
8230				}
8231			} );
8232		}
8233
8234		return this;
8235	},
8236
8237	toggleClass: function( value, stateVal ) {
8238		var classNames, className, i, self,
8239			type = typeof value,
8240			isValidValue = type === "string" || Array.isArray( value );
8241
8242		if ( isFunction( value ) ) {
8243			return this.each( function( i ) {
8244				jQuery( this ).toggleClass(
8245					value.call( this, i, getClass( this ), stateVal ),
8246					stateVal
8247				);
8248			} );
8249		}
8250
8251		if ( typeof stateVal === "boolean" && isValidValue ) {
8252			return stateVal ? this.addClass( value ) : this.removeClass( value );
8253		}
8254
8255		classNames = classesToArray( value );
8256
8257		return this.each( function() {
8258			if ( isValidValue ) {
8259
8260				// Toggle individual class names
8261				self = jQuery( this );
8262
8263				for ( i = 0; i < classNames.length; i++ ) {
8264					className = classNames[ i ];
8265
8266					// Check each className given, space separated list
8267					if ( self.hasClass( className ) ) {
8268						self.removeClass( className );
8269					} else {
8270						self.addClass( className );
8271					}
8272				}
8273
8274			// Toggle whole class name
8275			} else if ( value === undefined || type === "boolean" ) {
8276				className = getClass( this );
8277				if ( className ) {
8278
8279					// Store className if set
8280					dataPriv.set( this, "__className__", className );
8281				}
8282
8283				// If the element has a class name or if we're passed `false`,
8284				// then remove the whole classname (if there was one, the above saved it).
8285				// Otherwise bring back whatever was previously saved (if anything),
8286				// falling back to the empty string if nothing was stored.
8287				if ( this.setAttribute ) {
8288					this.setAttribute( "class",
8289						className || value === false ?
8290							"" :
8291							dataPriv.get( this, "__className__" ) || ""
8292					);
8293				}
8294			}
8295		} );
8296	},
8297
8298	hasClass: function( selector ) {
8299		var className, elem,
8300			i = 0;
8301
8302		className = " " + selector + " ";
8303		while ( ( elem = this[ i++ ] ) ) {
8304			if ( elem.nodeType === 1 &&
8305				( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) {
8306				return true;
8307			}
8308		}
8309
8310		return false;
8311	}
8312} );
8313
8314
8315
8316
8317var rreturn = /\r/g;
8318
8319jQuery.fn.extend( {
8320	val: function( value ) {
8321		var hooks, ret, valueIsFunction,
8322			elem = this[ 0 ];
8323
8324		if ( !arguments.length ) {
8325			if ( elem ) {
8326				hooks = jQuery.valHooks[ elem.type ] ||
8327					jQuery.valHooks[ elem.nodeName.toLowerCase() ];
8328
8329				if ( hooks &&
8330					"get" in hooks &&
8331					( ret = hooks.get( elem, "value" ) ) !== undefined
8332				) {
8333					return ret;
8334				}
8335
8336				ret = elem.value;
8337
8338				// Handle most common string cases
8339				if ( typeof ret === "string" ) {
8340					return ret.replace( rreturn, "" );
8341				}
8342
8343				// Handle cases where value is null/undef or number
8344				return ret == null ? "" : ret;
8345			}
8346
8347			return;
8348		}
8349
8350		valueIsFunction = isFunction( value );
8351
8352		return this.each( function( i ) {
8353			var val;
8354
8355			if ( this.nodeType !== 1 ) {
8356				return;
8357			}
8358
8359			if ( valueIsFunction ) {
8360				val = value.call( this, i, jQuery( this ).val() );
8361			} else {
8362				val = value;
8363			}
8364
8365			// Treat null/undefined as ""; convert numbers to string
8366			if ( val == null ) {
8367				val = "";
8368
8369			} else if ( typeof val === "number" ) {
8370				val += "";
8371
8372			} else if ( Array.isArray( val ) ) {
8373				val = jQuery.map( val, function( value ) {
8374					return value == null ? "" : value + "";
8375				} );
8376			}
8377
8378			hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
8379
8380			// If set returns undefined, fall back to normal setting
8381			if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) {
8382				this.value = val;
8383			}
8384		} );
8385	}
8386} );
8387
8388jQuery.extend( {
8389	valHooks: {
8390		option: {
8391			get: function( elem ) {
8392
8393				var val = jQuery.find.attr( elem, "value" );
8394				return val != null ?
8395					val :
8396
8397					// Support: IE <=10 - 11 only
8398					// option.text throws exceptions (trac-14686, trac-14858)
8399					// Strip and collapse whitespace
8400					// https://html.spec.whatwg.org/#strip-and-collapse-whitespace
8401					stripAndCollapse( jQuery.text( elem ) );
8402			}
8403		},
8404		select: {
8405			get: function( elem ) {
8406				var value, option, i,
8407					options = elem.options,
8408					index = elem.selectedIndex,
8409					one = elem.type === "select-one",
8410					values = one ? null : [],
8411					max = one ? index + 1 : options.length;
8412
8413				if ( index < 0 ) {
8414					i = max;
8415
8416				} else {
8417					i = one ? index : 0;
8418				}
8419
8420				// Loop through all the selected options
8421				for ( ; i < max; i++ ) {
8422					option = options[ i ];
8423
8424					// Support: IE <=9 only
8425					// IE8-9 doesn't update selected after form reset (trac-2551)
8426					if ( ( option.selected || i === index ) &&
8427
8428							// Don't return options that are disabled or in a disabled optgroup
8429							!option.disabled &&
8430							( !option.parentNode.disabled ||
8431								!nodeName( option.parentNode, "optgroup" ) ) ) {
8432
8433						// Get the specific value for the option
8434						value = jQuery( option ).val();
8435
8436						// We don't need an array for one selects
8437						if ( one ) {
8438							return value;
8439						}
8440
8441						// Multi-Selects return an array
8442						values.push( value );
8443					}
8444				}
8445
8446				return values;
8447			},
8448
8449			set: function( elem, value ) {
8450				var optionSet, option,
8451					options = elem.options,
8452					values = jQuery.makeArray( value ),
8453					i = options.length;
8454
8455				while ( i-- ) {
8456					option = options[ i ];
8457
8458					/* eslint-disable no-cond-assign */
8459
8460					if ( option.selected =
8461						jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1
8462					) {
8463						optionSet = true;
8464					}
8465
8466					/* eslint-enable no-cond-assign */
8467				}
8468
8469				// Force browsers to behave consistently when non-matching value is set
8470				if ( !optionSet ) {
8471					elem.selectedIndex = -1;
8472				}
8473				return values;
8474			}
8475		}
8476	}
8477} );
8478
8479// Radios and checkboxes getter/setter
8480jQuery.each( [ "radio", "checkbox" ], function() {
8481	jQuery.valHooks[ this ] = {
8482		set: function( elem, value ) {
8483			if ( Array.isArray( value ) ) {
8484				return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 );
8485			}
8486		}
8487	};
8488	if ( !support.checkOn ) {
8489		jQuery.valHooks[ this ].get = function( elem ) {
8490			return elem.getAttribute( "value" ) === null ? "on" : elem.value;
8491		};
8492	}
8493} );
8494
8495
8496
8497
8498// Return jQuery for attributes-only inclusion
8499var location = window.location;
8500
8501var nonce = { guid: Date.now() };
8502
8503var rquery = ( /\?/ );
8504
8505
8506
8507// Cross-browser xml parsing
8508jQuery.parseXML = function( data ) {
8509	var xml, parserErrorElem;
8510	if ( !data || typeof data !== "string" ) {
8511		return null;
8512	}
8513
8514	// Support: IE 9 - 11 only
8515	// IE throws on parseFromString with invalid input.
8516	try {
8517		xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" );
8518	} catch ( e ) {}
8519
8520	parserErrorElem = xml && xml.getElementsByTagName( "parsererror" )[ 0 ];
8521	if ( !xml || parserErrorElem ) {
8522		jQuery.error( "Invalid XML: " + (
8523			parserErrorElem ?
8524				jQuery.map( parserErrorElem.childNodes, function( el ) {
8525					return el.textContent;
8526				} ).join( "\n" ) :
8527				data
8528		) );
8529	}
8530	return xml;
8531};
8532
8533
8534var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
8535	stopPropagationCallback = function( e ) {
8536		e.stopPropagation();
8537	};
8538
8539jQuery.extend( jQuery.event, {
8540
8541	trigger: function( event, data, elem, onlyHandlers ) {
8542
8543		var i, cur, tmp, bubbleType, ontype, handle, special, lastElement,
8544			eventPath = [ elem || document ],
8545			type = hasOwn.call( event, "type" ) ? event.type : event,
8546			namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : [];
8547
8548		cur = lastElement = tmp = elem = elem || document;
8549
8550		// Don't do events on text and comment nodes
8551		if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
8552			return;
8553		}
8554
8555		// focus/blur morphs to focusin/out; ensure we're not firing them right now
8556		if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
8557			return;
8558		}
8559
8560		if ( type.indexOf( "." ) > -1 ) {
8561
8562			// Namespaced trigger; create a regexp to match event type in handle()
8563			namespaces = type.split( "." );
8564			type = namespaces.shift();
8565			namespaces.sort();
8566		}
8567		ontype = type.indexOf( ":" ) < 0 && "on" + type;
8568
8569		// Caller can pass in a jQuery.Event object, Object, or just an event type string
8570		event = event[ jQuery.expando ] ?
8571			event :
8572			new jQuery.Event( type, typeof event === "object" && event );
8573
8574		// Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
8575		event.isTrigger = onlyHandlers ? 2 : 3;
8576		event.namespace = namespaces.join( "." );
8577		event.rnamespace = event.namespace ?
8578			new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) :
8579			null;
8580
8581		// Clean up the event in case it is being reused
8582		event.result = undefined;
8583		if ( !event.target ) {
8584			event.target = elem;
8585		}
8586
8587		// Clone any incoming data and prepend the event, creating the handler arg list
8588		data = data == null ?
8589			[ event ] :
8590			jQuery.makeArray( data, [ event ] );
8591
8592		// Allow special events to draw outside the lines
8593		special = jQuery.event.special[ type ] || {};
8594		if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
8595			return;
8596		}
8597
8598		// Determine event propagation path in advance, per W3C events spec (trac-9951)
8599		// Bubble up to document, then to window; watch for a global ownerDocument var (trac-9724)
8600		if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) {
8601
8602			bubbleType = special.delegateType || type;
8603			if ( !rfocusMorph.test( bubbleType + type ) ) {
8604				cur = cur.parentNode;
8605			}
8606			for ( ; cur; cur = cur.parentNode ) {
8607				eventPath.push( cur );
8608				tmp = cur;
8609			}
8610
8611			// Only add window if we got to document (e.g., not plain obj or detached DOM)
8612			if ( tmp === ( elem.ownerDocument || document ) ) {
8613				eventPath.push( tmp.defaultView || tmp.parentWindow || window );
8614			}
8615		}
8616
8617		// Fire handlers on the event path
8618		i = 0;
8619		while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) {
8620			lastElement = cur;
8621			event.type = i > 1 ?
8622				bubbleType :
8623				special.bindType || type;
8624
8625			// jQuery handler
8626			handle = ( dataPriv.get( cur, "events" ) || Object.create( null ) )[ event.type ] &&
8627				dataPriv.get( cur, "handle" );
8628			if ( handle ) {
8629				handle.apply( cur, data );
8630			}
8631
8632			// Native handler
8633			handle = ontype && cur[ ontype ];
8634			if ( handle && handle.apply && acceptData( cur ) ) {
8635				event.result = handle.apply( cur, data );
8636				if ( event.result === false ) {
8637					event.preventDefault();
8638				}
8639			}
8640		}
8641		event.type = type;
8642
8643		// If nobody prevented the default action, do it now
8644		if ( !onlyHandlers && !event.isDefaultPrevented() ) {
8645
8646			if ( ( !special._default ||
8647				special._default.apply( eventPath.pop(), data ) === false ) &&
8648				acceptData( elem ) ) {
8649
8650				// Call a native DOM method on the target with the same name as the event.
8651				// Don't do default actions on window, that's where global variables be (trac-6170)
8652				if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) {
8653
8654					// Don't re-trigger an onFOO event when we call its FOO() method
8655					tmp = elem[ ontype ];
8656
8657					if ( tmp ) {
8658						elem[ ontype ] = null;
8659					}
8660
8661					// Prevent re-triggering of the same event, since we already bubbled it above
8662					jQuery.event.triggered = type;
8663
8664					if ( event.isPropagationStopped() ) {
8665						lastElement.addEventListener( type, stopPropagationCallback );
8666					}
8667
8668					elem[ type ]();
8669
8670					if ( event.isPropagationStopped() ) {
8671						lastElement.removeEventListener( type, stopPropagationCallback );
8672					}
8673
8674					jQuery.event.triggered = undefined;
8675
8676					if ( tmp ) {
8677						elem[ ontype ] = tmp;
8678					}
8679				}
8680			}
8681		}
8682
8683		return event.result;
8684	},
8685
8686	// Piggyback on a donor event to simulate a different one
8687	// Used only for `focus(in | out)` events
8688	simulate: function( type, elem, event ) {
8689		var e = jQuery.extend(
8690			new jQuery.Event(),
8691			event,
8692			{
8693				type: type,
8694				isSimulated: true
8695			}
8696		);
8697
8698		jQuery.event.trigger( e, null, elem );
8699	}
8700
8701} );
8702
8703jQuery.fn.extend( {
8704
8705	trigger: function( type, data ) {
8706		return this.each( function() {
8707			jQuery.event.trigger( type, data, this );
8708		} );
8709	},
8710	triggerHandler: function( type, data ) {
8711		var elem = this[ 0 ];
8712		if ( elem ) {
8713			return jQuery.event.trigger( type, data, elem, true );
8714		}
8715	}
8716} );
8717
8718
8719var
8720	rbracket = /\[\]$/,
8721	rCRLF = /\r?\n/g,
8722	rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
8723	rsubmittable = /^(?:input|select|textarea|keygen)/i;
8724
8725function buildParams( prefix, obj, traditional, add ) {
8726	var name;
8727
8728	if ( Array.isArray( obj ) ) {
8729
8730		// Serialize array item.
8731		jQuery.each( obj, function( i, v ) {
8732			if ( traditional || rbracket.test( prefix ) ) {
8733
8734				// Treat each array item as a scalar.
8735				add( prefix, v );
8736
8737			} else {
8738
8739				// Item is non-scalar (array or object), encode its numeric index.
8740				buildParams(
8741					prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]",
8742					v,
8743					traditional,
8744					add
8745				);
8746			}
8747		} );
8748
8749	} else if ( !traditional && toType( obj ) === "object" ) {
8750
8751		// Serialize object item.
8752		for ( name in obj ) {
8753			buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
8754		}
8755
8756	} else {
8757
8758		// Serialize scalar item.
8759		add( prefix, obj );
8760	}
8761}
8762
8763// Serialize an array of form elements or a set of
8764// key/values into a query string
8765jQuery.param = function( a, traditional ) {
8766	var prefix,
8767		s = [],
8768		add = function( key, valueOrFunction ) {
8769
8770			// If value is a function, invoke it and use its return value
8771			var value = isFunction( valueOrFunction ) ?
8772				valueOrFunction() :
8773				valueOrFunction;
8774
8775			s[ s.length ] = encodeURIComponent( key ) + "=" +
8776				encodeURIComponent( value == null ? "" : value );
8777		};
8778
8779	if ( a == null ) {
8780		return "";
8781	}
8782
8783	// If an array was passed in, assume that it is an array of form elements.
8784	if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
8785
8786		// Serialize the form elements
8787		jQuery.each( a, function() {
8788			add( this.name, this.value );
8789		} );
8790
8791	} else {
8792
8793		// If traditional, encode the "old" way (the way 1.3.2 or older
8794		// did it), otherwise encode params recursively.
8795		for ( prefix in a ) {
8796			buildParams( prefix, a[ prefix ], traditional, add );
8797		}
8798	}
8799
8800	// Return the resulting serialization
8801	return s.join( "&" );
8802};
8803
8804jQuery.fn.extend( {
8805	serialize: function() {
8806		return jQuery.param( this.serializeArray() );
8807	},
8808	serializeArray: function() {
8809		return this.map( function() {
8810
8811			// Can add propHook for "elements" to filter or add form elements
8812			var elements = jQuery.prop( this, "elements" );
8813			return elements ? jQuery.makeArray( elements ) : this;
8814		} ).filter( function() {
8815			var type = this.type;
8816
8817			// Use .is( ":disabled" ) so that fieldset[disabled] works
8818			return this.name && !jQuery( this ).is( ":disabled" ) &&
8819				rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
8820				( this.checked || !rcheckableType.test( type ) );
8821		} ).map( function( _i, elem ) {
8822			var val = jQuery( this ).val();
8823
8824			if ( val == null ) {
8825				return null;
8826			}
8827
8828			if ( Array.isArray( val ) ) {
8829				return jQuery.map( val, function( val ) {
8830					return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
8831				} );
8832			}
8833
8834			return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
8835		} ).get();
8836	}
8837} );
8838
8839
8840var
8841	r20 = /%20/g,
8842	rhash = /#.*$/,
8843	rantiCache = /([?&])_=[^&]*/,
8844	rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg,
8845
8846	// trac-7653, trac-8125, trac-8152: local protocol detection
8847	rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
8848	rnoContent = /^(?:GET|HEAD)$/,
8849	rprotocol = /^\/\//,
8850
8851	/* Prefilters
8852	 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
8853	 * 2) These are called:
8854	 *    - BEFORE asking for a transport
8855	 *    - AFTER param serialization (s.data is a string if s.processData is true)
8856	 * 3) key is the dataType
8857	 * 4) the catchall symbol "*" can be used
8858	 * 5) execution will start with transport dataType and THEN continue down to "*" if needed
8859	 */
8860	prefilters = {},
8861
8862	/* Transports bindings
8863	 * 1) key is the dataType
8864	 * 2) the catchall symbol "*" can be used
8865	 * 3) selection will start with transport dataType and THEN go to "*" if needed
8866	 */
8867	transports = {},
8868
8869	// Avoid comment-prolog char sequence (trac-10098); must appease lint and evade compression
8870	allTypes = "*/".concat( "*" ),
8871
8872	// Anchor tag for parsing the document origin
8873	originAnchor = document.createElement( "a" );
8874
8875originAnchor.href = location.href;
8876
8877// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
8878function addToPrefiltersOrTransports( structure ) {
8879
8880	// dataTypeExpression is optional and defaults to "*"
8881	return function( dataTypeExpression, func ) {
8882
8883		if ( typeof dataTypeExpression !== "string" ) {
8884			func = dataTypeExpression;
8885			dataTypeExpression = "*";
8886		}
8887
8888		var dataType,
8889			i = 0,
8890			dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || [];
8891
8892		if ( isFunction( func ) ) {
8893
8894			// For each dataType in the dataTypeExpression
8895			while ( ( dataType = dataTypes[ i++ ] ) ) {
8896
8897				// Prepend if requested
8898				if ( dataType[ 0 ] === "+" ) {
8899					dataType = dataType.slice( 1 ) || "*";
8900					( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func );
8901
8902				// Otherwise append
8903				} else {
8904					( structure[ dataType ] = structure[ dataType ] || [] ).push( func );
8905				}
8906			}
8907		}
8908	};
8909}
8910
8911// Base inspection function for prefilters and transports
8912function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
8913
8914	var inspected = {},
8915		seekingTransport = ( structure === transports );
8916
8917	function inspect( dataType ) {
8918		var selected;
8919		inspected[ dataType ] = true;
8920		jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
8921			var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
8922			if ( typeof dataTypeOrTransport === "string" &&
8923				!seekingTransport && !inspected[ dataTypeOrTransport ] ) {
8924
8925				options.dataTypes.unshift( dataTypeOrTransport );
8926				inspect( dataTypeOrTransport );
8927				return false;
8928			} else if ( seekingTransport ) {
8929				return !( selected = dataTypeOrTransport );
8930			}
8931		} );
8932		return selected;
8933	}
8934
8935	return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
8936}
8937
8938// A special extend for ajax options
8939// that takes "flat" options (not to be deep extended)
8940// Fixes trac-9887
8941function ajaxExtend( target, src ) {
8942	var key, deep,
8943		flatOptions = jQuery.ajaxSettings.flatOptions || {};
8944
8945	for ( key in src ) {
8946		if ( src[ key ] !== undefined ) {
8947			( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
8948		}
8949	}
8950	if ( deep ) {
8951		jQuery.extend( true, target, deep );
8952	}
8953
8954	return target;
8955}
8956
8957/* Handles responses to an ajax request:
8958 * - finds the right dataType (mediates between content-type and expected dataType)
8959 * - returns the corresponding response
8960 */
8961function ajaxHandleResponses( s, jqXHR, responses ) {
8962
8963	var ct, type, finalDataType, firstDataType,
8964		contents = s.contents,
8965		dataTypes = s.dataTypes;
8966
8967	// Remove auto dataType and get content-type in the process
8968	while ( dataTypes[ 0 ] === "*" ) {
8969		dataTypes.shift();
8970		if ( ct === undefined ) {
8971			ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" );
8972		}
8973	}
8974
8975	// Check if we're dealing with a known content-type
8976	if ( ct ) {
8977		for ( type in contents ) {
8978			if ( contents[ type ] && contents[ type ].test( ct ) ) {
8979				dataTypes.unshift( type );
8980				break;
8981			}
8982		}
8983	}
8984
8985	// Check to see if we have a response for the expected dataType
8986	if ( dataTypes[ 0 ] in responses ) {
8987		finalDataType = dataTypes[ 0 ];
8988	} else {
8989
vendor: 9,527 bytes, lines 8990-9365
8990		// Try convertible dataTypes
8991		for ( type in responses ) {
8992			if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) {
8993				finalDataType = type;
8994				break;
8995			}
8996			if ( !firstDataType ) {
8997				firstDataType = type;
8998			}
8999		}
9000
9001		// Or just use first one
9002		finalDataType = finalDataType || firstDataType;
9003	}
9004
9005	// If we found a dataType
9006	// We add the dataType to the list if needed
9007	// and return the corresponding response
9008	if ( finalDataType ) {
9009		if ( finalDataType !== dataTypes[ 0 ] ) {
9010			dataTypes.unshift( finalDataType );
9011		}
9012		return responses[ finalDataType ];
9013	}
9014}
9015
9016/* Chain conversions given the request and the original response
9017 * Also sets the responseXXX fields on the jqXHR instance
9018 */
9019function ajaxConvert( s, response, jqXHR, isSuccess ) {
9020	var conv2, current, conv, tmp, prev,
9021		converters = {},
9022
9023		// Work with a copy of dataTypes in case we need to modify it for conversion
9024		dataTypes = s.dataTypes.slice();
9025
9026	// Create converters map with lowercased keys
9027	if ( dataTypes[ 1 ] ) {
9028		for ( conv in s.converters ) {
9029			converters[ conv.toLowerCase() ] = s.converters[ conv ];
9030		}
9031	}
9032
9033	current = dataTypes.shift();
9034
9035	// Convert to each sequential dataType
9036	while ( current ) {
9037
9038		if ( s.responseFields[ current ] ) {
9039			jqXHR[ s.responseFields[ current ] ] = response;
9040		}
9041
9042		// Apply the dataFilter if provided
9043		if ( !prev && isSuccess && s.dataFilter ) {
9044			response = s.dataFilter( response, s.dataType );
9045		}
9046
9047		prev = current;
9048		current = dataTypes.shift();
9049
9050		if ( current ) {
9051
9052			// There's only work to do if current dataType is non-auto
9053			if ( current === "*" ) {
9054
9055				current = prev;
9056
9057			// Convert response if prev dataType is non-auto and differs from current
9058			} else if ( prev !== "*" && prev !== current ) {
9059
9060				// Seek a direct converter
9061				conv = converters[ prev + " " + current ] || converters[ "* " + current ];
9062
9063				// If none found, seek a pair
9064				if ( !conv ) {
9065					for ( conv2 in converters ) {
9066
9067						// If conv2 outputs current
9068						tmp = conv2.split( " " );
9069						if ( tmp[ 1 ] === current ) {
9070
9071							// If prev can be converted to accepted input
9072							conv = converters[ prev + " " + tmp[ 0 ] ] ||
9073								converters[ "* " + tmp[ 0 ] ];
9074							if ( conv ) {
9075
9076								// Condense equivalence converters
9077								if ( conv === true ) {
9078									conv = converters[ conv2 ];
9079
9080								// Otherwise, insert the intermediate dataType
9081								} else if ( converters[ conv2 ] !== true ) {
9082									current = tmp[ 0 ];
9083									dataTypes.unshift( tmp[ 1 ] );
9084								}
9085								break;
9086							}
9087						}
9088					}
9089				}
9090
9091				// Apply converter (if not an equivalence)
9092				if ( conv !== true ) {
9093
9094					// Unless errors are allowed to bubble, catch and return them
9095					if ( conv && s.throws ) {
9096						response = conv( response );
9097					} else {
9098						try {
9099							response = conv( response );
9100						} catch ( e ) {
9101							return {
9102								state: "parsererror",
9103								error: conv ? e : "No conversion from " + prev + " to " + current
9104							};
9105						}
9106					}
9107				}
9108			}
9109		}
9110	}
9111
9112	return { state: "success", data: response };
9113}
9114
9115jQuery.extend( {
9116
9117	// Counter for holding the number of active queries
9118	active: 0,
9119
9120	// Last-Modified header cache for next request
9121	lastModified: {},
9122	etag: {},
9123
9124	ajaxSettings: {
9125		url: location.href,
9126		type: "GET",
9127		isLocal: rlocalProtocol.test( location.protocol ),
9128		global: true,
9129		processData: true,
9130		async: true,
9131		contentType: "application/x-www-form-urlencoded; charset=UTF-8",
9132
9133		/*
9134		timeout: 0,
9135		data: null,
9136		dataType: null,
9137		username: null,
9138		password: null,
9139		cache: null,
9140		throws: false,
9141		traditional: false,
9142		headers: {},
9143		*/
9144
9145		accepts: {
9146			"*": allTypes,
9147			text: "text/plain",
9148			html: "text/html",
9149			xml: "application/xml, text/xml",
9150			json: "application/json, text/javascript"
9151		},
9152
9153		contents: {
9154			xml: /\bxml\b/,
9155			html: /\bhtml/,
9156			json: /\bjson\b/
9157		},
9158
9159		responseFields: {
9160			xml: "responseXML",
9161			text: "responseText",
9162			json: "responseJSON"
9163		},
9164
9165		// Data converters
9166		// Keys separate source (or catchall "*") and destination types with a single space
9167		converters: {
9168
9169			// Convert anything to text
9170			"* text": String,
9171
9172			// Text to html (true = no transformation)
9173			"text html": true,
9174
9175			// Evaluate text as a json expression
9176			"text json": JSON.parse,
9177
9178			// Parse text as xml
9179			"text xml": jQuery.parseXML
9180		},
9181
9182		// For options that shouldn't be deep extended:
9183		// you can add your own custom options here if
9184		// and when you create one that shouldn't be
9185		// deep extended (see ajaxExtend)
9186		flatOptions: {
9187			url: true,
9188			context: true
9189		}
9190	},
9191
9192	// Creates a full fledged settings object into target
9193	// with both ajaxSettings and settings fields.
9194	// If target is omitted, writes into ajaxSettings.
9195	ajaxSetup: function( target, settings ) {
9196		return settings ?
9197
9198			// Building a settings object
9199			ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
9200
9201			// Extending ajaxSettings
9202			ajaxExtend( jQuery.ajaxSettings, target );
9203	},
9204
9205	ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
9206	ajaxTransport: addToPrefiltersOrTransports( transports ),
9207
9208	// Main method
9209	ajax: function( url, options ) {
9210
9211		// If url is an object, simulate pre-1.5 signature
9212		if ( typeof url === "object" ) {
9213			options = url;
9214			url = undefined;
9215		}
9216
9217		// Force options to be an object
9218		options = options || {};
9219
9220		var transport,
9221
9222			// URL without anti-cache param
9223			cacheURL,
9224
9225			// Response headers
9226			responseHeadersString,
9227			responseHeaders,
9228
9229			// timeout handle
9230			timeoutTimer,
9231
9232			// Url cleanup var
9233			urlAnchor,
9234
9235			// Request state (becomes false upon send and true upon completion)
9236			completed,
9237
9238			// To know if global events are to be dispatched
9239			fireGlobals,
9240
9241			// Loop variable
9242			i,
9243
9244			// uncached part of the url
9245			uncached,
9246
9247			// Create the final options object
9248			s = jQuery.ajaxSetup( {}, options ),
9249
9250			// Callbacks context
9251			callbackContext = s.context || s,
9252
9253			// Context for global events is callbackContext if it is a DOM node or jQuery collection
9254			globalEventContext = s.context &&
9255				( callbackContext.nodeType || callbackContext.jquery ) ?
9256				jQuery( callbackContext ) :
9257				jQuery.event,
9258
9259			// Deferreds
9260			deferred = jQuery.Deferred(),
9261			completeDeferred = jQuery.Callbacks( "once memory" ),
9262
9263			// Status-dependent callbacks
9264			statusCode = s.statusCode || {},
9265
9266			// Headers (they are sent all at once)
9267			requestHeaders = {},
9268			requestHeadersNames = {},
9269
9270			// Default abort message
9271			strAbort = "canceled",
9272
9273			// Fake xhr
9274			jqXHR = {
9275				readyState: 0,
9276
9277				// Builds headers hashtable if needed
9278				getResponseHeader: function( key ) {
9279					var match;
9280					if ( completed ) {
9281						if ( !responseHeaders ) {
9282							responseHeaders = {};
9283							while ( ( match = rheaders.exec( responseHeadersString ) ) ) {
9284								responseHeaders[ match[ 1 ].toLowerCase() + " " ] =
9285									( responseHeaders[ match[ 1 ].toLowerCase() + " " ] || [] )
9286										.concat( match[ 2 ] );
9287							}
9288						}
9289						match = responseHeaders[ key.toLowerCase() + " " ];
9290					}
9291					return match == null ? null : match.join( ", " );
9292				},
9293
9294				// Raw string
9295				getAllResponseHeaders: function() {
9296					return completed ? responseHeadersString : null;
9297				},
9298
9299				// Caches the header
9300				setRequestHeader: function( name, value ) {
9301					if ( completed == null ) {
9302						name = requestHeadersNames[ name.toLowerCase() ] =
9303							requestHeadersNames[ name.toLowerCase() ] || name;
9304						requestHeaders[ name ] = value;
9305					}
9306					return this;
9307				},
9308
9309				// Overrides response content-type header
9310				overrideMimeType: function( type ) {
9311					if ( completed == null ) {
9312						s.mimeType = type;
9313					}
9314					return this;
9315				},
9316
9317				// Status-dependent callbacks
9318				statusCode: function( map ) {
9319					var code;
9320					if ( map ) {
9321						if ( completed ) {
9322
9323							// Execute the appropriate callbacks
9324							jqXHR.always( map[ jqXHR.status ] );
9325						} else {
9326
9327							// Lazy-add the new callbacks in a way that preserves old ones
9328							for ( code in map ) {
9329								statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
9330							}
9331						}
9332					}
9333					return this;
9334				},
9335
9336				// Cancel the request
9337				abort: function( statusText ) {
9338					var finalText = statusText || strAbort;
9339					if ( transport ) {
9340						transport.abort( finalText );
9341					}
9342					done( 0, finalText );
9343					return this;
9344				}
9345			};
9346
9347		// Attach deferreds
9348		deferred.promise( jqXHR );
9349
9350		// Add protocol if not provided (prefilters might expect it)
9351		// Handle falsy url in the settings object (trac-10093: consistency with old signature)
9352		// We also use the url parameter if available
9353		s.url = ( ( url || s.url || location.href ) + "" )
9354			.replace( rprotocol, location.protocol + "//" );
9355
9356		// Alias method option to type as per ticket trac-12004
9357		s.type = options.method || options.type || s.method || s.type;
9358
9359		// Extract dataTypes list
9360		s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ];
9361
9362		// A cross-domain request is in order when the origin doesn't match the current origin.
9363		if ( s.crossDomain == null ) {
9364			urlAnchor = document.createElement( "a" );
9365
vendor: 32,506 bytes, lines 9366-10529
9366			// Support: IE <=8 - 11, Edge 12 - 15
9367			// IE throws exception on accessing the href property if url is malformed,
9368			// e.g. http://example.com:80x/
9369			try {
9370				urlAnchor.href = s.url;
9371
9372				// Support: IE <=8 - 11 only
9373				// Anchor's host property isn't correctly set when s.url is relative
9374				urlAnchor.href = urlAnchor.href;
9375				s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !==
9376					urlAnchor.protocol + "//" + urlAnchor.host;
9377			} catch ( e ) {
9378
9379				// If there is an error parsing the URL, assume it is crossDomain,
9380				// it can be rejected by the transport if it is invalid
9381				s.crossDomain = true;
9382			}
9383		}
9384
9385		// Convert data if not already a string
9386		if ( s.data && s.processData && typeof s.data !== "string" ) {
9387			s.data = jQuery.param( s.data, s.traditional );
9388		}
9389
9390		// Apply prefilters
9391		inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
9392
9393		// If request was aborted inside a prefilter, stop there
9394		if ( completed ) {
9395			return jqXHR;
9396		}
9397
9398		// We can fire global events as of now if asked to
9399		// Don't fire events if jQuery.event is undefined in an AMD-usage scenario (trac-15118)
9400		fireGlobals = jQuery.event && s.global;
9401
9402		// Watch for a new set of requests
9403		if ( fireGlobals && jQuery.active++ === 0 ) {
9404			jQuery.event.trigger( "ajaxStart" );
9405		}
9406
9407		// Uppercase the type
9408		s.type = s.type.toUpperCase();
9409
9410		// Determine if request has content
9411		s.hasContent = !rnoContent.test( s.type );
9412
9413		// Save the URL in case we're toying with the If-Modified-Since
9414		// and/or If-None-Match header later on
9415		// Remove hash to simplify url manipulation
9416		cacheURL = s.url.replace( rhash, "" );
9417
9418		// More options handling for requests with no content
9419		if ( !s.hasContent ) {
9420
9421			// Remember the hash so we can put it back
9422			uncached = s.url.slice( cacheURL.length );
9423
9424			// If data is available and should be processed, append data to url
9425			if ( s.data && ( s.processData || typeof s.data === "string" ) ) {
9426				cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data;
9427
9428				// trac-9682: remove data so that it's not used in an eventual retry
9429				delete s.data;
9430			}
9431
9432			// Add or update anti-cache param if needed
9433			if ( s.cache === false ) {
9434				cacheURL = cacheURL.replace( rantiCache, "$1" );
9435				uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce.guid++ ) +
9436					uncached;
9437			}
9438
9439			// Put hash and anti-cache on the URL that will be requested (gh-1732)
9440			s.url = cacheURL + uncached;
9441
9442		// Change '%20' to '+' if this is encoded form body content (gh-2658)
9443		} else if ( s.data && s.processData &&
9444			( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) {
9445			s.data = s.data.replace( r20, "+" );
9446		}
9447
9448		// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
9449		if ( s.ifModified ) {
9450			if ( jQuery.lastModified[ cacheURL ] ) {
9451				jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
9452			}
9453			if ( jQuery.etag[ cacheURL ] ) {
9454				jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
9455			}
9456		}
9457
9458		// Set the correct header, if data is being sent
9459		if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
9460			jqXHR.setRequestHeader( "Content-Type", s.contentType );
9461		}
9462
9463		// Set the Accepts header for the server, depending on the dataType
9464		jqXHR.setRequestHeader(
9465			"Accept",
9466			s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ?
9467				s.accepts[ s.dataTypes[ 0 ] ] +
9468					( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
9469				s.accepts[ "*" ]
9470		);
9471
9472		// Check for headers option
9473		for ( i in s.headers ) {
9474			jqXHR.setRequestHeader( i, s.headers[ i ] );
9475		}
9476
9477		// Allow custom headers/mimetypes and early abort
9478		if ( s.beforeSend &&
9479			( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) {
9480
9481			// Abort if not done already and return
9482			return jqXHR.abort();
9483		}
9484
9485		// Aborting is no longer a cancellation
9486		strAbort = "abort";
9487
9488		// Install callbacks on deferreds
9489		completeDeferred.add( s.complete );
9490		jqXHR.done( s.success );
9491		jqXHR.fail( s.error );
9492
9493		// Get transport
9494		transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
9495
9496		// If no transport, we auto-abort
9497		if ( !transport ) {
9498			done( -1, "No Transport" );
9499		} else {
9500			jqXHR.readyState = 1;
9501
9502			// Send global event
9503			if ( fireGlobals ) {
9504				globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
9505			}
9506
9507			// If request was aborted inside ajaxSend, stop there
9508			if ( completed ) {
9509				return jqXHR;
9510			}
9511
9512			// Timeout
9513			if ( s.async && s.timeout > 0 ) {
9514				timeoutTimer = window.setTimeout( function() {
9515					jqXHR.abort( "timeout" );
9516				}, s.timeout );
9517			}
9518
9519			try {
9520				completed = false;
9521				transport.send( requestHeaders, done );
9522			} catch ( e ) {
9523
9524				// Rethrow post-completion exceptions
9525				if ( completed ) {
9526					throw e;
9527				}
9528
9529				// Propagate others as results
9530				done( -1, e );
9531			}
9532		}
9533
9534		// Callback for when everything is done
9535		function done( status, nativeStatusText, responses, headers ) {
9536			var isSuccess, success, error, response, modified,
9537				statusText = nativeStatusText;
9538
9539			// Ignore repeat invocations
9540			if ( completed ) {
9541				return;
9542			}
9543
9544			completed = true;
9545
9546			// Clear timeout if it exists
9547			if ( timeoutTimer ) {
9548				window.clearTimeout( timeoutTimer );
9549			}
9550
9551			// Dereference transport for early garbage collection
9552			// (no matter how long the jqXHR object will be used)
9553			transport = undefined;
9554
9555			// Cache response headers
9556			responseHeadersString = headers || "";
9557
9558			// Set readyState
9559			jqXHR.readyState = status > 0 ? 4 : 0;
9560
9561			// Determine if successful
9562			isSuccess = status >= 200 && status < 300 || status === 304;
9563
9564			// Get response data
9565			if ( responses ) {
9566				response = ajaxHandleResponses( s, jqXHR, responses );
9567			}
9568
9569			// Use a noop converter for missing script but not if jsonp
9570			if ( !isSuccess &&
9571				jQuery.inArray( "script", s.dataTypes ) > -1 &&
9572				jQuery.inArray( "json", s.dataTypes ) < 0 ) {
9573				s.converters[ "text script" ] = function() {};
9574			}
9575
9576			// Convert no matter what (that way responseXXX fields are always set)
9577			response = ajaxConvert( s, response, jqXHR, isSuccess );
9578
9579			// If successful, handle type chaining
9580			if ( isSuccess ) {
9581
9582				// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
9583				if ( s.ifModified ) {
9584					modified = jqXHR.getResponseHeader( "Last-Modified" );
9585					if ( modified ) {
9586						jQuery.lastModified[ cacheURL ] = modified;
9587					}
9588					modified = jqXHR.getResponseHeader( "etag" );
9589					if ( modified ) {
9590						jQuery.etag[ cacheURL ] = modified;
9591					}
9592				}
9593
9594				// if no content
9595				if ( status === 204 || s.type === "HEAD" ) {
9596					statusText = "nocontent";
9597
9598				// if not modified
9599				} else if ( status === 304 ) {
9600					statusText = "notmodified";
9601
9602				// If we have data, let's convert it
9603				} else {
9604					statusText = response.state;
9605					success = response.data;
9606					error = response.error;
9607					isSuccess = !error;
9608				}
9609			} else {
9610
9611				// Extract error from statusText and normalize for non-aborts
9612				error = statusText;
9613				if ( status || !statusText ) {
9614					statusText = "error";
9615					if ( status < 0 ) {
9616						status = 0;
9617					}
9618				}
9619			}
9620
9621			// Set data for the fake xhr object
9622			jqXHR.status = status;
9623			jqXHR.statusText = ( nativeStatusText || statusText ) + "";
9624
9625			// Success/Error
9626			if ( isSuccess ) {
9627				deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
9628			} else {
9629				deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
9630			}
9631
9632			// Status-dependent callbacks
9633			jqXHR.statusCode( statusCode );
9634			statusCode = undefined;
9635
9636			if ( fireGlobals ) {
9637				globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
9638					[ jqXHR, s, isSuccess ? success : error ] );
9639			}
9640
9641			// Complete
9642			completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
9643
9644			if ( fireGlobals ) {
9645				globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
9646
9647				// Handle the global AJAX counter
9648				if ( !( --jQuery.active ) ) {
9649					jQuery.event.trigger( "ajaxStop" );
9650				}
9651			}
9652		}
9653
9654		return jqXHR;
9655	},
9656
9657	getJSON: function( url, data, callback ) {
9658		return jQuery.get( url, data, callback, "json" );
9659	},
9660
9661	getScript: function( url, callback ) {
9662		return jQuery.get( url, undefined, callback, "script" );
9663	}
9664} );
9665
9666jQuery.each( [ "get", "post" ], function( _i, method ) {
9667	jQuery[ method ] = function( url, data, callback, type ) {
9668
9669		// Shift arguments if data argument was omitted
9670		if ( isFunction( data ) ) {
9671			type = type || callback;
9672			callback = data;
9673			data = undefined;
9674		}
9675
9676		// The url can be an options object (which then must have .url)
9677		return jQuery.ajax( jQuery.extend( {
9678			url: url,
9679			type: method,
9680			dataType: type,
9681			data: data,
9682			success: callback
9683		}, jQuery.isPlainObject( url ) && url ) );
9684	};
9685} );
9686
9687jQuery.ajaxPrefilter( function( s ) {
9688	var i;
9689	for ( i in s.headers ) {
9690		if ( i.toLowerCase() === "content-type" ) {
9691			s.contentType = s.headers[ i ] || "";
9692		}
9693	}
9694} );
9695
9696
9697jQuery._evalUrl = function( url, options, doc ) {
9698	return jQuery.ajax( {
9699		url: url,
9700
9701		// Make this explicit, since user can override this through ajaxSetup (trac-11264)
9702		type: "GET",
9703		dataType: "script",
9704		cache: true,
9705		async: false,
9706		global: false,
9707
9708		// Only evaluate the response if it is successful (gh-4126)
9709		// dataFilter is not invoked for failure responses, so using it instead
9710		// of the default converter is kludgy but it works.
9711		converters: {
9712			"text script": function() {}
9713		},
9714		dataFilter: function( response ) {
9715			jQuery.globalEval( response, options, doc );
9716		}
9717	} );
9718};
9719
9720
9721jQuery.fn.extend( {
9722	wrapAll: function( html ) {
9723		var wrap;
9724
9725		if ( this[ 0 ] ) {
9726			if ( isFunction( html ) ) {
9727				html = html.call( this[ 0 ] );
9728			}
9729
9730			// The elements to wrap the target around
9731			wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );
9732
9733			if ( this[ 0 ].parentNode ) {
9734				wrap.insertBefore( this[ 0 ] );
9735			}
9736
9737			wrap.map( function() {
9738				var elem = this;
9739
9740				while ( elem.firstElementChild ) {
9741					elem = elem.firstElementChild;
9742				}
9743
9744				return elem;
9745			} ).append( this );
9746		}
9747
9748		return this;
9749	},
9750
9751	wrapInner: function( html ) {
9752		if ( isFunction( html ) ) {
9753			return this.each( function( i ) {
9754				jQuery( this ).wrapInner( html.call( this, i ) );
9755			} );
9756		}
9757
9758		return this.each( function() {
9759			var self = jQuery( this ),
9760				contents = self.contents();
9761
9762			if ( contents.length ) {
9763				contents.wrapAll( html );
9764
9765			} else {
9766				self.append( html );
9767			}
9768		} );
9769	},
9770
9771	wrap: function( html ) {
9772		var htmlIsFunction = isFunction( html );
9773
9774		return this.each( function( i ) {
9775			jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html );
9776		} );
9777	},
9778
9779	unwrap: function( selector ) {
9780		this.parent( selector ).not( "body" ).each( function() {
9781			jQuery( this ).replaceWith( this.childNodes );
9782		} );
9783		return this;
9784	}
9785} );
9786
9787
9788jQuery.expr.pseudos.hidden = function( elem ) {
9789	return !jQuery.expr.pseudos.visible( elem );
9790};
9791jQuery.expr.pseudos.visible = function( elem ) {
9792	return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length );
9793};
9794
9795
9796
9797
9798jQuery.ajaxSettings.xhr = function() {
9799	try {
9800		return new window.XMLHttpRequest();
9801	} catch ( e ) {}
9802};
9803
9804var xhrSuccessStatus = {
9805
9806		// File protocol always yields status code 0, assume 200
9807		0: 200,
9808
9809		// Support: IE <=9 only
9810		// trac-1450: sometimes IE returns 1223 when it should be 204
9811		1223: 204
9812	},
9813	xhrSupported = jQuery.ajaxSettings.xhr();
9814
9815support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
9816support.ajax = xhrSupported = !!xhrSupported;
9817
9818jQuery.ajaxTransport( function( options ) {
9819	var callback, errorCallback;
9820
9821	// Cross domain only allowed if supported through XMLHttpRequest
9822	if ( support.cors || xhrSupported && !options.crossDomain ) {
9823		return {
9824			send: function( headers, complete ) {
9825				var i,
9826					xhr = options.xhr();
9827
9828				xhr.open(
9829					options.type,
9830					options.url,
9831					options.async,
9832					options.username,
9833					options.password
9834				);
9835
9836				// Apply custom fields if provided
9837				if ( options.xhrFields ) {
9838					for ( i in options.xhrFields ) {
9839						xhr[ i ] = options.xhrFields[ i ];
9840					}
9841				}
9842
9843				// Override mime type if needed
9844				if ( options.mimeType && xhr.overrideMimeType ) {
9845					xhr.overrideMimeType( options.mimeType );
9846				}
9847
9848				// X-Requested-With header
9849				// For cross-domain requests, seeing as conditions for a preflight are
9850				// akin to a jigsaw puzzle, we simply never set it to be sure.
9851				// (it can always be set on a per-request basis or even using ajaxSetup)
9852				// For same-domain requests, won't change header if already provided.
9853				if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) {
9854					headers[ "X-Requested-With" ] = "XMLHttpRequest";
9855				}
9856
9857				// Set headers
9858				for ( i in headers ) {
9859					xhr.setRequestHeader( i, headers[ i ] );
9860				}
9861
9862				// Callback
9863				callback = function( type ) {
9864					return function() {
9865						if ( callback ) {
9866							callback = errorCallback = xhr.onload =
9867								xhr.onerror = xhr.onabort = xhr.ontimeout =
9868									xhr.onreadystatechange = null;
9869
9870							if ( type === "abort" ) {
9871								xhr.abort();
9872							} else if ( type === "error" ) {
9873
9874								// Support: IE <=9 only
9875								// On a manual native abort, IE9 throws
9876								// errors on any property access that is not readyState
9877								if ( typeof xhr.status !== "number" ) {
9878									complete( 0, "error" );
9879								} else {
9880									complete(
9881
9882										// File: protocol always yields status 0; see trac-8605, trac-14207
9883										xhr.status,
9884										xhr.statusText
9885									);
9886								}
9887							} else {
9888								complete(
9889									xhrSuccessStatus[ xhr.status ] || xhr.status,
9890									xhr.statusText,
9891
9892									// Support: IE <=9 only
9893									// IE9 has no XHR2 but throws on binary (trac-11426)
9894									// For XHR2 non-text, let the caller handle it (gh-2498)
9895									( xhr.responseType || "text" ) !== "text"  ||
9896									typeof xhr.responseText !== "string" ?
9897										{ binary: xhr.response } :
9898										{ text: xhr.responseText },
9899									xhr.getAllResponseHeaders()
9900								);
9901							}
9902						}
9903					};
9904				};
9905
9906				// Listen to events
9907				xhr.onload = callback();
9908				errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" );
9909
9910				// Support: IE 9 only
9911				// Use onreadystatechange to replace onabort
9912				// to handle uncaught aborts
9913				if ( xhr.onabort !== undefined ) {
9914					xhr.onabort = errorCallback;
9915				} else {
9916					xhr.onreadystatechange = function() {
9917
9918						// Check readyState before timeout as it changes
9919						if ( xhr.readyState === 4 ) {
9920
9921							// Allow onerror to be called first,
9922							// but that will not handle a native abort
9923							// Also, save errorCallback to a variable
9924							// as xhr.onerror cannot be accessed
9925							window.setTimeout( function() {
9926								if ( callback ) {
9927									errorCallback();
9928								}
9929							} );
9930						}
9931					};
9932				}
9933
9934				// Create the abort callback
9935				callback = callback( "abort" );
9936
9937				try {
9938
9939					// Do send the request (this may raise an exception)
9940					xhr.send( options.hasContent && options.data || null );
9941				} catch ( e ) {
9942
9943					// trac-14683: Only rethrow if this hasn't been notified as an error yet
9944					if ( callback ) {
9945						throw e;
9946					}
9947				}
9948			},
9949
9950			abort: function() {
9951				if ( callback ) {
9952					callback();
9953				}
9954			}
9955		};
9956	}
9957} );
9958
9959
9960
9961
9962// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432)
9963jQuery.ajaxPrefilter( function( s ) {
9964	if ( s.crossDomain ) {
9965		s.contents.script = false;
9966	}
9967} );
9968
9969// Install script dataType
9970jQuery.ajaxSetup( {
9971	accepts: {
9972		script: "text/javascript, application/javascript, " +
9973			"application/ecmascript, application/x-ecmascript"
9974	},
9975	contents: {
9976		script: /\b(?:java|ecma)script\b/
9977	},
9978	converters: {
9979		"text script": function( text ) {
9980			jQuery.globalEval( text );
9981			return text;
9982		}
9983	}
9984} );
9985
9986// Handle cache's special case and crossDomain
9987jQuery.ajaxPrefilter( "script", function( s ) {
9988	if ( s.cache === undefined ) {
9989		s.cache = false;
9990	}
9991	if ( s.crossDomain ) {
9992		s.type = "GET";
9993	}
9994} );
9995
9996// Bind script tag hack transport
9997jQuery.ajaxTransport( "script", function( s ) {
9998
9999	// This transport only deals with cross domain or forced-by-attrs requests
10000	if ( s.crossDomain || s.scriptAttrs ) {
10001		var script, callback;
10002		return {
10003			send: function( _, complete ) {
10004				script = jQuery( "<script>" )
10005					.attr( s.scriptAttrs || {} )
10006					.prop( { charset: s.scriptCharset, src: s.url } )
10007					.on( "load error", callback = function( evt ) {
10008						script.remove();
10009						callback = null;
10010						if ( evt ) {
10011							complete( evt.type === "error" ? 404 : 200, evt.type );
10012						}
10013					} );
10014
10015				// Use native DOM manipulation to avoid our domManip AJAX trickery
10016				document.head.appendChild( script[ 0 ] );
10017			},
10018			abort: function() {
10019				if ( callback ) {
10020					callback();
10021				}
10022			}
10023		};
10024	}
10025} );
10026
10027
10028
10029
10030var oldCallbacks = [],
10031	rjsonp = /(=)\?(?=&|$)|\?\?/;
10032
10033// Default jsonp settings
10034jQuery.ajaxSetup( {
10035	jsonp: "callback",
10036	jsonpCallback: function() {
10037		var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce.guid++ ) );
10038		this[ callback ] = true;
10039		return callback;
10040	}
10041} );
10042
10043// Detect, normalize options and install callbacks for jsonp requests
10044jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
10045
10046	var callbackName, overwritten, responseContainer,
10047		jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
10048			"url" :
10049			typeof s.data === "string" &&
10050				( s.contentType || "" )
10051					.indexOf( "application/x-www-form-urlencoded" ) === 0 &&
10052				rjsonp.test( s.data ) && "data"
10053		);
10054
10055	// Handle iff the expected data type is "jsonp" or we have a parameter to set
10056	if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
10057
10058		// Get callback name, remembering preexisting value associated with it
10059		callbackName = s.jsonpCallback = isFunction( s.jsonpCallback ) ?
10060			s.jsonpCallback() :
10061			s.jsonpCallback;
10062
10063		// Insert callback into url or form data
10064		if ( jsonProp ) {
10065			s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
10066		} else if ( s.jsonp !== false ) {
10067			s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
10068		}
10069
10070		// Use data converter to retrieve json after script execution
10071		s.converters[ "script json" ] = function() {
10072			if ( !responseContainer ) {
10073				jQuery.error( callbackName + " was not called" );
10074			}
10075			return responseContainer[ 0 ];
10076		};
10077
10078		// Force json dataType
10079		s.dataTypes[ 0 ] = "json";
10080
10081		// Install callback
10082		overwritten = window[ callbackName ];
10083		window[ callbackName ] = function() {
10084			responseContainer = arguments;
10085		};
10086
10087		// Clean-up function (fires after converters)
10088		jqXHR.always( function() {
10089
10090			// If previous value didn't exist - remove it
10091			if ( overwritten === undefined ) {
10092				jQuery( window ).removeProp( callbackName );
10093
10094			// Otherwise restore preexisting value
10095			} else {
10096				window[ callbackName ] = overwritten;
10097			}
10098
10099			// Save back as free
10100			if ( s[ callbackName ] ) {
10101
10102				// Make sure that re-using the options doesn't screw things around
10103				s.jsonpCallback = originalSettings.jsonpCallback;
10104
10105				// Save the callback name for future use
10106				oldCallbacks.push( callbackName );
10107			}
10108
10109			// Call if it was a function and we have a response
10110			if ( responseContainer && isFunction( overwritten ) ) {
10111				overwritten( responseContainer[ 0 ] );
10112			}
10113
10114			responseContainer = overwritten = undefined;
10115		} );
10116
10117		// Delegate to script
10118		return "script";
10119	}
10120} );
10121
10122
10123
10124
10125// Support: Safari 8 only
10126// In Safari 8 documents created via document.implementation.createHTMLDocument
10127// collapse sibling forms: the second one becomes a child of the first one.
10128// Because of that, this security measure has to be disabled in Safari 8.
10129// https://bugs.webkit.org/show_bug.cgi?id=137337
10130support.createHTMLDocument = ( function() {
10131	var body = document.implementation.createHTMLDocument( "" ).body;
10132	body.innerHTML = "<form></form><form></form>";
10133	return body.childNodes.length === 2;
10134} )();
10135
10136
10137// Argument "data" should be string of html
10138// context (optional): If specified, the fragment will be created in this context,
10139// defaults to document
10140// keepScripts (optional): If true, will include scripts passed in the html string
10141jQuery.parseHTML = function( data, context, keepScripts ) {
10142	if ( typeof data !== "string" ) {
10143		return [];
10144	}
10145	if ( typeof context === "boolean" ) {
10146		keepScripts = context;
10147		context = false;
10148	}
10149
10150	var base, parsed, scripts;
10151
10152	if ( !context ) {
10153
10154		// Stop scripts or inline event handlers from being executed immediately
10155		// by using document.implementation
10156		if ( support.createHTMLDocument ) {
10157			context = document.implementation.createHTMLDocument( "" );
10158
10159			// Set the base href for the created document
10160			// so any parsed elements with URLs
10161			// are based on the document's URL (gh-2965)
10162			base = context.createElement( "base" );
10163			base.href = document.location.href;
10164			context.head.appendChild( base );
10165		} else {
10166			context = document;
10167		}
10168	}
10169
10170	parsed = rsingleTag.exec( data );
10171	scripts = !keepScripts && [];
10172
10173	// Single tag
10174	if ( parsed ) {
10175		return [ context.createElement( parsed[ 1 ] ) ];
10176	}
10177
10178	parsed = buildFragment( [ data ], context, scripts );
10179
10180	if ( scripts && scripts.length ) {
10181		jQuery( scripts ).remove();
10182	}
10183
10184	return jQuery.merge( [], parsed.childNodes );
10185};
10186
10187
10188/**
10189 * Load a url into a page
10190 */
10191jQuery.fn.load = function( url, params, callback ) {
10192	var selector, type, response,
10193		self = this,
10194		off = url.indexOf( " " );
10195
10196	if ( off > -1 ) {
10197		selector = stripAndCollapse( url.slice( off ) );
10198		url = url.slice( 0, off );
10199	}
10200
10201	// If it's a function
10202	if ( isFunction( params ) ) {
10203
10204		// We assume that it's the callback
10205		callback = params;
10206		params = undefined;
10207
10208	// Otherwise, build a param string
10209	} else if ( params && typeof params === "object" ) {
10210		type = "POST";
10211	}
10212
10213	// If we have elements to modify, make the request
10214	if ( self.length > 0 ) {
10215		jQuery.ajax( {
10216			url: url,
10217
10218			// If "type" variable is undefined, then "GET" method will be used.
10219			// Make value of this field explicit since
10220			// user can override it through ajaxSetup method
10221			type: type || "GET",
10222			dataType: "html",
10223			data: params
10224		} ).done( function( responseText ) {
10225
10226			// Save response for use in complete callback
10227			response = arguments;
10228
10229			self.html( selector ?
10230
10231				// If a selector was specified, locate the right elements in a dummy div
10232				// Exclude scripts to avoid IE 'Permission Denied' errors
10233				jQuery( "<div>" ).append( jQuery.parseHTML( responseText ) ).find( selector ) :
10234
10235				// Otherwise use the full result
10236				responseText );
10237
10238		// If the request succeeds, this function gets "data", "status", "jqXHR"
10239		// but they are ignored because response was set above.
10240		// If it fails, this function gets "jqXHR", "status", "error"
10241		} ).always( callback && function( jqXHR, status ) {
10242			self.each( function() {
10243				callback.apply( this, response || [ jqXHR.responseText, status, jqXHR ] );
10244			} );
10245		} );
10246	}
10247
10248	return this;
10249};
10250
10251
10252
10253
10254jQuery.expr.pseudos.animated = function( elem ) {
10255	return jQuery.grep( jQuery.timers, function( fn ) {
10256		return elem === fn.elem;
10257	} ).length;
10258};
10259
10260
10261
10262
10263jQuery.offset = {
10264	setOffset: function( elem, options, i ) {
10265		var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
10266			position = jQuery.css( elem, "position" ),
10267			curElem = jQuery( elem ),
10268			props = {};
10269
10270		// Set position first, in-case top/left are set even on static elem
10271		if ( position === "static" ) {
10272			elem.style.position = "relative";
10273		}
10274
10275		curOffset = curElem.offset();
10276		curCSSTop = jQuery.css( elem, "top" );
10277		curCSSLeft = jQuery.css( elem, "left" );
10278		calculatePosition = ( position === "absolute" || position === "fixed" ) &&
10279			( curCSSTop + curCSSLeft ).indexOf( "auto" ) > -1;
10280
10281		// Need to be able to calculate position if either
10282		// top or left is auto and position is either absolute or fixed
10283		if ( calculatePosition ) {
10284			curPosition = curElem.position();
10285			curTop = curPosition.top;
10286			curLeft = curPosition.left;
10287
10288		} else {
10289			curTop = parseFloat( curCSSTop ) || 0;
10290			curLeft = parseFloat( curCSSLeft ) || 0;
10291		}
10292
10293		if ( isFunction( options ) ) {
10294
10295			// Use jQuery.extend here to allow modification of coordinates argument (gh-1848)
10296			options = options.call( elem, i, jQuery.extend( {}, curOffset ) );
10297		}
10298
10299		if ( options.top != null ) {
10300			props.top = ( options.top - curOffset.top ) + curTop;
10301		}
10302		if ( options.left != null ) {
10303			props.left = ( options.left - curOffset.left ) + curLeft;
10304		}
10305
10306		if ( "using" in options ) {
10307			options.using.call( elem, props );
10308
10309		} else {
10310			curElem.css( props );
10311		}
10312	}
10313};
10314
10315jQuery.fn.extend( {
10316
10317	// offset() relates an element's border box to the document origin
10318	offset: function( options ) {
10319
10320		// Preserve chaining for setter
10321		if ( arguments.length ) {
10322			return options === undefined ?
10323				this :
10324				this.each( function( i ) {
10325					jQuery.offset.setOffset( this, options, i );
10326				} );
10327		}
10328
10329		var rect, win,
10330			elem = this[ 0 ];
10331
10332		if ( !elem ) {
10333			return;
10334		}
10335
10336		// Return zeros for disconnected and hidden (display: none) elements (gh-2310)
10337		// Support: IE <=11 only
10338		// Running getBoundingClientRect on a
10339		// disconnected node in IE throws an error
10340		if ( !elem.getClientRects().length ) {
10341			return { top: 0, left: 0 };
10342		}
10343
10344		// Get document-relative position by adding viewport scroll to viewport-relative gBCR
10345		rect = elem.getBoundingClientRect();
10346		win = elem.ownerDocument.defaultView;
10347		return {
10348			top: rect.top + win.pageYOffset,
10349			left: rect.left + win.pageXOffset
10350		};
10351	},
10352
10353	// position() relates an element's margin box to its offset parent's padding box
10354	// This corresponds to the behavior of CSS absolute positioning
10355	position: function() {
10356		if ( !this[ 0 ] ) {
10357			return;
10358		}
10359
10360		var offsetParent, offset, doc,
10361			elem = this[ 0 ],
10362			parentOffset = { top: 0, left: 0 };
10363
10364		// position:fixed elements are offset from the viewport, which itself always has zero offset
10365		if ( jQuery.css( elem, "position" ) === "fixed" ) {
10366
10367			// Assume position:fixed implies availability of getBoundingClientRect
10368			offset = elem.getBoundingClientRect();
10369
10370		} else {
10371			offset = this.offset();
10372
10373			// Account for the *real* offset parent, which can be the document or its root element
10374			// when a statically positioned element is identified
10375			doc = elem.ownerDocument;
10376			offsetParent = elem.offsetParent || doc.documentElement;
10377			while ( offsetParent &&
10378				( offsetParent === doc.body || offsetParent === doc.documentElement ) &&
10379				jQuery.css( offsetParent, "position" ) === "static" ) {
10380
10381				offsetParent = offsetParent.parentNode;
10382			}
10383			if ( offsetParent && offsetParent !== elem && offsetParent.nodeType === 1 ) {
10384
10385				// Incorporate borders into its offset, since they are outside its content origin
10386				parentOffset = jQuery( offsetParent ).offset();
10387				parentOffset.top += jQuery.css( offsetParent, "borderTopWidth", true );
10388				parentOffset.left += jQuery.css( offsetParent, "borderLeftWidth", true );
10389			}
10390		}
10391
10392		// Subtract parent offsets and element margins
10393		return {
10394			top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
10395			left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true )
10396		};
10397	},
10398
10399	// This method will return documentElement in the following cases:
10400	// 1) For the element inside the iframe without offsetParent, this method will return
10401	//    documentElement of the parent window
10402	// 2) For the hidden or detached element
10403	// 3) For body or html element, i.e. in case of the html node - it will return itself
10404	//
10405	// but those exceptions were never presented as a real life use-cases
10406	// and might be considered as more preferable results.
10407	//
10408	// This logic, however, is not guaranteed and can change at any point in the future
10409	offsetParent: function() {
10410		return this.map( function() {
10411			var offsetParent = this.offsetParent;
10412
10413			while ( offsetParent && jQuery.css( offsetParent, "position" ) === "static" ) {
10414				offsetParent = offsetParent.offsetParent;
10415			}
10416
10417			return offsetParent || documentElement;
10418		} );
10419	}
10420} );
10421
10422// Create scrollLeft and scrollTop methods
10423jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
10424	var top = "pageYOffset" === prop;
10425
10426	jQuery.fn[ method ] = function( val ) {
10427		return access( this, function( elem, method, val ) {
10428
10429			// Coalesce documents and windows
10430			var win;
10431			if ( isWindow( elem ) ) {
10432				win = elem;
10433			} else if ( elem.nodeType === 9 ) {
10434				win = elem.defaultView;
10435			}
10436
10437			if ( val === undefined ) {
10438				return win ? win[ prop ] : elem[ method ];
10439			}
10440
10441			if ( win ) {
10442				win.scrollTo(
10443					!top ? val : win.pageXOffset,
10444					top ? val : win.pageYOffset
10445				);
10446
10447			} else {
10448				elem[ method ] = val;
10449			}
10450		}, method, val, arguments.length );
10451	};
10452} );
10453
10454// Support: Safari <=7 - 9.1, Chrome <=37 - 49
10455// Add the top/left cssHooks using jQuery.fn.position
10456// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
10457// Blink bug: https://bugs.chromium.org/p/chromium/issues/detail?id=589347
10458// getComputedStyle returns percent when specified for top/left/bottom/right;
10459// rather than make the css module depend on the offset module, just check for it here
10460jQuery.each( [ "top", "left" ], function( _i, prop ) {
10461	jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
10462		function( elem, computed ) {
10463			if ( computed ) {
10464				computed = curCSS( elem, prop );
10465
10466				// If curCSS returns percentage, fallback to offset
10467				return rnumnonpx.test( computed ) ?
10468					jQuery( elem ).position()[ prop ] + "px" :
10469					computed;
10470			}
10471		}
10472	);
10473} );
10474
10475
10476// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
10477jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
10478	jQuery.each( {
10479		padding: "inner" + name,
10480		content: type,
10481		"": "outer" + name
10482	}, function( defaultExtra, funcName ) {
10483
10484		// Margin is only for outerHeight, outerWidth
10485		jQuery.fn[ funcName ] = function( margin, value ) {
10486			var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
10487				extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
10488
10489			return access( this, function( elem, type, value ) {
10490				var doc;
10491
10492				if ( isWindow( elem ) ) {
10493
10494					// $( window ).outerWidth/Height return w/h including scrollbars (gh-1729)
10495					return funcName.indexOf( "outer" ) === 0 ?
10496						elem[ "inner" + name ] :
10497						elem.document.documentElement[ "client" + name ];
10498				}
10499
10500				// Get document width or height
10501				if ( elem.nodeType === 9 ) {
10502					doc = elem.documentElement;
10503
10504					// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],
10505					// whichever is greatest
10506					return Math.max(
10507						elem.body[ "scroll" + name ], doc[ "scroll" + name ],
10508						elem.body[ "offset" + name ], doc[ "offset" + name ],
10509						doc[ "client" + name ]
10510					);
10511				}
10512
10513				return value === undefined ?
10514
10515					// Get width or height on the element, requesting but not forcing parseFloat
10516					jQuery.css( elem, type, extra ) :
10517
10518					// Set width or height on the element
10519					jQuery.style( elem, type, value, extra );
10520			}, type, chainable ? margin : undefined, chainable );
10521		};
10522	} );
10523} );
10524
10525
10526jQuery.each( [
10527	"ajaxStart",
10528	"ajaxStop",
10529	"ajaxComplete",
10530	"ajaxError",
10531	"ajaxSuccess",
10532	"ajaxSend"
10533], function( _i, type ) {
10534	jQuery.fn[ type ] = function( fn ) {
10535		return this.on( type, fn );
10536	};
10537} );
10538
10539
10540
10541
10542jQuery.fn.extend( {
10543
10544	bind: function( types, data, fn ) {
10545		return this.on( types, null, data, fn );
10546	},
10547	unbind: function( types, fn ) {
10548		return this.off( types, null, fn );
10549	},
10550
10551	delegate: function( selector, types, data, fn ) {
10552		return this.on( types, selector, data, fn );
10553	},
10554	undelegate: function( selector, types, fn ) {
10555
10556		// ( namespace ) or ( selector, types [, fn] )
10557		return arguments.length === 1 ?
10558			this.off( selector, "**" ) :
10559			this.off( types, selector || "**", fn );
10560	},
10561
10562	hover: function( fnOver, fnOut ) {
10563		return this
10564			.on( "mouseenter", fnOver )
10565			.on( "mouseleave", fnOut || fnOver );
10566	}
10567} );
10568
10569jQuery.each(
10570	( "blur focus focusin focusout resize scroll click dblclick " +
10571	"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
10572	"change select submit keydown keypress keyup contextmenu" ).split( " " ),
10573	function( _i, name ) {
10574
10575		// Handle event binding
10576		jQuery.fn[ name ] = function( data, fn ) {
10577			return arguments.length > 0 ?
10578				this.on( name, null, data, fn ) :
10579				this.trigger( name );
10580		};
10581	}
10582);
10583
10584
10585
10586
10587// Support: Android <=4.0 only
10588// Make sure we trim BOM and NBSP
10589// Require that the "whitespace run" starts from a non-whitespace
10590// to avoid O(N^2) behavior when the engine would try matching "\s+$" at each space position.
10591var rtrim = /^[\s\uFEFF\xA0]+|([^\s\uFEFF\xA0])[\s\uFEFF\xA0]+$/g;
10592
10593// Bind a function to a context, optionally partially applying any
10594// arguments.
10595// jQuery.proxy is deprecated to promote standards (specifically Function#bind)
10596// However, it is not slated for removal any time soon
10597jQuery.proxy = function( fn, context ) {
10598	var tmp, args, proxy;
10599
10600	if ( typeof context === "string" ) {
10601		tmp = fn[ context ];
10602		context = fn;
10603		fn = tmp;
10604	}
10605
10606	// Quick check to determine if target is callable, in the spec
10607	// this throws a TypeError, but we will just return undefined.
10608	if ( !isFunction( fn ) ) {
10609		return undefined;
10610	}
10611
10612	// Simulated bind
10613	args = slice.call( arguments, 2 );
10614	proxy = function() {
10615		return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
10616	};
10617
10618	// Set the guid of unique handler to the same of original handler, so it can be removed
10619	proxy.guid = fn.guid = fn.guid || jQuery.guid++;
10620
10621	return proxy;
10622};
10623
10624jQuery.holdReady = function( hold ) {
10625	if ( hold ) {
10626		jQuery.readyWait++;
10627	} else {
10628		jQuery.ready( true );
10629	}
10630};
10631jQuery.isArray = Array.isArray;
10632jQuery.parseJSON = JSON.parse;
10633jQuery.nodeName = nodeName;
10634jQuery.isFunction = isFunction;
10635jQuery.isWindow = isWindow;
10636jQuery.camelCase = camelCase;
10637jQuery.type = toType;
10638
10639jQuery.now = Date.now;
10640
10641jQuery.isNumeric = function( obj ) {
10642
10643	// As of jQuery 3.0, isNumeric is limited to
10644	// strings and numbers (primitives or objects)
10645	// that can be coerced to finite numbers (gh-2662)
10646	var type = jQuery.type( obj );
10647	return ( type === "number" || type === "string" ) &&
10648
10649		// parseFloat NaNs numeric-cast false positives ("")
10650		// ...but misinterprets leading-number strings, particularly hex literals ("0x...")
10651		// subtraction forces infinities to NaN
10652		!isNaN( obj - parseFloat( obj ) );
10653};
10654
10655jQuery.trim = function( text ) {
10656	return text == null ?
10657		"" :
10658		( text + "" ).replace( rtrim, "$1" );
10659};
10660
10661
10662
10663// Register as a named AMD module, since jQuery can be concatenated with other
10664// files that may use define, but not via a proper concatenation script that
10665// understands anonymous AMD modules. A named AMD is safest and most robust
10666// way to register. Lowercase jquery is used because AMD module names are
10667// derived from file names, and jQuery is normally delivered in a lowercase
10668// file name. Do this after creating the global so that if an AMD module wants
10669// to call noConflict to hide this version of jQuery, it will work.
10670
10671// Note that for maximum portability, libraries that are not jQuery should
10672// declare themselves as anonymous modules, and avoid setting a global if an
10673// AMD loader is present. jQuery is a special case. For more information, see
10674// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon
10675
10676if ( typeof define === "function" && define.amd ) {
10677	define( "jquery", [], function() {
10678		return jQuery;
10679	} );
10680}
10681
10682
10683
10684
10685var
10686
10687	// Map over jQuery in case of overwrite
10688	_jQuery = window.jQuery,
10689
10690	// Map over the $ in case of overwrite
10691	_$ = window.$;
10692
10693jQuery.noConflict = function( deep ) {
10694	if ( window.$ === jQuery ) {
10695		window.$ = _$;
10696	}
10697
10698	if ( deep && window.jQuery === jQuery ) {
10699		window.jQuery = _jQuery;
10700	}
10701
10702	return jQuery;
10703};
10704
10705// Expose jQuery and $ identifiers, even in AMD
10706// (trac-7102#comment:10, https://github.com/jquery/jquery/pull/557)
10707// and CommonJS for browser emulators (trac-13566)
10708if ( typeof noGlobal === "undefined" ) {
10709	window.jQuery = window.$ = jQuery;
10710}
10711
10712
10713
10714
10715return jQuery;
10716} );
10717// To get jquery version use
10718// $.fn.jquery
10719
10720// Compatibility with legacy jquery API
10721var fn_toggle = jQuery.fn.toggle;
10722
10723jQuery.fn.extend({
10724  size: function () {
10725    return this.length;
10726  },
10727  bind: function( types, data, fn ) {
10728		return this.on( types, null, data, fn );
10729	},
10730	unbind: function( types, fn ) {
10731		return this.off( types, null, fn );
10732	},
10733	live: function( types, data, fn ) {
10734		jQuery(this.context).on(types, this.selector, data, fn );
10735		return this;
10736	},
10737	die: function( types, fn ) {
10738		jQuery(this.context).off( types, this.selector || "**", fn );
10739		return this;
10740	},
10741	error: function( msg ) {
10742		throw new Error( msg );
10743	},
10744  __eventsToggle: function( fn ) {
10745		// Save reference to arguments for access in closure
10746		var args = arguments,
10747			guid = fn.guid || jQuery.guid++,
10748			i = 0,
10749			toggler = function( event ) {
10750				// Figure out which function to execute
10751				var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i;
10752				jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 );
10753
10754				// Make sure that clicks stop
10755				event.preventDefault();
10756
10757				// and execute the function
10758				return args[ lastToggle ].apply( this, arguments ) || false;
10759			};
10760
10761		// link all the functions, so any of them can unbind this click handler
10762		toggler.guid = guid;
10763		while ( i < args.length ) {
10764			args[ i++ ].guid = guid;
10765		}
10766
10767		return this.click( toggler );
10768	},
10769  toggle: function( state, fn2 ) {
10770   
10771    if ( jQuery.isFunction( state ) && jQuery.isFunction( fn2 ) ) {
vendor: 6,279 bytes, lines 10772-10966
10772      // EventsToggle was deprecated in 1.8 and removed in 1.9
10773      return jQuery.fn.__eventsToggle.apply( this, arguments );
10774    }
10775  
10776    return fn_toggle.apply(this, arguments);
10777  }
10778});
10779
10780// jquery addSelf
10781jQuery.fn.andSelf = jQuery.fn.addBack;
10782
10783// jquery.browser
10784(function() {
10785
10786  var matched, browser;
10787
10788  // Use of jQuery.browser is frowned upon.
10789  // More details: http://api.jquery.com/jQuery.browser
10790  // jQuery.uaMatch maintained for back-compat
10791  jQuery.uaMatch = function( ua ) {
10792    ua = ua.toLowerCase();
10793  
10794    var match = /(chrome)[ \/]([\w.]+)/.exec( ua ) ||
10795      /(webkit)[ \/]([\w.]+)/.exec( ua ) ||
10796      /(opera)(?:.*version|)[ \/]([\w.]+)/.exec( ua ) ||
10797      /(msie) ([\w.]+)/.exec( ua ) ||
10798      ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec( ua ) ||
10799      [];
10800  
10801    return {
10802      browser: match[ 1 ] || "",
10803      version: match[ 2 ] || "0"
10804    };
10805  };
10806  
10807  matched = jQuery.uaMatch( navigator.userAgent );
10808  browser = {};
10809  
10810  if ( matched.browser ) {
10811    browser[ matched.browser ] = true;
10812    browser.version = matched.version;
10813  }
10814  
10815  // Chrome is Webkit, but Webkit is also Safari.
10816  if ( browser.chrome ) {
10817    browser.webkit = true;
10818  } else if ( browser.webkit ) {
10819    browser.safari = true;
10820  }
10821  
10822  jQuery.browser = browser;
10823
10824})();
10825/*! jQuery UI - v1.13.2 - 2022-07-14
10826* http://jqueryui.com
10827* 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
10828* Copyright jQuery Foundation and other contributors; Licensed MIT */
10829
10830( function( factory ) {
10831	"use strict";
10832	
10833	if ( typeof define === "function" && define.amd ) {
10834
10835		// AMD. Register as an anonymous module.
10836		define( [ "jquery" ], factory );
10837	} else {
10838
10839		// Browser globals
10840		factory( jQuery );
10841	}
10842} )( function( $ ) {
10843"use strict";
10844
10845$.ui = $.ui || {};
10846
10847var version = $.ui.version = "1.13.2";
10848
10849
10850/*!
10851 * jQuery UI Widget 1.13.2
10852 * http://jqueryui.com
10853 *
10854 * Copyright jQuery Foundation and other contributors
10855 * Released under the MIT license.
10856 * http://jquery.org/license
10857 */
10858
10859//>>label: Widget
10860//>>group: Core
10861//>>description: Provides a factory for creating stateful widgets with a common API.
10862//>>docs: http://api.jqueryui.com/jQuery.widget/
10863//>>demos: http://jqueryui.com/widget/
10864
10865
10866var widgetUuid = 0;
10867var widgetHasOwnProperty = Array.prototype.hasOwnProperty;
10868var widgetSlice = Array.prototype.slice;
10869
10870$.cleanData = ( function( orig ) {
10871	return function( elems ) {
10872		var events, elem, i;
10873		for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) {
10874
10875			// Only trigger remove when necessary to save time
10876			events = $._data( elem, "events" );
10877			if ( events && events.remove ) {
10878				$( elem ).triggerHandler( "remove" );
10879			}
10880		}
10881		orig( elems );
10882	};
10883} )( $.cleanData );
10884
10885$.widget = function( name, base, prototype ) {
10886	var existingConstructor, constructor, basePrototype;
10887
10888	// ProxiedPrototype allows the provided prototype to remain unmodified
10889	// so that it can be used as a mixin for multiple widgets (#8876)
10890	var proxiedPrototype = {};
10891
10892	var namespace = name.split( "." )[ 0 ];
10893	name = name.split( "." )[ 1 ];
10894	var fullName = namespace + "-" + name;
10895
10896	if ( !prototype ) {
10897		prototype = base;
10898		base = $.Widget;
10899	}
10900
10901	if ( Array.isArray( prototype ) ) {
10902		prototype = $.extend.apply( null, [ {} ].concat( prototype ) );
10903	}
10904
10905	// Create selector for plugin
10906	$.expr.pseudos[ fullName.toLowerCase() ] = function( elem ) {
10907		return !!$.data( elem, fullName );
10908	};
10909
10910	$[ namespace ] = $[ namespace ] || {};
10911	existingConstructor = $[ namespace ][ name ];
10912	constructor = $[ namespace ][ name ] = function( options, element ) {
10913
10914		// Allow instantiation without "new" keyword
10915		if ( !this || !this._createWidget ) {
10916			return new constructor( options, element );
10917		}
10918
10919		// Allow instantiation without initializing for simple inheritance
10920		// must use "new" keyword (the code above always passes args)
10921		if ( arguments.length ) {
10922			this._createWidget( options, element );
10923		}
10924	};
10925
10926	// Extend with the existing constructor to carry over any static properties
10927	$.extend( constructor, existingConstructor, {
10928		version: prototype.version,
10929
10930		// Copy the object used to create the prototype in case we need to
10931		// redefine the widget later
10932		_proto: $.extend( {}, prototype ),
10933
10934		// Track widgets that inherit from this widget in case this widget is
10935		// redefined after a widget inherits from it
10936		_childConstructors: []
10937	} );
10938
10939	basePrototype = new base();
10940
10941	// We need to make the options hash a property directly on the new instance
10942	// otherwise we'll modify the options hash on the prototype that we're
10943	// inheriting from
10944	basePrototype.options = $.widget.extend( {}, basePrototype.options );
10945	$.each( prototype, function( prop, value ) {
10946		if ( typeof value !== "function" ) {
10947			proxiedPrototype[ prop ] = value;
10948			return;
10949		}
10950		proxiedPrototype[ prop ] = ( function() {
10951			function _super() {
10952				return base.prototype[ prop ].apply( this, arguments );
10953			}
10954
10955			function _superApply( args ) {
10956				return base.prototype[ prop ].apply( this, args );
10957			}
10958
10959			return function() {
10960				var __super = this._super;
10961				var __superApply = this._superApply;
10962				var returnValue;
10963
10964				this._super = _super;
10965				this._superApply = _superApply;
10966
vendor: 32,706 bytes, lines 10967-12091
10967				returnValue = value.apply( this, arguments );
10968
10969				this._super = __super;
10970				this._superApply = __superApply;
10971
10972				return returnValue;
10973			};
10974		} )();
10975	} );
10976	constructor.prototype = $.widget.extend( basePrototype, {
10977
10978		// TODO: remove support for widgetEventPrefix
10979		// always use the name + a colon as the prefix, e.g., draggable:start
10980		// don't prefix for widgets that aren't DOM-based
10981		widgetEventPrefix: existingConstructor ? ( basePrototype.widgetEventPrefix || name ) : name
10982	}, proxiedPrototype, {
10983		constructor: constructor,
10984		namespace: namespace,
10985		widgetName: name,
10986		widgetFullName: fullName
10987	} );
10988
10989	// If this widget is being redefined then we need to find all widgets that
10990	// are inheriting from it and redefine all of them so that they inherit from
10991	// the new version of this widget. We're essentially trying to replace one
10992	// level in the prototype chain.
10993	if ( existingConstructor ) {
10994		$.each( existingConstructor._childConstructors, function( i, child ) {
10995			var childPrototype = child.prototype;
10996
10997			// Redefine the child widget using the same prototype that was
10998			// originally used, but inherit from the new version of the base
10999			$.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor,
11000				child._proto );
11001		} );
11002
11003		// Remove the list of existing child constructors from the old constructor
11004		// so the old child constructors can be garbage collected
11005		delete existingConstructor._childConstructors;
11006	} else {
11007		base._childConstructors.push( constructor );
11008	}
11009
11010	$.widget.bridge( name, constructor );
11011
11012	return constructor;
11013};
11014
11015$.widget.extend = function( target ) {
11016	var input = widgetSlice.call( arguments, 1 );
11017	var inputIndex = 0;
11018	var inputLength = input.length;
11019	var key;
11020	var value;
11021
11022	for ( ; inputIndex < inputLength; inputIndex++ ) {
11023		for ( key in input[ inputIndex ] ) {
11024			value = input[ inputIndex ][ key ];
11025			if ( widgetHasOwnProperty.call( input[ inputIndex ], key ) && value !== undefined ) {
11026
11027				// Clone objects
11028				if ( $.isPlainObject( value ) ) {
11029					target[ key ] = $.isPlainObject( target[ key ] ) ?
11030						$.widget.extend( {}, target[ key ], value ) :
11031
11032						// Don't extend strings, arrays, etc. with objects
11033						$.widget.extend( {}, value );
11034
11035				// Copy everything else by reference
11036				} else {
11037					target[ key ] = value;
11038				}
11039			}
11040		}
11041	}
11042	return target;
11043};
11044
11045$.widget.bridge = function( name, object ) {
11046	var fullName = object.prototype.widgetFullName || name;
11047	$.fn[ name ] = function( options ) {
11048		var isMethodCall = typeof options === "string";
11049		var args = widgetSlice.call( arguments, 1 );
11050		var returnValue = this;
11051
11052		if ( isMethodCall ) {
11053
11054			// If this is an empty collection, we need to have the instance method
11055			// return undefined instead of the jQuery instance
11056			if ( !this.length && options === "instance" ) {
11057				returnValue = undefined;
11058			} else {
11059				this.each( function() {
11060					var methodValue;
11061					var instance = $.data( this, fullName );
11062
11063					if ( options === "instance" ) {
11064						returnValue = instance;
11065						return false;
11066					}
11067
11068					if ( !instance ) {
11069						return $.error( "cannot call methods on " + name +
11070							" prior to initialization; " +
11071							"attempted to call method '" + options + "'" );
11072					}
11073
11074					if ( typeof instance[ options ] !== "function" ||
11075						options.charAt( 0 ) === "_" ) {
11076						return $.error( "no such method '" + options + "' for " + name +
11077							" widget instance" );
11078					}
11079
11080					methodValue = instance[ options ].apply( instance, args );
11081
11082					if ( methodValue !== instance && methodValue !== undefined ) {
11083						returnValue = methodValue && methodValue.jquery ?
11084							returnValue.pushStack( methodValue.get() ) :
11085							methodValue;
11086						return false;
11087					}
11088				} );
11089			}
11090		} else {
11091
11092			// Allow multiple hashes to be passed on init
11093			if ( args.length ) {
11094				options = $.widget.extend.apply( null, [ options ].concat( args ) );
11095			}
11096
11097			this.each( function() {
11098				var instance = $.data( this, fullName );
11099				if ( instance ) {
11100					instance.option( options || {} );
11101					if ( instance._init ) {
11102						instance._init();
11103					}
11104				} else {
11105					$.data( this, fullName, new object( options, this ) );
11106				}
11107			} );
11108		}
11109
11110		return returnValue;
11111	};
11112};
11113
11114$.Widget = function( /* options, element */ ) {};
11115$.Widget._childConstructors = [];
11116
11117$.Widget.prototype = {
11118	widgetName: "widget",
11119	widgetEventPrefix: "",
11120	defaultElement: "<div>",
11121
11122	options: {
11123		classes: {},
11124		disabled: false,
11125
11126		// Callbacks
11127		create: null
11128	},
11129
11130	_createWidget: function( options, element ) {
11131		element = $( element || this.defaultElement || this )[ 0 ];
11132		this.element = $( element );
11133		this.uuid = widgetUuid++;
11134		this.eventNamespace = "." + this.widgetName + this.uuid;
11135
11136		this.bindings = $();
11137		this.hoverable = $();
11138		this.focusable = $();
11139		this.classesElementLookup = {};
11140
11141		if ( element !== this ) {
11142			$.data( element, this.widgetFullName, this );
11143			this._on( true, this.element, {
11144				remove: function( event ) {
11145					if ( event.target === element ) {
11146						this.destroy();
11147					}
11148				}
11149			} );
11150			this.document = $( element.style ?
11151
11152				// Element within the document
11153				element.ownerDocument :
11154
11155				// Element is window or document
11156				element.document || element );
11157			this.window = $( this.document[ 0 ].defaultView || this.document[ 0 ].parentWindow );
11158		}
11159
11160		this.options = $.widget.extend( {},
11161			this.options,
11162			this._getCreateOptions(),
11163			options );
11164
11165		this._create();
11166
11167		if ( this.options.disabled ) {
11168			this._setOptionDisabled( this.options.disabled );
11169		}
11170
11171		this._trigger( "create", null, this._getCreateEventData() );
11172		this._init();
11173	},
11174
11175	_getCreateOptions: function() {
11176		return {};
11177	},
11178
11179	_getCreateEventData: $.noop,
11180
11181	_create: $.noop,
11182
11183	_init: $.noop,
11184
11185	destroy: function() {
11186		var that = this;
11187
11188		this._destroy();
11189		$.each( this.classesElementLookup, function( key, value ) {
11190			that._removeClass( value, key );
11191		} );
11192
11193		// We can probably remove the unbind calls in 2.0
11194		// all event bindings should go through this._on()
11195		this.element
11196			.off( this.eventNamespace )
11197			.removeData( this.widgetFullName );
11198		this.widget()
11199			.off( this.eventNamespace )
11200			.removeAttr( "aria-disabled" );
11201
11202		// Clean up events and states
11203		this.bindings.off( this.eventNamespace );
11204	},
11205
11206	_destroy: $.noop,
11207
11208	widget: function() {
11209		return this.element;
11210	},
11211
11212	option: function( key, value ) {
11213		var options = key;
11214		var parts;
11215		var curOption;
11216		var i;
11217
11218		if ( arguments.length === 0 ) {
11219
11220			// Don't return a reference to the internal hash
11221			return $.widget.extend( {}, this.options );
11222		}
11223
11224		if ( typeof key === "string" ) {
11225
11226			// Handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
11227			options = {};
11228			parts = key.split( "." );
11229			key = parts.shift();
11230			if ( parts.length ) {
11231				curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
11232				for ( i = 0; i < parts.length - 1; i++ ) {
11233					curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
11234					curOption = curOption[ parts[ i ] ];
11235				}
11236				key = parts.pop();
11237				if ( arguments.length === 1 ) {
11238					return curOption[ key ] === undefined ? null : curOption[ key ];
11239				}
11240				curOption[ key ] = value;
11241			} else {
11242				if ( arguments.length === 1 ) {
11243					return this.options[ key ] === undefined ? null : this.options[ key ];
11244				}
11245				options[ key ] = value;
11246			}
11247		}
11248
11249		this._setOptions( options );
11250
11251		return this;
11252	},
11253
11254	_setOptions: function( options ) {
11255		var key;
11256
11257		for ( key in options ) {
11258			this._setOption( key, options[ key ] );
11259		}
11260
11261		return this;
11262	},
11263
11264	_setOption: function( key, value ) {
11265		if ( key === "classes" ) {
11266			this._setOptionClasses( value );
11267		}
11268
11269		this.options[ key ] = value;
11270
11271		if ( key === "disabled" ) {
11272			this._setOptionDisabled( value );
11273		}
11274
11275		return this;
11276	},
11277
11278	_setOptionClasses: function( value ) {
11279		var classKey, elements, currentElements;
11280
11281		for ( classKey in value ) {
11282			currentElements = this.classesElementLookup[ classKey ];
11283			if ( value[ classKey ] === this.options.classes[ classKey ] ||
11284					!currentElements ||
11285					!currentElements.length ) {
11286				continue;
11287			}
11288
11289			// We are doing this to create a new jQuery object because the _removeClass() call
11290			// on the next line is going to destroy the reference to the current elements being
11291			// tracked. We need to save a copy of this collection so that we can add the new classes
11292			// below.
11293			elements = $( currentElements.get() );
11294			this._removeClass( currentElements, classKey );
11295
11296			// We don't use _addClass() here, because that uses this.options.classes
11297			// for generating the string of classes. We want to use the value passed in from
11298			// _setOption(), this is the new value of the classes option which was passed to
11299			// _setOption(). We pass this value directly to _classes().
11300			elements.addClass( this._classes( {
11301				element: elements,
11302				keys: classKey,
11303				classes: value,
11304				add: true
11305			} ) );
11306		}
11307	},
11308
11309	_setOptionDisabled: function( value ) {
11310		this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, !!value );
11311
11312		// If the widget is becoming disabled, then nothing is interactive
11313		if ( value ) {
11314			this._removeClass( this.hoverable, null, "ui-state-hover" );
11315			this._removeClass( this.focusable, null, "ui-state-focus" );
11316		}
11317	},
11318
11319	enable: function() {
11320		return this._setOptions( { disabled: false } );
11321	},
11322
11323	disable: function() {
11324		return this._setOptions( { disabled: true } );
11325	},
11326
11327	_classes: function( options ) {
11328		var full = [];
11329		var that = this;
11330
11331		options = $.extend( {
11332			element: this.element,
11333			classes: this.options.classes || {}
11334		}, options );
11335
11336		function bindRemoveEvent() {
11337			var nodesToBind = [];
11338
11339			options.element.each( function( _, element ) {
11340				var isTracked = $.map( that.classesElementLookup, function( elements ) {
11341					return elements;
11342				} )
11343					.some( function( elements ) {
11344						return elements.is( element );
11345					} );
11346
11347				if ( !isTracked ) {
11348					nodesToBind.push( element );
11349				}
11350			} );
11351
11352			that._on( $( nodesToBind ), {
11353				remove: "_untrackClassesElement"
11354			} );
11355		}
11356
11357		function processClassString( classes, checkOption ) {
11358			var current, i;
11359			for ( i = 0; i < classes.length; i++ ) {
11360				current = that.classesElementLookup[ classes[ i ] ] || $();
11361				if ( options.add ) {
11362					bindRemoveEvent();
11363					current = $( $.uniqueSort( current.get().concat( options.element.get() ) ) );
11364				} else {
11365					current = $( current.not( options.element ).get() );
11366				}
11367				that.classesElementLookup[ classes[ i ] ] = current;
11368				full.push( classes[ i ] );
11369				if ( checkOption && options.classes[ classes[ i ] ] ) {
11370					full.push( options.classes[ classes[ i ] ] );
11371				}
11372			}
11373		}
11374
11375		if ( options.keys ) {
11376			processClassString( options.keys.match( /\S+/g ) || [], true );
11377		}
11378		if ( options.extra ) {
11379			processClassString( options.extra.match( /\S+/g ) || [] );
11380		}
11381
11382		return full.join( " " );
11383	},
11384
11385	_untrackClassesElement: function( event ) {
11386		var that = this;
11387		$.each( that.classesElementLookup, function( key, value ) {
11388			if ( $.inArray( event.target, value ) !== -1 ) {
11389				that.classesElementLookup[ key ] = $( value.not( event.target ).get() );
11390			}
11391		} );
11392
11393		this._off( $( event.target ) );
11394	},
11395
11396	_removeClass: function( element, keys, extra ) {
11397		return this._toggleClass( element, keys, extra, false );
11398	},
11399
11400	_addClass: function( element, keys, extra ) {
11401		return this._toggleClass( element, keys, extra, true );
11402	},
11403
11404	_toggleClass: function( element, keys, extra, add ) {
11405		add = ( typeof add === "boolean" ) ? add : extra;
11406		var shift = ( typeof element === "string" || element === null ),
11407			options = {
11408				extra: shift ? keys : extra,
11409				keys: shift ? element : keys,
11410				element: shift ? this.element : element,
11411				add: add
11412			};
11413		options.element.toggleClass( this._classes( options ), add );
11414		return this;
11415	},
11416
11417	_on: function( suppressDisabledCheck, element, handlers ) {
11418		var delegateElement;
11419		var instance = this;
11420
11421		// No suppressDisabledCheck flag, shuffle arguments
11422		if ( typeof suppressDisabledCheck !== "boolean" ) {
11423			handlers = element;
11424			element = suppressDisabledCheck;
11425			suppressDisabledCheck = false;
11426		}
11427
11428		// No element argument, shuffle and use this.element
11429		if ( !handlers ) {
11430			handlers = element;
11431			element = this.element;
11432			delegateElement = this.widget();
11433		} else {
11434			element = delegateElement = $( element );
11435			this.bindings = this.bindings.add( element );
11436		}
11437
11438		$.each( handlers, function( event, handler ) {
11439			function handlerProxy() {
11440
11441				// Allow widgets to customize the disabled handling
11442				// - disabled as an array instead of boolean
11443				// - disabled class as method for disabling individual parts
11444				if ( !suppressDisabledCheck &&
11445						( instance.options.disabled === true ||
11446						$( this ).hasClass( "ui-state-disabled" ) ) ) {
11447					return;
11448				}
11449				return ( typeof handler === "string" ? instance[ handler ] : handler )
11450					.apply( instance, arguments );
11451			}
11452
11453			// Copy the guid so direct unbinding works
11454			if ( typeof handler !== "string" ) {
11455				handlerProxy.guid = handler.guid =
11456					handler.guid || handlerProxy.guid || $.guid++;
11457			}
11458
11459			var match = event.match( /^([\w:-]*)\s*(.*)$/ );
11460			var eventName = match[ 1 ] + instance.eventNamespace;
11461			var selector = match[ 2 ];
11462
11463			if ( selector ) {
11464				delegateElement.on( eventName, selector, handlerProxy );
11465			} else {
11466				element.on( eventName, handlerProxy );
11467			}
11468		} );
11469	},
11470
11471	_off: function( element, eventName ) {
11472		eventName = ( eventName || "" ).split( " " ).join( this.eventNamespace + " " ) +
11473			this.eventNamespace;
11474		element.off( eventName );
11475
11476		// Clear the stack to avoid memory leaks (#10056)
11477		this.bindings = $( this.bindings.not( element ).get() );
11478		this.focusable = $( this.focusable.not( element ).get() );
11479		this.hoverable = $( this.hoverable.not( element ).get() );
11480	},
11481
11482	_delay: function( handler, delay ) {
11483		function handlerProxy() {
11484			return ( typeof handler === "string" ? instance[ handler ] : handler )
11485				.apply( instance, arguments );
11486		}
11487		var instance = this;
11488		return setTimeout( handlerProxy, delay || 0 );
11489	},
11490
11491	_hoverable: function( element ) {
11492		this.hoverable = this.hoverable.add( element );
11493		this._on( element, {
11494			mouseenter: function( event ) {
11495				this._addClass( $( event.currentTarget ), null, "ui-state-hover" );
11496			},
11497			mouseleave: function( event ) {
11498				this._removeClass( $( event.currentTarget ), null, "ui-state-hover" );
11499			}
11500		} );
11501	},
11502
11503	_focusable: function( element ) {
11504		this.focusable = this.focusable.add( element );
11505		this._on( element, {
11506			focusin: function( event ) {
11507				this._addClass( $( event.currentTarget ), null, "ui-state-focus" );
11508			},
11509			focusout: function( event ) {
11510				this._removeClass( $( event.currentTarget ), null, "ui-state-focus" );
11511			}
11512		} );
11513	},
11514
11515	_trigger: function( type, event, data ) {
11516		var prop, orig;
11517		var callback = this.options[ type ];
11518
11519		data = data || {};
11520		event = $.Event( event );
11521		event.type = ( type === this.widgetEventPrefix ?
11522			type :
11523			this.widgetEventPrefix + type ).toLowerCase();
11524
11525		// The original event may come from any element
11526		// so we need to reset the target on the new event
11527		event.target = this.element[ 0 ];
11528
11529		// Copy original event properties over to the new event
11530		orig = event.originalEvent;
11531		if ( orig ) {
11532			for ( prop in orig ) {
11533				if ( !( prop in event ) ) {
11534					event[ prop ] = orig[ prop ];
11535				}
11536			}
11537		}
11538
11539		this.element.trigger( event, data );
11540		return !( typeof callback === "function" &&
11541			callback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false ||
11542			event.isDefaultPrevented() );
11543	}
11544};
11545
11546$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
11547	$.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
11548		if ( typeof options === "string" ) {
11549			options = { effect: options };
11550		}
11551
11552		var hasOptions;
11553		var effectName = !options ?
11554			method :
11555			options === true || typeof options === "number" ?
11556				defaultEffect :
11557				options.effect || defaultEffect;
11558
11559		options = options || {};
11560		if ( typeof options === "number" ) {
11561			options = { duration: options };
11562		} else if ( options === true ) {
11563			options = {};
11564		}
11565
11566		hasOptions = !$.isEmptyObject( options );
11567		options.complete = callback;
11568
11569		if ( options.delay ) {
11570			element.delay( options.delay );
11571		}
11572
11573		if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
11574			element[ method ]( options );
11575		} else if ( effectName !== method && element[ effectName ] ) {
11576			element[ effectName ]( options.duration, options.easing, callback );
11577		} else {
11578			element.queue( function( next ) {
11579				$( this )[ method ]();
11580				if ( callback ) {
11581					callback.call( element[ 0 ] );
11582				}
11583				next();
11584			} );
11585		}
11586	};
11587} );
11588
11589var widget = $.widget;
11590
11591
11592/*!
11593 * jQuery UI Position 1.13.2
11594 * http://jqueryui.com
11595 *
11596 * Copyright jQuery Foundation and other contributors
11597 * Released under the MIT license.
11598 * http://jquery.org/license
11599 *
11600 * http://api.jqueryui.com/position/
11601 */
11602
11603//>>label: Position
11604//>>group: Core
11605//>>description: Positions elements relative to other elements.
11606//>>docs: http://api.jqueryui.com/position/
11607//>>demos: http://jqueryui.com/position/
11608
11609
11610( function() {
11611var cachedScrollbarWidth,
11612	max = Math.max,
11613	abs = Math.abs,
11614	rhorizontal = /left|center|right/,
11615	rvertical = /top|center|bottom/,
11616	roffset = /[\+\-]\d+(\.[\d]+)?%?/,
11617	rposition = /^\w+/,
11618	rpercent = /%$/,
11619	_position = $.fn.position;
11620
11621function getOffsets( offsets, width, height ) {
11622	return [
11623		parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
11624		parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
11625	];
11626}
11627
11628function parseCss( element, property ) {
11629	return parseInt( $.css( element, property ), 10 ) || 0;
11630}
11631
11632function isWindow( obj ) {
11633	return obj != null && obj === obj.window;
11634}
11635
11636function getDimensions( elem ) {
11637	var raw = elem[ 0 ];
11638	if ( raw.nodeType === 9 ) {
11639		return {
11640			width: elem.width(),
11641			height: elem.height(),
11642			offset: { top: 0, left: 0 }
11643		};
11644	}
11645	if ( isWindow( raw ) ) {
11646		return {
11647			width: elem.width(),
11648			height: elem.height(),
11649			offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
11650		};
11651	}
11652	if ( raw.preventDefault ) {
11653		return {
11654			width: 0,
11655			height: 0,
11656			offset: { top: raw.pageY, left: raw.pageX }
11657		};
11658	}
11659	return {
11660		width: elem.outerWidth(),
11661		height: elem.outerHeight(),
11662		offset: elem.offset()
11663	};
11664}
11665
11666$.position = {
11667	scrollbarWidth: function() {
11668		if ( cachedScrollbarWidth !== undefined ) {
11669			return cachedScrollbarWidth;
11670		}
11671		var w1, w2,
11672			div = $( "<div style=" +
11673				"'display:block;position:absolute;width:200px;height:200px;overflow:hidden;'>" +
11674				"<div style='height:300px;width:auto;'></div></div>" ),
11675			innerDiv = div.children()[ 0 ];
11676
11677		$( "body" ).append( div );
11678		w1 = innerDiv.offsetWidth;
11679		div.css( "overflow", "scroll" );
11680
11681		w2 = innerDiv.offsetWidth;
11682
11683		if ( w1 === w2 ) {
11684			w2 = div[ 0 ].clientWidth;
11685		}
11686
11687		div.remove();
11688
11689		return ( cachedScrollbarWidth = w1 - w2 );
11690	},
11691	getScrollInfo: function( within ) {
11692		var overflowX = within.isWindow || within.isDocument ? "" :
11693				within.element.css( "overflow-x" ),
11694			overflowY = within.isWindow || within.isDocument ? "" :
11695				within.element.css( "overflow-y" ),
11696			hasOverflowX = overflowX === "scroll" ||
11697				( overflowX === "auto" && within.width < within.element[ 0 ].scrollWidth ),
11698			hasOverflowY = overflowY === "scroll" ||
11699				( overflowY === "auto" && within.height < within.element[ 0 ].scrollHeight );
11700		return {
11701			width: hasOverflowY ? $.position.scrollbarWidth() : 0,
11702			height: hasOverflowX ? $.position.scrollbarWidth() : 0
11703		};
11704	},
11705	getWithinInfo: function( element ) {
11706		var withinElement = $( element || window ),
11707			isElemWindow = isWindow( withinElement[ 0 ] ),
11708			isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9,
11709			hasOffset = !isElemWindow && !isDocument;
11710		return {
11711			element: withinElement,
11712			isWindow: isElemWindow,
11713			isDocument: isDocument,
11714			offset: hasOffset ? $( element ).offset() : { left: 0, top: 0 },
11715			scrollLeft: withinElement.scrollLeft(),
11716			scrollTop: withinElement.scrollTop(),
11717			width: withinElement.outerWidth(),
11718			height: withinElement.outerHeight()
11719		};
11720	}
11721};
11722
11723$.fn.position = function( options ) {
11724	if ( !options || !options.of ) {
11725		return _position.apply( this, arguments );
11726	}
11727
11728	// Make a copy, we don't want to modify arguments
11729	options = $.extend( {}, options );
11730
11731	var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
11732
11733		// Make sure string options are treated as CSS selectors
11734		target = typeof options.of === "string" ?
11735			$( document ).find( options.of ) :
11736			$( options.of ),
11737
11738		within = $.position.getWithinInfo( options.within ),
11739		scrollInfo = $.position.getScrollInfo( within ),
11740		collision = ( options.collision || "flip" ).split( " " ),
11741		offsets = {};
11742
11743	dimensions = getDimensions( target );
11744	if ( target[ 0 ].preventDefault ) {
11745
11746		// Force left top to allow flipping
11747		options.at = "left top";
11748	}
11749	targetWidth = dimensions.width;
11750	targetHeight = dimensions.height;
11751	targetOffset = dimensions.offset;
11752
11753	// Clone to reuse original targetOffset later
11754	basePosition = $.extend( {}, targetOffset );
11755
11756	// Force my and at to have valid horizontal and vertical positions
11757	// if a value is missing or invalid, it will be converted to center
11758	$.each( [ "my", "at" ], function() {
11759		var pos = ( options[ this ] || "" ).split( " " ),
11760			horizontalOffset,
11761			verticalOffset;
11762
11763		if ( pos.length === 1 ) {
11764			pos = rhorizontal.test( pos[ 0 ] ) ?
11765				pos.concat( [ "center" ] ) :
11766				rvertical.test( pos[ 0 ] ) ?
11767					[ "center" ].concat( pos ) :
11768					[ "center", "center" ];
11769		}
11770		pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
11771		pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
11772
11773		// Calculate offsets
11774		horizontalOffset = roffset.exec( pos[ 0 ] );
11775		verticalOffset = roffset.exec( pos[ 1 ] );
11776		offsets[ this ] = [
11777			horizontalOffset ? horizontalOffset[ 0 ] : 0,
11778			verticalOffset ? verticalOffset[ 0 ] : 0
11779		];
11780
11781		// Reduce to just the positions without the offsets
11782		options[ this ] = [
11783			rposition.exec( pos[ 0 ] )[ 0 ],
11784			rposition.exec( pos[ 1 ] )[ 0 ]
11785		];
11786	} );
11787
11788	// Normalize collision option
11789	if ( collision.length === 1 ) {
11790		collision[ 1 ] = collision[ 0 ];
11791	}
11792
11793	if ( options.at[ 0 ] === "right" ) {
11794		basePosition.left += targetWidth;
11795	} else if ( options.at[ 0 ] === "center" ) {
11796		basePosition.left += targetWidth / 2;
11797	}
11798
11799	if ( options.at[ 1 ] === "bottom" ) {
11800		basePosition.top += targetHeight;
11801	} else if ( options.at[ 1 ] === "center" ) {
11802		basePosition.top += targetHeight / 2;
11803	}
11804
11805	atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
11806	basePosition.left += atOffset[ 0 ];
11807	basePosition.top += atOffset[ 1 ];
11808
11809	return this.each( function() {
11810		var collisionPosition, using,
11811			elem = $( this ),
11812			elemWidth = elem.outerWidth(),
11813			elemHeight = elem.outerHeight(),
11814			marginLeft = parseCss( this, "marginLeft" ),
11815			marginTop = parseCss( this, "marginTop" ),
11816			collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) +
11817				scrollInfo.width,
11818			collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) +
11819				scrollInfo.height,
11820			position = $.extend( {}, basePosition ),
11821			myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
11822
11823		if ( options.my[ 0 ] === "right" ) {
11824			position.left -= elemWidth;
11825		} else if ( options.my[ 0 ] === "center" ) {
11826			position.left -= elemWidth / 2;
11827		}
11828
11829		if ( options.my[ 1 ] === "bottom" ) {
11830			position.top -= elemHeight;
11831		} else if ( options.my[ 1 ] === "center" ) {
11832			position.top -= elemHeight / 2;
11833		}
11834
11835		position.left += myOffset[ 0 ];
11836		position.top += myOffset[ 1 ];
11837
11838		collisionPosition = {
11839			marginLeft: marginLeft,
11840			marginTop: marginTop
11841		};
11842
11843		$.each( [ "left", "top" ], function( i, dir ) {
11844			if ( $.ui.position[ collision[ i ] ] ) {
11845				$.ui.position[ collision[ i ] ][ dir ]( position, {
11846					targetWidth: targetWidth,
11847					targetHeight: targetHeight,
11848					elemWidth: elemWidth,
11849					elemHeight: elemHeight,
11850					collisionPosition: collisionPosition,
11851					collisionWidth: collisionWidth,
11852					collisionHeight: collisionHeight,
11853					offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
11854					my: options.my,
11855					at: options.at,
11856					within: within,
11857					elem: elem
11858				} );
11859			}
11860		} );
11861
11862		if ( options.using ) {
11863
11864			// Adds feedback as second argument to using callback, if present
11865			using = function( props ) {
11866				var left = targetOffset.left - position.left,
11867					right = left + targetWidth - elemWidth,
11868					top = targetOffset.top - position.top,
11869					bottom = top + targetHeight - elemHeight,
11870					feedback = {
11871						target: {
11872							element: target,
11873							left: targetOffset.left,
11874							top: targetOffset.top,
11875							width: targetWidth,
11876							height: targetHeight
11877						},
11878						element: {
11879							element: elem,
11880							left: position.left,
11881							top: position.top,
11882							width: elemWidth,
11883							height: elemHeight
11884						},
11885						horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
11886						vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
11887					};
11888				if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
11889					feedback.horizontal = "center";
11890				}
11891				if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
11892					feedback.vertical = "middle";
11893				}
11894				if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
11895					feedback.important = "horizontal";
11896				} else {
11897					feedback.important = "vertical";
11898				}
11899				options.using.call( this, props, feedback );
11900			};
11901		}
11902
11903		elem.offset( $.extend( position, { using: using } ) );
11904	} );
11905};
11906
11907$.ui.position = {
11908	fit: {
11909		left: function( position, data ) {
11910			var within = data.within,
11911				withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
11912				outerWidth = within.width,
11913				collisionPosLeft = position.left - data.collisionPosition.marginLeft,
11914				overLeft = withinOffset - collisionPosLeft,
11915				overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
11916				newOverRight;
11917
11918			// Element is wider than within
11919			if ( data.collisionWidth > outerWidth ) {
11920
11921				// Element is initially over the left side of within
11922				if ( overLeft > 0 && overRight <= 0 ) {
11923					newOverRight = position.left + overLeft + data.collisionWidth - outerWidth -
11924						withinOffset;
11925					position.left += overLeft - newOverRight;
11926
11927				// Element is initially over right side of within
11928				} else if ( overRight > 0 && overLeft <= 0 ) {
11929					position.left = withinOffset;
11930
11931				// Element is initially over both left and right sides of within
11932				} else {
11933					if ( overLeft > overRight ) {
11934						position.left = withinOffset + outerWidth - data.collisionWidth;
11935					} else {
11936						position.left = withinOffset;
11937					}
11938				}
11939
11940			// Too far left -> align with left edge
11941			} else if ( overLeft > 0 ) {
11942				position.left += overLeft;
11943
11944			// Too far right -> align with right edge
11945			} else if ( overRight > 0 ) {
11946				position.left -= overRight;
11947
11948			// Adjust based on position and margin
11949			} else {
11950				position.left = max( position.left - collisionPosLeft, position.left );
11951			}
11952		},
11953		top: function( position, data ) {
11954			var within = data.within,
11955				withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
11956				outerHeight = data.within.height,
11957				collisionPosTop = position.top - data.collisionPosition.marginTop,
11958				overTop = withinOffset - collisionPosTop,
11959				overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
11960				newOverBottom;
11961
11962			// Element is taller than within
11963			if ( data.collisionHeight > outerHeight ) {
11964
11965				// Element is initially over the top of within
11966				if ( overTop > 0 && overBottom <= 0 ) {
11967					newOverBottom = position.top + overTop + data.collisionHeight - outerHeight -
11968						withinOffset;
11969					position.top += overTop - newOverBottom;
11970
11971				// Element is initially over bottom of within
11972				} else if ( overBottom > 0 && overTop <= 0 ) {
11973					position.top = withinOffset;
11974
11975				// Element is initially over both top and bottom of within
11976				} else {
11977					if ( overTop > overBottom ) {
11978						position.top = withinOffset + outerHeight - data.collisionHeight;
11979					} else {
11980						position.top = withinOffset;
11981					}
11982				}
11983
11984			// Too far up -> align with top
11985			} else if ( overTop > 0 ) {
11986				position.top += overTop;
11987
11988			// Too far down -> align with bottom edge
11989			} else if ( overBottom > 0 ) {
11990				position.top -= overBottom;
11991
11992			// Adjust based on position and margin
11993			} else {
11994				position.top = max( position.top - collisionPosTop, position.top );
11995			}
11996		}
11997	},
11998	flip: {
11999		left: function( position, data ) {
12000			var within = data.within,
12001				withinOffset = within.offset.left + within.scrollLeft,
12002				outerWidth = within.width,
12003				offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
12004				collisionPosLeft = position.left - data.collisionPosition.marginLeft,
12005				overLeft = collisionPosLeft - offsetLeft,
12006				overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
12007				myOffset = data.my[ 0 ] === "left" ?
12008					-data.elemWidth :
12009					data.my[ 0 ] === "right" ?
12010						data.elemWidth :
12011						0,
12012				atOffset = data.at[ 0 ] === "left" ?
12013					data.targetWidth :
12014					data.at[ 0 ] === "right" ?
12015						-data.targetWidth :
12016						0,
12017				offset = -2 * data.offset[ 0 ],
12018				newOverRight,
12019				newOverLeft;
12020
12021			if ( overLeft < 0 ) {
12022				newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth -
12023					outerWidth - withinOffset;
12024				if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
12025					position.left += myOffset + atOffset + offset;
12026				}
12027			} else if ( overRight > 0 ) {
12028				newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset +
12029					atOffset + offset - offsetLeft;
12030				if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
12031					position.left += myOffset + atOffset + offset;
12032				}
12033			}
12034		},
12035		top: function( position, data ) {
12036			var within = data.within,
12037				withinOffset = within.offset.top + within.scrollTop,
12038				outerHeight = within.height,
12039				offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
12040				collisionPosTop = position.top - data.collisionPosition.marginTop,
12041				overTop = collisionPosTop - offsetTop,
12042				overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
12043				top = data.my[ 1 ] === "top",
12044				myOffset = top ?
12045					-data.elemHeight :
12046					data.my[ 1 ] === "bottom" ?
12047						data.elemHeight :
12048						0,
12049				atOffset = data.at[ 1 ] === "top" ?
12050					data.targetHeight :
12051					data.at[ 1 ] === "bottom" ?
12052						-data.targetHeight :
12053						0,
12054				offset = -2 * data.offset[ 1 ],
12055				newOverTop,
12056				newOverBottom;
12057			if ( overTop < 0 ) {
12058				newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight -
12059					outerHeight - withinOffset;
12060				if ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) {
12061					position.top += myOffset + atOffset + offset;
12062				}
12063			} else if ( overBottom > 0 ) {
12064				newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset +
12065					offset - offsetTop;
12066				if ( newOverTop > 0 || abs( newOverTop ) < overBottom ) {
12067					position.top += myOffset + atOffset + offset;
12068				}
12069			}
12070		}
12071	},
12072	flipfit: {
12073		left: function() {
12074			$.ui.position.flip.left.apply( this, arguments );
12075			$.ui.position.fit.left.apply( this, arguments );
12076		},
12077		top: function() {
12078			$.ui.position.flip.top.apply( this, arguments );
12079			$.ui.position.fit.top.apply( this, arguments );
12080		}
12081	}
12082};
12083
12084} )();
12085
12086var position = $.ui.position;
12087
12088
12089/*!
12090 * jQuery UI :data 1.13.2
12091 * http://jqueryui.com
vendor: 29,600 bytes, lines 12092-13245
12092 *
12093 * Copyright jQuery Foundation and other contributors
12094 * Released under the MIT license.
12095 * http://jquery.org/license
12096 */
12097
12098//>>label: :data Selector
12099//>>group: Core
12100//>>description: Selects elements which have data stored under the specified key.
12101//>>docs: http://api.jqueryui.com/data-selector/
12102
12103
12104var data = $.extend( $.expr.pseudos, {
12105	data: $.expr.createPseudo ?
12106		$.expr.createPseudo( function( dataName ) {
12107			return function( elem ) {
12108				return !!$.data( elem, dataName );
12109			};
12110		} ) :
12111
12112		// Support: jQuery <1.8
12113		function( elem, i, match ) {
12114			return !!$.data( elem, match[ 3 ] );
12115		}
12116} );
12117
12118/*!
12119 * jQuery UI Disable Selection 1.13.2
12120 * http://jqueryui.com
12121 *
12122 * Copyright jQuery Foundation and other contributors
12123 * Released under the MIT license.
12124 * http://jquery.org/license
12125 */
12126
12127//>>label: disableSelection
12128//>>group: Core
12129//>>description: Disable selection of text content within the set of matched elements.
12130//>>docs: http://api.jqueryui.com/disableSelection/
12131
12132// This file is deprecated
12133
12134var disableSelection = $.fn.extend( {
12135	disableSelection: ( function() {
12136		var eventType = "onselectstart" in document.createElement( "div" ) ?
12137			"selectstart" :
12138			"mousedown";
12139
12140		return function() {
12141			return this.on( eventType + ".ui-disableSelection", function( event ) {
12142				event.preventDefault();
12143			} );
12144		};
12145	} )(),
12146
12147	enableSelection: function() {
12148		return this.off( ".ui-disableSelection" );
12149	}
12150} );
12151
12152
12153
12154// Create a local jQuery because jQuery Color relies on it and the
12155// global may not exist with AMD and a custom build (#10199).
12156// This module is a noop if used as a regular AMD module.
12157// eslint-disable-next-line no-unused-vars
12158var jQuery = $;
12159
12160
12161/*!
12162 * jQuery Color Animations v2.2.0
12163 * https://github.com/jquery/jquery-color
12164 *
12165 * Copyright OpenJS Foundation and other contributors
12166 * Released under the MIT license.
12167 * http://jquery.org/license
12168 *
12169 * Date: Sun May 10 09:02:36 2020 +0200
12170 */
12171
12172
12173
12174	var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor " +
12175		"borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",
12176
12177	class2type = {},
12178	toString = class2type.toString,
12179
12180	// plusequals test for += 100 -= 100
12181	rplusequals = /^([\-+])=\s*(\d+\.?\d*)/,
12182
12183	// a set of RE's that can match strings and generate color tuples.
12184	stringParsers = [ {
12185			re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
12186			parse: function( execResult ) {
12187				return [
12188					execResult[ 1 ],
12189					execResult[ 2 ],
12190					execResult[ 3 ],
12191					execResult[ 4 ]
12192				];
12193			}
12194		}, {
12195			re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
12196			parse: function( execResult ) {
12197				return [
12198					execResult[ 1 ] * 2.55,
12199					execResult[ 2 ] * 2.55,
12200					execResult[ 3 ] * 2.55,
12201					execResult[ 4 ]
12202				];
12203			}
12204		}, {
12205
12206			// this regex ignores A-F because it's compared against an already lowercased string
12207			re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})?/,
12208			parse: function( execResult ) {
12209				return [
12210					parseInt( execResult[ 1 ], 16 ),
12211					parseInt( execResult[ 2 ], 16 ),
12212					parseInt( execResult[ 3 ], 16 ),
12213					execResult[ 4 ] ?
12214						( parseInt( execResult[ 4 ], 16 ) / 255 ).toFixed( 2 ) :
12215						1
12216				];
12217			}
12218		}, {
12219
12220			// this regex ignores A-F because it's compared against an already lowercased string
12221			re: /#([a-f0-9])([a-f0-9])([a-f0-9])([a-f0-9])?/,
12222			parse: function( execResult ) {
12223				return [
12224					parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),
12225					parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),
12226					parseInt( execResult[ 3 ] + execResult[ 3 ], 16 ),
12227					execResult[ 4 ] ?
12228						( parseInt( execResult[ 4 ] + execResult[ 4 ], 16 ) / 255 )
12229							.toFixed( 2 ) :
12230						1
12231				];
12232			}
12233		}, {
12234			re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
12235			space: "hsla",
12236			parse: function( execResult ) {
12237				return [
12238					execResult[ 1 ],
12239					execResult[ 2 ] / 100,
12240					execResult[ 3 ] / 100,
12241					execResult[ 4 ]
12242				];
12243			}
12244		} ],
12245
12246	// jQuery.Color( )
12247	color = jQuery.Color = function( color, green, blue, alpha ) {
12248		return new jQuery.Color.fn.parse( color, green, blue, alpha );
12249	},
12250	spaces = {
12251		rgba: {
12252			props: {
12253				red: {
12254					idx: 0,
12255					type: "byte"
12256				},
12257				green: {
12258					idx: 1,
12259					type: "byte"
12260				},
12261				blue: {
12262					idx: 2,
12263					type: "byte"
12264				}
12265			}
12266		},
12267
12268		hsla: {
12269			props: {
12270				hue: {
12271					idx: 0,
12272					type: "degrees"
12273				},
12274				saturation: {
12275					idx: 1,
12276					type: "percent"
12277				},
12278				lightness: {
12279					idx: 2,
12280					type: "percent"
12281				}
12282			}
12283		}
12284	},
12285	propTypes = {
12286		"byte": {
12287			floor: true,
12288			max: 255
12289		},
12290		"percent": {
12291			max: 1
12292		},
12293		"degrees": {
12294			mod: 360,
12295			floor: true
12296		}
12297	},
12298	support = color.support = {},
12299
12300	// element for support tests
12301	supportElem = jQuery( "<p>" )[ 0 ],
12302
12303	// colors = jQuery.Color.names
12304	colors,
12305
12306	// local aliases of functions called often
12307	each = jQuery.each;
12308
12309// determine rgba support immediately
12310supportElem.style.cssText = "background-color:rgba(1,1,1,.5)";
12311support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1;
12312
12313// define cache name and alpha properties
12314// for rgba and hsla spaces
12315each( spaces, function( spaceName, space ) {
12316	space.cache = "_" + spaceName;
12317	space.props.alpha = {
12318		idx: 3,
12319		type: "percent",
12320		def: 1
12321	};
12322} );
12323
12324// Populate the class2type map
12325jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
12326	function( _i, name ) {
12327		class2type[ "[object " + name + "]" ] = name.toLowerCase();
12328	} );
12329
12330function getType( obj ) {
12331	if ( obj == null ) {
12332		return obj + "";
12333	}
12334
12335	return typeof obj === "object" ?
12336		class2type[ toString.call( obj ) ] || "object" :
12337		typeof obj;
12338}
12339
12340function clamp( value, prop, allowEmpty ) {
12341	var type = propTypes[ prop.type ] || {};
12342
12343	if ( value == null ) {
12344		return ( allowEmpty || !prop.def ) ? null : prop.def;
12345	}
12346
12347	// ~~ is an short way of doing floor for positive numbers
12348	value = type.floor ? ~~value : parseFloat( value );
12349
12350	// IE will pass in empty strings as value for alpha,
12351	// which will hit this case
12352	if ( isNaN( value ) ) {
12353		return prop.def;
12354	}
12355
12356	if ( type.mod ) {
12357
12358		// we add mod before modding to make sure that negatives values
12359		// get converted properly: -10 -> 350
12360		return ( value + type.mod ) % type.mod;
12361	}
12362
12363	// for now all property types without mod have min and max
12364	return Math.min( type.max, Math.max( 0, value ) );
12365}
12366
12367function stringParse( string ) {
12368	var inst = color(),
12369		rgba = inst._rgba = [];
12370
12371	string = string.toLowerCase();
12372
12373	each( stringParsers, function( _i, parser ) {
12374		var parsed,
12375			match = parser.re.exec( string ),
12376			values = match && parser.parse( match ),
12377			spaceName = parser.space || "rgba";
12378
12379		if ( values ) {
12380			parsed = inst[ spaceName ]( values );
12381
12382			// if this was an rgba parse the assignment might happen twice
12383			// oh well....
12384			inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ];
12385			rgba = inst._rgba = parsed._rgba;
12386
12387			// exit each( stringParsers ) here because we matched
12388			return false;
12389		}
12390	} );
12391
12392	// Found a stringParser that handled it
12393	if ( rgba.length ) {
12394
12395		// if this came from a parsed string, force "transparent" when alpha is 0
12396		// chrome, (and maybe others) return "transparent" as rgba(0,0,0,0)
12397		if ( rgba.join() === "0,0,0,0" ) {
12398			jQuery.extend( rgba, colors.transparent );
12399		}
12400		return inst;
12401	}
12402
12403	// named colors
12404	return colors[ string ];
12405}
12406
12407color.fn = jQuery.extend( color.prototype, {
12408	parse: function( red, green, blue, alpha ) {
12409		if ( red === undefined ) {
12410			this._rgba = [ null, null, null, null ];
12411			return this;
12412		}
12413		if ( red.jquery || red.nodeType ) {
12414			red = jQuery( red ).css( green );
12415			green = undefined;
12416		}
12417
12418		var inst = this,
12419			type = getType( red ),
12420			rgba = this._rgba = [];
12421
12422		// more than 1 argument specified - assume ( red, green, blue, alpha )
12423		if ( green !== undefined ) {
12424			red = [ red, green, blue, alpha ];
12425			type = "array";
12426		}
12427
12428		if ( type === "string" ) {
12429			return this.parse( stringParse( red ) || colors._default );
12430		}
12431
12432		if ( type === "array" ) {
12433			each( spaces.rgba.props, function( _key, prop ) {
12434				rgba[ prop.idx ] = clamp( red[ prop.idx ], prop );
12435			} );
12436			return this;
12437		}
12438
12439		if ( type === "object" ) {
12440			if ( red instanceof color ) {
12441				each( spaces, function( _spaceName, space ) {
12442					if ( red[ space.cache ] ) {
12443						inst[ space.cache ] = red[ space.cache ].slice();
12444					}
12445				} );
12446			} else {
12447				each( spaces, function( _spaceName, space ) {
12448					var cache = space.cache;
12449					each( space.props, function( key, prop ) {
12450
12451						// if the cache doesn't exist, and we know how to convert
12452						if ( !inst[ cache ] && space.to ) {
12453
12454							// if the value was null, we don't need to copy it
12455							// if the key was alpha, we don't need to copy it either
12456							if ( key === "alpha" || red[ key ] == null ) {
12457								return;
12458							}
12459							inst[ cache ] = space.to( inst._rgba );
12460						}
12461
12462						// this is the only case where we allow nulls for ALL properties.
12463						// call clamp with alwaysAllowEmpty
12464						inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true );
12465					} );
12466
12467					// everything defined but alpha?
12468					if ( inst[ cache ] && jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) {
12469
12470						// use the default of 1
12471						if ( inst[ cache ][ 3 ] == null ) {
12472							inst[ cache ][ 3 ] = 1;
12473						}
12474
12475						if ( space.from ) {
12476							inst._rgba = space.from( inst[ cache ] );
12477						}
12478					}
12479				} );
12480			}
12481			return this;
12482		}
12483	},
12484	is: function( compare ) {
12485		var is = color( compare ),
12486			same = true,
12487			inst = this;
12488
12489		each( spaces, function( _, space ) {
12490			var localCache,
12491				isCache = is[ space.cache ];
12492			if ( isCache ) {
12493				localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || [];
12494				each( space.props, function( _, prop ) {
12495					if ( isCache[ prop.idx ] != null ) {
12496						same = ( isCache[ prop.idx ] === localCache[ prop.idx ] );
12497						return same;
12498					}
12499				} );
12500			}
12501			return same;
12502		} );
12503		return same;
12504	},
12505	_space: function() {
12506		var used = [],
12507			inst = this;
12508		each( spaces, function( spaceName, space ) {
12509			if ( inst[ space.cache ] ) {
12510				used.push( spaceName );
12511			}
12512		} );
12513		return used.pop();
12514	},
12515	transition: function( other, distance ) {
12516		var end = color( other ),
12517			spaceName = end._space(),
12518			space = spaces[ spaceName ],
12519			startColor = this.alpha() === 0 ? color( "transparent" ) : this,
12520			start = startColor[ space.cache ] || space.to( startColor._rgba ),
12521			result = start.slice();
12522
12523		end = end[ space.cache ];
12524		each( space.props, function( _key, prop ) {
12525			var index = prop.idx,
12526				startValue = start[ index ],
12527				endValue = end[ index ],
12528				type = propTypes[ prop.type ] || {};
12529
12530			// if null, don't override start value
12531			if ( endValue === null ) {
12532				return;
12533			}
12534
12535			// if null - use end
12536			if ( startValue === null ) {
12537				result[ index ] = endValue;
12538			} else {
12539				if ( type.mod ) {
12540					if ( endValue - startValue > type.mod / 2 ) {
12541						startValue += type.mod;
12542					} else if ( startValue - endValue > type.mod / 2 ) {
12543						startValue -= type.mod;
12544					}
12545				}
12546				result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop );
12547			}
12548		} );
12549		return this[ spaceName ]( result );
12550	},
12551	blend: function( opaque ) {
12552
12553		// if we are already opaque - return ourself
12554		if ( this._rgba[ 3 ] === 1 ) {
12555			return this;
12556		}
12557
12558		var rgb = this._rgba.slice(),
12559			a = rgb.pop(),
12560			blend = color( opaque )._rgba;
12561
12562		return color( jQuery.map( rgb, function( v, i ) {
12563			return ( 1 - a ) * blend[ i ] + a * v;
12564		} ) );
12565	},
12566	toRgbaString: function() {
12567		var prefix = "rgba(",
12568			rgba = jQuery.map( this._rgba, function( v, i ) {
12569				if ( v != null ) {
12570					return v;
12571				}
12572				return i > 2 ? 1 : 0;
12573			} );
12574
12575		if ( rgba[ 3 ] === 1 ) {
12576			rgba.pop();
12577			prefix = "rgb(";
12578		}
12579
12580		return prefix + rgba.join() + ")";
12581	},
12582	toHslaString: function() {
12583		var prefix = "hsla(",
12584			hsla = jQuery.map( this.hsla(), function( v, i ) {
12585				if ( v == null ) {
12586					v = i > 2 ? 1 : 0;
12587				}
12588
12589				// catch 1 and 2
12590				if ( i && i < 3 ) {
12591					v = Math.round( v * 100 ) + "%";
12592				}
12593				return v;
12594			} );
12595
12596		if ( hsla[ 3 ] === 1 ) {
12597			hsla.pop();
12598			prefix = "hsl(";
12599		}
12600		return prefix + hsla.join() + ")";
12601	},
12602	toHexString: function( includeAlpha ) {
12603		var rgba = this._rgba.slice(),
12604			alpha = rgba.pop();
12605
12606		if ( includeAlpha ) {
12607			rgba.push( ~~( alpha * 255 ) );
12608		}
12609
12610		return "#" + jQuery.map( rgba, function( v ) {
12611
12612			// default to 0 when nulls exist
12613			v = ( v || 0 ).toString( 16 );
12614			return v.length === 1 ? "0" + v : v;
12615		} ).join( "" );
12616	},
12617	toString: function() {
12618		return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString();
12619	}
12620} );
12621color.fn.parse.prototype = color.fn;
12622
12623// hsla conversions adapted from:
12624// https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021
12625
12626function hue2rgb( p, q, h ) {
12627	h = ( h + 1 ) % 1;
12628	if ( h * 6 < 1 ) {
12629		return p + ( q - p ) * h * 6;
12630	}
12631	if ( h * 2 < 1 ) {
12632		return q;
12633	}
12634	if ( h * 3 < 2 ) {
12635		return p + ( q - p ) * ( ( 2 / 3 ) - h ) * 6;
12636	}
12637	return p;
12638}
12639
12640spaces.hsla.to = function( rgba ) {
12641	if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) {
12642		return [ null, null, null, rgba[ 3 ] ];
12643	}
12644	var r = rgba[ 0 ] / 255,
12645		g = rgba[ 1 ] / 255,
12646		b = rgba[ 2 ] / 255,
12647		a = rgba[ 3 ],
12648		max = Math.max( r, g, b ),
12649		min = Math.min( r, g, b ),
12650		diff = max - min,
12651		add = max + min,
12652		l = add * 0.5,
12653		h, s;
12654
12655	if ( min === max ) {
12656		h = 0;
12657	} else if ( r === max ) {
12658		h = ( 60 * ( g - b ) / diff ) + 360;
12659	} else if ( g === max ) {
12660		h = ( 60 * ( b - r ) / diff ) + 120;
12661	} else {
12662		h = ( 60 * ( r - g ) / diff ) + 240;
12663	}
12664
12665	// chroma (diff) == 0 means greyscale which, by definition, saturation = 0%
12666	// otherwise, saturation is based on the ratio of chroma (diff) to lightness (add)
12667	if ( diff === 0 ) {
12668		s = 0;
12669	} else if ( l <= 0.5 ) {
12670		s = diff / add;
12671	} else {
12672		s = diff / ( 2 - add );
12673	}
12674	return [ Math.round( h ) % 360, s, l, a == null ? 1 : a ];
12675};
12676
12677spaces.hsla.from = function( hsla ) {
12678	if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) {
12679		return [ null, null, null, hsla[ 3 ] ];
12680	}
12681	var h = hsla[ 0 ] / 360,
12682		s = hsla[ 1 ],
12683		l = hsla[ 2 ],
12684		a = hsla[ 3 ],
12685		q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s,
12686		p = 2 * l - q;
12687
12688	return [
12689		Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ),
12690		Math.round( hue2rgb( p, q, h ) * 255 ),
12691		Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ),
12692		a
12693	];
12694};
12695
12696
12697each( spaces, function( spaceName, space ) {
12698	var props = space.props,
12699		cache = space.cache,
12700		to = space.to,
12701		from = space.from;
12702
12703	// makes rgba() and hsla()
12704	color.fn[ spaceName ] = function( value ) {
12705
12706		// generate a cache for this space if it doesn't exist
12707		if ( to && !this[ cache ] ) {
12708			this[ cache ] = to( this._rgba );
12709		}
12710		if ( value === undefined ) {
12711			return this[ cache ].slice();
12712		}
12713
12714		var ret,
12715			type = getType( value ),
12716			arr = ( type === "array" || type === "object" ) ? value : arguments,
12717			local = this[ cache ].slice();
12718
12719		each( props, function( key, prop ) {
12720			var val = arr[ type === "object" ? key : prop.idx ];
12721			if ( val == null ) {
12722				val = local[ prop.idx ];
12723			}
12724			local[ prop.idx ] = clamp( val, prop );
12725		} );
12726
12727		if ( from ) {
12728			ret = color( from( local ) );
12729			ret[ cache ] = local;
12730			return ret;
12731		} else {
12732			return color( local );
12733		}
12734	};
12735
12736	// makes red() green() blue() alpha() hue() saturation() lightness()
12737	each( props, function( key, prop ) {
12738
12739		// alpha is included in more than one space
12740		if ( color.fn[ key ] ) {
12741			return;
12742		}
12743		color.fn[ key ] = function( value ) {
12744			var local, cur, match, fn,
12745				vtype = getType( value );
12746
12747			if ( key === "alpha" ) {
12748				fn = this._hsla ? "hsla" : "rgba";
12749			} else {
12750				fn = spaceName;
12751			}
12752			local = this[ fn ]();
12753			cur = local[ prop.idx ];
12754
12755			if ( vtype === "undefined" ) {
12756				return cur;
12757			}
12758
12759			if ( vtype === "function" ) {
12760				value = value.call( this, cur );
12761				vtype = getType( value );
12762			}
12763			if ( value == null && prop.empty ) {
12764				return this;
12765			}
12766			if ( vtype === "string" ) {
12767				match = rplusequals.exec( value );
12768				if ( match ) {
12769					value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 );
12770				}
12771			}
12772			local[ prop.idx ] = value;
12773			return this[ fn ]( local );
12774		};
12775	} );
12776} );
12777
12778// add cssHook and .fx.step function for each named hook.
12779// accept a space separated string of properties
12780color.hook = function( hook ) {
12781	var hooks = hook.split( " " );
12782	each( hooks, function( _i, hook ) {
12783		jQuery.cssHooks[ hook ] = {
12784			set: function( elem, value ) {
12785				var parsed, curElem,
12786					backgroundColor = "";
12787
12788				if ( value !== "transparent" && ( getType( value ) !== "string" || ( parsed = stringParse( value ) ) ) ) {
12789					value = color( parsed || value );
12790					if ( !support.rgba && value._rgba[ 3 ] !== 1 ) {
12791						curElem = hook === "backgroundColor" ? elem.parentNode : elem;
12792						while (
12793							( backgroundColor === "" || backgroundColor === "transparent" ) &&
12794							curElem && curElem.style
12795						) {
12796							try {
12797								backgroundColor = jQuery.css( curElem, "backgroundColor" );
12798								curElem = curElem.parentNode;
12799							} catch ( e ) {
12800							}
12801						}
12802
12803						value = value.blend( backgroundColor && backgroundColor !== "transparent" ?
12804							backgroundColor :
12805							"_default" );
12806					}
12807
12808					value = value.toRgbaString();
12809				}
12810				try {
12811					elem.style[ hook ] = value;
12812				} catch ( e ) {
12813
12814					// wrapped to prevent IE from throwing errors on "invalid" values like 'auto' or 'inherit'
12815				}
12816			}
12817		};
12818		jQuery.fx.step[ hook ] = function( fx ) {
12819			if ( !fx.colorInit ) {
12820				fx.start = color( fx.elem, hook );
12821				fx.end = color( fx.end );
12822				fx.colorInit = true;
12823			}
12824			jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) );
12825		};
12826	} );
12827
12828};
12829
12830color.hook( stepHooks );
12831
12832jQuery.cssHooks.borderColor = {
12833	expand: function( value ) {
12834		var expanded = {};
12835
12836		each( [ "Top", "Right", "Bottom", "Left" ], function( _i, part ) {
12837			expanded[ "border" + part + "Color" ] = value;
12838		} );
12839		return expanded;
12840	}
12841};
12842
12843// Basic color names only.
12844// Usage of any of the other color names requires adding yourself or including
12845// jquery.color.svg-names.js.
12846colors = jQuery.Color.names = {
12847
12848	// 4.1. Basic color keywords
12849	aqua: "#00ffff",
12850	black: "#000000",
12851	blue: "#0000ff",
12852	fuchsia: "#ff00ff",
12853	gray: "#808080",
12854	green: "#008000",
12855	lime: "#00ff00",
12856	maroon: "#800000",
12857	navy: "#000080",
12858	olive: "#808000",
12859	purple: "#800080",
12860	red: "#ff0000",
12861	silver: "#c0c0c0",
12862	teal: "#008080",
12863	white: "#ffffff",
12864	yellow: "#ffff00",
12865
12866	// 4.2.3. "transparent" color keyword
12867	transparent: [ null, null, null, 0 ],
12868
12869	_default: "#ffffff"
12870};
12871
12872
12873/*!
12874 * jQuery UI Effects 1.13.2
12875 * http://jqueryui.com
12876 *
12877 * Copyright jQuery Foundation and other contributors
12878 * Released under the MIT license.
12879 * http://jquery.org/license
12880 */
12881
12882//>>label: Effects Core
12883//>>group: Effects
12884/* eslint-disable max-len */
12885//>>description: Extends the internal jQuery effects. Includes morphing and easing. Required by all other effects.
12886/* eslint-enable max-len */
12887//>>docs: http://api.jqueryui.com/category/effects-core/
12888//>>demos: http://jqueryui.com/effect/
12889
12890
12891var dataSpace = "ui-effects-",
12892	dataSpaceStyle = "ui-effects-style",
12893	dataSpaceAnimated = "ui-effects-animated";
12894
12895$.effects = {
12896	effect: {}
12897};
12898
12899/******************************************************************************/
12900/****************************** CLASS ANIMATIONS ******************************/
12901/******************************************************************************/
12902( function() {
12903
12904var classAnimationActions = [ "add", "remove", "toggle" ],
12905	shorthandStyles = {
12906		border: 1,
12907		borderBottom: 1,
12908		borderColor: 1,
12909		borderLeft: 1,
12910		borderRight: 1,
12911		borderTop: 1,
12912		borderWidth: 1,
12913		margin: 1,
12914		padding: 1
12915	};
12916
12917$.each(
12918	[ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ],
12919	function( _, prop ) {
12920		$.fx.step[ prop ] = function( fx ) {
12921			if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) {
12922				jQuery.style( fx.elem, prop, fx.end );
12923				fx.setAttr = true;
12924			}
12925		};
12926	}
12927);
12928
12929function camelCase( string ) {
12930	return string.replace( /-([\da-z])/gi, function( all, letter ) {
12931		return letter.toUpperCase();
12932	} );
12933}
12934
12935function getElementStyles( elem ) {
12936	var key, len,
12937		style = elem.ownerDocument.defaultView ?
12938			elem.ownerDocument.defaultView.getComputedStyle( elem, null ) :
12939			elem.currentStyle,
12940		styles = {};
12941
12942	if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) {
12943		len = style.length;
12944		while ( len-- ) {
12945			key = style[ len ];
12946			if ( typeof style[ key ] === "string" ) {
12947				styles[ camelCase( key ) ] = style[ key ];
12948			}
12949		}
12950
12951	// Support: Opera, IE <9
12952	} else {
12953		for ( key in style ) {
12954			if ( typeof style[ key ] === "string" ) {
12955				styles[ key ] = style[ key ];
12956			}
12957		}
12958	}
12959
12960	return styles;
12961}
12962
12963function styleDifference( oldStyle, newStyle ) {
12964	var diff = {},
12965		name, value;
12966
12967	for ( name in newStyle ) {
12968		value = newStyle[ name ];
12969		if ( oldStyle[ name ] !== value ) {
12970			if ( !shorthandStyles[ name ] ) {
12971				if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) {
12972					diff[ name ] = value;
12973				}
12974			}
12975		}
12976	}
12977
12978	return diff;
12979}
12980
12981// Support: jQuery <1.8
12982if ( !$.fn.addBack ) {
12983	$.fn.addBack = function( selector ) {
12984		return this.add( selector == null ?
12985			this.prevObject : this.prevObject.filter( selector )
12986		);
12987	};
12988}
12989
12990$.effects.animateClass = function( value, duration, easing, callback ) {
12991	var o = $.speed( duration, easing, callback );
12992
12993	return this.queue( function() {
12994		var animated = $( this ),
12995			baseClass = animated.attr( "class" ) || "",
12996			applyClassChange,
12997			allAnimations = o.children ? animated.find( "*" ).addBack() : animated;
12998
12999		// Map the animated objects to store the original styles.
13000		allAnimations = allAnimations.map( function() {
13001			var el = $( this );
13002			return {
13003				el: el,
13004				start: getElementStyles( this )
13005			};
13006		} );
13007
13008		// Apply class change
13009		applyClassChange = function() {
13010			$.each( classAnimationActions, function( i, action ) {
13011				if ( value[ action ] ) {
13012					animated[ action + "Class" ]( value[ action ] );
13013				}
13014			} );
13015		};
13016		applyClassChange();
13017
13018		// Map all animated objects again - calculate new styles and diff
13019		allAnimations = allAnimations.map( function() {
13020			this.end = getElementStyles( this.el[ 0 ] );
13021			this.diff = styleDifference( this.start, this.end );
13022			return this;
13023		} );
13024
13025		// Apply original class
13026		animated.attr( "class", baseClass );
13027
13028		// Map all animated objects again - this time collecting a promise
13029		allAnimations = allAnimations.map( function() {
13030			var styleInfo = this,
13031				dfd = $.Deferred(),
13032				opts = $.extend( {}, o, {
13033					queue: false,
13034					complete: function() {
13035						dfd.resolve( styleInfo );
13036					}
13037				} );
13038
13039			this.el.animate( this.diff, opts );
13040			return dfd.promise();
13041		} );
13042
13043		// Once all animations have completed:
13044		$.when.apply( $, allAnimations.get() ).done( function() {
13045
13046			// Set the final class
13047			applyClassChange();
13048
13049			// For each animated element,
13050			// clear all css properties that were animated
13051			$.each( arguments, function() {
13052				var el = this.el;
13053				$.each( this.diff, function( key ) {
13054					el.css( key, "" );
13055				} );
13056			} );
13057
13058			// This is guarnteed to be there if you use jQuery.speed()
13059			// it also handles dequeuing the next anim...
13060			o.complete.call( animated[ 0 ] );
13061		} );
13062	} );
13063};
13064
13065$.fn.extend( {
13066	addClass: ( function( orig ) {
13067		return function( classNames, speed, easing, callback ) {
13068			return speed ?
13069				$.effects.animateClass.call( this,
13070					{ add: classNames }, speed, easing, callback ) :
13071				orig.apply( this, arguments );
13072		};
13073	} )( $.fn.addClass ),
13074
13075	removeClass: ( function( orig ) {
13076		return function( classNames, speed, easing, callback ) {
13077			return arguments.length > 1 ?
13078				$.effects.animateClass.call( this,
13079					{ remove: classNames }, speed, easing, callback ) :
13080				orig.apply( this, arguments );
13081		};
13082	} )( $.fn.removeClass ),
13083
13084	toggleClass: ( function( orig ) {
13085		return function( classNames, force, speed, easing, callback ) {
13086			if ( typeof force === "boolean" || force === undefined ) {
13087				if ( !speed ) {
13088
13089					// Without speed parameter
13090					return orig.apply( this, arguments );
13091				} else {
13092					return $.effects.animateClass.call( this,
13093						( force ? { add: classNames } : { remove: classNames } ),
13094						speed, easing, callback );
13095				}
13096			} else {
13097
13098				// Without force parameter
13099				return $.effects.animateClass.call( this,
13100					{ toggle: classNames }, force, speed, easing );
13101			}
13102		};
13103	} )( $.fn.toggleClass ),
13104
13105	switchClass: function( remove, add, speed, easing, callback ) {
13106		return $.effects.animateClass.call( this, {
13107			add: add,
13108			remove: remove
13109		}, speed, easing, callback );
13110	}
13111} );
13112
13113} )();
13114
13115/******************************************************************************/
13116/*********************************** EFFECTS **********************************/
13117/******************************************************************************/
13118
13119( function() {
13120
13121if ( $.expr && $.expr.pseudos && $.expr.pseudos.animated ) {
13122	$.expr.pseudos.animated = ( function( orig ) {
13123		return function( elem ) {
13124			return !!$( elem ).data( dataSpaceAnimated ) || orig( elem );
13125		};
13126	} )( $.expr.pseudos.animated );
13127}
13128
13129if ( $.uiBackCompat !== false ) {
13130	$.extend( $.effects, {
13131
13132		// Saves a set of properties in a data storage
13133		save: function( element, set ) {
13134			var i = 0, length = set.length;
13135			for ( ; i < length; i++ ) {
13136				if ( set[ i ] !== null ) {
13137					element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] );
13138				}
13139			}
13140		},
13141
13142		// Restores a set of previously saved properties from a data storage
13143		restore: function( element, set ) {
13144			var val, i = 0, length = set.length;
13145			for ( ; i < length; i++ ) {
13146				if ( set[ i ] !== null ) {
13147					val = element.data( dataSpace + set[ i ] );
13148					element.css( set[ i ], val );
13149				}
13150			}
13151		},
13152
13153		setMode: function( el, mode ) {
13154			if ( mode === "toggle" ) {
13155				mode = el.is( ":hidden" ) ? "show" : "hide";
13156			}
13157			return mode;
13158		},
13159
13160		// Wraps the element around a wrapper that copies position properties
13161		createWrapper: function( element ) {
13162
13163			// If the element is already wrapped, return it
13164			if ( element.parent().is( ".ui-effects-wrapper" ) ) {
13165				return element.parent();
13166			}
13167
13168			// Wrap the element
13169			var props = {
13170					width: element.outerWidth( true ),
13171					height: element.outerHeight( true ),
13172					"float": element.css( "float" )
13173				},
13174				wrapper = $( "<div></div>" )
13175					.addClass( "ui-effects-wrapper" )
13176					.css( {
13177						fontSize: "100%",
13178						background: "transparent",
13179						border: "none",
13180						margin: 0,
13181						padding: 0
13182					} ),
13183
13184				// Store the size in case width/height are defined in % - Fixes #5245
13185				size = {
13186					width: element.width(),
13187					height: element.height()
13188				},
13189				active = document.activeElement;
13190
13191			// Support: Firefox
13192			// Firefox incorrectly exposes anonymous content
13193			// https://bugzilla.mozilla.org/show_bug.cgi?id=561664
13194			try {
13195				// eslint-disable-next-line no-unused-expressions
13196				active.id;
13197			} catch ( e ) {
13198				active = document.body;
13199			}
13200
13201			element.wrap( wrapper );
13202
13203			// Fixes #7595 - Elements lose focus when wrapped.
13204			if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
13205				$( active ).trigger( "focus" );
13206			}
13207
13208			// Hotfix for jQuery 1.4 since some change in wrap() seems to actually
13209			// lose the reference to the wrapped element
13210			wrapper = element.parent();
13211
13212			// Transfer positioning properties to the wrapper
13213			if ( element.css( "position" ) === "static" ) {
13214				wrapper.css( { position: "relative" } );
13215				element.css( { position: "relative" } );
13216			} else {
13217				$.extend( props, {
13218					position: element.css( "position" ),
13219					zIndex: element.css( "z-index" )
13220				} );
13221				$.each( [ "top", "left", "bottom", "right" ], function( i, pos ) {
13222					props[ pos ] = element.css( pos );
13223					if ( isNaN( parseInt( props[ pos ], 10 ) ) ) {
13224						props[ pos ] = "auto";
13225					}
13226				} );
13227				element.css( {
13228					position: "relative",
13229					top: 0,
13230					left: 0,
13231					right: "auto",
13232					bottom: "auto"
13233				} );
13234			}
13235			element.css( size );
13236
13237			return wrapper.css( props ).show();
13238		},
13239
13240		removeWrapper: function( element ) {
13241			var active = document.activeElement;
13242
13243			if ( element.parent().is( ".ui-effects-wrapper" ) ) {
13244				element.parent().replaceWith( element );
13245
vendor: 6,832 bytes, lines 13246-13526
13246				// Fixes #7595 - Elements lose focus when wrapped.
13247				if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
13248					$( active ).trigger( "focus" );
13249				}
13250			}
13251
13252			return element;
13253		}
13254	} );
13255}
13256
13257$.extend( $.effects, {
13258	version: "1.13.2",
13259
13260	define: function( name, mode, effect ) {
13261		if ( !effect ) {
13262			effect = mode;
13263			mode = "effect";
13264		}
13265
13266		$.effects.effect[ name ] = effect;
13267		$.effects.effect[ name ].mode = mode;
13268
13269		return effect;
13270	},
13271
13272	scaledDimensions: function( element, percent, direction ) {
13273		if ( percent === 0 ) {
13274			return {
13275				height: 0,
13276				width: 0,
13277				outerHeight: 0,
13278				outerWidth: 0
13279			};
13280		}
13281
13282		var x = direction !== "horizontal" ? ( ( percent || 100 ) / 100 ) : 1,
13283			y = direction !== "vertical" ? ( ( percent || 100 ) / 100 ) : 1;
13284
13285		return {
13286			height: element.height() * y,
13287			width: element.width() * x,
13288			outerHeight: element.outerHeight() * y,
13289			outerWidth: element.outerWidth() * x
13290		};
13291
13292	},
13293
13294	clipToBox: function( animation ) {
13295		return {
13296			width: animation.clip.right - animation.clip.left,
13297			height: animation.clip.bottom - animation.clip.top,
13298			left: animation.clip.left,
13299			top: animation.clip.top
13300		};
13301	},
13302
13303	// Injects recently queued functions to be first in line (after "inprogress")
13304	unshift: function( element, queueLength, count ) {
13305		var queue = element.queue();
13306
13307		if ( queueLength > 1 ) {
13308			queue.splice.apply( queue,
13309				[ 1, 0 ].concat( queue.splice( queueLength, count ) ) );
13310		}
13311		element.dequeue();
13312	},
13313
13314	saveStyle: function( element ) {
13315		element.data( dataSpaceStyle, element[ 0 ].style.cssText );
13316	},
13317
13318	restoreStyle: function( element ) {
13319		element[ 0 ].style.cssText = element.data( dataSpaceStyle ) || "";
13320		element.removeData( dataSpaceStyle );
13321	},
13322
13323	mode: function( element, mode ) {
13324		var hidden = element.is( ":hidden" );
13325
13326		if ( mode === "toggle" ) {
13327			mode = hidden ? "show" : "hide";
13328		}
13329		if ( hidden ? mode === "hide" : mode === "show" ) {
13330			mode = "none";
13331		}
13332		return mode;
13333	},
13334
13335	// Translates a [top,left] array into a baseline value
13336	getBaseline: function( origin, original ) {
13337		var y, x;
13338
13339		switch ( origin[ 0 ] ) {
13340		case "top":
13341			y = 0;
13342			break;
13343		case "middle":
13344			y = 0.5;
13345			break;
13346		case "bottom":
13347			y = 1;
13348			break;
13349		default:
13350			y = origin[ 0 ] / original.height;
13351		}
13352
13353		switch ( origin[ 1 ] ) {
13354		case "left":
13355			x = 0;
13356			break;
13357		case "center":
13358			x = 0.5;
13359			break;
13360		case "right":
13361			x = 1;
13362			break;
13363		default:
13364			x = origin[ 1 ] / original.width;
13365		}
13366
13367		return {
13368			x: x,
13369			y: y
13370		};
13371	},
13372
13373	// Creates a placeholder element so that the original element can be made absolute
13374	createPlaceholder: function( element ) {
13375		var placeholder,
13376			cssPosition = element.css( "position" ),
13377			position = element.position();
13378
13379		// Lock in margins first to account for form elements, which
13380		// will change margin if you explicitly set height
13381		// see: http://jsfiddle.net/JZSMt/3/ https://bugs.webkit.org/show_bug.cgi?id=107380
13382		// Support: Safari
13383		element.css( {
13384			marginTop: element.css( "marginTop" ),
13385			marginBottom: element.css( "marginBottom" ),
13386			marginLeft: element.css( "marginLeft" ),
13387			marginRight: element.css( "marginRight" )
13388		} )
13389		.outerWidth( element.outerWidth() )
13390		.outerHeight( element.outerHeight() );
13391
13392		if ( /^(static|relative)/.test( cssPosition ) ) {
13393			cssPosition = "absolute";
13394
13395			placeholder = $( "<" + element[ 0 ].nodeName + ">" ).insertAfter( element ).css( {
13396
13397				// Convert inline to inline block to account for inline elements
13398				// that turn to inline block based on content (like img)
13399				display: /^(inline|ruby)/.test( element.css( "display" ) ) ?
13400					"inline-block" :
13401					"block",
13402				visibility: "hidden",
13403
13404				// Margins need to be set to account for margin collapse
13405				marginTop: element.css( "marginTop" ),
13406				marginBottom: element.css( "marginBottom" ),
13407				marginLeft: element.css( "marginLeft" ),
13408				marginRight: element.css( "marginRight" ),
13409				"float": element.css( "float" )
13410			} )
13411			.outerWidth( element.outerWidth() )
13412			.outerHeight( element.outerHeight() )
13413			.addClass( "ui-effects-placeholder" );
13414
13415			element.data( dataSpace + "placeholder", placeholder );
13416		}
13417
13418		element.css( {
13419			position: cssPosition,
13420			left: position.left,
13421			top: position.top
13422		} );
13423
13424		return placeholder;
13425	},
13426
13427	removePlaceholder: function( element ) {
13428		var dataKey = dataSpace + "placeholder",
13429				placeholder = element.data( dataKey );
13430
13431		if ( placeholder ) {
13432			placeholder.remove();
13433			element.removeData( dataKey );
13434		}
13435	},
13436
13437	// Removes a placeholder if it exists and restores
13438	// properties that were modified during placeholder creation
13439	cleanUp: function( element ) {
13440		$.effects.restoreStyle( element );
13441		$.effects.removePlaceholder( element );
13442	},
13443
13444	setTransition: function( element, list, factor, value ) {
13445		value = value || {};
13446		$.each( list, function( i, x ) {
13447			var unit = element.cssUnit( x );
13448			if ( unit[ 0 ] > 0 ) {
13449				value[ x ] = unit[ 0 ] * factor + unit[ 1 ];
13450			}
13451		} );
13452		return value;
13453	}
13454} );
13455
13456// Return an effect options object for the given parameters:
13457function _normalizeArguments( effect, options, speed, callback ) {
13458
13459	// Allow passing all options as the first parameter
13460	if ( $.isPlainObject( effect ) ) {
13461		options = effect;
13462		effect = effect.effect;
13463	}
13464
13465	// Convert to an object
13466	effect = { effect: effect };
13467
13468	// Catch (effect, null, ...)
13469	if ( options == null ) {
13470		options = {};
13471	}
13472
13473	// Catch (effect, callback)
13474	if ( typeof options === "function" ) {
13475		callback = options;
13476		speed = null;
13477		options = {};
13478	}
13479
13480	// Catch (effect, speed, ?)
13481	if ( typeof options === "number" || $.fx.speeds[ options ] ) {
13482		callback = speed;
13483		speed = options;
13484		options = {};
13485	}
13486
13487	// Catch (effect, options, callback)
13488	if ( typeof speed === "function" ) {
13489		callback = speed;
13490		speed = null;
13491	}
13492
13493	// Add options to effect
13494	if ( options ) {
13495		$.extend( effect, options );
13496	}
13497
13498	speed = speed || options.duration;
13499	effect.duration = $.fx.off ? 0 :
13500		typeof speed === "number" ? speed :
13501		speed in $.fx.speeds ? $.fx.speeds[ speed ] :
13502		$.fx.speeds._default;
13503
13504	effect.complete = callback || options.complete;
13505
13506	return effect;
13507}
13508
13509function standardAnimationOption( option ) {
13510
13511	// Valid standard speeds (nothing, number, named speed)
13512	if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) {
13513		return true;
13514	}
13515
13516	// Invalid strings - treat as "normal" speed
13517	if ( typeof option === "string" && !$.effects.effect[ option ] ) {
13518		return true;
13519	}
13520
13521	// Complete callback
13522	if ( typeof option === "function" ) {
13523		return true;
13524	}
13525
13526	// Options hash (but not naming an effect)
vendor: 4,998 bytes, lines 13527-13710
13527	if ( typeof option === "object" && !option.effect ) {
13528		return true;
13529	}
13530
13531	// Didn't match any standard API
13532	return false;
13533}
13534
13535$.fn.extend( {
13536	effect: function( /* effect, options, speed, callback */ ) {
13537		var args = _normalizeArguments.apply( this, arguments ),
13538			effectMethod = $.effects.effect[ args.effect ],
13539			defaultMode = effectMethod.mode,
13540			queue = args.queue,
13541			queueName = queue || "fx",
13542			complete = args.complete,
13543			mode = args.mode,
13544			modes = [],
13545			prefilter = function( next ) {
13546				var el = $( this ),
13547					normalizedMode = $.effects.mode( el, mode ) || defaultMode;
13548
13549				// Sentinel for duck-punching the :animated pseudo-selector
13550				el.data( dataSpaceAnimated, true );
13551
13552				// Save effect mode for later use,
13553				// we can't just call $.effects.mode again later,
13554				// as the .show() below destroys the initial state
13555				modes.push( normalizedMode );
13556
13557				// See $.uiBackCompat inside of run() for removal of defaultMode in 1.14
13558				if ( defaultMode && ( normalizedMode === "show" ||
13559						( normalizedMode === defaultMode && normalizedMode === "hide" ) ) ) {
13560					el.show();
13561				}
13562
13563				if ( !defaultMode || normalizedMode !== "none" ) {
13564					$.effects.saveStyle( el );
13565				}
13566
13567				if ( typeof next === "function" ) {
13568					next();
13569				}
13570			};
13571
13572		if ( $.fx.off || !effectMethod ) {
13573
13574			// Delegate to the original method (e.g., .show()) if possible
13575			if ( mode ) {
13576				return this[ mode ]( args.duration, complete );
13577			} else {
13578				return this.each( function() {
13579					if ( complete ) {
13580						complete.call( this );
13581					}
13582				} );
13583			}
13584		}
13585
13586		function run( next ) {
13587			var elem = $( this );
13588
13589			function cleanup() {
13590				elem.removeData( dataSpaceAnimated );
13591
13592				$.effects.cleanUp( elem );
13593
13594				if ( args.mode === "hide" ) {
13595					elem.hide();
13596				}
13597
13598				done();
13599			}
13600
13601			function done() {
13602				if ( typeof complete === "function" ) {
13603					complete.call( elem[ 0 ] );
13604				}
13605
13606				if ( typeof next === "function" ) {
13607					next();
13608				}
13609			}
13610
13611			// Override mode option on a per element basis,
13612			// as toggle can be either show or hide depending on element state
13613			args.mode = modes.shift();
13614
13615			if ( $.uiBackCompat !== false && !defaultMode ) {
13616				if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) {
13617
13618					// Call the core method to track "olddisplay" properly
13619					elem[ mode ]();
13620					done();
13621				} else {
13622					effectMethod.call( elem[ 0 ], args, done );
13623				}
13624			} else {
13625				if ( args.mode === "none" ) {
13626
13627					// Call the core method to track "olddisplay" properly
13628					elem[ mode ]();
13629					done();
13630				} else {
13631					effectMethod.call( elem[ 0 ], args, cleanup );
13632				}
13633			}
13634		}
13635
13636		// Run prefilter on all elements first to ensure that
13637		// any showing or hiding happens before placeholder creation,
13638		// which ensures that any layout changes are correctly captured.
13639		return queue === false ?
13640			this.each( prefilter ).each( run ) :
13641			this.queue( queueName, prefilter ).queue( queueName, run );
13642	},
13643
13644	show: ( function( orig ) {
13645		return function( option ) {
13646			if ( standardAnimationOption( option ) ) {
13647				return orig.apply( this, arguments );
13648			} else {
13649				var args = _normalizeArguments.apply( this, arguments );
13650				args.mode = "show";
13651				return this.effect.call( this, args );
13652			}
13653		};
13654	} )( $.fn.show ),
13655
13656	hide: ( function( orig ) {
13657		return function( option ) {
13658			if ( standardAnimationOption( option ) ) {
13659				return orig.apply( this, arguments );
13660			} else {
13661				var args = _normalizeArguments.apply( this, arguments );
13662				args.mode = "hide";
13663				return this.effect.call( this, args );
13664			}
13665		};
13666	} )( $.fn.hide ),
13667
13668	toggle: ( function( orig ) {
13669		return function( option ) {
13670			if ( standardAnimationOption( option ) || typeof option === "boolean" ) {
13671				return orig.apply( this, arguments );
13672			} else {
13673				var args = _normalizeArguments.apply( this, arguments );
13674				args.mode = "toggle";
13675				return this.effect.call( this, args );
13676			}
13677		};
13678	} )( $.fn.toggle ),
13679
13680	cssUnit: function( key ) {
13681		var style = this.css( key ),
13682			val = [];
13683
13684		$.each( [ "em", "px", "%", "pt" ], function( i, unit ) {
13685			if ( style.indexOf( unit ) > 0 ) {
13686				val = [ parseFloat( style ), unit ];
13687			}
13688		} );
13689		return val;
13690	},
13691
13692	cssClip: function( clipObj ) {
13693		if ( clipObj ) {
13694			return this.css( "clip", "rect(" + clipObj.top + "px " + clipObj.right + "px " +
13695				clipObj.bottom + "px " + clipObj.left + "px)" );
13696		}
13697		return parseClip( this.css( "clip" ), this );
13698	},
13699
13700	transfer: function( options, done ) {
13701		var element = $( this ),
13702			target = $( options.to ),
13703			targetFixed = target.css( "position" ) === "fixed",
13704			body = $( "body" ),
13705			fixTop = targetFixed ? body.scrollTop() : 0,
13706			fixLeft = targetFixed ? body.scrollLeft() : 0,
13707			endPosition = target.offset(),
13708			animation = {
13709				top: endPosition.top - fixTop,
13710				left: endPosition.left - fixLeft,
vendor: 26,433 bytes, lines 13711-14677
13711				height: target.innerHeight(),
13712				width: target.innerWidth()
13713			},
13714			startPosition = element.offset(),
13715			transfer = $( "<div class='ui-effects-transfer'></div>" );
13716
13717		transfer
13718			.appendTo( "body" )
13719			.addClass( options.className )
13720			.css( {
13721				top: startPosition.top - fixTop,
13722				left: startPosition.left - fixLeft,
13723				height: element.innerHeight(),
13724				width: element.innerWidth(),
13725				position: targetFixed ? "fixed" : "absolute"
13726			} )
13727			.animate( animation, options.duration, options.easing, function() {
13728				transfer.remove();
13729				if ( typeof done === "function" ) {
13730					done();
13731				}
13732			} );
13733	}
13734} );
13735
13736function parseClip( str, element ) {
13737		var outerWidth = element.outerWidth(),
13738			outerHeight = element.outerHeight(),
13739			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)\)$/,
13740			values = clipRegex.exec( str ) || [ "", 0, outerWidth, outerHeight, 0 ];
13741
13742		return {
13743			top: parseFloat( values[ 1 ] ) || 0,
13744			right: values[ 2 ] === "auto" ? outerWidth : parseFloat( values[ 2 ] ),
13745			bottom: values[ 3 ] === "auto" ? outerHeight : parseFloat( values[ 3 ] ),
13746			left: parseFloat( values[ 4 ] ) || 0
13747		};
13748}
13749
13750$.fx.step.clip = function( fx ) {
13751	if ( !fx.clipInit ) {
13752		fx.start = $( fx.elem ).cssClip();
13753		if ( typeof fx.end === "string" ) {
13754			fx.end = parseClip( fx.end, fx.elem );
13755		}
13756		fx.clipInit = true;
13757	}
13758
13759	$( fx.elem ).cssClip( {
13760		top: fx.pos * ( fx.end.top - fx.start.top ) + fx.start.top,
13761		right: fx.pos * ( fx.end.right - fx.start.right ) + fx.start.right,
13762		bottom: fx.pos * ( fx.end.bottom - fx.start.bottom ) + fx.start.bottom,
13763		left: fx.pos * ( fx.end.left - fx.start.left ) + fx.start.left
13764	} );
13765};
13766
13767} )();
13768
13769/******************************************************************************/
13770/*********************************** EASING ***********************************/
13771/******************************************************************************/
13772
13773( function() {
13774
13775// Based on easing equations from Robert Penner (http://www.robertpenner.com/easing)
13776
13777var baseEasings = {};
13778
13779$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) {
13780	baseEasings[ name ] = function( p ) {
13781		return Math.pow( p, i + 2 );
13782	};
13783} );
13784
13785$.extend( baseEasings, {
13786	Sine: function( p ) {
13787		return 1 - Math.cos( p * Math.PI / 2 );
13788	},
13789	Circ: function( p ) {
13790		return 1 - Math.sqrt( 1 - p * p );
13791	},
13792	Elastic: function( p ) {
13793		return p === 0 || p === 1 ? p :
13794			-Math.pow( 2, 8 * ( p - 1 ) ) * Math.sin( ( ( p - 1 ) * 80 - 7.5 ) * Math.PI / 15 );
13795	},
13796	Back: function( p ) {
13797		return p * p * ( 3 * p - 2 );
13798	},
13799	Bounce: function( p ) {
13800		var pow2,
13801			bounce = 4;
13802
13803		while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}
13804		return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 );
13805	}
13806} );
13807
13808$.each( baseEasings, function( name, easeIn ) {
13809	$.easing[ "easeIn" + name ] = easeIn;
13810	$.easing[ "easeOut" + name ] = function( p ) {
13811		return 1 - easeIn( 1 - p );
13812	};
13813	$.easing[ "easeInOut" + name ] = function( p ) {
13814		return p < 0.5 ?
13815			easeIn( p * 2 ) / 2 :
13816			1 - easeIn( p * -2 + 2 ) / 2;
13817	};
13818} );
13819
13820} )();
13821
13822var effect = $.effects;
13823
13824
13825/*!
13826 * jQuery UI Effects Blind 1.13.2
13827 * http://jqueryui.com
13828 *
13829 * Copyright jQuery Foundation and other contributors
13830 * Released under the MIT license.
13831 * http://jquery.org/license
13832 */
13833
13834//>>label: Blind Effect
13835//>>group: Effects
13836//>>description: Blinds the element.
13837//>>docs: http://api.jqueryui.com/blind-effect/
13838//>>demos: http://jqueryui.com/effect/
13839
13840
13841var effectsEffectBlind = $.effects.define( "blind", "hide", function( options, done ) {
13842	var map = {
13843			up: [ "bottom", "top" ],
13844			vertical: [ "bottom", "top" ],
13845			down: [ "top", "bottom" ],
13846			left: [ "right", "left" ],
13847			horizontal: [ "right", "left" ],
13848			right: [ "left", "right" ]
13849		},
13850		element = $( this ),
13851		direction = options.direction || "up",
13852		start = element.cssClip(),
13853		animate = { clip: $.extend( {}, start ) },
13854		placeholder = $.effects.createPlaceholder( element );
13855
13856	animate.clip[ map[ direction ][ 0 ] ] = animate.clip[ map[ direction ][ 1 ] ];
13857
13858	if ( options.mode === "show" ) {
13859		element.cssClip( animate.clip );
13860		if ( placeholder ) {
13861			placeholder.css( $.effects.clipToBox( animate ) );
13862		}
13863
13864		animate.clip = start;
13865	}
13866
13867	if ( placeholder ) {
13868		placeholder.animate( $.effects.clipToBox( animate ), options.duration, options.easing );
13869	}
13870
13871	element.animate( animate, {
13872		queue: false,
13873		duration: options.duration,
13874		easing: options.easing,
13875		complete: done
13876	} );
13877} );
13878
13879
13880/*!
13881 * jQuery UI Effects Bounce 1.13.2
13882 * http://jqueryui.com
13883 *
13884 * Copyright jQuery Foundation and other contributors
13885 * Released under the MIT license.
13886 * http://jquery.org/license
13887 */
13888
13889//>>label: Bounce Effect
13890//>>group: Effects
13891//>>description: Bounces an element horizontally or vertically n times.
13892//>>docs: http://api.jqueryui.com/bounce-effect/
13893//>>demos: http://jqueryui.com/effect/
13894
13895
13896var effectsEffectBounce = $.effects.define( "bounce", function( options, done ) {
13897	var upAnim, downAnim, refValue,
13898		element = $( this ),
13899
13900		// Defaults:
13901		mode = options.mode,
13902		hide = mode === "hide",
13903		show = mode === "show",
13904		direction = options.direction || "up",
13905		distance = options.distance,
13906		times = options.times || 5,
13907
13908		// Number of internal animations
13909		anims = times * 2 + ( show || hide ? 1 : 0 ),
13910		speed = options.duration / anims,
13911		easing = options.easing,
13912
13913		// Utility:
13914		ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
13915		motion = ( direction === "up" || direction === "left" ),
13916		i = 0,
13917
13918		queuelen = element.queue().length;
13919
13920	$.effects.createPlaceholder( element );
13921
13922	refValue = element.css( ref );
13923
13924	// Default distance for the BIGGEST bounce is the outer Distance / 3
13925	if ( !distance ) {
13926		distance = element[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3;
13927	}
13928
13929	if ( show ) {
13930		downAnim = { opacity: 1 };
13931		downAnim[ ref ] = refValue;
13932
13933		// If we are showing, force opacity 0 and set the initial position
13934		// then do the "first" animation
13935		element
13936			.css( "opacity", 0 )
13937			.css( ref, motion ? -distance * 2 : distance * 2 )
13938			.animate( downAnim, speed, easing );
13939	}
13940
13941	// Start at the smallest distance if we are hiding
13942	if ( hide ) {
13943		distance = distance / Math.pow( 2, times - 1 );
13944	}
13945
13946	downAnim = {};
13947	downAnim[ ref ] = refValue;
13948
13949	// Bounces up/down/left/right then back to 0 -- times * 2 animations happen here
13950	for ( ; i < times; i++ ) {
13951		upAnim = {};
13952		upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
13953
13954		element
13955			.animate( upAnim, speed, easing )
13956			.animate( downAnim, speed, easing );
13957
13958		distance = hide ? distance * 2 : distance / 2;
13959	}
13960
13961	// Last Bounce when Hiding
13962	if ( hide ) {
13963		upAnim = { opacity: 0 };
13964		upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
13965
13966		element.animate( upAnim, speed, easing );
13967	}
13968
13969	element.queue( done );
13970
13971	$.effects.unshift( element, queuelen, anims + 1 );
13972} );
13973
13974
13975/*!
13976 * jQuery UI Effects Clip 1.13.2
13977 * http://jqueryui.com
13978 *
13979 * Copyright jQuery Foundation and other contributors
13980 * Released under the MIT license.
13981 * http://jquery.org/license
13982 */
13983
13984//>>label: Clip Effect
13985//>>group: Effects
13986//>>description: Clips the element on and off like an old TV.
13987//>>docs: http://api.jqueryui.com/clip-effect/
13988//>>demos: http://jqueryui.com/effect/
13989
13990
13991var effectsEffectClip = $.effects.define( "clip", "hide", function( options, done ) {
13992	var start,
13993		animate = {},
13994		element = $( this ),
13995		direction = options.direction || "vertical",
13996		both = direction === "both",
13997		horizontal = both || direction === "horizontal",
13998		vertical = both || direction === "vertical";
13999
14000	start = element.cssClip();
14001	animate.clip = {
14002		top: vertical ? ( start.bottom - start.top ) / 2 : start.top,
14003		right: horizontal ? ( start.right - start.left ) / 2 : start.right,
14004		bottom: vertical ? ( start.bottom - start.top ) / 2 : start.bottom,
14005		left: horizontal ? ( start.right - start.left ) / 2 : start.left
14006	};
14007
14008	$.effects.createPlaceholder( element );
14009
14010	if ( options.mode === "show" ) {
14011		element.cssClip( animate.clip );
14012		animate.clip = start;
14013	}
14014
14015	element.animate( animate, {
14016		queue: false,
14017		duration: options.duration,
14018		easing: options.easing,
14019		complete: done
14020	} );
14021
14022} );
14023
14024
14025/*!
14026 * jQuery UI Effects Drop 1.13.2
14027 * http://jqueryui.com
14028 *
14029 * Copyright jQuery Foundation and other contributors
14030 * Released under the MIT license.
14031 * http://jquery.org/license
14032 */
14033
14034//>>label: Drop Effect
14035//>>group: Effects
14036//>>description: Moves an element in one direction and hides it at the same time.
14037//>>docs: http://api.jqueryui.com/drop-effect/
14038//>>demos: http://jqueryui.com/effect/
14039
14040
14041var effectsEffectDrop = $.effects.define( "drop", "hide", function( options, done ) {
14042
14043	var distance,
14044		element = $( this ),
14045		mode = options.mode,
14046		show = mode === "show",
14047		direction = options.direction || "left",
14048		ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
14049		motion = ( direction === "up" || direction === "left" ) ? "-=" : "+=",
14050		oppositeMotion = ( motion === "+=" ) ? "-=" : "+=",
14051		animation = {
14052			opacity: 0
14053		};
14054
14055	$.effects.createPlaceholder( element );
14056
14057	distance = options.distance ||
14058		element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ) / 2;
14059
14060	animation[ ref ] = motion + distance;
14061
14062	if ( show ) {
14063		element.css( animation );
14064
14065		animation[ ref ] = oppositeMotion + distance;
14066		animation.opacity = 1;
14067	}
14068
14069	// Animate
14070	element.animate( animation, {
14071		queue: false,
14072		duration: options.duration,
14073		easing: options.easing,
14074		complete: done
14075	} );
14076} );
14077
14078
14079/*!
14080 * jQuery UI Effects Explode 1.13.2
14081 * http://jqueryui.com
14082 *
14083 * Copyright jQuery Foundation and other contributors
14084 * Released under the MIT license.
14085 * http://jquery.org/license
14086 */
14087
14088//>>label: Explode Effect
14089//>>group: Effects
14090/* eslint-disable max-len */
14091//>>description: Explodes an element in all directions into n pieces. Implodes an element to its original wholeness.
14092/* eslint-enable max-len */
14093//>>docs: http://api.jqueryui.com/explode-effect/
14094//>>demos: http://jqueryui.com/effect/
14095
14096
14097var effectsEffectExplode = $.effects.define( "explode", "hide", function( options, done ) {
14098
14099	var i, j, left, top, mx, my,
14100		rows = options.pieces ? Math.round( Math.sqrt( options.pieces ) ) : 3,
14101		cells = rows,
14102		element = $( this ),
14103		mode = options.mode,
14104		show = mode === "show",
14105
14106		// Show and then visibility:hidden the element before calculating offset
14107		offset = element.show().css( "visibility", "hidden" ).offset(),
14108
14109		// Width and height of a piece
14110		width = Math.ceil( element.outerWidth() / cells ),
14111		height = Math.ceil( element.outerHeight() / rows ),
14112		pieces = [];
14113
14114	// Children animate complete:
14115	function childComplete() {
14116		pieces.push( this );
14117		if ( pieces.length === rows * cells ) {
14118			animComplete();
14119		}
14120	}
14121
14122	// Clone the element for each row and cell.
14123	for ( i = 0; i < rows; i++ ) { // ===>
14124		top = offset.top + i * height;
14125		my = i - ( rows - 1 ) / 2;
14126
14127		for ( j = 0; j < cells; j++ ) { // |||
14128			left = offset.left + j * width;
14129			mx = j - ( cells - 1 ) / 2;
14130
14131			// Create a clone of the now hidden main element that will be absolute positioned
14132			// within a wrapper div off the -left and -top equal to size of our pieces
14133			element
14134				.clone()
14135				.appendTo( "body" )
14136				.wrap( "<div></div>" )
14137				.css( {
14138					position: "absolute",
14139					visibility: "visible",
14140					left: -j * width,
14141					top: -i * height
14142				} )
14143
14144				// Select the wrapper - make it overflow: hidden and absolute positioned based on
14145				// where the original was located +left and +top equal to the size of pieces
14146				.parent()
14147					.addClass( "ui-effects-explode" )
14148					.css( {
14149						position: "absolute",
14150						overflow: "hidden",
14151						width: width,
14152						height: height,
14153						left: left + ( show ? mx * width : 0 ),
14154						top: top + ( show ? my * height : 0 ),
14155						opacity: show ? 0 : 1
14156					} )
14157					.animate( {
14158						left: left + ( show ? 0 : mx * width ),
14159						top: top + ( show ? 0 : my * height ),
14160						opacity: show ? 1 : 0
14161					}, options.duration || 500, options.easing, childComplete );
14162		}
14163	}
14164
14165	function animComplete() {
14166		element.css( {
14167			visibility: "visible"
14168		} );
14169		$( pieces ).remove();
14170		done();
14171	}
14172} );
14173
14174
14175/*!
14176 * jQuery UI Effects Fade 1.13.2
14177 * http://jqueryui.com
14178 *
14179 * Copyright jQuery Foundation and other contributors
14180 * Released under the MIT license.
14181 * http://jquery.org/license
14182 */
14183
14184//>>label: Fade Effect
14185//>>group: Effects
14186//>>description: Fades the element.
14187//>>docs: http://api.jqueryui.com/fade-effect/
14188//>>demos: http://jqueryui.com/effect/
14189
14190
14191var effectsEffectFade = $.effects.define( "fade", "toggle", function( options, done ) {
14192	var show = options.mode === "show";
14193
14194	$( this )
14195		.css( "opacity", show ? 0 : 1 )
14196		.animate( {
14197			opacity: show ? 1 : 0
14198		}, {
14199			queue: false,
14200			duration: options.duration,
14201			easing: options.easing,
14202			complete: done
14203		} );
14204} );
14205
14206
14207/*!
14208 * jQuery UI Effects Fold 1.13.2
14209 * http://jqueryui.com
14210 *
14211 * Copyright jQuery Foundation and other contributors
14212 * Released under the MIT license.
14213 * http://jquery.org/license
14214 */
14215
14216//>>label: Fold Effect
14217//>>group: Effects
14218//>>description: Folds an element first horizontally and then vertically.
14219//>>docs: http://api.jqueryui.com/fold-effect/
14220//>>demos: http://jqueryui.com/effect/
14221
14222
14223var effectsEffectFold = $.effects.define( "fold", "hide", function( options, done ) {
14224
14225	// Create element
14226	var element = $( this ),
14227		mode = options.mode,
14228		show = mode === "show",
14229		hide = mode === "hide",
14230		size = options.size || 15,
14231		percent = /([0-9]+)%/.exec( size ),
14232		horizFirst = !!options.horizFirst,
14233		ref = horizFirst ? [ "right", "bottom" ] : [ "bottom", "right" ],
14234		duration = options.duration / 2,
14235
14236		placeholder = $.effects.createPlaceholder( element ),
14237
14238		start = element.cssClip(),
14239		animation1 = { clip: $.extend( {}, start ) },
14240		animation2 = { clip: $.extend( {}, start ) },
14241
14242		distance = [ start[ ref[ 0 ] ], start[ ref[ 1 ] ] ],
14243
14244		queuelen = element.queue().length;
14245
14246	if ( percent ) {
14247		size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ];
14248	}
14249	animation1.clip[ ref[ 0 ] ] = size;
14250	animation2.clip[ ref[ 0 ] ] = size;
14251	animation2.clip[ ref[ 1 ] ] = 0;
14252
14253	if ( show ) {
14254		element.cssClip( animation2.clip );
14255		if ( placeholder ) {
14256			placeholder.css( $.effects.clipToBox( animation2 ) );
14257		}
14258
14259		animation2.clip = start;
14260	}
14261
14262	// Animate
14263	element
14264		.queue( function( next ) {
14265			if ( placeholder ) {
14266				placeholder
14267					.animate( $.effects.clipToBox( animation1 ), duration, options.easing )
14268					.animate( $.effects.clipToBox( animation2 ), duration, options.easing );
14269			}
14270
14271			next();
14272		} )
14273		.animate( animation1, duration, options.easing )
14274		.animate( animation2, duration, options.easing )
14275		.queue( done );
14276
14277	$.effects.unshift( element, queuelen, 4 );
14278} );
14279
14280
14281/*!
14282 * jQuery UI Effects Highlight 1.13.2
14283 * http://jqueryui.com
14284 *
14285 * Copyright jQuery Foundation and other contributors
14286 * Released under the MIT license.
14287 * http://jquery.org/license
14288 */
14289
14290//>>label: Highlight Effect
14291//>>group: Effects
14292//>>description: Highlights the background of an element in a defined color for a custom duration.
14293//>>docs: http://api.jqueryui.com/highlight-effect/
14294//>>demos: http://jqueryui.com/effect/
14295
14296
14297var effectsEffectHighlight = $.effects.define( "highlight", "show", function( options, done ) {
14298	var element = $( this ),
14299		animation = {
14300			backgroundColor: element.css( "backgroundColor" )
14301		};
14302
14303	if ( options.mode === "hide" ) {
14304		animation.opacity = 0;
14305	}
14306
14307	$.effects.saveStyle( element );
14308
14309	element
14310		.css( {
14311			backgroundImage: "none",
14312			backgroundColor: options.color || "#ffff99"
14313		} )
14314		.animate( animation, {
14315			queue: false,
14316			duration: options.duration,
14317			easing: options.easing,
14318			complete: done
14319		} );
14320} );
14321
14322
14323/*!
14324 * jQuery UI Effects Size 1.13.2
14325 * http://jqueryui.com
14326 *
14327 * Copyright jQuery Foundation and other contributors
14328 * Released under the MIT license.
14329 * http://jquery.org/license
14330 */
14331
14332//>>label: Size Effect
14333//>>group: Effects
14334//>>description: Resize an element to a specified width and height.
14335//>>docs: http://api.jqueryui.com/size-effect/
14336//>>demos: http://jqueryui.com/effect/
14337
14338
14339var effectsEffectSize = $.effects.define( "size", function( options, done ) {
14340
14341	// Create element
14342	var baseline, factor, temp,
14343		element = $( this ),
14344
14345		// Copy for children
14346		cProps = [ "fontSize" ],
14347		vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ],
14348		hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ],
14349
14350		// Set options
14351		mode = options.mode,
14352		restore = mode !== "effect",
14353		scale = options.scale || "both",
14354		origin = options.origin || [ "middle", "center" ],
14355		position = element.css( "position" ),
14356		pos = element.position(),
14357		original = $.effects.scaledDimensions( element ),
14358		from = options.from || original,
14359		to = options.to || $.effects.scaledDimensions( element, 0 );
14360
14361	$.effects.createPlaceholder( element );
14362
14363	if ( mode === "show" ) {
14364		temp = from;
14365		from = to;
14366		to = temp;
14367	}
14368
14369	// Set scaling factor
14370	factor = {
14371		from: {
14372			y: from.height / original.height,
14373			x: from.width / original.width
14374		},
14375		to: {
14376			y: to.height / original.height,
14377			x: to.width / original.width
14378		}
14379	};
14380
14381	// Scale the css box
14382	if ( scale === "box" || scale === "both" ) {
14383
14384		// Vertical props scaling
14385		if ( factor.from.y !== factor.to.y ) {
14386			from = $.effects.setTransition( element, vProps, factor.from.y, from );
14387			to = $.effects.setTransition( element, vProps, factor.to.y, to );
14388		}
14389
14390		// Horizontal props scaling
14391		if ( factor.from.x !== factor.to.x ) {
14392			from = $.effects.setTransition( element, hProps, factor.from.x, from );
14393			to = $.effects.setTransition( element, hProps, factor.to.x, to );
14394		}
14395	}
14396
14397	// Scale the content
14398	if ( scale === "content" || scale === "both" ) {
14399
14400		// Vertical props scaling
14401		if ( factor.from.y !== factor.to.y ) {
14402			from = $.effects.setTransition( element, cProps, factor.from.y, from );
14403			to = $.effects.setTransition( element, cProps, factor.to.y, to );
14404		}
14405	}
14406
14407	// Adjust the position properties based on the provided origin points
14408	if ( origin ) {
14409		baseline = $.effects.getBaseline( origin, original );
14410		from.top = ( original.outerHeight - from.outerHeight ) * baseline.y + pos.top;
14411		from.left = ( original.outerWidth - from.outerWidth ) * baseline.x + pos.left;
14412		to.top = ( original.outerHeight - to.outerHeight ) * baseline.y + pos.top;
14413		to.left = ( original.outerWidth - to.outerWidth ) * baseline.x + pos.left;
14414	}
14415	delete from.outerHeight;
14416	delete from.outerWidth;
14417	element.css( from );
14418
14419	// Animate the children if desired
14420	if ( scale === "content" || scale === "both" ) {
14421
14422		vProps = vProps.concat( [ "marginTop", "marginBottom" ] ).concat( cProps );
14423		hProps = hProps.concat( [ "marginLeft", "marginRight" ] );
14424
14425		// Only animate children with width attributes specified
14426		// TODO: is this right? should we include anything with css width specified as well
14427		element.find( "*[width]" ).each( function() {
14428			var child = $( this ),
14429				childOriginal = $.effects.scaledDimensions( child ),
14430				childFrom = {
14431					height: childOriginal.height * factor.from.y,
14432					width: childOriginal.width * factor.from.x,
14433					outerHeight: childOriginal.outerHeight * factor.from.y,
14434					outerWidth: childOriginal.outerWidth * factor.from.x
14435				},
14436				childTo = {
14437					height: childOriginal.height * factor.to.y,
14438					width: childOriginal.width * factor.to.x,
14439					outerHeight: childOriginal.height * factor.to.y,
14440					outerWidth: childOriginal.width * factor.to.x
14441				};
14442
14443			// Vertical props scaling
14444			if ( factor.from.y !== factor.to.y ) {
14445				childFrom = $.effects.setTransition( child, vProps, factor.from.y, childFrom );
14446				childTo = $.effects.setTransition( child, vProps, factor.to.y, childTo );
14447			}
14448
14449			// Horizontal props scaling
14450			if ( factor.from.x !== factor.to.x ) {
14451				childFrom = $.effects.setTransition( child, hProps, factor.from.x, childFrom );
14452				childTo = $.effects.setTransition( child, hProps, factor.to.x, childTo );
14453			}
14454
14455			if ( restore ) {
14456				$.effects.saveStyle( child );
14457			}
14458
14459			// Animate children
14460			child.css( childFrom );
14461			child.animate( childTo, options.duration, options.easing, function() {
14462
14463				// Restore children
14464				if ( restore ) {
14465					$.effects.restoreStyle( child );
14466				}
14467			} );
14468		} );
14469	}
14470
14471	// Animate
14472	element.animate( to, {
14473		queue: false,
14474		duration: options.duration,
14475		easing: options.easing,
14476		complete: function() {
14477
14478			var offset = element.offset();
14479
14480			if ( to.opacity === 0 ) {
14481				element.css( "opacity", from.opacity );
14482			}
14483
14484			if ( !restore ) {
14485				element
14486					.css( "position", position === "static" ? "relative" : position )
14487					.offset( offset );
14488
14489				// Need to save style here so that automatic style restoration
14490				// doesn't restore to the original styles from before the animation.
14491				$.effects.saveStyle( element );
14492			}
14493
14494			done();
14495		}
14496	} );
14497
14498} );
14499
14500
14501/*!
14502 * jQuery UI Effects Scale 1.13.2
14503 * http://jqueryui.com
14504 *
14505 * Copyright jQuery Foundation and other contributors
14506 * Released under the MIT license.
14507 * http://jquery.org/license
14508 */
14509
14510//>>label: Scale Effect
14511//>>group: Effects
14512//>>description: Grows or shrinks an element and its content.
14513//>>docs: http://api.jqueryui.com/scale-effect/
14514//>>demos: http://jqueryui.com/effect/
14515
14516
14517var effectsEffectScale = $.effects.define( "scale", function( options, done ) {
14518
14519	// Create element
14520	var el = $( this ),
14521		mode = options.mode,
14522		percent = parseInt( options.percent, 10 ) ||
14523			( parseInt( options.percent, 10 ) === 0 ? 0 : ( mode !== "effect" ? 0 : 100 ) ),
14524
14525		newOptions = $.extend( true, {
14526			from: $.effects.scaledDimensions( el ),
14527			to: $.effects.scaledDimensions( el, percent, options.direction || "both" ),
14528			origin: options.origin || [ "middle", "center" ]
14529		}, options );
14530
14531	// Fade option to support puff
14532	if ( options.fade ) {
14533		newOptions.from.opacity = 1;
14534		newOptions.to.opacity = 0;
14535	}
14536
14537	$.effects.effect.size.call( this, newOptions, done );
14538} );
14539
14540
14541/*!
14542 * jQuery UI Effects Puff 1.13.2
14543 * http://jqueryui.com
14544 *
14545 * Copyright jQuery Foundation and other contributors
14546 * Released under the MIT license.
14547 * http://jquery.org/license
14548 */
14549
14550//>>label: Puff Effect
14551//>>group: Effects
14552//>>description: Creates a puff effect by scaling the element up and hiding it at the same time.
14553//>>docs: http://api.jqueryui.com/puff-effect/
14554//>>demos: http://jqueryui.com/effect/
14555
14556
14557var effectsEffectPuff = $.effects.define( "puff", "hide", function( options, done ) {
14558	var newOptions = $.extend( true, {}, options, {
14559		fade: true,
14560		percent: parseInt( options.percent, 10 ) || 150
14561	} );
14562
14563	$.effects.effect.scale.call( this, newOptions, done );
14564} );
14565
14566
14567/*!
14568 * jQuery UI Effects Pulsate 1.13.2
14569 * http://jqueryui.com
14570 *
14571 * Copyright jQuery Foundation and other contributors
14572 * Released under the MIT license.
14573 * http://jquery.org/license
14574 */
14575
14576//>>label: Pulsate Effect
14577//>>group: Effects
14578//>>description: Pulsates an element n times by changing the opacity to zero and back.
14579//>>docs: http://api.jqueryui.com/pulsate-effect/
14580//>>demos: http://jqueryui.com/effect/
14581
14582
14583var effectsEffectPulsate = $.effects.define( "pulsate", "show", function( options, done ) {
14584	var element = $( this ),
14585		mode = options.mode,
14586		show = mode === "show",
14587		hide = mode === "hide",
14588		showhide = show || hide,
14589
14590		// Showing or hiding leaves off the "last" animation
14591		anims = ( ( options.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ),
14592		duration = options.duration / anims,
14593		animateTo = 0,
14594		i = 1,
14595		queuelen = element.queue().length;
14596
14597	if ( show || !element.is( ":visible" ) ) {
14598		element.css( "opacity", 0 ).show();
14599		animateTo = 1;
14600	}
14601
14602	// Anims - 1 opacity "toggles"
14603	for ( ; i < anims; i++ ) {
14604		element.animate( { opacity: animateTo }, duration, options.easing );
14605		animateTo = 1 - animateTo;
14606	}
14607
14608	element.animate( { opacity: animateTo }, duration, options.easing );
14609
14610	element.queue( done );
14611
14612	$.effects.unshift( element, queuelen, anims + 1 );
14613} );
14614
14615
14616/*!
14617 * jQuery UI Effects Shake 1.13.2
14618 * http://jqueryui.com
14619 *
14620 * Copyright jQuery Foundation and other contributors
14621 * Released under the MIT license.
14622 * http://jquery.org/license
14623 */
14624
14625//>>label: Shake Effect
14626//>>group: Effects
14627//>>description: Shakes an element horizontally or vertically n times.
14628//>>docs: http://api.jqueryui.com/shake-effect/
14629//>>demos: http://jqueryui.com/effect/
14630
14631
14632var effectsEffectShake = $.effects.define( "shake", function( options, done ) {
14633
14634	var i = 1,
14635		element = $( this ),
14636		direction = options.direction || "left",
14637		distance = options.distance || 20,
14638		times = options.times || 3,
14639		anims = times * 2 + 1,
14640		speed = Math.round( options.duration / anims ),
14641		ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
14642		positiveMotion = ( direction === "up" || direction === "left" ),
14643		animation = {},
14644		animation1 = {},
14645		animation2 = {},
14646
14647		queuelen = element.queue().length;
14648
14649	$.effects.createPlaceholder( element );
14650
14651	// Animation
14652	animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance;
14653	animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2;
14654	animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2;
14655
14656	// Animate
14657	element.animate( animation, speed, options.easing );
14658
14659	// Shakes
14660	for ( ; i < times; i++ ) {
14661		element
14662			.animate( animation1, speed, options.easing )
14663			.animate( animation2, speed, options.easing );
14664	}
14665
14666	element
14667		.animate( animation1, speed, options.easing )
14668		.animate( animation, speed / 2, options.easing )
14669		.queue( done );
14670
14671	$.effects.unshift( element, queuelen, anims + 1 );
14672} );
14673
14674
14675/*!
14676 * jQuery UI Effects Slide 1.13.2
14677 * http://jqueryui.com
vendor: 19,531 bytes, lines 14678-15425
14678 *
14679 * Copyright jQuery Foundation and other contributors
14680 * Released under the MIT license.
14681 * http://jquery.org/license
14682 */
14683
14684//>>label: Slide Effect
14685//>>group: Effects
14686//>>description: Slides an element in and out of the viewport.
14687//>>docs: http://api.jqueryui.com/slide-effect/
14688//>>demos: http://jqueryui.com/effect/
14689
14690
14691var effectsEffectSlide = $.effects.define( "slide", "show", function( options, done ) {
14692	var startClip, startRef,
14693		element = $( this ),
14694		map = {
14695			up: [ "bottom", "top" ],
14696			down: [ "top", "bottom" ],
14697			left: [ "right", "left" ],
14698			right: [ "left", "right" ]
14699		},
14700		mode = options.mode,
14701		direction = options.direction || "left",
14702		ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
14703		positiveMotion = ( direction === "up" || direction === "left" ),
14704		distance = options.distance ||
14705			element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ),
14706		animation = {};
14707
14708	$.effects.createPlaceholder( element );
14709
14710	startClip = element.cssClip();
14711	startRef = element.position()[ ref ];
14712
14713	// Define hide animation
14714	animation[ ref ] = ( positiveMotion ? -1 : 1 ) * distance + startRef;
14715	animation.clip = element.cssClip();
14716	animation.clip[ map[ direction ][ 1 ] ] = animation.clip[ map[ direction ][ 0 ] ];
14717
14718	// Reverse the animation if we're showing
14719	if ( mode === "show" ) {
14720		element.cssClip( animation.clip );
14721		element.css( ref, animation[ ref ] );
14722		animation.clip = startClip;
14723		animation[ ref ] = startRef;
14724	}
14725
14726	// Actually animate
14727	element.animate( animation, {
14728		queue: false,
14729		duration: options.duration,
14730		easing: options.easing,
14731		complete: done
14732	} );
14733} );
14734
14735
14736/*!
14737 * jQuery UI Effects Transfer 1.13.2
14738 * http://jqueryui.com
14739 *
14740 * Copyright jQuery Foundation and other contributors
14741 * Released under the MIT license.
14742 * http://jquery.org/license
14743 */
14744
14745//>>label: Transfer Effect
14746//>>group: Effects
14747//>>description: Displays a transfer effect from one element to another.
14748//>>docs: http://api.jqueryui.com/transfer-effect/
14749//>>demos: http://jqueryui.com/effect/
14750
14751
14752var effect;
14753if ( $.uiBackCompat !== false ) {
14754	effect = $.effects.define( "transfer", function( options, done ) {
14755		$( this ).transfer( options, done );
14756	} );
14757}
14758var effectsEffectTransfer = effect;
14759
14760
14761/*!
14762 * jQuery UI Focusable 1.13.2
14763 * http://jqueryui.com
14764 *
14765 * Copyright jQuery Foundation and other contributors
14766 * Released under the MIT license.
14767 * http://jquery.org/license
14768 */
14769
14770//>>label: :focusable Selector
14771//>>group: Core
14772//>>description: Selects elements which can be focused.
14773//>>docs: http://api.jqueryui.com/focusable-selector/
14774
14775
14776// Selectors
14777$.ui.focusable = function( element, hasTabindex ) {
14778	var map, mapName, img, focusableIfVisible, fieldset,
14779		nodeName = element.nodeName.toLowerCase();
14780
14781	if ( "area" === nodeName ) {
14782		map = element.parentNode;
14783		mapName = map.name;
14784		if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
14785			return false;
14786		}
14787		img = $( "img[usemap='#" + mapName + "']" );
14788		return img.length > 0 && img.is( ":visible" );
14789	}
14790
14791	if ( /^(input|select|textarea|button|object)$/.test( nodeName ) ) {
14792		focusableIfVisible = !element.disabled;
14793
14794		if ( focusableIfVisible ) {
14795
14796			// Form controls within a disabled fieldset are disabled.
14797			// However, controls within the fieldset's legend do not get disabled.
14798			// Since controls generally aren't placed inside legends, we skip
14799			// this portion of the check.
14800			fieldset = $( element ).closest( "fieldset" )[ 0 ];
14801			if ( fieldset ) {
14802				focusableIfVisible = !fieldset.disabled;
14803			}
14804		}
14805	} else if ( "a" === nodeName ) {
14806		focusableIfVisible = element.href || hasTabindex;
14807	} else {
14808		focusableIfVisible = hasTabindex;
14809	}
14810
14811	return focusableIfVisible && $( element ).is( ":visible" ) && visible( $( element ) );
14812};
14813
14814// Support: IE 8 only
14815// IE 8 doesn't resolve inherit to visible/hidden for computed values
14816function visible( element ) {
14817	var visibility = element.css( "visibility" );
14818	while ( visibility === "inherit" ) {
14819		element = element.parent();
14820		visibility = element.css( "visibility" );
14821	}
14822	return visibility === "visible";
14823}
14824
14825$.extend( $.expr.pseudos, {
14826	focusable: function( element ) {
14827		return $.ui.focusable( element, $.attr( element, "tabindex" ) != null );
14828	}
14829} );
14830
14831var focusable = $.ui.focusable;
14832
14833
14834
14835// Support: IE8 Only
14836// IE8 does not support the form attribute and when it is supplied. It overwrites the form prop
14837// with a string, so we need to find the proper form.
14838var form = $.fn._form = function() {
14839	return typeof this[ 0 ].form === "string" ? this.closest( "form" ) : $( this[ 0 ].form );
14840};
14841
14842
14843/*!
14844 * jQuery UI Form Reset Mixin 1.13.2
14845 * http://jqueryui.com
14846 *
14847 * Copyright jQuery Foundation and other contributors
14848 * Released under the MIT license.
14849 * http://jquery.org/license
14850 */
14851
14852//>>label: Form Reset Mixin
14853//>>group: Core
14854//>>description: Refresh input widgets when their form is reset
14855//>>docs: http://api.jqueryui.com/form-reset-mixin/
14856
14857
14858var formResetMixin = $.ui.formResetMixin = {
14859	_formResetHandler: function() {
14860		var form = $( this );
14861
14862		// Wait for the form reset to actually happen before refreshing
14863		setTimeout( function() {
14864			var instances = form.data( "ui-form-reset-instances" );
14865			$.each( instances, function() {
14866				this.refresh();
14867			} );
14868		} );
14869	},
14870
14871	_bindFormResetHandler: function() {
14872		this.form = this.element._form();
14873		if ( !this.form.length ) {
14874			return;
14875		}
14876
14877		var instances = this.form.data( "ui-form-reset-instances" ) || [];
14878		if ( !instances.length ) {
14879
14880			// We don't use _on() here because we use a single event handler per form
14881			this.form.on( "reset.ui-form-reset", this._formResetHandler );
14882		}
14883		instances.push( this );
14884		this.form.data( "ui-form-reset-instances", instances );
14885	},
14886
14887	_unbindFormResetHandler: function() {
14888		if ( !this.form.length ) {
14889			return;
14890		}
14891
14892		var instances = this.form.data( "ui-form-reset-instances" );
14893		instances.splice( $.inArray( this, instances ), 1 );
14894		if ( instances.length ) {
14895			this.form.data( "ui-form-reset-instances", instances );
14896		} else {
14897			this.form
14898				.removeData( "ui-form-reset-instances" )
14899				.off( "reset.ui-form-reset" );
14900		}
14901	}
14902};
14903
14904
14905/*!
14906 * jQuery UI Support for jQuery core 1.8.x and newer 1.13.2
14907 * http://jqueryui.com
14908 *
14909 * Copyright jQuery Foundation and other contributors
14910 * Released under the MIT license.
14911 * http://jquery.org/license
14912 *
14913 */
14914
14915//>>label: jQuery 1.8+ Support
14916//>>group: Core
14917//>>description: Support version 1.8.x and newer of jQuery core
14918
14919
14920// Support: jQuery 1.9.x or older
14921// $.expr[ ":" ] is deprecated.
14922if ( !$.expr.pseudos ) {
14923	$.expr.pseudos = $.expr[ ":" ];
14924}
14925
14926// Support: jQuery 1.11.x or older
14927// $.unique has been renamed to $.uniqueSort
14928if ( !$.uniqueSort ) {
14929	$.uniqueSort = $.unique;
14930}
14931
14932// Support: jQuery 2.2.x or older.
14933// This method has been defined in jQuery 3.0.0.
14934// Code from https://github.com/jquery/jquery/blob/e539bac79e666bba95bba86d690b4e609dca2286/src/selector/escapeSelector.js
14935if ( !$.escapeSelector ) {
14936
14937	// CSS string/identifier serialization
14938	// https://drafts.csswg.org/cssom/#common-serializing-idioms
14939	var rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g;
14940
14941	var fcssescape = function( ch, asCodePoint ) {
14942		if ( asCodePoint ) {
14943
14944			// U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER
14945			if ( ch === "\0" ) {
14946				return "\uFFFD";
14947			}
14948
14949			// Control characters and (dependent upon position) numbers get escaped as code points
14950			return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " ";
14951		}
14952
14953		// Other potentially-special ASCII characters get backslash-escaped
14954		return "\\" + ch;
14955	};
14956
14957	$.escapeSelector = function( sel ) {
14958		return ( sel + "" ).replace( rcssescape, fcssescape );
14959	};
14960}
14961
14962// Support: jQuery 3.4.x or older
14963// These methods have been defined in jQuery 3.5.0.
14964if ( !$.fn.even || !$.fn.odd ) {
14965	$.fn.extend( {
14966		even: function() {
14967			return this.filter( function( i ) {
14968				return i % 2 === 0;
14969			} );
14970		},
14971		odd: function() {
14972			return this.filter( function( i ) {
14973				return i % 2 === 1;
14974			} );
14975		}
14976	} );
14977}
14978
14979;
14980/*!
14981 * jQuery UI Keycode 1.13.2
14982 * http://jqueryui.com
14983 *
14984 * Copyright jQuery Foundation and other contributors
14985 * Released under the MIT license.
14986 * http://jquery.org/license
14987 */
14988
14989//>>label: Keycode
14990//>>group: Core
14991//>>description: Provide keycodes as keynames
14992//>>docs: http://api.jqueryui.com/jQuery.ui.keyCode/
14993
14994
14995var keycode = $.ui.keyCode = {
14996	BACKSPACE: 8,
14997	COMMA: 188,
14998	DELETE: 46,
14999	DOWN: 40,
15000	END: 35,
15001	ENTER: 13,
15002	ESCAPE: 27,
15003	HOME: 36,
15004	LEFT: 37,
15005	PAGE_DOWN: 34,
15006	PAGE_UP: 33,
15007	PERIOD: 190,
15008	RIGHT: 39,
15009	SPACE: 32,
15010	TAB: 9,
15011	UP: 38
15012};
15013
15014
15015/*!
15016 * jQuery UI Labels 1.13.2
15017 * http://jqueryui.com
15018 *
15019 * Copyright jQuery Foundation and other contributors
15020 * Released under the MIT license.
15021 * http://jquery.org/license
15022 */
15023
15024//>>label: labels
15025//>>group: Core
15026//>>description: Find all the labels associated with a given input
15027//>>docs: http://api.jqueryui.com/labels/
15028
15029
15030var labels = $.fn.labels = function() {
15031	var ancestor, selector, id, labels, ancestors;
15032
15033	if ( !this.length ) {
15034		return this.pushStack( [] );
15035	}
15036
15037	// Check control.labels first
15038	if ( this[ 0 ].labels && this[ 0 ].labels.length ) {
15039		return this.pushStack( this[ 0 ].labels );
15040	}
15041
15042	// Support: IE <= 11, FF <= 37, Android <= 2.3 only
15043	// Above browsers do not support control.labels. Everything below is to support them
15044	// as well as document fragments. control.labels does not work on document fragments
15045	labels = this.eq( 0 ).parents( "label" );
15046
15047	// Look for the label based on the id
15048	id = this.attr( "id" );
15049	if ( id ) {
15050
15051		// We don't search against the document in case the element
15052		// is disconnected from the DOM
15053		ancestor = this.eq( 0 ).parents().last();
15054
15055		// Get a full set of top level ancestors
15056		ancestors = ancestor.add( ancestor.length ? ancestor.siblings() : this.siblings() );
15057
15058		// Create a selector for the label based on the id
15059		selector = "label[for='" + $.escapeSelector( id ) + "']";
15060
15061		labels = labels.add( ancestors.find( selector ).addBack( selector ) );
15062
15063	}
15064
15065	// Return whatever we have found for labels
15066	return this.pushStack( labels );
15067};
15068
15069
15070/*!
15071 * jQuery UI Scroll Parent 1.13.2
15072 * http://jqueryui.com
15073 *
15074 * Copyright jQuery Foundation and other contributors
15075 * Released under the MIT license.
15076 * http://jquery.org/license
15077 */
15078
15079//>>label: scrollParent
15080//>>group: Core
15081//>>description: Get the closest ancestor element that is scrollable.
15082//>>docs: http://api.jqueryui.com/scrollParent/
15083
15084
15085var scrollParent = $.fn.scrollParent = function( includeHidden ) {
15086	var position = this.css( "position" ),
15087		excludeStaticParent = position === "absolute",
15088		overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/,
15089		scrollParent = this.parents().filter( function() {
15090			var parent = $( this );
15091			if ( excludeStaticParent && parent.css( "position" ) === "static" ) {
15092				return false;
15093			}
15094			return overflowRegex.test( parent.css( "overflow" ) + parent.css( "overflow-y" ) +
15095				parent.css( "overflow-x" ) );
15096		} ).eq( 0 );
15097
15098	return position === "fixed" || !scrollParent.length ?
15099		$( this[ 0 ].ownerDocument || document ) :
15100		scrollParent;
15101};
15102
15103
15104/*!
15105 * jQuery UI Tabbable 1.13.2
15106 * http://jqueryui.com
15107 *
15108 * Copyright jQuery Foundation and other contributors
15109 * Released under the MIT license.
15110 * http://jquery.org/license
15111 */
15112
15113//>>label: :tabbable Selector
15114//>>group: Core
15115//>>description: Selects elements which can be tabbed to.
15116//>>docs: http://api.jqueryui.com/tabbable-selector/
15117
15118
15119var tabbable = $.extend( $.expr.pseudos, {
15120	tabbable: function( element ) {
15121		var tabIndex = $.attr( element, "tabindex" ),
15122			hasTabindex = tabIndex != null;
15123		return ( !hasTabindex || tabIndex >= 0 ) && $.ui.focusable( element, hasTabindex );
15124	}
15125} );
15126
15127
15128/*!
15129 * jQuery UI Unique ID 1.13.2
15130 * http://jqueryui.com
15131 *
15132 * Copyright jQuery Foundation and other contributors
15133 * Released under the MIT license.
15134 * http://jquery.org/license
15135 */
15136
15137//>>label: uniqueId
15138//>>group: Core
15139//>>description: Functions to generate and remove uniqueId's
15140//>>docs: http://api.jqueryui.com/uniqueId/
15141
15142
15143var uniqueId = $.fn.extend( {
15144	uniqueId: ( function() {
15145		var uuid = 0;
15146
15147		return function() {
15148			return this.each( function() {
15149				if ( !this.id ) {
15150					this.id = "ui-id-" + ( ++uuid );
15151				}
15152			} );
15153		};
15154	} )(),
15155
15156	removeUniqueId: function() {
15157		return this.each( function() {
15158			if ( /^ui-id-\d+$/.test( this.id ) ) {
15159				$( this ).removeAttr( "id" );
15160			}
15161		} );
15162	}
15163} );
15164
15165
15166/*!
15167 * jQuery UI Accordion 1.13.2
15168 * http://jqueryui.com
15169 *
15170 * Copyright jQuery Foundation and other contributors
15171 * Released under the MIT license.
15172 * http://jquery.org/license
15173 */
15174
15175//>>label: Accordion
15176//>>group: Widgets
15177/* eslint-disable max-len */
15178//>>description: Displays collapsible content panels for presenting information in a limited amount of space.
15179/* eslint-enable max-len */
15180//>>docs: http://api.jqueryui.com/accordion/
15181//>>demos: http://jqueryui.com/accordion/
15182//>>css.structure: ../../themes/base/core.css
15183//>>css.structure: ../../themes/base/accordion.css
15184//>>css.theme: ../../themes/base/theme.css
15185
15186
15187var widgetsAccordion = $.widget( "ui.accordion", {
15188	version: "1.13.2",
15189	options: {
15190		active: 0,
15191		animate: {},
15192		classes: {
15193			"ui-accordion-header": "ui-corner-top",
15194			"ui-accordion-header-collapsed": "ui-corner-all",
15195			"ui-accordion-content": "ui-corner-bottom"
15196		},
15197		collapsible: false,
15198		event: "click",
15199		header: function( elem ) {
15200			return elem.find( "> li > :first-child" ).add( elem.find( "> :not(li)" ).even() );
15201		},
15202		heightStyle: "auto",
15203		icons: {
15204			activeHeader: "ui-icon-triangle-1-s",
15205			header: "ui-icon-triangle-1-e"
15206		},
15207
15208		// Callbacks
15209		activate: null,
15210		beforeActivate: null
15211	},
15212
15213	hideProps: {
15214		borderTopWidth: "hide",
15215		borderBottomWidth: "hide",
15216		paddingTop: "hide",
15217		paddingBottom: "hide",
15218		height: "hide"
15219	},
15220
15221	showProps: {
15222		borderTopWidth: "show",
15223		borderBottomWidth: "show",
15224		paddingTop: "show",
15225		paddingBottom: "show",
15226		height: "show"
15227	},
15228
15229	_create: function() {
15230		var options = this.options;
15231
15232		this.prevShow = this.prevHide = $();
15233		this._addClass( "ui-accordion", "ui-widget ui-helper-reset" );
15234		this.element.attr( "role", "tablist" );
15235
15236		// Don't allow collapsible: false and active: false / null
15237		if ( !options.collapsible && ( options.active === false || options.active == null ) ) {
15238			options.active = 0;
15239		}
15240
15241		this._processPanels();
15242
15243		// handle negative values
15244		if ( options.active < 0 ) {
15245			options.active += this.headers.length;
15246		}
15247		this._refresh();
15248	},
15249
15250	_getCreateEventData: function() {
15251		return {
15252			header: this.active,
15253			panel: !this.active.length ? $() : this.active.next()
15254		};
15255	},
15256
15257	_createIcons: function() {
15258		var icon, children,
15259			icons = this.options.icons;
15260
15261		if ( icons ) {
15262			icon = $( "<span>" );
15263			this._addClass( icon, "ui-accordion-header-icon", "ui-icon " + icons.header );
15264			icon.prependTo( this.headers );
15265			children = this.active.children( ".ui-accordion-header-icon" );
15266			this._removeClass( children, icons.header )
15267				._addClass( children, null, icons.activeHeader )
15268				._addClass( this.headers, "ui-accordion-icons" );
15269		}
15270	},
15271
15272	_destroyIcons: function() {
15273		this._removeClass( this.headers, "ui-accordion-icons" );
15274		this.headers.children( ".ui-accordion-header-icon" ).remove();
15275	},
15276
15277	_destroy: function() {
15278		var contents;
15279
15280		// Clean up main element
15281		this.element.removeAttr( "role" );
15282
15283		// Clean up headers
15284		this.headers
15285			.removeAttr( "role aria-expanded aria-selected aria-controls tabIndex" )
15286			.removeUniqueId();
15287
15288		this._destroyIcons();
15289
15290		// Clean up content panels
15291		contents = this.headers.next()
15292			.css( "display", "" )
15293			.removeAttr( "role aria-hidden aria-labelledby" )
15294			.removeUniqueId();
15295
15296		if ( this.options.heightStyle !== "content" ) {
15297			contents.css( "height", "" );
15298		}
15299	},
15300
15301	_setOption: function( key, value ) {
15302		if ( key === "active" ) {
15303
15304			// _activate() will handle invalid values and update this.options
15305			this._activate( value );
15306			return;
15307		}
15308
15309		if ( key === "event" ) {
15310			if ( this.options.event ) {
15311				this._off( this.headers, this.options.event );
15312			}
15313			this._setupEvents( value );
15314		}
15315
15316		this._super( key, value );
15317
15318		// Setting collapsible: false while collapsed; open first panel
15319		if ( key === "collapsible" && !value && this.options.active === false ) {
15320			this._activate( 0 );
15321		}
15322
15323		if ( key === "icons" ) {
15324			this._destroyIcons();
15325			if ( value ) {
15326				this._createIcons();
15327			}
15328		}
15329	},
15330
15331	_setOptionDisabled: function( value ) {
15332		this._super( value );
15333
15334		this.element.attr( "aria-disabled", value );
15335
15336		// Support: IE8 Only
15337		// #5332 / #6059 - opacity doesn't cascade to positioned elements in IE
15338		// so we need to add the disabled class to the headers and panels
15339		this._toggleClass( null, "ui-state-disabled", !!value );
15340		this._toggleClass( this.headers.add( this.headers.next() ), null, "ui-state-disabled",
15341			!!value );
15342	},
15343
15344	_keydown: function( event ) {
15345		if ( event.altKey || event.ctrlKey ) {
15346			return;
15347		}
15348
15349		var keyCode = $.ui.keyCode,
15350			length = this.headers.length,
15351			currentIndex = this.headers.index( event.target ),
15352			toFocus = false;
15353
15354		switch ( event.keyCode ) {
15355		case keyCode.RIGHT:
15356		case keyCode.DOWN:
15357			toFocus = this.headers[ ( currentIndex + 1 ) % length ];
15358			break;
15359		case keyCode.LEFT:
15360		case keyCode.UP:
15361			toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
15362			break;
15363		case keyCode.SPACE:
15364		case keyCode.ENTER:
15365			this._eventHandler( event );
15366			break;
15367		case keyCode.HOME:
15368			toFocus = this.headers[ 0 ];
15369			break;
15370		case keyCode.END:
15371			toFocus = this.headers[ length - 1 ];
15372			break;
15373		}
15374
15375		if ( toFocus ) {
15376			$( event.target ).attr( "tabIndex", -1 );
15377			$( toFocus ).attr( "tabIndex", 0 );
15378			$( toFocus ).trigger( "focus" );
15379			event.preventDefault();
15380		}
15381	},
15382
15383	_panelKeyDown: function( event ) {
15384		if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) {
15385			$( event.currentTarget ).prev().trigger( "focus" );
15386		}
15387	},
15388
15389	refresh: function() {
15390		var options = this.options;
15391		this._processPanels();
15392
15393		// Was collapsed or no panel
15394		if ( ( options.active === false && options.collapsible === true ) ||
15395				!this.headers.length ) {
15396			options.active = false;
15397			this.active = $();
15398
15399		// active false only when collapsible is true
15400		} else if ( options.active === false ) {
15401			this._activate( 0 );
15402
15403		// was active, but active panel is gone
15404		} else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
15405
15406			// all remaining panel are disabled
15407			if ( this.headers.length === this.headers.find( ".ui-state-disabled" ).length ) {
15408				options.active = false;
15409				this.active = $();
15410
15411			// activate previous panel
15412			} else {
15413				this._activate( Math.max( 0, options.active - 1 ) );
15414			}
15415
15416		// was active, active panel still exists
15417		} else {
15418
15419			// make sure active index is correct
15420			options.active = this.headers.index( this.active );
15421		}
15422
15423		this._destroyIcons();
15424
15425		this._refresh();
vendor: 6,928 bytes, lines 15426-15667
15426	},
15427
15428	_processPanels: function() {
15429		var prevHeaders = this.headers,
15430			prevPanels = this.panels;
15431
15432		if ( typeof this.options.header === "function" ) {
15433			this.headers = this.options.header( this.element );
15434		} else {
15435			this.headers = this.element.find( this.options.header );
15436		}
15437		this._addClass( this.headers, "ui-accordion-header ui-accordion-header-collapsed",
15438			"ui-state-default" );
15439
15440		this.panels = this.headers.next().filter( ":not(.ui-accordion-content-active)" ).hide();
15441		this._addClass( this.panels, "ui-accordion-content", "ui-helper-reset ui-widget-content" );
15442
15443		// Avoid memory leaks (#10056)
15444		if ( prevPanels ) {
15445			this._off( prevHeaders.not( this.headers ) );
15446			this._off( prevPanels.not( this.panels ) );
15447		}
15448	},
15449
15450	_refresh: function() {
15451		var maxHeight,
15452			options = this.options,
15453			heightStyle = options.heightStyle,
15454			parent = this.element.parent();
15455
15456		this.active = this._findActive( options.active );
15457		this._addClass( this.active, "ui-accordion-header-active", "ui-state-active" )
15458			._removeClass( this.active, "ui-accordion-header-collapsed" );
15459		this._addClass( this.active.next(), "ui-accordion-content-active" );
15460		this.active.next().show();
15461
15462		this.headers
15463			.attr( "role", "tab" )
15464			.each( function() {
15465				var header = $( this ),
15466					headerId = header.uniqueId().attr( "id" ),
15467					panel = header.next(),
15468					panelId = panel.uniqueId().attr( "id" );
15469				header.attr( "aria-controls", panelId );
15470				panel.attr( "aria-labelledby", headerId );
15471			} )
15472			.next()
15473				.attr( "role", "tabpanel" );
15474
15475		this.headers
15476			.not( this.active )
15477				.attr( {
15478					"aria-selected": "false",
15479					"aria-expanded": "false",
15480					tabIndex: -1
15481				} )
15482				.next()
15483					.attr( {
15484						"aria-hidden": "true"
15485					} )
15486					.hide();
15487
15488		// Make sure at least one header is in the tab order
15489		if ( !this.active.length ) {
15490			this.headers.eq( 0 ).attr( "tabIndex", 0 );
15491		} else {
15492			this.active.attr( {
15493				"aria-selected": "true",
15494				"aria-expanded": "true",
15495				tabIndex: 0
15496			} )
15497				.next()
15498					.attr( {
15499						"aria-hidden": "false"
15500					} );
15501		}
15502
15503		this._createIcons();
15504
15505		this._setupEvents( options.event );
15506
15507		if ( heightStyle === "fill" ) {
15508			maxHeight = parent.height();
15509			this.element.siblings( ":visible" ).each( function() {
15510				var elem = $( this ),
15511					position = elem.css( "position" );
15512
15513				if ( position === "absolute" || position === "fixed" ) {
15514					return;
15515				}
15516				maxHeight -= elem.outerHeight( true );
15517			} );
15518
15519			this.headers.each( function() {
15520				maxHeight -= $( this ).outerHeight( true );
15521			} );
15522
15523			this.headers.next()
15524				.each( function() {
15525					$( this ).height( Math.max( 0, maxHeight -
15526						$( this ).innerHeight() + $( this ).height() ) );
15527				} )
15528				.css( "overflow", "auto" );
15529		} else if ( heightStyle === "auto" ) {
15530			maxHeight = 0;
15531			this.headers.next()
15532				.each( function() {
15533					var isVisible = $( this ).is( ":visible" );
15534					if ( !isVisible ) {
15535						$( this ).show();
15536					}
15537					maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() );
15538					if ( !isVisible ) {
15539						$( this ).hide();
15540					}
15541				} )
15542				.height( maxHeight );
15543		}
15544	},
15545
15546	_activate: function( index ) {
15547		var active = this._findActive( index )[ 0 ];
15548
15549		// Trying to activate the already active panel
15550		if ( active === this.active[ 0 ] ) {
15551			return;
15552		}
15553
15554		// Trying to collapse, simulate a click on the currently active header
15555		active = active || this.active[ 0 ];
15556
15557		this._eventHandler( {
15558			target: active,
15559			currentTarget: active,
15560			preventDefault: $.noop
15561		} );
15562	},
15563
15564	_findActive: function( selector ) {
15565		return typeof selector === "number" ? this.headers.eq( selector ) : $();
15566	},
15567
15568	_setupEvents: function( event ) {
15569		var events = {
15570			keydown: "_keydown"
15571		};
15572		if ( event ) {
15573			$.each( event.split( " " ), function( index, eventName ) {
15574				events[ eventName ] = "_eventHandler";
15575			} );
15576		}
15577
15578		this._off( this.headers.add( this.headers.next() ) );
15579		this._on( this.headers, events );
15580		this._on( this.headers.next(), { keydown: "_panelKeyDown" } );
15581		this._hoverable( this.headers );
15582		this._focusable( this.headers );
15583	},
15584
15585	_eventHandler: function( event ) {
15586		var activeChildren, clickedChildren,
15587			options = this.options,
15588			active = this.active,
15589			clicked = $( event.currentTarget ),
15590			clickedIsActive = clicked[ 0 ] === active[ 0 ],
15591			collapsing = clickedIsActive && options.collapsible,
15592			toShow = collapsing ? $() : clicked.next(),
15593			toHide = active.next(),
15594			eventData = {
15595				oldHeader: active,
15596				oldPanel: toHide,
15597				newHeader: collapsing ? $() : clicked,
15598				newPanel: toShow
15599			};
15600
15601		event.preventDefault();
15602
15603		if (
15604
15605				// click on active header, but not collapsible
15606				( clickedIsActive && !options.collapsible ) ||
15607
15608				// allow canceling activation
15609				( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
15610			return;
15611		}
15612
15613		options.active = collapsing ? false : this.headers.index( clicked );
15614
15615		// When the call to ._toggle() comes after the class changes
15616		// it causes a very odd bug in IE 8 (see #6720)
15617		this.active = clickedIsActive ? $() : clicked;
15618		this._toggle( eventData );
15619
15620		// Switch classes
15621		// corner classes on the previously active header stay after the animation
15622		this._removeClass( active, "ui-accordion-header-active", "ui-state-active" );
15623		if ( options.icons ) {
15624			activeChildren = active.children( ".ui-accordion-header-icon" );
15625			this._removeClass( activeChildren, null, options.icons.activeHeader )
15626				._addClass( activeChildren, null, options.icons.header );
15627		}
15628
15629		if ( !clickedIsActive ) {
15630			this._removeClass( clicked, "ui-accordion-header-collapsed" )
15631				._addClass( clicked, "ui-accordion-header-active", "ui-state-active" );
15632			if ( options.icons ) {
15633				clickedChildren = clicked.children( ".ui-accordion-header-icon" );
15634				this._removeClass( clickedChildren, null, options.icons.header )
15635					._addClass( clickedChildren, null, options.icons.activeHeader );
15636			}
15637
15638			this._addClass( clicked.next(), "ui-accordion-content-active" );
15639		}
15640	},
15641
15642	_toggle: function( data ) {
15643		var toShow = data.newPanel,
15644			toHide = this.prevShow.length ? this.prevShow : data.oldPanel;
15645
15646		// Handle activating a panel during the animation for another activation
15647		this.prevShow.add( this.prevHide ).stop( true, true );
15648		this.prevShow = toShow;
15649		this.prevHide = toHide;
15650
15651		if ( this.options.animate ) {
15652			this._animate( toShow, toHide, data );
15653		} else {
15654			toHide.hide();
15655			toShow.show();
15656			this._toggleComplete( data );
15657		}
15658
15659		toHide.attr( {
15660			"aria-hidden": "true"
15661		} );
15662		toHide.prev().attr( {
15663			"aria-selected": "false",
15664			"aria-expanded": "false"
15665		} );
15666
15667		// if we're switching panels, remove the old header from the tab order
vendor: 6,870 bytes, lines 15668-15919
15668		// if we're opening from collapsed state, remove the previous header from the tab order
15669		// if we're collapsing, then keep the collapsing header in the tab order
15670		if ( toShow.length && toHide.length ) {
15671			toHide.prev().attr( {
15672				"tabIndex": -1,
15673				"aria-expanded": "false"
15674			} );
15675		} else if ( toShow.length ) {
15676			this.headers.filter( function() {
15677				return parseInt( $( this ).attr( "tabIndex" ), 10 ) === 0;
15678			} )
15679				.attr( "tabIndex", -1 );
15680		}
15681
15682		toShow
15683			.attr( "aria-hidden", "false" )
15684			.prev()
15685				.attr( {
15686					"aria-selected": "true",
15687					"aria-expanded": "true",
15688					tabIndex: 0
15689				} );
15690	},
15691
15692	_animate: function( toShow, toHide, data ) {
15693		var total, easing, duration,
15694			that = this,
15695			adjust = 0,
15696			boxSizing = toShow.css( "box-sizing" ),
15697			down = toShow.length &&
15698				( !toHide.length || ( toShow.index() < toHide.index() ) ),
15699			animate = this.options.animate || {},
15700			options = down && animate.down || animate,
15701			complete = function() {
15702				that._toggleComplete( data );
15703			};
15704
15705		if ( typeof options === "number" ) {
15706			duration = options;
15707		}
15708		if ( typeof options === "string" ) {
15709			easing = options;
15710		}
15711
15712		// fall back from options to animation in case of partial down settings
15713		easing = easing || options.easing || animate.easing;
15714		duration = duration || options.duration || animate.duration;
15715
15716		if ( !toHide.length ) {
15717			return toShow.animate( this.showProps, duration, easing, complete );
15718		}
15719		if ( !toShow.length ) {
15720			return toHide.animate( this.hideProps, duration, easing, complete );
15721		}
15722
15723		total = toShow.show().outerHeight();
15724		toHide.animate( this.hideProps, {
15725			duration: duration,
15726			easing: easing,
15727			step: function( now, fx ) {
15728				fx.now = Math.round( now );
15729			}
15730		} );
15731		toShow
15732			.hide()
15733			.animate( this.showProps, {
15734				duration: duration,
15735				easing: easing,
15736				complete: complete,
15737				step: function( now, fx ) {
15738					fx.now = Math.round( now );
15739					if ( fx.prop !== "height" ) {
15740						if ( boxSizing === "content-box" ) {
15741							adjust += fx.now;
15742						}
15743					} else if ( that.options.heightStyle !== "content" ) {
15744						fx.now = Math.round( total - toHide.outerHeight() - adjust );
15745						adjust = 0;
15746					}
15747				}
15748			} );
15749	},
15750
15751	_toggleComplete: function( data ) {
15752		var toHide = data.oldPanel,
15753			prev = toHide.prev();
15754
15755		this._removeClass( toHide, "ui-accordion-content-active" );
15756		this._removeClass( prev, "ui-accordion-header-active" )
15757			._addClass( prev, "ui-accordion-header-collapsed" );
15758
15759		// Work around for rendering bug in IE (#5421)
15760		if ( toHide.length ) {
15761			toHide.parent()[ 0 ].className = toHide.parent()[ 0 ].className;
15762		}
15763		this._trigger( "activate", null, data );
15764	}
15765} );
15766
15767
15768
15769var safeActiveElement = $.ui.safeActiveElement = function( document ) {
15770	var activeElement;
15771
15772	// Support: IE 9 only
15773	// IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe>
15774	try {
15775		activeElement = document.activeElement;
15776	} catch ( error ) {
15777		activeElement = document.body;
15778	}
15779
15780	// Support: IE 9 - 11 only
15781	// IE may return null instead of an element
15782	// Interestingly, this only seems to occur when NOT in an iframe
15783	if ( !activeElement ) {
15784		activeElement = document.body;
15785	}
15786
15787	// Support: IE 11 only
15788	// IE11 returns a seemingly empty object in some cases when accessing
15789	// document.activeElement from an <iframe>
15790	if ( !activeElement.nodeName ) {
15791		activeElement = document.body;
15792	}
15793
15794	return activeElement;
15795};
15796
15797
15798/*!
15799 * jQuery UI Menu 1.13.2
15800 * http://jqueryui.com
15801 *
15802 * Copyright jQuery Foundation and other contributors
15803 * Released under the MIT license.
15804 * http://jquery.org/license
15805 */
15806
15807//>>label: Menu
15808//>>group: Widgets
15809//>>description: Creates nestable menus.
15810//>>docs: http://api.jqueryui.com/menu/
15811//>>demos: http://jqueryui.com/menu/
15812//>>css.structure: ../../themes/base/core.css
15813//>>css.structure: ../../themes/base/menu.css
15814//>>css.theme: ../../themes/base/theme.css
15815
15816
15817var widgetsMenu = $.widget( "ui.menu", {
15818	version: "1.13.2",
15819	defaultElement: "<ul>",
15820	delay: 300,
15821	options: {
15822		icons: {
15823			submenu: "ui-icon-caret-1-e"
15824		},
15825		items: "> *",
15826		menus: "ul",
15827		position: {
15828			my: "left top",
15829			at: "right top"
15830		},
15831		role: "menu",
15832
15833		// Callbacks
15834		blur: null,
15835		focus: null,
15836		select: null
15837	},
15838
15839	_create: function() {
15840		this.activeMenu = this.element;
15841
15842		// Flag used to prevent firing of the click handler
15843		// as the event bubbles up through nested menus
15844		this.mouseHandled = false;
15845		this.lastMousePosition = { x: null, y: null };
15846		this.element
15847			.uniqueId()
15848			.attr( {
15849				role: this.options.role,
15850				tabIndex: 0
15851			} );
15852
15853		this._addClass( "ui-menu", "ui-widget ui-widget-content" );
15854		this._on( {
15855
15856			// Prevent focus from sticking to links inside menu after clicking
15857			// them (focus should always stay on UL during navigation).
15858			"mousedown .ui-menu-item": function( event ) {
15859				event.preventDefault();
15860
15861				this._activateItem( event );
15862			},
15863			"click .ui-menu-item": function( event ) {
15864				var target = $( event.target );
15865				var active = $( $.ui.safeActiveElement( this.document[ 0 ] ) );
15866				if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) {
15867					this.select( event );
15868
15869					// Only set the mouseHandled flag if the event will bubble, see #9469.
15870					if ( !event.isPropagationStopped() ) {
15871						this.mouseHandled = true;
15872					}
15873
15874					// Open submenu on click
15875					if ( target.has( ".ui-menu" ).length ) {
15876						this.expand( event );
15877					} else if ( !this.element.is( ":focus" ) &&
15878							active.closest( ".ui-menu" ).length ) {
15879
15880						// Redirect focus to the menu
15881						this.element.trigger( "focus", [ true ] );
15882
15883						// If the active item is on the top level, let it stay active.
15884						// Otherwise, blur the active item since it is no longer visible.
15885						if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) {
15886							clearTimeout( this.timer );
15887						}
15888					}
15889				}
15890			},
15891			"mouseenter .ui-menu-item": "_activateItem",
15892			"mousemove .ui-menu-item": "_activateItem",
15893			mouseleave: "collapseAll",
15894			"mouseleave .ui-menu": "collapseAll",
15895			focus: function( event, keepActiveItem ) {
15896
15897				// If there's already an active item, keep it active
15898				// If not, activate the first item
15899				var item = this.active || this._menuItems().first();
15900
15901				if ( !keepActiveItem ) {
15902					this.focus( event, item );
15903				}
15904			},
15905			blur: function( event ) {
15906				this._delay( function() {
15907					var notContained = !$.contains(
15908						this.element[ 0 ],
15909						$.ui.safeActiveElement( this.document[ 0 ] )
15910					);
15911					if ( notContained ) {
15912						this.collapseAll( event );
15913					}
15914				} );
15915			},
15916			keydown: "_keydown"
15917		} );
15918
15919		this.refresh();
vendor: 13,612 bytes, lines 15920-16408
15920
15921		// Clicks outside of a menu collapse any open menus
15922		this._on( this.document, {
15923			click: function( event ) {
15924				if ( this._closeOnDocumentClick( event ) ) {
15925					this.collapseAll( event, true );
15926				}
15927
15928				// Reset the mouseHandled flag
15929				this.mouseHandled = false;
15930			}
15931		} );
15932	},
15933
15934	_activateItem: function( event ) {
15935
15936		// Ignore mouse events while typeahead is active, see #10458.
15937		// Prevents focusing the wrong item when typeahead causes a scroll while the mouse
15938		// is over an item in the menu
15939		if ( this.previousFilter ) {
15940			return;
15941		}
15942
15943		// If the mouse didn't actually move, but the page was scrolled, ignore the event (#9356)
15944		if ( event.clientX === this.lastMousePosition.x &&
15945				event.clientY === this.lastMousePosition.y ) {
15946			return;
15947		}
15948
15949		this.lastMousePosition = {
15950			x: event.clientX,
15951			y: event.clientY
15952		};
15953
15954		var actualTarget = $( event.target ).closest( ".ui-menu-item" ),
15955			target = $( event.currentTarget );
15956
15957		// Ignore bubbled events on parent items, see #11641
15958		if ( actualTarget[ 0 ] !== target[ 0 ] ) {
15959			return;
15960		}
15961
15962		// If the item is already active, there's nothing to do
15963		if ( target.is( ".ui-state-active" ) ) {
15964			return;
15965		}
15966
15967		// Remove ui-state-active class from siblings of the newly focused menu item
15968		// to avoid a jump caused by adjacent elements both having a class with a border
15969		this._removeClass( target.siblings().children( ".ui-state-active" ),
15970			null, "ui-state-active" );
15971		this.focus( event, target );
15972	},
15973
15974	_destroy: function() {
15975		var items = this.element.find( ".ui-menu-item" )
15976				.removeAttr( "role aria-disabled" ),
15977			submenus = items.children( ".ui-menu-item-wrapper" )
15978				.removeUniqueId()
15979				.removeAttr( "tabIndex role aria-haspopup" );
15980
15981		// Destroy (sub)menus
15982		this.element
15983			.removeAttr( "aria-activedescendant" )
15984			.find( ".ui-menu" ).addBack()
15985				.removeAttr( "role aria-labelledby aria-expanded aria-hidden aria-disabled " +
15986					"tabIndex" )
15987				.removeUniqueId()
15988				.show();
15989
15990		submenus.children().each( function() {
15991			var elem = $( this );
15992			if ( elem.data( "ui-menu-submenu-caret" ) ) {
15993				elem.remove();
15994			}
15995		} );
15996	},
15997
15998	_keydown: function( event ) {
15999		var match, prev, character, skip,
16000			preventDefault = true;
16001
16002		switch ( event.keyCode ) {
16003		case $.ui.keyCode.PAGE_UP:
16004			this.previousPage( event );
16005			break;
16006		case $.ui.keyCode.PAGE_DOWN:
16007			this.nextPage( event );
16008			break;
16009		case $.ui.keyCode.HOME:
16010			this._move( "first", "first", event );
16011			break;
16012		case $.ui.keyCode.END:
16013			this._move( "last", "last", event );
16014			break;
16015		case $.ui.keyCode.UP:
16016			this.previous( event );
16017			break;
16018		case $.ui.keyCode.DOWN:
16019			this.next( event );
16020			break;
16021		case $.ui.keyCode.LEFT:
16022			this.collapse( event );
16023			break;
16024		case $.ui.keyCode.RIGHT:
16025			if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
16026				this.expand( event );
16027			}
16028			break;
16029		case $.ui.keyCode.ENTER:
16030		case $.ui.keyCode.SPACE:
16031			this._activate( event );
16032			break;
16033		case $.ui.keyCode.ESCAPE:
16034			this.collapse( event );
16035			break;
16036		default:
16037			preventDefault = false;
16038			prev = this.previousFilter || "";
16039			skip = false;
16040
16041			// Support number pad values
16042			character = event.keyCode >= 96 && event.keyCode <= 105 ?
16043				( event.keyCode - 96 ).toString() : String.fromCharCode( event.keyCode );
16044
16045			clearTimeout( this.filterTimer );
16046
16047			if ( character === prev ) {
16048				skip = true;
16049			} else {
16050				character = prev + character;
16051			}
16052
16053			match = this._filterMenuItems( character );
16054			match = skip && match.index( this.active.next() ) !== -1 ?
16055				this.active.nextAll( ".ui-menu-item" ) :
16056				match;
16057
16058			// If no matches on the current filter, reset to the last character pressed
16059			// to move down the menu to the first item that starts with that character
16060			if ( !match.length ) {
16061				character = String.fromCharCode( event.keyCode );
16062				match = this._filterMenuItems( character );
16063			}
16064
16065			if ( match.length ) {
16066				this.focus( event, match );
16067				this.previousFilter = character;
16068				this.filterTimer = this._delay( function() {
16069					delete this.previousFilter;
16070				}, 1000 );
16071			} else {
16072				delete this.previousFilter;
16073			}
16074		}
16075
16076		if ( preventDefault ) {
16077			event.preventDefault();
16078		}
16079	},
16080
16081	_activate: function( event ) {
16082		if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
16083			if ( this.active.children( "[aria-haspopup='true']" ).length ) {
16084				this.expand( event );
16085			} else {
16086				this.select( event );
16087			}
16088		}
16089	},
16090
16091	refresh: function() {
16092		var menus, items, newSubmenus, newItems, newWrappers,
16093			that = this,
16094			icon = this.options.icons.submenu,
16095			submenus = this.element.find( this.options.menus );
16096
16097		this._toggleClass( "ui-menu-icons", null, !!this.element.find( ".ui-icon" ).length );
16098
16099		// Initialize nested menus
16100		newSubmenus = submenus.filter( ":not(.ui-menu)" )
16101			.hide()
16102			.attr( {
16103				role: this.options.role,
16104				"aria-hidden": "true",
16105				"aria-expanded": "false"
16106			} )
16107			.each( function() {
16108				var menu = $( this ),
16109					item = menu.prev(),
16110					submenuCaret = $( "<span>" ).data( "ui-menu-submenu-caret", true );
16111
16112				that._addClass( submenuCaret, "ui-menu-icon", "ui-icon " + icon );
16113				item
16114					.attr( "aria-haspopup", "true" )
16115					.prepend( submenuCaret );
16116				menu.attr( "aria-labelledby", item.attr( "id" ) );
16117			} );
16118
16119		this._addClass( newSubmenus, "ui-menu", "ui-widget ui-widget-content ui-front" );
16120
16121		menus = submenus.add( this.element );
16122		items = menus.find( this.options.items );
16123
16124		// Initialize menu-items containing spaces and/or dashes only as dividers
16125		items.not( ".ui-menu-item" ).each( function() {
16126			var item = $( this );
16127			if ( that._isDivider( item ) ) {
16128				that._addClass( item, "ui-menu-divider", "ui-widget-content" );
16129			}
16130		} );
16131
16132		// Don't refresh list items that are already adapted
16133		newItems = items.not( ".ui-menu-item, .ui-menu-divider" );
16134		newWrappers = newItems.children()
16135			.not( ".ui-menu" )
16136				.uniqueId()
16137				.attr( {
16138					tabIndex: -1,
16139					role: this._itemRole()
16140				} );
16141		this._addClass( newItems, "ui-menu-item" )
16142			._addClass( newWrappers, "ui-menu-item-wrapper" );
16143
16144		// Add aria-disabled attribute to any disabled menu item
16145		items.filter( ".ui-state-disabled" ).attr( "aria-disabled", "true" );
16146
16147		// If the active item has been removed, blur the menu
16148		if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
16149			this.blur();
16150		}
16151	},
16152
16153	_itemRole: function() {
16154		return {
16155			menu: "menuitem",
16156			listbox: "option"
16157		}[ this.options.role ];
16158	},
16159
16160	_setOption: function( key, value ) {
16161		if ( key === "icons" ) {
16162			var icons = this.element.find( ".ui-menu-icon" );
16163			this._removeClass( icons, null, this.options.icons.submenu )
16164				._addClass( icons, null, value.submenu );
16165		}
16166		this._super( key, value );
16167	},
16168
16169	_setOptionDisabled: function( value ) {
16170		this._super( value );
16171
16172		this.element.attr( "aria-disabled", String( value ) );
16173		this._toggleClass( null, "ui-state-disabled", !!value );
16174	},
16175
16176	focus: function( event, item ) {
16177		var nested, focused, activeParent;
16178		this.blur( event, event && event.type === "focus" );
16179
16180		this._scrollIntoView( item );
16181
16182		this.active = item.first();
16183
16184		focused = this.active.children( ".ui-menu-item-wrapper" );
16185		this._addClass( focused, null, "ui-state-active" );
16186
16187		// Only update aria-activedescendant if there's a role
16188		// otherwise we assume focus is managed elsewhere
16189		if ( this.options.role ) {
16190			this.element.attr( "aria-activedescendant", focused.attr( "id" ) );
16191		}
16192
16193		// Highlight active parent menu item, if any
16194		activeParent = this.active
16195			.parent()
16196				.closest( ".ui-menu-item" )
16197					.children( ".ui-menu-item-wrapper" );
16198		this._addClass( activeParent, null, "ui-state-active" );
16199
16200		if ( event && event.type === "keydown" ) {
16201			this._close();
16202		} else {
16203			this.timer = this._delay( function() {
16204				this._close();
16205			}, this.delay );
16206		}
16207
16208		nested = item.children( ".ui-menu" );
16209		if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) {
16210			this._startOpening( nested );
16211		}
16212		this.activeMenu = item.parent();
16213
16214		this._trigger( "focus", event, { item: item } );
16215	},
16216
16217	_scrollIntoView: function( item ) {
16218		var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
16219		if ( this._hasScroll() ) {
16220			borderTop = parseFloat( $.css( this.activeMenu[ 0 ], "borderTopWidth" ) ) || 0;
16221			paddingTop = parseFloat( $.css( this.activeMenu[ 0 ], "paddingTop" ) ) || 0;
16222			offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
16223			scroll = this.activeMenu.scrollTop();
16224			elementHeight = this.activeMenu.height();
16225			itemHeight = item.outerHeight();
16226
16227			if ( offset < 0 ) {
16228				this.activeMenu.scrollTop( scroll + offset );
16229			} else if ( offset + itemHeight > elementHeight ) {
16230				this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );
16231			}
16232		}
16233	},
16234
16235	blur: function( event, fromFocus ) {
16236		if ( !fromFocus ) {
16237			clearTimeout( this.timer );
16238		}
16239
16240		if ( !this.active ) {
16241			return;
16242		}
16243
16244		this._removeClass( this.active.children( ".ui-menu-item-wrapper" ),
16245			null, "ui-state-active" );
16246
16247		this._trigger( "blur", event, { item: this.active } );
16248		this.active = null;
16249	},
16250
16251	_startOpening: function( submenu ) {
16252		clearTimeout( this.timer );
16253
16254		// Don't open if already open fixes a Firefox bug that caused a .5 pixel
16255		// shift in the submenu position when mousing over the caret icon
16256		if ( submenu.attr( "aria-hidden" ) !== "true" ) {
16257			return;
16258		}
16259
16260		this.timer = this._delay( function() {
16261			this._close();
16262			this._open( submenu );
16263		}, this.delay );
16264	},
16265
16266	_open: function( submenu ) {
16267		var position = $.extend( {
16268			of: this.active
16269		}, this.options.position );
16270
16271		clearTimeout( this.timer );
16272		this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) )
16273			.hide()
16274			.attr( "aria-hidden", "true" );
16275
16276		submenu
16277			.show()
16278			.removeAttr( "aria-hidden" )
16279			.attr( "aria-expanded", "true" )
16280			.position( position );
16281	},
16282
16283	collapseAll: function( event, all ) {
16284		clearTimeout( this.timer );
16285		this.timer = this._delay( function() {
16286
16287			// If we were passed an event, look for the submenu that contains the event
16288			var currentMenu = all ? this.element :
16289				$( event && event.target ).closest( this.element.find( ".ui-menu" ) );
16290
16291			// If we found no valid submenu ancestor, use the main menu to close all
16292			// sub menus anyway
16293			if ( !currentMenu.length ) {
16294				currentMenu = this.element;
16295			}
16296
16297			this._close( currentMenu );
16298
16299			this.blur( event );
16300
16301			// Work around active item staying active after menu is blurred
16302			this._removeClass( currentMenu.find( ".ui-state-active" ), null, "ui-state-active" );
16303
16304			this.activeMenu = currentMenu;
16305		}, all ? 0 : this.delay );
16306	},
16307
16308	// With no arguments, closes the currently active menu - if nothing is active
16309	// it closes all menus.  If passed an argument, it will search for menus BELOW
16310	_close: function( startMenu ) {
16311		if ( !startMenu ) {
16312			startMenu = this.active ? this.active.parent() : this.element;
16313		}
16314
16315		startMenu.find( ".ui-menu" )
16316			.hide()
16317			.attr( "aria-hidden", "true" )
16318			.attr( "aria-expanded", "false" );
16319	},
16320
16321	_closeOnDocumentClick: function( event ) {
16322		return !$( event.target ).closest( ".ui-menu" ).length;
16323	},
16324
16325	_isDivider: function( item ) {
16326
16327		// Match hyphen, em dash, en dash
16328		return !/[^\-\u2014\u2013\s]/.test( item.text() );
16329	},
16330
16331	collapse: function( event ) {
16332		var newItem = this.active &&
16333			this.active.parent().closest( ".ui-menu-item", this.element );
16334		if ( newItem && newItem.length ) {
16335			this._close();
16336			this.focus( event, newItem );
16337		}
16338	},
16339
16340	expand: function( event ) {
16341		var newItem = this.active && this._menuItems( this.active.children( ".ui-menu" ) ).first();
16342
16343		if ( newItem && newItem.length ) {
16344			this._open( newItem.parent() );
16345
16346			// Delay so Firefox will not hide activedescendant change in expanding submenu from AT
16347			this._delay( function() {
16348				this.focus( event, newItem );
16349			} );
16350		}
16351	},
16352
16353	next: function( event ) {
16354		this._move( "next", "first", event );
16355	},
16356
16357	previous: function( event ) {
16358		this._move( "prev", "last", event );
16359	},
16360
16361	isFirstItem: function() {
16362		return this.active && !this.active.prevAll( ".ui-menu-item" ).length;
16363	},
16364
16365	isLastItem: function() {
16366		return this.active && !this.active.nextAll( ".ui-menu-item" ).length;
16367	},
16368
16369	_menuItems: function( menu ) {
16370		return ( menu || this.element )
16371			.find( this.options.items )
16372			.filter( ".ui-menu-item" );
16373	},
16374
16375	_move: function( direction, filter, event ) {
16376		var next;
16377		if ( this.active ) {
16378			if ( direction === "first" || direction === "last" ) {
16379				next = this.active
16380					[ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )
16381					.last();
16382			} else {
16383				next = this.active
16384					[ direction + "All" ]( ".ui-menu-item" )
16385					.first();
16386			}
16387		}
16388		if ( !next || !next.length || !this.active ) {
16389			next = this._menuItems( this.activeMenu )[ filter ]();
16390		}
16391
16392		this.focus( event, next );
16393	},
16394
16395	nextPage: function( event ) {
16396		var item, base, height;
16397
16398		if ( !this.active ) {
16399			this.next( event );
16400			return;
16401		}
16402		if ( this.isLastItem() ) {
16403			return;
16404		}
16405		if ( this._hasScroll() ) {
16406			base = this.active.offset().top;
16407			height = this.element.innerHeight();
16408
vendor: 20,225 bytes, lines 16409-17147
16409			// jQuery 3.2 doesn't include scrollbars in innerHeight, add it back.
16410			if ( $.fn.jquery.indexOf( "3.2." ) === 0 ) {
16411				height += this.element[ 0 ].offsetHeight - this.element.outerHeight();
16412			}
16413
16414			this.active.nextAll( ".ui-menu-item" ).each( function() {
16415				item = $( this );
16416				return item.offset().top - base - height < 0;
16417			} );
16418
16419			this.focus( event, item );
16420		} else {
16421			this.focus( event, this._menuItems( this.activeMenu )
16422				[ !this.active ? "first" : "last" ]() );
16423		}
16424	},
16425
16426	previousPage: function( event ) {
16427		var item, base, height;
16428		if ( !this.active ) {
16429			this.next( event );
16430			return;
16431		}
16432		if ( this.isFirstItem() ) {
16433			return;
16434		}
16435		if ( this._hasScroll() ) {
16436			base = this.active.offset().top;
16437			height = this.element.innerHeight();
16438
16439			// jQuery 3.2 doesn't include scrollbars in innerHeight, add it back.
16440			if ( $.fn.jquery.indexOf( "3.2." ) === 0 ) {
16441				height += this.element[ 0 ].offsetHeight - this.element.outerHeight();
16442			}
16443
16444			this.active.prevAll( ".ui-menu-item" ).each( function() {
16445				item = $( this );
16446				return item.offset().top - base + height > 0;
16447			} );
16448
16449			this.focus( event, item );
16450		} else {
16451			this.focus( event, this._menuItems( this.activeMenu ).first() );
16452		}
16453	},
16454
16455	_hasScroll: function() {
16456		return this.element.outerHeight() < this.element.prop( "scrollHeight" );
16457	},
16458
16459	select: function( event ) {
16460
16461		// TODO: It should never be possible to not have an active item at this
16462		// point, but the tests don't trigger mouseenter before click.
16463		this.active = this.active || $( event.target ).closest( ".ui-menu-item" );
16464		var ui = { item: this.active };
16465		if ( !this.active.has( ".ui-menu" ).length ) {
16466			this.collapseAll( event, true );
16467		}
16468		this._trigger( "select", event, ui );
16469	},
16470
16471	_filterMenuItems: function( character ) {
16472		var escapedCharacter = character.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ),
16473			regex = new RegExp( "^" + escapedCharacter, "i" );
16474
16475		return this.activeMenu
16476			.find( this.options.items )
16477
16478				// Only match on items, not dividers or other content (#10571)
16479				.filter( ".ui-menu-item" )
16480					.filter( function() {
16481						return regex.test(
16482							String.prototype.trim.call(
16483								$( this ).children( ".ui-menu-item-wrapper" ).text() ) );
16484					} );
16485	}
16486} );
16487
16488
16489/*!
16490 * jQuery UI Autocomplete 1.13.2
16491 * http://jqueryui.com
16492 *
16493 * Copyright jQuery Foundation and other contributors
16494 * Released under the MIT license.
16495 * http://jquery.org/license
16496 */
16497
16498//>>label: Autocomplete
16499//>>group: Widgets
16500//>>description: Lists suggested words as the user is typing.
16501//>>docs: http://api.jqueryui.com/autocomplete/
16502//>>demos: http://jqueryui.com/autocomplete/
16503//>>css.structure: ../../themes/base/core.css
16504//>>css.structure: ../../themes/base/autocomplete.css
16505//>>css.theme: ../../themes/base/theme.css
16506
16507
16508$.widget( "ui.autocomplete", {
16509	version: "1.13.2",
16510	defaultElement: "<input>",
16511	options: {
16512		appendTo: null,
16513		autoFocus: false,
16514		delay: 300,
16515		minLength: 1,
16516		position: {
16517			my: "left top",
16518			at: "left bottom",
16519			collision: "none"
16520		},
16521		source: null,
16522
16523		// Callbacks
16524		change: null,
16525		close: null,
16526		focus: null,
16527		open: null,
16528		response: null,
16529		search: null,
16530		select: null
16531	},
16532
16533	requestIndex: 0,
16534	pending: 0,
16535	liveRegionTimer: null,
16536
16537	_create: function() {
16538
16539		// Some browsers only repeat keydown events, not keypress events,
16540		// so we use the suppressKeyPress flag to determine if we've already
16541		// handled the keydown event. #7269
16542		// Unfortunately the code for & in keypress is the same as the up arrow,
16543		// so we use the suppressKeyPressRepeat flag to avoid handling keypress
16544		// events when we know the keydown event was used to modify the
16545		// search term. #7799
16546		var suppressKeyPress, suppressKeyPressRepeat, suppressInput,
16547			nodeName = this.element[ 0 ].nodeName.toLowerCase(),
16548			isTextarea = nodeName === "textarea",
16549			isInput = nodeName === "input";
16550
16551		// Textareas are always multi-line
16552		// Inputs are always single-line, even if inside a contentEditable element
16553		// IE also treats inputs as contentEditable
16554		// All other element types are determined by whether or not they're contentEditable
16555		this.isMultiLine = isTextarea || !isInput && this._isContentEditable( this.element );
16556
16557		this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ];
16558		this.isNewMenu = true;
16559
16560		this._addClass( "ui-autocomplete-input" );
16561		this.element.attr( "autocomplete", "off" );
16562
16563		this._on( this.element, {
16564			keydown: function( event ) {
16565				if ( this.element.prop( "readOnly" ) ) {
16566					suppressKeyPress = true;
16567					suppressInput = true;
16568					suppressKeyPressRepeat = true;
16569					return;
16570				}
16571
16572				suppressKeyPress = false;
16573				suppressInput = false;
16574				suppressKeyPressRepeat = false;
16575				var keyCode = $.ui.keyCode;
16576				switch ( event.keyCode ) {
16577				case keyCode.PAGE_UP:
16578					suppressKeyPress = true;
16579					this._move( "previousPage", event );
16580					break;
16581				case keyCode.PAGE_DOWN:
16582					suppressKeyPress = true;
16583					this._move( "nextPage", event );
16584					break;
16585				case keyCode.UP:
16586					suppressKeyPress = true;
16587					this._keyEvent( "previous", event );
16588					break;
16589				case keyCode.DOWN:
16590					suppressKeyPress = true;
16591					this._keyEvent( "next", event );
16592					break;
16593				case keyCode.ENTER:
16594
16595					// when menu is open and has focus
16596					if ( this.menu.active ) {
16597
16598						// #6055 - Opera still allows the keypress to occur
16599						// which causes forms to submit
16600						suppressKeyPress = true;
16601						event.preventDefault();
16602						this.menu.select( event );
16603					}
16604					break;
16605				case keyCode.TAB:
16606					if ( this.menu.active ) {
16607						this.menu.select( event );
16608					}
16609					break;
16610				case keyCode.ESCAPE:
16611					if ( this.menu.element.is( ":visible" ) ) {
16612						if ( !this.isMultiLine ) {
16613							this._value( this.term );
16614						}
16615						this.close( event );
16616
16617						// Different browsers have different default behavior for escape
16618						// Single press can mean undo or clear
16619						// Double press in IE means clear the whole form
16620						event.preventDefault();
16621					}
16622					break;
16623				default:
16624					suppressKeyPressRepeat = true;
16625
16626					// search timeout should be triggered before the input value is changed
16627					this._searchTimeout( event );
16628					break;
16629				}
16630			},
16631			keypress: function( event ) {
16632				if ( suppressKeyPress ) {
16633					suppressKeyPress = false;
16634					if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
16635						event.preventDefault();
16636					}
16637					return;
16638				}
16639				if ( suppressKeyPressRepeat ) {
16640					return;
16641				}
16642
16643				// Replicate some key handlers to allow them to repeat in Firefox and Opera
16644				var keyCode = $.ui.keyCode;
16645				switch ( event.keyCode ) {
16646				case keyCode.PAGE_UP:
16647					this._move( "previousPage", event );
16648					break;
16649				case keyCode.PAGE_DOWN:
16650					this._move( "nextPage", event );
16651					break;
16652				case keyCode.UP:
16653					this._keyEvent( "previous", event );
16654					break;
16655				case keyCode.DOWN:
16656					this._keyEvent( "next", event );
16657					break;
16658				}
16659			},
16660			input: function( event ) {
16661				if ( suppressInput ) {
16662					suppressInput = false;
16663					event.preventDefault();
16664					return;
16665				}
16666				this._searchTimeout( event );
16667			},
16668			focus: function() {
16669				this.selectedItem = null;
16670				this.previous = this._value();
16671			},
16672			blur: function( event ) {
16673				clearTimeout( this.searching );
16674				this.close( event );
16675				this._change( event );
16676			}
16677		} );
16678
16679		this._initSource();
16680		this.menu = $( "<ul>" )
16681			.appendTo( this._appendTo() )
16682			.menu( {
16683
16684				// disable ARIA support, the live region takes care of that
16685				role: null
16686			} )
16687			.hide()
16688
16689			// Support: IE 11 only, Edge <= 14
16690			// For other browsers, we preventDefault() on the mousedown event
16691			// to keep the dropdown from taking focus from the input. This doesn't
16692			// work for IE/Edge, causing problems with selection and scrolling (#9638)
16693			// Happily, IE and Edge support an "unselectable" attribute that
16694			// prevents an element from receiving focus, exactly what we want here.
16695			.attr( {
16696				"unselectable": "on"
16697			} )
16698			.menu( "instance" );
16699
16700		this._addClass( this.menu.element, "ui-autocomplete", "ui-front" );
16701		this._on( this.menu.element, {
16702			mousedown: function( event ) {
16703
16704				// Prevent moving focus out of the text field
16705				event.preventDefault();
16706			},
16707			menufocus: function( event, ui ) {
16708				var label, item;
16709
16710				// support: Firefox
16711				// Prevent accidental activation of menu items in Firefox (#7024 #9118)
16712				if ( this.isNewMenu ) {
16713					this.isNewMenu = false;
16714					if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {
16715						this.menu.blur();
16716
16717						this.document.one( "mousemove", function() {
16718							$( event.target ).trigger( event.originalEvent );
16719						} );
16720
16721						return;
16722					}
16723				}
16724
16725				item = ui.item.data( "ui-autocomplete-item" );
16726				if ( false !== this._trigger( "focus", event, { item: item } ) ) {
16727
16728					// use value to match what will end up in the input, if it was a key event
16729					if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
16730						this._value( item.value );
16731					}
16732				}
16733
16734				// Announce the value in the liveRegion
16735				label = ui.item.attr( "aria-label" ) || item.value;
16736				if ( label && String.prototype.trim.call( label ).length ) {
16737					clearTimeout( this.liveRegionTimer );
16738					this.liveRegionTimer = this._delay( function() {
16739						this.liveRegion.html( $( "<div>" ).text( label ) );
16740					}, 100 );
16741				}
16742			},
16743			menuselect: function( event, ui ) {
16744				var item = ui.item.data( "ui-autocomplete-item" ),
16745					previous = this.previous;
16746
16747				// Only trigger when focus was lost (click on menu)
16748				if ( this.element[ 0 ] !== $.ui.safeActiveElement( this.document[ 0 ] ) ) {
16749					this.element.trigger( "focus" );
16750					this.previous = previous;
16751
16752					// #6109 - IE triggers two focus events and the second
16753					// is asynchronous, so we need to reset the previous
16754					// term synchronously and asynchronously :-(
16755					this._delay( function() {
16756						this.previous = previous;
16757						this.selectedItem = item;
16758					} );
16759				}
16760
16761				if ( false !== this._trigger( "select", event, { item: item } ) ) {
16762					this._value( item.value );
16763				}
16764
16765				// reset the term after the select event
16766				// this allows custom select handling to work properly
16767				this.term = this._value();
16768
16769				this.close( event );
16770				this.selectedItem = item;
16771			}
16772		} );
16773
16774		this.liveRegion = $( "<div>", {
16775			role: "status",
16776			"aria-live": "assertive",
16777			"aria-relevant": "additions"
16778		} )
16779			.appendTo( this.document[ 0 ].body );
16780
16781		this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" );
16782
16783		// Turning off autocomplete prevents the browser from remembering the
16784		// value when navigating through history, so we re-enable autocomplete
16785		// if the page is unloaded before the widget is destroyed. #7790
16786		this._on( this.window, {
16787			beforeunload: function() {
16788				this.element.removeAttr( "autocomplete" );
16789			}
16790		} );
16791	},
16792
16793	_destroy: function() {
16794		clearTimeout( this.searching );
16795		this.element.removeAttr( "autocomplete" );
16796		this.menu.element.remove();
16797		this.liveRegion.remove();
16798	},
16799
16800	_setOption: function( key, value ) {
16801		this._super( key, value );
16802		if ( key === "source" ) {
16803			this._initSource();
16804		}
16805		if ( key === "appendTo" ) {
16806			this.menu.element.appendTo( this._appendTo() );
16807		}
16808		if ( key === "disabled" && value && this.xhr ) {
16809			this.xhr.abort();
16810		}
16811	},
16812
16813	_isEventTargetInWidget: function( event ) {
16814		var menuElement = this.menu.element[ 0 ];
16815
16816		return event.target === this.element[ 0 ] ||
16817			event.target === menuElement ||
16818			$.contains( menuElement, event.target );
16819	},
16820
16821	_closeOnClickOutside: function( event ) {
16822		if ( !this._isEventTargetInWidget( event ) ) {
16823			this.close();
16824		}
16825	},
16826
16827	_appendTo: function() {
16828		var element = this.options.appendTo;
16829
16830		if ( element ) {
16831			element = element.jquery || element.nodeType ?
16832				$( element ) :
16833				this.document.find( element ).eq( 0 );
16834		}
16835
16836		if ( !element || !element[ 0 ] ) {
16837			element = this.element.closest( ".ui-front, dialog" );
16838		}
16839
16840		if ( !element.length ) {
16841			element = this.document[ 0 ].body;
16842		}
16843
16844		return element;
16845	},
16846
16847	_initSource: function() {
16848		var array, url,
16849			that = this;
16850		if ( Array.isArray( this.options.source ) ) {
16851			array = this.options.source;
16852			this.source = function( request, response ) {
16853				response( $.ui.autocomplete.filter( array, request.term ) );
16854			};
16855		} else if ( typeof this.options.source === "string" ) {
16856			url = this.options.source;
16857			this.source = function( request, response ) {
16858				if ( that.xhr ) {
16859					that.xhr.abort();
16860				}
16861				that.xhr = $.ajax( {
16862					url: url,
16863					data: request,
16864					dataType: "json",
16865					success: function( data ) {
16866						response( data );
16867					},
16868					error: function() {
16869						response( [] );
16870					}
16871				} );
16872			};
16873		} else {
16874			this.source = this.options.source;
16875		}
16876	},
16877
16878	_searchTimeout: function( event ) {
16879		clearTimeout( this.searching );
16880		this.searching = this._delay( function() {
16881
16882			// Search if the value has changed, or if the user retypes the same value (see #7434)
16883			var equalValues = this.term === this._value(),
16884				menuVisible = this.menu.element.is( ":visible" ),
16885				modifierKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
16886
16887			if ( !equalValues || ( equalValues && !menuVisible && !modifierKey ) ) {
16888				this.selectedItem = null;
16889				this.search( null, event );
16890			}
16891		}, this.options.delay );
16892	},
16893
16894	search: function( value, event ) {
16895		value = value != null ? value : this._value();
16896
16897		// Always save the actual value, not the one passed as an argument
16898		this.term = this._value();
16899
16900		if ( value.length < this.options.minLength ) {
16901			return this.close( event );
16902		}
16903
16904		if ( this._trigger( "search", event ) === false ) {
16905			return;
16906		}
16907
16908		return this._search( value );
16909	},
16910
16911	_search: function( value ) {
16912		this.pending++;
16913		this._addClass( "ui-autocomplete-loading" );
16914		this.cancelSearch = false;
16915
16916		this.source( { term: value }, this._response() );
16917	},
16918
16919	_response: function() {
16920		var index = ++this.requestIndex;
16921
16922		return function( content ) {
16923			if ( index === this.requestIndex ) {
16924				this.__response( content );
16925			}
16926
16927			this.pending--;
16928			if ( !this.pending ) {
16929				this._removeClass( "ui-autocomplete-loading" );
16930			}
16931		}.bind( this );
16932	},
16933
16934	__response: function( content ) {
16935		if ( content ) {
16936			content = this._normalize( content );
16937		}
16938		this._trigger( "response", null, { content: content } );
16939		if ( !this.options.disabled && content && content.length && !this.cancelSearch ) {
16940			this._suggest( content );
16941			this._trigger( "open" );
16942		} else {
16943
16944			// use ._close() instead of .close() so we don't cancel future searches
16945			this._close();
16946		}
16947	},
16948
16949	close: function( event ) {
16950		this.cancelSearch = true;
16951		this._close( event );
16952	},
16953
16954	_close: function( event ) {
16955
16956		// Remove the handler that closes the menu on outside clicks
16957		this._off( this.document, "mousedown" );
16958
16959		if ( this.menu.element.is( ":visible" ) ) {
16960			this.menu.element.hide();
16961			this.menu.blur();
16962			this.isNewMenu = true;
16963			this._trigger( "close", event );
16964		}
16965	},
16966
16967	_change: function( event ) {
16968		if ( this.previous !== this._value() ) {
16969			this._trigger( "change", event, { item: this.selectedItem } );
16970		}
16971	},
16972
16973	_normalize: function( items ) {
16974
16975		// assume all items have the right format when the first item is complete
16976		if ( items.length && items[ 0 ].label && items[ 0 ].value ) {
16977			return items;
16978		}
16979		return $.map( items, function( item ) {
16980			if ( typeof item === "string" ) {
16981				return {
16982					label: item,
16983					value: item
16984				};
16985			}
16986			return $.extend( {}, item, {
16987				label: item.label || item.value,
16988				value: item.value || item.label
16989			} );
16990		} );
16991	},
16992
16993	_suggest: function( items ) {
16994		var ul = this.menu.element.empty();
16995		this._renderMenu( ul, items );
16996		this.isNewMenu = true;
16997		this.menu.refresh();
16998
16999		// Size and position menu
17000		ul.show();
17001		this._resizeMenu();
17002		ul.position( $.extend( {
17003			of: this.element
17004		}, this.options.position ) );
17005
17006		if ( this.options.autoFocus ) {
17007			this.menu.next();
17008		}
17009
17010		// Listen for interactions outside of the widget (#6642)
17011		this._on( this.document, {
17012			mousedown: "_closeOnClickOutside"
17013		} );
17014	},
17015
17016	_resizeMenu: function() {
17017		var ul = this.menu.element;
17018		ul.outerWidth( Math.max(
17019
17020			// Firefox wraps long text (possibly a rounding bug)
17021			// so we add 1px to avoid the wrapping (#7513)
17022			ul.width( "" ).outerWidth() + 1,
17023			this.element.outerWidth()
17024		) );
17025	},
17026
17027	_renderMenu: function( ul, items ) {
17028		var that = this;
17029		$.each( items, function( index, item ) {
17030			that._renderItemData( ul, item );
17031		} );
17032	},
17033
17034	_renderItemData: function( ul, item ) {
17035		return this._renderItem( ul, item ).data( "ui-autocomplete-item", item );
17036	},
17037
17038	_renderItem: function( ul, item ) {
17039		return $( "<li>" )
17040			.append( $( "<div>" ).text( item.label ) )
17041			.appendTo( ul );
17042	},
17043
17044	_move: function( direction, event ) {
17045		if ( !this.menu.element.is( ":visible" ) ) {
17046			this.search( null, event );
17047			return;
17048		}
17049		if ( this.menu.isFirstItem() && /^previous/.test( direction ) ||
17050				this.menu.isLastItem() && /^next/.test( direction ) ) {
17051
17052			if ( !this.isMultiLine ) {
17053				this._value( this.term );
17054			}
17055
17056			this.menu.blur();
17057			return;
17058		}
17059		this.menu[ direction ]( event );
17060	},
17061
17062	widget: function() {
17063		return this.menu.element;
17064	},
17065
17066	_value: function() {
17067		return this.valueMethod.apply( this.element, arguments );
17068	},
17069
17070	_keyEvent: function( keyEvent, event ) {
17071		if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
17072			this._move( keyEvent, event );
17073
17074			// Prevents moving cursor to beginning/end of the text field in some browsers
17075			event.preventDefault();
17076		}
17077	},
17078
17079	// Support: Chrome <=50
17080	// We should be able to just use this.element.prop( "isContentEditable" )
17081	// but hidden elements always report false in Chrome.
17082	// https://code.google.com/p/chromium/issues/detail?id=313082
17083	_isContentEditable: function( element ) {
17084		if ( !element.length ) {
17085			return false;
17086		}
17087
17088		var editable = element.prop( "contentEditable" );
17089
17090		if ( editable === "inherit" ) {
17091			return this._isContentEditable( element.parent() );
17092		}
17093
17094		return editable === "true";
17095	}
17096} );
17097
17098$.extend( $.ui.autocomplete, {
17099	escapeRegex: function( value ) {
17100		return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
17101	},
17102	filter: function( array, term ) {
17103		var matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), "i" );
17104		return $.grep( array, function( value ) {
17105			return matcher.test( value.label || value.value || value );
17106		} );
17107	}
17108} );
17109
17110// Live region extension, adding a `messages` option
17111// NOTE: This is an experimental API. We are still investigating
17112// a full solution for string manipulation and internationalization.
17113$.widget( "ui.autocomplete", $.ui.autocomplete, {
17114	options: {
17115		messages: {
17116			noResults: "No search results.",
17117			results: function( amount ) {
17118				return amount + ( amount > 1 ? " results are" : " result is" ) +
17119					" available, use up and down arrow keys to navigate.";
17120			}
17121		}
17122	},
17123
17124	__response: function( content ) {
17125		var message;
17126		this._superApply( arguments );
17127		if ( this.options.disabled || this.cancelSearch ) {
17128			return;
17129		}
17130		if ( content && content.length ) {
17131			message = this.options.messages.results( content.length );
17132		} else {
17133			message = this.options.messages.noResults;
17134		}
17135		clearTimeout( this.liveRegionTimer );
17136		this.liveRegionTimer = this._delay( function() {
17137			this.liveRegion.html( $( "<div>" ).text( message ) );
17138		}, 100 );
17139	}
17140} );
17141
17142var widgetsAutocomplete = $.ui.autocomplete;
17143
17144
17145/*!
17146 * jQuery UI Controlgroup 1.13.2
17147 * http://jqueryui.com
vendor: 7,245 bytes, lines 17148-17385
17148 *
17149 * Copyright jQuery Foundation and other contributors
17150 * Released under the MIT license.
17151 * http://jquery.org/license
17152 */
17153
17154//>>label: Controlgroup
17155//>>group: Widgets
17156//>>description: Visually groups form control widgets
17157//>>docs: http://api.jqueryui.com/controlgroup/
17158//>>demos: http://jqueryui.com/controlgroup/
17159//>>css.structure: ../../themes/base/core.css
17160//>>css.structure: ../../themes/base/controlgroup.css
17161//>>css.theme: ../../themes/base/theme.css
17162
17163
17164var controlgroupCornerRegex = /ui-corner-([a-z]){2,6}/g;
17165
17166var widgetsControlgroup = $.widget( "ui.controlgroup", {
17167	version: "1.13.2",
17168	defaultElement: "<div>",
17169	options: {
17170		direction: "horizontal",
17171		disabled: null,
17172		onlyVisible: true,
17173		items: {
17174			"button": "input[type=button], input[type=submit], input[type=reset], button, a",
17175			"controlgroupLabel": ".ui-controlgroup-label",
17176			"checkboxradio": "input[type='checkbox'], input[type='radio']",
17177			"selectmenu": "select",
17178			"spinner": ".ui-spinner-input"
17179		}
17180	},
17181
17182	_create: function() {
17183		this._enhance();
17184	},
17185
17186	// To support the enhanced option in jQuery Mobile, we isolate DOM manipulation
17187	_enhance: function() {
17188		this.element.attr( "role", "toolbar" );
17189		this.refresh();
17190	},
17191
17192	_destroy: function() {
17193		this._callChildMethod( "destroy" );
17194		this.childWidgets.removeData( "ui-controlgroup-data" );
17195		this.element.removeAttr( "role" );
17196		if ( this.options.items.controlgroupLabel ) {
17197			this.element
17198				.find( this.options.items.controlgroupLabel )
17199				.find( ".ui-controlgroup-label-contents" )
17200				.contents().unwrap();
17201		}
17202	},
17203
17204	_initWidgets: function() {
17205		var that = this,
17206			childWidgets = [];
17207
17208		// First we iterate over each of the items options
17209		$.each( this.options.items, function( widget, selector ) {
17210			var labels;
17211			var options = {};
17212
17213			// Make sure the widget has a selector set
17214			if ( !selector ) {
17215				return;
17216			}
17217
17218			if ( widget === "controlgroupLabel" ) {
17219				labels = that.element.find( selector );
17220				labels.each( function() {
17221					var element = $( this );
17222
17223					if ( element.children( ".ui-controlgroup-label-contents" ).length ) {
17224						return;
17225					}
17226					element.contents()
17227						.wrapAll( "<span class='ui-controlgroup-label-contents'></span>" );
17228				} );
17229				that._addClass( labels, null, "ui-widget ui-widget-content ui-state-default" );
17230				childWidgets = childWidgets.concat( labels.get() );
17231				return;
17232			}
17233
17234			// Make sure the widget actually exists
17235			if ( !$.fn[ widget ] ) {
17236				return;
17237			}
17238
17239			// We assume everything is in the middle to start because we can't determine
17240			// first / last elements until all enhancments are done.
17241			if ( that[ "_" + widget + "Options" ] ) {
17242				options = that[ "_" + widget + "Options" ]( "middle" );
17243			} else {
17244				options = { classes: {} };
17245			}
17246
17247			// Find instances of this widget inside controlgroup and init them
17248			that.element
17249				.find( selector )
17250				.each( function() {
17251					var element = $( this );
17252					var instance = element[ widget ]( "instance" );
17253
17254					// We need to clone the default options for this type of widget to avoid
17255					// polluting the variable options which has a wider scope than a single widget.
17256					var instanceOptions = $.widget.extend( {}, options );
17257
17258					// If the button is the child of a spinner ignore it
17259					// TODO: Find a more generic solution
17260					if ( widget === "button" && element.parent( ".ui-spinner" ).length ) {
17261						return;
17262					}
17263
17264					// Create the widget if it doesn't exist
17265					if ( !instance ) {
17266						instance = element[ widget ]()[ widget ]( "instance" );
17267					}
17268					if ( instance ) {
17269						instanceOptions.classes =
17270							that._resolveClassesValues( instanceOptions.classes, instance );
17271					}
17272					element[ widget ]( instanceOptions );
17273
17274					// Store an instance of the controlgroup to be able to reference
17275					// from the outermost element for changing options and refresh
17276					var widgetElement = element[ widget ]( "widget" );
17277					$.data( widgetElement[ 0 ], "ui-controlgroup-data",
17278						instance ? instance : element[ widget ]( "instance" ) );
17279
17280					childWidgets.push( widgetElement[ 0 ] );
17281				} );
17282		} );
17283
17284		this.childWidgets = $( $.uniqueSort( childWidgets ) );
17285		this._addClass( this.childWidgets, "ui-controlgroup-item" );
17286	},
17287
17288	_callChildMethod: function( method ) {
17289		this.childWidgets.each( function() {
17290			var element = $( this ),
17291				data = element.data( "ui-controlgroup-data" );
17292			if ( data && data[ method ] ) {
17293				data[ method ]();
17294			}
17295		} );
17296	},
17297
17298	_updateCornerClass: function( element, position ) {
17299		var remove = "ui-corner-top ui-corner-bottom ui-corner-left ui-corner-right ui-corner-all";
17300		var add = this._buildSimpleOptions( position, "label" ).classes.label;
17301
17302		this._removeClass( element, null, remove );
17303		this._addClass( element, null, add );
17304	},
17305
17306	_buildSimpleOptions: function( position, key ) {
17307		var direction = this.options.direction === "vertical";
17308		var result = {
17309			classes: {}
17310		};
17311		result.classes[ key ] = {
17312			"middle": "",
17313			"first": "ui-corner-" + ( direction ? "top" : "left" ),
17314			"last": "ui-corner-" + ( direction ? "bottom" : "right" ),
17315			"only": "ui-corner-all"
17316		}[ position ];
17317
17318		return result;
17319	},
17320
17321	_spinnerOptions: function( position ) {
17322		var options = this._buildSimpleOptions( position, "ui-spinner" );
17323
17324		options.classes[ "ui-spinner-up" ] = "";
17325		options.classes[ "ui-spinner-down" ] = "";
17326
17327		return options;
17328	},
17329
17330	_buttonOptions: function( position ) {
17331		return this._buildSimpleOptions( position, "ui-button" );
17332	},
17333
17334	_checkboxradioOptions: function( position ) {
17335		return this._buildSimpleOptions( position, "ui-checkboxradio-label" );
17336	},
17337
17338	_selectmenuOptions: function( position ) {
17339		var direction = this.options.direction === "vertical";
17340		return {
17341			width: direction ? "auto" : false,
17342			classes: {
17343				middle: {
17344					"ui-selectmenu-button-open": "",
17345					"ui-selectmenu-button-closed": ""
17346				},
17347				first: {
17348					"ui-selectmenu-button-open": "ui-corner-" + ( direction ? "top" : "tl" ),
17349					"ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "top" : "left" )
17350				},
17351				last: {
17352					"ui-selectmenu-button-open": direction ? "" : "ui-corner-tr",
17353					"ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "bottom" : "right" )
17354				},
17355				only: {
17356					"ui-selectmenu-button-open": "ui-corner-top",
17357					"ui-selectmenu-button-closed": "ui-corner-all"
17358				}
17359
17360			}[ position ]
17361		};
17362	},
17363
17364	_resolveClassesValues: function( classes, instance ) {
17365		var result = {};
17366		$.each( classes, function( key ) {
17367			var current = instance.options.classes[ key ] || "";
17368			current = String.prototype.trim.call( current.replace( controlgroupCornerRegex, "" ) );
17369			result[ key ] = ( current + " " + classes[ key ] ).replace( /\s+/g, " " );
17370		} );
17371		return result;
17372	},
17373
17374	_setOption: function( key, value ) {
17375		if ( key === "direction" ) {
17376			this._removeClass( "ui-controlgroup-" + this.options.direction );
17377		}
17378
17379		this._super( key, value );
17380		if ( key === "disabled" ) {
17381			this._callChildMethod( value ? "disable" : "enable" );
17382			return;
17383		}
17384
17385		this.refresh();
vendor: 6,618 bytes, lines 17386-17614
17386	},
17387
17388	refresh: function() {
17389		var children,
17390			that = this;
17391
17392		this._addClass( "ui-controlgroup ui-controlgroup-" + this.options.direction );
17393
17394		if ( this.options.direction === "horizontal" ) {
17395			this._addClass( null, "ui-helper-clearfix" );
17396		}
17397		this._initWidgets();
17398
17399		children = this.childWidgets;
17400
17401		// We filter here because we need to track all childWidgets not just the visible ones
17402		if ( this.options.onlyVisible ) {
17403			children = children.filter( ":visible" );
17404		}
17405
17406		if ( children.length ) {
17407
17408			// We do this last because we need to make sure all enhancment is done
17409			// before determining first and last
17410			$.each( [ "first", "last" ], function( index, value ) {
17411				var instance = children[ value ]().data( "ui-controlgroup-data" );
17412
17413				if ( instance && that[ "_" + instance.widgetName + "Options" ] ) {
17414					var options = that[ "_" + instance.widgetName + "Options" ](
17415						children.length === 1 ? "only" : value
17416					);
17417					options.classes = that._resolveClassesValues( options.classes, instance );
17418					instance.element[ instance.widgetName ]( options );
17419				} else {
17420					that._updateCornerClass( children[ value ](), value );
17421				}
17422			} );
17423
17424			// Finally call the refresh method on each of the child widgets.
17425			this._callChildMethod( "refresh" );
17426		}
17427	}
17428} );
17429
17430/*!
17431 * jQuery UI Checkboxradio 1.13.2
17432 * http://jqueryui.com
17433 *
17434 * Copyright jQuery Foundation and other contributors
17435 * Released under the MIT license.
17436 * http://jquery.org/license
17437 */
17438
17439//>>label: Checkboxradio
17440//>>group: Widgets
17441//>>description: Enhances a form with multiple themeable checkboxes or radio buttons.
17442//>>docs: http://api.jqueryui.com/checkboxradio/
17443//>>demos: http://jqueryui.com/checkboxradio/
17444//>>css.structure: ../../themes/base/core.css
17445//>>css.structure: ../../themes/base/button.css
17446//>>css.structure: ../../themes/base/checkboxradio.css
17447//>>css.theme: ../../themes/base/theme.css
17448
17449
17450$.widget( "ui.checkboxradio", [ $.ui.formResetMixin, {
17451	version: "1.13.2",
17452	options: {
17453		disabled: null,
17454		label: null,
17455		icon: true,
17456		classes: {
17457			"ui-checkboxradio-label": "ui-corner-all",
17458			"ui-checkboxradio-icon": "ui-corner-all"
17459		}
17460	},
17461
17462	_getCreateOptions: function() {
17463		var disabled, labels, labelContents;
17464		var options = this._super() || {};
17465
17466		// We read the type here, because it makes more sense to throw a element type error first,
17467		// rather then the error for lack of a label. Often if its the wrong type, it
17468		// won't have a label (e.g. calling on a div, btn, etc)
17469		this._readType();
17470
17471		labels = this.element.labels();
17472
17473		// If there are multiple labels, use the last one
17474		this.label = $( labels[ labels.length - 1 ] );
17475		if ( !this.label.length ) {
17476			$.error( "No label found for checkboxradio widget" );
17477		}
17478
17479		this.originalLabel = "";
17480
17481		// We need to get the label text but this may also need to make sure it does not contain the
17482		// input itself.
17483		// The label contents could be text, html, or a mix. We wrap all elements
17484		// and read the wrapper's `innerHTML` to get a string representation of
17485		// the label, without the input as part of it.
17486		labelContents = this.label.contents().not( this.element[ 0 ] );
17487
17488		if ( labelContents.length ) {
17489			this.originalLabel += labelContents
17490				.clone()
17491				.wrapAll( "<div></div>" )
17492				.parent()
17493				.html();
17494		}
17495
17496		// Set the label option if we found label text
17497		if ( this.originalLabel ) {
17498			options.label = this.originalLabel;
17499		}
17500
17501		disabled = this.element[ 0 ].disabled;
17502		if ( disabled != null ) {
17503			options.disabled = disabled;
17504		}
17505		return options;
17506	},
17507
17508	_create: function() {
17509		var checked = this.element[ 0 ].checked;
17510
17511		this._bindFormResetHandler();
17512
17513		if ( this.options.disabled == null ) {
17514			this.options.disabled = this.element[ 0 ].disabled;
17515		}
17516
17517		this._setOption( "disabled", this.options.disabled );
17518		this._addClass( "ui-checkboxradio", "ui-helper-hidden-accessible" );
17519		this._addClass( this.label, "ui-checkboxradio-label", "ui-button ui-widget" );
17520
17521		if ( this.type === "radio" ) {
17522			this._addClass( this.label, "ui-checkboxradio-radio-label" );
17523		}
17524
17525		if ( this.options.label && this.options.label !== this.originalLabel ) {
17526			this._updateLabel();
17527		} else if ( this.originalLabel ) {
17528			this.options.label = this.originalLabel;
17529		}
17530
17531		this._enhance();
17532
17533		if ( checked ) {
17534			this._addClass( this.label, "ui-checkboxradio-checked", "ui-state-active" );
17535		}
17536
17537		this._on( {
17538			change: "_toggleClasses",
17539			focus: function() {
17540				this._addClass( this.label, null, "ui-state-focus ui-visual-focus" );
17541			},
17542			blur: function() {
17543				this._removeClass( this.label, null, "ui-state-focus ui-visual-focus" );
17544			}
17545		} );
17546	},
17547
17548	_readType: function() {
17549		var nodeName = this.element[ 0 ].nodeName.toLowerCase();
17550		this.type = this.element[ 0 ].type;
17551		if ( nodeName !== "input" || !/radio|checkbox/.test( this.type ) ) {
17552			$.error( "Can't create checkboxradio on element.nodeName=" + nodeName +
17553				" and element.type=" + this.type );
17554		}
17555	},
17556
17557	// Support jQuery Mobile enhanced option
17558	_enhance: function() {
17559		this._updateIcon( this.element[ 0 ].checked );
17560	},
17561
17562	widget: function() {
17563		return this.label;
17564	},
17565
17566	_getRadioGroup: function() {
17567		var group;
17568		var name = this.element[ 0 ].name;
17569		var nameSelector = "input[name='" + $.escapeSelector( name ) + "']";
17570
17571		if ( !name ) {
17572			return $( [] );
17573		}
17574
17575		if ( this.form.length ) {
17576			group = $( this.form[ 0 ].elements ).filter( nameSelector );
17577		} else {
17578
17579			// Not inside a form, check all inputs that also are not inside a form
17580			group = $( nameSelector ).filter( function() {
17581				return $( this )._form().length === 0;
17582			} );
17583		}
17584
17585		return group.not( this.element );
17586	},
17587
17588	_toggleClasses: function() {
17589		var checked = this.element[ 0 ].checked;
17590		this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked );
17591
17592		if ( this.options.icon && this.type === "checkbox" ) {
17593			this._toggleClass( this.icon, null, "ui-icon-check ui-state-checked", checked )
17594				._toggleClass( this.icon, null, "ui-icon-blank", !checked );
17595		}
17596
17597		if ( this.type === "radio" ) {
17598			this._getRadioGroup()
17599				.each( function() {
17600					var instance = $( this ).checkboxradio( "instance" );
17601
17602					if ( instance ) {
17603						instance._removeClass( instance.label,
17604							"ui-checkboxradio-checked", "ui-state-active" );
17605					}
17606				} );
17607		}
17608	},
17609
17610	_destroy: function() {
17611		this._unbindFormResetHandler();
17612
17613		if ( this.icon ) {
17614			this.icon.remove();
vendor: 4,657 bytes, lines 17615-17787
17615			this.iconSpace.remove();
17616		}
17617	},
17618
17619	_setOption: function( key, value ) {
17620
17621		// We don't allow the value to be set to nothing
17622		if ( key === "label" && !value ) {
17623			return;
17624		}
17625
17626		this._super( key, value );
17627
17628		if ( key === "disabled" ) {
17629			this._toggleClass( this.label, null, "ui-state-disabled", value );
17630			this.element[ 0 ].disabled = value;
17631
17632			// Don't refresh when setting disabled
17633			return;
17634		}
17635		this.refresh();
17636	},
17637
17638	_updateIcon: function( checked ) {
17639		var toAdd = "ui-icon ui-icon-background ";
17640
17641		if ( this.options.icon ) {
17642			if ( !this.icon ) {
17643				this.icon = $( "<span>" );
17644				this.iconSpace = $( "<span> </span>" );
17645				this._addClass( this.iconSpace, "ui-checkboxradio-icon-space" );
17646			}
17647
17648			if ( this.type === "checkbox" ) {
17649				toAdd += checked ? "ui-icon-check ui-state-checked" : "ui-icon-blank";
17650				this._removeClass( this.icon, null, checked ? "ui-icon-blank" : "ui-icon-check" );
17651			} else {
17652				toAdd += "ui-icon-blank";
17653			}
17654			this._addClass( this.icon, "ui-checkboxradio-icon", toAdd );
17655			if ( !checked ) {
17656				this._removeClass( this.icon, null, "ui-icon-check ui-state-checked" );
17657			}
17658			this.icon.prependTo( this.label ).after( this.iconSpace );
17659		} else if ( this.icon !== undefined ) {
17660			this.icon.remove();
17661			this.iconSpace.remove();
17662			delete this.icon;
17663		}
17664	},
17665
17666	_updateLabel: function() {
17667
17668		// Remove the contents of the label ( minus the icon, icon space, and input )
17669		var contents = this.label.contents().not( this.element[ 0 ] );
17670		if ( this.icon ) {
17671			contents = contents.not( this.icon[ 0 ] );
17672		}
17673		if ( this.iconSpace ) {
17674			contents = contents.not( this.iconSpace[ 0 ] );
17675		}
17676		contents.remove();
17677
17678		this.label.append( this.options.label );
17679	},
17680
17681	refresh: function() {
17682		var checked = this.element[ 0 ].checked,
17683			isDisabled = this.element[ 0 ].disabled;
17684
17685		this._updateIcon( checked );
17686		this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked );
17687		if ( this.options.label !== null ) {
17688			this._updateLabel();
17689		}
17690
17691		if ( isDisabled !== this.options.disabled ) {
17692			this._setOptions( { "disabled": isDisabled } );
17693		}
17694	}
17695
17696} ] );
17697
17698var widgetsCheckboxradio = $.ui.checkboxradio;
17699
17700
17701/*!
17702 * jQuery UI Button 1.13.2
17703 * http://jqueryui.com
17704 *
17705 * Copyright jQuery Foundation and other contributors
17706 * Released under the MIT license.
17707 * http://jquery.org/license
17708 */
17709
17710//>>label: Button
17711//>>group: Widgets
17712//>>description: Enhances a form with themeable buttons.
17713//>>docs: http://api.jqueryui.com/button/
17714//>>demos: http://jqueryui.com/button/
17715//>>css.structure: ../../themes/base/core.css
17716//>>css.structure: ../../themes/base/button.css
17717//>>css.theme: ../../themes/base/theme.css
17718
17719
17720$.widget( "ui.button", {
17721	version: "1.13.2",
17722	defaultElement: "<button>",
17723	options: {
17724		classes: {
17725			"ui-button": "ui-corner-all"
17726		},
17727		disabled: null,
17728		icon: null,
17729		iconPosition: "beginning",
17730		label: null,
17731		showLabel: true
17732	},
17733
17734	_getCreateOptions: function() {
17735		var disabled,
17736
17737			// This is to support cases like in jQuery Mobile where the base widget does have
17738			// an implementation of _getCreateOptions
17739			options = this._super() || {};
17740
17741		this.isInput = this.element.is( "input" );
17742
17743		disabled = this.element[ 0 ].disabled;
17744		if ( disabled != null ) {
17745			options.disabled = disabled;
17746		}
17747
17748		this.originalLabel = this.isInput ? this.element.val() : this.element.html();
17749		if ( this.originalLabel ) {
17750			options.label = this.originalLabel;
17751		}
17752
17753		return options;
17754	},
17755
17756	_create: function() {
17757		if ( !this.option.showLabel & !this.options.icon ) {
17758			this.options.showLabel = true;
17759		}
17760
17761		// We have to check the option again here even though we did in _getCreateOptions,
17762		// because null may have been passed on init which would override what was set in
17763		// _getCreateOptions
17764		if ( this.options.disabled == null ) {
17765			this.options.disabled = this.element[ 0 ].disabled || false;
17766		}
17767
17768		this.hasTitle = !!this.element.attr( "title" );
17769
17770		// Check to see if the label needs to be set or if its already correct
17771		if ( this.options.label && this.options.label !== this.originalLabel ) {
17772			if ( this.isInput ) {
17773				this.element.val( this.options.label );
17774			} else {
17775				this.element.html( this.options.label );
17776			}
17777		}
17778		this._addClass( "ui-button", "ui-widget" );
17779		this._setOption( "disabled", this.options.disabled );
17780		this._enhance();
17781
17782		if ( this.element.is( "a" ) ) {
17783			this._on( {
17784				"keyup": function( event ) {
17785					if ( event.keyCode === $.ui.keyCode.SPACE ) {
17786						event.preventDefault();
17787
vendor: 8,360 bytes, lines 17788-18088
17788						// Support: PhantomJS <= 1.9, IE 8 Only
17789						// If a native click is available use it so we actually cause navigation
17790						// otherwise just trigger a click event
17791						if ( this.element[ 0 ].click ) {
17792							this.element[ 0 ].click();
17793						} else {
17794							this.element.trigger( "click" );
17795						}
17796					}
17797				}
17798			} );
17799		}
17800	},
17801
17802	_enhance: function() {
17803		if ( !this.element.is( "button" ) ) {
17804			this.element.attr( "role", "button" );
17805		}
17806
17807		if ( this.options.icon ) {
17808			this._updateIcon( "icon", this.options.icon );
17809			this._updateTooltip();
17810		}
17811	},
17812
17813	_updateTooltip: function() {
17814		this.title = this.element.attr( "title" );
17815
17816		if ( !this.options.showLabel && !this.title ) {
17817			this.element.attr( "title", this.options.label );
17818		}
17819	},
17820
17821	_updateIcon: function( option, value ) {
17822		var icon = option !== "iconPosition",
17823			position = icon ? this.options.iconPosition : value,
17824			displayBlock = position === "top" || position === "bottom";
17825
17826		// Create icon
17827		if ( !this.icon ) {
17828			this.icon = $( "<span>" );
17829
17830			this._addClass( this.icon, "ui-button-icon", "ui-icon" );
17831
17832			if ( !this.options.showLabel ) {
17833				this._addClass( "ui-button-icon-only" );
17834			}
17835		} else if ( icon ) {
17836
17837			// If we are updating the icon remove the old icon class
17838			this._removeClass( this.icon, null, this.options.icon );
17839		}
17840
17841		// If we are updating the icon add the new icon class
17842		if ( icon ) {
17843			this._addClass( this.icon, null, value );
17844		}
17845
17846		this._attachIcon( position );
17847
17848		// If the icon is on top or bottom we need to add the ui-widget-icon-block class and remove
17849		// the iconSpace if there is one.
17850		if ( displayBlock ) {
17851			this._addClass( this.icon, null, "ui-widget-icon-block" );
17852			if ( this.iconSpace ) {
17853				this.iconSpace.remove();
17854			}
17855		} else {
17856
17857			// Position is beginning or end so remove the ui-widget-icon-block class and add the
17858			// space if it does not exist
17859			if ( !this.iconSpace ) {
17860				this.iconSpace = $( "<span> </span>" );
17861				this._addClass( this.iconSpace, "ui-button-icon-space" );
17862			}
17863			this._removeClass( this.icon, null, "ui-wiget-icon-block" );
17864			this._attachIconSpace( position );
17865		}
17866	},
17867
17868	_destroy: function() {
17869		this.element.removeAttr( "role" );
17870
17871		if ( this.icon ) {
17872			this.icon.remove();
17873		}
17874		if ( this.iconSpace ) {
17875			this.iconSpace.remove();
17876		}
17877		if ( !this.hasTitle ) {
17878			this.element.removeAttr( "title" );
17879		}
17880	},
17881
17882	_attachIconSpace: function( iconPosition ) {
17883		this.icon[ /^(?:end|bottom)/.test( iconPosition ) ? "before" : "after" ]( this.iconSpace );
17884	},
17885
17886	_attachIcon: function( iconPosition ) {
17887		this.element[ /^(?:end|bottom)/.test( iconPosition ) ? "append" : "prepend" ]( this.icon );
17888	},
17889
17890	_setOptions: function( options ) {
17891		var newShowLabel = options.showLabel === undefined ?
17892				this.options.showLabel :
17893				options.showLabel,
17894			newIcon = options.icon === undefined ? this.options.icon : options.icon;
17895
17896		if ( !newShowLabel && !newIcon ) {
17897			options.showLabel = true;
17898		}
17899		this._super( options );
17900	},
17901
17902	_setOption: function( key, value ) {
17903		if ( key === "icon" ) {
17904			if ( value ) {
17905				this._updateIcon( key, value );
17906			} else if ( this.icon ) {
17907				this.icon.remove();
17908				if ( this.iconSpace ) {
17909					this.iconSpace.remove();
17910				}
17911			}
17912		}
17913
17914		if ( key === "iconPosition" ) {
17915			this._updateIcon( key, value );
17916		}
17917
17918		// Make sure we can't end up with a button that has neither text nor icon
17919		if ( key === "showLabel" ) {
17920				this._toggleClass( "ui-button-icon-only", null, !value );
17921				this._updateTooltip();
17922		}
17923
17924		if ( key === "label" ) {
17925			if ( this.isInput ) {
17926				this.element.val( value );
17927			} else {
17928
17929				// If there is an icon, append it, else nothing then append the value
17930				// this avoids removal of the icon when setting label text
17931				this.element.html( value );
17932				if ( this.icon ) {
17933					this._attachIcon( this.options.iconPosition );
17934					this._attachIconSpace( this.options.iconPosition );
17935				}
17936			}
17937		}
17938
17939		this._super( key, value );
17940
17941		if ( key === "disabled" ) {
17942			this._toggleClass( null, "ui-state-disabled", value );
17943			this.element[ 0 ].disabled = value;
17944			if ( value ) {
17945				this.element.trigger( "blur" );
17946			}
17947		}
17948	},
17949
17950	refresh: function() {
17951
17952		// Make sure to only check disabled if its an element that supports this otherwise
17953		// check for the disabled class to determine state
17954		var isDisabled = this.element.is( "input, button" ) ?
17955			this.element[ 0 ].disabled : this.element.hasClass( "ui-button-disabled" );
17956
17957		if ( isDisabled !== this.options.disabled ) {
17958			this._setOptions( { disabled: isDisabled } );
17959		}
17960
17961		this._updateTooltip();
17962	}
17963} );
17964
17965// DEPRECATED
17966if ( $.uiBackCompat !== false ) {
17967
17968	// Text and Icons options
17969	$.widget( "ui.button", $.ui.button, {
17970		options: {
17971			text: true,
17972			icons: {
17973				primary: null,
17974				secondary: null
17975			}
17976		},
17977
17978		_create: function() {
17979			if ( this.options.showLabel && !this.options.text ) {
17980				this.options.showLabel = this.options.text;
17981			}
17982			if ( !this.options.showLabel && this.options.text ) {
17983				this.options.text = this.options.showLabel;
17984			}
17985			if ( !this.options.icon && ( this.options.icons.primary ||
17986					this.options.icons.secondary ) ) {
17987				if ( this.options.icons.primary ) {
17988					this.options.icon = this.options.icons.primary;
17989				} else {
17990					this.options.icon = this.options.icons.secondary;
17991					this.options.iconPosition = "end";
17992				}
17993			} else if ( this.options.icon ) {
17994				this.options.icons.primary = this.options.icon;
17995			}
17996			this._super();
17997		},
17998
17999		_setOption: function( key, value ) {
18000			if ( key === "text" ) {
18001				this._super( "showLabel", value );
18002				return;
18003			}
18004			if ( key === "showLabel" ) {
18005				this.options.text = value;
18006			}
18007			if ( key === "icon" ) {
18008				this.options.icons.primary = value;
18009			}
18010			if ( key === "icons" ) {
18011				if ( value.primary ) {
18012					this._super( "icon", value.primary );
18013					this._super( "iconPosition", "beginning" );
18014				} else if ( value.secondary ) {
18015					this._super( "icon", value.secondary );
18016					this._super( "iconPosition", "end" );
18017				}
18018			}
18019			this._superApply( arguments );
18020		}
18021	} );
18022
18023	$.fn.button = ( function( orig ) {
18024		return function( options ) {
18025			var isMethodCall = typeof options === "string";
18026			var args = Array.prototype.slice.call( arguments, 1 );
18027			var returnValue = this;
18028
18029			if ( isMethodCall ) {
18030
18031				// If this is an empty collection, we need to have the instance method
18032				// return undefined instead of the jQuery instance
18033				if ( !this.length && options === "instance" ) {
18034					returnValue = undefined;
18035				} else {
18036					this.each( function() {
18037						var methodValue;
18038						var type = $( this ).attr( "type" );
18039						var name = type !== "checkbox" && type !== "radio" ?
18040							"button" :
18041							"checkboxradio";
18042						var instance = $.data( this, "ui-" + name );
18043
18044						if ( options === "instance" ) {
18045							returnValue = instance;
18046							return false;
18047						}
18048
18049						if ( !instance ) {
18050							return $.error( "cannot call methods on button" +
18051								" prior to initialization; " +
18052								"attempted to call method '" + options + "'" );
18053						}
18054
18055						if ( typeof instance[ options ] !== "function" ||
18056							options.charAt( 0 ) === "_" ) {
18057							return $.error( "no such method '" + options + "' for button" +
18058								" widget instance" );
18059						}
18060
18061						methodValue = instance[ options ].apply( instance, args );
18062
18063						if ( methodValue !== instance && methodValue !== undefined ) {
18064							returnValue = methodValue && methodValue.jquery ?
18065								returnValue.pushStack( methodValue.get() ) :
18066								methodValue;
18067							return false;
18068						}
18069					} );
18070				}
18071			} else {
18072
18073				// Allow multiple hashes to be passed on init
18074				if ( args.length ) {
18075					options = $.widget.extend.apply( null, [ options ].concat( args ) );
18076				}
18077
18078				this.each( function() {
18079					var type = $( this ).attr( "type" );
18080					var name = type !== "checkbox" && type !== "radio" ? "button" : "checkboxradio";
18081					var instance = $.data( this, "ui-" + name );
18082
18083					if ( instance ) {
18084						instance.option( options || {} );
18085						if ( instance._init ) {
18086							instance._init();
18087						}
18088					} else {
vendor: 19,025 bytes, lines 18089-18533
18089						if ( name === "button" ) {
18090							orig.call( $( this ), options );
18091							return;
18092						}
18093
18094						$( this ).checkboxradio( $.extend( { icon: false }, options ) );
18095					}
18096				} );
18097			}
18098
18099			return returnValue;
18100		};
18101	} )( $.fn.button );
18102
18103	$.fn.buttonset = function() {
18104		if ( !$.ui.controlgroup ) {
18105			$.error( "Controlgroup widget missing" );
18106		}
18107		if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" && arguments[ 2 ] ) {
18108			return this.controlgroup.apply( this,
18109				[ arguments[ 0 ], "items.button", arguments[ 2 ] ] );
18110		}
18111		if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" ) {
18112			return this.controlgroup.apply( this, [ arguments[ 0 ], "items.button" ] );
18113		}
18114		if ( typeof arguments[ 0 ] === "object" && arguments[ 0 ].items ) {
18115			arguments[ 0 ].items = {
18116				button: arguments[ 0 ].items
18117			};
18118		}
18119		return this.controlgroup.apply( this, arguments );
18120	};
18121}
18122
18123var widgetsButton = $.ui.button;
18124
18125
18126/* eslint-disable max-len, camelcase */
18127/*!
18128 * jQuery UI Datepicker 1.13.2
18129 * http://jqueryui.com
18130 *
18131 * Copyright jQuery Foundation and other contributors
18132 * Released under the MIT license.
18133 * http://jquery.org/license
18134 */
18135
18136//>>label: Datepicker
18137//>>group: Widgets
18138//>>description: Displays a calendar from an input or inline for selecting dates.
18139//>>docs: http://api.jqueryui.com/datepicker/
18140//>>demos: http://jqueryui.com/datepicker/
18141//>>css.structure: ../../themes/base/core.css
18142//>>css.structure: ../../themes/base/datepicker.css
18143//>>css.theme: ../../themes/base/theme.css
18144
18145
18146$.extend( $.ui, { datepicker: { version: "1.13.2" } } );
18147
18148var datepicker_instActive;
18149
18150function datepicker_getZindex( elem ) {
18151	var position, value;
18152	while ( elem.length && elem[ 0 ] !== document ) {
18153
18154		// Ignore z-index if position is set to a value where z-index is ignored by the browser
18155		// This makes behavior of this function consistent across browsers
18156		// WebKit always returns auto if the element is positioned
18157		position = elem.css( "position" );
18158		if ( position === "absolute" || position === "relative" || position === "fixed" ) {
18159
18160			// IE returns 0 when zIndex is not specified
18161			// other browsers return a string
18162			// we ignore the case of nested elements with an explicit value of 0
18163			// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
18164			value = parseInt( elem.css( "zIndex" ), 10 );
18165			if ( !isNaN( value ) && value !== 0 ) {
18166				return value;
18167			}
18168		}
18169		elem = elem.parent();
18170	}
18171
18172	return 0;
18173}
18174
18175/* Date picker manager.
18176   Use the singleton instance of this class, $.datepicker, to interact with the date picker.
18177   Settings for (groups of) date pickers are maintained in an instance object,
18178   allowing multiple different settings on the same page. */
18179
18180function Datepicker() {
18181	this._curInst = null; // The current instance in use
18182	this._keyEvent = false; // If the last event was a key event
18183	this._disabledInputs = []; // List of date picker inputs that have been disabled
18184	this._datepickerShowing = false; // True if the popup picker is showing , false if not
18185	this._inDialog = false; // True if showing within a "dialog", false if not
18186	this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division
18187	this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class
18188	this._appendClass = "ui-datepicker-append"; // The name of the append marker class
18189	this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class
18190	this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class
18191	this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class
18192	this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class
18193	this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class
18194	this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class
18195	this.regional = []; // Available regional settings, indexed by language code
18196	this.regional[ "" ] = { // Default regional settings
18197		closeText: "Done", // Display text for close link
18198		prevText: "Prev", // Display text for previous month link
18199		nextText: "Next", // Display text for next month link
18200		currentText: "Today", // Display text for current month link
18201		monthNames: [ "January", "February", "March", "April", "May", "June",
18202			"July", "August", "September", "October", "November", "December" ], // Names of months for drop-down and formatting
18203		monthNamesShort: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ], // For formatting
18204		dayNames: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], // For formatting
18205		dayNamesShort: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], // For formatting
18206		dayNamesMin: [ "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" ], // Column headings for days starting at Sunday
18207		weekHeader: "Wk", // Column header for week of the year
18208		dateFormat: "mm/dd/yy", // See format options on parseDate
18209		firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
18210		isRTL: false, // True if right-to-left language, false if left-to-right
18211		showMonthAfterYear: false, // True if the year select precedes month, false for month then year
18212		yearSuffix: "", // Additional text to append to the year in the month headers,
18213		selectMonthLabel: "Select month", // Invisible label for month selector
18214		selectYearLabel: "Select year" // Invisible label for year selector
18215	};
18216	this._defaults = { // Global defaults for all the date picker instances
18217		showOn: "focus", // "focus" for popup on focus,
18218			// "button" for trigger button, or "both" for either
18219		showAnim: "fadeIn", // Name of jQuery animation for popup
18220		showOptions: {}, // Options for enhanced animations
18221		defaultDate: null, // Used when field is blank: actual date,
18222			// +/-number for offset from today, null for today
18223		appendText: "", // Display text following the input box, e.g. showing the format
18224		buttonText: "...", // Text for trigger button
18225		buttonImage: "", // URL for trigger button image
18226		buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
18227		hideIfNoPrevNext: false, // True to hide next/previous month links
18228			// if not applicable, false to just disable them
18229		navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
18230		gotoCurrent: false, // True if today link goes back to current selection instead
18231		changeMonth: false, // True if month can be selected directly, false if only prev/next
18232		changeYear: false, // True if year can be selected directly, false if only prev/next
18233		yearRange: "c-10:c+10", // Range of years to display in drop-down,
18234			// either relative to today's year (-nn:+nn), relative to currently displayed year
18235			// (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
18236		showOtherMonths: false, // True to show dates in other months, false to leave blank
18237		selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
18238		showWeek: false, // True to show week of the year, false to not show it
18239		calculateWeek: this.iso8601Week, // How to calculate the week of the year,
18240			// takes a Date and returns the number of the week for it
18241		shortYearCutoff: "+10", // Short year values < this are in the current century,
18242			// > this are in the previous century,
18243			// string value starting with "+" for current year + value
18244		minDate: null, // The earliest selectable date, or null for no limit
18245		maxDate: null, // The latest selectable date, or null for no limit
18246		duration: "fast", // Duration of display/closure
18247		beforeShowDay: null, // Function that takes a date and returns an array with
18248			// [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "",
18249			// [2] = cell title (optional), e.g. $.datepicker.noWeekends
18250		beforeShow: null, // Function that takes an input field and
18251			// returns a set of custom settings for the date picker
18252		onSelect: null, // Define a callback function when a date is selected
18253		onChangeMonthYear: null, // Define a callback function when the month or year is changed
18254		onClose: null, // Define a callback function when the datepicker is closed
18255		onUpdateDatepicker: null, // Define a callback function when the datepicker is updated
18256		numberOfMonths: 1, // Number of months to show at a time
18257		showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
18258		stepMonths: 1, // Number of months to step back/forward
18259		stepBigMonths: 12, // Number of months to step back/forward for the big links
18260		altField: "", // Selector for an alternate field to store selected dates into
18261		altFormat: "", // The date format to use for the alternate field
18262		constrainInput: true, // The input is constrained by the current date format
18263		showButtonPanel: false, // True to show button panel, false to not show it
18264		autoSize: false, // True to size the input for the date format, false to leave as is
18265		disabled: false // The initial disabled state
18266	};
18267	$.extend( this._defaults, this.regional[ "" ] );
18268	this.regional.en = $.extend( true, {}, this.regional[ "" ] );
18269	this.regional[ "en-US" ] = $.extend( true, {}, this.regional.en );
18270	this.dpDiv = datepicker_bindHover( $( "<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) );
18271}
18272
18273$.extend( Datepicker.prototype, {
18274
18275	/* Class name added to elements to indicate already configured with a date picker. */
18276	markerClassName: "hasDatepicker",
18277
18278	//Keep track of the maximum number of rows displayed (see #7043)
18279	maxRows: 4,
18280
18281	// TODO rename to "widget" when switching to widget factory
18282	_widgetDatepicker: function() {
18283		return this.dpDiv;
18284	},
18285
18286	/* Override the default settings for all instances of the date picker.
18287	 * @param  settings  object - the new settings to use as defaults (anonymous object)
18288	 * @return the manager object
18289	 */
18290	setDefaults: function( settings ) {
18291		datepicker_extendRemove( this._defaults, settings || {} );
18292		return this;
18293	},
18294
18295	/* Attach the date picker to a jQuery selection.
18296	 * @param  target	element - the target input field or division or span
18297	 * @param  settings  object - the new settings to use for this date picker instance (anonymous)
18298	 */
18299	_attachDatepicker: function( target, settings ) {
18300		var nodeName, inline, inst;
18301		nodeName = target.nodeName.toLowerCase();
18302		inline = ( nodeName === "div" || nodeName === "span" );
18303		if ( !target.id ) {
18304			this.uuid += 1;
18305			target.id = "dp" + this.uuid;
18306		}
18307		inst = this._newInst( $( target ), inline );
18308		inst.settings = $.extend( {}, settings || {} );
18309		if ( nodeName === "input" ) {
18310			this._connectDatepicker( target, inst );
18311		} else if ( inline ) {
18312			this._inlineDatepicker( target, inst );
18313		}
18314	},
18315
18316	/* Create a new instance object. */
18317	_newInst: function( target, inline ) {
18318		var id = target[ 0 ].id.replace( /([^A-Za-z0-9_\-])/g, "\\\\$1" ); // escape jQuery meta chars
18319		return { id: id, input: target, // associated target
18320			selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
18321			drawMonth: 0, drawYear: 0, // month being drawn
18322			inline: inline, // is datepicker inline or not
18323			dpDiv: ( !inline ? this.dpDiv : // presentation div
18324			datepicker_bindHover( $( "<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) ) ) };
18325	},
18326
18327	/* Attach the date picker to an input field. */
18328	_connectDatepicker: function( target, inst ) {
18329		var input = $( target );
18330		inst.append = $( [] );
18331		inst.trigger = $( [] );
18332		if ( input.hasClass( this.markerClassName ) ) {
18333			return;
18334		}
18335		this._attachments( input, inst );
18336		input.addClass( this.markerClassName ).on( "keydown", this._doKeyDown ).
18337			on( "keypress", this._doKeyPress ).on( "keyup", this._doKeyUp );
18338		this._autoSize( inst );
18339		$.data( target, "datepicker", inst );
18340
18341		//If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
18342		if ( inst.settings.disabled ) {
18343			this._disableDatepicker( target );
18344		}
18345	},
18346
18347	/* Make attachments based on settings. */
18348	_attachments: function( input, inst ) {
18349		var showOn, buttonText, buttonImage,
18350			appendText = this._get( inst, "appendText" ),
18351			isRTL = this._get( inst, "isRTL" );
18352
18353		if ( inst.append ) {
18354			inst.append.remove();
18355		}
18356		if ( appendText ) {
18357			inst.append = $( "<span>" )
18358				.addClass( this._appendClass )
18359				.text( appendText );
18360			input[ isRTL ? "before" : "after" ]( inst.append );
18361		}
18362
18363		input.off( "focus", this._showDatepicker );
18364
18365		if ( inst.trigger ) {
18366			inst.trigger.remove();
18367		}
18368
18369		showOn = this._get( inst, "showOn" );
18370		if ( showOn === "focus" || showOn === "both" ) { // pop-up date picker when in the marked field
18371			input.on( "focus", this._showDatepicker );
18372		}
18373		if ( showOn === "button" || showOn === "both" ) { // pop-up date picker when button clicked
18374			buttonText = this._get( inst, "buttonText" );
18375			buttonImage = this._get( inst, "buttonImage" );
18376
18377			if ( this._get( inst, "buttonImageOnly" ) ) {
18378				inst.trigger = $( "<img>" )
18379					.addClass( this._triggerClass )
18380					.attr( {
18381						src: buttonImage,
18382						alt: buttonText,
18383						title: buttonText
18384					} );
18385			} else {
18386				inst.trigger = $( "<button type='button'>" )
18387					.addClass( this._triggerClass );
18388				if ( buttonImage ) {
18389					inst.trigger.html(
18390						$( "<img>" )
18391							.attr( {
18392								src: buttonImage,
18393								alt: buttonText,
18394								title: buttonText
18395							} )
18396					);
18397				} else {
18398					inst.trigger.text( buttonText );
18399				}
18400			}
18401
18402			input[ isRTL ? "before" : "after" ]( inst.trigger );
18403			inst.trigger.on( "click", function() {
18404				if ( $.datepicker._datepickerShowing && $.datepicker._lastInput === input[ 0 ] ) {
18405					$.datepicker._hideDatepicker();
18406				} else if ( $.datepicker._datepickerShowing && $.datepicker._lastInput !== input[ 0 ] ) {
18407					$.datepicker._hideDatepicker();
18408					$.datepicker._showDatepicker( input[ 0 ] );
18409				} else {
18410					$.datepicker._showDatepicker( input[ 0 ] );
18411				}
18412				return false;
18413			} );
18414		}
18415	},
18416
18417	/* Apply the maximum length for the date format. */
18418	_autoSize: function( inst ) {
18419		if ( this._get( inst, "autoSize" ) && !inst.inline ) {
18420			var findMax, max, maxI, i,
18421				date = new Date( 2009, 12 - 1, 20 ), // Ensure double digits
18422				dateFormat = this._get( inst, "dateFormat" );
18423
18424			if ( dateFormat.match( /[DM]/ ) ) {
18425				findMax = function( names ) {
18426					max = 0;
18427					maxI = 0;
18428					for ( i = 0; i < names.length; i++ ) {
18429						if ( names[ i ].length > max ) {
18430							max = names[ i ].length;
18431							maxI = i;
18432						}
18433					}
18434					return maxI;
18435				};
18436				date.setMonth( findMax( this._get( inst, ( dateFormat.match( /MM/ ) ?
18437					"monthNames" : "monthNamesShort" ) ) ) );
18438				date.setDate( findMax( this._get( inst, ( dateFormat.match( /DD/ ) ?
18439					"dayNames" : "dayNamesShort" ) ) ) + 20 - date.getDay() );
18440			}
18441			inst.input.attr( "size", this._formatDate( inst, date ).length );
18442		}
18443	},
18444
18445	/* Attach an inline date picker to a div. */
18446	_inlineDatepicker: function( target, inst ) {
18447		var divSpan = $( target );
18448		if ( divSpan.hasClass( this.markerClassName ) ) {
18449			return;
18450		}
18451		divSpan.addClass( this.markerClassName ).append( inst.dpDiv );
18452		$.data( target, "datepicker", inst );
18453		this._setDate( inst, this._getDefaultDate( inst ), true );
18454		this._updateDatepicker( inst );
18455		this._updateAlternate( inst );
18456
18457		//If disabled option is true, disable the datepicker before showing it (see ticket #5665)
18458		if ( inst.settings.disabled ) {
18459			this._disableDatepicker( target );
18460		}
18461
18462		// Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
18463		// http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
18464		inst.dpDiv.css( "display", "block" );
18465	},
18466
18467	/* Pop-up the date picker in a "dialog" box.
18468	 * @param  input element - ignored
18469	 * @param  date	string or Date - the initial date to display
18470	 * @param  onSelect  function - the function to call when a date is selected
18471	 * @param  settings  object - update the dialog date picker instance's settings (anonymous object)
18472	 * @param  pos int[2] - coordinates for the dialog's position within the screen or
18473	 *					event - with x/y coordinates or
18474	 *					leave empty for default (screen centre)
18475	 * @return the manager object
18476	 */
18477	_dialogDatepicker: function( input, date, onSelect, settings, pos ) {
18478		var id, browserWidth, browserHeight, scrollX, scrollY,
18479			inst = this._dialogInst; // internal instance
18480
18481		if ( !inst ) {
18482			this.uuid += 1;
18483			id = "dp" + this.uuid;
18484			this._dialogInput = $( "<input type='text' id='" + id +
18485				"' style='position: absolute; top: -100px; width: 0px;'/>" );
18486			this._dialogInput.on( "keydown", this._doKeyDown );
18487			$( "body" ).append( this._dialogInput );
18488			inst = this._dialogInst = this._newInst( this._dialogInput, false );
18489			inst.settings = {};
18490			$.data( this._dialogInput[ 0 ], "datepicker", inst );
18491		}
18492		datepicker_extendRemove( inst.settings, settings || {} );
18493		date = ( date && date.constructor === Date ? this._formatDate( inst, date ) : date );
18494		this._dialogInput.val( date );
18495
18496		this._pos = ( pos ? ( pos.length ? pos : [ pos.pageX, pos.pageY ] ) : null );
18497		if ( !this._pos ) {
18498			browserWidth = document.documentElement.clientWidth;
18499			browserHeight = document.documentElement.clientHeight;
18500			scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
18501			scrollY = document.documentElement.scrollTop || document.body.scrollTop;
18502			this._pos = // should use actual width/height below
18503				[ ( browserWidth / 2 ) - 100 + scrollX, ( browserHeight / 2 ) - 150 + scrollY ];
18504		}
18505
18506		// Move input on screen for focus, but hidden behind dialog
18507		this._dialogInput.css( "left", ( this._pos[ 0 ] + 20 ) + "px" ).css( "top", this._pos[ 1 ] + "px" );
18508		inst.settings.onSelect = onSelect;
18509		this._inDialog = true;
18510		this.dpDiv.addClass( this._dialogClass );
18511		this._showDatepicker( this._dialogInput[ 0 ] );
18512		if ( $.blockUI ) {
18513			$.blockUI( this.dpDiv );
18514		}
18515		$.data( this._dialogInput[ 0 ], "datepicker", inst );
18516		return this;
18517	},
18518
18519	/* Detach a datepicker from its control.
18520	 * @param  target	element - the target input field or division or span
18521	 */
18522	_destroyDatepicker: function( target ) {
18523		var nodeName,
18524			$target = $( target ),
18525			inst = $.data( target, "datepicker" );
18526
18527		if ( !$target.hasClass( this.markerClassName ) ) {
18528			return;
18529		}
18530
18531		nodeName = target.nodeName.toLowerCase();
18532		$.removeData( target, "datepicker" );
18533		if ( nodeName === "input" ) {
vendor: 12,182 bytes, lines 18534-18885
18534			inst.append.remove();
18535			inst.trigger.remove();
18536			$target.removeClass( this.markerClassName ).
18537				off( "focus", this._showDatepicker ).
18538				off( "keydown", this._doKeyDown ).
18539				off( "keypress", this._doKeyPress ).
18540				off( "keyup", this._doKeyUp );
18541		} else if ( nodeName === "div" || nodeName === "span" ) {
18542			$target.removeClass( this.markerClassName ).empty();
18543		}
18544
18545		if ( datepicker_instActive === inst ) {
18546			datepicker_instActive = null;
18547			this._curInst = null;
18548		}
18549	},
18550
18551	/* Enable the date picker to a jQuery selection.
18552	 * @param  target	element - the target input field or division or span
18553	 */
18554	_enableDatepicker: function( target ) {
18555		var nodeName, inline,
18556			$target = $( target ),
18557			inst = $.data( target, "datepicker" );
18558
18559		if ( !$target.hasClass( this.markerClassName ) ) {
18560			return;
18561		}
18562
18563		nodeName = target.nodeName.toLowerCase();
18564		if ( nodeName === "input" ) {
18565			target.disabled = false;
18566			inst.trigger.filter( "button" ).
18567				each( function() {
18568					this.disabled = false;
18569				} ).end().
18570				filter( "img" ).css( { opacity: "1.0", cursor: "" } );
18571		} else if ( nodeName === "div" || nodeName === "span" ) {
18572			inline = $target.children( "." + this._inlineClass );
18573			inline.children().removeClass( "ui-state-disabled" );
18574			inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ).
18575				prop( "disabled", false );
18576		}
18577		this._disabledInputs = $.map( this._disabledInputs,
18578
18579			// Delete entry
18580			function( value ) {
18581				return ( value === target ? null : value );
18582			} );
18583	},
18584
18585	/* Disable the date picker to a jQuery selection.
18586	 * @param  target	element - the target input field or division or span
18587	 */
18588	_disableDatepicker: function( target ) {
18589		var nodeName, inline,
18590			$target = $( target ),
18591			inst = $.data( target, "datepicker" );
18592
18593		if ( !$target.hasClass( this.markerClassName ) ) {
18594			return;
18595		}
18596
18597		nodeName = target.nodeName.toLowerCase();
18598		if ( nodeName === "input" ) {
18599			target.disabled = true;
18600			inst.trigger.filter( "button" ).
18601				each( function() {
18602					this.disabled = true;
18603				} ).end().
18604				filter( "img" ).css( { opacity: "0.5", cursor: "default" } );
18605		} else if ( nodeName === "div" || nodeName === "span" ) {
18606			inline = $target.children( "." + this._inlineClass );
18607			inline.children().addClass( "ui-state-disabled" );
18608			inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ).
18609				prop( "disabled", true );
18610		}
18611		this._disabledInputs = $.map( this._disabledInputs,
18612
18613			// Delete entry
18614			function( value ) {
18615				return ( value === target ? null : value );
18616			} );
18617		this._disabledInputs[ this._disabledInputs.length ] = target;
18618	},
18619
18620	/* Is the first field in a jQuery collection disabled as a datepicker?
18621	 * @param  target	element - the target input field or division or span
18622	 * @return boolean - true if disabled, false if enabled
18623	 */
18624	_isDisabledDatepicker: function( target ) {
18625		if ( !target ) {
18626			return false;
18627		}
18628		for ( var i = 0; i < this._disabledInputs.length; i++ ) {
18629			if ( this._disabledInputs[ i ] === target ) {
18630				return true;
18631			}
18632		}
18633		return false;
18634	},
18635
18636	/* Retrieve the instance data for the target control.
18637	 * @param  target  element - the target input field or division or span
18638	 * @return  object - the associated instance data
18639	 * @throws  error if a jQuery problem getting data
18640	 */
18641	_getInst: function( target ) {
18642		try {
18643			return $.data( target, "datepicker" );
18644		} catch ( err ) {
18645			throw "Missing instance data for this datepicker";
18646		}
18647	},
18648
18649	/* Update or retrieve the settings for a date picker attached to an input field or division.
18650	 * @param  target  element - the target input field or division or span
18651	 * @param  name	object - the new settings to update or
18652	 *				string - the name of the setting to change or retrieve,
18653	 *				when retrieving also "all" for all instance settings or
18654	 *				"defaults" for all global defaults
18655	 * @param  value   any - the new value for the setting
18656	 *				(omit if above is an object or to retrieve a value)
18657	 */
18658	_optionDatepicker: function( target, name, value ) {
18659		var settings, date, minDate, maxDate,
18660			inst = this._getInst( target );
18661
18662		if ( arguments.length === 2 && typeof name === "string" ) {
18663			return ( name === "defaults" ? $.extend( {}, $.datepicker._defaults ) :
18664				( inst ? ( name === "all" ? $.extend( {}, inst.settings ) :
18665				this._get( inst, name ) ) : null ) );
18666		}
18667
18668		settings = name || {};
18669		if ( typeof name === "string" ) {
18670			settings = {};
18671			settings[ name ] = value;
18672		}
18673
18674		if ( inst ) {
18675			if ( this._curInst === inst ) {
18676				this._hideDatepicker();
18677			}
18678
18679			date = this._getDateDatepicker( target, true );
18680			minDate = this._getMinMaxDate( inst, "min" );
18681			maxDate = this._getMinMaxDate( inst, "max" );
18682			datepicker_extendRemove( inst.settings, settings );
18683
18684			// reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
18685			if ( minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined ) {
18686				inst.settings.minDate = this._formatDate( inst, minDate );
18687			}
18688			if ( maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined ) {
18689				inst.settings.maxDate = this._formatDate( inst, maxDate );
18690			}
18691			if ( "disabled" in settings ) {
18692				if ( settings.disabled ) {
18693					this._disableDatepicker( target );
18694				} else {
18695					this._enableDatepicker( target );
18696				}
18697			}
18698			this._attachments( $( target ), inst );
18699			this._autoSize( inst );
18700			this._setDate( inst, date );
18701			this._updateAlternate( inst );
18702			this._updateDatepicker( inst );
18703		}
18704	},
18705
18706	// Change method deprecated
18707	_changeDatepicker: function( target, name, value ) {
18708		this._optionDatepicker( target, name, value );
18709	},
18710
18711	/* Redraw the date picker attached to an input field or division.
18712	 * @param  target  element - the target input field or division or span
18713	 */
18714	_refreshDatepicker: function( target ) {
18715		var inst = this._getInst( target );
18716		if ( inst ) {
18717			this._updateDatepicker( inst );
18718		}
18719	},
18720
18721	/* Set the dates for a jQuery selection.
18722	 * @param  target element - the target input field or division or span
18723	 * @param  date	Date - the new date
18724	 */
18725	_setDateDatepicker: function( target, date ) {
18726		var inst = this._getInst( target );
18727		if ( inst ) {
18728			this._setDate( inst, date );
18729			this._updateDatepicker( inst );
18730			this._updateAlternate( inst );
18731		}
18732	},
18733
18734	/* Get the date(s) for the first entry in a jQuery selection.
18735	 * @param  target element - the target input field or division or span
18736	 * @param  noDefault boolean - true if no default date is to be used
18737	 * @return Date - the current date
18738	 */
18739	_getDateDatepicker: function( target, noDefault ) {
18740		var inst = this._getInst( target );
18741		if ( inst && !inst.inline ) {
18742			this._setDateFromField( inst, noDefault );
18743		}
18744		return ( inst ? this._getDate( inst ) : null );
18745	},
18746
18747	/* Handle keystrokes. */
18748	_doKeyDown: function( event ) {
18749		var onSelect, dateStr, sel,
18750			inst = $.datepicker._getInst( event.target ),
18751			handled = true,
18752			isRTL = inst.dpDiv.is( ".ui-datepicker-rtl" );
18753
18754		inst._keyEvent = true;
18755		if ( $.datepicker._datepickerShowing ) {
18756			switch ( event.keyCode ) {
18757				case 9: $.datepicker._hideDatepicker();
18758						handled = false;
18759						break; // hide on tab out
18760				case 13: sel = $( "td." + $.datepicker._dayOverClass + ":not(." +
18761									$.datepicker._currentClass + ")", inst.dpDiv );
18762						if ( sel[ 0 ] ) {
18763							$.datepicker._selectDay( event.target, inst.selectedMonth, inst.selectedYear, sel[ 0 ] );
18764						}
18765
18766						onSelect = $.datepicker._get( inst, "onSelect" );
18767						if ( onSelect ) {
18768							dateStr = $.datepicker._formatDate( inst );
18769
18770							// Trigger custom callback
18771							onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] );
18772						} else {
18773							$.datepicker._hideDatepicker();
18774						}
18775
18776						return false; // don't submit the form
18777				case 27: $.datepicker._hideDatepicker();
18778						break; // hide on escape
18779				case 33: $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
18780							-$.datepicker._get( inst, "stepBigMonths" ) :
18781							-$.datepicker._get( inst, "stepMonths" ) ), "M" );
18782						break; // previous month/year on page up/+ ctrl
18783				case 34: $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
18784							+$.datepicker._get( inst, "stepBigMonths" ) :
18785							+$.datepicker._get( inst, "stepMonths" ) ), "M" );
18786						break; // next month/year on page down/+ ctrl
18787				case 35: if ( event.ctrlKey || event.metaKey ) {
18788							$.datepicker._clearDate( event.target );
18789						}
18790						handled = event.ctrlKey || event.metaKey;
18791						break; // clear on ctrl or command +end
18792				case 36: if ( event.ctrlKey || event.metaKey ) {
18793							$.datepicker._gotoToday( event.target );
18794						}
18795						handled = event.ctrlKey || event.metaKey;
18796						break; // current on ctrl or command +home
18797				case 37: if ( event.ctrlKey || event.metaKey ) {
18798							$.datepicker._adjustDate( event.target, ( isRTL ? +1 : -1 ), "D" );
18799						}
18800						handled = event.ctrlKey || event.metaKey;
18801
18802						// -1 day on ctrl or command +left
18803						if ( event.originalEvent.altKey ) {
18804							$.datepicker._adjustDate( event.target, ( event.ctrlKey ?
18805								-$.datepicker._get( inst, "stepBigMonths" ) :
18806								-$.datepicker._get( inst, "stepMonths" ) ), "M" );
18807						}
18808
18809						// next month/year on alt +left on Mac
18810						break;
18811				case 38: if ( event.ctrlKey || event.metaKey ) {
18812							$.datepicker._adjustDate( event.target, -7, "D" );
18813						}
18814						handled = event.ctrlKey || event.metaKey;
18815						break; // -1 week on ctrl or command +up
18816				case 39: if ( event.ctrlKey || event.metaKey ) {
18817							$.datepicker._adjustDate( event.target, ( isRTL ? -1 : +1 ), "D" );
18818						}
18819						handled = event.ctrlKey || event.metaKey;
18820
18821						// +1 day on ctrl or command +right
18822						if ( event.originalEvent.altKey ) {
18823							$.datepicker._adjustDate( event.target, ( event.ctrlKey ?
18824								+$.datepicker._get( inst, "stepBigMonths" ) :
18825								+$.datepicker._get( inst, "stepMonths" ) ), "M" );
18826						}
18827
18828						// next month/year on alt +right
18829						break;
18830				case 40: if ( event.ctrlKey || event.metaKey ) {
18831							$.datepicker._adjustDate( event.target, +7, "D" );
18832						}
18833						handled = event.ctrlKey || event.metaKey;
18834						break; // +1 week on ctrl or command +down
18835				default: handled = false;
18836			}
18837		} else if ( event.keyCode === 36 && event.ctrlKey ) { // display the date picker on ctrl+home
18838			$.datepicker._showDatepicker( this );
18839		} else {
18840			handled = false;
18841		}
18842
18843		if ( handled ) {
18844			event.preventDefault();
18845			event.stopPropagation();
18846		}
18847	},
18848
18849	/* Filter entered characters - based on date format. */
18850	_doKeyPress: function( event ) {
18851		var chars, chr,
18852			inst = $.datepicker._getInst( event.target );
18853
18854		if ( $.datepicker._get( inst, "constrainInput" ) ) {
18855			chars = $.datepicker._possibleChars( $.datepicker._get( inst, "dateFormat" ) );
18856			chr = String.fromCharCode( event.charCode == null ? event.keyCode : event.charCode );
18857			return event.ctrlKey || event.metaKey || ( chr < " " || !chars || chars.indexOf( chr ) > -1 );
18858		}
18859	},
18860
18861	/* Synchronise manual entry and field/alternate field. */
18862	_doKeyUp: function( event ) {
18863		var date,
18864			inst = $.datepicker._getInst( event.target );
18865
18866		if ( inst.input.val() !== inst.lastVal ) {
18867			try {
18868				date = $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ),
18869					( inst.input ? inst.input.val() : null ),
18870					$.datepicker._getFormatConfig( inst ) );
18871
18872				if ( date ) { // only if valid
18873					$.datepicker._setDateFromField( inst );
18874					$.datepicker._updateAlternate( inst );
18875					$.datepicker._updateDatepicker( inst );
18876				}
18877			} catch ( err ) {
18878			}
18879		}
18880		return true;
18881	},
18882
18883	/* Pop-up the date picker for a given input field.
18884	 * If false returned from beforeShow event handler do not show.
18885	 * @param  input  element - the input field attached to the date picker or
vendor: 1,885 bytes, lines 18886-18943
18886	 *					event - if triggered by focus
18887	 */
18888	_showDatepicker: function( input ) {
18889		input = input.target || input;
18890		if ( input.nodeName.toLowerCase() !== "input" ) { // find from button/image trigger
18891			input = $( "input", input.parentNode )[ 0 ];
18892		}
18893
18894		if ( $.datepicker._isDisabledDatepicker( input ) || $.datepicker._lastInput === input ) { // already here
18895			return;
18896		}
18897
18898		var inst, beforeShow, beforeShowSettings, isFixed,
18899			offset, showAnim, duration;
18900
18901		inst = $.datepicker._getInst( input );
18902		if ( $.datepicker._curInst && $.datepicker._curInst !== inst ) {
18903			$.datepicker._curInst.dpDiv.stop( true, true );
18904			if ( inst && $.datepicker._datepickerShowing ) {
18905				$.datepicker._hideDatepicker( $.datepicker._curInst.input[ 0 ] );
18906			}
18907		}
18908
18909		beforeShow = $.datepicker._get( inst, "beforeShow" );
18910		beforeShowSettings = beforeShow ? beforeShow.apply( input, [ input, inst ] ) : {};
18911		if ( beforeShowSettings === false ) {
18912			return;
18913		}
18914		datepicker_extendRemove( inst.settings, beforeShowSettings );
18915
18916		inst.lastVal = null;
18917		$.datepicker._lastInput = input;
18918		$.datepicker._setDateFromField( inst );
18919
18920		if ( $.datepicker._inDialog ) { // hide cursor
18921			input.value = "";
18922		}
18923		if ( !$.datepicker._pos ) { // position below input
18924			$.datepicker._pos = $.datepicker._findPos( input );
18925			$.datepicker._pos[ 1 ] += input.offsetHeight; // add the height
18926		}
18927
18928		isFixed = false;
18929		$( input ).parents().each( function() {
18930			isFixed |= $( this ).css( "position" ) === "fixed";
18931			return !isFixed;
18932		} );
18933
18934		offset = { left: $.datepicker._pos[ 0 ], top: $.datepicker._pos[ 1 ] };
18935		$.datepicker._pos = null;
18936
18937		//to avoid flashes on Firefox
18938		inst.dpDiv.empty();
18939
18940		// determine sizing offscreen
18941		inst.dpDiv.css( { position: "absolute", display: "block", top: "-1000px" } );
18942		$.datepicker._updateDatepicker( inst );
18943
vendor: 8,237 bytes, lines 18944-19167
18944		// fix width for dynamic number of date pickers
18945		// and adjust position before showing
18946		offset = $.datepicker._checkOffset( inst, offset, isFixed );
18947		inst.dpDiv.css( { position: ( $.datepicker._inDialog && $.blockUI ?
18948			"static" : ( isFixed ? "fixed" : "absolute" ) ), display: "none",
18949			left: offset.left + "px", top: offset.top + "px" } );
18950
18951		if ( !inst.inline ) {
18952			showAnim = $.datepicker._get( inst, "showAnim" );
18953			duration = $.datepicker._get( inst, "duration" );
18954			inst.dpDiv.css( "z-index", datepicker_getZindex( $( input ) ) + 1 );
18955			$.datepicker._datepickerShowing = true;
18956
18957			if ( $.effects && $.effects.effect[ showAnim ] ) {
18958				inst.dpDiv.show( showAnim, $.datepicker._get( inst, "showOptions" ), duration );
18959			} else {
18960				inst.dpDiv[ showAnim || "show" ]( showAnim ? duration : null );
18961			}
18962
18963			if ( $.datepicker._shouldFocusInput( inst ) ) {
18964				inst.input.trigger( "focus" );
18965			}
18966
18967			$.datepicker._curInst = inst;
18968		}
18969	},
18970
18971	/* Generate the date picker content. */
18972	_updateDatepicker: function( inst ) {
18973		this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
18974		datepicker_instActive = inst; // for delegate hover events
18975		inst.dpDiv.empty().append( this._generateHTML( inst ) );
18976		this._attachHandlers( inst );
18977
18978		var origyearshtml,
18979			numMonths = this._getNumberOfMonths( inst ),
18980			cols = numMonths[ 1 ],
18981			width = 17,
18982			activeCell = inst.dpDiv.find( "." + this._dayOverClass + " a" ),
18983			onUpdateDatepicker = $.datepicker._get( inst, "onUpdateDatepicker" );
18984
18985		if ( activeCell.length > 0 ) {
18986			datepicker_handleMouseover.apply( activeCell.get( 0 ) );
18987		}
18988
18989		inst.dpDiv.removeClass( "ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4" ).width( "" );
18990		if ( cols > 1 ) {
18991			inst.dpDiv.addClass( "ui-datepicker-multi-" + cols ).css( "width", ( width * cols ) + "em" );
18992		}
18993		inst.dpDiv[ ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ? "add" : "remove" ) +
18994			"Class" ]( "ui-datepicker-multi" );
18995		inst.dpDiv[ ( this._get( inst, "isRTL" ) ? "add" : "remove" ) +
18996			"Class" ]( "ui-datepicker-rtl" );
18997
18998		if ( inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {
18999			inst.input.trigger( "focus" );
19000		}
19001
19002		// Deffered render of the years select (to avoid flashes on Firefox)
19003		if ( inst.yearshtml ) {
19004			origyearshtml = inst.yearshtml;
19005			setTimeout( function() {
19006
19007				//assure that inst.yearshtml didn't change.
19008				if ( origyearshtml === inst.yearshtml && inst.yearshtml ) {
19009					inst.dpDiv.find( "select.ui-datepicker-year" ).first().replaceWith( inst.yearshtml );
19010				}
19011				origyearshtml = inst.yearshtml = null;
19012			}, 0 );
19013		}
19014
19015		if ( onUpdateDatepicker ) {
19016			onUpdateDatepicker.apply( ( inst.input ? inst.input[ 0 ] : null ), [ inst ] );
19017		}
19018	},
19019
19020	// #6694 - don't focus the input if it's already focused
19021	// this breaks the change event in IE
19022	// Support: IE and jQuery <1.9
19023	_shouldFocusInput: function( inst ) {
19024		return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" );
19025	},
19026
19027	/* Check positioning to remain on screen. */
19028	_checkOffset: function( inst, offset, isFixed ) {
19029		var dpWidth = inst.dpDiv.outerWidth(),
19030			dpHeight = inst.dpDiv.outerHeight(),
19031			inputWidth = inst.input ? inst.input.outerWidth() : 0,
19032			inputHeight = inst.input ? inst.input.outerHeight() : 0,
19033			viewWidth = document.documentElement.clientWidth + ( isFixed ? 0 : $( document ).scrollLeft() ),
19034			viewHeight = document.documentElement.clientHeight + ( isFixed ? 0 : $( document ).scrollTop() );
19035
19036		offset.left -= ( this._get( inst, "isRTL" ) ? ( dpWidth - inputWidth ) : 0 );
19037		offset.left -= ( isFixed && offset.left === inst.input.offset().left ) ? $( document ).scrollLeft() : 0;
19038		offset.top -= ( isFixed && offset.top === ( inst.input.offset().top + inputHeight ) ) ? $( document ).scrollTop() : 0;
19039
19040		// Now check if datepicker is showing outside window viewport - move to a better place if so.
19041		offset.left -= Math.min( offset.left, ( offset.left + dpWidth > viewWidth && viewWidth > dpWidth ) ?
19042			Math.abs( offset.left + dpWidth - viewWidth ) : 0 );
19043		offset.top -= Math.min( offset.top, ( offset.top + dpHeight > viewHeight && viewHeight > dpHeight ) ?
19044			Math.abs( dpHeight + inputHeight ) : 0 );
19045
19046		return offset;
19047	},
19048
19049	/* Find an object's position on the screen. */
19050	_findPos: function( obj ) {
19051		var position,
19052			inst = this._getInst( obj ),
19053			isRTL = this._get( inst, "isRTL" );
19054
19055		while ( obj && ( obj.type === "hidden" || obj.nodeType !== 1 || $.expr.pseudos.hidden( obj ) ) ) {
19056			obj = obj[ isRTL ? "previousSibling" : "nextSibling" ];
19057		}
19058
19059		position = $( obj ).offset();
19060		return [ position.left, position.top ];
19061	},
19062
19063	/* Hide the date picker from view.
19064	 * @param  input  element - the input field attached to the date picker
19065	 */
19066	_hideDatepicker: function( input ) {
19067		var showAnim, duration, postProcess, onClose,
19068			inst = this._curInst;
19069
19070		if ( !inst || ( input && inst !== $.data( input, "datepicker" ) ) ) {
19071			return;
19072		}
19073
19074		if ( this._datepickerShowing ) {
19075			showAnim = this._get( inst, "showAnim" );
19076			duration = this._get( inst, "duration" );
19077			postProcess = function() {
19078				$.datepicker._tidyDialog( inst );
19079			};
19080
19081			// DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed
19082			if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) {
19083				inst.dpDiv.hide( showAnim, $.datepicker._get( inst, "showOptions" ), duration, postProcess );
19084			} else {
19085				inst.dpDiv[ ( showAnim === "slideDown" ? "slideUp" :
19086					( showAnim === "fadeIn" ? "fadeOut" : "hide" ) ) ]( ( showAnim ? duration : null ), postProcess );
19087			}
19088
19089			if ( !showAnim ) {
19090				postProcess();
19091			}
19092			this._datepickerShowing = false;
19093
19094			onClose = this._get( inst, "onClose" );
19095			if ( onClose ) {
19096				onClose.apply( ( inst.input ? inst.input[ 0 ] : null ), [ ( inst.input ? inst.input.val() : "" ), inst ] );
19097			}
19098
19099			this._lastInput = null;
19100			if ( this._inDialog ) {
19101				this._dialogInput.css( { position: "absolute", left: "0", top: "-100px" } );
19102				if ( $.blockUI ) {
19103					$.unblockUI();
19104					$( "body" ).append( this.dpDiv );
19105				}
19106			}
19107			this._inDialog = false;
19108		}
19109	},
19110
19111	/* Tidy up after a dialog display. */
19112	_tidyDialog: function( inst ) {
19113		inst.dpDiv.removeClass( this._dialogClass ).off( ".ui-datepicker-calendar" );
19114	},
19115
19116	/* Close date picker if clicked elsewhere. */
19117	_checkExternalClick: function( event ) {
19118		if ( !$.datepicker._curInst ) {
19119			return;
19120		}
19121
19122		var $target = $( event.target ),
19123			inst = $.datepicker._getInst( $target[ 0 ] );
19124
19125		if ( ( ( $target[ 0 ].id !== $.datepicker._mainDivId &&
19126				$target.parents( "#" + $.datepicker._mainDivId ).length === 0 &&
19127				!$target.hasClass( $.datepicker.markerClassName ) &&
19128				!$target.closest( "." + $.datepicker._triggerClass ).length &&
19129				$.datepicker._datepickerShowing && !( $.datepicker._inDialog && $.blockUI ) ) ) ||
19130			( $target.hasClass( $.datepicker.markerClassName ) && $.datepicker._curInst !== inst ) ) {
19131				$.datepicker._hideDatepicker();
19132		}
19133	},
19134
19135	/* Adjust one of the date sub-fields. */
19136	_adjustDate: function( id, offset, period ) {
19137		var target = $( id ),
19138			inst = this._getInst( target[ 0 ] );
19139
19140		if ( this._isDisabledDatepicker( target[ 0 ] ) ) {
19141			return;
19142		}
19143		this._adjustInstDate( inst, offset, period );
19144		this._updateDatepicker( inst );
19145	},
19146
19147	/* Action for current link. */
19148	_gotoToday: function( id ) {
19149		var date,
19150			target = $( id ),
19151			inst = this._getInst( target[ 0 ] );
19152
19153		if ( this._get( inst, "gotoCurrent" ) && inst.currentDay ) {
19154			inst.selectedDay = inst.currentDay;
19155			inst.drawMonth = inst.selectedMonth = inst.currentMonth;
19156			inst.drawYear = inst.selectedYear = inst.currentYear;
19157		} else {
19158			date = new Date();
19159			inst.selectedDay = date.getDate();
19160			inst.drawMonth = inst.selectedMonth = date.getMonth();
19161			inst.drawYear = inst.selectedYear = date.getFullYear();
19162		}
19163		this._notifyChange( inst );
19164		this._adjustDate( target );
19165	},
19166
19167	/* Action for selecting a new month/year. */
vendor: 43,872 bytes, lines 19168-20338
19168	_selectMonthYear: function( id, select, period ) {
19169		var target = $( id ),
19170			inst = this._getInst( target[ 0 ] );
19171
19172		inst[ "selected" + ( period === "M" ? "Month" : "Year" ) ] =
19173		inst[ "draw" + ( period === "M" ? "Month" : "Year" ) ] =
19174			parseInt( select.options[ select.selectedIndex ].value, 10 );
19175
19176		this._notifyChange( inst );
19177		this._adjustDate( target );
19178	},
19179
19180	/* Action for selecting a day. */
19181	_selectDay: function( id, month, year, td ) {
19182		var inst,
19183			target = $( id );
19184
19185		if ( $( td ).hasClass( this._unselectableClass ) || this._isDisabledDatepicker( target[ 0 ] ) ) {
19186			return;
19187		}
19188
19189		inst = this._getInst( target[ 0 ] );
19190		inst.selectedDay = inst.currentDay = parseInt( $( "a", td ).attr( "data-date" ) );
19191		inst.selectedMonth = inst.currentMonth = month;
19192		inst.selectedYear = inst.currentYear = year;
19193		this._selectDate( id, this._formatDate( inst,
19194			inst.currentDay, inst.currentMonth, inst.currentYear ) );
19195	},
19196
19197	/* Erase the input field and hide the date picker. */
19198	_clearDate: function( id ) {
19199		var target = $( id );
19200		this._selectDate( target, "" );
19201	},
19202
19203	/* Update the input field with the selected date. */
19204	_selectDate: function( id, dateStr ) {
19205		var onSelect,
19206			target = $( id ),
19207			inst = this._getInst( target[ 0 ] );
19208
19209		dateStr = ( dateStr != null ? dateStr : this._formatDate( inst ) );
19210		if ( inst.input ) {
19211			inst.input.val( dateStr );
19212		}
19213		this._updateAlternate( inst );
19214
19215		onSelect = this._get( inst, "onSelect" );
19216		if ( onSelect ) {
19217			onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] );  // trigger custom callback
19218		} else if ( inst.input ) {
19219			inst.input.trigger( "change" ); // fire the change event
19220		}
19221
19222		if ( inst.inline ) {
19223			this._updateDatepicker( inst );
19224		} else {
19225			this._hideDatepicker();
19226			this._lastInput = inst.input[ 0 ];
19227			if ( typeof( inst.input[ 0 ] ) !== "object" ) {
19228				inst.input.trigger( "focus" ); // restore focus
19229			}
19230			this._lastInput = null;
19231		}
19232	},
19233
19234	/* Update any alternate field to synchronise with the main field. */
19235	_updateAlternate: function( inst ) {
19236		var altFormat, date, dateStr,
19237			altField = this._get( inst, "altField" );
19238
19239		if ( altField ) { // update alternate field too
19240			altFormat = this._get( inst, "altFormat" ) || this._get( inst, "dateFormat" );
19241			date = this._getDate( inst );
19242			dateStr = this.formatDate( altFormat, date, this._getFormatConfig( inst ) );
19243			$( document ).find( altField ).val( dateStr );
19244		}
19245	},
19246
19247	/* Set as beforeShowDay function to prevent selection of weekends.
19248	 * @param  date  Date - the date to customise
19249	 * @return [boolean, string] - is this date selectable?, what is its CSS class?
19250	 */
19251	noWeekends: function( date ) {
19252		var day = date.getDay();
19253		return [ ( day > 0 && day < 6 ), "" ];
19254	},
19255
19256	/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
19257	 * @param  date  Date - the date to get the week for
19258	 * @return  number - the number of the week within the year that contains this date
19259	 */
19260	iso8601Week: function( date ) {
19261		var time,
19262			checkDate = new Date( date.getTime() );
19263
19264		// Find Thursday of this week starting on Monday
19265		checkDate.setDate( checkDate.getDate() + 4 - ( checkDate.getDay() || 7 ) );
19266
19267		time = checkDate.getTime();
19268		checkDate.setMonth( 0 ); // Compare with Jan 1
19269		checkDate.setDate( 1 );
19270		return Math.floor( Math.round( ( time - checkDate ) / 86400000 ) / 7 ) + 1;
19271	},
19272
19273	/* Parse a string value into a date object.
19274	 * See formatDate below for the possible formats.
19275	 *
19276	 * @param  format string - the expected format of the date
19277	 * @param  value string - the date in the above format
19278	 * @param  settings Object - attributes include:
19279	 *					shortYearCutoff  number - the cutoff year for determining the century (optional)
19280	 *					dayNamesShort	string[7] - abbreviated names of the days from Sunday (optional)
19281	 *					dayNames		string[7] - names of the days from Sunday (optional)
19282	 *					monthNamesShort string[12] - abbreviated names of the months (optional)
19283	 *					monthNames		string[12] - names of the months (optional)
19284	 * @return  Date - the extracted date value or null if value is blank
19285	 */
19286	parseDate: function( format, value, settings ) {
19287		if ( format == null || value == null ) {
19288			throw "Invalid arguments";
19289		}
19290
19291		value = ( typeof value === "object" ? value.toString() : value + "" );
19292		if ( value === "" ) {
19293			return null;
19294		}
19295
19296		var iFormat, dim, extra,
19297			iValue = 0,
19298			shortYearCutoffTemp = ( settings ? settings.shortYearCutoff : null ) || this._defaults.shortYearCutoff,
19299			shortYearCutoff = ( typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp :
19300				new Date().getFullYear() % 100 + parseInt( shortYearCutoffTemp, 10 ) ),
19301			dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort,
19302			dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames,
19303			monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort,
19304			monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames,
19305			year = -1,
19306			month = -1,
19307			day = -1,
19308			doy = -1,
19309			literal = false,
19310			date,
19311
19312			// Check whether a format character is doubled
19313			lookAhead = function( match ) {
19314				var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
19315				if ( matches ) {
19316					iFormat++;
19317				}
19318				return matches;
19319			},
19320
19321			// Extract a number from the string value
19322			getNumber = function( match ) {
19323				var isDoubled = lookAhead( match ),
19324					size = ( match === "@" ? 14 : ( match === "!" ? 20 :
19325					( match === "y" && isDoubled ? 4 : ( match === "o" ? 3 : 2 ) ) ) ),
19326					minSize = ( match === "y" ? size : 1 ),
19327					digits = new RegExp( "^\\d{" + minSize + "," + size + "}" ),
19328					num = value.substring( iValue ).match( digits );
19329				if ( !num ) {
19330					throw "Missing number at position " + iValue;
19331				}
19332				iValue += num[ 0 ].length;
19333				return parseInt( num[ 0 ], 10 );
19334			},
19335
19336			// Extract a name from the string value and convert to an index
19337			getName = function( match, shortNames, longNames ) {
19338				var index = -1,
19339					names = $.map( lookAhead( match ) ? longNames : shortNames, function( v, k ) {
19340						return [ [ k, v ] ];
19341					} ).sort( function( a, b ) {
19342						return -( a[ 1 ].length - b[ 1 ].length );
19343					} );
19344
19345				$.each( names, function( i, pair ) {
19346					var name = pair[ 1 ];
19347					if ( value.substr( iValue, name.length ).toLowerCase() === name.toLowerCase() ) {
19348						index = pair[ 0 ];
19349						iValue += name.length;
19350						return false;
19351					}
19352				} );
19353				if ( index !== -1 ) {
19354					return index + 1;
19355				} else {
19356					throw "Unknown name at position " + iValue;
19357				}
19358			},
19359
19360			// Confirm that a literal character matches the string value
19361			checkLiteral = function() {
19362				if ( value.charAt( iValue ) !== format.charAt( iFormat ) ) {
19363					throw "Unexpected literal at position " + iValue;
19364				}
19365				iValue++;
19366			};
19367
19368		for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
19369			if ( literal ) {
19370				if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
19371					literal = false;
19372				} else {
19373					checkLiteral();
19374				}
19375			} else {
19376				switch ( format.charAt( iFormat ) ) {
19377					case "d":
19378						day = getNumber( "d" );
19379						break;
19380					case "D":
19381						getName( "D", dayNamesShort, dayNames );
19382						break;
19383					case "o":
19384						doy = getNumber( "o" );
19385						break;
19386					case "m":
19387						month = getNumber( "m" );
19388						break;
19389					case "M":
19390						month = getName( "M", monthNamesShort, monthNames );
19391						break;
19392					case "y":
19393						year = getNumber( "y" );
19394						break;
19395					case "@":
19396						date = new Date( getNumber( "@" ) );
19397						year = date.getFullYear();
19398						month = date.getMonth() + 1;
19399						day = date.getDate();
19400						break;
19401					case "!":
19402						date = new Date( ( getNumber( "!" ) - this._ticksTo1970 ) / 10000 );
19403						year = date.getFullYear();
19404						month = date.getMonth() + 1;
19405						day = date.getDate();
19406						break;
19407					case "'":
19408						if ( lookAhead( "'" ) ) {
19409							checkLiteral();
19410						} else {
19411							literal = true;
19412						}
19413						break;
19414					default:
19415						checkLiteral();
19416				}
19417			}
19418		}
19419
19420		if ( iValue < value.length ) {
19421			extra = value.substr( iValue );
19422			if ( !/^\s+/.test( extra ) ) {
19423				throw "Extra/unparsed characters found in date: " + extra;
19424			}
19425		}
19426
19427		if ( year === -1 ) {
19428			year = new Date().getFullYear();
19429		} else if ( year < 100 ) {
19430			year += new Date().getFullYear() - new Date().getFullYear() % 100 +
19431				( year <= shortYearCutoff ? 0 : -100 );
19432		}
19433
19434		if ( doy > -1 ) {
19435			month = 1;
19436			day = doy;
19437			do {
19438				dim = this._getDaysInMonth( year, month - 1 );
19439				if ( day <= dim ) {
19440					break;
19441				}
19442				month++;
19443				day -= dim;
19444			} while ( true );
19445		}
19446
19447		date = this._daylightSavingAdjust( new Date( year, month - 1, day ) );
19448		if ( date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day ) {
19449			throw "Invalid date"; // E.g. 31/02/00
19450		}
19451		return date;
19452	},
19453
19454	/* Standard date formats. */
19455	ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601)
19456	COOKIE: "D, dd M yy",
19457	ISO_8601: "yy-mm-dd",
19458	RFC_822: "D, d M y",
19459	RFC_850: "DD, dd-M-y",
19460	RFC_1036: "D, d M y",
19461	RFC_1123: "D, d M yy",
19462	RFC_2822: "D, d M yy",
19463	RSS: "D, d M y", // RFC 822
19464	TICKS: "!",
19465	TIMESTAMP: "@",
19466	W3C: "yy-mm-dd", // ISO 8601
19467
19468	_ticksTo1970: ( ( ( 1970 - 1 ) * 365 + Math.floor( 1970 / 4 ) - Math.floor( 1970 / 100 ) +
19469		Math.floor( 1970 / 400 ) ) * 24 * 60 * 60 * 10000000 ),
19470
19471	/* Format a date object into a string value.
19472	 * The format can be combinations of the following:
19473	 * d  - day of month (no leading zero)
19474	 * dd - day of month (two digit)
19475	 * o  - day of year (no leading zeros)
19476	 * oo - day of year (three digit)
19477	 * D  - day name short
19478	 * DD - day name long
19479	 * m  - month of year (no leading zero)
19480	 * mm - month of year (two digit)
19481	 * M  - month name short
19482	 * MM - month name long
19483	 * y  - year (two digit)
19484	 * yy - year (four digit)
19485	 * @ - Unix timestamp (ms since 01/01/1970)
19486	 * ! - Windows ticks (100ns since 01/01/0001)
19487	 * "..." - literal text
19488	 * '' - single quote
19489	 *
19490	 * @param  format string - the desired format of the date
19491	 * @param  date Date - the date value to format
19492	 * @param  settings Object - attributes include:
19493	 *					dayNamesShort	string[7] - abbreviated names of the days from Sunday (optional)
19494	 *					dayNames		string[7] - names of the days from Sunday (optional)
19495	 *					monthNamesShort string[12] - abbreviated names of the months (optional)
19496	 *					monthNames		string[12] - names of the months (optional)
19497	 * @return  string - the date in the above format
19498	 */
19499	formatDate: function( format, date, settings ) {
19500		if ( !date ) {
19501			return "";
19502		}
19503
19504		var iFormat,
19505			dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort,
19506			dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames,
19507			monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort,
19508			monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames,
19509
19510			// Check whether a format character is doubled
19511			lookAhead = function( match ) {
19512				var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
19513				if ( matches ) {
19514					iFormat++;
19515				}
19516				return matches;
19517			},
19518
19519			// Format a number, with leading zero if necessary
19520			formatNumber = function( match, value, len ) {
19521				var num = "" + value;
19522				if ( lookAhead( match ) ) {
19523					while ( num.length < len ) {
19524						num = "0" + num;
19525					}
19526				}
19527				return num;
19528			},
19529
19530			// Format a name, short or long as requested
19531			formatName = function( match, value, shortNames, longNames ) {
19532				return ( lookAhead( match ) ? longNames[ value ] : shortNames[ value ] );
19533			},
19534			output = "",
19535			literal = false;
19536
19537		if ( date ) {
19538			for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
19539				if ( literal ) {
19540					if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
19541						literal = false;
19542					} else {
19543						output += format.charAt( iFormat );
19544					}
19545				} else {
19546					switch ( format.charAt( iFormat ) ) {
19547						case "d":
19548							output += formatNumber( "d", date.getDate(), 2 );
19549							break;
19550						case "D":
19551							output += formatName( "D", date.getDay(), dayNamesShort, dayNames );
19552							break;
19553						case "o":
19554							output += formatNumber( "o",
19555								Math.round( ( new Date( date.getFullYear(), date.getMonth(), date.getDate() ).getTime() - new Date( date.getFullYear(), 0, 0 ).getTime() ) / 86400000 ), 3 );
19556							break;
19557						case "m":
19558							output += formatNumber( "m", date.getMonth() + 1, 2 );
19559							break;
19560						case "M":
19561							output += formatName( "M", date.getMonth(), monthNamesShort, monthNames );
19562							break;
19563						case "y":
19564							output += ( lookAhead( "y" ) ? date.getFullYear() :
19565								( date.getFullYear() % 100 < 10 ? "0" : "" ) + date.getFullYear() % 100 );
19566							break;
19567						case "@":
19568							output += date.getTime();
19569							break;
19570						case "!":
19571							output += date.getTime() * 10000 + this._ticksTo1970;
19572							break;
19573						case "'":
19574							if ( lookAhead( "'" ) ) {
19575								output += "'";
19576							} else {
19577								literal = true;
19578							}
19579							break;
19580						default:
19581							output += format.charAt( iFormat );
19582					}
19583				}
19584			}
19585		}
19586		return output;
19587	},
19588
19589	/* Extract all possible characters from the date format. */
19590	_possibleChars: function( format ) {
19591		var iFormat,
19592			chars = "",
19593			literal = false,
19594
19595			// Check whether a format character is doubled
19596			lookAhead = function( match ) {
19597				var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
19598				if ( matches ) {
19599					iFormat++;
19600				}
19601				return matches;
19602			};
19603
19604		for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
19605			if ( literal ) {
19606				if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
19607					literal = false;
19608				} else {
19609					chars += format.charAt( iFormat );
19610				}
19611			} else {
19612				switch ( format.charAt( iFormat ) ) {
19613					case "d": case "m": case "y": case "@":
19614						chars += "0123456789";
19615						break;
19616					case "D": case "M":
19617						return null; // Accept anything
19618					case "'":
19619						if ( lookAhead( "'" ) ) {
19620							chars += "'";
19621						} else {
19622							literal = true;
19623						}
19624						break;
19625					default:
19626						chars += format.charAt( iFormat );
19627				}
19628			}
19629		}
19630		return chars;
19631	},
19632
19633	/* Get a setting value, defaulting if necessary. */
19634	_get: function( inst, name ) {
19635		return inst.settings[ name ] !== undefined ?
19636			inst.settings[ name ] : this._defaults[ name ];
19637	},
19638
19639	/* Parse existing date and initialise date picker. */
19640	_setDateFromField: function( inst, noDefault ) {
19641		if ( inst.input.val() === inst.lastVal ) {
19642			return;
19643		}
19644
19645		var dateFormat = this._get( inst, "dateFormat" ),
19646			dates = inst.lastVal = inst.input ? inst.input.val() : null,
19647			defaultDate = this._getDefaultDate( inst ),
19648			date = defaultDate,
19649			settings = this._getFormatConfig( inst );
19650
19651		try {
19652			date = this.parseDate( dateFormat, dates, settings ) || defaultDate;
19653		} catch ( event ) {
19654			dates = ( noDefault ? "" : dates );
19655		}
19656		inst.selectedDay = date.getDate();
19657		inst.drawMonth = inst.selectedMonth = date.getMonth();
19658		inst.drawYear = inst.selectedYear = date.getFullYear();
19659		inst.currentDay = ( dates ? date.getDate() : 0 );
19660		inst.currentMonth = ( dates ? date.getMonth() : 0 );
19661		inst.currentYear = ( dates ? date.getFullYear() : 0 );
19662		this._adjustInstDate( inst );
19663	},
19664
19665	/* Retrieve the default date shown on opening. */
19666	_getDefaultDate: function( inst ) {
19667		return this._restrictMinMax( inst,
19668			this._determineDate( inst, this._get( inst, "defaultDate" ), new Date() ) );
19669	},
19670
19671	/* A date may be specified as an exact value or a relative one. */
19672	_determineDate: function( inst, date, defaultDate ) {
19673		var offsetNumeric = function( offset ) {
19674				var date = new Date();
19675				date.setDate( date.getDate() + offset );
19676				return date;
19677			},
19678			offsetString = function( offset ) {
19679				try {
19680					return $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ),
19681						offset, $.datepicker._getFormatConfig( inst ) );
19682				} catch ( e ) {
19683
19684					// Ignore
19685				}
19686
19687				var date = ( offset.toLowerCase().match( /^c/ ) ?
19688					$.datepicker._getDate( inst ) : null ) || new Date(),
19689					year = date.getFullYear(),
19690					month = date.getMonth(),
19691					day = date.getDate(),
19692					pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,
19693					matches = pattern.exec( offset );
19694
19695				while ( matches ) {
19696					switch ( matches[ 2 ] || "d" ) {
19697						case "d" : case "D" :
19698							day += parseInt( matches[ 1 ], 10 ); break;
19699						case "w" : case "W" :
19700							day += parseInt( matches[ 1 ], 10 ) * 7; break;
19701						case "m" : case "M" :
19702							month += parseInt( matches[ 1 ], 10 );
19703							day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) );
19704							break;
19705						case "y": case "Y" :
19706							year += parseInt( matches[ 1 ], 10 );
19707							day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) );
19708							break;
19709					}
19710					matches = pattern.exec( offset );
19711				}
19712				return new Date( year, month, day );
19713			},
19714			newDate = ( date == null || date === "" ? defaultDate : ( typeof date === "string" ? offsetString( date ) :
19715				( typeof date === "number" ? ( isNaN( date ) ? defaultDate : offsetNumeric( date ) ) : new Date( date.getTime() ) ) ) );
19716
19717		newDate = ( newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate );
19718		if ( newDate ) {
19719			newDate.setHours( 0 );
19720			newDate.setMinutes( 0 );
19721			newDate.setSeconds( 0 );
19722			newDate.setMilliseconds( 0 );
19723		}
19724		return this._daylightSavingAdjust( newDate );
19725	},
19726
19727	/* Handle switch to/from daylight saving.
19728	 * Hours may be non-zero on daylight saving cut-over:
19729	 * > 12 when midnight changeover, but then cannot generate
19730	 * midnight datetime, so jump to 1AM, otherwise reset.
19731	 * @param  date  (Date) the date to check
19732	 * @return  (Date) the corrected date
19733	 */
19734	_daylightSavingAdjust: function( date ) {
19735		if ( !date ) {
19736			return null;
19737		}
19738		date.setHours( date.getHours() > 12 ? date.getHours() + 2 : 0 );
19739		return date;
19740	},
19741
19742	/* Set the date(s) directly. */
19743	_setDate: function( inst, date, noChange ) {
19744		var clear = !date,
19745			origMonth = inst.selectedMonth,
19746			origYear = inst.selectedYear,
19747			newDate = this._restrictMinMax( inst, this._determineDate( inst, date, new Date() ) );
19748
19749		inst.selectedDay = inst.currentDay = newDate.getDate();
19750		inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
19751		inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
19752		if ( ( origMonth !== inst.selectedMonth || origYear !== inst.selectedYear ) && !noChange ) {
19753			this._notifyChange( inst );
19754		}
19755		this._adjustInstDate( inst );
19756		if ( inst.input ) {
19757			inst.input.val( clear ? "" : this._formatDate( inst ) );
19758		}
19759	},
19760
19761	/* Retrieve the date(s) directly. */
19762	_getDate: function( inst ) {
19763		var startDate = ( !inst.currentYear || ( inst.input && inst.input.val() === "" ) ? null :
19764			this._daylightSavingAdjust( new Date(
19765			inst.currentYear, inst.currentMonth, inst.currentDay ) ) );
19766			return startDate;
19767	},
19768
19769	/* Attach the onxxx handlers.  These are declared statically so
19770	 * they work with static code transformers like Caja.
19771	 */
19772	_attachHandlers: function( inst ) {
19773		var stepMonths = this._get( inst, "stepMonths" ),
19774			id = "#" + inst.id.replace( /\\\\/g, "\\" );
19775		inst.dpDiv.find( "[data-handler]" ).map( function() {
19776			var handler = {
19777				prev: function() {
19778					$.datepicker._adjustDate( id, -stepMonths, "M" );
19779				},
19780				next: function() {
19781					$.datepicker._adjustDate( id, +stepMonths, "M" );
19782				},
19783				hide: function() {
19784					$.datepicker._hideDatepicker();
19785				},
19786				today: function() {
19787					$.datepicker._gotoToday( id );
19788				},
19789				selectDay: function() {
19790					$.datepicker._selectDay( id, +this.getAttribute( "data-month" ), +this.getAttribute( "data-year" ), this );
19791					return false;
19792				},
19793				selectMonth: function() {
19794					$.datepicker._selectMonthYear( id, this, "M" );
19795					return false;
19796				},
19797				selectYear: function() {
19798					$.datepicker._selectMonthYear( id, this, "Y" );
19799					return false;
19800				}
19801			};
19802			$( this ).on( this.getAttribute( "data-event" ), handler[ this.getAttribute( "data-handler" ) ] );
19803		} );
19804	},
19805
19806	/* Generate the HTML for the current state of the date picker. */
19807	_generateHTML: function( inst ) {
19808		var maxDraw, prevText, prev, nextText, next, currentText, gotoDate,
19809			controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,
19810			monthNames, monthNamesShort, beforeShowDay, showOtherMonths,
19811			selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,
19812			cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,
19813			printDate, dRow, tbody, daySettings, otherMonth, unselectable,
19814			tempDate = new Date(),
19815			today = this._daylightSavingAdjust(
19816				new Date( tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate() ) ), // clear time
19817			isRTL = this._get( inst, "isRTL" ),
19818			showButtonPanel = this._get( inst, "showButtonPanel" ),
19819			hideIfNoPrevNext = this._get( inst, "hideIfNoPrevNext" ),
19820			navigationAsDateFormat = this._get( inst, "navigationAsDateFormat" ),
19821			numMonths = this._getNumberOfMonths( inst ),
19822			showCurrentAtPos = this._get( inst, "showCurrentAtPos" ),
19823			stepMonths = this._get( inst, "stepMonths" ),
19824			isMultiMonth = ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ),
19825			currentDate = this._daylightSavingAdjust( ( !inst.currentDay ? new Date( 9999, 9, 9 ) :
19826				new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) ),
19827			minDate = this._getMinMaxDate( inst, "min" ),
19828			maxDate = this._getMinMaxDate( inst, "max" ),
19829			drawMonth = inst.drawMonth - showCurrentAtPos,
19830			drawYear = inst.drawYear;
19831
19832		if ( drawMonth < 0 ) {
19833			drawMonth += 12;
19834			drawYear--;
19835		}
19836		if ( maxDate ) {
19837			maxDraw = this._daylightSavingAdjust( new Date( maxDate.getFullYear(),
19838				maxDate.getMonth() - ( numMonths[ 0 ] * numMonths[ 1 ] ) + 1, maxDate.getDate() ) );
19839			maxDraw = ( minDate && maxDraw < minDate ? minDate : maxDraw );
19840			while ( this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 ) ) > maxDraw ) {
19841				drawMonth--;
19842				if ( drawMonth < 0 ) {
19843					drawMonth = 11;
19844					drawYear--;
19845				}
19846			}
19847		}
19848		inst.drawMonth = drawMonth;
19849		inst.drawYear = drawYear;
19850
19851		prevText = this._get( inst, "prevText" );
19852		prevText = ( !navigationAsDateFormat ? prevText : this.formatDate( prevText,
19853			this._daylightSavingAdjust( new Date( drawYear, drawMonth - stepMonths, 1 ) ),
19854			this._getFormatConfig( inst ) ) );
19855
19856		if ( this._canAdjustMonth( inst, -1, drawYear, drawMonth ) ) {
19857			prev = $( "<a>" )
19858				.attr( {
19859					"class": "ui-datepicker-prev ui-corner-all",
19860					"data-handler": "prev",
19861					"data-event": "click",
19862					title: prevText
19863				} )
19864				.append(
19865					$( "<span>" )
19866						.addClass( "ui-icon ui-icon-circle-triangle-" +
19867							( isRTL ? "e" : "w" ) )
19868						.text( prevText )
19869				)[ 0 ].outerHTML;
19870		} else if ( hideIfNoPrevNext ) {
19871			prev = "";
19872		} else {
19873			prev = $( "<a>" )
19874				.attr( {
19875					"class": "ui-datepicker-prev ui-corner-all ui-state-disabled",
19876					title: prevText
19877				} )
19878				.append(
19879					$( "<span>" )
19880						.addClass( "ui-icon ui-icon-circle-triangle-" +
19881							( isRTL ? "e" : "w" ) )
19882						.text( prevText )
19883				)[ 0 ].outerHTML;
19884		}
19885
19886		nextText = this._get( inst, "nextText" );
19887		nextText = ( !navigationAsDateFormat ? nextText : this.formatDate( nextText,
19888			this._daylightSavingAdjust( new Date( drawYear, drawMonth + stepMonths, 1 ) ),
19889			this._getFormatConfig( inst ) ) );
19890
19891		if ( this._canAdjustMonth( inst, +1, drawYear, drawMonth ) ) {
19892			next = $( "<a>" )
19893				.attr( {
19894					"class": "ui-datepicker-next ui-corner-all",
19895					"data-handler": "next",
19896					"data-event": "click",
19897					title: nextText
19898				} )
19899				.append(
19900					$( "<span>" )
19901						.addClass( "ui-icon ui-icon-circle-triangle-" +
19902							( isRTL ? "w" : "e" ) )
19903						.text( nextText )
19904				)[ 0 ].outerHTML;
19905		} else if ( hideIfNoPrevNext ) {
19906			next = "";
19907		} else {
19908			next = $( "<a>" )
19909				.attr( {
19910					"class": "ui-datepicker-next ui-corner-all ui-state-disabled",
19911					title: nextText
19912				} )
19913				.append(
19914					$( "<span>" )
19915						.attr( "class", "ui-icon ui-icon-circle-triangle-" +
19916							( isRTL ? "w" : "e" ) )
19917						.text( nextText )
19918				)[ 0 ].outerHTML;
19919		}
19920
19921		currentText = this._get( inst, "currentText" );
19922		gotoDate = ( this._get( inst, "gotoCurrent" ) && inst.currentDay ? currentDate : today );
19923		currentText = ( !navigationAsDateFormat ? currentText :
19924			this.formatDate( currentText, gotoDate, this._getFormatConfig( inst ) ) );
19925
19926		controls = "";
19927		if ( !inst.inline ) {
19928			controls = $( "<button>" )
19929				.attr( {
19930					type: "button",
19931					"class": "ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all",
19932					"data-handler": "hide",
19933					"data-event": "click"
19934				} )
19935				.text( this._get( inst, "closeText" ) )[ 0 ].outerHTML;
19936		}
19937
19938		buttonPanel = "";
19939		if ( showButtonPanel ) {
19940			buttonPanel = $( "<div class='ui-datepicker-buttonpane ui-widget-content'>" )
19941				.append( isRTL ? controls : "" )
19942				.append( this._isInRange( inst, gotoDate ) ?
19943					$( "<button>" )
19944						.attr( {
19945							type: "button",
19946							"class": "ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all",
19947							"data-handler": "today",
19948							"data-event": "click"
19949						} )
19950						.text( currentText ) :
19951					"" )
19952				.append( isRTL ? "" : controls )[ 0 ].outerHTML;
19953		}
19954
19955		firstDay = parseInt( this._get( inst, "firstDay" ), 10 );
19956		firstDay = ( isNaN( firstDay ) ? 0 : firstDay );
19957
19958		showWeek = this._get( inst, "showWeek" );
19959		dayNames = this._get( inst, "dayNames" );
19960		dayNamesMin = this._get( inst, "dayNamesMin" );
19961		monthNames = this._get( inst, "monthNames" );
19962		monthNamesShort = this._get( inst, "monthNamesShort" );
19963		beforeShowDay = this._get( inst, "beforeShowDay" );
19964		showOtherMonths = this._get( inst, "showOtherMonths" );
19965		selectOtherMonths = this._get( inst, "selectOtherMonths" );
19966		defaultDate = this._getDefaultDate( inst );
19967		html = "";
19968
19969		for ( row = 0; row < numMonths[ 0 ]; row++ ) {
19970			group = "";
19971			this.maxRows = 4;
19972			for ( col = 0; col < numMonths[ 1 ]; col++ ) {
19973				selectedDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, inst.selectedDay ) );
19974				cornerClass = " ui-corner-all";
19975				calender = "";
19976				if ( isMultiMonth ) {
19977					calender += "<div class='ui-datepicker-group";
19978					if ( numMonths[ 1 ] > 1 ) {
19979						switch ( col ) {
19980							case 0: calender += " ui-datepicker-group-first";
19981								cornerClass = " ui-corner-" + ( isRTL ? "right" : "left" ); break;
19982							case numMonths[ 1 ] - 1: calender += " ui-datepicker-group-last";
19983								cornerClass = " ui-corner-" + ( isRTL ? "left" : "right" ); break;
19984							default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break;
19985						}
19986					}
19987					calender += "'>";
19988				}
19989				calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" +
19990					( /all|left/.test( cornerClass ) && row === 0 ? ( isRTL ? next : prev ) : "" ) +
19991					( /all|right/.test( cornerClass ) && row === 0 ? ( isRTL ? prev : next ) : "" ) +
19992					this._generateMonthYearHeader( inst, drawMonth, drawYear, minDate, maxDate,
19993					row > 0 || col > 0, monthNames, monthNamesShort ) + // draw month headers
19994					"</div><table class='ui-datepicker-calendar'><thead>" +
19995					"<tr>";
19996				thead = ( showWeek ? "<th class='ui-datepicker-week-col'>" + this._get( inst, "weekHeader" ) + "</th>" : "" );
19997				for ( dow = 0; dow < 7; dow++ ) { // days of the week
19998					day = ( dow + firstDay ) % 7;
19999					thead += "<th scope='col'" + ( ( dow + firstDay + 6 ) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "" ) + ">" +
20000						"<span title='" + dayNames[ day ] + "'>" + dayNamesMin[ day ] + "</span></th>";
20001				}
20002				calender += thead + "</tr></thead><tbody>";
20003				daysInMonth = this._getDaysInMonth( drawYear, drawMonth );
20004				if ( drawYear === inst.selectedYear && drawMonth === inst.selectedMonth ) {
20005					inst.selectedDay = Math.min( inst.selectedDay, daysInMonth );
20006				}
20007				leadDays = ( this._getFirstDayOfMonth( drawYear, drawMonth ) - firstDay + 7 ) % 7;
20008				curRows = Math.ceil( ( leadDays + daysInMonth ) / 7 ); // calculate the number of rows to generate
20009				numRows = ( isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows ); //If multiple months, use the higher number of rows (see #7043)
20010				this.maxRows = numRows;
20011				printDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 - leadDays ) );
20012				for ( dRow = 0; dRow < numRows; dRow++ ) { // create date picker rows
20013					calender += "<tr>";
20014					tbody = ( !showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
20015						this._get( inst, "calculateWeek" )( printDate ) + "</td>" );
20016					for ( dow = 0; dow < 7; dow++ ) { // create date picker days
20017						daySettings = ( beforeShowDay ?
20018							beforeShowDay.apply( ( inst.input ? inst.input[ 0 ] : null ), [ printDate ] ) : [ true, "" ] );
20019						otherMonth = ( printDate.getMonth() !== drawMonth );
20020						unselectable = ( otherMonth && !selectOtherMonths ) || !daySettings[ 0 ] ||
20021							( minDate && printDate < minDate ) || ( maxDate && printDate > maxDate );
20022						tbody += "<td class='" +
20023							( ( dow + firstDay + 6 ) % 7 >= 5 ? " ui-datepicker-week-end" : "" ) + // highlight weekends
20024							( otherMonth ? " ui-datepicker-other-month" : "" ) + // highlight days from other months
20025							( ( printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent ) || // user pressed key
20026							( defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime() ) ?
20027
20028							// or defaultDate is current printedDate and defaultDate is selectedDate
20029							" " + this._dayOverClass : "" ) + // highlight selected day
20030							( unselectable ? " " + this._unselectableClass + " ui-state-disabled" : "" ) +  // highlight unselectable days
20031							( otherMonth && !showOtherMonths ? "" : " " + daySettings[ 1 ] + // highlight custom dates
20032							( printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "" ) + // highlight selected day
20033							( printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "" ) ) + "'" + // highlight today (if different)
20034							( ( !otherMonth || showOtherMonths ) && daySettings[ 2 ] ? " title='" + daySettings[ 2 ].replace( /'/g, "&#39;" ) + "'" : "" ) + // cell title
20035							( unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'" ) + ">" + // actions
20036							( otherMonth && !showOtherMonths ? "&#xa0;" : // display for other months
20037							( unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" +
20038							( printDate.getTime() === today.getTime() ? " ui-state-highlight" : "" ) +
20039							( printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "" ) + // highlight selected day
20040							( otherMonth ? " ui-priority-secondary" : "" ) + // distinguish dates from other months
20041							"' href='#' aria-current='" + ( printDate.getTime() === currentDate.getTime() ? "true" : "false" ) + // mark date as selected for screen reader
20042							"' data-date='" + printDate.getDate() + // store date as data
20043							"'>" + printDate.getDate() + "</a>" ) ) + "</td>"; // display selectable date
20044						printDate.setDate( printDate.getDate() + 1 );
20045						printDate = this._daylightSavingAdjust( printDate );
20046					}
20047					calender += tbody + "</tr>";
20048				}
20049				drawMonth++;
20050				if ( drawMonth > 11 ) {
20051					drawMonth = 0;
20052					drawYear++;
20053				}
20054				calender += "</tbody></table>" + ( isMultiMonth ? "</div>" +
20055							( ( numMonths[ 0 ] > 0 && col === numMonths[ 1 ] - 1 ) ? "<div class='ui-datepicker-row-break'></div>" : "" ) : "" );
20056				group += calender;
20057			}
20058			html += group;
20059		}
20060		html += buttonPanel;
20061		inst._keyEvent = false;
20062		return html;
20063	},
20064
20065	/* Generate the month and year header. */
20066	_generateMonthYearHeader: function( inst, drawMonth, drawYear, minDate, maxDate,
20067			secondary, monthNames, monthNamesShort ) {
20068
20069		var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,
20070			changeMonth = this._get( inst, "changeMonth" ),
20071			changeYear = this._get( inst, "changeYear" ),
20072			showMonthAfterYear = this._get( inst, "showMonthAfterYear" ),
20073			selectMonthLabel = this._get( inst, "selectMonthLabel" ),
20074			selectYearLabel = this._get( inst, "selectYearLabel" ),
20075			html = "<div class='ui-datepicker-title'>",
20076			monthHtml = "";
20077
20078		// Month selection
20079		if ( secondary || !changeMonth ) {
20080			monthHtml += "<span class='ui-datepicker-month'>" + monthNames[ drawMonth ] + "</span>";
20081		} else {
20082			inMinYear = ( minDate && minDate.getFullYear() === drawYear );
20083			inMaxYear = ( maxDate && maxDate.getFullYear() === drawYear );
20084			monthHtml += "<select class='ui-datepicker-month' aria-label='" + selectMonthLabel + "' data-handler='selectMonth' data-event='change'>";
20085			for ( month = 0; month < 12; month++ ) {
20086				if ( ( !inMinYear || month >= minDate.getMonth() ) && ( !inMaxYear || month <= maxDate.getMonth() ) ) {
20087					monthHtml += "<option value='" + month + "'" +
20088						( month === drawMonth ? " selected='selected'" : "" ) +
20089						">" + monthNamesShort[ month ] + "</option>";
20090				}
20091			}
20092			monthHtml += "</select>";
20093		}
20094
20095		if ( !showMonthAfterYear ) {
20096			html += monthHtml + ( secondary || !( changeMonth && changeYear ) ? "&#xa0;" : "" );
20097		}
20098
20099		// Year selection
20100		if ( !inst.yearshtml ) {
20101			inst.yearshtml = "";
20102			if ( secondary || !changeYear ) {
20103				html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
20104			} else {
20105
20106				// determine range of years to display
20107				years = this._get( inst, "yearRange" ).split( ":" );
20108				thisYear = new Date().getFullYear();
20109				determineYear = function( value ) {
20110					var year = ( value.match( /c[+\-].*/ ) ? drawYear + parseInt( value.substring( 1 ), 10 ) :
20111						( value.match( /[+\-].*/ ) ? thisYear + parseInt( value, 10 ) :
20112						parseInt( value, 10 ) ) );
20113					return ( isNaN( year ) ? thisYear : year );
20114				};
20115				year = determineYear( years[ 0 ] );
20116				endYear = Math.max( year, determineYear( years[ 1 ] || "" ) );
20117				year = ( minDate ? Math.max( year, minDate.getFullYear() ) : year );
20118				endYear = ( maxDate ? Math.min( endYear, maxDate.getFullYear() ) : endYear );
20119				inst.yearshtml += "<select class='ui-datepicker-year' aria-label='" + selectYearLabel + "' data-handler='selectYear' data-event='change'>";
20120				for ( ; year <= endYear; year++ ) {
20121					inst.yearshtml += "<option value='" + year + "'" +
20122						( year === drawYear ? " selected='selected'" : "" ) +
20123						">" + year + "</option>";
20124				}
20125				inst.yearshtml += "</select>";
20126
20127				html += inst.yearshtml;
20128				inst.yearshtml = null;
20129			}
20130		}
20131
20132		html += this._get( inst, "yearSuffix" );
20133		if ( showMonthAfterYear ) {
20134			html += ( secondary || !( changeMonth && changeYear ) ? "&#xa0;" : "" ) + monthHtml;
20135		}
20136		html += "</div>"; // Close datepicker_header
20137		return html;
20138	},
20139
20140	/* Adjust one of the date sub-fields. */
20141	_adjustInstDate: function( inst, offset, period ) {
20142		var year = inst.selectedYear + ( period === "Y" ? offset : 0 ),
20143			month = inst.selectedMonth + ( period === "M" ? offset : 0 ),
20144			day = Math.min( inst.selectedDay, this._getDaysInMonth( year, month ) ) + ( period === "D" ? offset : 0 ),
20145			date = this._restrictMinMax( inst, this._daylightSavingAdjust( new Date( year, month, day ) ) );
20146
20147		inst.selectedDay = date.getDate();
20148		inst.drawMonth = inst.selectedMonth = date.getMonth();
20149		inst.drawYear = inst.selectedYear = date.getFullYear();
20150		if ( period === "M" || period === "Y" ) {
20151			this._notifyChange( inst );
20152		}
20153	},
20154
20155	/* Ensure a date is within any min/max bounds. */
20156	_restrictMinMax: function( inst, date ) {
20157		var minDate = this._getMinMaxDate( inst, "min" ),
20158			maxDate = this._getMinMaxDate( inst, "max" ),
20159			newDate = ( minDate && date < minDate ? minDate : date );
20160		return ( maxDate && newDate > maxDate ? maxDate : newDate );
20161	},
20162
20163	/* Notify change of month/year. */
20164	_notifyChange: function( inst ) {
20165		var onChange = this._get( inst, "onChangeMonthYear" );
20166		if ( onChange ) {
20167			onChange.apply( ( inst.input ? inst.input[ 0 ] : null ),
20168				[ inst.selectedYear, inst.selectedMonth + 1, inst ] );
20169		}
20170	},
20171
20172	/* Determine the number of months to show. */
20173	_getNumberOfMonths: function( inst ) {
20174		var numMonths = this._get( inst, "numberOfMonths" );
20175		return ( numMonths == null ? [ 1, 1 ] : ( typeof numMonths === "number" ? [ 1, numMonths ] : numMonths ) );
20176	},
20177
20178	/* Determine the current maximum date - ensure no time components are set. */
20179	_getMinMaxDate: function( inst, minMax ) {
20180		return this._determineDate( inst, this._get( inst, minMax + "Date" ), null );
20181	},
20182
20183	/* Find the number of days in a given month. */
20184	_getDaysInMonth: function( year, month ) {
20185		return 32 - this._daylightSavingAdjust( new Date( year, month, 32 ) ).getDate();
20186	},
20187
20188	/* Find the day of the week of the first of a month. */
20189	_getFirstDayOfMonth: function( year, month ) {
20190		return new Date( year, month, 1 ).getDay();
20191	},
20192
20193	/* Determines if we should allow a "next/prev" month display change. */
20194	_canAdjustMonth: function( inst, offset, curYear, curMonth ) {
20195		var numMonths = this._getNumberOfMonths( inst ),
20196			date = this._daylightSavingAdjust( new Date( curYear,
20197			curMonth + ( offset < 0 ? offset : numMonths[ 0 ] * numMonths[ 1 ] ), 1 ) );
20198
20199		if ( offset < 0 ) {
20200			date.setDate( this._getDaysInMonth( date.getFullYear(), date.getMonth() ) );
20201		}
20202		return this._isInRange( inst, date );
20203	},
20204
20205	/* Is the given date in the accepted range? */
20206	_isInRange: function( inst, date ) {
20207		var yearSplit, currentYear,
20208			minDate = this._getMinMaxDate( inst, "min" ),
20209			maxDate = this._getMinMaxDate( inst, "max" ),
20210			minYear = null,
20211			maxYear = null,
20212			years = this._get( inst, "yearRange" );
20213			if ( years ) {
20214				yearSplit = years.split( ":" );
20215				currentYear = new Date().getFullYear();
20216				minYear = parseInt( yearSplit[ 0 ], 10 );
20217				maxYear = parseInt( yearSplit[ 1 ], 10 );
20218				if ( yearSplit[ 0 ].match( /[+\-].*/ ) ) {
20219					minYear += currentYear;
20220				}
20221				if ( yearSplit[ 1 ].match( /[+\-].*/ ) ) {
20222					maxYear += currentYear;
20223				}
20224			}
20225
20226		return ( ( !minDate || date.getTime() >= minDate.getTime() ) &&
20227			( !maxDate || date.getTime() <= maxDate.getTime() ) &&
20228			( !minYear || date.getFullYear() >= minYear ) &&
20229			( !maxYear || date.getFullYear() <= maxYear ) );
20230	},
20231
20232	/* Provide the configuration settings for formatting/parsing. */
20233	_getFormatConfig: function( inst ) {
20234		var shortYearCutoff = this._get( inst, "shortYearCutoff" );
20235		shortYearCutoff = ( typeof shortYearCutoff !== "string" ? shortYearCutoff :
20236			new Date().getFullYear() % 100 + parseInt( shortYearCutoff, 10 ) );
20237		return { shortYearCutoff: shortYearCutoff,
20238			dayNamesShort: this._get( inst, "dayNamesShort" ), dayNames: this._get( inst, "dayNames" ),
20239			monthNamesShort: this._get( inst, "monthNamesShort" ), monthNames: this._get( inst, "monthNames" ) };
20240	},
20241
20242	/* Format the given date for display. */
20243	_formatDate: function( inst, day, month, year ) {
20244		if ( !day ) {
20245			inst.currentDay = inst.selectedDay;
20246			inst.currentMonth = inst.selectedMonth;
20247			inst.currentYear = inst.selectedYear;
20248		}
20249		var date = ( day ? ( typeof day === "object" ? day :
20250			this._daylightSavingAdjust( new Date( year, month, day ) ) ) :
20251			this._daylightSavingAdjust( new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) );
20252		return this.formatDate( this._get( inst, "dateFormat" ), date, this._getFormatConfig( inst ) );
20253	}
20254} );
20255
20256/*
20257 * Bind hover events for datepicker elements.
20258 * Done via delegate so the binding only occurs once in the lifetime of the parent div.
20259 * Global datepicker_instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
20260 */
20261function datepicker_bindHover( dpDiv ) {
20262	var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";
20263	return dpDiv.on( "mouseout", selector, function() {
20264			$( this ).removeClass( "ui-state-hover" );
20265			if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) {
20266				$( this ).removeClass( "ui-datepicker-prev-hover" );
20267			}
20268			if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) {
20269				$( this ).removeClass( "ui-datepicker-next-hover" );
20270			}
20271		} )
20272		.on( "mouseover", selector, datepicker_handleMouseover );
20273}
20274
20275function datepicker_handleMouseover() {
20276	if ( !$.datepicker._isDisabledDatepicker( datepicker_instActive.inline ? datepicker_instActive.dpDiv.parent()[ 0 ] : datepicker_instActive.input[ 0 ] ) ) {
20277		$( this ).parents( ".ui-datepicker-calendar" ).find( "a" ).removeClass( "ui-state-hover" );
20278		$( this ).addClass( "ui-state-hover" );
20279		if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) {
20280			$( this ).addClass( "ui-datepicker-prev-hover" );
20281		}
20282		if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) {
20283			$( this ).addClass( "ui-datepicker-next-hover" );
20284		}
20285	}
20286}
20287
20288/* jQuery extend now ignores nulls! */
20289function datepicker_extendRemove( target, props ) {
20290	$.extend( target, props );
20291	for ( var name in props ) {
20292		if ( props[ name ] == null ) {
20293			target[ name ] = props[ name ];
20294		}
20295	}
20296	return target;
20297}
20298
20299/* Invoke the datepicker functionality.
20300   @param  options  string - a command, optionally followed by additional parameters or
20301					Object - settings for attaching new datepicker functionality
20302   @return  jQuery object */
20303$.fn.datepicker = function( options ) {
20304
20305	/* Verify an empty collection wasn't passed - Fixes #6976 */
20306	if ( !this.length ) {
20307		return this;
20308	}
20309
20310	/* Initialise the date picker. */
20311	if ( !$.datepicker.initialized ) {
20312		$( document ).on( "mousedown", $.datepicker._checkExternalClick );
20313		$.datepicker.initialized = true;
20314	}
20315
20316	/* Append datepicker main container to body if not exist. */
20317	if ( $( "#" + $.datepicker._mainDivId ).length === 0 ) {
20318		$( "body" ).append( $.datepicker.dpDiv );
20319	}
20320
20321	var otherArgs = Array.prototype.slice.call( arguments, 1 );
20322	if ( typeof options === "string" && ( options === "isDisabled" || options === "getDate" || options === "widget" ) ) {
20323		return $.datepicker[ "_" + options + "Datepicker" ].
20324			apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) );
20325	}
20326	if ( options === "option" && arguments.length === 2 && typeof arguments[ 1 ] === "string" ) {
20327		return $.datepicker[ "_" + options + "Datepicker" ].
20328			apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) );
20329	}
20330	return this.each( function() {
20331		if ( typeof options === "string" ) {
20332			$.datepicker[ "_" + options + "Datepicker" ]
20333				.apply( $.datepicker, [ this ].concat( otherArgs ) );
20334		} else {
20335			$.datepicker._attachDatepicker( this, options );
20336		}
20337	} );
20338};
vendor: 14,641 bytes, lines 20339-20890
20339
20340$.datepicker = new Datepicker(); // singleton instance
20341$.datepicker.initialized = false;
20342$.datepicker.uuid = new Date().getTime();
20343$.datepicker.version = "1.13.2";
20344
20345var widgetsDatepicker = $.datepicker;
20346
20347
20348
20349// This file is deprecated
20350var ie = $.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() );
20351
20352/*!
20353 * jQuery UI Mouse 1.13.2
20354 * http://jqueryui.com
20355 *
20356 * Copyright jQuery Foundation and other contributors
20357 * Released under the MIT license.
20358 * http://jquery.org/license
20359 */
20360
20361//>>label: Mouse
20362//>>group: Widgets
20363//>>description: Abstracts mouse-based interactions to assist in creating certain widgets.
20364//>>docs: http://api.jqueryui.com/mouse/
20365
20366
20367var mouseHandled = false;
20368$( document ).on( "mouseup", function() {
20369	mouseHandled = false;
20370} );
20371
20372var widgetsMouse = $.widget( "ui.mouse", {
20373	version: "1.13.2",
20374	options: {
20375		cancel: "input, textarea, button, select, option",
20376		distance: 1,
20377		delay: 0
20378	},
20379	_mouseInit: function() {
20380		var that = this;
20381
20382		this.element
20383			.on( "mousedown." + this.widgetName, function( event ) {
20384				return that._mouseDown( event );
20385			} )
20386			.on( "click." + this.widgetName, function( event ) {
20387				if ( true === $.data( event.target, that.widgetName + ".preventClickEvent" ) ) {
20388					$.removeData( event.target, that.widgetName + ".preventClickEvent" );
20389					event.stopImmediatePropagation();
20390					return false;
20391				}
20392			} );
20393
20394		this.started = false;
20395	},
20396
20397	// TODO: make sure destroying one instance of mouse doesn't mess with
20398	// other instances of mouse
20399	_mouseDestroy: function() {
20400		this.element.off( "." + this.widgetName );
20401		if ( this._mouseMoveDelegate ) {
20402			this.document
20403				.off( "mousemove." + this.widgetName, this._mouseMoveDelegate )
20404				.off( "mouseup." + this.widgetName, this._mouseUpDelegate );
20405		}
20406	},
20407
20408	_mouseDown: function( event ) {
20409
20410		// don't let more than one widget handle mouseStart
20411		if ( mouseHandled ) {
20412			return;
20413		}
20414
20415		this._mouseMoved = false;
20416
20417		// We may have missed mouseup (out of window)
20418		if ( this._mouseStarted ) {
20419			this._mouseUp( event );
20420		}
20421
20422		this._mouseDownEvent = event;
20423
20424		var that = this,
20425			btnIsLeft = ( event.which === 1 ),
20426
20427			// event.target.nodeName works around a bug in IE 8 with
20428			// disabled inputs (#7620)
20429			elIsCancel = ( typeof this.options.cancel === "string" && event.target.nodeName ?
20430				$( event.target ).closest( this.options.cancel ).length : false );
20431		if ( !btnIsLeft || elIsCancel || !this._mouseCapture( event ) ) {
20432			return true;
20433		}
20434
20435		this.mouseDelayMet = !this.options.delay;
20436		if ( !this.mouseDelayMet ) {
20437			this._mouseDelayTimer = setTimeout( function() {
20438				that.mouseDelayMet = true;
20439			}, this.options.delay );
20440		}
20441
20442		if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) {
20443			this._mouseStarted = ( this._mouseStart( event ) !== false );
20444			if ( !this._mouseStarted ) {
20445				event.preventDefault();
20446				return true;
20447			}
20448		}
20449
20450		// Click event may never have fired (Gecko & Opera)
20451		if ( true === $.data( event.target, this.widgetName + ".preventClickEvent" ) ) {
20452			$.removeData( event.target, this.widgetName + ".preventClickEvent" );
20453		}
20454
20455		// These delegates are required to keep context
20456		this._mouseMoveDelegate = function( event ) {
20457			return that._mouseMove( event );
20458		};
20459		this._mouseUpDelegate = function( event ) {
20460			return that._mouseUp( event );
20461		};
20462
20463		this.document
20464			.on( "mousemove." + this.widgetName, this._mouseMoveDelegate )
20465			.on( "mouseup." + this.widgetName, this._mouseUpDelegate );
20466
20467		event.preventDefault();
20468
20469		mouseHandled = true;
20470		return true;
20471	},
20472
20473	_mouseMove: function( event ) {
20474
20475		// Only check for mouseups outside the document if you've moved inside the document
20476		// at least once. This prevents the firing of mouseup in the case of IE<9, which will
20477		// fire a mousemove event if content is placed under the cursor. See #7778
20478		// Support: IE <9
20479		if ( this._mouseMoved ) {
20480
20481			// IE mouseup check - mouseup happened when mouse was out of window
20482			if ( $.ui.ie && ( !document.documentMode || document.documentMode < 9 ) &&
20483					!event.button ) {
20484				return this._mouseUp( event );
20485
20486			// Iframe mouseup check - mouseup occurred in another document
20487			} else if ( !event.which ) {
20488
20489				// Support: Safari <=8 - 9
20490				// Safari sets which to 0 if you press any of the following keys
20491				// during a drag (#14461)
20492				if ( event.originalEvent.altKey || event.originalEvent.ctrlKey ||
20493						event.originalEvent.metaKey || event.originalEvent.shiftKey ) {
20494					this.ignoreMissingWhich = true;
20495				} else if ( !this.ignoreMissingWhich ) {
20496					return this._mouseUp( event );
20497				}
20498			}
20499		}
20500
20501		if ( event.which || event.button ) {
20502			this._mouseMoved = true;
20503		}
20504
20505		if ( this._mouseStarted ) {
20506			this._mouseDrag( event );
20507			return event.preventDefault();
20508		}
20509
20510		if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) {
20511			this._mouseStarted =
20512				( this._mouseStart( this._mouseDownEvent, event ) !== false );
20513			if ( this._mouseStarted ) {
20514				this._mouseDrag( event );
20515			} else {
20516				this._mouseUp( event );
20517			}
20518		}
20519
20520		return !this._mouseStarted;
20521	},
20522
20523	_mouseUp: function( event ) {
20524		this.document
20525			.off( "mousemove." + this.widgetName, this._mouseMoveDelegate )
20526			.off( "mouseup." + this.widgetName, this._mouseUpDelegate );
20527
20528		if ( this._mouseStarted ) {
20529			this._mouseStarted = false;
20530
20531			if ( event.target === this._mouseDownEvent.target ) {
20532				$.data( event.target, this.widgetName + ".preventClickEvent", true );
20533			}
20534
20535			this._mouseStop( event );
20536		}
20537
20538		if ( this._mouseDelayTimer ) {
20539			clearTimeout( this._mouseDelayTimer );
20540			delete this._mouseDelayTimer;
20541		}
20542
20543		this.ignoreMissingWhich = false;
20544		mouseHandled = false;
20545		event.preventDefault();
20546	},
20547
20548	_mouseDistanceMet: function( event ) {
20549		return ( Math.max(
20550				Math.abs( this._mouseDownEvent.pageX - event.pageX ),
20551				Math.abs( this._mouseDownEvent.pageY - event.pageY )
20552			) >= this.options.distance
20553		);
20554	},
20555
20556	_mouseDelayMet: function( /* event */ ) {
20557		return this.mouseDelayMet;
20558	},
20559
20560	// These are placeholder methods, to be overriden by extending plugin
20561	_mouseStart: function( /* event */ ) {},
20562	_mouseDrag: function( /* event */ ) {},
20563	_mouseStop: function( /* event */ ) {},
20564	_mouseCapture: function( /* event */ ) {
20565		return true;
20566	}
20567} );
20568
20569
20570
20571// $.ui.plugin is deprecated. Use $.widget() extensions instead.
20572var plugin = $.ui.plugin = {
20573	add: function( module, option, set ) {
20574		var i,
20575			proto = $.ui[ module ].prototype;
20576		for ( i in set ) {
20577			proto.plugins[ i ] = proto.plugins[ i ] || [];
20578			proto.plugins[ i ].push( [ option, set[ i ] ] );
20579		}
20580	},
20581	call: function( instance, name, args, allowDisconnected ) {
20582		var i,
20583			set = instance.plugins[ name ];
20584
20585		if ( !set ) {
20586			return;
20587		}
20588
20589		if ( !allowDisconnected && ( !instance.element[ 0 ].parentNode ||
20590				instance.element[ 0 ].parentNode.nodeType === 11 ) ) {
20591			return;
20592		}
20593
20594		for ( i = 0; i < set.length; i++ ) {
20595			if ( instance.options[ set[ i ][ 0 ] ] ) {
20596				set[ i ][ 1 ].apply( instance.element, args );
20597			}
20598		}
20599	}
20600};
20601
20602
20603
20604var safeBlur = $.ui.safeBlur = function( element ) {
20605
20606	// Support: IE9 - 10 only
20607	// If the <body> is blurred, IE will switch windows, see #9420
20608	if ( element && element.nodeName.toLowerCase() !== "body" ) {
20609		$( element ).trigger( "blur" );
20610	}
20611};
20612
20613
20614/*!
20615 * jQuery UI Draggable 1.13.2
20616 * http://jqueryui.com
20617 *
20618 * Copyright jQuery Foundation and other contributors
20619 * Released under the MIT license.
20620 * http://jquery.org/license
20621 */
20622
20623//>>label: Draggable
20624//>>group: Interactions
20625//>>description: Enables dragging functionality for any element.
20626//>>docs: http://api.jqueryui.com/draggable/
20627//>>demos: http://jqueryui.com/draggable/
20628//>>css.structure: ../../themes/base/draggable.css
20629
20630
20631$.widget( "ui.draggable", $.ui.mouse, {
20632	version: "1.13.2",
20633	widgetEventPrefix: "drag",
20634	options: {
20635		addClasses: true,
20636		appendTo: "parent",
20637		axis: false,
20638		connectToSortable: false,
20639		containment: false,
20640		cursor: "auto",
20641		cursorAt: false,
20642		grid: false,
20643		handle: false,
20644		helper: "original",
20645		iframeFix: false,
20646		opacity: false,
20647		refreshPositions: false,
20648		revert: false,
20649		revertDuration: 500,
20650		scope: "default",
20651		scroll: true,
20652		scrollSensitivity: 20,
20653		scrollSpeed: 20,
20654		snap: false,
20655		snapMode: "both",
20656		snapTolerance: 20,
20657		stack: false,
20658		zIndex: false,
20659
20660		// Callbacks
20661		drag: null,
20662		start: null,
20663		stop: null
20664	},
20665	_create: function() {
20666
20667		if ( this.options.helper === "original" ) {
20668			this._setPositionRelative();
20669		}
20670		if ( this.options.addClasses ) {
20671			this._addClass( "ui-draggable" );
20672		}
20673		this._setHandleClassName();
20674
20675		this._mouseInit();
20676	},
20677
20678	_setOption: function( key, value ) {
20679		this._super( key, value );
20680		if ( key === "handle" ) {
20681			this._removeHandleClassName();
20682			this._setHandleClassName();
20683		}
20684	},
20685
20686	_destroy: function() {
20687		if ( ( this.helper || this.element ).is( ".ui-draggable-dragging" ) ) {
20688			this.destroyOnClear = true;
20689			return;
20690		}
20691		this._removeHandleClassName();
20692		this._mouseDestroy();
20693	},
20694
20695	_mouseCapture: function( event ) {
20696		var o = this.options;
20697
20698		// Among others, prevent a drag on a resizable-handle
20699		if ( this.helper || o.disabled ||
20700				$( event.target ).closest( ".ui-resizable-handle" ).length > 0 ) {
20701			return false;
20702		}
20703
20704		//Quit if we're not on a valid handle
20705		this.handle = this._getHandle( event );
20706		if ( !this.handle ) {
20707			return false;
20708		}
20709
20710		this._blurActiveElement( event );
20711
20712		this._blockFrames( o.iframeFix === true ? "iframe" : o.iframeFix );
20713
20714		return true;
20715
20716	},
20717
20718	_blockFrames: function( selector ) {
20719		this.iframeBlocks = this.document.find( selector ).map( function() {
20720			var iframe = $( this );
20721
20722			return $( "<div>" )
20723				.css( "position", "absolute" )
20724				.appendTo( iframe.parent() )
20725				.outerWidth( iframe.outerWidth() )
20726				.outerHeight( iframe.outerHeight() )
20727				.offset( iframe.offset() )[ 0 ];
20728		} );
20729	},
20730
20731	_unblockFrames: function() {
20732		if ( this.iframeBlocks ) {
20733			this.iframeBlocks.remove();
20734			delete this.iframeBlocks;
20735		}
20736	},
20737
20738	_blurActiveElement: function( event ) {
20739		var activeElement = $.ui.safeActiveElement( this.document[ 0 ] ),
20740			target = $( event.target );
20741
20742		// Don't blur if the event occurred on an element that is within
20743		// the currently focused element
20744		// See #10527, #12472
20745		if ( target.closest( activeElement ).length ) {
20746			return;
20747		}
20748
20749		// Blur any element that currently has focus, see #4261
20750		$.ui.safeBlur( activeElement );
20751	},
20752
20753	_mouseStart: function( event ) {
20754
20755		var o = this.options;
20756
20757		//Create and append the visible helper
20758		this.helper = this._createHelper( event );
20759
20760		this._addClass( this.helper, "ui-draggable-dragging" );
20761
20762		//Cache the helper size
20763		this._cacheHelperProportions();
20764
20765		//If ddmanager is used for droppables, set the global draggable
20766		if ( $.ui.ddmanager ) {
20767			$.ui.ddmanager.current = this;
20768		}
20769
20770		/*
20771		 * - Position generation -
20772		 * This block generates everything position related - it's the core of draggables.
20773		 */
20774
20775		//Cache the margins of the original element
20776		this._cacheMargins();
20777
20778		//Store the helper's css position
20779		this.cssPosition = this.helper.css( "position" );
20780		this.scrollParent = this.helper.scrollParent( true );
20781		this.offsetParent = this.helper.offsetParent();
20782		this.hasFixedAncestor = this.helper.parents().filter( function() {
20783				return $( this ).css( "position" ) === "fixed";
20784			} ).length > 0;
20785
20786		//The element's absolute position on the page minus margins
20787		this.positionAbs = this.element.offset();
20788		this._refreshOffsets( event );
20789
20790		//Generate the original position
20791		this.originalPosition = this.position = this._generatePosition( event, false );
20792		this.originalPageX = event.pageX;
20793		this.originalPageY = event.pageY;
20794
20795		//Adjust the mouse offset relative to the helper if "cursorAt" is supplied
20796		if ( o.cursorAt ) {
20797			this._adjustOffsetFromHelper( o.cursorAt );
20798		}
20799
20800		//Set a containment if given in the options
20801		this._setContainment();
20802
20803		//Trigger event + callbacks
20804		if ( this._trigger( "start", event ) === false ) {
20805			this._clear();
20806			return false;
20807		}
20808
20809		//Recache the helper size
20810		this._cacheHelperProportions();
20811
20812		//Prepare the droppable offsets
20813		if ( $.ui.ddmanager && !o.dropBehaviour ) {
20814			$.ui.ddmanager.prepareOffsets( this, event );
20815		}
20816
20817		// Execute the drag once - this causes the helper not to be visible before getting its
20818		// correct position
20819		this._mouseDrag( event, true );
20820
20821		// If the ddmanager is used for droppables, inform the manager that dragging has started
20822		// (see #5003)
20823		if ( $.ui.ddmanager ) {
20824			$.ui.ddmanager.dragStart( this, event );
20825		}
20826
20827		return true;
20828	},
20829
20830	_refreshOffsets: function( event ) {
20831		this.offset = {
20832			top: this.positionAbs.top - this.margins.top,
20833			left: this.positionAbs.left - this.margins.left,
20834			scroll: false,
20835			parent: this._getParentOffset(),
20836			relative: this._getRelativeOffset()
20837		};
20838
20839		this.offset.click = {
20840			left: event.pageX - this.offset.left,
20841			top: event.pageY - this.offset.top
20842		};
20843	},
20844
20845	_mouseDrag: function( event, noPropagation ) {
20846
20847		// reset any necessary cached properties (see #5009)
20848		if ( this.hasFixedAncestor ) {
20849			this.offset.parent = this._getParentOffset();
20850		}
20851
20852		//Compute the helpers position
20853		this.position = this._generatePosition( event, true );
20854		this.positionAbs = this._convertPositionTo( "absolute" );
20855
20856		//Call plugins and callbacks and use the resulting position if something is returned
20857		if ( !noPropagation ) {
20858			var ui = this._uiHash();
20859			if ( this._trigger( "drag", event, ui ) === false ) {
20860				this._mouseUp( new $.Event( "mouseup", event ) );
20861				return false;
20862			}
20863			this.position = ui.position;
20864		}
20865
20866		this.helper[ 0 ].style.left = this.position.left + "px";
20867		this.helper[ 0 ].style.top = this.position.top + "px";
20868
20869		if ( $.ui.ddmanager ) {
20870			$.ui.ddmanager.drag( this, event );
20871		}
20872
20873		return false;
20874	},
20875
20876	_mouseStop: function( event ) {
20877
20878		//If we are using droppables, inform the manager about the drop
20879		var that = this,
20880			dropped = false;
20881		if ( $.ui.ddmanager && !this.options.dropBehaviour ) {
20882			dropped = $.ui.ddmanager.drop( this, event );
20883		}
20884
20885		//if a drop comes from outside (a sortable)
20886		if ( this.dropped ) {
20887			dropped = this.dropped;
20888			this.dropped = false;
20889		}
20890
vendor: 29,295 bytes, lines 20891-21851
20891		if ( ( this.options.revert === "invalid" && !dropped ) ||
20892				( this.options.revert === "valid" && dropped ) ||
20893				this.options.revert === true || ( typeof this.options.revert === "function" &&
20894				this.options.revert.call( this.element, dropped ) )
20895		) {
20896			$( this.helper ).animate(
20897				this.originalPosition,
20898				parseInt( this.options.revertDuration, 10 ),
20899				function() {
20900					if ( that._trigger( "stop", event ) !== false ) {
20901						that._clear();
20902					}
20903				}
20904			);
20905		} else {
20906			if ( this._trigger( "stop", event ) !== false ) {
20907				this._clear();
20908			}
20909		}
20910
20911		return false;
20912	},
20913
20914	_mouseUp: function( event ) {
20915		this._unblockFrames();
20916
20917		// If the ddmanager is used for droppables, inform the manager that dragging has stopped
20918		// (see #5003)
20919		if ( $.ui.ddmanager ) {
20920			$.ui.ddmanager.dragStop( this, event );
20921		}
20922
20923		// Only need to focus if the event occurred on the draggable itself, see #10527
20924		if ( this.handleElement.is( event.target ) ) {
20925
20926			// The interaction is over; whether or not the click resulted in a drag,
20927			// focus the element
20928			this.element.trigger( "focus" );
20929		}
20930
20931		return $.ui.mouse.prototype._mouseUp.call( this, event );
20932	},
20933
20934	cancel: function() {
20935
20936		if ( this.helper.is( ".ui-draggable-dragging" ) ) {
20937			this._mouseUp( new $.Event( "mouseup", { target: this.element[ 0 ] } ) );
20938		} else {
20939			this._clear();
20940		}
20941
20942		return this;
20943
20944	},
20945
20946	_getHandle: function( event ) {
20947		return this.options.handle ?
20948			!!$( event.target ).closest( this.element.find( this.options.handle ) ).length :
20949			true;
20950	},
20951
20952	_setHandleClassName: function() {
20953		this.handleElement = this.options.handle ?
20954			this.element.find( this.options.handle ) : this.element;
20955		this._addClass( this.handleElement, "ui-draggable-handle" );
20956	},
20957
20958	_removeHandleClassName: function() {
20959		this._removeClass( this.handleElement, "ui-draggable-handle" );
20960	},
20961
20962	_createHelper: function( event ) {
20963
20964		var o = this.options,
20965			helperIsFunction = typeof o.helper === "function",
20966			helper = helperIsFunction ?
20967				$( o.helper.apply( this.element[ 0 ], [ event ] ) ) :
20968				( o.helper === "clone" ?
20969					this.element.clone().removeAttr( "id" ) :
20970					this.element );
20971
20972		if ( !helper.parents( "body" ).length ) {
20973			helper.appendTo( ( o.appendTo === "parent" ?
20974				this.element[ 0 ].parentNode :
20975				o.appendTo ) );
20976		}
20977
20978		// Http://bugs.jqueryui.com/ticket/9446
20979		// a helper function can return the original element
20980		// which wouldn't have been set to relative in _create
20981		if ( helperIsFunction && helper[ 0 ] === this.element[ 0 ] ) {
20982			this._setPositionRelative();
20983		}
20984
20985		if ( helper[ 0 ] !== this.element[ 0 ] &&
20986				!( /(fixed|absolute)/ ).test( helper.css( "position" ) ) ) {
20987			helper.css( "position", "absolute" );
20988		}
20989
20990		return helper;
20991
20992	},
20993
20994	_setPositionRelative: function() {
20995		if ( !( /^(?:r|a|f)/ ).test( this.element.css( "position" ) ) ) {
20996			this.element[ 0 ].style.position = "relative";
20997		}
20998	},
20999
21000	_adjustOffsetFromHelper: function( obj ) {
21001		if ( typeof obj === "string" ) {
21002			obj = obj.split( " " );
21003		}
21004		if ( Array.isArray( obj ) ) {
21005			obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 };
21006		}
21007		if ( "left" in obj ) {
21008			this.offset.click.left = obj.left + this.margins.left;
21009		}
21010		if ( "right" in obj ) {
21011			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
21012		}
21013		if ( "top" in obj ) {
21014			this.offset.click.top = obj.top + this.margins.top;
21015		}
21016		if ( "bottom" in obj ) {
21017			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
21018		}
21019	},
21020
21021	_isRootNode: function( element ) {
21022		return ( /(html|body)/i ).test( element.tagName ) || element === this.document[ 0 ];
21023	},
21024
21025	_getParentOffset: function() {
21026
21027		//Get the offsetParent and cache its position
21028		var po = this.offsetParent.offset(),
21029			document = this.document[ 0 ];
21030
21031		// This is a special case where we need to modify a offset calculated on start, since the
21032		// following happened:
21033		// 1. The position of the helper is absolute, so it's position is calculated based on the
21034		// next positioned parent
21035		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't
21036		// the document, which means that the scroll is included in the initial calculation of the
21037		// offset of the parent, and never recalculated upon drag
21038		if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== document &&
21039				$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) {
21040			po.left += this.scrollParent.scrollLeft();
21041			po.top += this.scrollParent.scrollTop();
21042		}
21043
21044		if ( this._isRootNode( this.offsetParent[ 0 ] ) ) {
21045			po = { top: 0, left: 0 };
21046		}
21047
21048		return {
21049			top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ),
21050			left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 )
21051		};
21052
21053	},
21054
21055	_getRelativeOffset: function() {
21056		if ( this.cssPosition !== "relative" ) {
21057			return { top: 0, left: 0 };
21058		}
21059
21060		var p = this.element.position(),
21061			scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
21062
21063		return {
21064			top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) +
21065				( !scrollIsRootNode ? this.scrollParent.scrollTop() : 0 ),
21066			left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) +
21067				( !scrollIsRootNode ? this.scrollParent.scrollLeft() : 0 )
21068		};
21069
21070	},
21071
21072	_cacheMargins: function() {
21073		this.margins = {
21074			left: ( parseInt( this.element.css( "marginLeft" ), 10 ) || 0 ),
21075			top: ( parseInt( this.element.css( "marginTop" ), 10 ) || 0 ),
21076			right: ( parseInt( this.element.css( "marginRight" ), 10 ) || 0 ),
21077			bottom: ( parseInt( this.element.css( "marginBottom" ), 10 ) || 0 )
21078		};
21079	},
21080
21081	_cacheHelperProportions: function() {
21082		this.helperProportions = {
21083			width: this.helper.outerWidth(),
21084			height: this.helper.outerHeight()
21085		};
21086	},
21087
21088	_setContainment: function() {
21089
21090		var isUserScrollable, c, ce,
21091			o = this.options,
21092			document = this.document[ 0 ];
21093
21094		this.relativeContainer = null;
21095
21096		if ( !o.containment ) {
21097			this.containment = null;
21098			return;
21099		}
21100
21101		if ( o.containment === "window" ) {
21102			this.containment = [
21103				$( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
21104				$( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top,
21105				$( window ).scrollLeft() + $( window ).width() -
21106					this.helperProportions.width - this.margins.left,
21107				$( window ).scrollTop() +
21108					( $( window ).height() || document.body.parentNode.scrollHeight ) -
21109					this.helperProportions.height - this.margins.top
21110			];
21111			return;
21112		}
21113
21114		if ( o.containment === "document" ) {
21115			this.containment = [
21116				0,
21117				0,
21118				$( document ).width() - this.helperProportions.width - this.margins.left,
21119				( $( document ).height() || document.body.parentNode.scrollHeight ) -
21120					this.helperProportions.height - this.margins.top
21121			];
21122			return;
21123		}
21124
21125		if ( o.containment.constructor === Array ) {
21126			this.containment = o.containment;
21127			return;
21128		}
21129
21130		if ( o.containment === "parent" ) {
21131			o.containment = this.helper[ 0 ].parentNode;
21132		}
21133
21134		c = $( o.containment );
21135		ce = c[ 0 ];
21136
21137		if ( !ce ) {
21138			return;
21139		}
21140
21141		isUserScrollable = /(scroll|auto)/.test( c.css( "overflow" ) );
21142
21143		this.containment = [
21144			( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) +
21145				( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ),
21146			( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) +
21147				( parseInt( c.css( "paddingTop" ), 10 ) || 0 ),
21148			( isUserScrollable ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -
21149				( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) -
21150				( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) -
21151				this.helperProportions.width -
21152				this.margins.left -
21153				this.margins.right,
21154			( isUserScrollable ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -
21155				( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) -
21156				( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) -
21157				this.helperProportions.height -
21158				this.margins.top -
21159				this.margins.bottom
21160		];
21161		this.relativeContainer = c;
21162	},
21163
21164	_convertPositionTo: function( d, pos ) {
21165
21166		if ( !pos ) {
21167			pos = this.position;
21168		}
21169
21170		var mod = d === "absolute" ? 1 : -1,
21171			scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
21172
21173		return {
21174			top: (
21175
21176				// The absolute mouse position
21177				pos.top	+
21178
21179				// Only for relative positioned nodes: Relative offset from element to offset parent
21180				this.offset.relative.top * mod +
21181
21182				// The offsetParent's offset without borders (offset + border)
21183				this.offset.parent.top * mod -
21184				( ( this.cssPosition === "fixed" ?
21185					-this.offset.scroll.top :
21186					( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) * mod )
21187			),
21188			left: (
21189
21190				// The absolute mouse position
21191				pos.left +
21192
21193				// Only for relative positioned nodes: Relative offset from element to offset parent
21194				this.offset.relative.left * mod +
21195
21196				// The offsetParent's offset without borders (offset + border)
21197				this.offset.parent.left * mod	-
21198				( ( this.cssPosition === "fixed" ?
21199					-this.offset.scroll.left :
21200					( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) * mod )
21201			)
21202		};
21203
21204	},
21205
21206	_generatePosition: function( event, constrainPosition ) {
21207
21208		var containment, co, top, left,
21209			o = this.options,
21210			scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ),
21211			pageX = event.pageX,
21212			pageY = event.pageY;
21213
21214		// Cache the scroll
21215		if ( !scrollIsRootNode || !this.offset.scroll ) {
21216			this.offset.scroll = {
21217				top: this.scrollParent.scrollTop(),
21218				left: this.scrollParent.scrollLeft()
21219			};
21220		}
21221
21222		/*
21223		 * - Position constraining -
21224		 * Constrain the position to a mix of grid, containment.
21225		 */
21226
21227		// If we are not dragging yet, we won't check for options
21228		if ( constrainPosition ) {
21229			if ( this.containment ) {
21230				if ( this.relativeContainer ) {
21231					co = this.relativeContainer.offset();
21232					containment = [
21233						this.containment[ 0 ] + co.left,
21234						this.containment[ 1 ] + co.top,
21235						this.containment[ 2 ] + co.left,
21236						this.containment[ 3 ] + co.top
21237					];
21238				} else {
21239					containment = this.containment;
21240				}
21241
21242				if ( event.pageX - this.offset.click.left < containment[ 0 ] ) {
21243					pageX = containment[ 0 ] + this.offset.click.left;
21244				}
21245				if ( event.pageY - this.offset.click.top < containment[ 1 ] ) {
21246					pageY = containment[ 1 ] + this.offset.click.top;
21247				}
21248				if ( event.pageX - this.offset.click.left > containment[ 2 ] ) {
21249					pageX = containment[ 2 ] + this.offset.click.left;
21250				}
21251				if ( event.pageY - this.offset.click.top > containment[ 3 ] ) {
21252					pageY = containment[ 3 ] + this.offset.click.top;
21253				}
21254			}
21255
21256			if ( o.grid ) {
21257
21258				//Check for grid elements set to 0 to prevent divide by 0 error causing invalid
21259				// argument errors in IE (see ticket #6950)
21260				top = o.grid[ 1 ] ? this.originalPageY + Math.round( ( pageY -
21261					this.originalPageY ) / o.grid[ 1 ] ) * o.grid[ 1 ] : this.originalPageY;
21262				pageY = containment ? ( ( top - this.offset.click.top >= containment[ 1 ] ||
21263					top - this.offset.click.top > containment[ 3 ] ) ?
21264						top :
21265						( ( top - this.offset.click.top >= containment[ 1 ] ) ?
21266							top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) : top;
21267
21268				left = o.grid[ 0 ] ? this.originalPageX +
21269					Math.round( ( pageX - this.originalPageX ) / o.grid[ 0 ] ) * o.grid[ 0 ] :
21270					this.originalPageX;
21271				pageX = containment ? ( ( left - this.offset.click.left >= containment[ 0 ] ||
21272					left - this.offset.click.left > containment[ 2 ] ) ?
21273						left :
21274						( ( left - this.offset.click.left >= containment[ 0 ] ) ?
21275							left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) : left;
21276			}
21277
21278			if ( o.axis === "y" ) {
21279				pageX = this.originalPageX;
21280			}
21281
21282			if ( o.axis === "x" ) {
21283				pageY = this.originalPageY;
21284			}
21285		}
21286
21287		return {
21288			top: (
21289
21290				// The absolute mouse position
21291				pageY -
21292
21293				// Click offset (relative to the element)
21294				this.offset.click.top -
21295
21296				// Only for relative positioned nodes: Relative offset from element to offset parent
21297				this.offset.relative.top -
21298
21299				// The offsetParent's offset without borders (offset + border)
21300				this.offset.parent.top +
21301				( this.cssPosition === "fixed" ?
21302					-this.offset.scroll.top :
21303					( scrollIsRootNode ? 0 : this.offset.scroll.top ) )
21304			),
21305			left: (
21306
21307				// The absolute mouse position
21308				pageX -
21309
21310				// Click offset (relative to the element)
21311				this.offset.click.left -
21312
21313				// Only for relative positioned nodes: Relative offset from element to offset parent
21314				this.offset.relative.left -
21315
21316				// The offsetParent's offset without borders (offset + border)
21317				this.offset.parent.left +
21318				( this.cssPosition === "fixed" ?
21319					-this.offset.scroll.left :
21320					( scrollIsRootNode ? 0 : this.offset.scroll.left ) )
21321			)
21322		};
21323
21324	},
21325
21326	_clear: function() {
21327		this._removeClass( this.helper, "ui-draggable-dragging" );
21328		if ( this.helper[ 0 ] !== this.element[ 0 ] && !this.cancelHelperRemoval ) {
21329			this.helper.remove();
21330		}
21331		this.helper = null;
21332		this.cancelHelperRemoval = false;
21333		if ( this.destroyOnClear ) {
21334			this.destroy();
21335		}
21336	},
21337
21338	// From now on bulk stuff - mainly helpers
21339
21340	_trigger: function( type, event, ui ) {
21341		ui = ui || this._uiHash();
21342		$.ui.plugin.call( this, type, [ event, ui, this ], true );
21343
21344		// Absolute position and offset (see #6884 ) have to be recalculated after plugins
21345		if ( /^(drag|start|stop)/.test( type ) ) {
21346			this.positionAbs = this._convertPositionTo( "absolute" );
21347			ui.offset = this.positionAbs;
21348		}
21349		return $.Widget.prototype._trigger.call( this, type, event, ui );
21350	},
21351
21352	plugins: {},
21353
21354	_uiHash: function() {
21355		return {
21356			helper: this.helper,
21357			position: this.position,
21358			originalPosition: this.originalPosition,
21359			offset: this.positionAbs
21360		};
21361	}
21362
21363} );
21364
21365$.ui.plugin.add( "draggable", "connectToSortable", {
21366	start: function( event, ui, draggable ) {
21367		var uiSortable = $.extend( {}, ui, {
21368			item: draggable.element
21369		} );
21370
21371		draggable.sortables = [];
21372		$( draggable.options.connectToSortable ).each( function() {
21373			var sortable = $( this ).sortable( "instance" );
21374
21375			if ( sortable && !sortable.options.disabled ) {
21376				draggable.sortables.push( sortable );
21377
21378				// RefreshPositions is called at drag start to refresh the containerCache
21379				// which is used in drag. This ensures it's initialized and synchronized
21380				// with any changes that might have happened on the page since initialization.
21381				sortable.refreshPositions();
21382				sortable._trigger( "activate", event, uiSortable );
21383			}
21384		} );
21385	},
21386	stop: function( event, ui, draggable ) {
21387		var uiSortable = $.extend( {}, ui, {
21388			item: draggable.element
21389		} );
21390
21391		draggable.cancelHelperRemoval = false;
21392
21393		$.each( draggable.sortables, function() {
21394			var sortable = this;
21395
21396			if ( sortable.isOver ) {
21397				sortable.isOver = 0;
21398
21399				// Allow this sortable to handle removing the helper
21400				draggable.cancelHelperRemoval = true;
21401				sortable.cancelHelperRemoval = false;
21402
21403				// Use _storedCSS To restore properties in the sortable,
21404				// as this also handles revert (#9675) since the draggable
21405				// may have modified them in unexpected ways (#8809)
21406				sortable._storedCSS = {
21407					position: sortable.placeholder.css( "position" ),
21408					top: sortable.placeholder.css( "top" ),
21409					left: sortable.placeholder.css( "left" )
21410				};
21411
21412				sortable._mouseStop( event );
21413
21414				// Once drag has ended, the sortable should return to using
21415				// its original helper, not the shared helper from draggable
21416				sortable.options.helper = sortable.options._helper;
21417			} else {
21418
21419				// Prevent this Sortable from removing the helper.
21420				// However, don't set the draggable to remove the helper
21421				// either as another connected Sortable may yet handle the removal.
21422				sortable.cancelHelperRemoval = true;
21423
21424				sortable._trigger( "deactivate", event, uiSortable );
21425			}
21426		} );
21427	},
21428	drag: function( event, ui, draggable ) {
21429		$.each( draggable.sortables, function() {
21430			var innermostIntersecting = false,
21431				sortable = this;
21432
21433			// Copy over variables that sortable's _intersectsWith uses
21434			sortable.positionAbs = draggable.positionAbs;
21435			sortable.helperProportions = draggable.helperProportions;
21436			sortable.offset.click = draggable.offset.click;
21437
21438			if ( sortable._intersectsWith( sortable.containerCache ) ) {
21439				innermostIntersecting = true;
21440
21441				$.each( draggable.sortables, function() {
21442
21443					// Copy over variables that sortable's _intersectsWith uses
21444					this.positionAbs = draggable.positionAbs;
21445					this.helperProportions = draggable.helperProportions;
21446					this.offset.click = draggable.offset.click;
21447
21448					if ( this !== sortable &&
21449							this._intersectsWith( this.containerCache ) &&
21450							$.contains( sortable.element[ 0 ], this.element[ 0 ] ) ) {
21451						innermostIntersecting = false;
21452					}
21453
21454					return innermostIntersecting;
21455				} );
21456			}
21457
21458			if ( innermostIntersecting ) {
21459
21460				// If it intersects, we use a little isOver variable and set it once,
21461				// so that the move-in stuff gets fired only once.
21462				if ( !sortable.isOver ) {
21463					sortable.isOver = 1;
21464
21465					// Store draggable's parent in case we need to reappend to it later.
21466					draggable._parent = ui.helper.parent();
21467
21468					sortable.currentItem = ui.helper
21469						.appendTo( sortable.element )
21470						.data( "ui-sortable-item", true );
21471
21472					// Store helper option to later restore it
21473					sortable.options._helper = sortable.options.helper;
21474
21475					sortable.options.helper = function() {
21476						return ui.helper[ 0 ];
21477					};
21478
21479					// Fire the start events of the sortable with our passed browser event,
21480					// and our own helper (so it doesn't create a new one)
21481					event.target = sortable.currentItem[ 0 ];
21482					sortable._mouseCapture( event, true );
21483					sortable._mouseStart( event, true, true );
21484
21485					// Because the browser event is way off the new appended portlet,
21486					// modify necessary variables to reflect the changes
21487					sortable.offset.click.top = draggable.offset.click.top;
21488					sortable.offset.click.left = draggable.offset.click.left;
21489					sortable.offset.parent.left -= draggable.offset.parent.left -
21490						sortable.offset.parent.left;
21491					sortable.offset.parent.top -= draggable.offset.parent.top -
21492						sortable.offset.parent.top;
21493
21494					draggable._trigger( "toSortable", event );
21495
21496					// Inform draggable that the helper is in a valid drop zone,
21497					// used solely in the revert option to handle "valid/invalid".
21498					draggable.dropped = sortable.element;
21499
21500					// Need to refreshPositions of all sortables in the case that
21501					// adding to one sortable changes the location of the other sortables (#9675)
21502					$.each( draggable.sortables, function() {
21503						this.refreshPositions();
21504					} );
21505
21506					// Hack so receive/update callbacks work (mostly)
21507					draggable.currentItem = draggable.element;
21508					sortable.fromOutside = draggable;
21509				}
21510
21511				if ( sortable.currentItem ) {
21512					sortable._mouseDrag( event );
21513
21514					// Copy the sortable's position because the draggable's can potentially reflect
21515					// a relative position, while sortable is always absolute, which the dragged
21516					// element has now become. (#8809)
21517					ui.position = sortable.position;
21518				}
21519			} else {
21520
21521				// If it doesn't intersect with the sortable, and it intersected before,
21522				// we fake the drag stop of the sortable, but make sure it doesn't remove
21523				// the helper by using cancelHelperRemoval.
21524				if ( sortable.isOver ) {
21525
21526					sortable.isOver = 0;
21527					sortable.cancelHelperRemoval = true;
21528
21529					// Calling sortable's mouseStop would trigger a revert,
21530					// so revert must be temporarily false until after mouseStop is called.
21531					sortable.options._revert = sortable.options.revert;
21532					sortable.options.revert = false;
21533
21534					sortable._trigger( "out", event, sortable._uiHash( sortable ) );
21535					sortable._mouseStop( event, true );
21536
21537					// Restore sortable behaviors that were modfied
21538					// when the draggable entered the sortable area (#9481)
21539					sortable.options.revert = sortable.options._revert;
21540					sortable.options.helper = sortable.options._helper;
21541
21542					if ( sortable.placeholder ) {
21543						sortable.placeholder.remove();
21544					}
21545
21546					// Restore and recalculate the draggable's offset considering the sortable
21547					// may have modified them in unexpected ways. (#8809, #10669)
21548					ui.helper.appendTo( draggable._parent );
21549					draggable._refreshOffsets( event );
21550					ui.position = draggable._generatePosition( event, true );
21551
21552					draggable._trigger( "fromSortable", event );
21553
21554					// Inform draggable that the helper is no longer in a valid drop zone
21555					draggable.dropped = false;
21556
21557					// Need to refreshPositions of all sortables just in case removing
21558					// from one sortable changes the location of other sortables (#9675)
21559					$.each( draggable.sortables, function() {
21560						this.refreshPositions();
21561					} );
21562				}
21563			}
21564		} );
21565	}
21566} );
21567
21568$.ui.plugin.add( "draggable", "cursor", {
21569	start: function( event, ui, instance ) {
21570		var t = $( "body" ),
21571			o = instance.options;
21572
21573		if ( t.css( "cursor" ) ) {
21574			o._cursor = t.css( "cursor" );
21575		}
21576		t.css( "cursor", o.cursor );
21577	},
21578	stop: function( event, ui, instance ) {
21579		var o = instance.options;
21580		if ( o._cursor ) {
21581			$( "body" ).css( "cursor", o._cursor );
21582		}
21583	}
21584} );
21585
21586$.ui.plugin.add( "draggable", "opacity", {
21587	start: function( event, ui, instance ) {
21588		var t = $( ui.helper ),
21589			o = instance.options;
21590		if ( t.css( "opacity" ) ) {
21591			o._opacity = t.css( "opacity" );
21592		}
21593		t.css( "opacity", o.opacity );
21594	},
21595	stop: function( event, ui, instance ) {
21596		var o = instance.options;
21597		if ( o._opacity ) {
21598			$( ui.helper ).css( "opacity", o._opacity );
21599		}
21600	}
21601} );
21602
21603$.ui.plugin.add( "draggable", "scroll", {
21604	start: function( event, ui, i ) {
21605		if ( !i.scrollParentNotHidden ) {
21606			i.scrollParentNotHidden = i.helper.scrollParent( false );
21607		}
21608
21609		if ( i.scrollParentNotHidden[ 0 ] !== i.document[ 0 ] &&
21610				i.scrollParentNotHidden[ 0 ].tagName !== "HTML" ) {
21611			i.overflowOffset = i.scrollParentNotHidden.offset();
21612		}
21613	},
21614	drag: function( event, ui, i  ) {
21615
21616		var o = i.options,
21617			scrolled = false,
21618			scrollParent = i.scrollParentNotHidden[ 0 ],
21619			document = i.document[ 0 ];
21620
21621		if ( scrollParent !== document && scrollParent.tagName !== "HTML" ) {
21622			if ( !o.axis || o.axis !== "x" ) {
21623				if ( ( i.overflowOffset.top + scrollParent.offsetHeight ) - event.pageY <
21624						o.scrollSensitivity ) {
21625					scrollParent.scrollTop = scrolled = scrollParent.scrollTop + o.scrollSpeed;
21626				} else if ( event.pageY - i.overflowOffset.top < o.scrollSensitivity ) {
21627					scrollParent.scrollTop = scrolled = scrollParent.scrollTop - o.scrollSpeed;
21628				}
21629			}
21630
21631			if ( !o.axis || o.axis !== "y" ) {
21632				if ( ( i.overflowOffset.left + scrollParent.offsetWidth ) - event.pageX <
21633						o.scrollSensitivity ) {
21634					scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft + o.scrollSpeed;
21635				} else if ( event.pageX - i.overflowOffset.left < o.scrollSensitivity ) {
21636					scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft - o.scrollSpeed;
21637				}
21638			}
21639
21640		} else {
21641
21642			if ( !o.axis || o.axis !== "x" ) {
21643				if ( event.pageY - $( document ).scrollTop() < o.scrollSensitivity ) {
21644					scrolled = $( document ).scrollTop( $( document ).scrollTop() - o.scrollSpeed );
21645				} else if ( $( window ).height() - ( event.pageY - $( document ).scrollTop() ) <
21646						o.scrollSensitivity ) {
21647					scrolled = $( document ).scrollTop( $( document ).scrollTop() + o.scrollSpeed );
21648				}
21649			}
21650
21651			if ( !o.axis || o.axis !== "y" ) {
21652				if ( event.pageX - $( document ).scrollLeft() < o.scrollSensitivity ) {
21653					scrolled = $( document ).scrollLeft(
21654						$( document ).scrollLeft() - o.scrollSpeed
21655					);
21656				} else if ( $( window ).width() - ( event.pageX - $( document ).scrollLeft() ) <
21657						o.scrollSensitivity ) {
21658					scrolled = $( document ).scrollLeft(
21659						$( document ).scrollLeft() + o.scrollSpeed
21660					);
21661				}
21662			}
21663
21664		}
21665
21666		if ( scrolled !== false && $.ui.ddmanager && !o.dropBehaviour ) {
21667			$.ui.ddmanager.prepareOffsets( i, event );
21668		}
21669
21670	}
21671} );
21672
21673$.ui.plugin.add( "draggable", "snap", {
21674	start: function( event, ui, i ) {
21675
21676		var o = i.options;
21677
21678		i.snapElements = [];
21679
21680		$( o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap )
21681			.each( function() {
21682				var $t = $( this ),
21683					$o = $t.offset();
21684				if ( this !== i.element[ 0 ] ) {
21685					i.snapElements.push( {
21686						item: this,
21687						width: $t.outerWidth(), height: $t.outerHeight(),
21688						top: $o.top, left: $o.left
21689					} );
21690				}
21691			} );
21692
21693	},
21694	drag: function( event, ui, inst ) {
21695
21696		var ts, bs, ls, rs, l, r, t, b, i, first,
21697			o = inst.options,
21698			d = o.snapTolerance,
21699			x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
21700			y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
21701
21702		for ( i = inst.snapElements.length - 1; i >= 0; i-- ) {
21703
21704			l = inst.snapElements[ i ].left - inst.margins.left;
21705			r = l + inst.snapElements[ i ].width;
21706			t = inst.snapElements[ i ].top - inst.margins.top;
21707			b = t + inst.snapElements[ i ].height;
21708
21709			if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d ||
21710					!$.contains( inst.snapElements[ i ].item.ownerDocument,
21711					inst.snapElements[ i ].item ) ) {
21712				if ( inst.snapElements[ i ].snapping ) {
21713					if ( inst.options.snap.release ) {
21714						inst.options.snap.release.call(
21715							inst.element,
21716							event,
21717							$.extend( inst._uiHash(), { snapItem: inst.snapElements[ i ].item } )
21718						);
21719					}
21720				}
21721				inst.snapElements[ i ].snapping = false;
21722				continue;
21723			}
21724
21725			if ( o.snapMode !== "inner" ) {
21726				ts = Math.abs( t - y2 ) <= d;
21727				bs = Math.abs( b - y1 ) <= d;
21728				ls = Math.abs( l - x2 ) <= d;
21729				rs = Math.abs( r - x1 ) <= d;
21730				if ( ts ) {
21731					ui.position.top = inst._convertPositionTo( "relative", {
21732						top: t - inst.helperProportions.height,
21733						left: 0
21734					} ).top;
21735				}
21736				if ( bs ) {
21737					ui.position.top = inst._convertPositionTo( "relative", {
21738						top: b,
21739						left: 0
21740					} ).top;
21741				}
21742				if ( ls ) {
21743					ui.position.left = inst._convertPositionTo( "relative", {
21744						top: 0,
21745						left: l - inst.helperProportions.width
21746					} ).left;
21747				}
21748				if ( rs ) {
21749					ui.position.left = inst._convertPositionTo( "relative", {
21750						top: 0,
21751						left: r
21752					} ).left;
21753				}
21754			}
21755
21756			first = ( ts || bs || ls || rs );
21757
21758			if ( o.snapMode !== "outer" ) {
21759				ts = Math.abs( t - y1 ) <= d;
21760				bs = Math.abs( b - y2 ) <= d;
21761				ls = Math.abs( l - x1 ) <= d;
21762				rs = Math.abs( r - x2 ) <= d;
21763				if ( ts ) {
21764					ui.position.top = inst._convertPositionTo( "relative", {
21765						top: t,
21766						left: 0
21767					} ).top;
21768				}
21769				if ( bs ) {
21770					ui.position.top = inst._convertPositionTo( "relative", {
21771						top: b - inst.helperProportions.height,
21772						left: 0
21773					} ).top;
21774				}
21775				if ( ls ) {
21776					ui.position.left = inst._convertPositionTo( "relative", {
21777						top: 0,
21778						left: l
21779					} ).left;
21780				}
21781				if ( rs ) {
21782					ui.position.left = inst._convertPositionTo( "relative", {
21783						top: 0,
21784						left: r - inst.helperProportions.width
21785					} ).left;
21786				}
21787			}
21788
21789			if ( !inst.snapElements[ i ].snapping && ( ts || bs || ls || rs || first ) ) {
21790				if ( inst.options.snap.snap ) {
21791					inst.options.snap.snap.call(
21792						inst.element,
21793						event,
21794						$.extend( inst._uiHash(), {
21795							snapItem: inst.snapElements[ i ].item
21796						} ) );
21797				}
21798			}
21799			inst.snapElements[ i ].snapping = ( ts || bs || ls || rs || first );
21800
21801		}
21802
21803	}
21804} );
21805
21806$.ui.plugin.add( "draggable", "stack", {
21807	start: function( event, ui, instance ) {
21808		var min,
21809			o = instance.options,
21810			group = $.makeArray( $( o.stack ) ).sort( function( a, b ) {
21811				return ( parseInt( $( a ).css( "zIndex" ), 10 ) || 0 ) -
21812					( parseInt( $( b ).css( "zIndex" ), 10 ) || 0 );
21813			} );
21814
21815		if ( !group.length ) {
21816			return;
21817		}
21818
21819		min = parseInt( $( group[ 0 ] ).css( "zIndex" ), 10 ) || 0;
21820		$( group ).each( function( i ) {
21821			$( this ).css( "zIndex", min + i );
21822		} );
21823		this.css( "zIndex", ( min + group.length ) );
21824	}
21825} );
21826
21827$.ui.plugin.add( "draggable", "zIndex", {
21828	start: function( event, ui, instance ) {
21829		var t = $( ui.helper ),
21830			o = instance.options;
21831
21832		if ( t.css( "zIndex" ) ) {
21833			o._zIndex = t.css( "zIndex" );
21834		}
21835		t.css( "zIndex", o.zIndex );
21836	},
21837	stop: function( event, ui, instance ) {
21838		var o = instance.options;
21839
21840		if ( o._zIndex ) {
21841			$( ui.helper ).css( "zIndex", o._zIndex );
21842		}
21843	}
21844} );
21845
21846var widgetsDraggable = $.ui.draggable;
21847
21848
21849/*!
21850 * jQuery UI Resizable 1.13.2
21851 * http://jqueryui.com
vendor: 18,161 bytes, lines 21852-22564
21852 *
21853 * Copyright jQuery Foundation and other contributors
21854 * Released under the MIT license.
21855 * http://jquery.org/license
21856 */
21857
21858//>>label: Resizable
21859//>>group: Interactions
21860//>>description: Enables resize functionality for any element.
21861//>>docs: http://api.jqueryui.com/resizable/
21862//>>demos: http://jqueryui.com/resizable/
21863//>>css.structure: ../../themes/base/core.css
21864//>>css.structure: ../../themes/base/resizable.css
21865//>>css.theme: ../../themes/base/theme.css
21866
21867
21868$.widget( "ui.resizable", $.ui.mouse, {
21869	version: "1.13.2",
21870	widgetEventPrefix: "resize",
21871	options: {
21872		alsoResize: false,
21873		animate: false,
21874		animateDuration: "slow",
21875		animateEasing: "swing",
21876		aspectRatio: false,
21877		autoHide: false,
21878		classes: {
21879			"ui-resizable-se": "ui-icon ui-icon-gripsmall-diagonal-se"
21880		},
21881		containment: false,
21882		ghost: false,
21883		grid: false,
21884		handles: "e,s,se",
21885		helper: false,
21886		maxHeight: null,
21887		maxWidth: null,
21888		minHeight: 10,
21889		minWidth: 10,
21890
21891		// See #7960
21892		zIndex: 90,
21893
21894		// Callbacks
21895		resize: null,
21896		start: null,
21897		stop: null
21898	},
21899
21900	_num: function( value ) {
21901		return parseFloat( value ) || 0;
21902	},
21903
21904	_isNumber: function( value ) {
21905		return !isNaN( parseFloat( value ) );
21906	},
21907
21908	_hasScroll: function( el, a ) {
21909
21910		if ( $( el ).css( "overflow" ) === "hidden" ) {
21911			return false;
21912		}
21913
21914		var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
21915			has = false;
21916
21917		if ( el[ scroll ] > 0 ) {
21918			return true;
21919		}
21920
21921		// TODO: determine which cases actually cause this to happen
21922		// if the element doesn't have the scroll set, see if it's possible to
21923		// set the scroll
21924		try {
21925			el[ scroll ] = 1;
21926			has = ( el[ scroll ] > 0 );
21927			el[ scroll ] = 0;
21928		} catch ( e ) {
21929
21930			// `el` might be a string, then setting `scroll` will throw
21931			// an error in strict mode; ignore it.
21932		}
21933		return has;
21934	},
21935
21936	_create: function() {
21937
21938		var margins,
21939			o = this.options,
21940			that = this;
21941		this._addClass( "ui-resizable" );
21942
21943		$.extend( this, {
21944			_aspectRatio: !!( o.aspectRatio ),
21945			aspectRatio: o.aspectRatio,
21946			originalElement: this.element,
21947			_proportionallyResizeElements: [],
21948			_helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null
21949		} );
21950
21951		// Wrap the element if it cannot hold child nodes
21952		if ( this.element[ 0 ].nodeName.match( /^(canvas|textarea|input|select|button|img)$/i ) ) {
21953
21954			this.element.wrap(
21955				$( "<div class='ui-wrapper'></div>" ).css( {
21956					overflow: "hidden",
21957					position: this.element.css( "position" ),
21958					width: this.element.outerWidth(),
21959					height: this.element.outerHeight(),
21960					top: this.element.css( "top" ),
21961					left: this.element.css( "left" )
21962				} )
21963			);
21964
21965			this.element = this.element.parent().data(
21966				"ui-resizable", this.element.resizable( "instance" )
21967			);
21968
21969			this.elementIsWrapper = true;
21970
21971			margins = {
21972				marginTop: this.originalElement.css( "marginTop" ),
21973				marginRight: this.originalElement.css( "marginRight" ),
21974				marginBottom: this.originalElement.css( "marginBottom" ),
21975				marginLeft: this.originalElement.css( "marginLeft" )
21976			};
21977
21978			this.element.css( margins );
21979			this.originalElement.css( "margin", 0 );
21980
21981			// support: Safari
21982			// Prevent Safari textarea resize
21983			this.originalResizeStyle = this.originalElement.css( "resize" );
21984			this.originalElement.css( "resize", "none" );
21985
21986			this._proportionallyResizeElements.push( this.originalElement.css( {
21987				position: "static",
21988				zoom: 1,
21989				display: "block"
21990			} ) );
21991
21992			// Support: IE9
21993			// avoid IE jump (hard set the margin)
21994			this.originalElement.css( margins );
21995
21996			this._proportionallyResize();
21997		}
21998
21999		this._setupHandles();
22000
22001		if ( o.autoHide ) {
22002			$( this.element )
22003				.on( "mouseenter", function() {
22004					if ( o.disabled ) {
22005						return;
22006					}
22007					that._removeClass( "ui-resizable-autohide" );
22008					that._handles.show();
22009				} )
22010				.on( "mouseleave", function() {
22011					if ( o.disabled ) {
22012						return;
22013					}
22014					if ( !that.resizing ) {
22015						that._addClass( "ui-resizable-autohide" );
22016						that._handles.hide();
22017					}
22018				} );
22019		}
22020
22021		this._mouseInit();
22022	},
22023
22024	_destroy: function() {
22025
22026		this._mouseDestroy();
22027		this._addedHandles.remove();
22028
22029		var wrapper,
22030			_destroy = function( exp ) {
22031				$( exp )
22032					.removeData( "resizable" )
22033					.removeData( "ui-resizable" )
22034					.off( ".resizable" );
22035			};
22036
22037		// TODO: Unwrap at same DOM position
22038		if ( this.elementIsWrapper ) {
22039			_destroy( this.element );
22040			wrapper = this.element;
22041			this.originalElement.css( {
22042				position: wrapper.css( "position" ),
22043				width: wrapper.outerWidth(),
22044				height: wrapper.outerHeight(),
22045				top: wrapper.css( "top" ),
22046				left: wrapper.css( "left" )
22047			} ).insertAfter( wrapper );
22048			wrapper.remove();
22049		}
22050
22051		this.originalElement.css( "resize", this.originalResizeStyle );
22052		_destroy( this.originalElement );
22053
22054		return this;
22055	},
22056
22057	_setOption: function( key, value ) {
22058		this._super( key, value );
22059
22060		switch ( key ) {
22061		case "handles":
22062			this._removeHandles();
22063			this._setupHandles();
22064			break;
22065		case "aspectRatio":
22066			this._aspectRatio = !!value;
22067			break;
22068		default:
22069			break;
22070		}
22071	},
22072
22073	_setupHandles: function() {
22074		var o = this.options, handle, i, n, hname, axis, that = this;
22075		this.handles = o.handles ||
22076			( !$( ".ui-resizable-handle", this.element ).length ?
22077				"e,s,se" : {
22078					n: ".ui-resizable-n",
22079					e: ".ui-resizable-e",
22080					s: ".ui-resizable-s",
22081					w: ".ui-resizable-w",
22082					se: ".ui-resizable-se",
22083					sw: ".ui-resizable-sw",
22084					ne: ".ui-resizable-ne",
22085					nw: ".ui-resizable-nw"
22086				} );
22087
22088		this._handles = $();
22089		this._addedHandles = $();
22090		if ( this.handles.constructor === String ) {
22091
22092			if ( this.handles === "all" ) {
22093				this.handles = "n,e,s,w,se,sw,ne,nw";
22094			}
22095
22096			n = this.handles.split( "," );
22097			this.handles = {};
22098
22099			for ( i = 0; i < n.length; i++ ) {
22100
22101				handle = String.prototype.trim.call( n[ i ] );
22102				hname = "ui-resizable-" + handle;
22103				axis = $( "<div>" );
22104				this._addClass( axis, "ui-resizable-handle " + hname );
22105
22106				axis.css( { zIndex: o.zIndex } );
22107
22108				this.handles[ handle ] = ".ui-resizable-" + handle;
22109				if ( !this.element.children( this.handles[ handle ] ).length ) {
22110					this.element.append( axis );
22111					this._addedHandles = this._addedHandles.add( axis );
22112				}
22113			}
22114
22115		}
22116
22117		this._renderAxis = function( target ) {
22118
22119			var i, axis, padPos, padWrapper;
22120
22121			target = target || this.element;
22122
22123			for ( i in this.handles ) {
22124
22125				if ( this.handles[ i ].constructor === String ) {
22126					this.handles[ i ] = this.element.children( this.handles[ i ] ).first().show();
22127				} else if ( this.handles[ i ].jquery || this.handles[ i ].nodeType ) {
22128					this.handles[ i ] = $( this.handles[ i ] );
22129					this._on( this.handles[ i ], { "mousedown": that._mouseDown } );
22130				}
22131
22132				if ( this.elementIsWrapper &&
22133						this.originalElement[ 0 ]
22134							.nodeName
22135							.match( /^(textarea|input|select|button)$/i ) ) {
22136					axis = $( this.handles[ i ], this.element );
22137
22138					padWrapper = /sw|ne|nw|se|n|s/.test( i ) ?
22139						axis.outerHeight() :
22140						axis.outerWidth();
22141
22142					padPos = [ "padding",
22143						/ne|nw|n/.test( i ) ? "Top" :
22144						/se|sw|s/.test( i ) ? "Bottom" :
22145						/^e$/.test( i ) ? "Right" : "Left" ].join( "" );
22146
22147					target.css( padPos, padWrapper );
22148
22149					this._proportionallyResize();
22150				}
22151
22152				this._handles = this._handles.add( this.handles[ i ] );
22153			}
22154		};
22155
22156		// TODO: make renderAxis a prototype function
22157		this._renderAxis( this.element );
22158
22159		this._handles = this._handles.add( this.element.find( ".ui-resizable-handle" ) );
22160		this._handles.disableSelection();
22161
22162		this._handles.on( "mouseover", function() {
22163			if ( !that.resizing ) {
22164				if ( this.className ) {
22165					axis = this.className.match( /ui-resizable-(se|sw|ne|nw|n|e|s|w)/i );
22166				}
22167				that.axis = axis && axis[ 1 ] ? axis[ 1 ] : "se";
22168			}
22169		} );
22170
22171		if ( o.autoHide ) {
22172			this._handles.hide();
22173			this._addClass( "ui-resizable-autohide" );
22174		}
22175	},
22176
22177	_removeHandles: function() {
22178		this._addedHandles.remove();
22179	},
22180
22181	_mouseCapture: function( event ) {
22182		var i, handle,
22183			capture = false;
22184
22185		for ( i in this.handles ) {
22186			handle = $( this.handles[ i ] )[ 0 ];
22187			if ( handle === event.target || $.contains( handle, event.target ) ) {
22188				capture = true;
22189			}
22190		}
22191
22192		return !this.options.disabled && capture;
22193	},
22194
22195	_mouseStart: function( event ) {
22196
22197		var curleft, curtop, cursor,
22198			o = this.options,
22199			el = this.element;
22200
22201		this.resizing = true;
22202
22203		this._renderProxy();
22204
22205		curleft = this._num( this.helper.css( "left" ) );
22206		curtop = this._num( this.helper.css( "top" ) );
22207
22208		if ( o.containment ) {
22209			curleft += $( o.containment ).scrollLeft() || 0;
22210			curtop += $( o.containment ).scrollTop() || 0;
22211		}
22212
22213		this.offset = this.helper.offset();
22214		this.position = { left: curleft, top: curtop };
22215
22216		this.size = this._helper ? {
22217				width: this.helper.width(),
22218				height: this.helper.height()
22219			} : {
22220				width: el.width(),
22221				height: el.height()
22222			};
22223
22224		this.originalSize = this._helper ? {
22225				width: el.outerWidth(),
22226				height: el.outerHeight()
22227			} : {
22228				width: el.width(),
22229				height: el.height()
22230			};
22231
22232		this.sizeDiff = {
22233			width: el.outerWidth() - el.width(),
22234			height: el.outerHeight() - el.height()
22235		};
22236
22237		this.originalPosition = { left: curleft, top: curtop };
22238		this.originalMousePosition = { left: event.pageX, top: event.pageY };
22239
22240		this.aspectRatio = ( typeof o.aspectRatio === "number" ) ?
22241			o.aspectRatio :
22242			( ( this.originalSize.width / this.originalSize.height ) || 1 );
22243
22244		cursor = $( ".ui-resizable-" + this.axis ).css( "cursor" );
22245		$( "body" ).css( "cursor", cursor === "auto" ? this.axis + "-resize" : cursor );
22246
22247		this._addClass( "ui-resizable-resizing" );
22248		this._propagate( "start", event );
22249		return true;
22250	},
22251
22252	_mouseDrag: function( event ) {
22253
22254		var data, props,
22255			smp = this.originalMousePosition,
22256			a = this.axis,
22257			dx = ( event.pageX - smp.left ) || 0,
22258			dy = ( event.pageY - smp.top ) || 0,
22259			trigger = this._change[ a ];
22260
22261		this._updatePrevProperties();
22262
22263		if ( !trigger ) {
22264			return false;
22265		}
22266
22267		data = trigger.apply( this, [ event, dx, dy ] );
22268
22269		this._updateVirtualBoundaries( event.shiftKey );
22270		if ( this._aspectRatio || event.shiftKey ) {
22271			data = this._updateRatio( data, event );
22272		}
22273
22274		data = this._respectSize( data, event );
22275
22276		this._updateCache( data );
22277
22278		this._propagate( "resize", event );
22279
22280		props = this._applyChanges();
22281
22282		if ( !this._helper && this._proportionallyResizeElements.length ) {
22283			this._proportionallyResize();
22284		}
22285
22286		if ( !$.isEmptyObject( props ) ) {
22287			this._updatePrevProperties();
22288			this._trigger( "resize", event, this.ui() );
22289			this._applyChanges();
22290		}
22291
22292		return false;
22293	},
22294
22295	_mouseStop: function( event ) {
22296
22297		this.resizing = false;
22298		var pr, ista, soffseth, soffsetw, s, left, top,
22299			o = this.options, that = this;
22300
22301		if ( this._helper ) {
22302
22303			pr = this._proportionallyResizeElements;
22304			ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName );
22305			soffseth = ista && this._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height;
22306			soffsetw = ista ? 0 : that.sizeDiff.width;
22307
22308			s = {
22309				width: ( that.helper.width()  - soffsetw ),
22310				height: ( that.helper.height() - soffseth )
22311			};
22312			left = ( parseFloat( that.element.css( "left" ) ) +
22313				( that.position.left - that.originalPosition.left ) ) || null;
22314			top = ( parseFloat( that.element.css( "top" ) ) +
22315				( that.position.top - that.originalPosition.top ) ) || null;
22316
22317			if ( !o.animate ) {
22318				this.element.css( $.extend( s, { top: top, left: left } ) );
22319			}
22320
22321			that.helper.height( that.size.height );
22322			that.helper.width( that.size.width );
22323
22324			if ( this._helper && !o.animate ) {
22325				this._proportionallyResize();
22326			}
22327		}
22328
22329		$( "body" ).css( "cursor", "auto" );
22330
22331		this._removeClass( "ui-resizable-resizing" );
22332
22333		this._propagate( "stop", event );
22334
22335		if ( this._helper ) {
22336			this.helper.remove();
22337		}
22338
22339		return false;
22340
22341	},
22342
22343	_updatePrevProperties: function() {
22344		this.prevPosition = {
22345			top: this.position.top,
22346			left: this.position.left
22347		};
22348		this.prevSize = {
22349			width: this.size.width,
22350			height: this.size.height
22351		};
22352	},
22353
22354	_applyChanges: function() {
22355		var props = {};
22356
22357		if ( this.position.top !== this.prevPosition.top ) {
22358			props.top = this.position.top + "px";
22359		}
22360		if ( this.position.left !== this.prevPosition.left ) {
22361			props.left = this.position.left + "px";
22362		}
22363		if ( this.size.width !== this.prevSize.width ) {
22364			props.width = this.size.width + "px";
22365		}
22366		if ( this.size.height !== this.prevSize.height ) {
22367			props.height = this.size.height + "px";
22368		}
22369
22370		this.helper.css( props );
22371
22372		return props;
22373	},
22374
22375	_updateVirtualBoundaries: function( forceAspectRatio ) {
22376		var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b,
22377			o = this.options;
22378
22379		b = {
22380			minWidth: this._isNumber( o.minWidth ) ? o.minWidth : 0,
22381			maxWidth: this._isNumber( o.maxWidth ) ? o.maxWidth : Infinity,
22382			minHeight: this._isNumber( o.minHeight ) ? o.minHeight : 0,
22383			maxHeight: this._isNumber( o.maxHeight ) ? o.maxHeight : Infinity
22384		};
22385
22386		if ( this._aspectRatio || forceAspectRatio ) {
22387			pMinWidth = b.minHeight * this.aspectRatio;
22388			pMinHeight = b.minWidth / this.aspectRatio;
22389			pMaxWidth = b.maxHeight * this.aspectRatio;
22390			pMaxHeight = b.maxWidth / this.aspectRatio;
22391
22392			if ( pMinWidth > b.minWidth ) {
22393				b.minWidth = pMinWidth;
22394			}
22395			if ( pMinHeight > b.minHeight ) {
22396				b.minHeight = pMinHeight;
22397			}
22398			if ( pMaxWidth < b.maxWidth ) {
22399				b.maxWidth = pMaxWidth;
22400			}
22401			if ( pMaxHeight < b.maxHeight ) {
22402				b.maxHeight = pMaxHeight;
22403			}
22404		}
22405		this._vBoundaries = b;
22406	},
22407
22408	_updateCache: function( data ) {
22409		this.offset = this.helper.offset();
22410		if ( this._isNumber( data.left ) ) {
22411			this.position.left = data.left;
22412		}
22413		if ( this._isNumber( data.top ) ) {
22414			this.position.top = data.top;
22415		}
22416		if ( this._isNumber( data.height ) ) {
22417			this.size.height = data.height;
22418		}
22419		if ( this._isNumber( data.width ) ) {
22420			this.size.width = data.width;
22421		}
22422	},
22423
22424	_updateRatio: function( data ) {
22425
22426		var cpos = this.position,
22427			csize = this.size,
22428			a = this.axis;
22429
22430		if ( this._isNumber( data.height ) ) {
22431			data.width = ( data.height * this.aspectRatio );
22432		} else if ( this._isNumber( data.width ) ) {
22433			data.height = ( data.width / this.aspectRatio );
22434		}
22435
22436		if ( a === "sw" ) {
22437			data.left = cpos.left + ( csize.width - data.width );
22438			data.top = null;
22439		}
22440		if ( a === "nw" ) {
22441			data.top = cpos.top + ( csize.height - data.height );
22442			data.left = cpos.left + ( csize.width - data.width );
22443		}
22444
22445		return data;
22446	},
22447
22448	_respectSize: function( data ) {
22449
22450		var o = this._vBoundaries,
22451			a = this.axis,
22452			ismaxw = this._isNumber( data.width ) && o.maxWidth && ( o.maxWidth < data.width ),
22453			ismaxh = this._isNumber( data.height ) && o.maxHeight && ( o.maxHeight < data.height ),
22454			isminw = this._isNumber( data.width ) && o.minWidth && ( o.minWidth > data.width ),
22455			isminh = this._isNumber( data.height ) && o.minHeight && ( o.minHeight > data.height ),
22456			dw = this.originalPosition.left + this.originalSize.width,
22457			dh = this.originalPosition.top + this.originalSize.height,
22458			cw = /sw|nw|w/.test( a ), ch = /nw|ne|n/.test( a );
22459		if ( isminw ) {
22460			data.width = o.minWidth;
22461		}
22462		if ( isminh ) {
22463			data.height = o.minHeight;
22464		}
22465		if ( ismaxw ) {
22466			data.width = o.maxWidth;
22467		}
22468		if ( ismaxh ) {
22469			data.height = o.maxHeight;
22470		}
22471
22472		if ( isminw && cw ) {
22473			data.left = dw - o.minWidth;
22474		}
22475		if ( ismaxw && cw ) {
22476			data.left = dw - o.maxWidth;
22477		}
22478		if ( isminh && ch ) {
22479			data.top = dh - o.minHeight;
22480		}
22481		if ( ismaxh && ch ) {
22482			data.top = dh - o.maxHeight;
22483		}
22484
22485		// Fixing jump error on top/left - bug #2330
22486		if ( !data.width && !data.height && !data.left && data.top ) {
22487			data.top = null;
22488		} else if ( !data.width && !data.height && !data.top && data.left ) {
22489			data.left = null;
22490		}
22491
22492		return data;
22493	},
22494
22495	_getPaddingPlusBorderDimensions: function( element ) {
22496		var i = 0,
22497			widths = [],
22498			borders = [
22499				element.css( "borderTopWidth" ),
22500				element.css( "borderRightWidth" ),
22501				element.css( "borderBottomWidth" ),
22502				element.css( "borderLeftWidth" )
22503			],
22504			paddings = [
22505				element.css( "paddingTop" ),
22506				element.css( "paddingRight" ),
22507				element.css( "paddingBottom" ),
22508				element.css( "paddingLeft" )
22509			];
22510
22511		for ( ; i < 4; i++ ) {
22512			widths[ i ] = ( parseFloat( borders[ i ] ) || 0 );
22513			widths[ i ] += ( parseFloat( paddings[ i ] ) || 0 );
22514		}
22515
22516		return {
22517			height: widths[ 0 ] + widths[ 2 ],
22518			width: widths[ 1 ] + widths[ 3 ]
22519		};
22520	},
22521
22522	_proportionallyResize: function() {
22523
22524		if ( !this._proportionallyResizeElements.length ) {
22525			return;
22526		}
22527
22528		var prel,
22529			i = 0,
22530			element = this.helper || this.element;
22531
22532		for ( ; i < this._proportionallyResizeElements.length; i++ ) {
22533
22534			prel = this._proportionallyResizeElements[ i ];
22535
22536			// TODO: Seems like a bug to cache this.outerDimensions
22537			// considering that we are in a loop.
22538			if ( !this.outerDimensions ) {
22539				this.outerDimensions = this._getPaddingPlusBorderDimensions( prel );
22540			}
22541
22542			prel.css( {
22543				height: ( element.height() - this.outerDimensions.height ) || 0,
22544				width: ( element.width() - this.outerDimensions.width ) || 0
22545			} );
22546
22547		}
22548
22549	},
22550
22551	_renderProxy: function() {
22552
22553		var el = this.element, o = this.options;
22554		this.elementOffset = el.offset();
22555
22556		if ( this._helper ) {
22557
22558			this.helper = this.helper || $( "<div></div>" ).css( { overflow: "hidden" } );
22559
22560			this._addClass( this.helper, this._helper );
22561			this.helper.css( {
22562				width: this.element.outerWidth(),
22563				height: this.element.outerHeight(),
22564				position: "absolute",
vendor: 6,636 bytes, lines 22565-22805
22565				left: this.elementOffset.left + "px",
22566				top: this.elementOffset.top + "px",
22567				zIndex: ++o.zIndex //TODO: Don't modify option
22568			} );
22569
22570			this.helper
22571				.appendTo( "body" )
22572				.disableSelection();
22573
22574		} else {
22575			this.helper = this.element;
22576		}
22577
22578	},
22579
22580	_change: {
22581		e: function( event, dx ) {
22582			return { width: this.originalSize.width + dx };
22583		},
22584		w: function( event, dx ) {
22585			var cs = this.originalSize, sp = this.originalPosition;
22586			return { left: sp.left + dx, width: cs.width - dx };
22587		},
22588		n: function( event, dx, dy ) {
22589			var cs = this.originalSize, sp = this.originalPosition;
22590			return { top: sp.top + dy, height: cs.height - dy };
22591		},
22592		s: function( event, dx, dy ) {
22593			return { height: this.originalSize.height + dy };
22594		},
22595		se: function( event, dx, dy ) {
22596			return $.extend( this._change.s.apply( this, arguments ),
22597				this._change.e.apply( this, [ event, dx, dy ] ) );
22598		},
22599		sw: function( event, dx, dy ) {
22600			return $.extend( this._change.s.apply( this, arguments ),
22601				this._change.w.apply( this, [ event, dx, dy ] ) );
22602		},
22603		ne: function( event, dx, dy ) {
22604			return $.extend( this._change.n.apply( this, arguments ),
22605				this._change.e.apply( this, [ event, dx, dy ] ) );
22606		},
22607		nw: function( event, dx, dy ) {
22608			return $.extend( this._change.n.apply( this, arguments ),
22609				this._change.w.apply( this, [ event, dx, dy ] ) );
22610		}
22611	},
22612
22613	_propagate: function( n, event ) {
22614		$.ui.plugin.call( this, n, [ event, this.ui() ] );
22615		if ( n !== "resize" ) {
22616			this._trigger( n, event, this.ui() );
22617		}
22618	},
22619
22620	plugins: {},
22621
22622	ui: function() {
22623		return {
22624			originalElement: this.originalElement,
22625			element: this.element,
22626			helper: this.helper,
22627			position: this.position,
22628			size: this.size,
22629			originalSize: this.originalSize,
22630			originalPosition: this.originalPosition
22631		};
22632	}
22633
22634} );
22635
22636/*
22637 * Resizable Extensions
22638 */
22639
22640$.ui.plugin.add( "resizable", "animate", {
22641
22642	stop: function( event ) {
22643		var that = $( this ).resizable( "instance" ),
22644			o = that.options,
22645			pr = that._proportionallyResizeElements,
22646			ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName ),
22647			soffseth = ista && that._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height,
22648			soffsetw = ista ? 0 : that.sizeDiff.width,
22649			style = {
22650				width: ( that.size.width - soffsetw ),
22651				height: ( that.size.height - soffseth )
22652			},
22653			left = ( parseFloat( that.element.css( "left" ) ) +
22654				( that.position.left - that.originalPosition.left ) ) || null,
22655			top = ( parseFloat( that.element.css( "top" ) ) +
22656				( that.position.top - that.originalPosition.top ) ) || null;
22657
22658		that.element.animate(
22659			$.extend( style, top && left ? { top: top, left: left } : {} ), {
22660				duration: o.animateDuration,
22661				easing: o.animateEasing,
22662				step: function() {
22663
22664					var data = {
22665						width: parseFloat( that.element.css( "width" ) ),
22666						height: parseFloat( that.element.css( "height" ) ),
22667						top: parseFloat( that.element.css( "top" ) ),
22668						left: parseFloat( that.element.css( "left" ) )
22669					};
22670
22671					if ( pr && pr.length ) {
22672						$( pr[ 0 ] ).css( { width: data.width, height: data.height } );
22673					}
22674
22675					// Propagating resize, and updating values for each animation step
22676					that._updateCache( data );
22677					that._propagate( "resize", event );
22678
22679				}
22680			}
22681		);
22682	}
22683
22684} );
22685
22686$.ui.plugin.add( "resizable", "containment", {
22687
22688	start: function() {
22689		var element, p, co, ch, cw, width, height,
22690			that = $( this ).resizable( "instance" ),
22691			o = that.options,
22692			el = that.element,
22693			oc = o.containment,
22694			ce = ( oc instanceof $ ) ?
22695				oc.get( 0 ) :
22696				( /parent/.test( oc ) ) ? el.parent().get( 0 ) : oc;
22697
22698		if ( !ce ) {
22699			return;
22700		}
22701
22702		that.containerElement = $( ce );
22703
22704		if ( /document/.test( oc ) || oc === document ) {
22705			that.containerOffset = {
22706				left: 0,
22707				top: 0
22708			};
22709			that.containerPosition = {
22710				left: 0,
22711				top: 0
22712			};
22713
22714			that.parentData = {
22715				element: $( document ),
22716				left: 0,
22717				top: 0,
22718				width: $( document ).width(),
22719				height: $( document ).height() || document.body.parentNode.scrollHeight
22720			};
22721		} else {
22722			element = $( ce );
22723			p = [];
22724			$( [ "Top", "Right", "Left", "Bottom" ] ).each( function( i, name ) {
22725				p[ i ] = that._num( element.css( "padding" + name ) );
22726			} );
22727
22728			that.containerOffset = element.offset();
22729			that.containerPosition = element.position();
22730			that.containerSize = {
22731				height: ( element.innerHeight() - p[ 3 ] ),
22732				width: ( element.innerWidth() - p[ 1 ] )
22733			};
22734
22735			co = that.containerOffset;
22736			ch = that.containerSize.height;
22737			cw = that.containerSize.width;
22738			width = ( that._hasScroll( ce, "left" ) ? ce.scrollWidth : cw );
22739			height = ( that._hasScroll( ce ) ? ce.scrollHeight : ch );
22740
22741			that.parentData = {
22742				element: ce,
22743				left: co.left,
22744				top: co.top,
22745				width: width,
22746				height: height
22747			};
22748		}
22749	},
22750
22751	resize: function( event ) {
22752		var woset, hoset, isParent, isOffsetRelative,
22753			that = $( this ).resizable( "instance" ),
22754			o = that.options,
22755			co = that.containerOffset,
22756			cp = that.position,
22757			pRatio = that._aspectRatio || event.shiftKey,
22758			cop = {
22759				top: 0,
22760				left: 0
22761			},
22762			ce = that.containerElement,
22763			continueResize = true;
22764
22765		if ( ce[ 0 ] !== document && ( /static/ ).test( ce.css( "position" ) ) ) {
22766			cop = co;
22767		}
22768
22769		if ( cp.left < ( that._helper ? co.left : 0 ) ) {
22770			that.size.width = that.size.width +
22771				( that._helper ?
22772					( that.position.left - co.left ) :
22773					( that.position.left - cop.left ) );
22774
22775			if ( pRatio ) {
22776				that.size.height = that.size.width / that.aspectRatio;
22777				continueResize = false;
22778			}
22779			that.position.left = o.helper ? co.left : 0;
22780		}
22781
22782		if ( cp.top < ( that._helper ? co.top : 0 ) ) {
22783			that.size.height = that.size.height +
22784				( that._helper ?
22785					( that.position.top - co.top ) :
22786					that.position.top );
22787
22788			if ( pRatio ) {
22789				that.size.width = that.size.height * that.aspectRatio;
22790				continueResize = false;
22791			}
22792			that.position.top = that._helper ? co.top : 0;
22793		}
22794
22795		isParent = that.containerElement.get( 0 ) === that.element.parent().get( 0 );
22796		isOffsetRelative = /relative|absolute/.test( that.containerElement.css( "position" ) );
22797
22798		if ( isParent && isOffsetRelative ) {
22799			that.offset.left = that.parentData.left + that.position.left;
22800			that.offset.top = that.parentData.top + that.position.top;
22801		} else {
22802			that.offset.left = that.element.offset().left;
22803			that.offset.top = that.element.offset().top;
22804		}
22805
vendor: 34,793 bytes, lines 22806-24153
22806		woset = Math.abs( that.sizeDiff.width +
22807			( that._helper ?
22808				that.offset.left - cop.left :
22809				( that.offset.left - co.left ) ) );
22810
22811		hoset = Math.abs( that.sizeDiff.height +
22812			( that._helper ?
22813				that.offset.top - cop.top :
22814				( that.offset.top - co.top ) ) );
22815
22816		if ( woset + that.size.width >= that.parentData.width ) {
22817			that.size.width = that.parentData.width - woset;
22818			if ( pRatio ) {
22819				that.size.height = that.size.width / that.aspectRatio;
22820				continueResize = false;
22821			}
22822		}
22823
22824		if ( hoset + that.size.height >= that.parentData.height ) {
22825			that.size.height = that.parentData.height - hoset;
22826			if ( pRatio ) {
22827				that.size.width = that.size.height * that.aspectRatio;
22828				continueResize = false;
22829			}
22830		}
22831
22832		if ( !continueResize ) {
22833			that.position.left = that.prevPosition.left;
22834			that.position.top = that.prevPosition.top;
22835			that.size.width = that.prevSize.width;
22836			that.size.height = that.prevSize.height;
22837		}
22838	},
22839
22840	stop: function() {
22841		var that = $( this ).resizable( "instance" ),
22842			o = that.options,
22843			co = that.containerOffset,
22844			cop = that.containerPosition,
22845			ce = that.containerElement,
22846			helper = $( that.helper ),
22847			ho = helper.offset(),
22848			w = helper.outerWidth() - that.sizeDiff.width,
22849			h = helper.outerHeight() - that.sizeDiff.height;
22850
22851		if ( that._helper && !o.animate && ( /relative/ ).test( ce.css( "position" ) ) ) {
22852			$( this ).css( {
22853				left: ho.left - cop.left - co.left,
22854				width: w,
22855				height: h
22856			} );
22857		}
22858
22859		if ( that._helper && !o.animate && ( /static/ ).test( ce.css( "position" ) ) ) {
22860			$( this ).css( {
22861				left: ho.left - cop.left - co.left,
22862				width: w,
22863				height: h
22864			} );
22865		}
22866	}
22867} );
22868
22869$.ui.plugin.add( "resizable", "alsoResize", {
22870
22871	start: function() {
22872		var that = $( this ).resizable( "instance" ),
22873			o = that.options;
22874
22875		$( o.alsoResize ).each( function() {
22876			var el = $( this );
22877			el.data( "ui-resizable-alsoresize", {
22878				width: parseFloat( el.width() ), height: parseFloat( el.height() ),
22879				left: parseFloat( el.css( "left" ) ), top: parseFloat( el.css( "top" ) )
22880			} );
22881		} );
22882	},
22883
22884	resize: function( event, ui ) {
22885		var that = $( this ).resizable( "instance" ),
22886			o = that.options,
22887			os = that.originalSize,
22888			op = that.originalPosition,
22889			delta = {
22890				height: ( that.size.height - os.height ) || 0,
22891				width: ( that.size.width - os.width ) || 0,
22892				top: ( that.position.top - op.top ) || 0,
22893				left: ( that.position.left - op.left ) || 0
22894			};
22895
22896			$( o.alsoResize ).each( function() {
22897				var el = $( this ), start = $( this ).data( "ui-resizable-alsoresize" ), style = {},
22898					css = el.parents( ui.originalElement[ 0 ] ).length ?
22899							[ "width", "height" ] :
22900							[ "width", "height", "top", "left" ];
22901
22902				$.each( css, function( i, prop ) {
22903					var sum = ( start[ prop ] || 0 ) + ( delta[ prop ] || 0 );
22904					if ( sum && sum >= 0 ) {
22905						style[ prop ] = sum || null;
22906					}
22907				} );
22908
22909				el.css( style );
22910			} );
22911	},
22912
22913	stop: function() {
22914		$( this ).removeData( "ui-resizable-alsoresize" );
22915	}
22916} );
22917
22918$.ui.plugin.add( "resizable", "ghost", {
22919
22920	start: function() {
22921
22922		var that = $( this ).resizable( "instance" ), cs = that.size;
22923
22924		that.ghost = that.originalElement.clone();
22925		that.ghost.css( {
22926			opacity: 0.25,
22927			display: "block",
22928			position: "relative",
22929			height: cs.height,
22930			width: cs.width,
22931			margin: 0,
22932			left: 0,
22933			top: 0
22934		} );
22935
22936		that._addClass( that.ghost, "ui-resizable-ghost" );
22937
22938		// DEPRECATED
22939		// TODO: remove after 1.12
22940		if ( $.uiBackCompat !== false && typeof that.options.ghost === "string" ) {
22941
22942			// Ghost option
22943			that.ghost.addClass( this.options.ghost );
22944		}
22945
22946		that.ghost.appendTo( that.helper );
22947
22948	},
22949
22950	resize: function() {
22951		var that = $( this ).resizable( "instance" );
22952		if ( that.ghost ) {
22953			that.ghost.css( {
22954				position: "relative",
22955				height: that.size.height,
22956				width: that.size.width
22957			} );
22958		}
22959	},
22960
22961	stop: function() {
22962		var that = $( this ).resizable( "instance" );
22963		if ( that.ghost && that.helper ) {
22964			that.helper.get( 0 ).removeChild( that.ghost.get( 0 ) );
22965		}
22966	}
22967
22968} );
22969
22970$.ui.plugin.add( "resizable", "grid", {
22971
22972	resize: function() {
22973		var outerDimensions,
22974			that = $( this ).resizable( "instance" ),
22975			o = that.options,
22976			cs = that.size,
22977			os = that.originalSize,
22978			op = that.originalPosition,
22979			a = that.axis,
22980			grid = typeof o.grid === "number" ? [ o.grid, o.grid ] : o.grid,
22981			gridX = ( grid[ 0 ] || 1 ),
22982			gridY = ( grid[ 1 ] || 1 ),
22983			ox = Math.round( ( cs.width - os.width ) / gridX ) * gridX,
22984			oy = Math.round( ( cs.height - os.height ) / gridY ) * gridY,
22985			newWidth = os.width + ox,
22986			newHeight = os.height + oy,
22987			isMaxWidth = o.maxWidth && ( o.maxWidth < newWidth ),
22988			isMaxHeight = o.maxHeight && ( o.maxHeight < newHeight ),
22989			isMinWidth = o.minWidth && ( o.minWidth > newWidth ),
22990			isMinHeight = o.minHeight && ( o.minHeight > newHeight );
22991
22992		o.grid = grid;
22993
22994		if ( isMinWidth ) {
22995			newWidth += gridX;
22996		}
22997		if ( isMinHeight ) {
22998			newHeight += gridY;
22999		}
23000		if ( isMaxWidth ) {
23001			newWidth -= gridX;
23002		}
23003		if ( isMaxHeight ) {
23004			newHeight -= gridY;
23005		}
23006
23007		if ( /^(se|s|e)$/.test( a ) ) {
23008			that.size.width = newWidth;
23009			that.size.height = newHeight;
23010		} else if ( /^(ne)$/.test( a ) ) {
23011			that.size.width = newWidth;
23012			that.size.height = newHeight;
23013			that.position.top = op.top - oy;
23014		} else if ( /^(sw)$/.test( a ) ) {
23015			that.size.width = newWidth;
23016			that.size.height = newHeight;
23017			that.position.left = op.left - ox;
23018		} else {
23019			if ( newHeight - gridY <= 0 || newWidth - gridX <= 0 ) {
23020				outerDimensions = that._getPaddingPlusBorderDimensions( this );
23021			}
23022
23023			if ( newHeight - gridY > 0 ) {
23024				that.size.height = newHeight;
23025				that.position.top = op.top - oy;
23026			} else {
23027				newHeight = gridY - outerDimensions.height;
23028				that.size.height = newHeight;
23029				that.position.top = op.top + os.height - newHeight;
23030			}
23031			if ( newWidth - gridX > 0 ) {
23032				that.size.width = newWidth;
23033				that.position.left = op.left - ox;
23034			} else {
23035				newWidth = gridX - outerDimensions.width;
23036				that.size.width = newWidth;
23037				that.position.left = op.left + os.width - newWidth;
23038			}
23039		}
23040	}
23041
23042} );
23043
23044var widgetsResizable = $.ui.resizable;
23045
23046
23047/*!
23048 * jQuery UI Dialog 1.13.2
23049 * http://jqueryui.com
23050 *
23051 * Copyright jQuery Foundation and other contributors
23052 * Released under the MIT license.
23053 * http://jquery.org/license
23054 */
23055
23056//>>label: Dialog
23057//>>group: Widgets
23058//>>description: Displays customizable dialog windows.
23059//>>docs: http://api.jqueryui.com/dialog/
23060//>>demos: http://jqueryui.com/dialog/
23061//>>css.structure: ../../themes/base/core.css
23062//>>css.structure: ../../themes/base/dialog.css
23063//>>css.theme: ../../themes/base/theme.css
23064
23065
23066$.widget( "ui.dialog", {
23067	version: "1.13.2",
23068	options: {
23069		appendTo: "body",
23070		autoOpen: true,
23071		buttons: [],
23072		classes: {
23073			"ui-dialog": "ui-corner-all",
23074			"ui-dialog-titlebar": "ui-corner-all"
23075		},
23076		closeOnEscape: true,
23077		closeText: "Close",
23078		draggable: true,
23079		hide: null,
23080		height: "auto",
23081		maxHeight: null,
23082		maxWidth: null,
23083		minHeight: 150,
23084		minWidth: 150,
23085		modal: false,
23086		position: {
23087			my: "center",
23088			at: "center",
23089			of: window,
23090			collision: "fit",
23091
23092			// Ensure the titlebar is always visible
23093			using: function( pos ) {
23094				var topOffset = $( this ).css( pos ).offset().top;
23095				if ( topOffset < 0 ) {
23096					$( this ).css( "top", pos.top - topOffset );
23097				}
23098			}
23099		},
23100		resizable: true,
23101		show: null,
23102		title: null,
23103		width: 300,
23104
23105		// Callbacks
23106		beforeClose: null,
23107		close: null,
23108		drag: null,
23109		dragStart: null,
23110		dragStop: null,
23111		focus: null,
23112		open: null,
23113		resize: null,
23114		resizeStart: null,
23115		resizeStop: null
23116	},
23117
23118	sizeRelatedOptions: {
23119		buttons: true,
23120		height: true,
23121		maxHeight: true,
23122		maxWidth: true,
23123		minHeight: true,
23124		minWidth: true,
23125		width: true
23126	},
23127
23128	resizableRelatedOptions: {
23129		maxHeight: true,
23130		maxWidth: true,
23131		minHeight: true,
23132		minWidth: true
23133	},
23134
23135	_create: function() {
23136		this.originalCss = {
23137			display: this.element[ 0 ].style.display,
23138			width: this.element[ 0 ].style.width,
23139			minHeight: this.element[ 0 ].style.minHeight,
23140			maxHeight: this.element[ 0 ].style.maxHeight,
23141			height: this.element[ 0 ].style.height
23142		};
23143		this.originalPosition = {
23144			parent: this.element.parent(),
23145			index: this.element.parent().children().index( this.element )
23146		};
23147		this.originalTitle = this.element.attr( "title" );
23148		if ( this.options.title == null && this.originalTitle != null ) {
23149			this.options.title = this.originalTitle;
23150		}
23151
23152		// Dialogs can't be disabled
23153		if ( this.options.disabled ) {
23154			this.options.disabled = false;
23155		}
23156
23157		this._createWrapper();
23158
23159		this.element
23160			.show()
23161			.removeAttr( "title" )
23162			.appendTo( this.uiDialog );
23163
23164		this._addClass( "ui-dialog-content", "ui-widget-content" );
23165
23166		this._createTitlebar();
23167		this._createButtonPane();
23168
23169		if ( this.options.draggable && $.fn.draggable ) {
23170			this._makeDraggable();
23171		}
23172		if ( this.options.resizable && $.fn.resizable ) {
23173			this._makeResizable();
23174		}
23175
23176		this._isOpen = false;
23177
23178		this._trackFocus();
23179	},
23180
23181	_init: function() {
23182		if ( this.options.autoOpen ) {
23183			this.open();
23184		}
23185	},
23186
23187	_appendTo: function() {
23188		var element = this.options.appendTo;
23189		if ( element && ( element.jquery || element.nodeType ) ) {
23190			return $( element );
23191		}
23192		return this.document.find( element || "body" ).eq( 0 );
23193	},
23194
23195	_destroy: function() {
23196		var next,
23197			originalPosition = this.originalPosition;
23198
23199		this._untrackInstance();
23200		this._destroyOverlay();
23201
23202		this.element
23203			.removeUniqueId()
23204			.css( this.originalCss )
23205
23206			// Without detaching first, the following becomes really slow
23207			.detach();
23208
23209		this.uiDialog.remove();
23210
23211		if ( this.originalTitle ) {
23212			this.element.attr( "title", this.originalTitle );
23213		}
23214
23215		next = originalPosition.parent.children().eq( originalPosition.index );
23216
23217		// Don't try to place the dialog next to itself (#8613)
23218		if ( next.length && next[ 0 ] !== this.element[ 0 ] ) {
23219			next.before( this.element );
23220		} else {
23221			originalPosition.parent.append( this.element );
23222		}
23223	},
23224
23225	widget: function() {
23226		return this.uiDialog;
23227	},
23228
23229	disable: $.noop,
23230	enable: $.noop,
23231
23232	close: function( event ) {
23233		var that = this;
23234
23235		if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) {
23236			return;
23237		}
23238
23239		this._isOpen = false;
23240		this._focusedElement = null;
23241		this._destroyOverlay();
23242		this._untrackInstance();
23243
23244		if ( !this.opener.filter( ":focusable" ).trigger( "focus" ).length ) {
23245
23246			// Hiding a focused element doesn't trigger blur in WebKit
23247			// so in case we have nothing to focus on, explicitly blur the active element
23248			// https://bugs.webkit.org/show_bug.cgi?id=47182
23249			$.ui.safeBlur( $.ui.safeActiveElement( this.document[ 0 ] ) );
23250		}
23251
23252		this._hide( this.uiDialog, this.options.hide, function() {
23253			that._trigger( "close", event );
23254		} );
23255	},
23256
23257	isOpen: function() {
23258		return this._isOpen;
23259	},
23260
23261	moveToTop: function() {
23262		this._moveToTop();
23263	},
23264
23265	_moveToTop: function( event, silent ) {
23266		var moved = false,
23267			zIndices = this.uiDialog.siblings( ".ui-front:visible" ).map( function() {
23268				return +$( this ).css( "z-index" );
23269			} ).get(),
23270			zIndexMax = Math.max.apply( null, zIndices );
23271
23272		if ( zIndexMax >= +this.uiDialog.css( "z-index" ) ) {
23273			this.uiDialog.css( "z-index", zIndexMax + 1 );
23274			moved = true;
23275		}
23276
23277		if ( moved && !silent ) {
23278			this._trigger( "focus", event );
23279		}
23280		return moved;
23281	},
23282
23283	open: function() {
23284		var that = this;
23285		if ( this._isOpen ) {
23286			if ( this._moveToTop() ) {
23287				this._focusTabbable();
23288			}
23289			return;
23290		}
23291
23292		this._isOpen = true;
23293		this.opener = $( $.ui.safeActiveElement( this.document[ 0 ] ) );
23294
23295		this._size();
23296		this._position();
23297		this._createOverlay();
23298		this._moveToTop( null, true );
23299
23300		// Ensure the overlay is moved to the top with the dialog, but only when
23301		// opening. The overlay shouldn't move after the dialog is open so that
23302		// modeless dialogs opened after the modal dialog stack properly.
23303		if ( this.overlay ) {
23304			this.overlay.css( "z-index", this.uiDialog.css( "z-index" ) - 1 );
23305		}
23306
23307		this._show( this.uiDialog, this.options.show, function() {
23308			that._focusTabbable();
23309			that._trigger( "focus" );
23310		} );
23311
23312		// Track the dialog immediately upon opening in case a focus event
23313		// somehow occurs outside of the dialog before an element inside the
23314		// dialog is focused (#10152)
23315		this._makeFocusTarget();
23316
23317		this._trigger( "open" );
23318	},
23319
23320	_focusTabbable: function() {
23321
23322		// Set focus to the first match:
23323		// 1. An element that was focused previously
23324		// 2. First element inside the dialog matching [autofocus]
23325		// 3. Tabbable element inside the content element
23326		// 4. Tabbable element inside the buttonpane
23327		// 5. The close button
23328		// 6. The dialog itself
23329		var hasFocus = this._focusedElement;
23330		if ( !hasFocus ) {
23331			hasFocus = this.element.find( "[autofocus]" );
23332		}
23333		if ( !hasFocus.length ) {
23334			hasFocus = this.element.find( ":tabbable" );
23335		}
23336		if ( !hasFocus.length ) {
23337			hasFocus = this.uiDialogButtonPane.find( ":tabbable" );
23338		}
23339		if ( !hasFocus.length ) {
23340			hasFocus = this.uiDialogTitlebarClose.filter( ":tabbable" );
23341		}
23342		if ( !hasFocus.length ) {
23343			hasFocus = this.uiDialog;
23344		}
23345		hasFocus.eq( 0 ).trigger( "focus" );
23346	},
23347
23348	_restoreTabbableFocus: function() {
23349		var activeElement = $.ui.safeActiveElement( this.document[ 0 ] ),
23350			isActive = this.uiDialog[ 0 ] === activeElement ||
23351				$.contains( this.uiDialog[ 0 ], activeElement );
23352		if ( !isActive ) {
23353			this._focusTabbable();
23354		}
23355	},
23356
23357	_keepFocus: function( event ) {
23358		event.preventDefault();
23359		this._restoreTabbableFocus();
23360
23361		// support: IE
23362		// IE <= 8 doesn't prevent moving focus even with event.preventDefault()
23363		// so we check again later
23364		this._delay( this._restoreTabbableFocus );
23365	},
23366
23367	_createWrapper: function() {
23368		this.uiDialog = $( "<div>" )
23369			.hide()
23370			.attr( {
23371
23372				// Setting tabIndex makes the div focusable
23373				tabIndex: -1,
23374				role: "dialog"
23375			} )
23376			.appendTo( this._appendTo() );
23377
23378		this._addClass( this.uiDialog, "ui-dialog", "ui-widget ui-widget-content ui-front" );
23379		this._on( this.uiDialog, {
23380			keydown: function( event ) {
23381				if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
23382						event.keyCode === $.ui.keyCode.ESCAPE ) {
23383					event.preventDefault();
23384					this.close( event );
23385					return;
23386				}
23387
23388				// Prevent tabbing out of dialogs
23389				if ( event.keyCode !== $.ui.keyCode.TAB || event.isDefaultPrevented() ) {
23390					return;
23391				}
23392				var tabbables = this.uiDialog.find( ":tabbable" ),
23393					first = tabbables.first(),
23394					last = tabbables.last();
23395
23396				if ( ( event.target === last[ 0 ] || event.target === this.uiDialog[ 0 ] ) &&
23397						!event.shiftKey ) {
23398					this._delay( function() {
23399						first.trigger( "focus" );
23400					} );
23401					event.preventDefault();
23402				} else if ( ( event.target === first[ 0 ] ||
23403						event.target === this.uiDialog[ 0 ] ) && event.shiftKey ) {
23404					this._delay( function() {
23405						last.trigger( "focus" );
23406					} );
23407					event.preventDefault();
23408				}
23409			},
23410			mousedown: function( event ) {
23411				if ( this._moveToTop( event ) ) {
23412					this._focusTabbable();
23413				}
23414			}
23415		} );
23416
23417		// We assume that any existing aria-describedby attribute means
23418		// that the dialog content is marked up properly
23419		// otherwise we brute force the content as the description
23420		if ( !this.element.find( "[aria-describedby]" ).length ) {
23421			this.uiDialog.attr( {
23422				"aria-describedby": this.element.uniqueId().attr( "id" )
23423			} );
23424		}
23425	},
23426
23427	_createTitlebar: function() {
23428		var uiDialogTitle;
23429
23430		this.uiDialogTitlebar = $( "<div>" );
23431		this._addClass( this.uiDialogTitlebar,
23432			"ui-dialog-titlebar", "ui-widget-header ui-helper-clearfix" );
23433		this._on( this.uiDialogTitlebar, {
23434			mousedown: function( event ) {
23435
23436				// Don't prevent click on close button (#8838)
23437				// Focusing a dialog that is partially scrolled out of view
23438				// causes the browser to scroll it into view, preventing the click event
23439				if ( !$( event.target ).closest( ".ui-dialog-titlebar-close" ) ) {
23440
23441					// Dialog isn't getting focus when dragging (#8063)
23442					this.uiDialog.trigger( "focus" );
23443				}
23444			}
23445		} );
23446
23447		// Support: IE
23448		// Use type="button" to prevent enter keypresses in textboxes from closing the
23449		// dialog in IE (#9312)
23450		this.uiDialogTitlebarClose = $( "<button type='button'></button>" )
23451			.button( {
23452				label: $( "<a>" ).text( this.options.closeText ).html(),
23453				icon: "ui-icon-closethick",
23454				showLabel: false
23455			} )
23456			.appendTo( this.uiDialogTitlebar );
23457
23458		this._addClass( this.uiDialogTitlebarClose, "ui-dialog-titlebar-close" );
23459		this._on( this.uiDialogTitlebarClose, {
23460			click: function( event ) {
23461				event.preventDefault();
23462				this.close( event );
23463			}
23464		} );
23465
23466		uiDialogTitle = $( "<span>" ).uniqueId().prependTo( this.uiDialogTitlebar );
23467		this._addClass( uiDialogTitle, "ui-dialog-title" );
23468		this._title( uiDialogTitle );
23469
23470		this.uiDialogTitlebar.prependTo( this.uiDialog );
23471
23472		this.uiDialog.attr( {
23473			"aria-labelledby": uiDialogTitle.attr( "id" )
23474		} );
23475	},
23476
23477	_title: function( title ) {
23478		if ( this.options.title ) {
23479			title.text( this.options.title );
23480		} else {
23481			title.html( "&#160;" );
23482		}
23483	},
23484
23485	_createButtonPane: function() {
23486		this.uiDialogButtonPane = $( "<div>" );
23487		this._addClass( this.uiDialogButtonPane, "ui-dialog-buttonpane",
23488			"ui-widget-content ui-helper-clearfix" );
23489
23490		this.uiButtonSet = $( "<div>" )
23491			.appendTo( this.uiDialogButtonPane );
23492		this._addClass( this.uiButtonSet, "ui-dialog-buttonset" );
23493
23494		this._createButtons();
23495	},
23496
23497	_createButtons: function() {
23498		var that = this,
23499			buttons = this.options.buttons;
23500
23501		// If we already have a button pane, remove it
23502		this.uiDialogButtonPane.remove();
23503		this.uiButtonSet.empty();
23504
23505		if ( $.isEmptyObject( buttons ) || ( Array.isArray( buttons ) && !buttons.length ) ) {
23506			this._removeClass( this.uiDialog, "ui-dialog-buttons" );
23507			return;
23508		}
23509
23510		$.each( buttons, function( name, props ) {
23511			var click, buttonOptions;
23512			props = typeof props === "function" ?
23513				{ click: props, text: name } :
23514				props;
23515
23516			// Default to a non-submitting button
23517			props = $.extend( { type: "button" }, props );
23518
23519			// Change the context for the click callback to be the main element
23520			click = props.click;
23521			buttonOptions = {
23522				icon: props.icon,
23523				iconPosition: props.iconPosition,
23524				showLabel: props.showLabel,
23525
23526				// Deprecated options
23527				icons: props.icons,
23528				text: props.text
23529			};
23530
23531			delete props.click;
23532			delete props.icon;
23533			delete props.iconPosition;
23534			delete props.showLabel;
23535
23536			// Deprecated options
23537			delete props.icons;
23538			if ( typeof props.text === "boolean" ) {
23539				delete props.text;
23540			}
23541
23542			$( "<button></button>", props )
23543				.button( buttonOptions )
23544				.appendTo( that.uiButtonSet )
23545				.on( "click", function() {
23546					click.apply( that.element[ 0 ], arguments );
23547				} );
23548		} );
23549		this._addClass( this.uiDialog, "ui-dialog-buttons" );
23550		this.uiDialogButtonPane.appendTo( this.uiDialog );
23551	},
23552
23553	_makeDraggable: function() {
23554		var that = this,
23555			options = this.options;
23556
23557		function filteredUi( ui ) {
23558			return {
23559				position: ui.position,
23560				offset: ui.offset
23561			};
23562		}
23563
23564		this.uiDialog.draggable( {
23565			cancel: ".ui-dialog-content, .ui-dialog-titlebar-close",
23566			handle: ".ui-dialog-titlebar",
23567			containment: "document",
23568			start: function( event, ui ) {
23569				that._addClass( $( this ), "ui-dialog-dragging" );
23570				that._blockFrames();
23571				that._trigger( "dragStart", event, filteredUi( ui ) );
23572			},
23573			drag: function( event, ui ) {
23574				that._trigger( "drag", event, filteredUi( ui ) );
23575			},
23576			stop: function( event, ui ) {
23577				var left = ui.offset.left - that.document.scrollLeft(),
23578					top = ui.offset.top - that.document.scrollTop();
23579
23580				options.position = {
23581					my: "left top",
23582					at: "left" + ( left >= 0 ? "+" : "" ) + left + " " +
23583						"top" + ( top >= 0 ? "+" : "" ) + top,
23584					of: that.window
23585				};
23586				that._removeClass( $( this ), "ui-dialog-dragging" );
23587				that._unblockFrames();
23588				that._trigger( "dragStop", event, filteredUi( ui ) );
23589			}
23590		} );
23591	},
23592
23593	_makeResizable: function() {
23594		var that = this,
23595			options = this.options,
23596			handles = options.resizable,
23597
23598			// .ui-resizable has position: relative defined in the stylesheet
23599			// but dialogs have to use absolute or fixed positioning
23600			position = this.uiDialog.css( "position" ),
23601			resizeHandles = typeof handles === "string" ?
23602				handles :
23603				"n,e,s,w,se,sw,ne,nw";
23604
23605		function filteredUi( ui ) {
23606			return {
23607				originalPosition: ui.originalPosition,
23608				originalSize: ui.originalSize,
23609				position: ui.position,
23610				size: ui.size
23611			};
23612		}
23613
23614		this.uiDialog.resizable( {
23615			cancel: ".ui-dialog-content",
23616			containment: "document",
23617			alsoResize: this.element,
23618			maxWidth: options.maxWidth,
23619			maxHeight: options.maxHeight,
23620			minWidth: options.minWidth,
23621			minHeight: this._minHeight(),
23622			handles: resizeHandles,
23623			start: function( event, ui ) {
23624				that._addClass( $( this ), "ui-dialog-resizing" );
23625				that._blockFrames();
23626				that._trigger( "resizeStart", event, filteredUi( ui ) );
23627			},
23628			resize: function( event, ui ) {
23629				that._trigger( "resize", event, filteredUi( ui ) );
23630			},
23631			stop: function( event, ui ) {
23632				var offset = that.uiDialog.offset(),
23633					left = offset.left - that.document.scrollLeft(),
23634					top = offset.top - that.document.scrollTop();
23635
23636				options.height = that.uiDialog.height();
23637				options.width = that.uiDialog.width();
23638				options.position = {
23639					my: "left top",
23640					at: "left" + ( left >= 0 ? "+" : "" ) + left + " " +
23641						"top" + ( top >= 0 ? "+" : "" ) + top,
23642					of: that.window
23643				};
23644				that._removeClass( $( this ), "ui-dialog-resizing" );
23645				that._unblockFrames();
23646				that._trigger( "resizeStop", event, filteredUi( ui ) );
23647			}
23648		} )
23649			.css( "position", position );
23650	},
23651
23652	_trackFocus: function() {
23653		this._on( this.widget(), {
23654			focusin: function( event ) {
23655				this._makeFocusTarget();
23656				this._focusedElement = $( event.target );
23657			}
23658		} );
23659	},
23660
23661	_makeFocusTarget: function() {
23662		this._untrackInstance();
23663		this._trackingInstances().unshift( this );
23664	},
23665
23666	_untrackInstance: function() {
23667		var instances = this._trackingInstances(),
23668			exists = $.inArray( this, instances );
23669		if ( exists !== -1 ) {
23670			instances.splice( exists, 1 );
23671		}
23672	},
23673
23674	_trackingInstances: function() {
23675		var instances = this.document.data( "ui-dialog-instances" );
23676		if ( !instances ) {
23677			instances = [];
23678			this.document.data( "ui-dialog-instances", instances );
23679		}
23680		return instances;
23681	},
23682
23683	_minHeight: function() {
23684		var options = this.options;
23685
23686		return options.height === "auto" ?
23687			options.minHeight :
23688			Math.min( options.minHeight, options.height );
23689	},
23690
23691	_position: function() {
23692
23693		// Need to show the dialog to get the actual offset in the position plugin
23694		var isVisible = this.uiDialog.is( ":visible" );
23695		if ( !isVisible ) {
23696			this.uiDialog.show();
23697		}
23698		this.uiDialog.position( this.options.position );
23699		if ( !isVisible ) {
23700			this.uiDialog.hide();
23701		}
23702	},
23703
23704	_setOptions: function( options ) {
23705		var that = this,
23706			resize = false,
23707			resizableOptions = {};
23708
23709		$.each( options, function( key, value ) {
23710			that._setOption( key, value );
23711
23712			if ( key in that.sizeRelatedOptions ) {
23713				resize = true;
23714			}
23715			if ( key in that.resizableRelatedOptions ) {
23716				resizableOptions[ key ] = value;
23717			}
23718		} );
23719
23720		if ( resize ) {
23721			this._size();
23722			this._position();
23723		}
23724		if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
23725			this.uiDialog.resizable( "option", resizableOptions );
23726		}
23727	},
23728
23729	_setOption: function( key, value ) {
23730		var isDraggable, isResizable,
23731			uiDialog = this.uiDialog;
23732
23733		if ( key === "disabled" ) {
23734			return;
23735		}
23736
23737		this._super( key, value );
23738
23739		if ( key === "appendTo" ) {
23740			this.uiDialog.appendTo( this._appendTo() );
23741		}
23742
23743		if ( key === "buttons" ) {
23744			this._createButtons();
23745		}
23746
23747		if ( key === "closeText" ) {
23748			this.uiDialogTitlebarClose.button( {
23749
23750				// Ensure that we always pass a string
23751				label: $( "<a>" ).text( "" + this.options.closeText ).html()
23752			} );
23753		}
23754
23755		if ( key === "draggable" ) {
23756			isDraggable = uiDialog.is( ":data(ui-draggable)" );
23757			if ( isDraggable && !value ) {
23758				uiDialog.draggable( "destroy" );
23759			}
23760
23761			if ( !isDraggable && value ) {
23762				this._makeDraggable();
23763			}
23764		}
23765
23766		if ( key === "position" ) {
23767			this._position();
23768		}
23769
23770		if ( key === "resizable" ) {
23771
23772			// currently resizable, becoming non-resizable
23773			isResizable = uiDialog.is( ":data(ui-resizable)" );
23774			if ( isResizable && !value ) {
23775				uiDialog.resizable( "destroy" );
23776			}
23777
23778			// Currently resizable, changing handles
23779			if ( isResizable && typeof value === "string" ) {
23780				uiDialog.resizable( "option", "handles", value );
23781			}
23782
23783			// Currently non-resizable, becoming resizable
23784			if ( !isResizable && value !== false ) {
23785				this._makeResizable();
23786			}
23787		}
23788
23789		if ( key === "title" ) {
23790			this._title( this.uiDialogTitlebar.find( ".ui-dialog-title" ) );
23791		}
23792	},
23793
23794	_size: function() {
23795
23796		// If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
23797		// divs will both have width and height set, so we need to reset them
23798		var nonContentHeight, minContentHeight, maxContentHeight,
23799			options = this.options;
23800
23801		// Reset content sizing
23802		this.element.show().css( {
23803			width: "auto",
23804			minHeight: 0,
23805			maxHeight: "none",
23806			height: 0
23807		} );
23808
23809		if ( options.minWidth > options.width ) {
23810			options.width = options.minWidth;
23811		}
23812
23813		// Reset wrapper sizing
23814		// determine the height of all the non-content elements
23815		nonContentHeight = this.uiDialog.css( {
23816			height: "auto",
23817			width: options.width
23818		} )
23819			.outerHeight();
23820		minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
23821		maxContentHeight = typeof options.maxHeight === "number" ?
23822			Math.max( 0, options.maxHeight - nonContentHeight ) :
23823			"none";
23824
23825		if ( options.height === "auto" ) {
23826			this.element.css( {
23827				minHeight: minContentHeight,
23828				maxHeight: maxContentHeight,
23829				height: "auto"
23830			} );
23831		} else {
23832			this.element.height( Math.max( 0, options.height - nonContentHeight ) );
23833		}
23834
23835		if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
23836			this.uiDialog.resizable( "option", "minHeight", this._minHeight() );
23837		}
23838	},
23839
23840	_blockFrames: function() {
23841		this.iframeBlocks = this.document.find( "iframe" ).map( function() {
23842			var iframe = $( this );
23843
23844			return $( "<div>" )
23845				.css( {
23846					position: "absolute",
23847					width: iframe.outerWidth(),
23848					height: iframe.outerHeight()
23849				} )
23850				.appendTo( iframe.parent() )
23851				.offset( iframe.offset() )[ 0 ];
23852		} );
23853	},
23854
23855	_unblockFrames: function() {
23856		if ( this.iframeBlocks ) {
23857			this.iframeBlocks.remove();
23858			delete this.iframeBlocks;
23859		}
23860	},
23861
23862	_allowInteraction: function( event ) {
23863		if ( $( event.target ).closest( ".ui-dialog" ).length ) {
23864			return true;
23865		}
23866
23867		// TODO: Remove hack when datepicker implements
23868		// the .ui-front logic (#8989)
23869		return !!$( event.target ).closest( ".ui-datepicker" ).length;
23870	},
23871
23872	_createOverlay: function() {
23873		if ( !this.options.modal ) {
23874			return;
23875		}
23876
23877		var jqMinor = $.fn.jquery.substring( 0, 4 );
23878
23879		// We use a delay in case the overlay is created from an
23880		// event that we're going to be cancelling (#2804)
23881		var isOpening = true;
23882		this._delay( function() {
23883			isOpening = false;
23884		} );
23885
23886		if ( !this.document.data( "ui-dialog-overlays" ) ) {
23887
23888			// Prevent use of anchors and inputs
23889			// This doesn't use `_on()` because it is a shared event handler
23890			// across all open modal dialogs.
23891			this.document.on( "focusin.ui-dialog", function( event ) {
23892				if ( isOpening ) {
23893					return;
23894				}
23895
23896				var instance = this._trackingInstances()[ 0 ];
23897				if ( !instance._allowInteraction( event ) ) {
23898					event.preventDefault();
23899					instance._focusTabbable();
23900
23901					// Support: jQuery >=3.4 <3.6 only
23902					// Focus re-triggering in jQuery 3.4/3.5 makes the original element
23903					// have its focus event propagated last, breaking the re-targeting.
23904					// Trigger focus in a delay in addition if needed to avoid the issue
23905					// See https://github.com/jquery/jquery/issues/4382
23906					if ( jqMinor === "3.4." || jqMinor === "3.5." ) {
23907						instance._delay( instance._restoreTabbableFocus );
23908					}
23909				}
23910			}.bind( this ) );
23911		}
23912
23913		this.overlay = $( "<div>" )
23914			.appendTo( this._appendTo() );
23915
23916		this._addClass( this.overlay, null, "ui-widget-overlay ui-front" );
23917		this._on( this.overlay, {
23918			mousedown: "_keepFocus"
23919		} );
23920		this.document.data( "ui-dialog-overlays",
23921			( this.document.data( "ui-dialog-overlays" ) || 0 ) + 1 );
23922	},
23923
23924	_destroyOverlay: function() {
23925		if ( !this.options.modal ) {
23926			return;
23927		}
23928
23929		if ( this.overlay ) {
23930			var overlays = this.document.data( "ui-dialog-overlays" ) - 1;
23931
23932			if ( !overlays ) {
23933				this.document.off( "focusin.ui-dialog" );
23934				this.document.removeData( "ui-dialog-overlays" );
23935			} else {
23936				this.document.data( "ui-dialog-overlays", overlays );
23937			}
23938
23939			this.overlay.remove();
23940			this.overlay = null;
23941		}
23942	}
23943} );
23944
23945// DEPRECATED
23946// TODO: switch return back to widget declaration at top of file when this is removed
23947if ( $.uiBackCompat !== false ) {
23948
23949	// Backcompat for dialogClass option
23950	$.widget( "ui.dialog", $.ui.dialog, {
23951		options: {
23952			dialogClass: ""
23953		},
23954		_createWrapper: function() {
23955			this._super();
23956			this.uiDialog.addClass( this.options.dialogClass );
23957		},
23958		_setOption: function( key, value ) {
23959			if ( key === "dialogClass" ) {
23960				this.uiDialog
23961					.removeClass( this.options.dialogClass )
23962					.addClass( value );
23963			}
23964			this._superApply( arguments );
23965		}
23966	} );
23967}
23968
23969var widgetsDialog = $.ui.dialog;
23970
23971
23972/*!
23973 * jQuery UI Droppable 1.13.2
23974 * http://jqueryui.com
23975 *
23976 * Copyright jQuery Foundation and other contributors
23977 * Released under the MIT license.
23978 * http://jquery.org/license
23979 */
23980
23981//>>label: Droppable
23982//>>group: Interactions
23983//>>description: Enables drop targets for draggable elements.
23984//>>docs: http://api.jqueryui.com/droppable/
23985//>>demos: http://jqueryui.com/droppable/
23986
23987
23988$.widget( "ui.droppable", {
23989	version: "1.13.2",
23990	widgetEventPrefix: "drop",
23991	options: {
23992		accept: "*",
23993		addClasses: true,
23994		greedy: false,
23995		scope: "default",
23996		tolerance: "intersect",
23997
23998		// Callbacks
23999		activate: null,
24000		deactivate: null,
24001		drop: null,
24002		out: null,
24003		over: null
24004	},
24005	_create: function() {
24006
24007		var proportions,
24008			o = this.options,
24009			accept = o.accept;
24010
24011		this.isover = false;
24012		this.isout = true;
24013
24014		this.accept = typeof accept === "function" ? accept : function( d ) {
24015			return d.is( accept );
24016		};
24017
24018		this.proportions = function( /* valueToWrite */ ) {
24019			if ( arguments.length ) {
24020
24021				// Store the droppable's proportions
24022				proportions = arguments[ 0 ];
24023			} else {
24024
24025				// Retrieve or derive the droppable's proportions
24026				return proportions ?
24027					proportions :
24028					proportions = {
24029						width: this.element[ 0 ].offsetWidth,
24030						height: this.element[ 0 ].offsetHeight
24031					};
24032			}
24033		};
24034
24035		this._addToManager( o.scope );
24036
24037		if ( o.addClasses ) {
24038			this._addClass( "ui-droppable" );
24039		}
24040
24041	},
24042
24043	_addToManager: function( scope ) {
24044
24045		// Add the reference and positions to the manager
24046		$.ui.ddmanager.droppables[ scope ] = $.ui.ddmanager.droppables[ scope ] || [];
24047		$.ui.ddmanager.droppables[ scope ].push( this );
24048	},
24049
24050	_splice: function( drop ) {
24051		var i = 0;
24052		for ( ; i < drop.length; i++ ) {
24053			if ( drop[ i ] === this ) {
24054				drop.splice( i, 1 );
24055			}
24056		}
24057	},
24058
24059	_destroy: function() {
24060		var drop = $.ui.ddmanager.droppables[ this.options.scope ];
24061
24062		this._splice( drop );
24063	},
24064
24065	_setOption: function( key, value ) {
24066
24067		if ( key === "accept" ) {
24068			this.accept = typeof value === "function" ? value : function( d ) {
24069				return d.is( value );
24070			};
24071		} else if ( key === "scope" ) {
24072			var drop = $.ui.ddmanager.droppables[ this.options.scope ];
24073
24074			this._splice( drop );
24075			this._addToManager( value );
24076		}
24077
24078		this._super( key, value );
24079	},
24080
24081	_activate: function( event ) {
24082		var draggable = $.ui.ddmanager.current;
24083
24084		this._addActiveClass();
24085		if ( draggable ) {
24086			this._trigger( "activate", event, this.ui( draggable ) );
24087		}
24088	},
24089
24090	_deactivate: function( event ) {
24091		var draggable = $.ui.ddmanager.current;
24092
24093		this._removeActiveClass();
24094		if ( draggable ) {
24095			this._trigger( "deactivate", event, this.ui( draggable ) );
24096		}
24097	},
24098
24099	_over: function( event ) {
24100
24101		var draggable = $.ui.ddmanager.current;
24102
24103		// Bail if draggable and droppable are same element
24104		if ( !draggable || ( draggable.currentItem ||
24105				draggable.element )[ 0 ] === this.element[ 0 ] ) {
24106			return;
24107		}
24108
24109		if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem ||
24110				draggable.element ) ) ) {
24111			this._addHoverClass();
24112			this._trigger( "over", event, this.ui( draggable ) );
24113		}
24114
24115	},
24116
24117	_out: function( event ) {
24118
24119		var draggable = $.ui.ddmanager.current;
24120
24121		// Bail if draggable and droppable are same element
24122		if ( !draggable || ( draggable.currentItem ||
24123				draggable.element )[ 0 ] === this.element[ 0 ] ) {
24124			return;
24125		}
24126
24127		if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem ||
24128				draggable.element ) ) ) {
24129			this._removeHoverClass();
24130			this._trigger( "out", event, this.ui( draggable ) );
24131		}
24132
24133	},
24134
24135	_drop: function( event, custom ) {
24136
24137		var draggable = custom || $.ui.ddmanager.current,
24138			childrenIntersection = false;
24139
24140		// Bail if draggable and droppable are same element
24141		if ( !draggable || ( draggable.currentItem ||
24142				draggable.element )[ 0 ] === this.element[ 0 ] ) {
24143			return false;
24144		}
24145
24146		this.element
24147			.find( ":data(ui-droppable)" )
24148			.not( ".ui-draggable-dragging" )
24149			.each( function() {
24150				var inst = $( this ).droppable( "instance" );
24151				if (
24152					inst.options.greedy &&
24153					!inst.options.disabled &&
vendor: 4,579 bytes, lines 24154-24314
24154					inst.options.scope === draggable.options.scope &&
24155					inst.accept.call(
24156						inst.element[ 0 ], ( draggable.currentItem || draggable.element )
24157					) &&
24158					$.ui.intersect(
24159						draggable,
24160						$.extend( inst, { offset: inst.element.offset() } ),
24161						inst.options.tolerance, event
24162					)
24163				) {
24164					childrenIntersection = true;
24165					return false;
24166				}
24167			} );
24168		if ( childrenIntersection ) {
24169			return false;
24170		}
24171
24172		if ( this.accept.call( this.element[ 0 ],
24173				( draggable.currentItem || draggable.element ) ) ) {
24174			this._removeActiveClass();
24175			this._removeHoverClass();
24176
24177			this._trigger( "drop", event, this.ui( draggable ) );
24178			return this.element;
24179		}
24180
24181		return false;
24182
24183	},
24184
24185	ui: function( c ) {
24186		return {
24187			draggable: ( c.currentItem || c.element ),
24188			helper: c.helper,
24189			position: c.position,
24190			offset: c.positionAbs
24191		};
24192	},
24193
24194	// Extension points just to make backcompat sane and avoid duplicating logic
24195	// TODO: Remove in 1.14 along with call to it below
24196	_addHoverClass: function() {
24197		this._addClass( "ui-droppable-hover" );
24198	},
24199
24200	_removeHoverClass: function() {
24201		this._removeClass( "ui-droppable-hover" );
24202	},
24203
24204	_addActiveClass: function() {
24205		this._addClass( "ui-droppable-active" );
24206	},
24207
24208	_removeActiveClass: function() {
24209		this._removeClass( "ui-droppable-active" );
24210	}
24211} );
24212
24213$.ui.intersect = ( function() {
24214	function isOverAxis( x, reference, size ) {
24215		return ( x >= reference ) && ( x < ( reference + size ) );
24216	}
24217
24218	return function( draggable, droppable, toleranceMode, event ) {
24219
24220		if ( !droppable.offset ) {
24221			return false;
24222		}
24223
24224		var x1 = ( draggable.positionAbs ||
24225				draggable.position.absolute ).left + draggable.margins.left,
24226			y1 = ( draggable.positionAbs ||
24227				draggable.position.absolute ).top + draggable.margins.top,
24228			x2 = x1 + draggable.helperProportions.width,
24229			y2 = y1 + draggable.helperProportions.height,
24230			l = droppable.offset.left,
24231			t = droppable.offset.top,
24232			r = l + droppable.proportions().width,
24233			b = t + droppable.proportions().height;
24234
24235		switch ( toleranceMode ) {
24236		case "fit":
24237			return ( l <= x1 && x2 <= r && t <= y1 && y2 <= b );
24238		case "intersect":
24239			return ( l < x1 + ( draggable.helperProportions.width / 2 ) && // Right Half
24240				x2 - ( draggable.helperProportions.width / 2 ) < r && // Left Half
24241				t < y1 + ( draggable.helperProportions.height / 2 ) && // Bottom Half
24242				y2 - ( draggable.helperProportions.height / 2 ) < b ); // Top Half
24243		case "pointer":
24244			return isOverAxis( event.pageY, t, droppable.proportions().height ) &&
24245				isOverAxis( event.pageX, l, droppable.proportions().width );
24246		case "touch":
24247			return (
24248				( y1 >= t && y1 <= b ) || // Top edge touching
24249				( y2 >= t && y2 <= b ) || // Bottom edge touching
24250				( y1 < t && y2 > b ) // Surrounded vertically
24251			) && (
24252				( x1 >= l && x1 <= r ) || // Left edge touching
24253				( x2 >= l && x2 <= r ) || // Right edge touching
24254				( x1 < l && x2 > r ) // Surrounded horizontally
24255			);
24256		default:
24257			return false;
24258		}
24259	};
24260} )();
24261
24262/*
24263	This manager tracks offsets of draggables and droppables
24264*/
24265$.ui.ddmanager = {
24266	current: null,
24267	droppables: { "default": [] },
24268	prepareOffsets: function( t, event ) {
24269
24270		var i, j,
24271			m = $.ui.ddmanager.droppables[ t.options.scope ] || [],
24272			type = event ? event.type : null, // workaround for #2317
24273			list = ( t.currentItem || t.element ).find( ":data(ui-droppable)" ).addBack();
24274
24275		droppablesLoop: for ( i = 0; i < m.length; i++ ) {
24276
24277			// No disabled and non-accepted
24278			if ( m[ i ].options.disabled || ( t && !m[ i ].accept.call( m[ i ].element[ 0 ],
24279					( t.currentItem || t.element ) ) ) ) {
24280				continue;
24281			}
24282
24283			// Filter out elements in the current dragged item
24284			for ( j = 0; j < list.length; j++ ) {
24285				if ( list[ j ] === m[ i ].element[ 0 ] ) {
24286					m[ i ].proportions().height = 0;
24287					continue droppablesLoop;
24288				}
24289			}
24290
24291			m[ i ].visible = m[ i ].element.css( "display" ) !== "none";
24292			if ( !m[ i ].visible ) {
24293				continue;
24294			}
24295
24296			// Activate the droppable if used directly from draggables
24297			if ( type === "mousedown" ) {
24298				m[ i ]._activate.call( m[ i ], event );
24299			}
24300
24301			m[ i ].offset = m[ i ].element.offset();
24302			m[ i ].proportions( {
24303				width: m[ i ].element[ 0 ].offsetWidth,
24304				height: m[ i ].element[ 0 ].offsetHeight
24305			} );
24306
24307		}
24308
24309	},
24310	drop: function( draggable, event ) {
24311
24312		var dropped = false;
24313
24314		// Create a copy of the droppables in case the list changes during the drop (#9116)
vendor: 4,304 bytes, lines 24315-24457
24315		$.each( ( $.ui.ddmanager.droppables[ draggable.options.scope ] || [] ).slice(), function() {
24316
24317			if ( !this.options ) {
24318				return;
24319			}
24320			if ( !this.options.disabled && this.visible &&
24321					$.ui.intersect( draggable, this, this.options.tolerance, event ) ) {
24322				dropped = this._drop.call( this, event ) || dropped;
24323			}
24324
24325			if ( !this.options.disabled && this.visible && this.accept.call( this.element[ 0 ],
24326					( draggable.currentItem || draggable.element ) ) ) {
24327				this.isout = true;
24328				this.isover = false;
24329				this._deactivate.call( this, event );
24330			}
24331
24332		} );
24333		return dropped;
24334
24335	},
24336	dragStart: function( draggable, event ) {
24337
24338		// Listen for scrolling so that if the dragging causes scrolling the position of the
24339		// droppables can be recalculated (see #5003)
24340		draggable.element.parentsUntil( "body" ).on( "scroll.droppable", function() {
24341			if ( !draggable.options.refreshPositions ) {
24342				$.ui.ddmanager.prepareOffsets( draggable, event );
24343			}
24344		} );
24345	},
24346	drag: function( draggable, event ) {
24347
24348		// If you have a highly dynamic page, you might try this option. It renders positions
24349		// every time you move the mouse.
24350		if ( draggable.options.refreshPositions ) {
24351			$.ui.ddmanager.prepareOffsets( draggable, event );
24352		}
24353
24354		// Run through all droppables and check their positions based on specific tolerance options
24355		$.each( $.ui.ddmanager.droppables[ draggable.options.scope ] || [], function() {
24356
24357			if ( this.options.disabled || this.greedyChild || !this.visible ) {
24358				return;
24359			}
24360
24361			var parentInstance, scope, parent,
24362				intersects = $.ui.intersect( draggable, this, this.options.tolerance, event ),
24363				c = !intersects && this.isover ?
24364					"isout" :
24365					( intersects && !this.isover ? "isover" : null );
24366			if ( !c ) {
24367				return;
24368			}
24369
24370			if ( this.options.greedy ) {
24371
24372				// find droppable parents with same scope
24373				scope = this.options.scope;
24374				parent = this.element.parents( ":data(ui-droppable)" ).filter( function() {
24375					return $( this ).droppable( "instance" ).options.scope === scope;
24376				} );
24377
24378				if ( parent.length ) {
24379					parentInstance = $( parent[ 0 ] ).droppable( "instance" );
24380					parentInstance.greedyChild = ( c === "isover" );
24381				}
24382			}
24383
24384			// We just moved into a greedy child
24385			if ( parentInstance && c === "isover" ) {
24386				parentInstance.isover = false;
24387				parentInstance.isout = true;
24388				parentInstance._out.call( parentInstance, event );
24389			}
24390
24391			this[ c ] = true;
24392			this[ c === "isout" ? "isover" : "isout" ] = false;
24393			this[ c === "isover" ? "_over" : "_out" ].call( this, event );
24394
24395			// We just moved out of a greedy child
24396			if ( parentInstance && c === "isout" ) {
24397				parentInstance.isout = false;
24398				parentInstance.isover = true;
24399				parentInstance._over.call( parentInstance, event );
24400			}
24401		} );
24402
24403	},
24404	dragStop: function( draggable, event ) {
24405		draggable.element.parentsUntil( "body" ).off( "scroll.droppable" );
24406
24407		// Call prepareOffsets one final time since IE does not fire return scroll events when
24408		// overflow was caused by drag (see #5003)
24409		if ( !draggable.options.refreshPositions ) {
24410			$.ui.ddmanager.prepareOffsets( draggable, event );
24411		}
24412	}
24413};
24414
24415// DEPRECATED
24416// TODO: switch return back to widget declaration at top of file when this is removed
24417if ( $.uiBackCompat !== false ) {
24418
24419	// Backcompat for activeClass and hoverClass options
24420	$.widget( "ui.droppable", $.ui.droppable, {
24421		options: {
24422			hoverClass: false,
24423			activeClass: false
24424		},
24425		_addActiveClass: function() {
24426			this._super();
24427			if ( this.options.activeClass ) {
24428				this.element.addClass( this.options.activeClass );
24429			}
24430		},
24431		_removeActiveClass: function() {
24432			this._super();
24433			if ( this.options.activeClass ) {
24434				this.element.removeClass( this.options.activeClass );
24435			}
24436		},
24437		_addHoverClass: function() {
24438			this._super();
24439			if ( this.options.hoverClass ) {
24440				this.element.addClass( this.options.hoverClass );
24441			}
24442		},
24443		_removeHoverClass: function() {
24444			this._super();
24445			if ( this.options.hoverClass ) {
24446				this.element.removeClass( this.options.hoverClass );
24447			}
24448		}
24449	} );
24450}
24451
24452var widgetsDroppable = $.ui.droppable;
24453
24454
24455/*!
24456 * jQuery UI Progressbar 1.13.2
24457 * http://jqueryui.com
vendor: 12,231 bytes, lines 24458-24918
24458 *
24459 * Copyright jQuery Foundation and other contributors
24460 * Released under the MIT license.
24461 * http://jquery.org/license
24462 */
24463
24464//>>label: Progressbar
24465//>>group: Widgets
24466/* eslint-disable max-len */
24467//>>description: Displays a status indicator for loading state, standard percentage, and other progress indicators.
24468/* eslint-enable max-len */
24469//>>docs: http://api.jqueryui.com/progressbar/
24470//>>demos: http://jqueryui.com/progressbar/
24471//>>css.structure: ../../themes/base/core.css
24472//>>css.structure: ../../themes/base/progressbar.css
24473//>>css.theme: ../../themes/base/theme.css
24474
24475
24476var widgetsProgressbar = $.widget( "ui.progressbar", {
24477	version: "1.13.2",
24478	options: {
24479		classes: {
24480			"ui-progressbar": "ui-corner-all",
24481			"ui-progressbar-value": "ui-corner-left",
24482			"ui-progressbar-complete": "ui-corner-right"
24483		},
24484		max: 100,
24485		value: 0,
24486
24487		change: null,
24488		complete: null
24489	},
24490
24491	min: 0,
24492
24493	_create: function() {
24494
24495		// Constrain initial value
24496		this.oldValue = this.options.value = this._constrainedValue();
24497
24498		this.element.attr( {
24499
24500			// Only set static values; aria-valuenow and aria-valuemax are
24501			// set inside _refreshValue()
24502			role: "progressbar",
24503			"aria-valuemin": this.min
24504		} );
24505		this._addClass( "ui-progressbar", "ui-widget ui-widget-content" );
24506
24507		this.valueDiv = $( "<div>" ).appendTo( this.element );
24508		this._addClass( this.valueDiv, "ui-progressbar-value", "ui-widget-header" );
24509		this._refreshValue();
24510	},
24511
24512	_destroy: function() {
24513		this.element.removeAttr( "role aria-valuemin aria-valuemax aria-valuenow" );
24514
24515		this.valueDiv.remove();
24516	},
24517
24518	value: function( newValue ) {
24519		if ( newValue === undefined ) {
24520			return this.options.value;
24521		}
24522
24523		this.options.value = this._constrainedValue( newValue );
24524		this._refreshValue();
24525	},
24526
24527	_constrainedValue: function( newValue ) {
24528		if ( newValue === undefined ) {
24529			newValue = this.options.value;
24530		}
24531
24532		this.indeterminate = newValue === false;
24533
24534		// Sanitize value
24535		if ( typeof newValue !== "number" ) {
24536			newValue = 0;
24537		}
24538
24539		return this.indeterminate ? false :
24540			Math.min( this.options.max, Math.max( this.min, newValue ) );
24541	},
24542
24543	_setOptions: function( options ) {
24544
24545		// Ensure "value" option is set after other values (like max)
24546		var value = options.value;
24547		delete options.value;
24548
24549		this._super( options );
24550
24551		this.options.value = this._constrainedValue( value );
24552		this._refreshValue();
24553	},
24554
24555	_setOption: function( key, value ) {
24556		if ( key === "max" ) {
24557
24558			// Don't allow a max less than min
24559			value = Math.max( this.min, value );
24560		}
24561		this._super( key, value );
24562	},
24563
24564	_setOptionDisabled: function( value ) {
24565		this._super( value );
24566
24567		this.element.attr( "aria-disabled", value );
24568		this._toggleClass( null, "ui-state-disabled", !!value );
24569	},
24570
24571	_percentage: function() {
24572		return this.indeterminate ?
24573			100 :
24574			100 * ( this.options.value - this.min ) / ( this.options.max - this.min );
24575	},
24576
24577	_refreshValue: function() {
24578		var value = this.options.value,
24579			percentage = this._percentage();
24580
24581		this.valueDiv
24582			.toggle( this.indeterminate || value > this.min )
24583			.width( percentage.toFixed( 0 ) + "%" );
24584
24585		this
24586			._toggleClass( this.valueDiv, "ui-progressbar-complete", null,
24587				value === this.options.max )
24588			._toggleClass( "ui-progressbar-indeterminate", null, this.indeterminate );
24589
24590		if ( this.indeterminate ) {
24591			this.element.removeAttr( "aria-valuenow" );
24592			if ( !this.overlayDiv ) {
24593				this.overlayDiv = $( "<div>" ).appendTo( this.valueDiv );
24594				this._addClass( this.overlayDiv, "ui-progressbar-overlay" );
24595			}
24596		} else {
24597			this.element.attr( {
24598				"aria-valuemax": this.options.max,
24599				"aria-valuenow": value
24600			} );
24601			if ( this.overlayDiv ) {
24602				this.overlayDiv.remove();
24603				this.overlayDiv = null;
24604			}
24605		}
24606
24607		if ( this.oldValue !== value ) {
24608			this.oldValue = value;
24609			this._trigger( "change" );
24610		}
24611		if ( value === this.options.max ) {
24612			this._trigger( "complete" );
24613		}
24614	}
24615} );
24616
24617
24618/*!
24619 * jQuery UI Selectable 1.13.2
24620 * http://jqueryui.com
24621 *
24622 * Copyright jQuery Foundation and other contributors
24623 * Released under the MIT license.
24624 * http://jquery.org/license
24625 */
24626
24627//>>label: Selectable
24628//>>group: Interactions
24629//>>description: Allows groups of elements to be selected with the mouse.
24630//>>docs: http://api.jqueryui.com/selectable/
24631//>>demos: http://jqueryui.com/selectable/
24632//>>css.structure: ../../themes/base/selectable.css
24633
24634
24635var widgetsSelectable = $.widget( "ui.selectable", $.ui.mouse, {
24636	version: "1.13.2",
24637	options: {
24638		appendTo: "body",
24639		autoRefresh: true,
24640		distance: 0,
24641		filter: "*",
24642		tolerance: "touch",
24643
24644		// Callbacks
24645		selected: null,
24646		selecting: null,
24647		start: null,
24648		stop: null,
24649		unselected: null,
24650		unselecting: null
24651	},
24652	_create: function() {
24653		var that = this;
24654
24655		this._addClass( "ui-selectable" );
24656
24657		this.dragged = false;
24658
24659		// Cache selectee children based on filter
24660		this.refresh = function() {
24661			that.elementPos = $( that.element[ 0 ] ).offset();
24662			that.selectees = $( that.options.filter, that.element[ 0 ] );
24663			that._addClass( that.selectees, "ui-selectee" );
24664			that.selectees.each( function() {
24665				var $this = $( this ),
24666					selecteeOffset = $this.offset(),
24667					pos = {
24668						left: selecteeOffset.left - that.elementPos.left,
24669						top: selecteeOffset.top - that.elementPos.top
24670					};
24671				$.data( this, "selectable-item", {
24672					element: this,
24673					$element: $this,
24674					left: pos.left,
24675					top: pos.top,
24676					right: pos.left + $this.outerWidth(),
24677					bottom: pos.top + $this.outerHeight(),
24678					startselected: false,
24679					selected: $this.hasClass( "ui-selected" ),
24680					selecting: $this.hasClass( "ui-selecting" ),
24681					unselecting: $this.hasClass( "ui-unselecting" )
24682				} );
24683			} );
24684		};
24685		this.refresh();
24686
24687		this._mouseInit();
24688
24689		this.helper = $( "<div>" );
24690		this._addClass( this.helper, "ui-selectable-helper" );
24691	},
24692
24693	_destroy: function() {
24694		this.selectees.removeData( "selectable-item" );
24695		this._mouseDestroy();
24696	},
24697
24698	_mouseStart: function( event ) {
24699		var that = this,
24700			options = this.options;
24701
24702		this.opos = [ event.pageX, event.pageY ];
24703		this.elementPos = $( this.element[ 0 ] ).offset();
24704
24705		if ( this.options.disabled ) {
24706			return;
24707		}
24708
24709		this.selectees = $( options.filter, this.element[ 0 ] );
24710
24711		this._trigger( "start", event );
24712
24713		$( options.appendTo ).append( this.helper );
24714
24715		// position helper (lasso)
24716		this.helper.css( {
24717			"left": event.pageX,
24718			"top": event.pageY,
24719			"width": 0,
24720			"height": 0
24721		} );
24722
24723		if ( options.autoRefresh ) {
24724			this.refresh();
24725		}
24726
24727		this.selectees.filter( ".ui-selected" ).each( function() {
24728			var selectee = $.data( this, "selectable-item" );
24729			selectee.startselected = true;
24730			if ( !event.metaKey && !event.ctrlKey ) {
24731				that._removeClass( selectee.$element, "ui-selected" );
24732				selectee.selected = false;
24733				that._addClass( selectee.$element, "ui-unselecting" );
24734				selectee.unselecting = true;
24735
24736				// selectable UNSELECTING callback
24737				that._trigger( "unselecting", event, {
24738					unselecting: selectee.element
24739				} );
24740			}
24741		} );
24742
24743		$( event.target ).parents().addBack().each( function() {
24744			var doSelect,
24745				selectee = $.data( this, "selectable-item" );
24746			if ( selectee ) {
24747				doSelect = ( !event.metaKey && !event.ctrlKey ) ||
24748					!selectee.$element.hasClass( "ui-selected" );
24749				that._removeClass( selectee.$element, doSelect ? "ui-unselecting" : "ui-selected" )
24750					._addClass( selectee.$element, doSelect ? "ui-selecting" : "ui-unselecting" );
24751				selectee.unselecting = !doSelect;
24752				selectee.selecting = doSelect;
24753				selectee.selected = doSelect;
24754
24755				// selectable (UN)SELECTING callback
24756				if ( doSelect ) {
24757					that._trigger( "selecting", event, {
24758						selecting: selectee.element
24759					} );
24760				} else {
24761					that._trigger( "unselecting", event, {
24762						unselecting: selectee.element
24763					} );
24764				}
24765				return false;
24766			}
24767		} );
24768
24769	},
24770
24771	_mouseDrag: function( event ) {
24772
24773		this.dragged = true;
24774
24775		if ( this.options.disabled ) {
24776			return;
24777		}
24778
24779		var tmp,
24780			that = this,
24781			options = this.options,
24782			x1 = this.opos[ 0 ],
24783			y1 = this.opos[ 1 ],
24784			x2 = event.pageX,
24785			y2 = event.pageY;
24786
24787		if ( x1 > x2 ) {
24788			tmp = x2; x2 = x1; x1 = tmp;
24789		}
24790		if ( y1 > y2 ) {
24791			tmp = y2; y2 = y1; y1 = tmp;
24792		}
24793		this.helper.css( { left: x1, top: y1, width: x2 - x1, height: y2 - y1 } );
24794
24795		this.selectees.each( function() {
24796			var selectee = $.data( this, "selectable-item" ),
24797				hit = false,
24798				offset = {};
24799
24800			//prevent helper from being selected if appendTo: selectable
24801			if ( !selectee || selectee.element === that.element[ 0 ] ) {
24802				return;
24803			}
24804
24805			offset.left   = selectee.left   + that.elementPos.left;
24806			offset.right  = selectee.right  + that.elementPos.left;
24807			offset.top    = selectee.top    + that.elementPos.top;
24808			offset.bottom = selectee.bottom + that.elementPos.top;
24809
24810			if ( options.tolerance === "touch" ) {
24811				hit = ( !( offset.left > x2 || offset.right < x1 || offset.top > y2 ||
24812                    offset.bottom < y1 ) );
24813			} else if ( options.tolerance === "fit" ) {
24814				hit = ( offset.left > x1 && offset.right < x2 && offset.top > y1 &&
24815                    offset.bottom < y2 );
24816			}
24817
24818			if ( hit ) {
24819
24820				// SELECT
24821				if ( selectee.selected ) {
24822					that._removeClass( selectee.$element, "ui-selected" );
24823					selectee.selected = false;
24824				}
24825				if ( selectee.unselecting ) {
24826					that._removeClass( selectee.$element, "ui-unselecting" );
24827					selectee.unselecting = false;
24828				}
24829				if ( !selectee.selecting ) {
24830					that._addClass( selectee.$element, "ui-selecting" );
24831					selectee.selecting = true;
24832
24833					// selectable SELECTING callback
24834					that._trigger( "selecting", event, {
24835						selecting: selectee.element
24836					} );
24837				}
24838			} else {
24839
24840				// UNSELECT
24841				if ( selectee.selecting ) {
24842					if ( ( event.metaKey || event.ctrlKey ) && selectee.startselected ) {
24843						that._removeClass( selectee.$element, "ui-selecting" );
24844						selectee.selecting = false;
24845						that._addClass( selectee.$element, "ui-selected" );
24846						selectee.selected = true;
24847					} else {
24848						that._removeClass( selectee.$element, "ui-selecting" );
24849						selectee.selecting = false;
24850						if ( selectee.startselected ) {
24851							that._addClass( selectee.$element, "ui-unselecting" );
24852							selectee.unselecting = true;
24853						}
24854
24855						// selectable UNSELECTING callback
24856						that._trigger( "unselecting", event, {
24857							unselecting: selectee.element
24858						} );
24859					}
24860				}
24861				if ( selectee.selected ) {
24862					if ( !event.metaKey && !event.ctrlKey && !selectee.startselected ) {
24863						that._removeClass( selectee.$element, "ui-selected" );
24864						selectee.selected = false;
24865
24866						that._addClass( selectee.$element, "ui-unselecting" );
24867						selectee.unselecting = true;
24868
24869						// selectable UNSELECTING callback
24870						that._trigger( "unselecting", event, {
24871							unselecting: selectee.element
24872						} );
24873					}
24874				}
24875			}
24876		} );
24877
24878		return false;
24879	},
24880
24881	_mouseStop: function( event ) {
24882		var that = this;
24883
24884		this.dragged = false;
24885
24886		$( ".ui-unselecting", this.element[ 0 ] ).each( function() {
24887			var selectee = $.data( this, "selectable-item" );
24888			that._removeClass( selectee.$element, "ui-unselecting" );
24889			selectee.unselecting = false;
24890			selectee.startselected = false;
24891			that._trigger( "unselected", event, {
24892				unselected: selectee.element
24893			} );
24894		} );
24895		$( ".ui-selecting", this.element[ 0 ] ).each( function() {
24896			var selectee = $.data( this, "selectable-item" );
24897			that._removeClass( selectee.$element, "ui-selecting" )
24898				._addClass( selectee.$element, "ui-selected" );
24899			selectee.selecting = false;
24900			selectee.selected = true;
24901			selectee.startselected = true;
24902			that._trigger( "selected", event, {
24903				selected: selectee.element
24904			} );
24905		} );
24906		this._trigger( "stop", event );
24907
24908		this.helper.remove();
24909
24910		return false;
24911	}
24912
24913} );
24914
24915
24916/*!
24917 * jQuery UI Selectmenu 1.13.2
24918 * http://jqueryui.com
vendor: 20,756 bytes, lines 24919-25749
24919 *
24920 * Copyright jQuery Foundation and other contributors
24921 * Released under the MIT license.
24922 * http://jquery.org/license
24923 */
24924
24925//>>label: Selectmenu
24926//>>group: Widgets
24927/* eslint-disable max-len */
24928//>>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.
24929/* eslint-enable max-len */
24930//>>docs: http://api.jqueryui.com/selectmenu/
24931//>>demos: http://jqueryui.com/selectmenu/
24932//>>css.structure: ../../themes/base/core.css
24933//>>css.structure: ../../themes/base/selectmenu.css, ../../themes/base/button.css
24934//>>css.theme: ../../themes/base/theme.css
24935
24936
24937var widgetsSelectmenu = $.widget( "ui.selectmenu", [ $.ui.formResetMixin, {
24938	version: "1.13.2",
24939	defaultElement: "<select>",
24940	options: {
24941		appendTo: null,
24942		classes: {
24943			"ui-selectmenu-button-open": "ui-corner-top",
24944			"ui-selectmenu-button-closed": "ui-corner-all"
24945		},
24946		disabled: null,
24947		icons: {
24948			button: "ui-icon-triangle-1-s"
24949		},
24950		position: {
24951			my: "left top",
24952			at: "left bottom",
24953			collision: "none"
24954		},
24955		width: false,
24956
24957		// Callbacks
24958		change: null,
24959		close: null,
24960		focus: null,
24961		open: null,
24962		select: null
24963	},
24964
24965	_create: function() {
24966		var selectmenuId = this.element.uniqueId().attr( "id" );
24967		this.ids = {
24968			element: selectmenuId,
24969			button: selectmenuId + "-button",
24970			menu: selectmenuId + "-menu"
24971		};
24972
24973		this._drawButton();
24974		this._drawMenu();
24975		this._bindFormResetHandler();
24976
24977		this._rendered = false;
24978		this.menuItems = $();
24979	},
24980
24981	_drawButton: function() {
24982		var icon,
24983			that = this,
24984			item = this._parseOption(
24985				this.element.find( "option:selected" ),
24986				this.element[ 0 ].selectedIndex
24987			);
24988
24989		// Associate existing label with the new button
24990		this.labels = this.element.labels().attr( "for", this.ids.button );
24991		this._on( this.labels, {
24992			click: function( event ) {
24993				this.button.trigger( "focus" );
24994				event.preventDefault();
24995			}
24996		} );
24997
24998		// Hide original select element
24999		this.element.hide();
25000
25001		// Create button
25002		this.button = $( "<span>", {
25003			tabindex: this.options.disabled ? -1 : 0,
25004			id: this.ids.button,
25005			role: "combobox",
25006			"aria-expanded": "false",
25007			"aria-autocomplete": "list",
25008			"aria-owns": this.ids.menu,
25009			"aria-haspopup": "true",
25010			title: this.element.attr( "title" )
25011		} )
25012			.insertAfter( this.element );
25013
25014		this._addClass( this.button, "ui-selectmenu-button ui-selectmenu-button-closed",
25015			"ui-button ui-widget" );
25016
25017		icon = $( "<span>" ).appendTo( this.button );
25018		this._addClass( icon, "ui-selectmenu-icon", "ui-icon " + this.options.icons.button );
25019		this.buttonItem = this._renderButtonItem( item )
25020			.appendTo( this.button );
25021
25022		if ( this.options.width !== false ) {
25023			this._resizeButton();
25024		}
25025
25026		this._on( this.button, this._buttonEvents );
25027		this.button.one( "focusin", function() {
25028
25029			// Delay rendering the menu items until the button receives focus.
25030			// The menu may have already been rendered via a programmatic open.
25031			if ( !that._rendered ) {
25032				that._refreshMenu();
25033			}
25034		} );
25035	},
25036
25037	_drawMenu: function() {
25038		var that = this;
25039
25040		// Create menu
25041		this.menu = $( "<ul>", {
25042			"aria-hidden": "true",
25043			"aria-labelledby": this.ids.button,
25044			id: this.ids.menu
25045		} );
25046
25047		// Wrap menu
25048		this.menuWrap = $( "<div>" ).append( this.menu );
25049		this._addClass( this.menuWrap, "ui-selectmenu-menu", "ui-front" );
25050		this.menuWrap.appendTo( this._appendTo() );
25051
25052		// Initialize menu widget
25053		this.menuInstance = this.menu
25054			.menu( {
25055				classes: {
25056					"ui-menu": "ui-corner-bottom"
25057				},
25058				role: "listbox",
25059				select: function( event, ui ) {
25060					event.preventDefault();
25061
25062					// Support: IE8
25063					// If the item was selected via a click, the text selection
25064					// will be destroyed in IE
25065					that._setSelection();
25066
25067					that._select( ui.item.data( "ui-selectmenu-item" ), event );
25068				},
25069				focus: function( event, ui ) {
25070					var item = ui.item.data( "ui-selectmenu-item" );
25071
25072					// Prevent inital focus from firing and check if its a newly focused item
25073					if ( that.focusIndex != null && item.index !== that.focusIndex ) {
25074						that._trigger( "focus", event, { item: item } );
25075						if ( !that.isOpen ) {
25076							that._select( item, event );
25077						}
25078					}
25079					that.focusIndex = item.index;
25080
25081					that.button.attr( "aria-activedescendant",
25082						that.menuItems.eq( item.index ).attr( "id" ) );
25083				}
25084			} )
25085			.menu( "instance" );
25086
25087		// Don't close the menu on mouseleave
25088		this.menuInstance._off( this.menu, "mouseleave" );
25089
25090		// Cancel the menu's collapseAll on document click
25091		this.menuInstance._closeOnDocumentClick = function() {
25092			return false;
25093		};
25094
25095		// Selects often contain empty items, but never contain dividers
25096		this.menuInstance._isDivider = function() {
25097			return false;
25098		};
25099	},
25100
25101	refresh: function() {
25102		this._refreshMenu();
25103		this.buttonItem.replaceWith(
25104			this.buttonItem = this._renderButtonItem(
25105
25106				// Fall back to an empty object in case there are no options
25107				this._getSelectedItem().data( "ui-selectmenu-item" ) || {}
25108			)
25109		);
25110		if ( this.options.width === null ) {
25111			this._resizeButton();
25112		}
25113	},
25114
25115	_refreshMenu: function() {
25116		var item,
25117			options = this.element.find( "option" );
25118
25119		this.menu.empty();
25120
25121		this._parseOptions( options );
25122		this._renderMenu( this.menu, this.items );
25123
25124		this.menuInstance.refresh();
25125		this.menuItems = this.menu.find( "li" )
25126			.not( ".ui-selectmenu-optgroup" )
25127				.find( ".ui-menu-item-wrapper" );
25128
25129		this._rendered = true;
25130
25131		if ( !options.length ) {
25132			return;
25133		}
25134
25135		item = this._getSelectedItem();
25136
25137		// Update the menu to have the correct item focused
25138		this.menuInstance.focus( null, item );
25139		this._setAria( item.data( "ui-selectmenu-item" ) );
25140
25141		// Set disabled state
25142		this._setOption( "disabled", this.element.prop( "disabled" ) );
25143	},
25144
25145	open: function( event ) {
25146		if ( this.options.disabled ) {
25147			return;
25148		}
25149
25150		// If this is the first time the menu is being opened, render the items
25151		if ( !this._rendered ) {
25152			this._refreshMenu();
25153		} else {
25154
25155			// Menu clears focus on close, reset focus to selected item
25156			this._removeClass( this.menu.find( ".ui-state-active" ), null, "ui-state-active" );
25157			this.menuInstance.focus( null, this._getSelectedItem() );
25158		}
25159
25160		// If there are no options, don't open the menu
25161		if ( !this.menuItems.length ) {
25162			return;
25163		}
25164
25165		this.isOpen = true;
25166		this._toggleAttr();
25167		this._resizeMenu();
25168		this._position();
25169
25170		this._on( this.document, this._documentClick );
25171
25172		this._trigger( "open", event );
25173	},
25174
25175	_position: function() {
25176		this.menuWrap.position( $.extend( { of: this.button }, this.options.position ) );
25177	},
25178
25179	close: function( event ) {
25180		if ( !this.isOpen ) {
25181			return;
25182		}
25183
25184		this.isOpen = false;
25185		this._toggleAttr();
25186
25187		this.range = null;
25188		this._off( this.document );
25189
25190		this._trigger( "close", event );
25191	},
25192
25193	widget: function() {
25194		return this.button;
25195	},
25196
25197	menuWidget: function() {
25198		return this.menu;
25199	},
25200
25201	_renderButtonItem: function( item ) {
25202		var buttonItem = $( "<span>" );
25203
25204		this._setText( buttonItem, item.label );
25205		this._addClass( buttonItem, "ui-selectmenu-text" );
25206
25207		return buttonItem;
25208	},
25209
25210	_renderMenu: function( ul, items ) {
25211		var that = this,
25212			currentOptgroup = "";
25213
25214		$.each( items, function( index, item ) {
25215			var li;
25216
25217			if ( item.optgroup !== currentOptgroup ) {
25218				li = $( "<li>", {
25219					text: item.optgroup
25220				} );
25221				that._addClass( li, "ui-selectmenu-optgroup", "ui-menu-divider" +
25222					( item.element.parent( "optgroup" ).prop( "disabled" ) ?
25223						" ui-state-disabled" :
25224						"" ) );
25225
25226				li.appendTo( ul );
25227
25228				currentOptgroup = item.optgroup;
25229			}
25230
25231			that._renderItemData( ul, item );
25232		} );
25233	},
25234
25235	_renderItemData: function( ul, item ) {
25236		return this._renderItem( ul, item ).data( "ui-selectmenu-item", item );
25237	},
25238
25239	_renderItem: function( ul, item ) {
25240		var li = $( "<li>" ),
25241			wrapper = $( "<div>", {
25242				title: item.element.attr( "title" )
25243			} );
25244
25245		if ( item.disabled ) {
25246			this._addClass( li, null, "ui-state-disabled" );
25247		}
25248		this._setText( wrapper, item.label );
25249
25250		return li.append( wrapper ).appendTo( ul );
25251	},
25252
25253	_setText: function( element, value ) {
25254		if ( value ) {
25255			element.text( value );
25256		} else {
25257			element.html( "&#160;" );
25258		}
25259	},
25260
25261	_move: function( direction, event ) {
25262		var item, next,
25263			filter = ".ui-menu-item";
25264
25265		if ( this.isOpen ) {
25266			item = this.menuItems.eq( this.focusIndex ).parent( "li" );
25267		} else {
25268			item = this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( "li" );
25269			filter += ":not(.ui-state-disabled)";
25270		}
25271
25272		if ( direction === "first" || direction === "last" ) {
25273			next = item[ direction === "first" ? "prevAll" : "nextAll" ]( filter ).eq( -1 );
25274		} else {
25275			next = item[ direction + "All" ]( filter ).eq( 0 );
25276		}
25277
25278		if ( next.length ) {
25279			this.menuInstance.focus( event, next );
25280		}
25281	},
25282
25283	_getSelectedItem: function() {
25284		return this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( "li" );
25285	},
25286
25287	_toggle: function( event ) {
25288		this[ this.isOpen ? "close" : "open" ]( event );
25289	},
25290
25291	_setSelection: function() {
25292		var selection;
25293
25294		if ( !this.range ) {
25295			return;
25296		}
25297
25298		if ( window.getSelection ) {
25299			selection = window.getSelection();
25300			selection.removeAllRanges();
25301			selection.addRange( this.range );
25302
25303		// Support: IE8
25304		} else {
25305			this.range.select();
25306		}
25307
25308		// Support: IE
25309		// Setting the text selection kills the button focus in IE, but
25310		// restoring the focus doesn't kill the selection.
25311		this.button.trigger( "focus" );
25312	},
25313
25314	_documentClick: {
25315		mousedown: function( event ) {
25316			if ( !this.isOpen ) {
25317				return;
25318			}
25319
25320			if ( !$( event.target ).closest( ".ui-selectmenu-menu, #" +
25321				$.escapeSelector( this.ids.button ) ).length ) {
25322				this.close( event );
25323			}
25324		}
25325	},
25326
25327	_buttonEvents: {
25328
25329		// Prevent text selection from being reset when interacting with the selectmenu (#10144)
25330		mousedown: function() {
25331			var selection;
25332
25333			if ( window.getSelection ) {
25334				selection = window.getSelection();
25335				if ( selection.rangeCount ) {
25336					this.range = selection.getRangeAt( 0 );
25337				}
25338
25339			// Support: IE8
25340			} else {
25341				this.range = document.selection.createRange();
25342			}
25343		},
25344
25345		click: function( event ) {
25346			this._setSelection();
25347			this._toggle( event );
25348		},
25349
25350		keydown: function( event ) {
25351			var preventDefault = true;
25352			switch ( event.keyCode ) {
25353			case $.ui.keyCode.TAB:
25354			case $.ui.keyCode.ESCAPE:
25355				this.close( event );
25356				preventDefault = false;
25357				break;
25358			case $.ui.keyCode.ENTER:
25359				if ( this.isOpen ) {
25360					this._selectFocusedItem( event );
25361				}
25362				break;
25363			case $.ui.keyCode.UP:
25364				if ( event.altKey ) {
25365					this._toggle( event );
25366				} else {
25367					this._move( "prev", event );
25368				}
25369				break;
25370			case $.ui.keyCode.DOWN:
25371				if ( event.altKey ) {
25372					this._toggle( event );
25373				} else {
25374					this._move( "next", event );
25375				}
25376				break;
25377			case $.ui.keyCode.SPACE:
25378				if ( this.isOpen ) {
25379					this._selectFocusedItem( event );
25380				} else {
25381					this._toggle( event );
25382				}
25383				break;
25384			case $.ui.keyCode.LEFT:
25385				this._move( "prev", event );
25386				break;
25387			case $.ui.keyCode.RIGHT:
25388				this._move( "next", event );
25389				break;
25390			case $.ui.keyCode.HOME:
25391			case $.ui.keyCode.PAGE_UP:
25392				this._move( "first", event );
25393				break;
25394			case $.ui.keyCode.END:
25395			case $.ui.keyCode.PAGE_DOWN:
25396				this._move( "last", event );
25397				break;
25398			default:
25399				this.menu.trigger( event );
25400				preventDefault = false;
25401			}
25402
25403			if ( preventDefault ) {
25404				event.preventDefault();
25405			}
25406		}
25407	},
25408
25409	_selectFocusedItem: function( event ) {
25410		var item = this.menuItems.eq( this.focusIndex ).parent( "li" );
25411		if ( !item.hasClass( "ui-state-disabled" ) ) {
25412			this._select( item.data( "ui-selectmenu-item" ), event );
25413		}
25414	},
25415
25416	_select: function( item, event ) {
25417		var oldIndex = this.element[ 0 ].selectedIndex;
25418
25419		// Change native select element
25420		this.element[ 0 ].selectedIndex = item.index;
25421		this.buttonItem.replaceWith( this.buttonItem = this._renderButtonItem( item ) );
25422		this._setAria( item );
25423		this._trigger( "select", event, { item: item } );
25424
25425		if ( item.index !== oldIndex ) {
25426			this._trigger( "change", event, { item: item } );
25427		}
25428
25429		this.close( event );
25430	},
25431
25432	_setAria: function( item ) {
25433		var id = this.menuItems.eq( item.index ).attr( "id" );
25434
25435		this.button.attr( {
25436			"aria-labelledby": id,
25437			"aria-activedescendant": id
25438		} );
25439		this.menu.attr( "aria-activedescendant", id );
25440	},
25441
25442	_setOption: function( key, value ) {
25443		if ( key === "icons" ) {
25444			var icon = this.button.find( "span.ui-icon" );
25445			this._removeClass( icon, null, this.options.icons.button )
25446				._addClass( icon, null, value.button );
25447		}
25448
25449		this._super( key, value );
25450
25451		if ( key === "appendTo" ) {
25452			this.menuWrap.appendTo( this._appendTo() );
25453		}
25454
25455		if ( key === "width" ) {
25456			this._resizeButton();
25457		}
25458	},
25459
25460	_setOptionDisabled: function( value ) {
25461		this._super( value );
25462
25463		this.menuInstance.option( "disabled", value );
25464		this.button.attr( "aria-disabled", value );
25465		this._toggleClass( this.button, null, "ui-state-disabled", value );
25466
25467		this.element.prop( "disabled", value );
25468		if ( value ) {
25469			this.button.attr( "tabindex", -1 );
25470			this.close();
25471		} else {
25472			this.button.attr( "tabindex", 0 );
25473		}
25474	},
25475
25476	_appendTo: function() {
25477		var element = this.options.appendTo;
25478
25479		if ( element ) {
25480			element = element.jquery || element.nodeType ?
25481				$( element ) :
25482				this.document.find( element ).eq( 0 );
25483		}
25484
25485		if ( !element || !element[ 0 ] ) {
25486			element = this.element.closest( ".ui-front, dialog" );
25487		}
25488
25489		if ( !element.length ) {
25490			element = this.document[ 0 ].body;
25491		}
25492
25493		return element;
25494	},
25495
25496	_toggleAttr: function() {
25497		this.button.attr( "aria-expanded", this.isOpen );
25498
25499		// We can't use two _toggleClass() calls here, because we need to make sure
25500		// we always remove classes first and add them second, otherwise if both classes have the
25501		// same theme class, it will be removed after we add it.
25502		this._removeClass( this.button, "ui-selectmenu-button-" +
25503			( this.isOpen ? "closed" : "open" ) )
25504			._addClass( this.button, "ui-selectmenu-button-" +
25505				( this.isOpen ? "open" : "closed" ) )
25506			._toggleClass( this.menuWrap, "ui-selectmenu-open", null, this.isOpen );
25507
25508		this.menu.attr( "aria-hidden", !this.isOpen );
25509	},
25510
25511	_resizeButton: function() {
25512		var width = this.options.width;
25513
25514		// For `width: false`, just remove inline style and stop
25515		if ( width === false ) {
25516			this.button.css( "width", "" );
25517			return;
25518		}
25519
25520		// For `width: null`, match the width of the original element
25521		if ( width === null ) {
25522			width = this.element.show().outerWidth();
25523			this.element.hide();
25524		}
25525
25526		this.button.outerWidth( width );
25527	},
25528
25529	_resizeMenu: function() {
25530		this.menu.outerWidth( Math.max(
25531			this.button.outerWidth(),
25532
25533			// Support: IE10
25534			// IE10 wraps long text (possibly a rounding bug)
25535			// so we add 1px to avoid the wrapping
25536			this.menu.width( "" ).outerWidth() + 1
25537		) );
25538	},
25539
25540	_getCreateOptions: function() {
25541		var options = this._super();
25542
25543		options.disabled = this.element.prop( "disabled" );
25544
25545		return options;
25546	},
25547
25548	_parseOptions: function( options ) {
25549		var that = this,
25550			data = [];
25551		options.each( function( index, item ) {
25552			if ( item.hidden ) {
25553				return;
25554			}
25555
25556			data.push( that._parseOption( $( item ), index ) );
25557		} );
25558		this.items = data;
25559	},
25560
25561	_parseOption: function( option, index ) {
25562		var optgroup = option.parent( "optgroup" );
25563
25564		return {
25565			element: option,
25566			index: index,
25567			value: option.val(),
25568			label: option.text(),
25569			optgroup: optgroup.attr( "label" ) || "",
25570			disabled: optgroup.prop( "disabled" ) || option.prop( "disabled" )
25571		};
25572	},
25573
25574	_destroy: function() {
25575		this._unbindFormResetHandler();
25576		this.menuWrap.remove();
25577		this.button.remove();
25578		this.element.show();
25579		this.element.removeUniqueId();
25580		this.labels.attr( "for", this.ids.element );
25581	}
25582} ] );
25583
25584
25585/*!
25586 * jQuery UI Slider 1.13.2
25587 * http://jqueryui.com
25588 *
25589 * Copyright jQuery Foundation and other contributors
25590 * Released under the MIT license.
25591 * http://jquery.org/license
25592 */
25593
25594//>>label: Slider
25595//>>group: Widgets
25596//>>description: Displays a flexible slider with ranges and accessibility via keyboard.
25597//>>docs: http://api.jqueryui.com/slider/
25598//>>demos: http://jqueryui.com/slider/
25599//>>css.structure: ../../themes/base/core.css
25600//>>css.structure: ../../themes/base/slider.css
25601//>>css.theme: ../../themes/base/theme.css
25602
25603
25604var widgetsSlider = $.widget( "ui.slider", $.ui.mouse, {
25605	version: "1.13.2",
25606	widgetEventPrefix: "slide",
25607
25608	options: {
25609		animate: false,
25610		classes: {
25611			"ui-slider": "ui-corner-all",
25612			"ui-slider-handle": "ui-corner-all",
25613
25614			// Note: ui-widget-header isn't the most fittingly semantic framework class for this
25615			// element, but worked best visually with a variety of themes
25616			"ui-slider-range": "ui-corner-all ui-widget-header"
25617		},
25618		distance: 0,
25619		max: 100,
25620		min: 0,
25621		orientation: "horizontal",
25622		range: false,
25623		step: 1,
25624		value: 0,
25625		values: null,
25626
25627		// Callbacks
25628		change: null,
25629		slide: null,
25630		start: null,
25631		stop: null
25632	},
25633
25634	// Number of pages in a slider
25635	// (how many times can you page up/down to go through the whole range)
25636	numPages: 5,
25637
25638	_create: function() {
25639		this._keySliding = false;
25640		this._mouseSliding = false;
25641		this._animateOff = true;
25642		this._handleIndex = null;
25643		this._detectOrientation();
25644		this._mouseInit();
25645		this._calculateNewMax();
25646
25647		this._addClass( "ui-slider ui-slider-" + this.orientation,
25648			"ui-widget ui-widget-content" );
25649
25650		this._refresh();
25651
25652		this._animateOff = false;
25653	},
25654
25655	_refresh: function() {
25656		this._createRange();
25657		this._createHandles();
25658		this._setupEvents();
25659		this._refreshValue();
25660	},
25661
25662	_createHandles: function() {
25663		var i, handleCount,
25664			options = this.options,
25665			existingHandles = this.element.find( ".ui-slider-handle" ),
25666			handle = "<span tabindex='0'></span>",
25667			handles = [];
25668
25669		handleCount = ( options.values && options.values.length ) || 1;
25670
25671		if ( existingHandles.length > handleCount ) {
25672			existingHandles.slice( handleCount ).remove();
25673			existingHandles = existingHandles.slice( 0, handleCount );
25674		}
25675
25676		for ( i = existingHandles.length; i < handleCount; i++ ) {
25677			handles.push( handle );
25678		}
25679
25680		this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) );
25681
25682		this._addClass( this.handles, "ui-slider-handle", "ui-state-default" );
25683
25684		this.handle = this.handles.eq( 0 );
25685
25686		this.handles.each( function( i ) {
25687			$( this )
25688				.data( "ui-slider-handle-index", i )
25689				.attr( "tabIndex", 0 );
25690		} );
25691	},
25692
25693	_createRange: function() {
25694		var options = this.options;
25695
25696		if ( options.range ) {
25697			if ( options.range === true ) {
25698				if ( !options.values ) {
25699					options.values = [ this._valueMin(), this._valueMin() ];
25700				} else if ( options.values.length && options.values.length !== 2 ) {
25701					options.values = [ options.values[ 0 ], options.values[ 0 ] ];
25702				} else if ( Array.isArray( options.values ) ) {
25703					options.values = options.values.slice( 0 );
25704				}
25705			}
25706
25707			if ( !this.range || !this.range.length ) {
25708				this.range = $( "<div>" )
25709					.appendTo( this.element );
25710
25711				this._addClass( this.range, "ui-slider-range" );
25712			} else {
25713				this._removeClass( this.range, "ui-slider-range-min ui-slider-range-max" );
25714
25715				// Handle range switching from true to min/max
25716				this.range.css( {
25717					"left": "",
25718					"bottom": ""
25719				} );
25720			}
25721			if ( options.range === "min" || options.range === "max" ) {
25722				this._addClass( this.range, "ui-slider-range-" + options.range );
25723			}
25724		} else {
25725			if ( this.range ) {
25726				this.range.remove();
25727			}
25728			this.range = null;
25729		}
25730	},
25731
25732	_setupEvents: function() {
25733		this._off( this.handles );
25734		this._on( this.handles, this._handleEvents );
25735		this._hoverable( this.handles );
25736		this._focusable( this.handles );
25737	},
25738
25739	_destroy: function() {
25740		this.handles.remove();
25741		if ( this.range ) {
25742			this.range.remove();
25743		}
25744
25745		this._mouseDestroy();
25746	},
25747
25748	_mouseCapture: function( event ) {
25749		var position, normValue, distance, closestHandle, index, allowed, offset, mou
vendor: 22,163 bytes, lines 25749-26575
25749seOverHandle,
25750			that = this,
25751			o = this.options;
25752
25753		if ( o.disabled ) {
25754			return false;
25755		}
25756
25757		this.elementSize = {
25758			width: this.element.outerWidth(),
25759			height: this.element.outerHeight()
25760		};
25761		this.elementOffset = this.element.offset();
25762
25763		position = { x: event.pageX, y: event.pageY };
25764		normValue = this._normValueFromMouse( position );
25765		distance = this._valueMax() - this._valueMin() + 1;
25766		this.handles.each( function( i ) {
25767			var thisDistance = Math.abs( normValue - that.values( i ) );
25768			if ( ( distance > thisDistance ) ||
25769				( distance === thisDistance &&
25770					( i === that._lastChangedValue || that.values( i ) === o.min ) ) ) {
25771				distance = thisDistance;
25772				closestHandle = $( this );
25773				index = i;
25774			}
25775		} );
25776
25777		allowed = this._start( event, index );
25778		if ( allowed === false ) {
25779			return false;
25780		}
25781		this._mouseSliding = true;
25782
25783		this._handleIndex = index;
25784
25785		this._addClass( closestHandle, null, "ui-state-active" );
25786		closestHandle.trigger( "focus" );
25787
25788		offset = closestHandle.offset();
25789		mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" );
25790		this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
25791			left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
25792			top: event.pageY - offset.top -
25793				( closestHandle.height() / 2 ) -
25794				( parseInt( closestHandle.css( "borderTopWidth" ), 10 ) || 0 ) -
25795				( parseInt( closestHandle.css( "borderBottomWidth" ), 10 ) || 0 ) +
25796				( parseInt( closestHandle.css( "marginTop" ), 10 ) || 0 )
25797		};
25798
25799		if ( !this.handles.hasClass( "ui-state-hover" ) ) {
25800			this._slide( event, index, normValue );
25801		}
25802		this._animateOff = true;
25803		return true;
25804	},
25805
25806	_mouseStart: function() {
25807		return true;
25808	},
25809
25810	_mouseDrag: function( event ) {
25811		var position = { x: event.pageX, y: event.pageY },
25812			normValue = this._normValueFromMouse( position );
25813
25814		this._slide( event, this._handleIndex, normValue );
25815
25816		return false;
25817	},
25818
25819	_mouseStop: function( event ) {
25820		this._removeClass( this.handles, null, "ui-state-active" );
25821		this._mouseSliding = false;
25822
25823		this._stop( event, this._handleIndex );
25824		this._change( event, this._handleIndex );
25825
25826		this._handleIndex = null;
25827		this._clickOffset = null;
25828		this._animateOff = false;
25829
25830		return false;
25831	},
25832
25833	_detectOrientation: function() {
25834		this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
25835	},
25836
25837	_normValueFromMouse: function( position ) {
25838		var pixelTotal,
25839			pixelMouse,
25840			percentMouse,
25841			valueTotal,
25842			valueMouse;
25843
25844		if ( this.orientation === "horizontal" ) {
25845			pixelTotal = this.elementSize.width;
25846			pixelMouse = position.x - this.elementOffset.left -
25847				( this._clickOffset ? this._clickOffset.left : 0 );
25848		} else {
25849			pixelTotal = this.elementSize.height;
25850			pixelMouse = position.y - this.elementOffset.top -
25851				( this._clickOffset ? this._clickOffset.top : 0 );
25852		}
25853
25854		percentMouse = ( pixelMouse / pixelTotal );
25855		if ( percentMouse > 1 ) {
25856			percentMouse = 1;
25857		}
25858		if ( percentMouse < 0 ) {
25859			percentMouse = 0;
25860		}
25861		if ( this.orientation === "vertical" ) {
25862			percentMouse = 1 - percentMouse;
25863		}
25864
25865		valueTotal = this._valueMax() - this._valueMin();
25866		valueMouse = this._valueMin() + percentMouse * valueTotal;
25867
25868		return this._trimAlignValue( valueMouse );
25869	},
25870
25871	_uiHash: function( index, value, values ) {
25872		var uiHash = {
25873			handle: this.handles[ index ],
25874			handleIndex: index,
25875			value: value !== undefined ? value : this.value()
25876		};
25877
25878		if ( this._hasMultipleValues() ) {
25879			uiHash.value = value !== undefined ? value : this.values( index );
25880			uiHash.values = values || this.values();
25881		}
25882
25883		return uiHash;
25884	},
25885
25886	_hasMultipleValues: function() {
25887		return this.options.values && this.options.values.length;
25888	},
25889
25890	_start: function( event, index ) {
25891		return this._trigger( "start", event, this._uiHash( index ) );
25892	},
25893
25894	_slide: function( event, index, newVal ) {
25895		var allowed, otherVal,
25896			currentValue = this.value(),
25897			newValues = this.values();
25898
25899		if ( this._hasMultipleValues() ) {
25900			otherVal = this.values( index ? 0 : 1 );
25901			currentValue = this.values( index );
25902
25903			if ( this.options.values.length === 2 && this.options.range === true ) {
25904				newVal =  index === 0 ? Math.min( otherVal, newVal ) : Math.max( otherVal, newVal );
25905			}
25906
25907			newValues[ index ] = newVal;
25908		}
25909
25910		if ( newVal === currentValue ) {
25911			return;
25912		}
25913
25914		allowed = this._trigger( "slide", event, this._uiHash( index, newVal, newValues ) );
25915
25916		// A slide can be canceled by returning false from the slide callback
25917		if ( allowed === false ) {
25918			return;
25919		}
25920
25921		if ( this._hasMultipleValues() ) {
25922			this.values( index, newVal );
25923		} else {
25924			this.value( newVal );
25925		}
25926	},
25927
25928	_stop: function( event, index ) {
25929		this._trigger( "stop", event, this._uiHash( index ) );
25930	},
25931
25932	_change: function( event, index ) {
25933		if ( !this._keySliding && !this._mouseSliding ) {
25934
25935			//store the last changed value index for reference when handles overlap
25936			this._lastChangedValue = index;
25937			this._trigger( "change", event, this._uiHash( index ) );
25938		}
25939	},
25940
25941	value: function( newValue ) {
25942		if ( arguments.length ) {
25943			this.options.value = this._trimAlignValue( newValue );
25944			this._refreshValue();
25945			this._change( null, 0 );
25946			return;
25947		}
25948
25949		return this._value();
25950	},
25951
25952	values: function( index, newValue ) {
25953		var vals,
25954			newValues,
25955			i;
25956
25957		if ( arguments.length > 1 ) {
25958			this.options.values[ index ] = this._trimAlignValue( newValue );
25959			this._refreshValue();
25960			this._change( null, index );
25961			return;
25962		}
25963
25964		if ( arguments.length ) {
25965			if ( Array.isArray( arguments[ 0 ] ) ) {
25966				vals = this.options.values;
25967				newValues = arguments[ 0 ];
25968				for ( i = 0; i < vals.length; i += 1 ) {
25969					vals[ i ] = this._trimAlignValue( newValues[ i ] );
25970					this._change( null, i );
25971				}
25972				this._refreshValue();
25973			} else {
25974				if ( this._hasMultipleValues() ) {
25975					return this._values( index );
25976				} else {
25977					return this.value();
25978				}
25979			}
25980		} else {
25981			return this._values();
25982		}
25983	},
25984
25985	_setOption: function( key, value ) {
25986		var i,
25987			valsLength = 0;
25988
25989		if ( key === "range" && this.options.range === true ) {
25990			if ( value === "min" ) {
25991				this.options.value = this._values( 0 );
25992				this.options.values = null;
25993			} else if ( value === "max" ) {
25994				this.options.value = this._values( this.options.values.length - 1 );
25995				this.options.values = null;
25996			}
25997		}
25998
25999		if ( Array.isArray( this.options.values ) ) {
26000			valsLength = this.options.values.length;
26001		}
26002
26003		this._super( key, value );
26004
26005		switch ( key ) {
26006			case "orientation":
26007				this._detectOrientation();
26008				this._removeClass( "ui-slider-horizontal ui-slider-vertical" )
26009					._addClass( "ui-slider-" + this.orientation );
26010				this._refreshValue();
26011				if ( this.options.range ) {
26012					this._refreshRange( value );
26013				}
26014
26015				// Reset positioning from previous orientation
26016				this.handles.css( value === "horizontal" ? "bottom" : "left", "" );
26017				break;
26018			case "value":
26019				this._animateOff = true;
26020				this._refreshValue();
26021				this._change( null, 0 );
26022				this._animateOff = false;
26023				break;
26024			case "values":
26025				this._animateOff = true;
26026				this._refreshValue();
26027
26028				// Start from the last handle to prevent unreachable handles (#9046)
26029				for ( i = valsLength - 1; i >= 0; i-- ) {
26030					this._change( null, i );
26031				}
26032				this._animateOff = false;
26033				break;
26034			case "step":
26035			case "min":
26036			case "max":
26037				this._animateOff = true;
26038				this._calculateNewMax();
26039				this._refreshValue();
26040				this._animateOff = false;
26041				break;
26042			case "range":
26043				this._animateOff = true;
26044				this._refresh();
26045				this._animateOff = false;
26046				break;
26047		}
26048	},
26049
26050	_setOptionDisabled: function( value ) {
26051		this._super( value );
26052
26053		this._toggleClass( null, "ui-state-disabled", !!value );
26054	},
26055
26056	//internal value getter
26057	// _value() returns value trimmed by min and max, aligned by step
26058	_value: function() {
26059		var val = this.options.value;
26060		val = this._trimAlignValue( val );
26061
26062		return val;
26063	},
26064
26065	//internal values getter
26066	// _values() returns array of values trimmed by min and max, aligned by step
26067	// _values( index ) returns single value trimmed by min and max, aligned by step
26068	_values: function( index ) {
26069		var val,
26070			vals,
26071			i;
26072
26073		if ( arguments.length ) {
26074			val = this.options.values[ index ];
26075			val = this._trimAlignValue( val );
26076
26077			return val;
26078		} else if ( this._hasMultipleValues() ) {
26079
26080			// .slice() creates a copy of the array
26081			// this copy gets trimmed by min and max and then returned
26082			vals = this.options.values.slice();
26083			for ( i = 0; i < vals.length; i += 1 ) {
26084				vals[ i ] = this._trimAlignValue( vals[ i ] );
26085			}
26086
26087			return vals;
26088		} else {
26089			return [];
26090		}
26091	},
26092
26093	// Returns the step-aligned value that val is closest to, between (inclusive) min and max
26094	_trimAlignValue: function( val ) {
26095		if ( val <= this._valueMin() ) {
26096			return this._valueMin();
26097		}
26098		if ( val >= this._valueMax() ) {
26099			return this._valueMax();
26100		}
26101		var step = ( this.options.step > 0 ) ? this.options.step : 1,
26102			valModStep = ( val - this._valueMin() ) % step,
26103			alignValue = val - valModStep;
26104
26105		if ( Math.abs( valModStep ) * 2 >= step ) {
26106			alignValue += ( valModStep > 0 ) ? step : ( -step );
26107		}
26108
26109		// Since JavaScript has problems with large floats, round
26110		// the final value to 5 digits after the decimal point (see #4124)
26111		return parseFloat( alignValue.toFixed( 5 ) );
26112	},
26113
26114	_calculateNewMax: function() {
26115		var max = this.options.max,
26116			min = this._valueMin(),
26117			step = this.options.step,
26118			aboveMin = Math.round( ( max - min ) / step ) * step;
26119		max = aboveMin + min;
26120		if ( max > this.options.max ) {
26121
26122			//If max is not divisible by step, rounding off may increase its value
26123			max -= step;
26124		}
26125		this.max = parseFloat( max.toFixed( this._precision() ) );
26126	},
26127
26128	_precision: function() {
26129		var precision = this._precisionOf( this.options.step );
26130		if ( this.options.min !== null ) {
26131			precision = Math.max( precision, this._precisionOf( this.options.min ) );
26132		}
26133		return precision;
26134	},
26135
26136	_precisionOf: function( num ) {
26137		var str = num.toString(),
26138			decimal = str.indexOf( "." );
26139		return decimal === -1 ? 0 : str.length - decimal - 1;
26140	},
26141
26142	_valueMin: function() {
26143		return this.options.min;
26144	},
26145
26146	_valueMax: function() {
26147		return this.max;
26148	},
26149
26150	_refreshRange: function( orientation ) {
26151		if ( orientation === "vertical" ) {
26152			this.range.css( { "width": "", "left": "" } );
26153		}
26154		if ( orientation === "horizontal" ) {
26155			this.range.css( { "height": "", "bottom": "" } );
26156		}
26157	},
26158
26159	_refreshValue: function() {
26160		var lastValPercent, valPercent, value, valueMin, valueMax,
26161			oRange = this.options.range,
26162			o = this.options,
26163			that = this,
26164			animate = ( !this._animateOff ) ? o.animate : false,
26165			_set = {};
26166
26167		if ( this._hasMultipleValues() ) {
26168			this.handles.each( function( i ) {
26169				valPercent = ( that.values( i ) - that._valueMin() ) / ( that._valueMax() -
26170					that._valueMin() ) * 100;
26171				_set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
26172				$( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
26173				if ( that.options.range === true ) {
26174					if ( that.orientation === "horizontal" ) {
26175						if ( i === 0 ) {
26176							that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
26177								left: valPercent + "%"
26178							}, o.animate );
26179						}
26180						if ( i === 1 ) {
26181							that.range[ animate ? "animate" : "css" ]( {
26182								width: ( valPercent - lastValPercent ) + "%"
26183							}, {
26184								queue: false,
26185								duration: o.animate
26186							} );
26187						}
26188					} else {
26189						if ( i === 0 ) {
26190							that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
26191								bottom: ( valPercent ) + "%"
26192							}, o.animate );
26193						}
26194						if ( i === 1 ) {
26195							that.range[ animate ? "animate" : "css" ]( {
26196								height: ( valPercent - lastValPercent ) + "%"
26197							}, {
26198								queue: false,
26199								duration: o.animate
26200							} );
26201						}
26202					}
26203				}
26204				lastValPercent = valPercent;
26205			} );
26206		} else {
26207			value = this.value();
26208			valueMin = this._valueMin();
26209			valueMax = this._valueMax();
26210			valPercent = ( valueMax !== valueMin ) ?
26211					( value - valueMin ) / ( valueMax - valueMin ) * 100 :
26212					0;
26213			_set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
26214			this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
26215
26216			if ( oRange === "min" && this.orientation === "horizontal" ) {
26217				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
26218					width: valPercent + "%"
26219				}, o.animate );
26220			}
26221			if ( oRange === "max" && this.orientation === "horizontal" ) {
26222				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
26223					width: ( 100 - valPercent ) + "%"
26224				}, o.animate );
26225			}
26226			if ( oRange === "min" && this.orientation === "vertical" ) {
26227				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
26228					height: valPercent + "%"
26229				}, o.animate );
26230			}
26231			if ( oRange === "max" && this.orientation === "vertical" ) {
26232				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
26233					height: ( 100 - valPercent ) + "%"
26234				}, o.animate );
26235			}
26236		}
26237	},
26238
26239	_handleEvents: {
26240		keydown: function( event ) {
26241			var allowed, curVal, newVal, step,
26242				index = $( event.target ).data( "ui-slider-handle-index" );
26243
26244			switch ( event.keyCode ) {
26245				case $.ui.keyCode.HOME:
26246				case $.ui.keyCode.END:
26247				case $.ui.keyCode.PAGE_UP:
26248				case $.ui.keyCode.PAGE_DOWN:
26249				case $.ui.keyCode.UP:
26250				case $.ui.keyCode.RIGHT:
26251				case $.ui.keyCode.DOWN:
26252				case $.ui.keyCode.LEFT:
26253					event.preventDefault();
26254					if ( !this._keySliding ) {
26255						this._keySliding = true;
26256						this._addClass( $( event.target ), null, "ui-state-active" );
26257						allowed = this._start( event, index );
26258						if ( allowed === false ) {
26259							return;
26260						}
26261					}
26262					break;
26263			}
26264
26265			step = this.options.step;
26266			if ( this._hasMultipleValues() ) {
26267				curVal = newVal = this.values( index );
26268			} else {
26269				curVal = newVal = this.value();
26270			}
26271
26272			switch ( event.keyCode ) {
26273				case $.ui.keyCode.HOME:
26274					newVal = this._valueMin();
26275					break;
26276				case $.ui.keyCode.END:
26277					newVal = this._valueMax();
26278					break;
26279				case $.ui.keyCode.PAGE_UP:
26280					newVal = this._trimAlignValue(
26281						curVal + ( ( this._valueMax() - this._valueMin() ) / this.numPages )
26282					);
26283					break;
26284				case $.ui.keyCode.PAGE_DOWN:
26285					newVal = this._trimAlignValue(
26286						curVal - ( ( this._valueMax() - this._valueMin() ) / this.numPages ) );
26287					break;
26288				case $.ui.keyCode.UP:
26289				case $.ui.keyCode.RIGHT:
26290					if ( curVal === this._valueMax() ) {
26291						return;
26292					}
26293					newVal = this._trimAlignValue( curVal + step );
26294					break;
26295				case $.ui.keyCode.DOWN:
26296				case $.ui.keyCode.LEFT:
26297					if ( curVal === this._valueMin() ) {
26298						return;
26299					}
26300					newVal = this._trimAlignValue( curVal - step );
26301					break;
26302			}
26303
26304			this._slide( event, index, newVal );
26305		},
26306		keyup: function( event ) {
26307			var index = $( event.target ).data( "ui-slider-handle-index" );
26308
26309			if ( this._keySliding ) {
26310				this._keySliding = false;
26311				this._stop( event, index );
26312				this._change( event, index );
26313				this._removeClass( $( event.target ), null, "ui-state-active" );
26314			}
26315		}
26316	}
26317} );
26318
26319
26320/*!
26321 * jQuery UI Sortable 1.13.2
26322 * http://jqueryui.com
26323 *
26324 * Copyright jQuery Foundation and other contributors
26325 * Released under the MIT license.
26326 * http://jquery.org/license
26327 */
26328
26329//>>label: Sortable
26330//>>group: Interactions
26331//>>description: Enables items in a list to be sorted using the mouse.
26332//>>docs: http://api.jqueryui.com/sortable/
26333//>>demos: http://jqueryui.com/sortable/
26334//>>css.structure: ../../themes/base/sortable.css
26335
26336
26337var widgetsSortable = $.widget( "ui.sortable", $.ui.mouse, {
26338	version: "1.13.2",
26339	widgetEventPrefix: "sort",
26340	ready: false,
26341	options: {
26342		appendTo: "parent",
26343		axis: false,
26344		connectWith: false,
26345		containment: false,
26346		cursor: "auto",
26347		cursorAt: false,
26348		dropOnEmpty: true,
26349		forcePlaceholderSize: false,
26350		forceHelperSize: false,
26351		grid: false,
26352		handle: false,
26353		helper: "original",
26354		items: "> *",
26355		opacity: false,
26356		placeholder: false,
26357		revert: false,
26358		scroll: true,
26359		scrollSensitivity: 20,
26360		scrollSpeed: 20,
26361		scope: "default",
26362		tolerance: "intersect",
26363		zIndex: 1000,
26364
26365		// Callbacks
26366		activate: null,
26367		beforeStop: null,
26368		change: null,
26369		deactivate: null,
26370		out: null,
26371		over: null,
26372		receive: null,
26373		remove: null,
26374		sort: null,
26375		start: null,
26376		stop: null,
26377		update: null
26378	},
26379
26380	_isOverAxis: function( x, reference, size ) {
26381		return ( x >= reference ) && ( x < ( reference + size ) );
26382	},
26383
26384	_isFloating: function( item ) {
26385		return ( /left|right/ ).test( item.css( "float" ) ) ||
26386			( /inline|table-cell/ ).test( item.css( "display" ) );
26387	},
26388
26389	_create: function() {
26390		this.containerCache = {};
26391		this._addClass( "ui-sortable" );
26392
26393		//Get the items
26394		this.refresh();
26395
26396		//Let's determine the parent's offset
26397		this.offset = this.element.offset();
26398
26399		//Initialize mouse events for interaction
26400		this._mouseInit();
26401
26402		this._setHandleClassName();
26403
26404		//We're ready to go
26405		this.ready = true;
26406
26407	},
26408
26409	_setOption: function( key, value ) {
26410		this._super( key, value );
26411
26412		if ( key === "handle" ) {
26413			this._setHandleClassName();
26414		}
26415	},
26416
26417	_setHandleClassName: function() {
26418		var that = this;
26419		this._removeClass( this.element.find( ".ui-sortable-handle" ), "ui-sortable-handle" );
26420		$.each( this.items, function() {
26421			that._addClass(
26422				this.instance.options.handle ?
26423					this.item.find( this.instance.options.handle ) :
26424					this.item,
26425				"ui-sortable-handle"
26426			);
26427		} );
26428	},
26429
26430	_destroy: function() {
26431		this._mouseDestroy();
26432
26433		for ( var i = this.items.length - 1; i >= 0; i-- ) {
26434			this.items[ i ].item.removeData( this.widgetName + "-item" );
26435		}
26436
26437		return this;
26438	},
26439
26440	_mouseCapture: function( event, overrideHandle ) {
26441		var currentItem = null,
26442			validHandle = false,
26443			that = this;
26444
26445		if ( this.reverting ) {
26446			return false;
26447		}
26448
26449		if ( this.options.disabled || this.options.type === "static" ) {
26450			return false;
26451		}
26452
26453		//We have to refresh the items data once first
26454		this._refreshItems( event );
26455
26456		//Find out if the clicked node (or one of its parents) is a actual item in this.items
26457		$( event.target ).parents().each( function() {
26458			if ( $.data( this, that.widgetName + "-item" ) === that ) {
26459				currentItem = $( this );
26460				return false;
26461			}
26462		} );
26463		if ( $.data( event.target, that.widgetName + "-item" ) === that ) {
26464			currentItem = $( event.target );
26465		}
26466
26467		if ( !currentItem ) {
26468			return false;
26469		}
26470		if ( this.options.handle && !overrideHandle ) {
26471			$( this.options.handle, currentItem ).find( "*" ).addBack().each( function() {
26472				if ( this === event.target ) {
26473					validHandle = true;
26474				}
26475			} );
26476			if ( !validHandle ) {
26477				return false;
26478			}
26479		}
26480
26481		this.currentItem = currentItem;
26482		this._removeCurrentsFromItems();
26483		return true;
26484
26485	},
26486
26487	_mouseStart: function( event, overrideHandle, noActivation ) {
26488
26489		var i, body,
26490			o = this.options;
26491
26492		this.currentContainer = this;
26493
26494		//We only need to call refreshPositions, because the refreshItems call has been moved to
26495		// mouseCapture
26496		this.refreshPositions();
26497
26498		//Prepare the dragged items parent
26499		this.appendTo = $( o.appendTo !== "parent" ?
26500				o.appendTo :
26501				this.currentItem.parent() );
26502
26503		//Create and append the visible helper
26504		this.helper = this._createHelper( event );
26505
26506		//Cache the helper size
26507		this._cacheHelperProportions();
26508
26509		/*
26510		 * - Position generation -
26511		 * This block generates everything position related - it's the core of draggables.
26512		 */
26513
26514		//Cache the margins of the original element
26515		this._cacheMargins();
26516
26517		//The element's absolute position on the page minus margins
26518		this.offset = this.currentItem.offset();
26519		this.offset = {
26520			top: this.offset.top - this.margins.top,
26521			left: this.offset.left - this.margins.left
26522		};
26523
26524		$.extend( this.offset, {
26525			click: { //Where the click happened, relative to the element
26526				left: event.pageX - this.offset.left,
26527				top: event.pageY - this.offset.top
26528			},
26529
26530			// This is a relative to absolute position minus the actual position calculation -
26531			// only used for relative positioned helper
26532			relative: this._getRelativeOffset()
26533		} );
26534
26535		// After we get the helper offset, but before we get the parent offset we can
26536		// change the helper's position to absolute
26537		// TODO: Still need to figure out a way to make relative sorting possible
26538		this.helper.css( "position", "absolute" );
26539		this.cssPosition = this.helper.css( "position" );
26540
26541		//Adjust the mouse offset relative to the helper if "cursorAt" is supplied
26542		if ( o.cursorAt ) {
26543			this._adjustOffsetFromHelper( o.cursorAt );
26544		}
26545
26546		//Cache the former DOM position
26547		this.domPosition = {
26548			prev: this.currentItem.prev()[ 0 ],
26549			parent: this.currentItem.parent()[ 0 ]
26550		};
26551
26552		// If the helper is not the original, hide the original so it's not playing any role during
26553		// the drag, won't cause anything bad this way
26554		if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {
26555			this.currentItem.hide();
26556		}
26557
26558		//Create the placeholder
26559		this._createPlaceholder();
26560
26561		//Get the next scrolling parent
26562		this.scrollParent = this.placeholder.scrollParent();
26563
26564		$.extend( this.offset, {
26565			parent: this._getParentOffset()
26566		} );
26567
26568		//Set a containment if given in the options
26569		if ( o.containment ) {
26570			this._setContainment();
26571		}
26572
26573		if ( o.cursor && o.cursor !== "auto" ) { // cursor option
26574			body = this.document.find( "body" );
26575
vendor: 10,284 bytes, lines 26576-26936
26576			// Support: IE
26577			this.storedCursor = body.css( "cursor" );
26578			body.css( "cursor", o.cursor );
26579
26580			this.storedStylesheet =
26581				$( "<style>*{ cursor: " + o.cursor + " !important; }</style>" ).appendTo( body );
26582		}
26583
26584		// We need to make sure to grab the zIndex before setting the
26585		// opacity, because setting the opacity to anything lower than 1
26586		// causes the zIndex to change from "auto" to 0.
26587		if ( o.zIndex ) { // zIndex option
26588			if ( this.helper.css( "zIndex" ) ) {
26589				this._storedZIndex = this.helper.css( "zIndex" );
26590			}
26591			this.helper.css( "zIndex", o.zIndex );
26592		}
26593
26594		if ( o.opacity ) { // opacity option
26595			if ( this.helper.css( "opacity" ) ) {
26596				this._storedOpacity = this.helper.css( "opacity" );
26597			}
26598			this.helper.css( "opacity", o.opacity );
26599		}
26600
26601		//Prepare scrolling
26602		if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
26603				this.scrollParent[ 0 ].tagName !== "HTML" ) {
26604			this.overflowOffset = this.scrollParent.offset();
26605		}
26606
26607		//Call callbacks
26608		this._trigger( "start", event, this._uiHash() );
26609
26610		//Recache the helper size
26611		if ( !this._preserveHelperProportions ) {
26612			this._cacheHelperProportions();
26613		}
26614
26615		//Post "activate" events to possible containers
26616		if ( !noActivation ) {
26617			for ( i = this.containers.length - 1; i >= 0; i-- ) {
26618				this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) );
26619			}
26620		}
26621
26622		//Prepare possible droppables
26623		if ( $.ui.ddmanager ) {
26624			$.ui.ddmanager.current = this;
26625		}
26626
26627		if ( $.ui.ddmanager && !o.dropBehaviour ) {
26628			$.ui.ddmanager.prepareOffsets( this, event );
26629		}
26630
26631		this.dragging = true;
26632
26633		this._addClass( this.helper, "ui-sortable-helper" );
26634
26635		//Move the helper, if needed
26636		if ( !this.helper.parent().is( this.appendTo ) ) {
26637			this.helper.detach().appendTo( this.appendTo );
26638
26639			//Update position
26640			this.offset.parent = this._getParentOffset();
26641		}
26642
26643		//Generate the original position
26644		this.position = this.originalPosition = this._generatePosition( event );
26645		this.originalPageX = event.pageX;
26646		this.originalPageY = event.pageY;
26647		this.lastPositionAbs = this.positionAbs = this._convertPositionTo( "absolute" );
26648
26649		this._mouseDrag( event );
26650
26651		return true;
26652
26653	},
26654
26655	_scroll: function( event ) {
26656		var o = this.options,
26657			scrolled = false;
26658
26659		if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
26660				this.scrollParent[ 0 ].tagName !== "HTML" ) {
26661
26662			if ( ( this.overflowOffset.top + this.scrollParent[ 0 ].offsetHeight ) -
26663					event.pageY < o.scrollSensitivity ) {
26664				this.scrollParent[ 0 ].scrollTop =
26665					scrolled = this.scrollParent[ 0 ].scrollTop + o.scrollSpeed;
26666			} else if ( event.pageY - this.overflowOffset.top < o.scrollSensitivity ) {
26667				this.scrollParent[ 0 ].scrollTop =
26668					scrolled = this.scrollParent[ 0 ].scrollTop - o.scrollSpeed;
26669			}
26670
26671			if ( ( this.overflowOffset.left + this.scrollParent[ 0 ].offsetWidth ) -
26672					event.pageX < o.scrollSensitivity ) {
26673				this.scrollParent[ 0 ].scrollLeft = scrolled =
26674					this.scrollParent[ 0 ].scrollLeft + o.scrollSpeed;
26675			} else if ( event.pageX - this.overflowOffset.left < o.scrollSensitivity ) {
26676				this.scrollParent[ 0 ].scrollLeft = scrolled =
26677					this.scrollParent[ 0 ].scrollLeft - o.scrollSpeed;
26678			}
26679
26680		} else {
26681
26682			if ( event.pageY - this.document.scrollTop() < o.scrollSensitivity ) {
26683				scrolled = this.document.scrollTop( this.document.scrollTop() - o.scrollSpeed );
26684			} else if ( this.window.height() - ( event.pageY - this.document.scrollTop() ) <
26685					o.scrollSensitivity ) {
26686				scrolled = this.document.scrollTop( this.document.scrollTop() + o.scrollSpeed );
26687			}
26688
26689			if ( event.pageX - this.document.scrollLeft() < o.scrollSensitivity ) {
26690				scrolled = this.document.scrollLeft(
26691					this.document.scrollLeft() - o.scrollSpeed
26692				);
26693			} else if ( this.window.width() - ( event.pageX - this.document.scrollLeft() ) <
26694					o.scrollSensitivity ) {
26695				scrolled = this.document.scrollLeft(
26696					this.document.scrollLeft() + o.scrollSpeed
26697				);
26698			}
26699
26700		}
26701
26702		return scrolled;
26703	},
26704
26705	_mouseDrag: function( event ) {
26706		var i, item, itemElement, intersection,
26707			o = this.options;
26708
26709		//Compute the helpers position
26710		this.position = this._generatePosition( event );
26711		this.positionAbs = this._convertPositionTo( "absolute" );
26712
26713		//Set the helper position
26714		if ( !this.options.axis || this.options.axis !== "y" ) {
26715			this.helper[ 0 ].style.left = this.position.left + "px";
26716		}
26717		if ( !this.options.axis || this.options.axis !== "x" ) {
26718			this.helper[ 0 ].style.top = this.position.top + "px";
26719		}
26720
26721		//Do scrolling
26722		if ( o.scroll ) {
26723			if ( this._scroll( event ) !== false ) {
26724
26725				//Update item positions used in position checks
26726				this._refreshItemPositions( true );
26727
26728				if ( $.ui.ddmanager && !o.dropBehaviour ) {
26729					$.ui.ddmanager.prepareOffsets( this, event );
26730				}
26731			}
26732		}
26733
26734		this.dragDirection = {
26735			vertical: this._getDragVerticalDirection(),
26736			horizontal: this._getDragHorizontalDirection()
26737		};
26738
26739		//Rearrange
26740		for ( i = this.items.length - 1; i >= 0; i-- ) {
26741
26742			//Cache variables and intersection, continue if no intersection
26743			item = this.items[ i ];
26744			itemElement = item.item[ 0 ];
26745			intersection = this._intersectsWithPointer( item );
26746			if ( !intersection ) {
26747				continue;
26748			}
26749
26750			// Only put the placeholder inside the current Container, skip all
26751			// items from other containers. This works because when moving
26752			// an item from one container to another the
26753			// currentContainer is switched before the placeholder is moved.
26754			//
26755			// Without this, moving items in "sub-sortables" can cause
26756			// the placeholder to jitter between the outer and inner container.
26757			if ( item.instance !== this.currentContainer ) {
26758				continue;
26759			}
26760
26761			// Cannot intersect with itself
26762			// no useless actions that have been done before
26763			// no action if the item moved is the parent of the item checked
26764			if ( itemElement !== this.currentItem[ 0 ] &&
26765				this.placeholder[ intersection === 1 ?
26766				"next" : "prev" ]()[ 0 ] !== itemElement &&
26767				!$.contains( this.placeholder[ 0 ], itemElement ) &&
26768				( this.options.type === "semi-dynamic" ?
26769					!$.contains( this.element[ 0 ], itemElement ) :
26770					true
26771				)
26772			) {
26773
26774				this.direction = intersection === 1 ? "down" : "up";
26775
26776				if ( this.options.tolerance === "pointer" ||
26777						this._intersectsWithSides( item ) ) {
26778					this._rearrange( event, item );
26779				} else {
26780					break;
26781				}
26782
26783				this._trigger( "change", event, this._uiHash() );
26784				break;
26785			}
26786		}
26787
26788		//Post events to containers
26789		this._contactContainers( event );
26790
26791		//Interconnect with droppables
26792		if ( $.ui.ddmanager ) {
26793			$.ui.ddmanager.drag( this, event );
26794		}
26795
26796		//Call callbacks
26797		this._trigger( "sort", event, this._uiHash() );
26798
26799		this.lastPositionAbs = this.positionAbs;
26800		return false;
26801
26802	},
26803
26804	_mouseStop: function( event, noPropagation ) {
26805
26806		if ( !event ) {
26807			return;
26808		}
26809
26810		//If we are using droppables, inform the manager about the drop
26811		if ( $.ui.ddmanager && !this.options.dropBehaviour ) {
26812			$.ui.ddmanager.drop( this, event );
26813		}
26814
26815		if ( this.options.revert ) {
26816			var that = this,
26817				cur = this.placeholder.offset(),
26818				axis = this.options.axis,
26819				animation = {};
26820
26821			if ( !axis || axis === "x" ) {
26822				animation.left = cur.left - this.offset.parent.left - this.margins.left +
26823					( this.offsetParent[ 0 ] === this.document[ 0 ].body ?
26824						0 :
26825						this.offsetParent[ 0 ].scrollLeft
26826					);
26827			}
26828			if ( !axis || axis === "y" ) {
26829				animation.top = cur.top - this.offset.parent.top - this.margins.top +
26830					( this.offsetParent[ 0 ] === this.document[ 0 ].body ?
26831						0 :
26832						this.offsetParent[ 0 ].scrollTop
26833					);
26834			}
26835			this.reverting = true;
26836			$( this.helper ).animate(
26837				animation,
26838				parseInt( this.options.revert, 10 ) || 500,
26839				function() {
26840					that._clear( event );
26841				}
26842			);
26843		} else {
26844			this._clear( event, noPropagation );
26845		}
26846
26847		return false;
26848
26849	},
26850
26851	cancel: function() {
26852
26853		if ( this.dragging ) {
26854
26855			this._mouseUp( new $.Event( "mouseup", { target: null } ) );
26856
26857			if ( this.options.helper === "original" ) {
26858				this.currentItem.css( this._storedCSS );
26859				this._removeClass( this.currentItem, "ui-sortable-helper" );
26860			} else {
26861				this.currentItem.show();
26862			}
26863
26864			//Post deactivating events to containers
26865			for ( var i = this.containers.length - 1; i >= 0; i-- ) {
26866				this.containers[ i ]._trigger( "deactivate", null, this._uiHash( this ) );
26867				if ( this.containers[ i ].containerCache.over ) {
26868					this.containers[ i ]._trigger( "out", null, this._uiHash( this ) );
26869					this.containers[ i ].containerCache.over = 0;
26870				}
26871			}
26872
26873		}
26874
26875		if ( this.placeholder ) {
26876
26877			//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately,
26878			// it unbinds ALL events from the original node!
26879			if ( this.placeholder[ 0 ].parentNode ) {
26880				this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] );
26881			}
26882			if ( this.options.helper !== "original" && this.helper &&
26883					this.helper[ 0 ].parentNode ) {
26884				this.helper.remove();
26885			}
26886
26887			$.extend( this, {
26888				helper: null,
26889				dragging: false,
26890				reverting: false,
26891				_noFinalSort: null
26892			} );
26893
26894			if ( this.domPosition.prev ) {
26895				$( this.domPosition.prev ).after( this.currentItem );
26896			} else {
26897				$( this.domPosition.parent ).prepend( this.currentItem );
26898			}
26899		}
26900
26901		return this;
26902
26903	},
26904
26905	serialize: function( o ) {
26906
26907		var items = this._getItemsAsjQuery( o && o.connected ),
26908			str = [];
26909		o = o || {};
26910
26911		$( items ).each( function() {
26912			var res = ( $( o.item || this ).attr( o.attribute || "id" ) || "" )
26913				.match( o.expression || ( /(.+)[\-=_](.+)/ ) );
26914			if ( res ) {
26915				str.push(
26916					( o.key || res[ 1 ] + "[]" ) +
26917					"=" + ( o.key && o.expression ? res[ 1 ] : res[ 2 ] ) );
26918			}
26919		} );
26920
26921		if ( !str.length && o.key ) {
26922			str.push( o.key + "=" );
26923		}
26924
26925		return str.join( "&" );
26926
26927	},
26928
26929	toArray: function( o ) {
26930
26931		var items = this._getItemsAsjQuery( o && o.connected ),
26932			ret = [];
26933
26934		o = o || {};
26935
26936		items.each( function() {
vendor: 9,873 bytes, lines 26937-27249
26937			ret.push( $( o.item || this ).attr( o.attribute || "id" ) || "" );
26938		} );
26939		return ret;
26940
26941	},
26942
26943	/* Be careful with the following core functions */
26944	_intersectsWith: function( item ) {
26945
26946		var x1 = this.positionAbs.left,
26947			x2 = x1 + this.helperProportions.width,
26948			y1 = this.positionAbs.top,
26949			y2 = y1 + this.helperProportions.height,
26950			l = item.left,
26951			r = l + item.width,
26952			t = item.top,
26953			b = t + item.height,
26954			dyClick = this.offset.click.top,
26955			dxClick = this.offset.click.left,
26956			isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t &&
26957				( y1 + dyClick ) < b ),
26958			isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l &&
26959				( x1 + dxClick ) < r ),
26960			isOverElement = isOverElementHeight && isOverElementWidth;
26961
26962		if ( this.options.tolerance === "pointer" ||
26963			this.options.forcePointerForContainers ||
26964			( this.options.tolerance !== "pointer" &&
26965				this.helperProportions[ this.floating ? "width" : "height" ] >
26966				item[ this.floating ? "width" : "height" ] )
26967		) {
26968			return isOverElement;
26969		} else {
26970
26971			return ( l < x1 + ( this.helperProportions.width / 2 ) && // Right Half
26972				x2 - ( this.helperProportions.width / 2 ) < r && // Left Half
26973				t < y1 + ( this.helperProportions.height / 2 ) && // Bottom Half
26974				y2 - ( this.helperProportions.height / 2 ) < b ); // Top Half
26975
26976		}
26977	},
26978
26979	_intersectsWithPointer: function( item ) {
26980		var verticalDirection, horizontalDirection,
26981			isOverElementHeight = ( this.options.axis === "x" ) ||
26982				this._isOverAxis(
26983					this.positionAbs.top + this.offset.click.top, item.top, item.height ),
26984			isOverElementWidth = ( this.options.axis === "y" ) ||
26985				this._isOverAxis(
26986					this.positionAbs.left + this.offset.click.left, item.left, item.width ),
26987			isOverElement = isOverElementHeight && isOverElementWidth;
26988
26989		if ( !isOverElement ) {
26990			return false;
26991		}
26992
26993		verticalDirection = this.dragDirection.vertical;
26994		horizontalDirection = this.dragDirection.horizontal;
26995
26996		return this.floating ?
26997			( ( horizontalDirection === "right" || verticalDirection === "down" ) ? 2 : 1 ) :
26998			( verticalDirection && ( verticalDirection === "down" ? 2 : 1 ) );
26999
27000	},
27001
27002	_intersectsWithSides: function( item ) {
27003
27004		var isOverBottomHalf = this._isOverAxis( this.positionAbs.top +
27005				this.offset.click.top, item.top + ( item.height / 2 ), item.height ),
27006			isOverRightHalf = this._isOverAxis( this.positionAbs.left +
27007				this.offset.click.left, item.left + ( item.width / 2 ), item.width ),
27008			verticalDirection = this.dragDirection.vertical,
27009			horizontalDirection = this.dragDirection.horizontal;
27010
27011		if ( this.floating && horizontalDirection ) {
27012			return ( ( horizontalDirection === "right" && isOverRightHalf ) ||
27013				( horizontalDirection === "left" && !isOverRightHalf ) );
27014		} else {
27015			return verticalDirection && ( ( verticalDirection === "down" && isOverBottomHalf ) ||
27016				( verticalDirection === "up" && !isOverBottomHalf ) );
27017		}
27018
27019	},
27020
27021	_getDragVerticalDirection: function() {
27022		var delta = this.positionAbs.top - this.lastPositionAbs.top;
27023		return delta !== 0 && ( delta > 0 ? "down" : "up" );
27024	},
27025
27026	_getDragHorizontalDirection: function() {
27027		var delta = this.positionAbs.left - this.lastPositionAbs.left;
27028		return delta !== 0 && ( delta > 0 ? "right" : "left" );
27029	},
27030
27031	refresh: function( event ) {
27032		this._refreshItems( event );
27033		this._setHandleClassName();
27034		this.refreshPositions();
27035		return this;
27036	},
27037
27038	_connectWith: function() {
27039		var options = this.options;
27040		return options.connectWith.constructor === String ?
27041			[ options.connectWith ] :
27042			options.connectWith;
27043	},
27044
27045	_getItemsAsjQuery: function( connected ) {
27046
27047		var i, j, cur, inst,
27048			items = [],
27049			queries = [],
27050			connectWith = this._connectWith();
27051
27052		if ( connectWith && connected ) {
27053			for ( i = connectWith.length - 1; i >= 0; i-- ) {
27054				cur = $( connectWith[ i ], this.document[ 0 ] );
27055				for ( j = cur.length - 1; j >= 0; j-- ) {
27056					inst = $.data( cur[ j ], this.widgetFullName );
27057					if ( inst && inst !== this && !inst.options.disabled ) {
27058						queries.push( [ typeof inst.options.items === "function" ?
27059							inst.options.items.call( inst.element ) :
27060							$( inst.options.items, inst.element )
27061								.not( ".ui-sortable-helper" )
27062								.not( ".ui-sortable-placeholder" ), inst ] );
27063					}
27064				}
27065			}
27066		}
27067
27068		queries.push( [ typeof this.options.items === "function" ?
27069			this.options.items
27070				.call( this.element, null, { options: this.options, item: this.currentItem } ) :
27071			$( this.options.items, this.element )
27072				.not( ".ui-sortable-helper" )
27073				.not( ".ui-sortable-placeholder" ), this ] );
27074
27075		function addItems() {
27076			items.push( this );
27077		}
27078		for ( i = queries.length - 1; i >= 0; i-- ) {
27079			queries[ i ][ 0 ].each( addItems );
27080		}
27081
27082		return $( items );
27083
27084	},
27085
27086	_removeCurrentsFromItems: function() {
27087
27088		var list = this.currentItem.find( ":data(" + this.widgetName + "-item)" );
27089
27090		this.items = $.grep( this.items, function( item ) {
27091			for ( var j = 0; j < list.length; j++ ) {
27092				if ( list[ j ] === item.item[ 0 ] ) {
27093					return false;
27094				}
27095			}
27096			return true;
27097		} );
27098
27099	},
27100
27101	_refreshItems: function( event ) {
27102
27103		this.items = [];
27104		this.containers = [ this ];
27105
27106		var i, j, cur, inst, targetData, _queries, item, queriesLength,
27107			items = this.items,
27108			queries = [ [ typeof this.options.items === "function" ?
27109				this.options.items.call( this.element[ 0 ], event, { item: this.currentItem } ) :
27110				$( this.options.items, this.element ), this ] ],
27111			connectWith = this._connectWith();
27112
27113		//Shouldn't be run the first time through due to massive slow-down
27114		if ( connectWith && this.ready ) {
27115			for ( i = connectWith.length - 1; i >= 0; i-- ) {
27116				cur = $( connectWith[ i ], this.document[ 0 ] );
27117				for ( j = cur.length - 1; j >= 0; j-- ) {
27118					inst = $.data( cur[ j ], this.widgetFullName );
27119					if ( inst && inst !== this && !inst.options.disabled ) {
27120						queries.push( [ typeof inst.options.items === "function" ?
27121							inst.options.items
27122								.call( inst.element[ 0 ], event, { item: this.currentItem } ) :
27123							$( inst.options.items, inst.element ), inst ] );
27124						this.containers.push( inst );
27125					}
27126				}
27127			}
27128		}
27129
27130		for ( i = queries.length - 1; i >= 0; i-- ) {
27131			targetData = queries[ i ][ 1 ];
27132			_queries = queries[ i ][ 0 ];
27133
27134			for ( j = 0, queriesLength = _queries.length; j < queriesLength; j++ ) {
27135				item = $( _queries[ j ] );
27136
27137				// Data for target checking (mouse manager)
27138				item.data( this.widgetName + "-item", targetData );
27139
27140				items.push( {
27141					item: item,
27142					instance: targetData,
27143					width: 0, height: 0,
27144					left: 0, top: 0
27145				} );
27146			}
27147		}
27148
27149	},
27150
27151	_refreshItemPositions: function( fast ) {
27152		var i, item, t, p;
27153
27154		for ( i = this.items.length - 1; i >= 0; i-- ) {
27155			item = this.items[ i ];
27156
27157			//We ignore calculating positions of all connected containers when we're not over them
27158			if ( this.currentContainer && item.instance !== this.currentContainer &&
27159					item.item[ 0 ] !== this.currentItem[ 0 ] ) {
27160				continue;
27161			}
27162
27163			t = this.options.toleranceElement ?
27164				$( this.options.toleranceElement, item.item ) :
27165				item.item;
27166
27167			if ( !fast ) {
27168				item.width = t.outerWidth();
27169				item.height = t.outerHeight();
27170			}
27171
27172			p = t.offset();
27173			item.left = p.left;
27174			item.top = p.top;
27175		}
27176	},
27177
27178	refreshPositions: function( fast ) {
27179
27180		// Determine whether items are being displayed horizontally
27181		this.floating = this.items.length ?
27182			this.options.axis === "x" || this._isFloating( this.items[ 0 ].item ) :
27183			false;
27184
27185		// This has to be redone because due to the item being moved out/into the offsetParent,
27186		// the offsetParent's position will change
27187		if ( this.offsetParent && this.helper ) {
27188			this.offset.parent = this._getParentOffset();
27189		}
27190
27191		this._refreshItemPositions( fast );
27192
27193		var i, p;
27194
27195		if ( this.options.custom && this.options.custom.refreshContainers ) {
27196			this.options.custom.refreshContainers.call( this );
27197		} else {
27198			for ( i = this.containers.length - 1; i >= 0; i-- ) {
27199				p = this.containers[ i ].element.offset();
27200				this.containers[ i ].containerCache.left = p.left;
27201				this.containers[ i ].containerCache.top = p.top;
27202				this.containers[ i ].containerCache.width =
27203					this.containers[ i ].element.outerWidth();
27204				this.containers[ i ].containerCache.height =
27205					this.containers[ i ].element.outerHeight();
27206			}
27207		}
27208
27209		return this;
27210	},
27211
27212	_createPlaceholder: function( that ) {
27213		that = that || this;
27214		var className, nodeName,
27215			o = that.options;
27216
27217		if ( !o.placeholder || o.placeholder.constructor === String ) {
27218			className = o.placeholder;
27219			nodeName = that.currentItem[ 0 ].nodeName.toLowerCase();
27220			o.placeholder = {
27221				element: function() {
27222
27223					var element = $( "<" + nodeName + ">", that.document[ 0 ] );
27224
27225					that._addClass( element, "ui-sortable-placeholder",
27226							className || that.currentItem[ 0 ].className )
27227						._removeClass( element, "ui-sortable-helper" );
27228
27229					if ( nodeName === "tbody" ) {
27230						that._createTrPlaceholder(
27231							that.currentItem.find( "tr" ).eq( 0 ),
27232							$( "<tr>", that.document[ 0 ] ).appendTo( element )
27233						);
27234					} else if ( nodeName === "tr" ) {
27235						that._createTrPlaceholder( that.currentItem, element );
27236					} else if ( nodeName === "img" ) {
27237						element.attr( "src", that.currentItem.attr( "src" ) );
27238					}
27239
27240					if ( !className ) {
27241						element.css( "visibility", "hidden" );
27242					}
27243
27244					return element;
27245				},
27246				update: function( container, p ) {
27247
27248					// 1. If a className is set as 'placeholder option, we don't force sizes -
27249					// the class is responsible for that
vendor: 10,802 bytes, lines 27250-27564
27250					// 2. The option 'forcePlaceholderSize can be enabled to force it even if a
27251					// class name is specified
27252					if ( className && !o.forcePlaceholderSize ) {
27253						return;
27254					}
27255
27256					// If the element doesn't have a actual height or width by itself (without
27257					// styles coming from a stylesheet), it receives the inline height and width
27258					// from the dragged item. Or, if it's a tbody or tr, it's going to have a height
27259					// anyway since we're populating them with <td>s above, but they're unlikely to
27260					// be the correct height on their own if the row heights are dynamic, so we'll
27261					// always assign the height of the dragged item given forcePlaceholderSize
27262					// is true.
27263					if ( !p.height() || ( o.forcePlaceholderSize &&
27264							( nodeName === "tbody" || nodeName === "tr" ) ) ) {
27265						p.height(
27266							that.currentItem.innerHeight() -
27267							parseInt( that.currentItem.css( "paddingTop" ) || 0, 10 ) -
27268							parseInt( that.currentItem.css( "paddingBottom" ) || 0, 10 ) );
27269					}
27270					if ( !p.width() ) {
27271						p.width(
27272							that.currentItem.innerWidth() -
27273							parseInt( that.currentItem.css( "paddingLeft" ) || 0, 10 ) -
27274							parseInt( that.currentItem.css( "paddingRight" ) || 0, 10 ) );
27275					}
27276				}
27277			};
27278		}
27279
27280		//Create the placeholder
27281		that.placeholder = $( o.placeholder.element.call( that.element, that.currentItem ) );
27282
27283		//Append it after the actual current item
27284		that.currentItem.after( that.placeholder );
27285
27286		//Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
27287		o.placeholder.update( that, that.placeholder );
27288
27289	},
27290
27291	_createTrPlaceholder: function( sourceTr, targetTr ) {
27292		var that = this;
27293
27294		sourceTr.children().each( function() {
27295			$( "<td>&#160;</td>", that.document[ 0 ] )
27296				.attr( "colspan", $( this ).attr( "colspan" ) || 1 )
27297				.appendTo( targetTr );
27298		} );
27299	},
27300
27301	_contactContainers: function( event ) {
27302		var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, cur, nearBottom,
27303			floating, axis,
27304			innermostContainer = null,
27305			innermostIndex = null;
27306
27307		// Get innermost container that intersects with item
27308		for ( i = this.containers.length - 1; i >= 0; i-- ) {
27309
27310			// Never consider a container that's located within the item itself
27311			if ( $.contains( this.currentItem[ 0 ], this.containers[ i ].element[ 0 ] ) ) {
27312				continue;
27313			}
27314
27315			if ( this._intersectsWith( this.containers[ i ].containerCache ) ) {
27316
27317				// If we've already found a container and it's more "inner" than this, then continue
27318				if ( innermostContainer &&
27319						$.contains(
27320							this.containers[ i ].element[ 0 ],
27321							innermostContainer.element[ 0 ] ) ) {
27322					continue;
27323				}
27324
27325				innermostContainer = this.containers[ i ];
27326				innermostIndex = i;
27327
27328			} else {
27329
27330				// container doesn't intersect. trigger "out" event if necessary
27331				if ( this.containers[ i ].containerCache.over ) {
27332					this.containers[ i ]._trigger( "out", event, this._uiHash( this ) );
27333					this.containers[ i ].containerCache.over = 0;
27334				}
27335			}
27336
27337		}
27338
27339		// If no intersecting containers found, return
27340		if ( !innermostContainer ) {
27341			return;
27342		}
27343
27344		// Move the item into the container if it's not there already
27345		if ( this.containers.length === 1 ) {
27346			if ( !this.containers[ innermostIndex ].containerCache.over ) {
27347				this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) );
27348				this.containers[ innermostIndex ].containerCache.over = 1;
27349			}
27350		} else {
27351
27352			// When entering a new container, we will find the item with the least distance and
27353			// append our item near it
27354			dist = 10000;
27355			itemWithLeastDistance = null;
27356			floating = innermostContainer.floating || this._isFloating( this.currentItem );
27357			posProperty = floating ? "left" : "top";
27358			sizeProperty = floating ? "width" : "height";
27359			axis = floating ? "pageX" : "pageY";
27360
27361			for ( j = this.items.length - 1; j >= 0; j-- ) {
27362				if ( !$.contains(
27363						this.containers[ innermostIndex ].element[ 0 ], this.items[ j ].item[ 0 ] )
27364				) {
27365					continue;
27366				}
27367				if ( this.items[ j ].item[ 0 ] === this.currentItem[ 0 ] ) {
27368					continue;
27369				}
27370
27371				cur = this.items[ j ].item.offset()[ posProperty ];
27372				nearBottom = false;
27373				if ( event[ axis ] - cur > this.items[ j ][ sizeProperty ] / 2 ) {
27374					nearBottom = true;
27375				}
27376
27377				if ( Math.abs( event[ axis ] - cur ) < dist ) {
27378					dist = Math.abs( event[ axis ] - cur );
27379					itemWithLeastDistance = this.items[ j ];
27380					this.direction = nearBottom ? "up" : "down";
27381				}
27382			}
27383
27384			//Check if dropOnEmpty is enabled
27385			if ( !itemWithLeastDistance && !this.options.dropOnEmpty ) {
27386				return;
27387			}
27388
27389			if ( this.currentContainer === this.containers[ innermostIndex ] ) {
27390				if ( !this.currentContainer.containerCache.over ) {
27391					this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash() );
27392					this.currentContainer.containerCache.over = 1;
27393				}
27394				return;
27395			}
27396
27397			if ( itemWithLeastDistance ) {
27398				this._rearrange( event, itemWithLeastDistance, null, true );
27399			} else {
27400				this._rearrange( event, null, this.containers[ innermostIndex ].element, true );
27401			}
27402			this._trigger( "change", event, this._uiHash() );
27403			this.containers[ innermostIndex ]._trigger( "change", event, this._uiHash( this ) );
27404			this.currentContainer = this.containers[ innermostIndex ];
27405
27406			//Update the placeholder
27407			this.options.placeholder.update( this.currentContainer, this.placeholder );
27408
27409			//Update scrollParent
27410			this.scrollParent = this.placeholder.scrollParent();
27411
27412			//Update overflowOffset
27413			if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
27414					this.scrollParent[ 0 ].tagName !== "HTML" ) {
27415				this.overflowOffset = this.scrollParent.offset();
27416			}
27417
27418			this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) );
27419			this.containers[ innermostIndex ].containerCache.over = 1;
27420		}
27421
27422	},
27423
27424	_createHelper: function( event ) {
27425
27426		var o = this.options,
27427			helper = typeof o.helper === "function" ?
27428				$( o.helper.apply( this.element[ 0 ], [ event, this.currentItem ] ) ) :
27429				( o.helper === "clone" ? this.currentItem.clone() : this.currentItem );
27430
27431		//Add the helper to the DOM if that didn't happen already
27432		if ( !helper.parents( "body" ).length ) {
27433			this.appendTo[ 0 ].appendChild( helper[ 0 ] );
27434		}
27435
27436		if ( helper[ 0 ] === this.currentItem[ 0 ] ) {
27437			this._storedCSS = {
27438				width: this.currentItem[ 0 ].style.width,
27439				height: this.currentItem[ 0 ].style.height,
27440				position: this.currentItem.css( "position" ),
27441				top: this.currentItem.css( "top" ),
27442				left: this.currentItem.css( "left" )
27443			};
27444		}
27445
27446		if ( !helper[ 0 ].style.width || o.forceHelperSize ) {
27447			helper.width( this.currentItem.width() );
27448		}
27449		if ( !helper[ 0 ].style.height || o.forceHelperSize ) {
27450			helper.height( this.currentItem.height() );
27451		}
27452
27453		return helper;
27454
27455	},
27456
27457	_adjustOffsetFromHelper: function( obj ) {
27458		if ( typeof obj === "string" ) {
27459			obj = obj.split( " " );
27460		}
27461		if ( Array.isArray( obj ) ) {
27462			obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 };
27463		}
27464		if ( "left" in obj ) {
27465			this.offset.click.left = obj.left + this.margins.left;
27466		}
27467		if ( "right" in obj ) {
27468			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
27469		}
27470		if ( "top" in obj ) {
27471			this.offset.click.top = obj.top + this.margins.top;
27472		}
27473		if ( "bottom" in obj ) {
27474			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
27475		}
27476	},
27477
27478	_getParentOffset: function() {
27479
27480		//Get the offsetParent and cache its position
27481		this.offsetParent = this.helper.offsetParent();
27482		var po = this.offsetParent.offset();
27483
27484		// This is a special case where we need to modify a offset calculated on start, since the
27485		// following happened:
27486		// 1. The position of the helper is absolute, so it's position is calculated based on the
27487		// next positioned parent
27488		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't
27489		// the document, which means that the scroll is included in the initial calculation of the
27490		// offset of the parent, and never recalculated upon drag
27491		if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== this.document[ 0 ] &&
27492				$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) {
27493			po.left += this.scrollParent.scrollLeft();
27494			po.top += this.scrollParent.scrollTop();
27495		}
27496
27497		// This needs to be actually done for all browsers, since pageX/pageY includes this
27498		// information with an ugly IE fix
27499		if ( this.offsetParent[ 0 ] === this.document[ 0 ].body ||
27500				( this.offsetParent[ 0 ].tagName &&
27501				this.offsetParent[ 0 ].tagName.toLowerCase() === "html" && $.ui.ie ) ) {
27502			po = { top: 0, left: 0 };
27503		}
27504
27505		return {
27506			top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ),
27507			left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 )
27508		};
27509
27510	},
27511
27512	_getRelativeOffset: function() {
27513
27514		if ( this.cssPosition === "relative" ) {
27515			var p = this.currentItem.position();
27516			return {
27517				top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) +
27518					this.scrollParent.scrollTop(),
27519				left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) +
27520					this.scrollParent.scrollLeft()
27521			};
27522		} else {
27523			return { top: 0, left: 0 };
27524		}
27525
27526	},
27527
27528	_cacheMargins: function() {
27529		this.margins = {
27530			left: ( parseInt( this.currentItem.css( "marginLeft" ), 10 ) || 0 ),
27531			top: ( parseInt( this.currentItem.css( "marginTop" ), 10 ) || 0 )
27532		};
27533	},
27534
27535	_cacheHelperProportions: function() {
27536		this.helperProportions = {
27537			width: this.helper.outerWidth(),
27538			height: this.helper.outerHeight()
27539		};
27540	},
27541
27542	_setContainment: function() {
27543
27544		var ce, co, over,
27545			o = this.options;
27546		if ( o.containment === "parent" ) {
27547			o.containment = this.helper[ 0 ].parentNode;
27548		}
27549		if ( o.containment === "document" || o.containment === "window" ) {
27550			this.containment = [
27551				0 - this.offset.relative.left - this.offset.parent.left,
27552				0 - this.offset.relative.top - this.offset.parent.top,
27553				o.containment === "document" ?
27554					this.document.width() :
27555					this.window.width() - this.helperProportions.width - this.margins.left,
27556				( o.containment === "document" ?
27557					( this.document.height() || document.body.parentNode.scrollHeight ) :
27558					this.window.height() || this.document[ 0 ].body.parentNode.scrollHeight
27559				) - this.helperProportions.height - this.margins.top
27560			];
27561		}
27562
27563		if ( !( /^(document|window|parent)$/ ).test( o.containment ) ) {
27564			ce = $( o.containment )[ 0 ];
vendor: 2,294 bytes, lines 27565-27625
27565			co = $( o.containment ).offset();
27566			over = ( $( ce ).css( "overflow" ) !== "hidden" );
27567
27568			this.containment = [
27569				co.left + ( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) +
27570					( parseInt( $( ce ).css( "paddingLeft" ), 10 ) || 0 ) - this.margins.left,
27571				co.top + ( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) +
27572					( parseInt( $( ce ).css( "paddingTop" ), 10 ) || 0 ) - this.margins.top,
27573				co.left + ( over ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -
27574					( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) -
27575					( parseInt( $( ce ).css( "paddingRight" ), 10 ) || 0 ) -
27576					this.helperProportions.width - this.margins.left,
27577				co.top + ( over ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -
27578					( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) -
27579					( parseInt( $( ce ).css( "paddingBottom" ), 10 ) || 0 ) -
27580					this.helperProportions.height - this.margins.top
27581			];
27582		}
27583
27584	},
27585
27586	_convertPositionTo: function( d, pos ) {
27587
27588		if ( !pos ) {
27589			pos = this.position;
27590		}
27591		var mod = d === "absolute" ? 1 : -1,
27592			scroll = this.cssPosition === "absolute" &&
27593				!( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
27594				$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ?
27595					this.offsetParent :
27596					this.scrollParent,
27597			scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName );
27598
27599		return {
27600			top: (
27601
27602				// The absolute mouse position
27603				pos.top	+
27604
27605				// Only for relative positioned nodes: Relative offset from element to offset parent
27606				this.offset.relative.top * mod +
27607
27608				// The offsetParent's offset without borders (offset + border)
27609				this.offset.parent.top * mod -
27610				( ( this.cssPosition === "fixed" ?
27611					-this.scrollParent.scrollTop() :
27612					( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod )
27613			),
27614			left: (
27615
27616				// The absolute mouse position
27617				pos.left +
27618
27619				// Only for relative positioned nodes: Relative offset from element to offset parent
27620				this.offset.relative.left * mod +
27621
27622				// The offsetParent's offset without borders (offset + border)
27623				this.offset.parent.left * mod	-
27624				( ( this.cssPosition === "fixed" ?
27625					-this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 :
vendor: 42,069 bytes, lines 27626-29139
27626					scroll.scrollLeft() ) * mod )
27627			)
27628		};
27629
27630	},
27631
27632	_generatePosition: function( event ) {
27633
27634		var top, left,
27635			o = this.options,
27636			pageX = event.pageX,
27637			pageY = event.pageY,
27638			scroll = this.cssPosition === "absolute" &&
27639				!( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
27640				$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ?
27641					this.offsetParent :
27642					this.scrollParent,
27643				scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName );
27644
27645		// This is another very weird special case that only happens for relative elements:
27646		// 1. If the css position is relative
27647		// 2. and the scroll parent is the document or similar to the offset parent
27648		// we have to refresh the relative offset during the scroll so there are no jumps
27649		if ( this.cssPosition === "relative" && !( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
27650				this.scrollParent[ 0 ] !== this.offsetParent[ 0 ] ) ) {
27651			this.offset.relative = this._getRelativeOffset();
27652		}
27653
27654		/*
27655		 * - Position constraining -
27656		 * Constrain the position to a mix of grid, containment.
27657		 */
27658
27659		if ( this.originalPosition ) { //If we are not dragging yet, we won't check for options
27660
27661			if ( this.containment ) {
27662				if ( event.pageX - this.offset.click.left < this.containment[ 0 ] ) {
27663					pageX = this.containment[ 0 ] + this.offset.click.left;
27664				}
27665				if ( event.pageY - this.offset.click.top < this.containment[ 1 ] ) {
27666					pageY = this.containment[ 1 ] + this.offset.click.top;
27667				}
27668				if ( event.pageX - this.offset.click.left > this.containment[ 2 ] ) {
27669					pageX = this.containment[ 2 ] + this.offset.click.left;
27670				}
27671				if ( event.pageY - this.offset.click.top > this.containment[ 3 ] ) {
27672					pageY = this.containment[ 3 ] + this.offset.click.top;
27673				}
27674			}
27675
27676			if ( o.grid ) {
27677				top = this.originalPageY + Math.round( ( pageY - this.originalPageY ) /
27678					o.grid[ 1 ] ) * o.grid[ 1 ];
27679				pageY = this.containment ?
27680					( ( top - this.offset.click.top >= this.containment[ 1 ] &&
27681						top - this.offset.click.top <= this.containment[ 3 ] ) ?
27682							top :
27683							( ( top - this.offset.click.top >= this.containment[ 1 ] ) ?
27684								top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) :
27685								top;
27686
27687				left = this.originalPageX + Math.round( ( pageX - this.originalPageX ) /
27688					o.grid[ 0 ] ) * o.grid[ 0 ];
27689				pageX = this.containment ?
27690					( ( left - this.offset.click.left >= this.containment[ 0 ] &&
27691						left - this.offset.click.left <= this.containment[ 2 ] ) ?
27692							left :
27693							( ( left - this.offset.click.left >= this.containment[ 0 ] ) ?
27694								left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) :
27695								left;
27696			}
27697
27698		}
27699
27700		return {
27701			top: (
27702
27703				// The absolute mouse position
27704				pageY -
27705
27706				// Click offset (relative to the element)
27707				this.offset.click.top -
27708
27709				// Only for relative positioned nodes: Relative offset from element to offset parent
27710				this.offset.relative.top -
27711
27712				// The offsetParent's offset without borders (offset + border)
27713				this.offset.parent.top +
27714				( ( this.cssPosition === "fixed" ?
27715					-this.scrollParent.scrollTop() :
27716					( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) )
27717			),
27718			left: (
27719
27720				// The absolute mouse position
27721				pageX -
27722
27723				// Click offset (relative to the element)
27724				this.offset.click.left -
27725
27726				// Only for relative positioned nodes: Relative offset from element to offset parent
27727				this.offset.relative.left -
27728
27729				// The offsetParent's offset without borders (offset + border)
27730				this.offset.parent.left +
27731				( ( this.cssPosition === "fixed" ?
27732					-this.scrollParent.scrollLeft() :
27733					scrollIsRootNode ? 0 : scroll.scrollLeft() ) )
27734			)
27735		};
27736
27737	},
27738
27739	_rearrange: function( event, i, a, hardRefresh ) {
27740
27741		if ( a ) {
27742			a[ 0 ].appendChild( this.placeholder[ 0 ] );
27743		} else {
27744			i.item[ 0 ].parentNode.insertBefore( this.placeholder[ 0 ],
27745				( this.direction === "down" ? i.item[ 0 ] : i.item[ 0 ].nextSibling ) );
27746		}
27747
27748		//Various things done here to improve the performance:
27749		// 1. we create a setTimeout, that calls refreshPositions
27750		// 2. on the instance, we have a counter variable, that get's higher after every append
27751		// 3. on the local scope, we copy the counter variable, and check in the timeout,
27752		// if it's still the same
27753		// 4. this lets only the last addition to the timeout stack through
27754		this.counter = this.counter ? ++this.counter : 1;
27755		var counter = this.counter;
27756
27757		this._delay( function() {
27758			if ( counter === this.counter ) {
27759
27760				//Precompute after each DOM insertion, NOT on mousemove
27761				this.refreshPositions( !hardRefresh );
27762			}
27763		} );
27764
27765	},
27766
27767	_clear: function( event, noPropagation ) {
27768
27769		this.reverting = false;
27770
27771		// We delay all events that have to be triggered to after the point where the placeholder
27772		// has been removed and everything else normalized again
27773		var i,
27774			delayedTriggers = [];
27775
27776		// We first have to update the dom position of the actual currentItem
27777		// Note: don't do it if the current item is already removed (by a user), or it gets
27778		// reappended (see #4088)
27779		if ( !this._noFinalSort && this.currentItem.parent().length ) {
27780			this.placeholder.before( this.currentItem );
27781		}
27782		this._noFinalSort = null;
27783
27784		if ( this.helper[ 0 ] === this.currentItem[ 0 ] ) {
27785			for ( i in this._storedCSS ) {
27786				if ( this._storedCSS[ i ] === "auto" || this._storedCSS[ i ] === "static" ) {
27787					this._storedCSS[ i ] = "";
27788				}
27789			}
27790			this.currentItem.css( this._storedCSS );
27791			this._removeClass( this.currentItem, "ui-sortable-helper" );
27792		} else {
27793			this.currentItem.show();
27794		}
27795
27796		if ( this.fromOutside && !noPropagation ) {
27797			delayedTriggers.push( function( event ) {
27798				this._trigger( "receive", event, this._uiHash( this.fromOutside ) );
27799			} );
27800		}
27801		if ( ( this.fromOutside ||
27802				this.domPosition.prev !==
27803				this.currentItem.prev().not( ".ui-sortable-helper" )[ 0 ] ||
27804				this.domPosition.parent !== this.currentItem.parent()[ 0 ] ) && !noPropagation ) {
27805
27806			// Trigger update callback if the DOM position has changed
27807			delayedTriggers.push( function( event ) {
27808				this._trigger( "update", event, this._uiHash() );
27809			} );
27810		}
27811
27812		// Check if the items Container has Changed and trigger appropriate
27813		// events.
27814		if ( this !== this.currentContainer ) {
27815			if ( !noPropagation ) {
27816				delayedTriggers.push( function( event ) {
27817					this._trigger( "remove", event, this._uiHash() );
27818				} );
27819				delayedTriggers.push( ( function( c ) {
27820					return function( event ) {
27821						c._trigger( "receive", event, this._uiHash( this ) );
27822					};
27823				} ).call( this, this.currentContainer ) );
27824				delayedTriggers.push( ( function( c ) {
27825					return function( event ) {
27826						c._trigger( "update", event, this._uiHash( this ) );
27827					};
27828				} ).call( this, this.currentContainer ) );
27829			}
27830		}
27831
27832		//Post events to containers
27833		function delayEvent( type, instance, container ) {
27834			return function( event ) {
27835				container._trigger( type, event, instance._uiHash( instance ) );
27836			};
27837		}
27838		for ( i = this.containers.length - 1; i >= 0; i-- ) {
27839			if ( !noPropagation ) {
27840				delayedTriggers.push( delayEvent( "deactivate", this, this.containers[ i ] ) );
27841			}
27842			if ( this.containers[ i ].containerCache.over ) {
27843				delayedTriggers.push( delayEvent( "out", this, this.containers[ i ] ) );
27844				this.containers[ i ].containerCache.over = 0;
27845			}
27846		}
27847
27848		//Do what was originally in plugins
27849		if ( this.storedCursor ) {
27850			this.document.find( "body" ).css( "cursor", this.storedCursor );
27851			this.storedStylesheet.remove();
27852		}
27853		if ( this._storedOpacity ) {
27854			this.helper.css( "opacity", this._storedOpacity );
27855		}
27856		if ( this._storedZIndex ) {
27857			this.helper.css( "zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex );
27858		}
27859
27860		this.dragging = false;
27861
27862		if ( !noPropagation ) {
27863			this._trigger( "beforeStop", event, this._uiHash() );
27864		}
27865
27866		//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately,
27867		// it unbinds ALL events from the original node!
27868		this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] );
27869
27870		if ( !this.cancelHelperRemoval ) {
27871			if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {
27872				this.helper.remove();
27873			}
27874			this.helper = null;
27875		}
27876
27877		if ( !noPropagation ) {
27878			for ( i = 0; i < delayedTriggers.length; i++ ) {
27879
27880				// Trigger all delayed events
27881				delayedTriggers[ i ].call( this, event );
27882			}
27883			this._trigger( "stop", event, this._uiHash() );
27884		}
27885
27886		this.fromOutside = false;
27887		return !this.cancelHelperRemoval;
27888
27889	},
27890
27891	_trigger: function() {
27892		if ( $.Widget.prototype._trigger.apply( this, arguments ) === false ) {
27893			this.cancel();
27894		}
27895	},
27896
27897	_uiHash: function( _inst ) {
27898		var inst = _inst || this;
27899		return {
27900			helper: inst.helper,
27901			placeholder: inst.placeholder || $( [] ),
27902			position: inst.position,
27903			originalPosition: inst.originalPosition,
27904			offset: inst.positionAbs,
27905			item: inst.currentItem,
27906			sender: _inst ? _inst.element : null
27907		};
27908	}
27909
27910} );
27911
27912
27913/*!
27914 * jQuery UI Spinner 1.13.2
27915 * http://jqueryui.com
27916 *
27917 * Copyright jQuery Foundation and other contributors
27918 * Released under the MIT license.
27919 * http://jquery.org/license
27920 */
27921
27922//>>label: Spinner
27923//>>group: Widgets
27924//>>description: Displays buttons to easily input numbers via the keyboard or mouse.
27925//>>docs: http://api.jqueryui.com/spinner/
27926//>>demos: http://jqueryui.com/spinner/
27927//>>css.structure: ../../themes/base/core.css
27928//>>css.structure: ../../themes/base/spinner.css
27929//>>css.theme: ../../themes/base/theme.css
27930
27931
27932function spinnerModifier( fn ) {
27933	return function() {
27934		var previous = this.element.val();
27935		fn.apply( this, arguments );
27936		this._refresh();
27937		if ( previous !== this.element.val() ) {
27938			this._trigger( "change" );
27939		}
27940	};
27941}
27942
27943$.widget( "ui.spinner", {
27944	version: "1.13.2",
27945	defaultElement: "<input>",
27946	widgetEventPrefix: "spin",
27947	options: {
27948		classes: {
27949			"ui-spinner": "ui-corner-all",
27950			"ui-spinner-down": "ui-corner-br",
27951			"ui-spinner-up": "ui-corner-tr"
27952		},
27953		culture: null,
27954		icons: {
27955			down: "ui-icon-triangle-1-s",
27956			up: "ui-icon-triangle-1-n"
27957		},
27958		incremental: true,
27959		max: null,
27960		min: null,
27961		numberFormat: null,
27962		page: 10,
27963		step: 1,
27964
27965		change: null,
27966		spin: null,
27967		start: null,
27968		stop: null
27969	},
27970
27971	_create: function() {
27972
27973		// handle string values that need to be parsed
27974		this._setOption( "max", this.options.max );
27975		this._setOption( "min", this.options.min );
27976		this._setOption( "step", this.options.step );
27977
27978		// Only format if there is a value, prevents the field from being marked
27979		// as invalid in Firefox, see #9573.
27980		if ( this.value() !== "" ) {
27981
27982			// Format the value, but don't constrain.
27983			this._value( this.element.val(), true );
27984		}
27985
27986		this._draw();
27987		this._on( this._events );
27988		this._refresh();
27989
27990		// Turning off autocomplete prevents the browser from remembering the
27991		// value when navigating through history, so we re-enable autocomplete
27992		// if the page is unloaded before the widget is destroyed. #7790
27993		this._on( this.window, {
27994			beforeunload: function() {
27995				this.element.removeAttr( "autocomplete" );
27996			}
27997		} );
27998	},
27999
28000	_getCreateOptions: function() {
28001		var options = this._super();
28002		var element = this.element;
28003
28004		$.each( [ "min", "max", "step" ], function( i, option ) {
28005			var value = element.attr( option );
28006			if ( value != null && value.length ) {
28007				options[ option ] = value;
28008			}
28009		} );
28010
28011		return options;
28012	},
28013
28014	_events: {
28015		keydown: function( event ) {
28016			if ( this._start( event ) && this._keydown( event ) ) {
28017				event.preventDefault();
28018			}
28019		},
28020		keyup: "_stop",
28021		focus: function() {
28022			this.previous = this.element.val();
28023		},
28024		blur: function( event ) {
28025			if ( this.cancelBlur ) {
28026				delete this.cancelBlur;
28027				return;
28028			}
28029
28030			this._stop();
28031			this._refresh();
28032			if ( this.previous !== this.element.val() ) {
28033				this._trigger( "change", event );
28034			}
28035		},
28036		mousewheel: function( event, delta ) {
28037			var activeElement = $.ui.safeActiveElement( this.document[ 0 ] );
28038			var isActive = this.element[ 0 ] === activeElement;
28039
28040			if ( !isActive || !delta ) {
28041				return;
28042			}
28043
28044			if ( !this.spinning && !this._start( event ) ) {
28045				return false;
28046			}
28047
28048			this._spin( ( delta > 0 ? 1 : -1 ) * this.options.step, event );
28049			clearTimeout( this.mousewheelTimer );
28050			this.mousewheelTimer = this._delay( function() {
28051				if ( this.spinning ) {
28052					this._stop( event );
28053				}
28054			}, 100 );
28055			event.preventDefault();
28056		},
28057		"mousedown .ui-spinner-button": function( event ) {
28058			var previous;
28059
28060			// We never want the buttons to have focus; whenever the user is
28061			// interacting with the spinner, the focus should be on the input.
28062			// If the input is focused then this.previous is properly set from
28063			// when the input first received focus. If the input is not focused
28064			// then we need to set this.previous based on the value before spinning.
28065			previous = this.element[ 0 ] === $.ui.safeActiveElement( this.document[ 0 ] ) ?
28066				this.previous : this.element.val();
28067			function checkFocus() {
28068				var isActive = this.element[ 0 ] === $.ui.safeActiveElement( this.document[ 0 ] );
28069				if ( !isActive ) {
28070					this.element.trigger( "focus" );
28071					this.previous = previous;
28072
28073					// support: IE
28074					// IE sets focus asynchronously, so we need to check if focus
28075					// moved off of the input because the user clicked on the button.
28076					this._delay( function() {
28077						this.previous = previous;
28078					} );
28079				}
28080			}
28081
28082			// Ensure focus is on (or stays on) the text field
28083			event.preventDefault();
28084			checkFocus.call( this );
28085
28086			// Support: IE
28087			// IE doesn't prevent moving focus even with event.preventDefault()
28088			// so we set a flag to know when we should ignore the blur event
28089			// and check (again) if focus moved off of the input.
28090			this.cancelBlur = true;
28091			this._delay( function() {
28092				delete this.cancelBlur;
28093				checkFocus.call( this );
28094			} );
28095
28096			if ( this._start( event ) === false ) {
28097				return;
28098			}
28099
28100			this._repeat( null, $( event.currentTarget )
28101				.hasClass( "ui-spinner-up" ) ? 1 : -1, event );
28102		},
28103		"mouseup .ui-spinner-button": "_stop",
28104		"mouseenter .ui-spinner-button": function( event ) {
28105
28106			// button will add ui-state-active if mouse was down while mouseleave and kept down
28107			if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) {
28108				return;
28109			}
28110
28111			if ( this._start( event ) === false ) {
28112				return false;
28113			}
28114			this._repeat( null, $( event.currentTarget )
28115				.hasClass( "ui-spinner-up" ) ? 1 : -1, event );
28116		},
28117
28118		// TODO: do we really want to consider this a stop?
28119		// shouldn't we just stop the repeater and wait until mouseup before
28120		// we trigger the stop event?
28121		"mouseleave .ui-spinner-button": "_stop"
28122	},
28123
28124	// Support mobile enhanced option and make backcompat more sane
28125	_enhance: function() {
28126		this.uiSpinner = this.element
28127			.attr( "autocomplete", "off" )
28128			.wrap( "<span>" )
28129			.parent()
28130
28131				// Add buttons
28132				.append(
28133					"<a></a><a></a>"
28134				);
28135	},
28136
28137	_draw: function() {
28138		this._enhance();
28139
28140		this._addClass( this.uiSpinner, "ui-spinner", "ui-widget ui-widget-content" );
28141		this._addClass( "ui-spinner-input" );
28142
28143		this.element.attr( "role", "spinbutton" );
28144
28145		// Button bindings
28146		this.buttons = this.uiSpinner.children( "a" )
28147			.attr( "tabIndex", -1 )
28148			.attr( "aria-hidden", true )
28149			.button( {
28150				classes: {
28151					"ui-button": ""
28152				}
28153			} );
28154
28155		// TODO: Right now button does not support classes this is already updated in button PR
28156		this._removeClass( this.buttons, "ui-corner-all" );
28157
28158		this._addClass( this.buttons.first(), "ui-spinner-button ui-spinner-up" );
28159		this._addClass( this.buttons.last(), "ui-spinner-button ui-spinner-down" );
28160		this.buttons.first().button( {
28161			"icon": this.options.icons.up,
28162			"showLabel": false
28163		} );
28164		this.buttons.last().button( {
28165			"icon": this.options.icons.down,
28166			"showLabel": false
28167		} );
28168
28169		// IE 6 doesn't understand height: 50% for the buttons
28170		// unless the wrapper has an explicit height
28171		if ( this.buttons.height() > Math.ceil( this.uiSpinner.height() * 0.5 ) &&
28172				this.uiSpinner.height() > 0 ) {
28173			this.uiSpinner.height( this.uiSpinner.height() );
28174		}
28175	},
28176
28177	_keydown: function( event ) {
28178		var options = this.options,
28179			keyCode = $.ui.keyCode;
28180
28181		switch ( event.keyCode ) {
28182		case keyCode.UP:
28183			this._repeat( null, 1, event );
28184			return true;
28185		case keyCode.DOWN:
28186			this._repeat( null, -1, event );
28187			return true;
28188		case keyCode.PAGE_UP:
28189			this._repeat( null, options.page, event );
28190			return true;
28191		case keyCode.PAGE_DOWN:
28192			this._repeat( null, -options.page, event );
28193			return true;
28194		}
28195
28196		return false;
28197	},
28198
28199	_start: function( event ) {
28200		if ( !this.spinning && this._trigger( "start", event ) === false ) {
28201			return false;
28202		}
28203
28204		if ( !this.counter ) {
28205			this.counter = 1;
28206		}
28207		this.spinning = true;
28208		return true;
28209	},
28210
28211	_repeat: function( i, steps, event ) {
28212		i = i || 500;
28213
28214		clearTimeout( this.timer );
28215		this.timer = this._delay( function() {
28216			this._repeat( 40, steps, event );
28217		}, i );
28218
28219		this._spin( steps * this.options.step, event );
28220	},
28221
28222	_spin: function( step, event ) {
28223		var value = this.value() || 0;
28224
28225		if ( !this.counter ) {
28226			this.counter = 1;
28227		}
28228
28229		value = this._adjustValue( value + step * this._increment( this.counter ) );
28230
28231		if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false ) {
28232			this._value( value );
28233			this.counter++;
28234		}
28235	},
28236
28237	_increment: function( i ) {
28238		var incremental = this.options.incremental;
28239
28240		if ( incremental ) {
28241			return typeof incremental === "function" ?
28242				incremental( i ) :
28243				Math.floor( i * i * i / 50000 - i * i / 500 + 17 * i / 200 + 1 );
28244		}
28245
28246		return 1;
28247	},
28248
28249	_precision: function() {
28250		var precision = this._precisionOf( this.options.step );
28251		if ( this.options.min !== null ) {
28252			precision = Math.max( precision, this._precisionOf( this.options.min ) );
28253		}
28254		return precision;
28255	},
28256
28257	_precisionOf: function( num ) {
28258		var str = num.toString(),
28259			decimal = str.indexOf( "." );
28260		return decimal === -1 ? 0 : str.length - decimal - 1;
28261	},
28262
28263	_adjustValue: function( value ) {
28264		var base, aboveMin,
28265			options = this.options;
28266
28267		// Make sure we're at a valid step
28268		// - find out where we are relative to the base (min or 0)
28269		base = options.min !== null ? options.min : 0;
28270		aboveMin = value - base;
28271
28272		// - round to the nearest step
28273		aboveMin = Math.round( aboveMin / options.step ) * options.step;
28274
28275		// - rounding is based on 0, so adjust back to our base
28276		value = base + aboveMin;
28277
28278		// Fix precision from bad JS floating point math
28279		value = parseFloat( value.toFixed( this._precision() ) );
28280
28281		// Clamp the value
28282		if ( options.max !== null && value > options.max ) {
28283			return options.max;
28284		}
28285		if ( options.min !== null && value < options.min ) {
28286			return options.min;
28287		}
28288
28289		return value;
28290	},
28291
28292	_stop: function( event ) {
28293		if ( !this.spinning ) {
28294			return;
28295		}
28296
28297		clearTimeout( this.timer );
28298		clearTimeout( this.mousewheelTimer );
28299		this.counter = 0;
28300		this.spinning = false;
28301		this._trigger( "stop", event );
28302	},
28303
28304	_setOption: function( key, value ) {
28305		var prevValue, first, last;
28306
28307		if ( key === "culture" || key === "numberFormat" ) {
28308			prevValue = this._parse( this.element.val() );
28309			this.options[ key ] = value;
28310			this.element.val( this._format( prevValue ) );
28311			return;
28312		}
28313
28314		if ( key === "max" || key === "min" || key === "step" ) {
28315			if ( typeof value === "string" ) {
28316				value = this._parse( value );
28317			}
28318		}
28319		if ( key === "icons" ) {
28320			first = this.buttons.first().find( ".ui-icon" );
28321			this._removeClass( first, null, this.options.icons.up );
28322			this._addClass( first, null, value.up );
28323			last = this.buttons.last().find( ".ui-icon" );
28324			this._removeClass( last, null, this.options.icons.down );
28325			this._addClass( last, null, value.down );
28326		}
28327
28328		this._super( key, value );
28329	},
28330
28331	_setOptionDisabled: function( value ) {
28332		this._super( value );
28333
28334		this._toggleClass( this.uiSpinner, null, "ui-state-disabled", !!value );
28335		this.element.prop( "disabled", !!value );
28336		this.buttons.button( value ? "disable" : "enable" );
28337	},
28338
28339	_setOptions: spinnerModifier( function( options ) {
28340		this._super( options );
28341	} ),
28342
28343	_parse: function( val ) {
28344		if ( typeof val === "string" && val !== "" ) {
28345			val = window.Globalize && this.options.numberFormat ?
28346				Globalize.parseFloat( val, 10, this.options.culture ) : +val;
28347		}
28348		return val === "" || isNaN( val ) ? null : val;
28349	},
28350
28351	_format: function( value ) {
28352		if ( value === "" ) {
28353			return "";
28354		}
28355		return window.Globalize && this.options.numberFormat ?
28356			Globalize.format( value, this.options.numberFormat, this.options.culture ) :
28357			value;
28358	},
28359
28360	_refresh: function() {
28361		this.element.attr( {
28362			"aria-valuemin": this.options.min,
28363			"aria-valuemax": this.options.max,
28364
28365			// TODO: what should we do with values that can't be parsed?
28366			"aria-valuenow": this._parse( this.element.val() )
28367		} );
28368	},
28369
28370	isValid: function() {
28371		var value = this.value();
28372
28373		// Null is invalid
28374		if ( value === null ) {
28375			return false;
28376		}
28377
28378		// If value gets adjusted, it's invalid
28379		return value === this._adjustValue( value );
28380	},
28381
28382	// Update the value without triggering change
28383	_value: function( value, allowAny ) {
28384		var parsed;
28385		if ( value !== "" ) {
28386			parsed = this._parse( value );
28387			if ( parsed !== null ) {
28388				if ( !allowAny ) {
28389					parsed = this._adjustValue( parsed );
28390				}
28391				value = this._format( parsed );
28392			}
28393		}
28394		this.element.val( value );
28395		this._refresh();
28396	},
28397
28398	_destroy: function() {
28399		this.element
28400			.prop( "disabled", false )
28401			.removeAttr( "autocomplete role aria-valuemin aria-valuemax aria-valuenow" );
28402
28403		this.uiSpinner.replaceWith( this.element );
28404	},
28405
28406	stepUp: spinnerModifier( function( steps ) {
28407		this._stepUp( steps );
28408	} ),
28409	_stepUp: function( steps ) {
28410		if ( this._start() ) {
28411			this._spin( ( steps || 1 ) * this.options.step );
28412			this._stop();
28413		}
28414	},
28415
28416	stepDown: spinnerModifier( function( steps ) {
28417		this._stepDown( steps );
28418	} ),
28419	_stepDown: function( steps ) {
28420		if ( this._start() ) {
28421			this._spin( ( steps || 1 ) * -this.options.step );
28422			this._stop();
28423		}
28424	},
28425
28426	pageUp: spinnerModifier( function( pages ) {
28427		this._stepUp( ( pages || 1 ) * this.options.page );
28428	} ),
28429
28430	pageDown: spinnerModifier( function( pages ) {
28431		this._stepDown( ( pages || 1 ) * this.options.page );
28432	} ),
28433
28434	value: function( newVal ) {
28435		if ( !arguments.length ) {
28436			return this._parse( this.element.val() );
28437		}
28438		spinnerModifier( this._value ).call( this, newVal );
28439	},
28440
28441	widget: function() {
28442		return this.uiSpinner;
28443	}
28444} );
28445
28446// DEPRECATED
28447// TODO: switch return back to widget declaration at top of file when this is removed
28448if ( $.uiBackCompat !== false ) {
28449
28450	// Backcompat for spinner html extension points
28451	$.widget( "ui.spinner", $.ui.spinner, {
28452		_enhance: function() {
28453			this.uiSpinner = this.element
28454				.attr( "autocomplete", "off" )
28455				.wrap( this._uiSpinnerHtml() )
28456				.parent()
28457
28458					// Add buttons
28459					.append( this._buttonHtml() );
28460		},
28461		_uiSpinnerHtml: function() {
28462			return "<span>";
28463		},
28464
28465		_buttonHtml: function() {
28466			return "<a></a><a></a>";
28467		}
28468	} );
28469}
28470
28471var widgetsSpinner = $.ui.spinner;
28472
28473
28474/*!
28475 * jQuery UI Tabs 1.13.2
28476 * http://jqueryui.com
28477 *
28478 * Copyright jQuery Foundation and other contributors
28479 * Released under the MIT license.
28480 * http://jquery.org/license
28481 */
28482
28483//>>label: Tabs
28484//>>group: Widgets
28485//>>description: Transforms a set of container elements into a tab structure.
28486//>>docs: http://api.jqueryui.com/tabs/
28487//>>demos: http://jqueryui.com/tabs/
28488//>>css.structure: ../../themes/base/core.css
28489//>>css.structure: ../../themes/base/tabs.css
28490//>>css.theme: ../../themes/base/theme.css
28491
28492
28493$.widget( "ui.tabs", {
28494	version: "1.13.2",
28495	delay: 300,
28496	options: {
28497		active: null,
28498		classes: {
28499			"ui-tabs": "ui-corner-all",
28500			"ui-tabs-nav": "ui-corner-all",
28501			"ui-tabs-panel": "ui-corner-bottom",
28502			"ui-tabs-tab": "ui-corner-top"
28503		},
28504		collapsible: false,
28505		event: "click",
28506		heightStyle: "content",
28507		hide: null,
28508		show: null,
28509
28510		// Callbacks
28511		activate: null,
28512		beforeActivate: null,
28513		beforeLoad: null,
28514		load: null
28515	},
28516
28517	_isLocal: ( function() {
28518		var rhash = /#.*$/;
28519
28520		return function( anchor ) {
28521			var anchorUrl, locationUrl;
28522
28523			anchorUrl = anchor.href.replace( rhash, "" );
28524			locationUrl = location.href.replace( rhash, "" );
28525
28526			// Decoding may throw an error if the URL isn't UTF-8 (#9518)
28527			try {
28528				anchorUrl = decodeURIComponent( anchorUrl );
28529			} catch ( error ) {}
28530			try {
28531				locationUrl = decodeURIComponent( locationUrl );
28532			} catch ( error ) {}
28533
28534			return anchor.hash.length > 1 && anchorUrl === locationUrl;
28535		};
28536	} )(),
28537
28538	_create: function() {
28539		var that = this,
28540			options = this.options;
28541
28542		this.running = false;
28543
28544		this._addClass( "ui-tabs", "ui-widget ui-widget-content" );
28545		this._toggleClass( "ui-tabs-collapsible", null, options.collapsible );
28546
28547		this._processTabs();
28548		options.active = this._initialActive();
28549
28550		// Take disabling tabs via class attribute from HTML
28551		// into account and update option properly.
28552		if ( Array.isArray( options.disabled ) ) {
28553			options.disabled = $.uniqueSort( options.disabled.concat(
28554				$.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) {
28555					return that.tabs.index( li );
28556				} )
28557			) ).sort();
28558		}
28559
28560		// Check for length avoids error when initializing empty list
28561		if ( this.options.active !== false && this.anchors.length ) {
28562			this.active = this._findActive( options.active );
28563		} else {
28564			this.active = $();
28565		}
28566
28567		this._refresh();
28568
28569		if ( this.active.length ) {
28570			this.load( options.active );
28571		}
28572	},
28573
28574	_initialActive: function() {
28575		var active = this.options.active,
28576			collapsible = this.options.collapsible,
28577			locationHash = location.hash.substring( 1 );
28578
28579		if ( active === null ) {
28580
28581			// check the fragment identifier in the URL
28582			if ( locationHash ) {
28583				this.tabs.each( function( i, tab ) {
28584					if ( $( tab ).attr( "aria-controls" ) === locationHash ) {
28585						active = i;
28586						return false;
28587					}
28588				} );
28589			}
28590
28591			// Check for a tab marked active via a class
28592			if ( active === null ) {
28593				active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) );
28594			}
28595
28596			// No active tab, set to false
28597			if ( active === null || active === -1 ) {
28598				active = this.tabs.length ? 0 : false;
28599			}
28600		}
28601
28602		// Handle numbers: negative, out of range
28603		if ( active !== false ) {
28604			active = this.tabs.index( this.tabs.eq( active ) );
28605			if ( active === -1 ) {
28606				active = collapsible ? false : 0;
28607			}
28608		}
28609
28610		// Don't allow collapsible: false and active: false
28611		if ( !collapsible && active === false && this.anchors.length ) {
28612			active = 0;
28613		}
28614
28615		return active;
28616	},
28617
28618	_getCreateEventData: function() {
28619		return {
28620			tab: this.active,
28621			panel: !this.active.length ? $() : this._getPanelForTab( this.active )
28622		};
28623	},
28624
28625	_tabKeydown: function( event ) {
28626		var focusedTab = $( $.ui.safeActiveElement( this.document[ 0 ] ) ).closest( "li" ),
28627			selectedIndex = this.tabs.index( focusedTab ),
28628			goingForward = true;
28629
28630		if ( this._handlePageNav( event ) ) {
28631			return;
28632		}
28633
28634		switch ( event.keyCode ) {
28635		case $.ui.keyCode.RIGHT:
28636		case $.ui.keyCode.DOWN:
28637			selectedIndex++;
28638			break;
28639		case $.ui.keyCode.UP:
28640		case $.ui.keyCode.LEFT:
28641			goingForward = false;
28642			selectedIndex--;
28643			break;
28644		case $.ui.keyCode.END:
28645			selectedIndex = this.anchors.length - 1;
28646			break;
28647		case $.ui.keyCode.HOME:
28648			selectedIndex = 0;
28649			break;
28650		case $.ui.keyCode.SPACE:
28651
28652			// Activate only, no collapsing
28653			event.preventDefault();
28654			clearTimeout( this.activating );
28655			this._activate( selectedIndex );
28656			return;
28657		case $.ui.keyCode.ENTER:
28658
28659			// Toggle (cancel delayed activation, allow collapsing)
28660			event.preventDefault();
28661			clearTimeout( this.activating );
28662
28663			// Determine if we should collapse or activate
28664			this._activate( selectedIndex === this.options.active ? false : selectedIndex );
28665			return;
28666		default:
28667			return;
28668		}
28669
28670		// Focus the appropriate tab, based on which key was pressed
28671		event.preventDefault();
28672		clearTimeout( this.activating );
28673		selectedIndex = this._focusNextTab( selectedIndex, goingForward );
28674
28675		// Navigating with control/command key will prevent automatic activation
28676		if ( !event.ctrlKey && !event.metaKey ) {
28677
28678			// Update aria-selected immediately so that AT think the tab is already selected.
28679			// Otherwise AT may confuse the user by stating that they need to activate the tab,
28680			// but the tab will already be activated by the time the announcement finishes.
28681			focusedTab.attr( "aria-selected", "false" );
28682			this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" );
28683
28684			this.activating = this._delay( function() {
28685				this.option( "active", selectedIndex );
28686			}, this.delay );
28687		}
28688	},
28689
28690	_panelKeydown: function( event ) {
28691		if ( this._handlePageNav( event ) ) {
28692			return;
28693		}
28694
28695		// Ctrl+up moves focus to the current tab
28696		if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {
28697			event.preventDefault();
28698			this.active.trigger( "focus" );
28699		}
28700	},
28701
28702	// Alt+page up/down moves focus to the previous/next tab (and activates)
28703	_handlePageNav: function( event ) {
28704		if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {
28705			this._activate( this._focusNextTab( this.options.active - 1, false ) );
28706			return true;
28707		}
28708		if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {
28709			this._activate( this._focusNextTab( this.options.active + 1, true ) );
28710			return true;
28711		}
28712	},
28713
28714	_findNextTab: function( index, goingForward ) {
28715		var lastTabIndex = this.tabs.length - 1;
28716
28717		function constrain() {
28718			if ( index > lastTabIndex ) {
28719				index = 0;
28720			}
28721			if ( index < 0 ) {
28722				index = lastTabIndex;
28723			}
28724			return index;
28725		}
28726
28727		while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {
28728			index = goingForward ? index + 1 : index - 1;
28729		}
28730
28731		return index;
28732	},
28733
28734	_focusNextTab: function( index, goingForward ) {
28735		index = this._findNextTab( index, goingForward );
28736		this.tabs.eq( index ).trigger( "focus" );
28737		return index;
28738	},
28739
28740	_setOption: function( key, value ) {
28741		if ( key === "active" ) {
28742
28743			// _activate() will handle invalid values and update this.options
28744			this._activate( value );
28745			return;
28746		}
28747
28748		this._super( key, value );
28749
28750		if ( key === "collapsible" ) {
28751			this._toggleClass( "ui-tabs-collapsible", null, value );
28752
28753			// Setting collapsible: false while collapsed; open first panel
28754			if ( !value && this.options.active === false ) {
28755				this._activate( 0 );
28756			}
28757		}
28758
28759		if ( key === "event" ) {
28760			this._setupEvents( value );
28761		}
28762
28763		if ( key === "heightStyle" ) {
28764			this._setupHeightStyle( value );
28765		}
28766	},
28767
28768	_sanitizeSelector: function( hash ) {
28769		return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : "";
28770	},
28771
28772	refresh: function() {
28773		var options = this.options,
28774			lis = this.tablist.children( ":has(a[href])" );
28775
28776		// Get disabled tabs from class attribute from HTML
28777		// this will get converted to a boolean if needed in _refresh()
28778		options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) {
28779			return lis.index( tab );
28780		} );
28781
28782		this._processTabs();
28783
28784		// Was collapsed or no tabs
28785		if ( options.active === false || !this.anchors.length ) {
28786			options.active = false;
28787			this.active = $();
28788
28789		// was active, but active tab is gone
28790		} else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {
28791
28792			// all remaining tabs are disabled
28793			if ( this.tabs.length === options.disabled.length ) {
28794				options.active = false;
28795				this.active = $();
28796
28797			// activate previous tab
28798			} else {
28799				this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );
28800			}
28801
28802		// was active, active tab still exists
28803		} else {
28804
28805			// make sure active index is correct
28806			options.active = this.tabs.index( this.active );
28807		}
28808
28809		this._refresh();
28810	},
28811
28812	_refresh: function() {
28813		this._setOptionDisabled( this.options.disabled );
28814		this._setupEvents( this.options.event );
28815		this._setupHeightStyle( this.options.heightStyle );
28816
28817		this.tabs.not( this.active ).attr( {
28818			"aria-selected": "false",
28819			"aria-expanded": "false",
28820			tabIndex: -1
28821		} );
28822		this.panels.not( this._getPanelForTab( this.active ) )
28823			.hide()
28824			.attr( {
28825				"aria-hidden": "true"
28826			} );
28827
28828		// Make sure one tab is in the tab order
28829		if ( !this.active.length ) {
28830			this.tabs.eq( 0 ).attr( "tabIndex", 0 );
28831		} else {
28832			this.active
28833				.attr( {
28834					"aria-selected": "true",
28835					"aria-expanded": "true",
28836					tabIndex: 0
28837				} );
28838			this._addClass( this.active, "ui-tabs-active", "ui-state-active" );
28839			this._getPanelForTab( this.active )
28840				.show()
28841				.attr( {
28842					"aria-hidden": "false"
28843				} );
28844		}
28845	},
28846
28847	_processTabs: function() {
28848		var that = this,
28849			prevTabs = this.tabs,
28850			prevAnchors = this.anchors,
28851			prevPanels = this.panels;
28852
28853		this.tablist = this._getList().attr( "role", "tablist" );
28854		this._addClass( this.tablist, "ui-tabs-nav",
28855			"ui-helper-reset ui-helper-clearfix ui-widget-header" );
28856
28857		// Prevent users from focusing disabled tabs via click
28858		this.tablist
28859			.on( "mousedown" + this.eventNamespace, "> li", function( event ) {
28860				if ( $( this ).is( ".ui-state-disabled" ) ) {
28861					event.preventDefault();
28862				}
28863			} )
28864
28865			// Support: IE <9
28866			// Preventing the default action in mousedown doesn't prevent IE
28867			// from focusing the element, so if the anchor gets focused, blur.
28868			// We don't have to worry about focusing the previously focused
28869			// element since clicking on a non-focusable element should focus
28870			// the body anyway.
28871			.on( "focus" + this.eventNamespace, ".ui-tabs-anchor", function() {
28872				if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) {
28873					this.blur();
28874				}
28875			} );
28876
28877		this.tabs = this.tablist.find( "> li:has(a[href])" )
28878			.attr( {
28879				role: "tab",
28880				tabIndex: -1
28881			} );
28882		this._addClass( this.tabs, "ui-tabs-tab", "ui-state-default" );
28883
28884		this.anchors = this.tabs.map( function() {
28885			return $( "a", this )[ 0 ];
28886		} )
28887			.attr( {
28888				tabIndex: -1
28889			} );
28890		this._addClass( this.anchors, "ui-tabs-anchor" );
28891
28892		this.panels = $();
28893
28894		this.anchors.each( function( i, anchor ) {
28895			var selector, panel, panelId,
28896				anchorId = $( anchor ).uniqueId().attr( "id" ),
28897				tab = $( anchor ).closest( "li" ),
28898				originalAriaControls = tab.attr( "aria-controls" );
28899
28900			// Inline tab
28901			if ( that._isLocal( anchor ) ) {
28902				selector = anchor.hash;
28903				panelId = selector.substring( 1 );
28904				panel = that.element.find( that._sanitizeSelector( selector ) );
28905
28906			// remote tab
28907			} else {
28908
28909				// If the tab doesn't already have aria-controls,
28910				// generate an id by using a throw-away element
28911				panelId = tab.attr( "aria-controls" ) || $( {} ).uniqueId()[ 0 ].id;
28912				selector = "#" + panelId;
28913				panel = that.element.find( selector );
28914				if ( !panel.length ) {
28915					panel = that._createPanel( panelId );
28916					panel.insertAfter( that.panels[ i - 1 ] || that.tablist );
28917				}
28918				panel.attr( "aria-live", "polite" );
28919			}
28920
28921			if ( panel.length ) {
28922				that.panels = that.panels.add( panel );
28923			}
28924			if ( originalAriaControls ) {
28925				tab.data( "ui-tabs-aria-controls", originalAriaControls );
28926			}
28927			tab.attr( {
28928				"aria-controls": panelId,
28929				"aria-labelledby": anchorId
28930			} );
28931			panel.attr( "aria-labelledby", anchorId );
28932		} );
28933
28934		this.panels.attr( "role", "tabpanel" );
28935		this._addClass( this.panels, "ui-tabs-panel", "ui-widget-content" );
28936
28937		// Avoid memory leaks (#10056)
28938		if ( prevTabs ) {
28939			this._off( prevTabs.not( this.tabs ) );
28940			this._off( prevAnchors.not( this.anchors ) );
28941			this._off( prevPanels.not( this.panels ) );
28942		}
28943	},
28944
28945	// Allow overriding how to find the list for rare usage scenarios (#7715)
28946	_getList: function() {
28947		return this.tablist || this.element.find( "ol, ul" ).eq( 0 );
28948	},
28949
28950	_createPanel: function( id ) {
28951		return $( "<div>" )
28952			.attr( "id", id )
28953			.data( "ui-tabs-destroy", true );
28954	},
28955
28956	_setOptionDisabled: function( disabled ) {
28957		var currentItem, li, i;
28958
28959		if ( Array.isArray( disabled ) ) {
28960			if ( !disabled.length ) {
28961				disabled = false;
28962			} else if ( disabled.length === this.anchors.length ) {
28963				disabled = true;
28964			}
28965		}
28966
28967		// Disable tabs
28968		for ( i = 0; ( li = this.tabs[ i ] ); i++ ) {
28969			currentItem = $( li );
28970			if ( disabled === true || $.inArray( i, disabled ) !== -1 ) {
28971				currentItem.attr( "aria-disabled", "true" );
28972				this._addClass( currentItem, null, "ui-state-disabled" );
28973			} else {
28974				currentItem.removeAttr( "aria-disabled" );
28975				this._removeClass( currentItem, null, "ui-state-disabled" );
28976			}
28977		}
28978
28979		this.options.disabled = disabled;
28980
28981		this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null,
28982			disabled === true );
28983	},
28984
28985	_setupEvents: function( event ) {
28986		var events = {};
28987		if ( event ) {
28988			$.each( event.split( " " ), function( index, eventName ) {
28989				events[ eventName ] = "_eventHandler";
28990			} );
28991		}
28992
28993		this._off( this.anchors.add( this.tabs ).add( this.panels ) );
28994
28995		// Always prevent the default action, even when disabled
28996		this._on( true, this.anchors, {
28997			click: function( event ) {
28998				event.preventDefault();
28999			}
29000		} );
29001		this._on( this.anchors, events );
29002		this._on( this.tabs, { keydown: "_tabKeydown" } );
29003		this._on( this.panels, { keydown: "_panelKeydown" } );
29004
29005		this._focusable( this.tabs );
29006		this._hoverable( this.tabs );
29007	},
29008
29009	_setupHeightStyle: function( heightStyle ) {
29010		var maxHeight,
29011			parent = this.element.parent();
29012
29013		if ( heightStyle === "fill" ) {
29014			maxHeight = parent.height();
29015			maxHeight -= this.element.outerHeight() - this.element.height();
29016
29017			this.element.siblings( ":visible" ).each( function() {
29018				var elem = $( this ),
29019					position = elem.css( "position" );
29020
29021				if ( position === "absolute" || position === "fixed" ) {
29022					return;
29023				}
29024				maxHeight -= elem.outerHeight( true );
29025			} );
29026
29027			this.element.children().not( this.panels ).each( function() {
29028				maxHeight -= $( this ).outerHeight( true );
29029			} );
29030
29031			this.panels.each( function() {
29032				$( this ).height( Math.max( 0, maxHeight -
29033					$( this ).innerHeight() + $( this ).height() ) );
29034			} )
29035				.css( "overflow", "auto" );
29036		} else if ( heightStyle === "auto" ) {
29037			maxHeight = 0;
29038			this.panels.each( function() {
29039				maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
29040			} ).height( maxHeight );
29041		}
29042	},
29043
29044	_eventHandler: function( event ) {
29045		var options = this.options,
29046			active = this.active,
29047			anchor = $( event.currentTarget ),
29048			tab = anchor.closest( "li" ),
29049			clickedIsActive = tab[ 0 ] === active[ 0 ],
29050			collapsing = clickedIsActive && options.collapsible,
29051			toShow = collapsing ? $() : this._getPanelForTab( tab ),
29052			toHide = !active.length ? $() : this._getPanelForTab( active ),
29053			eventData = {
29054				oldTab: active,
29055				oldPanel: toHide,
29056				newTab: collapsing ? $() : tab,
29057				newPanel: toShow
29058			};
29059
29060		event.preventDefault();
29061
29062		if ( tab.hasClass( "ui-state-disabled" ) ||
29063
29064				// tab is already loading
29065				tab.hasClass( "ui-tabs-loading" ) ||
29066
29067				// can't switch durning an animation
29068				this.running ||
29069
29070				// click on active header, but not collapsible
29071				( clickedIsActive && !options.collapsible ) ||
29072
29073				// allow canceling activation
29074				( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
29075			return;
29076		}
29077
29078		options.active = collapsing ? false : this.tabs.index( tab );
29079
29080		this.active = clickedIsActive ? $() : tab;
29081		if ( this.xhr ) {
29082			this.xhr.abort();
29083		}
29084
29085		if ( !toHide.length && !toShow.length ) {
29086			$.error( "jQuery UI Tabs: Mismatching fragment identifier." );
29087		}
29088
29089		if ( toShow.length ) {
29090			this.load( this.tabs.index( tab ), event );
29091		}
29092		this._toggle( event, eventData );
29093	},
29094
29095	// Handles show/hide for selecting tabs
29096	_toggle: function( event, eventData ) {
29097		var that = this,
29098			toShow = eventData.newPanel,
29099			toHide = eventData.oldPanel;
29100
29101		this.running = true;
29102
29103		function complete() {
29104			that.running = false;
29105			that._trigger( "activate", event, eventData );
29106		}
29107
29108		function show() {
29109			that._addClass( eventData.newTab.closest( "li" ), "ui-tabs-active", "ui-state-active" );
29110
29111			if ( toShow.length && that.options.show ) {
29112				that._show( toShow, that.options.show, complete );
29113			} else {
29114				toShow.show();
29115				complete();
29116			}
29117		}
29118
29119		// Start out by hiding, then showing, then completing
29120		if ( toHide.length && this.options.hide ) {
29121			this._hide( toHide, this.options.hide, function() {
29122				that._removeClass( eventData.oldTab.closest( "li" ),
29123					"ui-tabs-active", "ui-state-active" );
29124				show();
29125			} );
29126		} else {
29127			this._removeClass( eventData.oldTab.closest( "li" ),
29128				"ui-tabs-active", "ui-state-active" );
29129			toHide.hide();
29130			show();
29131		}
29132
29133		toHide.attr( "aria-hidden", "true" );
29134		eventData.oldTab.attr( {
29135			"aria-selected": "false",
29136			"aria-expanded": "false"
29137		} );
29138
29139		// If we're switching tabs, remove the old tab from the tab order.
vendor: 4,129 bytes, lines 29140-29311
29140		// If we're opening from collapsed state, remove the previous tab from the tab order.
29141		// If we're collapsing, then keep the collapsing tab in the tab order.
29142		if ( toShow.length && toHide.length ) {
29143			eventData.oldTab.attr( "tabIndex", -1 );
29144		} else if ( toShow.length ) {
29145			this.tabs.filter( function() {
29146				return $( this ).attr( "tabIndex" ) === 0;
29147			} )
29148				.attr( "tabIndex", -1 );
29149		}
29150
29151		toShow.attr( "aria-hidden", "false" );
29152		eventData.newTab.attr( {
29153			"aria-selected": "true",
29154			"aria-expanded": "true",
29155			tabIndex: 0
29156		} );
29157	},
29158
29159	_activate: function( index ) {
29160		var anchor,
29161			active = this._findActive( index );
29162
29163		// Trying to activate the already active panel
29164		if ( active[ 0 ] === this.active[ 0 ] ) {
29165			return;
29166		}
29167
29168		// Trying to collapse, simulate a click on the current active header
29169		if ( !active.length ) {
29170			active = this.active;
29171		}
29172
29173		anchor = active.find( ".ui-tabs-anchor" )[ 0 ];
29174		this._eventHandler( {
29175			target: anchor,
29176			currentTarget: anchor,
29177			preventDefault: $.noop
29178		} );
29179	},
29180
29181	_findActive: function( index ) {
29182		return index === false ? $() : this.tabs.eq( index );
29183	},
29184
29185	_getIndex: function( index ) {
29186
29187		// meta-function to give users option to provide a href string instead of a numerical index.
29188		if ( typeof index === "string" ) {
29189			index = this.anchors.index( this.anchors.filter( "[href$='" +
29190				$.escapeSelector( index ) + "']" ) );
29191		}
29192
29193		return index;
29194	},
29195
29196	_destroy: function() {
29197		if ( this.xhr ) {
29198			this.xhr.abort();
29199		}
29200
29201		this.tablist
29202			.removeAttr( "role" )
29203			.off( this.eventNamespace );
29204
29205		this.anchors
29206			.removeAttr( "role tabIndex" )
29207			.removeUniqueId();
29208
29209		this.tabs.add( this.panels ).each( function() {
29210			if ( $.data( this, "ui-tabs-destroy" ) ) {
29211				$( this ).remove();
29212			} else {
29213				$( this ).removeAttr( "role tabIndex " +
29214					"aria-live aria-busy aria-selected aria-labelledby aria-hidden aria-expanded" );
29215			}
29216		} );
29217
29218		this.tabs.each( function() {
29219			var li = $( this ),
29220				prev = li.data( "ui-tabs-aria-controls" );
29221			if ( prev ) {
29222				li
29223					.attr( "aria-controls", prev )
29224					.removeData( "ui-tabs-aria-controls" );
29225			} else {
29226				li.removeAttr( "aria-controls" );
29227			}
29228		} );
29229
29230		this.panels.show();
29231
29232		if ( this.options.heightStyle !== "content" ) {
29233			this.panels.css( "height", "" );
29234		}
29235	},
29236
29237	enable: function( index ) {
29238		var disabled = this.options.disabled;
29239		if ( disabled === false ) {
29240			return;
29241		}
29242
29243		if ( index === undefined ) {
29244			disabled = false;
29245		} else {
29246			index = this._getIndex( index );
29247			if ( Array.isArray( disabled ) ) {
29248				disabled = $.map( disabled, function( num ) {
29249					return num !== index ? num : null;
29250				} );
29251			} else {
29252				disabled = $.map( this.tabs, function( li, num ) {
29253					return num !== index ? num : null;
29254				} );
29255			}
29256		}
29257		this._setOptionDisabled( disabled );
29258	},
29259
29260	disable: function( index ) {
29261		var disabled = this.options.disabled;
29262		if ( disabled === true ) {
29263			return;
29264		}
29265
29266		if ( index === undefined ) {
29267			disabled = true;
29268		} else {
29269			index = this._getIndex( index );
29270			if ( $.inArray( index, disabled ) !== -1 ) {
29271				return;
29272			}
29273			if ( Array.isArray( disabled ) ) {
29274				disabled = $.merge( [ index ], disabled ).sort();
29275			} else {
29276				disabled = [ index ];
29277			}
29278		}
29279		this._setOptionDisabled( disabled );
29280	},
29281
29282	load: function( index, event ) {
29283		index = this._getIndex( index );
29284		var that = this,
29285			tab = this.tabs.eq( index ),
29286			anchor = tab.find( ".ui-tabs-anchor" ),
29287			panel = this._getPanelForTab( tab ),
29288			eventData = {
29289				tab: tab,
29290				panel: panel
29291			},
29292			complete = function( jqXHR, status ) {
29293				if ( status === "abort" ) {
29294					that.panels.stop( false, true );
29295				}
29296
29297				that._removeClass( tab, "ui-tabs-loading" );
29298				panel.removeAttr( "aria-busy" );
29299
29300				if ( jqXHR === that.xhr ) {
29301					delete that.xhr;
29302				}
29303			};
29304
29305		// Not remote
29306		if ( this._isLocal( anchor[ 0 ] ) ) {
29307			return;
29308		}
29309
29310		this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );
29311
vendor: 17,064 bytes, lines 29312-29910
29312		// Support: jQuery <1.8
29313		// jQuery <1.8 returns false if the request is canceled in beforeSend,
29314		// but as of 1.8, $.ajax() always returns a jqXHR object.
29315		if ( this.xhr && this.xhr.statusText !== "canceled" ) {
29316			this._addClass( tab, "ui-tabs-loading" );
29317			panel.attr( "aria-busy", "true" );
29318
29319			this.xhr
29320				.done( function( response, status, jqXHR ) {
29321
29322					// support: jQuery <1.8
29323					// http://bugs.jquery.com/ticket/11778
29324					setTimeout( function() {
29325						panel.html( response );
29326						that._trigger( "load", event, eventData );
29327
29328						complete( jqXHR, status );
29329					}, 1 );
29330				} )
29331				.fail( function( jqXHR, status ) {
29332
29333					// support: jQuery <1.8
29334					// http://bugs.jquery.com/ticket/11778
29335					setTimeout( function() {
29336						complete( jqXHR, status );
29337					}, 1 );
29338				} );
29339		}
29340	},
29341
29342	_ajaxSettings: function( anchor, event, eventData ) {
29343		var that = this;
29344		return {
29345
29346			// Support: IE <11 only
29347			// Strip any hash that exists to prevent errors with the Ajax request
29348			url: anchor.attr( "href" ).replace( /#.*$/, "" ),
29349			beforeSend: function( jqXHR, settings ) {
29350				return that._trigger( "beforeLoad", event,
29351					$.extend( { jqXHR: jqXHR, ajaxSettings: settings }, eventData ) );
29352			}
29353		};
29354	},
29355
29356	_getPanelForTab: function( tab ) {
29357		var id = $( tab ).attr( "aria-controls" );
29358		return this.element.find( this._sanitizeSelector( "#" + id ) );
29359	}
29360} );
29361
29362// DEPRECATED
29363// TODO: Switch return back to widget declaration at top of file when this is removed
29364if ( $.uiBackCompat !== false ) {
29365
29366	// Backcompat for ui-tab class (now ui-tabs-tab)
29367	$.widget( "ui.tabs", $.ui.tabs, {
29368		_processTabs: function() {
29369			this._superApply( arguments );
29370			this._addClass( this.tabs, "ui-tab" );
29371		}
29372	} );
29373}
29374
29375var widgetsTabs = $.ui.tabs;
29376
29377
29378/*!
29379 * jQuery UI Tooltip 1.13.2
29380 * http://jqueryui.com
29381 *
29382 * Copyright jQuery Foundation and other contributors
29383 * Released under the MIT license.
29384 * http://jquery.org/license
29385 */
29386
29387//>>label: Tooltip
29388//>>group: Widgets
29389//>>description: Shows additional information for any element on hover or focus.
29390//>>docs: http://api.jqueryui.com/tooltip/
29391//>>demos: http://jqueryui.com/tooltip/
29392//>>css.structure: ../../themes/base/core.css
29393//>>css.structure: ../../themes/base/tooltip.css
29394//>>css.theme: ../../themes/base/theme.css
29395
29396
29397$.widget( "ui.tooltip", {
29398	version: "1.13.2",
29399	options: {
29400		classes: {
29401			"ui-tooltip": "ui-corner-all ui-widget-shadow"
29402		},
29403		content: function() {
29404			var title = $( this ).attr( "title" );
29405
29406			// Escape title, since we're going from an attribute to raw HTML
29407			return $( "<a>" ).text( title ).html();
29408		},
29409		hide: true,
29410
29411		// Disabled elements have inconsistent behavior across browsers (#8661)
29412		items: "[title]:not([disabled])",
29413		position: {
29414			my: "left top+15",
29415			at: "left bottom",
29416			collision: "flipfit flip"
29417		},
29418		show: true,
29419		track: false,
29420
29421		// Callbacks
29422		close: null,
29423		open: null
29424	},
29425
29426	_addDescribedBy: function( elem, id ) {
29427		var describedby = ( elem.attr( "aria-describedby" ) || "" ).split( /\s+/ );
29428		describedby.push( id );
29429		elem
29430			.data( "ui-tooltip-id", id )
29431			.attr( "aria-describedby", String.prototype.trim.call( describedby.join( " " ) ) );
29432	},
29433
29434	_removeDescribedBy: function( elem ) {
29435		var id = elem.data( "ui-tooltip-id" ),
29436			describedby = ( elem.attr( "aria-describedby" ) || "" ).split( /\s+/ ),
29437			index = $.inArray( id, describedby );
29438
29439		if ( index !== -1 ) {
29440			describedby.splice( index, 1 );
29441		}
29442
29443		elem.removeData( "ui-tooltip-id" );
29444		describedby = String.prototype.trim.call( describedby.join( " " ) );
29445		if ( describedby ) {
29446			elem.attr( "aria-describedby", describedby );
29447		} else {
29448			elem.removeAttr( "aria-describedby" );
29449		}
29450	},
29451
29452	_create: function() {
29453		this._on( {
29454			mouseover: "open",
29455			focusin: "open"
29456		} );
29457
29458		// IDs of generated tooltips, needed for destroy
29459		this.tooltips = {};
29460
29461		// IDs of parent tooltips where we removed the title attribute
29462		this.parents = {};
29463
29464		// Append the aria-live region so tooltips announce correctly
29465		this.liveRegion = $( "<div>" )
29466			.attr( {
29467				role: "log",
29468				"aria-live": "assertive",
29469				"aria-relevant": "additions"
29470			} )
29471			.appendTo( this.document[ 0 ].body );
29472		this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" );
29473
29474		this.disabledTitles = $( [] );
29475	},
29476
29477	_setOption: function( key, value ) {
29478		var that = this;
29479
29480		this._super( key, value );
29481
29482		if ( key === "content" ) {
29483			$.each( this.tooltips, function( id, tooltipData ) {
29484				that._updateContent( tooltipData.element );
29485			} );
29486		}
29487	},
29488
29489	_setOptionDisabled: function( value ) {
29490		this[ value ? "_disable" : "_enable" ]();
29491	},
29492
29493	_disable: function() {
29494		var that = this;
29495
29496		// Close open tooltips
29497		$.each( this.tooltips, function( id, tooltipData ) {
29498			var event = $.Event( "blur" );
29499			event.target = event.currentTarget = tooltipData.element[ 0 ];
29500			that.close( event, true );
29501		} );
29502
29503		// Remove title attributes to prevent native tooltips
29504		this.disabledTitles = this.disabledTitles.add(
29505			this.element.find( this.options.items ).addBack()
29506				.filter( function() {
29507					var element = $( this );
29508					if ( element.is( "[title]" ) ) {
29509						return element
29510							.data( "ui-tooltip-title", element.attr( "title" ) )
29511							.removeAttr( "title" );
29512					}
29513				} )
29514		);
29515	},
29516
29517	_enable: function() {
29518
29519		// restore title attributes
29520		this.disabledTitles.each( function() {
29521			var element = $( this );
29522			if ( element.data( "ui-tooltip-title" ) ) {
29523				element.attr( "title", element.data( "ui-tooltip-title" ) );
29524			}
29525		} );
29526		this.disabledTitles = $( [] );
29527	},
29528
29529	open: function( event ) {
29530		var that = this,
29531			target = $( event ? event.target : this.element )
29532
29533				// we need closest here due to mouseover bubbling,
29534				// but always pointing at the same event target
29535				.closest( this.options.items );
29536
29537		// No element to show a tooltip for or the tooltip is already open
29538		if ( !target.length || target.data( "ui-tooltip-id" ) ) {
29539			return;
29540		}
29541
29542		if ( target.attr( "title" ) ) {
29543			target.data( "ui-tooltip-title", target.attr( "title" ) );
29544		}
29545
29546		target.data( "ui-tooltip-open", true );
29547
29548		// Kill parent tooltips, custom or native, for hover
29549		if ( event && event.type === "mouseover" ) {
29550			target.parents().each( function() {
29551				var parent = $( this ),
29552					blurEvent;
29553				if ( parent.data( "ui-tooltip-open" ) ) {
29554					blurEvent = $.Event( "blur" );
29555					blurEvent.target = blurEvent.currentTarget = this;
29556					that.close( blurEvent, true );
29557				}
29558				if ( parent.attr( "title" ) ) {
29559					parent.uniqueId();
29560					that.parents[ this.id ] = {
29561						element: this,
29562						title: parent.attr( "title" )
29563					};
29564					parent.attr( "title", "" );
29565				}
29566			} );
29567		}
29568
29569		this._registerCloseHandlers( event, target );
29570		this._updateContent( target, event );
29571	},
29572
29573	_updateContent: function( target, event ) {
29574		var content,
29575			contentOption = this.options.content,
29576			that = this,
29577			eventType = event ? event.type : null;
29578
29579		if ( typeof contentOption === "string" || contentOption.nodeType ||
29580				contentOption.jquery ) {
29581			return this._open( event, target, contentOption );
29582		}
29583
29584		content = contentOption.call( target[ 0 ], function( response ) {
29585
29586			// IE may instantly serve a cached response for ajax requests
29587			// delay this call to _open so the other call to _open runs first
29588			that._delay( function() {
29589
29590				// Ignore async response if tooltip was closed already
29591				if ( !target.data( "ui-tooltip-open" ) ) {
29592					return;
29593				}
29594
29595				// JQuery creates a special event for focusin when it doesn't
29596				// exist natively. To improve performance, the native event
29597				// object is reused and the type is changed. Therefore, we can't
29598				// rely on the type being correct after the event finished
29599				// bubbling, so we set it back to the previous value. (#8740)
29600				if ( event ) {
29601					event.type = eventType;
29602				}
29603				this._open( event, target, response );
29604			} );
29605		} );
29606		if ( content ) {
29607			this._open( event, target, content );
29608		}
29609	},
29610
29611	_open: function( event, target, content ) {
29612		var tooltipData, tooltip, delayedShow, a11yContent,
29613			positionOption = $.extend( {}, this.options.position );
29614
29615		if ( !content ) {
29616			return;
29617		}
29618
29619		// Content can be updated multiple times. If the tooltip already
29620		// exists, then just update the content and bail.
29621		tooltipData = this._find( target );
29622		if ( tooltipData ) {
29623			tooltipData.tooltip.find( ".ui-tooltip-content" ).html( content );
29624			return;
29625		}
29626
29627		// If we have a title, clear it to prevent the native tooltip
29628		// we have to check first to avoid defining a title if none exists
29629		// (we don't want to cause an element to start matching [title])
29630		//
29631		// We use removeAttr only for key events, to allow IE to export the correct
29632		// accessible attributes. For mouse events, set to empty string to avoid
29633		// native tooltip showing up (happens only when removing inside mouseover).
29634		if ( target.is( "[title]" ) ) {
29635			if ( event && event.type === "mouseover" ) {
29636				target.attr( "title", "" );
29637			} else {
29638				target.removeAttr( "title" );
29639			}
29640		}
29641
29642		tooltipData = this._tooltip( target );
29643		tooltip = tooltipData.tooltip;
29644		this._addDescribedBy( target, tooltip.attr( "id" ) );
29645		tooltip.find( ".ui-tooltip-content" ).html( content );
29646
29647		// Support: Voiceover on OS X, JAWS on IE <= 9
29648		// JAWS announces deletions even when aria-relevant="additions"
29649		// Voiceover will sometimes re-read the entire log region's contents from the beginning
29650		this.liveRegion.children().hide();
29651		a11yContent = $( "<div>" ).html( tooltip.find( ".ui-tooltip-content" ).html() );
29652		a11yContent.removeAttr( "name" ).find( "[name]" ).removeAttr( "name" );
29653		a11yContent.removeAttr( "id" ).find( "[id]" ).removeAttr( "id" );
29654		a11yContent.appendTo( this.liveRegion );
29655
29656		function position( event ) {
29657			positionOption.of = event;
29658			if ( tooltip.is( ":hidden" ) ) {
29659				return;
29660			}
29661			tooltip.position( positionOption );
29662		}
29663		if ( this.options.track && event && /^mouse/.test( event.type ) ) {
29664			this._on( this.document, {
29665				mousemove: position
29666			} );
29667
29668			// trigger once to override element-relative positioning
29669			position( event );
29670		} else {
29671			tooltip.position( $.extend( {
29672				of: target
29673			}, this.options.position ) );
29674		}
29675
29676		tooltip.hide();
29677
29678		this._show( tooltip, this.options.show );
29679
29680		// Handle tracking tooltips that are shown with a delay (#8644). As soon
29681		// as the tooltip is visible, position the tooltip using the most recent
29682		// event.
29683		// Adds the check to add the timers only when both delay and track options are set (#14682)
29684		if ( this.options.track && this.options.show && this.options.show.delay ) {
29685			delayedShow = this.delayedShow = setInterval( function() {
29686				if ( tooltip.is( ":visible" ) ) {
29687					position( positionOption.of );
29688					clearInterval( delayedShow );
29689				}
29690			}, 13 );
29691		}
29692
29693		this._trigger( "open", event, { tooltip: tooltip } );
29694	},
29695
29696	_registerCloseHandlers: function( event, target ) {
29697		var events = {
29698			keyup: function( event ) {
29699				if ( event.keyCode === $.ui.keyCode.ESCAPE ) {
29700					var fakeEvent = $.Event( event );
29701					fakeEvent.currentTarget = target[ 0 ];
29702					this.close( fakeEvent, true );
29703				}
29704			}
29705		};
29706
29707		// Only bind remove handler for delegated targets. Non-delegated
29708		// tooltips will handle this in destroy.
29709		if ( target[ 0 ] !== this.element[ 0 ] ) {
29710			events.remove = function() {
29711				var targetElement = this._find( target );
29712				if ( targetElement ) {
29713					this._removeTooltip( targetElement.tooltip );
29714				}
29715			};
29716		}
29717
29718		if ( !event || event.type === "mouseover" ) {
29719			events.mouseleave = "close";
29720		}
29721		if ( !event || event.type === "focusin" ) {
29722			events.focusout = "close";
29723		}
29724		this._on( true, target, events );
29725	},
29726
29727	close: function( event ) {
29728		var tooltip,
29729			that = this,
29730			target = $( event ? event.currentTarget : this.element ),
29731			tooltipData = this._find( target );
29732
29733		// The tooltip may already be closed
29734		if ( !tooltipData ) {
29735
29736			// We set ui-tooltip-open immediately upon open (in open()), but only set the
29737			// additional data once there's actually content to show (in _open()). So even if the
29738			// tooltip doesn't have full data, we always remove ui-tooltip-open in case we're in
29739			// the period between open() and _open().
29740			target.removeData( "ui-tooltip-open" );
29741			return;
29742		}
29743
29744		tooltip = tooltipData.tooltip;
29745
29746		// Disabling closes the tooltip, so we need to track when we're closing
29747		// to avoid an infinite loop in case the tooltip becomes disabled on close
29748		if ( tooltipData.closing ) {
29749			return;
29750		}
29751
29752		// Clear the interval for delayed tracking tooltips
29753		clearInterval( this.delayedShow );
29754
29755		// Only set title if we had one before (see comment in _open())
29756		// If the title attribute has changed since open(), don't restore
29757		if ( target.data( "ui-tooltip-title" ) && !target.attr( "title" ) ) {
29758			target.attr( "title", target.data( "ui-tooltip-title" ) );
29759		}
29760
29761		this._removeDescribedBy( target );
29762
29763		tooltipData.hiding = true;
29764		tooltip.stop( true );
29765		this._hide( tooltip, this.options.hide, function() {
29766			that._removeTooltip( $( this ) );
29767		} );
29768
29769		target.removeData( "ui-tooltip-open" );
29770		this._off( target, "mouseleave focusout keyup" );
29771
29772		// Remove 'remove' binding only on delegated targets
29773		if ( target[ 0 ] !== this.element[ 0 ] ) {
29774			this._off( target, "remove" );
29775		}
29776		this._off( this.document, "mousemove" );
29777
29778		if ( event && event.type === "mouseleave" ) {
29779			$.each( this.parents, function( id, parent ) {
29780				$( parent.element ).attr( "title", parent.title );
29781				delete that.parents[ id ];
29782			} );
29783		}
29784
29785		tooltipData.closing = true;
29786		this._trigger( "close", event, { tooltip: tooltip } );
29787		if ( !tooltipData.hiding ) {
29788			tooltipData.closing = false;
29789		}
29790	},
29791
29792	_tooltip: function( element ) {
29793		var tooltip = $( "<div>" ).attr( "role", "tooltip" ),
29794			content = $( "<div>" ).appendTo( tooltip ),
29795			id = tooltip.uniqueId().attr( "id" );
29796
29797		this._addClass( content, "ui-tooltip-content" );
29798		this._addClass( tooltip, "ui-tooltip", "ui-widget ui-widget-content" );
29799
29800		tooltip.appendTo( this._appendTo( element ) );
29801
29802		return this.tooltips[ id ] = {
29803			element: element,
29804			tooltip: tooltip
29805		};
29806	},
29807
29808	_find: function( target ) {
29809		var id = target.data( "ui-tooltip-id" );
29810		return id ? this.tooltips[ id ] : null;
29811	},
29812
29813	_removeTooltip: function( tooltip ) {
29814
29815		// Clear the interval for delayed tracking tooltips
29816		clearInterval( this.delayedShow );
29817
29818		tooltip.remove();
29819		delete this.tooltips[ tooltip.attr( "id" ) ];
29820	},
29821
29822	_appendTo: function( target ) {
29823		var element = target.closest( ".ui-front, dialog" );
29824
29825		if ( !element.length ) {
29826			element = this.document[ 0 ].body;
29827		}
29828
29829		return element;
29830	},
29831
29832	_destroy: function() {
29833		var that = this;
29834
29835		// Close open tooltips
29836		$.each( this.tooltips, function( id, tooltipData ) {
29837
29838			// Delegate to close method to handle common cleanup
29839			var event = $.Event( "blur" ),
29840				element = tooltipData.element;
29841			event.target = event.currentTarget = element[ 0 ];
29842			that.close( event, true );
29843
29844			// Remove immediately; destroying an open tooltip doesn't use the
29845			// hide animation
29846			$( "#" + id ).remove();
29847
29848			// Restore the title
29849			if ( element.data( "ui-tooltip-title" ) ) {
29850
29851				// If the title attribute has changed since open(), don't restore
29852				if ( !element.attr( "title" ) ) {
29853					element.attr( "title", element.data( "ui-tooltip-title" ) );
29854				}
29855				element.removeData( "ui-tooltip-title" );
29856			}
29857		} );
29858		this.liveRegion.remove();
29859	}
29860} );
29861
29862// DEPRECATED
29863// TODO: Switch return back to widget declaration at top of file when this is removed
29864if ( $.uiBackCompat !== false ) {
29865
29866	// Backcompat for tooltipClass option
29867	$.widget( "ui.tooltip", $.ui.tooltip, {
29868		options: {
29869			tooltipClass: null
29870		},
29871		_tooltip: function() {
29872			var tooltipData = this._superApply( arguments );
29873			if ( this.options.tooltipClass ) {
29874				tooltipData.tooltip.addClass( this.options.tooltipClass );
29875			}
29876			return tooltipData;
29877		}
29878	} );
29879}
29880
29881var widgetsTooltip = $.ui.tooltip;
29882
29883
29884
29885
29886} );
29887// jquery.dialog
29888(function () {
29889	
29890	var dialog = jQuery.fn.dialog;
29891
29892	jQuery.fn.dialog = function() {
29893
29894		var check_methods = ['destroy', 'close'];
29895
29896		if (arguments && arguments.length > 0 && check_methods.indexOf(arguments[0]) > -1) {
29897			try {
29898				return dialog.apply(this, arguments);
29899			} catch(err) {
29900				// if we call methods on dialog prior to initialization and error will be thrown,
29901				// just ignore it.
29902				return this;
29903			}
29904		}
29905
29906		return dialog.apply(this, arguments);
29907	}
29908
29909})();
29910// ColorBox v1.3.15 - a full featured, light-weight, customizable lightbox based on jQuery 1.3+
29911// Copyright (c) 2010 Jack Moore - [email protected]
29912// Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
29913(function ($, window) {
29914	
29915	var
29916	// ColorBox Default Settings.	
29917	// See http://colorpowered.com/colorbox for details.
29918	defaults = {
29919		transition: "elastic",
29920		speed: 300,
29921		width: false,
29922		initialWidth: "600",
29923		innerWidth: false,
29924		maxWidth: false,
29925		height: false,
29926		initialHeight: "450",
29927		innerHeight: false,
29928		maxHeight: false,
29929		scalePhotos: true,
29930		scrolling: true,
29931		inline: false,
29932		html: false,
29933		iframe: false,
29934		photo: false,
29935		href: false,
29936		title: false,
29937		rel: false,
29938		opacity: 0.9,
29939		preloading: true,
29940		current: "image {current} of {total}",
29941		previous: "previous",
29942		next: "next",
29943		close: "close",
29944		open: false,
29945		returnFocus: true,
29946		loop: true,
29947		slideshow: false,
29948		slideshowAuto: true,
29949		slideshowSpeed: 2500,
29950		slideshowStart: "start slideshow",
29951		slideshowStop: "stop slideshow",
29952		onOpen: false,
29953		onLoad: false,
29954		onComplete: false,
29955		onCleanup: false,
29956		onClosed: false,
29957		overlayClose: true,		
29958		escKey: true,
29959		arrowKey: true
29960	},
29961	
29962	// Abstracting the HTML and event identifiers for easy rebranding
29963	colorbox = 'colorbox',
29964	prefix = 'cbox',
29965	
29966	// Events	
29967	event_open = prefix + '_open',
29968	event_load = prefix + '_load',
29969	event_complete = prefix + '_complete',
29970	event_cleanup = prefix + '_cleanup',
29971	event_closed = prefix + '_closed',
29972	event_purge = prefix + '_purge',
29973	event_loaded = prefix + '_loaded',
29974	
29975	// Special Handling for IE
29976	isIE = $.browser.msie && !$.support.opacity, // feature detection alone gave a false positive on at least one phone browser and on some development versions of Chrome.
29977	isIE6 = isIE && $.browser.version < 7,
29978	event_ie6 = prefix + '_IE6',
29979
29980	// Cached jQuery Object Variables
29981	$overlay,
29982	$box,
29983	$wrap,
29984	$content,
29985	$topBorder,
29986	$leftBorder,
29987	$rightBorder,
29988	$bottomBorder,
29989	$related,
29990	$window,
29991	$loaded,
29992	$loadingBay,
29993	$loadingOverlay,
29994	$title,
29995	$current,
29996	$slideshow,
29997	$next,
29998	$prev,
29999	$close,
30000
30001	// Variables for cached values or use across multiple functions
30002	interfaceHeight,
30003	interfaceWidth,
30004	loadedHeight,
30005	loadedWidth,
30006	element,
30007	index,
30008	settings,
30009	open,
30010	active,
30011	closing = false,
30012	
30013	publicMethod,
30014	boxElement = prefix + 'Element';
30015	
30016	// ****************
30017	// HELPER FUNCTIONS
30018	// ****************
30019
30020	// jQuery object generator to reduce code size
30021	function $div(id, css) { 
30022		id = id ? ' id="' + prefix + id + '"' : '';
30023		css = css ? ' style="' + css + '"' : '';
30024		return $('<div' + id + css + '/>');
30025	}
30026
30027	// Convert % values to pixels
30028	function setSize(size, dimension) {
30029		dimension = dimension === 'x' ? $window.width() : $window.height();
30030		return (typeof size === 'string') ? Math.round((/%/.test(size) ? (dimension / 100) * parseInt(size, 10) : parseInt(size, 10))) : size;
30031	}
30032	
30033	// Checks an href to see if it is a photo.
30034	// There is a force photo option (photo: true) for hrefs that cannot be matched by this regex.
30035	function isImage(url) {
30036		return settings.photo || /\.(gif|png|jpg|jpeg|bmp)(?:\?([^#]*))?(?:#(\.*))?$/i.test(url);
30037	}
30038	
30039	// Assigns function results to their respective settings.  This allows functions to be used as values.
30040	function process(settings) {
30041		for (var i in settings) {
30042			if ($.isFunction(settings[i]) && i.substring(0, 2) !== 'on') { // checks to make sure the function isn't one of the callbacks, they will be handled at the appropriate time.
30043			    settings[i] = settings[i].call(element);
30044			}
30045		}
30046		settings.rel = settings.rel || element.rel || 'nofollow';
30047		settings.href = settings.href || $(element).attr('href');
30048		settings.title = settings.title || element.title;
30049		return settings;
30050	}
30051
30052	function trigger(event, callback) {
30053		if (callback) {
30054			callback.call(element);
30055		}
30056		$.event.trigger(event);
30057	}
30058
30059	// Slideshow functionality
30060	function slideshow() {
30061		var
30062		timeOut,
30063		className = prefix + "Slideshow_",
30064		click = "click." + prefix,
30065		start,
30066		stop,
30067		clear;
30068		
30069		if (settings.slideshow && $related[1]) {
30070			start = function () {
30071				$slideshow
30072					.text(settings.slideshowStop)
30073					.unbind(click)
30074					.bind(event_complete, function () {
30075						if (index < $related.length - 1 || settings.loop) {
30076							timeOut = setTimeout(publicMethod.next, settings.slideshowSpeed);
30077						}
30078					})
30079					.bind(event_load, function () {
30080						clearTimeout(timeOut);
30081					})
30082					.one(click + ' ' + event_cleanup, stop);
30083				$box.removeClass(className + "off").addClass(className + "on");
30084				timeOut = setTimeout(publicMethod.next, settings.slideshowSpeed);
30085			};
30086			
30087			stop = function () {
30088				clearTimeout(timeOut);
30089				$slideshow
30090					.text(settings.slideshowStart)
30091					.unbind([event_complete, event_load, event_cleanup, click].join(' '))
30092					.one(click, start);
30093				$box.removeClass(className + "on").addClass(className + "off");
30094			};
30095			
30096			if (settings.slideshowAuto) {
30097				start();
30098			} else {
30099				stop();
30100			}
30101		}
30102	}
30103
30104	function launch(elem) {
30105		if (!closing) {
30106			
30107			element = elem;
30108			
30109			settings = process($.extend({}, $.data(element, colorbox)));
30110			
30111			$related = $(element);
30112			
30113			index = 0;
30114			
30115			if (settings.rel !== 'nofollow') {
30116				$related = $('.' + boxElement).filter(function () {
30117					var relRelated = $.data(this, colorbox).rel || this.rel;
30118					return (relRelated === settings.rel);
30119				});
30120				index = $related.index(element);
30121				
30122				// Check direct calls to ColorBox.
30123				if (index === -1) {
30124					$related = $related.add(element);
30125					index = $related.length - 1;
30126				}
30127			}
30128			
30129			if (!open) {
30130				open = active = true; // Prevents the page-change action from queuing up if the visitor holds down the left or right 
30130keys.
30131				
30132				$box.show();
30133				
30134				if (settings.returnFocus) {
30135					try {
30136						element.blur();
30137						$(element).one(event_closed, function () {
30138							try {
30139								this.focus();
30140							} catch (e) {
30141								// do nothing
30142							}
30143						});
30144					} catch (e) {
30145						// do nothing
30146					}
30147				}
30148				
30149				// +settings.opacity avoids a problem in IE when using non-zero-prefixed-string-values, like '.5'
30150				$overlay.css({"opacity": +settings.opacity, "cursor": settings.overlayClose ? "pointer" : "auto"}).show();
30151				
30152				// Opens inital empty ColorBox prior to content being loaded.
30153				settings.w = setSize(settings.initialWidth, 'x');
30154				settings.h = setSize(settings.initialHeight, 'y');
30155				publicMethod.position(0);
30156				
30157				if (isIE6) {
30158					$window.bind('resize.' + event_ie6 + ' scroll.' + event_ie6, function () {
30159						$overlay.css({width: $window.width(), height: $window.height(), top: $window.scrollTop(), left: $window.scrollLeft()});
30160					}).trigger('scroll.' + event_ie6);
30161				}
30162				
30163				trigger(event_open, settings.onOpen);
30164				
30165				$current.add($prev).add($next).add($slideshow).add($title).hide();
30166				
30167				$close.html(settings.close).show();
30168			}
30169			
30170			publicMethod.load(true);
30171		}
30172	}
30173
30174	// ****************
30175	// PUBLIC FUNCTIONS
30176	// Usage format: $.fn.colorbox.close();
30177	// Usage from within an iframe: parent.$.fn.colorbox.close();
30178	// ****************
30179	
30180	publicMethod = $.fn[colorbox] = $[colorbox] = function (options, callback) {
30181		var $this = this, autoOpen;
30182		
30183		if (!$this[0] && $this.selector) { // if a selector was given and it didn't match any elements, go ahead and exit.
30184			return $this;
30185		}
30186		
30187		options = options || {};
30188		
30189		if (callback) {
30190			options.onComplete = callback;
30191		}
30192		
30193		if (!$this[0] || $this.selector === undefined) { // detects $.colorbox() and $.fn.colorbox()
30194			$this = $('<a/>');
30195			options.open = true; // assume an immediate open
30196		}
30197		
30198		$this.each(function () {
30199			$.data(this, colorbox, $.extend({}, $.data(this, colorbox) || defaults, options));
30200			$(this).addClass(boxElement);
30201		});
30202		
30203		autoOpen = options.open;
30204		
30205		if ($.isFunction(autoOpen)) {
30206			autoOpen = autoOpen.call($this);
30207		}
30208		
30209		if (autoOpen) {
30210			launch($this[0]);
30211		}
30212		
30213		return $this;
30214	};
30215
30216	// Initialize ColorBox: store common calculations, preload the interface graphics, append the html.
30217	// This preps colorbox for a speedy open when clicked, and lightens the burdon on the browser by only
30218	// having to run once, instead of each time colorbox is opened.
30219	publicMethod.init = function () {
30220		// Create & Append jQuery Objects
30221		$window = $(window);
30222		$box = $div().attr({id: colorbox, 'class': isIE ? prefix + 'IE' : ''});
30223		$overlay = $div("Overlay", isIE6 ? 'position:absolute' : '').hide();
30224		
30225		$wrap = $div("Wrapper");
30226		$content = $div("Content").append(
30227			$loaded = $div("LoadedContent", 'width:0; height:0; overflow:hidden'),
30228			$loadingOverlay = $div("LoadingOverlay").add($div("LoadingGraphic")),
30229			$title = $div("Title"),
30230			$current = $div("Current"),
30231			$next = $div("Next"),
30232			$prev = $div("Previous"),
30233			$slideshow = $div("Slideshow").bind(event_open, slideshow),
30234			$close = $div("Close")
30235		);
30236		$wrap.append( // The 3x3 Grid that makes up ColorBox
30237			$div().append(
30238				$div("TopLeft"),
30239				$topBorder = $div("TopCenter"),
30240				$div("TopRight")
30241			),
30242			$div(false, 'clear:left').append(
30243				$leftBorder = $div("MiddleLeft"),
30244				$content,
30245				$rightBorder = $div("MiddleRight")
30246			),
30247			$div(false, 'clear:left').append(
30248				$div("BottomLeft"),
30249				$bottomBorder = $div("BottomCenter"),
30250				$div("BottomRight")
30251			)
30252		).children().children().css({'float': 'left'});
30253		
30254		$loadingBay = $div(false, 'position:absolute; width:9999px; visibility:hidden; display:none');
30255		
30256		$('body').prepend($overlay, $box.append($wrap, $loadingBay));
30257		
30258		$content.children()
30259		.hover(function () {
30260			$(this).addClass('hover');
30261		}, function () {
30262			$(this).removeClass('hover');
30263		}).addClass('hover');
30264		
30265		// Cache values needed for size calculations
30266		interfaceHeight = $topBorder.height() + $bottomBorder.height() + $content.outerHeight(true) - $content.height();//Subtraction needed for IE6
30267		interfaceWidth = $leftBorder.width() + $rightBorder.width() + $content.outerWidth(true) - $content.width();
30268		loadedHeight = $loaded.outerHeight(true);
30269		loadedWidth = $loaded.outerWidth(true);
30270		
30271		// Setting padding to remove the need to do size conversions during the animation step.
30272		$box.css({"padding-bottom": interfaceHeight, "padding-right": interfaceWidth}).hide();
30273		
30274		// Setup button events.
30275		$next.click(publicMethod.next);
30276		$prev.click(publicMethod.prev);
30277		$close.click(publicMethod.close);
30278		
30279		// Adding the 'hover' class allowed the browser to load the hover-state
30280		// background graphics.  The class can now can be removed.
30281		$content.children().removeClass('hover');
30282		
30283		$('.' + boxElement).live('click', function (e) {
30284			// checks to see if it was a non-left mouse-click and for clicks modified with ctrl, shift, or alt.
30285			if (!((e.button !== 0 && typeof e.button !== 'undefined') || e.ctrlKey || e.shiftKey || e.altKey)) {
30286				e.preventDefault();
30287				launch(this);
30288			}
30289		});
30290		
30291		$overlay.click(function () {
30292			if (settings.overlayClose) {
30293				publicMethod.close();
30294			}
30295		});
30296		
30297		// Set Navigation Key Bindings
30298		$(document).bind("keydown", function (e) {
30299			if (open && settings.escKey && e.keyCode === 27) {
30300				e.preventDefault();
30301				publicMethod.close();
30302			}
30303			if (open && settings.arrowKey && !active && $related[1]) {
30304				if (e.keyCode === 37 && (index || settings.loop)) {
30305					e.preventDefault();
30306					$prev.click();
30307				} else if (e.keyCode === 39 && (index < $related.length - 1 || settings.loop)) {
30308					e.preventDefault();
30309					$next.click();
30310				}
30311			}
30312		});
30313	};
30314	
30315	publicMethod.remove = function () {
30316		$box.add($overlay).remove();
30317		$('.' + boxElement).die('click').removeData(colorbox).removeClass(boxElement);
30318	};
30319
30320	publicMethod.position = function (speed, loadedCallback) {
30321		var
30322		animate_speed,
30323		// keeps the top and left positions within the browser's viewport.
30324		posTop = Math.max(document.documentElement.clientHeight - settings.h - loadedHeight - interfaceHeight, 0) / 2 + $window.scrollTop(),
30325		posLeft = Math.max($window.width() - settings.w - loadedWidth - interfaceWidth, 0) / 2 + $window.scrollLeft();
30326		
30327		// setting the speed to 0 to reduce the delay between same-sized content.
30328		animate_speed = ($box.width() === settings.w + loadedWidth && $box.height() === settings.h + loadedHeight) ? 0 : speed;
30329		
30330		// this gives the wrapper plenty of breathing room so it's floated contents can move around smoothly,
30331		// but it has to be shrank down around the size of div#colorbox when it's done.  If not,
30332		// it can invoke an obscure IE bug when using iframes.
30333		$wrap[0].style.width = $wrap[0].style.height = "9999px";
30334		
30335		function modalDimensions(that) {
30336			// loading overlay height has to be explicitly set for IE6.
30337			$topBorder[0].style.width = $bottomBorder[0].style.width = $content[0].style.width = that.style.width;
30338			$loadingOverlay[0].style.height = $loadingOverlay[1].style.height = $content[0].style.height = $leftBorder[0].style.height = $rightBorder[0].style.height = that.style.height;
30339		}
30340		
30341		$box.dequeue().animate({width: settings.w + loadedWidth, height: settings.h + loadedHeight, top: posTop, left: posLeft}, {
30342			duration: animate_speed,
30343			complete: function () {
30344				modalDimensions(this);
30345				
30346				active = false;
30347				
30348				// shrink the wrapper down to exactly the size of colorbox to avoid a bug in IE's iframe implementation.
30349				$wrap[0].style.width = (settings.w + loadedWidth + interfaceWidth) + "px";
30350				$wrap[0].style.height = (settings.h + loadedHeight + interfaceHeight) + "px";
30351				
30352				if (loadedCallback) {
30353					loadedCallback();
30354				}
30355			},
30356			step: function () {
30357				modalDimensions(this);
30358			}
30359		});
30360	};
30361
30362	publicMethod.resize = function (options) {
30363		if (open) {
30364			options = options || {};
30365			
30366			if (options.width) {
30367				settings.w = setSize(options.width, 'x') - loadedWidth - interfaceWidth;
30368			}
30369			if (options.innerWidth) {
30370				settings.w = setSize(options.innerWidth, 'x');
30371			}
30372			$loaded.css({width: settings.w});
30373			
30374			if (options.height) {
30375				settings.h = setSize(options.height, 'y') - loadedHeight - interfaceHeight;
30376			}
30377			if (options.innerHeight) {
30378				settings.h = setSize(options.innerHeight, 'y');
30379			}
30380			if (!options.innerHeight && !options.height) {				
30381				var $child = $loaded.wrapInner("<div style='overflow:auto'></div>").children(); // temporary wrapper to get an accurate estimate of just how high the total content should be.
30382				settings.h = $child.height();
30383				$child.replaceWith($child.children()); // ditch the temporary wrapper div used in height calculation
30384			}
30385			$loaded.css({height: settings.h});
30386			
30387			publicMethod.position(settings.transition === "none" ? 0 : settings.speed);
30388		}
30389	};
30390
30391	publicMethod.prep = function (object) {
30392		if (!open) {
30393			return;
30394		}
30395		
30396		var photo,
30397		speed = settings.transition === "none" ? 0 : settings.speed;
30398		
30399		$window.unbind('resize.' + prefix);
30400		$loaded.remove();
30401		$loaded = $div('LoadedContent').html(object);
30402		
30403		function getWidth() {
30404			settings.w = settings.w || $loaded.width();
30405			settings.w = settings.mw && settings.mw < settings.w ? settings.mw : settings.w;
30406			return settings.w;
30407		}
30408		function getHeight() {
30409			settings.h = settings.h || $loaded.height();
30410			settings.h = settings.mh && settings.mh < settings.h ? settings.mh : settings.h;
30411			return settings.h;
30412		}
30413		
30414		$loaded.hide()
30415		.appendTo($loadingBay.show())// content has to be appended to the DOM for accurate size calculations.
30416		.css({width: getWidth(), overflow: settings.scrolling ? 'auto' : 'hidden'})
30417		.css({height: getHeight()})// sets the height independently from the width in case the new width influences the value of height.
30418		.prependTo($content);
30419		
30420		$loadingBay.hide();
30421		
30422		// floating the IMG removes the bottom line-height and fixed a problem where IE miscalculates the width of the parent element as 100% of the document width.
30423		$('#' + prefix + 'Photo').css({cssFloat: 'none', marginLeft: 'auto', marginRight: 'auto'});
30424		
30425		// Hides SELECT elements in IE6 because they would otherwise sit on top of the overlay.
30426		if (isIE6) {
30427			$('select').not($box.find('select')).filter(function () {
30428				return this.style.visibility !== 'hidden';
30429			}).css({'visibility': 'hidden'}).one(event_cleanup, function () {
30430				this.style.visibility = 'inherit';
30431			});
30432		}
30433				
30434		function setPosition(s) {
30435			var prev, prevSrc, next, nextSrc, total = $related.length, loop = settings.loop;
30436			publicMethod.position(s, function () {
30437				function defilter() {
30438					if (isIE) {
30439						//IE adds a filter when ColorBox fades in and out that can cause problems if the loaded content contains transparent pngs.
30440						$box[0].style.removeAttribute("filter"); 
30441					}
30442				}
30443				
30444				if (!open) {
30445					return;
30446				}
30447				
30448				if (isIE) {
30449					//This fadeIn helps the bicubic resampling to kick-in.
30450					if (photo) {
30451						$loaded.fadeIn(100);
30452					}
30453				}
30454				
30455				$loaded.show();
30456				
30457				trigger(event_loaded);
30458				
30459				$title.show().html(settings.title);
30460				
30461				if (total > 1) { // handle grouping
30462					if (typeof settings.current === "string") {
30463						$current.html(settings.current.replace(/\{current\}/, index + 1).replace(/\{total\}/, total)).show();
30464					}
30465					
30466					$next[(loop || index < total - 1) ? "show" : "hide"]().html(settings.next);
30467					$prev[(loop || index) ? "show" : "hide"]().html(settings.previous);
30468					
30469					prev = index ? $related[index - 1] : $related[total - 1];
30470					next = index < total - 1 ? $related[index + 1] : $related[0];
30471					
30472					if (settings.slideshow) {
30473						$slideshow.show();
30474					}
30475					
30476					// Preloads images within a rel group
30477					if (settings.preloading) {
30478						nextSrc = $.data(next, colorbox).href || next.href;
30479						prevSrc = $.data(prev, colorbox).href || prev.href;
30480						
30481						nextSrc = $.isFunction(nextSrc) ? nextSrc.call(next) : nextSrc;
30482						prevSrc = $.isFunction(prevSrc) ? prevSrc.call(prev) : prevSrc;
30483						
30484						if (isImage(nextSrc)) {
30485							$('<img/>')[0].src = nextSrc;
30486						}
30487						
30488						if (isImage(prevSrc)) {
30489							$('<img/>')[0].src = prevSrc;
30490						}
30491					}
30492				}
30493				
30494				$loadingOverlay.hide();
30495				
30496				if (settings.transition === 'fade') {
30497					$box.fadeTo(speed, 1, function () {
30498						defilter();
30499					});
30500				} else {
30501					defilter();
30502				}
30503				
30504				$window.bind('resize.' + prefix, function () {
30505					publicMethod.position(0);
30506				});
30507				
30508				trigger(event_complete, settings.onComplete);
30509			});
30510		}
30511		
30512		if (settings.transition === 'fade') {
30513			$box.fadeTo(speed, 0, function () {
30514				setPosition(0);
30515			});
30516		} else {
30517			setPosition(speed);
30518		}
30519	};
30520
30521	publicMethod.load = function (launched) {
30522		var href, img, setResize, prep = publicMethod.prep;
30523		
30524		active = true;
30525		element = $related[index];
30526		
30527		if (!launched) {
30528			settings = process($.extend({}, $.data(element, colorbox)));
30529		}
30530		
30531		trigger(event_purge);
30532		
30533		trigger(event_load, settings.onLoad);
30534		
30535		settings.h = settings.height ?
30536				setSize(settings.height, 'y') - loadedHeight - interfaceHeight :
30537				settings.innerHeight && setSize(settings.innerHeight, 'y');
30538		
30539		settings.w = settings.width ?
30540				setSize(settings.width, 'x') - loadedWidth - interfaceWidth :
30541				settings.innerWidth && setSize(settings.innerWidth, 'x');
30542		
30543		// Sets the minimum dimensions for use in image scaling
30544		settings.mw = settings.w;
30545		settings.mh = settings.h;
30546		
30547		// Re-evaluate the minimum width and height based on maxWidth and maxHeight values.
30548		// If the width or height exceed the maxWidth or maxHeight, use the maximum values instead.
30549		if (settings.maxWidth) {
30550			settings.mw = setSize(settings.maxWidth, 'x') - loadedWidth - interfaceWidth;
30551			settings.mw = settings.w && settings.w < settings.mw ? settings.w : settings.mw;
30552		}
30553		if (settings.maxHeight) {
30554			settings.mh = setSize(settings.maxHeight, 'y') - loadedHeight - interfaceHeight;
30555			settings.mh = settings.h && settings.h < settings.mh ? settings.h : settings.mh;
30556		}
30557		
30558		href = settings.href;
30559		
30560		$loadingOverlay.show();
30561
30562		if (settings.inline) {
30563			// Inserts an empty placeholder where inline content is being pulled from.
30564			// An event is bound to put inline content back when ColorBox closes or loads new content.
30565			$div().hide().insertBefore($(href)[0]).one(event_purge, function () {
30566				$(this).replaceWith($loaded.children());
30567			});
30568			prep($(href));
30569		} else if (settings.iframe) {
30570			// IFrame element won't be added to the DOM until it is ready to be displayed,
30571			// to avoid problems with DOM-ready JS that might be trying to run in that iframe.
30572			$box.one(event_loaded, function () {
30573				var iframe = $("<iframe frameborder='0' style='width:100%; height:100%; border:0; display:block'/>")[0];
30574				iframe.name = prefix + (+new Date());
30575				iframe.src = settings.href;
30576				
30577				if (!settings.scrolling) {
30578					iframe.scrolling = "no";
30579				}
30580				
30581				if (isIE) {
30582					iframe.allowtransparency = "true";
30583				}
30584				
30585				$(iframe).appendTo($loaded).one(event_purge, function () {
30586					iframe.src = "//about:blank";
30587				});
30588			});
30589			
30590			prep(" ");
30591		} else if (settings.html) {
30592			prep(settings.html);
30593		} else if (isImage(href)) {
30594			img = new Image();
30595			img.onload = function () {
30596				var percent;
30597				img.onload = null;
30598				img.id = prefix + 'Photo';
30599				$(img).css({border: 'none', display: 'block', cssFloat: 'left'});
30600				if (settings.scalePhotos) {
30601					setResize = function () {
30602						img.height -= img.height * percent;
30603						img.width -= img.width * percent;	
30604					};
30605					if (settings.mw && img.width > settings.mw) {
30606						percent = (img.width - settings.mw) / img.width;
30607						setResize();
30608					}
30609					if (settings.mh && img.height > settings.mh) {
30610						percent = (img.height - settings.mh) / img.height;
30611						setResize();
30612					}
30613				}
30614				
30615				if (settings.h) {
30616					img.style.marginTop = Math.max(settings.h - img.height, 0) / 2 + 'px';
30617				}
30618				
30619				if ($related[1] && (index < $related.length - 1 || settings.loop)) {
30620					$(img).css({cursor: 'pointer'}).click(publicMethod.next);
30621				}
30622				
30623				if (isIE) {
30624					img.style.msInterpolationMode = 'bicubic';
30625				}
30626				
30627				setTimeout(function () { // Chrome will sometimes report a 0 by 0 size if there isn't pause in execution
30628					prep(img);
30629				}, 1);
30630			};
30631			
30632			setTimeout(function () { // Opera 10.6+ will sometimes load the src before the onload function is set
30633				img.src = href;
30634			}, 1);	
30635		} else if (href) {
30636			$loadingBay.load(href, function (data, status, xhr) {
30637				prep(status === 'error' ? 'Request unsuccessful: ' + xhr.statusText : $(this).children());
30638			});
30639		}
30640	};
30641
30642	// Navigates to the next page/image in a set.
30643	publicMethod.next = function () {
30644		if (!active) {
30645			index = index < $related.length - 1 ? index + 1 : 0;
30646			publicMethod.load();
30647		}
30648	};
30649	
30650	publicMethod.prev = function () {
30651		if (!active) {
30652			index = index ? index - 1 : $related.length - 1;
30653			publicMethod.load();
30654		}
30655	};
30656
30657	// Note: to use this within an iframe use the following format: parent.$.fn.colorbox.close();
30658	publicMethod.close = function () {
30659		if (open && !closing) {
30660			closing = true;
30661			
30662			open = false;
30663			
30664			trigger(event_cleanup, settings.onCleanup);
30665			
30666			$window.unbind('.' + prefix + ' .' + event_ie6);
30667			
30668			$overlay.fadeTo('fast', 0);
30669			
30670			$box.stop().fadeTo('fast', 0, function () {
30671				
30672				trigger(event_purge);
30673				
30674				$loaded.remove();
30675				
30676				$box.add($overlay).css({'opacity': 1, cursor: 'auto'}).hide();
30677				
30678				setTimeout(function () {
30679					closing = false;
30680					trigger(event_closed, settings.onClosed);
30681				}, 1);
30682			});
30683		}
30684	};
30685
30686	// A method for fetching the current element ColorBox is referencing.
30687	// returns a jQuery object.
30688	publicMethod.element = function () {
30689		return $(element);
30690	};
30691
30692	publicMethod.settings = defaults;
30693
30694	// Initializes ColorBox when the DOM has loaded
30695	$(publicMethod.init);
30696
30697}(jQuery, this));
30698/*  
30699  Watermark plugin for jQuery
30700  Version: 3.0.6
30701  http://jquery-watermark.googlecode.com/
30702
30703  Copyright (c) 2009-2010 Todd Northrop
30704  http://www.speednet.biz/
30705  
30706  June 21, 2010
30707
30708  Requires:  jQuery 1.2.3+
30709  
30710  Dual licensed under the MIT or GPL Version 2 licenses.
30711  See mit-license.txt and gpl2-license.txt in the project root for details.
30712------------------------------------------------------*/
30713
30714(function ($) {
30715
30716var
30717  // Will speed up references to undefined
30718  undefined,
30719
30720  // String constants for data names
30721  dataFlag = "watermark",
30722  dataClass = "watermarkClass",
30723  dataFocus = "watermarkFocus",
30724  dataFormSubmit = "watermarkSubmit",
30725  dataMaxLen = "watermarkMaxLength",
30726  dataPassword = "watermarkPassword",
30727  dataText = "watermarkText",
30728  
30729  // Includes only elements with watermark defined
30730  selWatermarkDefined = ":data(" + dataFlag + ")",
30731
30732  // Includes only elements capable of having watermark
30733  selWatermarkAble = ":text,:password,:search,textarea",
30734  
30735  // triggerFns:
30736  // Array of function names to look for in the global namespace.
30737  // Any such functions found will be hijacked to trigger a call to
30738  // hideAll() any time they are called.  The default value is the
30739  // ASP.NET function that validates the controls on the page
30740  // prior to a postback.
30741  // 
30742  // Am I missing other important trigger function(s) to look for?
30743  // Please leave me feedback:
30744  // http://code.google.com/p/jquery-watermark/issues/list
30745  triggerFns = [
30746    "Page_ClientValidate"
30747  ],
30748  
30749  // Holds a value of true if a watermark was displayed since the last
30750  // hideAll() was executed. Avoids repeatedly calling hideAll().
30751  pageDirty = false;
30752
30753// Extends jQuery with a custom selector - ":data(...)"
30754// :data(<name>)  Includes elements that have a specific name defined in the jQuery data collection. (Only the existence of the name is checked; the value is ignored.)
30755// :data(<name>=<value>)  Includes elements that have a specific jQuery data name defined, with a specific value associated with it.
30756// :data(<name>!=<value>)  Includes elements that have a specific jQuery data name defined, with a value that is not equal to the value specified.
30757// :data(<name>^=<value>)  Includes elements that have a specific jQuery data name defined, with a value that starts with the value specified.
30758// :data(<name>$=<value>)  Includes elements that have a specific jQuery data name defined, with a value that ends with the value specified.
30759// :data(<name>*=<value>)  Includes elements that have a specific jQuery data name defined, with a value that contains the value specified.
30760$.extend($.expr[":"], {
30761  "search": function (elem) {
30762    return "search" === (elem.type || "");
30763  },
30764  
30765  "data": function (element, index, matches, set) {
30766    var data, parts = /^((?:[^=!^$*]|[!^$*](?!=))+)(?:([!^$*]?=)(.*))?$/.exec(matches[3]);
30767
30768    if (parts) {
30769      data = $(element).data(parts[1]);
30770      
30771      if (data !== undefined) {
30772
30773        if (parts[2]) {
30774          data = "" + data;
30775        
30776          switch (parts[2]) {
30777            case "=":
30778              return (data == parts[3]);
30779            case "!=":
30780              return (data != parts[3]);
30781            case "^=":
30782              return (data.slice(0, parts[3].length) == parts[3]);
30783            case "$=":
30784              return (data.slice(-parts[3].length) == parts[3]);
30785            case "*=":
30786              return (data.indexOf(parts[3]) !== -1);
30787          }
30788        }
30789
30790        return true;
30791      }
30792    }
30793    
30794    return false;
30795  }
30796});
30797
30798$.watermark = {
30799
30800  // Current version number of the plugin
30801  version: "3.0.6",
30802    
30803  // Default options used when watermarks are instantiated.
30804  // Can be changed to affect the default behavior for all
30805  // new or updated watermarks.
30806  // BREAKING CHANGE:  The $.watermark.className
30807  // property that was present prior to version 3.0.2 must
30808  // be changed to $.watermark.options.className
30809  options: {
30810    
30811    // Default class name for all watermarks
30812    className: "watermark",
30813    
30814    // If true, plugin will detect and use native browser support for
30815    // watermarks, if available. (e.g., WebKit's placeholder attribute.)
30816    useNative: true
30817  },
30818  
30819  // Hide one or more watermarks by specifying any selector type
30820  // i.e., DOM element, string selector, jQuery matched set, etc.
30821  hide: function (selector) {
30822    $(selector).filter(selWatermarkDefined).each(
30823      function () {
30824        $.watermark._hide($(this));
30825      }
30826    );
30827  },
30828  
30829  // Internal use only.
30830  _hide: function ($input, focus) {
30831    var inputVal = $input.val() || "",
30832      inputWm = $input.data(dataText) || "",
30833      maxLen = $input.data(dataMaxLen) || 0,
30834      className = $input.data(dataClass);
30835  
30836    if ((inputWm.length) && (inputVal == inputWm)) {
30837      $input.val("");
30838      
30839      // Password type?
30840      if ($input.data(dataPassword)) {
30841        
30842        if (($input.attr("type") || "") === "text") {
30843          var $pwd = $input.data(dataPassword) || [], 
30844            $wrap = $input.parent() || [];
30845            
30846          if (($pwd.length) && ($wrap.length)) {
30847            $wrap[0].removeChild($input[0]); // Can't use jQuery methods, because they destroy data
30848            $wrap[0].appendChild($pwd[0]);
30849            $input = $pwd;
30850          }
30851        }
30852      }
30853      
30854      if (maxLen) {
30855        $input.attr("maxLength", maxLen);
30856        $input.removeData(dataMaxLen);
30857      }
30858    
30859      if (focus) {
30860        $input.attr("autocomplete", "off");  // Avoid NS_ERROR_XPC_JS_THREW_STRING error in Firefox
30861        
30862        window.setTimeout(
30863          function () {
30864            $input.select();  // Fix missing cursor in IE
30865          }
30866        , 1);
30867      }
30868    }
30869    
30870    className && $input.removeClass(className);
30871  },
30872  
30873  // Display one or more watermarks by specifying any selector type
30874  // i.e., DOM element, string selector, jQuery matched set, etc.
30875  // If conditions are not right for displaying a watermark, ensures that watermark is not shown.
30876  show: function (selector) {
30877    $(selector).filter(selWatermarkDefined).each(
30878      function () {
30879        $.watermark._show($(this));
30880      }
30881    );
30882  },
30883  
30884  // Internal use only.
30885  _show: function ($input) {
30886    var val = $input.val() || "",
30887      text = $input.data(dataText) || "",
30888      type = $input.attr("type") || "",
30889      className = $input.data(dataClass);
30890
30891    if (((val.length == 0) || (val == text)) && (!$input.data(data
30891Focus))) {
30892      pageDirty = true;
30893    
30894      // Password type?
30895      if ($input.data(dataPassword)) {
30896        
30897        if (type === "password") {
30898          var $pwd = $input.data(dataPassword) || [],
30899            $wrap = $input.parent() || [];
30900            
30901          if (($pwd.length) && ($wrap.length)) {
30902            $wrap[0].removeChild($input[0]); // Can't use jQuery methods, because they destroy data
30903            $wrap[0].appendChild($pwd[0]);
30904            $input = $pwd;
30905            $input.attr("maxLength", text.length);
30906          }
30907        }
30908      }
30909    
30910      // Ensure maxLength big enough to hold watermark (input of type="text" or type="search" only)
30911      if ((type === "text") || (type === "search")) {
30912        var maxLen = $input.attr("maxLength") || 0;
30913        
30914        if ((maxLen > 0) && (text.length > maxLen)) {
30915          $input.data(dataMaxLen, maxLen);
30916          $input.attr("maxLength", text.length);
30917        }
30918      }
30919            
30920      className && $input.addClass(className);
30921      $input.val(text);
30922    }
30923    else {
30924      $.watermark._hide($input);
30925    }
30926  },
30927  
30928  // Hides all watermarks on the current page.
30929  hideAll: function () {
30930    if (pageDirty) {
30931      $.watermark.hide(selWatermarkAble);
30932      pageDirty = false;
30933    }
30934  },
30935  
30936  // Displays all watermarks on the current page.
30937  showAll: function () {
30938    $.watermark.show(selWatermarkAble);
30939  }
30940};
30941
30942$.fn.watermark = function (text, options) {
30943  /// <summary>
30944  ///   Set watermark text and class name on all input elements of type="text/password/search" and
30945  ///   textareas within the matched set. If className is not specified in options, the default is
30946  ///   "watermark". Within the matched set, only input elements with type="text/password/search"
30947  ///   and textareas are affected; all other elements are ignored.
30948  /// </summary>
30949  /// <returns type="jQuery">
30950  ///   Returns the original jQuery matched set (not just the input and texarea elements).
30951  /// </returns>
30952  /// <param name="text" type="String">
30953  ///   Text to display as a watermark when the input or textarea element has an empty value and does not
30954  ///   have focus. The first time watermark() is called on an element, if this argument is empty (or not
30955  ///   a String type), then the watermark will have the net effect of only changing the class name when
30956  ///   the input or textarea element's value is empty and it does not have focus.
30957  /// </param>
30958  /// <param name="options" type="Object" optional="true">
30959  ///   Provides the ability to override the default watermark options ($.watermark.options). For backward
30960  ///   compatibility, if a string value is supplied, it is used as the class name that overrides the class
30961  ///   name in $.watermark.options.className. Properties include:
30962  ///     className: When the watermark is visible, the element will be styled using this class name.
30963  ///     useNative (Boolean or Function): Specifies if native browser support for watermarks will supersede
30964  ///       plugin functionality. If useNative is a function, the return value from the function will
30965  ///       determine if native support is used. The function is passed one argument -- a jQuery object
30966  ///       containing the element being tested as the only element in its matched set -- and the DOM
30967  ///       element being tested is the object on which the function is invoked (the value of "this").
30968  /// </param>
30969  /// <remarks>
30970  ///   The effect of changing the text and class name on an input element is called a watermark because
30971  ///   typically light gray text is used to provide a hint as to what type of input is required. However,
30972  ///   the appearance of the watermark can be something completely different: simply change the CSS style
30973  ///   pertaining to the supplied class name.
30974  ///   
30975  ///   The first time watermark() is called on an element, the watermark text and class name are initialized,
30976  ///   and the focus and blur events are hooked in order to control the display of the watermark.  Also, as
30977  ///   of version 3.0, drag and drop events are hooked to guard against dropped text being appended to the
30978  ///   watermark.  If native watermark support is provided by the browser, it is detected and used, unless
30979  ///   the useNative option is set to false.
30980  ///   
30981  ///   Subsequently, watermark() can be called again on an element in order to change the watermark text
30982  ///   and/or class name, and it can also be called without any arguments in order to refresh the display.
30983  ///   
30984  ///   For example, after changing the value of the input or textarea element programmatically, watermark()
30985  ///   should be called without any arguments to refresh the display, because the change event is only
30986  ///   triggered by user actions, not by programmatic changes to an input or textarea element's value.
30987  ///   
30988  ///   The one exception to programmatic updates is for password input elements:  you are strongly cautioned
30989  ///   against changing the value of a password input element programmatically (after the page loads).
30990  ///   The reason is that some fairly hairy code is required behind the scenes to make the watermarks bypass
30991  ///   IE security and switch back and forth between clear text (for watermarks) and obscured text (for
30992  ///   passwords).  It is *possible* to make programmatic changes, but it must be done in a certain way, and
30993  ///   overall it is not recommended.
30994  /// </remarks>
30995  
30996  if (!this.length) {
30997    return this;
30998  }
30999  
31000  var hasClass = false,
31001    hasText = (typeof(text) === "string");
31002  
31003  if (typeof(options) === "object") {
31004    hasClass = (typeof(options.className) === "string");
31005    options = $.extend({}, $.watermark.options, options);
31006  }
31007  else if (typeof(options) === "string") {
31008    hasClass = true;
31009    options = $.extend({}, $.watermark.options, {className: options});
31010  }
31011  else {
31012    options = $.watermark.options;
31013  }
31014  
31015  if (typeof(options.useNative) !== "function") {
31016    options.useNative = options.useNative? function () { return true; } : function () { return false; };
31017  }
31018  
31019  return this.each(
31020    function () {
31021      var $input = $(this);
31022      
31023      if (!$input.is(selWatermarkAble)) {
31024        return;
31025      }
31026      
31027      // Watermark already initialized?
31028      if ($input.data(dataFlag)) {
31029      
31030        // If re-defining text or class, first remove existing watermark, then make changes
31031        if (hasText || hasClass) {
31032          $.watermark._hide($input);
31033      
31034          if (hasText) {
31035            $input.data(dataText, text);
31036          }
31037          
31038          if (hasClass) {
31039            $input.data(dataClass, options.className);
31040          }
31041        }
31042      }
31043      else {
31044      
31045        // Detect and use native browser support, if enabled in options
31046        if (options.useNative.call(this, $input)) {
31047          
31048          // Placeholder attribute (WebKit)
31049          // Big thanks to Opera for the wacky test required
31050          if ((("" + $input.css("-webkit-appearance")).replace("undefined", "") !== "") && (($input.attr("tagName") || "") !== "TEXTAREA")) {
31051            
31052            // className is not set because WebKit doesn't appear to have
31053            // a separate class name property for placeholders (watermarks).
31054            if (hasText) {
31055              $input.attr("placeholder", text);
31056            }
31057            
31058            // Only set data flag for non-native watermarks (purposely commented-out)
31059            // $input.data(dataFlag, 1);
31060            return;
31061          }
31062        }
31063        
31064        $input.data(dataText, hasText? text : "");
31065        $input.data(dataClass, options.className);
31066        $input.data(dataFlag, 1); // Flag indicates watermark was initialized
31067        
31068        // Special processing for password type
31069        if (($input.attr("type") || "") === "password") {
31070          var $wrap = $input.wrap("<span>").parent(),
31071            $wm = $($wrap.html().replace(/type=["']?password["']?/i, 'type="text"'));
31072          
31073          $wm.data(dataText, $input.data(dataText));
31074          $wm.data(dataClass, $input.data(dataClass));
31075          $wm.data(dataFlag, 1);
31076          $wm.attr("maxLength", text.length);
31077          
31078          $wm.focus(
31079            function () {
31080              $.watermark._hide($wm, true);
31081            }
31082          ).bind("dragenter",
31083            function () {
31084              $.watermark._hide($wm);
31085            }
31086          ).bind("dragend",
31087            function () {
31088              window.setTimeout(function () { $wm.blur(); }, 1);
31089            }
31090          );
31091          $input.blur(
31092            function () {
31093              $.watermark._show($input);
31094            }
31095          ).bind("dragleave",
31096            function () {
31097              $.watermark._show($input);
31098            }
31099          );
31100          
31101          $wm.data(dataPassword, $input);
31102          $input.data(dataPassword, $wm);
31103        }
31104        else {
31105          
31106          $input.focus(
31107            function () {
31108              $input.data(dataFocus, 1);
31109              $.watermark._hide($input, true);
31110            }
31111          ).blur(
31112            function () {
31113              $input.data(dataFocus, 0);
31114              $.watermark._show($input);
31115            }
31116          ).bind("dragenter",
31117            function () {
31118              $.watermark._hide($input);
31119            }
31120          ).bind("dragleave",
31121            function () {
31122              $.watermark._show($input);
31123            }
31124          ).bind("dragend",
31125            function () {
31126              window.setTimeout(function () { $.watermark._show($input); }, 1);
31127            }
31128          ).bind("drop",
31129            // Firefox makes this lovely function necessary because the dropped text
31130            // is merged with the watermark before the drop event is called.
31131            function (evt) {
31132              var dropText = evt.originalEvent.dataTransfer.getData("Text");
31133              
31134              if ($input.val().replace(dropText, "") === $input.data(dataText)) {
31135                $input.val(dropText);
31136              }
31137              
31138              $input.focus();
31139            }
31140          );
31141        }
31142        
31143        // In order to reliably clear all watermarks before form submission,
31144        // we need to replace the form's submit function with our own
31145        // function.  Otherwise watermarks won't be cleared when the form
31146        // is submitted programmatically.
31147        if (this.form) {
31148          var form = this.form,
31149            $form = $(form);
31150          
31151          if (!$form.data(dataFormSubmit)) {
31152            $form.submit($.watermark.hideAll);
31153            
31154            // form.submit exists for all browsers except Google Chrome
31155            // (see "else" below for explanation)
31156            if (form.submit) {
31157              $form.data(dataFormSubmit, form.submit);
31158              
31159              form.submit = (function (f, $f) {
31160                return function () {
31161                  var nativeSubmit = $f.data(dataFormSubmit);
31162                  
31163                  $.watermark.hideAll();
31164                  
31165                  if (nativeSubmit.apply) {
31166                    nativeSubmit.apply(f, Array.prototype.slice.call(arguments));
31167                  }
31168                  else {
31169                    nativeSubmit();
31170                  }
31171                };
31172              })(form, $form);
31173            }
31174            else {
31175              $form.data(dataFormSubmit, 1);
31176              
31177              // This strangeness is due to the fact that Google Chrome's
31178              // form.submit function is not visible to JavaScript (identifies
31179              // as "undefined").  I had to invent a solution here because hours
31180              // of Googling (ironically) for an answer did not turn up anything
31181              // useful.  Within my own form.submit function I delete the form's
31182              // submit function, and then call the non-existent function --
31183              // which, in the world of Google Chrome, still exists.
31184              form.submit = (function (f) {
31185                return function () {
31186                  $.watermark.hideAll();
31187                  delete f.submit;
31188                  f.submit();
31189                };
31190              })(form);
31191            }
31192          }
31193        }
31194      }
31195      
31196      $.watermark._show($input);
31197    }
31198  );
31199};
31200
31201// Hijack any functions found in the triggerFns list
31202if (triggerFns.length) {
31203
31204  // Wait until DOM is ready before searching
31205  $(function () {
31206    var i, name, fn;
31207  
31208    for (i=triggerFns.length-1; i>=0; i--) {
31209      name = triggerFns[i];
31210      fn = window[name];
31211      
31212      if (typeof(fn) === "function") {
31213        window[name] = (function (origFn) {
31214          return function () {
31215            $.watermark.hideAll();
31216            return origFn.apply(null, Array.prototype.slice.call(arguments));
31217          };
31218        })(fn);
31219      }
31220    }
31221  });
31222}
31223
31224})(jQuery);
31225
31226
31227/*
31228 * jQuery File Upload Plugin 3.2
31229 *
31230 * Copyright 2010, Sebastian Tschan, AQUANTUM
31231 * Licensed under the MIT license:
31232 * http://creativecommons.org/licenses/MIT/
31233 *
31234 * https://blueimp.net
31235 * http://www.aquantum.de
31236 */
31237
31238/*jslint browser: true */
31239/*global File, FileReader, FormData, unescape, jQuery */
31240
31241(function ($) {
31242
31243    var FileUpload = function (container) {
31244        var fileUpload = this,
31245        uploadForm = (container.is('form') ? container : container.find('form').first()),
31246        fileInput = uploadForm.find('input:file').first(),
31247        settings = {
31248            namespace: 'file_upload',
31249            cssClass: 'file_upload',
31250            dropZone: container,
31251            url: uploadForm.attr('action'),
31252            method: uploadForm.attr('method'),
31253            fieldName: fileInput.attr('name'),
31254            multipart: true,
31255            formData: function () {
31256                return uploadForm.serializeArray();
31257            },
31258            withCredentials: false
31259        },
31260        documentListeners = {},
31261        dropZoneListeners = {},
31262        fileInputListeners = {},
31263        undef = 'undefined',
31264        func = 'function',
31265        protocolRegExp = /^http(s)?:\/\//,
31266
31267        isXHRUploadCapable = function () {
31268            return typeof XMLHttpRequest !== undef && typeof File !== undef && (
31269                !settings.multipart || typeof FormData !== undef || typeof FileReader !== undef
31270            );
31271        },
31272
31273        initEventHandlers = function () {
31274            if (typeof settings.onDocumentDragEnter === func) {
31275                documentListeners['dragenter.' + settings.namespace] = settings.onDocumentDragEnter;
31276            }
31277            if (typeof settings.onDocumentDragLeave === func) {
31278                documentListeners['dragleave.' + settings.namespace] = settings.onDocumentDragLeave;
31279            }
31280            documentListeners['dragover.'   + settings.namespace] = fileUpload.onDocumentDragOver;
31281            documentListeners['drop.'       + settings.namespace] = fileUpload.onDocumentDrop;
31282            $(document).bind(documentListeners);
31283            if (typeof settings.onDragEnter === func) {
31284                dropZoneListeners['dragenter.' + settings.namespace] = settings.onDragEnter;
31285            }
31286            if (typeof settings.onDragLeave === func) {
31287                dropZoneListeners['dragleave.' + settings.namespace] = settings.onDragLeave;
31288            }
31289            dropZoneListeners['dragover.'   + settings.namespace] = fileUpload.onDragOver;
31290            dropZoneListeners['drop.'       + settings.namespace] = fileUpload.onDrop;
31291            settings.dropZone.bind(dropZoneListeners);
31292            fileInputListeners['change.'    + settings.namespace] = fileUpload.onChange;
31293            fileInput.bind(fileInputListeners);
31294        },
31295
31296        removeEventHandlers = function () {
31297            $.each(documentListeners, function (key, value) {
31298                $(document).unbind(key, value);
31299            });
31300            $.each(dropZoneListeners, function (key, value) {
31301                settings.dropZone.unbind(key, value);
31302            });
31303            $.each(fileInputListeners, function (key, value) {
31304                fileInput.unbind(key, value);
31305            });
31306        },
31307
31308        initUploadEventHandlers = function (files, index, xhr, settings) {
31309            if (typeof settings.onProgress === func) {
31310                xhr.upload.onprogress = function (e) {
31311                    settings.onProgress(e, files, index, xhr, settings);
31312                };
31313            }
31314            if (typeof settings.onLoad === func) {
31315                xhr.onload = function (e) {
31316                    settings.onLoad(e, files, index, xhr, settings);
31317                };
31318            }
31319            if (typeof settings.onAbort === func) {
31320                xhr.onabort = function (e) {
31321                    settings.onAbort(e, files, index, xhr, settings);
31322                };
31323            }
31324            if (typeof settings.onError === func) {
31325                xhr.onerror = function (e) {
31326                    settings.onError(e, files, index, xhr, settings);
31327                };
31328            }
31329        },
31330
31331        getFormData = function (settings) {
31332            if (typeof settings.formData === func) {
31333                return settings.formData();
31334            } else if ($.isArray(settings.formData)) {
31335                return settings.formData;
31336            } else if (settings.formData) {
31337                var formData = [];
31338                $.each(settings.formData, function (name, value) {
31339                    formData.push({name: name, value: value});
31340                });
31341                return formData;
31342            }
31343            return [];
31344        },
31345
31346        buildMultiPartFormData = function (boundary, file, fileContent, fields) {
31347            var doubleDash = '--',
31348                crlf     = '\r\n',
31349                formData = '';
31350            $.each(fields, function (index, field) {
31351                formData += doubleDash + boundary + crlf +
31352                    'Content-Disposition: form-data; name="' +
31353                    unescape(encodeURIComponent(field.name)) +
31354                    '"' + crlf + crlf +
31355                    unescape(encodeURIComponent(field.value)) + crlf;
31356            });
31357            formData += doubleDash + boundary + crlf +
31358                'Content-Disposition: form-data; name="' +
31359                unescape(encodeURIComponent(settings.fieldName)) +
31360                '"; filename="' + unescape(encodeURIComponent(file.name)) + '"' + crlf +
31361                'Content-Type: ' + file.type + crlf + crlf +
31362                fileContent + crlf +
31363                doubleDash + boundary + doubleDash + crlf;
31364            return formData;
31365        },
31366
31367        isSameDomain = function (url) {
31368            if (protocolRegExp.test(url)) {
31369                var host = location.host,
31370                    indexStart = location.protocol.length + 2,
31371                    index = url.indexOf(host, indexStart),
31372                    pathIndex = index + host.length;
31373                if ((index === indexStart || index === url.indexOf('@', indexStart) + 1) && (
31374                    url.length === pathIndex || $.inArray(url.charAt(pathIndex), ['/', '?', '#']))) {
31375                    return true;
31376                }
31377                return false;
31378            }
31379            return true;
31380        },
31381
31382        uploadFile = function (files, index, xhr, settings) {
31383            var sameDomain = isSameDomain(settings.url),
31384                file = files[index],
31385                formData, fileReader;
31386            initUploadEventHandlers(files, index, xhr, settings);
31387            xhr.open(settings.method, settings.url, true);
31388            if (sameDomain) {
31389                xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
31390            } else if (settings.withCredentials) {
31391                xhr.withCredentials = true;
31392            }
31393            if (!settings.multipart) {
31394                if (sameDomain) {
31395                    xhr.setRequestHeader('X-File-Name', unescape(encodeURIComponent(file.name)));
31396                }
31397                xhr.setRequestHeader('Content-Type', file.type);
31398                xhr.send(file);
31399            } else {
31400                if (typeof FormData !== undef) {
31401                    formData = new FormData();
31402                    $.each(getFormData(settings), function (index, field) {
31403                        formData.append(field.name, field.value);
31404                    });
31405                    formData.append(settings.fieldName, file);
31406                    xhr.send(formData);
31407                } else if (typeof FileReader !== undef) {
31408                    fileReader = new FileReader();
31409                       fileReader.onload = function (e) {
31410                        var fileContent = e.target.result,
31411                            boundary = '----MultiPartFormBoundary' + (new Date()).getTime();
31412                        xhr.setRequestHeader('Content-Type', 'multipart/form-data; boundary=' + boundary);
31413                        xhr.sendAsBinary(buildMultiPartFormData(
31414                            boundary,
31415                            file,
31416                            fileContent,
31417                            getFormData(settings)
31418                        ));
31419                    };
31420                    fileReader.readAsBinaryString(file);
31421                } else {
31422                    $.error('Browser does neither support FormData nor FileReader interface');
31423                }
31424            }
31425        },
31426
31427        handleFile = function (event, files, index) {
31428            var xhr = new XMLHttpRequest(),
31429                uploadSettings = $.extend({}, settings);
31430            if (typeof settings.initUpload === func) {
31431                settings.initUpload(
31432                    event,
31433                    files,
31434                    index,
31435                    xhr,
31436                    uploadSettings,
31437                    function () {
31438                        uploadFile(files, index, xhr, uploadSettings);
31439                    }
31440                );
31441            } else {
31442                uploadFile(files, index, xhr, uploadSettings);
31443            }
31444        },
31445
31446        handleFiles = function (event, files) {
31447            var i;
31448            for (i = 0; i < files.length; i += 1) {
31449                handleFile(event, files, i);
31450            }
31451        },
31452
31453        legacyUploadFormDataInit = function (input, settings) {
31454            var formData = getFormData(settings);
31455            uploadForm.find(':input').not(':disabled')
31456                .attr('disabled', true)
31457                .addClass(settings.namespace + '_disabled');
31458            $.each(formData, function (index, field) {
31459                uploadForm.append(
31460                    $('<input type="hidden"/>')
31461                        .attr('name', field.name)
31462                        .val(field.value)
31463                        .addClass(settings.namespace + '_form_data')
31464                );
31465            });
31466            input.insertAfter(fileInput);
31467        },
31468
31469        legacyUploadFormDataReset = function (input, settings) {
31470            input.remove();
31471            uploadForm.find('.' + settings.namespace + '_disabled')
31472                .removeAttr('disabled')
31473                .removeClass(settings.namespace + '_disabled');
31474            uploadForm.find('.' + settings.namespace + '_form_data').remove();
31475        },
31476
31477        legacyUpload = function (input, iframe, settings) {
31478            iframe
31479                .unbind('abort')
31480                .bind('abort', function (e) {
31481                    iframe.readyState = 0;
31482                    // javascript:false as iframe src prevents warning popups on HTTPS in IE6
31483                    // concat is used here to prevent the "Script URL" JSLint error:
31484                    iframe.unbind('load').attr('src', 'javascript'.concat(':false;'));
31485                    if (typeof settings.onAbort === func) {
31486                        settings.onAbort(e, [{name: input.val(), type: null, size: null}], 0, iframe, settings);
31487                    }
31488                })
31489                .unbind('load')
31490                .bind('load', function (e) {
31491                    iframe.readyState = 4;
31492                    if (typeof settings.onLoad === func) {
31493                        settings.onLoad(e, [{name: input.val(), type: null, size: null}], 0, iframe, settings);
31494                    }
31495                });
31496            uploadForm
31497                .attr('action', settings.url)
31498                .attr('target', iframe.attr('name'));
31499            legacyUploadFormDataInit(input, settings);
31500            iframe.readyState = 2;
31501            uploadForm.get(0).submit();
31502            legacyUploadFormDataReset(input, settings);
31503        },
31504
31505        handleLegacyUpload = function (event, input) {
31506            // javascript:false as iframe src prevents warning popups on HTTPS in IE6:
31507            var iframe = $('<iframe src="javascript:false;" style="display:none" name="iframe_' +
31508                settings.namespace + (new Date()).getTime() + '"></iframe>'),
31509                uploadSettings = $.extend({}, settings);
31510            iframe.readyState = 0;
31511            iframe.abort = function () {
31512                iframe.trigger('abort');
31513            };
31514            iframe.bind('load', function () {
31515                iframe.unbind('load');
31516                if (typeof settings.initUpload === func) {
31517                    settings.initUpload(
31518                        event,
31519                        [{name: input.val(), type: null, size: null}],
31520                        0,
31521                        iframe,
31522                        uploadSettings,
31523                        function () {
31524                            legacyUpload(input, iframe, uploadSettings);
31525                        }
31526                    );
31527                } else {
31528                    legacyUpload(input, iframe, uploadSettings);
31529                }
31530            }).appendTo(uploadForm);
31531        },
31532
31533        resetFileInput = function () {
31534            var inputClone = fileInput.clone(true);
31535            $('<form/>').append(inputClone).get(0).reset();
31536            fileInput.replaceWith(inputClone);
31537            fileInput = inputClone;
31538        };
31539
31540        this.onDocumentDragOver = function (e) {
31541            if (typeof settings.onDocumentDragOver === func &&
31542                settings.onDocumentDragOver(e) === false) {
31543                return false;
31544            }
31545            e.preventDefault();
31546        };
31547        
31548        this.onDocumentDrop = function (e) {
31549            if (typeof settings.onDocumentDrop === func &&
31550                settings.onDocumentDrop(e) === false) {
31551                return false;
31552            }
31553            e.preventDefault();
31554        };
31555
31556        this.onDragOver = function (e) {
31557            if (typeof settings.onDragOver === func &&
31558                settings.onDragOver(e) === false) {
31559                return false;
31560            }
31561            var dataTransfer = e.originalEvent.dataTransfer;
31562            if (dataTransfer) {
31563                dataTransfer.dropEffect = dataTransfer.effectAllowed = 'copy';
31564            }
31565            e.preventDefault();
31566        };
31567
31568        this.onDrop = function (e) {
31569            if (typeof settings.onDrop === func &&
31570                settings.onDrop(e) === false) {
31571                return false;
31572            }
31573            var dataTransfer = e.originalEvent.dataTransfer;
31574            if (dataTransfer && dataTransfer.files && isXHRUploadCapable()) {
31575                handleFiles(e, dataTransfer.files);
31576            }
31577            e.preventDefault();
31578        };
31579        
31580        this.onChange = function (e) {
31581            if (typeof settings.onChange === func &&
31582                settings.onChange(e) === false) {
31583                return false;
31584            }
31585            if (e.target.files && isXHRUploadCapable()) {
31586                handleFiles(e, e.target.files);
31587            } else {
31588                handleLegacyUpload(e, $(e.target));
31589            }
31590            resetFileInput();
31591        };
31592
31593        this.init = function (options) {
31594            if (options) {
31595                $.extend(settings, options);
31596            }
31597            if (container.data(settings.namespace)) {
31598                $.error('FileUpload with namespace "' + settings.namespace + '" already assigned to this element');
31599                return;
31600            }
31601            container
31602                .data(settings.namespace, fileUpload)
31603                .addClass(settings.cssClass);
31604            settings.dropZone.addClass(settings.cssClass);
31605            initEventHandlers();
31606        };
31607        
31608        this.destroy = function () {
31609            removeEventHandlers();
31610            container
31611                .removeData(settings.namespace)
31612                .removeClass(settings.cssClass);
31613            settings.dropZone.removeClass(settings.cssClass);
31614        };
31615    },
31616
31617    methods = {
31618        init : function (options) {
31619            return this.each(function () {
31620                (new FileUpload($(this))).init(options);
31621            });
31622        },
31623                
31624        destroy : function (namespace) {
31625            return this.each(function () {
31626                namespace = namespace ? namespace : 'file_upload';
31627                var fileUpload = $(this).data(namespace);
31628                if (fileUpload) {
31629                    fileUpload.destroy();
31630                } else {
31631                    $.error('No FileUpload with namespace "' + namespace + '" assigned to this element');
31632                }
31633            });
31634
31635        }
31636    };
31637    
31638    $.fn.fileUpload = function (method) {
31639        if (methods[method]) {
31640            return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
31641        } else if (typeof method === 'object' || !method) {
31642            return methods.init.apply(this, arguments);
31643        } else {
31644            $.error('Method ' + method + ' does not exist on jQuery.fileUpload');
31645        }
31646    };
31647    
31648}(jQuery));
31649
31650/*
31651 * jQuery File Upload User Interface Plugin 3.2
31652 *
31653 * Copyright 2010, Sebastian Tschan, AQUANTUM
31654 * Licensed under the MIT license:
31655 * http://creativecommons.org/licenses/MIT/
31656 *
31657 * https://blueimp.net
31658 * http://www.aquantum.de
31659 */
31660
31661/*jslint browser: true */
31662/*global jQuery */
31663
31664(function ($) {
31665
31666    var UploadHandler = function (container, options) {
31667        var uploadHandler = this,
31668            undef = 'undefined',
31669            func = 'function',
31670            dragOverTimeout,
31671            isDropZoneEnlarged;
31672        
31673        this.dropZone = container;
31674        this.progressSelector = '.file_upload_progress div';
31675        this.cancelSelector = '.file_upload_cancel div';
31676        this.cssClassSmall = 'file_upload_small';
31677        this.cssClassLarge = 'file_upload_large';
31678        this.cssClassHighlight = 'file_upload_highlight';
31679        this.dropEffect = 'highlight';
31680        this.uploadTable = this.downloadTable = $();
31681        
31682        this.buildUploadRow = this.buildDownloadRow = function () {
31683            return null;
31684        };
31685
31686        this.addNode = function (parentNode, node, callBack) {
31687            if (node) {
31688                node.hide().appendTo(parentNode).fadeIn(function () {
31689                    if (typeof callBack === func) {
31690                        try {
31691                            callBack();
31692                        } catch (e) {
31693                            // Fix endless exception loop:
31694                            $(this).stop();
31695                            throw e;
31696                        }
31697                    }
31698                });
31699            } else if (typeof callBack === func) {
31700                callBack();
31701            }
31702        };
31703
31704        this.removeNode = function (node, callBack) {
31705            if (node) {
31706                node.fadeOut(function () {
31707                    $(this).remove();
31708                    if (typeof callBack === func) {
31709                        try {
31710                            callBack();
31711                        } catch (e) {
31712                            // Fix endless exception loop:
31713                            $(this).stop();
31714                            throw e;
31715                        }
31716                    }
31717                });
31718            } else if (typeof callBack === func) {
31719                callBack();
31720            }
31721        };
31722
31723        this.onAbort = function (event, files, index, xhr, handler) {
31724            uploadHandler.removeNode(handler.uploadRow);
31725        };
31726        
31727        this.cancelUpload = function (event, files, index, xhr, handler) {
31728            var readyState = xhr.readyState;
31729            xhr.abort();
31730            // If readyState is below 2, abort() has no effect:
31731            if (isNaN(readyState) || readyState < 2) {
31732                handler.onAbort(event, files, index, xhr, handler);
31733            }
31734        };
31735        
31736        this.initProgressBar = function (node, value) {
31737            if (typeof node.progressbar === func) {
31738                return node.progressbar({
31739                    value: value
31740                });
31741            } else {
31742                var progressbar = $('<progress value="' + value + '" max="100"/>').appendTo(node);
31743                progressbar.progressbar = function (key, value) {
31744                    progressbar.attr('value', value);
31745                };
31746                return progressbar;
31747            }
31748        };
31749        
31750        this.initUploadRow = function (event, files, index, xhr, handler, callBack) {
31751            var uploadRow = handler.uploadRow = uploadHandler.buildUploadRow(files, index);
31752            if (uploadRow) {
31753                handler.progressbar = uploadHandler.initProgressBar(
31754                    uploadRow.find(uploadHandler.progressSelector),
31755                    (xhr.upload ? 0 : 100)
31756                );
31757                uploadRow.find(uploadHandler.cancelSelector).click(function (e) {
31758                    uploadHandler.cancelUpload(e, files, index, xhr, handler);
31759                });
31760            }
31761            uploadHandler.addNode(uploadHandler.uploadTable, uploadRow, callBack);
31762        };
31763        
31764        this.initUpload = function (event, files, index, xhr, handler, callBack) {
31765            uploadHandler.initUploadRow(event, files, index, xhr, handler, function () {
31766                if (typeof uploadHandler.beforeSend === func) {
31767                    uploadHandler.beforeSend(event, files, index, xhr, handler, callBack);
31768                } else {
31769                    callBack();
31770                }
31771            });
31772        };
31773        
31774        this.onProgress = function (event, files, index, xhr, handler) {
31775            if (handler.progressbar) {
31776                handler.progressbar.progressbar(
31777                    'value',
31778                    parseInt(event.loaded / event.total * 100, 10)
31779                );
31780            }
31781        };
31782        
31783        this.parseResponse = function (xhr) {
31784            if (typeof xhr.responseText !== undef) {
31785                return $.parseJSON(xhr.responseText);
31786            } else {
31787                // Instead of an XHR object, an iframe is used for legacy browsers:
31788                return $.parseJSON(xhr.contents().text());
31789            }
31790        };
31791        
31792        this.initDownloadRow = function (event, files, index, xhr, handler, callBack) {
31793            var json, downloadRow;
31794            try {
31795                json = handler.response = uploadHandler.parseResponse(xhr);
31796                downloadRow = handler.downloadRow = uploadHandler.buildDownloadRow(json);
31797                uploadHandler.addNode(uploadHandler.downloadTable, downloadRow, callBack);
31798            } catch (e) {
31799                if (typeof uploadHandler.onError === func) {
31800                    handler.originalEvent = event;
31801                    uploadHandler.onError(e, files, index, xhr, handler);
31802                } else {
31803                    throw e;
31804                }
31805            }
31806        };
31807        
31808        this.onLoad = function (event, files, index, xhr, handler) {
31809            uploadHandler.removeNode(handler.uploadRow, function () {
31810                uploadHandler.initDownloadRow(event, files, index, xhr, handler, function () {alert('Line no : 161...');
31811                    if (typeof uploadHandler.onComplete === func) {
31812                        uploadHandler.onComplete(event, files, index, xhr, handler);
31813                    }
31814                });
31815            });
31816        };
31817
31818        this.dropZoneEnlarge = function () {
31819            if (!isDropZoneEnlarged) {
31820                if (typeof uploadHandler.dropZone.switchClass === func) {
31821                    uploadHandler.dropZone.switchClass(
31822                        uploadHandler.cssClassSmall,
31823                        uploadHandler.cssClassLarge
31824                    );
31825                } else {
31826                    uploadHandler.dropZone.addClass(uploadHandler.cssClassLarge);
31827                    uploadHandler.dropZone.removeClass(uploadHandler.cssClassSmall);
31828                }
31829                isDropZoneEnlarged = true;
31830            }
31831        };
31832        
31833        this.dropZoneReduce = function () {
31834            if (typeof uploadHandler.dropZone.switchClass === func) {
31835                uploadHandler.dropZone.switchClass(
31836                    uploadHandler.cssClassLarge,
31837                    uploadHandler.cssClassSmall
31838                );
31839            } else {
31840                uploadHandler.dropZone.addClass(uploadHandler.cssClassSmall);
31841                uploadHandler.dropZone.removeClass(uploadHandler.cssClassLarge);
31842            }
31843            isDropZoneEnlarged = false;
31844        };
31845
31846        this.onDocumentDragEnter = function (event) {
31847            uploadHandler.dropZoneEnlarge();
31848        };
31849        
31850        this.onDocumentDragOver = function (event) {
31851            if (dragOverTimeout) {
31852                clearTimeout(dragOverTimeout);
31853            }
31854            dragOverTimeout = setTimeout(function () {
31855                uploadHandler.dropZoneReduce();
31856            }, 200);
31857        };
31858        
31859        this.onDragEnter = this.onDragLeave = function (event) {
31860            uploadHandler.dropZone.toggleClass(uploadHandler.cssClassHighlight);
31861        };
31862        
31863        this.onDrop = function (event) {
31864            if (dragOverTimeout) {
31865                clearTimeout(dragOverTimeout);
31866            }
31867            if (uploadHandler.dropEffect && typeof uploadHandler.dropZone.effect === func) {
31868                uploadHandler.dropZone.effect(uploadHandler.dropEffect, function () {
31869                    uploadHandler.dropZone.removeClass(uploadHandler.cssClassHighlight);
31870                    uploadHandler.dropZoneReduce();
31871                });
31872            } else {
31873                uploadHandler.dropZone.removeClass(uploadHandler.cssClassHighlight);
31874                uploadHandler.dropZoneReduce();
31875            }
31876        };
31877
31878        $.extend(this, options);
31879    },
31880
31881    methods = {
31882        init : function (options) {
31883            return this.each(function () {
31884                $(this).fileUpload(new UploadHandler($(this), options));
31885            });
31886        },
31887        
31888        destroy : function (namespace) {
31889            return this.each(function () {
31890                $(this).fileUpload('destroy', namespace);
31891            });
31892        }
31893    };
31894    
31895    $.fn.fileUploadUI = function (method) {
31896        if (methods[method]) {
31897            return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
31898        } else if (typeof method === 'object' || !method) {
31899            return methods.init.apply(this, arguments);
31900        } else {
31901            $.error('Method ' + method + ' does not exist on jQuery.fileUploadUI');
31902        }
31903    };
31904    
31905}(jQuery));
31906/**
31907 * jQuery custom event "outerClick".
31908 * @author Senad Dizdar
31909 * 
31910 * Copyright (C) 2010-2011, cloudHQ 
31911 * All rights reserved.
31912 * 
31913 * The outerClick event is fired when an element outside of all target element is clicked.
31914 * 
31915 * Usage:
31916 * $(selector).bind("outerClick", fn);   // Bind the function fn to the outerClick event on each of the matched elements.
31917 * $(selector).outerClick(fn);           // Bind the function fn to the outerClick event on each of the matched elements.
31918 * $(selector).trigger("outerClick");    // Trigger the outerClick event on each of the matched elements.
31919 * $(selector).outerClick();             // Trigger the outerClick event on each of the matched elements.
31920 * $(selector).unbind("outerClick", fn); // Unbind the function fn from the outerClick event on each of the matched elements.
31921 * $(selector).unbind("outerClick");     // Unbind all outerClick events from each of the matched elements.
31922 */
31923
31924/*global jQuery */
31925(function ($, elements, OUTER_CLICK) {
31926  
31927  /**
31928   * Check if the event should be fired.
31929   * @param {Object} event The click event.
31930   * @private
31931   */
31932  function check(event) {
31933    var j = 0;
31934    for (var i = 0, l = elements.length, target = event.target, el; i < l; i++) 
31935    {
31936      el = elements[i];
31937      if (el !== target && !(el.contains ? el.contains(target) : el.compareDocumentPosition ? el.compareDocumentPosition(target) & 16 : 1)) 
31938      {
31939        j++;
31940      }
31941    }
31942    if (j == elements.length)
31943    {
31944      $.event.trigger(OUTER_CLICK, event, el);
31945    }
31946  }
31947  
31948  
31949  $.event.special[OUTER_CLICK] = {
31950    
31951    setup: function () 
31952    {
31953      var i = elements.length;
31954      if (!i) 
31955      {
31956        $.event.add(document, 'click', check);
31957      }
31958      if ($.inArray(this, elements) < 0) 
31959      {
31960        elements[i] = this;
31961      }
31962    },
31963    
31964    teardown: function () 
31965    {
31966      var i = $.inArray(this, elements);
31967      if (i >= 0) 
31968      {
31969        elements.splice(i, 1);
31970        if (!elements.length) 
31971        {
31972          $.event.remove(document, 'click', check);
31973        }
31974      }
31975    }
31976    
31977  };
31978  
31979  /**
31980   * Event helper outerClick
31981   * 
31982   * @param  {Function}
31982 [fn]  A function to bind to the outerClick event on each of the matched elements.
31983   *                          If fn is omitted the event is triggered.
31984   * @return {jQuery}         Returns the jQuery object.
31985   */
31986  $.fn[OUTER_CLICK] = function (fn) 
31987  {
31988    return fn ? this.bind(OUTER_CLICK, fn) : this.trigger(OUTER_CLICK);
31989  };
31990  
31991})(jQuery, [], 'outerClick');
31992
31993
31994
31995
31996/*
31997 * jQuery JSON Plugin
31998 * version: 1.0 (2008-04-17)
31999 *
32000 * This document is licensed as free software under the terms of the
32001 * MIT License: http://www.opensource.org/licenses/mit-license.php
32002 *
32003 * Brantley Harris technically wrote this plugin, but it is based somewhat
32004 * on the JSON.org website's http://www.json.org/json2.js, which proclaims:
32005 * "NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.", a sentiment that
32006 * I uphold.  I really just cleaned it up.
32007 *
32008 * It is also based heavily on MochiKit's serializeJSON, which is 
32009 * copywrited 2005 by Bob Ippolito.
32010 */
32011 
32012(function($) {   
32013    function toIntegersAtLease(n) 
32014    // Format integers to have at least two digits.
32015    {    
32016        return n < 10 ? '0' + n : n;
32017    }
32018
32019    Date.prototype.toJSON = function(date)
32020    // Yes, it polutes the Date namespace, but we'll allow it here, as
32021    // it's damned usefull.
32022    {
32023        return this.getUTCFullYear()   + '-' +
32024             toIntegersAtLease(this.getUTCMonth()) + '-' +
32025             toIntegersAtLease(this.getUTCDate());
32026    };
32027
32028    var escapeable = /["\\\x00-\x1f\x7f-\x9f]/g;
32029    var meta = {    // table of character substitutions
32030            '\b': '\\b',
32031            '\t': '\\t',
32032            '\n': '\\n',
32033            '\f': '\\f',
32034            '\r': '\\r',
32035            '"' : '\\"',
32036            '\\': '\\\\'
32037        };
32038        
32039    $.quoteString = function(string)
32040    // Places quotes around a string, inteligently.
32041    // If the string contains no control characters, no quote characters, and no
32042    // backslash characters, then we can safely slap some quotes around it.
32043    // Otherwise we must also replace the offending characters with safe escape
32044    // sequences.
32045    {
32046        if (escapeable.test(string))
32047        {
32048            return '"' + string.replace(escapeable, function (a) 
32049            {
32050                var c = meta[a];
32051                if (typeof c === 'string') {
32052                    return c;
32053                }
32054                c = a.charCodeAt();
32055                return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16);
32056            }) + '"';
32057        }
32058        return '"' + string + '"';
32059    };
32060    
32061    $.toJSON = function(o, compact)
32062    {
32063        var type = typeof(o);
32064        
32065        if (type == "undefined")
32066            return "undefined";
32067        else if (type == "number" || type == "boolean")
32068            return o + "";
32069        else if (o === null)
32070            return "null";
32071        
32072        // Is it a string?
32073        if (type == "string") 
32074        {
32075            return $.quoteString(o);
32076        }
32077        
32078        // Does it have a .toJSON function?
32079        if (type == "object" && typeof o.toJSON == "function") 
32080            return o.toJSON(compact);
32081        
32082        // Is it an array?
32083        if (type != "function" && typeof(o.length) == "number") 
32084        {
32085            var ret = [];
32086            for (var i = 0; i < o.length; i++) {
32087                ret.push( $.toJSON(o[i], compact) );
32088            }
32089            if (compact)
32090                return "[" + ret.join(",") + "]";
32091            else
32092                return "[" + ret.join(", ") + "]";
32093        }
32094        
32095        // If it's a function, we have to warn somebody!
32096        if (type == "function") {
32097            throw new TypeError("Unable to convert object of type 'function' to json.");
32098        }
32099        
32100        // It's probably an object, then.
32101        var ret = [];
32102        for (var k in o) {
32103            var name;
32104            type = typeof(k);
32105            
32106            if (type == "number")
32107                name = '"' + k + '"';
32108            else if (type == "string")
32109                name = $.quoteString(k);
32110            else
32111                continue;  //skip non-string or number keys
32112            
32113            var val = $.toJSON(o[k], compact);
32114            if (typeof(val) != "string") {
32115                // skip non-serializable values
32116                continue;
32117            }
32118            
32119            if (compact)
32120                ret.push(name + ":" + val);
32121            else
32122                ret.push(name + ": " + val);
32123        }
32124        return "{" + ret.join(", ") + "}";
32125    };
32126    
32127    $.compactJSON = function(o)
32128    {
32129        return $.toJSON(o, true);
32130    };
32131    
32132    $.evalJSON = function(src)
32133    // Evals JSON that we know to be safe.
32134    {
32135        return eval("(" + src + ")");
32136    };
32137    
32138    $.secureEvalJSON = function(src)
32139    // Evals JSON in a way that is *more* secure.
32140    {
32141        var filtered = src;
32142        filtered = filtered.replace(/\\["\\\/bfnrtu]/g, '@');
32143        filtered = filtered.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']');
32144        filtered = filtered.replace(/(?:^|:|,)(?:\s*\[)+/g, '');
32145        
32146        if (/^[\],:{}\s]*$/.test(filtered))
32147            return eval("(" + src + ")");
32148        else
32149            throw new SyntaxError("Error parsing JSON, source is not valid.");
32150    };
32151})(jQuery);
32152
32153(function ($) {
32154    $.format = (function () {
32155        function strDay(value) {
32156            switch (parseInt(value)) {
32157            case 0:
32158                return "Sunday";
32159            case 1:
32160                return "Monday";
32161            case 2:
32162                return "Tuesday";
32163            case 3:
32164                return "Wednesday";
32165            case 4:
32166                return "Thursday";
32167            case 5:
32168                return "Friday";
32169            case 6:
32170                return "Saturday";
32171            default:
32172                return value;
32173            }
32174        }
32175
32176        function strMonth(value) {
32177            switch (parseInt(value)) {
32178            case 1:
32179                return "Jan";
32180            case 2:
32181                return "Feb";
32182            case 3:
32183                return "Mar";
32184            case 4:
32185                return "Apr";
32186            case 5:
32187                return "May";
32188            case 6:
32189                return "Jun";
32190            case 7:
32191                return "Jul";
32192            case 8:
32193                return "Aug";
32194            case 9:
32195                return "Sep";
32196            case 10:
32197                return "Oct";
32198            case 11:
32199                return "Nov";
32200            case 12:
32201                return "Dec";
32202            default:
32203                return value;
32204            }
32205        }
32206
32207        var parseMonth = function (value) {
32208                switch (value) {
32209                case "Jan":
32210                    return "01";
32211                case "Feb":
32212                    return "02";
32213                case "Mar":
32214                    return "03";
32215                case "Apr":
32216                    return "04";
32217                case "May":
32218                    return "05";
32219                case "Jun":
32220                    return "06";
32221                case "Jul":
32222                    return "07";
32223                case "Aug":
32224                    return "08";
32225                case "Sep":
32226                    return "09";
32227                case "Oct":
32228                    return "10";
32229                case "Nov":
32230                    return "11";
32231                case "Dec":
32232                    return "12";
32233                default:
32234                    return value;
32235                }
32236            };
32237
32238        var parseTime = function (value) {
32239                var retValue = value;
32240                var millis = "";
32241                if (retValue.indexOf(".") !== -1) {
32242                    var delimited = retValue.split('.');
32243                    retValue = delimited[0];
32244                    millis = delimited[1];
32245                }
32246
32247                var values3 = retValue.split(":");
32248
32249                if (values3.length === 3) {
32250                    hour = values3[0];
32251                    minute = values3[1];
32252                    second = values3[2];
32253
32254                    return {
32255                        time: retValue,
32256                        hour: hour,
32257                        minute: minute,
32258                        second: second,
32259                        millis: millis
32260                    };
32261                } else {
32262                    return {
32263                        time: "",
32264                        hour: "",
32265                        minute: "",
32266                        second: "",
32267                        millis: ""
32268                    };
32269                }
32270            };
32271
32272        return {
32273            date: function (value, format) {
32274                /* 
32275          value = new java.util.Date()
32276                  2009-12-18 10:54:50.546 
32277        */
32278                try {
32279                    var date = null;
32280                    var year = null;
32281                    var month = null;
32282                    var dayOfMonth = null;
32283                    var dayOfWeek = null;
32284                    var time = null;
32285                    if (typeof value.getFullYear === "function") {
32286                        year = value.getFullYear();
32287                        month = value.getMonth() + 1;
32288                        dayOfMonth = value.getDate();
32289                        dayOfWeek = value.getDay();
32290                        time = parseTime(value.toTimeString());
32291          } else if (value.search(/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.?\d{0,3}[-+]?\d{2}:\d{2}/) != -1) { /* 2009-04-19T16:11:05+02:00 */
32292                        var values = value.split(/[T\+-]/);
32293                        year = values[0];
32294                        month = values[1];
32295                        dayOfMonth = values[2];
32296                        time = parseTime(values[3].split(".")[0]);
32297                        date = new Date(year, month - 1, dayOfMonth);
32298                        dayOfWeek = date.getDay();
32299                    } else {
32300                        var values = value.split(" ");
32301                        switch (values.length) {
32302                        case 6:
32303                            /* Wed Jan 13 10:43:41 CET 2010 */
32304                            year = values[5];
32305                            month = parseMonth(values[1]);
32306                            dayOfMonth = values[2];
32307                            time = parseTime(values[3]);
32308                            date = new Date(year, month - 1, dayOfMonth);
32309                            dayOfWeek = date.getDay();
32310                            break;
32311                        case 2:
32312                            /* 2009-12-18 10:54:50.546 */
32313                            var values2 = values[0].split("-");
32314                            year = values2[0];
32315                            month = values2[1];
32316                            dayOfMonth = values2[2];
32317                            time = parseTime(values[1]);
32318                            date = new Date(year, month - 1, dayOfMonth);
32319                            dayOfWeek = date.getDay();
32320                            break;
32321                        case 7:
32322                            /* Tue Mar 01 2011 12:01:42 GMT-0800 (PST) */
32323                        case 9:
32324                            /*added by Larry, for Fri Apr 08 2011 00:00:00 GMT+0800 (China Standard Time) */
32325                        case 10:
32326                            /* added by Larry, for Fri Apr 08 2011 00:00:00 GMT+0200 (W. Europe Daylight Time) */
32327                            year = values[3];
32328                            month = parseMonth(values[1]);
32329                            dayOfMonth = values[2];
32330                            time = parseTime(values[4]);
32331                            date = new Date(year, month - 1, dayOfMonth);
32332                            dayOfWeek = date.getDay();
32333                            break;
32334                        default:
32335                            return value;
32336                        }
32337                    }
32338
32339                    var pattern = "";
32340                    var retValue = "";
32341                    /*
32342            Issue 1 - variable scope issue in format.date 
32343                      Thanks jakemonO
32344          */
32345                    for (var i = 0; i < format.length; i++) {
32346                        var currentPattern = format.charAt(i);
32347                        pattern += currentPattern;
32348                        switch (pattern) {
32349                        case "ddd":
32350                            retValue += strDay(dayOfWeek);
32351                            pattern = "";
32352                            break;
32353                        case "dd":
32354                            if (format.charAt(i + 1) == "d") {
32355                                break;
32356                            }
32357                            if (String(dayOfMonth).length === 1) {
32358                                dayOfMonth = '0' + dayOfMonth;
32359                            }
32360                            retValue += dayOfMonth;
32361                            pattern = "";
32362                            break;
32363                        case "MMM":
32364                            retValue += strMonth(month);
32365                            pattern = "";
32366                            break;
32367                        case "MM":
32368                            if (format.charAt(i + 1) == "M") {
32369                                break;
32370                            }
32371                            if (String(month).length === 1) {
32372                                month = '0' + month;
32373                            }
32374                            retValue += month;
32375                            pattern = "";
32376                            break;
32377                        case "yyyy":
32378                            retValue += year;
32379                            pattern = "";
32380                            break;
32381                        case "HH":
32382                            retValue += time.hour;
32383                            pattern = "";
32384                            break;
32385                        case "hh":
32386                            /* time.hour is "00" as string == is used instead of === */
32387                            retValue += (time.hour == 0 ? 12 : time.hour < 13 ? time.hour : time.hour - 12);
32388                            pattern = "";
32389                            break;
32390                        case "mm":
32391                            retValue += time.minute;
32392                            pattern = "";
32393                            break;
32394                        case "ss":
32395                            /* ensure only seconds are added to the return string */
32396                            retValue += time.second.substring(0, 2);
32397                            pattern = "";
32398                            break;
32399                        case "SSS":
32400                            retValue += time.millis.substring(0, 3);
32401                            pattern = "";
32402                            break;
32403                        case "a":
32404                            retValue += time.hour >= 12 ? "PM" : "AM";
32405                            pattern = "";
32406                            break;
32407                        case " ":
32408                            retValue += currentPattern;
32409                            pattern = "";
32410                            break;
32411                        case "/":
32412                            retValue += currentPattern;
32413                            pattern = "";
32414                            break;
32415                        case ":":
32416                            retValue += currentPattern;
32417                            pattern = "";
32418                            break;
32419                        default:
32420                            if (pattern.length === 2 && pattern.indexOf("y") !== 0 && pattern != "SS") {
32421                                retValue += pattern.substring(0, 1);
32422                                pattern = pattern.substring(1, 2);
32423                            } else if ((pattern.length === 3 && pattern.indexOf("yyy") === -1)) {
32424                                pattern = "";
32425                            }
32426                        }
32427                    }
32428                    return retValue;
32429                } catch (e) {
32430                    console.log(e);
32431                    return value;
32432                }
32433            }
32434        };
32435    }());
32436}(jQuery));
32437
32438(function ($) {
32439         $.fn.localTimeFromUTC = function (format) {
32440            return this.each(function () {
32441    
32442                // get time offset from browser
32443                var currentDate = new Date();
32444                var offset = -(currentDate.getTimezoneOffset() / 60);
32445    
32446                // get provided date
32447                var tagText = $(this).html();
32448                var givenDate = new Date($.format.date(tagText, format));
32449    
32450                // format the date
32451                var localDateString = $.format.date(givenDate, format);
32452                $(this).html(localDateString + ' ' + givenDate);
32453            });
32454        };
32455 })(jQuery);
32456
32457$(document).ready(function () {
32458    $(".shortDateFormat").each(function (idx, elem) {
32459        if ($(elem).is(":input")) {
32460            $(elem).val($.format.date($(elem).val(), "dd/MM/yyyy"));
32461        } else {
32462            $(elem).text($.format.date($(elem).text(), "dd/MM/yyyy"));
32463        }
32464    });
32465    $(".longDateFormat").each(function (idx, elem) {
32466        if ($(elem).is(":input")) {
32467            $(elem).val($.format.date($(elem).val(), "dd/MM/yyyy hh:mm:ss"));
32468        } else {
32469            $(elem).text($.format.date($(elem).text(), "dd/MM/yyyy hh:mm:ss"));
32470        }
32471    });
32472});
32473// Domain Public by Eric Wendelin http://eriwen.com/ (2008)
32474//                  Luke Smith http://lucassmith.name/ (2008)
32475//                  Loic Dachary <[email protected]> (2008)
32476//                  Johan Euphrosine <[email protected]> (2008)
32477//                  Øyvind Sean Kinsey http://kinsey.no/blog (2010)
32478//
32479// Information and discussions
32480// http://jspoker.pokersource.info/skin/test-printstacktrace.html
32481// http://eriwen.com/javascript/js-stack-trace/
32482// http://eriwen.com/javascript/stacktrace-update/
32483// http://pastie.org/253058
32484//
32485// guessFunctionNameFromLines comes from firebug
32486//
32487// Software License Agreement (BSD License)
32488//
32489// Copyright (c) 2007, Parakey Inc.
32490// All rights reserved.
32491//
32492// Redistribution and use of this software in source and binary forms, with or without modification,
32493// are permitted provided that the following conditions are met:
32494//
32495// * Redistributions of source code must retain the above
32496//   copyright notice, this list of conditions and the
32497//   following disclaimer.
32498//
32499// * Redistributions in binary form must reproduce the above
32500//   copyright notice, this list of conditions and the
32501//   following disclaimer in the documentation and/or other
32502//   materials provided with the distribution.
32503//
32504// * Neither the name of Parakey Inc. nor the names of its
32505//   contributors may be used to endorse or promote products
32506//   derived from this software without specific prior
32507//   written permission of Parakey Inc.
32508//
32509// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
32510// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
32511// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
32512// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32513// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32514// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
32515// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32516// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32517
32518/**
32519 * Main function giving a function stack trace with a forced or passed in Error 
32520 *
32521 * @cfg {Error} e The error to create a stacktrace from (optional)
32522 * @cfg {Boolean} guess If we should try to resolve the names of anonymous functions
32523 * @return {Array} of Strings with functions, lines, files, and arguments where possible 
32524 */
32525function printStackTrace(options) {
32526    var ex = (options && options.e) ? options.e : null;
32527    var guess = options ? !!options.guess : true;
32528    
32529    var p = new printStackTrace.implementation();
32530    var result = p.run(ex);
32531    return (guess) ? p.guessFunctions(result) : result;
32532}
32533
32534printStackTrace.implementation = function() {};
32535
32536printStackTrace.implementation.prototype = {
32537    run: function(ex) {
32538        ex = ex ||
32539            (function() {
32540                try {
32541                    var _err = __undef__ << 1;
32542                } catch (e) {
32543                    return e;
32544                }
32545            })();
32546        // Use either the stored mode, or resolve it
32547        var mode = this._mode || this.mode(ex);
32548        if (mode === 'other') {
32549            return this.other(arguments.callee);
32550        } else {
32551            return this[mode](ex);
32552        }
32553    },
32554    
32555    /**
32556     * @return {String} mode of operation for the environment in question.
32557     */
32558    mode: function(e) {
32559        if (e['arguments']) {
32560            return (this._mode = 'chrome');
32561        } else if (window.opera && e.stacktrace) {
32562            return (this._mode = 'opera10');
32563        } else if (e.stack) {
32564            return (this._mode = 'firefox');
32565        } else if (window.opera && !('stacktrace' in e)) { //Opera 9-
32566            return (this._mode = 'opera');
32567        }
32568        return (this._mode = 'other');
32569    },
32570
32571    /**
32572     * Given a context, function name, and callback function, overwrite it so that it calls
32573     * printStackTrace() first with a callback and then runs the rest of the body.
32574     * 
32575     * @param {Object} context of execution (e.g. window)
32576     * @param {String} functionName to instrument
32577     * @param {Function} function to call with a stack trace on invocation
32578     */
32579    instrumentFunction: function(context, functionName, callback) {
32580        context = context || window;
32581        context['_old' + functionName] = context[functionName];
32582        context[functionName] = function() { 
32583            callback.call(this, printStackTrace());
32584            return context['_old' + functionName].apply(this, arguments);
32585        };
32586        context[functionName]._instrumented = true;
32587    },
32588    
32589    /**
32590     * Given a context and function name of a function that has been
32591     * instrumented, revert the function to it's original (non-instrumented)
32592     * state.
32593     *
32594     * @param {Object} context of execution (e.g. window)
32595     * @param {String} functionName to de-instrument
32596     */
32597    deinstrumentFunction: function(context, functionName) {
32598        if (context[functionName].constructor === Function &&
32599                context[functionName]._instrumented &&
32600                context['_old' + functionName].constructor === Function) {
32601            context[functionName] = context['_old' + functionName];
32602        }
32603    },
32604    
32605    /**
32606     * Given an Error object, return a formatted Array based on Chrome's stack string.
32607     * 
32608     * @param e - Error object to inspect
32609     * @return Array<String> of function calls, files and line numbers
32610     */
32611    chrome: function(e) {
32612        return e.stack.replace(/^[^\(]+?[\n$]/gm, '').replace(/^\s+at\s+/gm, '').replace(/^Object.<anonymous>\s*\(/gm, '{anonymous}()@').split('\n');
32613    },
32614
32615    /**
32616     * Given an Error object, return a formatted Array based on Firefox's stack string.
32617     * 
32618     * @param e - Error object to inspect
32619     * @return Array<String> of function calls, files and line numbers
32620     */
32621    firefox: function(e) {
32622        return e.stack.replace(/(?:\n@:0)?\s+$/m, '').replace(/^\(/gm, '{anonymous}(').split('\n');
32623    },
32624
32625    /**
32626     * Given an Error object, return a formatted Array based on Opera 10's stacktrace string.
32627     * 
32628     * @param e - Error object to inspect
32629     * @return Array<String> of function calls, files and line numbers
32630     */
32631    opera10: function(e) {
32632        var stack = e.stacktrace;
32633        var lines = stack.split('\n'), ANON = '{anonymous}',
32634            lineRE = /.*line (\d+), column (\d+) in ((<anonymous function\:?\s*(\S+))|([^\(]+)\([^\)]*\))(?: in )?(.*)\s*$/i, i, j, len;
32635        for (i = 2, j = 0, len = lines.length; i < len - 2; i++) {
32636            if (lineRE.test(lines[i])) {
32637                var location = RegExp.$6 + ':' + RegExp.$1 + ':' + RegExp.$2;
32638                var fnName = RegExp.$3;
32639                fnName = fnName.replace(/<anonymous function\:?\s?(\S+)?>/g, ANON);
32640                lines[j++] = fnName + '@' + location;
32641            }
32642        }
32643        
32644        lines.splice(j, lines.length - j);
32645        return lines;
32646    },
32647    
32648    // Opera 7.x-9.x only!
32649    opera: function(e) {
32650        var lines = e.message.split('\n'), ANON = '{anonymous}', 
32651            lineRE = /Line\s+(\d+).*script\s+(http\S+)(?:.*in\s+function\s+(\S+))?/i, 
32652            i, j, len;
32653        
32654        for (i = 4, j = 0, len = lines.length; i < len; i += 2) {
32655            //TODO: RegExp.exec() would probably be cleaner here
32656            if (lineRE.test(lines[i])) {
32657                lines[j++] = (RegExp.$3 ? RegExp.$3 + '()@' + RegExp.$2 + RegExp.$1 : ANON + '()@' + RegExp.$2 + ':' + RegExp.$1) + ' -- ' + lines[i + 1].replace(/^\s+/, '');
32658            }
32659        }
32660        
32661        lines.splice(j, lines.length - j);
32662        return lines;
32663    },
32664    
32665    // Safari, IE, and others
32666    other: function(curr) {
32667        var ANON = '{anonymous}', fnRE = /function\s*([\w\-$]+)?\s*\(/i,
32668            stack = [], j = 0, fn, args;
32669        
32670        var maxStackSize = 10;
32671        while (curr && stack.length < maxStackSize) {
32672            fn = fnRE.test(curr.toString()) ? RegExp.$1 || ANON : ANON;
32673            args = Array.prototype.slice.call(curr['arguments']);
32674            stack[j++] = fn + '(' + this.stringifyArguments(args) + ')';
32675            curr = curr.caller;
32676        }
32677        return stack;
32678    },
32679    
32680    /**
32681     * Given arguments array as a String, subsituting type names for non-string types.
32682     *
32683     * @param {Arguments} object
32684     * @return {Array} of Strings with stringified arguments
32685     */
32686    stringifyArguments: function(args) {
32687        for (var i = 0; i < args.length; ++i) {
32688            var arg = args[i];
32689            if (arg === undefined) {
32690                args[i] = 'undefined';
32691            } else if (arg === null) {
32692                args[i] = 'null';
32693            } else if (arg.constructor) {
32694                if (arg.constructor === Array) {
32695                    if (arg.length < 3) {
32696                        args[i] = '[' + this.stringifyArguments(arg) + ']';
32697                    } else {
32698                        args[i] = '[' + this.stringifyArguments(Array.prototype.slice.call(arg, 0, 1)) + '...' + this.stringifyArguments(Array.prototype.slice.call(arg, -1)) + ']';
32699                    }
32700                } else if (arg.constructor === Object) {
32701                    args[i] = '#object';
32702                } else if (arg.constructor === Function) {
32703                    args[i] = '#function';
32704                } else if (arg.constructor === String) {
32705                    args[i] = '"' + arg + '"';
32706                }
32707            }
32708        }
32709        return args.join(',');
32710    },
32711    
32712    sourceCache: {},
32713    
32714    /**
32715     * @return the text from a given URL.
32716     */
32717    ajax: function(url) {
32718        var req = this.createXMLHTTPObject();
32719        if (!req) {
32720            return;
32721        }
32722        req.open('GET', url, false);
32723        req.setRequestHeader('User-Agent', 'XMLHTTP/1.0');
32724        req.send('');
32725        return req.responseText;
32726    },
32727    
32728    /**
32729     * Try XHR methods in order and store XHR factory.
32730     *
32731     * @return <Function> XHR function or equivalent
32732     */
32733    createXMLHTTPObject: function() {
32734        var xmlhttp, XMLHttpFactories = [
32735            function() {
32736                return new XMLHttpRequest();
32737            }, function() {
32738                return new ActiveXObject('Msxml2.XMLHTTP');
32739            }, function() {
32740                return new ActiveXObject('Msxml3.XMLHTTP');
32741            }, function() {
32742                return new ActiveXObject('Microsoft.XMLHTTP');
32743            }
32744        ];
32745        for (var i = 0; i < XMLHttpFactories.length; i++) {
32746            try {
32747                xmlhttp = XMLHttpFactories[i]();
32748                // Use memoization to cache the factory
32749                this.createXMLHTTPObject = XMLHttpFactories[i];
32750                return xmlhttp;
32751            } catch (e) {}
32752        }
32753    },
32754
32755    /**
32756     * Given a URL, check if it is in the same domain (so we can get the source
32757     * via Ajax).
32758     *
32759     * @param url <String> source url
32760     * @return False if we need a cross-domain request
32761     */
32762    isSameDomain: function(url) {
32763        return url.indexOf(location.hostname) !== -1;
32764    },
32765    
32766    /**
32767     * Get source code from given URL if in the same domain.
32768     *
32769     * @param url <String> JS source URL
32770     * @return <String> Source code
32771     */
32772    getSource: function(url) {
32773        if (!(url in this.sourceCache)) {
32774            this.sourceCache[url] = this.ajax(url).split('\n');
32775        }
32776        return this.sourceCache[url];
32777    },
32778    
32779    guessFunctions: function(stack) {
32780        for (var i = 0; i < stack.length; ++i) {
32781            var reStack = /\{anonymous\}\(.*\)@(\w+:\/\/([\-\w\.]+)+(:\d+)?[^:]+):(\d+):?(\d+)?/;
32782            var frame = stack[i], m = reStack.exec(frame);
32783            if (m) {
32784                var file = m[1], lineno = m[4]; //m[7] is character position in Chrome
32785                if (file && this.isSameDomain(file) && lineno) {
32786                    var functionName = this.guessFunctionName(file, lineno);
32787                    stack[i] = frame.replace('{anonymous}', functionName);
32788                }
32789            }
32790        }
32791        return stack;
32792    },
32793    
32794    guessFunctionName: function(url, lineNo) {
32795        try {
32796            return this.guessFunctionNameFromLines(lineNo, this.getSource(url));
32797        } catch (e) {
32798            return 'getSource failed with url: ' + url + ', exception: ' + e.toString();
32799        }
32800    },
32801    
32802    guessFunctionNameFromLines: function(lineNo, source) {
32803        var reFunctionArgNames = /function ([^(]*)\(([^)]*)\)/;
32804        var reGuessFunction = /['"]?([0-9A-Za-z_]+)['"]?\s*[:=]\s*(function|eval|new Function)/;
32805        // Walk backwards from the first line in the function until we find the line which
32806        // matches the pattern above, which is the function definition
32807        var line = "", maxLines = 10;
32808        for (var i = 0; i < maxLines; ++i) {
32809            line = source[lineNo - i] + line;
32810            if (line !== undefined) {
32811                var m = reGuessFunction.exec(line);
32812                if (m && m[1]) {
32813                    return m[1];
32814                } else {
32815                    m = reFunctionArgNames.exec(line);
32816                    if (m && m[1]) {
32817                        return m[1];
32818                    }
32819                }
32820            }
32821        }
32822        return '(?)';
32823    }
32824};
32825
32826/**
32827 * @author Senad Dizdar
32828 * 
32829 * Copyright (C) 2010-2011, cloudHQ 
32830 * All rights reserved.
32831 *
32832 */
32833
32834g_jstree_refresh_inprogress = 0;
32835
32836function c_files(){
32837  var left_tree_expand_plan = new Array();
32838  var upload = new Object();
32839  
32840  /*********************************************/
32841  /* PUBLIC FUNCTIONS                           */
32842  /*********************************************/
32843  
32844  /***
32845   * Initilize for creating of c_files object
32846   */
32847  this.fn_init = function fn_init(){
32848
32849    $('input.working_link').unbind('click').bind('click', function() {      
32850      if ($(this).hasClass('noclick')) {
32851        return false;
32852      }
32853      var text = "Working...";
32854      if ($(this).attr('notif_to_display') != null)
32855        text = $(this).attr('notif_to_display');
32856      try { g_cmn.fn_working_overlay(true, text); } catch(er)  { }
32857      return true;
32858    });
32859
32860    // setup resizing of columns
32861    fn_right_jstree_columns_setup();
32862    
32863    // call server to intilize 
32864    $.ajax({
32865      type: "POST",
32866      url: g_site_url + "main_cloud_fs_interface/cloudhq_init",
32867      dataType: "json",
32868      data: { 'raise_authorization_error_flag': true },
32869      async: true,
32870      success: function(response){
32871        if (response.verify_credential) {
32872          var res_ver_cred = response.verify_credential;
32873          var txt = 'Authorization for <b>' + res_ver_cred.what_nice + '</b> expired. <br>';
32874          var url = g_site_url + "modify_services/" + res_ver_cred.what + "?email_or_login=" + res_ver_cred.email_or_login;
32875          txt += 'Do you want to reauthorize cloudHQ with ' + res_ver_cred.what_nice + '?';
32876          if (res_ver_cred.domain && res_ver_cred.domain != 'nil') 
32877            url += "&domain=" + res_ver_cred.domain;
32878          
32879          g_cmn.fn_error_dialog("ERROR", txt, {
32880            width: "500px",
32881            buttons: {
32882              "Ignore": function(){
32883                fn_init_ignore_authorization_error();
32884                $(this).dialog("close");
32885              },
32886              "Ok": function(){
32887                location.href = url;
32888                $(this).dialog("close");
32889              }
32890            }
32891          });
32892        }
32893        else {
32894          if (response.error) {
32895            g_cmn.fn_error_dialog("ERROR", "<center>Sorry, a temporary error has occurred.<br/>Please refresh the page.</center>", {
32896              width: "370px"
32897            });
32898          }
32899          else {
32900            fn_display_left_jstree(response);
32901            fn_display_copy_node_jstree(response);
32902            fn_display_move_node_jstree(response);
32903            
32904            fn_resize_areas();
32905            $(window).resize(function(){
32906              fn_resize_areas();
32907            });
32908            
32909          }
32910        }
32911      },
32912      failure: function(response){
32913        alert("Failure");
32914      }
32915    });
32916  }
32917
32918  var fn_init_ignore_authorization_error = function fn_init_ignore_authorization_error(){
32919    
32920    // setup resizing of columns
32921    fn_right_jstree_columns_setup();
32922    
32923    // call server to intilize 
32924    $.ajax({
32925      type: "POST",
32926      url: g_site_url + "main_cloud_fs_interface/cloudhq_init",
32927      dataType: "json",
32928      data: { 'raise_authorization_error_flag': false },
32929      async: true,
32930      success: function(response){
32931        if (response.verify_credential) {
32932          $(this).dialog("close");
32933          g_cmn.fn_error_dialog("ERROR", "<center>Sorry, a temporary error has occurred.<br/>Please refresh the page.</center>", {
32934            width: "370px"
32935          });
32936
32937        }
32938        else {
32939          if (response.error) {
32940            g_cmn.fn_error_dialog("ERROR", "<center>Sorry, a temporary error has occurred.<br/>Please refresh the page.</center>", {
32941              width: "370px"
32942            });
32943          }
32944          else {
32945            fn_display_left_jstree(response);
32946            fn_display_copy_node_jstree(response);
32947            fn_display_move_node_jstree(response);
32948            
32949            fn_resize_areas();
32950            $(window).resize(function(){
32951              fn_resize_areas();
32952            });
32953            
32954          }
32955        }
32956      },
32957      failure: function(response){
32958        alert("Failure");
32959      }
32960    });
32961  }
32962
32963  /*********************************************/
32964  /* PRIVATE FUNCTIONS                         */
32965  /*********************************************/
32966  var fn_display_left_jstree = function fn_display_left_jstree(response) {
32967    $('#left_jstree_container').jstree("destroy");
32968    $('#left_jstree_container').bind('load_node.jstree', function(event, data){
32969      // alert("reopen");
32970    })
32971    .jstree({
32972      "core": {
32973        html_titles: true
32974      },
32975      "json_data": {
32976        "correct_state": true,
32977        "data": response,
32978        "ajax": {
32979          "url": function(n) {
32980            if (n == -1) 
32981              return false;
32982            else {
32983              g_cmn.fn_notif_win(true, "Loading...", null);
32984              return g_site_url + "main_cloud_fs_interface/cloudhq_dir";
32985            }
32986          },
32987          "success": function(obj, t, x){
32988            $('#loading').css('display', 'none');
32989            
32990            if (t == "success") {
32991              
32992              var response = JSON.parse(x.responseText);
32993              if (response['error']) {
32994                // g_cmn.fn_error_dialog("ERROR", "<center>Sorry, a temporary error has occurred.<br/>Please refresh the page.</center>", { width: "370px" });
32995                // g_cmn.fn_notif_win(true, "Something went wrong... <br>Please refresh the page", 5000);
32996              }
32997              else 
32998                g_cmn.fn_notif_win(false, "", null);
32999            }
33000            else {
33001              g_cmn.fn_notif_win(false, "", null);
33002            }
33003          },
33004          "error": function(obj){
33005            // g_cmn.fn_error_dialog("ERROR", "<center>Sorry, a temporary error has occurred.<br/>Please refresh the page.</center>", { width: "370px" });
33006            // alert ("error: jQuery internal error. Please refresh the page.");
33007          },
33008          "data": function(element) {
33009
33010            if (element.data('jstree') == null) {
33011              // g_cmn.fn_notif_win(true, "Something went wrong... <br>Please refresh the page", 5000);
33012              g_cmn.fn_log("ERROR", "element.data('jstree') is null (1)");
33013            }
33014
33015            return {
33016              "obj":       $.toJSON(element.data('jstree')),
33017              "file_flag": $.toJSON(false)
33018            }
33019          }
33020        }
33021      },
33022      "themes": {
33023        "theme": "cloudhq",
33024        "dots": false,
33025        "icons": true
33026      },
33027      "plugins": ["themes", "json_data", "ui", "crrm", "types"]
33028    });
33029      
33030    // bind that on select node we call open node and display right tree 
33031    $("#left_jstree_container").bind("select_node.jstree", function(e, data){
33032
33033      // alert('event.originalEvent.type='+e.originalEvent.type);
33034      
33035      // if this is not click
33036      if (!(data && data.args[2] && data.args[2].originalEvent && data.args[2].originalEvent.type == 'click'))
33037      {
33038        if (g_jstree_refresh_inprogress > 1) {
33039          if ($("#left_jstree_container .jstree-open").length >= g_jstree_refresh_inprogress - 1) 
33040            g_jstree_refresh_inprogress = 0;
33041          else 
33042            return false;
33043        }
33044      }
33045        
33046      $("#left_jstree_container").jstree('open_node', data.rslt.obj);
33047      fn_display_right_jstree(data.rslt.obj);
33048
33049    });
33050    
33051    $('#refresh_item_btn').unbind("click").bind('click', function(e, data){
33052      fn_refresh_server(null, '');
33053    });
33054    
33055    
33056    // initilize upload logic
33057    fn_make_file_upload();
33058    
33059    // do resizable
33060    var padding_between_left_and_right = $('#files_container').width() -  $('#right_container').width() - $("#left_dir_container").width();
33061    $("#left_dir_container").resizable(
33062      { 
33063        maxWidth: 650,  
33064        minWidth: 250,
33065        handles: 'e', 
33066        resize: function() {
33067          var total_width = $('#files_container').width();
33068          $('#right_container').width(total_width - $("#left_dir_container").width() - padding_between_left_and_right);
33069          $('#right_dir_nofiles_wrap').width($('#right_container').width());
33070        }
33071      });
33072              
33073  } /* fn_display_left_jstree */
33074
33075
33076 /*
33077  * Display right jstree given root object
33078  */
33079  var fn_display_right_jstree = function fn_display_right_jstree(data_rslt_obj){
33080   
33081    var flag = false;
33082    var dir_obj;
33083    var current_ins_id = 0;
33084    
33085    if (data_rslt_obj == null)
33086    {
33087      g_cmn.fn_log("ERROR", "fn_display_right_jstree: data_rslt_obj is null (0)");
33088      return;
33089    }
33090
33091    if (data_rslt_obj.data('jstree') == null)
33092    {
33093      g_cmn.fn_log("ERROR", "fn_display_right_jstree: data_rslt_obj.data('jstree') is null (0)");
33094      return;
33095    }
33096
33097    // GROT: we save it into global so that 'copy'  and 'move' operations know where we stand
33098    // The right way is that copy/move dialogs query jstree to see top level
33099    g_top_right_jstree_node = data_rslt_obj.clone(true, true);
33100
33101    var top_right_jstree_node = data_rslt_obj.clone(true, true);
33102    var tmp = top_right_jstree_node.data('jstree');
33103    if (tmp && tmp['is_create_disabled'])
33104      g_is_create_disabled = true;
33105    else
33106      g_is_create_disabled = false;
33107	  
33108	if (tmp && tmp['is_folder_create_disabled'])
33109      g_is_folder_create_disabled = true;
33110    else
33111      g_is_folder_create_disabled = false;
33112    
33113    // this variable is used to check whether we are building a new tree
33114    // if set to true, that means we still have not build a tree completly  
33115    var first_call = true;
33116    
33117    // display the right container
33118    $('#right_dir_container').show();
33119    $('#right_jstree_container').show();
33120    $('#right_doc_container').hide();
33121    
33122    // display breadcrump for right tree
33123    // As of now that is just title
33124    var fn_display_breadcrumb = function(data_rslt_obj){
33125      var d = data_rslt_obj.data('jstree');
33126      $('#right_dir_container .right_dir_breadcrumb').html(d['title_no_html']);
33127      $('#synch_wizard_button_form_data').empty();
33128      if (d.is_folder && !d.is_synch_disabled) {
33129        // add input rows with obj (which is json object) and name (just string)
33130        $(document.createElement('input')).attr({'type': 'hidden', 'name': 'obj', 'value' : $.toJSON(d) }).appendTo($('#synch_wizard_button_form_data'));
33131        $('#synch_wizard_button_wrapper').show();
33132      }
33133      else
33134        $('#synch_wizard_button_wrapper').hide();
33135
33136    }
33137    
33138    fn_display_breadcrumb(data_rslt_obj);
33139    
33140    $('#main_checkbox').removeClass('toggle');
33141    $('#main_checkbox').attr({
33142      'checked': false
33143    });
33144    $('#right_dir_nofiles_container').hide();
33145    $('#right_jstree_container').jstree("destroy");
33146    $('#right_jstree_container').bind('load_node.jstree', function(event, data){
33147      // on load we need to resize right 
33148      fn_right_jstree_columns_resize();
33149    }).bind("before.jstree", function(e, data){
33150      if (data.func === "open_node") {
33151        // alert("open_node");
33152        // when server sends data it fills up metadata. This metadata puts "is_folder" flag. 
33153        var jstree = data.args[0].data('jstree');
33154        var is_folder = false;
33155        if (jstree) 
33156          is_folder = jstree['is_folder'];
33157        
33158        if (is_folder == true) {
33159          // find element id in left jstree and select it
33160          var n = $("#left_jstree_container " + "#" + data.args[0].attr("id"));
33161          $("#left_jstree_container").jstree('deselect_all');
33162          $("#left_jstree_container").jstree('select_node', n, false);
33163          document.getElementById('left_jstree_container').scrollTop = document.getElementById(data.args[0].attr("id")).offsetTop;
33164        }
33165        e.stopImmediatePropagation();
33166        return false;
33167      }
33168    }).jstree({
33169      "core": {
33170        html_titles: true
33171      },
33172      "json_data": {
33173        "ajax": {
33174          "url": function(n){
33175            g_cmn.fn_notif_win(true, "Loading...", null);
33176            return g_site_url + "main_cloud_fs_interface/cloudhq_dir";
33177          },
33178          "success": function(obj, t, x){
33179            // We display no files *only* if this is very first call
33180            if (first_call == true) {
33181              if (obj == null || obj.length == null || obj.length == 0) {
33182                $('#right_jstree_container').jstree("destroy").hide();
33183                $('#right_dir_nofile_content').html('Empty folder');
33184                $('#right_dir_nofiles_container').show();
33185              }
33186            }
33187            first_call = false;
33188            g_cmn.fn_notif_win(false, "", null);
33189          },
33190          "error": function(obj){
33191            // g_cmn.fn_notif_win(true, "Something went wrong... <br>Please refresh the page", 5000);
33192          },
33193          "data": function(element){
33194          
33195            var obj = null;
33196            if (element.attr == null || element.attr("id") == null) 
33197              obj = top_right_jstree_node.data('jstree');
33198            else 
33199              obj = element.data('jstree');
33200            
33201            if (obj == null) {
33202              //g_cmn.fn_notif_win(true, "Something went wrong... <br>Please refresh the page", 5000);
33203              g_cmn.fn_log("ERROR", "obj.data('jstree') is null (2)");
33204            }
33205
33206            return {
33207              "obj":       $.toJSON(obj),
33208              "file_flag": $.toJSON(true)
33209            }
33210          }
33211        }
33212      },
33213      "themes": {
33214        "theme": "cloudhq",
33215        "dots": false,
33216        "icons": true
33217      },
33218      "plugins": ["themes", "json_data", "ui", "crrm", "types" ]
33219    });
33220    
33221    $("#right_jstree_container").unbind("select_node.jstree").bind("select_node.jstree", function(e, data){
33222      // when server sends data it fills up metadata. This metadata puts "is_folder" flag. 
33223      var jstree = data.rslt.obj.data('jstree');
33224      var is_folder = false;
33225      if (jstree) 
33226        is_folder = jstree['is_folder'];
33227      
33228      if (is_folder == true) {
33229        // find element id in left jstree and select it
33230        var n = $("#left_jstree_container " + "#" + data.rslt.obj.attr("id"));
33231        $("#left_jstree_container").jstree('deselect_all');
33232        $("#left_jstree_container").jstree('select_node', n, false);
33233        document.getElementById('left_jstree_container').scrollTop = document.getElementById(data.rslt.obj.attr("id")).offsetTop;
33234        fn_display_right_jstree(data.rslt.obj);
33235      }
33236      else {
33237        // maybe we should disable view of documents?
33238        // var obj = $(data.rslt.obj).data('jstree');
33239        // fn_view_document(obj);
33240      }
33241    });
33242    
33243    $('#main_checkbox').unbind("click").bind('click', function(){
33244      if ($(this).hasClass('checkbox_icon')) {
33245        $(this).removeClass('checkbox_icon');
33246        $(this).addClass('checkbox_icon-checked');
33247        $("#right_jstree_container").jstree("check_all");
33248      }
33249      else {
33250        $(this).addClass('checkbox_icon');
33251        $(this).removeClass('checkbox_icon-checked');
33252        $("#right_jstree_container").jstree("uncheck_all");
33253      }
33254    });
33255    
33256    $('#upload_new_file_btn').unbind("click").bind('click', function(e, data){
33257
33258      if (top_right_jstree_node.length > 0 && top_right_jstree_node.data('jstree').what == 'google_gmail')
33259        fn_error_dialog('Error', 'Creating new Gmail messages is not supported.');
33260      else if (g_is_create_disabled == false) {
33261        // The node_id is in form which will be submited on upload
33262        var d = top_right_jstree_node.data('jstree');
33263        $('#upload_new_file_dialog #upload_obj').val($.toJSON(d));
33264        upload_new_file_dialog.dialog('open');
33265      } else 
33266        g_cmn.fn_notif_win(true, 'Upload not allowed on this level', 5000);
33267    });
33268    
33269    $('#new_folder_btn').unbind("click").bind('click', function(){
33270    
33271      if (top_right_jstree_node.length > 0 && top_right_jstree_node.data('jstree').what == 'google_gmail')
33272        fn_error_dialog('Error', 'Creating of new Gmail labels is not supported.');
33273      else if (g_is_create_disabled == false && g_is_folder_create_disabled == false) 
33274        create_new_folder_dialog.dialog('open');
33275      else 
33276        g_cmn.fn_notif_win(true, 'New folder creation not allowed on this level', 5000);
33277    });
33278
33279    $('#copy_item_btn').unbind("click").bind('click', function(){
33280      if (!fn_get_checked_element_flag()) {
33281        fn_error_dialog('Error', 'Nothing selected.');
33282      }
33283      else if (fn_is_item_gmail()) {
33284        fn_error_dialog('Error', 'Copy for Gmail is not supported.');
33285      }
33286      else {
33287        copy_node_dialog.dialog('open');
33288      }
33289    });
33290    
33291    $('#move_item_btn').unbind("click").bind('click', function(){
33292      if (!fn_get_checked_element_flag()) 
33293        fn_error_dialog('Error', 'Nothing selected.');
33294      else if (fn_is_item_gmail()) {
33295        fn_error_dialog('Error', 'Move for Gmail is not supported.');
33296      }
33297      else {
33298        move_node_dialog.dialog('open');
33299      }
33300    });
33301    
33302    $('#delete_item_btn').unbind("click").bind('click', function(){
33303      if (!fn_get_checked_element_flag()) 
33304        fn_error_dialog('Error', 'Nothing selected.');
33305      else if (fn_is_item_gmail()) {
33306        fn_error_dialog('Error', 'Delete for Gmail is not supported.');
33307      }
33308      else {
33309        var checked_obj = $("#right_jstree_container").jstree("get_checked");
33310        var doc = document;
33311        var ul_node = doc.createElement('ul');
33312        $(checked_obj).each(function(){
33313          var node_text = $('#left_jstree_container').jstree("get_text", this);
33314          var li_node = doc.createElement('li');
33315          $(li_node).html(node_text);
33316          $(li_node).appendTo(ul_node);
33317        });
33318        $('#delete_node_list').html('');
33319        $(ul_node).appendTo($('#delete_node_list'));
33320        delete_node_dialog.dialog('open');
33321      }
33322    });
33323    
33324    $('#download_item_btn').unbind("click").bind('click', function(){
33325      if (!fn_get_checked_element_flag()) 
33326        fn_error_dialog('Error', 'Nothing selected.');
33327      else if (fn_is_item_gmail()) {
33328        fn_error_dialog('Error', 'Download for Gmail is not supported.');
33329      }
33330      else {
33331        var checked_obj = $("#right_jstree_container").jstree("get_checked");
33332        var doc = document;
33333        var ul_node = doc.createElement('ul');
33334        $(checked_obj).each(function(){
33335          var node_text = $('#left_jstree_container').jstree("get_text", this);
33336          var li_node = doc.createElement('li');
33337          $(li_node).html(node_text);
33338          $(li_node).appendTo(ul_node);
33339        });
33340        $('#download_node_list').html('');
33341        $(ul_node).appendTo($('#download_node_list'));
33342        download_node_dialog.dialog('open');
33343      }
33344    });
33345    
33346    $('#add_item_btn').unbind("click").bind('click', function(){
33347      $('#add_menu').slideToggle('fast', function(){
33348      });
33349      $('#add_item_btn').unbind("outerClick").bind('outerClick', function(){
33350        $('#add_menu').hide();
33351      });
33352    });
33353    
33354    $('#info_item_btn').unbind("click").bind('click', function(){
33355      if (!fn_get_checked_element_flag()) 
33356        fn_error_dialog('Error', 'Nothing selected.');
33357      else {
33358        g_cmn.fn_notif_win(true, "Getting Info...", null);
33359        var obj_list = fn_get_checked_obj_list();
33360        $.ajax({
33361          type: "POST",
33362          url: g_site_url + "main_cloud_fs_interface/info",
33363          dataType: "json",
33364          data: {
33365            "obj_list": $.toJSON(obj_list)
33366          },
33367          async: true,
33368          success: function(response){
33369            if (response.error) {
33370              g_cmn.fn_error_dialog("ERROR", "<center>Sorry, a temporary error has occurred.<br/>Please refresh the page.</center>", {
33371                width: "370px"
33372              });
33373              // g_cmn.fn_notif_win(true, "Getting info failed. <br\>" + response.error , 5000);
33374            }
33375            else {
33376              var res_len = response.length;
33377              if (res_len) {
33378                var doc = document;
33379                var node_info = doc.createElement('div');
33380                for (var i = 0; i < res_len; i++) {
33381                  var ul_node = doc.createElement('ul');
33382                  var result = response[i];
33383                  var li_node_obj = $('#right_jstree_container').find('li#dir_' + result.gid);
33384                  var li_title = doc.createElement('li');
33385                  $(li_title).html(result.title).addClass('filename');
33386                  $(li_title).appendTo(ul_node);
33387                  
33388                  var li_datetime = doc.createElement('li');
33389                  var last_modified = result.last_modified;
33390                  $(li_datetime).html(last_modified).addClass('datetime');
33391                  li_node_obj.find('span.jstree_datetime').html(last_modified);
33392                  $(li_datetime).appendTo(ul_node);
33393                  
33394                  var li_sharing = doc.createElement('li');
33395                  var get_is_sharing = result.what == 'sugarsync' && result.sharing_enabled != undefined ? result.sharing_enabled : 'N/A';
33396                  $(li_sharing).html(get_is_sharing).addClass('share_enabled');
33397                  // li_node_obj.find('span.jstree_size').html(get_is_sharing);
33398                  $(li_sharing).appendTo(ul_node);
33399                  
33400                  var li_obj_type = doc.createElement('li');
33401                  var get_obj_type = result.obj_type ? result.obj_type : 'N/A';
33402                  $(li_obj_type).html(get_obj_type).addClass('media_type');
33403                  // li_node_obj.find('span.jstree_size').html(get_obj_type);
33404                  $(li_obj_type).appendTo(ul_node);
33405                  
33406                  var li_shared_people = doc.createElement('li');
33407                  var shared_people = result.acl != null ? result.acl.length : 'N/A';
33408                  $(li_shared_people).html(shared_people).addClass('shared_people');
33409                  // li_node_obj.find('span.jstree_owner').html(shared_people);
33410                  $(li_shared_people).appendTo(ul_node);
33411                  $(ul_node).appendTo(node_info);
33412                }
33413                $('.file_info_response').html('');
33414                $(node_info).appendTo($('.file_info_response'));
33415                g_cmn.fn_notif_win(false, "", null);
33416                info_node_dialog.dialog('open');
33417              }
33418            }
33419          },
33420          failure: function(response){
33421            g_cmn.fn_notif_win(false, "", null);
33422            g_cmn.fn_error_dialog("ERROR", "<center>Sorry, a temporary error has occurred.<br/>Please refresh the page.</center>", {
33423              width: "370px"
33424            });
33425          }
33426        });
33427      }
33428    });
33429  } /* fn_display_right_jstree */
33430  
33431  var info_node_dialog = $("#info_node_dialog").dialog({
33432    autoOpen: false,
33433    resizable: false,
33434    width: 700,
33435    height: 350,
33436    title: "Files Info...",
33437    modal: true,
33438    buttons: {
33439      "Ok": function(){
33440        $(this).dialog("close");
33441      }
33442    }
33443  });
33444  
33445  var upload_new_file_dialog = $("#upload_new_file_dialog").dialog({
33446    autoOpen: false,
33447    resizable: false,
33448    width: 450,
33449    height: 340,
33450    title: "Files Upload",
33451    modal: true,
33452    buttons: {
33453      "Cancel": function(){
33454        $(this).dialog("close");
33455      }
33456    }
33457  });
33458  
33459  var create_new_folder_dialog = $("#create_new_folder_dialog").dialog({
33460    autoOpen: false,
33461    resizable: false,
33462    width: 460,
33463    height: 225,
33464    title: "Create Folder",
33465    modal: true,
33466    buttons: {
33467      "Cancel": function(){
33468        $(this).dialog("close");
33469      },
33470      "Create folder": function(){
33471        var folder_name = $('#folder_name').val();
33472        if (folder_name == '') 
33473          g_cmn.fn_notif_win(true, "Please enter the folder name", 5000);
33474        else {
33475          g_cmn.fn_notif_win(true, "Creating folder...", null);
33476          var obj = g_top_right_jstree_node.data('jstree');
33477          $.ajax({
33478            type: "POST",
33479            url: g_site_url + "main_cloud_fs_interface/new_dir",
33480            dataType: "json",
33481            data: {
33482              "obj": $.toJSON(obj),
33483              "folder_name": $.toJSON(folder_name)
33484            },
33485            async: true,
33486            success: function(response){
33487              if (response.error) {
33488                fn_error_dialog("Error during folder creation", response.error);
33489                g_cmn.fn_notif_win(false, "", null);
33490                // g_cmn.fn_notif_win(true, "Folder creation failed.<br\>" + response.error , 5000);
33491              }
33492              else {
33493                g_cmn.fn_notif_win(true, "Folder created", 5000);
33494                fn_refresh_server(obj, 'new_dir');
33495              }
33496            },
33497            failure: function(response){
33498              g_cmn.fn_notif_win(false, "", null);
33499              alert("Failure");
33500            }
33501          });
33502          $(this).dialog("close");
33503        }
33504      }
33505    }
33506  });
33507  
33508  var copy_node_dialog = $("#copy_node_dialog").dialog({
33509    autoOpen: false,
33510    resizable: false,
33511    width: 700,
33512    height: 550,
33513    title: "Files Copy",
33514    modal: true,
33515    buttons: {
33516      "Cancel": function(){
33517        g_cmn.fn_notif_win(false, "", null);
33518        $(this).dialog("close");
33519      },
33520      "Copy": function(){
33521        var $folder_element = $($("#copy_node_jstree_container .jstree-clicked")).parent('li');
33522        if ($folder_element.length < 1) 
33523          g_cmn.fn_notif_win(true, "Select destination to copy", 5000);
33524        else {
33525          var folder_obj = $folder_element.data('jstree');
33526          
33527          if (folder_obj['is_create_disabled'] == true) { 
33528            g_cmn.fn_notif_win(true, 'Creation of files is not allowed on this level. <br/>Please select different destination.', 5000);
33529          }
33530          
33531          else {
33532          
33533            if ($("#copy_node_dialog input[type='checkbox']").is(':checked'))
33534              upload_convert_policy = 1
33535            else
33536              upload_convert_policy = 0
33537            var obj_list = fn_get_checked_obj_list();
33538            g_cmn.fn_notif_win(true, "Copying...", null);
33539            $.ajax({
33540              type: "POST",
33541              url: g_site_url + "main_cloud_fs_interface/copy",
33542              dataType: "json",
33543              data: {
33544                "obj_list": $.toJSON(obj_list),
33545                "target_obj": $.toJSON(folder_obj),
33546                "upload_convert_policy"   : $.toJSON(upload_convert_policy)
33547              },
33548              async: true,
33549              success: function(response){
33550                if (response.error) {
33551                  fn_error_dialog("Error during copy", response.error);
33552                  g_cmn.fn_notif_win(false, "", null);
33553                }
33554                else 
33555                  if (response.long_running_operation) {
33556                    g_cmn.fn_notif_win(false, null);
33557                    fn_refresh_server(folder_obj, 'copy');
33558                    g_cmn.fn_normal_dialog("Copy operation started", "", "Since copy will take longer than 2 minutes we started a background job which will copy the selected files.<br/><br/>You will receive an email when the job finishes.", {
33559                      width: "550px"
33560                    });
33561                  }
33562                  else if (response.status_txt) {
33563                    fn_refresh_server(folder_obj, 'copy');
33564                    g_cmn.fn_notif_win(true, response.status_txt, 5000);
33565                  }
33566                  else {
33567                    fn_refresh_server(folder_obj, 'copy');
33568                    g_cmn.fn_notif_win(true, "Files copied", 5000);
33569                  }
33570              },
33571              failure: function(response){
33572                g_cmn.fn_notif_win(false, "", null);
33573              }
33574            });
33575            $(this).dialog("close");
33576          }
33577        }
33578      }
33579    }
33580  });
33581  
33582  var move_node_dialog = $("#move_node_dialog").dialog({
33583    autoOpen: false,
33584    resizable: false,
33585    width: 700,
33586    height: 550,
33587    title: "Files Move",
33588    modal: true,
33589    buttons: {
33590      "Cancel": function(){
33591        g_cmn.fn_notif_win(false, "", null);
33592        $(this).dialog("close");
33593      },
33594      "Move": function(){
33595        var $target_element = $($("#move_node_jstree_container .jstree-clicked")).parent('li');
33596        if ($target_element.length < 1) 
33597          g_cmn.fn_notif_win(true, "Please select destination", 5000);
33598        else {
33599          var target_obj = $target_element.data('jstree');
33600          
33601          if (target_obj['is_create_disabled'] == true) {
33602            g_cmn.fn_notif_win(true, 'Creation of files is not allowed on this level. <br/>Please select different destination.', 5000);
33603          }
33604          else {
33605          
33606            var obj_list = fn_get_checked_obj_list();
33607            
33608            if ($("#copy_node_dialog input[type='checkbox']").is(':checked'))
33609              upload_convert_policy = 1
33610            else
33611              upload_convert_policy = 0
33612            g_cmn.fn_notif_win(true, "Moving...", null);
33613            $.ajax({
33614              type: "POST",
33615              url: g_site_url + "main_cloud_fs_interface/move",
33616              dataType: "json",
33617              data: {
33618                "obj_list": $.toJSON(obj_list),
33619                "target_obj": $.toJSON(target_obj),
33620                "upload_convert_policy": $.toJSON(upload_convert_policy)
33621              },
33622              async: true,
33623              success: function(response){
33624                if (response.error) {
33625                  fn_error_dialog("Error during move", response.error);
33626                  g_cmn.fn_notif_win(false, "", null);
33627                  fn_refresh_server(null, 'move');
33628                } 
33629                else if (response.long_running_operation) {
33630                  g_cmn.fn_notif_win(false, "Move job started", 1000);
33631                  g_cmn.fn_normal_dialog("Move operation started", "", "Since move operation will take longer than 2 minutes we started a background job which will move the files.<br/><br/>You will receive an email when the move finishes.", {
33632                    width: "550px"
33633                  });
33634                }
33635                else {
33636                  g_cmn.fn_notif_win(true, "Success", 5000);
33637                  fn_refresh_server(null, 'move');
33638                }
33639              },
33640              failure: function(response){
33641                g_cmn.fn_notif_win(false, "", null);
33642                // alert("Failure");
33643              }
33644            });
33645            $(this).dialog("close");
33646          }
33647        }
33648      }
33649    }
33650  });
33651  
33652  var delete_node_dialog = $("#delete_node_dialog").dialog({
33653    autoOpen: false,
33654    resizable: false,
33655    width: 450,
33656    title: "Files Delete",
33657    modal: true,
33658    buttons: {
33659      "Cancel": function(){
33660        $(this).dialog("close");
33661      },
33662      "Delete": function(){
33663        var obj_list = fn_get_checked_obj_list();
33664        g_cmn.fn_notif_win(true, "Deleting files...", null);
33665        $.ajax({
33666          type: "POST",
33667          url: g_site_url + "main_cloud_fs_interface/delete",
33668          dataType: "json",
33669          data: {
33670            "obj_list": $.toJSON(obj_list)
33671          },
33672          async: true,
33673          success: function(response){
33674            if (response.error) {
33675              fn_error_dialog("Error during delete", response.error);
33676              g_cmn.fn_notif_win(false, "", null);
33677            }
33678            else if (response.long_running_operation) {
33679              g_cmn.fn_notif_win(false, "Delete job started", 1000);
33680              g_cmn.fn_normal_dialog("Delete operation started", "", "Since delete will take longer than 2 minutes we started a background job which will finish the deletion of the files.<br/><br/>You will receive an email when the job finishes.", {
33681                width: "550px"
33682              });
33683            }
33684            else {
33685              g_cmn.fn_notif_win(true, "Success", 5000);
33686              fn_refresh_server(null, 'delete');
33687            }
33688          },
33689          failure: function(response){
33690            g_cmn.fn_notif_win(false, "", null);
33691          }
33692        });
33693        $(this).dialog("close");
33694      }
33695    }
33696  });
33697  
33698  var download_node_dialog = $('#download_node_dialog').dialog({
33699    autoOpen: false,
33700    resizable: false,
33701    width: 450,
33702    title: "Files Download",
33703    modal: true,
33704    buttons: {
33705      "Cancel": function(){
33706        $(this).dialog("close");
33707      },
33708      "Download": function(){
33709        fn_download_documents();
33710        $(this).dialog("close");
33711      }
33712    }
33713  });
33714  
33715  /**
33716   * Display document represented by node
33717   * @param {Object} obj_id
33718   */
33719  var fn_view_document = function fn_view_document(obj){
33720    g_cmn.fn_working_overlay(true, "Downloading...");
33721    var obj_list = new Array();
33722    obj_list.push(obj);
33723    $.ajax({
33724      type: "POST",
33725      url: g_site_url + "main_cloud_fs_interface/download",
33726      dataType: "json",
33727      data: {
33728        "obj_list": $.toJSON(obj_list)
33729      },
33730      async: true,
33731      success: function(response){
33732        g_cmn.fn_working_overlay(false, null);
33733        if (response.error) {;
33734          fn_error_dialog("Download failed", response.error);
33735        }
33736        else if (response.long_running_operation) {
33737          fn_error_dialog("Download failed", "Operation timed out - please try again");
33738        }
33739		    else if (response.media_type == 'text/html') {
33740    			var view_uri = g_site_url +
33741                'main_cloud_fs_interface/get_file?save_as=0' +
33742                '&filename=' +
33743                response.filename +
33744                '&media_type=' +
33745                response.media_type +
33746                '&title=' +
33747                response.title;
33748    			$('#right_doc_container #right_doc_image_content').hide();
33749                $('#right_doc_container #right_doc_video_content').hide();
33750                $('#right_doc_container #right_doc_iframe_content').show().attr('src', view_uri);
33751                $('#right_dir_container').hide();
33752                $('#right_doc_container').show();
33753                $('#right_doc_container a').unbind('click').bind('click', function(){
33754                  $('#right_dir_container').show();
33755                  $('#right_doc_container').hide();
33756                  return false;
33757                });
33758    		}
33759        else {
33760          if (response.media_type == 'application/pdf' ||
33761          response.media_type == 'application/vnd.ms-powerpoint' ||
33762          response.media_type == 'application/msword' ||
33763          response.media_type == 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' ||
33764          response.media_type == 'application/x-vnd.oasis.opendocument.spreadsheet' ||
33765          response.media_type == 'application/vnd.oasis.opendocument.text') {
33766            g_cmn.fn_notif_win(true, "File downloaded", 5000);
33767            // since users might have popup blocker, we will display document as iFrame
33768            var view_uri = 'https://docs.google.com/viewer?embedded=true&url=' +
33769            encodeURIComponent(g_site_url +
33770            'main_cloud_fs_interface/get_file?save_as=0' +
33771            '&filename=' +
33772            response.filename +
33773            '&media_type=' +
33774            response.media_type +
33775            '&title=' +
33776            response.title);
33777            $('#right_doc_container #right_doc_image_content').hide();
33778            $('#right_doc_container #right_doc_video_content').hide();
33779            $('#right_doc_container #right_doc_iframe_content').show().attr('src', view_uri);
33780            $('#right_dir_container').hide();
33781            $('#right_doc_container').show();
33782            $('#right_doc_container a').unbind('click').bind('click', function(){
33783              $('#right_dir_container').show();
33784              $('#right_doc_container').hide();
33785              return false;
33786            });
33787          }
33788          else 
33789            if (response.media_type == 'image/jpeg' ||
33790            response.media_type == 'image/gif' ||
33791            response.media_type == 'image/tiff' ||
33792            response.media_type == 'image/png' ||
33793            response.media_type == 'image/bmp') {
33794              g_cmn.fn_notif_win(true, "File downloaded", 5000);
33795              // since users might have popup blocker, we will display document as iFrame
33796              var view_uri = g_site_url + 'main_cloud_fs_interface/get_file?save_as=0' +
33797              '&filename=' +
33798              encodeURIComponent(response.filename) +
33799              '&media_type=' +
33800              encodeURIComponent(response.media_type) +
33801              '&title=' +
33802              encodeURIComponent(response.title);
33803              $('#right_doc_container #right_doc_iframe_content').hide();
33804              $('#right_doc_container #right_doc_video_content').hide();
33805              $('#right_doc_container #right_doc_image_content').show().attr('src', view_uri);
33806              $('#right_dir_container').hide();
33807              $('#right_doc_container').show();
33808              $('#right_doc_container a').unbind('click').bind('click', function(){
33809                $('#right_dir_container').show();
33810                $('#right_doc_container').hide();
33811                return false;
33812              });
33813              
33814            }
33815            else 
33816              if (response.media_type == 'video/mpeg' ||
33817              response.media_type == 'application/x-shockwave-flash' ||
33818              response.media_type == 'video/x-ms-wmv') {
33819                g_cmn.fn_notif_win(true, "File downloaded", 5000);
33820                var view_uri = g_site_url + 'main_cloud_fs_interface/get_file?save_as=0' +
33821                '&filename=' +
33822                encodeURIComponent(response.filename) +
33823                '&media_type=' +
33824                encodeURIComponent(response.media_type) +
33825                '&title=' +
33826                encodeURIComponent(response.title);
33827                $('#right_doc_container #right_doc_iframe_content').hide();
33828                $('#right_doc_container #right_doc_image_content').hide();
33829                $('#right_doc_container #right_doc_video_content').show().attr({
33830                  'src': view_uri,
33831                  'type': response.media_type
33832                });
33833                $('#right_dir_container').hide();
33834                $('#right_doc_container').show();
33835                $('#right_doc_container a').unbind('click').bind('click', function(){
33836                  $('#right_dir_container').show();
33837                  $('#right_doc_container').hide();
33838                  return false;
33839                });
33840                
33841              }
33842              else {
33843                g_cmn.fn_notif_win(true, "Success", 5000);
33844                location.href = g_site_url + 'main_cloud_fs_interface/get_file?save_as=1' +
33845                '&filename=' +
33846                encodeURIComponent(response.filename) +
33847                '&media_type=' +
33848                encodeURIComponent(response.media_type) +
33849                '&title=' +
33850                encodeURIComponent(response.title);
33851                
33852              }
33853        }
33854      },
33855      failure: function(response){
33856        g_cmn.fn_working_overlay(false, null);
33857        g_cmn.fn_error_dialog("ERROR", "<center>Sorry, a temporary error has occurred.<br/>Please refresh the page.</center>", {
33858            width: "370px"
33859          });
33860      }
33861    });
33862    
33863  }
33864  
33865  /***
33866   * Function used to refresh the tree on calling when click on refresh button
33867   * operation of copy , move, delete and new folder .
33868   * @param {Object} dir_id
33869   */
33870  var fn_refresh_server = function fn_refresh_server(obj, operation){
33871    var d = null;
33872    if (obj) 
33873      d = {
33874        "obj": $.toJSON(obj)
33875      }
33876      
33877    g_cmn.fn_notif_win(true, "Refreshing...", null);
33878    $.ajax({
33879      type: "POST",
33880      url: g_site_url + "main_cloud_fs_interface/refresh_cloudhq_dir",
33881      dataType: "json",
33882      data: d,
33883      async: true,
33884      success: function(response){
33885        if (response.error) {
33886          g_cmn.fn_notif_win(false, "", null);
33887        }
33888        else {
33889          // we can just count number of open nodes in left tree and decrement them in event on 'select_node.jstree'
33890          g_jstree_refresh_inprogress = $("#left_jstree_container .jstree-open").length;
33891          $("#left_jstree_container").jstree('refresh');
33892          $("#right_jstree_container").jstree('refresh');
33893      
33894          $('#main_checkbox').addClass('checkbox_icon');
33895          $('#main_checkbox').removeClass('checkbox_icon-checked');
33896          $("#right_jstree_container").jstree("uncheck_all");
33897    
33898          g_cmn.fn_notif_win(false, "", null);
33899        }
33900      },
33901      failure: function(response){
33902        g_cmn.fn_notif_win(false, "", null);
33903        alert("Failure");
33904      }
33905    });
33906  }
33907  
33908  /**
33909   * Download documents given list of document ids
33910   * @param {Object} obj_list
33911   */
33912  var fn_download_documents = function fn_download_documents(){
33913    var obj_list = fn_get_checked_obj_list();
33914    g_cmn.fn_notif_win(true, "Downloading...", null);
33915    g_cmn.fn_working_overlay(); 
33916    $.ajax({
33917      type: "POST",
33918      url: g_site_url + "main_cloud_fs_interface/download",
33919      dataType: "json",
33920      data: {
33921        "obj_list": $.toJSON(obj_list),
33922        "download_type": $.toJSON("batch")
33923      },
33924      async: true,
33925      success: function(response){
33926        g_cmn.fn_working_overlay(false); 
33927        if (response.error) {
33928          g_cmn.fn_error_dialog("ERROR", "<center>Sorry, a temporary error has occurred.<br/>Please refresh the page.</center>", {
33929            width: "370px"
33930          });
33931        } 
33932        else if (response.long_running_operation) {
33933          g_cmn.fn_notif_win(false, "Download job started", 1000);
33934          g_cmn.fn_normal_dialog("Download job started", "", "Since download tool longer than 2 minutes we started a background job which will download the selected files and create a zip file.<br/><br/>You will receive an email with a download link when the job is done.", {
33935            width: "580px",
33936           close: function() { location.reload(true); } 
33937          });
33938        }
33939        else {
33940          g_cmn.fn_notif_win(true, "Success", 5000);
33941          location.href = g_site_url + 'main_cloud_fs_interface/get_file?save_as=1' +
33942          '&filename=' +
33943          encodeURIComponent(response.filename) +
33944          '&media_type=' +
33945          encodeURIComponent(response.media_type) +
33946          '&title=' +
33947          encodeURIComponent(response.title);
33948        }
33949      },
33950      failure: function(response){
33951        g_cmn.fn_working_overlay(false); 
33952        g_cmn.fn_notif_win(false, "", null);
33953        g_cmn.fn_error_dialog("ERROR", "<center>Sorry, a temporary error has occurred.<br/>Please refresh the page.</center>", {
33954          width: "370px"
33955        });
33956      }
33957    });
33958  };
33959  
33960  /**
33961   * Checks wether something is checked (selected)
33962   */
33963  var fn_get_checked_element_flag = function fn_get_checked_element_flag(){
33964    var checked_item = $("#right_jstree_container").jstree("get_checked").length;
33965    return checked_item > 0 ? true : false;
33966  }
33967
33968  /**
33969   * Checks weather the selected item is gmail
33970   */
33971  var fn_is_item_gmail = function fn_is_item_gmail() {
33972    var checked_item = $("#right_jstree_container").jstree("get_checked");
33973    if (checked_item.length > 0 && checked_item.data('jstree').what == 'google_gmail')
33974      return true;
33975    else
33976      return false;
33977  }
33978
33979  /**
33980   * Checks weather the selected item is gmail
33981   */
33982  var fn_is_item_evernote_tags = function fn_is_item_gmail() {
33983    var checked_item = $("#right_jstree_container").jstree("get_checked");
33984    if (checked_item.length > 0 && checked_item.data('jstree').what == 'evernote'  && checked_item.data('jstree')['obj_type'] == 'exp2:tags-folder' )
33985      return true;
33986    else
33987      return false;
33988  }
33989
33990  /**
33991   * Checks weather the selected item is gmail
33992   */
33993  var fn_is_item_evernote_top = function fn_is_item_gmail() {
33994    var checked_item = $("#right_jstree_container").jstree("get_checked");
33995    if (checked_item.length > 0 && checked_item.data('jstree').what == 'evernote'  && checked_item.data('jstree')['is_root'] == true )
33996      return true;
33997    else
33998      return false;
33999  }
34000
34001  /**
34002   * Returns list of selected objects
34003   */
34004  var fn_get_checked_obj_list = function fn_get_checked_obj_list(){
34005    var obj_list = new Array();
34006    var checked_element_list = $("#right_jstree_container").jstree("get_checked");
34007    $(checked_element_list).each(function(){
34008      obj_list.push($(this).data('jstree'));
34009    });
34010    return obj_list;
34011  }
34012  
34013  /**
34014   * Wrapper around displaying error dialog
34015   */
34016  var fn_error_dialog = function fn_error_dialog(title, text){
34017    g_cmn.fn_error_dialog(title, text);
34018  }
34019  
34020  /**
34021   * generate copy node jstree given response from cloudHQ_init
34022   * @param {Object} response
34023   */
34024  var fn_display_copy_node_jstree = function fn_display_copy_node_jstree(response){
34025    $(function(){
34026      $('#copy_node_jstree_container').jstree("destroy");
34027      $('#copy_node_jstree_container').jstree({
34028        "core": {
34029          html_titles: true
34030        },
34031        "json_data": {
34032          "correct_state": true,
34033          "data": response,
34034          "ajax": {
34035            "url": function(n){
34036              if (n == -1) 
34037                return false;
34038              else {
34039                g_cmn.fn_notif_win(true, "Loading...", null);
34040                return g_site_url + "main_cloud_fs_interface/cloudhq_dir";
34041              }
34042            },
34043            "success": function(obj, t, x){
34044              g_cmn.fn_notif_win(false, "", null);
34045            },
34046            "error": function(obj){
34047              alert("error");
34048            },
34049            "data": function(obj) {
34050              return {
34051                "obj": $.toJSON(obj.data('jstree')),
34052                "file_flag": $.toJSON(false)
34053              }
34054            }
34055          }
34056        },
34057        "themes": {
34058          "theme": "cloudhq",
34059          "dots": false,
34060          "icons": true
34061        },
34062        "plugins": ["themes", "json_data", "ui"]
34063      });
34064      
34065    });
34066    
34067  } /* fn_display_copy_node_jstree */
34068  /**
34069   * generate jstree for move dialog given response from cloudHQ_init
34070   * @param {Object} response
34071   */
34072  var fn_display_move_node_jstree = function fn_display_move_node_jstree(response){
34073    $(function(){
34074      $('#move_node_jstree_container').jstree("destroy");
34075      $('#move_node_jstree_container').jstree({
34076        "core": {
34077          html_titles: true
34078        },
34079        "json_data": {
34080          "correct_state": true,
34081          "data": response,
34082          "ajax": {
34083            "url": function(n){
34084              if (n == -1) 
34085                return false;
34086              else {
34087                g_cmn.fn_notif_win(true, "Loading...", null);
34088                return g_site_url + "main_cloud_fs_interface/cloudhq_dir";
34089              }
34090            },
34091            "success": function(obj, t, x){
34092              g_cmn.fn_notif_win(false, "", null);
34093            },
34094            "error": function(obj){
34095              alert("error");
34096            },
34097            "data": function(obj){
34098              return {
34099                "obj": $.toJSON(obj.data('jstree')),
34100                "file_flag": $.toJSON(false)
34101              }
34102            }
34103          }
34104        },
34105        "themes": {
34106          "theme": "cloudhq",
34107          "dots": false,
34108          "icons": true
34109        },
34110        "plugins": ["themes", "json_data", "ui"]
34111      });
34112      
34113    });
34114    
34115  } /* fn_display_move_node_jstree */
34116  /**
34117   * Call ajax to upload file using fileUploadUI
34118   */
34119  var fn_make_file_upload = function fn_make_file_upload(){
34120    $('.upload').fileUploadUI({
34121      uploadTable: false,
34122      downloadTable: false,
34123      buildUploadRow: false,
34124      buildDownloadRow: false,
34125      onLoad: function(event, files, index, xhr, handler){
34126        if (xhr && xhr.responseText) {
34127          var response = JSON.parse(xhr.responseText);
34128          if (response['error']) {
34129            fn_error_dialog("Error during upload", response['error']);
34130            g_cmn.fn_notif_win(false, "", null);
34131          }
34132          else 
34133            g_cmn.fn_notif_win(true, "Success", 5000);
34134        }
34135        else {
34136          g_cmn.fn_notif_win(true, "Success", 5000);
34137        }
34138        fn_refresh_server(null, '');
34139      },
34140      onAbort: function(event, files, index, xhr, handler){
34141        // alert('abort');
34142      },
34143      onError: function(event, files, index, xhr, handler){
34144        // alert('error');
34145      },
34146      initUpload: function(event, files, index, xhr, handler, callBack){
34147        g_cmn.fn_notif_win(true, "Upload of file " + files[0].name + " in progress...", null);
34148        $("#upload_new_file_dialog").dialog("close");
34149        callBack();
34150      }
34151    });
34152  }
34153  
34154  
34155  /**
34156   * Setup resize columns function
34157   */
34158  var fn_right_jstree_columns_setup = function fn_right_jstree_columns_setup(){
34159    $(".info_header .file-name-block").resizable({
34160      containment: 'parent',
34161      handles: 'e',
34162      alsoResize: '#right_jstree_container .jstree_filename'
34163    });
34164    $(".info_header .size").resizable({
34165      containment: 'parent',
34166      handles: 'e',
34167      alsoResize: '#right_jstree_container .jstree_size'
34168    });
34169    $(".info_header .date-time").resizable({
34170      containment: 'parent',
34171      handles: 'e',
34172      alsoResize: '#right_jstree_container .jstree_datetime'
34173    });
34174    $(".info_header .owner").resizable({
34175      containment: 'parent',
34176      handles: 'e',
34177      alsoResize: '#right_jstree_container .jstree_owner'
34178    });
34179  }
34180  
34181  /**
34182   * Resize columns
34183   */
34184  var fn_right_jstree_columns_resize = function fn_right_jstree_columns_resize(){
34185    $('#right_jstree_container .jstree_filename').width($(".info_header .file-name-block").width());
34186    $('#right_jstree_container .jstree_size').width($(".info_header .size").width());
34187    $('#right_jstree_container .jstree_datetime').width($(".info_header .date-time").width());
34188    // owner is last one so just 100% is ok
34189    $('#right_jstree_container .jstree_owner').width('100%');
34190  }
34191  
34192  
34193  var fn_resize_areas = function fn_resize_areas(){
34194    //$('body').height($(window).height());
34195    //$('.main-outer-wrapper').height($(window).height() - $('.footer').height() - 9);
34196    var top_banner_height = $('#banner-top').is(':visible') ? $('#banner-top').height() * 1 : 0;
34197    $('.main_content_container').height($(window).height() - $('.footer').height() - $('#top-header').height() - 40 - top_banner_height);
34198    
34199    // left tree height
34200    var lth = $('.main_content_container').height() - $('.add_chrome_extension').height() - 9;
34201    $('#left_jstree_container').height(lth - 6);
34202    
34203    // right doc height
34204    var dh = $('#right_doc_container').height() - 18;
34205    $('#right_doc_container iframe').height(dh);
34206    
34207    // right jstree height
34208    var rth = $('#right_dir_container').height() -
34209    $('#right_dir_breadcrumb').height() -
34210    $('#right_dir_header').height() -
34211    60;
34212    $('#right_jstree_container').height(rth);
34213    
34214  }
34215};   
34216         
34217/* ------------------------------------------- 
34218  var fn_display_contextmenu = function(node)
34219  {
34220      return {
34221        create : false,
34222        rename : false,
34223        remove : false,
34224        ccp    : false,
34225        "move_to" : {
34226          "separator_before"    : false,
34227          "separator_after"     : true,
34228          "label"               : "Move to...",
34229          "action"              : function (obj) { alert("Move to..."); }
34230        },
34231        "copy_to" : {
34232          "separator_before"    : false,
34233          "separator_after"     : true,
34234          "label"               : "Copy to...",
34235          "action"              : function (obj) { alert("Copy to..."); }
34236        },
34237        "delete" : {
34238          "separator_before"    : false,
34239          "separator_after"     : true,
34240          "label"               : "Delete",
34241          "action"              : function (obj) { alert("Delete..."); }
34242        },
34243        "download" : {
34244          "separator_before"    : false,
34245          "separator_after"     : true,
34246          "label"               : "Download",
34247          "action"              : function (obj) { alert("Download..."); }
34248        },
34249        "move_to" : {
34250          "separator_before"    : false,
34251          "separator_after"     : true,
34252          "label"               : "Move to...",
34253          "action"              : function (obj) { alert("Move to..."); }
34254        }
34255      }
34256  }  
34257}
34258
34259 var fn_display_breadcrumb = function(data_rslt_obj)
34260{
34261
34262  var fn_get_selected_left_tree_node = function()
34263  {
34264    $('#left_jstree_container .jstree-clicked').each(function() {
34265      var selected_node = $(this).parent('li');
34266      if(selected_node)
34267        return fn_get_left_tree_bredcums(selected_node, '');
34268      else
34269        return "";
34270    });
34271  }
34272
34273  var fn_get_left_tree_bredcums = function(data_rslt_obj, current_bredcums)
34274  {
34275    var current_obj_id = data_rslt_obj.attr('id');
34276    var parent_obj = $(data_rslt_obj.parent().parent());
34277    var parent_id = parent_obj.attr('id');
34278    var current_node = fn_fetch_breadcum_text(data_rslt_obj);
34279    if(parent_id==('left_jstree_container' || '' || 'undefined'))
34280    {
34281      $('#right_dir_breadcrumb').html(current_node + current_bredcums);
34282    }
34283    else
34284    {
34285      current_bredcums = ' > ' + current_node + current_bredcums;
34286      fn_get_left_tree_bredcums(parent_obj, current_bredcums);
34287    }
34288  }
34289
34290  var fn_fetch_breadcum_text = function(data_rslt_obj)
34291  {
34292    var node_name = $(data_rslt_obj[0].children[1]).text();
34293    return node_name!='' ? node_name : '';
34294  }
34295  
34296  var current_obj_id = data_rslt_obj.attr('id');
34297  var root
34298  while ()
34299  var parent_obj = $(data_rslt_obj.parent().parent());
34300  var parent_id = parent_obj.attr('id');
34301  var current_node = fn_fetch_breadcum_text(data_rslt_obj);
34302  
34303  
34304  if (parent_id==('left_jstree_container' || '' || 'undefined') || current_obj_id==('right_jstree_container' || '' || 'undefined'))
34305  {
34306    // if($.inArray(current_obj_id, left_tree_expand_plan) < 0)
34307    left_tree_expand_plan.push(current_obj_id);
34308    $('#right_dir_breadcrumb').html('');
34309    var get_left_breadcums = '';
34310    if(from!='left')
34311    {
34312      fn_get_selected_left_tree_node();
34313      get_left_breadcums = $('#right_dir_breadcrumb').html();
34314    }
34315    $('#right_dir_breadcrumb').html(get_left_breadcums + current_node + current_bredcums);
34316  }
34317  else
34318  {
34319    current_bredcums = ' > ' + current_node + current_bredcums;
34320    // if($.inArray(current_obj_id, left_tree_expand_plan) < 0)
34321    left_tree_expand_plan.push(current_obj_id);
34322    fn_display_breadcrumb(parent_obj, current_bredcums, from);
34323  }
34324}
34325
34326 */
34327
34328/**
34329 * @author Senad Dizdar
34330 */
34331
34332if (typeof srv_check_refresh_default === "undefined") {
34333  srv_check_refresh_default = false;
34334}
34335
34336function c_srv()
34337{
34338  var srv_check_delay = 15000;
34339  var srv_check_timeout = null;
34340  var srv_check_refresh = srv_check_refresh_default;
34341  
34342  this.name = "c_srv";
34343  
34344  this.fn_init = function()
34345  {
34346    // wait 5 secs here. if background job fails we could be constantly pinging server!
34347    if (srv_check_refresh)
34348    {
34349      window.setTimeout(check_services_state, 5000);
34350    }
34351  };
34352  
34353  function check_services_state(delay) {
34354     
34355     if(delay && delay > 0) {
34356       if(srv_check_timeout) {
34357          window.clearTimeout(srv_check_timeout);
34358       }
34359       srv_check_delay    = Math.max(5000, Math.min(delay, 60000));
34360       srv_check_timeout  = window.setTimeout(function() {
34361         check_services_state(false);
34362       }, srv_check_delay);
34363       return;
34364     };
34365     
34366     function check_action_name(actions, name) {
34367       return $.grep(actions, function(x) {
34368          return x.name == name;
34369       }).length > 0;
34370     };
34371    
34372     $.ajax({
34373      type : "GET",
34374      url : g_site_url + "main_services/check_services_state",
34375      dataType : "json",
34376      success : function(response) {
34377        if (response.error) {
34378          check_services_state(srv_check_delay * 2);
34379        } else {
34380          if (response.actions && response.actions.length > 0) {
34381            if(check_action_name(response.actions, 'reconfigure_service_configs')) {
34382              // g_cmn.fn_notif_win(true, 'Cataloging and verifying your configured services ...' , 10000);
34383            } else if(check_action_name(response.actions, 'reconfigure_service_configs_and_group_them')) {
34384              // g_cmn.fn_notif_win(true, 'Cataloging and verifying your configured services ...' , 10000);
34385
34386            } else if (check_action_name(response.actions, 'refresh_google_apps_accounts')) {
34387              // g_cmn.fn_notif_win(true, 'Cataloging Google Apps accounts ...' , 10000);
34388            }
34389            srv_check_refresh = true;
34390            check_services_state(10000);
34391          } else {
34392            if(srv_check_refresh) {
34393              g_cmn.fn_working_overlay(true, "Loading services ...");
34394              window.location.reload();
34395            }
34396          }
34397        }
34398      },
34399      failure : function(response) {
34400        check_services_state(srv_check_delay * 2);
34401      }
34402    });    
34403  };
34404  
34405}
34406/**
34407 * @author Senad Dizdar
34408 */
34409
34410function c_bckp()
34411{
34412  this.name = "c_bckp";
34413  
34414  this.fn_init = function()
34415  {
34416
34417    // call server to intilize 
34418    $.ajax(
34419    {
34420      type: "GET",
34421      url: g_site_url + "main_cloud_fs_interface/cloudhq_init",
34422      dataType: "json",
34423      data: { 'call_for_backup': true},
34424      async: true,    
34425      success: function(response)
34426      {
34427        if (response.error)
34428        {
34429          g_cmn.fn_notif_win(true, "Something went wrong... <br>Please refresh the page." , 5000);
34430        }
34431        else
34432        {
34433          fn_display_dialog_jstree(response);
34434        }
34435      },
34436      failure: function(response)
34437      {
34438        alert("Failure");
34439      }
34440    });
34441
34442    // If backup is not enabled but it not specified destination for backup we should display ...
34443    $('#start_stop_container form').submit(function(){
34444      if (($('#target_obj').val() =='""' || $('#location').val() =='Not selected') && $('#is_backup_enabled').is(':checked'))
34445      { 
34446        g_cmn.fn_error_dialog("ERROR", "Please specify backup destination");
34447        return false;
34448      }
34449    });
34450
34451    $('#save_backup_configs_form').submit(function(){ 
34452      return false;
34453    });
34454
34455    $('.service_checkbox').click(function(e) {
34456      if (!$(this).is(':checked')) {
34457        service_name = $(this).attr('service_name');
34458        service_email_or_login = $(this).attr('service_email_or_login');
34459        g_cmn.fn_normal_dialog("Confirmation", 
34460          "Exclude " + service_name + " (" + service_email_or_login + ") from backup.<br/><br/>" + "Are you sure?", "", 
34461          { 
34462            width: "550px", 
34463            buttons: {
34464              "No": function() {
34465                try { g_cmn.fn_working_overlay(true, 'Reverting...'); } catch(er)  { }
34466                $(this).dialog("close"); 
34467                document.location.reload(true);
34468              },
34469              "Yes": function() {
34470                try { g_cmn.fn_working_overlay(true, 'Saving...'); } catch(er)  { }
34471                $(this).dialog("close"); 
34472                document.save_backup_configs_form.submit(); // use javascript to skip jQuery
34473              }
34474            }
34475        });
34476      } else
34477      {
34478        try { g_cmn.fn_working_overlay(true, 'Saving...'); } catch(er)  { }
34479        $(this).dialog("close"); 
34480        document.save_backup_configs_form.submit(); // use javascript to skip jQuery
34481      }
34482
34483      return true;
34484    });
34485
34486    $('#get_backup_place').unbind("click").bind('click', function(){
34487      if ($('#is_backup_enabled').attr('value') == '0')
34488      {
34489        g_cmn.fn_normal_dialog("Notice", "Please stop the backup before modifying it", "", 
34490          { width: "450px", buttons: {
34491            "OK": function() {
34492                $(this).dialog("close"); 
34493            }
34494          }
34495        });
34496        return false;
34497      }
34498      select_target_dialog.dialog('open');
34499    });
34500
34501  }
34502  
34503
34504  /*********************************************/
34505  /* PRIVATE FUNCTIONS                         */
34506  /*********************************************/
34507  var fn_display_dialog_jstree = function(response)
34508  {
34509    $(function () {
34510      $('#select_target_jstree_container').jstree("destroy");
34511      $('#select_target_jstree_container').bind('load_node.jstree', function(event, data)
34512       {
34513         // alert("reopen");
34514       }).jstree({
34515         "core": {
34516          html_titles: true
34517        },
34518        "json_data" : {
34519          "correct_state" : true,
34520          "data" : response,
34521          "ajax" : { "url" :function (n) {
34522              if (n==-1)
34523                return false;
34524              else{
34525                g_cmn.fn_notif_win(true, "Loading...", null);
34526                return g_site_url + "main_cloud_fs_interface/cloudhq_dir";
34527              }
34528            },
34529            "success": function (obj, t, x) {
34530              $('#loading').css('display','none');
34531              if ( t == "success" )
34532              {
34533                var response = JSON.parse(x.responseText);
34534                if (response['error'])
34535                  g_cmn.fn_notif_win(true, "Something went wrong... <br>Please refresh the page ." , 5000);
34536                else
34537                  g_cmn.fn_notif_win(false, "", null);
34538              }
34539              else
34540              {
34541                g_cmn.fn_notif_win(false, "", null);
34542              }
34543            },
34544            "error" : function (obj) {
34545              g_cmn.fn_notif_win(true, "Something went wrong... <br>Please refresh the page." , 5000);
34546              alert ("error: jQuery internal error. Please refresh the page.");
34547            },
34548            "data" : function (obj) {
34549              
34550              return { "obj"       : $.toJSON(obj.data('jstree')), 
34551                       "file_flag" : $.toJSON(false) }
34552            }
34553          }
34554        },
34555        "contextmenu" : {
34556          "items": function(node){
34557            return fn_display_contextmenu(node);
34558          } // end function
34559        },
34560        "themes"   : {
34561          "theme" : "cloudhq",
34562          "dots" : false,
34563          "icons" : true
34564        },
34565        "plugins"  : [ "themes", "json_data", "ui", "crrm", "types" ]
34566      });
34567
34568    });
34569
34570  } /* fn_display_left_jstree */
34571  
34572  var select_target_dialog = $("#select_target_dialog").dialog({
34573    autoOpen: false, resizable: false, width: 650, height: 350, title: "Select target folder for archives",
34574    modal: true,
34575    buttons: { 
34576      "Cancel": function() { 
34577        $(this).dialog("close"); 
34578      },
34579      "Select": function() {
34580        var folder_obj = $($("#select_target_jstree_container .jstree-clicked")).parent('li');
34581        if( folder_obj.length < 1 )
34582        { 
34583          /* alert('cancel');*/
34584        }
34585        else
34586        {
34587          if (folder_obj.data('jstree')['is_create_disabled'] == true)
34588          {
34589            g_cmn.fn_notif_win(true, 'New folder creation not allowed on this level' , 3000);
34590            return;
34591          }
34592          
34593          var folder_obj_id = folder_obj.attr('id');
34594          var target_obj = folder_obj.data('jstree');
34595          var target_id = folder_obj_id.split('_')[1];
34596          var is_not_top_parent_id = true;
34597          var target_dir = '';
34598          var i=0;
34599          while (is_not_top_parent_id)
34600          {
34601            if(i!=0)
34602              folder_obj = $('#'+folder_obj_id).parent().parent();
34603
34604            i++;
34605
34606            folder_obj_id = folder_obj.attr('id');
34607            if(folder_obj_id=='select_target_jstree_container')
34608              is_not_top_parent_id = false;
34609            else
34610            {
34611              var d = folder_obj.data('jstree');
34612              if (d) text = d['title_no_html'];
34613              text = text.replace('SugarSync Workspaces (', 'SugarSync (')
34614              if (target_dir == '')
34615                target_dir = text;
34616              else
34617                target_dir = text  + " > " + target_dir;
34618            }
34619          }
34620          $('#target_obj').val($.toJSON(target_obj));
34621          $('#target_dir').val(target_dir);
34622          $('#location').val(target_dir).attr('title', target_dir);
34623          
34624          try { g_cmn.fn_working_overlay(true, 'Saving...'); } catch(er)  { }
34625          $('#save_backup_location_form').submit();
34626
34627          $(this).dialog("close"); 
34628        }
34629      }
34630    }
34631  });
34632}
34633
34634/**
34635 * @author Senad Dizdar
34636 * 
34637 * Copyright (C) 2010-2011, cloudHQ 
34638 * All rights reserved.
34639 *
34640 */
34641
34642function c_synch()
34643{
34644  /* private variables */
34645  var synch_update_timer = null;
34646  var synch_update_timer_value = 30000;
34647  var running_flag = null;
34648  
34649  function init_search() {
34650    
34651    var search_box = $('.search-box');
34652    
34653    function search() {
34654      
34655      var words = $(search_box).val();
34656      words = words.replace(/^\s+|\s+$/gm,''); // trim
34657      words = words.split(' ');
34658      words = jQuery.grep(words, function(word, i){
34659        return word != '';
34660      });
34661      words = jQuery.map(words, function(word, i) {
34662        return '(?=.*' + word.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&") + ')';
34663      });
34664      
34665      if (words.length == 0) {
34666        //$('.synch_group').removeClass('collapsed');
34667        $('.synch_dir_rows').css('display', 'block');
34668        search_box.css('border-color', '').css('background-color', '');
34669        return;
34670      }
34671      
34672      search_box.css('border-color', '#195070')
34673        .css('background-color', '#f3f8ff');
34674
34675      var flag = "i";
34676      var pattern = "" + words.join("") + "";
34677      var regEx = new RegExp(pattern, flag);
34678      
34679      $('.synch_group').addClass('collapsed');
34680      $('.synch_dir_rows').each(function() {
34681       
34682        var row = $(this);
34683        var matches = [];
34684        
34685        row.find('.search-include').each(function() {
34686          var el = $(this);
34687          if(el.val && el.val() != '') {
34688            res = el.val().match(regEx);
34689            if (res != null) {
34690              for(var i = 0; i < res.length; i++) {
34691                matches.push(res[i]);
34692              }
34693            }
34694          }
34695        });
34696        
34697        if(matches.length > 0) {
34698          // found match.
34699          row.closest('.synch_group').removeClass('collapsed');
34700          row.css('display', '');
34701        } else {
34702          row.css('display', 'none');
34703        }
34704        
34705      });
34706    }
34707    
34708    var timeout = null;
34709    
34710    search_box.keyup(function() {
34711      
34712      // optimize. do a lookup only 0.5 sec after we stop typing.
34713      if (timeout != null)
34714        window.clearTimeout(timeout);
34715      
34716      timeout = window.setTimeout(search, 500);
34717      
34718    });
34719    
34720    search();
34721    
34722  };
34723  
34724  
34725  /*********************************************/
34726  /* PUBLIC FUNCTIONS                         */
34727  /*********************************************/
34728  this.fn_init = function(input_running_flag){
34729    
34730    fn_update_buttons();
34731    
34732    $("form").bind("submit", function(e){
34733      var notif_to_display = $('input[name="submit"]', $(this)).attr('notif_to_display');
34734      if (notif_to_display != null) 
34735        g_cmn.fn_notif_win(true, notif_to_display);
34736      
34737      g_cmn.fn_working_overlay();
34738      return true;
34739    });
34740    
34741    var tagText = $('#utc_last_job_operation').html();
34742    if (tagText) 
34743    {
34744      var givenDate = new Date($.format.date(tagText, ""));
34745      if ((givenDate + "") == 'Invalid Date')
34746        var givenDate = tagText;
34747      $('#utc_last_job_operation').html(' ' + givenDate);
34748      
34749      
34750    }
34751    
34752    // click on checkboxes is submit
34753    $(".checkbox_enabled input:checkbox").bind("click", function(e) {
34754      try { g_cmn.fn_notif_win(true, "Saving...");  } catch(er)  { }
34755      $('#synch_form').submit();
34756    });
34757    
34758    running_flag = input_running_flag;
34759    
34760    // disable monitoring status
34761    // synch_update_timer = setTimeout(function(){ fn_get_synch_status_text_ajax(); }, 30000);
34762    
34763    init_search();
34764  };
34765  
34766  /***
34767   * Initialize jstree inside dialog
34768   * @param {Object} dir1_or_dir2
34769   */
34770  this.fn_init_jstree_inside_dialog = function(dir1_or_dir2)
34771  {
34772    // call server to intilize 
34773    $.ajax(
34774    {
34775      type: "GET",
34776      url: g_site_url + "main_cloud_fs_interface/cloudhq_init",
34777      dataType: "json",
34778      data: { 'call_for_synch': $.toJSON(true),
34779              'dir1_or_dir2'  : $.toJSON(dir1_or_dir2)
34780             },
34781      async: true,    
34782      success: function(response)
34783      {
34784        if (response.error)
34785        {
34786          g_cmn.fn_notif_win(true, "Something went wrong... <br>Please refresh the page." , 5000);
34787        }
34788        else
34789        {
34790          fn_display_jstree(response, dir1_or_dir2);
34791        }
34792      },
34793      failure: function(response)
34794      {
34795        alert("Failure");
34796      }
34797    });
34798  };
34799  
34800  /*********************************************/
34801  /* PRIVATE FUNCTIONS                         */
34802  /*********************************************/
34803  
34804  /* fn_display_jstree: display jstree. 
34805   * response:     data received from cloudhq_init 
34806   * dir1_or_dir2: whether this is for dir1 or dir2
34807   */
34808  var fn_display_jstree = function(response, dir1_or_dir2)
34809  {
34810    $(function () {
34811      $('#select_synch_jstree_container_' + dir1_or_dir2).jstree("destroy");
34812      $('#select_synch_jstree_container_' + dir1_or_dir2).bind('load_node.jstree', function(event, data)
34813       {
34814         // alert("reopen");
34815       }).jstree({
34816         "core": {
34817          html_titles: true
34818        },
34819        "json_data" : {
34820          "correct_state" : true,
34821          "data" : response,
34822          "ajax" : { "url" :function (n) {
34823              if (n==-1)
34824                return false;
34825              else{
34826                g_cmn.fn_notif_win(true, "Loading...", null);
34827                return g_site_url + "main_cloud_fs_interface/cloudhq_dir";
34828              }
34829            },
34830            "success": function (obj, t, x) {
34831              $('#loading').css('display','none');
34832              if ( t == "success" )
34833              {
34834                var response = JSON.parse(x.responseText);
34835                if (response['error'])
34836                  g_cmn.fn_notif_win(true, "Something went wrong... <br>Please refresh the page ." , 5000);
34837                else
34838                  g_cmn.fn_notif_win(false, "", null);
34839              }
34840              else
34841              {
34842                g_cmn.fn_notif_win(false, "", null);
34843              }
34844            },
34845            "error" : function (obj) {
34846              g_cmn.fn_notif_win(true, "Something went wrong... <br>Please refresh the page." , 5000);
34847              alert ("error: jQuery internal error. Please refresh the page.");
34848            },
34849            "data" : function (obj) {
34850              return { "obj"       : $.toJSON(obj.data('jstree')), 
34851                       "file_flag" : $.toJSON(true) }
34852            }
34853          }
34854        },
34855        "contextmenu" : {
34856          "items": function(node){
34857          } // end function
34858        },
34859        "themes"   : {
34860          "theme" : "cloudhq",
34861          "dots" : false,
34862          "icons" : true
34863        },
34864        "plugins"  : [ "themes", "json_data", "ui", "crrm", "types" ]
34865      });
34866
34867    });
34868
34869  } /* fn_display_jstree */
34870  
34871  /***
34872   * 
34873   * @param {Object} dir1
34874   * @param {Object} dir2
34875   */
34876  var fn_add_dir_row = function(dir1, dir2)
34877  {
34878    var doc = document;
34879    var dir_rows = doc.createElement('div');
34880    var dir_text = '';
34881    var add_row_count  = $('div.synch_dir_rows').length;
34882    $(dir_rows).attr({'id': 'synch_dir_rows' + add_row_count }).addClass('synch_dir_rows');
34883    
34884    var i = 1;
34885    [dir1, dir2].forEach(
34886      function(e)
34887      {
34888        var dir1_or_dir2 = 'dir' + i; // 'dir1' or 'dir2'
34889        var dir_res = e['dir_res'];
34890         
34891        var dir_rows_input = doc.createElement("input");
34892        $(dir_rows_input).attr({'readonly': 'readonly', 'title' : dir_res['name'] }).addClass('location').val(dir_res['name']);
34893        $(dir_rows_input).appendTo(dir_rows);
34894      
34895        // add input rows with obj (which is json object) and name (just string)
34896        $(doc.createElement('input'))
34897        .attr({'type': 'hidden', 'name': dir1_or_dir2 + '_obj_list[]', 'id' : dir1_or_dir2 + '_id_' + add_row_count, 'value' : $.toJSON(dir_res['obj']) }) 
34898        .appendTo(dir_rows);
34899        $(doc.createElement('input'))
34900        .attr({'type': 'hidden', 'name': dir1_or_dir2 + '_name_list[]', 'id' : dir1_or_dir2 + '_name_' + add_row_count, 'value' : dir_res['name'] })
34901        .appendTo(dir_rows);
34902        
34903        // add options: delete replicate is 1, upload converstion policy is 0
34904        $(doc.createElement('input'))
34905        .attr({'type': 'hidden', 'name': 'replicate_delete_list[' + add_row_count + ']', 'id' : 'replicate_delete_' + add_row_count, 'value' : '1' })
34906        .appendTo(dir_rows);
34907        $(doc.createElement('input'))
34908        .attr({'type': 'hidden', 'name': 'upload_convert_policy_list[' + add_row_count + ']', 'id' : 'upload_convert_policy_' + add_row_count, 'value' : '0' })
34909        .appendTo(dir_rows);
34910        
34911        i = i + 1;
34912      }
34913    );
34914    
34915    var dir_rows_span = doc.createElement("span");
34916    var dir_rows_a = doc.createElement("a");
34917    $(dir_rows_a).attr({'href': 'javascript:void(0);', 'title' : dir_res['name'] }).html(' <img src="/images/remove.png" />');
34918    $(dir_rows_a).appendTo(dir_rows_span);
34919    $(dir_rows_span).appendTo(dir_rows);
34920        
34921    add_row_count++;
34922    
34923    $('#pre_synch_folder').append(dir_rows);
34924    
34925    g_cmn.fn_notif_win(true, "Saving..." , 5000);
34926    $('#synch_form').submit();
34927  }
34928  
34929  
34930  /***
34931   * 
34932   */
34933  var fn_synch_folder_dialog_on_select_folder = function($dialog, dir1_or_dir2) 
34934  {
34935    var next_step  = $dialog.dialog('option', 'next_step');
34936    var folder_obj = $($("#select_synch_jstree_container_" + dir1_or_dir2 + " .jstree-clicked")).parent('li');
34937    if (folder_obj.length < 1)
34938    { 
34939       $dialog.dialog("close"); 
34940      /* alert('cancel');*/
34941    }
34942    else
34943    {
34944      if (folder_obj.data('jstree')['is_synch_disabled'] == true)
34945      {
34946        g_cmn.fn_error_dialog("ERROR", "Synchronization is not allowed on this level. Please select a child folder.", { width: "550px" });
34947        // g_cmn.fn_notif_win(true, 'Synchronization is not allowed on this level.' , 3000);
34948        return;
34949      }
34950
34951      var selected_node = new Array();
34952      var checked_obj = $("#select_synch_jstree_container_"  + dir1_or_dir2 + " .jstree-clicked").parent('li');
34953
34954      $(checked_obj).each(
34955        function() {
34956          dir_res = fn_get_selected_folder($(this));
34957  
34958          fn_check_selection($(this), 
34959            function() {
34960              
34961              // Add this to the dialog options
34962               $dialog.dialog('option', 'selected', { dir_res: dir_res });
34963              
34964              // go to next step
34965              if (jQuery.isFunction(next_step))
34966              {
34967                $dialog.dialog("close"); 
34968                next_step();
34969              }
34970            }
34971          );
34972       });
34973    }
34974  }
34975  
34976  var synch_folder_dialog_dir1 = $("#select_synch_folder_dialog_dir1").dialog({
34977    autoOpen: false, resizable: false, width: 700, height: 550, title: "Select folders for synchronization",
34978    modal: true,
34979    buttons: { 
34980      "Cancel": function() { 
34981         $(this).dialog("close"); 
34982      },
34983      "Select Folder": function() {
34984        fn_synch_folder_dialog_on_select_folder($("#select_synch_folder_dialog_dir1"), 'dir1');
34985      }
34986    }
34987  });
34988
34989  var synch_folder_dialog_dir2 = $("#select_synch_folder_dialog_dir2").dialog({
34990    autoOpen: false, resizable: false, width: 700, height: 550, title: "Select folders for synchronization",
34991    modal: true,
34992    buttons: { 
34993      "Cancel": function() { 
34994         $("#select_synch_folder_dialog_dir2").dialog("close"); 
34995      },
34996      "Select Folder": function(){
34997        fn_synch_folder_dialog_on_select_folder($("#select_synch_folder_dialog_dir2"), 'dir2');
34998      }
34999    }
35000  });
35001  
35002  /***
35003   * 
35004   * Select dir2 and then after selected call fn_add_dir_row and fn_update_buttons.
35005   */
35006  var fn_select_dir2 = function()
35007  {
35008    $('#select_synch_jstree_container_dir1').hide();
35009    $('#select_synch_jstree_container_dir2').show();
35010    synch_folder_dialog_dir2.dialog('option', 'next_step', function() {
35011      fn_add_dir_row(synch_folder_dialog_dir1.dialog('option', 'selected'), synch_folder_dialog_dir2.dialog('option', 'selected'));
35012      fn_update_buttons();
35013    });
35014    dir1_selected = synch_folder_dialog_dir1.dialog('option', 'selected')['dir_res']['obj'];
35015    if (dir1_selected['nice_path']) {
35016      $('#dialog_header_container_dir1_what').html(dir1_selected['nice_path'])
35017    } else {
35018      $('#dialog_header_container_dir1_what').html(dir1_selected['path']);
35019    }
35020    synch_folder_dialog_dir2.dialog( { title: 'Select Folder, Project, or Collection' } );
35021    synch_folder_dialog_dir2.dialog('open');
35022  }
35023
35024  /***
35025   * Select dir1 and then after selected call next_step.
35026   * @param {Function} next_step
35027   */
35028  var fn_select_dir1 = function(next_step)
35029  {
35030    $('#select_synch_jstree_container_dir1').show();
35031    $('#select_synch_jstree_container_dir2').hide();
35032    synch_folder_dialog_dir1.dialog('option', 'next_step', next_step);
35033    synch_folder_dialog_dir1.dialog( { title: 'Select Folder, Project, or Collection' } );
35034    synch_folder_dialog_dir1.dialog('open');
35035  }
35036
35037  var fn_update_buttons = function()
35038  {
35039    
35040    var rows_count = $('.synch_dir_rows input').length;
35041    
35042    if (rows_count > 0)
35043    {
35044      $('#get_synch_folder_button_wrapper span:eq(0)').hide();
35045      $('#get_synch_folder_button_wrapper span:eq(1)').show();
35046    }
35047    else
35048    {
35049      $('#get_synch_folder_button_wrapper span:eq(0)').show();
35050      $('#get_synch_folder_button_wrapper span:eq(1)').hide();
35051      
35052    }
35053    
35054    $('#add_synch_folder_or_file_pair_fast').unbind("click").bind('click', function(){
35055
35056      fn_select_dir1(fn_select_dir2);
35057      return false;
35058    });
35059    
35060    
35061    if ($('#pre_synch_folder span').length == 0)
35062      $('#synch_pairs_header').hide();
35063    else
35064      $('#synch_pairs_header').show();
35065   
35066    /*
35067    $('#pre_synch_folder .synch_dir_rows span.button_grayed, .button_say_stop, #pre_synch_folder .synch_dir_rows .checkbox_grayed').bind('click', function() {
35068      var $t = $(this);
35069      g_cmn.fn_normal_dialog("Notice", "Please stop the synchronization before modifying it", "", 
35070        { width: "450px", buttons: {
35071          "OK": function() {
35072              $(this).dialog("close"); 
35073          }
35074        }
35075      });
35076      return false;
35077    });
35078    */
35079    
35080    $('#pre_synch_folder .synch_dir_rows .synch_config_delete').bind('click', function() {
35081      var $t = $(this);
35082      g_cmn.fn_normal_dialog("Confirmation", "Are you sure?", 
35083        "When you delete a sync pair, then ALL meta-data will be lost so any new sync pair between these folders will need to copy/download/catalog all files again. <br/><br/>Note that deleting of a sync pair will not delete any files.", 
35084        { width: "650px", buttons: {
35085          "No": function() {
35086              $(this).dialog("close"); 
35087              return false
35088          },
35089          "Yes": function() {
35090              // alert($t.html());
35091              g_cmn.fn_notif_win(true, "Deleting sync pair..." , 5000);
35092              var id_of_form = $t.attr('form_id');
35093              $('#' + id_of_form).submit();
35094              $(this).dialog("close"); 
35095          }
35096        }
35097      });
35098      return false;
35099    });
35100  }
35101  
35102  
35103  /**
35104   * Check whether user selection is valid
35105   * @param  {string}   dir_res:   object to check agains 
35106   * @param  {function} func_cont: function to call if everything is ok
35107   * @return {string}   Nothing
35108   * 
35109   * given id of the object verify folder selection is valid
35110   * NOTE: we don't check anything here!
35111   *
35112   */
35113  var fn_check_selection = function(f, func_cont)
35114  {
35115    func_cont();
35116    return;
35117    /*
35118    var ref = f.data('jstree')['ref'];
35119    var elems = $('.synch_dir_rows input[name="dir1_obj_list[]"], .synch_dir_rows input[name="dir2_obj_list[]"]');
35120    var o, e, pe;
35121    
35122    
35123    for (i = 0; i < elems.length; i ++)
35124    {
35125      e = $(elems[i]);
35126      
35127      o = JSON.parse(e.attr('value'));
35128      if (ref == o['ref'])
35129      {
35130        g_cmn.fn_error_dialog("ERROR", "Folder is already selected for synchronization.", { width: "400px" });
35131        return; 
35132      }
35133      p = f.parents('li');
35134      
35135      for (j = 0; j < p.length; j ++)
35136      {
35137        pe = $(p[j]);
35138        o = JSON.parse(e.attr('value'));
35139        if (pe.data('jstree')['ref'] ==  o['ref'])
35140        {
35141          g_cmn.fn_error_dialog("ERROR", "Parent folder is already selected for synchronization.", { width: "450px" });
35142          return; 
35143        }
35144      }
35145    }
35146    
35147    func_cont();
35148    */
35149  }
35150  
35151  var fn_get_selected_folder = function(folder_element)
35152  {
35153    var folder_element_id = folder_element.attr('id');
35154    var target_id = folder_element_id.split('_')[1];
35155    var target_obj = folder_element.data('jstree');
35156    
35157    var is_not_top_parent_id = true;
35158    var target_name = '';
35159    var i=0;
35160    while (is_not_top_parent_id)
35161    {
35162      if(i!=0)
35163        folder_element = $('#'+folder_element_id).parent().parent();
35164
35165      i++;
35166      folder_element_id = folder_element.attr('id');
35167      if(folder_element_id=='select_synch_jstree_container_dir1' || folder_element_id=='select_synch_jstree_container_dir2')
35168        is_not_top_parent_id = false;
35169      else
35170      {
35171        var d = folder_element.data('jstree');
35172        if (d) text = d['title_no_html'];
35173          text = text.replace('SugarSync Workspaces (', 'SugarSync (')
35174        if (target_name == '')
35175          target_name = text;
35176        else
35177          target_name = text  + " > " + target_name;
35178      }
35179    }
35180    return { id: target_id, obj: target_obj, name: target_name }
35181  }
35182  
35183
35184  /* fn_get_synch_status_text_ajax()
35185   * loop and update #synch_status_text_content with status of the syncrhonization
35186   */
35187  var fn_get_synch_status_text_ajax = function()
35188  {
35189    $.ajax({
35190      type: "GET",
35191      url: g_site_url + "main_synch/get_synch_status_ajax",
35192      dataType: "json",
35193      async: true,
35194      success: function(response){
35195        if (response.error) {
35196          g_cmn.fn_notif_win(true, "Something went wrong... <br>Please refresh the page.", 5000);
35197        }
35198        else {
35199          $('#synch_status_text_content').html(response.data.text);
35200          if (response.data.running_flag == false && running_flag == true)
35201          {
35202            g_cmn.fn_normal_dialog("Notification", "", "Synchronization job finished", { buttons: { "Refresh Page": function() { location.reload(true); } }, close: function() { location.reload(true); } } );
35203          }
35204          else if (response.data.running_flag == true && running_flag == false)
35205          {
35206            g_cmn.fn_normal_dialog("Notification", "", "Synchronization job started", { buttons: { "Refresh Page": function() { location.reload(true); } }, close: function() { location.reload(true); } } );
35207          }
35208          else
35209          {
35210            clearTimeout(synch_update_timer);
35211            synch_update_timer_value = synch_update_timer_value + 20000;
35212            if (synch_update_timer_value < 120000)
35213              synch_update_timer_value = 120000;
35214            synch_update_timer = setTimeout(function(){ fn_get_synch_status_text_ajax();}, synch_update_timer_value);
35215          }
35216        }
35217      },
35218      failure: function(response){
35219        g_cmn.fn_notif_win(true, "Something went wrong... <br>Please refresh the page.", 5000);
35220      }
35221    });
35222  }
35223  
35224}
35225
35226/**
35227 * @author Senad Dizdar
35228 * 
35229 * Copyright (C) 2010-2011, cloudHQ 
35230 * All rights reserved.
35231 *
35232 */
35233
35234function c_synch_wizard()
35235{
35236  /* private variables */
35237  
35238  /*********************************************/
35239  /* PUBLIC FUNCTIONS                         */
35240  /*********************************************/
35241  this.fn_init = function(service_what, service_email_or_login, logged_in, is_bcx_evernote_integration, is_bcx_simple_view, list_sp_web_urls)
35242  {
35243    if (service_what == "" && logged_in == false)
35244    {
35245    }
35246    else if (service_what != "" && logged_in == false)
35247    {
35248
35249    }
35250    else
35251    {
35252      $('form').bind('submit', function() {
35253        try { g_cmn.fn_working_overlay(true, "Working..."); } catch(er)  { }
35254        return true;
35255      });
35256    }
35257    
35258    // disable adding 37signals for free plans
35259    /*$('.service_image_container a.not_allowed_by_selected_plan').unbind('click').bind('click', function() {
35260      g_cmn.fn_error_dialog("This service is only supported by Premium Plan", "<span>Please select 15-days free Premium Plan trial to sync this service.<br/><br/>If you have already started Personal Plan, please contact us to convert your Personal Plan to 15-days free Premium Plan trial.</span><br/><br/>", { width: "650px" });
35261      return false;
35262    });*/
35263    
35264    try {
35265      var l = $('#select_synch_jstree_container').length;
35266      if (l > 0) {
35267        fn_init_jstree(service_what, service_email_or_login, is_bcx_evernote_integration, is_bcx_simple_view, list_sp_web_urls);
35268        $('.buttons_container #select_folder_button').unbind('click').bind('click', function(){
35269          fn_on_select_folder();
35270        });
35271      
35272      }
35273    } 
35274    catch (er) {
35275    }
35276    
35277    $('.service_path_link_dir1').unbind('click').bind('click', function() {
35278      service_path_dialog_dir1_dialog.dialog('open');
35279      return false;
35280    });
35281    
35282    $('.service_path_link_dir2').unbind('click').bind('click', function() {
35283      service_path_dialog_dir2_dialog.dialog('open');
35284      return false;
35285    });
35286    
35287    $('#new_folder_button').unbind("click").bind('click', function(){
35288    
35289      var parent_folder_obj = $($("#select_synch_jstree_container .jstree-clicked")).parent('li');
35290      if (parent_folder_obj.length < 1) {
35291        g_cmn.fn_error_dialog("ERROR", "Nothing selected. Please select a parent folder.", {
35292          width: "550px"
35293        });
35294        return;
35295      }
35296
35297      parent_folder_obj_data = parent_folder_obj.data('jstree');
35298      if (parent_folder_obj_data['is_folder_create_disabled'] == true ) {
35299        g_cmn.fn_error_dialog("ERROR", "The parent is read-only.", {
35300          width: "550px"
35301        });
35302        return;
35303      }
35304      new_folder_dialog.dialog('option', 'parent_folder_obj_data', parent_folder_obj_data);
35305      new_folder_dialog.dialog('option', 'is_bcx_evernote_integration', is_bcx_evernote_integration);
35306      new_folder_dialog.dialog('option', 'is_new_folder_option_selected', false);
35307      if (parent_folder_obj_data['nice_path']) {
35308        $('#dialog_header_container_dir1_what').html(parent_folder_obj_data['nice_path'])
35309      } else {
35310        $('#dialog_header_container_dir1_what').html(parent_folder_obj_data['path']);
35311      }
35312      new_folder_dialog.dialog('open');
35313    });
35314    
35315
35316    // when user selects a service we check it whether it can be sync'd
35317    if (logged_in)
35318    {
35319      $('a.add_service_button').bind('click', function() {
35320        if ($(this).hasClass('noclick')) {
35321          return false;
35322        }
35323        g_cmn.fn_working_overlay(true, "Checking...");
35324        var selected_elem = $(this);
35325        fn_check_selected_service($('img', $(this)).attr('id'), function() { 
35326          window.location = selected_elem.attr('href');
35327        })
35328        return false;
35329      });
35330    }
35331
35332    $('#evernote_exp2_read_write_enabled').bind('click', 
35333      function() {
35334        if ($('#evernote_exp2_read_write_enabled').is(":checked")) {
35335          $('#evernote_exp2_read_write_enabled_div').removeClass('ui-state-disabled');
35336          $('#evernote_exp2_read_write_enabled_div input').attr("disabled", null);
35337          $('#evernote_exp2_read_write_enabled_div input:first').attr('checked', 'checked');
35338          $('#save_synch_config').submit(); 
35339
35340        }
35341        else {
35342          $('#evernote_exp2_read_write_enabled_div').removeClass('ui-state-disabled').addClass('ui-state-disabled');
35343          $('#evernote_exp2_read_write_enabled_div input').attr("disabled", "disabled");
35344          $('#evernote_exp2_read_write_enabled_div input').attr("checked", null);
35345          $('#save_synch_config').submit(); 
35346        }
35347
35348      }
35349    );
35350
35351    $('#evernote_exp2_read_only_enabled').bind('click', 
35352      function() {
35353        if ($('#evernote_exp2_read_only_enabled').is(":checked")) {
35354          $('#evernote_exp2_read_only_enabled_div').removeClass('ui-state-disabled');
35355          $('#evernote_exp2_read_only_enabled_div input').attr("disabled", null);
35356          $('#evernote_exp2_read_only_enabled_div input:first').attr('checked', 'checked');
35357          $('#save_synch_config').submit(); 
35358        }
35359        else {
35360          $('#evernote_exp2_read_only_enabled_div').removeClass('ui-state-disabled').addClass('ui-state-disabled');
35361          $('#evernote_exp2_read_only_enabled_div input').attr("disabled", "disabled");
35362          $('#evernote_exp2_read_only_enabled_div input').attr("checked", null);
35363          $('#save_synch_config').submit(); 
35364        }
35365      }
35366    );
35367    // alert('after');
35368    
35369  }
35370  
35371  $('#select_option_button').click(function() {
35372    var check = $('input[name=what_to_sync]:checked');
35373
35374    $('#input_what_to_sync').val(check.val());
35375    if (check.val() == 'account') {
35376      fn_select_root_folder();
35377    }
35378    else if (check.val() == 'folder') {
35379      var obj = JSON.parse($('#what_to_sync_folder_obj').val());
35380      fn_select_existing_folder(obj);
35381    }
35382    else if (check.val() == 'create') {
35383      $($("#select_synch_jstree_container li.jstree-root > a")).addClass('jstree-clicked');
35384      fn_select_new_folder();
35385    }
35386    //else if (check.val() == 'restore_email') {
35387    //  $('#wrapper_select_folder').show();
35388    //  $('#wrapper_what_to_sync').remove();
35389    //}
35390    else {
35391      $('#wrapper_select_folder').show();
35392      $('#wrapper_what_to_sync').remove();
35393    }
35394  }); 
35395  
35396  
35397  var is_bcx_evernote_integration;
35398 
35399  
35400  new_folder_dialog_title_text = $('#new_folder_dialog_title_text').html();
35401  var new_folder_dialog = $("#new_folder_dialog").dialog({
35402    autoOpen: false,
35403    resizable: false,
35404    width: 805,
35405    height: 255,
35406    title: new_folder_dialog_title_text,
35407    modal: true,
35408    buttons: {
35409      "Cancel": function(){
35410        $(this).dialog("close");
35411      },
35412      "Create": function(){
35413        var folder_name = $('#folder_name').val();
35414        if (folder_name == '') 
35415          g_cmn.fn_error_dialog("", "Please enter folder name");
35416        else {
35417          g_cmn.fn_working_overlay(true, "Creating folder...");
35418          parent_folder_obj_data = new_folder_dialog.dialog('option', 'parent_folder_obj_data');
35419          is_bcx_evernote_integration = new_folder_dialog.dialog('option', 'is_bcx_evernote_integration');
35420          is_new_folder_option_selected  = new_folder_dialog.dialog('option', 'is_new_folder_option_selected');
35421          $.ajax({
35422            type: "POST",
35423            url: g_site_url + "main_cloud_fs_interface/new_dir",
35424            dataType: "json",
35425            data: {
35426              "obj": $.toJSON(parent_folder_obj_data),
35427              "folder_name": $.toJSON(folder_name),
35428              "is_bcx_evernote_integration": $.toJSON(is_bcx_evernote_integration),
35429
35430            },
35431            async: true,
35432            success: function(response){
35433              if (response.error) {
35434                g_cmn.fn_working_overlay(false, null);
35435                g_cmn.fn_error_dialog("Error during folder creation", response.error);
35436                // g_cmn.fn_notif_win(true, "Folder creation failed.<br\>" + response.error , 5000);
35437              }
35438              else {
35439                if (is_new_folder_option_selected == true) {
35440                  fn_select_new_folder(response);
35441                } 
35442                else {
35443                  g_cmn.fn_notif_win(true, "Folder created", 5000);
35444                  fn_refresh_server(parent_folder_obj_data, 'new_dir');
35445                }                
35446              }
35447            },
35448            failure: function(response){
35449              g_cmn.fn_working_overlay(false, null);
35450              alert("Failure");
35451            }
35452          });
35453          $(this).dialog("close");
35454        }
35455      }
35456    }
35457  });
35458  
35459  /***
35460   * Function used to refresh the tree on calling when click on refresh button
35461   * operation of copy , move, delete and new folder .
35462   * @param {Object} dir_id
35463   */
35464  var fn_refresh_server = function fn_refresh_server(obj, operation){
35465    var d = null;
35466    if (obj) 
35467      d = {
35468        "obj": $.toJSON(obj)
35469      }
35470      
35471    g_cmn.fn_notif_win(true, "Refreshing...", null);
35472    $.ajax({
35473      type: "POST",
35474      url: g_site_url + "main_cloud_fs_interface/refresh_cloudhq_dir",
35475      dataType: "json",
35476      data: d,
35477      async: true,
35478      success: function(response){
35479        if (response.error) {
35480          g_cmn.fn_notif_win(false, "", null);
35481        }
35482        else {
35483          // we can just count number of open nodes in left tree and decrement them in event on 'select_node.jstree'
35484          $("#select_synch_jstree_container").jstree('refresh');
35485          g_cmn.fn_working_overlay(false, null);
35486        }
35487      },
35488      failure: function(response){
35489        g_cmn.fn_working_overlay(false, null);
35490        alert("Failure");
35491      }
35492    });
35493  }
35494  
35495  var service_path_dialog_dir1_dialog = $('#service_path_dialog_dir1').dialog({
35496    autoOpen: false, resizable: false, width: 850, height: 190, title: "Synchronization Folder ",
35497    modal: true,
35498    buttons: { 
35499      "OK": function() { 
35500         $(this).dialog("close"); 
35501      }
35502    }
35503  });
35504  
35505  var service_path_dialog_dir2_dialog = $('#service_path_dialog_dir2').dialog({
35506    autoOpen: false, resizable: false, width: 850, height: 190, title: "Synchronization Folder ",
35507    modal: true,
35508    buttons: { 
35509      "OK": function() { 
35510         $(this).dialog("close"); 
35511      }
35512    }
35513  });
35514    
35515  
35516  /*********************************************/
35517  /* PRIVATE FUNCTIONS                         */
35518  /*********************************************/
35519  
35520  /***
35521   * Initialize jstree inside dialog
35522   * @param {Object} service
35523   */
35524  var fn_init_jstree = function(service_what, service_email_or_login, is_bcx_evernote_integration, is_bcx_simple_view, list_sp_web_urls)
35525  {
35526    g_cmn.fn_working_overlay(true, "Loading data...");
35527    // call server to intilize 
35528    $.ajax(
35529    {
35530      type: "GET",
35531      url: g_site_url + "main_cloud_fs_interface/cloudhq_init",
35532      dataType: "json",
35533      data: { 'call_for_synch'   : $.toJSON(true),
35534              'browse_only_list' : $.toJSON([{ 'what' : service_what, 'email_or_login': service_email_or_login }]),
35535              'is_bcx_evernote_integration': $.toJSON(is_bcx_evernote_integration),
35536              'is_bcx_simple_view': $.toJSON(is_bcx_simple_view),
35537              'list_sp_web_urls': $.toJSON(list_sp_web_urls)
35538             },
35539      async: true,    
35540      success: function(response)
35541      {
35542        g_cmn.fn_working_overlay(false);
35543        if (response.error)
35544        {
35545          g_cmn.fn_error_dialog("ERROR", "Sorry, a temporary error has occurred. <br/>Please try again.", { width: "550px" });
35546        }
35547        else
35548        {
35549          fn_display_jstree(response, is_bcx_evernote_integration, is_bcx_simple_view, list_sp_web_urls);
35550        }
35551
35552        var node = $("#select_synch_jstree_container ul li");
35553        if (node.length == 1) {
35554          $("#select_synch_jstree_container").jstree("open_node", node.first());
35555        }
35556      },
35557      failure: function(response)
35558      {
35559        g_cmn.fn_working_overlay(false);
35560        g_cmn.fn_error_dialog("ERROR", "Sorry, a temporary error has occurred. <br/>Please try again.", { width: "550px" });
35561      }
35562    });
35563  }
35564  
35565  /* fn_display_jstree: display jstree. 
35566   * response:     data received from cloudhq_init 
35567   */
35568  var fn_display_jstree = function(response, is_bcx_evernote_integration, is_bcx_simple_view, list_sp_web_urls)
35569  {
35570    $(function () {
35571      $('#select_synch_jstree_container').jstree("destroy");
35572      $('#select_synch_jstree_container').bind('load_node.jstree', function(event, data)
35573       {
35574         // alert("reopen");
35575       }).jstree({
35576         "core": {
35577          html_titles: true
35578        },
35579        "json_data" : {
35580          "correct_state" : true,
35581          "data" : response,
35582          "ajax" : { "url" :function (n) {
35583              if (n==-1)
35584                return false;
35585              else{
35586                g_cmn.fn_notif_win(true, "Loading...", null);
35587                return g_site_url + "main_cloud_fs_interface/cloudhq_dir";
35588              }
35589            },
35590            "success": function (obj, t, x) {
35591              $('#loading').css('display','none');
35592              if ( t == "success" )
35593              {
35594                var response = JSON.parse(x.responseText);
35595                if (response['error'])
35596                  g_cmn.fn_notif_win(true, "Something went wrong... <br>Please refresh the page ." , 5000);
35597                else
35598                  g_cmn.fn_notif_win(false, "", null);
35599              }
35600              else
35601              {
35602                g_cmn.fn_notif_win(false, "", null);
35603              }
35604            },
35605            "error" : function (obj) {
35606              g_cmn.fn_notif_win(true, "Something went wrong... <br>Please refresh the page." , 5000);
35607            },
35608            "data" : function (obj) {
35609              return { "obj"       : $.toJSON(obj.data('jstree')), 
35610                       "file_flag" : $.toJSON(false),
35611                       "is_synch_wizard"            : $.toJSON(true),
35612                       "is_bcx_evernote_integration": $.toJSON(is_bcx_evernote_integration),
35613                       "is_bcx_simple_view"         : $.toJSON(is_bcx_simple_view),
35614                       "list_sp_web_urls"           : $.toJSON(list_sp_web_urls)
35615                     }
35616            }
35617          }
35618        },
35619        "contextmenu" : {
35620          "items": function(node){
35621          } // end function
35622        },
35623        "themes"   : {
35624          "theme" : "cloudhq",
35625          "dots" : false,
35626          "icons" : true
35627        },
35628        "plugins"  : [ "themes", "json_data", "ui", "crrm", "types" ]
35629      });
35630
35631    });
35632    
35633    $("#select_synch_jstree_container").bind("select_node.jstree", function(e, data){        
35634      $("#select_synch_jstree_container").jstree('open_node', data.rslt.obj);
35635      /* now update */
35636      $('#what_selected_container .what_selected_nothing').hide();
35637      $('#what_selected_container .what_selected_something').show();
35638      var max_path_length = 85;
35639      
35640      var path = data.rslt.obj.data('jstree')['nice_path'];
35641      if (!path) {
35642        path = data.rslt.obj.data('jstree')['path'];
35643      }
35644      if (path.length > max_path_length) {
35645        var filename = path.replace(/^.*[\\\/]/, '');
35646        if (filename == '') { // no file at all
35647          path = path.substring(0, max_path_length - 3) + '...';
35648        }
35649        else {
35650          if (filename.length > max_path_length) { // there is file but too long
35651            path = filename.substring(0, max_path_length - 3) + '...';
35652          }
35653          else {
35654            var dirname = path.replace(/\\/g, '/').replace(/\/[^\/]*$/, '');
35655            var max_dirname_length = max_path_length - filename.length - 1;
35656            if (max_dirname_length > 3) {
35657              dirname = dirname.substring(0, max_dirname_length - 3) + '...';
35658              path = dirname + "/" + filename;
35659            }
35660            else {
35661              path = filename;
35662            }
35663          }
35664        }
35665      }
35666      
35667      $('#what_selected_container .what_selected_something .what_selected_something_value').html(path);
35668
35669      // now rename buttons
35670      var child_obj_type_user_friendly_name = data.rslt.obj.data('jstree')['child_obj_type_user_friendly_name'];
35671      if (child_obj_type_user_friendly_name != null)
35672      {
35673        $(".child_obj_type_user_friendly_name").html(child_obj_type_user_friendly_name);
35674      }
35675
35676      var is_folder_create_disabled = data.rslt.obj.data('jstree')['is_folder_create_disabled'];
35677      if (is_folder_create_disabled)
35678      {
35679        $('#new_folder_button').addClass('ui-state-disabled');
35680      }
35681      else
35682      {
35683        $('#new_folder_button').removeClass('ui-state-disabled');
35684      }
35685
35686    });
35687    
35688    /*
35689    var on_click_delegate = function(e) {
35690      var node_id = $(this).parent('li.jstree-closed').attr("id"); //get ID of clicked node
35691      if (node_id != null) {
35692        $("#" + node_id + " .jstree-icon").trigger('click');
35693        $('#select_synch_jstree_container').undelegate("a","click", on_click_delegate);
35694      }
35695      return true;
35696    }
35697    
35698    $('#select_synch_jstree_container').delegate("a","click", on_click_delegate);
35699    */
35700   
35701  } /* fn_display_jstree */
35702 
35703  /***
35704   * 
35705   */
35706  var fn_select_root_folder = function() {
35707    var rootObj = $($("#select_synch_jstree_container li.jstree-root")).data('jstree');
35708    fn_check_selected_folder(rootObj,
35709      function()
35710      {
35711        var dir_row = $('<div></div>');
35712        dir_row.append($('<input type="hidden" name="obj_list[]" />').val($.toJSON(rootObj)));
35713        dir_row.append($('<input type="hidden" name="name_list[]" />').val(rootObj['title_no_html']));
35714        $('#synch_folder').append(dir_row);
35715        g_cmn.fn_working_overlay(true, "Saving...");
35716        $('#select_folder_form').submit();
35717      }
35718    );
35719  };
35720  
35721  var fn_select_existing_folder = function(folderObj) {
35722    folderObj['title_no_html'] = folderObj['title'];
35723    fn_select_new_folder(folderObj);
35724  };
35725  
35726  var fn_select_new_folder = function(obj) {
35727    if(obj) {
35728      fn_check_selected_folder(obj,
35729        function()
35730        {
35731          var dir_row = $('<div></div>');
35732          dir_row.append($('<input type="hidden" name="obj_list[]" />').val($.toJSON(obj)));
35733          dir_row.append($('<input type="hidden" name="name_list[]" />').val(obj['title_no_html']));
35734          $('#synch_folder').append(dir_row);
35735          g_cmn.fn_working_overlay(true, "Saving...");
35736          $('#select_folder_form').submit();
35737        }
35738      );
35739    } else {
35740      // if we don't have an object then open dialog
35741      var rootObj = $($("#select_synch_jstree_container li.jstree-root")).data('jstree');
35742      if (rootObj == null) {
35743        window.location = 'https://www.cloudhq.net/main_services/refresh'
35744      }
35745
35746      if (rootObj['nice_path']) {
35747        $('#dialog_header_container_dir1_what').html(rootObj['nice_path'])
35748      } else {
35749        $('#dialog_header_container_dir1_what').html(rootObj['path']);
35750      }
35751      new_folder_dialog.dialog('option', 'parent_folder_obj_data', rootObj);
35752      new_folder_dialog.dialog('option', 'is_bcx_evernote_integration', false);
35753      new_folder_dialog.dialog('option', 'is_new_folder_option_selected', true);
35754      new_folder_dialog.dialog('open');
35755    }
35756  };
35757  
35758  var fn_on_select_folder = function() 
35759  {
35760    var folder_obj = $($("#select_synch_jstree_container .jstree-clicked")).parent('li');
35761    if (folder_obj.length < 1)
35762    { 
35763      g_cmn.fn_error_dialog("ERROR", "Nothing select. Please select a folder to synchronize.", { width: "550px" });
35764      return;
35765    }
35766    else
35767    {
35768      if (folder_obj.data('jstree')['is_synch_disabled'] == true && folder_obj.data('jstree').what == 'sugarsync')
35769      {
35770        g_cmn.fn_error_dialog("ERROR", "Synchronization is not allowed on this level. Please select a SugarSync workspace.", { width: "550px" });
35771        return;
35772      }
35773
35774      var selected_node = new Array();
35775      var checked_obj = $("#select_synch_jstree_container .jstree-clicked").parent('li');
35776      
35777      $(checked_obj).each(
35778        function() {
35779          dir_res = fn_get_selected_folder($(this));
35780          fn_check_selected_folder(dir_res['obj'],
35781            function()
35782            {
35783              var dir_row = document.createElement('div');
35784              // add input rows with obj (which is json object) and name (just string)
35785              $(document.createElement('input'))
35786              .attr({'type': 'hidden', 'name': 'obj_list[]', 'value' : $.toJSON(dir_res['obj']) }) 
35787              .appendTo(dir_row);
35788              $(document.createElement('input'))
35789              .attr({'type': 'hidden', 'name': 'name_list[]',  'value' : dir_res['name'] })
35790              .appendTo(dir_row);
35791              
35792              $('#synch_folder').append(dir_row);
35793              
35794              g_cmn.fn_working_overlay(true, "Saving...");
35795              $('#select_folder_form').submit();
35796            }
35797          );
35798          
35799       });
35800    }
35801  }
35802  
35803  var fn_check_selected_folder = function(obj, next_step)
35804  {
35805      g_cmn.fn_working_overlay(true, "Checking...");
35806      $.ajax({
35807        type: "POST",
35808        url: g_site_url + "synch_wizard/check_select_folder_ajax",
35809        dataType: "json",
35810        data: {
35811          "obj": $.toJSON(obj)
35812        },
35813        async: true,
35814        success: function(response){
35815          if (response.warning && response.warning.cancel_action == 'return_to_select_folder_dir') {
35816            g_cmn.fn_normal_dialog("Warning", response.warning.title, response.warning.body, {
35817              width: "950px",
35818              buttons: {
35819                "<< Go Back, Select Different Folder": function(){
35820                  $(this).dialog("close");
35821                  g_cmn.fn_working_overlay(false, "Working...");
35822                  window.location = response.warning.cancel_link;
35823                },
35824                "Sync Anyway": function(){
35825                  next_step();
35826                  $(this).dialog("close");
35827                }
35828              }
35829            });
35830          }
35831          else if (response.warning && response.warning.cancel_action == 'return_to_start') {
35832            g_cmn.fn_normal_dialog("Warning", response.warning.title, response.warning.body, {
35833              width: "950px",
35834              buttons: {
35835                "<< Go Back": function(){
35836                  $(this).dialog("close");
35837                  g_cmn.fn_working_overlay(false, "Working...");
35838                  window.location = response.warning.cancel_link;
35839                },
35840                "Sync Anyway": function(){
35841                  next_step();
35842                  $(this).dialog("close");
35843                }
35844              }
35845            });
35846          }
35847          else if (response.warning) {
35848            g_cmn.fn_normal_dialog("Warning", response.warning.title, response.warning.body, {
35849              width: "950px",
35850              buttons: {
35851                "Cancel, Try Different Folder": function(){
35852                  $(this).dialog("close");
35853                },
35854                "Sync Anyway": function(){
35855                  next_step();
35856                  $(this).dialog("close");
35857                }
35858              }
35859            });
35860          }
35861          else if (response.error && response.error.cancel_action == 'return_to_select_folder_dir') {
35862            g_cmn.fn_error_dialog_with_text("Error", response.error.title, response.error.body, {
35863              width: "950px",
35864              buttons: {
35865                "<< Go Back": function(){
35866                  $(this).dialog("close");
35867                  g_cmn.fn_working_overlay(false, "Working...");
35868                  window.location = response.error.cancel_link;
35869                },
35870                "Close": function() {
35871                  $(this).dialog("close");
35872                }
35873              }
35874            });
35875          }
35876          else if (response.notification) {
35877            g_cmn.fn_normal_dialog("Notification", response.notification.title, response.notification.body, {
35878              width: "950px",
35879              buttons: {
35880                "OK": function(){
35881                  next_step();
35882                  $(this).dialog("close");
35883                }
35884              }
35885            });
35886          }
35887          else if (response.error) {
35888            g_cmn.fn_error_dialog_with_text("Error", response.error.title, response.error.body, {
35889              width: "950px",
35890              buttons: {
35891                "Close": function(){
35892                  $(this).dialog("close");
35893                }
35894              }
35895            });
35896          }
35897          else
35898          {
35899            next_step();
35900          }
35901        },
35902        failure: function(response){
35903          next_step();
35904        }
35905      });
35906          
35907  }
35908
35909  var fn_check_selected_service = function(what, next_step)
35910  {
35911      g_cmn.fn_working_overlay(true, "Checking...");
35912      $.ajax({
35913        type: "POST",
35914        url: g_site_url + "synch_wizard/check_select_service_ajax",
35915        dataType: "json",
35916        data: {
35917          "what": $.toJSON(what)
35918        },
35919        async: true,
35920        success: function(response){
35921
35922          if (response.warning && response.warning.cancel_action == 'return_to_select_service') {
35923            g_cmn.fn_normal_dialog("Warning", response.warning.title, response.warning.body, {
35924              width: "950px",
35925              buttons: {
35926                "<< Go Back, Select Different Service": function(){
35927                  $(this).dialog("close");
35928                  g_cmn.fn_working_overlay(false, "Working...");
35929                  window.location = response.warning.cancel_link;
35930                },
35931                "Sync Anyway": function(){
35932                  next_step();
35933                  $(this).dialog("close");
35934                }
35935              }
35936            });
35937          }
35938          else if (response.error && response.error.cancel_action == 'return_to_start') {
35939            g_cmn.fn_error_dialog_with_text("Error", response.error.title, response.error.body, {
35940              width: "950px",
35941              buttons: {
35942                "<< Cancel Wizard": function(){
35943                  $(this).dialog("close");
35944                  g_cmn.fn_working_overlay(true, "Restarting...");
35945                  window.location = response.error.cancel_link;
35946                },
35947                "Try Different Service": function(){
35948                  g_cmn.fn_working_overlay(true, "Reloading...");
35949                  $(this).dialog("close");
35950                  window.location.reload(true);
35951                }
35952              },   
35953              close: function() {
35954                g_cmn.fn_working_overlay(true, "Reloading...");
35955                window.location.reload(true);
35956              }
35957            });
35958          }
35959          else if (response.error && response.error.cancel_action == "return_to_select_folder_dir") {
35960            g_cmn.fn_error_dialog_with_text("Error", response.error.title, response.error.body, {
35961              width: "950px",
35962              buttons: {
35963                "<< Go Back": function(){
35964                  $(this).dialog("close");
35965                  g_cmn.fn_working_overlay(false, "Checking...");
35966                  window.location = response.error.cancel_link;
35967                },
35968                "Try Different Service": function(){
35969                  g_cmn.fn_working_overlay(true, "Reloading...");
35970                  $(this).dialog("close");
35971                  window.location.reload(true);
35972                }
35973              },
35974              close: function() {
35975                g_cmn.fn_working_overlay(true, "Reloading...");
35976                window.location.reload(true);
35977              }
35978            });
35979          
35980          }
35981          else if (response.error) {
35982            g_cmn.fn_error_dialog_with_text("Error", response.error.title, response.error.body, {
35983              width: "950px",
35984              buttons: {
35985                "Try Different Service": function(){
35986                  g_cmn.fn_working_overlay(true, "Reloading...");
35987                  $(this).dialog("close");
35988                  window.location.reload(true);
35989                }
35990              },
35991              close: function() {
35992                g_cmn.fn_working_overlay(true, "Reloading...");
35993                window.location.reload(true);
35994              }
35995            });
35996          }
35997          else 
35998          {
35999            next_step();
36000          }
36001        },
36002        failure: function(response){
36003          next_step();
36004        }
36005      });
36006          
36007  }
36008
36009  var fn_get_selected_folder = function(folder_element)
36010  {
36011    var folder_element_id = folder_element.attr('id');
36012    var target_id = folder_element_id.split('_')[1];
36013    var target_obj = folder_element.data('jstree');
36014    
36015    var is_not_top_parent_id = true;
36016    var target_name = '';
36017    var i=0;
36018    while (is_not_top_parent_id)
36019    {
36020      if(i!=0)
36021        folder_element = $('#'+folder_element_id).parent().parent();
36022
36023      i++;
36024      folder_element_id = folder_element.attr('id');
36025      if (folder_element_id=='select_synch_jstree_container')
36026        is_not_top_parent_id = false;
36027      else
36028      {
36029        var d = folder_element.data('jstree');
36030        if (d) text = d['title_no_html'];
36031          text = text.replace('SugarSync Workspaces (', 'SugarSync (')
36032        if (target_name == '')
36033          target_name = text;
36034        else
36035          target_name = text  + " > " + target_name;
36036      }
36037    }
36038    return { id: target_id, obj: target_obj, name: target_name }
36039  }
36040 
36041  
36042}
36043
36044/**
36045 * @author Senad Dizdar
36046 * 
36047 * Copyright (C) 2010-2012, cloudHQ 
36048 * All rights reserved.
36049 *
36050 */
36051
36052function c_synch_new_wizard()
36053{
36054  /* private variables */
36055  
36056  /*********************************************/
36057  /* PUBLIC FUNCTIONS                         */
36058  /*********************************************/
36059  this.fn_init = function(service_what, service_email_or_login, logged_in)
36060  {
36061  }
36062}
36063/**
36064 * @author Senad Dizdar
36065 */
36066
36067function c_synch_wizard_setup_synch_to_central_cloud() {
36068  var self = this;
36069  var fbrowser = null;
36070  this.name = "c_replication";
36071  this.target_obj = null;
36072
36073  this.fn_init = function() {
36074   
36075    fbrowser = FileBrowser({
36076      fsParams : {
36077        call_for_backup : true
36078      },
36079      selectedObj: self.target_obj,
36080      onSelect : function(path, target_obj) {
36081        self.target_obj = target_obj;
36082        $('#target_dir_ref').val(target_obj.ref);
36083        $('#target_dir_what').val(target_obj.what);
36084        $('#target_dir_email_or_login').val(target_obj.email_or_login);
36085        var target_dir = path;
36086        var dir_name = target_dir.replace(/ +/g, " ");
36087        $('#target_dir_path').val(dir_name);
36088      }
36089    });
36090    fbrowser.create();
36091
36092    // reset target dir    
36093    $('#target_dir_ref').val('');
36094    $('#target_dir_what').val('');
36095    $('#target_dir_email_or_login').val('');
36096    
36097    // create steps
36098    $('.step-command').click(function() {
36099      var btn = $(this);
36100      var step = btn.attr('data-next');
36101      var validator = btn.attr('data-validator') || '';
36102
36103      if (validator && !step_validators[validator].call()) {
36104        return;
36105      }
36106
36107      stepInit(step);
36108
36109      $('.step').removeClass('active');
36110      $('.step.' + step).addClass('active');
36111    });
36112
36113    $('#service_list_checkbox_all').checkboxAll($('.service-list-checkbox'));
36114    $('#form_synch_wizard_setup_synch_to_central_cloud').submit(function() {
36115      try {
36116        g_cmn.fn_working_overlay(true, 'Starting configuration of synch pairs ...');
36117      } catch(er) {
36118      }
36119      $('#form_synch_wizard_setup_synch_to_central_cloud').submit();
36120    });
36121
36122    $('.service_checkbox').click(function(e) {
36123      if (!$(this).is(':checked')) {
36124        service_name = $(this).attr('service_name');
36125        service_email_or_login = $(this).attr('service_email_or_login');
36126        g_cmn.fn_normal_dialog("Confirmation", "Exclude " + service_name + " (" + service_email_or_login + ") from backup.<br/><br/>" + "Are you sure?", "", {
36127          width : "550px",
36128          buttons : {
36129            "No" : function() {
36130              try {
36131                g_cmn.fn_working_overlay(true, 'Reverting...');
36132              } catch(er) {
36133              }
36134              $(this).dialog("close");
36135              document.location.reload(true);
36136            },
36137            "Yes" : function() {
36138              try {
36139                g_cmn.fn_working_overlay(true, 'Saving...');
36140              } catch(er) {
36141              }
36142              $(this).dialog("close");
36143              document.save_backup_configs_form.submit();
36144              // use javascript to skip jQuery
36145            }
36146          }
36147        });
36148      } else {
36149        try {
36150          g_cmn.fn_working_overlay(true, 'Saving...');
36151        } catch(er) {
36152        }
36153        $(this).dialog("close");
36154        document.save_backup_configs_form.submit();
36155        // use javascript to skip jQuery
36156      }
36157
36158      return true;
36159    });
36160
36161    //disableRow();
36162  };
36163
36164  /*********************************************/
36165  /* PRIVATE FUNCTIONS                         */
36166  /*********************************************/
36167
36168  function stepInit(step) {
36169    if (step == 'step-3') {
36170      $('.text_number_of_sync_pairs').text($('.service-list-checkbox:checked').length);
36171      $('.text_destination_sync_folder').text(self.target_obj.path);
36172    }
36173  }
36174
36175  var step_validators = {
36176    'validate_services_selected' : function() {
36177      if ($('.service-list-checkbox:checked').length == 0) {
36178        g_cmn.fn_error_dialog("ERROR", "Please select at least one service!");
36179        return false;
36180      }
36181      return true;
36182    },
36183    'validate_folder_selected' : function() {
36184      if (!self.target_obj || !self.target_obj.ref || self.target_obj.ref == '') {
36185        g_cmn.fn_error_dialog("ERROR", "Please specify replication destination folder.");
36186        return false;
36187      }
36188      return true;
36189    }
36190  };
36191
36192  var disableRow = function() {
36193    var $tr = $("#table_services tr[data-rel='" + self.target_obj.what + "_" + self.target_obj.email_or_login + "']");
36194    $('#table_services tr').removeClass('disabled');
36195    $('#table_services input[type=checkbox]').removeAttr('disabled');
36196    $tr.addClass('disabled').find('input[type=checkbox]').attr('disabled', 'disabled');
36197  };
36198
36199}
36200
36201/**
36202 * @author Senad Dizdar
36203 */
36204
36205function c_support_us()
36206{
36207  this.name = "c_support_us";
36208  
36209  this.fn_init = function()
36210  {
36211  }
36212  
36213}
36214/**
36215 * @author Senad Dizdar
36216 * 
36217 * Copyright (C) 2010-2011, cloudHQ 
36218 * All rights reserved.
36219 *
36220 */
36221
36222 $.fn.serializeObject = function()
36223{
36224    var o = {};
36225    var a = this.serializeArray();
36226    $.each(a, function() {
36227        if (o[this.name] !== undefined) {
36228            if (!o[this.name].push) {
36229                o[this.name] = [o[this.name]];
36230            }
36231            o[this.name].push(this.value || '');
36232        } else {
36233            o[this.name] = this.value || '';
36234        }
36235    });
36236    return o;
36237};
36238
36239function c_system_report()
36240{
36241  
36242  /*********************************************/
36243  /* PUBLIC FUNCTIONS                         */
36244  /*********************************************/
36245  this.fn_init = function()
36246  {
36247    $('.utc_time').each(function(i, el) {
36248      var tagText = $(el).html();
36249      var givenDate = Date($.format.date(tagText, ""));
36250      if ((givenDate + "") == 'Invalid Date')
36251        givenDate = tagText;
36252      $(el).html(' ' + givenDate);
36253    });
36254    
36255    $('[type="image"]').live('click', function(e){
36256      var $form = $(this).parents('form');
36257      $form.data('what',$(this).attr('name'));
36258      $form.data('how', $(this).attr('value'));
36259    });
36260    
36261    $('[type="submit"]').live('click', function(e){
36262      var $form = $(this).parents('form');
36263      $form.data('what',$(this).attr('what'));
36264      $form.data('how', $(this).attr('how'));
36265    });
36266
36267    $("#modify_conflicts_form, #delete_conflicts_form, #retry_conflicts_form, #not_supported_conflicts_form").bind("submit", 
36268      function() 
36269      { 
36270        if ($(this).find(':checkbox:checked').length == 0)
36271        {
36272           g_cmn.fn_error_dialog("ERROR", "Use the checkboxes to select one or more items.", { width: "550px" });
36273           return false;
36274        }
36275        else
36276        {
36277          var checkbox_list = $(this).find(':checkbox[name="id_list[]"]:checked');
36278          var id_list = [];
36279          $.each(checkbox_list, function() { 
36280            id_list.push(this.value);
36281          });
36282          var what = $(this).data('what');
36283          var how  = $(this).data('how');
36284          
36285          // TODO: Add dialog to display confirmation
36286          fn_resolve_conflict_ajax(what, how, id_list);
36287          
36288        }
36289        return false; 
36290      }
36291    );
36292    
36293    $('.select_all').click(function () {
36294      $(this).parents('fieldset:eq(0)').find(':checkbox').filter(':not(:disabled)').attr('checked', this.checked);
36295    });
36296  
36297    $(".modify_conflicts_details, .non_supported_conflicts_details, .delete_conflicts_details").bind("click", function(ev) {
36298      var $t = $(ev.target);
36299      var text = $('#reason_' + $t.attr('id')).html();
36300      g_cmn.fn_normal_dialog("Details", "", text,
36301        {
36302          width: "950px",
36303          buttons: {
36304            "OK": function(){
36305              $(this).dialog("close");
36306            }
36307          }
36308        } 
36309      );
36310      return false;
36311    });
36312
36313  }
36314  /***
36315   * send ajax request to resolve conflicts
36316   * @param {String} what    what is operation
36317   * @param {String} how     how to fix it
36318   * @param {List}   id_list list of ids of conflict records
36319   */
36320  var fn_resolve_conflict_ajax = function(what, how, id_list)
36321  {
36322    
36323    g_cmn.fn_notif_win(true, "Working..."); 
36324    g_cmn.fn_working_overlay(); 
36325    
36326    
36327    // alert('what='+$(this).data('what'));
36328    // alert('how='+$(this).data('how'))
36329    // alert( $.toJSON(id_list));
36330    $.ajax(
36331      {
36332        type: "POST",
36333        url: g_site_url + "main_system_report/resolve_conflict",
36334        dataType: "json",
36335        data: {
36336          "id_list": $.toJSON(id_list),
36337          "what":    $.toJSON(what),
36338          "how":     $.toJSON(how)
36339        },
36340        async: true,
36341        success: function(response) {
36342          g_cmn.fn_working_overlay(false); 
36343          g_cmn.fn_notif_win(false);
36344          if (response.error) {
36345            g_cmn.fn_error_dialog("ERROR", response.error, {
36346              width: "370px",
36347              close: function() { location.reload(true); } 
36348            });
36349          }
36350          else if (response.long_running_operation) {
36351            g_cmn.fn_notif_win(false, "Job started", 1000);
36352            g_cmn.fn_normal_dialog("Operation started in background", "", "We started a background job.<br/><br/>You will receive an email when the job finishes.", {
36353              width: "650px",
36354              close: function() { location.reload(true); } 
36355            });
36356          }
36357          else {
36358            g_cmn.fn_notif_win(false, response.message, 1000);
36359            location.reload(true); 
36360          }
36361        }
36362      }
36363    );    
36364    
36365  }
36366  
36367  
36368}
36369
36370/**
36371 * @author Senad Dizdar
36372 * 
36373 * Copyright (C) 2010-2011, cloudHQ 
36374 * All rights reserved.
36375 *
36376 */
36377
36378 
36379function c_account()
36380{
36381  
36382  /*********************************************/
36383  /* PUBLIC FUNCTIONS                         */
36384  /*********************************************/
36385  this.fn_init = function(){
36386  
36387    $('#downgrade_premium_beta').unbind("click").bind('click', function(){
36388      no_need_to_downgrade_dialog.dialog('open');
36389    });
36390    
36391    
36392  }
36393  
36394    var no_need_to_downgrade_dialog = $('#no_need_to_downgrade_dialog').dialog({
36395      autoOpen: false, resizable: false, width: 510, title: "Downgrade Service",
36396      modal: true,
36397      buttons: {
36398        "OK": function() {
36399          $(this).dialog("close"); 
36400        }
36401      }
36402    });
36403  
36404}
36405/**
36406 * @author Senad Dizdar
36407 */
36408
36409function c_synch_template_configs()
36410{
36411  this.name = "c_synch_template_configs";
36412  
36413  this.fn_init = function()
36414  {
36415
36416    $('.delete_button').unbind('click').bind('click', function() {
36417      var $t = $(this);
36418      g_cmn.fn_normal_dialog("Confirmation", "Are you sure?", "", 
36419        { width: "350px", buttons: {
36420          "No": function() {
36421            $(this).dialog("close"); 
36422          },
36423          "Yes": function() {
36424            $t.parent('form').submit();
36425            $(this).dialog("close"); 
36426          }
36427        }
36428      });
36429      return false;
36430    });
36431
36432    fn_set_upload_convert_policy();
36433    $('.synch_template_configs_can_be_edited #services_service1_id').change(function() {
36434      fn_set_upload_convert_policy();
36435    });
36436    $('.synch_template_configs_can_be_edited #services_service2_id').change(function() {
36437      fn_set_upload_convert_policy();
36438    });
36439
36440    fn_set_is_one_way_synch_enabled();
36441    $('.synch_template_configs_can_be_edited #synch_template_config_is_one_way_synch_enabled').change(function() {
36442      fn_set_is_one_way_synch_enabled();
36443    });
36444
36445
36446  }
36447  
36448  /* PRIVATE FUNCTIONS */
36449  var fn_set_upload_convert_policy = function()
36450  {
36451    services_service1_id_val = $('.synch_template_configs_can_be_edited #services_service1_id').val();
36452    services_service2_id_val = $('.synch_template_configs_can_be_edited #services_service2_id').val();
36453    services_service1_id_text = $(".synch_template_configs_can_be_edited #services_service1_id option[value='" + services_service1_id_val +"']").text();
36454    services_service2_id_text = $(".synch_template_configs_can_be_edited #services_service2_id option[value='" + services_service2_id_val +"']").text();
36455
36456    if (services_service1_id_text.match(/Google Docs/) ||  services_service2_id_text.match(/Google Docs/)) {
36457      $('.synch_template_configs_can_be_edited #synch_template_config_upload_convert_policy').removeAttr('disabled');
36458      $(".synch_template_configs_can_be_edited label[for='synch_template_config_upload_convert_policy']").removeClass('ui-state-disabled');
36459    }
36460    else {
36461      $('.synch_template_configs_can_be_edited #synch_template_config_upload_convert_policy').attr('disabled', true);
36462      $(".synch_template_configs_can_be_edited label[for='synch_template_config_upload_convert_policy']").addClass('ui-state-disabled');
36463    }
36464
36465  }
36466
36467  var fn_set_is_one_way_synch_enabled = function()
36468  {
36469    if ($('.synch_template_configs_can_be_edited #synch_template_config_is_one_way_synch_enabled').is(':checked')) {
36470      $('.synch_template_configs_can_be_edited #synch_template_config_overwrite_modify_of_target').removeAttr('disabled');
36471      $(".synch_template_configs_can_be_edited label[for='synch_template_config_overwrite_modify_of_target']").removeClass('ui-state-disabled');
36472    }
36473    else {
36474      $('.synch_template_configs_can_be_edited #synch_template_config_overwrite_modify_of_target').attr('disabled', true);
36475      $(".synch_template_configs_can_be_edited label[for='synch_template_config_overwrite_modify_of_target']").addClass('ui-state-disabled');
36476    }
36477  }
36478    
36479}
36480/**
36481 * @author Senad Dizdar
36482 */
36483
36484function c_synch_exclude_configs()
36485{
36486  this.fn_init = function()
36487  {
36488    $('.delete_button').unbind('click').bind('click', function() {
36489      g_cmn.fn_working_overlay(false, "");
36490    });
36491
36492  }
36493    
36494}
36495var FileBrowser = function(param) {
36496  
36497  var selectedObj = null;
36498  var selectedPath = null;
36499  
36500  var options = $.extend({
36501    selectedObj: null,
36502    onSelect: function(path, obj) {},
36503    fsParams: {
36504      is_bcx_evernote_integration: false,
36505      is_bcx_simple_view: false,
36506      call_for_backup: false
36507    }
36508  }, param || {}); 
36509  
36510  function create() {
36511    fn_init_jstree();
36512  }
36513  
36514  function enable(enable) {
36515    var container = $('#select_synch_jstree_container').parent();
36516    container.css('position', 'relative');
36517    container.find('.jstree_mask').remove();
36518    if(enable == false) {
36519      var div = $('<div class="jstree_mask" style="background:#fff;position:absolute;top:0;left:0;right:0;bottom:0"> </div>');
36520      div.css('opacity', 0.4); 
36521      container.append(div);
36522    }
36523  }
36524  
36525  function getSelectedPath() {
36526    return selectedPath;
36527  }
36528  
36529  function getSelectedObj() {
36530    return selectedObj;
36531  }
36532 
36533  /***
36534   * Initialize jstree inside dialog
36535   * @param {Object} service
36536   */
36537  var fn_init_jstree = function() {
36538    
36539    // call server to intilize
36540    $.ajax({
36541      type : "GET",
36542      url : g_site_url + "main_cloud_fs_interface/cloudhq_init",
36543      dataType : "json",
36544      data : options.fsParams,
36545      async : true,
36546      success : function(response) {
36547        if (response.error) {
36548          g_cmn.fn_error_dialog("ERROR", "Sorry, a temporary error has occurred. <br/>Please try again.", {
36549            width : "550px"
36550          });
36551        } else {
36552          fn_display_jstree(response);
36553        }
36554        var node = $("#select_synch_jstree_container ul li");
36555        if (node.length == 1) {
36556          $("#select_synch_jstree_container").jstree("open_node", node.first());
36557        }
36558      },
36559      failure : function(response) {
36560        g_cmn.fn_error_dialog("ERROR", "Sorry, a temporary error has occurred. <br/>Please try again.", {
36561          width : "550px"
36562        });
36563      }
36564    });
36565    
36566    var new_folder_dialog = $("#new_folder_dialog").dialog({
36567      autoOpen : false,
36568      resizable : false,
36569      width : 805,
36570      height : 255,
36571      title : 'Create folder',
36572      modal : true,
36573      buttons : {
36574        "Cancel" : function() {
36575          $(this).dialog("close");
36576        },
36577        "Create" : function() {
36578          var folder_name = $('#folder_name').val();
36579          if (folder_name == '')
36580            g_cmn.fn_error_dialog("", "Please enter folder name");
36581          else {
36582            g_cmn.fn_working_overlay(true, "Creating folder...");
36583            d_parent_folder_obj_data = getSelectedObj();
36584            d_is_bcx_evernote_integration = options.fsParams.is_bcx_evernote_integration;
36585
36586            $.ajax({
36587              type : "POST",
36588              url : g_site_url + "main_cloud_fs_interface/new_dir",
36589              dataType : "json",
36590              data : {
36591                "obj" : $.toJSON(d_parent_folder_obj_data),
36592                "folder_name" : $.toJSON(folder_name),
36593                "is_bcx_evernote_integration" : $.toJSON(d_is_bcx_evernote_integration),
36594              },
36595              async : true,
36596              success : function(response) {
36597                if (response.error) {
36598                  g_cmn.fn_working_overlay(false, null);
36599                  g_cmn.fn_error_dialog("Error during folder creation", response.error);
36600                  // g_cmn.fn_notif_win(true, "Folder creation failed.<br\>" + response.error , 5000);
36601                } else {
36602                  g_cmn.fn_notif_win(true, "Folder created", 5000);
36603                  fn_refresh_server(null, 'new_dir');
36604                }
36605              },
36606              failure : function(response) {
36607                g_cmn.fn_working_overlay(false, null);
36608                alert("Failure");
36609              }
36610            });
36611            $(this).dialog("close");
36612          }
36613        }
36614      }
36615    }); 
36616
36617    $('#new_folder_button').unbind("click").bind('click', function(){
36618    
36619      var parent_folder_obj = getSelectedObj();
36620      if (parent_folder_obj == null) {
36621        g_cmn.fn_error_dialog("ERROR", "Nothing selected. Please select a parent folder.", {
36622          width: "550px"
36623        });
36624        return;
36625      }
36626
36627      if (parent_folder_obj['is_folder_create_disabled'] == true ) {
36628        g_cmn.fn_error_dialog("ERROR", "The parent is read-only.", {
36629          width: "550px"
36630        });
36631        return;
36632      }
36633
36634      if (parent_folder_obj['nice_path']) {
36635        $('#dialog_header_container_dir1_what').html(parent_folder_obj['nice_path'])
36636      } else {
36637        $('#dialog_header_container_dir1_what').html(parent_folder_obj['path']);
36638      }
36639      new_folder_dialog.dialog('open');
36640    });
36641    
36642    
36643  };
36644  
36645  /***
36646   * fn_display_jstree: display jstree.
36647   * response:     data received from cloudhq_init
36648   */
36649  var fn_display_jstree = function(response) {
36650    $(function() {
36651      var container = $('#select_synch_jstree_container');
36652      container.jstree("destroy").css('position', 'relative');
36653      container.bind('load_node.jstree', function(event, data) {
36654        // alert("reopen");
36655      }).jstree({
36656        "core" : {
36657          html_titles : true
36658        },
36659        "json_data" : {
36660          "correct_state" : true,
36661          "data" : response,
36662          "ajax" : {
36663            "url" : function(n) {
36664              if (n == -1)
36665                return false;
36666              else {
36667                g_cmn.fn_notif_win(true, "Loading...", null);
36668                return g_site_url + "main_cloud_fs_interface/cloudhq_dir";
36669              }
36670            },
36671            "success" : function(obj, t, x) {
36672              $('#loading').css('display', 'none');
36673              if (t == "success") {
36674                var response = JSON.parse(x.responseText);
36675                if (response['error'])
36676                  g_cmn.fn_notif_win(true, "Something went wrong... <br>Please refresh the page .", 5000);
36677                else
36678                  g_cmn.fn_notif_win(false, "", null);
36679              } else {
36680                g_cmn.fn_notif_win(false, "", null);
36681              }
36682            },
36683            "error" : function(obj) {
36684              g_cmn.fn_notif_win(true, "Something went wrong... <br>Please refresh the page.", 5000);
36685            },
36686            "data" : function(obj) {
36687              return {
36688                "obj" : $.toJSON(obj.data('jstree')),
36689                "file_flag" : $.toJSON(false),
36690                "is_bcx_evernote_integration" : $.toJSON(options.fsParams.is_bcx_evernote_integration),
36691                "is_bcx_simple_view" : $.toJSON(options.fsParams.is_bcx_simple_view),
36692                "without_imap": $.toJSON(options.fsParams.without_imap)
36693              };
36694            }
36695          }
36696        },
36697        "contextmenu" : {
36698          "items" : function(node) {
36699          } // end function
36700        },
36701        "themes" : {
36702          "theme" : "cloudhq",
36703          "dots" : false,
36704          "icons" : true
36705        },
36706        "plugins" : ["themes", "json_data", "ui", "crrm", "types"]
36707      });
36708
36709    });
36710
36711    $("#select_synch_jstree_container").bind("select_node.jstree", function(e, data) {
36712      $("#select_synch_jstree_container").jstree('open_node', data.rslt.obj);
36713      /* now update */
36714      $('#what_selected_container .what_selected_nothing').hide();
36715      $('#what_selected_container .what_selected_something').show();
36716      var max_path_length = 85;
36717
36718      var obj = data.rslt.obj.data('jstree');
36719      var path = obj['path'];
36720      var short_path = obj['short_path'];
36721      var shorthen_path = path;
36722
36723      var service_what = data.rslt.obj.data('jstree')['what'];
36724      var service_email_or_login = data.rslt.obj.data('jstree')['email_or_login'];
36725
36726      if (shorthen_path.length > max_path_length) {
36727        var filename = shorthen_path.replace(/^.*[\\\/]/, '');
36728        if (filename == '') {// no file at all
36729          shorthen_path = shorthen_path.substring(0, max_path_length - 3) + '...';
36730        } else {
36731          if (filename.length > max_path_length) {// there is file but too long
36732            shorthen_path = filename.substring(0, max_path_length - 3) + '...';
36733          } else {
36734            var dirname = shorthen_path.replace(/\\/g, '/').replace(/\/[^\/]*$/, '');
36735            var max_dirname_length = max_path_length - filename.length - 1;
36736            if (max_dirname_length > 3) {
36737              dirname = dirname.substring(0, max_dirname_length - 3) + '...';
36738              shorthen_path = dirname + "/" + filename;
36739            } else {
36740              shorthen_path = filename;
36741            }
36742          }
36743        }
36744      }
36745
36746      $('#what_selected_container .what_selected_something .what_selected_something_value').html(shorthen_path);
36747
36748      $('#what_selected_container .what_selected_something .what_selected_something_value_service_what').html(service_what);
36749      $('#what_selected_container .what_selected_something .what_selected_something_value_service_email_or_login').html(service_email_or_login);
36750      $('#what_selected_container .what_selected_something .what_selected_something_value_short_path').html(short_path);
36751
36752      selectedObj  = obj;
36753      selectedPath = path;
36754      
36755      options.onSelect(selectedPath, selectedObj);
36756      
36757      // now rename buttons
36758      var child_obj_type_user_friendly_name = obj['child_obj_type_user_friendly_name'];
36759      if (child_obj_type_user_friendly_name != null) {
36760        $(".child_obj_type_user_friendly_name").html(child_obj_type_user_friendly_name);
36761      }
36762
36763      var is_folder_create_disabled = obj['is_folder_create_disabled'];
36764      if (is_folder_create_disabled) {
36765        $('#new_folder_button').attr('disabled', 'disabled');
36766      } else {
36767        $('#new_folder_button').removeAttr('disabled');
36768      }
36769
36770    });
36771
36772  };
36773  
36774
36775  /***
36776   * Function used to refresh the tree on calling when click on refresh button
36777   * operation of copy , move, delete and new folder .
36778   * @param {Object} dir_id
36779   */
36780  var fn_refresh_server = function fn_refresh_server(obj, operation) {
36781    var d = null;
36782    if (obj)
36783      d = {
36784        "obj" : $.toJSON(obj)
36785      };
36786
36787    g_cmn.fn_notif_win(true, "Refreshing...", null);
36788    $.ajax({
36789      type : "POST",
36790      url : g_site_url + "main_cloud_fs_interface/refresh_cloudhq_dir",
36791      dataType : "json",
36792      data : d,
36793      async : true,
36794      success : function(response) {
36795        if (response.error) {
36796          g_cmn.fn_notif_win(false, "", null);
36797        } else {
36798          // we can just count number of open nodes in left tree and decrement them in event on 'select_node.jstree'
36799          $("#select_synch_jstree_container").jstree('refresh');
36800          g_cmn.fn_working_overlay(false, null);
36801        }
36802      },
36803      failure : function(response) {
36804        g_cmn.fn_working_overlay(false, null);
36805        alert("Failure");
36806      }
36807    });
36808  };
36809
36810  
36811  /* Return object public methods */
36812  return {
36813    create: create,
36814    enable: enable,
36815    getSelectedPath: getSelectedPath,
36816    getSelectedObj: getSelectedObj
36817  };
36818
36819};
36820
36821/**
36822 * @author Senad Dizdar
36823 * 
36824 * Copyright (C) 2010-2011, cloudHQ 
36825 * All rights reserved.
36826 *
36827 */
36828
36829function c_cmn() // stands for Class_CoMmoN
36830{
36831  this.fn_init = function()
36832  {
36833    fn_resize_areas();
36834
36835    try {
36836      $(window).load(function(){
36837        fn_resize_areas();
36838      });
36839    } catch(e) { 
36840    }
36841    $(window).resize(function() {
36842       fn_resize_areas();
36843    }); 
36844    
36845    $('#report_a_bug, #report_a_problem').bind('click', function() { UserVoice.Popin.show(uservoiceBugOptions); return false; } );
36846    
36847    $('input.working_link').unbind('click').bind('click', function() {      
36848      if ($(this).hasClass('noclick')) {
36849        return false;
36850      }
36851      var text = "Working...";
36852      if ($(this).attr('notif_to_display') != null)
36853        text = $(this).attr('notif_to_display');
36854      try { g_cmn.fn_working_overlay(true, text); } catch(er)  { }
36855      return true;
36856    });
36857    
36858    $('a.working_link').unbind('click').bind('click', function() {
36859      if ($(this).hasClass('noclick')) {
36860        return false;
36861      }
36862      var text = "Working...";
36863      if ($(this).attr('notif_to_display') != null)
36864        text = $(this).attr('notif_to_display');
36865      try { g_cmn.fn_working_overlay(true, text); } catch(er)  { }
36866      return true;
36867    });
36868    
36869    $('button.working_link').unbind('click').bind('click', function() {
36870      if ($(this).hasClass('noclick')) {
36871        return false;
36872      }
36873      var text = "Working...";
36874      if ($(this).attr('notif_to_display') != null)
36875        text = $(this).attr('notif_to_display');
36876      try { g_cmn.fn_working_overlay(true, text); } catch(er)  { }
36877      return true;
36878    });
36879  }
36880
36881  /***
36882   * @param ref:     link to a window with all paramters
36883   * @param name:    name of the window
36884   * @param options: options of the window
36885  */
36886  this.fn_open_window = function(rel, name, options)
36887  {
36888    var pop_up_title = name;
36889    if ($.browser.msie)
36890      pop_up_title = pop_up_title.replace(' ', '_');
36891
36892    if($.browser.msie)
36893    {
36894      window.open(rel, '', options);
36895    }
36896    else
36897    {
36898      var newwindow = window.open(rel, name, options);
36899      if (window.focus && newwindow)
36900      {
36901        newwindow.focus()
36902      }
36903    }
36904    
36905  }
36906
36907
36908  /***
36909   * @param level:  fatal, debug, etc.
36910   * @param message: message to log
36911  */
36912  this.fn_log = function(level, message)
36913  {
36914    // see: https://github.com/emwendelin/javascript-stacktrace
36915    var stacktrace = null;
36916    if (level == 'ERROR')
36917       stacktrace = printStackTrace();
36918    $.ajax({
36919      type: "GET",
36920      url: g_site_url + "logger/ajax_message",
36921      dataType: "json",
36922      data: { 
36923               'level': $.toJSON(level), 
36924               'message': $.toJSON(message),
36925               'stacktrace': $.toJSON(stacktrace) 
36926            },
36927      async: true,
36928      success: function(response){}
36929     });
36930  }
36931  
36932  /***
36933   * @param display_flag: true or false - if false then we will hide notification
36934   * @param message: text to display - only needed if display_flag is true. The text to display. 
36935   * @param display_timeout: optional parameter. If set then notification will disappear after specified number of seconds.
36936  */
36937  this.fn_notif_win = function(display_flag, message, display_timeout)
36938  {
36939    $("#notif_win_msg_content span").html(message);
36940    if (display_flag == true)
36941    {
36942      $('#notif_win_msg').show();
36943      if (display_timeout != null)
36944      {
36945        setTimeout(function() {
36946          $("#notif_win_msg").hide();
36947        }, display_timeout);
36948      }
36949    }
36950    else
36951      $('#notif_win_msg').hide();
36952  }
36953
36954  this.fn_cleanup_text = function(text)
36955  { 
36956
36957    text = text.replace(/</g,'__OPEN__').replace(/>/g, '__CLOSE__');
36958    text = text.replace(/__OPEN__b__CLOSE__/g, '<b>');
36959    text = text.replace(/__OPEN__\/b__CLOSE__/g, '</b>');
36960    text = text.replace(/__OPEN__i__CLOSE__/g, '<i>');
36961    text = text.replace(/__OPEN__\/i__CLOSE__/g, '</i>');
36962    text = text.replace(/__OPEN__p__CLOSE__/g, '<p>');
36963    text = text.replace(/__OPEN__\/p__CLOSE__/g, '</p>');
36964    text = text.replace(/__OPEN__ol/g, '<ol');
36965    text = text.replace(/__OPEN__\/ol__CLOSE__/g, '</ol>');
36966    text = text.replace(/__OPEN__ul/g, '<ul');
36967    text = text.replace(/__OPEN__\/ul__CLOSE__/g, '</ul>');
36968    text = text.replace(/__OPEN__li/g, '<li');
36969    text = text.replace(/__OPEN__\/li__CLOSE__/g, '</li>');
36970    text = text.replace(/__OPEN__small/g, '<small');
36971    text = text.replace(/__OPEN__center__CLOSE__/g, '<center>');
36972    text = text.replace(/__OPEN__\/center__CLOSE__/g, '</center>');
36973    text = text.replace(/__OPEN__b__CLOSE__/g, '<b>');
36974    text = text.replace(/__OPEN__\/b__CLOSE__/g, '</b>');
36975    text = text.replace(/__OPEN__\/small__CLOSE__/g, '</small>');
36976    text = text.replace(/__OPEN__span/g, '<span');
36977    text = text.replace(/__OPEN__\/span__CLOSE__/g, '</span>');
36978    text = text.replace(/__OPEN__a/g, '<a');
36979    text = text.replace(/__OPEN__\/a__CLOSE__/g, '</a>');
36980    text = text.replace(/__OPEN__u/g, '<u');
36981    text = text.replace(/__OPEN__\/u__CLOSE__/g, '</u>');
36982    text = text.replace(/__OPEN__br\/__CLOSE__/g, '<br/>');
36983    text = text.replace(/__OPEN__br__CLOSE__/g, '<br>');
36984    text = text.replace(/__OPEN__td/g, '<td');
36985    text = text.replace(/__OPEN__\/td__CLOSE__/g, '</td>');
36986    text = text.replace(/__OPEN__tr/g, '<tr');
36987    text = text.replace(/__OPEN__\/tr__CLOSE__/g, '</tr>');
36988    text = text.replace(/__OPEN__table/g, '<table');
36989    text = text.replace(/__OPEN__\/table__CLOSE__/g, '</table>');
36990    text = text.replace(/__OPEN__tbody/g, '<tbody');
36991    text = text.replace(/__OPEN__\/tbody__CLOSE__/g, '</tbody>');
36992    text = text.replace(/__OPEN__/g,' ').replace(/__CLOSE__/g, '>');
36993
36994    return text
36995  }
36996  /**
36997   * display error dialog
36998   * @param {string} text text to display
36999   * @param {string} title title of the dialog
37000   * @return {string} Nothing
37001   */
37002  this.fn_error_dialog = function(title, text, settings)
37003  {
37004    var defaults = {
37005      autoOpen: true,
37006      resizable: true,
37007      width: 500,
37008      /* height: 170,*/
37009      title: title,
37010      dialogClass: "operation_error",
37011      modal: true
37012    };
37013    settings = $.extend(true, {}, defaults, settings);
37014    
37015    g_cmn.fn_working_overlay(false, "");
37016
37017    // we replace :
37018    // {small} ... __small__ to <small>.. </small>
37019    // {a} ... __a__ to <a> ... </a>
37020    // {br}
37021    text = g_cmn.fn_cleanup_text(text);
37022
37023    $('#error_dialog .dialog_header_container').html(text);
37024    $("#error_dialog").dialog('destroy').dialog(settings);
37025    
37026  }
37027  
37028  /**
37029   * display error dialog
37030   * @param {string} text text to display
37031   * @param {string} title title of the dialog
37032   * @return {string} Nothing
37033   */
37034  this.fn_error_dialog_with_text = function(title, header_text, body_text, settings)
37035  {
37036    header_text = g_cmn.fn_cleanup_text(header_text);
37037    body_text = g_cmn.fn_cleanup_text(body_text);
37038    
37039    var defaults = {
37040      autoOpen: true,
37041      resizable: true,
37042      /* width: 200,*/
37043      /* height: 170,*/
37044      title: title,
37045      dialogClass: "operation_error",
37046      modal: true
37047    };
37048    settings = $.extend(true, {}, defaults, settings);
37049    $('#normal_dialog .dialog_header_container').html(header_text);
37050    
37051    g_cmn.fn_working_overlay(false, "");
37052    $('#normal_dialog .dialog_body_container').html(body_text);
37053    $("#normal_dialog").dialog('destroy').dialog(settings);  
37054  }
37055  
37056
37057  /**
37058   * display normal dialog
37059   * @param {string} text text to display
37060   * @param {string} title title of the dialog
37061   * @return {string} Nothing
37062   */
37063  this.fn_normal_dialog = function(title, header_text, body_text, settings)
37064  {
37065    header_text = g_cmn.fn_cleanup_text(header_text);
37066    body_text = g_cmn.fn_cleanup_text(body_text);
37067    
37068    var defaults = {
37069      autoOpen: true,
37070      resizable: true,
37071      /* width: 200,*/
37072      /* height: 170,*/
37073      title: title,
37074      modal: true
37075    };
37076    settings = $.extend(true, {}, defaults, settings);
37077    $('#normal_dialog .dialog_header_container').html(header_text);
37078    
37079    g_cmn.fn_working_overlay(false, "");
37080    $('#normal_dialog .dialog_body_container').html(body_text);
37081    $("#normal_dialog").dialog('destroy').dialog(settings);
37082  }
37083  
37084  /**
37085   * display overlay
37086   * @param {boolean} mode if false then close
37087   */
37088  this.fn_working_overlay = function(mode, message)
37089  {
37090    if (mode == false) {
37091      $('#full_win_working_overlay').hide();
37092      this.fn_notif_win(false);
37093    }
37094    else {
37095      $('#full_win_working_overlay').show();
37096      if (message) this.fn_notif_win(true, message);
37097    }
37098  }
37099
37100  /**
37101   * @private
37102   */ 
37103  var fn_resize_areas = function()
37104  {
37105    /*$('body').height($(window).height());
37106    $('.footer').css('display', 'inline-block');
37107    var min_h = $('.main_content_container').height() + $('.main_content_container').offset().top;
37108    var h = $('body').height() - $('.footer').height() - 9;
37109    $('.main-wrapper').height(Math.max(min_h, h));
37110    $('.main-outer-wrapper').height(Math.max(min_h, h));*/
37111  }
37112
37113};
37114
37115window.date_format = (function() {
37116
37117  var MONTH_NAMES = [
37118    'January', 
37119    'February', 
37120    'March', 
37121    'April', 
37122    'May', 
37123    'June',
37124    'July', 
37125    'August', 
37126    'September', 
37127    'October', 
37128    'November', 
37129    'December'
37130  ];
37131  
37132  function get_formatted_date(date, prefomattedDate = false, hideYear = false) {
37133    const day = date.getDate();
37134    const month = MONTH_NAMES[date.getMonth()];
37135    const year = date.getFullYear();
37136    const hours = date.getHours();
37137    let minutes = date.getMinutes();
37138  
37139    if (minutes < 10) {
37140      // Adding leading zero to minutes
37141      minutes = `0${ minutes }`;
37142    }
37143  
37144    if (prefomattedDate) {
37145      // Today at 10:20
37146      // Yesterday at 10:20
37147      return `${ prefomattedDate } at ${ hours }:${ minutes }`;
37148    }
37149  
37150    if (hideYear) {
37151      // 10. January at 10:20
37152      return `${ day }. ${ month } at ${ hours }:${ minutes }`;
37153    }
37154  
37155    // 10. January 2017. at 10:20
37156    return `${ day }. ${ month } ${ year }. at ${ hours }:${ minutes }`;
37157  }
37158
37159  var self = {};
37160
37161  self.track_time_ago = function(element, options) {
37162
37163    options = $.extend({
37164      date: new Date(),
37165      interval: 15000
37166    }, options || {});
37167
37168    var $element = $(element);
37169
37170    var tick = function() {
37171      var text = date_format.time_ago(options.date).toLowerCase();
37172      $element.text(text);
37173    }
37174
37175    window.setInterval(tick, options.interval);
37176
37177    tick();
37178
37179    return $element;
37180
37181  };
37182
37183  self.time_ago = function(dateParam) {
37184
37185    if (!dateParam) {
37186      return null;
37187    }
37188
37189    const date = typeof dateParam === 'object' ? dateParam : new Date(dateParam);
37190    const DAY_IN_MS = 86400000; // 24 * 60 * 60 * 1000
37191    const today = new Date();
37192    const yesterday = new Date(today - DAY_IN_MS);
37193    const seconds = Math.round((today - date) / 1000);
37194    const minutes = Math.round(seconds / 60);
37195    const isToday = today.toDateString() === date.toDateString();
37196    const isYesterday = yesterday.toDateString() === date.toDateString();
37197    const isThisYear = today.getFullYear() === date.getFullYear();
37198
37199
37200    if (seconds < 5) {
37201      return 'now';
37202    } else if (seconds < 60) {
37203      return `${ seconds } seconds ago`;
37204    } else if (seconds < 90) {
37205      return 'about a minute ago';
37206    } else if (minutes < 60) {
37207      return `${ minutes } minutes ago`;
37208    } else if (isToday) {
37209      return get_formatted_date(date, 'Today'); // Today at 10:20
37210    } else if (isYesterday) {
37211      return get_formatted_date(date, 'Yesterday'); // Yesterday at 10:20
37212    } else if (isThisYear) {
37213      return get_formatted_date(date, false, true); // 10. January at 10:20
37214    }
37215
37216    return get_formatted_date(date); // 10. January 2017. at 10:20
37217  }
37218
37219  return self;
37220
37221})();
37222
37223window.c_ext = (function() {
37224
37225  function fn_is_chrome() {
37226    // please note, 
37227    // that IE11 now returns undefined again for window.chrome
37228    // and new Opera 30 outputs true for window.chrome
37229    // but needs to check if window.opr is not undefined
37230    // and new IE Edge outputs to true now for window.chrome
37231    // and if not iOS Chrome check
37232    // so use the below updated condition
37233    var isChromium = window.chrome;
37234    var winNav = window.navigator;
37235    var vendorName = winNav.vendor;
37236    var isOpera = typeof window.opr !== "undefined";
37237    var isIEedge = winNav.userAgent.indexOf("Edge") > -1;
37238    var isIOSChrome = winNav.userAgent.match("CriOS");
37239
37240    if (isIOSChrome) {
37241      return false;
37242    } else if(
37243      isChromium !== null &&
37244      typeof isChromium !== "undefined" &&
37245      vendorName === "Google Inc." &&
37246      isOpera === false &&
37247      isIEedge === false
37248    ) {
37249      return true;
37250    } else { 
37251      return false;
37252    }
37253  }
37254
37255  function fn_check_if_extension_installed_impl(extension_id, callback) {
37256    
37257    if (!fn_is_chrome()) {
37258      callback({ installed: false, supported: false});
37259    }
37260
37261    if (extension_id) {
37262
37263      // The extension's own cloudhq.js content script marks cloudhq.net pages with <head data-cloudhq-has-<ext>="true">,
37264      // where <ext> is the extension internal name with "_" replaced by "-". We read that internal name from a companion
37265      // attribute chrome-extension-{not-installed,installed,not-supported}-name on the detection element and use the
37266      // marker as a FALLBACK: first we try the resource probe, and only if that says "not installed" do we check the
37267      // marker. The marker is the only signal for MV3 extensions (e.g. the Outlook extension), which do not expose the
37268      // web_accessible_resources the probe looks for.
37269      // Require the id + name-attribute PAIRING in the selector: pages like main_dashboard/apps render a positive
37270      // [chrome-extension-installed] div (without a name attribute) BEFORE the [chrome-extension-not-installed] div,
37271      // and a plain id-only selector would match that first div and come back without the internal name.
37272      var marker_el = null;
37273      try {
37274        marker_el = document.querySelector('[chrome-extension-not-installed="' + extension_id + '"][chrome-extension-not-installed-name],[chrome-extension-installed="' + extension_id + '"][chrome-extension-installed-name],[chrome-extension-not-supported="' + extension_id + '"][chrome-extension-not-supported-name]');
37275      } catch(e) { }
37276      var ext_internal_name = marker_el ? (marker_el.getAttribute('chrome-extension-not-installed-name') || marker_el.getAttribute('chrome-extension-installed-name') || marker_el.getAttribute('chrome-extension-not-supported-name')) : null;
37277      var marker_attr = ext_internal_name ? ('data-cloudhq-has-' + ext_internal_name.replace(/_/g, '-')) : null;
37278
37279      // Called when the resource probe below concludes the extension is not installed. cloudhq.js sets its marker at
37280      // document_end (and it is the ONLY signal for MV3 extensions), so poll the head for ~2s before finally giving up.
37281      // Keep this short: the poll only delays the NEGATIVE verdict, i.e. how late the "Install it" hint shows for users
37282      // who really do not have the extension (installed users match on the first or second check). A real marker lands
37283      // within a few hundred ms of DOMContentLoaded (watch_video.html.erb budgets 500ms for the same marker), so 2s is
37284      // already a generous multiple of the realistic tail.
37285      function fn_check_extension_via_cloudhq_marker() {
37286        if (!marker_attr || !fn_is_chrome()) {
37287          callback({ installed: false, supported: true });
37288          return;
37289        }
37290        var marker_attempts = 0;
37291        var fn_poll_cloudhq_marker = function() {
37292          if (document.head && document.head.getAttribute(marker_attr) === 'true') {
37293            console.log(extension_id, ' is installed (' + marker_attr + ')');
37294            callback({ installed: true, supported: true });
37295            return;
37296          }
37297          marker_attempts++;
37298          if (marker_attempts >= 10) {
37299            console.log(extension_id, ' not installed (probe failed and ' + marker_attr + ' absent after polling)');
37300            callback({ installed: false, supported: true });
37301            return;
37302          }
37303          setTimeout(fn_poll_cloudhq_marker, 200);
37304        };
37305        fn_poll_cloudhq_marker();
37306      }
37307
37308      function fn_check_extension_via_inboxsdk_js(extension_id) {
37309        
37310        var url = 'chrome-extension://'+ extension_id +'/javascripts/inboxsdk.js';
37311        
37312        var xhr = new XMLHttpRequest();
37313        xhr.onerror = function() {  
37314          console.log(extension_id, ' unable to find inboxsdk_js; trying cloudhq.js page marker');
37315          fn_check_extension_via_cloudhq_marker();
37316        }
37317        xhr.onload = function() {
37318          console.log(extension_id, ' is installed (inboxsdk_js)');
37319          callback({ installed: true, supported: true});
37320        };
37321        try { xhr.open('GET', url); } catch(e) { }
37322        try { xhr.send(); } catch(e) { }
37323
37324      }
37325
37326      function fn_check_extension_via_background_js(extension_id) {
37327        var url = 'chrome-extension://'+ extension_id +'/javascripts/background.js';
37328        
37329        var xhr = new XMLHttpRequest();
37330        xhr.onerror = function() {
37331          console.log(extension_id, ' unable to find background_js ');
37332          fn_check_extension_via_inboxsdk_js(extension_id);
37333        }
37334        xhr.onload = function() {
37335          console.log(extension_id, ' is installed (background_js)');
37336          callback({ installed: true, supported: true});
37337        };
37338        try { xhr.open('GET', url); } catch(e) { }
37339        try { xhr.send(); } catch(e) { }
37340
37341      }
37342
37343      function fn_check_extension_via_popup_js(extension_id) {
37344        var url = 'chrome-extension://'+ extension_id +'/javascripts/popup.js';
37345        
37346        var xhr = new XMLHttpRequest();
37347        xhr.onerror = function() {
37348          console.log(extension_id, ' unable to find popup_js ');
37349          fn_check_extension_via_background_js(extension_id);
37350        }
37351        xhr.onload = function() {
37352          console.log(extension_id, ' is installed (popup_js)');
37353          callback({ installed: true, supported: true});
37354        };
37355        try { xhr.open('GET', url); } catch(e) { }
37356        try { xhr.send(); } catch(e) { }
37357
37358      }
37359      
37360      function fn_check_extension_via_logo(extension_id) {
37361        var url = 'chrome-extension://'+ extension_id +'/icons/logo.png';
37362        
37363        var xhr = new XMLHttpRequest();
37364        xhr.onerror = function() {
37365          console.log(extension_id, ' unable to find logo');
37366          fn_check_extension_via_popup_js(extension_id);
37367          // console.log(xhr.response);
37368        }
37369        xhr.onload = function() {
37370          console.log(extension_id, ' is installed (logo)');
37371          callback({ installed: true, supported: true});
37372        };
37373        try { xhr.open('GET', url); } catch(e) { }
37374        try { xhr.send(); } catch(e) { }
37375      }
37376
37377      // Old logic first: probe the extension's web_accessible_resources. On terminal failure the probe chain calls
37378      // fn_check_extension_via_cloudhq_marker() (from fn_check_extension_via_inboxsdk_js), which then polls the marker.
37379      fn_check_extension_via_logo(extension_id);
37380    }
37381
37382    return true;
37383
37384  }
37385
37386  var css_text = '[chrome-extension-installed],[chrome-extension-not-installed], [chrome-extension-not-supported] { display:none; }';
37387  if (fn_is_chrome()) {
37388    css_text += '\n[is-chrome-browser="false"] { display: none !important; }';
37389  } else {
37390    css_text += '\n[is-chrome-browser="true"] { display: none !important; }';
37391  }
37392
37393  var s = $('<style />');
37394  s.text(css_text);
37395  $(document.head).append(s);
37396  
37397  $(function() {
37398    $.unique($('[chrome-extension-installed],[chrome-extension-not-installed],[chrome-extension-not-supported]').map(function() { 
37399      return $(this).attr('chrome-extension-installed') || $(this).attr('chrome-extension-not-installed') || $(this).attr('chrome-extension-not-supported');
37400    })).each(function() {
37401      var extension_id = this;
37402      if (extension_id) {
37403
37404        fn_check_if_extension_installed_impl(extension_id, function(res) {
37405          
37406          var css_text = "";
37407
37408          if(res.supported && res.installed) {
37409            css_text += '\n[chrome-extension-installed="' + extension_
37409id + '"] { display: block; }';
37410          }
37411
37412          if(res.supported && !res.installed) {
37413            css_text += '\n[chrome-extension-not-installed="' + extension_id + '"] { display: block; }';
37414          }
37415
37416          if(!res.supported) {
37417            css_text += '\n[chrome-extension-not-supported="' + extension_id + '"] { display: block; }';
37418          }
37419          
37420          var s = $('<style />');
37421          s.text(css_text);
37422          $(document.head).append(s);
37423
37424        });
37425      }
37426    });
37427  });
37428
37429  return {
37430    fn_is_chrome: fn_is_chrome,
37431    fn_check_if_extension_installed: fn_check_if_extension_installed_impl
37432  };
37433
37434})();
37435
37436/**
37437 * @author Blaz Lipuscek
37438 */
37439(function($) {
37440
37441  $.fn.extend({
37442
37443    timeAgo: function(options) {
37444      var $element = $(this);
37445      date_format.track_time_ago($element, options);
37446      return $element;      
37447    },
37448
37449    submitViaAjax: function(options) {
37450
37451      var submitCount = 0;
37452      
37453      function run_ajax(method, action, data, options) {
37454        var ajaxOptions = $.extend({
37455          type: method,
37456          url: action,
37457          data: data,
37458          dataType : "json",
37459          timeout: 0, // infinit
37460          success: function(response, status, xhr) {
37461            if (timeout)
37462              window.clearTimeout(timeout);
37463            if (response.resubmit == true) {
37464              // we need to resubmit this method, make sure we pass on resubmit argument.
37465              var timeout = Math.min(submitCount, 3) * 10000;
37466              window.setTimeout(function() {
37467                run_ajax(method, action, data + '&resubmit=1', options);  
37468              }, timeout);
37469              return;
37470            } else if(response && response.next_page != null) {
37471              location.replace(response.next_page);
37472              return;
37473            } else if (response && response.message ) {
37474              try { g_cmn.fn_working_overlay(false); } catch(er)  { }
37475              g_cmn.fn_notif_win(true, response.message, 10000);
37476            } else {
37477              window.location.reload(true); 
37478            }
37479          },
37480          error: function(json) {
37481            if (timeout)
37482              window.clearTimeout(timeout);
37483            g_cmn.fn_notif_win(true, "Looks like an error occurred on server! Please try again ...", 6000);
37484            try { g_cmn.fn_working_overlay(false); } catch(er)  { }
37485          }
37486        }, (options['ajaxOptions']) || {});
37487        submitCount = submitCount + 1;
37488        $.ajax(ajaxOptions);        
37489      }
37490      
37491      options = options || {};
37492      var form = $(this);
37493      var formWorkingText = form.attr('data-working-text') || options['workingText'] || 'Working ...';
37494      var formWorkingTextAfter = form.attr('data-working-text-after') || options['workingTextAfter'] || 'Still working! This could take a few minutes ...';
37495      var timeout = null;
37496      var fromSubmitEvent = form.submit(function() {
37497        if (timeout)
37498          window.clearTimeout(timeout);
37499        try { g_cmn.fn_working_overlay(true, formWorkingText); } catch(er)  { }
37500        timeout = window.setTimeout(function() {
37501          try { g_cmn.fn_working_overlay(true, formWorkingTextAfter); } catch(er)  { }  
37502        }, 10000);
37503        var values = form.serialize();
37504        var method = form.attr('method');
37505        var action = form.attr('action');
37506        run_ajax(method, action, values, options);
37507        return false;
37508      });
37509      return fromSubmitEvent;
37510    },
37511
37512    checkboxAll : function(checkbox_selector) {
37513
37514      var $checkAll = $(this);
37515      var $checkboxes = $(checkbox_selector);
37516
37517      var checkAll = function(checked) {
37518        $checkboxes.each(function() {
37519          var $checkbox = $(this);
37520          if (checked) {
37521            if (!$checkbox.attr('disabled'))
37522              $checkbox.attr('checked', 'checked');
37523          } else
37524            $checkbox.removeAttr('checked');
37525        });
37526      };
37527
37528      var refreshCheckState = function() {
37529        var unchecked = false;
37530        $checkboxes.each(function() {
37531          var $checkbox = $(this);
37532          if (!$checkbox.is(':checked') && !$checkbox.attr('disabled'))
37533            unchecked = true;
37534        });
37535        if (!unchecked) {
37536          $checkAll.attr('checked', 'checked');
37537        } else {
37538          $checkAll.removeAttr('checked');
37539        }
37540      };
37541
37542      $checkAll.click(function() {
37543        var $check = $(this);
37544        var checked = $check.is(':checked');
37545        checkAll(checked);
37546        refreshCheckState();
37547      });
37548
37549      $checkboxes.click(refreshCheckState);
37550
37551      refreshCheckState();
37552    }
37553  });
37554  
37555  $(function() {
37556    $('.ajax-form').each(function() {
37557      $(this).submitViaAjax({});
37558    });
37559  });
37560
37561})(jQuery); 
37562
37563// From: http://www.quirksmode.org/js/detect.html
37564try {
37565  window.top.browserDetect = {
37566    init: function(){
37567      this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
37568      this.version = this.searchVersion(navigator.userAgent) ||
37569      this.searchVersion(navigator.appVersion) ||
37570      "an unknown version";
37571      this.OS = this.searchString(this.dataOS) || "an unknown OS";
37572    },
37573    searchString: function(data){
37574      for (var i = 0; i < data.length; i++) {
37575        var dataString = data[i].string;
37576        var dataProp = data[i].prop;
37577        this.versionSearchString = data[i].versionSearch || data[i].identity;
37578        if (dataString) {
37579          if (dataString.indexOf(data[i].subString) != -1) 
37580            return data[i].identity;
37581        }
37582        else 
37583          if (dataProp) 
37584            return data[i].identity;
37585      }
37586    },
37587    searchVersion: function(dataString){
37588      var index = dataString.indexOf(this.versionSearchString);
37589      if (index == -1) 
37590        return;
37591      return parseFloat(dataString.substring(index + this.versionSearchString.length + 1));
37592    },
37593    dataBrowser: [{
37594      string: navigator.userAgent,
37595      subString: "Flock",
37596      identity: "Flock"
37597    }, {
37598      string: navigator.userAgent,
37599      subString: "RockMelt",
37600      identity: "RockMelt"
37601    }, {
37602      string: navigator.userAgent,
37603      subString: "Chrome",
37604      identity: "Chrome"
37605    }, {
37606      string: navigator.userAgent,
37607      subString: "OmniWeb",
37608      versionSearch: "OmniWeb/",
37609      identity: "OmniWeb"
37610    }, {
37611      string: navigator.vendor,
37612      subString: "Apple",
37613      identity: "Safari",
37614      versionSearch: "Version"
37615    }, {
37616      prop: window.opera,
37617      identity: "Opera"
37618    }, {
37619      string: navigator.vendor,
37620      subString: "iCab",
37621      identity: "iCab"
37622    }, {
37623      string: navigator.vendor,
37624      subString: "KDE",
37625      identity: "Konqueror"
37626    }, {
37627      string: navigator.userAgent,
37628      subString: "Firefox",
37629      identity: "Firefox"
37630    }, {
37631      string: navigator.userAgent,
37632      subString: "Iceweasel",
37633      identity: "Firefox"
37634    }, {
37635      string: navigator.userAgent,
37636      subString: "Shiretoko",
37637      identity: "Firefox"
37638    }, {
37639      string: navigator.userAgent,
37640      subString: "Namoroka",
37641      identity: "Firefox"
37642    }, {
37643      string: navigator.userAgent,
37644      subString: "Minefield",
37645      identity: "Firefox"
37646    }, {
37647      string: navigator.vendor,
37648      subString: "Camino",
37649      identity: "Camino"
37650    }, { // for newer Netscapes (6+)
37651      string: navigator.userAgent,
37652      subString: "Netscape",
37653      identity: "Netscape"
37654    }, {
37655      string: navigator.userAgent,
37656      subString: "MSIE",
37657      identity: "Explorer",
37658      versionSearch: "MSIE"
37659    }, {
37660      string: navigator.userAgent,
37661      subString: "Gecko",
37662      identity: "Mozilla",
37663      versionSearch: "rv"
37664    }, { // for older Netscapes (4-)
37665      string: navigator.userAgent,
37666      subString: "Mozilla",
37667      identity: "Netscape",
37668      versionSearch: "Mozilla"
37669    }],
37670    dataOS: [{
37671      string: navigator.platform,
37672      subString: "Win",
37673      identity: "Windows"
37674    }, {
37675      string: navigator.platform,
37676      subString: "Mac",
37677      identity: "Mac"
37678    }, {
37679      string: navigator.userAgent,
37680      subString: "iPhone",
37681      identity: "iPhone/iPod"
37682    }, {
37683      string: navigator.userAgent,
37684      subString: "iPad",
37685      identity: "iPad"
37686    }, {
37687      string: navigator.userAgent,
37688      subString: "Android",
37689      identity: "Android"
37690    }, {
37691      string: navigator.platform,
37692      subString: "Linux",
37693      identity: "Linux"
37694    }]
37695  
37696  };
37697  browserDetect.init();
37698}
37699catch(e)
37700{
37701  
37702}
37703
37704/**
37705 * Cookie plugin
37706 *
37707 * Copyright (c) 2006 Klaus Hartl (stilbuero.de)
37708 * Dual licensed under the MIT and GPL licenses:
37709 * http://www.opensource.org/licenses/mit-license.php
37710 * http://www.gnu.org/licenses/gpl.html
37711 *
37712 */
37713
37714/**
37715 * Create a cookie with the given name and value and other optional parameters.
37716 *
37717 * @example $.cookie('the_cookie', 'the_value');
37718 * @desc Set the value of a cookie.
37719 * @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true });
37720 * @desc Create a cookie with all available options.
37721 * @example $.cookie('the_cookie', 'the_value');
37722 * @desc Create a session cookie.
37723 * @example $.cookie('the_cookie', null);
37724 * @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain
37725 *       used when the cookie was set.
37726 *
37727 * @param String name The name of the cookie.
37728 * @param String value The value of the cookie.
37729 * @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
37730 * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
37731 *                             If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
37732 *                             If set to null or omitted, the cookie will be a session cookie and will not be retained
37733 *                             when the the browser exits.
37734 * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
37735 * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
37736 * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
37737 *                        require a secure protocol (like HTTPS).
37738 * @type undefined
37739 *
37740 * @name $.cookie
37741 * @cat Plugins/Cookie
37742 * @author Klaus Hartl/[email protected]
37743 */
37744
37745/**
37746 * Get the value of a cookie with the given name.
37747 *
37748 * @example $.cookie('the_cookie');
37749 * @desc Get the value of a cookie.
37750 *
37751 * @param String name The name of the cookie.
37752 * @return The value of the cookie.
37753 * @type String
37754 *
37755 * @name $.cookie
37756 * @cat Plugins/Cookie
37757 * @author Klaus Hartl/[email protected]
37758 */
37759jQuery.cookie = function(name, value, options) {
37760    if (typeof value != 'undefined') { // name and value given, set cookie
37761        options = options || {};
37762        if (value === null) {
37763            value = '';
37764            options.expires = -1;
37765        }
37766        var expires = '';
37767        if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
37768            var date;
37769            if (typeof options.expires == 'number') {
37770                date = new Date();
37771                date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
37772            } else {
37773                date = options.expires;
37774            }
37775            expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
37776        }
37777        // CAUTION: Needed to parenthesize options.path and options.domain
37778        // in the following expressions, otherwise they evaluate to undefined
37779        // in the packed version for some reason...
37780        var path = options.path ? '; path=' + (options.path) : '';
37781        var domain = options.domain ? '; domain=' + (options.domain) : '';
37782        var secure = options.secure ? '; secure' : '';
37783        document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
37784    } else { // only name given, get cookie
37785        var cookieValue = null;
37786        if (document.cookie && document.cookie != '') {
37787            var cookies = document.cookie.split(';');
37788            for (var i = 0; i < cookies.length; i++) {
37789                var cookie = jQuery.trim(cookies[i]);
37790                // Does this cookie string begin with the name we want?
37791                if (cookie.substring(0, name.length + 1) == (name + '=')) {
37792                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
37793                    break;
37794                }
37795            }
37796        }
37797        return cookieValue;
37798    }
37799};
37800/*
37801 * jQuery Hotkeys Plugin
37802 * Copyright 2010, John Resig
37803 * Dual licensed under the MIT or GPL Version 2 licenses.
37804 *
37805 * Based upon the plugin by Tzury Bar Yochay:
37806 * http://github.com/tzuryby/hotkeys
37807 *
37808 * Original idea by:
37809 * Binny V A, http://www.openjs.com/scripts/events/keyboard_shortcuts/
37810*/
37811
37812/*
37813 * One small change is: now keys are passed by object { keys: '...' }
37814 * Might be useful, when you want to pass some other data to your handler
37815 */
37816
37817(function(jQuery){
37818
37819	jQuery.hotkeys = {
37820		version: "0.8",
37821
37822		specialKeys: {
37823			8: "backspace", 9: "tab", 10: "return", 13: "return", 16: "shift", 17: "ctrl", 18: "alt", 19: "pause",
37824			20: "capslock", 27: "esc", 32: "space", 33: "pageup", 34: "pagedown", 35: "end", 36: "home",
37825			37: "left", 38: "up", 39: "right", 40: "down", 45: "insert", 46: "del", 59: ";", 61: "=",
37826			96: "0", 97: "1", 98: "2", 99: "3", 100: "4", 101: "5", 102: "6", 103: "7",
37827			104: "8", 105: "9", 106: "*", 107: "+", 109: "-", 110: ".", 111 : "/",
37828			112: "f1", 113: "f2", 114: "f3", 115: "f4", 116: "f5", 117: "f6", 118: "f7", 119: "f8",
37829			120: "f9", 121: "f10", 122: "f11", 123: "f12", 144: "numlock", 145: "scroll", 173: "-", 186: ";", 187: "=",
37830			188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\", 221: "]", 222: "'"
37831		},
37832
37833		shiftNums: {
37834			"`": "~", "1": "!", "2": "@", "3": "#", "4": "$", "5": "%", "6": "^", "7": "&",
37835			"8": "*", "9": "(", "0": ")", "-": "_", "=": "+", ";": ": ", "'": "\"", ",": "<",
37836			".": ">",  "/": "?",  "\\": "|"
37837		}
37838	};
37839
37840	function keyHandler( handleObj ) {
37841		if ( typeof handleObj.data === "string" ) {
37842			handleObj.data = { keys: handleObj.data };
37843		}
37844
37845		// Only care when a possible input has been specified
37846		if ( !handleObj.data || !handleObj.data.keys || typeof handleObj.data.keys !== "string" ) {
37847			return;
37848		}
37849
37850		var origHandler = handleObj.handler,
37851			keys = handleObj.data.keys.toLowerCase().split(" "),
37852			textAcceptingInputTypes = ["text", "password", "number", "email", "url", "range", "date", "month", "week",
37853        "time", "datetime", "datetime-local", "search", "color", "tel"];
37854
37855		handleObj.handler = function( event ) {
37856			// Don't fire in text-accepting inputs that we didn't directly bind to
37857			if ( this !== event.target && (/textarea|select/i.test( event.target.nodeName ) ||
37858				jQuery.inArray(event.target.type, textAcceptingInputTypes) > -1 ) ) {
37859				return;
37860			}
37861
37862			var special = jQuery.hotkeys.specialKeys[ event.keyCode ],
37863				character = String.fromCharCode( event.which ).toLowerCase(),
37864				modif = "", possible = {};
37865
37866      jQuery.each([ "alt", "ctrl", "meta", "shift" ], function(index, specialKey) {
37867        if (event[specialKey + 'Key'] && special !== specialKey) {
37868          modif += specialKey + '+';
37869        }
37870      });
37871
37872
37873      modif = modif.replace('alt+ctrl+meta+shift', 'hyper');
37874
37875			if ( special ) {
37876				possible[ modif + special ] = true;
37877			}
37878
37879			if ( character ) {
37880				possible[ modif + character ] = true;
37881				possible[ modif + jQuery.hotkeys.shiftNums[ character ] ] = true;
37882
37883				// "$" can be triggered as "Shift+4" or "Shift+$" or just "$"
37884				if ( modif === "shift+" ) {
37885					possible[ jQuery.hotkeys.shiftNums[ character ] ] = true;
37886				}
37887			}
37888
37889			for ( var i = 0, l = keys.length; i < l; i++ ) {
37890				if ( possible[ keys[i] ] ) {
37891					return origHandler.apply( this, arguments );
37892				}
37893			}
37894		};
37895	}
37896
37897	jQuery.each([ "keydown", "keyup", "keypress" ], function() {
37898		jQuery.event.special[ this ] = { add: keyHandler };
37899	});
37900
37901})( this.jQuery );
37902/*
37903 * jsTree 1.0-rc1
37904 * http://jstree.com/
37905 *
37906 * Copyright (c) 2010 Ivan Bozhanov (vakata.com)
37907 *
37908 * Dual licensed under the MIT and GPL licenses (same as jQuery):
37909 *   http://www.opensource.org/licenses/mit-license.php
37910 *   http://www.gnu.org/licenses/gpl.html
37911 *
37912 * $Date: 2010-07-01 10:51:11 +0300 (четв, 01 юли 2010) $
37913 * $Revision: 191 $
37914 */
37915
37916/*jslint browser: true, onevar: true, undef: true, bitwise: true, strict: true */
37917/*global window : false, clearInterval: false, clearTimeout: false, document: false, setInterval: false, setTimeout: false, jQuery: false, navigator: false, XSLTProcessor: false, DOMParser: false, XMLSerializer: false*/
37918
37919"use strict";
37920// Common functions not related to jsTree 
37921// decided to move them to a `vakata` "namespace"
37922(function ($) {
37923	$.vakata = {};
37924	// CSS related functions
37925	$.vakata.css = {
37926		get_css : function(rule_name, delete_flag, sheet) {
37927			rule_name = rule_name.toLowerCase();
37928			var css_rules = sheet.cssRules || sheet.rules,
37929				j = 0;
37930			do {
37931				if(css_rules.length && j > css_rules.length + 5) { return false; }
37932				if(css_rules[j].selectorText && css_rules[j].selectorText.toLowerCase() == rule_name) {
37933					if(delete_flag === true) {
37934						if(sheet.removeRule) { sheet.removeRule(j); }
37935						if(sheet.deleteRule) { sheet.deleteRule(j); }
37936						return true;
37937					}
37938					else { return css_rules[j]; }
37939				}
37940			}
37941			while (css_rules[++j]);
37942			return false;
37943		},
37944		add_css : function(rule_name, sheet) {
37945			if($.jstree.css.get_css(rule_name, false, sheet)) { return false; }
37946			if(sheet.insertRule) { sheet.insertRule(rule_name + ' { }', 0); } else { sheet.addRule(rule_name, null, 0); }
37947			return $.vakata.css.get_css(rule_name);
37948		},
37949		remove_css : function(rule_name, sheet) { 
37950			return $.vakata.css.get_css(rule_name, true, sheet); 
37951		},
37952		add_sheet : function(opts) {
37953			var tmp;
37954			if(opts.str) {
37955				tmp = document.createElement("style");
37956				tmp.setAttribute('type',"text/css");
37957				if(tmp.styleSheet) {
37958					document.getElementsByTagName("head")[0].appendChild(tmp);
37959					tmp.styleSheet.cssText = opts.str;
37960				}
37961				else {
37962					tmp.appendChild(document.createTextNode(opts.str));
37963					document.getElementsByTagName("head")[0].appendChild(tmp);
37964				}
37965				return tmp.sheet || tmp.styleSheet;
37966			}
37967			if(opts.url) {
37968				if(document.createStyleSheet) {
37969					try { tmp = document.createStyleSheet(opts.url); } catch (e) { }
37970				}
37971				else {
37972					tmp			= document.createElement('link');
37973					tmp.rel		= 'stylesheet';
37974					tmp.type	= 'text/css';
37975					tmp.media	= "all";
37976					tmp.href	= opts.url;
37977					document.getElementsByTagName("head")[0].appendChild(tmp);
37978					return tmp.styleSheet;
37979				}
37980			}
37981		}
37982	};
37983})(jQuery);
37984
37985/* 
37986 * jsTree core 1.0
37987 */
37988(function ($) {
37989	// private variables 
37990	var instances = [],			// instance array (used by $.jstree.reference/create/focused)
37991		focused_instance = -1,	// the index in the instance array of the currently focused instance
37992		plugins = {},			// list of included plugins
37993		prepared_move = {},		// for the move plugin
37994		is_ie6 = false;
37995
37996	// jQuery plugin wrapper (thanks to jquery UI widget function)
37997	$.fn.jstree = function (settings) {
37998		var isMethodCall = (typeof settings == 'string'), // is this a method call like $().jstree("open_node")
37999			args = Array.prototype.slice.call(arguments, 1), 
38000			returnValue = this;
38001
38002		// extend settings and allow for multiple hashes and metadata
38003		if(!isMethodCall && $.meta) { args.push($.metadata.get(this).jstree); }
38004		settings = !isMethodCall && args.length ? $.extend.apply(null, [true, settings].concat(args)) : settings;
38005		// block calls to "private" methods
38006		if(isMethodCall && settings.substring(0, 1) == '_') { return returnValue; }
38007
38008		// if a method call execute the method on all selected instances
38009		if(isMethodCall) {
38010			this.each(function() {
38011				var instance = instances[$.data(this, "jstree-instance-id")],
38012					methodValue = (instance && $.isFunction(instance[settings])) ? instance[settings].apply(instance, args) : instance;
38013					if(typeof methodValue !== "undefined" && (settings.indexOf("is_" === 0) || (methodValue !== true && methodValue !== false))) { returnValue = methodValue; return false; }
38014			});
38015		}
38016		else {
38017			this.each(function() {
38018				var instance_id = $.data(this, "jstree-instance-id"),
38019					s = false;
38020				// if an instance already exists, destroy it first
38021				if(typeof instance_id !== "undefined" && instances[instance_id]) { instances[instance_id].destroy(); }
38022				// push a new empty object to the instances array
38023				instance_id = parseInt(instances.push({}),10) - 1;
38024				// store the jstree instance id to the container element
38025				$.data(this, "jstree-instance-id", instance_id);
38026				// clean up all plugins
38027				if(!settings) { settings = {}; }
38028				settings.plugins = $.isArray(settings.plugins) ? settings.plugins : $.jstree.defaults.plugins;
38029				if($.inArray("core", settings.plugins) === -1) { settings.plugins.unshift("core"); }
38030				
38031				// only unique plugins (NOT WORKING)
38032				// settings.plugins = settings.plugins.sort().join(",,").replace(/(,|^)([^,]+)(,,\2)+(,|$)/g,"$1$2$4").replace(/,,+/g,",").replace(/,$/,"").split(",");
38033
38034				// extend defaults with passed data
38035				s = $.extend(true, {}, $.jstree.defaults, settings);
38036				s.plugins = settings.plugins;
38037				$.each(plugins, function (i, val) { if($.inArray(i, s.plugins) === -1) { s[i] = null; delete s[i]; } });
38038				// push the new object to the instances array (at the same time set the default classes to the container) and init
38039				instances[instance_id] = new $.jstree._instance(instance_id, $(this).addClass("jstree jstree-" + instance_id), s); 
38040				// init all activated plugins for this instance
38041				$.each(instances[instance_id]._get_settings().plugins, function (i, val) { instances[instance_id].data[val] = {}; });
38042				$.each(instances[instance_id]._get_settings().plugins, function (i, val) { if(plugins[val]) { plugins[val].__init.apply(instances[instance_id]); } });
38043				// initialize the instance
38044				instances[instance_id].init();
38045			});
38046		}
38047		// return the jquery selection (or if it was a method call that returned a value - the returned value)
38048		return returnValue;
38049	};
38050	// object to store exposed functions and objects
38051	$.jstree = {
38052		defaults : {
38053			plugins : []
38054		},
38055		_focused : function () { return instances[focused_instance] || null; },
38056		_reference : function (needle) { 
38057			// get by instance id
38058			if(instances[needle]) { return instances[needle]; }
38059			// get by DOM (if still no luck - return null
38060			var o = $(needle); 
38061			if(!o.length && typeof needle === "string") { o = $("#" + needle); }
38062			if(!o.length) { return null; }
38063			return instances[o.closest(".jstree").data("jstree-instance-id")] || null; 
38064		},
38065		_instance : function (index, container, settings) { 
38066			// for plugins to store data in
38067			this.data = { core : {} };
38068			this.get_settings	= function () { return $.extend(true, {}, settings); };
38069			this._get_settings	= function () { return settings; };
38070			this.get_index		= function () { return index; };
38071			this.get_container	= function () { return container; };
38072			this._set_settings	= function (s) { 
38073				settings = $.extend(true, {}, settings, s);
38074			};
38075		},
38076		_fn : { },
38077		plugin : function (pname, pdata) {
38078			pdata = $.extend({}, {
38079				__init		: $.noop, 
38080				__destroy	: $.noop,
38081				_fn			: {},
38082				defaults	: false
38083			}, pdata);
38084			plugins[pname] = pdata;
38085
38086			$.jstree.defaults[pname] = pdata.defaults;
38087			$.each(pdata._fn, function (i, val) {
38088				val.plugin		= pname;
38089				val.old			= $.jstree._fn[i];
38090				$.jstree._fn[i] = function () {
38091					var rslt,
38092						func = val,
38093						args = Array.prototype.slice.call(arguments),
38094						evnt = new $.Event("before.jstree"),
38095						rlbk = false;
38096
38097					// Check if function belongs to the included plugins of this instance
38098					do {
38099						if(func && func.plugin && $.inArray(func.plugin, this._get_settings().plugins) !== -1) { break; }
38100						func = func.old;
38101					} while(func);
38102					if(!func) { return; }
38103
38104					// a chance to stop execution (or change arguments): 
38105					// * just bind to jstree.before
38106					// * check the additional data object (func property)
38107					// * call event.stopImmediatePropagation()
38108					// * return false (or an array of arguments)
38109					rslt = this.get_container().triggerHandler(evnt, { "func" : i, "inst" : this, "args" : args });
38110					if(rslt === false) { return; }
38111					if(typeof rslt !== "undefined") { args = rslt; }
38112
38113					// context and function to trigger events, then finally call the function
38114					if(i.indexOf("_") === 0) {
38115						rslt = func.apply(this, args);
38116					}
38117					else {
38118						rslt = func.apply(
38119							$.extend({}, this, { 
38120								__callback : function (data) { 
38121									this.get_container().triggerHandler( i + '.jstree', { "inst" : this, "args" : args, "rslt" : data, "rlbk" : rlbk });
38122								},
38123								__rollback : function () { 
38124									rlbk = this.get_rollback();
38125									return rlbk;
38126								},
38127								__call_old : function (replace_arguments) {
38128									return func.old.apply(this, (replace_arguments ? Array.prototype.slice.call(arguments, 1) : args ) );
38129								}
38130							}), args);
38131					}
38132
38133					// return the result
38134					return rslt;
38135				};
38136				$.jstree._fn[i].old = val.old;
38137				$.jstree._fn[i].plugin = pname;
38138			});
38139		},
38140		rollback : function (rb) {
38141			if(rb) {
38142				if(!$.isArray(rb)) { rb = [ rb ]; }
38143				$.each(rb, function (i, val) {
38144					instances[val.i].set_rollback(val.h, val.d);
38145				});
38146			}
38147		}
38148	};
38149	// set the prototype for all instances
38150	$.jstree._fn = $.jstree._instance.prototype = {};
38151
38152	// css functions - used internally
38153
38154	// load the css when DOM is ready
38155	$(function() {
38156		// code is copied form jQuery ($.browser is deprecated + there is a bug in IE)
38157		var u = navigator.userAgent.toLowerCase(),
38158			v = (u.match( /.+?(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [0,'0'])[1],
38159			css_string = '' + 
38160				'.jstree ul, .jstree li { display:block; margin:0 0 0 0; padding:0 0 0 0; list-style-type:none; } ' + 
38161				'.jstree li { display:block; min-height:18px; line-height:18px; white-space:nowrap; margin-left:18px; } ' + 
38162				'.jstree-rtl li { margin-left:0; margin-right:18px; } ' + 
38163				'.jstree > ul > li { margin-left:0px; /* color:black !important; */} ' + 
38164				'.jstree-rtl > ul > li { margin-right:0px; } ' + 
38165				'.jstree ins { display:inline-block; text-decoration:none; width:18px; height:18px; margin:0 0 0 0; padding:0; } ' + 
38166				'.jstree a { display:inline-block; line-height:16px; height:16px; /* color: black;*/ white-space:nowrap; text-decoration:none; padding:1px 2px; margin:0; } ' + 
38167				'.jstree a:focus { outline: none; } ' + 
38168				'.jstree a > ins { height:16px; width:16px; } ' + 
38169				'.jstree a > .jstree-icon { margin-right:3px; } ' + 
38170				'.jstree-rtl a > .jstree-icon { margin-left:3px; margin-right:0; } ' + 
38171				'li.jstree-open > ul { display:block; } ' + 
38172				'li.jstree-closed > ul { display:none; } ';
38173		// Correct IE 6 (does not support the > CSS selector)
38174		if(/msie/.test(u) && parseInt(v, 10) == 6) { 
38175			is_ie6 = true;
38176			css_string += '' + 
38177				'.jstree li { height:18px; margin-left:0; margin-right:0; } ' + 
38178				'.jstree li li { margin-left:18px; } ' + 
38179				'.jstree-rtl li li { margin-left:0px; margin-right:18px; } ' + 
38180				'li.jstree-open ul { display:block; } ' + 
38181				'li.jstree-closed ul { display:none !important; } ' + 
38182				'.jstree li a { display:inline; border-width:0 !important; padding:0px 2px !important; } ' + 
38183				'.jstree li a ins { height:16px; width:16px; margin-right:3px; } ' + 
38184				'.jstree-rtl li a ins { margin-right:0px; margin-left:3px; } ';
38185		}
38186		// Correct IE 7 (shifts anchor nodes onhover)
38187		if(/msie/.test(u) && parseInt(v, 10) == 7) { 
38188			css_string += '.jstree li a { border-width:0 !important; padding:0px 2px !important; } ';
38189		}
38190		$.vakata.css.add_sheet({ str : css_string });
38191	});
38192
38193	// core functions (open, close, create, update, delete)
38194	$.jstree.plugin("core", {
38195		__init : function () {
38196			this.data.core.to_open = $.map($.makeArray(this.get_settings().core.initially_open), function (n) { return "#" + n.toString().replace(/^#/,"").replace('\\/','/').replace('/','\\/'); });
38197		},
38198		defaults : { 
38199			html_titles	: false,
38200			animation	: 500,
38201			initially_open : [],
38202			rtl			: false,
38203			strings		: {
38204				loading		: "Loading ...",
38205				new_node	: "New node"
38206			}
38207		},
38208		_fn : { 
38209			init	: function () { 
38210				this.set_focus(); 
38211				if(this._get_settings().core.rtl) {
38212					this.get_container().addClass("jstree-rtl").css("direction", "rtl");
38213				}
38214				this.get_container().html("<ul><li class='jstree-last jstree-leaf'><ins>&#160;</ins><a class='jstree-loading' href='#'><ins class='jstree-icon'>&#160;</ins>" + this._get_settings().core.strings.loading + "</a></li></ul>");
38215				this.data.core.li_height = this.get_container().find("ul li.jstree-closed, ul li.jstree-leaf").eq(0).height() || 18;
38216
38217				this.get_container()
38218					.delegate("li > ins", "click.jstree", $.proxy(function (event) {
38219							var trgt = $(event.target);
38220							if(trgt.is("ins") && event.pageY - trgt.offset().top < this.data.core.li_height) { this.toggle_node(trgt); }
38221						}, this))
38222					.bind("mousedown.jstree", $.proxy(function () { 
38223							this.set_focus(); // This used to be setTimeout(set_focus,0) - why?
38224						}, this))
38225					.bind("dblclick.jstree", function (event) { 
38226						var sel;
38227						if(document.selection && document.selection.empty) { document.selection.empty(); }
38228						else {
38229							if(window.getSelection) {
38230								sel = window.getSelection();
38231								try { 
38232									sel.removeAllRanges();
38233									sel.collapse();
38234								} catch (err) { }
38235							}
38236						}
38237					});
38238				this.__callback();
38239				this.load_node(-1, function () { this.loaded(); this.reopen(); });
38240			},
38241			destroy	: function () { 
38242				var i,
38243					n = this.get_index(),
38244					s = this._get_settings(),
38245					_this = this;
38246
38247				$.each(s.plugins, function (i, val) {
38248					try { plugins[val].__destroy.apply(_this); } catch(err) { }
38249				});
38250				this.__callback();
38251				// set focus to another instance if this one is focused
38252				if(this.is_focused()) { 
38253					for(i in instances) { 
38254						if(instances.hasOwnProperty(i) && i != n) { 
38255							instances[i].set_focus(); 
38256							break; 
38257						} 
38258					}
38259				}
38260				// if no other instance found
38261				if(n === focused_instance) { focused_instance = -1; }
38262				// remove all traces of jstree in the DOM (only the ones set using jstree*) and cleans all events
38263				this.get_container()
38264					.unbind(".jstree")
38265					.undelegate(".jstree")
38266					.removeData("jstree-instance-id")
38267					.find("[class^='jstree']")
38268						.andSelf()
38269						.attr("class", function () { return this.className.replace(/jstree[^ ]*|$/ig,''); });
38270				// remove the actual data
38271				instances[n] = null;
38272				delete instances[n];
38273			},
38274			save_opened : function () {
38275				var _this = this;
38276				this.data.core.to_open = [];
38277				this.get_container().find(".jstree-open").each(function () { 
38278					_this.data.core.to_open.push("#" + this.id.toString().replace(/^#/,"").replace('\\/','/').replace('/','\\/')); 
38279				});
38280				this.__callback(_this.data.core.to_open);
38281			},
38282			reopen : function (is_callback) {
38283				var _this = this,
38284					done = true,
38285					current = [],
38286					remaining = [];
38287				if(!is_callback) { this.data.core.reopen = false; this.data.core.refreshing = true; }
38288				if(this.data.core.to_open.length) {
38289					$.each(this.data.core.to_open, function (i, val) {
38290						if(val == "#") { return true; }
38291						if($(val).length && $(val).is(".jstree-closed")) { current.push(val); }
38292						else { remaining.push(val); }
38293					});
38294					if(current.length) {
38295						this.data.core.to_open = remaining;
38296						$.each(current, function (i, val) { 
38297							_this.open_node(val, function () { _this.reopen(true); }, true); 
38298						});
38299						done = false;
38300					}
38301				}
38302				if(done) { 
38303					// TODO: find a more elegant approach to syncronizing returning requests
38304					if(this.data.core.reopen) { clearTimeout(this.data.core.reopen); }
38305					this.data.core.reopen = setTimeout(function () { _this.__callback({}, _this); }, 50);
38306					this.data.core.refreshing = false;
38307				}
38308			},
38309			refresh : function (obj) {
38310				var _this = this;
38311				this.save_opened();
38312				if(!obj) { obj = -1; }
38313				obj = this._get_node(obj);
38314				if(!obj) { obj = -1; }
38315				if(obj !== -1) { obj.children("UL").remove(); }
38316				this.load_node(obj, function () { _this.__callback({ "obj" : obj}); _this.reopen(); });
38317			},
38318			// Dummy function to fire after the first load (so that there is a jstree.loaded event)
38319			loaded	: function () { 
38320				this.__callback(); 
38321			},
38322			// deal with focus
38323			set_focus	: function () { 
38324				var f = $.jstree._focused();
38325				if(f && f !== this) {
38326					f.get_container().removeClass("jstree-focused"); 
38327				}
38328				if(f !== this) {
38329					this.get_container().addClass("jstree-focused"); 
38330					focused_instance = this.get_index(); 
38331				}
38332				this.__callback();
38333			},
38334			is_focused	: function () { 
38335				return focused_instance == this.get_index(); 
38336			},
38337
38338			// traverse
38339			_get_node		: function (obj) { 
38340				var $obj = $(obj, this.get_container()); 
38341				if($obj.is(".jstree") || obj == -1) { return -1; } 
38342				$obj = $obj.closest("li", this.get_container()); 
38343				return $obj.length ? $obj : false; 
38344			},
38345			_get_next		: function (obj, strict) {
38346				obj = this._get_node(obj);
38347				if(obj === -1) { return this.get_container().find("> ul > li:first-child"); }
38348				if(!obj.length) { return false; }
38349				if(strict) { return (obj.nextAll("li").size() > 0) ? obj.nextAll("li:eq(0)") : false; }
38350
38351				if(obj.hasClass("jstree-open")) { return obj.find("li:eq(0)"); }
38352				else if(obj.nextAll("li").size() > 0) { return obj.nextAll("li:eq(0)"); }
38353				else { return obj.parentsUntil(".jstree","li").next("li").eq(0); }
38354			},
38355			_get_prev		: function (obj, strict) {
38356				obj = this._get_node(obj);
38357				if(obj === -1) { return this.get_container().find("> ul > li:last-child"); }
38358				if(!obj.length) { return false; }
38359				if(strict) { return (obj.prevAll("li").length > 0) ? obj.prevAll("li:eq(0)") : false; }
38360
38361				if(obj.prev("li").length) {
38362					obj = obj.prev("li").eq(0);
38363					while(obj.hasClass("jstree-open")) { obj = obj.children("ul:eq(0)").children("li:last"); }
38364					return obj;
38365				}
38366				else { var o = obj.parentsUntil(".jstree","li:eq(0)"); return o.length ? o : false; }
38367			},
38368			_get_parent		: function (obj) {
38369				obj = this._get_node(obj);
38370				if(obj == -1 || !obj.length) { return false; }
38371				var o = obj.parentsUntil(".jstree", "li:eq(0)");
38372				return o.length ? o : -1;
38373			},
38374			_get_children	: function (obj) {
38375				obj = this._get_node(obj);
38376				if(obj === -1) { return this.get_container().children("ul:eq(0)").children("li"); }
38377				if(!obj.length) { return false; }
38378				return obj.children("ul:eq(0)").children("li");
38379			},
38380			get_path		: function (obj, id_mode) {
38381				var p = [],
38382					_this = this;
38383				obj = this._get_node(obj);
38384				if(obj === -1 || !obj || !obj.length) { return false; }
38385				obj.parentsUntil(".jstree", "li").each(function () {
38386					p.push( id_mode ? this.id : _this.get_text(this) );
38387				});
38388				p.reverse();
38389				p.push( id_mode ? obj.attr("id") : this.get_text(obj) );
38390				return p;
38391			},
38392
38393			is_open		: function (obj) { obj = this._get_node(obj); return obj && obj !== -1 && obj.hasClass("jstree-open"); },
38394			is_closed	: function (obj) { obj = this._get_node(obj); return obj && obj !== -1 && obj.hasClass("jstree-closed"); },
38395			is_leaf		: function (obj) { obj = this._get_node(obj); return obj && obj !== -1 && obj.hasClass("jstree-leaf"); },
38396			// open/close
38397			open_node	: function (obj, callback, skip_animation) {
38398				obj = this._get_node(obj);
38399				if(!obj.length) { return false; }
38400				if(!obj.hasClass("jstree-closed")) { if(callback) { callback.call(); } return false; }
38401				var s = skip_animation || is_ie6 ? 0 : this._get_settings().core.animation,
38402					t = this;
38403				if(!this._is_loaded(obj)) {
38404					// obj.children("a").addClass("jstree-loading");
38405          obj.children("ins").addClass("jstree-loading");
38406					this.load_node(obj, function () { t.open_node(obj, callback, skip_animation); }, callback);
38407				}
38408				else {
38409					if(s) { obj.children("ul").css("display","none"); }
38410					obj.removeClass("jstree-closed").addClass("jstree-open").children("a").removeClass("jstree-loading");
38411					if(s) { obj.children("ul").stop(true).slideDown(s, function () { this.style.display = ""; }); }
38412					this.__callback({ "obj" : obj });
38413					if(callback) { callback.call(); }
38414				}
38415			},
38416			close_node	: function (obj, skip_animation) {
38417				obj = this._get_node(obj);
38418				var s = skip_animation || is_ie6 ? 0 : this._get_settings().core.animation;
38419				if(!obj.length || !obj.hasClass("jstree-open")) { return false; }
38420				if(s) { obj.children("ul").attr("style","display:block !important"); }
38421				obj.removeClass("jstree-open").addClass("jstree-closed");
38422				if(s) { obj.children("ul").stop(true).slideUp(s, function () { this.style.display = ""; }); }
38423				this.__callback({ "obj" : obj });
38424			},
38425			toggle_node	: function (obj) {
38426				obj = this._get_node(obj);
38427				if(obj.hasClass("jstree-closed")) { return this.open_node(obj); }
38428				if(obj.hasClass("jstree-open")) { return this.close_node(obj); }
38429			},
38430			open_all	: function (obj, original_obj) {
38431				obj = obj ? this._get_node(obj) : this.get_container();
38432				if(!obj || obj === -1) { obj = this.get_container(); }
38433				if(original_obj) { 
38434					obj = obj.find("li.jstree-closed");
38435				}
38436				else {
38437					original_obj = obj;
38438					if(obj.is(".jstree-closed")) { obj = obj.find("li.jstree-closed").andSelf(); }
38439					else { obj = obj.find("li.jstree-closed"); }
38440				}
38441				var _this = this;
38442				obj.each(function () { 
38443					var __this = this; 
38444					if(!_this._is_loaded(this)) { _this.open_node(this, function() { _this.open_all(__this, original_obj); }, true); }
38445					else { _this.open_node(this, false, true); }
38446				});
38447				// so that callback is fired AFTER all nodes are open
38448				if(original_obj.find('li.jstree-closed').length === 0) { this.__callback({ "obj" : original_obj }); }
38449			},
38450			close_all	: function (obj) {
38451				var _this = this;
38452				obj = obj ? this._get_node(obj) : this.get_container();
38453				if(!obj || obj === -1) { obj = this.get_container(); }
38454				obj.find("li.jstree-open").andSelf().each(function () { _this.close_node(this); });
38455				this.__callback({ "obj" : obj });
38456			},
38457			clean_node	: function (obj) {
38458				obj = obj && obj != -1 ? $(obj) : this.get_container();
38459				obj = obj.is("li") ? obj.find("li").andSelf() : obj.find("li");
38460				obj.removeClass("jstree-last")
38461					.filter("li:last-child").addClass("jstree-last").end()
38462					.filter(":has(li)")
38463						.not(".jstree-open").removeClass("jstree-leaf").addClass("jstree-closed");
38464				obj.not(".jstree-open, .jstree-closed").addClass("jstree-leaf").children("ul").remove();
38465				this.__callback({ "obj" : obj });
38466			},
38467			// rollback
38468			get_rollback : function () { 
38469				this.__callback();
38470				return { i : this.get_index(), h : this.get_container().children("ul").clone(true), d : this.data }; 
38471			},
38472			set_rollback : function (html, data) {
38473				this.get_container().empty().append(html);
38474				this.data = data;
38475				this.__callback();
38476			},
38477			// Dummy functions to be overwritten by any datastore plugin included
38478			load_node	: function (obj, s_call, e_call) { this.__callback({ "obj" : obj }); },
38479			_is_loaded	: function (obj) { return true; },
38480
38481			// Basic operations: create
38482			create_node	: function (obj, position, js, callback, is_loaded) {
38483				obj = this._get_node(obj);
38484				position = typeof position === "undefined" ? "last" : position;
38485				var d = $("<li>"),
38486					s = this._get_settings().core,
38487					tmp;
38488
38489				if(obj !== -1 && !obj.length) { return false; }
38490				if(!is_loaded && !this._is_loaded(obj)) { this.load_node(obj, function () { this.create_node(obj, position, js, callback, true); }); return false; }
38491
38492				this.__rollback();
38493
38494				if(typeof js === "string") { js = { "data" : js }; }
38495				if(!js) { js = {}; }
38496				if(js.attr) { d.attr(js.attr); }
38497				if(js.state) { d.addClass("jstree-" + js.state); }
38498				if(!js.data) { js.data = s.strings.new_node; }
38499				if(!$.isArray(js.data)) { tmp = js.data; js.data = []; js.data.push(tmp); }
38500				$.each(js.data, function (i, m) {
38501					tmp = $("<a>");
38502					if($.isFunction(m)) { m = m.call(this, js); }
38503					if(typeof m == "string") { tmp.attr('href','#')[ s.html_titles ? "html" : "text" ](m); }
38504					else {
38505						if(!m.attr) { m.attr = {}; }
38506						if(!m.attr.href) { m.attr.href = '#'; }
38507						tmp.attr(m.attr)[ s.html_titles ? "html" : "text" ](m.title);
38508						if(m.language) { tmp.addClass(m.language); }
38509					}
38510					tmp.prepend("<ins class='jstree-icon'>&#160;</ins>");
38511					if(m.icon) { 
38512						if(m.icon.indexOf("/") === -1) { tmp.children("ins").addClass(m.icon); }
38513						else { tmp.children("ins").css("background","url('" + m.icon + "') center center no-repeat"); }
38514					}
38515					d.append(tmp);
38516				});
38517				d.prepend("<ins class='jstree-icon'>&#160;</ins>");
38518				if(obj === -1) {
38519					obj = this.get_container();
38520					if(position === "before") { position = "first"; }
38521					if(position === "after") { position = "last"; }
38522				}
38523				switch(position) {
38524					case "before": obj.before(d); tmp = this._get_parent(obj); break;
38525					case "after" : obj.after(d);  tmp = this._get_parent(obj); break;
38526					case "inside":
38527					case "first" :
38528						if(!obj.children("ul").length) { obj.append("<ul>"); }
38529						obj.children("ul").prepend(d);
38530						tmp = obj;
38531						break;
38532					case "last":
38533						if(!obj.children("ul").length) { obj.append("<ul>"); }
38534						obj.children("ul").append(d);
38535						tmp = obj;
38536						break;
38537					default:
38538						if(!obj.children("ul").length) { obj.append("<ul>"); }
38539						if(!position) { position = 0; }
38540						tmp = obj.children("ul").children("li").eq(position);
38541						if(tmp.length) { tmp.before(d); }
38542						else { obj.children("ul").append(d); }
38543						tmp = obj;
38544						break;
38545				}
38546				if(tmp === -1 || tmp.get(0) === this.get_container().get(0)) { tmp = -1; }
38547				this.clean_node(tmp);
38548				this.__callback({ "obj" : d, "parent" : tmp });
38549				if(callback) { callback.call(this, d); }
38550				return d;
38551			},
38552			// Basic operations: rename (deal with text)
38553			get_text	: function (obj) {
38554				obj = this._get_node(obj);
38555				if(!obj.length) { return false; }
38556				var s = this._get_settings().core.html_titles;
38557				obj = obj.children("a:eq(0)");
38558				if(s) {
38559					obj = obj.clone();
38560					obj.children("INS").remove();
38561					return obj.html();
38562				}
38563				else {
38564					obj = obj.contents().filter(function() { return this.nodeType == 3; })[0];
38565					return obj.nodeValue;
38566				}
38567			},
38568			set_text	: function (obj, val) {
38569				obj = this._get_node(obj);
38570				if(!obj.length) { return false; }
38571				obj = obj.children("a:eq(0)");
38572				if(this._get_settings().core.html_titles) {
38573					var tmp = obj.children("INS").clone();
38574					obj.html(val).prepend(tmp);
38575					this.__callback({ "obj" : obj, "name" : val });
38576					return true;
38577				}
38578				else {
38579					obj = obj.contents().filter(function() { return this.nodeType == 3; })[0];
38580					this.__callback({ "obj" : obj, "name" : val });
38581					return (obj.nodeValue = val);
38582				}
38583			},
38584			rename_node : function (obj, val) {
38585				obj = this._get_node(obj);
38586				this.__rollback();
38587				if(obj && obj.length && this.set_text.apply(this, Array.prototype.slice.call(arguments))) { this.__callback({ "obj" : obj, "name" : val }); }
38588			},
38589			// Basic operations: deleting nodes
38590			delete_node : function (obj) {
38591				obj = this._get_node(obj);
38592				if(!obj.length) { return false; }
38593				this.__rollback();
38594				var p = this._get_parent(obj), prev = this._get_prev(obj);
38595				obj = obj.remove();
38596				if(p !== -1 && p.find("> ul > li").length === 0) {
38597					p.removeClass("jstree-open jstree-closed").addClass("jstree-leaf");
38598				}
38599				this.clean_node(p);
38600				this.__callback({ "obj" : obj, "prev" : prev });
38601				return obj;
38602			},
38603			prepare_move : function (o, r, pos, cb, is_cb) {
38604				var p = {};
38605
38606				p.ot = $.jstree._reference(p.o) || this;
38607				p.o = p.ot._get_node(o);
38608				p.r = r === - 1 ? -1 : this._get_node(r);
38609				p.p = (typeof p === "undefined") ? "last" : pos; // TODO: move to a setting
38610				if(!is_cb && prepared_move.o && prepared_move.o[0] === p.o[0] && prepared_move.r[0] === p.r[0] && prepared_move.p === p.p) {
38611					this.__callback(prepared_move);
38612					if(cb) { cb.call(this, prepared_move); }
38613					return;
38614				}
38615				p.ot = $.jstree._reference(p.o) || this;
38616				p.rt = r === -1 ? p.ot : $.jstree._reference(p.r) || this;
38617				if(p.r === -1) {
38618					p.cr = -1;
38619					switch(p.p) {
38620						case "first":
38621						case "before":
38622						case "inside":
38623							p.cp = 0; 
38624							break;
38625						case "after":
38626						case "last":
38627							p.cp = p.rt.get_container().find(" > ul > li").length; 
38628							break;
38629						default:
38630							p.cp = p.p;
38631							break;
38632					}
38633				}
38634				else {
38635					if(!/^(before|after)$/.test(p.p) && !this._is_loaded(p.r)) {
38636						return this.load_node(p.r, function () { this.prepare_move(o, r, pos, cb, true); });
38637					}
38638					switch(p.p) {
38639						case "before":
38640							p.cp = p.r.index();
38641							p.cr = p.rt._get_parent(p.r);
38642							break;
38643						case "after":
38644							p.cp = p.r.index() + 1;
38645							p.cr = p.rt._get_parent(p.r);
38646							break;
38647						case "inside":
38648						case "first":
38649							p.cp = 0;
38650							p.cr = p.r;
38651							break;
38652						case "last":
38653							p.cp = p.r.find(" > ul > li").length; 
38654							p.cr = p.r;
38655							break;
38656						default: 
38657							p.cp = p.p;
38658							p.cr = p.r;
38659							break;
38660					}
38661				}
38662				p.np = p.cr == -1 ? p.rt.get_container() : p.cr;
38663				p.op = p.ot._get_parent(p.o);
38664				p.or = p.np.find(" > ul > li:nth-child(" + (p.cp + 1) + ")");
38665
38666				prepared_move = p;
38667				this.__callback(prepared_move);
38668				if(cb) { cb.call(this, prepared_move); }
38669			},
38670			check_move : function () {
38671				var obj = prepared_move, ret = true;
38672				if(obj.or[0] === obj.o[0]) { return false; }
38673				obj.o.each(function () { 
38674					if(obj.r.parentsUntil(".jstree").andSelf().filter("li").index(this) !== -1) { ret = false; return false; }
38675				});
38676				return ret;
38677			},
38678			move_node : function (obj, ref, position, is_copy, is_prepared, skip_check) {
38679				if(!is_prepared) { 
38680					return this.prepare_move(obj, ref, position, function (p) {
38681						this.move_node(p, false, false, is_copy, true, skip_check);
38682					});
38683				}
38684				if(!skip_check && !this.check_move()) { return false; }
38685
38686				this.__rollback();
38687				var o = false;
38688				if(is_copy) {
38689					o = obj.o.clone();
38690					o.find("*[id]").andSelf().each(function () {
38691						if(this.id) { this.id = "copy_" + this.id; }
38692					});
38693				}
38694				else { o = obj.o; }
38695
38696				if(obj.or.length) { obj.or.before(o); }
38697				else { 
38698					if(!obj.np.children("ul").length) { $("<ul>").appendTo(obj.np); }
38699					obj.np.children("ul:eq(0)").append(o); 
38700				}
38701
38702				try { 
38703					obj.ot.clean_node(obj.op);
38704					obj.rt.clean_node(obj.np);
38705					if(!obj.op.find("> ul > li").length) {
38706						obj.op.removeClass("jstree-open jstree-closed").addClass("jstree-leaf").children("ul").remove();
38707					}
38708				} catch (e) { }
38709
38710				if(is_copy) { 
38711					prepared_move.cy = true;
38712					prepared_move.oc = o; 
38713				}
38714				this.__callback(prepared_move);
38715				return prepared_move;
38716			},
38717			_get_move : function () { return prepared_move; }
38718		}
38719	});
38720})(jQuery);
38721//*/
38722
38723/* 
38724 * jsTree ui plugin 1.0
38725 * This plugins handles selecting/deselecting/hovering/dehovering nodes
38726 */
38727(function ($) {
38728	$.jstree.plugin("ui", {
38729		__init : function () { 
38730			this.data.ui.selected = $(); 
38731			this.data.ui.last_selected = false; 
38732			this.data.ui.hovered = null;
38733			this.data.ui.to_select = this.get_settings().ui.initially_select;
38734
38735			this.get_container()
38736			    .delegate("a", "click.jstree", $.proxy(function (event) {
38737				    // SENAD: don't trigger select node on checkbox
38738			      if (!$(event.target).hasClass('jstree-checkbox'))
38739            {
38740			        event.preventDefault();
38741	            this.select_node(event.currentTarget, true, event);
38742	          }
38743					}, this))
38744				.delegate("a", "mouseenter.jstree", $.proxy(function (event) {
38745						this.hover_node(event.target);
38746					}, this))
38747				.delegate("a", "mouseleave.jstree", $.proxy(function (event) {
38748						this.dehover_node(event.target);
38749					}, this))
38750				.bind("reopen.jstree", $.proxy(function () { 
38751						this.reselect();
38752					}, this))
38753				.bind("get_rollback.jstree", $.proxy(function () { 
38754						this.dehover_node();
38755						this.save_selected();
38756					}, this))
38757				.bind("set_rollback.jstree", $.proxy(function () { 
38758						this.reselect();
38759					}, this))
38760				.bind("close_node.jstree", $.proxy(function (event, data) { 
38761						var s = this._get_settings().ui,
38762							obj = this._get_node(data.rslt.obj),
38763							clk = (obj && obj.length) ? obj.children("ul").find(".jstree-clicked") : $(),
38764							_this = this;
38765						if(s.selected_parent_close === false || !clk.length) { return; }
38766						clk.each(function () { 
38767							_this.deselect_node(this);
38768							if(s.selected_parent_close === "select_parent") { _this.select_node(obj); }
38769						});
38770					}, this))
38771				.bind("delete_node.jstree", $.proxy(function (event, data) { 
38772						var s = this._get_settings().ui.select_prev_on_delete,
38773							obj = this._get_node(data.rslt.obj),
38774							clk = (obj && obj.length) ? obj.find(".jstree-clicked") : [],
38775							_this = this;
38776						clk.each(function () { _this.deselect_node(this); });
38777						if(s && clk.length) { this.select_node(data.rslt.prev); }
38778					}, this))
38779				.bind("move_node.jstree", $.proxy(function (event, data) { 
38780						if(data.rslt.cy) { 
38781							data.rslt.oc.find(".jstree-clicked").removeClass("jstree-clicked");
38782						}
38783					}, this));
38784		},
38785		defaults : {
38786			select_limit : -1, // 0, 1, 2 ... or -1 for unlimited
38787			select_multiple_modifier : "ctrl", // on, or ctrl, shift, alt
38788			select_range_modifier : "shift",
38789			selected_parent_close : "select_parent", // false, "deselect", "select_parent"
38790			select_prev_on_delete : true,
38791			disable_selecting_children : false,
38792			initially_select : []
38793		},
38794		_fn : { 
38795			_get_node : function (obj, allow_multiple) {
38796				if(typeof obj === "undefined" || obj === null) { return allow_multiple ? this.data.ui.selected : this.data.ui.last_selected; }
38797				var $obj = $(obj, this.get_container()); 
38798				if($obj.is(".jstree") || obj == -1) { return -1; } 
38799				$obj = $obj.closest("li", this.get_container()); 
38800				return $obj.length ? $obj : false; 
38801			},
38802			save_selected : function () {
38803				var _this = this;
38804				this.data.ui.to_select = [];
38805				this.data.ui.selected.each(function () { _this.data.ui.to_select.push("#" + this.id.toString().replace(/^#/,"").replace('\\/','/').replace('/','\\/')); });
38806				this.__callback(this.data.ui.to_select);
38807			},
38808			reselect : function () {
38809				var _this = this,
38810					s = this.data.ui.to_select;
38811				s = $.map($.makeArray(s), function (n) { return "#" + n.toString().replace(/^#/,"").replace('\\/','/').replace('/','\\/'); });
38812				this.deselect_all();
38813				$.each(s, function (i, val) { if(val && val !== "#") { _this.select_node(val); } });
38814				this.__callback();
38815			},
38816			refresh : function (obj) {
38817				this.save_selected();
38818				return this.__call_old();
38819			},
38820			hover_node : function (obj) {
38821				obj = this._get_node(obj);
38822				if(!obj.length) { return false; }
38823				//if(this.data.ui.hovered && obj.get(0) === this.data.ui.hovered.get(0)) { return; }
38824				if(!obj.hasClass("jstree-hovered")) { this.dehover_node(); }
38825				this.data.ui.hovered = obj.children("a").addClass("jstree-hovered").parent();
38826			  this.__callback({ "obj" : obj });
38827			},
38828			dehover_node : function () {
38829				var obj = this.data.ui.hovered, p;
38830				if(!obj || !obj.length) { return false; }
38831				p = obj.children("a").removeClass("jstree-hovered").parent();
38832				if(this.data.ui.hovered[0] === p[0]) { this.data.ui.hovered = null; }
38833				this.__callback({ "obj" : obj });
38834			},
38835			select_node : function (obj, check, e) {
38836				obj = this._get_node(obj);
38837				if(obj == -1 || !obj || !obj.length) { return false; }
38838				var s = this._get_settings().ui,
38839					is_multiple = (s.select_multiple_modifier == "on" || (s.select_multiple_modifier !== false && e && e[s.select_multiple_modifier + "Key"])),
38840          is_range = (s.select_range_modifier !== false && e && e[s.select_range_modifier + "Key"] && 
38841                      this.data.ui.last_selected && this.data.ui.last_selected[0] !== obj[0] && this.data.ui.last_selected.parent()[0] === obj.parent()[0]),
38842					is_selected = this.is_selected(obj),
38843					proceed = true,
38844          t = this;
38845				if(check) {
38846					if(s.disable_selecting_children && is_multiple && obj.parents("li", this.get_container()).children(".jstree-clicked").length) {
38847						return false;
38848					}
38849					proceed = false;
38850					switch(!0) {
38851            case (is_range):
38852               this.data.ui.last_selected.addClass("jstree-last-selected");
38853               obj = obj[ obj.index() < this.data.ui.last_selected.index() ? "nextUntil" : "prevUntil" ](".jstree-last-selected").andSelf();
38854               this.data.ui.last_selected.removeClass("jstree-last-selected");
38855               this.data.ui.selected.each(function () {
38856                 if(this !== t.data.ui.last_selected[0]) { t.deselect_node(this); }
38857               });
38858               is_selected = false;
38859               proceed = true;
38860               break;
38861						case (is_selected && !is_multiple): 
38862							this.deselect_all();
38863							is_selected = false;
38864							proceed = true;
38865							break;
38866						case (!is_selected && !is_multiple): 
38867							if(s.select_limit == -1 || s.select_limit > 0) {
38868								this.deselect_all();
38869								proceed = true;
38870							}
38871							break;
38872						case (is_selected && is_multiple): 
38873							this.deselect_node(obj);
38874							break;
38875						case (!is_selected && is_multiple): 
38876							if(s.select_limit == -1 || this.data.ui.selected.length + 1 <= s.select_limit) { 
38877								proceed = true;
38878							}
38879							break;
38880					}
38881				}
38882				if(proceed && !is_selected) {
38883          if(!is_range) { this.data.ui.last_selected = obj; }
38884					obj.children("a").addClass("jstree-clicked");
38885					this.data.ui.selected = this.data.ui.selected.add(obj);
38886					this.__callback({ "obj" : obj });
38887				}
38888			},
38889			deselect_node : function (obj) {
38890				obj = this._get_node(obj);
38891				if(!obj.length) { return false; }
38892				if(this.is_selected(obj)) {
38893					obj.children("a").removeClass("jstree-clicked");
38894					this.data.ui.selected = this.data.ui.selected.not(obj);
38895					if(this.data.ui.last_selected.get(0) === obj.get(0)) { this.data.ui.last_selected = this.data.ui.selected.eq(0); }
38896					this.__callback({ "obj" : obj });
38897				}
38898			},
38899			toggle_select : function (obj) {
38900				obj = this._get_node(obj);
38901				if(!obj.length) { return false; }
38902				if(this.is_selected(obj)) { this.deselect_node(obj); }
38903				else { this.select_node(obj); }
38904			},
38905			is_selected : function (obj) { return this.data.ui.selected.index(this._get_node(obj)) >= 0; },
38906			get_selected : function (context) { 
38907				return context ? $(context).find(".jstree-clicked").parent() : this.data.ui.selected; 
38908			},
38909			deselect_all : function (context) {
38910				if(context) { $(context).find(".jstree-clicked").removeClass("jstree-clicked"); } 
38911				else { this.get_container().find(".jstree-clicked").removeClass("jstree-clicked"); }
38912				this.data.ui.selected = $([]);
38913				this.data.ui.last_selected = false;
38914				this.__callback();
38915			}
38916		}
38917	});
38918	// include the selection plugin by default
38919	$.jstree.defaults.plugins.push("ui");
38920})(jQuery);
38921//*/
38922
38923/* 
38924 * jsTree CRRM plugin 1.0
38925 * Handles creating/renaming/removing/moving nodes by user interaction.
38926 */
38927(function ($) {
38928	$.jstree.plugin("crrm", { 
38929		__init : function () {
38930			this.get_container()
38931				.bind("move_node.jstree", $.proxy(function (e, data) {
38932					if(this._get_settings().crrm.move.open_onmove) {
38933						var t = this;
38934						data.rslt.np.parentsUntil(".jstree").andSelf().filter(".jstree-closed").each(function () {
38935							t.open_node(this, false, true);
38936						});
38937					}
38938				}, this));
38939		},
38940		defaults : {
38941			input_width_limit : 200,
38942			move : {
38943				always_copy			: false, // false, true or "multitree"
38944				open_onmove			: true,
38945				default_position	: "last",
38946				check_move			: function (m) { return true; }
38947			}
38948		},
38949		_fn : {
38950			_show_input : function (obj, callback) {
38951				obj = this._get_node(obj);
38952				var rtl = this._get_settings().core.rtl,
38953					w = this._get_settings().crrm.input_width_limit,
38954					w1 = obj.children("ins").width(),
38955					w2 = obj.find("> a:visible > ins").width() * obj.find("> a:visible > ins").length,
38956					t = this.get_text(obj),
38957					h1 = $("<div>", { css : { "position" : "absolute", "top" : "-200px", "left" : (rtl ? "0px" : "-1000px"), "visibility" : "hidden" } }).appendTo("body"),
38958					h2 = obj.css("position","relative").append(
38959					$("<input>", { 
38960						"value" : t,
38961						// "size" : t.length,
38962						"css" : {
38963							"padding" : "0",
38964							"border" : "1px solid silver",
38965							"position" : "absolute",
38966							"left"  : (rtl ? "auto" : (w1 + w2 + 4) + "px"),
38967							"right" : (rtl ? (w1 + w2 + 4) + "px" : "auto"),
38968							"top" : "0px",
38969							"height" : (this.data.core.li_height - 2) + "px",
38970							"lineHeight" : (this.data.core.li_height - 2) + "px",
38971							"width" : "150px" // will be set a bit further down
38972						},
38973						"blur" : $.proxy(function () {
38974							var i = obj.children("input"),
38975								v = i.val();
38976							if(v === "") { v = t; }
38977							i.remove(); // rollback purposes
38978							this.set_text(obj,t); // rollback purposes
38979							this.rename_node(obj, v);
38980							callback.call(this, obj, v, t);
38981							obj.css("position","");
38982						}, this),
38983						"keyup" : function (event) {
38984							var key = event.keyCode || event.which;
38985							if(key == 27) { this.value = t; this.blur(); return; }
38986							else if(key == 13) { this.blur(); return; }
38987							else {
38988								h2.width(Math.min(h1.text("pW" + this.value).width(),w));
38989							}
38990						}
38991					})
38992				).children("input"); 
38993				this.set_text(obj, "");
38994				h1.css({
38995						fontFamily		: h2.css('fontFamily')		|| '',
38996						fontSize		: h2.css('fontSize')		|| '',
38997						fontWeight		: h2.css('fontWeight')		|| '',
38998						fontStyle		: h2.css('fontStyle')		|| '',
38999						fontStretch		: h2.css('fontStretch')		|| '',
39000						fontVariant		: h2.css('fontVariant')		|| '',
39001						letterSpacing	: h2.css('letterSpacing')	|| '',
39002						wordSpacing		: h2.css('wordSpacing')		|| ''
39003				});
39004				h2.width(Math.min(h1.text("pW" + h2[0].value).width(),w))[0].select();
39005			},
39006			rename : function (obj) {
39007				obj = this._get_node(obj);
39008				this.__rollback();
39009				var f = this.__callback;
39010				this._show_input(obj, function (obj, new_name, old_name) { 
39011					f.call(this, { "obj" : obj, "new_name" : new_name, "old_name" : old_name });
39012				});
39013			},
39014			create : function (obj, position, js, callback, skip_rename) {
39015				var t, _this = this;
39016				obj = this._get_node(obj);
39017				if(!obj) { obj = -1; }
39018				this.__rollback();
39019				t = this.create_node(obj, position, js, function (t) {
39020					var p = this._get_parent(t),
39021						pos = $(t).index();
39022					if(callback) { callback.call(this, t); }
39023					if(p.length && p.hasClass("jstree-closed")) { this.open_node(p, false, true); }
39024					if(!skip_rename) { 
39025						this._show_input(t, function (obj, new_name, old_name) { 
39026							_this.__callback({ "obj" : obj, "name" : new_name, "parent" : p, "position" : pos });
39027						});
39028					}
39029					else { _this.__callback({ "obj" : t, "name" : this.get_text(t), "parent" : p, "position" : pos }); }
39030				});
39031				return t;
39032			},
39033			remove : function (obj) {
39034				obj = this._get_node(obj, true);
39035				this.__rollback();
39036				this.delete_node(obj);
39037				this.__callback({ "obj" : obj });
39038			},
39039			check_move : function () {
39040				if(!this.__call_old()) { return false; }
39041				var s = this._get_settings().crrm.move;
39042				if(!s.check_move.call(this, this._get_move())) { return false; }
39043				return true;
39044			},
39045			move_node : function (obj, ref, position, is_copy, is_prepared, skip_check) {
39046				var s = this._get_settings().crrm.move;
39047				if(!is_prepared) { 
39048					if(!position) { position = s.default_position; }
39049					if(position === "inside" && !s.default_position.match(/^(before|after)$/)) { position = s.default_position; }
39050					return this.__call_old(true, obj, ref, position, is_copy, false, skip_check);
39051				}
39052				// if the move is already prepared
39053				if(s.always_copy === true || (s.always_copy === "multitree" && obj.rt.get_index() !== obj.ot.get_index() )) {
39054					is_copy = true;
39055				}
39056				this.__call_old(true, obj, ref, position, is_copy, true, skip_check);
39057			},
39058
39059			cut : function (obj) {
39060				obj = this._get_node(obj);
39061				this.data.crrm.cp_nodes = false;
39062				this.data.crrm.ct_nodes = false;
39063				if(!obj || !obj.length) { return false; }
39064				this.data.crrm.ct_nodes = obj;
39065			},
39066			copy : function (obj) {
39067				obj = this._get_node(obj);
39068				this.data.crrm.cp_nodes = false;
39069				this.data.crrm.ct_nodes = false;
39070				if(!obj || !obj.length) { return false; }
39071				this.data.crrm.cp_nodes = obj;
39072			},
39073			paste : function (obj) { 
39074				obj = this._get_node(obj);
39075				if(!obj || !obj.length) { return false; }
39076				if(!this.data.crrm.ct_nodes && !this.data.crrm.cp_nodes) { return false; }
39077				if(this.data.crrm.ct_nodes) { this.move_node(this.data.crrm.ct_nodes, obj); }
39078				if(this.data.crrm.cp_nodes) { this.move_node(this.data.crrm.cp_nodes, obj, false, true); }
39079				this.data.crrm.cp_nodes = false;
39080				this.data.crrm.ct_nodes = false;
39081			}
39082		}
39083	});
39084	// include the crr plugin by default
39085	$.jstree.defaults.plugins.push("crrm");
39086})(jQuery);
39087
39088/* 
39089 * jsTree themes plugin 1.0
39090 * Handles loading and setting themes, as well as detecting path to themes, etc.
39091 */
39092(function ($) {
39093	var themes_loaded = [];
39094	// this variable stores the path to the themes folder - if left as false - it will be autodetected
39095	$.jstree._themes = false;
39096	$.jstree.plugin("themes", {
39097		__init : function () { 
39098			this.get_container()
39099				.bind("init.jstree", $.proxy(function () {
39100						var s = this._get_settings().themes;
39101						this.data.themes.dots = s.dots; 
39102						this.data.themes.icons = s.icons; 
39103						//alert(s.dots);
39104						this.set_theme(s.theme, s.url);
39105					}, this))
39106				.bind("loaded.jstree", $.proxy(function () {
39107						// bound here too, as simple HTML tree's won't honor dots & icons otherwise
39108						if(!this.data.themes.dots) { this.hide_dots(); }
39109						else { this.show_dots(); }
39110						if(!this.data.themes.icons) { this.hide_icons(); }
39111						else { this.show_icons(); }
39112					}, this));
39113		},
39114		defaults : { 
39115			theme : "default", 
39116			url : false,
39117			dots : true,
39118			icons : true
39119		},
39120		_fn : {
39121			set_theme : function (theme_name, theme_url) {
39122				if(!theme_name) { return false; }
39123				if(!theme_url) { theme_url = $.jstree._themes + theme_name + '/style.css'; }
39124				if($.inArray(theme_url, themes_loaded) == -1) {
39125					$.vakata.css.add_sheet({ "url" : theme_url, "rel" : "jstree" });
39126					themes_loaded.push(theme_url);
39127				}
39128				if(this.data.themes.theme != theme_name) {
39129					this.get_container().removeClass('jstree-' + this.data.themes.theme);
39130					this.data.themes.theme = theme_name;
39131				}
39132				this.get_container().addClass('jstree-' + theme_name);
39133				if(!this.data.themes.dots) { this.hide_dots(); }
39134				else { this.show_dots(); }
39135				if(!this.data.themes.icons) { this.hide_icons(); }
39136				else { this.show_icons(); }
39137				this.__callback();
39138			},
39139			get_theme	: function () { return this.data.themes.theme; },
39140
39141			show_dots	: function () { this.data.themes.dots = true; this.get_container().children("ul").removeClass("jstree-no-dots"); },
39142			hide_dots	: function () { this.data.themes.dots = false; this.get_container().children("ul").addClass("jstree-no-dots"); },
39143			toggle_dots	: function () { if(this.data.themes.dots) { this.hide_dots(); } else { this.show_dots(); } },
39144
39145			show_icons	: function () { this.data.themes.icons = true; this.get_container().children("ul").removeClass("jstree-no-icons"); },
39146			hide_icons	: function () { this.data.themes.icons = false; this.get_container().children("ul").addClass("jstree-no-icons"); },
39147			toggle_icons: function () { if(this.data.themes.icons) { this.hide_icons(); } else { this.show_icons(); } }
39148		}
39149	});
39150	// autodetect themes path
39151	$(function () {
39152		if($.jstree._themes === false) {
39153			$("script").each(function () { 
39154				if(this.src.toString().match(/jquery\.jstree[^\/]*?\.js(\?.*)?$/)) { 
39155					$.jstree._themes = this.src.toString().replace(/jquery\.jstree[^\/]*?\.js(\?.*)?$/, "") + 'themes/'; 
39156					return false; 
39157				}
39158			});
39159		}
39160		if($.jstree._themes === false) { $.jstree._themes = "/javascripts/jsTree/themes/"; }
39161	});
39162	// include the themes plugin by default
39163	$.jstree.defaults.plugins.push("themes");
39164})(jQuery);
39165//*/
39166
39167/*
39168 * jsTree hotkeys plugin 1.0
39169 * Enables keyboard navigation for all tree instances
39170 * Depends on the jstree ui & jquery hotkeys plugins
39171 */
39172(function ($) {
39173	var bound = [];
39174	function exec(i, event) {
39175		var f = $.jstree._focused(), tmp;
39176		if(f && f.data && f.data.hotkeys && f.data.hotkeys.enabled) { 
39177			tmp = f._get_settings().hotkeys[i];
39178			if(tmp) { return tmp.call(f, event); }
39179		}
39180	}
39181	$.jstree.plugin("hotkeys", {
39182		__init : function () {
39183			if(typeof $.hotkeys === "undefined") { throw "jsTree hotkeys: jQuery hotkeys plugin not included."; }
39184			if(!this.data.ui) { throw "jsTree hotkeys: jsTree UI plugin not included."; }
39185			$.each(this._get_settings().hotkeys, function (i, val) {
39186				if($.inArray(i, bound) == -1) {
39187					$(document).bind("keydown", i, function (event) { return exec(i, event); });
39188					bound.push(i);
39189				}
39190			});
39191			this.enable_hotkeys();
39192		},
39193		defaults : {
39194			"up" : function () { 
39195				var o = this.data.ui.hovered || this.data.ui.last_selected || -1;
39196				this.hover_node(this._get_prev(o));
39197				return false; 
39198			},
39199			"down" : function () { 
39200				var o = this.data.ui.hovered || this.data.ui.last_selected || -1;
39201				this.hover_node(this._get_next(o));
39202				return false;
39203			},
39204			"left" : function () { 
39205				var o = this.data.ui.hovered || this.data.ui.last_selected;
39206				if(o) {
39207					if(o.hasClass("jstree-open")) { this.close_node(o); }
39208					else { this.hover_node(this._get_prev(o)); }
39209				}
39210				return false;
39211			},
39212			"right" : function () { 
39213				var o = this.data.ui.hovered || this.data.ui.last_selected;
39214				if(o && o.length) {
39215					if(o.hasClass("jstree-closed")) { this.open_node(o); }
39216					else { this.hover_node(this._get_next(o)); }
39217				}
39218				return false;
39219			},
39220			"space" : function () { 
39221				if(this.data.ui.hovered) { this.data.ui.hovered.children("a:eq(0)").click(); } 
39222				return false; 
39223			},
39224			"ctrl+space" : function (event) { 
39225				event.type = "click";
39226				if(this.data.ui.hovered) { this.data.ui.hovered.children("a:eq(0)").trigger(event); } 
39227				return false; 
39228			},
39229			"f2" : function () { this.rename(this.data.ui.hovered || this.data.ui.last_selected); },
39230			"del" : function () { this.remove(this.data.ui.hovered || this._get_node(null)); }
39231		},
39232		_fn : {
39233			enable_hotkeys : function () {
39234				this.data.hotkeys.enabled = true;
39235			},
39236			disable_hotkeys : function () {
39237				this.data.hotkeys.enabled = false;
39238			}
39239		}
39240	});
39241})(jQuery);
39242//*/
39243
39244/* 
39245 * jsTree JSON 1.0
39246 * The JSON data store. Datastores are build by overriding the `load_node` and `_is_loaded` functions.
39247 */
39248(function ($) {
39249	$.jstree.plugin("json_data", {
39250		defaults : { 
39251	    // SENAD: chrome_extension: if set to true, then we call ajax calls via chrome.extension.sendRequest  
39252	    chrome_extension: false,
39253			data : false,
39254			ajax : false,
39255			correct_state : true,
39256			progressive_render : false
39257		},
39258		_fn : {
39259			load_node : function (obj, s_call, e_call) { 
39260		    var _this = this; 
39261		    this.load_node_json(obj, 
39262		      function () { 
39263		        _this.__callback({ "obj" : obj }); 
39264		        s_call.call(this); }, e_call); 
39265		    },
39266			_is_loaded : function (obj) { 
39267				var s = this._get_settings().json_data, d;
39268				obj = this._get_node(obj); 
39269				if(obj && obj !== -1 && s.progressive_render && !obj.is(".jstree-open, .jstree-leaf") && obj.children("ul").children("li").length === 0 && obj.data("jstree-children")) {
39270					d = this._parse_json(obj.data("jstree-children"));
39271					if(d) {
39272						obj.append(d);
39273						$.removeData(obj, "jstree-children");
39274					}
39275					this.clean_node(obj);
39276					return true;
39277				}
39278				return obj == -1 || !obj || !s.ajax || obj.is(".jstree-open, .jstree-leaf") || obj.children("ul").children("li").size() > 0;
39279			},
39280			load_node_json : function (obj, s_call, e_call) {
39281				var s = this.get_settings().json_data, d,
39282					error_func = function () {},
39283					success_func = function () {};
39284				obj = this._get_node(obj);
39285				if(obj && obj !== -1) {
39286					if(obj.data("jstree-is-loading")) { return; }
39287					else { obj.data("jstree-is-loading",true); }
39288				}
39289				switch(!0) {
39290					case (!s.data && !s.ajax): throw "Neither data nor ajax settings supplied.";
39291					case (!!s.data && !s.ajax) || (!!s.data && !!s.ajax && (!obj || obj === -1)):
39292						if(!obj || obj == -1) {
39293							d = this._parse_json(s.data);
39294							if(d) {
39295								this.get_container().children("ul").empty().append(d.children());
39296								this.clean_node();
39297							}
39298							else { 
39299								if(s.correct_state) { this.get_container().children("ul").empty(); }
39300							}
39301						}
39302						if(s_call) { s_call.call(this); }
39303						break;
39304					case (!s.data && !!s.ajax) || (!!s.data && !!s.ajax && obj && obj !== -1):
39305						error_func = function (x, t, e) {
39306							var ef = this.get_settings().json_data.ajax.error; 
39307							if(ef) { ef.call(this, x, t, e); }
39308							if(obj != -1 && obj.length) {
39309								obj.children(".jstree-loading").removeClass("jstree-loading");
39310								obj.data("jstree-is-loading",false);
39311								if(t === "success" && s.correct_state) { obj.removeClass("jstree-open jstree-closed").addClass("jstree-leaf"); }
39312							}
39313							else {
39314								if(t === "success" && s.correct_state) { this.get_container().children("ul").empty(); }
39315							}
39316							if(e_call) { e_call.call(this); }
39317						};
39318						success_func = function (d, t, x) {
39319							var sf = this.get_settings().json_data.ajax.success; 
39320							if(sf) { d = sf.call(this,d,t,x) || d; }
39321							if(d === "" || (!$.isArray(d) && !$.isPlainObject(d))) {
39322								return error_func.call(this, x, t, "");
39323							}
39324							d = this._parse_json(d);
39325							if(d) {
39326								if(obj === -1 || !obj) { this.get_container().children("ul").empty().append(d.children()); }
39327								else { obj.append(d).children(".jstree-loading").removeClass("jstree-loading"); obj.data("jstree-is-loading",false); }
39328								this.clean_node(obj);
39329								if(s_call) { s_call.call(this); }
39330							}
39331							else {
39332								if(obj === -1 || !obj) {
39333									if(s.correct_state) { 
39334										this.get_container().children("ul").empty(); 
39335										if(s_call) { s_call.call(this); }
39336									}
39337								}
39338								else {
39339									obj.children(".jstree-loading").removeClass("jstree-loading");
39340									obj.data("jstree-is-loading",false);
39341									if(s.correct_state) { 
39342										obj.removeClass("jstree-open jstree-closed").addClass("jstree-leaf"); 
39343										if(s_call) { s_call.call(this); } 
39344									}
39345								}
39346							}
39347						};
39348            s.ajax.context = this;
39349            if(!s.ajax.dataType) { s.ajax.dataType = "json"; }
39350            if($.isFunction(s.ajax.url)) { s.ajax.url = s.ajax.url.call(this, obj); }
39351            if($.isFunction(s.ajax.data)) { s.ajax.data = s.ajax.data.call(this, obj); }
39352            
39353						// SENAD: 
39354						// In case when chrome_extension flag is set, we using background.html to execute
39355						// our ajax since we cannot do cross-domain calls from inserted page.
39356						// See backgound.js for how we are processing.
39357						if (s.chrome_extension)	{
39358						  var context = this;
39359						  s.ajax.error = null;
39360						  s.ajax.success = null;
39361						  s.ajax.context = null;
39362						  chrome.extension.sendRequest({'action_name' : 'fn_ajax', 'action_params': s.ajax}, 
39363						      function(data) {
39364						        try { 
39365						          if (data == null)
39366						            throw('Failed to call fn_ajax. Unable to connect to background.html');
39367						          if (data.error)
39368						            throw('Action fn_ajax failed. error: '+ data.error);
39369						          success_func.call(context, data.result.s, data.result.t, data.result.x);
39370						        } catch(e) {
39371						          error_func.call(context, null, null, null);
39372						        }
39373						      }  
39374						    ); 
39375						}
39376						else {
39377	            s.ajax.error = error_func;
39378	            s.ajax.success = success_func;
39379  						$.ajax(s.ajax);
39380						}
39381						break;
39382				}
39383			},
39384			_parse_json : function (js, is_callback) {
39385				var d = false, 
39386					p = this._get_settings(),
39387					s = p.json_data,
39388					t = p.core.html_titles,
39389					tmp, i, j, ul1, ul2;
39390
39391				if(!js) { return d; }
39392				if($.isFunction(js)) { 
39393					js = js.call(this);
39394				}
39395				if($.isArray(js)) {
39396					d = $();
39397					if(!js.length) { return false; }
39398					for(i = 0, j = js.length; i < j; i++) {
39399						tmp = this._parse_json(js[i], true);
39400						if(tmp.length) { d = d.add(tmp); }
39401					}
39402				}
39403				else {
39404					if(typeof js == "string") { js = { data : js }; }
39405					if(!js.data && js.data !== "") { return d; }
39406					d = $("<li>");
39407					if(js.attr) { d.attr(js.attr); }
39408					if(js.metadata) { d.data("jstree", js.metadata); }
39409					if(js.state) { d.addClass("jstree-" + js.state); }
39410					if(!$.isArray(js.data)) { tmp = js.data; js.data = []; js.data.push(tmp); }
39411					$.each(js.data, function (i, m) {
39412						tmp = $("<a>");
39413						if($.isFunction(m)) { m = m.call(this, js); }
39414						if(typeof m == "string") { tmp.attr('href','#')[ t ? "html" : "text" ](m); }
39415						else {
39416							if(!m.attr) { m.attr = {}; }
39417							if(!m.attr.href) { m.attr.href = '#'; }
39418							tmp.attr(m.attr)[ t ? "html" : "text" ](m.title);
39419							if(m.language) { tmp.addClass(m.language); }
39420						}
39421						tmp.prepend("<ins class='jstree-icon'>&#160;</ins>");
39422						if(!m.icon && js.icon) { m.icon = js.icon; }
39423						if(m.icon) { 
39424							if(m.icon.indexOf("/") === -1) { tmp.children("ins").addClass(m.icon); }
39425							else { tmp.children("ins").css("background","url('" + m.icon + "') center center no-repeat"); }
39426						}
39427						d.append(tmp);
39428					});
39429					d.prepend("<ins class='jstree-icon'>&#160;</ins>");
39430					if(js.children) { 
39431						if(s.progressive_render && js.state !== "open") {
39432							d.addClass("jstree-closed").data("jstree-children", js.children);
39433						}
39434						else {
39435							if($.isFunction(js.children)) {
39436								js.children = js.children.call(this, js);
39437							}
39438							if($.isArray(js.children) && js.children.length) {
39439								tmp = this._parse_json(js.children, true);
39440								if(tmp.length) {
39441									ul2 = $("<ul>");
39442									ul2.append(tmp);
39443									d.append(ul2);
39444								}
39445							}
39446						}
39447					}
39448				}
39449				if(!is_callback) {
39450					ul1 = $("<ul>");
39451					ul1.append(d);
39452					d = ul1;
39453				}
39454				return d;
39455			},
39456			get_json : function (obj, li_attr, a_attr, is_callback) {
39457				var result = [], 
39458					s = this._get_settings(), 
39459					_this = this,
39460					tmp1, tmp2, li, a, t, lang;
39461				obj = this._get_node(obj);
39462				if(!obj || obj === -1) { obj = this.get_container().find("> ul > li"); }
39463				li_attr = $.isArray(li_attr) ? li_attr : [ "id", "class" ];
39464				if(!is_callback && this.data.types) { li_attr.push(s.types.type_attr); }
39465				a_attr = $.isArray(a_attr) ? a_attr : [ ];
39466
39467				obj.each(function () {
39468					li = $(this);
39469					tmp1 = { data : [] };
39470					if(li_attr.length) { tmp1.attr = { }; }
39471					$.each(li_attr, function (i, v) { 
39472						tmp2 = li.attr(v); 
39473						if(tmp2 && tmp2.length && tmp2.replace(/jstree[^ ]*|$/ig,'').length) {
39474							tmp1.attr[v] = tmp2.replace(/jstree[^ ]*|$/ig,''); 
39475						}
39476					});
39477					if(li.hasClass("jstree-open")) { tmp1.state = "open"; }
39478					if(li.hasClass("jstree-closed")) { tmp1.state = "closed"; }
39479					a = li.children("a");
39480					a.each(function () {
39481						t = $(this);
39482						if(
39483							a_attr.length || 
39484							$.inArray("languages", s.plugins) !== -1 || 
39485							t.children("ins").get(0).style.backgroundImage.length || 
39486							(t.children("ins").get(0).className && t.children("ins").get(0).className.replace(/jstree[^ ]*|$/ig,'').length)
39487						) { 
39488							lang = false;
39489							if($.inArray("languages", s.plugins) !== -1 && $.isArray(s.languages) && s.languages.length) {
39490								$.each(s.languages, function (l, lv) {
39491									if(t.hasClass(lv)) {
39492										lang = lv;
39493										return false;
39494									}
39495								});
39496							}
39497							tmp2 = { attr : { }, title : _this.get_text(t, lang) }; 
39498							$.each(a_attr, function (k, z) {
39499								tmp1.attr[z] = (t.attr(z) || "").replace(/jstree[^ ]*|$/ig,'');
39500							});
39501							$.each(s.languages, function (k, z) {
39502								if(t.hasClass(z)) { tmp2.language = z; return true; }
39503							});
39504							if(t.children("ins").get(0).className.replace(/jstree[^ ]*|$/ig,'').replace(/^\s+$/ig,"").length) {
39505								tmp2.icon = t.children("ins").get(0).className.replace(/jstree[^ ]*|$/ig,'').replace(/^\s+$/ig,"");
39506							}
39507							if(t.children("ins").get(0).style.backgroundImage.length) {
39508								tmp2.icon = t.children("ins").get(0).style.backgroundImage.replace("url(","").replace(")","");
39509							}
39510						}
39511						else {
39512							tmp2 = _this.get_text(t);
39513						}
39514						if(a.length > 1) { tmp1.data.push(tmp2); }
39515						else { tmp1.data = tmp2; }
39516					});
39517					li = li.find("> ul > li");
39518					if(li.length) { tmp1.children = _this.get_json(li, li_attr, a_attr, true); }
39519					result.push(tmp1);
39520				});
39521				return result;
39522			}
39523		}
39524	});
39525})(jQuery);
39526//*/
39527
39528/* 
39529 * jsTree languages plugin 1.0
39530 * Adds support for multiple language versions in one tree
39531 * This basically allows for many titles coexisting in one node, but only one of them being visible at any given time
39532 * This is useful for maintaining the same structure in many languages (hence the name of the plugin)
39533 */
39534(function ($) {
39535	$.jstree.plugin("languages", {
39536		__init : function () { this._load_css();  },
39537		defaults : [],
39538		_fn : {
39539			set_lang : function (i) { 
39540				var langs = this._get_settings().languages,
39541					st = false,
39542					selector = ".jstree-" + this.get_index() + ' a';
39543				if(!$.isArray(langs) || langs.length === 0) { return false; }
39544				if($.inArray(i,langs) == -1) {
39545					if(!!langs[i]) { i = langs[i]; }
39546					else { return false; }
39547				}
39548				if(i == this.data.languages.current_language) { return true; }
39549				st = $.vakata.css.get_css(selector + "." + this.data.languages.current_language, false, this.data.languages.language_css);
39550				if(st !== false) { st.style.display = "none"; }
39551				st = $.vakata.css.get_css(selector + "." + i, false, this.data.languages.language_css);
39552				if(st !== false) { st.style.display = ""; }
39553				this.data.languages.current_language = i;
39554				this.__callback(i);
39555				return true;
39556			},
39557			get_lang : function () {
39558				return this.data.languages.current_language;
39559			},
39560			get_text : function (obj, lang) {
39561				obj = this._get_node(obj) || this.data.ui.last_selected;
39562				if(!obj.size()) { return false; }
39563				var langs = this._get_settings().languages,
39564					s = this._get_settings().core.html_titles;
39565				if($.isArray(langs) && langs.length) {
39566					lang = (lang && $.inArray(lang,langs) != -1) ? lang : this.data.languages.current_language;
39567					obj = obj.children("a." + lang);
39568				}
39569				else { obj = obj.children("a:eq(0)"); }
39570				if(s) {
39571					obj = obj.clone();
39572					obj.children("INS").remove();
39573					return obj.html();
39574				}
39575				else {
39576					obj = obj.contents().filter(function() { return this.nodeType == 3; })[0];
39577					return obj.nodeValue;
39578				}
39579			},
39580			set_text : function (obj, val, lang) {
39581				obj = this._get_node(obj) || this.data.ui.last_selected;
39582				if(!obj.size()) { return false; }
39583				var langs = this._get_settings().languages,
39584					s = this._get_settings().core.html_titles,
39585					tmp;
39586				if($.isArray(langs) && langs.length) {
39587					lang = (lang && $.inArray(lang,langs) != -1) ? lang : this.data.languages.current_language;
39588					obj = obj.children("a." + lang);
39589				}
39590				else { obj = obj.children("a:eq(0)"); }
39591				if(s) {
39592					tmp = obj.children("INS").clone();
39593					obj.html(val).prepend(tmp);
39594					this.__callback({ "obj" : obj, "name" : val, "lang" : lang });
39595					return true;
39596				}
39597				else {
39598					obj = obj.contents().filter(function() { return this.nodeType == 3; })[0];
39599					this.__callback({ "obj" : obj, "name" : val, "lang" : lang });
39600					return (obj.nodeValue = val);
39601				}
39602			},
39603			_load_css : function () {
39604				var langs = this._get_settings().languages,
39605					str = "/* languages css */",
39606					selector = ".jstree-" + this.get_index() + ' a',
39607					ln;
39608				if($.isArray(langs) && langs.length) {
39609					this.data.languages.current_language = langs[0];
39610					for(ln = 0; ln < langs.length; ln++) {
39611						str += selector + "." + langs[ln] + " {";
39612						if(langs[ln] != this.data.languages.current_language) { str += " display:none; "; }
39613						str += " } ";
39614					}
39615					this.data.languages.language_css = $.vakata.css.add_sheet({ 'str' : str });
39616				}
39617			},
39618			create_node : function (obj, position, js, callback) {
39619				var t = this.__call_old(true, obj, position, js, function (t) {
39620					var langs = this._get_settings().languages,
39621						a = t.children("a"),
39622						ln;
39623					if($.isArray(langs) && langs.length) {
39624						for(ln = 0; ln < langs.length; ln++) {
39625							if(!a.is("." + langs[ln])) {
39626								t.append(a.eq(0).clone().removeClass(langs.join(" ")).addClass(langs[ln]));
39627							}
39628						}
39629						a.not("." + langs.join(", .")).remove();
39630					}
39631					if(callback) { callback.call(this, t); }
39632				});
39633				return t;
39634			}
39635		}
39636	});
39637})(jQuery);
39638//*/
39639
39640/*
39641 * jsTree cookies plugin 1.0
39642 * Stores the currently opened/selected nodes in a cookie and then restores them
39643 * Depends on the jquery.cookie plugin
39644 */
39645(function ($) {
39646	$.jstree.plugin("cookies", {
39647		__init : function () {
39648			if(typeof $.cookie === "undefined") { throw "jsTree cookie: jQuery cookie plugin not included."; }
39649
39650			var s = this._get_settings().cookies,
39651				tmp;
39652			if(!!s.save_opened) {
39653				tmp = $.cookie(s.save_opened);
39654				if(tmp && tmp.length) { this.data.core.to_open = tmp.split(","); }
39655			}
39656			if(!!s.save_selected) {
39657				tmp = $.cookie(s.save_selected);
39658				if(tmp && tmp.length && this.data.ui) { this.data.ui.to_select = tmp.split(","); }
39659			}
39660			this.get_container()
39661				.one( ( this.data.ui ? "reselect" : "reopen" ) + ".jstree", $.proxy(function () {
39662					this.get_container()
39663						.bind("open_node.jstree close_node.jstree select_node.jstree deselect_node.jstree", $.proxy(function (e) { 
39664								if(this._get_settings().cookies.auto_save) { this.save_cookie((e.handleObj.namespace + e.handleObj.type).replace("jstree","")); }
39665							}, this));
39666				}, this));
39667		},
39668		defaults : {
39669			save_opened		: "jstree_open",
39670			save_selected	: "jstree_select",
39671			auto_save		: true,
39672			cookie_options	: {}
39673		},
39674		_fn : {
39675			save_cookie : function (c) {
39676				if(this.data.core.refreshing) { return; }
39677				var s = this._get_settings().cookies;
39678				if(!c) { // if called manually and not by event
39679					if(s.save_opened) {
39680						this.save_opened();
39681						$.cookie(s.save_opened, this.data.core.to_open.join(","), s.cookie_options);
39682					}
39683					if(s.save_selected && this.data.ui) {
39684						this.save_selected();
39685						$.cookie(s.save_selected, this.data.ui.to_select.join(","), s.cookie_options);
39686					}
39687					return;
39688				}
39689				switch(c) {
39690					case "open_node":
39691					case "close_node":
39692						if(!!s.save_opened) { 
39693							this.save_opened(); 
39694							$.cookie(s.save_opened, this.data.core.to_open.join(","), s.cookie_options); 
39695						}
39696						break;
39697					case "select_node":
39698					case "deselect_node":
39699						if(!!s.save_selected && this.data.ui) { 
39700							this.save_selected(); 
39701							$.cookie(s.save_selected, this.data.ui.to_select.join(","), s.cookie_options); 
39702						}
39703						break;
39704				}
39705			}
39706		}
39707	});
39708	// include cookies by default
39709	$.jstree.defaults.plugins.push("cookies");
39710})(jQuery);
39711//*/
39712
39713/*
39714 * jsTree sort plugin 1.0
39715 * Sorts items alphabetically (or using any other function)
39716 */
39717(function ($) {
39718	$.jstree.plugin("sort", {
39719		__init : function () {
39720			this.get_container()
39721				.bind("load_node.jstree", $.proxy(function (e, data) {
39722						var obj = this._get_node(data.rslt.obj);
39723						obj = obj === -1 ? this.get_container().children("ul") : obj.children("ul");
39724						this.sort(obj);
39725					}, this))
39726				.bind("rename_node.jstree", $.proxy(function (e, data) {
39727						this.sort(data.rslt.obj.parent());
39728					}, this))
39729				.bind("move_node.jstree", $.proxy(function (e, data) {
39730						var m = data.rslt.np == -1 ? this.get_container() : data.rslt.np;
39731						this.sort(m.children("ul"));
39732					}, this));
39733		},
39734		defaults : function (a, b) { return this.get_text(a) > this.get_text(b) ? 1 : -1; },
39735		_fn : {
39736			sort : function (obj) {
39737				var s = this._get_settings().sort,
39738					t = this;
39739				obj.append($.makeArray(obj.children("li")).sort($.proxy(s, t)));
39740				obj.find("> li > ul").each(function() { t.sort($(this)); });
39741				this.clean_node(obj);
39742			}
39743		}
39744	});
39745})(jQuery);
39746//*/
39747
39748/*
39749 * jsTree DND plugin 1.0
39750 * Drag and drop plugin for moving/copying nodes
39751 */
39752(function ($) {
39753	var o = false,
39754		r = false,
39755		m = false,
39756		sli = false,
39757		sti = false,
39758		dir1 = false,
39759		dir2 = false;
39760	$.vakata.dnd = {
39761		is_down : false,
39762		is_drag : false,
39763		helper : false,
39764		scroll_spd : 10,
39765		init_x : 0,
39766		init_y : 0,
39767		threshold : 5,
39768		user_data : {},
39769
39770		drag_start : function (e, data, html) { 
39771			if($.vakata.dnd.is_drag) { $.vakata.drag_stop({}); }
39772			try {
39773				e.currentTarget.unselectable = "on";
39774				e.currentTarget.onselectstart = function() { return false; };
39775				if(e.currentTarget.style) { e.currentTarget.style.MozUserSelect = "none"; }
39776			} catch(err) { }
39777			$.vakata.dnd.init_x = e.pageX;
39778			$.vakata.dnd.init_y = e.pageY;
39779			$.vakata.dnd.user_data = data;
39780			$.vakata.dnd.is_down = true;
39781			$.vakata.dnd.helper = $("<div id='vakata-dragged'>").html(html).css("opacity", "0.75");
39782			$(document).bind("mousemove", $.vakata.dnd.drag);
39783			$(document).bind("mouseup", $.vakata.dnd.drag_stop);
39784			return false;
39785		},
39786		drag : function (e) { 
39787			if(!$.vakata.dnd.is_down) { return; }
39788			if(!$.vakata.dnd.is_drag) {
39789				if(Math.abs(e.pageX - $.vakata.dnd.init_x) > 5 || Math.abs(e.pageY - $.vakata.dnd.init_y) > 5) { 
39790					$.vakata.dnd.helper.appendTo("body");
39791					$.vakata.dnd.is_drag = true;
39792					$(document).triggerHandler("drag_start.vakata", { "event" : e, "data" : $.vakata.dnd.user_data });
39793				}
39794				else { return; }
39795			}
39796
39797			// maybe use a scrolling parent element instead of document?
39798			if(e.type === "mousemove") { // thought of adding scroll in order to move the helper, but mouse poisition is n/a
39799				var d = $(document), t = d.scrollTop(), l = d.scrollLeft();
39800				if(e.pageY - t < 20) { 
39801					if(sti && dir1 === "down") { clearInterval(sti); sti = false; }
39802					if(!sti) { dir1 = "up"; sti = setInterval(function () { $(document).scrollTop($(document).scrollTop() - $.vakata.dnd.scroll_spd); }, 150); }
39803				}
39804				else { 
39805					if(sti && dir1 === "up") { clearInterval(sti); sti = false; }
39806				}
39807				if($(window).height() - (e.pageY - t) < 20) {
39808					if(sti && dir1 === "up") { clearInterval(sti); sti = false; }
39809					if(!sti) { dir1 = "down"; sti = setInterval(function () { $(document).scrollTop($(document).scrollTop() + $.vakata.dnd.scroll_spd); }, 150); }
39810				}
39811				else { 
39812					if(sti && dir1 === "down") { clearInterval(sti); sti = false; }
39813				}
39814
39815				if(e.pageX - l < 20) {
39816					if(sli && dir2 === "right") { clearInterval(sli); sli = false; }
39817					if(!sli) { dir2 = "left"; sli = setInterval(function () { $(document).scrollLeft($(document).scrollLeft() - $.vakata.dnd.scroll_spd); }, 150); }
39818				}
39819				else { 
39820					if(sli && dir2 === "left") { clearInterval(sli); sli = false; }
39821				}
39822				if($(window).width() - (e.pageX - l) < 20) {
39823					if(sli && dir2 === "left") { clearInterval(sli); sli = false; }
39824					if(!sli) { dir2 = "right"; sli = setInterval(function () { $(document).scrollLeft($(document).scrollLeft() + $.vakata.dnd.scroll_spd); }, 150); }
39825				}
39826				else { 
39827					if(sli && dir2 === "right") { clearInterval(sli); sli = false; }
39828				}
39829			}
39830
39831			$.vakata.dnd.helper.css({ left : (e.pageX + 5) + "px", top : (e.pageY + 10) + "px" });
39832			$(document).triggerHandler("drag.vakata", { "event" : e, "data" : $.vakata.dnd.user_data });
39833		},
39834		drag_stop : function (e) {
39835			$(document).unbind("mousemove", $.vakata.dnd.drag);
39836			$(document).unbind("mouseup", $.vakata.dnd.drag_stop);
39837			$(document).triggerHandler("drag_stop.vakata", { "event" : e, "data" : $.vakata.dnd.user_data });
39838			$.vakata.dnd.helper.remove();
39839			$.vakata.dnd.init_x = 0;
39840			$.vakata.dnd.init_y = 0;
39841			$.vakata.dnd.user_data = {};
39842			$.vakata.dnd.is_down = false;
39843			$.vakata.dnd.is_drag = false;
39844		}
39845	};
39846	$(function() {
39847		var css_string = '#vakata-dragged { display:block; margin:0 0 0 0; padding:4px 4px 4px 24px; position:absolute; top:-2000px; line-height:16px; z-index:10000; } ';
39848		$.vakata.css.add_sheet({ str : css_string });
39849	});
39850
39851	$.jstree.plugin("dnd", {
39852		__init : function () {
39853			this.data.dnd = {
39854				active : false,
39855				after : false,
39856				inside : false,
39857				before : false,
39858				off : false,
39859				prepared : false,
39860				w : 0,
39861				to1 : false,
39862				to2 : false,
39863				cof : false,
39864				cw : false,
39865				ch : false,
39866				i1 : false,
39867				i2 : false
39868			};
39869			this.get_container()
39870				.bind("mouseenter.jstree", $.proxy(function () {
39871						if($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree && this.data.themes) {
39872							m.attr("class", "jstree-" + this.data.themes.theme); 
39873							$.vakata.dnd.helper.attr("class", "jstree-dnd-helper jstree-" + this.data.themes.theme);
39874						}
39875					}, this))
39876				.bind("mouseleave.jstree", $.proxy(function () {
39877						if($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree) {
39878							if(this.data.dnd.i1) { clearInterval(this.data.dnd.i1); }
39879							if(this.data.dnd.i2) { clearInterval(this.data.dnd.i2); }
39880						}
39881					}, this))
39882				.bind("mousemove.jstree", $.proxy(function (e) {
39883						if($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree) {
39884							var cnt = this.get_container()[0];
39885
39886							// Horizontal scroll
39887							if(e.pageX + 24 > this.data.dnd.cof.left + this.data.dnd.cw) {
39888								if(this.data.dnd.i1) { clearInterval(this.data.dnd.i1); }
39889								this.data.dnd.i1 = setInterval($.proxy(function () { this.scrollLeft += $.vakata.dnd.scroll_spd; }, cnt), 100);
39890							}
39891							else if(e.pageX - 24 < this.data.dnd.cof.left) {
39892								if(this.data.dnd.i1) { clearInterval(this.data.dnd.i1); }
39893								this.data.dnd.i1 = setInterval($.proxy(function () { this.scrollLeft -= $.vakata.dnd.scroll_spd; }, cnt), 100);
39894							}
39895							else {
39896								if(this.data.dnd.i1) { clearInterval(this.data.dnd.i1); }
39897							}
39898
39899							// Vertical scroll
39900							if(e.pageY + 24 > this.data.dnd.cof.top + this.data.dnd.ch) {
39901								if(this.data.dnd.i2) { clearInterval(this.data.dnd.i2); }
39902								this.data.dnd.i2 = setInterval($.proxy(function () { this.scrollTop += $.vakata.dnd.scroll_spd; }, cnt), 100);
39903							}
39904							else if(e.pageY - 24 < this.data.dnd.cof.top) {
39905								if(this.data.dnd.i2) { clearInterval(this.data.dnd.i2); }
39906								this.data.dnd.i2 = setInterval($.proxy(function () { this.scrollTop -= $.vakata.dnd.scroll_spd; }, cnt), 100);
39907							}
39908							else {
39909								if(this.data.dnd.i2) { clearInterval(this.data.dnd.i2); }
39910							}
39911
39912						}
39913					}, this))
39914				.delegate("a", "mousedown.jstree", $.proxy(function (e) { 
39915						if(e.which === 1) {
39916							this.start_drag(e.currentTarget, e);
39917							return false;
39918						}
39919					}, this))
39920				.delegate("a", "mouseenter.jstree", $.proxy(function (e) { 
39921						if($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree) {
39922							this.dnd_enter(e.currentTarget);
39923						}
39924					}, this))
39925				.delegate("a", "mousemove.jstree", $.proxy(function (e) { 
39926						if($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree) {
39927							if(typeof this.data.dnd.off.top === "undefined") { this.data.dnd.off = $(e.target).offset(); }
39928							this.data.dnd.w = (e.pageY - (this.data.dnd.off.top || 0)) % this.data.core.li_height;
39929							if(this.data.dnd.w < 0) { this.data.dnd.w += this.data.core.li_height; }
39930							this.dnd_show();
39931						}
39932					}, this))
39933				.delegate("a", "mouseleave.jstree", $.proxy(function (e) { 
39934						if($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree) {
39935							this.data.dnd.after		= false;
39936							this.data.dnd.before	= false;
39937							this.data.dnd.inside	= false;
39938							$.vakata.dnd.helper.children("ins").attr("class","jstree-invalid");
39939							m.hide();
39940							if(r && r[0] === e.target.parentNode) {
39941								if(this.data.dnd.to1) {
39942									clearTimeout(this.data.dnd.to1);
39943									this.data.dnd.to1 = false;
39944								}
39945								if(this.data.dnd.to2) {
39946									clearTimeout(this.data.dnd.to2);
39947									this.data.dnd.to2 = false;
39948								}
39949							}
39950						}
39951					}, this))
39952				.delegate("a", "mouseup.jstree", $.proxy(function (e) { 
39953						if($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree) {
39954							this.dnd_finish(e);
39955						}
39956					}, this));
39957
39958			$(document)
39959				.bind("drag_stop.vakata", $.proxy(function () {
39960						this.data.dnd.after		= false;
39961						this.data.dnd.before	= false;
39962						this.data.dnd.inside	= false;
39963						this.data.dnd.off		= false;
39964						this.data.dnd.prepared	= false;
39965						this.data.dnd.w			= false;
39966						this.data.dnd.to1		= false;
39967						this.data.dnd.to2		= false;
39968						this.data.dnd.active	= false;
39969						this.data.dnd.foreign	= false;
39970						if(m) { m.css({ "top" : "-2000px" }); }
39971					}, this))
39972				.bind("drag_start.vakata", $.proxy(function (e, data) {
39973						if(data.data.jstree) { 
39974							var et = $(data.event.target);
39975							if(et.closest(".jstree").hasClass("jstree-" + this.get_index())) {
39976								this.dnd_enter(et);
39977							}
39978						}
39979					}, this));
39980
39981			var s = this._get_settings().dnd;
39982			if(s.drag_target) {
39983				$(document)
39984					.delegate(s.drag_target, "mousedown.jstree", $.proxy(function (e) {
39985						o = e.target;
39986						$.vakata.dnd.drag_start(e, { jstree : true, obj : e.target }, "<ins class='jstree-icon'></ins>" + $(e.target).text() );
39987						if(this.data.themes) { 
39988							m.attr("class", "jstree-" + this.data.themes.theme); 
39989							$.vakata.dnd.helper.attr("class", "jstree-dnd-helper jstree-" + this.data.themes.theme); 
39990						}
39991						$.vakata.dnd.helper.children("ins").attr("class","jstree-invalid");
39992						var cnt = this.get_container();
39993						this.data.dnd.cof = cnt.offset();
39994						this.data.dnd.cw = parseInt(cnt.width(),10);
39995						this.data.dnd.ch = parseInt(cnt.height(),10);
39996						this.data.dnd.foreign = true;
39997						return false;
39998					}, this));
39999			}
40000			if(s.drop_target) {
40001				$(document)
40002					.delegate(s.drop_target, "mouseenter.jstree", $.proxy(function (e) {
40003							if(this.data.dnd.active && this._get_settings().dnd.drop_check.call(this, { "o" : o, "r" : $(e.target) })) {
40004								$.vakata.dnd.helper.children("ins").attr("class","jstree-ok");
40005							}
40006						}, this))
40007					.delegate(s.drop_target, "mouseleave.jstree", $.proxy(function (e) {
40008							if(this.data.dnd.active) {
40009								$.vakata.dnd.helper.children("ins").attr("class","jstree-invalid");
40010							}
40011						}, this))
40012					.delegate(s.drop_target, "mouseup.jstree", $.proxy(function (e) {
40013							if(this.data.dnd.active && $.vakata.dnd.helper.children("ins").hasClass("jstree-ok")) {
40014								this._get_settings().dnd.drop_finish.call(this, { "o" : o, "r" : $(e.target) });
40015							}
40016						}, this));
40017			}
40018		},
40019		defaults : {
40020			copy_modifier	: "ctrl",
40021			check_timeout	: 200,
40022			open_timeout	: 500,
40023			drop_target		: ".jstree-drop",
40024			drop_check		: function (data) { return true; },
40025			drop_finish		: $.noop,
40026			drag_target		: ".jstree-draggable",
40027			drag_finish		: $.noop,
40028			drag_check		: function (data) { return { after : false, before : false, inside : true }; }
40029		},
40030		_fn : {
40031			dnd_prepare : function () {
40032				if(!r || !r.length) { return; }
40033				this.data.dnd.off = r.offset();
40034				if(this._get_settings().core.rtl) {
40035					this.data.dnd.off.right = this.data.dnd.off.left + r.width();
40036				}
40037				if(this.data.dnd.foreign) {
40038					var a = this._get_settings().dnd.drag_check.call(this, { "o" : o, "r" : r });
40039					this.data.dnd.after = a.after;
40040					this.data.dnd.before = a.before;
40041					this.data.dnd.inside = a.inside;
40042					this.data.dnd.prepared = true;
40043					return this.dnd_show();
40044				}
40045				this.prepare_move(o, r, "before");
40046				this.data.dnd.before = this.check_move();
40047				this.prepare_move(o, r, "after");
40048				this.data.dnd.after = this.check_move();
40049				if(this._is_loaded(r)) {
40050					this.prepare_move(o, r, "inside");
40051					this.data.dnd.inside = this.check_move();
40052				}
40053				else {
40054					this.data.dnd.inside = false;
40055				}
40056				this.data.dnd.prepared = true;
40057				return this.dnd_show();
40058			},
40059			dnd_show : function () {
40060				if(!this.data.dnd.prepared) { return; }
40061				var o = ["before","inside","after"],
40062					r = false,
40063					rtl = this._get_settings().core.rtl,
40064					pos;
40065				if(this.data.dnd.w < this.data.core.li_height/3) { o = ["before","inside","after"]; }
40066				else if(this.data.dnd.w <= this.data.core.li_height*2/3) {
40067					o = this.data.dnd.w < this.data.core.li_height/2 ? ["inside","before","after"] : ["inside","after","before"];
40068				}
40069				else { o = ["after","inside","before"]; }
40070				$.each(o, $.proxy(function (i, val) { 
40071					if(this.data.dnd[val]) {
40072						$.vakata.dnd.helper.children("ins").attr("class","jstree-ok");
40073						r = val;
40074						return false;
40075					}
40076				}, this));
40077				if(r === false) { $.vakata.dnd.helper.children("ins").attr("class","jstree-invalid"); }
40078				
40079				pos = rtl ? (this.data.dnd.off.right - 18) : (this.data.dnd.off.left + 10);
40080				switch(r) {
40081					case "before":
40082						m.css({ "left" : pos + "px", "top" : (this.data.dnd.off.top - 6) + "px" }).show();
40083						break;
40084					case "after":
40085						m.css({ "left" : pos + "px", "top" : (this.data.dnd.off.top + this.data.core.li_height - 7) + "px" }).show();
40086						break;
40087					case "inside":
40088						m.css({ "left" : pos + ( rtl ? -4 : 4) + "px", "top" : (this.data.dnd.off.top + this.data.core.li_height/2 - 5) + "px" }).show();
40089						break;
40090					default:
40091						m.hide();
40092						break;
40093				}
40094				return r;
40095			},
40096			dnd_open : function () {
40097				this.data.dnd.to2 = false;
40098				this.open_node(r, $.proxy(this.dnd_prepare,this), true);
40099			},
40100			dnd_finish : function (e) {
40101				if(this.data.dnd.foreign) {
40102					if(this.data.dnd.after || this.data.dnd.before || this.data.dnd.inside) {
40103						this._get_settings().dnd.drag_finish.call(this, { "o" : o, "r" : r });
40104					}
40105				}
40106				else {
40107					this.dnd_prepare();
40108					this.move_node(o, r, this.dnd_show(), e[this._get_settings().dnd.copy_modifier + "Key"]);
40109				}
40110				o = false;
40111				r = false;
40112				m.hide();
40113			},
40114			dnd_enter : function (obj) {
40115				var s = this._get_settings().dnd;
40116				this.data.dnd.prepared = false;
40117				r = this._get_node(obj);
40118				if(s.check_timeout) { 
40119					// do the calculations after a minimal timeout (users tend to drag quickly to the desired location)
40120					if(this.data.dnd.to1) { clearTimeout(this.data.dnd.to1); }
40121					this.data.dnd.to1 = setTimeout($.proxy(this.dnd_prepare, this), s.check_timeout); 
40122				}
40123				else { 
40124					this.dnd_prepare(); 
40125				}
40126				if(s.open_timeout) { 
40127					if(this.data.dnd.to2) { clearTimeout(this.data.dnd.to2); }
40128					if(r && r.length && r.hasClass("jstree-closed")) { 
40129						// if the node is closed - open it, then recalculate
40130						this.data.dnd.to2 = setTimeout($.proxy(this.dnd_open, this), s.open_timeout);
40131					}
40132				}
40133				else {
40134					if(r && r.length && r.hasClass("jstree-closed")) { 
40135						this.dnd_open();
40136					}
40137				}
40138			},
40139			start_drag : function (obj, e) {
40140				o = this._get_node(obj);
40141				if(this.data.ui && this.is_selected(o)) { o = this._get_node(null, true); }
40142				$.vakata.dnd.drag_start(e, { jstree : true, obj : o }, "<ins class='jstree-icon'></ins>" + (o.length > 1 ? "Multiple selection" : this.get_text(o)) );
40143				if(this.data.themes) { 
40144					m.attr("class", "jstree-" + this.data.themes.theme); 
40145					$.vakata.dnd.helper.attr("class", "jstree-dnd-helper jstree-" + this.data.themes.theme); 
40146				}
40147				var cnt = this.get_container();
40148				this.data.dnd.cof = cnt.children("ul").offset();
40149				this.data.dnd.cw = parseInt(cnt.width(),10);
40150				this.data.dnd.ch = parseInt(cnt.height(),10);
40151				this.data.dnd.active = true;
40152			}
40153		}
40154	});
40155	$(function() {
40156		var css_string = '' + 
40157			'#vakata-dragged ins { display:block; text-decoration:none; width:16px; height:16px; margin:0 0 0 0; padding:0; position:absolute; top:4px; left:4px; } ' + 
40158			'#vakata-dragged .jstree-ok { background:green; } ' + 
40159			'#vakata-dragged .jstree-invalid { background:red; } ' + 
40160			'#jstree-marker { padding:0; margin:0; line-height:12px; font-size:1px; overflow:hidden; height:12px; width:8px; position:absolute; top:-30px; z-index:10000; background-repeat:no-repeat; display:none; background-color:silver; } ';
40161		$.vakata.css.add_sheet({ str : css_string });
40162		m = $("<div>").attr({ id : "jstree-marker" }).hide().appendTo("body");
40163		$(document).bind("drag_start.vakata", function (e, data) {
40164			if(data.data.jstree) { 
40165				m.show(); 
40166			}
40167		});
40168		$(document).bind("drag_stop.vakata", function (e, data) {
40169			if(data.data.jstree) { m.hide(); }
40170		});
40171	});
40172})(jQuery);
40173//*/
40174
40175/*
40176 * jsTree checkbox plugin 1.0
40177 * Inserts checkboxes in front of every node
40178 * Depends on the ui plugin
40179 * DOES NOT WORK NICELY WITH MULTITREE DRAG'N'DROP
40180 */
40181(function ($) {
40182	$.jstree.plugin("checkbox", {
40183		__init : function () {
40184      // SENAD: We are not disabling select_node. 
40185      // this.select_node = this.deselect_node = this.deselect_all = $.noop;
40186			this.get_selected = this.get_checked;
40187
40188			this.get_container()
40189				.bind("open_node.jstree create_node.jstree clean_node.jstree", $.proxy(function (e, data) { 
40190						this._prepare_checkboxes(data.rslt.obj);
40191					}, this))
40192				.bind("loaded.jstree", $.proxy(function (e) {
40193						this._prepare_checkboxes();
40194					}, this))
40195				.delegate("a .jstree-checkbox", "click.jstree", $.proxy(function (e) {
40196						if(this._get_node(e.target).hasClass("jstree-checked")) { this.uncheck_node(e.target); }
40197						else { this.check_node(e.target); }
40198						if(this.data.ui) { this.save_selected(); }
40199						if(this.data.cookies) { this.save_cookie("select_node"); }
40200						e.preventDefault();
40201					}, this));
40202		},
40203		__destroy : function () {
40204			this.get_container().find(".jstree-checkbox").remove();
40205		},
40206		_fn : {
40207			_prepare_checkboxes : function (obj) {
40208				obj = !obj || obj == -1 ? this.get_container() : this._get_node(obj);
40209				var c, _this = this, t;
40210				obj.each(function () {
40211					t = $(this);
40212					c = t.is("li") && t.hasClass("jstree-checked") ? "jstree-checked" : "jstree-unchecked";
40213					t.find("a").not(":has(.jstree-checkbox)").prepend("<ins class='jstree-checkbox'>&#160;</ins>").parent().not(".jstree-checked, .jstree-unchecked").addClass(c);
40214				});
40215				if(obj.is("li")) { this._repair_state(obj); }
40216				else { obj.find("> ul > li").each(function () { _this._repair_state(this); }); }
40217			},
40218			change_state : function (obj, state) {
40219				obj = this._get_node(obj);
40220				state = (state === false || state === true) ? state : obj.hasClass("jstree-checked");
40221				if(state) { obj.find("li").andSelf().removeClass("jstree-checked jstree-undetermined").addClass("jstree-unchecked"); }
40222				else { 
40223					obj.find("li").andSelf().removeClass("jstree-unchecked jstree-undetermined").addClass("jstree-checked"); 
40224					if(this.data.ui) { this.data.ui.last_selected = obj; }
40225					this.data.checkbox.last_selected = obj;
40226				}
40227				obj.parentsUntil(".jstree", "li").each(function () {
40228					var $this = $(this);
40229					if(state) {
40230						if($this.children("ul").children(".jstree-checked, .jstree-undetermined").length) {
40231							$this.parentsUntil(".jstree", "li").andSelf().removeClass("jstree-checked jstree-unchecked").addClass("jstree-undetermined");
40232							return false;
40233						}
40234						else {
40235							$this.removeClass("jstree-checked jstree-undetermined").addClass("jstree-unchecked");
40236						}
40237					}
40238					else {
40239						if($this.children("ul").children(".jstree-unchecked, .jstree-undetermined").length) {
40240							$this.parentsUntil(".jstree", "li").andSelf().removeClass("jstree-checked jstree-unchecked").addClass("jstree-undetermined");
40241							return false;
40242						}
40243						else {
40244							$this.removeClass("jstree-unchecked jstree-undetermined").addClass("jstree-checked");
40245						}
40246					}
40247				});
40248				if(this.data.ui) { this.data.ui.selected = this.get_checked(); }
40249				this.__callback(obj);
40250			},
40251			check_node : function (obj) {
40252				this.change_state(obj, false);
40253			},
40254			uncheck_node : function (obj) {
40255				this.change_state(obj, true);
40256			},
40257			check_all : function () {
40258				var _this = this;
40259				this.get_container().children("ul").children("li").each(function () {
40260					_this.check_node(this, false);
40261				});
40262			},
40263			uncheck_all : function () {
40264				var _this = this;
40265				this.get_container().children("ul").children("li").each(function () {
40266					_this.change_state(this, true);
40267				});
40268			},
40269
40270			is_checked : function(obj) {
40271				obj = this._get_node(obj);
40272				return obj.length ? obj.is(".jstree-checked") : false;
40273			},
40274			get_checked : function (obj) {
40275				obj = !obj || obj === -1 ? this.get_container() : this._get_node(obj);
40276				return obj.find("> ul > .jstree-checked, .jstree-undetermined > ul > .jstree-checked");
40277			},
40278			get_unchecked : function (obj) { 
40279				obj = !obj || obj === -1 ? this.get_container() : this._get_node(obj);
40280				return obj.find("> ul > .jstree-unchecked, .jstree-undetermined > ul > .jstree-unchecked");
40281			},
40282
40283			show_checkboxes : function () { this.get_container().children("ul").removeClass("jstree-no-checkboxes"); },
40284			hide_checkboxes : function () { this.get_container().children("ul").addClass("jstree-no-checkboxes"); },
40285
40286			_repair_state : function (obj) {
40287				obj = this._get_node(obj);
40288				if(!obj.length) { return; }
40289				var a = obj.find("> ul > .jstree-checked").length,
40290					b = obj.find("> ul > .jstree-undetermined").length,
40291					c = obj.find("> ul > li").length;
40292
40293				if(c === 0) { if(obj.hasClass("jstree-undetermined")) { this.check_node(obj); } }
40294				else if(a === 0 && b === 0) { this.uncheck_node(obj); }
40295				else if(a === c) { this.check_node(obj); }
40296				else { 
40297					obj.parentsUntil(".jstree","li").removeClass("jstree-checked jstree-unchecked").addClass("jstree-undetermined");
40298				}
40299			},
40300			reselect : function () {
40301				if(this.data.ui) { 
40302					var _this = this,
40303						s = this.data.ui.to_select;
40304					s = $.map($.makeArray(s), function (n) { return "#" + n.toString().replace(/^#/,"").replace('\\/','/').replace('/','\\/'); });
40305					this.deselect_all();
40306					$.each(s, function (i, val) { _this.check_node(val); });
40307					this.__callback();
40308				}
40309			}
40310		}
40311	});
40312})(jQuery);
40313//*/
40314
40315/* 
40316 * jsTree XML 1.0
40317 * The XML data store. Datastores are build by overriding the `load_node` and `_is_loaded` functions.
40318 */
40319(function ($) {
40320	$.vakata.xslt = function (xml, xsl, callback) {
40321		var rs = "", xm, xs, processor, support;
40322		if(document.recalc) {
40323			xm = document.createElement('xml');
40324			xs = document.createElement('xml');
40325			xm.innerHTML = xml;
40326			xs.innerHTML = xsl;
40327			$("body").append(xm).append(xs);
40328			setTimeout( (function (xm, xs, callback) {
40329				return function () {
40330					callback.call(null, xm.transformNode(xs.XMLDocument));
40331					setTimeout( (function (xm, xs) { return function () { jQuery("body").remove(xm).remove(xs); }; })(xm, xs), 200);
40332				};
40333			}) (xm, xs, callback), 100);
40334			return true;
40335		}
40336		if(typeof window.DOMParser !== "undefined" && typeof window.XMLHttpRequest !== "undefined" && typeof window.XSLTProcessor !== "undefined") {
40337			processor = new XSLTProcessor();
40338			support = $.isFunction(processor.transformDocument) ? (typeof window.XMLSerializer !== "undefined") : true;
40339			if(!support) { return false; }
40340			xml = new DOMParser().parseFromString(xml, "text/xml");
40341			xsl = new DOMParser().parseFromString(xsl, "text/xml");
40342			if($.isFunction(processor.transformDocument)) {
40343				rs = document.implementation.createDocument("", "", null);
40344				processor.transformDocument(xml, xsl, rs, null);
40345				callback.call(null, XMLSerializer().serializeToString(rs));
40346				return true;
40347			}
40348			else {
40349				processor.importStylesheet(xsl);
40350				rs = processor.transformToFragment(xml, document);
40351				callback.call(null, $("<div>").append(rs).html());
40352				return true;
40353			}
40354		}
40355		return false;
40356	};
40357	var xsl = {
40358		'nest' : '<?xml version="1.0" encoding="utf-8" ?>' + 
40359			'<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >' + 
40360			'<xsl:output method="html" encoding="utf-8" omit-xml-declaration="yes" standalone="no" indent="no" media-type="text/html" />' + 
40361			'<xsl:template match="/">' + 
40362			'	<xsl:call-template name="nodes">' + 
40363			'		<xsl:with-param name="node" select="/root" />' + 
40364			'	</xsl:call-template>' + 
40365			'</xsl:template>' + 
40366			'<xsl:template name="nodes">' + 
40367			'	<xsl:param name="node" />' + 
40368			'	<ul>' + 
40369			'	<xsl:for-each select="$node/item">' + 
40370			'		<xsl:variable name="children" select="count(./item) &gt; 0" />' + 
40371			'		<li>' + 
40372			'			<xsl:attribute name="class">' + 
40373			'				<xsl:if test="position() = last()">jstree-last </xsl:if>' + 
40374			'				<xsl:choose>' + 
40375			'					<xsl:when test="@state = \'open\'">jstree-open </xsl:when>' + 
40376			'					<xsl:when test="$children or @hasChildren or @state = \'closed\'">jstree-closed </xsl:when>' + 
40377			'					<xsl:otherwise>jstree-leaf </xsl:otherwise>' + 
40378			'				</xsl:choose>' + 
40379			'				<xsl:value-of select="@class" />' + 
40380			'			</xsl:attribute>' + 
40381			'			<xsl:for-each select="@*">' + 
40382			'				<xsl:if test="name() != \'class\' and name() != \'state\' and name() != \'hasChildren\'">' + 
40383			'					<xsl:attribute name="{name()}"><xsl:value-of select="." /></xsl:attribute>' + 
40384			'				</xsl:if>' + 
40385			'			</xsl:for-each>' + 
40386			'	<ins class="jstree-icon"><xsl:text>&#xa0;</xsl:text></ins>' + 
40387			'			<xsl:for-each select="content/name">' + 
40388			'				<a>' + 
40389			'				<xsl:attribute name="href">' + 
40390			'					<xsl:choose>' + 
40391			'					<xsl:when test="@href"><xsl:value-of select="@href" /></xsl:when>' + 
40392			'					<xsl:otherwise>#</xsl:otherwise>' + 
40393			'					</xsl:choose>' + 
40394			'				</xsl:attribute>' + 
40395			'				<xsl:attribute name="class"><xsl:value-of select="@lang" /> <xsl:value-of select="@class" /></xsl:attribute>' + 
40396			'				<xsl:attribute name="style"><xsl:value-of select="@style" /></xsl:attribute>' + 
40397			'				<xsl:for-each select="@*">' + 
40398			'					<xsl:if test="name() != \'style\' and name() != \'class\' and name() != \'href\'">' + 
40399			'						<xsl:attribute name="{name()}"><xsl:value-of select="." /></xsl:attribute>' + 
40400			'					</xsl:if>' + 
40401			'				</xsl:for-each>' + 
40402			'					<ins>' + 
40403			'						<xsl:attribute name="class">jstree-icon ' + 
40404			'							<xsl:if test="string-length(attribute::icon) > 0 and not(contains(@icon,\'/\'))"><xsl:value-of select="@icon" /></xsl:if>' + 
40405			'						</xsl:attribute>' + 
40406			'						<xsl:if test="string-length(attribute::icon) > 0 and contains(@icon,\'/\')"><xsl:attribute name="style">background:url(<xsl:value-of select="@icon" />) center center no-repeat;</xsl:attribute></xsl:if>' + 
40407			'						<xsl:text>&#xa0;</xsl:text>' + 
40408			'					</ins>' + 
40409			'					<xsl:value-of select="current()" />' + 
40410			'				</a>' + 
40411			'			</xsl:for-each>' + 
40412			'			<xsl:if test="$children or @hasChildren"><xsl:call-template name="nodes"><xsl:with-param name="node" select="current()" /></xsl:call-template></xsl:if>' + 
40413			'		</li>' + 
40414			'	</xsl:for-each>' + 
40415			'	</ul>' + 
40416			'</xsl:template>' + 
40417			'</xsl:stylesheet>',
40418
40419		'flat' : '<?xml version="1.0" encoding="utf-8" ?>' + 
40420			'<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >' + 
40421			'<xsl:output method="html" encoding="utf-8" omit-xml-declaration="yes" standalone="no" indent="no" media-type="text/xml" />' + 
40422			'<xsl:template match="/">' + 
40423			'	<ul>' + 
40424			'	<xsl:for-each select="//item[not(@parent_id) or @parent_id=0 or not(@parent_id = //item/@id)]">' + /* the last `or` may be removed */
40425			'		<xsl:call-template name="nodes">' + 
40426			'			<xsl:with-param name="node" select="." />' + 
40427			'			<xsl:with-param name="is_last" select="number(position() = last())" />' + 
40428			'		</xsl:call-template>' + 
40429			'	</xsl:for-each>' + 
40430			'	</ul>' + 
40431			'</xsl:template>' + 
40432			'<xsl:template name="nodes">' + 
40433			'	<xsl:param name="node" />' + 
40434			'	<xsl:param name="is_last" />' + 
40435			'	<xsl:variable name="children" select="count(//item[@parent_id=$node/attribute::id]) &gt; 0" />' + 
40436			'	<li>' + 
40437			'	<xsl:attribute name="class">' + 
40438			'		<xsl:if test="$is_last = true()">jstree-last </xsl:if>' + 
40439			'		<xsl:choose>' + 
40440			'			<xsl:when test="@state = \'open\'">jstree-open </xsl:when>' + 
40441			'			<xsl:when test="$children or @hasChildren or @state = \'closed\'">jstree-closed </xsl:when>' + 
40442			'			<xsl:otherwise>jstree-leaf </xsl:otherwise>' + 
40443			'		</xsl:choose>' + 
40444			'		<xsl:value-of select="@class" />' + 
40445			'	</xsl:attribute>' + 
40446			'	<xsl:for-each select="@*">' + 
40447			'		<xsl:if test="name() != \'parent_id\' and name() != \'hasChildren\' and name() != \'class\' and name() != \'state\'">
40447' + 
40448			'		<xsl:attribute name="{name()}"><xsl:value-of select="." /></xsl:attribute>' + 
40449			'		</xsl:if>' + 
40450			'	</xsl:for-each>' + 
40451			'	<ins class="jstree-icon"><xsl:text>&#xa0;</xsl:text></ins>' + 
40452			'	<xsl:for-each select="content/name">' + 
40453			'		<a>' + 
40454			'		<xsl:attribute name="href">' + 
40455			'			<xsl:choose>' + 
40456			'			<xsl:when test="@href"><xsl:value-of select="@href" /></xsl:when>' + 
40457			'			<xsl:otherwise>#</xsl:otherwise>' + 
40458			'			</xsl:choose>' + 
40459			'		</xsl:attribute>' + 
40460			'		<xsl:attribute name="class"><xsl:value-of select="@lang" /> <xsl:value-of select="@class" /></xsl:attribute>' + 
40461			'		<xsl:attribute name="style"><xsl:value-of select="@style" /></xsl:attribute>' + 
40462			'		<xsl:for-each select="@*">' + 
40463			'			<xsl:if test="name() != \'style\' and name() != \'class\' and name() != \'href\'">' + 
40464			'				<xsl:attribute name="{name()}"><xsl:value-of select="." /></xsl:attribute>' + 
40465			'			</xsl:if>' + 
40466			'		</xsl:for-each>' + 
40467			'			<ins>' + 
40468			'				<xsl:attribute name="class">jstree-icon ' + 
40469			'					<xsl:if test="string-length(attribute::icon) > 0 and not(contains(@icon,\'/\'))"><xsl:value-of select="@icon" /></xsl:if>' + 
40470			'				</xsl:attribute>' + 
40471			'				<xsl:if test="string-length(attribute::icon) > 0 and contains(@icon,\'/\')"><xsl:attribute name="style">background:url(<xsl:value-of select="@icon" />) center center no-repeat;</xsl:attribute></xsl:if>' + 
40472			'				<xsl:text>&#xa0;</xsl:text>' + 
40473			'			</ins>' + 
40474			'			<xsl:value-of select="current()" />' + 
40475			'		</a>' + 
40476			'	</xsl:for-each>' + 
40477			'	<xsl:if test="$children">' + 
40478			'		<ul>' + 
40479			'		<xsl:for-each select="//item[@parent_id=$node/attribute::id]">' + 
40480			'			<xsl:call-template name="nodes">' + 
40481			'				<xsl:with-param name="node" select="." />' + 
40482			'				<xsl:with-param name="is_last" select="number(position() = last())" />' + 
40483			'			</xsl:call-template>' + 
40484			'		</xsl:for-each>' + 
40485			'		</ul>' + 
40486			'	</xsl:if>' + 
40487			'	</li>' + 
40488			'</xsl:template>' + 
40489			'</xsl:stylesheet>'
40490	};
40491	$.jstree.plugin("xml_data", {
40492		defaults : { 
40493			data : false,
40494			ajax : false,
40495			xsl : "flat",
40496			clean_node : false,
40497			correct_state : true
40498		},
40499		_fn : {
40500			load_node : function (obj, s_call, e_call) { var _this = this; this.load_node_xml(obj, function () { _this.__callback({ "obj" : obj }); s_call.call(this); }, e_call); },
40501			_is_loaded : function (obj) { 
40502				var s = this._get_settings().xml_data;
40503				obj = this._get_node(obj);
40504				return obj == -1 || !obj || !s.ajax || obj.is(".jstree-open, .jstree-leaf") || obj.children("ul").children("li").size() > 0;
40505			},
40506			load_node_xml : function (obj, s_call, e_call) {
40507				var s = this.get_settings().xml_data,
40508					error_func = function () {},
40509					success_func = function () {};
40510
40511				obj = this._get_node(obj);
40512				if(obj && obj !== -1) {
40513					if(obj.data("jstree-is-loading")) { return; }
40514					else { obj.data("jstree-is-loading",true); }
40515				}
40516				switch(!0) {
40517					case (!s.data && !s.ajax): throw "Neither data nor ajax settings supplied.";
40518					case (!!s.data && !s.ajax) || (!!s.data && !!s.ajax && (!obj || obj === -1)):
40519						if(!obj || obj == -1) {
40520							this.parse_xml(s.data, $.proxy(function (d) {
40521								if(d) {
40522									d = d.replace(/ ?xmlns="[^"]*"/ig, "");
40523									if(d.length > 10) {
40524										d = $(d);
40525										this.get_container().children("ul").empty().append(d.children());
40526										if(s.clean_node) { this.clean_node(obj); }
40527										if(s_call) { s_call.call(this); }
40528									}
40529								}
40530								else { 
40531									if(s.correct_state) { 
40532										this.get_container().children("ul").empty(); 
40533										if(s_call) { s_call.call(this); }
40534									}
40535								}
40536							}, this));
40537						}
40538						break;
40539					case (!s.data && !!s.ajax) || (!!s.data && !!s.ajax && obj && obj !== -1):
40540						error_func = function (x, t, e) {
40541							var ef = this.get_settings().xml_data.ajax.error; 
40542							if(ef) { ef.call(this, x, t, e); }
40543							if(obj !== -1 && obj.length) {
40544								obj.children(".jstree-loading").removeClass("jstree-loading");
40545								obj.data("jstree-is-loading",false);
40546								if(t === "success" && s.correct_state) { obj.removeClass("jstree-open jstree-closed").addClass("jstree-leaf"); }
40547							}
40548							else {
40549								if(t === "success" && s.correct_state) { this.get_container().children("ul").empty(); }
40550							}
40551							if(e_call) { e_call.call(this); }
40552						};
40553						success_func = function (d, t, x) {
40554							d = x.responseText;
40555							var sf = this.get_settings().xml_data.ajax.success; 
40556							if(sf) { d = sf.call(this,d,t,x) || d; }
40557							if(d == "") {
40558								return error_func.call(this, x, t, "");
40559							}
40560							this.parse_xml(d, $.proxy(function (d) {
40561								if(d) {
40562									d = d.replace(/ ?xmlns="[^"]*"/ig, "");
40563									if(d.length > 10) {
40564										d = $(d);
40565										if(obj === -1 || !obj) { this.get_container().children("ul").empty().append(d.children()); }
40566										else { obj.children(".jstree-loading").removeClass("jstree-loading"); obj.append(d); obj.data("jstree-is-loading",false); }
40567										if(s.clean_node) { this.clean_node(obj); }
40568										if(s_call) { s_call.call(this); }
40569									}
40570									else {
40571										if(obj && obj !== -1) { 
40572											obj.children(".jstree-loading").removeClass("jstree-loading");
40573											obj.data("jstree-is-loading",false);
40574											if(s.correct_state) { 
40575												obj.removeClass("jstree-open jstree-closed").addClass("jstree-leaf"); 
40576												if(s_call) { s_call.call(this); } 
40577											}
40578										}
40579										else {
40580											if(s.correct_state) { 
40581												this.get_container().children("ul").empty();
40582												if(s_call) { s_call.call(this); } 
40583											}
40584										}
40585									}
40586								}
40587							}, this));
40588						};
40589						s.ajax.context = this;
40590						s.ajax.error = error_func;
40591						s.ajax.success = success_func;
40592						if(!s.ajax.dataType) { s.ajax.dataType = "xml"; }
40593						if($.isFunction(s.ajax.url)) { s.ajax.url = s.ajax.url.call(this, obj); }
40594						if($.isFunction(s.ajax.data)) { s.ajax.data = s.ajax.data.call(this, obj); }
40595						$.ajax(s.ajax);
40596						break;
40597				}
40598			},
40599			parse_xml : function (xml, callback) {
40600				var s = this._get_settings().xml_data;
40601				$.vakata.xslt(xml, xsl[s.xsl], callback);
40602			},
40603			get_xml : function (tp, obj, li_attr, a_attr, is_callback) {
40604				var result = "", 
40605					s = this._get_settings(), 
40606					_this = this,
40607					tmp1, tmp2, li, a, lang;
40608				if(!tp) { tp = "flat"; }
40609				if(!is_callback) { is_callback = 0; }
40610				obj = this._get_node(obj);
40611				if(!obj || obj === -1) { obj = this.get_container().find("> ul > li"); }
40612				li_attr = $.isArray(li_attr) ? li_attr : [ "id", "class" ];
40613				if(!is_callback && this.data.types && $.inArray(s.types.type_attr, li_attr) === -1) { li_attr.push(s.types.type_attr); }
40614
40615				a_attr = $.isArray(a_attr) ? a_attr : [ ];
40616
40617				if(!is_callback) { result += "<root>"; }
40618				obj.each(function () {
40619					result += "<item";
40620					li = $(this);
40621					$.each(li_attr, function (i, v) { result += " " + v + "=\"" + (li.attr(v) || "").replace(/jstree[^ ]*|$/ig,'').replace(/^\s+$/ig,"") + "\""; });
40622					if(li.hasClass("jstree-open")) { result += " state=\"open\""; }
40623					if(li.hasClass("jstree-closed")) { result += " state=\"closed\""; }
40624					if(tp === "flat") { result += " parent_id=\"" + is_callback + "\""; }
40625					result += ">";
40626					result += "<content>";
40627					a = li.children("a");
40628					a.each(function () {
40629						tmp1 = $(this);
40630						lang = false;
40631						result += "<name";
40632						if($.inArray("languages", s.plugins) !== -1) {
40633							$.each(s.languages, function (k, z) {
40634								if(tmp1.hasClass(z)) { result += " lang=\"" + z + "\""; lang = z; return false; }
40635							});
40636						}
40637						if(a_attr.length) { 
40638							$.each(a_attr, function (k, z) {
40639								result += " " + z + "=\"" + (tmp1.attr(z) || "").replace(/jstree[^ ]*|$/ig,'') + "\"";
40640							});
40641						}
40642						if(tmp1.children("ins").get(0).className.replace(/jstree[^ ]*|$/ig,'').replace(/^\s+$/ig,"").length) {
40643							result += ' icon="' + tmp1.children("ins").get(0).className.replace(/jstree[^ ]*|$/ig,'').replace(/^\s+$/ig,"") + '"';
40644						}
40645						if(tmp1.children("ins").get(0).style.backgroundImage.length) {
40646							result += ' icon="' + tmp1.children("ins").get(0).style.backgroundImage.replace("url(","").replace(")","") + '"';
40647						}
40648						result += ">";
40649						result += "<![CDATA[" + _this.get_text(tmp1, lang) + "]]>";
40650						result += "</name>";
40651					});
40652					result += "</content>";
40653					tmp2 = li[0].id;
40654					li = li.find("> ul > li");
40655					if(li.length) { tmp2 = _this.get_xml(tp, li, li_attr, a_attr, tmp2); }
40656					else { tmp2 = ""; }
40657					if(tp == "nest") { result += tmp2; }
40658					result += "</item>";
40659					if(tp == "flat") { result += tmp2; }
40660				});
40661				if(!is_callback) { result += "</root>"; }
40662				return result;
40663			}
40664		}
40665	});
40666})(jQuery);
40667//*/
40668
40669/*
40670 * jsTree search plugin 1.0
40671 * Enables both sync and async search on the tree
40672 * DOES NOT WORK WITH JSON PROGRESSIVE RENDER
40673 */
40674(function ($) {
40675	$.expr[':'].jstree_contains = function(a,i,m){
40676		return (a.textContent || a.innerText || "").toLowerCase().indexOf(m[3].toLowerCase())>=0;
40677	};
40678	$.jstree.plugin("search", {
40679		__init : function () {
40680			this.data.search.str = "";
40681			this.data.search.result = $();
40682		},
40683		defaults : {
40684			ajax : false, // OR ajax object
40685			case_insensitive : false
40686		},
40687		_fn : {
40688			search : function (str, skip_async) {
40689				if(str === "") { return; }
40690				var s = this.get_settings().search, 
40691					t = this,
40692					error_func = function () { },
40693					success_func = function () { };
40694				this.data.search.str = str;
40695
40696				if(!skip_async && s.ajax !== false && this.get_container().find(".jstree-closed:eq(0)").length > 0) {
40697					this.search.supress_callback = true;
40698					error_func = function () { };
40699					success_func = function (d, t, x) {
40700						var sf = this.get_settings().search.ajax.success; 
40701						if(sf) { d = sf.call(this,d,t,x) || d; }
40702						this.data.search.to_open = d;
40703						this._search_open();
40704					};
40705					s.ajax.context = this;
40706					s.ajax.error = error_func;
40707					s.ajax.success = success_func;
40708					if($.isFunction(s.ajax.url)) { s.ajax.url = s.ajax.url.call(this, str); }
40709					if($.isFunction(s.ajax.data)) { s.ajax.data = s.ajax.data.call(this, str); }
40710					if(!s.ajax.data) { s.ajax.data = { "search_string" : str }; }
40711					if(!s.ajax.dataType || /^json/.exec(s.ajax.dataType)) { s.ajax.dataType = "json"; }
40712					$.ajax(s.ajax);
40713					return;
40714				}
40715				if(this.data.search.result.length) { this.clear_search(); }
40716				this.data.search.result = this.get_container().find("a" + (this.data.languages ? "." + this.get_lang() : "" ) + ":" + (s.case_insensitive ? "jstree_contains" : "contains") + "(" + this.data.search.str + ")");
40717				this.data.search.result.addClass("jstree-search").parents(".jstree-closed").each(function () {
40718					t.open_node(this, false, true);
40719				});
40720				this.__callback({ nodes : this.data.search.result, str : str });
40721			},
40722			clear_search : function (str) {
40723				this.data.search.result.removeClass("jstree-search");
40724				this.__callback(this.data.search.result);
40725				this.data.search.result = $();
40726			},
40727			_search_open : function (is_callback) {
40728				var _this = this,
40729					done = true,
40730					current = [],
40731					remaining = [];
40732				if(this.data.search.to_open.length) {
40733					$.each(this.data.search.to_open, function (i, val) {
40734						if(val == "#") { return true; }
40735						if($(val).length && $(val).is(".jstree-closed")) { current.push(val); }
40736						else { remaining.push(val); }
40737					});
40738					if(current.length) {
40739						this.data.search.to_open = remaining;
40740						$.each(current, function (i, val) { 
40741							_this.open_node(val, function () { _this._search_open(true); }); 
40742						});
40743						done = false;
40744					}
40745				}
40746				if(done) { this.search(this.data.search.str, true); }
40747			}
40748		}
40749	});
40750})(jQuery);
40751//*/
40752
40753/*
40754 * jsTree contextmenu plugin 1.0
40755 */
40756(function ($) {
40757	$.vakata.context = {
40758		cnt		: $("<div id='vakata-contextmenu'>"),
40759		vis		: false,
40760		tgt		: false,
40761		par		: false,
40762		func	: false,
40763		data	: false,
40764		show	: function (s, t, x, y, d, p) {
40765			var html = $.vakata.context.parse(s), h, w;
40766			if(!html) { return; }
40767			$.vakata.context.vis = true;
40768			$.vakata.context.tgt = t;
40769			$.vakata.context.par = p || t || null;
40770			$.vakata.context.data = d || null;
40771			$.vakata.context.cnt
40772				.html(html)
40773				.css({ "visibility" : "hidden", "display" : "block", "left" : 0, "top" : 0 });
40774			h = $.vakata.context.cnt.height();
40775			w = $.vakata.context.cnt.width();
40776			if(x + w >
40776 $(document).width()) { 
40777				x = $(document).width() - (w + 5); 
40778				$.vakata.context.cnt.find("li > ul").addClass("right"); 
40779			}
40780			if(y + h > $(document).height()) { 
40781				y = y - (h + t[0].offsetHeight); 
40782				$.vakata.context.cnt.find("li > ul").addClass("bottom"); 
40783			}
40784
40785			$.vakata.context.cnt
40786				.css({ "left" : x, "top" : y })
40787				.find("li:has(ul)")
40788					.bind("mouseenter", function (e) { 
40789						var w = $(document).width(),
40790							h = $(document).height(),
40791							ul = $(this).children("ul").show(); 
40792						if(w !== $(document).width()) { ul.toggleClass("right"); }
40793						if(h !== $(document).height()) { ul.toggleClass("bottom"); }
40794					})
40795					.bind("mouseleave", function (e) { 
40796						$(this).children("ul").hide(); 
40797					})
40798					.end()
40799				.css({ "visibility" : "visible" })
40800				.show();
40801			$(document).triggerHandler("context_show.vakata");
40802		},
40803		hide	: function () {
40804			$.vakata.context.vis = false;
40805			$.vakata.context.cnt.attr("class","").hide();
40806			$(document).triggerHandler("context_hide.vakata");
40807		},
40808		parse	: function (s, is_callback) {
40809			if(!s) { return false; }
40810			var str = "",
40811				tmp = false,
40812				was_sep = true;
40813			if(!is_callback) { $.vakata.context.func = {}; }
40814			str += "<ul>";
40815			$.each(s, function (i, val) {
40816				if(!val) { return true; }
40817				$.vakata.context.func[i] = val.action;
40818				if(!was_sep && val.separator_before) {
40819					str += "<li class='vakata-separator vakata-separator-before'></li>";
40820				}
40821				was_sep = false;
40822				str += "<li class='" + (val._class || "") + (val._disabled ? " jstree-contextmenu-disabled " : "") + "'><ins ";
40823				if(val.icon && val.icon.indexOf("/") === -1) { str += " class='" + val.icon + "' "; }
40824				if(val.icon && val.icon.indexOf("/") !== -1) { str += " style='background:url(" + val.icon + ") center center no-repeat;' "; }
40825				str += ">&#160;</ins><a href='#' rel='" + i + "'>";
40826				if(val.submenu) {
40827					str += "<span style='float:right;'>&raquo;</span>";
40828				}
40829				str += val.label + "</a>";
40830				if(val.submenu) {
40831					tmp = $.vakata.context.parse(val.submenu, true);
40832					if(tmp) { str += tmp; }
40833				}
40834				str += "</li>";
40835				if(val.separator_after) {
40836					str += "<li class='vakata-separator vakata-separator-after'></li>";
40837					was_sep = true;
40838				}
40839			});
40840			str = str.replace(/<li class\='vakata-separator vakata-separator-after'\><\/li\>$/,"");
40841			str += "</ul>";
40842			return str.length > 10 ? str : false;
40843		},
40844		exec	: function (i) {
40845			if($.isFunction($.vakata.context.func[i])) {
40846				$.vakata.context.func[i].call($.vakata.context.data, $.vakata.context.par);
40847				return true;
40848			}
40849			else { return false; }
40850		}
40851	};
40852	$(function () {
40853		var css_string = '' + 
40854			'#vakata-contextmenu { display:none; position:absolute; margin:0; padding:0; min-width:180px; background:#ebebeb; border:1px solid silver; z-index:10000; *width:180px; } ' + 
40855			'#vakata-contextmenu ul { min-width:180px; *width:180px; } ' + 
40856			'#vakata-contextmenu ul, #vakata-contextmenu li { margin:0; padding:0; list-style-type:none; display:block; } ' + 
40857			'#vakata-contextmenu li { line-height:20px; min-height:20px; position:relative; padding:0px; } ' + 
40858			'#vakata-contextmenu li a { padding:1px 6px; line-height:17px; display:block; text-decoration:none; margin:1px 1px 0 1px; } ' + 
40859			'#vakata-contextmenu li ins { float:left; width:16px; height:16px; text-decoration:none; margin-right:2px; } ' + 
40860			'#vakata-contextmenu li a:hover, #vakata-contextmenu li.vakata-hover > a { background:gray; color:white; } ' + 
40861			'#vakata-contextmenu li ul { display:none; position:absolute; top:-2px; left:100%; background:#ebebeb; border:1px solid gray; } ' + 
40862			'#vakata-contextmenu .right { right:100%; left:auto; } ' + 
40863			'#vakata-contextmenu .bottom { bottom:-1px; top:auto; } ' + 
40864			'#vakata-contextmenu li.vakata-separator { min-height:0; height:1px; line-height:1px; font-size:1px; overflow:hidden; margin:0 2px; background:silver; /* border-top:1px solid #fefefe; */ padding:0; } ';
40865		$.vakata.css.add_sheet({ str : css_string });
40866		$.vakata.context.cnt
40867			.delegate("a","click", function (e) { e.preventDefault(); })
40868			.delegate("a","mouseup", function (e) {
40869				if(!$(this).parent().hasClass("jstree-contextmenu-disabled") && $.vakata.context.exec($(this).attr("rel"))) {
40870					$.vakata.context.hide();
40871				}
40872				else { $(this).blur(); }
40873			})
40874			.delegate("a","mouseover", function () {
40875				$.vakata.context.cnt.find(".vakata-hover").removeClass("vakata-hover");
40876			})
40877			.appendTo("body");
40878		$(document).bind("mousedown", function (e) { if($.vakata.context.vis && !$.contains($.vakata.context.cnt[0], e.target)) { $.vakata.context.hide(); } });
40879		if(typeof $.hotkeys !== "undefined") {
40880			$(document)
40881				.bind("keydown", "up", function (e) { 
40882					if($.vakata.context.vis) { 
40883						var o = $.vakata.context.cnt.find("ul:visible").last().children(".vakata-hover").removeClass("vakata-hover").prevAll("li:not(.vakata-separator)").first();
40884						if(!o.length) { o = $.vakata.context.cnt.find("ul:visible").last().children("li:not(.vakata-separator)").last(); }
40885						o.addClass("vakata-hover");
40886						e.stopImmediatePropagation(); 
40887						e.preventDefault();
40888					} 
40889				})
40890				.bind("keydown", "down", function (e) { 
40891					if($.vakata.context.vis) { 
40892						var o = $.vakata.context.cnt.find("ul:visible").last().children(".vakata-hover").removeClass("vakata-hover").nextAll("li:not(.vakata-separator)").first();
40893						if(!o.length) { o = $.vakata.context.cnt.find("ul:visible").last().children("li:not(.vakata-separator)").first(); }
40894						o.addClass("vakata-hover");
40895						e.stopImmediatePropagation(); 
40896						e.preventDefault();
40897					} 
40898				})
40899				.bind("keydown", "right", function (e) { 
40900					if($.vakata.context.vis) { 
40901						$.vakata.context.cnt.find(".vakata-hover").children("ul").show().children("li:not(.vakata-separator)").removeClass("vakata-hover").first().addClass("vakata-hover");
40902						e.stopImmediatePropagation(); 
40903						e.preventDefault();
40904					} 
40905				})
40906				.bind("keydown", "left", function (e) { 
40907					if($.vakata.context.vis) { 
40908						$.vakata.context.cnt.find(".vakata-hover").children("ul").hide().children(".vakata-separator").removeClass("vakata-hover");
40909						e.stopImmediatePropagation(); 
40910						e.preventDefault();
40911					} 
40912				})
40913				.bind("keydown", "esc", function (e) { 
40914					$.vakata.context.hide(); 
40915					e.preventDefault();
40916				})
40917				.bind("keydown", "space", function (e) { 
40918					$.vakata.context.cnt.find(".vakata-hover").last().children("a").click();
40919					e.preventDefault();
40920				});
40921		}
40922	});
40923
40924	$.jstree.plugin("contextmenu", {
40925		__init : function () {
40926			this.get_container()
40927				.delegate("a", "contextmenu.jstree", $.proxy(function (e) {
40928						e.preventDefault();
40929						this.show_contextmenu(e.currentTarget, e.pageX, e.pageY);
40930					}, this))
40931				.bind("destroy.jstree", $.proxy(function () {
40932						if(this.data.contextmenu) {
40933							$.vakata.context.hide();
40934						}
40935					}, this));
40936			$(document).bind("context_hide.vakata", $.proxy(function () { this.data.contextmenu = false; }, this));
40937		},
40938		defaults : { 
40939			select_node : false, // requires UI plugin
40940			show_at_node : true,
40941			items : { // Could be a function that should return an object like this one
40942				"create" : {
40943					"separator_before"	: false,
40944					"separator_after"	: true,
40945					"label"				: "Create",
40946					"action"			: function (obj) { this.create(obj); }
40947				},
40948				"rename" : {
40949					"separator_before"	: false,
40950					"separator_after"	: false,
40951					"label"				: "Rename",
40952					"action"			: function (obj) { this.rename(obj); }
40953				},
40954				"remove" : {
40955					"separator_before"	: false,
40956					"icon"				: false,
40957					"separator_after"	: false,
40958					"label"				: "Delete",
40959					"action"			: function (obj) { this.remove(obj); }
40960				},
40961				"ccp" : {
40962					"separator_before"	: true,
40963					"icon"				: false,
40964					"separator_after"	: false,
40965					"label"				: "Edit",
40966					"action"			: false,
40967					"submenu" : { 
40968						"cut" : {
40969							"separator_before"	: false,
40970							"separator_after"	: false,
40971							"label"				: "Cut",
40972							"action"			: function (obj) { this.cut(obj); }
40973						},
40974						"copy" : {
40975							"separator_before"	: false,
40976							"icon"				: false,
40977							"separator_after"	: false,
40978							"label"				: "Copy",
40979							"action"			: function (obj) { this.copy(obj); }
40980						},
40981						"paste" : {
40982							"separator_before"	: false,
40983							"icon"				: false,
40984							"separator_after"	: false,
40985							"label"				: "Paste",
40986							"action"			: function (obj) { this.paste(obj); }
40987						}
40988					}
40989				}
40990			}
40991		},
40992		_fn : {
40993			show_contextmenu : function (obj, x, y) {
40994				obj = this._get_node(obj);
40995				var s = this.get_settings().contextmenu,
40996					a = obj.children("a:visible:eq(0)"),
40997					o = false;
40998				if(s.select_node && this.data.ui && !this.is_selected(obj)) {
40999					this.deselect_all();
41000					this.select_node(obj, true);
41001				}
41002				if(s.show_at_node || typeof x === "undefined" || typeof y === "undefined") {
41003					o = a.offset();
41004					x = o.left;
41005					y = o.top + this.data.core.li_height;
41006				}
41007				if($.isFunction(s.items)) { s.items = s.items.call(this, obj); }
41008				this.data.contextmenu = true;
41009				$.vakata.context.show(s.items, a, x, y, this, obj);
41010				if(this.data.themes) { $.vakata.context.cnt.attr("class", "jstree-" + this.data.themes.theme + "-context"); }
41011			}
41012		}
41013	});
41014})(jQuery);
41015//*/
41016
41017/* 
41018 * jsTree types plugin 1.0
41019 * Adds support types of nodes
41020 * You can set an attribute on each li node, that represents its type.
41021 * According to the type setting the node may get custom icon/validation rules
41022 */
41023(function ($) {
41024	$.jstree.plugin("types", {
41025		__init : function () {
41026			var s = this._get_settings().types;
41027			this.data.types.attach_to = [];
41028			this.get_container()
41029				.bind("init.jstree", $.proxy(function () { 
41030						var types = s.types, 
41031							attr  = s.type_attr, 
41032							icons_css = "", 
41033							_this = this;
41034
41035						$.each(types, function (i, tp) {
41036							$.each(tp, function (k, v) { 
41037								if(!/^(max_depth|max_children|icon|valid_children)$/.test(k)) { _this.data.types.attach_to.push(k); }
41038							});
41039							if(!tp.icon) { return true; }
41040							if( tp.icon.image || tp.icon.position) {
41041								if(i == "default")	{ icons_css += '.jstree-' + _this.get_index() + ' a > .jstree-icon { '; }
41042								else				{ icons_css += '.jstree-' + _this.get_index() + ' li[' + attr + '=' + i + '] > a > .jstree-icon { '; }
41043								if(tp.icon.image)	{ icons_css += ' background-image:url(' + tp.icon.image + '); '; }
41044								if(tp.icon.position){ icons_css += ' background-position:' + tp.icon.position + '; '; }
41045								else				{ icons_css += ' background-position:0 0; '; }
41046								icons_css += '} ';
41047							}
41048						});
41049						if(icons_css != "") { $.vakata.css.add_sheet({ 'str' : icons_css }); }
41050					}, this))
41051				.bind("before.jstree", $.proxy(function (e, data) { 
41052						if($.inArray(data.func, this.data.types.attach_to) !== -1) {
41053							var s = this._get_settings().types.types,
41054								t = this._get_type(data.args[0]);
41055							if(
41056								( 
41057									(s[t] && typeof s[t][data.func] !== "undefined") || 
41058									(s["default"] && typeof s["default"][data.func] !== "undefined")
41059								) && !this._check(data.func, data.args[0])
41060							) {
41061								e.stopImmediatePropagation();
41062								return false;
41063							}
41064						}
41065					}, this));
41066		},
41067		defaults : {
41068			// defines maximum number of root nodes (-1 means unlimited, -2 means disable max_children checking)
41069			max_children		: -1,
41070			// defines the maximum depth of the tree (-1 means unlimited, -2 means disable max_depth checking)
41071			max_depth			: -1,
41072			// defines valid node types for the root nodes
41073			valid_children		: "all",
41074
41075			// where is the type stores (the rel attribute of the LI element)
41076			type_attr : "rel",
41077			// a list of types
41078			types : {
41079				// the default type
41080				"default" : {
41081					"max_children"	: -1,
41082					"max_depth"		: -1,
41083					"valid_children": "all"
41084
41085					// Bound functions - you can bind any other function here (using boolean or function)
41086					//"select_node"	: true,
41087					//"open_node"	: true,
41088					//"close_node"	: true,
41089					//"create_node"	: true,
41090					//"delete_node"	: true
41091				}
41092			}
41093		},
41094		_fn : {
41095			_get_type : function (obj) {
41096				obj = this._get_node(obj);
41097				return (!obj || !obj.length) ? false : obj.attr(this._get_settings().types.type_attr) || "default";
41098			},
41099			set_type : function (str, obj) {
41100				obj = this._get_node(obj);
41101				return (!obj.length || !str) ? false : obj.attr(this._get_settings().types.type_attr, str);
41102			},
41103			_check : function (rule, obj, opts) {
41104				var v = false, t = this._get_type(obj), d = 0, _this = this, s = this._get_settings().types;
41105				if(obj === -1) { 
41106					if(!!s[rule]) { v = s[rule]; }
41107					else { return; }
41108				}
41109				else {
41110					if(t === false) { return; }
41111					if(!!s.types[t] && !!s.types[t][rule]) { v = s.types[t][rule]; }
41112					else if(!!s.types["default"] && !!s.types["default"][rule]) { v = s.types["default"][rule]; }
41113				}
41114				if($.isFunction(v)) { v = v.call(this, obj); }
41115				if(rule === "max_depth" && obj !== -1 && opts !== false && s.max_depth !== -2 && v !== 0) {
41116					// also include the node itself - otherwise if root node it is not checked
41117					this._get_node(obj).children("a:eq(0)").parentsUntil(".jstree","li").each(function (i) {
41118						// check if current depth already exceeds global tree depth
41119						if(s.max_depth !== -1 && s.max_depth - (i + 1) <= 0) { v = 0; return false; }
41120						d = (i === 0) ? v : _this._check(rule, this, false);
41121						// check if current node max depth is already matched or exceeded
41122						if(d !== -1 && d - (i + 1) <= 0) { v = 0; return false; }
41123						// otherwise - set the max depth to the current value minus current depth
41124						if(d >= 0 && (d - (i + 1) < v || v < 0) ) { v = d - (i + 1); }
41125						// if the global tree depth exists and it minus the nodes calculated so far is less than `v` or `v` is unlimited
41126						if(s.max_depth >= 0 && (s.max_depth - (i + 1) < v || v < 0) ) { v = s.max_depth - (i + 1); }
41127					});
41128				}
41129				return v;
41130			},
41131			check_move : function () {
41132				if(!this.__call_old()) { return false; }
41133				var m  = this._get_move(),
41134					s  = m.rt._get_settings().types,
41135					mc = m.rt._check("max_children", m.cr),
41136					md = m.rt._check("max_depth", m.cr),
41137					vc = m.rt._check("valid_children", m.cr),
41138					ch = 0, d = 1, t;
41139
41140				if(vc === "none") { return false; } 
41141				if($.isArray(vc) && m.ot && m.ot._get_type) {
41142					m.o.each(function () {
41143						if($.inArray(m.ot._get_type(this), vc) === -1) { d = false; return false; }
41144					});
41145					if(d === false) { return false; }
41146				}
41147				if(s.max_children !== -2 && mc !== -1) {
41148					ch = m.cr === -1 ? this.get_container().children("> ul > li").not(m.o).length : m.cr.children("> ul > li").not(m.o).length;
41149					if(ch + m.o.length > mc) { return false; }
41150				}
41151				if(s.max_depth !== -2 && md !== -1) {
41152					d = 0;
41153					if(md === 0) { return false; }
41154					if(typeof m.o.d === "undefined") {
41155						// TODO: deal with progressive rendering and async when checking max_depth (how to know the depth of the moved node)
41156						t = m.o;
41157						while(t.length > 0) {
41158							t = t.find("> ul > li");
41159							d ++;
41160						}
41161						m.o.d = d;
41162					}
41163					if(md - m.o.d < 0) { return false; }
41164				}
41165				return true;
41166			},
41167			create_node : function (obj, position, js, callback, is_loaded, skip_check) {
41168				if(!skip_check && (is_loaded || this._is_loaded(obj))) {
41169					var p  = (position && position.match(/^before|after$/i) && obj !== -1) ? this._get_parent(obj) : this._get_node(obj),
41170						s  = this._get_settings().types,
41171						mc = this._check("max_children", p),
41172						md = this._check("max_depth", p),
41173						vc = this._check("valid_children", p),
41174						ch;
41175					if(!js) { js = {}; }
41176					if(vc === "none") { return false; } 
41177					if($.isArray(vc)) {
41178						if(!js.attr || !js.attr[s.type_attr]) { 
41179							if(!js.attr) { js.attr = {}; }
41180							js.attr[s.type_attr] = vc[0]; 
41181						}
41182						else {
41183							if($.inArray(js.attr[s.type_attr], vc) === -1) { return false; }
41184						}
41185					}
41186					if(s.max_children !== -2 && mc !== -1) {
41187						ch = p === -1 ? this.get_container().children("> ul > li").length : p.children("> ul > li").length;
41188						if(ch + 1 > mc) { return false; }
41189					}
41190					if(s.max_depth !== -2 && md !== -1 && (md - 1) < 0) { return false; }
41191				}
41192				return this.__call_old(true, obj, position, js, callback, is_loaded, skip_check);
41193			}
41194		}
41195	});
41196})(jQuery);
41197//*/
41198
41199/* 
41200 * jsTree HTML data 1.0
41201 * The HTML data store. Datastores are build by replacing the `load_node` and `_is_loaded` functions.
41202 */
41203(function ($) {
41204	$.jstree.plugin("html_data", {
41205		__init : function () { 
41206			// this used to use html() and clean the whitespace, but this way any attached data was lost
41207			this.data.html_data.original_container_html = this.get_container().find(" > ul > li").clone(true);
41208			// remove white space from LI node - otherwise nodes appear a bit to the right
41209			this.data.html_data.original_container_html.find("li").andSelf().contents().filter(function() { return this.nodeType == 3; }).remove();
41210		},
41211		defaults : { 
41212			data : false,
41213			ajax : false,
41214			correct_state : true
41215		},
41216		_fn : {
41217			load_node : function (obj, s_call, e_call) { var _this = this; this.load_node_html(obj, function () { _this.__callback({ "obj" : obj }); s_call.call(this); }, e_call); },
41218			_is_loaded : function (obj) { 
41219				obj = this._get_node(obj); 
41220				return obj == -1 || !obj || !this._get_settings().html_data.ajax || obj.is(".jstree-open, .jstree-leaf") || obj.children("ul").children("li").size() > 0;
41221			},
41222			load_node_html : function (obj, s_call, e_call) {
41223				var d,
41224					s = this.get_settings().html_data,
41225					error_func = function () {},
41226					success_func = function () {};
41227				obj = this._get_node(obj);
41228				if(obj && obj !== -1) {
41229					if(obj.data("jstree-is-loading")) { return; }
41230					else { obj.data("jstree-is-loading",true); }
41231				}
41232				switch(!0) {
41233					case (!s.data && !s.ajax):
41234						if(!obj || obj == -1) {
41235							this.get_container()
41236								.children("ul").empty()
41237								.append(this.data.html_data.original_container_html)
41238								.find("li, a").filter(function () { return this.firstChild.tagName !== "INS"; }).prepend("<ins class='jstree-icon'>&#160;</ins>").end()
41239								.filter("a").children("ins:first-child").not(".jstree-icon").addClass("jstree-icon");
41240							this.clean_node();
41241						}
41242						if(s_call) { s_call.call(this); }
41243						break;
41244					case (!!s.data && !s.ajax) || (!!s.data && !!s.ajax && (!obj || obj === -1)):
41245						if(!obj || obj == -1) {
41246							d = $(s.data);
41247							if(!d.is("ul")) { d = $("<ul>").append(d); }
41248							this.get_container()
41249								.children("ul").empty().append(d.children())
41250								.find("li, a").filter(function () { return this.firstChild.tagName !== "INS"; }).prepend("<ins class='jstree-icon'>&#160;</ins>").end()
41251								.filter("a").children("ins:first-child").not(".jstree-icon").addClass("jstree-icon");
41252							this.clean_node();
41253						}
41254						if(s_call) { s_call.call(this); }
41255						break;
41256					case (!s.data && !!s.ajax) || (!!s.data && !!s.ajax && obj && obj !== -1):
41257						obj = this._get_node(obj);
41258						error_func = function (x, t, e) {
41259							var ef = this.get_settings().html_data.ajax.error; 
41260							if(ef) { ef.call(this, x, t, e); }
41261							if(obj != -1 && obj.length) {
41262								obj.children(".jstree-loading").removeClass("jstree-loading");
41263								obj.data("jstree-is-loading",false);
41264								if(t === "success" && s.correct_state) { obj.removeClass("jstree-open jstree-closed").addClass("jstree-leaf"); }
41265							}
41266							else {
41267								if(t === "success" && s.correct_state) { this.get_container().children("ul").empty(); }
41268							}
41269							if(e_call) { e_call.call(this); }
41270						};
41271						success_func = function (d, t, x) {
41272							var sf = this.get_settings().html_data.ajax.success; 
41273							if(sf) { d = sf.call(this,d,t,x) || d; }
41274							if(d == "") {
41275								return error_func.call(this, x, t, "");
41276							}
41277							if(d) {
41278								d = $(d);
41279								if(!d.is("ul")) { d = $("<ul>").append(d); }
41280								if(obj == -1 || !obj) { this.get_container().children("ul").empty().append(d.children()).find("li, a").filter(function () { return this.firstChild.tagName !== "INS"; }).prepend("<ins class='jstree-icon'>&#160;</ins>").end().filter("a").children("ins:first-child").not(".jstree-icon").addClass("jstree-icon"); }
41281								else { obj.children(".jstree-loading").removeClass("jstree-loading"); obj.append(d).find("li, a").filter(function () { return this.firstChild.tagName !== "INS"; }).prepend("<ins class='jstree-icon'>&#160;</ins>").end().filter("a").children("ins:first-child").not(".jstree-icon").addClass("jstree-icon"); obj.data("jstree-is-loading",false); }
41282								this.clean_node(obj);
41283								if(s_call) { s_call.call(this); }
41284							}
41285							else {
41286								if(obj && obj !== -1) {
41287									obj.children(".jstree-loading").removeClass("jstree-loading");
41288									obj.data("jstree-is-loading",false);
41289									if(s.correct_state) { 
41290										obj.removeClass("jstree-open jstree-closed").addClass("jstree-leaf"); 
41291										if(s_call) { s_call.call(this); } 
41292									}
41293								}
41294								else {
41295									if(s.correct_state) { 
41296										this.get_container().children("ul").empty();
41297										if(s_call) { s_call.call(this); } 
41298									}
41299								}
41300							}
41301						};
41302						s.ajax.context = this;
41303						s.ajax.error = error_func;
41304						s.ajax.success = success_func;
41305						if(!s.ajax.dataType) { s.ajax.dataType = "html"; }
41306						if($.isFunction(s.ajax.url)) { s.ajax.url = s.ajax.url.call(this, obj); }
41307						if($.isFunction(s.ajax.data)) { s.ajax.data = s.ajax.data.call(this, obj); }
41308						$.ajax(s.ajax);
41309						break;
41310				}
41311			}
41312		}
41313	});
41314	// include the HTML data plugin by default
41315	$.jstree.defaults.plugins.push("html_data");
41316})(jQuery);
41317//*/
41318
41319/* 
41320 * jsTree themeroller plugin 1.0
41321 * Adds support for jQuery UI themes. Include this at the end of your plugins list, also make sure "themes" is not included.
41322 */
41323(function ($) {
41324	$.jstree.plugin("themeroller", {
41325		__init : function () {
41326			var s = this._get_settings().themeroller;
41327			this.get_container()
41328				.addClass("ui-widget-content")
41329				.delegate("a","mouseenter.jstree", function () {
41330					$(this).addClass(s.item_h);
41331				})
41332				.delegate("a","mouseleave.jstree", function () {
41333					$(this).removeClass(s.item_h);
41334				})
41335				.bind("open_node.jstree create_node.jstree", $.proxy(function (e, data) { 
41336						this._themeroller(data.rslt.obj);
41337					}, this))
41338				.bind("loaded.jstree refresh.jstree", $.proxy(function (e) {
41339						this._themeroller();
41340					}, this))
41341				.bind("close_node.jstree", $.proxy(function (e, data) {
41342						data.rslt.obj.children("ins").removeClass(s.opened).addClass(s.closed);
41343					}, this))
41344				.bind("select_node.jstree", $.proxy(function (e, data) {
41345						data.rslt.obj.children("a").addClass(s.item_a);
41346					}, this))
41347				.bind("deselect_node.jstree deselect_all.jstree", $.proxy(function (e, data) {
41348						this.get_container()
41349							.find("." + s.item_a).removeClass(s.item_a).end()
41350							.find(".jstree-clicked").addClass(s.item_a);
41351					}, this))
41352				.bind("move_node.jstree", $.proxy(function (e, data) {
41353						this._themeroller(data.rslt.o);
41354					}, this));
41355		},
41356		__destroy : function () {
41357			var s = this._get_settings().themeroller,
41358				c = [ "ui-icon" ];
41359			$.each(s, function (i, v) {
41360				v = v.split(" ");
41361				if(v.length) { c = c.concat(v); }
41362			});
41363			this.get_container()
41364				.removeClass("ui-widget-content")
41365				.find("." + c.join(", .")).removeClass(c.join(" "));
41366		},
41367		_fn : {
41368			_themeroller : function (obj) {
41369				var s = this._get_settings().themeroller;
41370				obj = !obj || obj == -1 ? this.get_container() : this._get_node(obj).parent();
41371				obj
41372					.find("li.jstree-closed > ins.jstree-icon").removeClass(s.opened).addClass("ui-icon " + s.closed).end()
41373					.find("li.jstree-open > ins.jstree-icon").removeClass(s.closed).addClass("ui-icon " + s.opened).end()
41374					.find("a").addClass(s.item)
41375						.children("ins.jstree-icon").addClass("ui-icon " + s.item_icon);
41376			}
41377		},
41378		defaults : {
41379			"opened" : "ui-icon-triangle-1-se",
41380			"closed" : "ui-icon-triangle-1-e",
41381			"item" : "ui-state-default",
41382			"item_h" : "ui-state-hover",
41383			"item_a" : "ui-state-active",
41384			"item_icon" : "ui-icon-folder-collapsed"
41385		}
41386	});
41387	$(function() {
41388		var css_string = '.jstree .ui-icon { overflow:visible; } .jstree a { padding:0 2px; }';
41389		$.vakata.css.add_sheet({ str : css_string });
41390	});
41391})(jQuery);
41392//*/
41393
41394/* 
41395 * jsTree unique plugin 1.0
41396 * Forces different names amongst siblings (still a bit experimental)
41397 * NOTE: does not check language versions (it will not be possible to have nodes with the same title, even in different languages)
41398 */
41399(function ($) {
41400	$.jstree.plugin("unique", {
41401		__init : function () {
41402			this.get_container()
41403				.bind("before.jstree", $.proxy(function (e, data) { 
41404						var nms = [], res = true, p, t;
41405						if(data.func == "move_node") {
41406							// obj, ref, position, is_copy, is_prepared, skip_check
41407							if(data.args[4] === true) {
41408								if(data.args[0].o && data.args[0].o.length) {
41409									data.args[0].o.children("a").each(function () { nms.push($(this).text().replace(/^\s+/g,"")); });
41410									res = this._check_unique(nms, data.args[0].np.find("> ul > li").not(data.args[0].o));
41411								}
41412							}
41413						}
41414						if(data.func == "create_node") {
41415							// obj, position, js, callback, is_loaded
41416							if(data.args[4] || this._is_loaded(data.args[0])) {
41417								p = this._get_node(data.args[0]);
41418								if(data.args[1] && (data.args[1] === "before" || data.args[1] === "after")) {
41419									p = this._get_parent(data.args[0]);
41420									if(!p || p === -1) { p = this.get_container(); }
41421								}
41422								if(typeof data.args[2] === "string") { nms.push(data.args[2]); }
41423								else if(!data.args[2] || !data.args[2].data) { nms.push(this._get_settings().core.strings.new_node); }
41424								else { nms.push(data.args[2].data); }
41425								res = this._check_unique(nms, p.find("> ul > li"));
41426							}
41427						}
41428						if(data.func == "rename_node") {
41429							// obj, val
41430							nms.push(data.args[1]);
41431							t = this._get_node(data.args[0]);
41432							p = this._get_parent(t);
41433							if(!p || p === -1) { p = this.get_container(); }
41434							res = this._check_unique(nms, p.find("> ul > li").not(t));
41435						}
41436						if(!res) {
41437							e.stopPropagation();
41438							return false;
41439						}
41440					}, this));
41441		},
41442		_fn : { 
41443			_check_unique : function (nms, p) {
41444				var cnms = [];
41445				p.children("a").each(function () { cnms.push($(this).text().replace(/^\s+/g,"")); });
41446				if(!cnms.length || !nms.length) { return true; }
41447				cnms = cnms.sort().join(",,").replace(/(,|^)([^,]+)(,,\2)+(,|$)/g,"$1$2$4").replace(/,,+/g,",").replace(/,$/,"").split(",");
41448				if((cnms.length + nms.length) != cnms.concat(nms).sort().join(",,").replace(/(,|^)([^,]+)(,,\2)+(,|$)/g,"$1$2$4").replace(/,,+/g,",").replace(/,$/,"").split(",").length) {
41449					return false;
41450				}
41451				return true;
41452			},
41453			check_move : function () {
41454				if(!this.__call_old()) { return false; }
41455				var p = this._get_move(), nms = [];
41456				if(p.o && p.o.length) {
41457					p.o.children("a").each(function () { nms.push($(this).text().replace(/^\s+/g,"")); });
41458					return this._check_unique(nms, p.np.find("> ul > li").not(p.o));
41459				}
41460				return true;
41461			}
41462		}
41463	});
41464})(jQuery);
41465//*/
41466
41467/* FileSaver.js
41468 * A saveAs() FileSaver implementation.
41469 * 1.3.2
41470 * 2016-06-16 18:25:19
41471 *
41472 * By Eli Grey, http://eligrey.com
41473 * License: MIT
41474 *   See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md
41475 */
41476
41477/*global self */
41478/*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */
41479
41480/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */
41481
41482var saveAs = saveAs || (function(view) {
41483	"use strict";
41484	// IE <10 is explicitly unsupported
41485	if (typeof view === "undefined" || typeof navigator !== "undefined" && /MSIE [1-9]\./.test(navigator.userAgent)) {
41486		return;
41487	}
41488	var
41489		  doc = view.document
41490		  // only get URL when necessary in case Blob.js hasn't overridden it yet
41491		, get_URL = function() {
41492			return view.URL || view.webkitURL || view;
41493		}
41494		, save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a")
41495		, can_use_save_link = "download" in save_link
41496		, click = function(node) {
41497			var event = new MouseEvent("click");
41498			node.dispatchEvent(event);
41499		}
41500		, is_safari = /constructor/i.test(view.HTMLElement) || view.safari
41501		, is_chrome_ios =/CriOS\/[\d]+/.test(navigator.userAgent)
41502		, throw_outside = function(ex) {
41503			(view.setImmediate || view.setTimeout)(function() {
41504				throw ex;
41505			}, 0);
41506		}
41507		, force_saveable_type = "application/octet-stream"
41508		// the Blob API is fundamentally broken as there is no "downloadfinished" event to subscribe to
41509		, arbitrary_revoke_timeout = 1000 * 40 // in ms
41510		, revoke = function(file) {
41511			var revoker = function() {
41512				if (typeof file === "string") { // file is an object URL
41513					get_URL().revokeObjectURL(file);
41514				} else { // file is a File
41515					file.remove();
41516				}
41517			};
41518			setTimeout(revoker, arbitrary_revoke_timeout);
41519		}
41520		, dispatch = function(filesaver, event_types, event) {
41521			event_types = [].concat(event_types);
41522			var i = event_types.length;
41523			while (i--) {
41524				var listener = filesaver["on" + event_types[i]];
41525				if (typeof listener === "function") {
41526					try {
41527						listener.call(filesaver, event || filesaver);
41528					} catch (ex) {
41529						throw_outside(ex);
41530					}
41531				}
41532			}
41533		}
41534		, auto_bom = function(blob) {
41535			// prepend BOM for UTF-8 XML and text/* types (including HTML)
41536			// note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF
41537			if (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) {
41538				return new Blob([String.fromCharCode(0xFEFF), blob], {type: blob.type});
41539			}
41540			return blob;
41541		}
41542		, FileSaver = function(blob, name, no_auto_bom) {
41543			if (!no_auto_bom) {
41544				blob = auto_bom(blob);
41545			}
41546			// First try a.download, then web filesystem, then object URLs
41547			var
41548				  filesaver = this
41549				, type = blob.type
41550				, force = type === force_saveable_type
41551				, object_url
41552				, dispatch_all = function() {
41553					dispatch(filesaver, "writestart progress write writeend".split(" "));
41554				}
41555				// on any filesys errors revert to saving with object URLs
41556				, fs_error = function() {
41557					if ((is_chrome_ios || (force && is_safari)) && view.FileReader) {
41558						// Safari doesn't allow downloading of blob urls
41559						var reader = new FileReader();
41560						reader.onloadend = function() {
41561							var url = is_chrome_ios ? reader.result : reader.result.replace(/^data:[^;]*;/, 'data:attachment/file;');
41562							var popup = view.open(url, '_blank');
41563							if(!popup) view.location.href = url;
41564							url=undefined; // release reference before dispatching
41565							filesaver.readyState = filesaver.DONE;
41566							dispatch_all();
41567						};
41568						reader.readAsDataURL(blob);
41569						filesaver.readyState = filesaver.INIT;
41570						return;
41571					}
41572					// don't create more object URLs than needed
41573					if (!object_url) {
41574						object_url = get_URL().createObjectURL(blob);
41575					}
41576					if (force) {
41577						view.location.href = object_url;
41578					} else {
41579						var opened = view.open(object_url, "_blank");
41580						if (!opened) {
41581							// Apple does not allow window.open, see https://developer.apple.com/library/safari/documentation/Tools/Conceptual/SafariExtensionGuide/WorkingwithWindowsandTabs/WorkingwithWindowsandTabs.html
41582							view.location.href = object_url;
41583						}
41584					}
41585					filesaver.readyState = filesaver.DONE;
41586					dispatch_all();
41587					revoke(object_url);
41588				}
41589			;
41590			filesaver.readyState = filesaver.INIT;
41591
41592			if (can_use_save_link) {
41593				object_url = get_URL().createObjectURL(blob);
41594				setTimeout(function() {
41595					save_link.href = object_url;
41596					save_link.download = name;
41597					click(save_link);
41598					dispatch_all();
41599					revoke(object_url);
41600					filesaver.readyState = filesaver.DONE;
41601				});
41602				return;
41603			}
41604
41605			fs_error();
41606		}
41607		, FS_proto = FileSaver.prototype
41608		, saveAs = function(blob, name, no_auto_bom) {
41609			return new FileSaver(blob, name || blob.name || "download", no_auto_bom);
41610		}
41611	;
41612	// IE 10+ (native saveAs)
41613	if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob) {
41614		return function(blob, name, no_auto_bom) {
41615			name = name || blob.name || "download";
41616
41617			if (!no_auto_bom) {
41618				blob = auto_bom(blob);
41619			}
41620			return navigator.msSaveOrOpenBlob(blob, name);
41621		};
41622	}
41623
41624	FS_proto.abort = function(){};
41625	FS_proto.readyState = FS_proto.INIT = 0;
41626	FS_proto.WRITING = 1;
41627	FS_proto.DONE = 2;
41628
41629	FS_proto.error =
41630	FS_proto.onwritestart =
41631	FS_proto.onprogress =
41632	FS_proto.onwrite =
41633	FS_proto.onabort =
41634	FS_proto.onerror =
41635	FS_proto.onwriteend =
41636		null;
41637
41638	return saveAs;
41639}(
41640	   typeof self !== "undefined" && self
41641	|| typeof window !== "undefined" && window
41642	|| this.content
41643));
41644// `self` is undefined in Firefox for Android content script context
41645// while `this` is nsIContentFrameMessageManager
41646// with an attribute `content` that corresponds to the window
41647
41648if (typeof module !== "undefined" && module.exports) {
41649  module.exports.saveAs = saveAs;
41650} else if ((typeof define !== "undefined" && define !== null) && (define.amd !== null)) {
41651  define("FileSaver.js", function() {
41652    return saveAs;
41653  });
41654}
41655
41656window.saveAs = saveAs;

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.