PageSourceSearch

https://www.sogeti.ie/wp-content/plugins/cg-archive-shortcode/src/…/src/js/lib/jquery-ui-1.13.3/jquery-ui.js

js sogeti.ie collected 2026-10-04 13:31:19 UTC 529,681 bytes, 19,070 lines download raw bytes

vendor: 529,681 bytes, lines 1-19070
1/*! jQuery UI - v1.13.3 - 2024-04-26
2* https://jqueryui.com
3* 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
4* Copyright OpenJS Foundation and other contributors; Licensed MIT */
5
6( function( factory ) {
7	"use strict";
8	
9	if ( typeof define === "function" && define.amd ) {
10
11		// AMD. Register as an anonymous module.
12		define( [ "jquery" ], factory );
13	} else {
14
15		// Browser globals
16		factory( jQuery );
17	}
18} )( function( $ ) {
19"use strict";
20
21$.ui = $.ui || {};
22
23var version = $.ui.version = "1.13.3";
24
25
26/*!
27 * jQuery UI Widget 1.13.3
28 * https://jqueryui.com
29 *
30 * Copyright OpenJS Foundation and other contributors
31 * Released under the MIT license.
32 * https://jquery.org/license
33 */
34
35//>>label: Widget
36//>>group: Core
37//>>description: Provides a factory for creating stateful widgets with a common API.
38//>>docs: https://api.jqueryui.com/jQuery.widget/
39//>>demos: https://jqueryui.com/widget/
40
41
42var widgetUuid = 0;
43var widgetHasOwnProperty = Array.prototype.hasOwnProperty;
44var widgetSlice = Array.prototype.slice;
45
46$.cleanData = ( function( orig ) {
47	return function( elems ) {
48		var events, elem, i;
49		for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) {
50
51			// Only trigger remove when necessary to save time
52			events = $._data( elem, "events" );
53			if ( events && events.remove ) {
54				$( elem ).triggerHandler( "remove" );
55			}
56		}
57		orig( elems );
58	};
59} )( $.cleanData );
60
61$.widget = function( name, base, prototype ) {
62	var existingConstructor, constructor, basePrototype;
63
64	// ProxiedPrototype allows the provided prototype to remain unmodified
65	// so that it can be used as a mixin for multiple widgets (#8876)
66	var proxiedPrototype = {};
67
68	var namespace = name.split( "." )[ 0 ];
69	name = name.split( "." )[ 1 ];
70	var fullName = namespace + "-" + name;
71
72	if ( !prototype ) {
73		prototype = base;
74		base = $.Widget;
75	}
76
77	if ( Array.isArray( prototype ) ) {
78		prototype = $.extend.apply( null, [ {} ].concat( prototype ) );
79	}
80
81	// Create selector for plugin
82	$.expr.pseudos[ fullName.toLowerCase() ] = function( elem ) {
83		return !!$.data( elem, fullName );
84	};
85
86	$[ namespace ] = $[ namespace ] || {};
87	existingConstructor = $[ namespace ][ name ];
88	constructor = $[ namespace ][ name ] = function( options, element ) {
89
90		// Allow instantiation without "new" keyword
91		if ( !this || !this._createWidget ) {
92			return new constructor( options, element );
93		}
94
95		// Allow instantiation without initializing for simple inheritance
96		// must use "new" keyword (the code above always passes args)
97		if ( arguments.length ) {
98			this._createWidget( options, element );
99		}
100	};
101
102	// Extend with the existing constructor to carry over any static properties
103	$.extend( constructor, existingConstructor, {
104		version: prototype.version,
105
106		// Copy the object used to create the prototype in case we need to
107		// redefine the widget later
108		_proto: $.extend( {}, prototype ),
109
110		// Track widgets that inherit from this widget in case this widget is
111		// redefined after a widget inherits from it
112		_childConstructors: []
113	} );
114
115	basePrototype = new base();
116
117	// We need to make the options hash a property directly on the new instance
118	// otherwise we'll modify the options hash on the prototype that we're
119	// inheriting from
120	basePrototype.options = $.widget.extend( {}, basePrototype.options );
121	$.each( prototype, function( prop, value ) {
122		if ( typeof value !== "function" ) {
123			proxiedPrototype[ prop ] = value;
124			return;
125		}
126		proxiedPrototype[ prop ] = ( function() {
127			function _super() {
128				return base.prototype[ prop ].apply( this, arguments );
129			}
130
131			function _superApply( args ) {
132				return base.prototype[ prop ].apply( this, args );
133			}
134
135			return function() {
136				var __super = this._super;
137				var __superApply = this._superApply;
138				var returnValue;
139
140				this._super = _super;
141				this._superApply = _superApply;
142
143				returnValue = value.apply( this, arguments );
144
145				this._super = __super;
146				this._superApply = __superApply;
147
148				return returnValue;
149			};
150		} )();
151	} );
152	constructor.prototype = $.widget.extend( basePrototype, {
153
154		// TODO: remove support for widgetEventPrefix
155		// always use the name + a colon as the prefix, e.g., draggable:start
156		// don't prefix for widgets that aren't DOM-based
157		widgetEventPrefix: existingConstructor ? ( basePrototype.widgetEventPrefix || name ) : name
158	}, proxiedPrototype, {
159		constructor: constructor,
160		namespace: namespace,
161		widgetName: name,
162		widgetFullName: fullName
163	} );
164
165	// If this widget is being redefined then we need to find all widgets that
166	// are inheriting from it and redefine all of them so that they inherit from
167	// the new version of this widget. We're essentially trying to replace one
168	// level in the prototype chain.
169	if ( existingConstructor ) {
170		$.each( existingConstructor._childConstructors, function( i, child ) {
171			var childPrototype = child.prototype;
172
173			// Redefine the child widget using the same prototype that was
174			// originally used, but inherit from the new version of the base
175			$.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor,
176				child._proto );
177		} );
178
179		// Remove the list of existing child constructors from the old constructor
180		// so the old child constructors can be garbage collected
181		delete existingConstructor._childConstructors;
182	} else {
183		base._childConstructors.push( constructor );
184	}
185
186	$.widget.bridge( name, constructor );
187
188	return constructor;
189};
190
191$.widget.extend = function( target ) {
192	var input = widgetSlice.call( arguments, 1 );
193	var inputIndex = 0;
194	var inputLength = input.length;
195	var key;
196	var value;
197
198	for ( ; inputIndex < inputLength; inputIndex++ ) {
199		for ( key in input[ inputIndex ] ) {
200			value = input[ inputIndex ][ key ];
201			if ( widgetHasOwnProperty.call( input[ inputIndex ], key ) && value !== undefined ) {
202
203				// Clone objects
204				if ( $.isPlainObject( value ) ) {
205					target[ key ] = $.isPlainObject( target[ key ] ) ?
206						$.widget.extend( {}, target[ key ], value ) :
207
208						// Don't extend strings, arrays, etc. with objects
209						$.widget.extend( {}, value );
210
211				// Copy everything else by reference
212				} else {
213					target[ key ] = value;
214				}
215			}
216		}
217	}
218	return target;
219};
220
221$.widget.bridge = function( name, object ) {
222	var fullName = object.prototype.widgetFullName || name;
223	$.fn[ name ] = function( options ) {
224		var isMethodCall = typeof options === "string";
225		var args = widgetSlice.call( arguments, 1 );
226		var returnValue = this;
227
228		if ( isMethodCall ) {
229
230			// If this is an empty collection, we need to have the instance method
231			// return undefined instead of the jQuery instance
232			if ( !this.length && options === "instance" ) {
233				returnValue = undefined;
234			} else {
235				this.each( function() {
236					var methodValue;
237					var instance = $.data( this, fullName );
238
239					if ( options === "instance" ) {
240						returnValue = instance;
241						return false;
242					}
243
244					if ( !instance ) {
245						return $.error( "cannot call methods on " + name +
246							" prior to initialization; " +
247							"attempted to call method '" + options + "'" );
248					}
249
250					if ( typeof instance[ options ] !== "function" ||
251						options.charAt( 0 ) === "_" ) {
252						return $.error( "no such method '" + options + "' for " + name +
253							" widget instance" );
254					}
255
256					methodValue = instance[ options ].apply( instance, args );
257
258					if ( methodValue !== instance && methodValue !== undefined ) {
259						returnValue = methodValue && methodValue.jquery ?
260							returnValue.pushStack( methodValue.get() ) :
261							methodValue;
262						return false;
263					}
264				} );
265			}
266		} else {
267
268			// Allow multiple hashes to be passed on init
269			if ( args.length ) {
270				options = $.widget.extend.apply( null, [ options ].concat( args ) );
271			}
272
273			this.each( function() {
274				var instance = $.data( this, fullName );
275				if ( instance ) {
276					instance.option( options || {} );
277					if ( instance._init ) {
278						instance._init();
279					}
280				} else {
281					$.data( this, fullName, new object( options, this ) );
282				}
283			} );
284		}
285
286		return returnValue;
287	};
288};
289
290$.Widget = function( /* options, element */ ) {};
291$.Widget._childConstructors = [];
292
293$.Widget.prototype = {
294	widgetName: "widget",
295	widgetEventPrefix: "",
296	defaultElement: "<div>",
297
298	options: {
299		classes: {},
300		disabled: false,
301
302		// Callbacks
303		create: null
304	},
305
306	_createWidget: function( options, element ) {
307		element = $( element || this.defaultElement || this )[ 0 ];
308		this.element = $( element );
309		this.uuid = widgetUuid++;
310		this.eventNamespace = "." + this.widgetName + this.uuid;
311
312		this.bindings = $();
313		this.hoverable = $();
314		this.focusable = $();
315		this.classesElementLookup = {};
316
317		if ( element !== this ) {
318			$.data( element, this.widgetFullName, this );
319			this._on( true, this.element, {
320				remove: function( event ) {
321					if ( event.target === element ) {
322						this.destroy();
323					}
324				}
325			} );
326			this.document = $( element.style ?
327
328				// Element within the document
329				element.ownerDocument :
330
331				// Element is window or document
332				element.document || element );
333			this.window = $( this.document[ 0 ].defaultView || this.document[ 0 ].parentWindow );
334		}
335
336		this.options = $.widget.extend( {},
337			this.options,
338			this._getCreateOptions(),
339			options );
340
341		this._create();
342
343		if ( this.options.disabled ) {
344			this._setOptionDisabled( this.options.disabled );
345		}
346
347		this._trigger( "create", null, this._getCreateEventData() );
348		this._init();
349	},
350
351	_getCreateOptions: function() {
352		return {};
353	},
354
355	_getCreateEventData: $.noop,
356
357	_create: $.noop,
358
359	_init: $.noop,
360
361	destroy: function() {
362		var that = this;
363
364		this._destroy();
365		$.each( this.classesElementLookup, function( key, value ) {
366			that._removeClass( value, key );
367		} );
368
369		// We can probably remove the unbind calls in 2.0
370		// all event bindings should go through this._on()
371		this.element
372			.off( this.eventNamespace )
373			.removeData( this.widgetFullName );
374		this.widget()
375			.off( this.eventNamespace )
376			.removeAttr( "aria-disabled" );
377
378		// Clean up events and states
379		this.bindings.off( this.eventNamespace );
380	},
381
382	_destroy: $.noop,
383
384	widget: function() {
385		return this.element;
386	},
387
388	option: function( key, value ) {
389		var options = key;
390		var parts;
391		var curOption;
392		var i;
393
394		if ( arguments.length === 0 ) {
395
396			// Don't return a reference to the internal hash
397			return $.widget.extend( {}, this.options );
398		}
399
400		if ( typeof key === "string" ) {
401
402			// Handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
403			options = {};
404			parts = key.split( "." );
405			key = parts.shift();
406			if ( parts.length ) {
407				curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
408				for ( i = 0; i < parts.length - 1; i++ ) {
409					curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
410					curOption = curOption[ parts[ i ] ];
411				}
412				key = parts.pop();
413				if ( arguments.length === 1 ) {
414					return curOption[ key ] === undefined ? null : curOption[ key ];
415				}
416				curOption[ key ] = value;
417			} else {
418				if ( arguments.length === 1 ) {
419					return this.options[ key ] === undefined ? null : this.options[ key ];
420				}
421				options[ key ] = value;
422			}
423		}
424
425		this._setOptions( options );
426
427		return this;
428	},
429
430	_setOptions: function( options ) {
431		var key;
432
433		for ( key in options ) {
434			this._setOption( key, options[ key ] );
435		}
436
437		return this;
438	},
439
440	_setOption: function( key, value ) {
441		if ( key === "classes" ) {
442			this._setOptionClasses( value );
443		}
444
445		this.options[ key ] = value;
446
447		if ( key === "disabled" ) {
448			this._setOptionDisabled( value );
449		}
450
451		return this;
452	},
453
454	_setOptionClasses: function( value ) {
455		var classKey, elements, currentElements;
456
457		for ( classKey in value ) {
458			currentElements = this.classesElementLookup[ classKey ];
459			if ( value[ classKey ] === this.options.classes[ classKey ] ||
460					!currentElements ||
461					!currentElements.length ) {
462				continue;
463			}
464
465			// We are doing this to create a new jQuery object because the _removeClass() call
466			// on the next line is going to destroy the reference to the current elements being
467			// tracked. We need to save a copy of this collection so that we can add the new classes
468			// below.
469			elements = $( currentElements.get() );
470			this._removeClass( currentElements, classKey );
471
472			// We don't use _addClass() here, because that uses this.options.classes
473			// for generating the string of classes. We want to use the value passed in from
474			// _setOption(), this is the new value of the classes option which was passed to
475			// _setOption(). We pass this value directly to _classes().
476			elements.addClass( this._classes( {
477				element: elements,
478				keys: classKey,
479				classes: value,
480				add: true
481			} ) );
482		}
483	},
484
485	_setOptionDisabled: function( value ) {
486		this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, !!value );
487
488		// If the widget is becoming disabled, then nothing is interactive
489		if ( value ) {
490			this._removeClass( this.hoverable, null, "ui-state-hover" );
491			this._removeClass( this.focusable, null, "ui-state-focus" );
492		}
493	},
494
495	enable: function() {
496		return this._setOptions( { disabled: false } );
497	},
498
499	disable: function() {
500		return this._setOptions( { disabled: true } );
501	},
502
503	_classes: function( options ) {
504		var full = [];
505		var that = this;
506
507		options = $.extend( {
508			element: this.element,
509			classes: this.options.classes || {}
510		}, options );
511
512		function bindRemoveEvent() {
513			var nodesToBind = [];
514
515			options.element.each( function( _, element ) {
516				var isTracked = $.map( that.classesElementLookup, function( elements ) {
517					return elements;
518				} )
519					.some( function( elements ) {
520						return elements.is( element );
521					} );
522
523				if ( !isTracked ) {
524					nodesToBind.push( element );
525				}
526			} );
527
528			that._on( $( nodesToBind ), {
529				remove: "_untrackClassesElement"
530			} );
531		}
532
533		function processClassString( classes, checkOption ) {
534			var current, i;
535			for ( i = 0; i < classes.length; i++ ) {
536				current = that.classesElementLookup[ classes[ i ] ] || $();
537				if ( options.add ) {
538					bindRemoveEvent();
539					current = $( $.uniqueSort( current.get().concat( options.element.get() ) ) );
540				} else {
541					current = $( current.not( options.element ).get() );
542				}
543				that.classesElementLookup[ classes[ i ] ] = current;
544				full.push( classes[ i ] );
545				if ( checkOption && options.classes[ classes[ i ] ] ) {
546					full.push( options.classes[ classes[ i ] ] );
547				}
548			}
549		}
550
551		if ( options.keys ) {
552			processClassString( options.keys.match( /\S+/g ) || [], true );
553		}
554		if ( options.extra ) {
555			processClassString( options.extra.match( /\S+/g ) || [] );
556		}
557
558		return full.join( " " );
559	},
560
561	_untrackClassesElement: function( event ) {
562		var that = this;
563		$.each( that.classesElementLookup, function( key, value ) {
564			if ( $.inArray( event.target, value ) !== -1 ) {
565				that.classesElementLookup[ key ] = $( value.not( event.target ).get() );
566			}
567		} );
568
569		this._off( $( event.target ) );
570	},
571
572	_removeClass: function( element, keys, extra ) {
573		return this._toggleClass( element, keys, extra, false );
574	},
575
576	_addClass: function( element, keys, extra ) {
577		return this._toggleClass( element, keys, extra, true );
578	},
579
580	_toggleClass: function( element, keys, extra, add ) {
581		add = ( typeof add === "boolean" ) ? add : extra;
582		var shift = ( typeof element === "string" || element === null ),
583			options = {
584				extra: shift ? keys : extra,
585				keys: shift ? element : keys,
586				element: shift ? this.element : element,
587				add: add
588			};
589		options.element.toggleClass( this._classes( options ), add );
590		return this;
591	},
592
593	_on: function( suppressDisabledCheck, element, handlers ) {
594		var delegateElement;
595		var instance = this;
596
597		// No suppressDisabledCheck flag, shuffle arguments
598		if ( typeof suppressDisabledCheck !== "boolean" ) {
599			handlers = element;
600			element = suppressDisabledCheck;
601			suppressDisabledCheck = false;
602		}
603
604		// No element argument, shuffle and use this.element
605		if ( !handlers ) {
606			handlers = element;
607			element = this.element;
608			delegateElement = this.widget();
609		} else {
610			element = delegateElement = $( element );
611			this.bindings = this.bindings.add( element );
612		}
613
614		$.each( handlers, function( event, handler ) {
615			function handlerProxy() {
616
617				// Allow widgets to customize the disabled handling
618				// - disabled as an array instead of boolean
619				// - disabled class as method for disabling individual parts
620				if ( !suppressDisabledCheck &&
621						( instance.options.disabled === true ||
622						$( this ).hasClass( "ui-state-disabled" ) ) ) {
623					return;
624				}
625				return ( typeof handler === "string" ? instance[ handler ] : handler )
626					.apply( instance, arguments );
627			}
628
629			// Copy the guid so direct unbinding works
630			if ( typeof handler !== "string" ) {
631				handlerProxy.guid = handler.guid =
632					handler.guid || handlerProxy.guid || $.guid++;
633			}
634
635			var match = event.match( /^([\w:-]*)\s*(.*)$/ );
636			var eventName = match[ 1 ] + instance.eventNamespace;
637			var selector = match[ 2 ];
638
639			if ( selector ) {
640				delegateElement.on( eventName, selector, handlerProxy );
641			} else {
642				element.on( eventName, handlerProxy );
643			}
644		} );
645	},
646
647	_off: function( element, eventName ) {
648		eventName = ( eventName || "" ).split( " " ).join( this.eventNamespace + " " ) +
649			this.eventNamespace;
650		element.off( eventName );
651
652		// Clear the stack to avoid memory leaks (#10056)
653		this.bindings = $( this.bindings.not( element ).get() );
654		this.focusable = $( this.focusable.not( element ).get() );
655		this.hoverable = $( this.hoverable.not( element ).get() );
656	},
657
658	_delay: function( handler, delay ) {
659		function handlerProxy() {
660			return ( typeof handler === "string" ? instance[ handler ] : handler )
661				.apply( instance, arguments );
662		}
663		var instance = this;
664		return setTimeout( handlerProxy, delay || 0 );
665	},
666
667	_hoverable: function( element ) {
668		this.hoverable = this.hoverable.add( element );
669		this._on( element, {
670			mouseenter: function( event ) {
671				this._addClass( $( event.currentTarget ), null, "ui-state-hover" );
672			},
673			mouseleave: function( event ) {
674				this._removeClass( $( event.currentTarget ), null, "ui-state-hover" );
675			}
676		} );
677	},
678
679	_focusable: function( element ) {
680		this.focusable = this.focusable.add( element );
681		this._on( element, {
682			focusin: function( event ) {
683				this._addClass( $( event.currentTarget ), null, "ui-state-focus" );
684			},
685			focusout: function( event ) {
686				this._removeClass( $( event.currentTarget ), null, "ui-state-focus" );
687			}
688		} );
689	},
690
691	_trigger: function( type, event, data ) {
692		var prop, orig;
693		var callback = this.options[ type ];
694
695		data = data || {};
696		event = $.Event( event );
697		event.type = ( type === this.widgetEventPrefix ?
698			type :
699			this.widgetEventPrefix + type ).toLowerCase();
700
701		// The original event may come from any element
702		// so we need to reset the target on the new event
703		event.target = this.element[ 0 ];
704
705		// Copy original event properties over to the new event
706		orig = event.originalEvent;
707		if ( orig ) {
708			for ( prop in orig ) {
709				if ( !( prop in event ) ) {
710					event[ prop ] = orig[ prop ];
711				}
712			}
713		}
714
715		this.element.trigger( event, data );
716		return !( typeof callback === "function" &&
717			callback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false ||
718			event.isDefaultPrevented() );
719	}
720};
721
722$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
723	$.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
724		if ( typeof options === "string" ) {
725			options = { effect: options };
726		}
727
728		var hasOptions;
729		var effectName = !options ?
730			method :
731			options === true || typeof options === "number" ?
732				defaultEffect :
733				options.effect || defaultEffect;
734
735		options = options || {};
736		if ( typeof options === "number" ) {
737			options = { duration: options };
738		} else if ( options === true ) {
739			options = {};
740		}
741
742		hasOptions = !$.isEmptyObject( options );
743		options.complete = callback;
744
745		if ( options.delay ) {
746			element.delay( options.delay );
747		}
748
749		if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
750			element[ method ]( options );
751		} else if ( effectName !== method && element[ effectName ] ) {
752			element[ effectName ]( options.duration, options.easing, callback );
753		} else {
754			element.queue( function( next ) {
755				$( this )[ method ]();
756				if ( callback ) {
757					callback.call( element[ 0 ] );
758				}
759				next();
760			} );
761		}
762	};
763} );
764
765var widget = $.widget;
766
767
768/*!
769 * jQuery UI Position 1.13.3
770 * https://jqueryui.com
771 *
772 * Copyright OpenJS Foundation and other contributors
773 * Released under the MIT license.
774 * https://jquery.org/license
775 *
776 * https://api.jqueryui.com/position/
777 */
778
779//>>label: Position
780//>>group: Core
781//>>description: Positions elements relative to other elements.
782//>>docs: https://api.jqueryui.com/position/
783//>>demos: https://jqueryui.com/position/
784
785
786( function() {
787var cachedScrollbarWidth,
788	max = Math.max,
789	abs = Math.abs,
790	rhorizontal = /left|center|right/,
791	rvertical = /top|center|bottom/,
792	roffset = /[\+\-]\d+(\.[\d]+)?%?/,
793	rposition = /^\w+/,
794	rpercent = /%$/,
795	_position = $.fn.position;
796
797function getOffsets( offsets, width, height ) {
798	return [
799		parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
800		parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
801	];
802}
803
804function parseCss( element, property ) {
805	return parseInt( $.css( element, property ), 10 ) || 0;
806}
807
808function isWindow( obj ) {
809	return obj != null && obj === obj.window;
810}
811
812function getDimensions( elem ) {
813	var raw = elem[ 0 ];
814	if ( raw.nodeType === 9 ) {
815		return {
816			width: elem.width(),
817			height: elem.height(),
818			offset: { top: 0, left: 0 }
819		};
820	}
821	if ( isWindow( raw ) ) {
822		return {
823			width: elem.width(),
824			height: elem.height(),
825			offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
826		};
827	}
828	if ( raw.preventDefault ) {
829		return {
830			width: 0,
831			height: 0,
832			offset: { top: raw.pageY, left: raw.pageX }
833		};
834	}
835	return {
836		width: elem.outerWidth(),
837		height: elem.outerHeight(),
838		offset: elem.offset()
839	};
840}
841
842$.position = {
843	scrollbarWidth: function() {
844		if ( cachedScrollbarWidth !== undefined ) {
845			return cachedScrollbarWidth;
846		}
847		var w1, w2,
848			div = $( "<div style=" +
849				"'display:block;position:absolute;width:200px;height:200px;overflow:hidden;'>" +
850				"<div style='height:300px;width:auto;'></div></div>" ),
851			innerDiv = div.children()[ 0 ];
852
853		$( "body" ).append( div );
854		w1 = innerDiv.offsetWidth;
855		div.css( "overflow", "scroll" );
856
857		w2 = innerDiv.offsetWidth;
858
859		if ( w1 === w2 ) {
860			w2 = div[ 0 ].clientWidth;
861		}
862
863		div.remove();
864
865		return ( cachedScrollbarWidth = w1 - w2 );
866	},
867	getScrollInfo: function( within ) {
868		var overflowX = within.isWindow || within.isDocument ? "" :
869				within.element.css( "overflow-x" ),
870			overflowY = within.isWindow || within.isDocument ? "" :
871				within.element.css( "overflow-y" ),
872			hasOverflowX = overflowX === "scroll" ||
873				( overflowX === "auto" && within.width < within.element[ 0 ].scrollWidth ),
874			hasOverflowY = overflowY === "scroll" ||
875				( overflowY === "auto" && within.height < within.element[ 0 ].scrollHeight );
876		return {
877			width: hasOverflowY ? $.position.scrollbarWidth() : 0,
878			height: hasOverflowX ? $.position.scrollbarWidth() : 0
879		};
880	},
881	getWithinInfo: function( element ) {
882		var withinElement = $( element || window ),
883			isElemWindow = isWindow( withinElement[ 0 ] ),
884			isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9,
885			hasOffset = !isElemWindow && !isDocument;
886		return {
887			element: withinElement,
888			isWindow: isElemWindow,
889			isDocument: isDocument,
890			offset: hasOffset ? $( element ).offset() : { left: 0, top: 0 },
891			scrollLeft: withinElement.scrollLeft(),
892			scrollTop: withinElement.scrollTop(),
893			width: withinElement.outerWidth(),
894			height: withinElement.outerHeight()
895		};
896	}
897};
898
899$.fn.position = function( options ) {
900	if ( !options || !options.of ) {
901		return _position.apply( this, arguments );
902	}
903
904	// Make a copy, we don't want to modify arguments
905	options = $.extend( {}, options );
906
907	var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
908
909		// Make sure string options are treated as CSS selectors
910		target = typeof options.of === "string" ?
911			$( document ).find( options.of ) :
912			$( options.of ),
913
914		within = $.position.getWithinInfo( options.within ),
915		scrollInfo = $.position.getScrollInfo( within ),
916		collision = ( options.collision || "flip" ).split( " " ),
917		offsets = {};
918
919	dimensions = getDimensions( target );
920	if ( target[ 0 ].preventDefault ) {
921
922		// Force left top to allow flipping
923		options.at = "left top";
924	}
925	targetWidth = dimensions.width;
926	targetHeight = dimensions.height;
927	targetOffset = dimensions.offset;
928
929	// Clone to reuse original targetOffset later
930	basePosition = $.extend( {}, targetOffset );
931
932	// Force my and at to have valid horizontal and vertical positions
933	// if a value is missing or invalid, it will be converted to center
934	$.each( [ "my", "at" ], function() {
935		var pos = ( options[ this ] || "" ).split( " " ),
936			horizontalOffset,
937			verticalOffset;
938
939		if ( pos.length === 1 ) {
940			pos = rhorizontal.test( pos[ 0 ] ) ?
941				pos.concat( [ "center" ] ) :
942				rvertical.test( pos[ 0 ] ) ?
943					[ "center" ].concat( pos ) :
944					[ "center", "center" ];
945		}
946		pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
947		pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
948
949		// Calculate offsets
950		horizontalOffset = roffset.exec( pos[ 0 ] );
951		verticalOffset = roffset.exec( pos[ 1 ] );
952		offsets[ this ] = [
953			horizontalOffset ? horizontalOffset[ 0 ] : 0,
954			verticalOffset ? verticalOffset[ 0 ] : 0
955		];
956
957		// Reduce to just the positions without the offsets
958		options[ this ] = [
959			rposition.exec( pos[ 0 ] )[ 0 ],
960			rposition.exec( pos[ 1 ] )[ 0 ]
961		];
962	} );
963
964	// Normalize collision option
965	if ( collision.length === 1 ) {
966		collision[ 1 ] = collision[ 0 ];
967	}
968
969	if ( options.at[ 0 ] === "right" ) {
970		basePosition.left += targetWidth;
971	} else if ( options.at[ 0 ] === "center" ) {
972		basePosition.left += targetWidth / 2;
973	}
974
975	if ( options.at[ 1 ] === "bottom" ) {
976		basePosition.top += targetHeight;
977	} else if ( options.at[ 1 ] === "center" ) {
978		basePosition.top += targetHeight / 2;
979	}
980
981	atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
982	basePosition.left += atOffset[ 0 ];
983	basePosition.top += atOffset[ 1 ];
984
985	return this.each( function() {
986		var collisionPosition, using,
987			elem = $( this ),
988			elemWidth = elem.outerWidth(),
989			elemHeight = elem.outerHeight(),
990			marginLeft = parseCss( this, "marginLeft" ),
991			marginTop = parseCss( this, "marginTop" ),
992			collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) +
993				scrollInfo.width,
994			collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) +
995				scrollInfo.height,
996			position = $.extend( {}, basePosition ),
997			myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
998
999		if ( options.my[ 0 ] === "right" ) {
1000			position.left -= elemWidth;
1001		} else if ( options.my[ 0 ] === "center" ) {
1002			position.left -= elemWidth / 2;
1003		}
1004
1005		if ( options.my[ 1 ] === "bottom" ) {
1006			position.top -= elemHeight;
1007		} else if ( options.my[ 1 ] === "center" ) {
1008			position.top -= elemHeight / 2;
1009		}
1010
1011		position.left += myOffset[ 0 ];
1012		position.top += myOffset[ 1 ];
1013
1014		collisionPosition = {
1015			marginLeft: marginLeft,
1016			marginTop: marginTop
1017		};
1018
1019		$.each( [ "left", "top" ], function( i, dir ) {
1020			if ( $.ui.position[ collision[ i ] ] ) {
1021				$.ui.position[ collision[ i ] ][ dir ]( position, {
1022					targetWidth: targetWidth,
1023					targetHeight: targetHeight,
1024					elemWidth: elemWidth,
1025					elemHeight: elemHeight,
1026					collisionPosition: collisionPosition,
1027					collisionWidth: collisionWidth,
1028					collisionHeight: collisionHeight,
1029					offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
1030					my: options.my,
1031					at: options.at,
1032					within: within,
1033					elem: elem
1034				} );
1035			}
1036		} );
1037
1038		if ( options.using ) {
1039
1040			// Adds feedback as second argument to using callback, if present
1041			using = function( props ) {
1042				var left = targetOffset.left - position.left,
1043					right = left + targetWidth - elemWidth,
1044					top = targetOffset.top - position.top,
1045					bottom = top + targetHeight - elemHeight,
1046					feedback = {
1047						target: {
1048							element: target,
1049							left: targetOffset.left,
1050							top: targetOffset.top,
1051							width: targetWidth,
1052							height: targetHeight
1053						},
1054						element: {
1055							element: elem,
1056							left: position.left,
1057							top: position.top,
1058							width: elemWidth,
1059							height: elemHeight
1060						},
1061						horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
1062						vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
1063					};
1064				if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
1065					feedback.horizontal = "center";
1066				}
1067				if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
1068					feedback.vertical = "middle";
1069				}
1070				if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
1071					feedback.important = "horizontal";
1072				} else {
1073					feedback.important = "vertical";
1074				}
1075				options.using.call( this, props, feedback );
1076			};
1077		}
1078
1079		elem.offset( $.extend( position, { using: using } ) );
1080	} );
1081};
1082
1083$.ui.position = {
1084	fit: {
1085		left: function( position, data ) {
1086			var within = data.within,
1087				withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
1088				outerWidth = within.width,
1089				collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1090				overLeft = withinOffset - collisionPosLeft,
1091				overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
1092				newOverRight;
1093
1094			// Element is wider than within
1095			if ( data.collisionWidth > outerWidth ) {
1096
1097				// Element is initially over the left side of within
1098				if ( overLeft > 0 && overRight <= 0 ) {
1099					newOverRight = position.left + overLeft + data.collisionWidth - outerWidth -
1100						withinOffset;
1101					position.left += overLeft - newOverRight;
1102
1103				// Element is initially over right side of within
1104				} else if ( overRight > 0 && overLeft <= 0 ) {
1105					position.left = withinOffset;
1106
1107				// Element is initially over both left and right sides of within
1108				} else {
1109					if ( overLeft > overRight ) {
1110						position.left = withinOffset + outerWidth - data.collisionWidth;
1111					} else {
1112						position.left = withinOffset;
1113					}
1114				}
1115
1116			// Too far left -> align with left edge
1117			} else if ( overLeft > 0 ) {
1118				position.left += overLeft;
1119
1120			// Too far right -> align with right edge
1121			} else if ( overRight > 0 ) {
1122				position.left -= overRight;
1123
1124			// Adjust based on position and margin
1125			} else {
1126				position.left = max( position.left - collisionPosLeft, position.left );
1127			}
1128		},
1129		top: function( position, data ) {
1130			var within = data.within,
1131				withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
1132				outerHeight = data.within.height,
1133				collisionPosTop = position.top - data.collisionPosition.marginTop,
1134				overTop = withinOffset - collisionPosTop,
1135				overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
1136				newOverBottom;
1137
1138			// Element is taller than within
1139			if ( data.collisionHeight > outerHeight ) {
1140
1141				// Element is initially over the top of within
1142				if ( overTop > 0 && overBottom <= 0 ) {
1143					newOverBottom = position.top + overTop + data.collisionHeight - outerHeight -
1144						withinOffset;
1145					position.top += overTop - newOverBottom;
1146
1147				// Element is initially over bottom of within
1148				} else if ( overBottom > 0 && overTop <= 0 ) {
1149					position.top = withinOffset;
1150
1151				// Element is initially over both top and bottom of within
1152				} else {
1153					if ( overTop > overBottom ) {
1154						position.top = withinOffset + outerHeight - data.collisionHeight;
1155					} else {
1156						position.top = withinOffset;
1157					}
1158				}
1159
1160			// Too far up -> align with top
1161			} else if ( overTop > 0 ) {
1162				position.top += overTop;
1163
1164			// Too far down -> align with bottom edge
1165			} else if ( overBottom > 0 ) {
1166				position.top -= overBottom;
1167
1168			// Adjust based on position and margin
1169			} else {
1170				position.top = max( position.top - collisionPosTop, position.top );
1171			}
1172		}
1173	},
1174	flip: {
1175		left: function( position, data ) {
1176			var within = data.within,
1177				withinOffset = within.offset.left + within.scrollLeft,
1178				outerWidth = within.width,
1179				offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
1180				collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1181				overLeft = collisionPosLeft - offsetLeft,
1182				overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
1183				myOffset = data.my[ 0 ] === "left" ?
1184					-data.elemWidth :
1185					data.my[ 0 ] === "right" ?
1186						data.elemWidth :
1187						0,
1188				atOffset = data.at[ 0 ] === "left" ?
1189					data.targetWidth :
1190					data.at[ 0 ] === "right" ?
1191						-data.targetWidth :
1192						0,
1193				offset = -2 * data.offset[ 0 ],
1194				newOverRight,
1195				newOverLeft;
1196
1197			if ( overLeft < 0 ) {
1198				newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth -
1199					outerWidth - withinOffset;
1200				if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
1201					position.left += myOffset + atOffset + offset;
1202				}
1203			} else if ( overRight > 0 ) {
1204				newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset +
1205					atOffset + offset - offsetLeft;
1206				if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
1207					position.left += myOffset + atOffset + offset;
1208				}
1209			}
1210		},
1211		top: function( position, data ) {
1212			var within = data.within,
1213				withinOffset = within.offset.top + within.scrollTop,
1214				outerHeight = within.height,
1215				offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
1216				collisionPosTop = position.top - data.collisionPosition.marginTop,
1217				overTop = collisionPosTop - offsetTop,
1218				overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
1219				top = data.my[ 1 ] === "top",
1220				myOffset = top ?
1221					-data.elemHeight :
1222					data.my[ 1 ] === "bottom" ?
1223						data.elemHeight :
1224						0,
1225				atOffset = data.at[ 1 ] === "top" ?
1226					data.targetHeight :
1227					data.at[ 1 ] === "bottom" ?
1228						-data.targetHeight :
1229						0,
1230				offset = -2 * data.offset[ 1 ],
1231				newOverTop,
1232				newOverBottom;
1233			if ( overTop < 0 ) {
1234				newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight -
1235					outerHeight - withinOffset;
1236				if ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) {
1237					position.top += myOffset + atOffset + offset;
1238				}
1239			} else if ( overBottom > 0 ) {
1240				newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset +
1241					offset - offsetTop;
1242				if ( newOverTop > 0 || abs( newOverTop ) < overBottom ) {
1243					position.top += myOffset + atOffset + offset;
1244				}
1245			}
1246		}
1247	},
1248	flipfit: {
1249		left: function() {
1250			$.ui.position.flip.left.apply( this, arguments );
1251			$.ui.position.fit.left.apply( this, arguments );
1252		},
1253		top: function() {
1254			$.ui.position.flip.top.apply( this, arguments );
1255			$.ui.position.fit.top.apply( this, arguments );
1256		}
1257	}
1258};
1259
1260} )();
1261
1262var position = $.ui.position;
1263
1264
1265/*!
1266 * jQuery UI :data 1.13.3
1267 * https://jqueryui.com
1268 *
1269 * Copyright OpenJS Foundation and other contributors
1270 * Released under the MIT license.
1271 * https://jquery.org/license
1272 */
1273
1274//>>label: :data Selector
1275//>>group: Core
1276//>>description: Selects elements which have data stored under the specified key.
1277//>>docs: https://api.jqueryui.com/data-selector/
1278
1279
1280var data = $.extend( $.expr.pseudos, {
1281	data: $.expr.createPseudo ?
1282		$.expr.createPseudo( function( dataName ) {
1283			return function( elem ) {
1284				return !!$.data( elem, dataName );
1285			};
1286		} ) :
1287
1288		// Support: jQuery <1.8
1289		function( elem, i, match ) {
1290			return !!$.data( elem, match[ 3 ] );
1291		}
1292} );
1293
1294/*!
1295 * jQuery UI Disable Selection 1.13.3
1296 * https://jqueryui.com
1297 *
1298 * Copyright OpenJS Foundation and other contributors
1299 * Released under the MIT license.
1300 * https://jquery.org/license
1301 */
1302
1303//>>label: disableSelection
1304//>>group: Core
1305//>>description: Disable selection of text content within the set of matched elements.
1306//>>docs: https://api.jqueryui.com/disableSelection/
1307
1308// This file is deprecated
1309
1310var disableSelection = $.fn.extend( {
1311	disableSelection: ( function() {
1312		var eventType = "onselectstart" in document.createElement( "div" ) ?
1313			"selectstart" :
1314			"mousedown";
1315
1316		return function() {
1317			return this.on( eventType + ".ui-disableSelection", function( event ) {
1318				event.preventDefault();
1319			} );
1320		};
1321	} )(),
1322
1323	enableSelection: function() {
1324		return this.off( ".ui-disableSelection" );
1325	}
1326} );
1327
1328
1329
1330// Create a local jQuery because jQuery Color relies on it and the
1331// global may not exist with AMD and a custom build (#10199).
1332// This module is a noop if used as a regular AMD module.
1333// eslint-disable-next-line no-unused-vars
1334var jQuery = $;
1335
1336
1337/*!
1338 * jQuery Color Animations v2.2.0
1339 * https://github.com/jquery/jquery-color
1340 *
1341 * Copyright OpenJS Foundation and other contributors
1342 * Released under the MIT license.
1343 * https://jquery.org/license
1344 *
1345 * Date: Sun May 10 09:02:36 2020 +0200
1346 */
1347
1348
1349
1350	var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor " +
1351		"borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",
1352
1353	class2type = {},
1354	toString = class2type.toString,
1355
1356	// plusequals test for += 100 -= 100
1357	rplusequals = /^([\-+])=\s*(\d+\.?\d*)/,
1358
1359	// a set of RE's that can match strings and generate color tuples.
1360	stringParsers = [ {
1361			re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
1362			parse: function( execResult ) {
1363				return [
1364					execResult[ 1 ],
1365					execResult[ 2 ],
1366					execResult[ 3 ],
1367					execResult[ 4 ]
1368				];
1369			}
1370		}, {
1371			re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
1372			parse: function( execResult ) {
1373				return [
1374					execResult[ 1 ] * 2.55,
1375					execResult[ 2 ] * 2.55,
1376					execResult[ 3 ] * 2.55,
1377					execResult[ 4 ]
1378				];
1379			}
1380		}, {
1381
1382			// this regex ignores A-F because it's compared against an already lowercased string
1383			re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})?/,
1384			parse: function( execResult ) {
1385				return [
1386					parseInt( execResult[ 1 ], 16 ),
1387					parseInt( execResult[ 2 ], 16 ),
1388					parseInt( execResult[ 3 ], 16 ),
1389					execResult[ 4 ] ?
1390						( parseInt( execResult[ 4 ], 16 ) / 255 ).toFixed( 2 ) :
1391						1
1392				];
1393			}
1394		}, {
1395
1396			// this regex ignores A-F because it's compared against an already lowercased string
1397			re: /#([a-f0-9])([a-f0-9])([a-f0-9])([a-f0-9])?/,
1398			parse: function( execResult ) {
1399				return [
1400					parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),
1401					parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),
1402					parseInt( execResult[ 3 ] + execResult[ 3 ], 16 ),
1403					execResult[ 4 ] ?
1404						( parseInt( execResult[ 4 ] + execResult[ 4 ], 16 ) / 255 )
1405							.toFixed( 2 ) :
1406						1
1407				];
1408			}
1409		}, {
1410			re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
1411			space: "hsla",
1412			parse: function( execResult ) {
1413				return [
1414					execResult[ 1 ],
1415					execResult[ 2 ] / 100,
1416					execResult[ 3 ] / 100,
1417					execResult[ 4 ]
1418				];
1419			}
1420		} ],
1421
1422	// jQuery.Color( )
1423	color = jQuery.Color = function( color, green, blue, alpha ) {
1424		return new jQuery.Color.fn.parse( color, green, blue, alpha );
1425	},
1426	spaces = {
1427		rgba: {
1428			props: {
1429				red: {
1430					idx: 0,
1431					type: "byte"
1432				},
1433				green: {
1434					idx: 1,
1435					type: "byte"
1436				},
1437				blue: {
1438					idx: 2,
1439					type: "byte"
1440				}
1441			}
1442		},
1443
1444		hsla: {
1445			props: {
1446				hue: {
1447					idx: 0,
1448					type: "degrees"
1449				},
1450				saturation: {
1451					idx: 1,
1452					type: "percent"
1453				},
1454				lightness: {
1455					idx: 2,
1456					type: "percent"
1457				}
1458			}
1459		}
1460	},
1461	propTypes = {
1462		"byte": {
1463			floor: true,
1464			max: 255
1465		},
1466		"percent": {
1467			max: 1
1468		},
1469		"degrees": {
1470			mod: 360,
1471			floor: true
1472		}
1473	},
1474	support = color.support = {},
1475
1476	// element for support tests
1477	supportElem = jQuery( "<p>" )[ 0 ],
1478
1479	// colors = jQuery.Color.names
1480	colors,
1481
1482	// local aliases of functions called often
1483	each = jQuery.each;
1484
1485// determine rgba support immediately
1486supportElem.style.cssText = "background-color:rgba(1,1,1,.5)";
1487support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1;
1488
1489// define cache name and alpha properties
1490// for rgba and hsla spaces
1491each( spaces, function( spaceName, space ) {
1492	space.cache = "_" + spaceName;
1493	space.props.alpha = {
1494		idx: 3,
1495		type: "percent",
1496		def: 1
1497	};
1498} );
1499
1500// Populate the class2type map
1501jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
1502	function( _i, name ) {
1503		class2type[ "[object " + name + "]" ] = name.toLowerCase();
1504	} );
1505
1506function getType( obj ) {
1507	if ( obj == null ) {
1508		return obj + "";
1509	}
1510
1511	return typeof obj === "object" ?
1512		class2type[ toString.call( obj ) ] || "object" :
1513		typeof obj;
1514}
1515
1516function clamp( value, prop, allowEmpty ) {
1517	var type = propTypes[ prop.type ] || {};
1518
1519	if ( value == null ) {
1520		return ( allowEmpty || !prop.def ) ? null : prop.def;
1521	}
1522
1523	// ~~ is an short way of doing floor for positive numbers
1524	value = type.floor ? ~~value : parseFloat( value );
1525
1526	// IE will pass in empty strings as value for alpha,
1527	// which will hit this case
1528	if ( isNaN( value ) ) {
1529		return prop.def;
1530	}
1531
1532	if ( type.mod ) {
1533
1534		// we add mod before modding to make sure that negatives values
1535		// get converted properly: -10 -> 350
1536		return ( value + type.mod ) % type.mod;
1537	}
1538
1539	// for now all property types without mod have min and max
1540	return Math.min( type.max, Math.max( 0, value ) );
1541}
1542
1543function stringParse( string ) {
1544	var inst = color(),
1545		rgba = inst._rgba = [];
1546
1547	string = string.toLowerCase();
1548
1549	each( stringParsers, function( _i, parser ) {
1550		var parsed,
1551			match = parser.re.exec( string ),
1552			values = match && parser.parse( match ),
1553			spaceName = parser.space || "rgba";
1554
1555		if ( values ) {
1556			parsed = inst[ spaceName ]( values );
1557
1558			// if this was an rgba parse the assignment might happen twice
1559			// oh well....
1560			inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ];
1561			rgba = inst._rgba = parsed._rgba;
1562
1563			// exit each( stringParsers ) here because we matched
1564			return false;
1565		}
1566	} );
1567
1568	// Found a stringParser that handled it
1569	if ( rgba.length ) {
1570
1571		// if this came from a parsed string, force "transparent" when alpha is 0
1572		// chrome, (and maybe others) return "transparent" as rgba(0,0,0,0)
1573		if ( rgba.join() === "0,0,0,0" ) {
1574			jQuery.extend( rgba, colors.transparent );
1575		}
1576		return inst;
1577	}
1578
1579	// named colors
1580	return colors[ string ];
1581}
1582
1583color.fn = jQuery.extend( color.prototype, {
1584	parse: function( red, green, blue, alpha ) {
1585		if ( red === undefined ) {
1586			this._rgba = [ null, null, null, null ];
1587			return this;
1588		}
1589		if ( red.jquery || red.nodeType ) {
1590			red = jQuery( red ).css( green );
1591			green = undefined;
1592		}
1593
1594		var inst = this,
1595			type = getType( red ),
1596			rgba = this._rgba = [];
1597
1598		// more than 1 argument specified - assume ( red, green, blue, alpha )
1599		if ( green !== undefined ) {
1600			red = [ red, green, blue, alpha ];
1601			type = "array";
1602		}
1603
1604		if ( type === "string" ) {
1605			return this.parse( stringParse( red ) || colors._default );
1606		}
1607
1608		if ( type === "array" ) {
1609			each( spaces.rgba.props, function( _key, prop ) {
1610				rgba[ prop.idx ] = clamp( red[ prop.idx ], prop );
1611			} );
1612			return this;
1613		}
1614
1615		if ( type === "object" ) {
1616			if ( red instanceof color ) {
1617				each( spaces, function( _spaceName, space ) {
1618					if ( red[ space.cache ] ) {
1619						inst[ space.cache ] = red[ space.cache ].slice();
1620					}
1621				} );
1622			} else {
1623				each( spaces, function( _spaceName, space ) {
1624					var cache = space.cache;
1625					each( space.props, function( key, prop ) {
1626
1627						// if the cache doesn't exist, and we know how to convert
1628						if ( !inst[ cache ] && space.to ) {
1629
1630							// if the value was null, we don't need to copy it
1631							// if the key was alpha, we don't need to copy it either
1632							if ( key === "alpha" || red[ key ] == null ) {
1633								return;
1634							}
1635							inst[ cache ] = space.to( inst._rgba );
1636						}
1637
1638						// this is the only case where we allow nulls for ALL properties.
1639						// call clamp with alwaysAllowEmpty
1640						inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true );
1641					} );
1642
1643					// everything defined but alpha?
1644					if ( inst[ cache ] && jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) {
1645
1646						// use the default of 1
1647						if ( inst[ cache ][ 3 ] == null ) {
1648							inst[ cache ][ 3 ] = 1;
1649						}
1650
1651						if ( space.from ) {
1652							inst._rgba = space.from( inst[ cache ] );
1653						}
1654					}
1655				} );
1656			}
1657			return this;
1658		}
1659	},
1660	is: function( compare ) {
1661		var is = color( compare ),
1662			same = true,
1663			inst = this;
1664
1665		each( spaces, function( _, space ) {
1666			var localCache,
1667				isCache = is[ space.cache ];
1668			if ( isCache ) {
1669				localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || [];
1670				each( space.props, function( _, prop ) {
1671					if ( isCache[ prop.idx ] != null ) {
1672						same = ( isCache[ prop.idx ] === localCache[ prop.idx ] );
1673						return same;
1674					}
1675				} );
1676			}
1677			return same;
1678		} );
1679		return same;
1680	},
1681	_space: function() {
1682		var used = [],
1683			inst = this;
1684		each( spaces, function( spaceName, space ) {
1685			if ( inst[ space.cache ] ) {
1686				used.push( spaceName );
1687			}
1688		} );
1689		return used.pop();
1690	},
1691	transition: function( other, distance ) {
1692		var end = color( other ),
1693			spaceName = end._space(),
1694			space = spaces[ spaceName ],
1695			startColor = this.alpha() === 0 ? color( "transparent" ) : this,
1696			start = startColor[ space.cache ] || space.to( startColor._rgba ),
1697			result = start.slice();
1698
1699		end = end[ space.cache ];
1700		each( space.props, function( _key, prop ) {
1701			var index = prop.idx,
1702				startValue = start[ index ],
1703				endValue = end[ index ],
1704				type = propTypes[ prop.type ] || {};
1705
1706			// if null, don't override start value
1707			if ( endValue === null ) {
1708				return;
1709			}
1710
1711			// if null - use end
1712			if ( startValue === null ) {
1713				result[ index ] = endValue;
1714			} else {
1715				if ( type.mod ) {
1716					if ( endValue - startValue > type.mod / 2 ) {
1717						startValue += type.mod;
1718					} else if ( startValue - endValue > type.mod / 2 ) {
1719						startValue -= type.mod;
1720					}
1721				}
1722				result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop );
1723			}
1724		} );
1725		return this[ spaceName ]( result );
1726	},
1727	blend: function( opaque ) {
1728
1729		// if we are already opaque - return ourself
1730		if ( this._rgba[ 3 ] === 1 ) {
1731			return this;
1732		}
1733
1734		var rgb = this._rgba.slice(),
1735			a = rgb.pop(),
1736			blend = color( opaque )._rgba;
1737
1738		return color( jQuery.map( rgb, function( v, i ) {
1739			return ( 1 - a ) * blend[ i ] + a * v;
1740		} ) );
1741	},
1742	toRgbaString: function() {
1743		var prefix = "rgba(",
1744			rgba = jQuery.map( this._rgba, function( v, i ) {
1745				if ( v != null ) {
1746					return v;
1747				}
1748				return i > 2 ? 1 : 0;
1749			} );
1750
1751		if ( rgba[ 3 ] === 1 ) {
1752			rgba.pop();
1753			prefix = "rgb(";
1754		}
1755
1756		return prefix + rgba.join() + ")";
1757	},
1758	toHslaString: function() {
1759		var prefix = "hsla(",
1760			hsla = jQuery.map( this.hsla(), function( v, i ) {
1761				if ( v == null ) {
1762					v = i > 2 ? 1 : 0;
1763				}
1764
1765				// catch 1 and 2
1766				if ( i && i < 3 ) {
1767					v = Math.round( v * 100 ) + "%";
1768				}
1769				return v;
1770			} );
1771
1772		if ( hsla[ 3 ] === 1 ) {
1773			hsla.pop();
1774			prefix = "hsl(";
1775		}
1776		return prefix + hsla.join() + ")";
1777	},
1778	toHexString: function( includeAlpha ) {
1779		var rgba = this._rgba.slice(),
1780			alpha = rgba.pop();
1781
1782		if ( includeAlpha ) {
1783			rgba.push( ~~( alpha * 255 ) );
1784		}
1785
1786		return "#" + jQuery.map( rgba, function( v ) {
1787
1788			// default to 0 when nulls exist
1789			v = ( v || 0 ).toString( 16 );
1790			return v.length === 1 ? "0" + v : v;
1791		} ).join( "" );
1792	},
1793	toString: function() {
1794		return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString();
1795	}
1796} );
1797color.fn.parse.prototype = color.fn;
1798
1799// hsla conversions adapted from:
1800// https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021
1801
1802function hue2rgb( p, q, h ) {
1803	h = ( h + 1 ) % 1;
1804	if ( h * 6 < 1 ) {
1805		return p + ( q - p ) * h * 6;
1806	}
1807	if ( h * 2 < 1 ) {
1808		return q;
1809	}
1810	if ( h * 3 < 2 ) {
1811		return p + ( q - p ) * ( ( 2 / 3 ) - h ) * 6;
1812	}
1813	return p;
1814}
1815
1816spaces.hsla.to = function( rgba ) {
1817	if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) {
1818		return [ null, null, null, rgba[ 3 ] ];
1819	}
1820	var r = rgba[ 0 ] / 255,
1821		g = rgba[ 1 ] / 255,
1822		b = rgba[ 2 ] / 255,
1823		a = rgba[ 3 ],
1824		max = Math.max( r, g, b ),
1825		min = Math.min( r, g, b ),
1826		diff = max - min,
1827		add = max + min,
1828		l = add * 0.5,
1829		h, s;
1830
1831	if ( min === max ) {
1832		h = 0;
1833	} else if ( r === max ) {
1834		h = ( 60 * ( g - b ) / diff ) + 360;
1835	} else if ( g === max ) {
1836		h = ( 60 * ( b - r ) / diff ) + 120;
1837	} else {
1838		h = ( 60 * ( r - g ) / diff ) + 240;
1839	}
1840
1841	// chroma (diff) == 0 means greyscale which, by definition, saturation = 0%
1842	// otherwise, saturation is based on the ratio of chroma (diff) to lightness (add)
1843	if ( diff === 0 ) {
1844		s = 0;
1845	} else if ( l <= 0.5 ) {
1846		s = diff / add;
1847	} else {
1848		s = diff / ( 2 - add );
1849	}
1850	return [ Math.round( h ) % 360, s, l, a == null ? 1 : a ];
1851};
1852
1853spaces.hsla.from = function( hsla ) {
1854	if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) {
1855		return [ null, null, null, hsla[ 3 ] ];
1856	}
1857	var h = hsla[ 0 ] / 360,
1858		s = hsla[ 1 ],
1859		l = hsla[ 2 ],
1860		a = hsla[ 3 ],
1861		q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s,
1862		p = 2 * l - q;
1863
1864	return [
1865		Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ),
1866		Math.round( hue2rgb( p, q, h ) * 255 ),
1867		Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ),
1868		a
1869	];
1870};
1871
1872
1873each( spaces, function( spaceName, space ) {
1874	var props = space.props,
1875		cache = space.cache,
1876		to = space.to,
1877		from = space.from;
1878
1879	// makes rgba() and hsla()
1880	color.fn[ spaceName ] = function( value ) {
1881
1882		// generate a cache for this space if it doesn't exist
1883		if ( to && !this[ cache ] ) {
1884			this[ cache ] = to( this._rgba );
1885		}
1886		if ( value === undefined ) {
1887			return this[ cache ].slice();
1888		}
1889
1890		var ret,
1891			type = getType( value ),
1892			arr = ( type === "array" || type === "object" ) ? value : arguments,
1893			local = this[ cache ].slice();
1894
1895		each( props, function( key, prop ) {
1896			var val = arr[ type === "object" ? key : prop.idx ];
1897			if ( val == null ) {
1898				val = local[ prop.idx ];
1899			}
1900			local[ prop.idx ] = clamp( val, prop );
1901		} );
1902
1903		if ( from ) {
1904			ret = color( from( local ) );
1905			ret[ cache ] = local;
1906			return ret;
1907		} else {
1908			return color( local );
1909		}
1910	};
1911
1912	// makes red() green() blue() alpha() hue() saturation() lightness()
1913	each( props, function( key, prop ) {
1914
1915		// alpha is included in more than one space
1916		if ( color.fn[ key ] ) {
1917			return;
1918		}
1919		color.fn[ key ] = function( value ) {
1920			var local, cur, match, fn,
1921				vtype = getType( value );
1922
1923			if ( key === "alpha" ) {
1924				fn = this._hsla ? "hsla" : "rgba";
1925			} else {
1926				fn = spaceName;
1927			}
1928			local = this[ fn ]();
1929			cur = local[ prop.idx ];
1930
1931			if ( vtype === "undefined" ) {
1932				return cur;
1933			}
1934
1935			if ( vtype === "function" ) {
1936				value = value.call( this, cur );
1937				vtype = getType( value );
1938			}
1939			if ( value == null && prop.empty ) {
1940				return this;
1941			}
1942			if ( vtype === "string" ) {
1943				match = rplusequals.exec( value );
1944				if ( match ) {
1945					value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 );
1946				}
1947			}
1948			local[ prop.idx ] = value;
1949			return this[ fn ]( local );
1950		};
1951	} );
1952} );
1953
1954// add cssHook and .fx.step function for each named hook.
1955// accept a space separated string of properties
1956color.hook = function( hook ) {
1957	var hooks = hook.split( " " );
1958	each( hooks, function( _i, hook ) {
1959		jQuery.cssHooks[ hook ] = {
1960			set: function( elem, value ) {
1961				var parsed, curElem,
1962					backgroundColor = "";
1963
1964				if ( value !== "transparent" && ( getType( value ) !== "string" || ( parsed = stringParse( value ) ) ) ) {
1965					value = color( parsed || value );
1966					if ( !support.rgba && value._rgba[ 3 ] !== 1 ) {
1967						curElem = hook === "backgroundColor" ? elem.parentNode : elem;
1968						while (
1969							( backgroundColor === "" || backgroundColor === "transparent" ) &&
1970							curElem && curElem.style
1971						) {
1972							try {
1973								backgroundColor = jQuery.css( curElem, "backgroundColor" );
1974								curElem = curElem.parentNode;
1975							} catch ( e ) {
1976							}
1977						}
1978
1979						value = value.blend( backgroundColor && backgroundColor !== "transparent" ?
1980							backgroundColor :
1981							"_default" );
1982					}
1983
1984					value = value.toRgbaString();
1985				}
1986				try {
1987					elem.style[ hook ] = value;
1988				} catch ( e ) {
1989
1990					// wrapped to prevent IE from throwing errors on "invalid" values like 'auto' or 'inherit'
1991				}
1992			}
1993		};
1994		jQuery.fx.step[ hook ] = function( fx ) {
1995			if ( !fx.colorInit ) {
1996				fx.start = color( fx.elem, hook );
1997				fx.end = color( fx.end );
1998				fx.colorInit = true;
1999			}
2000			jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) );
2001		};
2002	} );
2003
2004};
2005
2006color.hook( stepHooks );
2007
2008jQuery.cssHooks.borderColor = {
2009	expand: function( value ) {
2010		var expanded = {};
2011
2012		each( [ "Top", "Right", "Bottom", "Left" ], function( _i, part ) {
2013			expanded[ "border" + part + "Color" ] = value;
2014		} );
2015		return expanded;
2016	}
2017};
2018
2019// Basic color names only.
2020// Usage of any of the other color names requires adding yourself or including
2021// jquery.color.svg-names.js.
2022colors = jQuery.Color.names = {
2023
2024	// 4.1. Basic color keywords
2025	aqua: "#00ffff",
2026	black: "#000000",
2027	blue: "#0000ff",
2028	fuchsia: "#ff00ff",
2029	gray: "#808080",
2030	green: "#008000",
2031	lime: "#00ff00",
2032	maroon: "#800000",
2033	navy: "#000080",
2034	olive: "#808000",
2035	purple: "#800080",
2036	red: "#ff0000",
2037	silver: "#c0c0c0",
2038	teal: "#008080",
2039	white: "#ffffff",
2040	yellow: "#ffff00",
2041
2042	// 4.2.3. "transparent" color keyword
2043	transparent: [ null, null, null, 0 ],
2044
2045	_default: "#ffffff"
2046};
2047
2048
2049/*!
2050 * jQuery UI Effects 1.13.3
2051 * https://jqueryui.com
2052 *
2053 * Copyright OpenJS Foundation and other contributors
2054 * Released under the MIT license.
2055 * https://jquery.org/license
2056 */
2057
2058//>>label: Effects Core
2059//>>group: Effects
2060/* eslint-disable max-len */
2061//>>description: Extends the internal jQuery effects. Includes morphing and easing. Required by all other effects.
2062/* eslint-enable max-len */
2063//>>docs: https://api.jqueryui.com/category/effects-core/
2064//>>demos: https://jqueryui.com/effect/
2065
2066
2067var dataSpace = "ui-effects-",
2068	dataSpaceStyle = "ui-effects-style",
2069	dataSpaceAnimated = "ui-effects-animated";
2070
2071$.effects = {
2072	effect: {}
2073};
2074
2075/******************************************************************************/
2076/****************************** CLASS ANIMATIONS ******************************/
2077/******************************************************************************/
2078( function() {
2079
2080var classAnimationActions = [ "add", "remove", "toggle" ],
2081	shorthandStyles = {
2082		border: 1,
2083		borderBottom: 1,
2084		borderColor: 1,
2085		borderLeft: 1,
2086		borderRight: 1,
2087		borderTop: 1,
2088		borderWidth: 1,
2089		margin: 1,
2090		padding: 1
2091	};
2092
2093$.each(
2094	[ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ],
2095	function( _, prop ) {
2096		$.fx.step[ prop ] = function( fx ) {
2097			if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) {
2098				jQuery.style( fx.elem, prop, fx.end );
2099				fx.setAttr = true;
2100			}
2101		};
2102	}
2103);
2104
2105function camelCase( string ) {
2106	return string.replace( /-([\da-z])/gi, function( all, letter ) {
2107		return letter.toUpperCase();
2108	} );
2109}
2110
2111function getElementStyles( elem ) {
2112	var key, len,
2113		style = elem.ownerDocument.defaultView ?
2114			elem.ownerDocument.defaultView.getComputedStyle( elem, null ) :
2115			elem.currentStyle,
2116		styles = {};
2117
2118	if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) {
2119		len = style.length;
2120		while ( len-- ) {
2121			key = style[ len ];
2122			if ( typeof style[ key ] === "string" ) {
2123				styles[ camelCase( key ) ] = style[ key ];
2124			}
2125		}
2126
2127	// Support: Opera, IE <9
2128	} else {
2129		for ( key in style ) {
2130			if ( typeof style[ key ] === "string" ) {
2131				styles[ key ] = style[ key ];
2132			}
2133		}
2134	}
2135
2136	return styles;
2137}
2138
2139function styleDifference( oldStyle, newStyle ) {
2140	var diff = {},
2141		name, value;
2142
2143	for ( name in newStyle ) {
2144		value = newStyle[ name ];
2145		if ( oldStyle[ name ] !== value ) {
2146			if ( !shorthandStyles[ name ] ) {
2147				if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) {
2148					diff[ name ] = value;
2149				}
2150			}
2151		}
2152	}
2153
2154	return diff;
2155}
2156
2157// Support: jQuery <1.8
2158if ( !$.fn.addBack ) {
2159	$.fn.addBack = function( selector ) {
2160		return this.add( selector == null ?
2161			this.prevObject : this.prevObject.filter( selector )
2162		);
2163	};
2164}
2165
2166$.effects.animateClass = function( value, duration, easing, callback ) {
2167	var o = $.speed( duration, easing, callback );
2168
2169	return this.queue( function() {
2170		var animated = $( this ),
2171			baseClass = animated.attr( "class" ) || "",
2172			applyClassChange,
2173			allAnimations = o.children ? animated.find( "*" ).addBack() : animated;
2174
2175		// Map the animated objects to store the original styles.
2176		allAnimations = allAnimations.map( function() {
2177			var el = $( this );
2178			return {
2179				el: el,
2180				start: getElementStyles( this )
2181			};
2182		} );
2183
2184		// Apply class change
2185		applyClassChange = function() {
2186			$.each( classAnimationActions, function( i, action ) {
2187				if ( value[ action ] ) {
2188					animated[ action + "Class" ]( value[ action ] );
2189				}
2190			} );
2191		};
2192		applyClassChange();
2193
2194		// Map all animated objects again - calculate new styles and diff
2195		allAnimations = allAnimations.map( function() {
2196			this.end = getElementStyles( this.el[ 0 ] );
2197			this.diff = styleDifference( this.start, this.end );
2198			return this;
2199		} );
2200
2201		// Apply original class
2202		animated.attr( "class", baseClass );
2203
2204		// Map all animated objects again - this time collecting a promise
2205		allAnimations = allAnimations.map( function() {
2206			var styleInfo = this,
2207				dfd = $.Deferred(),
2208				opts = $.extend( {}, o, {
2209					queue: false,
2210					complete: function() {
2211						dfd.resolve( styleInfo );
2212					}
2213				} );
2214
2215			this.el.animate( this.diff, opts );
2216			return dfd.promise();
2217		} );
2218
2219		// Once all animations have completed:
2220		$.when.apply( $, allAnimations.get() ).done( function() {
2221
2222			// Set the final class
2223			applyClassChange();
2224
2225			// For each animated element,
2226			// clear all css properties that were animated
2227			$.each( arguments, function() {
2228				var el = this.el;
2229				$.each( this.diff, function( key ) {
2230					el.css( key, "" );
2231				} );
2232			} );
2233
2234			// This is guarnteed to be there if you use jQuery.speed()
2235			// it also handles dequeuing the next anim...
2236			o.complete.call( animated[ 0 ] );
2237		} );
2238	} );
2239};
2240
2241$.fn.extend( {
2242	addClass: ( function( orig ) {
2243		return function( classNames, speed, easing, callback ) {
2244			return speed ?
2245				$.effects.animateClass.call( this,
2246					{ add: classNames }, speed, easing, callback ) :
2247				orig.apply( this, arguments );
2248		};
2249	} )( $.fn.addClass ),
2250
2251	removeClass: ( function( orig ) {
2252		return function( classNames, speed, easing, callback ) {
2253			return arguments.length > 1 ?
2254				$.effects.animateClass.call( this,
2255					{ remove: classNames }, speed, easing, callback ) :
2256				orig.apply( this, arguments );
2257		};
2258	} )( $.fn.removeClass ),
2259
2260	toggleClass: ( function( orig ) {
2261		return function( classNames, force, speed, easing, callback ) {
2262			if ( typeof force === "boolean" || force === undefined ) {
2263				if ( !speed ) {
2264
2265					// Without speed parameter
2266					return orig.apply( this, arguments );
2267				} else {
2268					return $.effects.animateClass.call( this,
2269						( force ? { add: classNames } : { remove: classNames } ),
2270						speed, easing, callback );
2271				}
2272			} else {
2273
2274				// Without force parameter
2275				return $.effects.animateClass.call( this,
2276					{ toggle: classNames }, force, speed, easing );
2277			}
2278		};
2279	} )( $.fn.toggleClass ),
2280
2281	switchClass: function( remove, add, speed, easing, callback ) {
2282		return $.effects.animateClass.call( this, {
2283			add: add,
2284			remove: remove
2285		}, speed, easing, callback );
2286	}
2287} );
2288
2289} )();
2290
2291/******************************************************************************/
2292/*********************************** EFFECTS **********************************/
2293/******************************************************************************/
2294
2295( function() {
2296
2297if ( $.expr && $.expr.pseudos && $.expr.pseudos.animated ) {
2298	$.expr.pseudos.animated = ( function( orig ) {
2299		return function( elem ) {
2300			return !!$( elem ).data( dataSpaceAnimated ) || orig( elem );
2301		};
2302	} )( $.expr.pseudos.animated );
2303}
2304
2305if ( $.uiBackCompat !== false ) {
2306	$.extend( $.effects, {
2307
2308		// Saves a set of properties in a data storage
2309		save: function( element, set ) {
2310			var i = 0, length = set.length;
2311			for ( ; i < length; i++ ) {
2312				if ( set[ i ] !== null ) {
2313					element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] );
2314				}
2315			}
2316		},
2317
2318		// Restores a set of previously saved properties from a data storage
2319		restore: function( element, set ) {
2320			var val, i = 0, length = set.length;
2321			for ( ; i < length; i++ ) {
2322				if ( set[ i ] !== null ) {
2323					val = element.data( dataSpace + set[ i ] );
2324					element.css( set[ i ], val );
2325				}
2326			}
2327		},
2328
2329		setMode: function( el, mode ) {
2330			if ( mode === "toggle" ) {
2331				mode = el.is( ":hidden" ) ? "show" : "hide";
2332			}
2333			return mode;
2334		},
2335
2336		// Wraps the element around a wrapper that copies position properties
2337		createWrapper: function( element ) {
2338
2339			// If the element is already wrapped, return it
2340			if ( element.parent().is( ".ui-effects-wrapper" ) ) {
2341				return element.parent();
2342			}
2343
2344			// Wrap the element
2345			var props = {
2346					width: element.outerWidth( true ),
2347					height: element.outerHeight( true ),
2348					"float": element.css( "float" )
2349				},
2350				wrapper = $( "<div></div>" )
2351					.addClass( "ui-effects-wrapper" )
2352					.css( {
2353						fontSize: "100%",
2354						background: "transparent",
2355						border: "none",
2356						margin: 0,
2357						padding: 0
2358					} ),
2359
2360				// Store the size in case width/height are defined in % - Fixes #5245
2361				size = {
2362					width: element.width(),
2363					height: element.height()
2364				},
2365				active = document.activeElement;
2366
2367			// Support: Firefox
2368			// Firefox incorrectly exposes anonymous content
2369			// https://bugzilla.mozilla.org/show_bug.cgi?id=561664
2370			try {
2371				// eslint-disable-next-line no-unused-expressions
2372				active.id;
2373			} catch ( e ) {
2374				active = document.body;
2375			}
2376
2377			element.wrap( wrapper );
2378
2379			// Fixes #7595 - Elements lose focus when wrapped.
2380			if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
2381				$( active ).trigger( "focus" );
2382			}
2383
2384			// Hotfix for jQuery 1.4 since some change in wrap() seems to actually
2385			// lose the reference to the wrapped element
2386			wrapper = element.parent();
2387
2388			// Transfer positioning properties to the wrapper
2389			if ( element.css( "position" ) === "static" ) {
2390				wrapper.css( { position: "relative" } );
2391				element.css( { position: "relative" } );
2392			} else {
2393				$.extend( props, {
2394					position: element.css( "position" ),
2395					zIndex: element.css( "z-index" )
2396				} );
2397				$.each( [ "top", "left", "bottom", "right" ], function( i, pos ) {
2398					props[ pos ] = element.css( pos );
2399					if ( isNaN( parseInt( props[ pos ], 10 ) ) ) {
2400						props[ pos ] = "auto";
2401					}
2402				} );
2403				element.css( {
2404					position: "relative",
2405					top: 0,
2406					left: 0,
2407					right: "auto",
2408					bottom: "auto"
2409				} );
2410			}
2411			element.css( size );
2412
2413			return wrapper.css( props ).show();
2414		},
2415
2416		removeWrapper: function( element ) {
2417			var active = document.activeElement;
2418
2419			if ( element.parent().is( ".ui-effects-wrapper" ) ) {
2420				element.parent().replaceWith( element );
2421
2422				// Fixes #7595 - Elements lose focus when wrapped.
2423				if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
2424					$( active ).trigger( "focus" );
2425				}
2426			}
2427
2428			return element;
2429		}
2430	} );
2431}
2432
2433$.extend( $.effects, {
2434	version: "1.13.3",
2435
2436	define: function( name, mode, effect ) {
2437		if ( !effect ) {
2438			effect = mode;
2439			mode = "effect";
2440		}
2441
2442		$.effects.effect[ name ] = effect;
2443		$.effects.effect[ name ].mode = mode;
2444
2445		return effect;
2446	},
2447
2448	scaledDimensions: function( element, percent, direction ) {
2449		if ( percent === 0 ) {
2450			return {
2451				height: 0,
2452				width: 0,
2453				outerHeight: 0,
2454				outerWidth: 0
2455			};
2456		}
2457
2458		var x = direction !== "horizontal" ? ( ( percent || 100 ) / 100 ) : 1,
2459			y = direction !== "vertical" ? ( ( percent || 100 ) / 100 ) : 1;
2460
2461		return {
2462			height: element.height() * y,
2463			width: element.width() * x,
2464			outerHeight: element.outerHeight() * y,
2465			outerWidth: element.outerWidth() * x
2466		};
2467
2468	},
2469
2470	clipToBox: function( animation ) {
2471		return {
2472			width: animation.clip.right - animation.clip.left,
2473			height: animation.clip.bottom - animation.clip.top,
2474			left: animation.clip.left,
2475			top: animation.clip.top
2476		};
2477	},
2478
2479	// Injects recently queued functions to be first in line (after "inprogress")
2480	unshift: function( element, queueLength, count ) {
2481		var queue = element.queue();
2482
2483		if ( queueLength > 1 ) {
2484			queue.splice.apply( queue,
2485				[ 1, 0 ].concat( queue.splice( queueLength, count ) ) );
2486		}
2487		element.dequeue();
2488	},
2489
2490	saveStyle: function( element ) {
2491		element.data( dataSpaceStyle, element[ 0 ].style.cssText );
2492	},
2493
2494	restoreStyle: function( element ) {
2495		element[ 0 ].style.cssText = element.data( dataSpaceStyle ) || "";
2496		element.removeData( dataSpaceStyle );
2497	},
2498
2499	mode: function( element, mode ) {
2500		var hidden = element.is( ":hidden" );
2501
2502		if ( mode === "toggle" ) {
2503			mode = hidden ? "show" : "hide";
2504		}
2505		if ( hidden ? mode === "hide" : mode === "show" ) {
2506			mode = "none";
2507		}
2508		return mode;
2509	},
2510
2511	// Translates a [top,left] array into a baseline value
2512	getBaseline: function( origin, original ) {
2513		var y, x;
2514
2515		switch ( origin[ 0 ] ) {
2516		case "top":
2517			y = 0;
2518			break;
2519		case "middle":
2520			y = 0.5;
2521			break;
2522		case "bottom":
2523			y = 1;
2524			break;
2525		default:
2526			y = origin[ 0 ] / original.height;
2527		}
2528
2529		switch ( origin[ 1 ] ) {
2530		case "left":
2531			x = 0;
2532			break;
2533		case "center":
2534			x = 0.5;
2535			break;
2536		case "right":
2537			x = 1;
2538			break;
2539		default:
2540			x = origin[ 1 ] / original.width;
2541		}
2542
2543		return {
2544			x: x,
2545			y: y
2546		};
2547	},
2548
2549	// Creates a placeholder element so that the original element can be made absolute
2550	createPlaceholder: function( element ) {
2551		var placeholder,
2552			cssPosition = element.css( "position" ),
2553			position = element.position();
2554
2555		// Lock in margins first to account for form elements, which
2556		// will change margin if you explicitly set height
2557		// see: https://jsfiddle.net/JZSMt/3/ https://bugs.webkit.org/show_bug.cgi?id=107380
2558		// Support: Safari
2559		element.css( {
2560			marginTop: element.css( "marginTop" ),
2561			marginBottom: element.css( "marginBottom" ),
2562			marginLeft: element.css( "marginLeft" ),
2563			marginRight: element.css( "marginRight" )
2564		} )
2565		.outerWidth( element.outerWidth() )
2566		.outerHeight( element.outerHeight() );
2567
2568		if ( /^(static|relative)/.test( cssPosition ) ) {
2569			cssPosition = "absolute";
2570
2571			placeholder = $( "<" + element[ 0 ].nodeName + ">" ).insertAfter( element ).css( {
2572
2573				// Convert inline to inline block to account for inline elements
2574				// that turn to inline block based on content (like img)
2575				display: /^(inline|ruby)/.test( element.css( "display" ) ) ?
2576					"inline-block" :
2577					"block",
2578				visibility: "hidden",
2579
2580				// Margins need to be set to account for margin collapse
2581				marginTop: element.css( "marginTop" ),
2582				marginBottom: element.css( "marginBottom" ),
2583				marginLeft: element.css( "marginLeft" ),
2584				marginRight: element.css( "marginRight" ),
2585				"float": element.css( "float" )
2586			} )
2587			.outerWidth( element.outerWidth() )
2588			.outerHeight( element.outerHeight() )
2589			.addClass( "ui-effects-placeholder" );
2590
2591			element.data( dataSpace + "placeholder", placeholder );
2592		}
2593
2594		element.css( {
2595			position: cssPosition,
2596			left: position.left,
2597			top: position.top
2598		} );
2599
2600		return placeholder;
2601	},
2602
2603	removePlaceholder: function( element ) {
2604		var dataKey = dataSpace + "placeholder",
2605				placeholder = element.data( dataKey );
2606
2607		if ( placeholder ) {
2608			placeholder.remove();
2609			element.removeData( dataKey );
2610		}
2611	},
2612
2613	// Removes a placeholder if it exists and restores
2614	// properties that were modified during placeholder creation
2615	cleanUp: function( element ) {
2616		$.effects.restoreStyle( element );
2617		$.effects.removePlaceholder( element );
2618	},
2619
2620	setTransition: function( element, list, factor, value ) {
2621		value = value || {};
2622		$.each( list, function( i, x ) {
2623			var unit = element.cssUnit( x );
2624			if ( unit[ 0 ] > 0 ) {
2625				value[ x ] = unit[ 0 ] * factor + unit[ 1 ];
2626			}
2627		} );
2628		return value;
2629	}
2630} );
2631
2632// Return an effect options object for the given parameters:
2633function _normalizeArguments( effect, options, speed, callback ) {
2634
2635	// Allow passing all options as the first parameter
2636	if ( $.isPlainObject( effect ) ) {
2637		options = effect;
2638		effect = effect.effect;
2639	}
2640
2641	// Convert to an object
2642	effect = { effect: effect };
2643
2644	// Catch (effect, null, ...)
2645	if ( options == null ) {
2646		options = {};
2647	}
2648
2649	// Catch (effect, callback)
2650	if ( typeof options === "function" ) {
2651		callback = options;
2652		speed = null;
2653		options = {};
2654	}
2655
2656	// Catch (effect, speed, ?)
2657	if ( typeof options === "number" || $.fx.speeds[ options ] ) {
2658		callback = speed;
2659		speed = options;
2660		options = {};
2661	}
2662
2663	// Catch (effect, options, callback)
2664	if ( typeof speed === "function" ) {
2665		callback = speed;
2666		speed = null;
2667	}
2668
2669	// Add options to effect
2670	if ( options ) {
2671		$.extend( effect, options );
2672	}
2673
2674	speed = speed || options.duration;
2675	effect.duration = $.fx.off ? 0 :
2676		typeof speed === "number" ? speed :
2677		speed in $.fx.speeds ? $.fx.speeds[ speed ] :
2678		$.fx.speeds._default;
2679
2680	effect.complete = callback || options.complete;
2681
2682	return effect;
2683}
2684
2685function standardAnimationOption( option ) {
2686
2687	// Valid standard speeds (nothing, number, named speed)
2688	if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) {
2689		return true;
2690	}
2691
2692	// Invalid strings - treat as "normal" speed
2693	if ( typeof option === "string" && !$.effects.effect[ option ] ) {
2694		return true;
2695	}
2696
2697	// Complete callback
2698	if ( typeof option === "function" ) {
2699		return true;
2700	}
2701
2702	// Options hash (but not naming an effect)
2703	if ( typeof option === "object" && !option.effect ) {
2704		return true;
2705	}
2706
2707	// Didn't match any standard API
2708	return false;
2709}
2710
2711$.fn.extend( {
2712	effect: function( /* effect, options, speed, callback */ ) {
2713		var args = _normalizeArguments.apply( this, arguments ),
2714			effectMethod = $.effects.effect[ args.effect ],
2715			defaultMode = effectMethod.mode,
2716			queue = args.queue,
2717			queueName = queue || "fx",
2718			complete = args.complete,
2719			mode = args.mode,
2720			modes = [],
2721			prefilter = function( next ) {
2722				var el = $( this ),
2723					normalizedMode = $.effects.mode( el, mode ) || defaultMode;
2724
2725				// Sentinel for duck-punching the :animated pseudo-selector
2726				el.data( dataSpaceAnimated, true );
2727
2728				// Save effect mode for later use,
2729				// we can't just call $.effects.mode again later,
2730				// as the .show() below destroys the initial state
2731				modes.push( normalizedMode );
2732
2733				// See $.uiBackCompat inside of run() for removal of defaultMode in 1.14
2734				if ( defaultMode && ( normalizedMode === "show" ||
2735						( normalizedMode === defaultMode && normalizedMode === "hide" ) ) ) {
2736					el.show();
2737				}
2738
2739				if ( !defaultMode || normalizedMode !== "none" ) {
2740					$.effects.saveStyle( el );
2741				}
2742
2743				if ( typeof next === "function" ) {
2744					next();
2745				}
2746			};
2747
2748		if ( $.fx.off || !effectMethod ) {
2749
2750			// Delegate to the original method (e.g., .show()) if possible
2751			if ( mode ) {
2752				return this[ mode ]( args.duration, complete );
2753			} else {
2754				return this.each( function() {
2755					if ( complete ) {
2756						complete.call( this );
2757					}
2758				} );
2759			}
2760		}
2761
2762		function run( next ) {
2763			var elem = $( this );
2764
2765			function cleanup() {
2766				elem.removeData( dataSpaceAnimated );
2767
2768				$.effects.cleanUp( elem );
2769
2770				if ( args.mode === "hide" ) {
2771					elem.hide();
2772				}
2773
2774				done();
2775			}
2776
2777			function done() {
2778				if ( typeof complete === "function" ) {
2779					complete.call( elem[ 0 ] );
2780				}
2781
2782				if ( typeof next === "function" ) {
2783					next();
2784				}
2785			}
2786
2787			// Override mode option on a per element basis,
2788			// as toggle can be either show or hide depending on element state
2789			args.mode = modes.shift();
2790
2791			if ( $.uiBackCompat !== false && !defaultMode ) {
2792				if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) {
2793
2794					// Call the core method to track "olddisplay" properly
2795					elem[ mode ]();
2796					done();
2797				} else {
2798					effectMethod.call( elem[ 0 ], args, done );
2799				}
2800			} else {
2801				if ( args.mode === "none" ) {
2802
2803					// Call the core method to track "olddisplay" properly
2804					elem[ mode ]();
2805					done();
2806				} else {
2807					effectMethod.call( elem[ 0 ], args, cleanup );
2808				}
2809			}
2810		}
2811
2812		// Run prefilter on all elements first to ensure that
2813		// any showing or hiding happens before placeholder creation,
2814		// which ensures that any layout changes are correctly captured.
2815		return queue === false ?
2816			this.each( prefilter ).each( run ) :
2817			this.queue( queueName, prefilter ).queue( queueName, run );
2818	},
2819
2820	show: ( function( orig ) {
2821		return function( option ) {
2822			if ( standardAnimationOption( option ) ) {
2823				return orig.apply( this, arguments );
2824			} else {
2825				var args = _normalizeArguments.apply( this, arguments );
2826				args.mode = "show";
2827				return this.effect.call( this, args );
2828			}
2829		};
2830	} )( $.fn.show ),
2831
2832	hide: ( function( orig ) {
2833		return function( option ) {
2834			if ( standardAnimationOption( option ) ) {
2835				return orig.apply( this, arguments );
2836			} else {
2837				var args = _normalizeArguments.apply( this, arguments );
2838				args.mode = "hide";
2839				return this.effect.call( this, args );
2840			}
2841		};
2842	} )( $.fn.hide ),
2843
2844	toggle: ( function( orig ) {
2845		return function( option ) {
2846			if ( standardAnimationOption( option ) || typeof option === "boolean" ) {
2847				return orig.apply( this, arguments );
2848			} else {
2849				var args = _normalizeArguments.apply( this, arguments );
2850				args.mode = "toggle";
2851				return this.effect.call( this, args );
2852			}
2853		};
2854	} )( $.fn.toggle ),
2855
2856	cssUnit: function( key ) {
2857		var style = this.css( key ),
2858			val = [];
2859
2860		$.each( [ "em", "px", "%", "pt" ], function( i, unit ) {
2861			if ( style.indexOf( unit ) > 0 ) {
2862				val = [ parseFloat( style ), unit ];
2863			}
2864		} );
2865		return val;
2866	},
2867
2868	cssClip: function( clipObj ) {
2869		if ( clipObj ) {
2870			return this.css( "clip", "rect(" + clipObj.top + "px " + clipObj.right + "px " +
2871				clipObj.bottom + "px " + clipObj.left + "px)" );
2872		}
2873		return parseClip( this.css( "clip" ), this );
2874	},
2875
2876	transfer: function( options, done ) {
2877		var element = $( this ),
2878			target = $( options.to ),
2879			targetFixed = target.css( "position" ) === "fixed",
2880			body = $( "body" ),
2881			fixTop = targetFixed ? body.scrollTop() : 0,
2882			fixLeft = targetFixed ? body.scrollLeft() : 0,
2883			endPosition = target.offset(),
2884			animation = {
2885				top: endPosition.top - fixTop,
2886				left: endPosition.left - fixLeft,
2887				height: target.innerHeight(),
2888				width: target.innerWidth()
2889			},
2890			startPosition = element.offset(),
2891			transfer = $( "<div class='ui-effects-transfer'></div>" );
2892
2893		transfer
2894			.appendTo( "body" )
2895			.addClass( options.className )
2896			.css( {
2897				top: startPosition.top - fixTop,
2898				left: startPosition.left - fixLeft,
2899				height: element.innerHeight(),
2900				width: element.innerWidth(),
2901				position: targetFixed ? "fixed" : "absolute"
2902			} )
2903			.animate( animation, options.duration, options.easing, function() {
2904				transfer.remove();
2905				if ( typeof done === "function" ) {
2906					done();
2907				}
2908			} );
2909	}
2910} );
2911
2912function parseClip( str, element ) {
2913		var outerWidth = element.outerWidth(),
2914			outerHeight = element.outerHeight(),
2915			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)\)$/,
2916			values = clipRegex.exec( str ) || [ "", 0, outerWidth, outerHeight, 0 ];
2917
2918		return {
2919			top: parseFloat( values[ 1 ] ) || 0,
2920			right: values[ 2 ] === "auto" ? outerWidth : parseFloat( values[ 2 ] ),
2921			bottom: values[ 3 ] === "auto" ? outerHeight : parseFloat( values[ 3 ] ),
2922			left: parseFloat( values[ 4 ] ) || 0
2923		};
2924}
2925
2926$.fx.step.clip = function( fx ) {
2927	if ( !fx.clipInit ) {
2928		fx.start = $( fx.elem ).cssClip();
2929		if ( typeof fx.end === "string" ) {
2930			fx.end = parseClip( fx.end, fx.elem );
2931		}
2932		fx.clipInit = true;
2933	}
2934
2935	$( fx.elem ).cssClip( {
2936		top: fx.pos * ( fx.end.top - fx.start.top ) + fx.start.top,
2937		right: fx.pos * ( fx.end.right - fx.start.right ) + fx.start.right,
2938		bottom: fx.pos * ( fx.end.bottom - fx.start.bottom ) + fx.start.bottom,
2939		left: fx.pos * ( fx.end.left - fx.start.left ) + fx.start.left
2940	} );
2941};
2942
2943} )();
2944
2945/******************************************************************************/
2946/*********************************** EASING ***********************************/
2947/******************************************************************************/
2948
2949( function() {
2950
2951// Based on easing equations from Robert Penner (http://robertpenner.com/easing)
2952
2953var baseEasings = {};
2954
2955$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) {
2956	baseEasings[ name ] = function( p ) {
2957		return Math.pow( p, i + 2 );
2958	};
2959} );
2960
2961$.extend( baseEasings, {
2962	Sine: function( p ) {
2963		return 1 - Math.cos( p * Math.PI / 2 );
2964	},
2965	Circ: function( p ) {
2966		return 1 - Math.sqrt( 1 - p * p );
2967	},
2968	Elastic: function( p ) {
2969		return p === 0 || p === 1 ? p :
2970			-Math.pow( 2, 8 * ( p - 1 ) ) * Math.sin( ( ( p - 1 ) * 80 - 7.5 ) * Math.PI / 15 );
2971	},
2972	Back: function( p ) {
2973		return p * p * ( 3 * p - 2 );
2974	},
2975	Bounce: function( p ) {
2976		var pow2,
2977			bounce = 4;
2978
2979		while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}
2980		return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 );
2981	}
2982} );
2983
2984$.each( baseEasings, function( name, easeIn ) {
2985	$.easing[ "easeIn" + name ] = easeIn;
2986	$.easing[ "easeOut" + name ] = function( p ) {
2987		return 1 - easeIn( 1 - p );
2988	};
2989	$.easing[ "easeInOut" + name ] = function( p ) {
2990		return p < 0.5 ?
2991			easeIn( p * 2 ) / 2 :
2992			1 - easeIn( p * -2 + 2 ) / 2;
2993	};
2994} );
2995
2996} )();
2997
2998var effect = $.effects;
2999
3000
3001/*!
3002 * jQuery UI Effects Blind 1.13.3
3003 * https://jqueryui.com
3004 *
3005 * Copyright OpenJS Foundation and other contributors
3006 * Released under the MIT license.
3007 * https://jquery.org/license
3008 */
3009
3010//>>label: Blind Effect
3011//>>group: Effects
3012//>>description: Blinds the element.
3013//>>docs: https://api.jqueryui.com/blind-effect/
3014//>>demos: https://jqueryui.com/effect/
3015
3016
3017var effectsEffectBlind = $.effects.define( "blind", "hide", function( options, done ) {
3018	var map = {
3019			up: [ "bottom", "top" ],
3020			vertical: [ "bottom", "top" ],
3021			down: [ "top", "bottom" ],
3022			left: [ "right", "left" ],
3023			horizontal: [ "right", "left" ],
3024			right: [ "left", "right" ]
3025		},
3026		element = $( this ),
3027		direction = options.direction || "up",
3028		start = element.cssClip(),
3029		animate = { clip: $.extend( {}, start ) },
3030		placeholder = $.effects.createPlaceholder( element );
3031
3032	animate.clip[ map[ direction ][ 0 ] ] = animate.clip[ map[ direction ][ 1 ] ];
3033
3034	if ( options.mode === "show" ) {
3035		element.cssClip( animate.clip );
3036		if ( placeholder ) {
3037			placeholder.css( $.effects.clipToBox( animate ) );
3038		}
3039
3040		animate.clip = start;
3041	}
3042
3043	if ( placeholder ) {
3044		placeholder.animate( $.effects.clipToBox( animate ), options.duration, options.easing );
3045	}
3046
3047	element.animate( animate, {
3048		queue: false,
3049		duration: options.duration,
3050		easing: options.easing,
3051		complete: done
3052	} );
3053} );
3054
3055
3056/*!
3057 * jQuery UI Effects Bounce 1.13.3
3058 * https://jqueryui.com
3059 *
3060 * Copyright OpenJS Foundation and other contributors
3061 * Released under the MIT license.
3062 * https://jquery.org/license
3063 */
3064
3065//>>label: Bounce Effect
3066//>>group: Effects
3067//>>description: Bounces an element horizontally or vertically n times.
3068//>>docs: https://api.jqueryui.com/bounce-effect/
3069//>>demos: https://jqueryui.com/effect/
3070
3071
3072var effectsEffectBounce = $.effects.define( "bounce", function( options, done ) {
3073	var upAnim, downAnim, refValue,
3074		element = $( this ),
3075
3076		// Defaults:
3077		mode = options.mode,
3078		hide = mode === "hide",
3079		show = mode === "show",
3080		direction = options.direction || "up",
3081		distance = options.distance,
3082		times = options.times || 5,
3083
3084		// Number of internal animations
3085		anims = times * 2 + ( show || hide ? 1 : 0 ),
3086		speed = options.duration / anims,
3087		easing = options.easing,
3088
3089		// Utility:
3090		ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
3091		motion = ( direction === "up" || direction === "left" ),
3092		i = 0,
3093
3094		queuelen = element.queue().length;
3095
3096	$.effects.createPlaceholder( element );
3097
3098	refValue = element.css( ref );
3099
3100	// Default distance for the BIGGEST bounce is the outer Distance / 3
3101	if ( !distance ) {
3102		distance = element[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3;
3103	}
3104
3105	if ( show ) {
3106		downAnim = { opacity: 1 };
3107		downAnim[ ref ] = refValue;
3108
3109		// If we are showing, force opacity 0 and set the initial position
3110		// then do the "first" animation
3111		element
3112			.css( "opacity", 0 )
3113			.css( ref, motion ? -distance * 2 : distance * 2 )
3114			.animate( downAnim, speed, easing );
3115	}
3116
3117	// Start at the smallest distance if we are hiding
3118	if ( hide ) {
3119		distance = distance / Math.pow( 2, times - 1 );
3120	}
3121
3122	downAnim = {};
3123	downAnim[ ref ] = refValue;
3124
3125	// Bounces up/down/left/right then back to 0 -- times * 2 animations happen here
3126	for ( ; i < times; i++ ) {
3127		upAnim = {};
3128		upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
3129
3130		element
3131			.animate( upAnim, speed, easing )
3132			.animate( downAnim, speed, easing );
3133
3134		distance = hide ? distance * 2 : distance / 2;
3135	}
3136
3137	// Last Bounce when Hiding
3138	if ( hide ) {
3139		upAnim = { opacity: 0 };
3140		upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
3141
3142		element.animate( upAnim, speed, easing );
3143	}
3144
3145	element.queue( done );
3146
3147	$.effects.unshift( element, queuelen, anims + 1 );
3148} );
3149
3150
3151/*!
3152 * jQuery UI Effects Clip 1.13.3
3153 * https://jqueryui.com
3154 *
3155 * Copyright OpenJS Foundation and other contributors
3156 * Released under the MIT license.
3157 * https://jquery.org/license
3158 */
3159
3160//>>label: Clip Effect
3161//>>group: Effects
3162//>>description: Clips the element on and off like an old TV.
3163//>>docs: https://api.jqueryui.com/clip-effect/
3164//>>demos: https://jqueryui.com/effect/
3165
3166
3167var effectsEffectClip = $.effects.define( "clip", "hide", function( options, done ) {
3168	var start,
3169		animate = {},
3170		element = $( this ),
3171		direction = options.direction || "vertical",
3172		both = direction === "both",
3173		horizontal = both || direction === "horizontal",
3174		vertical = both || direction === "vertical";
3175
3176	start = element.cssClip();
3177	animate.clip = {
3178		top: vertical ? ( start.bottom - start.top ) / 2 : start.top,
3179		right: horizontal ? ( start.right - start.left ) / 2 : start.right,
3180		bottom: vertical ? ( start.bottom - start.top ) / 2 : start.bottom,
3181		left: horizontal ? ( start.right - start.left ) / 2 : start.left
3182	};
3183
3184	$.effects.createPlaceholder( element );
3185
3186	if ( options.mode === "show" ) {
3187		element.cssClip( animate.clip );
3188		animate.clip = start;
3189	}
3190
3191	element.animate( animate, {
3192		queue: false,
3193		duration: options.duration,
3194		easing: options.easing,
3195		complete: done
3196	} );
3197
3198} );
3199
3200
3201/*!
3202 * jQuery UI Effects Drop 1.13.3
3203 * https://jqueryui.com
3204 *
3205 * Copyright OpenJS Foundation and other contributors
3206 * Released under the MIT license.
3207 * https://jquery.org/license
3208 */
3209
3210//>>label: Drop Effect
3211//>>group: Effects
3212//>>description: Moves an element in one direction and hides it at the same time.
3213//>>docs: https://api.jqueryui.com/drop-effect/
3214//>>demos: https://jqueryui.com/effect/
3215
3216
3217var effectsEffectDrop = $.effects.define( "drop", "hide", function( options, done ) {
3218
3219	var distance,
3220		element = $( this ),
3221		mode = options.mode,
3222		show = mode === "show",
3223		direction = options.direction || "left",
3224		ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
3225		motion = ( direction === "up" || direction === "left" ) ? "-=" : "+=",
3226		oppositeMotion = ( motion === "+=" ) ? "-=" : "+=",
3227		animation = {
3228			opacity: 0
3229		};
3230
3231	$.effects.createPlaceholder( element );
3232
3233	distance = options.distance ||
3234		element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ) / 2;
3235
3236	animation[ ref ] = motion + distance;
3237
3238	if ( show ) {
3239		element.css( animation );
3240
3241		animation[ ref ] = oppositeMotion + distance;
3242		animation.opacity = 1;
3243	}
3244
3245	// Animate
3246	element.animate( animation, {
3247		queue: false,
3248		duration: options.duration,
3249		easing: options.easing,
3250		complete: done
3251	} );
3252} );
3253
3254
3255/*!
3256 * jQuery UI Effects Explode 1.13.3
3257 * https://jqueryui.com
3258 *
3259 * Copyright OpenJS Foundation and other contributors
3260 * Released under the MIT license.
3261 * https://jquery.org/license
3262 */
3263
3264//>>label: Explode Effect
3265//>>group: Effects
3266/* eslint-disable max-len */
3267//>>description: Explodes an element in all directions into n pieces. Implodes an element to its original wholeness.
3268/* eslint-enable max-len */
3269//>>docs: https://api.jqueryui.com/explode-effect/
3270//>>demos: https://jqueryui.com/effect/
3271
3272
3273var effectsEffectExplode = $.effects.define( "explode", "hide", function( options, done ) {
3274
3275	var i, j, left, top, mx, my,
3276		rows = options.pieces ? Math.round( Math.sqrt( options.pieces ) ) : 3,
3277		cells = rows,
3278		element = $( this ),
3279		mode = options.mode,
3280		show = mode === "show",
3281
3282		// Show and then visibility:hidden the element before calculating offset
3283		offset = element.show().css( "visibility", "hidden" ).offset(),
3284
3285		// Width and height of a piece
3286		width = Math.ceil( element.outerWidth() / cells ),
3287		height = Math.ceil( element.outerHeight() / rows ),
3288		pieces = [];
3289
3290	// Children animate complete:
3291	function childComplete() {
3292		pieces.push( this );
3293		if ( pieces.length === rows * cells ) {
3294			animComplete();
3295		}
3296	}
3297
3298	// Clone the element for each row and cell.
3299	for ( i = 0; i < rows; i++ ) { // ===>
3300		top = offset.top + i * height;
3301		my = i - ( rows - 1 ) / 2;
3302
3303		for ( j = 0; j < cells; j++ ) { // |||
3304			left = offset.left + j * width;
3305			mx = j - ( cells - 1 ) / 2;
3306
3307			// Create a clone of the now hidden main element that will be absolute positioned
3308			// within a wrapper div off the -left and -top equal to size of our pieces
3309			element
3310				.clone()
3311				.appendTo( "body" )
3312				.wrap( "<div></div>" )
3313				.css( {
3314					position: "absolute",
3315					visibility: "visible",
3316					left: -j * width,
3317					top: -i * height
3318				} )
3319
3320				// Select the wrapper - make it overflow: hidden and absolute positioned based on
3321				// where the original was located +left and +top equal to the size of pieces
3322				.parent()
3323					.addClass( "ui-effects-explode" )
3324					.css( {
3325						position: "absolute",
3326						overflow: "hidden",
3327						width: width,
3328						height: height,
3329						left: left + ( show ? mx * width : 0 ),
3330						top: top + ( show ? my * height : 0 ),
3331						opacity: show ? 0 : 1
3332					} )
3333					.animate( {
3334						left: left + ( show ? 0 : mx * width ),
3335						top: top + ( show ? 0 : my * height ),
3336						opacity: show ? 1 : 0
3337					}, options.duration || 500, options.easing, childComplete );
3338		}
3339	}
3340
3341	function animComplete() {
3342		element.css( {
3343			visibility: "visible"
3344		} );
3345		$( pieces ).remove();
3346		done();
3347	}
3348} );
3349
3350
3351/*!
3352 * jQuery UI Effects Fade 1.13.3
3353 * https://jqueryui.com
3354 *
3355 * Copyright OpenJS Foundation and other contributors
3356 * Released under the MIT license.
3357 * https://jquery.org/license
3358 */
3359
3360//>>label: Fade Effect
3361//>>group: Effects
3362//>>description: Fades the element.
3363//>>docs: https://api.jqueryui.com/fade-effect/
3364//>>demos: https://jqueryui.com/effect/
3365
3366
3367var effectsEffectFade = $.effects.define( "fade", "toggle", function( options, done ) {
3368	var show = options.mode === "show";
3369
3370	$( this )
3371		.css( "opacity", show ? 0 : 1 )
3372		.animate( {
3373			opacity: show ? 1 : 0
3374		}, {
3375			queue: false,
3376			duration: options.duration,
3377			easing: options.easing,
3378			complete: done
3379		} );
3380} );
3381
3382
3383/*!
3384 * jQuery UI Effects Fold 1.13.3
3385 * https://jqueryui.com
3386 *
3387 * Copyright OpenJS Foundation and other contributors
3388 * Released under the MIT license.
3389 * https://jquery.org/license
3390 */
3391
3392//>>label: Fold Effect
3393//>>group: Effects
3394//>>description: Folds an element first horizontally and then vertically.
3395//>>docs: https://api.jqueryui.com/fold-effect/
3396//>>demos: https://jqueryui.com/effect/
3397
3398
3399var effectsEffectFold = $.effects.define( "fold", "hide", function( options, done ) {
3400
3401	// Create element
3402	var element = $( this ),
3403		mode = options.mode,
3404		show = mode === "show",
3405		hide = mode === "hide",
3406		size = options.size || 15,
3407		percent = /([0-9]+)%/.exec( size ),
3408		horizFirst = !!options.horizFirst,
3409		ref = horizFirst ? [ "right", "bottom" ] : [ "bottom", "right" ],
3410		duration = options.duration / 2,
3411
3412		placeholder = $.effects.createPlaceholder( element ),
3413
3414		start = element.cssClip(),
3415		animation1 = { clip: $.extend( {}, start ) },
3416		animation2 = { clip: $.extend( {}, start ) },
3417
3418		distance = [ start[ ref[ 0 ] ], start[ ref[ 1 ] ] ],
3419
3420		queuelen = element.queue().length;
3421
3422	if ( percent ) {
3423		size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ];
3424	}
3425	animation1.clip[ ref[ 0 ] ] = size;
3426	animation2.clip[ ref[ 0 ] ] = size;
3427	animation2.clip[ ref[ 1 ] ] = 0;
3428
3429	if ( show ) {
3430		element.cssClip( animation2.clip );
3431		if ( placeholder ) {
3432			placeholder.css( $.effects.clipToBox( animation2 ) );
3433		}
3434
3435		animation2.clip = start;
3436	}
3437
3438	// Animate
3439	element
3440		.queue( function( next ) {
3441			if ( placeholder ) {
3442				placeholder
3443					.animate( $.effects.clipToBox( animation1 ), duration, options.easing )
3444					.animate( $.effects.clipToBox( animation2 ), duration, options.easing );
3445			}
3446
3447			next();
3448		} )
3449		.animate( animation1, duration, options.easing )
3450		.animate( animation2, duration, options.easing )
3451		.queue( done );
3452
3453	$.effects.unshift( element, queuelen, 4 );
3454} );
3455
3456
3457/*!
3458 * jQuery UI Effects Highlight 1.13.3
3459 * https://jqueryui.com
3460 *
3461 * Copyright OpenJS Foundation and other contributors
3462 * Released under the MIT license.
3463 * https://jquery.org/license
3464 */
3465
3466//>>label: Highlight Effect
3467//>>group: Effects
3468//>>description: Highlights the background of an element in a defined color for a custom duration.
3469//>>docs: https://api.jqueryui.com/highlight-effect/
3470//>>demos: https://jqueryui.com/effect/
3471
3472
3473var effectsEffectHighlight = $.effects.define( "highlight", "show", function( options, done ) {
3474	var element = $( this ),
3475		animation = {
3476			backgroundColor: element.css( "backgroundColor" )
3477		};
3478
3479	if ( options.mode === "hide" ) {
3480		animation.opacity = 0;
3481	}
3482
3483	$.effects.saveStyle( element );
3484
3485	element
3486		.css( {
3487			backgroundImage: "none",
3488			backgroundColor: options.color || "#ffff99"
3489		} )
3490		.animate( animation, {
3491			queue: false,
3492			duration: options.duration,
3493			easing: options.easing,
3494			complete: done
3495		} );
3496} );
3497
3498
3499/*!
3500 * jQuery UI Effects Size 1.13.3
3501 * https://jqueryui.com
3502 *
3503 * Copyright OpenJS Foundation and other contributors
3504 * Released under the MIT license.
3505 * https://jquery.org/license
3506 */
3507
3508//>>label: Size Effect
3509//>>group: Effects
3510//>>description: Resize an element to a specified width and height.
3511//>>docs: https://api.jqueryui.com/size-effect/
3512//>>demos: https://jqueryui.com/effect/
3513
3514
3515var effectsEffectSize = $.effects.define( "size", function( options, done ) {
3516
3517	// Create element
3518	var baseline, factor, temp,
3519		element = $( this ),
3520
3521		// Copy for children
3522		cProps = [ "fontSize" ],
3523		vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ],
3524		hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ],
3525
3526		// Set options
3527		mode = options.mode,
3528		restore = mode !== "effect",
3529		scale = options.scale || "both",
3530		origin = options.origin || [ "middle", "center" ],
3531		position = element.css( "position" ),
3532		pos = element.position(),
3533		original = $.effects.scaledDimensions( element ),
3534		from = options.from || original,
3535		to = options.to || $.effects.scaledDimensions( element, 0 );
3536
3537	$.effects.createPlaceholder( element );
3538
3539	if ( mode === "show" ) {
3540		temp = from;
3541		from = to;
3542		to = temp;
3543	}
3544
3545	// Set scaling factor
3546	factor = {
3547		from: {
3548			y: from.height / original.height,
3549			x: from.width / original.width
3550		},
3551		to: {
3552			y: to.height / original.height,
3553			x: to.width / original.width
3554		}
3555	};
3556
3557	// Scale the css box
3558	if ( scale === "box" || scale === "both" ) {
3559
3560		// Vertical props scaling
3561		if ( factor.from.y !== factor.to.y ) {
3562			from = $.effects.setTransition( element, vProps, factor.from.y, from );
3563			to = $.effects.setTransition( element, vProps, factor.to.y, to );
3564		}
3565
3566		// Horizontal props scaling
3567		if ( factor.from.x !== factor.to.x ) {
3568			from = $.effects.setTransition( element, hProps, factor.from.x, from );
3569			to = $.effects.setTransition( element, hProps, factor.to.x, to );
3570		}
3571	}
3572
3573	// Scale the content
3574	if ( scale === "content" || scale === "both" ) {
3575
3576		// Vertical props scaling
3577		if ( factor.from.y !== factor.to.y ) {
3578			from = $.effects.setTransition( element, cProps, factor.from.y, from );
3579			to = $.effects.setTransition( element, cProps, factor.to.y, to );
3580		}
3581	}
3582
3583	// Adjust the position properties based on the provided origin points
3584	if ( origin ) {
3585		baseline = $.effects.getBaseline( origin, original );
3586		from.top = ( original.outerHeight - from.outerHeight ) * baseline.y + pos.top;
3587		from.left = ( original.outerWidth - from.outerWidth ) * baseline.x + pos.left;
3588		to.top = ( original.outerHeight - to.outerHeight ) * baseline.y + pos.top;
3589		to.left = ( original.outerWidth - to.outerWidth ) * baseline.x + pos.left;
3590	}
3591	delete from.outerHeight;
3592	delete from.outerWidth;
3593	element.css( from );
3594
3595	// Animate the children if desired
3596	if ( scale === "content" || scale === "both" ) {
3597
3598		vProps = vProps.concat( [ "marginTop", "marginBottom" ] ).concat( cProps );
3599		hProps = hProps.concat( [ "marginLeft", "marginRight" ] );
3600
3601		// Only animate children with width attributes specified
3602		// TODO: is this right? should we include anything with css width specified as well
3603		element.find( "*[width]" ).each( function() {
3604			var child = $( this ),
3605				childOriginal = $.effects.scaledDimensions( child ),
3606				childFrom = {
3607					height: childOriginal.height * factor.from.y,
3608					width: childOriginal.width * factor.from.x,
3609					outerHeight: childOriginal.outerHeight * factor.from.y,
3610					outerWidth: childOriginal.outerWidth * factor.from.x
3611				},
3612				childTo = {
3613					height: childOriginal.height * factor.to.y,
3614					width: childOriginal.width * factor.to.x,
3615					outerHeight: childOriginal.height * factor.to.y,
3616					outerWidth: childOriginal.width * factor.to.x
3617				};
3618
3619			// Vertical props scaling
3620			if ( factor.from.y !== factor.to.y ) {
3621				childFrom = $.effects.setTransition( child, vProps, factor.from.y, childFrom );
3622				childTo = $.effects.setTransition( child, vProps, factor.to.y, childTo );
3623			}
3624
3625			// Horizontal props scaling
3626			if ( factor.from.x !== factor.to.x ) {
3627				childFrom = $.effects.setTransition( child, hProps, factor.from.x, childFrom );
3628				childTo = $.effects.setTransition( child, hProps, factor.to.x, childTo );
3629			}
3630
3631			if ( restore ) {
3632				$.effects.saveStyle( child );
3633			}
3634
3635			// Animate children
3636			child.css( childFrom );
3637			child.animate( childTo, options.duration, options.easing, function() {
3638
3639				// Restore children
3640				if ( restore ) {
3641					$.effects.restoreStyle( child );
3642				}
3643			} );
3644		} );
3645	}
3646
3647	// Animate
3648	element.animate( to, {
3649		queue: false,
3650		duration: options.duration,
3651		easing: options.easing,
3652		complete: function() {
3653
3654			var offset = element.offset();
3655
3656			if ( to.opacity === 0 ) {
3657				element.css( "opacity", from.opacity );
3658			}
3659
3660			if ( !restore ) {
3661				element
3662					.css( "position", position === "static" ? "relative" : position )
3663					.offset( offset );
3664
3665				// Need to save style here so that automatic style restoration
3666				// doesn't restore to the original styles from before the animation.
3667				$.effects.saveStyle( element );
3668			}
3669
3670			done();
3671		}
3672	} );
3673
3674} );
3675
3676
3677/*!
3678 * jQuery UI Effects Scale 1.13.3
3679 * https://jqueryui.com
3680 *
3681 * Copyright OpenJS Foundation and other contributors
3682 * Released under the MIT license.
3683 * https://jquery.org/license
3684 */
3685
3686//>>label: Scale Effect
3687//>>group: Effects
3688//>>description: Grows or shrinks an element and its content.
3689//>>docs: https://api.jqueryui.com/scale-effect/
3690//>>demos: https://jqueryui.com/effect/
3691
3692
3693var effectsEffectScale = $.effects.define( "scale", function( options, done ) {
3694
3695	// Create element
3696	var el = $( this ),
3697		mode = options.mode,
3698		percent = parseInt( options.percent, 10 ) ||
3699			( parseInt( options.percent, 10 ) === 0 ? 0 : ( mode !== "effect" ? 0 : 100 ) ),
3700
3701		newOptions = $.extend( true, {
3702			from: $.effects.scaledDimensions( el ),
3703			to: $.effects.scaledDimensions( el, percent, options.direction || "both" ),
3704			origin: options.origin || [ "middle", "center" ]
3705		}, options );
3706
3707	// Fade option to support puff
3708	if ( options.fade ) {
3709		newOptions.from.opacity = 1;
3710		newOptions.to.opacity = 0;
3711	}
3712
3713	$.effects.effect.size.call( this, newOptions, done );
3714} );
3715
3716
3717/*!
3718 * jQuery UI Effects Puff 1.13.3
3719 * https://jqueryui.com
3720 *
3721 * Copyright OpenJS Foundation and other contributors
3722 * Released under the MIT license.
3723 * https://jquery.org/license
3724 */
3725
3726//>>label: Puff Effect
3727//>>group: Effects
3728//>>description: Creates a puff effect by scaling the element up and hiding it at the same time.
3729//>>docs: https://api.jqueryui.com/puff-effect/
3730//>>demos: https://jqueryui.com/effect/
3731
3732
3733var effectsEffectPuff = $.effects.define( "puff", "hide", function( options, done ) {
3734	var newOptions = $.extend( true, {}, options, {
3735		fade: true,
3736		percent: parseInt( options.percent, 10 ) || 150
3737	} );
3738
3739	$.effects.effect.scale.call( this, newOptions, done );
3740} );
3741
3742
3743/*!
3744 * jQuery UI Effects Pulsate 1.13.3
3745 * https://jqueryui.com
3746 *
3747 * Copyright OpenJS Foundation and other contributors
3748 * Released under the MIT license.
3749 * https://jquery.org/license
3750 */
3751
3752//>>label: Pulsate Effect
3753//>>group: Effects
3754//>>description: Pulsates an element n times by changing the opacity to zero and back.
3755//>>docs: https://api.jqueryui.com/pulsate-effect/
3756//>>demos: https://jqueryui.com/effect/
3757
3758
3759var effectsEffectPulsate = $.effects.define( "pulsate", "show", function( options, done ) {
3760	var element = $( this ),
3761		mode = options.mode,
3762		show = mode === "show",
3763		hide = mode === "hide",
3764		showhide = show || hide,
3765
3766		// Showing or hiding leaves off the "last" animation
3767		anims = ( ( options.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ),
3768		duration = options.duration / anims,
3769		animateTo = 0,
3770		i = 1,
3771		queuelen = element.queue().length;
3772
3773	if ( show || !element.is( ":visible" ) ) {
3774		element.css( "opacity", 0 ).show();
3775		animateTo = 1;
3776	}
3777
3778	// Anims - 1 opacity "toggles"
3779	for ( ; i < anims; i++ ) {
3780		element.animate( { opacity: animateTo }, duration, options.easing );
3781		animateTo = 1 - animateTo;
3782	}
3783
3784	element.animate( { opacity: animateTo }, duration, options.easing );
3785
3786	element.queue( done );
3787
3788	$.effects.unshift( element, queuelen, anims + 1 );
3789} );
3790
3791
3792/*!
3793 * jQuery UI Effects Shake 1.13.3
3794 * https://jqueryui.com
3795 *
3796 * Copyright OpenJS Foundation and other contributors
3797 * Released under the MIT license.
3798 * https://jquery.org/license
3799 */
3800
3801//>>label: Shake Effect
3802//>>group: Effects
3803//>>description: Shakes an element horizontally or vertically n times.
3804//>>docs: https://api.jqueryui.com/shake-effect/
3805//>>demos: https://jqueryui.com/effect/
3806
3807
3808var effectsEffectShake = $.effects.define( "shake", function( options, done ) {
3809
3810	var i = 1,
3811		element = $( this ),
3812		direction = options.direction || "left",
3813		distance = options.distance || 20,
3814		times = options.times || 3,
3815		anims = times * 2 + 1,
3816		speed = Math.round( options.duration / anims ),
3817		ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
3818		positiveMotion = ( direction === "up" || direction === "left" ),
3819		animation = {},
3820		animation1 = {},
3821		animation2 = {},
3822
3823		queuelen = element.queue().length;
3824
3825	$.effects.createPlaceholder( element );
3826
3827	// Animation
3828	animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance;
3829	animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2;
3830	animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2;
3831
3832	// Animate
3833	element.animate( animation, speed, options.easing );
3834
3835	// Shakes
3836	for ( ; i < times; i++ ) {
3837		element
3838			.animate( animation1, speed, options.easing )
3839			.animate( animation2, speed, options.easing );
3840	}
3841
3842	element
3843		.animate( animation1, speed, options.easing )
3844		.animate( animation, speed / 2, options.easing )
3845		.queue( done );
3846
3847	$.effects.unshift( element, queuelen, anims + 1 );
3848} );
3849
3850
3851/*!
3852 * jQuery UI Effects Slide 1.13.3
3853 * https://jqueryui.com
3854 *
3855 * Copyright OpenJS Foundation and other contributors
3856 * Released under the MIT license.
3857 * https://jquery.org/license
3858 */
3859
3860//>>label: Slide Effect
3861//>>group: Effects
3862//>>description: Slides an element in and out of the viewport.
3863//>>docs: https://api.jqueryui.com/slide-effect/
3864//>>demos: https://jqueryui.com/effect/
3865
3866
3867var effectsEffectSlide = $.effects.define( "slide", "show", function( options, done ) {
3868	var startClip, startRef,
3869		element = $( this ),
3870		map = {
3871			up: [ "bottom", "top" ],
3872			down: [ "top", "bottom" ],
3873			left: [ "right", "left" ],
3874			right: [ "left", "right" ]
3875		},
3876		mode = options.mode,
3877		direction = options.direction || "left",
3878		ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
3879		positiveMotion = ( direction === "up" || direction === "left" ),
3880		distance = options.distance ||
3881			element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ),
3882		animation = {};
3883
3884	$.effects.createPlaceholder( element );
3885
3886	startClip = element.cssClip();
3887	startRef = element.position()[ ref ];
3888
3889	// Define hide animation
3890	animation[ ref ] = ( positiveMotion ? -1 : 1 ) * distance + startRef;
3891	animation.clip = element.cssClip();
3892	animation.clip[ map[ direction ][ 1 ] ] = animation.clip[ map[ direction ][ 0 ] ];
3893
3894	// Reverse the animation if we're showing
3895	if ( mode === "show" ) {
3896		element.cssClip( animation.clip );
3897		element.css( ref, animation[ ref ] );
3898		animation.clip = startClip;
3899		animation[ ref ] = startRef;
3900	}
3901
3902	// Actually animate
3903	element.animate( animation, {
3904		queue: false,
3905		duration: options.duration,
3906		easing: options.easing,
3907		complete: done
3908	} );
3909} );
3910
3911
3912/*!
3913 * jQuery UI Effects Transfer 1.13.3
3914 * https://jqueryui.com
3915 *
3916 * Copyright OpenJS Foundation and other contributors
3917 * Released under the MIT license.
3918 * https://jquery.org/license
3919 */
3920
3921//>>label: Transfer Effect
3922//>>group: Effects
3923//>>description: Displays a transfer effect from one element to another.
3924//>>docs: https://api.jqueryui.com/transfer-effect/
3925//>>demos: https://jqueryui.com/effect/
3926
3927
3928var effect;
3929if ( $.uiBackCompat !== false ) {
3930	effect = $.effects.define( "transfer", function( options, done ) {
3931		$( this ).transfer( options, done );
3932	} );
3933}
3934var effectsEffectTransfer = effect;
3935
3936
3937/*!
3938 * jQuery UI Focusable 1.13.3
3939 * https://jqueryui.com
3940 *
3941 * Copyright OpenJS Foundation and other contributors
3942 * Released under the MIT license.
3943 * https://jquery.org/license
3944 */
3945
3946//>>label: :focusable Selector
3947//>>group: Core
3948//>>description: Selects elements which can be focused.
3949//>>docs: https://api.jqueryui.com/focusable-selector/
3950
3951
3952// Selectors
3953$.ui.focusable = function( element, hasTabindex ) {
3954	var map, mapName, img, focusableIfVisible, fieldset,
3955		nodeName = element.nodeName.toLowerCase();
3956
3957	if ( "area" === nodeName ) {
3958		map = element.parentNode;
3959		mapName = map.name;
3960		if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
3961			return false;
3962		}
3963		img = $( "img[usemap='#" + mapName + "']" );
3964		return img.length > 0 && img.is( ":visible" );
3965	}
3966
3967	if ( /^(input|select|textarea|button|object)$/.test( nodeName ) ) {
3968		focusableIfVisible = !element.disabled;
3969
3970		if ( focusableIfVisible ) {
3971
3972			// Form controls within a disabled fieldset are disabled.
3973			// However, controls within the fieldset's legend do not get disabled.
3974			// Since controls generally aren't placed inside legends, we skip
3975			// this portion of the check.
3976			fieldset = $( element ).closest( "fieldset" )[ 0 ];
3977			if ( fieldset ) {
3978				focusableIfVisible = !fieldset.disabled;
3979			}
3980		}
3981	} else if ( "a" === nodeName ) {
3982		focusableIfVisible = element.href || hasTabindex;
3983	} else {
3984		focusableIfVisible = hasTabindex;
3985	}
3986
3987	return focusableIfVisible && $( element ).is( ":visible" ) && visible( $( element ) );
3988};
3989
3990// Support: IE 8 only
3991// IE 8 doesn't resolve inherit to visible/hidden for computed values
3992function visible( element ) {
3993	var visibility = element.css( "visibility" );
3994	while ( visibility === "inherit" ) {
3995		element = element.parent();
3996		visibility = element.css( "visibility" );
3997	}
3998	return visibility === "visible";
3999}
4000
4001$.extend( $.expr.pseudos, {
4002	focusable: function( element ) {
4003		return $.ui.focusable( element, $.attr( element, "tabindex" ) != null );
4004	}
4005} );
4006
4007var focusable = $.ui.focusable;
4008
4009
4010
4011// Support: IE8 Only
4012// IE8 does not support the form attribute and when it is supplied. It overwrites the form prop
4013// with a string, so we need to find the proper form.
4014var form = $.fn._form = function() {
4015	return typeof this[ 0 ].form === "string" ? this.closest( "form" ) : $( this[ 0 ].form );
4016};
4017
4018
4019/*!
4020 * jQuery UI Form Reset Mixin 1.13.3
4021 * https://jqueryui.com
4022 *
4023 * Copyright OpenJS Foundation and other contributors
4024 * Released under the MIT license.
4025 * https://jquery.org/license
4026 */
4027
4028//>>label: Form Reset Mixin
4029//>>group: Core
4030//>>description: Refresh input widgets when their form is reset
4031//>>docs: https://api.jqueryui.com/form-reset-mixin/
4032
4033
4034var formResetMixin = $.ui.formResetMixin = {
4035	_formResetHandler: function() {
4036		var form = $( this );
4037
4038		// Wait for the form reset to actually happen before refreshing
4039		setTimeout( function() {
4040			var instances = form.data( "ui-form-reset-instances" );
4041			$.each( instances, function() {
4042				this.refresh();
4043			} );
4044		} );
4045	},
4046
4047	_bindFormResetHandler: function() {
4048		this.form = this.element._form();
4049		if ( !this.form.length ) {
4050			return;
4051		}
4052
4053		var instances = this.form.data( "ui-form-reset-instances" ) || [];
4054		if ( !instances.length ) {
4055
4056			// We don't use _on() here because we use a single event handler per form
4057			this.form.on( "reset.ui-form-reset", this._formResetHandler );
4058		}
4059		instances.push( this );
4060		this.form.data( "ui-form-reset-instances", instances );
4061	},
4062
4063	_unbindFormResetHandler: function() {
4064		if ( !this.form.length ) {
4065			return;
4066		}
4067
4068		var instances = this.form.data( "ui-form-reset-instances" );
4069		instances.splice( $.inArray( this, instances ), 1 );
4070		if ( instances.length ) {
4071			this.form.data( "ui-form-reset-instances", instances );
4072		} else {
4073			this.form
4074				.removeData( "ui-form-reset-instances" )
4075				.off( "reset.ui-form-reset" );
4076		}
4077	}
4078};
4079
4080
4081/*!
4082 * jQuery UI Support for jQuery core 1.8.x and newer 1.13.3
4083 * https://jqueryui.com
4084 *
4085 * Copyright OpenJS Foundation and other contributors
4086 * Released under the MIT license.
4087 * https://jquery.org/license
4088 *
4089 */
4090
4091//>>label: jQuery 1.8+ Support
4092//>>group: Core
4093//>>description: Support version 1.8.x and newer of jQuery core
4094
4095
4096// Support: jQuery 1.9.x or older
4097// $.expr[ ":" ] is deprecated.
4098if ( !$.expr.pseudos ) {
4099	$.expr.pseudos = $.expr[ ":" ];
4100}
4101
4102// Support: jQuery 1.11.x or older
4103// $.unique has been renamed to $.uniqueSort
4104if ( !$.uniqueSort ) {
4105	$.uniqueSort = $.unique;
4106}
4107
4108// Support: jQuery 2.2.x or older.
4109// This method has been defined in jQuery 3.0.0.
4110// Code from https://github.com/jquery/jquery/blob/e539bac79e666bba95bba86d690b4e609dca2286/src/selector/escapeSelector.js
4111if ( !$.escapeSelector ) {
4112
4113	// CSS string/identifier serialization
4114	// https://drafts.csswg.org/cssom/#common-serializing-idioms
4115	var rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g;
4116
4117	var fcssescape = function( ch, asCodePoint ) {
4118		if ( asCodePoint ) {
4119
4120			// U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER
4121			if ( ch === "\0" ) {
4122				return "\uFFFD";
4123			}
4124
4125			// Control characters and (dependent upon position) numbers get escaped as code points
4126			return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " ";
4127		}
4128
4129		// Other potentially-special ASCII characters get backslash-escaped
4130		return "\\" + ch;
4131	};
4132
4133	$.escapeSelector = function( sel ) {
4134		return ( sel + "" ).replace( rcssescape, fcssescape );
4135	};
4136}
4137
4138// Support: jQuery 3.4.x or older
4139// These methods have been defined in jQuery 3.5.0.
4140if ( !$.fn.even || !$.fn.odd ) {
4141	$.fn.extend( {
4142		even: function() {
4143			return this.filter( function( i ) {
4144				return i % 2 === 0;
4145			} );
4146		},
4147		odd: function() {
4148			return this.filter( function( i ) {
4149				return i % 2 === 1;
4150			} );
4151		}
4152	} );
4153}
4154
4155;
4156/*!
4157 * jQuery UI Keycode 1.13.3
4158 * https://jqueryui.com
4159 *
4160 * Copyright OpenJS Foundation and other contributors
4161 * Released under the MIT license.
4162 * https://jquery.org/license
4163 */
4164
4165//>>label: Keycode
4166//>>group: Core
4167//>>description: Provide keycodes as keynames
4168//>>docs: https://api.jqueryui.com/jQuery.ui.keyCode/
4169
4170
4171var keycode = $.ui.keyCode = {
4172	BACKSPACE: 8,
4173	COMMA: 188,
4174	DELETE: 46,
4175	DOWN: 40,
4176	END: 35,
4177	ENTER: 13,
4178	ESCAPE: 27,
4179	HOME: 36,
4180	LEFT: 37,
4181	PAGE_DOWN: 34,
4182	PAGE_UP: 33,
4183	PERIOD: 190,
4184	RIGHT: 39,
4185	SPACE: 32,
4186	TAB: 9,
4187	UP: 38
4188};
4189
4190
4191/*!
4192 * jQuery UI Labels 1.13.3
4193 * https://jqueryui.com
4194 *
4195 * Copyright OpenJS Foundation and other contributors
4196 * Released under the MIT license.
4197 * https://jquery.org/license
4198 */
4199
4200//>>label: labels
4201//>>group: Core
4202//>>description: Find all the labels associated with a given input
4203//>>docs: https://api.jqueryui.com/labels/
4204
4205
4206var labels = $.fn.labels = function() {
4207	var ancestor, selector, id, labels, ancestors;
4208
4209	if ( !this.length ) {
4210		return this.pushStack( [] );
4211	}
4212
4213	// Check control.labels first
4214	if ( this[ 0 ].labels && this[ 0 ].labels.length ) {
4215		return this.pushStack( this[ 0 ].labels );
4216	}
4217
4218	// Support: IE <= 11, FF <= 37, Android <= 2.3 only
4219	// Above browsers do not support control.labels. Everything below is to support them
4220	// as well as document fragments. control.labels does not work on document fragments
4221	labels = this.eq( 0 ).parents( "label" );
4222
4223	// Look for the label based on the id
4224	id = this.attr( "id" );
4225	if ( id ) {
4226
4227		// We don't search against the document in case the element
4228		// is disconnected from the DOM
4229		ancestor = this.eq( 0 ).parents().last();
4230
4231		// Get a full set of top level ancestors
4232		ancestors = ancestor.add( ancestor.length ? ancestor.siblings() : this.siblings() );
4233
4234		// Create a selector for the label based on the id
4235		selector = "label[for='" + $.escapeSelector( id ) + "']";
4236
4237		labels = labels.add( ancestors.find( selector ).addBack( selector ) );
4238
4239	}
4240
4241	// Return whatever we have found for labels
4242	return this.pushStack( labels );
4243};
4244
4245
4246/*!
4247 * jQuery UI Scroll Parent 1.13.3
4248 * https://jqueryui.com
4249 *
4250 * Copyright OpenJS Foundation and other contributors
4251 * Released under the MIT license.
4252 * https://jquery.org/license
4253 */
4254
4255//>>label: scrollParent
4256//>>group: Core
4257//>>description: Get the closest ancestor element that is scrollable.
4258//>>docs: https://api.jqueryui.com/scrollParent/
4259
4260
4261var scrollParent = $.fn.scrollParent = function( includeHidden ) {
4262	var position = this.css( "position" ),
4263		excludeStaticParent = position === "absolute",
4264		overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/,
4265		scrollParent = this.parents().filter( function() {
4266			var parent = $( this );
4267			if ( excludeStaticParent && parent.css( "position" ) === "static" ) {
4268				return false;
4269			}
4270			return overflowRegex.test( parent.css( "overflow" ) + parent.css( "overflow-y" ) +
4271				parent.css( "overflow-x" ) );
4272		} ).eq( 0 );
4273
4274	return position === "fixed" || !scrollParent.length ?
4275		$( this[ 0 ].ownerDocument || document ) :
4276		scrollParent;
4277};
4278
4279
4280/*!
4281 * jQuery UI Tabbable 1.13.3
4282 * https://jqueryui.com
4283 *
4284 * Copyright OpenJS Foundation and other contributors
4285 * Released under the MIT license.
4286 * https://jquery.org/license
4287 */
4288
4289//>>label: :tabbable Selector
4290//>>group: Core
4291//>>description: Selects elements which can be tabbed to.
4292//>>docs: https://api.jqueryui.com/tabbable-selector/
4293
4294
4295var tabbable = $.extend( $.expr.pseudos, {
4296	tabbable: function( element ) {
4297		var tabIndex = $.attr( element, "tabindex" ),
4298			hasTabindex = tabIndex != null;
4299		return ( !hasTabindex || tabIndex >= 0 ) && $.ui.focusable( element, hasTabindex );
4300	}
4301} );
4302
4303
4304/*!
4305 * jQuery UI Unique ID 1.13.3
4306 * https://jqueryui.com
4307 *
4308 * Copyright OpenJS Foundation and other contributors
4309 * Released under the MIT license.
4310 * https://jquery.org/license
4311 */
4312
4313//>>label: uniqueId
4314//>>group: Core
4315//>>description: Functions to generate and remove uniqueId's
4316//>>docs: https://api.jqueryui.com/uniqueId/
4317
4318
4319var uniqueId = $.fn.extend( {
4320	uniqueId: ( function() {
4321		var uuid = 0;
4322
4323		return function() {
4324			return this.each( function() {
4325				if ( !this.id ) {
4326					this.id = "ui-id-" + ( ++uuid );
4327				}
4328			} );
4329		};
4330	} )(),
4331
4332	removeUniqueId: function() {
4333		return this.each( function() {
4334			if ( /^ui-id-\d+$/.test( this.id ) ) {
4335				$( this ).removeAttr( "id" );
4336			}
4337		} );
4338	}
4339} );
4340
4341
4342/*!
4343 * jQuery UI Accordion 1.13.3
4344 * https://jqueryui.com
4345 *
4346 * Copyright OpenJS Foundation and other contributors
4347 * Released under the MIT license.
4348 * https://jquery.org/license
4349 */
4350
4351//>>label: Accordion
4352//>>group: Widgets
4353/* eslint-disable max-len */
4354//>>description: Displays collapsible content panels for presenting information in a limited amount of space.
4355/* eslint-enable max-len */
4356//>>docs: https://api.jqueryui.com/accordion/
4357//>>demos: https://jqueryui.com/accordion/
4358//>>css.structure: ../../themes/base/core.css
4359//>>css.structure: ../../themes/base/accordion.css
4360//>>css.theme: ../../themes/base/theme.css
4361
4362
4363var widgetsAccordion = $.widget( "ui.accordion", {
4364	version: "1.13.3",
4365	options: {
4366		active: 0,
4367		animate: {},
4368		classes: {
4369			"ui-accordion-header": "ui-corner-top",
4370			"ui-accordion-header-collapsed": "ui-corner-all",
4371			"ui-accordion-content": "ui-corner-bottom"
4372		},
4373		collapsible: false,
4374		event: "click",
4375		header: function( elem ) {
4376			return elem.find( "> li > :first-child" ).add( elem.find( "> :not(li)" ).even() );
4377		},
4378		heightStyle: "auto",
4379		icons: {
4380			activeHeader: "ui-icon-triangle-1-s",
4381			header: "ui-icon-triangle-1-e"
4382		},
4383
4384		// Callbacks
4385		activate: null,
4386		beforeActivate: null
4387	},
4388
4389	hideProps: {
4390		borderTopWidth: "hide",
4391		borderBottomWidth: "hide",
4392		paddingTop: "hide",
4393		paddingBottom: "hide",
4394		height: "hide"
4395	},
4396
4397	showProps: {
4398		borderTopWidth: "show",
4399		borderBottomWidth: "show",
4400		paddingTop: "show",
4401		paddingBottom: "show",
4402		height: "show"
4403	},
4404
4405	_create: function() {
4406		var options = this.options;
4407
4408		this.prevShow = this.prevHide = $();
4409		this._addClass( "ui-accordion", "ui-widget ui-helper-reset" );
4410		this.element.attr( "role", "tablist" );
4411
4412		// Don't allow collapsible: false and active: false / null
4413		if ( !options.collapsible && ( options.active === false || options.active == null ) ) {
4414			options.active = 0;
4415		}
4416
4417		this._processPanels();
4418
4419		// handle negative values
4420		if ( options.active < 0 ) {
4421			options.active += this.headers.length;
4422		}
4423		this._refresh();
4424	},
4425
4426	_getCreateEventData: function() {
4427		return {
4428			header: this.active,
4429			panel: !this.active.length ? $() : this.active.next()
4430		};
4431	},
4432
4433	_createIcons: function() {
4434		var icon, children,
4435			icons = this.options.icons;
4436
4437		if ( icons ) {
4438			icon = $( "<span>" );
4439			this._addClass( icon, "ui-accordion-header-icon", "ui-icon " + icons.header );
4440			icon.prependTo( this.headers );
4441			children = this.active.children( ".ui-accordion-header-icon" );
4442			this._removeClass( children, icons.header )
4443				._addClass( children, null, icons.activeHeader )
4444				._addClass( this.headers, "ui-accordion-icons" );
4445		}
4446	},
4447
4448	_destroyIcons: function() {
4449		this._removeClass( this.headers, "ui-accordion-icons" );
4450		this.headers.children( ".ui-accordion-header-icon" ).remove();
4451	},
4452
4453	_destroy: function() {
4454		var contents;
4455
4456		// Clean up main element
4457		this.element.removeAttr( "role" );
4458
4459		// Clean up headers
4460		this.headers
4461			.removeAttr( "role aria-expanded aria-selected aria-controls tabIndex" )
4462			.removeUniqueId();
4463
4464		this._destroyIcons();
4465
4466		// Clean up content panels
4467		contents = this.headers.next()
4468			.css( "display", "" )
4469			.removeAttr( "role aria-hidden aria-labelledby" )
4470			.removeUniqueId();
4471
4472		if ( this.options.heightStyle !== "content" ) {
4473			contents.css( "height", "" );
4474		}
4475	},
4476
4477	_setOption: function( key, value ) {
4478		if ( key === "active" ) {
4479
4480			// _activate() will handle invalid values and update this.options
4481			this._activate( value );
4482			return;
4483		}
4484
4485		if ( key === "event" ) {
4486			if ( this.options.event ) {
4487				this._off( this.headers, this.options.event );
4488			}
4489			this._setupEvents( value );
4490		}
4491
4492		this._super( key, value );
4493
4494		// Setting collapsible: false while collapsed; open first panel
4495		if ( key === "collapsible" && !value && this.options.active === false ) {
4496			this._activate( 0 );
4497		}
4498
4499		if ( key === "icons" ) {
4500			this._destroyIcons();
4501			if ( value ) {
4502				this._createIcons();
4503			}
4504		}
4505	},
4506
4507	_setOptionDisabled: function( value ) {
4508		this._super( value );
4509
4510		this.element.attr( "aria-disabled", value );
4511
4512		// Support: IE8 Only
4513		// #5332 / #6059 - opacity doesn't cascade to positioned elements in IE
4514		// so we need to add the disabled class to the headers and panels
4515		this._toggleClass( null, "ui-state-disabled", !!value );
4516		this._toggleClass( this.headers.add( this.headers.next() ), null, "ui-state-disabled",
4517			!!value );
4518	},
4519
4520	_keydown: function( event ) {
4521		if ( event.altKey || event.ctrlKey ) {
4522			return;
4523		}
4524
4525		var keyCode = $.ui.keyCode,
4526			length = this.headers.length,
4527			currentIndex = this.headers.index( event.target ),
4528			toFocus = false;
4529
4530		switch ( event.keyCode ) {
4531		case keyCode.RIGHT:
4532		case keyCode.DOWN:
4533			toFocus = this.headers[ ( currentIndex + 1 ) % length ];
4534			break;
4535		case keyCode.LEFT:
4536		case keyCode.UP:
4537			toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
4538			break;
4539		case keyCode.SPACE:
4540		case keyCode.ENTER:
4541			this._eventHandler( event );
4542			break;
4543		case keyCode.HOME:
4544			toFocus = this.headers[ 0 ];
4545			break;
4546		case keyCode.END:
4547			toFocus = this.headers[ length - 1 ];
4548			break;
4549		}
4550
4551		if ( toFocus ) {
4552			$( event.target ).attr( "tabIndex", -1 );
4553			$( toFocus ).attr( "tabIndex", 0 );
4554			$( toFocus ).trigger( "focus" );
4555			event.preventDefault();
4556		}
4557	},
4558
4559	_panelKeyDown: function( event ) {
4560		if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) {
4561			$( event.currentTarget ).prev().trigger( "focus" );
4562		}
4563	},
4564
4565	refresh: function() {
4566		var options = this.options;
4567		this._processPanels();
4568
4569		// Was collapsed or no panel
4570		if ( ( options.active === false && options.collapsible === true ) ||
4571				!this.headers.length ) {
4572			options.active = false;
4573			this.active = $();
4574
4575		// active false only when collapsible is true
4576		} else if ( options.active === false ) {
4577			this._activate( 0 );
4578
4579		// was active, but active panel is gone
4580		} else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
4581
4582			// all remaining panel are disabled
4583			if ( this.headers.length === this.headers.find( ".ui-state-disabled" ).length ) {
4584				options.active = false;
4585				this.active = $();
4586
4587			// activate previous panel
4588			} else {
4589				this._activate( Math.max( 0, options.active - 1 ) );
4590			}
4591
4592		// was active, active panel still exists
4593		} else {
4594
4595			// make sure active index is correct
4596			options.active = this.headers.index( this.active );
4597		}
4598
4599		this._destroyIcons();
4600
4601		this._refresh();
4602	},
4603
4604	_processPanels: function() {
4605		var prevHeaders = this.headers,
4606			prevPanels = this.panels;
4607
4608		if ( typeof this.options.header === "function" ) {
4609			this.headers = this.options.header( this.element );
4610		} else {
4611			this.headers = this.element.find( this.options.header );
4612		}
4613		this._addClass( this.headers, "ui-accordion-header ui-accordion-header-collapsed",
4614			"ui-state-default" );
4615
4616		this.panels = this.headers.next().filter( ":not(.ui-accordion-content-active)" ).hide();
4617		this._addClass( this.panels, "ui-accordion-content", "ui-helper-reset ui-widget-content" );
4618
4619		// Avoid memory leaks (#10056)
4620		if ( prevPanels ) {
4621			this._off( prevHeaders.not( this.headers ) );
4622			this._off( prevPanels.not( this.panels ) );
4623		}
4624	},
4625
4626	_refresh: function() {
4627		var maxHeight,
4628			options = this.options,
4629			heightStyle = options.heightStyle,
4630			parent = this.element.parent();
4631
4632		this.active = this._findActive( options.active );
4633		this._addClass( this.active, "ui-accordion-header-active", "ui-state-active" )
4634			._removeClass( this.active, "ui-accordion-header-collapsed" );
4635		this._addClass( this.active.next(), "ui-accordion-content-active" );
4636		this.active.next().show();
4637
4638		this.headers
4639			.attr( "role", "tab" )
4640			.each( function() {
4641				var header = $( this ),
4642					headerId = header.uniqueId().attr( "id" ),
4643					panel = header.next(),
4644					panelId = panel.uniqueId().attr( "id" );
4645				header.attr( "aria-controls", panelId );
4646				panel.attr( "aria-labelledby", headerId );
4647			} )
4648			.next()
4649				.attr( "role", "tabpanel" );
4650
4651		this.headers
4652			.not( this.active )
4653				.attr( {
4654					"aria-selected": "false",
4655					"aria-expanded": "false",
4656					tabIndex: -1
4657				} )
4658				.next()
4659					.attr( {
4660						"aria-hidden": "true"
4661					} )
4662					.hide();
4663
4664		// Make sure at least one header is in the tab order
4665		if ( !this.active.length ) {
4666			this.headers.eq( 0 ).attr( "tabIndex", 0 );
4667		} else {
4668			this.active.attr( {
4669				"aria-selected": "true",
4670				"aria-expanded": "true",
4671				tabIndex: 0
4672			} )
4673				.next()
4674					.attr( {
4675						"aria-hidden": "false"
4676					} );
4677		}
4678
4679		this._createIcons();
4680
4681		this._setupEvents( options.event );
4682
4683		if ( heightStyle === "fill" ) {
4684			maxHeight = parent.height();
4685			this.element.siblings( ":visible" ).each( function() {
4686				var elem = $( this ),
4687					position = elem.css( "position" );
4688
4689				if ( position === "absolute" || position === "fixed" ) {
4690					return;
4691				}
4692				maxHeight -= elem.outerHeight( true );
4693			} );
4694
4695			this.headers.each( function() {
4696				maxHeight -= $( this ).outerHeight( true );
4697			} );
4698
4699			this.headers.next()
4700				.each( function() {
4701					$( this ).height( Math.max( 0, maxHeight -
4702						$( this ).innerHeight() + $( this ).height() ) );
4703				} )
4704				.css( "overflow", "auto" );
4705		} else if ( heightStyle === "auto" ) {
4706			maxHeight = 0;
4707			this.headers.next()
4708				.each( function() {
4709					var isVisible = $( this ).is( ":visible" );
4710					if ( !isVisible ) {
4711						$( this ).show();
4712					}
4713					maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() );
4714					if ( !isVisible ) {
4715						$( this ).hide();
4716					}
4717				} )
4718				.height( maxHeight );
4719		}
4720	},
4721
4722	_activate: function( index ) {
4723		var active = this._findActive( index )[ 0 ];
4724
4725		// Trying to activate the already active panel
4726		if ( active === this.active[ 0 ] ) {
4727			return;
4728		}
4729
4730		// Trying to collapse, simulate a click on the currently active header
4731		active = active || this.active[ 0 ];
4732
4733		this._eventHandler( {
4734			target: active,
4735			currentTarget: active,
4736			preventDefault: $.noop
4737		} );
4738	},
4739
4740	_findActive: function( selector ) {
4741		return typeof selector === "number" ? this.headers.eq( selector ) : $();
4742	},
4743
4744	_setupEvents: function( event ) {
4745		var events = {
4746			keydown: "_keydown"
4747		};
4748		if ( event ) {
4749			$.each( event.split( " " ), function( index, eventName ) {
4750				events[ eventName ] = "_eventHandler";
4751			} );
4752		}
4753
4754		this._off( this.headers.add( this.headers.next() ) );
4755		this._on( this.headers, events );
4756		this._on( this.headers.next(), { keydown: "_panelKeyDown" } );
4757		this._hoverable( this.headers );
4758		this._focusable( this.headers );
4759	},
4760
4761	_eventHandler: function( event ) {
4762		var activeChildren, clickedChildren,
4763			options = this.options,
4764			active = this.active,
4765			clicked = $( event.currentTarget ),
4766			clickedIsActive = clicked[ 0 ] === active[ 0 ],
4767			collapsing = clickedIsActive && options.collapsible,
4768			toShow = collapsing ? $() : clicked.next(),
4769			toHide = active.next(),
4770			eventData = {
4771				oldHeader: active,
4772				oldPanel: toHide,
4773				newHeader: collapsing ? $() : clicked,
4774				newPanel: toShow
4775			};
4776
4777		event.preventDefault();
4778
4779		if (
4780
4781				// click on active header, but not collapsible
4782				( clickedIsActive && !options.collapsible ) ||
4783
4784				// allow canceling activation
4785				( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
4786			return;
4787		}
4788
4789		options.active = collapsing ? false : this.headers.index( clicked );
4790
4791		// When the call to ._toggle() comes after the class changes
4792		// it causes a very odd bug in IE 8 (see #6720)
4793		this.active = clickedIsActive ? $() : clicked;
4794		this._toggle( eventData );
4795
4796		// Switch classes
4797		// corner classes on the previously active header stay after the animation
4798		this._removeClass( active, "ui-accordion-header-active", "ui-state-active" );
4799		if ( options.icons ) {
4800			activeChildren = active.children( ".ui-accordion-header-icon" );
4801			this._removeClass( activeChildren, null, options.icons.activeHeader )
4802				._addClass( activeChildren, null, options.icons.header );
4803		}
4804
4805		if ( !clickedIsActive ) {
4806			this._removeClass( clicked, "ui-accordion-header-collapsed" )
4807				._addClass( clicked, "ui-accordion-header-active", "ui-state-active" );
4808			if ( options.icons ) {
4809				clickedChildren = clicked.children( ".ui-accordion-header-icon" );
4810				this._removeClass( clickedChildren, null, options.icons.header )
4811					._addClass( clickedChildren, null, options.icons.activeHeader );
4812			}
4813
4814			this._addClass( clicked.next(), "ui-accordion-content-active" );
4815		}
4816	},
4817
4818	_toggle: function( data ) {
4819		var toShow = data.newPanel,
4820			toHide = this.prevShow.length ? this.prevShow : data.oldPanel;
4821
4822		// Handle activating a panel during the animation for another activation
4823		this.prevShow.add( this.prevHide ).stop( true, true );
4824		this.prevShow = toShow;
4825		this.prevHide = toHide;
4826
4827		if ( this.options.animate ) {
4828			this._animate( toShow, toHide, data );
4829		} else {
4830			toHide.hide();
4831			toShow.show();
4832			this._toggleComplete( data );
4833		}
4834
4835		toHide.attr( {
4836			"aria-hidden": "true"
4837		} );
4838		toHide.prev().attr( {
4839			"aria-selected": "false",
4840			"aria-expanded": "false"
4841		} );
4842
4843		// if we're switching panels, remove the old header from the tab order
4844		// if we're opening from collapsed state, remove the previous header from the tab order
4845		// if we're collapsing, then keep the collapsing header in the tab order
4846		if ( toShow.length && toHide.length ) {
4847			toHide.prev().attr( {
4848				"tabIndex": -1,
4849				"aria-expanded": "false"
4850			} );
4851		} else if ( toShow.length ) {
4852			this.headers.filter( function() {
4853				return parseInt( $( this ).attr( "tabIndex" ), 10 ) === 0;
4854			} )
4855				.attr( "tabIndex", -1 );
4856		}
4857
4858		toShow
4859			.attr( "aria-hidden", "false" )
4860			.prev()
4861				.attr( {
4862					"aria-selected": "true",
4863					"aria-expanded": "true",
4864					tabIndex: 0
4865				} );
4866	},
4867
4868	_animate: function( toShow, toHide, data ) {
4869		var total, easing, duration,
4870			that = this,
4871			adjust = 0,
4872			boxSizing = toShow.css( "box-sizing" ),
4873			down = toShow.length &&
4874				( !toHide.length || ( toShow.index() < toHide.index() ) ),
4875			animate = this.options.animate || {},
4876			options = down && animate.down || animate,
4877			complete = function() {
4878				that._toggleComplete( data );
4879			};
4880
4881		if ( typeof options === "number" ) {
4882			duration = options;
4883		}
4884		if ( typeof options === "string" ) {
4885			easing = options;
4886		}
4887
4888		// fall back from options to animation in case of partial down settings
4889		easing = easing || options.easing || animate.easing;
4890		duration = duration || options.duration || animate.duration;
4891
4892		if ( !toHide.length ) {
4893			return toShow.animate( this.showProps, duration, easing, complete );
4894		}
4895		if ( !toShow.length ) {
4896			return toHide.animate( this.hideProps, duration, easing, complete );
4897		}
4898
4899		total = toShow.show().outerHeight();
4900		toHide.animate( this.hideProps, {
4901			duration: duration,
4902			easing: easing,
4903			step: function( now, fx ) {
4904				fx.now = Math.round( now );
4905			}
4906		} );
4907		toShow
4908			.hide()
4909			.animate( this.showProps, {
4910				duration: duration,
4911				easing: easing,
4912				complete: complete,
4913				step: function( now, fx ) {
4914					fx.now = Math.round( now );
4915					if ( fx.prop !== "height" ) {
4916						if ( boxSizing === "content-box" ) {
4917							adjust += fx.now;
4918						}
4919					} else if ( that.options.heightStyle !== "content" ) {
4920						fx.now = Math.round( total - toHide.outerHeight() - adjust );
4921						adjust = 0;
4922					}
4923				}
4924			} );
4925	},
4926
4927	_toggleComplete: function( data ) {
4928		var toHide = data.oldPanel,
4929			prev = toHide.prev();
4930
4931		this._removeClass( toHide, "ui-accordion-content-active" );
4932		this._removeClass( prev, "ui-accordion-header-active" )
4933			._addClass( prev, "ui-accordion-header-collapsed" );
4934
4935		// Work around for rendering bug in IE (#5421)
4936		if ( toHide.length ) {
4937			toHide.parent()[ 0 ].className = toHide.parent()[ 0 ].className;
4938		}
4939		this._trigger( "activate", null, data );
4940	}
4941} );
4942
4943
4944
4945var safeActiveElement = $.ui.safeActiveElement = function( document ) {
4946	var activeElement;
4947
4948	// Support: IE 9 only
4949	// IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe>
4950	try {
4951		activeElement = document.activeElement;
4952	} catch ( error ) {
4953		activeElement = document.body;
4954	}
4955
4956	// Support: IE 9 - 11 only
4957	// IE may return null instead of an element
4958	// Interestingly, this only seems to occur when NOT in an iframe
4959	if ( !activeElement ) {
4960		activeElement = document.body;
4961	}
4962
4963	// Support: IE 11 only
4964	// IE11 returns a seemingly empty object in some cases when accessing
4965	// document.activeElement from an <iframe>
4966	if ( !activeElement.nodeName ) {
4967		activeElement = document.body;
4968	}
4969
4970	return activeElement;
4971};
4972
4973
4974/*!
4975 * jQuery UI Menu 1.13.3
4976 * https://jqueryui.com
4977 *
4978 * Copyright OpenJS Foundation and other contributors
4979 * Released under the MIT license.
4980 * https://jquery.org/license
4981 */
4982
4983//>>label: Menu
4984//>>group: Widgets
4985//>>description: Creates nestable menus.
4986//>>docs: https://api.jqueryui.com/menu/
4987//>>demos: https://jqueryui.com/menu/
4988//>>css.structure: ../../themes/base/core.css
4989//>>css.structure: ../../themes/base/menu.css
4990//>>css.theme: ../../themes/base/theme.css
4991
4992
4993var widgetsMenu = $.widget( "ui.menu", {
4994	version: "1.13.3",
4995	defaultElement: "<ul>",
4996	delay: 300,
4997	options: {
4998		icons: {
4999			submenu: "ui-icon-caret-1-e"
5000		},
5001		items: "> *",
5002		menus: "ul",
5003		position: {
5004			my: "left top",
5005			at: "right top"
5006		},
5007		role: "menu",
5008
5009		// Callbacks
5010		blur: null,
5011		focus: null,
5012		select: null
5013	},
5014
5015	_create: function() {
5016		this.activeMenu = this.element;
5017
5018		// Flag used to prevent firing of the click handler
5019		// as the event bubbles up through nested menus
5020		this.mouseHandled = false;
5021		this.lastMousePosition = { x: null, y: null };
5022		this.element
5023			.uniqueId()
5024			.attr( {
5025				role: this.options.role,
5026				tabIndex: 0
5027			} );
5028
5029		this._addClass( "ui-menu", "ui-widget ui-widget-content" );
5030		this._on( {
5031
5032			// Prevent focus from sticking to links inside menu after clicking
5033			// them (focus should always stay on UL during navigation).
5034			"mousedown .ui-menu-item": function( event ) {
5035				event.preventDefault();
5036
5037				this._activateItem( event );
5038			},
5039			"click .ui-menu-item": function( event ) {
5040				var target = $( event.target );
5041				var active = $( $.ui.safeActiveElement( this.document[ 0 ] ) );
5042				if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) {
5043					this.select( event );
5044
5045					// Only set the mouseHandled flag if the event will bubble, see #9469.
5046					if ( !event.isPropagationStopped() ) {
5047						this.mouseHandled = true;
5048					}
5049
5050					// Open submenu on click
5051					if ( target.has( ".ui-menu" ).length ) {
5052						this.expand( event );
5053					} else if ( !this.element.is( ":focus" ) &&
5054							active.closest( ".ui-menu" ).length ) {
5055
5056						// Redirect focus to the menu
5057						this.element.trigger( "focus", [ true ] );
5058
5059						// If the active item is on the top level, let it stay active.
5060						// Otherwise, blur the active item since it is no longer visible.
5061						if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) {
5062							clearTimeout( this.timer );
5063						}
5064					}
5065				}
5066			},
5067			"mouseenter .ui-menu-item": "_activateItem",
5068			"mousemove .ui-menu-item": "_activateItem",
5069			mouseleave: "collapseAll",
5070			"mouseleave .ui-menu": "collapseAll",
5071			focus: function( event, keepActiveItem ) {
5072
5073				// If there's already an active item, keep it active
5074				// If not, activate the first item
5075				var item = this.active || this._menuItems().first();
5076
5077				if ( !keepActiveItem ) {
5078					this.focus( event, item );
5079				}
5080			},
5081			blur: function( event ) {
5082				this._delay( function() {
5083					var notContained = !$.contains(
5084						this.element[ 0 ],
5085						$.ui.safeActiveElement( this.document[ 0 ] )
5086					);
5087					if ( notContained ) {
5088						this.collapseAll( event );
5089					}
5090				} );
5091			},
5092			keydown: "_keydown"
5093		} );
5094
5095		this.refresh();
5096
5097		// Clicks outside of a menu collapse any open menus
5098		this._on( this.document, {
5099			click: function( event ) {
5100				if ( this._closeOnDocumentClick( event ) ) {
5101					this.collapseAll( event, true );
5102				}
5103
5104				// Reset the mouseHandled flag
5105				this.mouseHandled = false;
5106			}
5107		} );
5108	},
5109
5110	_activateItem: function( event ) {
5111
5112		// Ignore mouse events while typeahead is active, see #10458.
5113		// Prevents focusing the wrong item when typeahead causes a scroll while the mouse
5114		// is over an item in the menu
5115		if ( this.previousFilter ) {
5116			return;
5117		}
5118
5119		// If the mouse didn't actually move, but the page was scrolled, ignore the event (#9356)
5120		if ( event.clientX === this.lastMousePosition.x &&
5121				event.clientY === this.lastMousePosition.y ) {
5122			return;
5123		}
5124
5125		this.lastMousePosition = {
5126			x: event.clientX,
5127			y: event.clientY
5128		};
5129
5130		var actualTarget = $( event.target ).closest( ".ui-menu-item" ),
5131			target = $( event.currentTarget );
5132
5133		// Ignore bubbled events on parent items, see #11641
5134		if ( actualTarget[ 0 ] !== target[ 0 ] ) {
5135			return;
5136		}
5137
5138		// If the item is already active, there's nothing to do
5139		if ( target.is( ".ui-state-active" ) ) {
5140			return;
5141		}
5142
5143		// Remove ui-state-active class from siblings of the newly focused menu item
5144		// to avoid a jump caused by adjacent elements both having a class with a border
5145		this._removeClass( target.siblings().children( ".ui-state-active" ),
5146			null, "ui-state-active" );
5147		this.focus( event, target );
5148	},
5149
5150	_destroy: function() {
5151		var items = this.element.find( ".ui-menu-item" )
5152				.removeAttr( "role aria-disabled" ),
5153			submenus = items.children( ".ui-menu-item-wrapper" )
5154				.removeUniqueId()
5155				.removeAttr( "tabIndex role aria-haspopup" );
5156
5157		// Destroy (sub)menus
5158		this.element
5159			.removeAttr( "aria-activedescendant" )
5160			.find( ".ui-menu" ).addBack()
5161				.removeAttr( "role aria-labelledby aria-expanded aria-hidden aria-disabled " +
5162					"tabIndex" )
5163				.removeUniqueId()
5164				.show();
5165
5166		submenus.children().each( function() {
5167			var elem = $( this );
5168			if ( elem.data( "ui-menu-submenu-caret" ) ) {
5169				elem.remove();
5170			}
5171		} );
5172	},
5173
5174	_keydown: function( event ) {
5175		var match, prev, character, skip,
5176			preventDefault = true;
5177
5178		switch ( event.keyCode ) {
5179		case $.ui.keyCode.PAGE_UP:
5180			this.previousPage( event );
5181			break;
5182		case $.ui.keyCode.PAGE_DOWN:
5183			this.nextPage( event );
5184			break;
5185		case $.ui.keyCode.HOME:
5186			this._move( "first", "first", event );
5187			break;
5188		case $.ui.keyCode.END:
5189			this._move( "last", "last", event );
5190			break;
5191		case $.ui.keyCode.UP:
5192			this.previous( event );
5193			break;
5194		case $.ui.keyCode.DOWN:
5195			this.next( event );
5196			break;
5197		case $.ui.keyCode.LEFT:
5198			this.collapse( event );
5199			break;
5200		case $.ui.keyCode.RIGHT:
5201			if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
5202				this.expand( event );
5203			}
5204			break;
5205		case $.ui.keyCode.ENTER:
5206		case $.ui.keyCode.SPACE:
5207			this._activate( event );
5208			break;
5209		case $.ui.keyCode.ESCAPE:
5210			this.collapse( event );
5211			break;
5212		default:
5213			preventDefault = false;
5214			prev = this.previousFilter || "";
5215			skip = false;
5216
5217			// Support number pad values
5218			character = event.keyCode >= 96 && event.keyCode <= 105 ?
5219				( event.keyCode - 96 ).toString() : String.fromCharCode( event.keyCode );
5220
5221			clearTimeout( this.filterTimer );
5222
5223			if ( character === prev ) {
5224				skip = true;
5225			} else {
5226				character = prev + character;
5227			}
5228
5229			match = this._filterMenuItems( character );
5230			match = skip && match.index( this.active.next() ) !== -1 ?
5231				this.active.nextAll( ".ui-menu-item" ) :
5232				match;
5233
5234			// If no matches on the current filter, reset to the last character pressed
5235			// to move down the menu to the first item that starts with that character
5236			if ( !match.length ) {
5237				character = String.fromCharCode( event.keyCode );
5238				match = this._filterMenuItems( character );
5239			}
5240
5241			if ( match.length ) {
5242				this.focus( event, match );
5243				this.previousFilter = character;
5244				this.filterTimer = this._delay( function() {
5245					delete this.previousFilter;
5246				}, 1000 );
5247			} else {
5248				delete this.previousFilter;
5249			}
5250		}
5251
5252		if ( preventDefault ) {
5253			event.preventDefault();
5254		}
5255	},
5256
5257	_activate: function( event ) {
5258		if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
5259			if ( this.active.children( "[aria-haspopup='true']" ).length ) {
5260				this.expand( event );
5261			} else {
5262				this.select( event );
5263			}
5264		}
5265	},
5266
5267	refresh: function() {
5268		var menus, items, newSubmenus, newItems, newWrappers,
5269			that = this,
5270			icon = this.options.icons.submenu,
5271			submenus = this.element.find( this.options.menus );
5272
5273		this._toggleClass( "ui-menu-icons", null, !!this.element.find( ".ui-icon" ).length );
5274
5275		// Initialize nested menus
5276		newSubmenus = submenus.filter( ":not(.ui-menu)" )
5277			.hide()
5278			.attr( {
5279				role: this.options.role,
5280				"aria-hidden": "true",
5281				"aria-expanded": "false"
5282			} )
5283			.each( function() {
5284				var menu = $( this ),
5285					item = menu.prev(),
5286					submenuCaret = $( "<span>" ).data( "ui-menu-submenu-caret", true );
5287
5288				that._addClass( submenuCaret, "ui-menu-icon", "ui-icon " + icon );
5289				item
5290					.attr( "aria-haspopup", "true" )
5291					.prepend( submenuCaret );
5292				menu.attr( "aria-labelledby", item.attr( "id" ) );
5293			} );
5294
5295		this._addClass( newSubmenus, "ui-menu", "ui-widget ui-widget-content ui-front" );
5296
5297		menus = submenus.add( this.element );
5298		items = menus.find( this.options.items );
5299
5300		// Initialize menu-items containing spaces and/or dashes only as dividers
5301		items.not( ".ui-menu-item" ).each( function() {
5302			var item = $( this );
5303			if ( that._isDivider( item ) ) {
5304				that._addClass( item, "ui-menu-divider", "ui-widget-content" );
5305			}
5306		} );
5307
5308		// Don't refresh list items that are already adapted
5309		newItems = items.not( ".ui-menu-item, .ui-menu-divider" );
5310		newWrappers = newItems.children()
5311			.not( ".ui-menu" )
5312				.uniqueId()
5313				.attr( {
5314					tabIndex: -1,
5315					role: this._itemRole()
5316				} );
5317		this._addClass( newItems, "ui-menu-item" )
5318			._addClass( newWrappers, "ui-menu-item-wrapper" );
5319
5320		// Add aria-disabled attribute to any disabled menu item
5321		items.filter( ".ui-state-disabled" ).attr( "aria-disabled", "true" );
5322
5323		// If the active item has been removed, blur the menu
5324		if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
5325			this.blur();
5326		}
5327	},
5328
5329	_itemRole: function() {
5330		return {
5331			menu: "menuitem",
5332			listbox: "option"
5333		}[ this.options.role ];
5334	},
5335
5336	_setOption: function( key, value ) {
5337		if ( key === "icons" ) {
5338			var icons = this.element.find( ".ui-menu-icon" );
5339			this._removeClass( icons, null, this.options.icons.submenu )
5340				._addClass( icons, null, value.submenu );
5341		}
5342		this._super( key, value );
5343	},
5344
5345	_setOptionDisabled: function( value ) {
5346		this._super( value );
5347
5348		this.element.attr( "aria-disabled", String( value ) );
5349		this._toggleClass( null, "ui-state-disabled", !!value );
5350	},
5351
5352	focus: function( event, item ) {
5353		var nested, focused, activeParent;
5354		this.blur( event, event && event.type === "focus" );
5355
5356		this._scrollIntoView( item );
5357
5358		this.active = item.first();
5359
5360		focused = this.active.children( ".ui-menu-item-wrapper" );
5361		this._addClass( focused, null, "ui-state-active" );
5362
5363		// Only update aria-activedescendant if there's a role
5364		// otherwise we assume focus is managed elsewhere
5365		if ( this.options.role ) {
5366			this.element.attr( "aria-activedescendant", focused.attr( "id" ) );
5367		}
5368
5369		// Highlight active parent menu item, if any
5370		activeParent = this.active
5371			.parent()
5372				.closest( ".ui-menu-item" )
5373					.children( ".ui-menu-item-wrapper" );
5374		this._addClass( activeParent, null, "ui-state-active" );
5375
5376		if ( event && event.type === "keydown" ) {
5377			this._close();
5378		} else {
5379			this.timer = this._delay( function() {
5380				this._close();
5381			}, this.delay );
5382		}
5383
5384		nested = item.children( ".ui-menu" );
5385		if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) {
5386			this._startOpening( nested );
5387		}
5388		this.activeMenu = item.parent();
5389
5390		this._trigger( "focus", event, { item: item } );
5391	},
5392
5393	_scrollIntoView: function( item ) {
5394		var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
5395		if ( this._hasScroll() ) {
5396			borderTop = parseFloat( $.css( this.activeMenu[ 0 ], "borderTopWidth" ) ) || 0;
5397			paddingTop = parseFloat( $.css( this.activeMenu[ 0 ], "paddingTop" ) ) || 0;
5398			offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
5399			scroll = this.activeMenu.scrollTop();
5400			elementHeight = this.activeMenu.height();
5401			itemHeight = item.outerHeight();
5402
5403			if ( offset < 0 ) {
5404				this.activeMenu.scrollTop( scroll + offset );
5405			} else if ( offset + itemHeight > elementHeight ) {
5406				this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );
5407			}
5408		}
5409	},
5410
5411	blur: function( event, fromFocus ) {
5412		if ( !fromFocus ) {
5413			clearTimeout( this.timer );
5414		}
5415
5416		if ( !this.active ) {
5417			return;
5418		}
5419
5420		this._removeClass( this.active.children( ".ui-menu-item-wrapper" ),
5421			null, "ui-state-active" );
5422
5423		this._trigger( "blur", event, { item: this.active } );
5424		this.active = null;
5425	},
5426
5427	_startOpening: function( submenu ) {
5428		clearTimeout( this.timer );
5429
5430		// Don't open if already open fixes a Firefox bug that caused a .5 pixel
5431		// shift in the submenu position when mousing over the caret icon
5432		if ( submenu.attr( "aria-hidden" ) !== "true" ) {
5433			return;
5434		}
5435
5436		this.timer = this._delay( function() {
5437			this._close();
5438			this._open( submenu );
5439		}, this.delay );
5440	},
5441
5442	_open: function( submenu ) {
5443		var position = $.extend( {
5444			of: this.active
5445		}, this.options.position );
5446
5447		clearTimeout( this.timer );
5448		this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) )
5449			.hide()
5450			.attr( "aria-hidden", "true" );
5451
5452		submenu
5453			.show()
5454			.removeAttr( "aria-hidden" )
5455			.attr( "aria-expanded", "true" )
5456			.position( position );
5457	},
5458
5459	collapseAll: function( event, all ) {
5460		clearTimeout( this.timer );
5461		this.timer = this._delay( function() {
5462
5463			// If we were passed an event, look for the submenu that contains the event
5464			var currentMenu = all ? this.element :
5465				$( event && event.target ).closest( this.element.find( ".ui-menu" ) );
5466
5467			// If we found no valid submenu ancestor, use the main menu to close all
5468			// sub menus anyway
5469			if ( !currentMenu.length ) {
5470				currentMenu = this.element;
5471			}
5472
5473			this._close( currentMenu );
5474
5475			this.blur( event );
5476
5477			// Work around active item staying active after menu is blurred
5478			this._removeClass( currentMenu.find( ".ui-state-active" ), null, "ui-state-active" );
5479
5480			this.activeMenu = currentMenu;
5481		}, all ? 0 : this.delay );
5482	},
5483
5484	// With no arguments, closes the currently active menu - if nothing is active
5485	// it closes all menus.  If passed an argument, it will search for menus BELOW
5486	_close: function( startMenu ) {
5487		if ( !startMenu ) {
5488			startMenu = this.active ? this.active.parent() : this.element;
5489		}
5490
5491		startMenu.find( ".ui-menu" )
5492			.hide()
5493			.attr( "aria-hidden", "true" )
5494			.attr( "aria-expanded", "false" );
5495	},
5496
5497	_closeOnDocumentClick: function( event ) {
5498		return !$( event.target ).closest( ".ui-menu" ).length;
5499	},
5500
5501	_isDivider: function( item ) {
5502
5503		// Match hyphen, em dash, en dash
5504		return !/[^\-\u2014\u2013\s]/.test( item.text() );
5505	},
5506
5507	collapse: function( event ) {
5508		var newItem = this.active &&
5509			this.active.parent().closest( ".ui-menu-item", this.element );
5510		if ( newItem && newItem.length ) {
5511			this._close();
5512			this.focus( event, newItem );
5513		}
5514	},
5515
5516	expand: function( event ) {
5517		var newItem = this.active && this._menuItems( this.active.children( ".ui-menu" ) ).first();
5518
5519		if ( newItem && newItem.length ) {
5520			this._open( newItem.parent() );
5521
5522			// Delay so Firefox will not hide activedescendant change in expanding submenu from AT
5523			this._delay( function() {
5524				this.focus( event, newItem );
5525			} );
5526		}
5527	},
5528
5529	next: function( event ) {
5530		this._move( "next", "first", event );
5531	},
5532
5533	previous: function( event ) {
5534		this._move( "prev", "last", event );
5535	},
5536
5537	isFirstItem: function() {
5538		return this.active && !this.active.prevAll( ".ui-menu-item" ).length;
5539	},
5540
5541	isLastItem: function() {
5542		return this.active && !this.active.nextAll( ".ui-menu-item" ).length;
5543	},
5544
5545	_menuItems: function( menu ) {
5546		return ( menu || this.element )
5547			.find( this.options.items )
5548			.filter( ".ui-menu-item" );
5549	},
5550
5551	_move: function( direction, filter, event ) {
5552		var next;
5553		if ( this.active ) {
5554			if ( direction === "first" || direction === "last" ) {
5555				next = this.active
5556					[ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )
5557					.last();
5558			} else {
5559				next = this.active
5560					[ direction + "All" ]( ".ui-menu-item" )
5561					.first();
5562			}
5563		}
5564		if ( !next || !next.length || !this.active ) {
5565			next = this._menuItems( this.activeMenu )[ filter ]();
5566		}
5567
5568		this.focus( event, next );
5569	},
5570
5571	nextPage: function( event ) {
5572		var item, base, height;
5573
5574		if ( !this.active ) {
5575			this.next( event );
5576			return;
5577		}
5578		if ( this.isLastItem() ) {
5579			return;
5580		}
5581		if ( this._hasScroll() ) {
5582			base = this.active.offset().top;
5583			height = this.element.innerHeight();
5584
5585			// jQuery 3.2 doesn't include scrollbars in innerHeight, add it back.
5586			if ( $.fn.jquery.indexOf( "3.2." ) === 0 ) {
5587				height += this.element[ 0 ].offsetHeight - this.element.outerHeight();
5588			}
5589
5590			this.active.nextAll( ".ui-menu-item" ).each( function() {
5591				item = $( this );
5592				return item.offset().top - base - height < 0;
5593			} );
5594
5595			this.focus( event, item );
5596		} else {
5597			this.focus( event, this._menuItems( this.activeMenu )
5598				[ !this.active ? "first" : "last" ]() );
5599		}
5600	},
5601
5602	previousPage: function( event ) {
5603		var item, base, height;
5604		if ( !this.active ) {
5605			this.next( event );
5606			return;
5607		}
5608		if ( this.isFirstItem() ) {
5609			return;
5610		}
5611		if ( this._hasScroll() ) {
5612			base = this.active.offset().top;
5613			height = this.element.innerHeight();
5614
5615			// jQuery 3.2 doesn't include scrollbars in innerHeight, add it back.
5616			if ( $.fn.jquery.indexOf( "3.2." ) === 0 ) {
5617				height += this.element[ 0 ].offsetHeight - this.element.outerHeight();
5618			}
5619
5620			this.active.prevAll( ".ui-menu-item" ).each( function() {
5621				item = $( this );
5622				return item.offset().top - base + height > 0;
5623			} );
5624
5625			this.focus( event, item );
5626		} else {
5627			this.focus( event, this._menuItems( this.activeMenu ).first() );
5628		}
5629	},
5630
5631	_hasScroll: function() {
5632		return this.element.outerHeight() < this.element.prop( "scrollHeight" );
5633	},
5634
5635	select: function( event ) {
5636
5637		// TODO: It should never be possible to not have an active item at this
5638		// point, but the tests don't trigger mouseenter before click.
5639		this.active = this.active || $( event.target ).closest( ".ui-menu-item" );
5640		var ui = { item: this.active };
5641		if ( !this.active.has( ".ui-menu" ).length ) {
5642			this.collapseAll( event, true );
5643		}
5644		this._trigger( "select", event, ui );
5645	},
5646
5647	_filterMenuItems: function( character ) {
5648		var escapedCharacter = character.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ),
5649			regex = new RegExp( "^" + escapedCharacter, "i" );
5650
5651		return this.activeMenu
5652			.find( this.options.items )
5653
5654				// Only match on items, not dividers or other content (#10571)
5655				.filter( ".ui-menu-item" )
5656					.filter( function() {
5657						return regex.test(
5658							String.prototype.trim.call(
5659								$( this ).children( ".ui-menu-item-wrapper" ).text() ) );
5660					} );
5661	}
5662} );
5663
5664
5665/*!
5666 * jQuery UI Autocomplete 1.13.3
5667 * https://jqueryui.com
5668 *
5669 * Copyright OpenJS Foundation and other contributors
5670 * Released under the MIT license.
5671 * https://jquery.org/license
5672 */
5673
5674//>>label: Autocomplete
5675//>>group: Widgets
5676//>>description: Lists suggested words as the user is typing.
5677//>>docs: https://api.jqueryui.com/autocomplete/
5678//>>demos: https://jqueryui.com/autocomplete/
5679//>>css.structure: ../../themes/base/core.css
5680//>>css.structure: ../../themes/base/autocomplete.css
5681//>>css.theme: ../../themes/base/theme.css
5682
5683
5684$.widget( "ui.autocomplete", {
5685	version: "1.13.3",
5686	defaultElement: "<input>",
5687	options: {
5688		appendTo: null,
5689		autoFocus: false,
5690		delay: 300,
5691		minLength: 1,
5692		position: {
5693			my: "left top",
5694			at: "left bottom",
5695			collision: "none"
5696		},
5697		source: null,
5698
5699		// Callbacks
5700		change: null,
5701		close: null,
5702		focus: null,
5703		open: null,
5704		response: null,
5705		search: null,
5706		select: null
5707	},
5708
5709	requestIndex: 0,
5710	pending: 0,
5711	liveRegionTimer: null,
5712
5713	_create: function() {
5714
5715		// Some browsers only repeat keydown events, not keypress events,
5716		// so we use the suppressKeyPress flag to determine if we've already
5717		// handled the keydown event. #7269
5718		// Unfortunately the code for & in keypress is the same as the up arrow,
5719		// so we use the suppressKeyPressRepeat flag to avoid handling keypress
5720		// events when we know the keydown event was used to modify the
5721		// search term. #7799
5722		var suppressKeyPress, suppressKeyPressRepeat, suppressInput,
5723			nodeName = this.element[ 0 ].nodeName.toLowerCase(),
5724			isTextarea = nodeName === "textarea",
5725			isInput = nodeName === "input";
5726
5727		// Textareas are always multi-line
5728		// Inputs are always single-line, even if inside a contentEditable element
5729		// IE also treats inputs as contentEditable
5730		// All other element types are determined by whether or not they're contentEditable
5731		this.isMultiLine = isTextarea || !isInput && this._isContentEditable( this.element );
5732
5733		this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ];
5734		this.isNewMenu = true;
5735
5736		this._addClass( "ui-autocomplete-input" );
5737		this.element.attr( "autocomplete", "off" );
5738
5739		this._on( this.element, {
5740			keydown: function( event ) {
5741				if ( this.element.prop( "readOnly" ) ) {
5742					suppressKeyPress = true;
5743					suppressInput = true;
5744					suppressKeyPressRepeat = true;
5745					return;
5746				}
5747
5748				suppressKeyPress = false;
5749				suppressInput = false;
5750				suppressKeyPressRepeat = false;
5751				var keyCode = $.ui.keyCode;
5752				switch ( event.keyCode ) {
5753				case keyCode.PAGE_UP:
5754					suppressKeyPress = true;
5755					this._move( "previousPage", event );
5756					break;
5757				case keyCode.PAGE_DOWN:
5758					suppressKeyPress = true;
5759					this._move( "nextPage", event );
5760					break;
5761				case keyCode.UP:
5762					suppressKeyPress = true;
5763					this._keyEvent( "previous", event );
5764					break;
5765				case keyCode.DOWN:
5766					suppressKeyPress = true;
5767					this._keyEvent( "next", event );
5768					break;
5769				case keyCode.ENTER:
5770
5771					// when menu is open and has focus
5772					if ( this.menu.active ) {
5773
5774						// #6055 - Opera still allows the keypress to occur
5775						// which causes forms to submit
5776						suppressKeyPress = true;
5777						event.preventDefault();
5778						this.menu.select( event );
5779					}
5780					break;
5781				case keyCode.TAB:
5782					if ( this.menu.active ) {
5783						this.menu.select( event );
5784					}
5785					break;
5786				case keyCode.ESCAPE:
5787					if ( this.menu.element.is( ":visible" ) ) {
5788						if ( !this.isMultiLine ) {
5789							this._value( this.term );
5790						}
5791						this.close( event );
5792
5793						// Different browsers have different default behavior for escape
5794						// Single press can mean undo or clear
5795						// Double press in IE means clear the whole form
5796						event.preventDefault();
5797					}
5798					break;
5799				default:
5800					suppressKeyPressRepeat = true;
5801
5802					// search timeout should be triggered before the input value is changed
5803					this._searchTimeout( event );
5804					break;
5805				}
5806			},
5807			keypress: function( event ) {
5808				if ( suppressKeyPress ) {
5809					suppressKeyPress = false;
5810					if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
5811						event.preventDefault();
5812					}
5813					return;
5814				}
5815				if ( suppressKeyPressRepeat ) {
5816					return;
5817				}
5818
5819				// Replicate some key handlers to allow them to repeat in Firefox and Opera
5820				var keyCode = $.ui.keyCode;
5821				switch ( event.keyCode ) {
5822				case keyCode.PAGE_UP:
5823					this._move( "previousPage", event );
5824					break;
5825				case keyCode.PAGE_DOWN:
5826					this._move( "nextPage", event );
5827					break;
5828				case keyCode.UP:
5829					this._keyEvent( "previous", event );
5830					break;
5831				case keyCode.DOWN:
5832					this._keyEvent( "next", event );
5833					break;
5834				}
5835			},
5836			input: function( event ) {
5837				if ( suppressInput ) {
5838					suppressInput = false;
5839					event.preventDefault();
5840					return;
5841				}
5842				this._searchTimeout( event );
5843			},
5844			focus: function() {
5845				this.selectedItem = null;
5846				this.previous = this._value();
5847			},
5848			blur: function( event ) {
5849				clearTimeout( this.searching );
5850				this.close( event );
5851				this._change( event );
5852			}
5853		} );
5854
5855		this._initSource();
5856		this.menu = $( "<ul>" )
5857			.appendTo( this._appendTo() )
5858			.menu( {
5859
5860				// disable ARIA support, the live region takes care of that
5861				role: null
5862			} )
5863			.hide()
5864
5865			// Support: IE 11 only, Edge <= 14
5866			// For other browsers, we preventDefault() on the mousedown event
5867			// to keep the dropdown from taking focus from the input. This doesn't
5868			// work for IE/Edge, causing problems with selection and scrolling (#9638)
5869			// Happily, IE and Edge support an "unselectable" attribute that
5870			// prevents an element from receiving focus, exactly what we want here.
5871			.attr( {
5872				"unselectable": "on"
5873			} )
5874			.menu( "instance" );
5875
5876		this._addClass( this.menu.element, "ui-autocomplete", "ui-front" );
5877		this._on( this.menu.element, {
5878			mousedown: function( event ) {
5879
5880				// Prevent moving focus out of the text field
5881				event.preventDefault();
5882			},
5883			menufocus: function( event, ui ) {
5884				var label, item;
5885
5886				// support: Firefox
5887				// Prevent accidental activation of menu items in Firefox (#7024 #9118)
5888				if ( this.isNewMenu ) {
5889					this.isNewMenu = false;
5890					if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {
5891						this.menu.blur();
5892
5893						this.document.one( "mousemove", function() {
5894							$( event.target ).trigger( event.originalEvent );
5895						} );
5896
5897						return;
5898					}
5899				}
5900
5901				item = ui.item.data( "ui-autocomplete-item" );
5902				if ( false !== this._trigger( "focus", event, { item: item } ) ) {
5903
5904					// use value to match what will end up in the input, if it was a key event
5905					if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
5906						this._value( item.value );
5907					}
5908				}
5909
5910				// Announce the value in the liveRegion
5911				label = ui.item.attr( "aria-label" ) || item.value;
5912				if ( label && String.prototype.trim.call( label ).length ) {
5913					clearTimeout( this.liveRegionTimer );
5914					this.liveRegionTimer = this._delay( function() {
5915						this.liveRegion.html( $( "<div>" ).text( label ) );
5916					}, 100 );
5917				}
5918			},
5919			menuselect: function( event, ui ) {
5920				var item = ui.item.data( "ui-autocomplete-item" ),
5921					previous = this.previous;
5922
5923				// Only trigger when focus was lost (click on menu)
5924				if ( this.element[ 0 ] !== $.ui.safeActiveElement( this.document[ 0 ] ) ) {
5925					this.element.trigger( "focus" );
5926					this.previous = previous;
5927
5928					// #6109 - IE triggers two focus events and the second
5929					// is asynchronous, so we need to reset the previous
5930					// term synchronously and asynchronously :-(
5931					this._delay( function() {
5932						this.previous = previous;
5933						this.selectedItem = item;
5934					} );
5935				}
5936
5937				if ( false !== this._trigger( "select", event, { item: item } ) ) {
5938					this._value( item.value );
5939				}
5940
5941				// reset the term after the select event
5942				// this allows custom select handling to work properly
5943				this.term = this._value();
5944
5945				this.close( event );
5946				this.selectedItem = item;
5947			}
5948		} );
5949
5950		this.liveRegion = $( "<div>", {
5951			role: "status",
5952			"aria-live": "assertive",
5953			"aria-relevant": "additions"
5954		} )
5955			.appendTo( this.document[ 0 ].body );
5956
5957		this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" );
5958
5959		// Turning off autocomplete prevents the browser from remembering the
5960		// value when navigating through history, so we re-enable autocomplete
5961		// if the page is unloaded before the widget is destroyed. #7790
5962		this._on( this.window, {
5963			beforeunload: function() {
5964				this.element.removeAttr( "autocomplete" );
5965			}
5966		} );
5967	},
5968
5969	_destroy: function() {
5970		clearTimeout( this.searching );
5971		this.element.removeAttr( "autocomplete" );
5972		this.menu.element.remove();
5973		this.liveRegion.remove();
5974	},
5975
5976	_setOption: function( key, value ) {
5977		this._super( key, value );
5978		if ( key === "source" ) {
5979			this._initSource();
5980		}
5981		if ( key === "appendTo" ) {
5982			this.menu.element.appendTo( this._appendTo() );
5983		}
5984		if ( key === "disabled" && value && this.xhr ) {
5985			this.xhr.abort();
5986		}
5987	},
5988
5989	_isEventTargetInWidget: function( event ) {
5990		var menuElement = this.menu.element[ 0 ];
5991
5992		return event.target === this.element[ 0 ] ||
5993			event.target === menuElement ||
5994			$.contains( menuElement, event.target );
5995	},
5996
5997	_closeOnClickOutside: function( event ) {
5998		if ( !this._isEventTargetInWidget( event ) ) {
5999			this.close();
6000		}
6001	},
6002
6003	_appendTo: function() {
6004		var element = this.options.appendTo;
6005
6006		if ( element ) {
6007			element = element.jquery || element.nodeType ?
6008				$( element ) :
6009				this.document.find( element ).eq( 0 );
6010		}
6011
6012		if ( !element || !element[ 0 ] ) {
6013			element = this.element.closest( ".ui-front, dialog" );
6014		}
6015
6016		if ( !element.length ) {
6017			element = this.document[ 0 ].body;
6018		}
6019
6020		return element;
6021	},
6022
6023	_initSource: function() {
6024		var array, url,
6025			that = this;
6026		if ( Array.isArray( this.options.source ) ) {
6027			array = this.options.source;
6028			this.source = function( request, response ) {
6029				response( $.ui.autocomplete.filter( array, request.term ) );
6030			};
6031		} else if ( typeof this.options.source === "string" ) {
6032			url = this.options.source;
6033			this.source = function( request, response ) {
6034				if ( that.xhr ) {
6035					that.xhr.abort();
6036				}
6037				that.xhr = $.ajax( {
6038					url: url,
6039					data: request,
6040					dataType: "json",
6041					success: function( data ) {
6042						response( data );
6043					},
6044					error: function() {
6045						response( [] );
6046					}
6047				} );
6048			};
6049		} else {
6050			this.source = this.options.source;
6051		}
6052	},
6053
6054	_searchTimeout: function( event ) {
6055		clearTimeout( this.searching );
6056		this.searching = this._delay( function() {
6057
6058			// Search if the value has changed, or if the user retypes the same value (see #7434)
6059			var equalValues = this.term === this._value(),
6060				menuVisible = this.menu.element.is( ":visible" ),
6061				modifierKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
6062
6063			if ( !equalValues || ( equalValues && !menuVisible && !modifierKey ) ) {
6064				this.selectedItem = null;
6065				this.search( null, event );
6066			}
6067		}, this.options.delay );
6068	},
6069
6070	search: function( value, event ) {
6071		value = value != null ? value : this._value();
6072
6073		// Always save the actual value, not the one passed as an argument
6074		this.term = this._value();
6075
6076		if ( value.length < this.options.minLength ) {
6077			return this.close( event );
6078		}
6079
6080		if ( this._trigger( "search", event ) === false ) {
6081			return;
6082		}
6083
6084		return this._search( value );
6085	},
6086
6087	_search: function( value ) {
6088		this.pending++;
6089		this._addClass( "ui-autocomplete-loading" );
6090		this.cancelSearch = false;
6091
6092		this.source( { term: value }, this._response() );
6093	},
6094
6095	_response: function() {
6096		var index = ++this.requestIndex;
6097
6098		return function( content ) {
6099			if ( index === this.requestIndex ) {
6100				this.__response( content );
6101			}
6102
6103			this.pending--;
6104			if ( !this.pending ) {
6105				this._removeClass( "ui-autocomplete-loading" );
6106			}
6107		}.bind( this );
6108	},
6109
6110	__response: function( content ) {
6111		if ( content ) {
6112			content = this._normalize( content );
6113		}
6114		this._trigger( "response", null, { content: content } );
6115		if ( !this.options.disabled && content && content.length && !this.cancelSearch ) {
6116			this._suggest( content );
6117			this._trigger( "open" );
6118		} else {
6119
6120			// use ._close() instead of .close() so we don't cancel future searches
6121			this._close();
6122		}
6123	},
6124
6125	close: function( event ) {
6126		this.cancelSearch = true;
6127		this._close( event );
6128	},
6129
6130	_close: function( event ) {
6131
6132		// Remove the handler that closes the menu on outside clicks
6133		this._off( this.document, "mousedown" );
6134
6135		if ( this.menu.element.is( ":visible" ) ) {
6136			this.menu.element.hide();
6137			this.menu.blur();
6138			this.isNewMenu = true;
6139			this._trigger( "close", event );
6140		}
6141	},
6142
6143	_change: function( event ) {
6144		if ( this.previous !== this._value() ) {
6145			this._trigger( "change", event, { item: this.selectedItem } );
6146		}
6147	},
6148
6149	_normalize: function( items ) {
6150
6151		// assume all items have the right format when the first item is complete
6152		if ( items.length && items[ 0 ].label && items[ 0 ].value ) {
6153			return items;
6154		}
6155		return $.map( items, function( item ) {
6156			if ( typeof item === "string" ) {
6157				return {
6158					label: item,
6159					value: item
6160				};
6161			}
6162			return $.extend( {}, item, {
6163				label: item.label || item.value,
6164				value: item.value || item.label
6165			} );
6166		} );
6167	},
6168
6169	_suggest: function( items ) {
6170		var ul = this.menu.element.empty();
6171		this._renderMenu( ul, items );
6172		this.isNewMenu = true;
6173		this.menu.refresh();
6174
6175		// Size and position menu
6176		ul.show();
6177		this._resizeMenu();
6178		ul.position( $.extend( {
6179			of: this.element
6180		}, this.options.position ) );
6181
6182		if ( this.options.autoFocus ) {
6183			this.menu.next();
6184		}
6185
6186		// Listen for interactions outside of the widget (#6642)
6187		this._on( this.document, {
6188			mousedown: "_closeOnClickOutside"
6189		} );
6190	},
6191
6192	_resizeMenu: function() {
6193		var ul = this.menu.element;
6194		ul.outerWidth( Math.max(
6195
6196			// Firefox wraps long text (possibly a rounding bug)
6197			// so we add 1px to avoid the wrapping (#7513)
6198			ul.width( "" ).outerWidth() + 1,
6199			this.element.outerWidth()
6200		) );
6201	},
6202
6203	_renderMenu: function( ul, items ) {
6204		var that = this;
6205		$.each( items, function( index, item ) {
6206			that._renderItemData( ul, item );
6207		} );
6208	},
6209
6210	_renderItemData: function( ul, item ) {
6211		return this._renderItem( ul, item ).data( "ui-autocomplete-item", item );
6212	},
6213
6214	_renderItem: function( ul, item ) {
6215		return $( "<li>" )
6216			.append( $( "<div>" ).text( item.label ) )
6217			.appendTo( ul );
6218	},
6219
6220	_move: function( direction, event ) {
6221		if ( !this.menu.element.is( ":visible" ) ) {
6222			this.search( null, event );
6223			return;
6224		}
6225		if ( this.menu.isFirstItem() && /^previous/.test( direction ) ||
6226				this.menu.isLastItem() && /^next/.test( direction ) ) {
6227
6228			if ( !this.isMultiLine ) {
6229				this._value( this.term );
6230			}
6231
6232			this.menu.blur();
6233			return;
6234		}
6235		this.menu[ direction ]( event );
6236	},
6237
6238	widget: function() {
6239		return this.menu.element;
6240	},
6241
6242	_value: function() {
6243		return this.valueMethod.apply( this.element, arguments );
6244	},
6245
6246	_keyEvent: function( keyEvent, event ) {
6247		if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
6248			this._move( keyEvent, event );
6249
6250			// Prevents moving cursor to beginning/end of the text field in some browsers
6251			event.preventDefault();
6252		}
6253	},
6254
6255	// Support: Chrome <=50
6256	// We should be able to just use this.element.prop( "isContentEditable" )
6257	// but hidden elements always report false in Chrome.
6258	// https://code.google.com/p/chromium/issues/detail?id=313082
6259	_isContentEditable: function( element ) {
6260		if ( !element.length ) {
6261			return false;
6262		}
6263
6264		var editable = element.prop( "contentEditable" );
6265
6266		if ( editable === "inherit" ) {
6267			return this._isContentEditable( element.parent() );
6268		}
6269
6270		return editable === "true";
6271	}
6272} );
6273
6274$.extend( $.ui.autocomplete, {
6275	escapeRegex: function( value ) {
6276		return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
6277	},
6278	filter: function( array, term ) {
6279		var matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), "i" );
6280		return $.grep( array, function( value ) {
6281			return matcher.test( value.label || value.value || value );
6282		} );
6283	}
6284} );
6285
6286// Live region extension, adding a `messages` option
6287// NOTE: This is an experimental API. We are still investigating
6288// a full solution for string manipulation and internationalization.
6289$.widget( "ui.autocomplete", $.ui.autocomplete, {
6290	options: {
6291		messages: {
6292			noResults: "No search results.",
6293			results: function( amount ) {
6294				return amount + ( amount > 1 ? " results are" : " result is" ) +
6295					" available, use up and down arrow keys to navigate.";
6296			}
6297		}
6298	},
6299
6300	__response: function( content ) {
6301		var message;
6302		this._superApply( arguments );
6303		if ( this.options.disabled || this.cancelSearch ) {
6304			return;
6305		}
6306		if ( content && content.length ) {
6307			message = this.options.messages.results( content.length );
6308		} else {
6309			message = this.options.messages.noResults;
6310		}
6311		clearTimeout( this.liveRegionTimer );
6312		this.liveRegionTimer = this._delay( function() {
6313			this.liveRegion.html( $( "<div>" ).text( message ) );
6314		}, 100 );
6315	}
6316} );
6317
6318var widgetsAutocomplete = $.ui.autocomplete;
6319
6320
6321/*!
6322 * jQuery UI Controlgroup 1.13.3
6323 * https://jqueryui.com
6324 *
6325 * Copyright OpenJS Foundation and other contributors
6326 * Released under the MIT license.
6327 * https://jquery.org/license
6328 */
6329
6330//>>label: Controlgroup
6331//>>group: Widgets
6332//>>description: Visually groups form control widgets
6333//>>docs: https://api.jqueryui.com/controlgroup/
6334//>>demos: https://jqueryui.com/controlgroup/
6335//>>css.structure: ../../themes/base/core.css
6336//>>css.structure: ../../themes/base/controlgroup.css
6337//>>css.theme: ../../themes/base/theme.css
6338
6339
6340var controlgroupCornerRegex = /ui-corner-([a-z]){2,6}/g;
6341
6342var widgetsControlgroup = $.widget( "ui.controlgroup", {
6343	version: "1.13.3",
6344	defaultElement: "<div>",
6345	options: {
6346		direction: "horizontal",
6347		disabled: null,
6348		onlyVisible: true,
6349		items: {
6350			"button": "input[type=button], input[type=submit], input[type=reset], button, a",
6351			"controlgroupLabel": ".ui-controlgroup-label",
6352			"checkboxradio": "input[type='checkbox'], input[type='radio']",
6353			"selectmenu": "select",
6354			"spinner": ".ui-spinner-input"
6355		}
6356	},
6357
6358	_create: function() {
6359		this._enhance();
6360	},
6361
6362	// To support the enhanced option in jQuery Mobile, we isolate DOM manipulation
6363	_enhance: function() {
6364		this.element.attr( "role", "toolbar" );
6365		this.refresh();
6366	},
6367
6368	_destroy: function() {
6369		this._callChildMethod( "destroy" );
6370		this.childWidgets.removeData( "ui-controlgroup-data" );
6371		this.element.removeAttr( "role" );
6372		if ( this.options.items.controlgroupLabel ) {
6373			this.element
6374				.find( this.options.items.controlgroupLabel )
6375				.find( ".ui-controlgroup-label-contents" )
6376				.contents().unwrap();
6377		}
6378	},
6379
6380	_initWidgets: function() {
6381		var that = this,
6382			childWidgets = [];
6383
6384		// First we iterate over each of the items options
6385		$.each( this.options.items, function( widget, selector ) {
6386			var labels;
6387			var options = {};
6388
6389			// Make sure the widget has a selector set
6390			if ( !selector ) {
6391				return;
6392			}
6393
6394			if ( widget === "controlgroupLabel" ) {
6395				labels = that.element.find( selector );
6396				labels.each( function() {
6397					var element = $( this );
6398
6399					if ( element.children( ".ui-controlgroup-label-contents" ).length ) {
6400						return;
6401					}
6402					element.contents()
6403						.wrapAll( "<span class='ui-controlgroup-label-contents'></span>" );
6404				} );
6405				that._addClass( labels, null, "ui-widget ui-widget-content ui-state-default" );
6406				childWidgets = childWidgets.concat( labels.get() );
6407				return;
6408			}
6409
6410			// Make sure the widget actually exists
6411			if ( !$.fn[ widget ] ) {
6412				return;
6413			}
6414
6415			// We assume everything is in the middle to start because we can't determine
6416			// first / last elements until all enhancments are done.
6417			if ( that[ "_" + widget + "Options" ] ) {
6418				options = that[ "_" + widget + "Options" ]( "middle" );
6419			} else {
6420				options = { classes: {} };
6421			}
6422
6423			// Find instances of this widget inside controlgroup and init them
6424			that.element
6425				.find( selector )
6426				.each( function() {
6427					var element = $( this );
6428					var instance = element[ widget ]( "instance" );
6429
6430					// We need to clone the default options for this type of widget to avoid
6431					// polluting the variable options which has a wider scope than a single widget.
6432					var instanceOptions = $.widget.extend( {}, options );
6433
6434					// If the button is the child of a spinner ignore it
6435					// TODO: Find a more generic solution
6436					if ( widget === "button" && element.parent( ".ui-spinner" ).length ) {
6437						return;
6438					}
6439
6440					// Create the widget if it doesn't exist
6441					if ( !instance ) {
6442						instance = element[ widget ]()[ widget ]( "instance" );
6443					}
6444					if ( instance ) {
6445						instanceOptions.classes =
6446							that._resolveClassesValues( instanceOptions.classes, instance );
6447					}
6448					element[ widget ]( instanceOptions );
6449
6450					// Store an instance of the controlgroup to be able to reference
6451					// from the outermost element for changing options and refresh
6452					var widgetElement = element[ widget ]( "widget" );
6453					$.data( widgetElement[ 0 ], "ui-controlgroup-data",
6454						instance ? instance : element[ widget ]( "instance" ) );
6455
6456					childWidgets.push( widgetElement[ 0 ] );
6457				} );
6458		} );
6459
6460		this.childWidgets = $( $.uniqueSort( childWidgets ) );
6461		this._addClass( this.childWidgets, "ui-controlgroup-item" );
6462	},
6463
6464	_callChildMethod: function( method ) {
6465		this.childWidgets.each( function() {
6466			var element = $( this ),
6467				data = element.data( "ui-controlgroup-data" );
6468			if ( data && data[ method ] ) {
6469				data[ method ]();
6470			}
6471		} );
6472	},
6473
6474	_updateCornerClass: function( element, position ) {
6475		var remove = "ui-corner-top ui-corner-bottom ui-corner-left ui-corner-right ui-corner-all";
6476		var add = this._buildSimpleOptions( position, "label" ).classes.label;
6477
6478		this._removeClass( element, null, remove );
6479		this._addClass( element, null, add );
6480	},
6481
6482	_buildSimpleOptions: function( position, key ) {
6483		var direction = this.options.direction === "vertical";
6484		var result = {
6485			classes: {}
6486		};
6487		result.classes[ key ] = {
6488			"middle": "",
6489			"first": "ui-corner-" + ( direction ? "top" : "left" ),
6490			"last": "ui-corner-" + ( direction ? "bottom" : "right" ),
6491			"only": "ui-corner-all"
6492		}[ position ];
6493
6494		return result;
6495	},
6496
6497	_spinnerOptions: function( position ) {
6498		var options = this._buildSimpleOptions( position, "ui-spinner" );
6499
6500		options.classes[ "ui-spinner-up" ] = "";
6501		options.classes[ "ui-spinner-down" ] = "";
6502
6503		return options;
6504	},
6505
6506	_buttonOptions: function( position ) {
6507		return this._buildSimpleOptions( position, "ui-button" );
6508	},
6509
6510	_checkboxradioOptions: function( position ) {
6511		return this._buildSimpleOptions( position, "ui-checkboxradio-label" );
6512	},
6513
6514	_selectmenuOptions: function( position ) {
6515		var direction = this.options.direction === "vertical";
6516		return {
6517			width: direction ? "auto" : false,
6518			classes: {
6519				middle: {
6520					"ui-selectmenu-button-open": "",
6521					"ui-selectmenu-button-closed": ""
6522				},
6523				first: {
6524					"ui-selectmenu-button-open": "ui-corner-" + ( direction ? "top" : "tl" ),
6525					"ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "top" : "left" )
6526				},
6527				last: {
6528					"ui-selectmenu-button-open": direction ? "" : "ui-corner-tr",
6529					"ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "bottom" : "right" )
6530				},
6531				only: {
6532					"ui-selectmenu-button-open": "ui-corner-top",
6533					"ui-selectmenu-button-closed": "ui-corner-all"
6534				}
6535
6536			}[ position ]
6537		};
6538	},
6539
6540	_resolveClassesValues: function( classes, instance ) {
6541		var result = {};
6542		$.each( classes, function( key ) {
6543			var current = instance.options.classes[ key ] || "";
6544			current = String.prototype.trim.call( current.replace( controlgroupCornerRegex, "" ) );
6545			result[ key ] = ( current + " " + classes[ key ] ).replace( /\s+/g, " " );
6546		} );
6547		return result;
6548	},
6549
6550	_setOption: function( key, value ) {
6551		if ( key === "direction" ) {
6552			this._removeClass( "ui-controlgroup-" + this.options.direction );
6553		}
6554
6555		this._super( key, value );
6556		if ( key === "disabled" ) {
6557			this._callChildMethod( value ? "disable" : "enable" );
6558			return;
6559		}
6560
6561		this.refresh();
6562	},
6563
6564	refresh: function() {
6565		var children,
6566			that = this;
6567
6568		this._addClass( "ui-controlgroup ui-controlgroup-" + this.options.direction );
6569
6570		if ( this.options.direction === "horizontal" ) {
6571			this._addClass( null, "ui-helper-clearfix" );
6572		}
6573		this._initWidgets();
6574
6575		children = this.childWidgets;
6576
6577		// We filter here because we need to track all childWidgets not just the visible ones
6578		if ( this.options.onlyVisible ) {
6579			children = children.filter( ":visible" );
6580		}
6581
6582		if ( children.length ) {
6583
6584			// We do this last because we need to make sure all enhancment is done
6585			// before determining first and last
6586			$.each( [ "first", "last" ], function( index, value ) {
6587				var instance = children[ value ]().data( "ui-controlgroup-data" );
6588
6589				if ( instance && that[ "_" + instance.widgetName + "Options" ] ) {
6590					var options = that[ "_" + instance.widgetName + "Options" ](
6591						children.length === 1 ? "only" : value
6592					);
6593					options.classes = that._resolveClassesValues( options.classes, instance );
6594					instance.element[ instance.widgetName ]( options );
6595				} else {
6596					that._updateCornerClass( children[ value ](), value );
6597				}
6598			} );
6599
6600			// Finally call the refresh method on each of the child widgets.
6601			this._callChildMethod( "refresh" );
6602		}
6603	}
6604} );
6605
6606/*!
6607 * jQuery UI Checkboxradio 1.13.3
6608 * https://jqueryui.com
6609 *
6610 * Copyright OpenJS Foundation and other contributors
6611 * Released under the MIT license.
6612 * https://jquery.org/license
6613 */
6614
6615//>>label: Checkboxradio
6616//>>group: Widgets
6617//>>description: Enhances a form with multiple themeable checkboxes or radio buttons.
6618//>>docs: https://api.jqueryui.com/checkboxradio/
6619//>>demos: https://jqueryui.com/checkboxradio/
6620//>>css.structure: ../../themes/base/core.css
6621//>>css.structure: ../../themes/base/button.css
6622//>>css.structure: ../../themes/base/checkboxradio.css
6623//>>css.theme: ../../themes/base/theme.css
6624
6625
6626$.widget( "ui.checkboxradio", [ $.ui.formResetMixin, {
6627	version: "1.13.3",
6628	options: {
6629		disabled: null,
6630		label: null,
6631		icon: true,
6632		classes: {
6633			"ui-checkboxradio-label": "ui-corner-all",
6634			"ui-checkboxradio-icon": "ui-corner-all"
6635		}
6636	},
6637
6638	_getCreateOptions: function() {
6639		var disabled, labels, labelContents;
6640		var options = this._super() || {};
6641
6642		// We read the type here, because it makes more sense to throw a element type error first,
6643		// rather then the error for lack of a label. Often if its the wrong type, it
6644		// won't have a label (e.g. calling on a div, btn, etc)
6645		this._readType();
6646
6647		labels = this.element.labels();
6648
6649		// If there are multiple labels, use the last one
6650		this.label = $( labels[ labels.length - 1 ] );
6651		if ( !this.label.length ) {
6652			$.error( "No label found for checkboxradio widget" );
6653		}
6654
6655		this.originalLabel = "";
6656
6657		// We need to get the label text but this may also need to make sure it does not contain the
6658		// input itself.
6659		// The label contents could be text, html, or a mix. We wrap all elements
6660		// and read the wrapper's `innerHTML` to get a string representation of
6661		// the label, without the input as part of it.
6662		labelContents = this.label.contents().not( this.element[ 0 ] );
6663
6664		if ( labelContents.length ) {
6665			this.originalLabel += labelContents
6666				.clone()
6667				.wrapAll( "<div></div>" )
6668				.parent()
6669				.html();
6670		}
6671
6672		// Set the label option if we found label text
6673		if ( this.originalLabel ) {
6674			options.label = this.originalLabel;
6675		}
6676
6677		disabled = this.element[ 0 ].disabled;
6678		if ( disabled != null ) {
6679			options.disabled = disabled;
6680		}
6681		return options;
6682	},
6683
6684	_create: function() {
6685		var checked = this.element[ 0 ].checked;
6686
6687		this._bindFormResetHandler();
6688
6689		if ( this.options.disabled == null ) {
6690			this.options.disabled = this.element[ 0 ].disabled;
6691		}
6692
6693		this._setOption( "disabled", this.options.disabled );
6694		this._addClass( "ui-checkboxradio", "ui-helper-hidden-accessible" );
6695		this._addClass( this.label, "ui-checkboxradio-label", "ui-button ui-widget" );
6696
6697		if ( this.type === "radio" ) {
6698			this._addClass( this.label, "ui-checkboxradio-radio-label" );
6699		}
6700
6701		if ( this.options.label && this.options.label !== this.originalLabel ) {
6702			this._updateLabel();
6703		} else if ( this.originalLabel ) {
6704			this.options.label = this.originalLabel;
6705		}
6706
6707		this._enhance();
6708
6709		if ( checked ) {
6710			this._addClass( this.label, "ui-checkboxradio-checked", "ui-state-active" );
6711		}
6712
6713		this._on( {
6714			change: "_toggleClasses",
6715			focus: function() {
6716				this._addClass( this.label, null, "ui-state-focus ui-visual-focus" );
6717			},
6718			blur: function() {
6719				this._removeClass( this.label, null, "ui-state-focus ui-visual-focus" );
6720			}
6721		} );
6722	},
6723
6724	_readType: function() {
6725		var nodeName = this.element[ 0 ].nodeName.toLowerCase();
6726		this.type = this.element[ 0 ].type;
6727		if ( nodeName !== "input" || !/radio|checkbox/.test( this.type ) ) {
6728			$.error( "Can't create checkboxradio on element.nodeName=" + nodeName +
6729				" and element.type=" + this.type );
6730		}
6731	},
6732
6733	// Support jQuery Mobile enhanced option
6734	_enhance: function() {
6735		this._updateIcon( this.element[ 0 ].checked );
6736	},
6737
6738	widget: function() {
6739		return this.label;
6740	},
6741
6742	_getRadioGroup: function() {
6743		var group;
6744		var name = this.element[ 0 ].name;
6745		var nameSelector = "input[name='" + $.escapeSelector( name ) + "']";
6746
6747		if ( !name ) {
6748			return $( [] );
6749		}
6750
6751		if ( this.form.length ) {
6752			group = $( this.form[ 0 ].elements ).filter( nameSelector );
6753		} else {
6754
6755			// Not inside a form, check all inputs that also are not inside a form
6756			group = $( nameSelector ).filter( function() {
6757				return $( this )._form().length === 0;
6758			} );
6759		}
6760
6761		return group.not( this.element );
6762	},
6763
6764	_toggleClasses: function() {
6765		var checked = this.element[ 0 ].checked;
6766		this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked );
6767
6768		if ( this.options.icon && this.type === "checkbox" ) {
6769			this._toggleClass( this.icon, null, "ui-icon-check ui-state-checked", checked )
6770				._toggleClass( this.icon, null, "ui-icon-blank", !checked );
6771		}
6772
6773		if ( this.type === "radio" ) {
6774			this._getRadioGroup()
6775				.each( function() {
6776					var instance = $( this ).checkboxradio( "instance" );
6777
6778					if ( instance ) {
6779						instance._removeClass( instance.label,
6780							"ui-checkboxradio-checked", "ui-state-active" );
6781					}
6782				} );
6783		}
6784	},
6785
6786	_destroy: function() {
6787		this._unbindFormResetHandler();
6788
6789		if ( this.icon ) {
6790			this.icon.remove();
6791			this.iconSpace.remove();
6792		}
6793	},
6794
6795	_setOption: function( key, value ) {
6796
6797		// We don't allow the value to be set to nothing
6798		if ( key === "label" && !value ) {
6799			return;
6800		}
6801
6802		this._super( key, value );
6803
6804		if ( key === "disabled" ) {
6805			this._toggleClass( this.label, null, "ui-state-disabled", value );
6806			this.element[ 0 ].disabled = value;
6807
6808			// Don't refresh when setting disabled
6809			return;
6810		}
6811		this.refresh();
6812	},
6813
6814	_updateIcon: function( checked ) {
6815		var toAdd = "ui-icon ui-icon-background ";
6816
6817		if ( this.options.icon ) {
6818			if ( !this.icon ) {
6819				this.icon = $( "<span>" );
6820				this.iconSpace = $( "<span> </span>" );
6821				this._addClass( this.iconSpace, "ui-checkboxradio-icon-space" );
6822			}
6823
6824			if ( this.type === "checkbox" ) {
6825				toAdd += checked ? "ui-icon-check ui-state-checked" : "ui-icon-blank";
6826				this._removeClass( this.icon, null, checked ? "ui-icon-blank" : "ui-icon-check" );
6827			} else {
6828				toAdd += "ui-icon-blank";
6829			}
6830			this._addClass( this.icon, "ui-checkboxradio-icon", toAdd );
6831			if ( !checked ) {
6832				this._removeClass( this.icon, null, "ui-icon-check ui-state-checked" );
6833			}
6834			this.icon.prependTo( this.label ).after( this.iconSpace );
6835		} else if ( this.icon !== undefined ) {
6836			this.icon.remove();
6837			this.iconSpace.remove();
6838			delete this.icon;
6839		}
6840	},
6841
6842	_updateLabel: function() {
6843
6844		// Remove the contents of the label ( minus the icon, icon space, and input )
6845		var contents = this.label.contents().not( this.element[ 0 ] );
6846		if ( this.icon ) {
6847			contents = contents.not( this.icon[ 0 ] );
6848		}
6849		if ( this.iconSpace ) {
6850			contents = contents.not( this.iconSpace[ 0 ] );
6851		}
6852		contents.remove();
6853
6854		this.label.append( this.options.label );
6855	},
6856
6857	refresh: function() {
6858		var checked = this.element[ 0 ].checked,
6859			isDisabled = this.element[ 0 ].disabled;
6860
6861		this._updateIcon( checked );
6862		this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked );
6863		if ( this.options.label !== null ) {
6864			this._updateLabel();
6865		}
6866
6867		if ( isDisabled !== this.options.disabled ) {
6868			this._setOptions( { "disabled": isDisabled } );
6869		}
6870	}
6871
6872} ] );
6873
6874var widgetsCheckboxradio = $.ui.checkboxradio;
6875
6876
6877/*!
6878 * jQuery UI Button 1.13.3
6879 * https://jqueryui.com
6880 *
6881 * Copyright OpenJS Foundation and other contributors
6882 * Released under the MIT license.
6883 * https://jquery.org/license
6884 */
6885
6886//>>label: Button
6887//>>group: Widgets
6888//>>description: Enhances a form with themeable buttons.
6889//>>docs: https://api.jqueryui.com/button/
6890//>>demos: https://jqueryui.com/button/
6891//>>css.structure: ../../themes/base/core.css
6892//>>css.structure: ../../themes/base/button.css
6893//>>css.theme: ../../themes/base/theme.css
6894
6895
6896$.widget( "ui.button", {
6897	version: "1.13.3",
6898	defaultElement: "<button>",
6899	options: {
6900		classes: {
6901			"ui-button": "ui-corner-all"
6902		},
6903		disabled: null,
6904		icon: null,
6905		iconPosition: "beginning",
6906		label: null,
6907		showLabel: true
6908	},
6909
6910	_getCreateOptions: function() {
6911		var disabled,
6912
6913			// This is to support cases like in jQuery Mobile where the base widget does have
6914			// an implementation of _getCreateOptions
6915			options = this._super() || {};
6916
6917		this.isInput = this.element.is( "input" );
6918
6919		disabled = this.element[ 0 ].disabled;
6920		if ( disabled != null ) {
6921			options.disabled = disabled;
6922		}
6923
6924		this.originalLabel = this.isInput ? this.element.val() : this.element.html();
6925		if ( this.originalLabel ) {
6926			options.label = this.originalLabel;
6927		}
6928
6929		return options;
6930	},
6931
6932	_create: function() {
6933		if ( !this.option.showLabel & !this.options.icon ) {
6934			this.options.showLabel = true;
6935		}
6936
6937		// We have to check the option again here even though we did in _getCreateOptions,
6938		// because null may have been passed on init which would override what was set in
6939		// _getCreateOptions
6940		if ( this.options.disabled == null ) {
6941			this.options.disabled = this.element[ 0 ].disabled || false;
6942		}
6943
6944		this.hasTitle = !!this.element.attr( "title" );
6945
6946		// Check to see if the label needs to be set or if its already correct
6947		if ( this.options.label && this.options.label !== this.originalLabel ) {
6948			if ( this.isInput ) {
6949				this.element.val( this.options.label );
6950			} else {
6951				this.element.html( this.options.label );
6952			}
6953		}
6954		this._addClass( "ui-button", "ui-widget" );
6955		this._setOption( "disabled", this.options.disabled );
6956		this._enhance();
6957
6958		if ( this.element.is( "a" ) ) {
6959			this._on( {
6960				"keyup": function( event ) {
6961					if ( event.keyCode === $.ui.keyCode.SPACE ) {
6962						event.preventDefault();
6963
6964						// Support: PhantomJS <= 1.9, IE 8 Only
6965						// If a native click is available use it so we actually cause navigation
6966						// otherwise just trigger a click event
6967						if ( this.element[ 0 ].click ) {
6968							this.element[ 0 ].click();
6969						} else {
6970							this.element.trigger( "click" );
6971						}
6972					}
6973				}
6974			} );
6975		}
6976	},
6977
6978	_enhance: function() {
6979		if ( !this.element.is( "button" ) ) {
6980			this.element.attr( "role", "button" );
6981		}
6982
6983		if ( this.options.icon ) {
6984			this._updateIcon( "icon", this.options.icon );
6985			this._updateTooltip();
6986		}
6987	},
6988
6989	_updateTooltip: function() {
6990		this.title = this.element.attr( "title" );
6991
6992		if ( !this.options.showLabel && !this.title ) {
6993			this.element.attr( "title", this.options.label );
6994		}
6995	},
6996
6997	_updateIcon: function( option, value ) {
6998		var icon = option !== "iconPosition",
6999			position = icon ? this.options.iconPosition : value,
7000			displayBlock = position === "top" || position === "bottom";
7001
7002		// Create icon
7003		if ( !this.icon ) {
7004			this.icon = $( "<span>" );
7005
7006			this._addClass( this.icon, "ui-button-icon", "ui-icon" );
7007
7008			if ( !this.options.showLabel ) {
7009				this._addClass( "ui-button-icon-only" );
7010			}
7011		} else if ( icon ) {
7012
7013			// If we are updating the icon remove the old icon class
7014			this._removeClass( this.icon, null, this.options.icon );
7015		}
7016
7017		// If we are updating the icon add the new icon class
7018		if ( icon ) {
7019			this._addClass( this.icon, null, value );
7020		}
7021
7022		this._attachIcon( position );
7023
7024		// If the icon is on top or bottom we need to add the ui-widget-icon-block class and remove
7025		// the iconSpace if there is one.
7026		if ( displayBlock ) {
7027			this._addClass( this.icon, null, "ui-widget-icon-block" );
7028			if ( this.iconSpace ) {
7029				this.iconSpace.remove();
7030			}
7031		} else {
7032
7033			// Position is beginning or end so remove the ui-widget-icon-block class and add the
7034			// space if it does not exist
7035			if ( !this.iconSpace ) {
7036				this.iconSpace = $( "<span> </span>" );
7037				this._addClass( this.iconSpace, "ui-button-icon-space" );
7038			}
7039			this._removeClass( this.icon, null, "ui-wiget-icon-block" );
7040			this._attachIconSpace( position );
7041		}
7042	},
7043
7044	_destroy: function() {
7045		this.element.removeAttr( "role" );
7046
7047		if ( this.icon ) {
7048			this.icon.remove();
7049		}
7050		if ( this.iconSpace ) {
7051			this.iconSpace.remove();
7052		}
7053		if ( !this.hasTitle ) {
7054			this.element.removeAttr( "title" );
7055		}
7056	},
7057
7058	_attachIconSpace: function( iconPosition ) {
7059		this.icon[ /^(?:end|bottom)/.test( iconPosition ) ? "before" : "after" ]( this.iconSpace );
7060	},
7061
7062	_attachIcon: function( iconPosition ) {
7063		this.element[ /^(?:end|bottom)/.test( iconPosition ) ? "append" : "prepend" ]( this.icon );
7064	},
7065
7066	_setOptions: function( options ) {
7067		var newShowLabel = options.showLabel === undefined ?
7068				this.options.showLabel :
7069				options.showLabel,
7070			newIcon = options.icon === undefined ? this.options.icon : options.icon;
7071
7072		if ( !newShowLabel && !newIcon ) {
7073			options.showLabel = true;
7074		}
7075		this._super( options );
7076	},
7077
7078	_setOption: function( key, value ) {
7079		if ( key === "icon" ) {
7080			if ( value ) {
7081				this._updateIcon( key, value );
7082			} else if ( this.icon ) {
7083				this.icon.remove();
7084				if ( this.iconSpace ) {
7085					this.iconSpace.remove();
7086				}
7087			}
7088		}
7089
7090		if ( key === "iconPosition" ) {
7091			this._updateIcon( key, value );
7092		}
7093
7094		// Make sure we can't end up with a button that has neither text nor icon
7095		if ( key === "showLabel" ) {
7096				this._toggleClass( "ui-button-icon-only", null, !value );
7097				this._updateTooltip();
7098		}
7099
7100		if ( key === "label" ) {
7101			if ( this.isInput ) {
7102				this.element.val( value );
7103			} else {
7104
7105				// If there is an icon, append it, else nothing then append the value
7106				// this avoids removal of the icon when setting label text
7107				this.element.html( value );
7108				if ( this.icon ) {
7109					this._attachIcon( this.options.iconPosition );
7110					this._attachIconSpace( this.options.iconPosition );
7111				}
7112			}
7113		}
7114
7115		this._super( key, value );
7116
7117		if ( key === "disabled" ) {
7118			this._toggleClass( null, "ui-state-disabled", value );
7119			this.element[ 0 ].disabled = value;
7120			if ( value ) {
7121				this.element.trigger( "blur" );
7122			}
7123		}
7124	},
7125
7126	refresh: function() {
7127
7128		// Make sure to only check disabled if its an element that supports this otherwise
7129		// check for the disabled class to determine state
7130		var isDisabled = this.element.is( "input, button" ) ?
7131			this.element[ 0 ].disabled : this.element.hasClass( "ui-button-disabled" );
7132
7133		if ( isDisabled !== this.options.disabled ) {
7134			this._setOptions( { disabled: isDisabled } );
7135		}
7136
7137		this._updateTooltip();
7138	}
7139} );
7140
7141// DEPRECATED
7142if ( $.uiBackCompat !== false ) {
7143
7144	// Text and Icons options
7145	$.widget( "ui.button", $.ui.button, {
7146		options: {
7147			text: true,
7148			icons: {
7149				primary: null,
7150				secondary: null
7151			}
7152		},
7153
7154		_create: function() {
7155			if ( this.options.showLabel && !this.options.text ) {
7156				this.options.showLabel = this.options.text;
7157			}
7158			if ( !this.options.showLabel && this.options.text ) {
7159				this.options.text = this.options.showLabel;
7160			}
7161			if ( !this.options.icon && ( this.options.icons.primary ||
7162					this.options.icons.secondary ) ) {
7163				if ( this.options.icons.primary ) {
7164					this.options.icon = this.options.icons.primary;
7165				} else {
7166					this.options.icon = this.options.icons.secondary;
7167					this.options.iconPosition = "end";
7168				}
7169			} else if ( this.options.icon ) {
7170				this.options.icons.primary = this.options.icon;
7171			}
7172			this._super();
7173		},
7174
7175		_setOption: function( key, value ) {
7176			if ( key === "text" ) {
7177				this._super( "showLabel", value );
7178				return;
7179			}
7180			if ( key === "showLabel" ) {
7181				this.options.text = value;
7182			}
7183			if ( key === "icon" ) {
7184				this.options.icons.primary = value;
7185			}
7186			if ( key === "icons" ) {
7187				if ( value.primary ) {
7188					this._super( "icon", value.primary );
7189					this._super( "iconPosition", "beginning" );
7190				} else if ( value.secondary ) {
7191					this._super( "icon", value.secondary );
7192					this._super( "iconPosition", "end" );
7193				}
7194			}
7195			this._superApply( arguments );
7196		}
7197	} );
7198
7199	$.fn.button = ( function( orig ) {
7200		return function( options ) {
7201			var isMethodCall = typeof options === "string";
7202			var args = Array.prototype.slice.call( arguments, 1 );
7203			var returnValue = this;
7204
7205			if ( isMethodCall ) {
7206
7207				// If this is an empty collection, we need to have the instance method
7208				// return undefined instead of the jQuery instance
7209				if ( !this.length && options === "instance" ) {
7210					returnValue = undefined;
7211				} else {
7212					this.each( function() {
7213						var methodValue;
7214						var type = $( this ).attr( "type" );
7215						var name = type !== "checkbox" && type !== "radio" ?
7216							"button" :
7217							"checkboxradio";
7218						var instance = $.data( this, "ui-" + name );
7219
7220						if ( options === "instance" ) {
7221							returnValue = instance;
7222							return false;
7223						}
7224
7225						if ( !instance ) {
7226							return $.error( "cannot call methods on button" +
7227								" prior to initialization; " +
7228								"attempted to call method '" + options + "'" );
7229						}
7230
7231						if ( typeof instance[ options ] !== "function" ||
7232							options.charAt( 0 ) === "_" ) {
7233							return $.error( "no such method '" + options + "' for button" +
7234								" widget instance" );
7235						}
7236
7237						methodValue = instance[ options ].apply( instance, args );
7238
7239						if ( methodValue !== instance && methodValue !== undefined ) {
7240							returnValue = methodValue && methodValue.jquery ?
7241								returnValue.pushStack( methodValue.get() ) :
7242								methodValue;
7243							return false;
7244						}
7245					} );
7246				}
7247			} else {
7248
7249				// Allow multiple hashes to be passed on init
7250				if ( args.length ) {
7251					options = $.widget.extend.apply( null, [ options ].concat( args ) );
7252				}
7253
7254				this.each( function() {
7255					var type = $( this ).attr( "type" );
7256					var name = type !== "checkbox" && type !== "radio" ? "button" : "checkboxradio";
7257					var instance = $.data( this, "ui-" + name );
7258
7259					if ( instance ) {
7260						instance.option( options || {} );
7261						if ( instance._init ) {
7262							instance._init();
7263						}
7264					} else {
7265						if ( name === "button" ) {
7266							orig.call( $( this ), options );
7267							return;
7268						}
7269
7270						$( this ).checkboxradio( $.extend( { icon: false }, options ) );
7271					}
7272				} );
7273			}
7274
7275			return returnValue;
7276		};
7277	} )( $.fn.button );
7278
7279	$.fn.buttonset = function() {
7280		if ( !$.ui.controlgroup ) {
7281			$.error( "Controlgroup widget missing" );
7282		}
7283		if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" && arguments[ 2 ] ) {
7284			return this.controlgroup.apply( this,
7285				[ arguments[ 0 ], "items.button", arguments[ 2 ] ] );
7286		}
7287		if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" ) {
7288			return this.controlgroup.apply( this, [ arguments[ 0 ], "items.button" ] );
7289		}
7290		if ( typeof arguments[ 0 ] === "object" && arguments[ 0 ].items ) {
7291			arguments[ 0 ].items = {
7292				button: arguments[ 0 ].items
7293			};
7294		}
7295		return this.controlgroup.apply( this, arguments );
7296	};
7297}
7298
7299var widgetsButton = $.ui.button;
7300
7301
7302/* eslint-disable max-len, camelcase */
7303/*!
7304 * jQuery UI Datepicker 1.13.3
7305 * https://jqueryui.com
7306 *
7307 * Copyright OpenJS Foundation and other contributors
7308 * Released under the MIT license.
7309 * https://jquery.org/license
7310 */
7311
7312//>>label: Datepicker
7313//>>group: Widgets
7314//>>description: Displays a calendar from an input or inline for selecting dates.
7315//>>docs: https://api.jqueryui.com/datepicker/
7316//>>demos: https://jqueryui.com/datepicker/
7317//>>css.structure: ../../themes/base/core.css
7318//>>css.structure: ../../themes/base/datepicker.css
7319//>>css.theme: ../../themes/base/theme.css
7320
7321
7322$.extend( $.ui, { datepicker: { version: "1.13.3" } } );
7323
7324var datepicker_instActive;
7325
7326function datepicker_getZindex( elem ) {
7327	var position, value;
7328	while ( elem.length && elem[ 0 ] !== document ) {
7329
7330		// Ignore z-index if position is set to a value where z-index is ignored by the browser
7331		// This makes behavior of this function consistent across browsers
7332		// WebKit always returns auto if the element is positioned
7333		position = elem.css( "position" );
7334		if ( position === "absolute" || position === "relative" || position === "fixed" ) {
7335
7336			// IE returns 0 when zIndex is not specified
7337			// other browsers return a string
7338			// we ignore the case of nested elements with an explicit value of 0
7339			// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
7340			value = parseInt( elem.css( "zIndex" ), 10 );
7341			if ( !isNaN( value ) && value !== 0 ) {
7342				return value;
7343			}
7344		}
7345		elem = elem.parent();
7346	}
7347
7348	return 0;
7349}
7350
7351/* Date picker manager.
7352   Use the singleton instance of this class, $.datepicker, to interact with the date picker.
7353   Settings for (groups of) date pickers are maintained in an instance object,
7354   allowing multiple different settings on the same page. */
7355
7356function Datepicker() {
7357	this._curInst = null; // The current instance in use
7358	this._keyEvent = false; // If the last event was a key event
7359	this._disabledInputs = []; // List of date picker inputs that have been disabled
7360	this._datepickerShowing = false; // True if the popup picker is showing , false if not
7361	this._inDialog = false; // True if showing within a "dialog", false if not
7362	this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division
7363	this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class
7364	this._appendClass = "ui-datepicker-append"; // The name of the append marker class
7365	this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class
7366	this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class
7367	this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class
7368	this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class
7369	this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class
7370	this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class
7371	this.regional = []; // Available regional settings, indexed by language code
7372	this.regional[ "" ] = { // Default regional settings
7373		closeText: "Done", // Display text for close link
7374		prevText: "Prev", // Display text for previous month link
7375		nextText: "Next", // Display text for next month link
7376		currentText: "Today", // Display text for current month link
7377		monthNames: [ "January", "February", "March", "April", "May", "June",
7378			"July", "August", "September", "October", "November", "December" ], // Names of months for drop-down and formatting
7379		monthNamesShort: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ], // For formatting
7380		dayNames: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], // For formatting
7381		dayNamesShort: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], // For formatting
7382		dayNamesMin: [ "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" ], // Column headings for days starting at Sunday
7383		weekHeader: "Wk", // Column header for week of the year
7384		dateFormat: "mm/dd/yy", // See format options on parseDate
7385		firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
7386		isRTL: false, // True if right-to-left language, false if left-to-right
7387		showMonthAfterYear: false, // True if the year select precedes month, false for month then year
7388		yearSuffix: "", // Additional text to append to the year in the month headers,
7389		selectMonthLabel: "Select month", // Invisible label for month selector
7390		selectYearLabel: "Select year" // Invisible label for year selector
7391	};
7392	this._defaults = { // Global defaults for all the date picker instances
7393		showOn: "focus", // "focus" for popup on focus,
7394			// "button" for trigger button, or "both" for either
7395		showAnim: "fadeIn", // Name of jQuery animation for popup
7396		showOptions: {}, // Options for enhanced animations
7397		defaultDate: null, // Used when field is blank: actual date,
7398			// +/-number for offset from today, null for today
7399		appendText: "", // Display text following the input box, e.g. showing the format
7400		buttonText: "...", // Text for trigger button
7401		buttonImage: "", // URL for trigger button image
7402		buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
7403		hideIfNoPrevNext: false, // True to hide next/previous month links
7404			// if not applicable, false to just disable them
7405		navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
7406		gotoCurrent: false, // True if today link goes back to current selection instead
7407		changeMonth: false, // True if month can be selected directly, false if only prev/next
7408		changeYear: false, // True if year can be selected directly, false if only prev/next
7409		yearRange: "c-10:c+10", // Range of years to display in drop-down,
7410			// either relative to today's year (-nn:+nn), relative to currently displayed year
7411			// (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
7412		showOtherMonths: false, // True to show dates in other months, false to leave blank
7413		selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
7414		showWeek: false, // True to show week of the year, false to not show it
7415		calculateWeek: this.iso8601Week, // How to calculate the week of the year,
7416			// takes a Date and returns the number of the week for it
7417		shortYearCutoff: "+10", // Short year values < this are in the current century,
7418			// > this are in the previous century,
7419			// string value starting with "+" for current year + value
7420		minDate: null, // The earliest selectable date, or null for no limit
7421		maxDate: null, // The latest selectable date, or null for no limit
7422		duration: "fast", // Duration of display/closure
7423		beforeShowDay: null, // Function that takes a date and returns an array with
7424			// [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "",
7425			// [2] = cell title (optional), e.g. $.datepicker.noWeekends
7426		beforeShow: null, // Function that takes an input field and
7427			// returns a set of custom settings for the date picker
7428		onSelect: null, // Define a callback function when a date is selected
7429		onChangeMonthYear: null, // Define a callback function when the month or year is changed
7430		onClose: null, // Define a callback function when the datepicker is closed
7431		onUpdateDatepicker: null, // Define a callback function when the datepicker is updated
7432		numberOfMonths: 1, // Number of months to show at a time
7433		showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
7434		stepMonths: 1, // Number of months to step back/forward
7435		stepBigMonths: 12, // Number of months to step back/forward for the big links
7436		altField: "", // Selector for an alternate field to store selected dates into
7437		altFormat: "", // The date format to use for the alternate field
7438		constrainInput: true, // The input is constrained by the current date format
7439		showButtonPanel: false, // True to show button panel, false to not show it
7440		autoSize: false, // True to size the input for the date format, false to leave as is
7441		disabled: false // The initial disabled state
7442	};
7443	$.extend( this._defaults, this.regional[ "" ] );
7444	this.regional.en = $.extend( true, {}, this.regional[ "" ] );
7445	this.regional[ "en-US" ] = $.extend( true, {}, this.regional.en );
7446	this.dpDiv = datepicker_bindHover( $( "<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) );
7447}
7448
7449$.extend( Datepicker.prototype, {
7450
7451	/* Class name added to elements to indicate already configured with a date picker. */
7452	markerClassName: "hasDatepicker",
7453
7454	//Keep track of the maximum number of rows displayed (see #7043)
7455	maxRows: 4,
7456
7457	// TODO rename to "widget" when switching to widget factory
7458	_widgetDatepicker: function() {
7459		return this.dpDiv;
7460	},
7461
7462	/* Override the default settings for all instances of the date picker.
7463	 * @param  settings  object - the new settings to use as defaults (anonymous object)
7464	 * @return the manager object
7465	 */
7466	setDefaults: function( settings ) {
7467		datepicker_extendRemove( this._defaults, settings || {} );
7468		return this;
7469	},
7470
7471	/* Attach the date picker to a jQuery selection.
7472	 * @param  target	element - the target input field or division or span
7473	 * @param  settings  object - the new settings to use for this date picker instance (anonymous)
7474	 */
7475	_attachDatepicker: function( target, settings ) {
7476		var nodeName, inline, inst;
7477		nodeName = target.nodeName.toLowerCase();
7478		inline = ( nodeName === "div" || nodeName === "span" );
7479		if ( !target.id ) {
7480			this.uuid += 1;
7481			target.id = "dp" + this.uuid;
7482		}
7483		inst = this._newInst( $( target ), inline );
7484		inst.settings = $.extend( {}, settings || {} );
7485		if ( nodeName === "input" ) {
7486			this._connectDatepicker( target, inst );
7487		} else if ( inline ) {
7488			this._inlineDatepicker( target, inst );
7489		}
7490	},
7491
7492	/* Create a new instance object. */
7493	_newInst: function( target, inline ) {
7494		var id = target[ 0 ].id.replace( /([^A-Za-z0-9_\-])/g, "\\\\$1" ); // escape jQuery meta chars
7495		return { id: id, input: target, // associated target
7496			selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
7497			drawMonth: 0, drawYear: 0, // month being drawn
7498			inline: inline, // is datepicker inline or not
7499			dpDiv: ( !inline ? this.dpDiv : // presentation div
7500			datepicker_bindHover( $( "<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) ) ) };
7501	},
7502
7503	/* Attach the date picker to an input field. */
7504	_connectDatepicker: function( target, inst ) {
7505		var input = $( target );
7506		inst.append = $( [] );
7507		inst.trigger = $( [] );
7508		if ( input.hasClass( this.markerClassName ) ) {
7509			return;
7510		}
7511		this._attachments( input, inst );
7512		input.addClass( this.markerClassName ).on( "keydown", this._doKeyDown ).
7513			on( "keypress", this._doKeyPress ).on( "keyup", this._doKeyUp );
7514		this._autoSize( inst );
7515		$.data( target, "datepicker", inst );
7516
7517		//If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
7518		if ( inst.settings.disabled ) {
7519			this._disableDatepicker( target );
7520		}
7521	},
7522
7523	/* Make attachments based on settings. */
7524	_attachments: function( input, inst ) {
7525		var showOn, buttonText, buttonImage,
7526			appendText = this._get( inst, "appendText" ),
7527			isRTL = this._get( inst, "isRTL" );
7528
7529		if ( inst.append ) {
7530			inst.append.remove();
7531		}
7532		if ( appendText ) {
7533			inst.append = $( "<span>" )
7534				.addClass( this._appendClass )
7535				.text( appendText );
7536			input[ isRTL ? "before" : "after" ]( inst.append );
7537		}
7538
7539		input.off( "focus", this._showDatepicker );
7540
7541		if ( inst.trigger ) {
7542			inst.trigger.remove();
7543		}
7544
7545		showOn = this._get( inst, "showOn" );
7546		if ( showOn === "focus" || showOn === "both" ) { // pop-up date picker when in the marked field
7547			input.on( "focus", this._showDatepicker );
7548		}
7549		if ( showOn === "button" || showOn === "both" ) { // pop-up date picker when button clicked
7550			buttonText = this._get( inst, "buttonText" );
7551			buttonImage = this._get( inst, "buttonImage" );
7552
7553			if ( this._get( inst, "buttonImageOnly" ) ) {
7554				inst.trigger = $( "<img>" )
7555					.addClass( this._triggerClass )
7556					.attr( {
7557						src: buttonImage,
7558						alt: buttonText,
7559						title: buttonText
7560					} );
7561			} else {
7562				inst.trigger = $( "<button type='button'>" )
7563					.addClass( this._triggerClass );
7564				if ( buttonImage ) {
7565					inst.trigger.html(
7566						$( "<img>" )
7567							.attr( {
7568								src: buttonImage,
7569								alt: buttonText,
7570								title: buttonText
7571							} )
7572					);
7573				} else {
7574					inst.trigger.text( buttonText );
7575				}
7576			}
7577
7578			input[ isRTL ? "before" : "after" ]( inst.trigger );
7579			inst.trigger.on( "click", function() {
7580				if ( $.datepicker._datepickerShowing && $.datepicker._lastInput === input[ 0 ] ) {
7581					$.datepicker._hideDatepicker();
7582				} else if ( $.datepicker._datepickerShowing && $.datepicker._lastInput !== input[ 0 ] ) {
7583					$.datepicker._hideDatepicker();
7584					$.datepicker._showDatepicker( input[ 0 ] );
7585				} else {
7586					$.datepicker._showDatepicker( input[ 0 ] );
7587				}
7588				return false;
7589			} );
7590		}
7591	},
7592
7593	/* Apply the maximum length for the date format. */
7594	_autoSize: function( inst ) {
7595		if ( this._get( inst, "autoSize" ) && !inst.inline ) {
7596			var findMax, max, maxI, i,
7597				date = new Date( 2009, 12 - 1, 20 ), // Ensure double digits
7598				dateFormat = this._get( inst, "dateFormat" );
7599
7600			if ( dateFormat.match( /[DM]/ ) ) {
7601				findMax = function( names ) {
7602					max = 0;
7603					maxI = 0;
7604					for ( i = 0; i < names.length; i++ ) {
7605						if ( names[ i ].length > max ) {
7606							max = names[ i ].length;
7607							maxI = i;
7608						}
7609					}
7610					return maxI;
7611				};
7612				date.setMonth( findMax( this._get( inst, ( dateFormat.match( /MM/ ) ?
7613					"monthNames" : "monthNamesShort" ) ) ) );
7614				date.setDate( findMax( this._get( inst, ( dateFormat.match( /DD/ ) ?
7615					"dayNames" : "dayNamesShort" ) ) ) + 20 - date.getDay() );
7616			}
7617			inst.input.attr( "size", this._formatDate( inst, date ).length );
7618		}
7619	},
7620
7621	/* Attach an inline date picker to a div. */
7622	_inlineDatepicker: function( target, inst ) {
7623		var divSpan = $( target );
7624		if ( divSpan.hasClass( this.markerClassName ) ) {
7625			return;
7626		}
7627		divSpan.addClass( this.markerClassName ).append( inst.dpDiv );
7628		$.data( target, "datepicker", inst );
7629		this._setDate( inst, this._getDefaultDate( inst ), true );
7630		this._updateDatepicker( inst );
7631		this._updateAlternate( inst );
7632
7633		//If disabled option is true, disable the datepicker before showing it (see ticket #5665)
7634		if ( inst.settings.disabled ) {
7635			this._disableDatepicker( target );
7636		}
7637
7638		// Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
7639		// https://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
7640		inst.dpDiv.css( "display", "block" );
7641	},
7642
7643	/* Pop-up the date picker in a "dialog" box.
7644	 * @param  input element - ignored
7645	 * @param  date	string or Date - the initial date to display
7646	 * @param  onSelect  function - the function to call when a date is selected
7647	 * @param  settings  object - update the dialog date picker instance's settings (anonymous object)
7648	 * @param  pos int[2] - coordinates for the dialog's position within the screen or
7649	 *					event - with x/y coordinates or
7650	 *					leave empty for default (screen centre)
7651	 * @return the manager object
7652	 */
7653	_dialogDatepicker: function( input, date, onSelect, settings, pos ) {
7654		var id, browserWidth, browserHeight, scrollX, scrollY,
7655			inst = this._dialogInst; // internal instance
7656
7657		if ( !inst ) {
7658			this.uuid += 1;
7659			id = "dp" + this.uuid;
7660			this._dialogInput = $( "<input type='text' id='" + id +
7661				"' style='position: absolute; top: -100px; width: 0px;'/>" );
7662			this._dialogInput.on( "keydown", this._doKeyDown );
7663			$( "body" ).append( this._dialogInput );
7664			inst = this._dialogInst = this._newInst( this._dialogInput, false );
7665			inst.settings = {};
7666			$.data( this._dialogInput[ 0 ], "datepicker", inst );
7667		}
7668		datepicker_extendRemove( inst.settings, settings || {} );
7669		date = ( date && date.constructor === Date ? this._formatDate( inst, date ) : date );
7670		this._dialogInput.val( date );
7671
7672		this._pos = ( pos ? ( pos.length ? pos : [ pos.pageX, pos.pageY ] ) : null );
7673		if ( !this._pos ) {
7674			browserWidth = document.documentElement.clientWidth;
7675			browserHeight = document.documentElement.clientHeight;
7676			scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
7677			scrollY = document.documentElement.scrollTop || document.body.scrollTop;
7678			this._pos = // should use actual width/height below
7679				[ ( browserWidth / 2 ) - 100 + scrollX, ( browserHeight / 2 ) - 150 + scrollY ];
7680		}
7681
7682		// Move input on screen for focus, but hidden behind dialog
7683		this._dialogInput.css( "left", ( this._pos[ 0 ] + 20 ) + "px" ).css( "top", this._pos[ 1 ] + "px" );
7684		inst.settings.onSelect = onSelect;
7685		this._inDialog = true;
7686		this.dpDiv.addClass( this._dialogClass );
7687		this._showDatepicker( this._dialogInput[ 0 ] );
7688		if ( $.blockUI ) {
7689			$.blockUI( this.dpDiv );
7690		}
7691		$.data( this._dialogInput[ 0 ], "datepicker", inst );
7692		return this;
7693	},
7694
7695	/* Detach a datepicker from its control.
7696	 * @param  target	element - the target input field or division or span
7697	 */
7698	_destroyDatepicker: function( target ) {
7699		var nodeName,
7700			$target = $( target ),
7701			inst = $.data( target, "datepicker" );
7702
7703		if ( !$target.hasClass( this.markerClassName ) ) {
7704			return;
7705		}
7706
7707		nodeName = target.nodeName.toLowerCase();
7708		$.removeData( target, "datepicker" );
7709		if ( nodeName === "input" ) {
7710			inst.append.remove();
7711			inst.trigger.remove();
7712			$target.removeClass( this.markerClassName ).
7713				off( "focus", this._showDatepicker ).
7714				off( "keydown", this._doKeyDown ).
7715				off( "keypress", this._doKeyPress ).
7716				off( "keyup", this._doKeyUp );
7717		} else if ( nodeName === "div" || nodeName === "span" ) {
7718			$target.removeClass( this.markerClassName ).empty();
7719		}
7720
7721		if ( datepicker_instActive === inst ) {
7722			datepicker_instActive = null;
7723			this._curInst = null;
7724		}
7725	},
7726
7727	/* Enable the date picker to a jQuery selection.
7728	 * @param  target	element - the target input field or division or span
7729	 */
7730	_enableDatepicker: function( target ) {
7731		var nodeName, inline,
7732			$target = $( target ),
7733			inst = $.data( target, "datepicker" );
7734
7735		if ( !$target.hasClass( this.markerClassName ) ) {
7736			return;
7737		}
7738
7739		nodeName = target.nodeName.toLowerCase();
7740		if ( nodeName === "input" ) {
7741			target.disabled = false;
7742			inst.trigger.filter( "button" ).
7743				each( function() {
7744					this.disabled = false;
7745				} ).end().
7746				filter( "img" ).css( { opacity: "1.0", cursor: "" } );
7747		} else if ( nodeName === "div" || nodeName === "span" ) {
7748			inline = $target.children( "." + this._inlineClass );
7749			inline.children().removeClass( "ui-state-disabled" );
7750			inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ).
7751				prop( "disabled", false );
7752		}
7753		this._disabledInputs = $.map( this._disabledInputs,
7754
7755			// Delete entry
7756			function( value ) {
7757				return ( value === target ? null : value );
7758			} );
7759	},
7760
7761	/* Disable the date picker to a jQuery selection.
7762	 * @param  target	element - the target input field or division or span
7763	 */
7764	_disableDatepicker: function( target ) {
7765		var nodeName, inline,
7766			$target = $( target ),
7767			inst = $.data( target, "datepicker" );
7768
7769		if ( !$target.hasClass( this.markerClassName ) ) {
7770			return;
7771		}
7772
7773		nodeName = target.nodeName.toLowerCase();
7774		if ( nodeName === "input" ) {
7775			target.disabled = true;
7776			inst.trigger.filter( "button" ).
7777				each( function() {
7778					this.disabled = true;
7779				} ).end().
7780				filter( "img" ).css( { opacity: "0.5", cursor: "default" } );
7781		} else if ( nodeName === "div" || nodeName === "span" ) {
7782			inline = $target.children( "." + this._inlineClass );
7783			inline.children().addClass( "ui-state-disabled" );
7784			inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ).
7785				prop( "disabled", true );
7786		}
7787		this._disabledInputs = $.map( this._disabledInputs,
7788
7789			// Delete entry
7790			function( value ) {
7791				return ( value === target ? null : value );
7792			} );
7793		this._disabledInputs[ this._disabledInputs.length ] = target;
7794	},
7795
7796	/* Is the first field in a jQuery collection disabled as a datepicker?
7797	 * @param  target	element - the target input field or division or span
7798	 * @return boolean - true if disabled, false if enabled
7799	 */
7800	_isDisabledDatepicker: function( target ) {
7801		if ( !target ) {
7802			return false;
7803		}
7804		for ( var i = 0; i < this._disabledInputs.length; i++ ) {
7805			if ( this._disabledInputs[ i ] === target ) {
7806				return true;
7807			}
7808		}
7809		return false;
7810	},
7811
7812	/* Retrieve the instance data for the target control.
7813	 * @param  target  element - the target input field or division or span
7814	 * @return  object - the associated instance data
7815	 * @throws  error if a jQuery problem getting data
7816	 */
7817	_getInst: function( target ) {
7818		try {
7819			return $.data( target, "datepicker" );
7820		} catch ( err ) {
7821			throw "Missing instance data for this datepicker";
7822		}
7823	},
7824
7825	/* Update or retrieve the settings for a date picker attached to an input field or division.
7826	 * @param  target  element - the target input field or division or span
7827	 * @param  name	object - the new settings to update or
7828	 *				string - the name of the setting to change or retrieve,
7829	 *				when retrieving also "all" for all instance settings or
7830	 *				"defaults" for all global defaults
7831	 * @param  value   any - the new value for the setting
7832	 *				(omit if above is an object or to retrieve a value)
7833	 */
7834	_optionDatepicker: function( target, name, value ) {
7835		var settings, date, minDate, maxDate,
7836			inst = this._getInst( target );
7837
7838		if ( arguments.length === 2 && typeof name === "string" ) {
7839			return ( name === "defaults" ? $.extend( {}, $.datepicker._defaults ) :
7840				( inst ? ( name === "all" ? $.extend( {}, inst.settings ) :
7841				this._get( inst, name ) ) : null ) );
7842		}
7843
7844		settings = name || {};
7845		if ( typeof name === "string" ) {
7846			settings = {};
7847			settings[ name ] = value;
7848		}
7849
7850		if ( inst ) {
7851			if ( this._curInst === inst ) {
7852				this._hideDatepicker();
7853			}
7854
7855			date = this._getDateDatepicker( target, true );
7856			minDate = this._getMinMaxDate( inst, "min" );
7857			maxDate = this._getMinMaxDate( inst, "max" );
7858			datepicker_extendRemove( inst.settings, settings );
7859
7860			// reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
7861			if ( minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined ) {
7862				inst.settings.minDate = this._formatDate( inst, minDate );
7863			}
7864			if ( maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined ) {
7865				inst.settings.maxDate = this._formatDate( inst, maxDate );
7866			}
7867			if ( "disabled" in settings ) {
7868				if ( settings.disabled ) {
7869					this._disableDatepicker( target );
7870				} else {
7871					this._enableDatepicker( target );
7872				}
7873			}
7874			this._attachments( $( target ), inst );
7875			this._autoSize( inst );
7876			this._setDate( inst, date );
7877			this._updateAlternate( inst );
7878			this._updateDatepicker( inst );
7879		}
7880	},
7881
7882	// Change method deprecated
7883	_changeDatepicker: function( target, name, value ) {
7884		this._optionDatepicker( target, name, value );
7885	},
7886
7887	/* Redraw the date picker attached to an input field or division.
7888	 * @param  target  element - the target input field or division or span
7889	 */
7890	_refreshDatepicker: function( target ) {
7891		var inst = this._getInst( target );
7892		if ( inst ) {
7893			this._updateDatepicker( inst );
7894		}
7895	},
7896
7897	/* Set the dates for a jQuery selection.
7898	 * @param  target element - the target input field or division or span
7899	 * @param  date	Date - the new date
7900	 */
7901	_setDateDatepicker: function( target, date ) {
7902		var inst = this._getInst( target );
7903		if ( inst ) {
7904			this._setDate( inst, date );
7905			this._updateDatepicker( inst );
7906			this._updateAlternate( inst );
7907		}
7908	},
7909
7910	/* Get the date(s) for the first entry in a jQuery selection.
7911	 * @param  target element - the target input field or division or span
7912	 * @param  noDefault boolean - true if no default date is to be used
7913	 * @return Date - the current date
7914	 */
7915	_getDateDatepicker: function( target, noDefault ) {
7916		var inst = this._getInst( target );
7917		if ( inst && !inst.inline ) {
7918			this._setDateFromField( inst, noDefault );
7919		}
7920		return ( inst ? this._getDate( inst ) : null );
7921	},
7922
7923	/* Handle keystrokes. */
7924	_doKeyDown: function( event ) {
7925		var onSelect, dateStr, sel,
7926			inst = $.datepicker._getInst( event.target ),
7927			handled = true,
7928			isRTL = inst.dpDiv.is( ".ui-datepicker-rtl" );
7929
7930		inst._keyEvent = true;
7931		if ( $.datepicker._datepickerShowing ) {
7932			switch ( event.keyCode ) {
7933				case 9: $.datepicker._hideDatepicker();
7934						handled = false;
7935						break; // hide on tab out
7936				case 13: sel = $( "td." + $.datepicker._dayOverClass + ":not(." +
7937									$.datepicker._currentClass + ")", inst.dpDiv );
7938						if ( sel[ 0 ] ) {
7939							$.datepicker._selectDay( event.target, inst.selectedMonth, inst.selectedYear, sel[ 0 ] );
7940						}
7941
7942						onSelect = $.datepicker._get( inst, "onSelect" );
7943						if ( onSelect ) {
7944							dateStr = $.datepicker._formatDate( inst );
7945
7946							// Trigger custom callback
7947							onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] );
7948						} else {
7949							$.datepicker._hideDatepicker();
7950						}
7951
7952						return false; // don't submit the form
7953				case 27: $.datepicker._hideDatepicker();
7954						break; // hide on escape
7955				case 33: $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
7956							-$.datepicker._get( inst, "stepBigMonths" ) :
7957							-$.datepicker._get( inst, "stepMonths" ) ), "M" );
7958						break; // previous month/year on page up/+ ctrl
7959				case 34: $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
7960							+$.datepicker._get( inst, "stepBigMonths" ) :
7961							+$.datepicker._get( inst, "stepMonths" ) ), "M" );
7962						break; // next month/year on page down/+ ctrl
7963				case 35: if ( event.ctrlKey || event.metaKey ) {
7964							$.datepicker._clearDate( event.target );
7965						}
7966						handled = event.ctrlKey || event.metaKey;
7967						break; // clear on ctrl or command +end
7968				case 36: if ( event.ctrlKey || event.metaKey ) {
7969							$.datepicker._gotoToday( event.target );
7970						}
7971						handled = event.ctrlKey || event.metaKey;
7972						break; // current on ctrl or command +home
7973				case 37: if ( event.ctrlKey || event.metaKey ) {
7974							$.datepicker._adjustDate( event.target, ( isRTL ? +1 : -1 ), "D" );
7975						}
7976						handled = event.ctrlKey || event.metaKey;
7977
7978						// -1 day on ctrl or command +left
7979						if ( event.originalEvent.altKey ) {
7980							$.datepicker._adjustDate( event.target, ( event.ctrlKey ?
7981								-$.datepicker._get( inst, "stepBigMonths" ) :
7982								-$.datepicker._get( inst, "stepMonths" ) ), "M" );
7983						}
7984
7985						// next month/year on alt +left on Mac
7986						break;
7987				case 38: if ( event.ctrlKey || event.metaKey ) {
7988							$.datepicker._adjustDate( event.target, -7, "D" );
7989						}
7990						handled = event.ctrlKey || event.metaKey;
7991						break; // -1 week on ctrl or command +up
7992				case 39: if ( event.ctrlKey || event.metaKey ) {
7993							$.datepicker._adjustDate( event.target, ( isRTL ? -1 : +1 ), "D" );
7994						}
7995						handled = event.ctrlKey || event.metaKey;
7996
7997						// +1 day on ctrl or command +right
7998						if ( event.originalEvent.altKey ) {
7999							$.datepicker._adjustDate( event.target, ( event.ctrlKey ?
8000								+$.datepicker._get( inst, "stepBigMonths" ) :
8001								+$.datepicker._get( inst, "stepMonths" ) ), "M" );
8002						}
8003
8004						// next month/year on alt +right
8005						break;
8006				case 40: if ( event.ctrlKey || event.metaKey ) {
8007							$.datepicker._adjustDate( event.target, +7, "D" );
8008						}
8009						handled = event.ctrlKey || event.metaKey;
8010						break; // +1 week on ctrl or command +down
8011				default: handled = false;
8012			}
8013		} else if ( event.keyCode === 36 && event.ctrlKey ) { // display the date picker on ctrl+home
8014			$.datepicker._showDatepicker( this );
8015		} else {
8016			handled = false;
8017		}
8018
8019		if ( handled ) {
8020			event.preventDefault();
8021			event.stopPropagation();
8022		}
8023	},
8024
8025	/* Filter entered characters - based on date format. */
8026	_doKeyPress: function( event ) {
8027		var chars, chr,
8028			inst = $.datepicker._getInst( event.target );
8029
8030		if ( $.datepicker._get( inst, "constrainInput" ) ) {
8031			chars = $.datepicker._possibleChars( $.datepicker._get( inst, "dateFormat" ) );
8032			chr = String.fromCharCode( event.charCode == null ? event.keyCode : event.charCode );
8033			return event.ctrlKey || event.metaKey || ( chr < " " || !chars || chars.indexOf( chr ) > -1 );
8034		}
8035	},
8036
8037	/* Synchronise manual entry and field/alternate field. */
8038	_doKeyUp: function( event ) {
8039		var date,
8040			inst = $.datepicker._getInst( event.target );
8041
8042		if ( inst.input.val() !== inst.lastVal ) {
8043			try {
8044				date = $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ),
8045					( inst.input ? inst.input.val() : null ),
8046					$.datepicker._getFormatConfig( inst ) );
8047
8048				if ( date ) { // only if valid
8049					$.datepicker._setDateFromField( inst );
8050					$.datepicker._updateAlternate( inst );
8051					$.datepicker._updateDatepicker( inst );
8052				}
8053			} catch ( err ) {
8054			}
8055		}
8056		return true;
8057	},
8058
8059	/* Pop-up the date picker for a given input field.
8060	 * If false returned from beforeShow event handler do not show.
8061	 * @param  input  element - the input field attached to the date picker or
8062	 *					event - if triggered by focus
8063	 */
8064	_showDatepicker: function( input ) {
8065		input = input.target || input;
8066		if ( input.nodeName.toLowerCase() !== "input" ) { // find from button/image trigger
8067			input = $( "input", input.parentNode )[ 0 ];
8068		}
8069
8070		if ( $.datepicker._isDisabledDatepicker( input ) || $.datepicker._lastInput === input ) { // already here
8071			return;
8072		}
8073
8074		var inst, beforeShow, beforeShowSettings, isFixed,
8075			offset, showAnim, duration;
8076
8077		inst = $.datepicker._getInst( input );
8078		if ( $.datepicker._curInst && $.datepicker._curInst !== inst ) {
8079			$.datepicker._curInst.dpDiv.stop( true, true );
8080			if ( inst && $.datepicker._datepickerShowing ) {
8081				$.datepicker._hideDatepicker( $.datepicker._curInst.input[ 0 ] );
8082			}
8083		}
8084
8085		beforeShow = $.datepicker._get( inst, "beforeShow" );
8086		beforeShowSettings = beforeShow ? beforeShow.apply( input, [ input, inst ] ) : {};
8087		if ( beforeShowSettings === false ) {
8088			return;
8089		}
8090		datepicker_extendRemove( inst.settings, beforeShowSettings );
8091
8092		inst.lastVal = null;
8093		$.datepicker._lastInput = input;
8094		$.datepicker._setDateFromField( inst );
8095
8096		if ( $.datepicker._inDialog ) { // hide cursor
8097			input.value = "";
8098		}
8099		if ( !$.datepicker._pos ) { // position below input
8100			$.datepicker._pos = $.datepicker._findPos( input );
8101			$.datepicker._pos[ 1 ] += input.offsetHeight; // add the height
8102		}
8103
8104		isFixed = false;
8105		$( input ).parents().each( function() {
8106			isFixed |= $( this ).css( "position" ) === "fixed";
8107			return !isFixed;
8108		} );
8109
8110		offset = { left: $.datepicker._pos[ 0 ], top: $.datepicker._pos[ 1 ] };
8111		$.datepicker._pos = null;
8112
8113		//to avoid flashes on Firefox
8114		inst.dpDiv.empty();
8115
8116		// determine sizing offscreen
8117		inst.dpDiv.css( { position: "absolute", display: "block", top: "-1000px" } );
8118		$.datepicker._updateDatepicker( inst );
8119
8120		// fix width for dynamic number of date pickers
8121		// and adjust position before showing
8122		offset = $.datepicker._checkOffset( inst, offset, isFixed );
8123		inst.dpDiv.css( { position: ( $.datepicker._inDialog && $.blockUI ?
8124			"static" : ( isFixed ? "fixed" : "absolute" ) ), display: "none",
8125			left: offset.left + "px", top: offset.top + "px" } );
8126
8127		if ( !inst.inline ) {
8128			showAnim = $.datepicker._get( inst, "showAnim" );
8129			duration = $.datepicker._get( inst, "duration" );
8130			inst.dpDiv.css( "z-index", datepicker_getZindex( $( input ) ) + 1 );
8131			$.datepicker._datepickerShowing = true;
8132
8133			if ( $.effects && $.effects.effect[ showAnim ] ) {
8134				inst.dpDiv.show( showAnim, $.datepicker._get( inst, "showOptions" ), duration );
8135			} else {
8136				inst.dpDiv[ showAnim || "show" ]( showAnim ? duration : null );
8137			}
8138
8139			if ( $.datepicker._shouldFocusInput( inst ) ) {
8140				inst.input.trigger( "focus" );
8141			}
8142
8143			$.datepicker._curInst = inst;
8144		}
8145	},
8146
8147	/* Generate the date picker content. */
8148	_updateDatepicker: function( inst ) {
8149		this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
8150		datepicker_instActive = inst; // for delegate hover events
8151		inst.dpDiv.empty().append( this._generateHTML( inst ) );
8152		this._attachHandlers( inst );
8153
8154		var origyearshtml,
8155			numMonths = this._getNumberOfMonths( inst ),
8156			cols = numMonths[ 1 ],
8157			width = 17,
8158			activeCell = inst.dpDiv.find( "." + this._dayOverClass + " a" ),
8159			onUpdateDatepicker = $.datepicker._get( inst, "onUpdateDatepicker" );
8160
8161		if ( activeCell.length > 0 ) {
8162			datepicker_handleMouseover.apply( activeCell.get( 0 ) );
8163		}
8164
8165		inst.dpDiv.removeClass( "ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4" ).width( "" );
8166		if ( cols > 1 ) {
8167			inst.dpDiv.addClass( "ui-datepicker-multi-" + cols ).css( "width", ( width * cols ) + "em" );
8168		}
8169		inst.dpDiv[ ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ? "add" : "remove" ) +
8170			"Class" ]( "ui-datepicker-multi" );
8171		inst.dpDiv[ ( this._get( inst, "isRTL" ) ? "add" : "remove" ) +
8172			"Class" ]( "ui-datepicker-rtl" );
8173
8174		if ( inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {
8175			inst.input.trigger( "focus" );
8176		}
8177
8178		// Deffered render of the years select (to avoid flashes on Firefox)
8179		if ( inst.yearshtml ) {
8180			origyearshtml = inst.yearshtml;
8181			setTimeout( function() {
8182
8183				//assure that inst.yearshtml didn't change.
8184				if ( origyearshtml === inst.yearshtml && inst.yearshtml ) {
8185					inst.dpDiv.find( "select.ui-datepicker-year" ).first().replaceWith( inst.yearshtml );
8186				}
8187				origyearshtml = inst.yearshtml = null;
8188			}, 0 );
8189		}
8190
8191		if ( onUpdateDatepicker ) {
8192			onUpdateDatepicker.apply( ( inst.input ? inst.input[ 0 ] : null ), [ inst ] );
8193		}
8194	},
8195
8196	// #6694 - don't focus the input if it's already focused
8197	// this breaks the change event in IE
8198	// Support: IE and jQuery <1.9
8199	_shouldFocusInput: function( inst ) {
8200		return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" );
8201	},
8202
8203	/* Check positioning to remain on screen. */
8204	_checkOffset: function( inst, offset, isFixed ) {
8205		var dpWidth = inst.dpDiv.outerWidth(),
8206			dpHeight = inst.dpDiv.outerHeight(),
8207			inputWidth = inst.input ? inst.input.outerWidth() : 0,
8208			inputHeight = inst.input ? inst.input.outerHeight() : 0,
8209			viewWidth = document.documentElement.clientWidth + ( isFixed ? 0 : $( document ).scrollLeft() ),
8210			viewHeight = document.documentElement.clientHeight + ( isFixed ? 0 : $( document ).scrollTop() );
8211
8212		offset.left -= ( this._get( inst, "isRTL" ) ? ( dpWidth - inputWidth ) : 0 );
8213		offset.left -= ( isFixed && offset.left === inst.input.offset().left ) ? $( document ).scrollLeft() : 0;
8214		offset.top -= ( isFixed && offset.top === ( inst.input.offset().top + inputHeight ) ) ? $( document ).scrollTop() : 0;
8215
8216		// Now check if datepicker is showing outside window viewport - move to a better place if so.
8217		offset.left -= Math.min( offset.left, ( offset.left + dpWidth > viewWidth && viewWidth > dpWidth ) ?
8218			Math.abs( offset.left + dpWidth - viewWidth ) : 0 );
8219		offset.top -= Math.min( offset.top, ( offset.top + dpHeight > viewHeight && viewHeight > dpHeight ) ?
8220			Math.abs( dpHeight + inputHeight ) : 0 );
8221
8222		return offset;
8223	},
8224
8225	/* Find an object's position on the screen. */
8226	_findPos: function( obj ) {
8227		var position,
8228			inst = this._getInst( obj ),
8229			isRTL = this._get( inst, "isRTL" );
8230
8231		while ( obj && ( obj.type === "hidden" || obj.nodeType !== 1 || $.expr.pseudos.hidden( obj ) ) ) {
8232			obj = obj[ isRTL ? "previousSibling" : "nextSibling" ];
8233		}
8234
8235		position = $( obj ).offset();
8236		return [ position.left, position.top ];
8237	},
8238
8239	/* Hide the date picker from view.
8240	 * @param  input  element - the input field attached to the date picker
8241	 */
8242	_hideDatepicker: function( input ) {
8243		var showAnim, duration, postProcess, onClose,
8244			inst = this._curInst;
8245
8246		if ( !inst || ( input && inst !== $.data( input, "datepicker" ) ) ) {
8247			return;
8248		}
8249
8250		if ( this._datepickerShowing ) {
8251			showAnim = this._get( inst, "showAnim" );
8252			duration = this._get( inst, "duration" );
8253			postProcess = function() {
8254				$.datepicker._tidyDialog( inst );
8255			};
8256
8257			// DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed
8258			if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) {
8259				inst.dpDiv.hide( showAnim, $.datepicker._get( inst, "showOptions" ), duration, postProcess );
8260			} else {
8261				inst.dpDiv[ ( showAnim === "slideDown" ? "slideUp" :
8262					( showAnim === "fadeIn" ? "fadeOut" : "hide" ) ) ]( ( showAnim ? duration : null ), postProcess );
8263			}
8264
8265			if ( !showAnim ) {
8266				postProcess();
8267			}
8268			this._datepickerShowing = false;
8269
8270			onClose = this._get( inst, "onClose" );
8271			if ( onClose ) {
8272				onClose.apply( ( inst.input ? inst.input[ 0 ] : null ), [ ( inst.input ? inst.input.val() : "" ), inst ] );
8273			}
8274
8275			this._lastInput = null;
8276			if ( this._inDialog ) {
8277				this._dialogInput.css( { position: "absolute", left: "0", top: "-100px" } );
8278				if ( $.blockUI ) {
8279					$.unblockUI();
8280					$( "body" ).append( this.dpDiv );
8281				}
8282			}
8283			this._inDialog = false;
8284		}
8285	},
8286
8287	/* Tidy up after a dialog display. */
8288	_tidyDialog: function( inst ) {
8289		inst.dpDiv.removeClass( this._dialogClass ).off( ".ui-datepicker-calendar" );
8290	},
8291
8292	/* Close date picker if clicked elsewhere. */
8293	_checkExternalClick: function( event ) {
8294		if ( !$.datepicker._curInst ) {
8295			return;
8296		}
8297
8298		var $target = $( event.target ),
8299			inst = $.datepicker._getInst( $target[ 0 ] );
8300
8301		if ( ( ( $target[ 0 ].id !== $.datepicker._mainDivId &&
8302				$target.parents( "#" + $.datepicker._mainDivId ).length === 0 &&
8303				!$target.hasClass( $.datepicker.markerClassName ) &&
8304				!$target.closest( "." + $.datepicker._triggerClass ).length &&
8305				$.datepicker._datepickerShowing && !( $.datepicker._inDialog && $.blockUI ) ) ) ||
8306			( $target.hasClass( $.datepicker.markerClassName ) && $.datepicker._curInst !== inst ) ) {
8307				$.datepicker._hideDatepicker();
8308		}
8309	},
8310
8311	/* Adjust one of the date sub-fields. */
8312	_adjustDate: function( id, offset, period ) {
8313		var target = $( id ),
8314			inst = this._getInst( target[ 0 ] );
8315
8316		if ( this._isDisabledDatepicker( target[ 0 ] ) ) {
8317			return;
8318		}
8319		this._adjustInstDate( inst, offset, period );
8320		this._updateDatepicker( inst );
8321	},
8322
8323	/* Action for current link. */
8324	_gotoToday: function( id ) {
8325		var date,
8326			target = $( id ),
8327			inst = this._getInst( target[ 0 ] );
8328
8329		if ( this._get( inst, "gotoCurrent" ) && inst.currentDay ) {
8330			inst.selectedDay = inst.currentDay;
8331			inst.drawMonth = inst.selectedMonth = inst.currentMonth;
8332			inst.drawYear = inst.selectedYear = inst.currentYear;
8333		} else {
8334			date = new Date();
8335			inst.selectedDay = date.getDate();
8336			inst.drawMonth = inst.selectedMonth = date.getMonth();
8337			inst.drawYear = inst.selectedYear = date.getFullYear();
8338		}
8339		this._notifyChange( inst );
8340		this._adjustDate( target );
8341	},
8342
8343	/* Action for selecting a new month/year. */
8344	_selectMonthYear: function( id, select, period ) {
8345		var target = $( id ),
8346			inst = this._getInst( target[ 0 ] );
8347
8348		inst[ "selected" + ( period === "M" ? "Month" : "Year" ) ] =
8349		inst[ "draw" + ( period === "M" ? "Month" : "Year" ) ] =
8350			parseInt( select.options[ select.selectedIndex ].value, 10 );
8351
8352		this._notifyChange( inst );
8353		this._adjustDate( target );
8354	},
8355
8356	/* Action for selecting a day. */
8357	_selectDay: function( id, month, year, td ) {
8358		var inst,
8359			target = $( id );
8360
8361		if ( $( td ).hasClass( this._unselectableClass ) || this._isDisabledDatepicker( target[ 0 ] ) ) {
8362			return;
8363		}
8364
8365		inst = this._getInst( target[ 0 ] );
8366		inst.selectedDay = inst.currentDay = parseInt( $( "a", td ).attr( "data-date" ) );
8367		inst.selectedMonth = inst.currentMonth = month;
8368		inst.selectedYear = inst.currentYear = year;
8369		this._selectDate( id, this._formatDate( inst,
8370			inst.currentDay, inst.currentMonth, inst.currentYear ) );
8371	},
8372
8373	/* Erase the input field and hide the date picker. */
8374	_clearDate: function( id ) {
8375		var target = $( id );
8376		this._selectDate( target, "" );
8377	},
8378
8379	/* Update the input field with the selected date. */
8380	_selectDate: function( id, dateStr ) {
8381		var onSelect,
8382			target = $( id ),
8383			inst = this._getInst( target[ 0 ] );
8384
8385		dateStr = ( dateStr != null ? dateStr : this._formatDate( inst ) );
8386		if ( inst.input ) {
8387			inst.input.val( dateStr );
8388		}
8389		this._updateAlternate( inst );
8390
8391		onSelect = this._get( inst, "onSelect" );
8392		if ( onSelect ) {
8393			onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] );  // trigger custom callback
8394		} else if ( inst.input ) {
8395			inst.input.trigger( "change" ); // fire the change event
8396		}
8397
8398		if ( inst.inline ) {
8399			this._updateDatepicker( inst );
8400		} else {
8401			this._hideDatepicker();
8402			this._lastInput = inst.input[ 0 ];
8403			if ( typeof( inst.input[ 0 ] ) !== "object" ) {
8404				inst.input.trigger( "focus" ); // restore focus
8405			}
8406			this._lastInput = null;
8407		}
8408	},
8409
8410	/* Update any alternate field to synchronise with the main field. */
8411	_updateAlternate: function( inst ) {
8412		var altFormat, date, dateStr,
8413			altField = this._get( inst, "altField" );
8414
8415		if ( altField ) { // update alternate field too
8416			altFormat = this._get( inst, "altFormat" ) || this._get( inst, "dateFormat" );
8417			date = this._getDate( inst );
8418			dateStr = this.formatDate( altFormat, date, this._getFormatConfig( inst ) );
8419			$( document ).find( altField ).val( dateStr );
8420		}
8421	},
8422
8423	/* Set as beforeShowDay function to prevent selection of weekends.
8424	 * @param  date  Date - the date to customise
8425	 * @return [boolean, string] - is this date selectable?, what is its CSS class?
8426	 */
8427	noWeekends: function( date ) {
8428		var day = date.getDay();
8429		return [ ( day > 0 && day < 6 ), "" ];
8430	},
8431
8432	/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
8433	 * @param  date  Date - the date to get the week for
8434	 * @return  number - the number of the week within the year that contains this date
8435	 */
8436	iso8601Week: function( date ) {
8437		var time,
8438			checkDate = new Date( date.getTime() );
8439
8440		// Find Thursday of this week starting on Monday
8441		checkDate.setDate( checkDate.getDate() + 4 - ( checkDate.getDay() || 7 ) );
8442
8443		time = checkDate.getTime();
8444		checkDate.setMonth( 0 ); // Compare with Jan 1
8445		checkDate.setDate( 1 );
8446		return Math.floor( Math.round( ( time - checkDate ) / 86400000 ) / 7 ) + 1;
8447	},
8448
8449	/* Parse a string value into a date object.
8450	 * See formatDate below for the possible formats.
8451	 *
8452	 * @param  format string - the expected format of the date
8453	 * @param  value string - the date in the above format
8454	 * @param  settings Object - attributes include:
8455	 *					shortYearCutoff  number - the cutoff year for determining the century (optional)
8456	 *					dayNamesShort	string[7] - abbreviated names of the days from Sunday (optional)
8457	 *					dayNames		string[7] - names of the days from Sunday (optional)
8458	 *					monthNamesShort string[12] - abbreviated names of the months (optional)
8459	 *					monthNames		string[12] - names of the months (optional)
8460	 * @return  Date - the extracted date value or null if value is blank
8461	 */
8462	parseDate: function( format, value, settings ) {
8463		if ( format == null || value == null ) {
8464			throw "Invalid arguments";
8465		}
8466
8467		value = ( typeof value === "object" ? value.toString() : value + "" );
8468		if ( value === "" ) {
8469			return null;
8470		}
8471
8472		var iFormat, dim, extra,
8473			iValue = 0,
8474			shortYearCutoffTemp = ( settings ? settings.shortYearCutoff : null ) || this._defaults.shortYearCutoff,
8475			shortYearCutoff = ( typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp :
8476				new Date().getFullYear() % 100 + parseInt( shortYearCutoffTemp, 10 ) ),
8477			dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort,
8478			dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames,
8479			monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort,
8480			monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames,
8481			year = -1,
8482			month = -1,
8483			day = -1,
8484			doy = -1,
8485			literal = false,
8486			date,
8487
8488			// Check whether a format character is doubled
8489			lookAhead = function( match ) {
8490				var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
8491				if ( matches ) {
8492					iFormat++;
8493				}
8494				return matches;
8495			},
8496
8497			// Extract a number from the string value
8498			getNumber = function( match ) {
8499				var isDoubled = lookAhead( match ),
8500					size = ( match === "@" ? 14 : ( match === "!" ? 20 :
8501					( match === "y" && isDoubled ? 4 : ( match === "o" ? 3 : 2 ) ) ) ),
8502					minSize = ( match === "y" ? size : 1 ),
8503					digits = new RegExp( "^\\d{" + minSize + "," + size + "}" ),
8504					num = value.substring( iValue ).match( digits );
8505				if ( !num ) {
8506					throw "Missing number at position " + iValue;
8507				}
8508				iValue += num[ 0 ].length;
8509				return parseInt( num[ 0 ], 10 );
8510			},
8511
8512			// Extract a name from the string value and convert to an index
8513			getName = function( match, shortNames, longNames ) {
8514				var index = -1,
8515					names = $.map( lookAhead( match ) ? longNames : shortNames, function( v, k ) {
8516						return [ [ k, v ] ];
8517					} ).sort( function( a, b ) {
8518						return -( a[ 1 ].length - b[ 1 ].length );
8519					} );
8520
8521				$.each( names, function( i, pair ) {
8522					var name = pair[ 1 ];
8523					if ( value.substr( iValue, name.length ).toLowerCase() === name.toLowerCase() ) {
8524						index = pair[ 0 ];
8525						iValue += name.length;
8526						return false;
8527					}
8528				} );
8529				if ( index !== -1 ) {
8530					return index + 1;
8531				} else {
8532					throw "Unknown name at position " + iValue;
8533				}
8534			},
8535
8536			// Confirm that a literal character matches the string value
8537			checkLiteral = function() {
8538				if ( value.charAt( iValue ) !== format.charAt( iFormat ) ) {
8539					throw "Unexpected literal at position " + iValue;
8540				}
8541				iValue++;
8542			};
8543
8544		for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
8545			if ( literal ) {
8546				if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
8547					literal = false;
8548				} else {
8549					checkLiteral();
8550				}
8551			} else {
8552				switch ( format.charAt( iFormat ) ) {
8553					case "d":
8554						day = getNumber( "d" );
8555						break;
8556					case "D":
8557						getName( "D", dayNamesShort, dayNames );
8558						break;
8559					case "o":
8560						doy = getNumber( "o" );
8561						break;
8562					case "m":
8563						month = getNumber( "m" );
8564						break;
8565					case "M":
8566						month = getName( "M", monthNamesShort, monthNames );
8567						break;
8568					case "y":
8569						year = getNumber( "y" );
8570						break;
8571					case "@":
8572						date = new Date( getNumber( "@" ) );
8573						year = date.getFullYear();
8574						month = date.getMonth() + 1;
8575						day = date.getDate();
8576						break;
8577					case "!":
8578						date = new Date( ( getNumber( "!" ) - this._ticksTo1970 ) / 10000 );
8579						year = date.getFullYear();
8580						month = date.getMonth() + 1;
8581						day = date.getDate();
8582						break;
8583					case "'":
8584						if ( lookAhead( "'" ) ) {
8585							checkLiteral();
8586						} else {
8587							literal = true;
8588						}
8589						break;
8590					default:
8591						checkLiteral();
8592				}
8593			}
8594		}
8595
8596		if ( iValue < value.length ) {
8597			extra = value.substr( iValue );
8598			if ( !/^\s+/.test( extra ) ) {
8599				throw "Extra/unparsed characters found in date: " + extra;
8600			}
8601		}
8602
8603		if ( year === -1 ) {
8604			year = new Date().getFullYear();
8605		} else if ( year < 100 ) {
8606			year += new Date().getFullYear() - new Date().getFullYear() % 100 +
8607				( year <= shortYearCutoff ? 0 : -100 );
8608		}
8609
8610		if ( doy > -1 ) {
8611			month = 1;
8612			day = doy;
8613			do {
8614				dim = this._getDaysInMonth( year, month - 1 );
8615				if ( day <= dim ) {
8616					break;
8617				}
8618				month++;
8619				day -= dim;
8620			} while ( true );
8621		}
8622
8623		date = this._daylightSavingAdjust( new Date( year, month - 1, day ) );
8624		if ( date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day ) {
8625			throw "Invalid date"; // E.g. 31/02/00
8626		}
8627		return date;
8628	},
8629
8630	/* Standard date formats. */
8631	ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601)
8632	COOKIE: "D, dd M yy",
8633	ISO_8601: "yy-mm-dd",
8634	RFC_822: "D, d M y",
8635	RFC_850: "DD, dd-M-y",
8636	RFC_1036: "D, d M y",
8637	RFC_1123: "D, d M yy",
8638	RFC_2822: "D, d M yy",
8639	RSS: "D, d M y", // RFC 822
8640	TICKS: "!",
8641	TIMESTAMP: "@",
8642	W3C: "yy-mm-dd", // ISO 8601
8643
8644	_ticksTo1970: ( ( ( 1970 - 1 ) * 365 + Math.floor( 1970 / 4 ) - Math.floor( 1970 / 100 ) +
8645		Math.floor( 1970 / 400 ) ) * 24 * 60 * 60 * 10000000 ),
8646
8647	/* Format a date object into a string value.
8648	 * The format can be combinations of the following:
8649	 * d  - day of month (no leading zero)
8650	 * dd - day of month (two digit)
8651	 * o  - day of year (no leading zeros)
8652	 * oo - day of year (three digit)
8653	 * D  - day name short
8654	 * DD - day name long
8655	 * m  - month of year (no leading zero)
8656	 * mm - month of year (two digit)
8657	 * M  - month name short
8658	 * MM - month name long
8659	 * y  - year (two digit)
8660	 * yy - year (four digit)
8661	 * @ - Unix timestamp (ms since 01/01/1970)
8662	 * ! - Windows ticks (100ns since 01/01/0001)
8663	 * "..." - literal text
8664	 * '' - single quote
8665	 *
8666	 * @param  format string - the desired format of the date
8667	 * @param  date Date - the date value to format
8668	 * @param  settings Object - attributes include:
8669	 *					dayNamesShort	string[7] - abbreviated names of the days from Sunday (optional)
8670	 *					dayNames		string[7] - names of the days from Sunday (optional)
8671	 *					monthNamesShort string[12] - abbreviated names of the months (optional)
8672	 *					monthNames		string[12] - names of the months (optional)
8673	 * @return  string - the date in the above format
8674	 */
8675	formatDate: function( format, date, settings ) {
8676		if ( !date ) {
8677			return "";
8678		}
8679
8680		var iFormat,
8681			dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort,
8682			dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames,
8683			monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort,
8684			monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames,
8685
8686			// Check whether a format character is doubled
8687			lookAhead = function( match ) {
8688				var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
8689				if ( matches ) {
8690					iFormat++;
8691				}
8692				return matches;
8693			},
8694
8695			// Format a number, with leading zero if necessary
8696			formatNumber = function( match, value, len ) {
8697				var num = "" + value;
8698				if ( lookAhead( match ) ) {
8699					while ( num.length < len ) {
8700						num = "0" + num;
8701					}
8702				}
8703				return num;
8704			},
8705
8706			// Format a name, short or long as requested
8707			formatName = function( match, value, shortNames, longNames ) {
8708				return ( lookAhead( match ) ? longNames[ value ] : shortNames[ value ] );
8709			},
8710			output = "",
8711			literal = false;
8712
8713		if ( date ) {
8714			for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
8715				if ( literal ) {
8716					if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
8717						literal = false;
8718					} else {
8719						output += format.charAt( iFormat );
8720					}
8721				} else {
8722					switch ( format.charAt( iFormat ) ) {
8723						case "d":
8724							output += formatNumber( "d", date.getDate(), 2 );
8725							break;
8726						case "D":
8727							output += formatName( "D", date.getDay(), dayNamesShort, dayNames );
8728							break;
8729						case "o":
8730							output += formatNumber( "o",
8731								Math.round( ( new Date( date.getFullYear(), date.getMonth(), date.getDate() ).getTime() - new Date( date.getFullYear(), 0, 0 ).getTime() ) / 86400000 ), 3 );
8732							break;
8733						case "m":
8734							output += formatNumber( "m", date.getMonth() + 1, 2 );
8735							break;
8736						case "M":
8737							output += formatName( "M", date.getMonth(), monthNamesShort, monthNames );
8738							break;
8739						case "y":
8740							output += ( lookAhead( "y" ) ? date.getFullYear() :
8741								( date.getFullYear() % 100 < 10 ? "0" : "" ) + date.getFullYear() % 100 );
8742							break;
8743						case "@":
8744							output += date.getTime();
8745							break;
8746						case "!":
8747							output += date.getTime() * 10000 + this._ticksTo1970;
8748							break;
8749						case "'":
8750							if ( lookAhead( "'" ) ) {
8751								output += "'";
8752							} else {
8753								literal = true;
8754							}
8755							break;
8756						default:
8757							output += format.charAt( iFormat );
8758					}
8759				}
8760			}
8761		}
8762		return output;
8763	},
8764
8765	/* Extract all possible characters from the date format. */
8766	_possibleChars: function( format ) {
8767		var iFormat,
8768			chars = "",
8769			literal = false,
8770
8771			// Check whether a format character is doubled
8772			lookAhead = function( match ) {
8773				var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
8774				if ( matches ) {
8775					iFormat++;
8776				}
8777				return matches;
8778			};
8779
8780		for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
8781			if ( literal ) {
8782				if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
8783					literal = false;
8784				} else {
8785					chars += format.charAt( iFormat );
8786				}
8787			} else {
8788				switch ( format.charAt( iFormat ) ) {
8789					case "d": case "m": case "y": case "@":
8790						chars += "0123456789";
8791						break;
8792					case "D": case "M":
8793						return null; // Accept anything
8794					case "'":
8795						if ( lookAhead( "'" ) ) {
8796							chars += "'";
8797						} else {
8798							literal = true;
8799						}
8800						break;
8801					default:
8802						chars += format.charAt( iFormat );
8803				}
8804			}
8805		}
8806		return chars;
8807	},
8808
8809	/* Get a setting value, defaulting if necessary. */
8810	_get: function( inst, name ) {
8811		return inst.settings[ name ] !== undefined ?
8812			inst.settings[ name ] : this._defaults[ name ];
8813	},
8814
8815	/* Parse existing date and initialise date picker. */
8816	_setDateFromField: function( inst, noDefault ) {
8817		if ( inst.input.val() === inst.lastVal ) {
8818			return;
8819		}
8820
8821		var dateFormat = this._get( inst, "dateFormat" ),
8822			dates = inst.lastVal = inst.input ? inst.input.val() : null,
8823			defaultDate = this._getDefaultDate( inst ),
8824			date = defaultDate,
8825			settings = this._getFormatConfig( inst );
8826
8827		try {
8828			date = this.parseDate( dateFormat, dates, settings ) || defaultDate;
8829		} catch ( event ) {
8830			dates = ( noDefault ? "" : dates );
8831		}
8832		inst.selectedDay = date.getDate();
8833		inst.drawMonth = inst.selectedMonth = date.getMonth();
8834		inst.drawYear = inst.selectedYear = date.getFullYear();
8835		inst.currentDay = ( dates ? date.getDate() : 0 );
8836		inst.currentMonth = ( dates ? date.getMonth() : 0 );
8837		inst.currentYear = ( dates ? date.getFullYear() : 0 );
8838		this._adjustInstDate( inst );
8839	},
8840
8841	/* Retrieve the default date shown on opening. */
8842	_getDefaultDate: function( inst ) {
8843		return this._restrictMinMax( inst,
8844			this._determineDate( inst, this._get( inst, "defaultDate" ), new Date() ) );
8845	},
8846
8847	/* A date may be specified as an exact value or a relative one. */
8848	_determineDate: function( inst, date, defaultDate ) {
8849		var offsetNumeric = function( offset ) {
8850				var date = new Date();
8851				date.setDate( date.getDate() + offset );
8852				return date;
8853			},
8854			offsetString = function( offset ) {
8855				try {
8856					return $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ),
8857						offset, $.datepicker._getFormatConfig( inst ) );
8858				} catch ( e ) {
8859
8860					// Ignore
8861				}
8862
8863				var date = ( offset.toLowerCase().match( /^c/ ) ?
8864					$.datepicker._getDate( inst ) : null ) || new Date(),
8865					year = date.getFullYear(),
8866					month = date.getMonth(),
8867					day = date.getDate(),
8868					pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,
8869					matches = pattern.exec( offset );
8870
8871				while ( matches ) {
8872					switch ( matches[ 2 ] || "d" ) {
8873						case "d" : case "D" :
8874							day += parseInt( matches[ 1 ], 10 ); break;
8875						case "w" : case "W" :
8876							day += parseInt( matches[ 1 ], 10 ) * 7; break;
8877						case "m" : case "M" :
8878							month += parseInt( matches[ 1 ], 10 );
8879							day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) );
8880							break;
8881						case "y": case "Y" :
8882							year += parseInt( matches[ 1 ], 10 );
8883							day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) );
8884							break;
8885					}
8886					matches = pattern.exec( offset );
8887				}
8888				return new Date( year, month, day );
8889			},
8890			newDate = ( date == null || date === "" ? defaultDate : ( typeof date === "string" ? offsetString( date ) :
8891				( typeof date === "number" ? ( isNaN( date ) ? defaultDate : offsetNumeric( date ) ) : new Date( date.getTime() ) ) ) );
8892
8893		newDate = ( newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate );
8894		if ( newDate ) {
8895			newDate.setHours( 0 );
8896			newDate.setMinutes( 0 );
8897			newDate.setSeconds( 0 );
8898			newDate.setMilliseconds( 0 );
8899		}
8900		return this._daylightSavingAdjust( newDate );
8901	},
8902
8903	/* Handle switch to/from daylight saving.
8904	 * Hours may be non-zero on daylight saving cut-over:
8905	 * > 12 when midnight changeover, but then cannot generate
8906	 * midnight datetime, so jump to 1AM, otherwise reset.
8907	 * @param  date  (Date) the date to check
8908	 * @return  (Date) the corrected date
8909	 */
8910	_daylightSavingAdjust: function( date ) {
8911		if ( !date ) {
8912			return null;
8913		}
8914		date.setHours( date.getHours() > 12 ? date.getHours() + 2 : 0 );
8915		return date;
8916	},
8917
8918	/* Set the date(s) directly. */
8919	_setDate: function( inst, date, noChange ) {
8920		var clear = !date,
8921			origMonth = inst.selectedMonth,
8922			origYear = inst.selectedYear,
8923			newDate = this._restrictMinMax( inst, this._determineDate( inst, date, new Date() ) );
8924
8925		inst.selectedDay = inst.currentDay = newDate.getDate();
8926		inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
8927		inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
8928		if ( ( origMonth !== inst.selectedMonth || origYear !== inst.selectedYear ) && !noChange ) {
8929			this._notifyChange( inst );
8930		}
8931		this._adjustInstDate( inst );
8932		if ( inst.input ) {
8933			inst.input.val( clear ? "" : this._formatDate( inst ) );
8934		}
8935	},
8936
8937	/* Retrieve the date(s) directly. */
8938	_getDate: function( inst ) {
8939		var startDate = ( !inst.currentYear || ( inst.input && inst.input.val() === "" ) ? null :
8940			this._daylightSavingAdjust( new Date(
8941			inst.currentYear, inst.currentMonth, inst.currentDay ) ) );
8942			return startDate;
8943	},
8944
8945	/* Attach the onxxx handlers.  These are declared statically so
8946	 * they work with static code transformers like Caja.
8947	 */
8948	_attachHandlers: function( inst ) {
8949		var stepMonths = this._get( inst, "stepMonths" ),
8950			id = "#" + inst.id.replace( /\\\\/g, "\\" );
8951		inst.dpDiv.find( "[data-handler]" ).map( function() {
8952			var handler = {
8953				prev: function() {
8954					$.datepicker._adjustDate( id, -stepMonths, "M" );
8955				},
8956				next: function() {
8957					$.datepicker._adjustDate( id, +stepMonths, "M" );
8958				},
8959				hide: function() {
8960					$.datepicker._hideDatepicker();
8961				},
8962				today: function() {
8963					$.datepicker._gotoToday( id );
8964				},
8965				selectDay: function() {
8966					$.datepicker._selectDay( id, +this.getAttribute( "data-month" ), +this.getAttribute( "data-year" ), this );
8967					return false;
8968				},
8969				selectMonth: function() {
8970					$.datepicker._selectMonthYear( id, this, "M" );
8971					return false;
8972				},
8973				selectYear: function() {
8974					$.datepicker._selectMonthYear( id, this, "Y" );
8975					return false;
8976				}
8977			};
8978			$( this ).on( this.getAttribute( "data-event" ), handler[ this.getAttribute( "data-handler" ) ] );
8979		} );
8980	},
8981
8982	/* Generate the HTML for the current state of the date picker. */
8983	_generateHTML: function( inst ) {
8984		var maxDraw, prevText, prev, nextText, next, currentText, gotoDate,
8985			controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,
8986			monthNames, monthNamesShort, beforeShowDay, showOtherMonths,
8987			selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,
8988			cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,
8989			printDate, dRow, tbody, daySettings, otherMonth, unselectable,
8990			tempDate = new Date(),
8991			today = this._daylightSavingAdjust(
8992				new Date( tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate() ) ), // clear time
8993			isRTL = this._get( inst, "isRTL" ),
8994			showButtonPanel = this._get( inst, "showButtonPanel" ),
8995			hideIfNoPrevNext = this._get( inst, "hideIfNoPrevNext" ),
8996			navigationAsDateFormat = this._get( inst, "navigationAsDateFormat" ),
8997			numMonths = this._getNumberOfMonths( inst ),
8998			showCurrentAtPos = this._get( inst, "showCurrentAtPos" ),
8999			stepMonths = this._get( inst, "stepMonths" ),
9000			isMultiMonth = ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ),
9001			currentDate = this._daylightSavingAdjust( ( !inst.currentDay ? new Date( 9999, 9, 9 ) :
9002				new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) ),
9003			minDate = this._getMinMaxDate( inst, "min" ),
9004			maxDate = this._getMinMaxDate( inst, "max" ),
9005			drawMonth = inst.drawMonth - showCurrentAtPos,
9006			drawYear = inst.drawYear;
9007
9008		if ( drawMonth < 0 ) {
9009			drawMonth += 12;
9010			drawYear--;
9011		}
9012		if ( maxDate ) {
9013			maxDraw = this._daylightSavingAdjust( new Date( maxDate.getFullYear(),
9014				maxDate.getMonth() - ( numMonths[ 0 ] * numMonths[ 1 ] ) + 1, maxDate.getDate() ) );
9015			maxDraw = ( minDate && maxDraw < minDate ? minDate : maxDraw );
9016			while ( this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 ) ) > maxDraw ) {
9017				drawMonth--;
9018				if ( drawMonth < 0 ) {
9019					drawMonth = 11;
9020					drawYear--;
9021				}
9022			}
9023		}
9024		inst.drawMonth = drawMonth;
9025		inst.drawYear = drawYear;
9026
9027		prevText = this._get( inst, "prevText" );
9028		prevText = ( !navigationAsDateFormat ? prevText : this.formatDate( prevText,
9029			this._daylightSavingAdjust( new Date( drawYear, drawMonth - stepMonths, 1 ) ),
9030			this._getFormatConfig( inst ) ) );
9031
9032		if ( this._canAdjustMonth( inst, -1, drawYear, drawMonth ) ) {
9033			prev = $( "<a>" )
9034				.attr( {
9035					"class": "ui-datepicker-prev ui-corner-all",
9036					"data-handler": "prev",
9037					"data-event": "click",
9038					title: prevText
9039				} )
9040				.append(
9041					$( "<span>" )
9042						.addClass( "ui-icon ui-icon-circle-triangle-" +
9043							( isRTL ? "e" : "w" ) )
9044						.text( prevText )
9045				)[ 0 ].outerHTML;
9046		} else if ( hideIfNoPrevNext ) {
9047			prev = "";
9048		} else {
9049			prev = $( "<a>" )
9050				.attr( {
9051					"class": "ui-datepicker-prev ui-corner-all ui-state-disabled",
9052					title: prevText
9053				} )
9054				.append(
9055					$( "<span>" )
9056						.addClass( "ui-icon ui-icon-circle-triangle-" +
9057							( isRTL ? "e" : "w" ) )
9058						.text( prevText )
9059				)[ 0 ].outerHTML;
9060		}
9061
9062		nextText = this._get( inst, "nextText" );
9063		nextText = ( !navigationAsDateFormat ? nextText : this.formatDate( nextText,
9064			this._daylightSavingAdjust( new Date( drawYear, drawMonth + stepMonths, 1 ) ),
9065			this._getFormatConfig( inst ) ) );
9066
9067		if ( this._canAdjustMonth( inst, +1, drawYear, drawMonth ) ) {
9068			next = $( "<a>" )
9069				.attr( {
9070					"class": "ui-datepicker-next ui-corner-all",
9071					"data-handler": "next",
9072					"data-event": "click",
9073					title: nextText
9074				} )
9075				.append(
9076					$( "<span>" )
9077						.addClass( "ui-icon ui-icon-circle-triangle-" +
9078							( isRTL ? "w" : "e" ) )
9079						.text( nextText )
9080				)[ 0 ].outerHTML;
9081		} else if ( hideIfNoPrevNext ) {
9082			next = "";
9083		} else {
9084			next = $( "<a>" )
9085				.attr( {
9086					"class": "ui-datepicker-next ui-corner-all ui-state-disabled",
9087					title: nextText
9088				} )
9089				.append(
9090					$( "<span>" )
9091						.attr( "class", "ui-icon ui-icon-circle-triangle-" +
9092							( isRTL ? "w" : "e" ) )
9093						.text( nextText )
9094				)[ 0 ].outerHTML;
9095		}
9096
9097		currentText = this._get( inst, "currentText" );
9098		gotoDate = ( this._get( inst, "gotoCurrent" ) && inst.currentDay ? currentDate : today );
9099		currentText = ( !navigationAsDateFormat ? currentText :
9100			this.formatDate( currentText, gotoDate, this._getFormatConfig( inst ) ) );
9101
9102		controls = "";
9103		if ( !inst.inline ) {
9104			controls = $( "<button>" )
9105				.attr( {
9106					type: "button",
9107					"class": "ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all",
9108					"data-handler": "hide",
9109					"data-event": "click"
9110				} )
9111				.text( this._get( inst, "closeText" ) )[ 0 ].outerHTML;
9112		}
9113
9114		buttonPanel = "";
9115		if ( showButtonPanel ) {
9116			buttonPanel = $( "<div class='ui-datepicker-buttonpane ui-widget-content'>" )
9117				.append( isRTL ? controls : "" )
9118				.append( this._isInRange( inst, gotoDate ) ?
9119					$( "<button>" )
9120						.attr( {
9121							type: "button",
9122							"class": "ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all",
9123							"data-handler": "today",
9124							"data-event": "click"
9125						} )
9126						.text( currentText ) :
9127					"" )
9128				.append( isRTL ? "" : controls )[ 0 ].outerHTML;
9129		}
9130
9131		firstDay = parseInt( this._get( inst, "firstDay" ), 10 );
9132		firstDay = ( isNaN( firstDay ) ? 0 : firstDay );
9133
9134		showWeek = this._get( inst, "showWeek" );
9135		dayNames = this._get( inst, "dayNames" );
9136		dayNamesMin = this._get( inst, "dayNamesMin" );
9137		monthNames = this._get( inst, "monthNames" );
9138		monthNamesShort = this._get( inst, "monthNamesShort" );
9139		beforeShowDay = this._get( inst, "beforeShowDay" );
9140		showOtherMonths = this._get( inst, "showOtherMonths" );
9141		selectOtherMonths = this._get( inst, "selectOtherMonths" );
9142		defaultDate = this._getDefaultDate( inst );
9143		html = "";
9144
9145		for ( row = 0; row < numMonths[ 0 ]; row++ ) {
9146			group = "";
9147			this.maxRows = 4;
9148			for ( col = 0; col < numMonths[ 1 ]; col++ ) {
9149				selectedDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, inst.selectedDay ) );
9150				cornerClass = " ui-corner-all";
9151				calender = "";
9152				if ( isMultiMonth ) {
9153					calender += "<div class='ui-datepicker-group";
9154					if ( numMonths[ 1 ] > 1 ) {
9155						switch ( col ) {
9156							case 0: calender += " ui-datepicker-group-first";
9157								cornerClass = " ui-corner-" + ( isRTL ? "right" : "left" ); break;
9158							case numMonths[ 1 ] - 1: calender += " ui-datepicker-group-last";
9159								cornerClass = " ui-corner-" + ( isRTL ? "left" : "right" ); break;
9160							default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break;
9161						}
9162					}
9163					calender += "'>";
9164				}
9165				calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" +
9166					( /all|left/.test( cornerClass ) && row === 0 ? ( isRTL ? next : prev ) : "" ) +
9167					( /all|right/.test( cornerClass ) && row === 0 ? ( isRTL ? prev : next ) : "" ) +
9168					this._generateMonthYearHeader( inst, drawMonth, drawYear, minDate, maxDate,
9169					row > 0 || col > 0, monthNames, monthNamesShort ) + // draw month headers
9170					"</div><table class='ui-datepicker-calendar'><thead>" +
9171					"<tr>";
9172				thead = ( showWeek ? "<th class='ui-datepicker-week-col'>" + this._get( inst, "weekHeader" ) + "</th>" : "" );
9173				for ( dow = 0; dow < 7; dow++ ) { // days of the week
9174					day = ( dow + firstDay ) % 7;
9175					thead += "<th scope='col'" + ( ( dow + firstDay + 6 ) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "" ) + ">" +
9176						"<span title='" + dayNames[ day ] + "'>" + dayNamesMin[ day ] + "</span></th>";
9177				}
9178				calender += thead + "</tr></thead><tbody>";
9179				daysInMonth = this._getDaysInMonth( drawYear, drawMonth );
9180				if ( drawYear === inst.selectedYear && drawMonth === inst.selectedMonth ) {
9181					inst.selectedDay = Math.min( inst.selectedDay, daysInMonth );
9182				}
9183				leadDays = ( this._getFirstDayOfMonth( drawYear, drawMonth ) - firstDay + 7 ) % 7;
9184				curRows = Math.ceil( ( leadDays + daysInMonth ) / 7 ); // calculate the number of rows to generate
9185				numRows = ( isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows ); //If multiple months, use the higher number of rows (see #7043)
9186				this.maxRows = numRows;
9187				printDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 - leadDays ) );
9188				for ( dRow = 0; dRow < numRows; dRow++ ) { // create date picker rows
9189					calender += "<tr>";
9190					tbody = ( !showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
9191						this._get( inst, "calculateWeek" )( printDate ) + "</td>" );
9192					for ( dow = 0; dow < 7; dow++ ) { // create date picker days
9193						daySettings = ( beforeShowDay ?
9194							beforeShowDay.apply( ( inst.input ? inst.input[ 0 ] : null ), [ printDate ] ) : [ true, "" ] );
9195						otherMonth = ( printDate.getMonth() !== drawMonth );
9196						unselectable = ( otherMonth && !selectOtherMonths ) || !daySettings[ 0 ] ||
9197							( minDate && printDate < minDate ) || ( maxDate && printDate > maxDate );
9198						tbody += "<td class='" +
9199							( ( dow + firstDay + 6 ) % 7 >= 5 ? " ui-datepicker-week-end" : "" ) + // highlight weekends
9200							( otherMonth ? " ui-datepicker-other-month" : "" ) + // highlight days from other months
9201							( ( printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent ) || // user pressed key
9202							( defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime() ) ?
9203
9204							// or defaultDate is current printedDate and defaultDate is selectedDate
9205							" " + this._dayOverClass : "" ) + // highlight selected day
9206							( unselectable ? " " + this._unselectableClass + " ui-state-disabled" : "" ) +  // highlight unselectable days
9207							( otherMonth && !showOtherMonths ? "" : " " + daySettings[ 1 ] + // highlight custom dates
9208							( printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "" ) + // highlight selected day
9209							( printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "" ) ) + "'" + // highlight today (if different)
9210							( ( !otherMonth || showOtherMonths ) && daySettings[ 2 ] ? " title='" + daySettings[ 2 ].replace( /'/g, "&#39;" ) + "'" : "" ) + // cell title
9211							( unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'" ) + ">" + // actions
9212							( otherMonth && !showOtherMonths ? "&#xa0;" : // display for other months
9213							( unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" +
9214							( printDate.getTime() === today.getTime() ? " ui-state-highlight" : "" ) +
9215							( printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "" ) + // highlight selected day
9216							( otherMonth ? " ui-priority-secondary" : "" ) + // distinguish dates from other months
9217							"' href='#' aria-current='" + ( printDate.getTime() === currentDate.getTime() ? "true" : "false" ) + // mark date as selected for screen reader
9218							"' data-date='" + printDate.getDate() + // store date as data
9219							"'>" + printDate.getDate() + "</a>" ) ) + "</td>"; // display selectable date
9220						printDate.setDate( printDate.getDate() + 1 );
9221						printDate = this._daylightSavingAdjust( printDate );
9222					}
9223					calender += tbody + "</tr>";
9224				}
9225				drawMonth++;
9226				if ( drawMonth > 11 ) {
9227					drawMonth = 0;
9228					drawYear++;
9229				}
9230				calender += "</tbody></table>" + ( isMultiMonth ? "</div>" +
9231							( ( numMonths[ 0 ] > 0 && col === numMonths[ 1 ] - 1 ) ? "<div class='ui-datepicker-row-break'></div>" : "" ) : "" );
9232				group += calender;
9233			}
9234			html += group;
9235		}
9236		html += buttonPanel;
9237		inst._keyEvent = false;
9238		return html;
9239	},
9240
9241	/* Generate the month and year header. */
9242	_generateMonthYearHeader: function( inst, drawMonth, drawYear, minDate, maxDate,
9243			secondary, monthNames, monthNamesShort ) {
9244
9245		var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,
9246			changeMonth = this._get( inst, "changeMonth" ),
9247			changeYear = this._get( inst, "changeYear" ),
9248			showMonthAfterYear = this._get( inst, "showMonthAfterYear" ),
9249			selectMonthLabel = this._get( inst, "selectMonthLabel" ),
9250			selectYearLabel = this._get( inst, "selectYearLabel" ),
9251			html = "<div class='ui-datepicker-title'>",
9252			monthHtml = "";
9253
9254		// Month selection
9255		if ( secondary || !changeMonth ) {
9256			monthHtml += "<span class='ui-datepicker-month'>" + monthNames[ drawMonth ] + "</span>";
9257		} else {
9258			inMinYear = ( minDate && minDate.getFullYear() === drawYear );
9259			inMaxYear = ( maxDate && maxDate.getFullYear() === drawYear );
9260			monthHtml += "<select class='ui-datepicker-month' aria-label='" + selectMonthLabel + "' data-handler='selectMonth' data-event='change'>";
9261			for ( month = 0; month < 12; month++ ) {
9262				if ( ( !inMinYear || month >= minDate.getMonth() ) && ( !inMaxYear || month <= maxDate.getMonth() ) ) {
9263					monthHtml += "<option value='" + month + "'" +
9264						( month === drawMonth ? " selected='selected'" : "" ) +
9265						">" + monthNamesShort[ month ] + "</option>";
9266				}
9267			}
9268			monthHtml += "</select>";
9269		}
9270
9271		if ( !showMonthAfterYear ) {
9272			html += monthHtml + ( secondary || !( changeMonth && changeYear ) ? "&#xa0;" : "" );
9273		}
9274
9275		// Year selection
9276		if ( !inst.yearshtml ) {
9277			inst.yearshtml = "";
9278			if ( secondary || !changeYear ) {
9279				html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
9280			} else {
9281
9282				// determine range of years to display
9283				years = this._get( inst, "yearRange" ).split( ":" );
9284				thisYear = new Date().getFullYear();
9285				determineYear = function( value ) {
9286					var year = ( value.match( /c[+\-].*/ ) ? drawYear + parseInt( value.substring( 1 ), 10 ) :
9287						( value.match( /[+\-].*/ ) ? thisYear + parseInt( value, 10 ) :
9288						parseInt( value, 10 ) ) );
9289					return ( isNaN( year ) ? thisYear : year );
9290				};
9291				year = determineYear( years[ 0 ] );
9292				endYear = Math.max( year, determineYear( years[ 1 ] || "" ) );
9293				year = ( minDate ? Math.max( year, minDate.getFullYear() ) : year );
9294				endYear = ( maxDate ? Math.min( endYear, maxDate.getFullYear() ) : endYear );
9295				inst.yearshtml += "<select class='ui-datepicker-year' aria-label='" + selectYearLabel + "' data-handler='selectYear' data-event='change'>";
9296				for ( ; year <= endYear; year++ ) {
9297					inst.yearshtml += "<option value='" + year + "'" +
9298						( year === drawYear ? " selected='selected'" : "" ) +
9299						">" + year + "</option>";
9300				}
9301				inst.yearshtml += "</select>";
9302
9303				html += inst.yearshtml;
9304				inst.yearshtml = null;
9305			}
9306		}
9307
9308		html += this._get( inst, "yearSuffix" );
9309		if ( showMonthAfterYear ) {
9310			html += ( secondary || !( changeMonth && changeYear ) ? "&#xa0;" : "" ) + monthHtml;
9311		}
9312		html += "</div>"; // Close datepicker_header
9313		return html;
9314	},
9315
9316	/* Adjust one of the date sub-fields. */
9317	_adjustInstDate: function( inst, offset, period ) {
9318		var year = inst.selectedYear + ( period === "Y" ? offset : 0 ),
9319			month = inst.selectedMonth + ( period === "M" ? offset : 0 ),
9320			day = Math.min( inst.selectedDay, this._getDaysInMonth( year, month ) ) + ( period === "D" ? offset : 0 ),
9321			date = this._restrictMinMax( inst, this._daylightSavingAdjust( new Date( year, month, day ) ) );
9322
9323		inst.selectedDay = date.getDate();
9324		inst.drawMonth = inst.selectedMonth = date.getMonth();
9325		inst.drawYear = inst.selectedYear = date.getFullYear();
9326		if ( period === "M" || period === "Y" ) {
9327			this._notifyChange( inst );
9328		}
9329	},
9330
9331	/* Ensure a date is within any min/max bounds. */
9332	_restrictMinMax: function( inst, date ) {
9333		var minDate = this._getMinMaxDate( inst, "min" ),
9334			maxDate = this._getMinMaxDate( inst, "max" ),
9335			newDate = ( minDate && date < minDate ? minDate : date );
9336		return ( maxDate && newDate > maxDate ? maxDate : newDate );
9337	},
9338
9339	/* Notify change of month/year. */
9340	_notifyChange: function( inst ) {
9341		var onChange = this._get( inst, "onChangeMonthYear" );
9342		if ( onChange ) {
9343			onChange.apply( ( inst.input ? inst.input[ 0 ] : null ),
9344				[ inst.selectedYear, inst.selectedMonth + 1, inst ] );
9345		}
9346	},
9347
9348	/* Determine the number of months to show. */
9349	_getNumberOfMonths: function( inst ) {
9350		var numMonths = this._get( inst, "numberOfMonths" );
9351		return ( numMonths == null ? [ 1, 1 ] : ( typeof numMonths === "number" ? [ 1, numMonths ] : numMonths ) );
9352	},
9353
9354	/* Determine the current maximum date - ensure no time components are set. */
9355	_getMinMaxDate: function( inst, minMax ) {
9356		return this._determineDate( inst, this._get( inst, minMax + "Date" ), null );
9357	},
9358
9359	/* Find the number of days in a given month. */
9360	_getDaysInMonth: function( year, month ) {
9361		return 32 - this._daylightSavingAdjust( new Date( year, month, 32 ) ).getDate();
9362	},
9363
9364	/* Find the day of the week of the first of a month. */
9365	_getFirstDayOfMonth: function( year, month ) {
9366		return new Date( year, month, 1 ).getDay();
9367	},
9368
9369	/* Determines if we should allow a "next/prev" month display change. */
9370	_canAdjustMonth: function( inst, offset, curYear, curMonth ) {
9371		var numMonths = this._getNumberOfMonths( inst ),
9372			date = this._daylightSavingAdjust( new Date( curYear,
9373			curMonth + ( offset < 0 ? offset : numMonths[ 0 ] * numMonths[ 1 ] ), 1 ) );
9374
9375		if ( offset < 0 ) {
9376			date.setDate( this._getDaysInMonth( date.getFullYear(), date.getMonth() ) );
9377		}
9378		return this._isInRange( inst, date );
9379	},
9380
9381	/* Is the given date in the accepted range? */
9382	_isInRange: function( inst, date ) {
9383		var yearSplit, currentYear,
9384			minDate = this._getMinMaxDate( inst, "min" ),
9385			maxDate = this._getMinMaxDate( inst, "max" ),
9386			minYear = null,
9387			maxYear = null,
9388			years = this._get( inst, "yearRange" );
9389			if ( years ) {
9390				yearSplit = years.split( ":" );
9391				currentYear = new Date().getFullYear();
9392				minYear = parseInt( yearSplit[ 0 ], 10 );
9393				maxYear = parseInt( yearSplit[ 1 ], 10 );
9394				if ( yearSplit[ 0 ].match( /[+\-].*/ ) ) {
9395					minYear += currentYear;
9396				}
9397				if ( yearSplit[ 1 ].match( /[+\-].*/ ) ) {
9398					maxYear += currentYear;
9399				}
9400			}
9401
9402		return ( ( !minDate || date.getTime() >= minDate.getTime() ) &&
9403			( !maxDate || date.getTime() <= maxDate.getTime() ) &&
9404			( !minYear || date.getFullYear() >= minYear ) &&
9405			( !maxYear || date.getFullYear() <= maxYear ) );
9406	},
9407
9408	/* Provide the configuration settings for formatting/parsing. */
9409	_getFormatConfig: function( inst ) {
9410		var shortYearCutoff = this._get( inst, "shortYearCutoff" );
9411		shortYearCutoff = ( typeof shortYearCutoff !== "string" ? shortYearCutoff :
9412			new Date().getFullYear() % 100 + parseInt( shortYearCutoff, 10 ) );
9413		return { shortYearCutoff: shortYearCutoff,
9414			dayNamesShort: this._get( inst, "dayNamesShort" ), dayNames: this._get( inst, "dayNames" ),
9415			monthNamesShort: this._get( inst, "monthNamesShort" ), monthNames: this._get( inst, "monthNames" ) };
9416	},
9417
9418	/* Format the given date for display. */
9419	_formatDate: function( inst, day, month, year ) {
9420		if ( !day ) {
9421			inst.currentDay = inst.selectedDay;
9422			inst.currentMonth = inst.selectedMonth;
9423			inst.currentYear = inst.selectedYear;
9424		}
9425		var date = ( day ? ( typeof day === "object" ? day :
9426			this._daylightSavingAdjust( new Date( year, month, day ) ) ) :
9427			this._daylightSavingAdjust( new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) );
9428		return this.formatDate( this._get( inst, "dateFormat" ), date, this._getFormatConfig( inst ) );
9429	}
9430} );
9431
9432/*
9433 * Bind hover events for datepicker elements.
9434 * Done via delegate so the binding only occurs once in the lifetime of the parent div.
9435 * Global datepicker_instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
9436 */
9437function datepicker_bindHover( dpDiv ) {
9438	var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";
9439	return dpDiv.on( "mouseout", selector, function() {
9440			$( this ).removeClass( "ui-state-hover" );
9441			if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) {
9442				$( this ).removeClass( "ui-datepicker-prev-hover" );
9443			}
9444			if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) {
9445				$( this ).removeClass( "ui-datepicker-next-hover" );
9446			}
9447		} )
9448		.on( "mouseover", selector, datepicker_handleMouseover );
9449}
9450
9451function datepicker_handleMouseover() {
9452	if ( !$.datepicker._isDisabledDatepicker( datepicker_instActive.inline ? datepicker_instActive.dpDiv.parent()[ 0 ] : datepicker_instActive.input[ 0 ] ) ) {
9453		$( this ).parents( ".ui-datepicker-calendar" ).find( "a" ).removeClass( "ui-state-hover" );
9454		$( this ).addClass( "ui-state-hover" );
9455		if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) {
9456			$( this ).addClass( "ui-datepicker-prev-hover" );
9457		}
9458		if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) {
9459			$( this ).addClass( "ui-datepicker-next-hover" );
9460		}
9461	}
9462}
9463
9464/* jQuery extend now ignores nulls! */
9465function datepicker_extendRemove( target, props ) {
9466	$.extend( target, props );
9467	for ( var name in props ) {
9468		if ( props[ name ] == null ) {
9469			target[ name ] = props[ name ];
9470		}
9471	}
9472	return target;
9473}
9474
9475/* Invoke the datepicker functionality.
9476   @param  options  string - a command, optionally followed by additional parameters or
9477					Object - settings for attaching new datepicker functionality
9478   @return  jQuery object */
9479$.fn.datepicker = function( options ) {
9480
9481	/* Verify an empty collection wasn't passed - Fixes #6976 */
9482	if ( !this.length ) {
9483		return this;
9484	}
9485
9486	/* Initialise the date picker. */
9487	if ( !$.datepicker.initialized ) {
9488		$( document ).on( "mousedown", $.datepicker._checkExternalClick );
9489		$.datepicker.initialized = true;
9490	}
9491
9492	/* Append datepicker main container to body if not exist. */
9493	if ( $( "#" + $.datepicker._mainDivId ).length === 0 ) {
9494		$( "body" ).append( $.datepicker.dpDiv );
9495	}
9496
9497	var otherArgs = Array.prototype.slice.call( arguments, 1 );
9498	if ( typeof options === "string" && ( options === "isDisabled" || options === "getDate" || options === "widget" ) ) {
9499		return $.datepicker[ "_" + options + "Datepicker" ].
9500			apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) );
9501	}
9502	if ( options === "option" && arguments.length === 2 && typeof arguments[ 1 ] === "string" ) {
9503		return $.datepicker[ "_" + options + "Datepicker" ].
9504			apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) );
9505	}
9506	return this.each( function() {
9507		if ( typeof options === "string" ) {
9508			$.datepicker[ "_" + options + "Datepicker" ]
9509				.apply( $.datepicker, [ this ].concat( otherArgs ) );
9510		} else {
9511			$.datepicker._attachDatepicker( this, options );
9512		}
9513	} );
9514};
9515
9516$.datepicker = new Datepicker(); // singleton instance
9517$.datepicker.initialized = false;
9518$.datepicker.uuid = new Date().getTime();
9519$.datepicker.version = "1.13.3";
9520
9521var widgetsDatepicker = $.datepicker;
9522
9523
9524
9525// This file is deprecated
9526var ie = $.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() );
9527
9528/*!
9529 * jQuery UI Mouse 1.13.3
9530 * https://jqueryui.com
9531 *
9532 * Copyright OpenJS Foundation and other contributors
9533 * Released under the MIT license.
9534 * https://jquery.org/license
9535 */
9536
9537//>>label: Mouse
9538//>>group: Widgets
9539//>>description: Abstracts mouse-based interactions to assist in creating certain widgets.
9540//>>docs: https://api.jqueryui.com/mouse/
9541
9542
9543var mouseHandled = false;
9544$( document ).on( "mouseup", function() {
9545	mouseHandled = false;
9546} );
9547
9548var widgetsMouse = $.widget( "ui.mouse", {
9549	version: "1.13.3",
9550	options: {
9551		cancel: "input, textarea, button, select, option",
9552		distance: 1,
9553		delay: 0
9554	},
9555	_mouseInit: function() {
9556		var that = this;
9557
9558		this.element
9559			.on( "mousedown." + this.widgetName, function( event ) {
9560				return that._mouseDown( event );
9561			} )
9562			.on( "click." + this.widgetName, function( event ) {
9563				if ( true === $.data( event.target, that.widgetName + ".preventClickEvent" ) ) {
9564					$.removeData( event.target, that.widgetName + ".preventClickEvent" );
9565					event.stopImmediatePropagation();
9566					return false;
9567				}
9568			} );
9569
9570		this.started = false;
9571	},
9572
9573	// TODO: make sure destroying one instance of mouse doesn't mess with
9574	// other instances of mouse
9575	_mouseDestroy: function() {
9576		this.element.off( "." + this.widgetName );
9577		if ( this._mouseMoveDelegate ) {
9578			this.document
9579				.off( "mousemove." + this.widgetName, this._mouseMoveDelegate )
9580				.off( "mouseup." + this.widgetName, this._mouseUpDelegate );
9581		}
9582	},
9583
9584	_mouseDown: function( event ) {
9585
9586		// don't let more than one widget handle mouseStart
9587		if ( mouseHandled ) {
9588			return;
9589		}
9590
9591		this._mouseMoved = false;
9592
9593		// We may have missed mouseup (out of window)
9594		if ( this._mouseStarted ) {
9595			this._mouseUp( event );
9596		}
9597
9598		this._mouseDownEvent = event;
9599
9600		var that = this,
9601			btnIsLeft = ( event.which === 1 ),
9602
9603			// event.target.nodeName works around a bug in IE 8 with
9604			// disabled inputs (#7620)
9605			elIsCancel = ( typeof this.options.cancel === "string" && event.target.nodeName ?
9606				$( event.target ).closest( this.options.cancel ).length : false );
9607		if ( !btnIsLeft || elIsCancel || !this._mouseCapture( event ) ) {
9608			return true;
9609		}
9610
9611		this.mouseDelayMet = !this.options.delay;
9612		if ( !this.mouseDelayMet ) {
9613			this._mouseDelayTimer = setTimeout( function() {
9614				that.mouseDelayMet = true;
9615			}, this.options.delay );
9616		}
9617
9618		if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) {
9619			this._mouseStarted = ( this._mouseStart( event ) !== false );
9620			if ( !this._mouseStarted ) {
9621				event.preventDefault();
9622				return true;
9623			}
9624		}
9625
9626		// Click event may never have fired (Gecko & Opera)
9627		if ( true === $.data( event.target, this.widgetName + ".preventClickEvent" ) ) {
9628			$.removeData( event.target, this.widgetName + ".preventClickEvent" );
9629		}
9630
9631		// These delegates are required to keep context
9632		this._mouseMoveDelegate = function( event ) {
9633			return that._mouseMove( event );
9634		};
9635		this._mouseUpDelegate = function( event ) {
9636			return that._mouseUp( event );
9637		};
9638
9639		this.document
9640			.on( "mousemove." + this.widgetName, this._mouseMoveDelegate )
9641			.on( "mouseup." + this.widgetName, this._mouseUpDelegate );
9642
9643		event.preventDefault();
9644
9645		mouseHandled = true;
9646		return true;
9647	},
9648
9649	_mouseMove: function( event ) {
9650
9651		// Only check for mouseups outside the document if you've moved inside the document
9652		// at least once. This prevents the firing of mouseup in the case of IE<9, which will
9653		// fire a mousemove event if content is placed under the cursor. See #7778
9654		// Support: IE <9
9655		if ( this._mouseMoved ) {
9656
9657			// IE mouseup check - mouseup happened when mouse was out of window
9658			if ( $.ui.ie && ( !document.documentMode || document.documentMode < 9 ) &&
9659					!event.button ) {
9660				return this._mouseUp( event );
9661
9662			// Iframe mouseup check - mouseup occurred in another document
9663			} else if ( !event.which ) {
9664
9665				// Support: Safari <=8 - 9
9666				// Safari sets which to 0 if you press any of the following keys
9667				// during a drag (#14461)
9668				if ( event.originalEvent.altKey || event.originalEvent.ctrlKey ||
9669						event.originalEvent.metaKey || event.originalEvent.shiftKey ) {
9670					this.ignoreMissingWhich = true;
9671				} else if ( !this.ignoreMissingWhich ) {
9672					return this._mouseUp( event );
9673				}
9674			}
9675		}
9676
9677		if ( event.which || event.button ) {
9678			this._mouseMoved = true;
9679		}
9680
9681		if ( this._mouseStarted ) {
9682			this._mouseDrag( event );
9683			return event.preventDefault();
9684		}
9685
9686		if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) {
9687			this._mouseStarted =
9688				( this._mouseStart( this._mouseDownEvent, event ) !== false );
9689			if ( this._mouseStarted ) {
9690				this._mouseDrag( event );
9691			} else {
9692				this._mouseUp( event );
9693			}
9694		}
9695
9696		return !this._mouseStarted;
9697	},
9698
9699	_mouseUp: function( event ) {
9700		this.document
9701			.off( "mousemove." + this.widgetName, this._mouseMoveDelegate )
9702			.off( "mouseup." + this.widgetName, this._mouseUpDelegate );
9703
9704		if ( this._mouseStarted ) {
9705			this._mouseStarted = false;
9706
9707			if ( event.target === this._mouseDownEvent.target ) {
9708				$.data( event.target, this.widgetName + ".preventClickEvent", true );
9709			}
9710
9711			this._mouseStop( event );
9712		}
9713
9714		if ( this._mouseDelayTimer ) {
9715			clearTimeout( this._mouseDelayTimer );
9716			delete this._mouseDelayTimer;
9717		}
9718
9719		this.ignoreMissingWhich = false;
9720		mouseHandled = false;
9721		event.preventDefault();
9722	},
9723
9724	_mouseDistanceMet: function( event ) {
9725		return ( Math.max(
9726				Math.abs( this._mouseDownEvent.pageX - event.pageX ),
9727				Math.abs( this._mouseDownEvent.pageY - event.pageY )
9728			) >= this.options.distance
9729		);
9730	},
9731
9732	_mouseDelayMet: function( /* event */ ) {
9733		return this.mouseDelayMet;
9734	},
9735
9736	// These are placeholder methods, to be overriden by extending plugin
9737	_mouseStart: function( /* event */ ) {},
9738	_mouseDrag: function( /* event */ ) {},
9739	_mouseStop: function( /* event */ ) {},
9740	_mouseCapture: function( /* event */ ) {
9741		return true;
9742	}
9743} );
9744
9745
9746
9747// $.ui.plugin is deprecated. Use $.widget() extensions instead.
9748var plugin = $.ui.plugin = {
9749	add: function( module, option, set ) {
9750		var i,
9751			proto = $.ui[ module ].prototype;
9752		for ( i in set ) {
9753			proto.plugins[ i ] = proto.plugins[ i ] || [];
9754			proto.plugins[ i ].push( [ option, set[ i ] ] );
9755		}
9756	},
9757	call: function( instance, name, args, allowDisconnected ) {
9758		var i,
9759			set = instance.plugins[ name ];
9760
9761		if ( !set ) {
9762			return;
9763		}
9764
9765		if ( !allowDisconnected && ( !instance.element[ 0 ].parentNode ||
9766				instance.element[ 0 ].parentNode.nodeType === 11 ) ) {
9767			return;
9768		}
9769
9770		for ( i = 0; i < set.length; i++ ) {
9771			if ( instance.options[ set[ i ][ 0 ] ] ) {
9772				set[ i ][ 1 ].apply( instance.element, args );
9773			}
9774		}
9775	}
9776};
9777
9778
9779
9780var safeBlur = $.ui.safeBlur = function( element ) {
9781
9782	// Support: IE9 - 10 only
9783	// If the <body> is blurred, IE will switch windows, see #9420
9784	if ( element && element.nodeName.toLowerCase() !== "body" ) {
9785		$( element ).trigger( "blur" );
9786	}
9787};
9788
9789
9790/*!
9791 * jQuery UI Draggable 1.13.3
9792 * https://jqueryui.com
9793 *
9794 * Copyright OpenJS Foundation and other contributors
9795 * Released under the MIT license.
9796 * https://jquery.org/license
9797 */
9798
9799//>>label: Draggable
9800//>>group: Interactions
9801//>>description: Enables dragging functionality for any element.
9802//>>docs: https://api.jqueryui.com/draggable/
9803//>>demos: https://jqueryui.com/draggable/
9804//>>css.structure: ../../themes/base/draggable.css
9805
9806
9807$.widget( "ui.draggable", $.ui.mouse, {
9808	version: "1.13.3",
9809	widgetEventPrefix: "drag",
9810	options: {
9811		addClasses: true,
9812		appendTo: "parent",
9813		axis: false,
9814		connectToSortable: false,
9815		containment: false,
9816		cursor: "auto",
9817		cursorAt: false,
9818		grid: false,
9819		handle: false,
9820		helper: "original",
9821		iframeFix: false,
9822		opacity: false,
9823		refreshPositions: false,
9824		revert: false,
9825		revertDuration: 500,
9826		scope: "default",
9827		scroll: true,
9828		scrollSensitivity: 20,
9829		scrollSpeed: 20,
9830		snap: false,
9831		snapMode: "both",
9832		snapTolerance: 20,
9833		stack: false,
9834		zIndex: false,
9835
9836		// Callbacks
9837		drag: null,
9838		start: null,
9839		stop: null
9840	},
9841	_create: function() {
9842
9843		if ( this.options.helper === "original" ) {
9844			this._setPositionRelative();
9845		}
9846		if ( this.options.addClasses ) {
9847			this._addClass( "ui-draggable" );
9848		}
9849		this._setHandleClassName();
9850
9851		this._mouseInit();
9852	},
9853
9854	_setOption: function( key, value ) {
9855		this._super( key, value );
9856		if ( key === "handle" ) {
9857			this._removeHandleClassName();
9858			this._setHandleClassName();
9859		}
9860	},
9861
9862	_destroy: function() {
9863		if ( ( this.helper || this.element ).is( ".ui-draggable-dragging" ) ) {
9864			this.destroyOnClear = true;
9865			return;
9866		}
9867		this._removeHandleClassName();
9868		this._mouseDestroy();
9869	},
9870
9871	_mouseCapture: function( event ) {
9872		var o = this.options;
9873
9874		// Among others, prevent a drag on a resizable-handle
9875		if ( this.helper || o.disabled ||
9876				$( event.target ).closest( ".ui-resizable-handle" ).length > 0 ) {
9877			return false;
9878		}
9879
9880		//Quit if we're not on a valid handle
9881		this.handle = this._getHandle( event );
9882		if ( !this.handle ) {
9883			return false;
9884		}
9885
9886		this._blurActiveElement( event );
9887
9888		this._blockFrames( o.iframeFix === true ? "iframe" : o.iframeFix );
9889
9890		return true;
9891
9892	},
9893
9894	_blockFrames: function( selector ) {
9895		this.iframeBlocks = this.document.find( selector ).map( function() {
9896			var iframe = $( this );
9897
9898			return $( "<div>" )
9899				.css( "position", "absolute" )
9900				.appendTo( iframe.parent() )
9901				.outerWidth( iframe.outerWidth() )
9902				.outerHeight( iframe.outerHeight() )
9903				.offset( iframe.offset() )[ 0 ];
9904		} );
9905	},
9906
9907	_unblockFrames: function() {
9908		if ( this.iframeBlocks ) {
9909			this.iframeBlocks.remove();
9910			delete this.iframeBlocks;
9911		}
9912	},
9913
9914	_blurActiveElement: function( event ) {
9915		var activeElement = $.ui.safeActiveElement( this.document[ 0 ] ),
9916			target = $( event.target );
9917
9918		// Don't blur if the event occurred on an element that is within
9919		// the currently focused element
9920		// See #10527, #12472
9921		if ( target.closest( activeElement ).length ) {
9922			return;
9923		}
9924
9925		// Blur any element that currently has focus, see #4261
9926		$.ui.safeBlur( activeElement );
9927	},
9928
9929	_mouseStart: function( event ) {
9930
9931		var o = this.options;
9932
9933		//Create and append the visible helper
9934		this.helper = this._createHelper( event );
9935
9936		this._addClass( this.helper, "ui-draggable-dragging" );
9937
9938		//Cache the helper size
9939		this._cacheHelperProportions();
9940
9941		//If ddmanager is used for droppables, set the global draggable
9942		if ( $.ui.ddmanager ) {
9943			$.ui.ddmanager.current = this;
9944		}
9945
9946		/*
9947		 * - Position generation -
9948		 * This block generates everything position related - it's the core of draggables.
9949		 */
9950
9951		//Cache the margins of the original element
9952		this._cacheMargins();
9953
9954		//Store the helper's css position
9955		this.cssPosition = this.helper.css( "position" );
9956		this.scrollParent = this.helper.scrollParent( true );
9957		this.offsetParent = this.helper.offsetParent();
9958		this.hasFixedAncestor = this.helper.parents().filter( function() {
9959				return $( this ).css( "position" ) === "fixed";
9960			} ).length > 0;
9961
9962		//The element's absolute position on the page minus margins
9963		this.positionAbs = this.element.offset();
9964		this._refreshOffsets( event );
9965
9966		//Generate the original position
9967		this.originalPosition = this.position = this._generatePosition( event, false );
9968		this.originalPageX = event.pageX;
9969		this.originalPageY = event.pageY;
9970
9971		//Adjust the mouse offset relative to the helper if "cursorAt" is supplied
9972		if ( o.cursorAt ) {
9973			this._adjustOffsetFromHelper( o.cursorAt );
9974		}
9975
9976		//Set a containment if given in the options
9977		this._setContainment();
9978
9979		//Trigger event + callbacks
9980		if ( this._trigger( "start", event ) === false ) {
9981			this._clear();
9982			return false;
9983		}
9984
9985		//Recache the helper size
9986		this._cacheHelperProportions();
9987
9988		//Prepare the droppable offsets
9989		if ( $.ui.ddmanager && !o.dropBehaviour ) {
9990			$.ui.ddmanager.prepareOffsets( this, event );
9991		}
9992
9993		// Execute the drag once - this causes the helper not to be visible before getting its
9994		// correct position
9995		this._mouseDrag( event, true );
9996
9997		// If the ddmanager is used for droppables, inform the manager that dragging has started
9998		// (see #5003)
9999		if ( $.ui.ddmanager ) {
10000			$.ui.ddmanager.dragStart( this, event );
10001		}
10002
10003		return true;
10004	},
10005
10006	_refreshOffsets: function( event ) {
10007		this.offset = {
10008			top: this.positionAbs.top - this.margins.top,
10009			left: this.positionAbs.left - this.margins.left,
10010			scroll: false,
10011			parent: this._getParentOffset(),
10012			relative: this._getRelativeOffset()
10013		};
10014
10015		this.offset.click = {
10016			left: event.pageX - this.offset.left,
10017			top: event.pageY - this.offset.top
10018		};
10019	},
10020
10021	_mouseDrag: function( event, noPropagation ) {
10022
10023		// reset any necessary cached properties (see #5009)
10024		if ( this.hasFixedAncestor ) {
10025			this.offset.parent = this._getParentOffset();
10026		}
10027
10028		//Compute the helpers position
10029		this.position = this._generatePosition( event, true );
10030		this.positionAbs = this._convertPositionTo( "absolute" );
10031
10032		//Call plugins and callbacks and use the resulting position if something is returned
10033		if ( !noPropagation ) {
10034			var ui = this._uiHash();
10035			if ( this._trigger( "drag", event, ui ) === false ) {
10036				this._mouseUp( new $.Event( "mouseup", event ) );
10037				return false;
10038			}
10039			this.position = ui.position;
10040		}
10041
10042		this.helper[ 0 ].style.left = this.position.left + "px";
10043		this.helper[ 0 ].style.top = this.position.top + "px";
10044
10045		if ( $.ui.ddmanager ) {
10046			$.ui.ddmanager.drag( this, event );
10047		}
10048
10049		return false;
10050	},
10051
10052	_mouseStop: function( event ) {
10053
10054		//If we are using droppables, inform the manager about the drop
10055		var that = this,
10056			dropped = false;
10057		if ( $.ui.ddmanager && !this.options.dropBehaviour ) {
10058			dropped = $.ui.ddmanager.drop( this, event );
10059		}
10060
10061		//if a drop comes from outside (a sortable)
10062		if ( this.dropped ) {
10063			dropped = this.dropped;
10064			this.dropped = false;
10065		}
10066
10067		if ( ( this.options.revert === "invalid" && !dropped ) ||
10068				( this.options.revert === "valid" && dropped ) ||
10069				this.options.revert === true || ( typeof this.options.revert === "function" &&
10070				this.options.revert.call( this.element, dropped ) )
10071		) {
10072			$( this.helper ).animate(
10073				this.originalPosition,
10074				parseInt( this.options.revertDuration, 10 ),
10075				function() {
10076					if ( that._trigger( "stop", event ) !== false ) {
10077						that._clear();
10078					}
10079				}
10080			);
10081		} else {
10082			if ( this._trigger( "stop", event ) !== false ) {
10083				this._clear();
10084			}
10085		}
10086
10087		return false;
10088	},
10089
10090	_mouseUp: function( event ) {
10091		this._unblockFrames();
10092
10093		// If the ddmanager is used for droppables, inform the manager that dragging has stopped
10094		// (see #5003)
10095		if ( $.ui.ddmanager ) {
10096			$.ui.ddmanager.dragStop( this, event );
10097		}
10098
10099		// Only need to focus if the event occurred on the draggable itself, see #10527
10100		if ( this.handleElement.is( event.target ) ) {
10101
10102			// The interaction is over; whether or not the click resulted in a drag,
10103			// focus the element
10104			this.element.trigger( "focus" );
10105		}
10106
10107		return $.ui.mouse.prototype._mouseUp.call( this, event );
10108	},
10109
10110	cancel: function() {
10111
10112		if ( this.helper.is( ".ui-draggable-dragging" ) ) {
10113			this._mouseUp( new $.Event( "mouseup", { target: this.element[ 0 ] } ) );
10114		} else {
10115			this._clear();
10116		}
10117
10118		return this;
10119
10120	},
10121
10122	_getHandle: function( event ) {
10123		return this.options.handle ?
10124			!!$( event.target ).closest( this.element.find( this.options.handle ) ).length :
10125			true;
10126	},
10127
10128	_setHandleClassName: function() {
10129		this.handleElement = this.options.handle ?
10130			this.element.find( this.options.handle ) : this.element;
10131		this._addClass( this.handleElement, "ui-draggable-handle" );
10132	},
10133
10134	_removeHandleClassName: function() {
10135		this._removeClass( this.handleElement, "ui-draggable-handle" );
10136	},
10137
10138	_createHelper: function( event ) {
10139
10140		var o = this.options,
10141			helperIsFunction = typeof o.helper === "function",
10142			helper = helperIsFunction ?
10143				$( o.helper.apply( this.element[ 0 ], [ event ] ) ) :
10144				( o.helper === "clone" ?
10145					this.element.clone().removeAttr( "id" ) :
10146					this.element );
10147
10148		if ( !helper.parents( "body" ).length ) {
10149			helper.appendTo( ( o.appendTo === "parent" ?
10150				this.element[ 0 ].parentNode :
10151				o.appendTo ) );
10152		}
10153
10154		// https://bugs.jqueryui.com/ticket/9446
10155		// a helper function can return the original element
10156		// which wouldn't have been set to relative in _create
10157		if ( helperIsFunction && helper[ 0 ] === this.element[ 0 ] ) {
10158			this._setPositionRelative();
10159		}
10160
10161		if ( helper[ 0 ] !== this.element[ 0 ] &&
10162				!( /(fixed|absolute)/ ).test( helper.css( "position" ) ) ) {
10163			helper.css( "position", "absolute" );
10164		}
10165
10166		return helper;
10167
10168	},
10169
10170	_setPositionRelative: function() {
10171		if ( !( /^(?:r|a|f)/ ).test( this.element.css( "position" ) ) ) {
10172			this.element[ 0 ].style.position = "relative";
10173		}
10174	},
10175
10176	_adjustOffsetFromHelper: function( obj ) {
10177		if ( typeof obj === "string" ) {
10178			obj = obj.split( " " );
10179		}
10180		if ( Array.isArray( obj ) ) {
10181			obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 };
10182		}
10183		if ( "left" in obj ) {
10184			this.offset.click.left = obj.left + this.margins.left;
10185		}
10186		if ( "right" in obj ) {
10187			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
10188		}
10189		if ( "top" in obj ) {
10190			this.offset.click.top = obj.top + this.margins.top;
10191		}
10192		if ( "bottom" in obj ) {
10193			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
10194		}
10195	},
10196
10197	_isRootNode: function( element ) {
10198		return ( /(html|body)/i ).test( element.tagName ) || element === this.document[ 0 ];
10199	},
10200
10201	_getParentOffset: function() {
10202
10203		//Get the offsetParent and cache its position
10204		var po = this.offsetParent.offset(),
10205			document = this.document[ 0 ];
10206
10207		// This is a special case where we need to modify a offset calculated on start, since the
10208		// following happened:
10209		// 1. The position of the helper is absolute, so it's position is calculated based on the
10210		// next positioned parent
10211		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't
10212		// the document, which means that the scroll is included in the initial calculation of the
10213		// offset of the parent, and never recalculated upon drag
10214		if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== document &&
10215				$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) {
10216			po.left += this.scrollParent.scrollLeft();
10217			po.top += this.scrollParent.scrollTop();
10218		}
10219
10220		if ( this._isRootNode( this.offsetParent[ 0 ] ) ) {
10221			po = { top: 0, left: 0 };
10222		}
10223
10224		return {
10225			top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ),
10226			left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 )
10227		};
10228
10229	},
10230
10231	_getRelativeOffset: function() {
10232		if ( this.cssPosition !== "relative" ) {
10233			return { top: 0, left: 0 };
10234		}
10235
10236		var p = this.element.position(),
10237			scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
10238
10239		return {
10240			top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) +
10241				( !scrollIsRootNode ? this.scrollParent.scrollTop() : 0 ),
10242			left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) +
10243				( !scrollIsRootNode ? this.scrollParent.scrollLeft() : 0 )
10244		};
10245
10246	},
10247
10248	_cacheMargins: function() {
10249		this.margins = {
10250			left: ( parseInt( this.element.css( "marginLeft" ), 10 ) || 0 ),
10251			top: ( parseInt( this.element.css( "marginTop" ), 10 ) || 0 ),
10252			right: ( parseInt( this.element.css( "marginRight" ), 10 ) || 0 ),
10253			bottom: ( parseInt( this.element.css( "marginBottom" ), 10 ) || 0 )
10254		};
10255	},
10256
10257	_cacheHelperProportions: function() {
10258		this.helperProportions = {
10259			width: this.helper.outerWidth(),
10260			height: this.helper.outerHeight()
10261		};
10262	},
10263
10264	_setContainment: function() {
10265
10266		var isUserScrollable, c, ce,
10267			o = this.options,
10268			document = this.document[ 0 ];
10269
10270		this.relativeContainer = null;
10271
10272		if ( !o.containment ) {
10273			this.containment = null;
10274			return;
10275		}
10276
10277		if ( o.containment === "window" ) {
10278			this.containment = [
10279				$( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
10280				$( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top,
10281				$( window ).scrollLeft() + $( window ).width() -
10282					this.helperProportions.width - this.margins.left,
10283				$( window ).scrollTop() +
10284					( $( window ).height() || document.body.parentNode.scrollHeight ) -
10285					this.helperProportions.height - this.margins.top
10286			];
10287			return;
10288		}
10289
10290		if ( o.containment === "document" ) {
10291			this.containment = [
10292				0,
10293				0,
10294				$( document ).width() - this.helperProportions.width - this.margins.left,
10295				( $( document ).height() || document.body.parentNode.scrollHeight ) -
10296					this.helperProportions.height - this.margins.top
10297			];
10298			return;
10299		}
10300
10301		if ( o.containment.constructor === Array ) {
10302			this.containment = o.containment;
10303			return;
10304		}
10305
10306		if ( o.containment === "parent" ) {
10307			o.containment = this.helper[ 0 ].parentNode;
10308		}
10309
10310		c = $( o.containment );
10311		ce = c[ 0 ];
10312
10313		if ( !ce ) {
10314			return;
10315		}
10316
10317		isUserScrollable = /(scroll|auto)/.test( c.css( "overflow" ) );
10318
10319		this.containment = [
10320			( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) +
10321				( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ),
10322			( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) +
10323				( parseInt( c.css( "paddingTop" ), 10 ) || 0 ),
10324			( isUserScrollable ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -
10325				( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) -
10326				( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) -
10327				this.helperProportions.width -
10328				this.margins.left -
10329				this.margins.right,
10330			( isUserScrollable ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -
10331				( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) -
10332				( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) -
10333				this.helperProportions.height -
10334				this.margins.top -
10335				this.margins.bottom
10336		];
10337		this.relativeContainer = c;
10338	},
10339
10340	_convertPositionTo: function( d, pos ) {
10341
10342		if ( !pos ) {
10343			pos = this.position;
10344		}
10345
10346		var mod = d === "absolute" ? 1 : -1,
10347			scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
10348
10349		return {
10350			top: (
10351
10352				// The absolute mouse position
10353				pos.top	+
10354
10355				// Only for relative positioned nodes: Relative offset from element to offset parent
10356				this.offset.relative.top * mod +
10357
10358				// The offsetParent's offset without borders (offset + border)
10359				this.offset.parent.top * mod -
10360				( ( this.cssPosition === "fixed" ?
10361					-this.offset.scroll.top :
10362					( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) * mod )
10363			),
10364			left: (
10365
10366				// The absolute mouse position
10367				pos.left +
10368
10369				// Only for relative positioned nodes: Relative offset from element to offset parent
10370				this.offset.relative.left * mod +
10371
10372				// The offsetParent's offset without borders (offset + border)
10373				this.offset.parent.left * mod	-
10374				( ( this.cssPosition === "fixed" ?
10375					-this.offset.scroll.left :
10376					( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) * mod )
10377			)
10378		};
10379
10380	},
10381
10382	_generatePosition: function( event, constrainPosition ) {
10383
10384		var containment, co, top, left,
10385			o = this.options,
10386			scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ),
10387			pageX = event.pageX,
10388			pageY = event.pageY;
10389
10390		// Cache the scroll
10391		if ( !scrollIsRootNode || !this.offset.scroll ) {
10392			this.offset.scroll = {
10393				top: this.scrollParent.scrollTop(),
10394				left: this.scrollParent.scrollLeft()
10395			};
10396		}
10397
10398		/*
10399		 * - Position constraining -
10400		 * Constrain the position to a mix of grid, containment.
10401		 */
10402
10403		// If we are not dragging yet, we won't check for options
10404		if ( constrainPosition ) {
10405			if ( this.containment ) {
10406				if ( this.relativeContainer ) {
10407					co = this.relativeContainer.offset();
10408					containment = [
10409						this.containment[ 0 ] + co.left,
10410						this.containment[ 1 ] + co.top,
10411						this.containment[ 2 ] + co.left,
10412						this.containment[ 3 ] + co.top
10413					];
10414				} else {
10415					containment = this.containment;
10416				}
10417
10418				if ( event.pageX - this.offset.click.left < containment[ 0 ] ) {
10419					pageX = containment[ 0 ] + this.offset.click.left;
10420				}
10421				if ( event.pageY - this.offset.click.top < containment[ 1 ] ) {
10422					pageY = containment[ 1 ] + this.offset.click.top;
10423				}
10424				if ( event.pageX - this.offset.click.left > containment[ 2 ] ) {
10425					pageX = containment[ 2 ] + this.offset.click.left;
10426				}
10427				if ( event.pageY - this.offset.click.top > containment[ 3 ] ) {
10428					pageY = containment[ 3 ] + this.offset.click.top;
10429				}
10430			}
10431
10432			if ( o.grid ) {
10433
10434				//Check for grid elements set to 0 to prevent divide by 0 error causing invalid
10435				// argument errors in IE (see ticket #6950)
10436				top = o.grid[ 1 ] ? this.originalPageY + Math.round( ( pageY -
10437					this.originalPageY ) / o.grid[ 1 ] ) * o.grid[ 1 ] : this.originalPageY;
10438				pageY = containment ? ( ( top - this.offset.click.top >= containment[ 1 ] ||
10439					top - this.offset.click.top > containment[ 3 ] ) ?
10440						top :
10441						( ( top - this.offset.click.top >= containment[ 1 ] ) ?
10442							top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) : top;
10443
10444				left = o.grid[ 0 ] ? this.originalPageX +
10445					Math.round( ( pageX - this.originalPageX ) / o.grid[ 0 ] ) * o.grid[ 0 ] :
10446					this.originalPageX;
10447				pageX = containment ? ( ( left - this.offset.click.left >= containment[ 0 ] ||
10448					left - this.offset.click.left > containment[ 2 ] ) ?
10449						left :
10450						( ( left - this.offset.click.left >= containment[ 0 ] ) ?
10451							left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) : left;
10452			}
10453
10454			if ( o.axis === "y" ) {
10455				pageX = this.originalPageX;
10456			}
10457
10458			if ( o.axis === "x" ) {
10459				pageY = this.originalPageY;
10460			}
10461		}
10462
10463		return {
10464			top: (
10465
10466				// The absolute mouse position
10467				pageY -
10468
10469				// Click offset (relative to the element)
10470				this.offset.click.top -
10471
10472				// Only for relative positioned nodes: Relative offset from element to offset parent
10473				this.offset.relative.top -
10474
10475				// The offsetParent's offset without borders (offset + border)
10476				this.offset.parent.top +
10477				( this.cssPosition === "fixed" ?
10478					-this.offset.scroll.top :
10479					( scrollIsRootNode ? 0 : this.offset.scroll.top ) )
10480			),
10481			left: (
10482
10483				// The absolute mouse position
10484				pageX -
10485
10486				// Click offset (relative to the element)
10487				this.offset.click.left -
10488
10489				// Only for relative positioned nodes: Relative offset from element to offset parent
10490				this.offset.relative.left -
10491
10492				// The offsetParent's offset without borders (offset + border)
10493				this.offset.parent.left +
10494				( this.cssPosition === "fixed" ?
10495					-this.offset.scroll.left :
10496					( scrollIsRootNode ? 0 : this.offset.scroll.left ) )
10497			)
10498		};
10499
10500	},
10501
10502	_clear: function() {
10503		this._removeClass( this.helper, "ui-draggable-dragging" );
10504		if ( this.helper[ 0 ] !== this.element[ 0 ] && !this.cancelHelperRemoval ) {
10505			this.helper.remove();
10506		}
10507		this.helper = null;
10508		this.cancelHelperRemoval = false;
10509		if ( this.destroyOnClear ) {
10510			this.destroy();
10511		}
10512	},
10513
10514	// From now on bulk stuff - mainly helpers
10515
10516	_trigger: function( type, event, ui ) {
10517		ui = ui || this._uiHash();
10518		$.ui.plugin.call( this, type, [ event, ui, this ], true );
10519
10520		// Absolute position and offset (see #6884 ) have to be recalculated after plugins
10521		if ( /^(drag|start|stop)/.test( type ) ) {
10522			this.positionAbs = this._convertPositionTo( "absolute" );
10523			ui.offset = this.positionAbs;
10524		}
10525		return $.Widget.prototype._trigger.call( this, type, event, ui );
10526	},
10527
10528	plugins: {},
10529
10530	_uiHash: function() {
10531		return {
10532			helper: this.helper,
10533			position: this.position,
10534			originalPosition: this.originalPosition,
10535			offset: this.positionAbs
10536		};
10537	}
10538
10539} );
10540
10541$.ui.plugin.add( "draggable", "connectToSortable", {
10542	start: function( event, ui, draggable ) {
10543		var uiSortable = $.extend( {}, ui, {
10544			item: draggable.element
10545		} );
10546
10547		draggable.sortables = [];
10548		$( draggable.options.connectToSortable ).each( function() {
10549			var sortable = $( this ).sortable( "instance" );
10550
10551			if ( sortable && !sortable.options.disabled ) {
10552				draggable.sortables.push( sortable );
10553
10554				// RefreshPositions is called at drag start to refresh the containerCache
10555				// which is used in drag. This ensures it's initialized and synchronized
10556				// with any changes that might have happened on the page since initialization.
10557				sortable.refreshPositions();
10558				sortable._trigger( "activate", event, uiSortable );
10559			}
10560		} );
10561	},
10562	stop: function( event, ui, draggable ) {
10563		var uiSortable = $.extend( {}, ui, {
10564			item: draggable.element
10565		} );
10566
10567		draggable.cancelHelperRemoval = false;
10568
10569		$.each( draggable.sortables, function() {
10570			var sortable = this;
10571
10572			if ( sortable.isOver ) {
10573				sortable.isOver = 0;
10574
10575				// Allow this sortable to handle removing the helper
10576				draggable.cancelHelperRemoval = true;
10577				sortable.cancelHelperRemoval = false;
10578
10579				// Use _storedCSS To restore properties in the sortable,
10580				// as this also handles revert (#9675) since the draggable
10581				// may have modified them in unexpected ways (#8809)
10582				sortable._storedCSS = {
10583					position: sortable.placeholder.css( "position" ),
10584					top: sortable.placeholder.css( "top" ),
10585					left: sortable.placeholder.css( "left" )
10586				};
10587
10588				sortable._mouseStop( event );
10589
10590				// Once drag has ended, the sortable should return to using
10591				// its original helper, not the shared helper from draggable
10592				sortable.options.helper = sortable.options._helper;
10593			} else {
10594
10595				// Prevent this Sortable from removing the helper.
10596				// However, don't set the draggable to remove the helper
10597				// either as another connected Sortable may yet handle the removal.
10598				sortable.cancelHelperRemoval = true;
10599
10600				sortable._trigger( "deactivate", event, uiSortable );
10601			}
10602		} );
10603	},
10604	drag: function( event, ui, draggable ) {
10605		$.each( draggable.sortables, function() {
10606			var innermostIntersecting = false,
10607				sortable = this;
10608
10609			// Copy over variables that sortable's _intersectsWith uses
10610			sortable.positionAbs = draggable.positionAbs;
10611			sortable.helperProportions = draggable.helperProportions;
10612			sortable.offset.click = draggable.offset.click;
10613
10614			if ( sortable._intersectsWith( sortable.containerCache ) ) {
10615				innermostIntersecting = true;
10616
10617				$.each( draggable.sortables, function() {
10618
10619					// Copy over variables that sortable's _intersectsWith uses
10620					this.positionAbs = draggable.positionAbs;
10621					this.helperProportions = draggable.helperProportions;
10622					this.offset.click = draggable.offset.click;
10623
10624					if ( this !== sortable &&
10625							this._intersectsWith( this.containerCache ) &&
10626							$.contains( sortable.element[ 0 ], this.element[ 0 ] ) ) {
10627						innermostIntersecting = false;
10628					}
10629
10630					return innermostIntersecting;
10631				} );
10632			}
10633
10634			if ( innermostIntersecting ) {
10635
10636				// If it intersects, we use a little isOver variable and set it once,
10637				// so that the move-in stuff gets fired only once.
10638				if ( !sortable.isOver ) {
10639					sortable.isOver = 1;
10640
10641					// Store draggable's parent in case we need to reappend to it later.
10642					draggable._parent = ui.helper.parent();
10643
10644					sortable.currentItem = ui.helper
10645						.appendTo( sortable.element )
10646						.data( "ui-sortable-item", true );
10647
10648					// Store helper option to later restore it
10649					sortable.options._helper = sortable.options.helper;
10650
10651					sortable.options.helper = function() {
10652						return ui.helper[ 0 ];
10653					};
10654
10655					// Fire the start events of the sortable with our passed browser event,
10656					// and our own helper (so it doesn't create a new one)
10657					event.target = sortable.currentItem[ 0 ];
10658					sortable._mouseCapture( event, true );
10659					sortable._mouseStart( event, true, true );
10660
10661					// Because the browser event is way off the new appended portlet,
10662					// modify necessary variables to reflect the changes
10663					sortable.offset.click.top = draggable.offset.click.top;
10664					sortable.offset.click.left = draggable.offset.click.left;
10665					sortable.offset.parent.left -= draggable.offset.parent.left -
10666						sortable.offset.parent.left;
10667					sortable.offset.parent.top -= draggable.offset.parent.top -
10668						sortable.offset.parent.top;
10669
10670					draggable._trigger( "toSortable", event );
10671
10672					// Inform draggable that the helper is in a valid drop zone,
10673					// used solely in the revert option to handle "valid/invalid".
10674					draggable.dropped = sortable.element;
10675
10676					// Need to refreshPositions of all sortables in the case that
10677					// adding to one sortable changes the location of the other sortables (#9675)
10678					$.each( draggable.sortables, function() {
10679						this.refreshPositions();
10680					} );
10681
10682					// Hack so receive/update callbacks work (mostly)
10683					draggable.currentItem = draggable.element;
10684					sortable.fromOutside = draggable;
10685				}
10686
10687				if ( sortable.currentItem ) {
10688					sortable._mouseDrag( event );
10689
10690					// Copy the sortable's position because the draggable's can potentially reflect
10691					// a relative position, while sortable is always absolute, which the dragged
10692					// element has now become. (#8809)
10693					ui.position = sortable.position;
10694				}
10695			} else {
10696
10697				// If it doesn't intersect with the sortable, and it intersected before,
10698				// we fake the drag stop of the sortable, but make sure it doesn't remove
10699				// the helper by using cancelHelperRemoval.
10700				if ( sortable.isOver ) {
10701
10702					sortable.isOver = 0;
10703					sortable.cancelHelperRemoval = true;
10704
10705					// Calling sortable's mouseStop would trigger a revert,
10706					// so revert must be temporarily false until after mouseStop is called.
10707					sortable.options._revert = sortable.options.revert;
10708					sortable.options.revert = false;
10709
10710					sortable._trigger( "out", event, sortable._uiHash( sortable ) );
10711					sortable._mouseStop( event, true );
10712
10713					// Restore sortable behaviors that were modfied
10714					// when the draggable entered the sortable area (#9481)
10715					sortable.options.revert = sortable.options._revert;
10716					sortable.options.helper = sortable.options._helper;
10717
10718					if ( sortable.placeholder ) {
10719						sortable.placeholder.remove();
10720					}
10721
10722					// Restore and recalculate the draggable's offset considering the sortable
10723					// may have modified them in unexpected ways. (#8809, #10669)
10724					ui.helper.appendTo( draggable._parent );
10725					draggable._refreshOffsets( event );
10726					ui.position = draggable._generatePosition( event, true );
10727
10728					draggable._trigger( "fromSortable", event );
10729
10730					// Inform draggable that the helper is no longer in a valid drop zone
10731					draggable.dropped = false;
10732
10733					// Need to refreshPositions of all sortables just in case removing
10734					// from one sortable changes the location of other sortables (#9675)
10735					$.each( draggable.sortables, function() {
10736						this.refreshPositions();
10737					} );
10738				}
10739			}
10740		} );
10741	}
10742} );
10743
10744$.ui.plugin.add( "draggable", "cursor", {
10745	start: function( event, ui, instance ) {
10746		var t = $( "body" ),
10747			o = instance.options;
10748
10749		if ( t.css( "cursor" ) ) {
10750			o._cursor = t.css( "cursor" );
10751		}
10752		t.css( "cursor", o.cursor );
10753	},
10754	stop: function( event, ui, instance ) {
10755		var o = instance.options;
10756		if ( o._cursor ) {
10757			$( "body" ).css( "cursor", o._cursor );
10758		}
10759	}
10760} );
10761
10762$.ui.plugin.add( "draggable", "opacity", {
10763	start: function( event, ui, instance ) {
10764		var t = $( ui.helper ),
10765			o = instance.options;
10766		if ( t.css( "opacity" ) ) {
10767			o._opacity = t.css( "opacity" );
10768		}
10769		t.css( "opacity", o.opacity );
10770	},
10771	stop: function( event, ui, instance ) {
10772		var o = instance.options;
10773		if ( o._opacity ) {
10774			$( ui.helper ).css( "opacity", o._opacity );
10775		}
10776	}
10777} );
10778
10779$.ui.plugin.add( "draggable", "scroll", {
10780	start: function( event, ui, i ) {
10781		if ( !i.scrollParentNotHidden ) {
10782			i.scrollParentNotHidden = i.helper.scrollParent( false );
10783		}
10784
10785		if ( i.scrollParentNotHidden[ 0 ] !== i.document[ 0 ] &&
10786				i.scrollParentNotHidden[ 0 ].tagName !== "HTML" ) {
10787			i.overflowOffset = i.scrollParentNotHidden.offset();
10788		}
10789	},
10790	drag: function( event, ui, i  ) {
10791
10792		var o = i.options,
10793			scrolled = false,
10794			scrollParent = i.scrollParentNotHidden[ 0 ],
10795			document = i.document[ 0 ];
10796
10797		if ( scrollParent !== document && scrollParent.tagName !== "HTML" ) {
10798			if ( !o.axis || o.axis !== "x" ) {
10799				if ( ( i.overflowOffset.top + scrollParent.offsetHeight ) - event.pageY <
10800						o.scrollSensitivity ) {
10801					scrollParent.scrollTop = scrolled = scrollParent.scrollTop + o.scrollSpeed;
10802				} else if ( event.pageY - i.overflowOffset.top < o.scrollSensitivity ) {
10803					scrollParent.scrollTop = scrolled = scrollParent.scrollTop - o.scrollSpeed;
10804				}
10805			}
10806
10807			if ( !o.axis || o.axis !== "y" ) {
10808				if ( ( i.overflowOffset.left + scrollParent.offsetWidth ) - event.pageX <
10809						o.scrollSensitivity ) {
10810					scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft + o.scrollSpeed;
10811				} else if ( event.pageX - i.overflowOffset.left < o.scrollSensitivity ) {
10812					scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft - o.scrollSpeed;
10813				}
10814			}
10815
10816		} else {
10817
10818			if ( !o.axis || o.axis !== "x" ) {
10819				if ( event.pageY - $( document ).scrollTop() < o.scrollSensitivity ) {
10820					scrolled = $( document ).scrollTop( $( document ).scrollTop() - o.scrollSpeed );
10821				} else if ( $( window ).height() - ( event.pageY - $( document ).scrollTop() ) <
10822						o.scrollSensitivity ) {
10823					scrolled = $( document ).scrollTop( $( document ).scrollTop() + o.scrollSpeed );
10824				}
10825			}
10826
10827			if ( !o.axis || o.axis !== "y" ) {
10828				if ( event.pageX - $( document ).scrollLeft() < o.scrollSensitivity ) {
10829					scrolled = $( document ).scrollLeft(
10830						$( document ).scrollLeft() - o.scrollSpeed
10831					);
10832				} else if ( $( window ).width() - ( event.pageX - $( document ).scrollLeft() ) <
10833						o.scrollSensitivity ) {
10834					scrolled = $( document ).scrollLeft(
10835						$( document ).scrollLeft() + o.scrollSpeed
10836					);
10837				}
10838			}
10839
10840		}
10841
10842		if ( scrolled !== false && $.ui.ddmanager && !o.dropBehaviour ) {
10843			$.ui.ddmanager.prepareOffsets( i, event );
10844		}
10845
10846	}
10847} );
10848
10849$.ui.plugin.add( "draggable", "snap", {
10850	start: function( event, ui, i ) {
10851
10852		var o = i.options;
10853
10854		i.snapElements = [];
10855
10856		$( o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap )
10857			.each( function() {
10858				var $t = $( this ),
10859					$o = $t.offset();
10860				if ( this !== i.element[ 0 ] ) {
10861					i.snapElements.push( {
10862						item: this,
10863						width: $t.outerWidth(), height: $t.outerHeight(),
10864						top: $o.top, left: $o.left
10865					} );
10866				}
10867			} );
10868
10869	},
10870	drag: function( event, ui, inst ) {
10871
10872		var ts, bs, ls, rs, l, r, t, b, i, first,
10873			o = inst.options,
10874			d = o.snapTolerance,
10875			x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
10876			y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
10877
10878		for ( i = inst.snapElements.length - 1; i >= 0; i-- ) {
10879
10880			l = inst.snapElements[ i ].left - inst.margins.left;
10881			r = l + inst.snapElements[ i ].width;
10882			t = inst.snapElements[ i ].top - inst.margins.top;
10883			b = t + inst.snapElements[ i ].height;
10884
10885			if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d ||
10886					!$.contains( inst.snapElements[ i ].item.ownerDocument,
10887					inst.snapElements[ i ].item ) ) {
10888				if ( inst.snapElements[ i ].snapping ) {
10889					if ( inst.options.snap.release ) {
10890						inst.options.snap.release.call(
10891							inst.element,
10892							event,
10893							$.extend( inst._uiHash(), { snapItem: inst.snapElements[ i ].item } )
10894						);
10895					}
10896				}
10897				inst.snapElements[ i ].snapping = false;
10898				continue;
10899			}
10900
10901			if ( o.snapMode !== "inner" ) {
10902				ts = Math.abs( t - y2 ) <= d;
10903				bs = Math.abs( b - y1 ) <= d;
10904				ls = Math.abs( l - x2 ) <= d;
10905				rs = Math.abs( r - x1 ) <= d;
10906				if ( ts ) {
10907					ui.position.top = inst._convertPositionTo( "relative", {
10908						top: t - inst.helperProportions.height,
10909						left: 0
10910					} ).top;
10911				}
10912				if ( bs ) {
10913					ui.position.top = inst._convertPositionTo( "relative", {
10914						top: b,
10915						left: 0
10916					} ).top;
10917				}
10918				if ( ls ) {
10919					ui.position.left = inst._convertPositionTo( "relative", {
10920						top: 0,
10921						left: l - inst.helperProportions.width
10922					} ).left;
10923				}
10924				if ( rs ) {
10925					ui.position.left = inst._convertPositionTo( "relative", {
10926						top: 0,
10927						left: r
10928					} ).left;
10929				}
10930			}
10931
10932			first = ( ts || bs || ls || rs );
10933
10934			if ( o.snapMode !== "outer" ) {
10935				ts = Math.abs( t - y1 ) <= d;
10936				bs = Math.abs( b - y2 ) <= d;
10937				ls = Math.abs( l - x1 ) <= d;
10938				rs = Math.abs( r - x2 ) <= d;
10939				if ( ts ) {
10940					ui.position.top = inst._convertPositionTo( "relative", {
10941						top: t,
10942						left: 0
10943					} ).top;
10944				}
10945				if ( bs ) {
10946					ui.position.top = inst._convertPositionTo( "relative", {
10947						top: b - inst.helperProportions.height,
10948						left: 0
10949					} ).top;
10950				}
10951				if ( ls ) {
10952					ui.position.left = inst._convertPositionTo( "relative", {
10953						top: 0,
10954						left: l
10955					} ).left;
10956				}
10957				if ( rs ) {
10958					ui.position.left = inst._convertPositionTo( "relative", {
10959						top: 0,
10960						left: r - inst.helperProportions.width
10961					} ).left;
10962				}
10963			}
10964
10965			if ( !inst.snapElements[ i ].snapping && ( ts || bs || ls || rs || first ) ) {
10966				if ( inst.options.snap.snap ) {
10967					inst.options.snap.snap.call(
10968						inst.element,
10969						event,
10970						$.extend( inst._uiHash(), {
10971							snapItem: inst.snapElements[ i ].item
10972						} ) );
10973				}
10974			}
10975			inst.snapElements[ i ].snapping = ( ts || bs || ls || rs || first );
10976
10977		}
10978
10979	}
10980} );
10981
10982$.ui.plugin.add( "draggable", "stack", {
10983	start: function( event, ui, instance ) {
10984		var min,
10985			o = instance.options,
10986			group = $.makeArray( $( o.stack ) ).sort( function( a, b ) {
10987				return ( parseInt( $( a ).css( "zIndex" ), 10 ) || 0 ) -
10988					( parseInt( $( b ).css( "zIndex" ), 10 ) || 0 );
10989			} );
10990
10991		if ( !group.length ) {
10992			return;
10993		}
10994
10995		min = parseInt( $( group[ 0 ] ).css( "zIndex" ), 10 ) || 0;
10996		$( group ).each( function( i ) {
10997			$( this ).css( "zIndex", min + i );
10998		} );
10999		this.css( "zIndex", ( min + group.length ) );
11000	}
11001} );
11002
11003$.ui.plugin.add( "draggable", "zIndex", {
11004	start: function( event, ui, instance ) {
11005		var t = $( ui.helper ),
11006			o = instance.options;
11007
11008		if ( t.css( "zIndex" ) ) {
11009			o._zIndex = t.css( "zIndex" );
11010		}
11011		t.css( "zIndex", o.zIndex );
11012	},
11013	stop: function( event, ui, instance ) {
11014		var o = instance.options;
11015
11016		if ( o._zIndex ) {
11017			$( ui.helper ).css( "zIndex", o._zIndex );
11018		}
11019	}
11020} );
11021
11022var widgetsDraggable = $.ui.draggable;
11023
11024
11025/*!
11026 * jQuery UI Resizable 1.13.3
11027 * https://jqueryui.com
11028 *
11029 * Copyright OpenJS Foundation and other contributors
11030 * Released under the MIT license.
11031 * https://jquery.org/license
11032 */
11033
11034//>>label: Resizable
11035//>>group: Interactions
11036//>>description: Enables resize functionality for any element.
11037//>>docs: https://api.jqueryui.com/resizable/
11038//>>demos: https://jqueryui.com/resizable/
11039//>>css.structure: ../../themes/base/core.css
11040//>>css.structure: ../../themes/base/resizable.css
11041//>>css.theme: ../../themes/base/theme.css
11042
11043
11044$.widget( "ui.resizable", $.ui.mouse, {
11045	version: "1.13.3",
11046	widgetEventPrefix: "resize",
11047	options: {
11048		alsoResize: false,
11049		animate: false,
11050		animateDuration: "slow",
11051		animateEasing: "swing",
11052		aspectRatio: false,
11053		autoHide: false,
11054		classes: {
11055			"ui-resizable-se": "ui-icon ui-icon-gripsmall-diagonal-se"
11056		},
11057		containment: false,
11058		ghost: false,
11059		grid: false,
11060		handles: "e,s,se",
11061		helper: false,
11062		maxHeight: null,
11063		maxWidth: null,
11064		minHeight: 10,
11065		minWidth: 10,
11066
11067		// See #7960
11068		zIndex: 90,
11069
11070		// Callbacks
11071		resize: null,
11072		start: null,
11073		stop: null
11074	},
11075
11076	_num: function( value ) {
11077		return parseFloat( value ) || 0;
11078	},
11079
11080	_isNumber: function( value ) {
11081		return !isNaN( parseFloat( value ) );
11082	},
11083
11084	_hasScroll: function( el, a ) {
11085
11086		if ( $( el ).css( "overflow" ) === "hidden" ) {
11087			return false;
11088		}
11089
11090		var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
11091			has = false;
11092
11093		if ( el[ scroll ] > 0 ) {
11094			return true;
11095		}
11096
11097		// TODO: determine which cases actually cause this to happen
11098		// if the element doesn't have the scroll set, see if it's possible to
11099		// set the scroll
11100		try {
11101			el[ scroll ] = 1;
11102			has = ( el[ scroll ] > 0 );
11103			el[ scroll ] = 0;
11104		} catch ( e ) {
11105
11106			// `el` might be a string, then setting `scroll` will throw
11107			// an error in strict mode; ignore it.
11108		}
11109		return has;
11110	},
11111
11112	_create: function() {
11113
11114		var margins,
11115			o = this.options,
11116			that = this;
11117		this._addClass( "ui-resizable" );
11118
11119		$.extend( this, {
11120			_aspectRatio: !!( o.aspectRatio ),
11121			aspectRatio: o.aspectRatio,
11122			originalElement: this.element,
11123			_proportionallyResizeElements: [],
11124			_helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null
11125		} );
11126
11127		// Wrap the element if it cannot hold child nodes
11128		if ( this.element[ 0 ].nodeName.match( /^(canvas|textarea|input|select|button|img)$/i ) ) {
11129
11130			this.element.wrap(
11131				$( "<div class='ui-wrapper'></div>" ).css( {
11132					overflow: "hidden",
11133					position: this.element.css( "position" ),
11134					width: this.element.outerWidth(),
11135					height: this.element.outerHeight(),
11136					top: this.element.css( "top" ),
11137					left: this.element.css( "left" )
11138				} )
11139			);
11140
11141			this.element = this.element.parent().data(
11142				"ui-resizable", this.element.resizable( "instance" )
11143			);
11144
11145			this.elementIsWrapper = true;
11146
11147			margins = {
11148				marginTop: this.originalElement.css( "marginTop" ),
11149				marginRight: this.originalElement.css( "marginRight" ),
11150				marginBottom: this.originalElement.css( "marginBottom" ),
11151				marginLeft: this.originalElement.css( "marginLeft" )
11152			};
11153
11154			this.element.css( margins );
11155			this.originalElement.css( "margin", 0 );
11156
11157			// support: Safari
11158			// Prevent Safari textarea resize
11159			this.originalResizeStyle = this.originalElement.css( "resize" );
11160			this.originalElement.css( "resize", "none" );
11161
11162			this._proportionallyResizeElements.push( this.originalElement.css( {
11163				position: "static",
11164				zoom: 1,
11165				display: "block"
11166			} ) );
11167
11168			// Support: IE9
11169			// avoid IE jump (hard set the margin)
11170			this.originalElement.css( margins );
11171
11172			this._proportionallyResize();
11173		}
11174
11175		this._setupHandles();
11176
11177		if ( o.autoHide ) {
11178			$( this.element )
11179				.on( "mouseenter", function() {
11180					if ( o.disabled ) {
11181						return;
11182					}
11183					that._removeClass( "ui-resizable-autohide" );
11184					that._handles.show();
11185				} )
11186				.on( "mouseleave", function() {
11187					if ( o.disabled ) {
11188						return;
11189					}
11190					if ( !that.resizing ) {
11191						that._addClass( "ui-resizable-autohide" );
11192						that._handles.hide();
11193					}
11194				} );
11195		}
11196
11197		this._mouseInit();
11198	},
11199
11200	_destroy: function() {
11201
11202		this._mouseDestroy();
11203		this._addedHandles.remove();
11204
11205		var wrapper,
11206			_destroy = function( exp ) {
11207				$( exp )
11208					.removeData( "resizable" )
11209					.removeData( "ui-resizable" )
11210					.off( ".resizable" );
11211			};
11212
11213		// TODO: Unwrap at same DOM position
11214		if ( this.elementIsWrapper ) {
11215			_destroy( this.element );
11216			wrapper = this.element;
11217			this.originalElement.css( {
11218				position: wrapper.css( "position" ),
11219				width: wrapper.outerWidth(),
11220				height: wrapper.outerHeight(),
11221				top: wrapper.css( "top" ),
11222				left: wrapper.css( "left" )
11223			} ).insertAfter( wrapper );
11224			wrapper.remove();
11225		}
11226
11227		this.originalElement.css( "resize", this.originalResizeStyle );
11228		_destroy( this.originalElement );
11229
11230		return this;
11231	},
11232
11233	_setOption: function( key, value ) {
11234		this._super( key, value );
11235
11236		switch ( key ) {
11237		case "handles":
11238			this._removeHandles();
11239			this._setupHandles();
11240			break;
11241		case "aspectRatio":
11242			this._aspectRatio = !!value;
11243			break;
11244		default:
11245			break;
11246		}
11247	},
11248
11249	_setupHandles: function() {
11250		var o = this.options, handle, i, n, hname, axis, that = this;
11251		this.handles = o.handles ||
11252			( !$( ".ui-resizable-handle", this.element ).length ?
11253				"e,s,se" : {
11254					n: ".ui-resizable-n",
11255					e: ".ui-resizable-e",
11256					s: ".ui-resizable-s",
11257					w: ".ui-resizable-w",
11258					se: ".ui-resizable-se",
11259					sw: ".ui-resizable-sw",
11260					ne: ".ui-resizable-ne",
11261					nw: ".ui-resizable-nw"
11262				} );
11263
11264		this._handles = $();
11265		this._addedHandles = $();
11266		if ( this.handles.constructor === String ) {
11267
11268			if ( this.handles === "all" ) {
11269				this.handles = "n,e,s,w,se,sw,ne,nw";
11270			}
11271
11272			n = this.handles.split( "," );
11273			this.handles = {};
11274
11275			for ( i = 0; i < n.length; i++ ) {
11276
11277				handle = String.prototype.trim.call( n[ i ] );
11278				hname = "ui-resizable-" + handle;
11279				axis = $( "<div>" );
11280				this._addClass( axis, "ui-resizable-handle " + hname );
11281
11282				axis.css( { zIndex: o.zIndex } );
11283
11284				this.handles[ handle ] = ".ui-resizable-" + handle;
11285				if ( !this.element.children( this.handles[ handle ] ).length ) {
11286					this.element.append( axis );
11287					this._addedHandles = this._addedHandles.add( axis );
11288				}
11289			}
11290
11291		}
11292
11293		this._renderAxis = function( target ) {
11294
11295			var i, axis, padPos, padWrapper;
11296
11297			target = target || this.element;
11298
11299			for ( i in this.handles ) {
11300
11301				if ( this.handles[ i ].constructor === String ) {
11302					this.handles[ i ] = this.element.children( this.handles[ i ] ).first().show();
11303				} else if ( this.handles[ i ].jquery || this.handles[ i ].nodeType ) {
11304					this.handles[ i ] = $( this.handles[ i ] );
11305					this._on( this.handles[ i ], { "mousedown": that._mouseDown } );
11306				}
11307
11308				if ( this.elementIsWrapper &&
11309						this.originalElement[ 0 ]
11310							.nodeName
11311							.match( /^(textarea|input|select|button)$/i ) ) {
11312					axis = $( this.handles[ i ], this.element );
11313
11314					padWrapper = /sw|ne|nw|se|n|s/.test( i ) ?
11315						axis.outerHeight() :
11316						axis.outerWidth();
11317
11318					padPos = [ "padding",
11319						/ne|nw|n/.test( i ) ? "Top" :
11320						/se|sw|s/.test( i ) ? "Bottom" :
11321						/^e$/.test( i ) ? "Right" : "Left" ].join( "" );
11322
11323					target.css( padPos, padWrapper );
11324
11325					this._proportionallyResize();
11326				}
11327
11328				this._handles = this._handles.add( this.handles[ i ] );
11329			}
11330		};
11331
11332		// TODO: make renderAxis a prototype function
11333		this._renderAxis( this.element );
11334
11335		this._handles = this._handles.add( this.element.find( ".ui-resizable-handle" ) );
11336		this._handles.disableSelection();
11337
11338		this._handles.on( "mouseover", function() {
11339			if ( !that.resizing ) {
11340				if ( this.className ) {
11341					axis = this.className.match( /ui-resizable-(se|sw|ne|nw|n|e|s|w)/i );
11342				}
11343				that.axis = axis && axis[ 1 ] ? axis[ 1 ] : "se";
11344			}
11345		} );
11346
11347		if ( o.autoHide ) {
11348			this._handles.hide();
11349			this._addClass( "ui-resizable-autohide" );
11350		}
11351	},
11352
11353	_removeHandles: function() {
11354		this._addedHandles.remove();
11355	},
11356
11357	_mouseCapture: function( event ) {
11358		var i, handle,
11359			capture = false;
11360
11361		for ( i in this.handles ) {
11362			handle = $( this.handles[ i ] )[ 0 ];
11363			if ( handle === event.target || $.contains( handle, event.target ) ) {
11364				capture = true;
11365			}
11366		}
11367
11368		return !this.options.disabled && capture;
11369	},
11370
11371	_mouseStart: function( event ) {
11372
11373		var curleft, curtop, cursor,
11374			o = this.options,
11375			el = this.element;
11376
11377		this.resizing = true;
11378
11379		this._renderProxy();
11380
11381		curleft = this._num( this.helper.css( "left" ) );
11382		curtop = this._num( this.helper.css( "top" ) );
11383
11384		if ( o.containment ) {
11385			curleft += $( o.containment ).scrollLeft() || 0;
11386			curtop += $( o.containment ).scrollTop() || 0;
11387		}
11388
11389		this.offset = this.helper.offset();
11390		this.position = { left: curleft, top: curtop };
11391
11392		this.size = this._helper ? {
11393				width: this.helper.width(),
11394				height: this.helper.height()
11395			} : {
11396				width: el.width(),
11397				height: el.height()
11398			};
11399
11400		this.originalSize = this._helper ? {
11401				width: el.outerWidth(),
11402				height: el.outerHeight()
11403			} : {
11404				width: el.width(),
11405				height: el.height()
11406			};
11407
11408		this.sizeDiff = {
11409			width: el.outerWidth() - el.width(),
11410			height: el.outerHeight() - el.height()
11411		};
11412
11413		this.originalPosition = { left: curleft, top: curtop };
11414		this.originalMousePosition = { left: event.pageX, top: event.pageY };
11415
11416		this.aspectRatio = ( typeof o.aspectRatio === "number" ) ?
11417			o.aspectRatio :
11418			( ( this.originalSize.width / this.originalSize.height ) || 1 );
11419
11420		cursor = $( ".ui-resizable-" + this.axis ).css( "cursor" );
11421		$( "body" ).css( "cursor", cursor === "auto" ? this.axis + "-resize" : cursor );
11422
11423		this._addClass( "ui-resizable-resizing" );
11424		this._propagate( "start", event );
11425		return true;
11426	},
11427
11428	_mouseDrag: function( event ) {
11429
11430		var data, props,
11431			smp = this.originalMousePosition,
11432			a = this.axis,
11433			dx = ( event.pageX - smp.left ) || 0,
11434			dy = ( event.pageY - smp.top ) || 0,
11435			trigger = this._change[ a ];
11436
11437		this._updatePrevProperties();
11438
11439		if ( !trigger ) {
11440			return false;
11441		}
11442
11443		data = trigger.apply( this, [ event, dx, dy ] );
11444
11445		this._updateVirtualBoundaries( event.shiftKey );
11446		if ( this._aspectRatio || event.shiftKey ) {
11447			data = this._updateRatio( data, event );
11448		}
11449
11450		data = this._respectSize( data, event );
11451
11452		this._updateCache( data );
11453
11454		this._propagate( "resize", event );
11455
11456		props = this._applyChanges();
11457
11458		if ( !this._helper && this._proportionallyResizeElements.length ) {
11459			this._proportionallyResize();
11460		}
11461
11462		if ( !$.isEmptyObject( props ) ) {
11463			this._updatePrevProperties();
11464			this._trigger( "resize", event, this.ui() );
11465			this._applyChanges();
11466		}
11467
11468		return false;
11469	},
11470
11471	_mouseStop: function( event ) {
11472
11473		this.resizing = false;
11474		var pr, ista, soffseth, soffsetw, s, left, top,
11475			o = this.options, that = this;
11476
11477		if ( this._helper ) {
11478
11479			pr = this._proportionallyResizeElements;
11480			ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName );
11481			soffseth = ista && this._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height;
11482			soffsetw = ista ? 0 : that.sizeDiff.width;
11483
11484			s = {
11485				width: ( that.helper.width()  - soffsetw ),
11486				height: ( that.helper.height() - soffseth )
11487			};
11488			left = ( parseFloat( that.element.css( "left" ) ) +
11489				( that.position.left - that.originalPosition.left ) ) || null;
11490			top = ( parseFloat( that.element.css( "top" ) ) +
11491				( that.position.top - that.originalPosition.top ) ) || null;
11492
11493			if ( !o.animate ) {
11494				this.element.css( $.extend( s, { top: top, left: left } ) );
11495			}
11496
11497			that.helper.height( that.size.height );
11498			that.helper.width( that.size.width );
11499
11500			if ( this._helper && !o.animate ) {
11501				this._proportionallyResize();
11502			}
11503		}
11504
11505		$( "body" ).css( "cursor", "auto" );
11506
11507		this._removeClass( "ui-resizable-resizing" );
11508
11509		this._propagate( "stop", event );
11510
11511		if ( this._helper ) {
11512			this.helper.remove();
11513		}
11514
11515		return false;
11516
11517	},
11518
11519	_updatePrevProperties: function() {
11520		this.prevPosition = {
11521			top: this.position.top,
11522			left: this.position.left
11523		};
11524		this.prevSize = {
11525			width: this.size.width,
11526			height: this.size.height
11527		};
11528	},
11529
11530	_applyChanges: function() {
11531		var props = {};
11532
11533		if ( this.position.top !== this.prevPosition.top ) {
11534			props.top = this.position.top + "px";
11535		}
11536		if ( this.position.left !== this.prevPosition.left ) {
11537			props.left = this.position.left + "px";
11538		}
11539
11540		this.helper.css( props );
11541
11542		if ( this.size.width !== this.prevSize.width ) {
11543			props.width = this.size.width + "px";
11544			this.helper.width( props.width );
11545		}
11546		if ( this.size.height !== this.prevSize.height ) {
11547			props.height = this.size.height + "px";
11548			this.helper.height( props.height );
11549		}
11550
11551		return props;
11552	},
11553
11554	_updateVirtualBoundaries: function( forceAspectRatio ) {
11555		var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b,
11556			o = this.options;
11557
11558		b = {
11559			minWidth: this._isNumber( o.minWidth ) ? o.minWidth : 0,
11560			maxWidth: this._isNumber( o.maxWidth ) ? o.maxWidth : Infinity,
11561			minHeight: this._isNumber( o.minHeight ) ? o.minHeight : 0,
11562			maxHeight: this._isNumber( o.maxHeight ) ? o.maxHeight : Infinity
11563		};
11564
11565		if ( this._aspectRatio || forceAspectRatio ) {
11566			pMinWidth = b.minHeight * this.aspectRatio;
11567			pMinHeight = b.minWidth / this.aspectRatio;
11568			pMaxWidth = b.maxHeight * this.aspectRatio;
11569			pMaxHeight = b.maxWidth / this.aspectRatio;
11570
11571			if ( pMinWidth > b.minWidth ) {
11572				b.minWidth = pMinWidth;
11573			}
11574			if ( pMinHeight > b.minHeight ) {
11575				b.minHeight = pMinHeight;
11576			}
11577			if ( pMaxWidth < b.maxWidth ) {
11578				b.maxWidth = pMaxWidth;
11579			}
11580			if ( pMaxHeight < b.maxHeight ) {
11581				b.maxHeight = pMaxHeight;
11582			}
11583		}
11584		this._vBoundaries = b;
11585	},
11586
11587	_updateCache: function( data ) {
11588		this.offset = this.helper.offset();
11589		if ( this._isNumber( data.left ) ) {
11590			this.position.left = data.left;
11591		}
11592		if ( this._isNumber( data.top ) ) {
11593			this.position.top = data.top;
11594		}
11595		if ( this._isNumber( data.height ) ) {
11596			this.size.height = data.height;
11597		}
11598		if ( this._isNumber( data.width ) ) {
11599			this.size.width = data.width;
11600		}
11601	},
11602
11603	_updateRatio: function( data ) {
11604
11605		var cpos = this.position,
11606			csize = this.size,
11607			a = this.axis;
11608
11609		if ( this._isNumber( data.height ) ) {
11610			data.width = ( data.height * this.aspectRatio );
11611		} else if ( this._isNumber( data.width ) ) {
11612			data.height = ( data.width / this.aspectRatio );
11613		}
11614
11615		if ( a === "sw" ) {
11616			data.left = cpos.left + ( csize.width - data.width );
11617			data.top = null;
11618		}
11619		if ( a === "nw" ) {
11620			data.top = cpos.top + ( csize.height - data.height );
11621			data.left = cpos.left + ( csize.width - data.width );
11622		}
11623
11624		return data;
11625	},
11626
11627	_respectSize: function( data ) {
11628
11629		var o = this._vBoundaries,
11630			a = this.axis,
11631			ismaxw = this._isNumber( data.width ) && o.maxWidth && ( o.maxWidth < data.width ),
11632			ismaxh = this._isNumber( data.height ) && o.maxHeight && ( o.maxHeight < data.height ),
11633			isminw = this._isNumber( data.width ) && o.minWidth && ( o.minWidth > data.width ),
11634			isminh = this._isNumber( data.height ) && o.minHeight && ( o.minHeight > data.height ),
11635			dw = this.originalPosition.left + this.originalSize.width,
11636			dh = this.originalPosition.top + this.originalSize.height,
11637			cw = /sw|nw|w/.test( a ), ch = /nw|ne|n/.test( a );
11638		if ( isminw ) {
11639			data.width = o.minWidth;
11640		}
11641		if ( isminh ) {
11642			data.height = o.minHeight;
11643		}
11644		if ( ismaxw ) {
11645			data.width = o.maxWidth;
11646		}
11647		if ( ismaxh ) {
11648			data.height = o.maxHeight;
11649		}
11650
11651		if ( isminw && cw ) {
11652			data.left = dw - o.minWidth;
11653		}
11654		if ( ismaxw && cw ) {
11655			data.left = dw - o.maxWidth;
11656		}
11657		if ( isminh && ch ) {
11658			data.top = dh - o.minHeight;
11659		}
11660		if ( ismaxh && ch ) {
11661			data.top = dh - o.maxHeight;
11662		}
11663
11664		// Fixing jump error on top/left - bug #2330
11665		if ( !data.width && !data.height && !data.left && data.top ) {
11666			data.top = null;
11667		} else if ( !data.width && !data.height && !data.top && data.left ) {
11668			data.left = null;
11669		}
11670
11671		return data;
11672	},
11673
11674	_getPaddingPlusBorderDimensions: function( element ) {
11675		var i = 0,
11676			widths = [],
11677			borders = [
11678				element.css( "borderTopWidth" ),
11679				element.css( "borderRightWidth" ),
11680				element.css( "borderBottomWidth" ),
11681				element.css( "borderLeftWidth" )
11682			],
11683			paddings = [
11684				element.css( "paddingTop" ),
11685				element.css( "paddingRight" ),
11686				element.css( "paddingBottom" ),
11687				element.css( "paddingLeft" )
11688			];
11689
11690		for ( ; i < 4; i++ ) {
11691			widths[ i ] = ( parseFloat( borders[ i ] ) || 0 );
11692			widths[ i ] += ( parseFloat( paddings[ i ] ) || 0 );
11693		}
11694
11695		return {
11696			height: widths[ 0 ] + widths[ 2 ],
11697			width: widths[ 1 ] + widths[ 3 ]
11698		};
11699	},
11700
11701	_proportionallyResize: function() {
11702
11703		if ( !this._proportionallyResizeElements.length ) {
11704			return;
11705		}
11706
11707		var prel,
11708			i = 0,
11709			element = this.helper || this.element;
11710
11711		for ( ; i < this._proportionallyResizeElements.length; i++ ) {
11712
11713			prel = this._proportionallyResizeElements[ i ];
11714
11715			// TODO: Seems like a bug to cache this.outerDimensions
11716			// considering that we are in a loop.
11717			if ( !this.outerDimensions ) {
11718				this.outerDimensions = this._getPaddingPlusBorderDimensions( prel );
11719			}
11720
11721			prel.css( {
11722				height: ( element.height() - this.outerDimensions.height ) || 0,
11723				width: ( element.width() - this.outerDimensions.width ) || 0
11724			} );
11725
11726		}
11727
11728	},
11729
11730	_renderProxy: function() {
11731
11732		var el = this.element, o = this.options;
11733		this.elementOffset = el.offset();
11734
11735		if ( this._helper ) {
11736
11737			this.helper = this.helper || $( "<div></div>" ).css( { overflow: "hidden" } );
11738
11739			this._addClass( this.helper, this._helper );
11740			this.helper.css( {
11741				width: this.element.outerWidth(),
11742				height: this.element.outerHeight(),
11743				position: "absolute",
11744				left: this.elementOffset.left + "px",
11745				top: this.elementOffset.top + "px",
11746				zIndex: ++o.zIndex //TODO: Don't modify option
11747			} );
11748
11749			this.helper
11750				.appendTo( "body" )
11751				.disableSelection();
11752
11753		} else {
11754			this.helper = this.element;
11755		}
11756
11757	},
11758
11759	_change: {
11760		e: function( event, dx ) {
11761			return { width: this.originalSize.width + dx };
11762		},
11763		w: function( event, dx ) {
11764			var cs = this.originalSize, sp = this.originalPosition;
11765			return { left: sp.left + dx, width: cs.width - dx };
11766		},
11767		n: function( event, dx, dy ) {
11768			var cs = this.originalSize, sp = this.originalPosition;
11769			return { top: sp.top + dy, height: cs.height - dy };
11770		},
11771		s: function( event, dx, dy ) {
11772			return { height: this.originalSize.height + dy };
11773		},
11774		se: function( event, dx, dy ) {
11775			return $.extend( this._change.s.apply( this, arguments ),
11776				this._change.e.apply( this, [ event, dx, dy ] ) );
11777		},
11778		sw: function( event, dx, dy ) {
11779			return $.extend( this._change.s.apply( this, arguments ),
11780				this._change.w.apply( this, [ event, dx, dy ] ) );
11781		},
11782		ne: function( event, dx, dy ) {
11783			return $.extend( this._change.n.apply( this, arguments ),
11784				this._change.e.apply( this, [ event, dx, dy ] ) );
11785		},
11786		nw: function( event, dx, dy ) {
11787			return $.extend( this._change.n.apply( this, arguments ),
11788				this._change.w.apply( this, [ event, dx, dy ] ) );
11789		}
11790	},
11791
11792	_propagate: function( n, event ) {
11793		$.ui.plugin.call( this, n, [ event, this.ui() ] );
11794		if ( n !== "resize" ) {
11795			this._trigger( n, event, this.ui() );
11796		}
11797	},
11798
11799	plugins: {},
11800
11801	ui: function() {
11802		return {
11803			originalElement: this.originalElement,
11804			element: this.element,
11805			helper: this.helper,
11806			position: this.position,
11807			size: this.size,
11808			originalSize: this.originalSize,
11809			originalPosition: this.originalPosition
11810		};
11811	}
11812
11813} );
11814
11815/*
11816 * Resizable Extensions
11817 */
11818
11819$.ui.plugin.add( "resizable", "animate", {
11820
11821	stop: function( event ) {
11822		var that = $( this ).resizable( "instance" ),
11823			o = that.options,
11824			pr = that._proportionallyResizeElements,
11825			ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName ),
11826			soffseth = ista && that._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height,
11827			soffsetw = ista ? 0 : that.sizeDiff.width,
11828			style = {
11829				width: ( that.size.width - soffsetw ),
11830				height: ( that.size.height - soffseth )
11831			},
11832			left = ( parseFloat( that.element.css( "left" ) ) +
11833				( that.position.left - that.originalPosition.left ) ) || null,
11834			top = ( parseFloat( that.element.css( "top" ) ) +
11835				( that.position.top - that.originalPosition.top ) ) || null;
11836
11837		that.element.animate(
11838			$.extend( style, top && left ? { top: top, left: left } : {} ), {
11839				duration: o.animateDuration,
11840				easing: o.animateEasing,
11841				step: function() {
11842
11843					var data = {
11844						width: parseFloat( that.element.css( "width" ) ),
11845						height: parseFloat( that.element.css( "height" ) ),
11846						top: parseFloat( that.element.css( "top" ) ),
11847						left: parseFloat( that.element.css( "left" ) )
11848					};
11849
11850					if ( pr && pr.length ) {
11851						$( pr[ 0 ] ).css( { width: data.width, height: data.height } );
11852					}
11853
11854					// Propagating resize, and updating values for each animation step
11855					that._updateCache( data );
11856					that._propagate( "resize", event );
11857
11858				}
11859			}
11860		);
11861	}
11862
11863} );
11864
11865$.ui.plugin.add( "resizable", "containment", {
11866
11867	start: function() {
11868		var element, p, co, ch, cw, width, height,
11869			that = $( this ).resizable( "instance" ),
11870			o = that.options,
11871			el = that.element,
11872			oc = o.containment,
11873			ce = ( oc instanceof $ ) ?
11874				oc.get( 0 ) :
11875				( /parent/.test( oc ) ) ? el.parent().get( 0 ) : oc;
11876
11877		if ( !ce ) {
11878			return;
11879		}
11880
11881		that.containerElement = $( ce );
11882
11883		if ( /document/.test( oc ) || oc === document ) {
11884			that.containerOffset = {
11885				left: 0,
11886				top: 0
11887			};
11888			that.containerPosition = {
11889				left: 0,
11890				top: 0
11891			};
11892
11893			that.parentData = {
11894				element: $( document ),
11895				left: 0,
11896				top: 0,
11897				width: $( document ).width(),
11898				height: $( document ).height() || document.body.parentNode.scrollHeight
11899			};
11900		} else {
11901			element = $( ce );
11902			p = [];
11903			$( [ "Top", "Right", "Left", "Bottom" ] ).each( function( i, name ) {
11904				p[ i ] = that._num( element.css( "padding" + name ) );
11905			} );
11906
11907			that.containerOffset = element.offset();
11908			that.containerPosition = element.position();
11909			that.containerSize = {
11910				height: ( element.innerHeight() - p[ 3 ] ),
11911				width: ( element.innerWidth() - p[ 1 ] )
11912			};
11913
11914			co = that.containerOffset;
11915			ch = that.containerSize.height;
11916			cw = that.containerSize.width;
11917			width = ( that._hasScroll( ce, "left" ) ? ce.scrollWidth : cw );
11918			height = ( that._hasScroll( ce ) ? ce.scrollHeight : ch );
11919
11920			that.parentData = {
11921				element: ce,
11922				left: co.left,
11923				top: co.top,
11924				width: width,
11925				height: height
11926			};
11927		}
11928	},
11929
11930	resize: function( event ) {
11931		var woset, hoset, isParent, isOffsetRelative,
11932			that = $( this ).resizable( "instance" ),
11933			o = that.options,
11934			co = that.containerOffset,
11935			cp = that.position,
11936			pRatio = that._aspectRatio || event.shiftKey,
11937			cop = {
11938				top: 0,
11939				left: 0
11940			},
11941			ce = that.containerElement,
11942			continueResize = true;
11943
11944		if ( ce[ 0 ] !== document && ( /static/ ).test( ce.css( "position" ) ) ) {
11945			cop = co;
11946		}
11947
11948		if ( cp.left < ( that._helper ? co.left : 0 ) ) {
11949			that.size.width = that.size.width +
11950				( that._helper ?
11951					( that.position.left - co.left ) :
11952					( that.position.left - cop.left ) );
11953
11954			if ( pRatio ) {
11955				that.size.height = that.size.width / that.aspectRatio;
11956				continueResize = false;
11957			}
11958			that.position.left = o.helper ? co.left : 0;
11959		}
11960
11961		if ( cp.top < ( that._helper ? co.top : 0 ) ) {
11962			that.size.height = that.size.height +
11963				( that._helper ?
11964					( that.position.top - co.top ) :
11965					that.position.top );
11966
11967			if ( pRatio ) {
11968				that.size.width = that.size.height * that.aspectRatio;
11969				continueResize = false;
11970			}
11971			that.position.top = that._helper ? co.top : 0;
11972		}
11973
11974		isParent = that.containerElement.get( 0 ) === that.element.parent().get( 0 );
11975		isOffsetRelative = /relative|absolute/.test( that.containerElement.css( "position" ) );
11976
11977		if ( isParent && isOffsetRelative ) {
11978			that.offset.left = that.parentData.left + that.position.left;
11979			that.offset.top = that.parentData.top + that.position.top;
11980		} else {
11981			that.offset.left = that.element.offset().left;
11982			that.offset.top = that.element.offset().top;
11983		}
11984
11985		woset = Math.abs( that.sizeDiff.width +
11986			( that._helper ?
11987				that.offset.left - cop.left :
11988				( that.offset.left - co.left ) ) );
11989
11990		hoset = Math.abs( that.sizeDiff.height +
11991			( that._helper ?
11992				that.offset.top - cop.top :
11993				( that.offset.top - co.top ) ) );
11994
11995		if ( woset + that.size.width >= that.parentData.width ) {
11996			that.size.width = that.parentData.width - woset;
11997			if ( pRatio ) {
11998				that.size.height = that.size.width / that.aspectRatio;
11999				continueResize = false;
12000			}
12001		}
12002
12003		if ( hoset + that.size.height >= that.parentData.height ) {
12004			that.size.height = that.parentData.height - hoset;
12005			if ( pRatio ) {
12006				that.size.width = that.size.height * that.aspectRatio;
12007				continueResize = false;
12008			}
12009		}
12010
12011		if ( !continueResize ) {
12012			that.position.left = that.prevPosition.left;
12013			that.position.top = that.prevPosition.top;
12014			that.size.width = that.prevSize.width;
12015			that.size.height = that.prevSize.height;
12016		}
12017	},
12018
12019	stop: function() {
12020		var that = $( this ).resizable( "instance" ),
12021			o = that.options,
12022			co = that.containerOffset,
12023			cop = that.containerPosition,
12024			ce = that.containerElement,
12025			helper = $( that.helper ),
12026			ho = helper.offset(),
12027			w = helper.outerWidth() - that.sizeDiff.width,
12028			h = helper.outerHeight() - that.sizeDiff.height;
12029
12030		if ( that._helper && !o.animate && ( /relative/ ).test( ce.css( "position" ) ) ) {
12031			$( this ).css( {
12032				left: ho.left - cop.left - co.left,
12033				width: w,
12034				height: h
12035			} );
12036		}
12037
12038		if ( that._helper && !o.animate && ( /static/ ).test( ce.css( "position" ) ) ) {
12039			$( this ).css( {
12040				left: ho.left - cop.left - co.left,
12041				width: w,
12042				height: h
12043			} );
12044		}
12045	}
12046} );
12047
12048$.ui.plugin.add( "resizable", "alsoResize", {
12049
12050	start: function() {
12051		var that = $( this ).resizable( "instance" ),
12052			o = that.options;
12053
12054		$( o.alsoResize ).each( function() {
12055			var el = $( this );
12056			el.data( "ui-resizable-alsoresize", {
12057				width: parseFloat( el.css( "width" ) ), height: parseFloat( el.css( "height" ) ),
12058				left: parseFloat( el.css( "left" ) ), top: parseFloat( el.css( "top" ) )
12059			} );
12060		} );
12061	},
12062
12063	resize: function( event, ui ) {
12064		var that = $( this ).resizable( "instance" ),
12065			o = that.options,
12066			os = that.originalSize,
12067			op = that.originalPosition,
12068			delta = {
12069				height: ( that.size.height - os.height ) || 0,
12070				width: ( that.size.width - os.width ) || 0,
12071				top: ( that.position.top - op.top ) || 0,
12072				left: ( that.position.left - op.left ) || 0
12073			};
12074
12075			$( o.alsoResize ).each( function() {
12076				var el = $( this ), start = $( this ).data( "ui-resizable-alsoresize" ), style = {},
12077					css = el.parents( ui.originalElement[ 0 ] ).length ?
12078							[ "width", "height" ] :
12079							[ "width", "height", "top", "left" ];
12080
12081				$.each( css, function( i, prop ) {
12082					var sum = ( start[ prop ] || 0 ) + ( delta[ prop ] || 0 );
12083					if ( sum && sum >= 0 ) {
12084						style[ prop ] = sum || null;
12085					}
12086				} );
12087
12088				el.css( style );
12089			} );
12090	},
12091
12092	stop: function() {
12093		$( this ).removeData( "ui-resizable-alsoresize" );
12094	}
12095} );
12096
12097$.ui.plugin.add( "resizable", "ghost", {
12098
12099	start: function() {
12100
12101		var that = $( this ).resizable( "instance" ), cs = that.size;
12102
12103		that.ghost = that.originalElement.clone();
12104		that.ghost.css( {
12105			opacity: 0.25,
12106			display: "block",
12107			position: "relative",
12108			height: cs.height,
12109			width: cs.width,
12110			margin: 0,
12111			left: 0,
12112			top: 0
12113		} );
12114
12115		that._addClass( that.ghost, "ui-resizable-ghost" );
12116
12117		// DEPRECATED
12118		// TODO: remove after 1.12
12119		if ( $.uiBackCompat !== false && typeof that.options.ghost === "string" ) {
12120
12121			// Ghost option
12122			that.ghost.addClass( this.options.ghost );
12123		}
12124
12125		that.ghost.appendTo( that.helper );
12126
12127	},
12128
12129	resize: function() {
12130		var that = $( this ).resizable( "instance" );
12131		if ( that.ghost ) {
12132			that.ghost.css( {
12133				position: "relative",
12134				height: that.size.height,
12135				width: that.size.width
12136			} );
12137		}
12138	},
12139
12140	stop: function() {
12141		var that = $( this ).resizable( "instance" );
12142		if ( that.ghost && that.helper ) {
12143			that.helper.get( 0 ).removeChild( that.ghost.get( 0 ) );
12144		}
12145	}
12146
12147} );
12148
12149$.ui.plugin.add( "resizable", "grid", {
12150
12151	resize: function() {
12152		var outerDimensions,
12153			that = $( this ).resizable( "instance" ),
12154			o = that.options,
12155			cs = that.size,
12156			os = that.originalSize,
12157			op = that.originalPosition,
12158			a = that.axis,
12159			grid = typeof o.grid === "number" ? [ o.grid, o.grid ] : o.grid,
12160			gridX = ( grid[ 0 ] || 1 ),
12161			gridY = ( grid[ 1 ] || 1 ),
12162			ox = Math.round( ( cs.width - os.width ) / gridX ) * gridX,
12163			oy = Math.round( ( cs.height - os.height ) / gridY ) * gridY,
12164			newWidth = os.width + ox,
12165			newHeight = os.height + oy,
12166			isMaxWidth = o.maxWidth && ( o.maxWidth < newWidth ),
12167			isMaxHeight = o.maxHeight && ( o.maxHeight < newHeight ),
12168			isMinWidth = o.minWidth && ( o.minWidth > newWidth ),
12169			isMinHeight = o.minHeight && ( o.minHeight > newHeight );
12170
12171		o.grid = grid;
12172
12173		if ( isMinWidth ) {
12174			newWidth += gridX;
12175		}
12176		if ( isMinHeight ) {
12177			newHeight += gridY;
12178		}
12179		if ( isMaxWidth ) {
12180			newWidth -= gridX;
12181		}
12182		if ( isMaxHeight ) {
12183			newHeight -= gridY;
12184		}
12185
12186		if ( /^(se|s|e)$/.test( a ) ) {
12187			that.size.width = newWidth;
12188			that.size.height = newHeight;
12189		} else if ( /^(ne)$/.test( a ) ) {
12190			that.size.width = newWidth;
12191			that.size.height = newHeight;
12192			that.position.top = op.top - oy;
12193		} else if ( /^(sw)$/.test( a ) ) {
12194			that.size.width = newWidth;
12195			that.size.height = newHeight;
12196			that.position.left = op.left - ox;
12197		} else {
12198			if ( newHeight - gridY <= 0 || newWidth - gridX <= 0 ) {
12199				outerDimensions = that._getPaddingPlusBorderDimensions( this );
12200			}
12201
12202			if ( newHeight - gridY > 0 ) {
12203				that.size.height = newHeight;
12204				that.position.top = op.top - oy;
12205			} else {
12206				newHeight = gridY - outerDimensions.height;
12207				that.size.height = newHeight;
12208				that.position.top = op.top + os.height - newHeight;
12209			}
12210			if ( newWidth - gridX > 0 ) {
12211				that.size.width = newWidth;
12212				that.position.left = op.left - ox;
12213			} else {
12214				newWidth = gridX - outerDimensions.width;
12215				that.size.width = newWidth;
12216				that.position.left = op.left + os.width - newWidth;
12217			}
12218		}
12219	}
12220
12221} );
12222
12223var widgetsResizable = $.ui.resizable;
12224
12225
12226/*!
12227 * jQuery UI Dialog 1.13.3
12228 * https://jqueryui.com
12229 *
12230 * Copyright OpenJS Foundation and other contributors
12231 * Released under the MIT license.
12232 * https://jquery.org/license
12233 */
12234
12235//>>label: Dialog
12236//>>group: Widgets
12237//>>description: Displays customizable dialog windows.
12238//>>docs: https://api.jqueryui.com/dialog/
12239//>>demos: https://jqueryui.com/dialog/
12240//>>css.structure: ../../themes/base/core.css
12241//>>css.structure: ../../themes/base/dialog.css
12242//>>css.theme: ../../themes/base/theme.css
12243
12244
12245$.widget( "ui.dialog", {
12246	version: "1.13.3",
12247	options: {
12248		appendTo: "body",
12249		autoOpen: true,
12250		buttons: [],
12251		classes: {
12252			"ui-dialog": "ui-corner-all",
12253			"ui-dialog-titlebar": "ui-corner-all"
12254		},
12255		closeOnEscape: true,
12256		closeText: "Close",
12257		draggable: true,
12258		hide: null,
12259		height: "auto",
12260		maxHeight: null,
12261		maxWidth: null,
12262		minHeight: 150,
12263		minWidth: 150,
12264		modal: false,
12265		position: {
12266			my: "center",
12267			at: "center",
12268			of: window,
12269			collision: "fit",
12270
12271			// Ensure the titlebar is always visible
12272			using: function( pos ) {
12273				var topOffset = $( this ).css( pos ).offset().top;
12274				if ( topOffset < 0 ) {
12275					$( this ).css( "top", pos.top - topOffset );
12276				}
12277			}
12278		},
12279		resizable: true,
12280		show: null,
12281		title: null,
12282		width: 300,
12283
12284		// Callbacks
12285		beforeClose: null,
12286		close: null,
12287		drag: null,
12288		dragStart: null,
12289		dragStop: null,
12290		focus: null,
12291		open: null,
12292		resize: null,
12293		resizeStart: null,
12294		resizeStop: null
12295	},
12296
12297	sizeRelatedOptions: {
12298		buttons: true,
12299		height: true,
12300		maxHeight: true,
12301		maxWidth: true,
12302		minHeight: true,
12303		minWidth: true,
12304		width: true
12305	},
12306
12307	resizableRelatedOptions: {
12308		maxHeight: true,
12309		maxWidth: true,
12310		minHeight: true,
12311		minWidth: true
12312	},
12313
12314	_create: function() {
12315		this.originalCss = {
12316			display: this.element[ 0 ].style.display,
12317			width: this.element[ 0 ].style.width,
12318			minHeight: this.element[ 0 ].style.minHeight,
12319			maxHeight: this.element[ 0 ].style.maxHeight,
12320			height: this.element[ 0 ].style.height
12321		};
12322		this.originalPosition = {
12323			parent: this.element.parent(),
12324			index: this.element.parent().children().index( this.element )
12325		};
12326		this.originalTitle = this.element.attr( "title" );
12327		if ( this.options.title == null && this.originalTitle != null ) {
12328			this.options.title = this.originalTitle;
12329		}
12330
12331		// Dialogs can't be disabled
12332		if ( this.options.disabled ) {
12333			this.options.disabled = false;
12334		}
12335
12336		this._createWrapper();
12337
12338		this.element
12339			.show()
12340			.removeAttr( "title" )
12341			.appendTo( this.uiDialog );
12342
12343		this._addClass( "ui-dialog-content", "ui-widget-content" );
12344
12345		this._createTitlebar();
12346		this._createButtonPane();
12347
12348		if ( this.options.draggable && $.fn.draggable ) {
12349			this._makeDraggable();
12350		}
12351		if ( this.options.resizable && $.fn.resizable ) {
12352			this._makeResizable();
12353		}
12354
12355		this._isOpen = false;
12356
12357		this._trackFocus();
12358	},
12359
12360	_init: function() {
12361		if ( this.options.autoOpen ) {
12362			this.open();
12363		}
12364	},
12365
12366	_appendTo: function() {
12367		var element = this.options.appendTo;
12368		if ( element && ( element.jquery || element.nodeType ) ) {
12369			return $( element );
12370		}
12371		return this.document.find( element || "body" ).eq( 0 );
12372	},
12373
12374	_destroy: function() {
12375		var next,
12376			originalPosition = this.originalPosition;
12377
12378		this._untrackInstance();
12379		this._destroyOverlay();
12380
12381		this.element
12382			.removeUniqueId()
12383			.css( this.originalCss )
12384
12385			// Without detaching first, the following becomes really slow
12386			.detach();
12387
12388		this.uiDialog.remove();
12389
12390		if ( this.originalTitle ) {
12391			this.element.attr( "title", this.originalTitle );
12392		}
12393
12394		next = originalPosition.parent.children().eq( originalPosition.index );
12395
12396		// Don't try to place the dialog next to itself (#8613)
12397		if ( next.length && next[ 0 ] !== this.element[ 0 ] ) {
12398			next.before( this.element );
12399		} else {
12400			originalPosition.parent.append( this.element );
12401		}
12402	},
12403
12404	widget: function() {
12405		return this.uiDialog;
12406	},
12407
12408	disable: $.noop,
12409	enable: $.noop,
12410
12411	close: function( event ) {
12412		var that = this;
12413
12414		if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) {
12415			return;
12416		}
12417
12418		this._isOpen = false;
12419		this._focusedElement = null;
12420		this._destroyOverlay();
12421		this._untrackInstance();
12422
12423		if ( !this.opener.filter( ":focusable" ).trigger( "focus" ).length ) {
12424
12425			// Hiding a focused element doesn't trigger blur in WebKit
12426			// so in case we have nothing to focus on, explicitly blur the active element
12427			// https://bugs.webkit.org/show_bug.cgi?id=47182
12428			$.ui.safeBlur( $.ui.safeActiveElement( this.document[ 0 ] ) );
12429		}
12430
12431		this._hide( this.uiDialog, this.options.hide, function() {
12432			that._trigger( "close", event );
12433		} );
12434	},
12435
12436	isOpen: function() {
12437		return this._isOpen;
12438	},
12439
12440	moveToTop: function() {
12441		this._moveToTop();
12442	},
12443
12444	_moveToTop: function( event, silent ) {
12445		var moved = false,
12446			zIndices = this.uiDialog.siblings( ".ui-front:visible" ).map( function() {
12447				return +$( this ).css( "z-index" );
12448			} ).get(),
12449			zIndexMax = Math.max.apply( null, zIndices );
12450
12451		if ( zIndexMax >= +this.uiDialog.css( "z-index" ) ) {
12452			this.uiDialog.css( "z-index", zIndexMax + 1 );
12453			moved = true;
12454		}
12455
12456		if ( moved && !silent ) {
12457			this._trigger( "focus", event );
12458		}
12459		return moved;
12460	},
12461
12462	open: function() {
12463		var that = this;
12464		if ( this._isOpen ) {
12465			if ( this._moveToTop() ) {
12466				this._focusTabbable();
12467			}
12468			return;
12469		}
12470
12471		this._isOpen = true;
12472		this.opener = $( $.ui.safeActiveElement( this.document[ 0 ] ) );
12473
12474		this._size();
12475		this._position();
12476		this._createOverlay();
12477		this._moveToTop( null, true );
12478
12479		// Ensure the overlay is moved to the top with the dialog, but only when
12480		// opening. The overlay shouldn't move after the dialog is open so that
12481		// modeless dialogs opened after the modal dialog stack properly.
12482		if ( this.overlay ) {
12483			this.overlay.css( "z-index", this.uiDialog.css( "z-index" ) - 1 );
12484		}
12485
12486		this._show( this.uiDialog, this.options.show, function() {
12487			that._focusTabbable();
12488			that._trigger( "focus" );
12489		} );
12490
12491		// Track the dialog immediately upon opening in case a focus event
12492		// somehow occurs outside of the dialog before an element inside the
12493		// dialog is focused (#10152)
12494		this._makeFocusTarget();
12495
12496		this._trigger( "open" );
12497	},
12498
12499	_focusTabbable: function() {
12500
12501		// Set focus to the first match:
12502		// 1. An element that was focused previously
12503		// 2. First element inside the dialog matching [autofocus]
12504		// 3. Tabbable element inside the content element
12505		// 4. Tabbable element inside the buttonpane
12506		// 5. The close button
12507		// 6. The dialog itself
12508		var hasFocus = this._focusedElement;
12509		if ( !hasFocus ) {
12510			hasFocus = this.element.find( "[autofocus]" );
12511		}
12512		if ( !hasFocus.length ) {
12513			hasFocus = this.element.find( ":tabbable" );
12514		}
12515		if ( !hasFocus.length ) {
12516			hasFocus = this.uiDialogButtonPane.find( ":tabbable" );
12517		}
12518		if ( !hasFocus.length ) {
12519			hasFocus = this.uiDialogTitlebarClose.filter( ":tabbable" );
12520		}
12521		if ( !hasFocus.length ) {
12522			hasFocus = this.uiDialog;
12523		}
12524		hasFocus.eq( 0 ).trigger( "focus" );
12525	},
12526
12527	_restoreTabbableFocus: function() {
12528		var activeElement = $.ui.safeActiveElement( this.document[ 0 ] ),
12529			isActive = this.uiDialog[ 0 ] === activeElement ||
12530				$.contains( this.uiDialog[ 0 ], activeElement );
12531		if ( !isActive ) {
12532			this._focusTabbable();
12533		}
12534	},
12535
12536	_keepFocus: function( event ) {
12537		event.preventDefault();
12538		this._restoreTabbableFocus();
12539
12540		// support: IE
12541		// IE <= 8 doesn't prevent moving focus even with event.preventDefault()
12542		// so we check again later
12543		this._delay( this._restoreTabbableFocus );
12544	},
12545
12546	_createWrapper: function() {
12547		this.uiDialog = $( "<div>" )
12548			.hide()
12549			.attr( {
12550
12551				// Setting tabIndex makes the div focusable
12552				tabIndex: -1,
12553				role: "dialog"
12554			} )
12555			.appendTo( this._appendTo() );
12556
12557		this._addClass( this.uiDialog, "ui-dialog", "ui-widget ui-widget-content ui-front" );
12558		this._on( this.uiDialog, {
12559			keydown: function( event ) {
12560				if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
12561						event.keyCode === $.ui.keyCode.ESCAPE ) {
12562					event.preventDefault();
12563					this.close( event );
12564					return;
12565				}
12566
12567				// Prevent tabbing out of dialogs
12568				if ( event.keyCode !== $.ui.keyCode.TAB || event.isDefaultPrevented() ) {
12569					return;
12570				}
12571				var tabbables = this.uiDialog.find( ":tabbable" ),
12572					first = tabbables.first(),
12573					last = tabbables.last();
12574
12575				if ( ( event.target === last[ 0 ] || event.target === this.uiDialog[ 0 ] ) &&
12576						!event.shiftKey ) {
12577					this._delay( function() {
12578						first.trigger( "focus" );
12579					} );
12580					event.preventDefault();
12581				} else if ( ( event.target === first[ 0 ] ||
12582						event.target === this.uiDialog[ 0 ] ) && event.shiftKey ) {
12583					this._delay( function() {
12584						last.trigger( "focus" );
12585					} );
12586					event.preventDefault();
12587				}
12588			},
12589			mousedown: function( event ) {
12590				if ( this._moveToTop( event ) ) {
12591					this._focusTabbable();
12592				}
12593			}
12594		} );
12595
12596		// We assume that any existing aria-describedby attribute means
12597		// that the dialog content is marked up properly
12598		// otherwise we brute force the content as the description
12599		if ( !this.element.find( "[aria-describedby]" ).length ) {
12600			this.uiDialog.attr( {
12601				"aria-describedby": this.element.uniqueId().attr( "id" )
12602			} );
12603		}
12604	},
12605
12606	_createTitlebar: function() {
12607		var uiDialogTitle;
12608
12609		this.uiDialogTitlebar = $( "<div>" );
12610		this._addClass( this.uiDialogTitlebar,
12611			"ui-dialog-titlebar", "ui-widget-header ui-helper-clearfix" );
12612		this._on( this.uiDialogTitlebar, {
12613			mousedown: function( event ) {
12614
12615				// Don't prevent click on close button (#8838)
12616				// Focusing a dialog that is partially scrolled out of view
12617				// causes the browser to scroll it into view, preventing the click event
12618				if ( !$( event.target ).closest( ".ui-dialog-titlebar-close" ) ) {
12619
12620					// Dialog isn't getting focus when dragging (#8063)
12621					this.uiDialog.trigger( "focus" );
12622				}
12623			}
12624		} );
12625
12626		// Support: IE
12627		// Use type="button" to prevent enter keypresses in textboxes from closing the
12628		// dialog in IE (#9312)
12629		this.uiDialogTitlebarClose = $( "<button type='button'></button>" )
12630			.button( {
12631				label: $( "<a>" ).text( this.options.closeText ).html(),
12632				icon: "ui-icon-closethick",
12633				showLabel: false
12634			} )
12635			.appendTo( this.uiDialogTitlebar );
12636
12637		this._addClass( this.uiDialogTitlebarClose, "ui-dialog-titlebar-close" );
12638		this._on( this.uiDialogTitlebarClose, {
12639			click: function( event ) {
12640				event.preventDefault();
12641				this.close( event );
12642			}
12643		} );
12644
12645		uiDialogTitle = $( "<span>" ).uniqueId().prependTo( this.uiDialogTitlebar );
12646		this._addClass( uiDialogTitle, "ui-dialog-title" );
12647		this._title( uiDialogTitle );
12648
12649		this.uiDialogTitlebar.prependTo( this.uiDialog );
12650
12651		this.uiDialog.attr( {
12652			"aria-labelledby": uiDialogTitle.attr( "id" )
12653		} );
12654	},
12655
12656	_title: function( title ) {
12657		if ( this.options.title ) {
12658			title.text( this.options.title );
12659		} else {
12660			title.html( "&#160;" );
12661		}
12662	},
12663
12664	_createButtonPane: function() {
12665		this.uiDialogButtonPane = $( "<div>" );
12666		this._addClass( this.uiDialogButtonPane, "ui-dialog-buttonpane",
12667			"ui-widget-content ui-helper-clearfix" );
12668
12669		this.uiButtonSet = $( "<div>" )
12670			.appendTo( this.uiDialogButtonPane );
12671		this._addClass( this.uiButtonSet, "ui-dialog-buttonset" );
12672
12673		this._createButtons();
12674	},
12675
12676	_createButtons: function() {
12677		var that = this,
12678			buttons = this.options.buttons;
12679
12680		// If we already have a button pane, remove it
12681		this.uiDialogButtonPane.remove();
12682		this.uiButtonSet.empty();
12683
12684		if ( $.isEmptyObject( buttons ) || ( Array.isArray( buttons ) && !buttons.length ) ) {
12685			this._removeClass( this.uiDialog, "ui-dialog-buttons" );
12686			return;
12687		}
12688
12689		$.each( buttons, function( name, props ) {
12690			var click, buttonOptions;
12691			props = typeof props === "function" ?
12692				{ click: props, text: name } :
12693				props;
12694
12695			// Default to a non-submitting button
12696			props = $.extend( { type: "button" }, props );
12697
12698			// Change the context for the click callback to be the main element
12699			click = props.click;
12700			buttonOptions = {
12701				icon: props.icon,
12702				iconPosition: props.iconPosition,
12703				showLabel: props.showLabel,
12704
12705				// Deprecated options
12706				icons: props.icons,
12707				text: props.text
12708			};
12709
12710			delete props.click;
12711			delete props.icon;
12712			delete props.iconPosition;
12713			delete props.showLabel;
12714
12715			// Deprecated options
12716			delete props.icons;
12717			if ( typeof props.text === "boolean" ) {
12718				delete props.text;
12719			}
12720
12721			$( "<button></button>", props )
12722				.button( buttonOptions )
12723				.appendTo( that.uiButtonSet )
12724				.on( "click", function() {
12725					click.apply( that.element[ 0 ], arguments );
12726				} );
12727		} );
12728		this._addClass( this.uiDialog, "ui-dialog-buttons" );
12729		this.uiDialogButtonPane.appendTo( this.uiDialog );
12730	},
12731
12732	_makeDraggable: function() {
12733		var that = this,
12734			options = this.options;
12735
12736		function filteredUi( ui ) {
12737			return {
12738				position: ui.position,
12739				offset: ui.offset
12740			};
12741		}
12742
12743		this.uiDialog.draggable( {
12744			cancel: ".ui-dialog-content, .ui-dialog-titlebar-close",
12745			handle: ".ui-dialog-titlebar",
12746			containment: "document",
12747			start: function( event, ui ) {
12748				that._addClass( $( this ), "ui-dialog-dragging" );
12749				that._blockFrames();
12750				that._trigger( "dragStart", event, filteredUi( ui ) );
12751			},
12752			drag: function( event, ui ) {
12753				that._trigger( "drag", event, filteredUi( ui ) );
12754			},
12755			stop: function( event, ui ) {
12756				var left = ui.offset.left - that.document.scrollLeft(),
12757					top = ui.offset.top - that.document.scrollTop();
12758
12759				options.position = {
12760					my: "left top",
12761					at: "left" + ( left >= 0 ? "+" : "" ) + left + " " +
12762						"top" + ( top >= 0 ? "+" : "" ) + top,
12763					of: that.window
12764				};
12765				that._removeClass( $( this ), "ui-dialog-dragging" );
12766				that._unblockFrames();
12767				that._trigger( "dragStop", event, filteredUi( ui ) );
12768			}
12769		} );
12770	},
12771
12772	_makeResizable: function() {
12773		var that = this,
12774			options = this.options,
12775			handles = options.resizable,
12776
12777			// .ui-resizable has position: relative defined in the stylesheet
12778			// but dialogs have to use absolute or fixed positioning
12779			position = this.uiDialog.css( "position" ),
12780			resizeHandles = typeof handles === "string" ?
12781				handles :
12782				"n,e,s,w,se,sw,ne,nw";
12783
12784		function filteredUi( ui ) {
12785			return {
12786				originalPosition: ui.originalPosition,
12787				originalSize: ui.originalSize,
12788				position: ui.position,
12789				size: ui.size
12790			};
12791		}
12792
12793		this.uiDialog.resizable( {
12794			cancel: ".ui-dialog-content",
12795			containment: "document",
12796			alsoResize: this.element,
12797			maxWidth: options.maxWidth,
12798			maxHeight: options.maxHeight,
12799			minWidth: options.minWidth,
12800			minHeight: this._minHeight(),
12801			handles: resizeHandles,
12802			start: function( event, ui ) {
12803				that._addClass( $( this ), "ui-dialog-resizing" );
12804				that._blockFrames();
12805				that._trigger( "resizeStart", event, filteredUi( ui ) );
12806			},
12807			resize: function( event, ui ) {
12808				that._trigger( "resize", event, filteredUi( ui ) );
12809			},
12810			stop: function( event, ui ) {
12811				var offset = that.uiDialog.offset(),
12812					left = offset.left - that.document.scrollLeft(),
12813					top = offset.top - that.document.scrollTop();
12814
12815				options.height = that.uiDialog.height();
12816				options.width = that.uiDialog.width();
12817				options.position = {
12818					my: "left top",
12819					at: "left" + ( left >= 0 ? "+" : "" ) + left + " " +
12820						"top" + ( top >= 0 ? "+" : "" ) + top,
12821					of: that.window
12822				};
12823				that._removeClass( $( this ), "ui-dialog-resizing" );
12824				that._unblockFrames();
12825				that._trigger( "resizeStop", event, filteredUi( ui ) );
12826			}
12827		} )
12828			.css( "position", position );
12829	},
12830
12831	_trackFocus: function() {
12832		this._on( this.widget(), {
12833			focusin: function( event ) {
12834				this._makeFocusTarget();
12835				this._focusedElement = $( event.target );
12836			}
12837		} );
12838	},
12839
12840	_makeFocusTarget: function() {
12841		this._untrackInstance();
12842		this._trackingInstances().unshift( this );
12843	},
12844
12845	_untrackInstance: function() {
12846		var instances = this._trackingInstances(),
12847			exists = $.inArray( this, instances );
12848		if ( exists !== -1 ) {
12849			instances.splice( exists, 1 );
12850		}
12851	},
12852
12853	_trackingInstances: function() {
12854		var instances = this.document.data( "ui-dialog-instances" );
12855		if ( !instances ) {
12856			instances = [];
12857			this.document.data( "ui-dialog-instances", instances );
12858		}
12859		return instances;
12860	},
12861
12862	_minHeight: function() {
12863		var options = this.options;
12864
12865		return options.height === "auto" ?
12866			options.minHeight :
12867			Math.min( options.minHeight, options.height );
12868	},
12869
12870	_position: function() {
12871
12872		// Need to show the dialog to get the actual offset in the position plugin
12873		var isVisible = this.uiDialog.is( ":visible" );
12874		if ( !isVisible ) {
12875			this.uiDialog.show();
12876		}
12877		this.uiDialog.position( this.options.position );
12878		if ( !isVisible ) {
12879			this.uiDialog.hide();
12880		}
12881	},
12882
12883	_setOptions: function( options ) {
12884		var that = this,
12885			resize = false,
12886			resizableOptions = {};
12887
12888		$.each( options, function( key, value ) {
12889			that._setOption( key, value );
12890
12891			if ( key in that.sizeRelatedOptions ) {
12892				resize = true;
12893			}
12894			if ( key in that.resizableRelatedOptions ) {
12895				resizableOptions[ key ] = value;
12896			}
12897		} );
12898
12899		if ( resize ) {
12900			this._size();
12901			this._position();
12902		}
12903		if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
12904			this.uiDialog.resizable( "option", resizableOptions );
12905		}
12906	},
12907
12908	_setOption: function( key, value ) {
12909		var isDraggable, isResizable,
12910			uiDialog = this.uiDialog;
12911
12912		if ( key === "disabled" ) {
12913			return;
12914		}
12915
12916		this._super( key, value );
12917
12918		if ( key === "appendTo" ) {
12919			this.uiDialog.appendTo( this._appendTo() );
12920		}
12921
12922		if ( key === "buttons" ) {
12923			this._createButtons();
12924		}
12925
12926		if ( key === "closeText" ) {
12927			this.uiDialogTitlebarClose.button( {
12928
12929				// Ensure that we always pass a string
12930				label: $( "<a>" ).text( "" + this.options.closeText ).html()
12931			} );
12932		}
12933
12934		if ( key === "draggable" ) {
12935			isDraggable = uiDialog.is( ":data(ui-draggable)" );
12936			if ( isDraggable && !value ) {
12937				uiDialog.draggable( "destroy" );
12938			}
12939
12940			if ( !isDraggable && value ) {
12941				this._makeDraggable();
12942			}
12943		}
12944
12945		if ( key === "position" ) {
12946			this._position();
12947		}
12948
12949		if ( key === "resizable" ) {
12950
12951			// currently resizable, becoming non-resizable
12952			isResizable = uiDialog.is( ":data(ui-resizable)" );
12953			if ( isResizable && !value ) {
12954				uiDialog.resizable( "destroy" );
12955			}
12956
12957			// Currently resizable, changing handles
12958			if ( isResizable && typeof value === "string" ) {
12959				uiDialog.resizable( "option", "handles", value );
12960			}
12961
12962			// Currently non-resizable, becoming resizable
12963			if ( !isResizable && value !== false ) {
12964				this._makeResizable();
12965			}
12966		}
12967
12968		if ( key === "title" ) {
12969			this._title( this.uiDialogTitlebar.find( ".ui-dialog-title" ) );
12970		}
12971	},
12972
12973	_size: function() {
12974
12975		// If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
12976		// divs will both have width and height set, so we need to reset them
12977		var nonContentHeight, minContentHeight, maxContentHeight,
12978			options = this.options;
12979
12980		// Reset content sizing
12981		this.element.show().css( {
12982			width: "auto",
12983			minHeight: 0,
12984			maxHeight: "none",
12985			height: 0
12986		} );
12987
12988		if ( options.minWidth > options.width ) {
12989			options.width = options.minWidth;
12990		}
12991
12992		// Reset wrapper sizing
12993		// determine the height of all the non-content elements
12994		nonContentHeight = this.uiDialog.css( {
12995			height: "auto",
12996			width: options.width
12997		} )
12998			.outerHeight();
12999		minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
13000		maxContentHeight = typeof options.maxHeight === "number" ?
13001			Math.max( 0, options.maxHeight - nonContentHeight ) :
13002			"none";
13003
13004		if ( options.height === "auto" ) {
13005			this.element.css( {
13006				minHeight: minContentHeight,
13007				maxHeight: maxContentHeight,
13008				height: "auto"
13009			} );
13010		} else {
13011			this.element.height( Math.max( 0, options.height - nonContentHeight ) );
13012		}
13013
13014		if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
13015			this.uiDialog.resizable( "option", "minHeight", this._minHeight() );
13016		}
13017	},
13018
13019	_blockFrames: function() {
13020		this.iframeBlocks = this.document.find( "iframe" ).map( function() {
13021			var iframe = $( this );
13022
13023			return $( "<div>" )
13024				.css( {
13025					position: "absolute",
13026					width: iframe.outerWidth(),
13027					height: iframe.outerHeight()
13028				} )
13029				.appendTo( iframe.parent() )
13030				.offset( iframe.offset() )[ 0 ];
13031		} );
13032	},
13033
13034	_unblockFrames: function() {
13035		if ( this.iframeBlocks ) {
13036			this.iframeBlocks.remove();
13037			delete this.iframeBlocks;
13038		}
13039	},
13040
13041	_allowInteraction: function( event ) {
13042		if ( $( event.target ).closest( ".ui-dialog" ).length ) {
13043			return true;
13044		}
13045
13046		// TODO: Remove hack when datepicker implements
13047		// the .ui-front logic (#8989)
13048		return !!$( event.target ).closest( ".ui-datepicker" ).length;
13049	},
13050
13051	_createOverlay: function() {
13052		if ( !this.options.modal ) {
13053			return;
13054		}
13055
13056		var jqMinor = $.fn.jquery.substring( 0, 4 );
13057
13058		// We use a delay in case the overlay is created from an
13059		// event that we're going to be cancelling (#2804)
13060		var isOpening = true;
13061		this._delay( function() {
13062			isOpening = false;
13063		} );
13064
13065		if ( !this.document.data( "ui-dialog-overlays" ) ) {
13066
13067			// Prevent use of anchors and inputs
13068			// This doesn't use `_on()` because it is a shared event handler
13069			// across all open modal dialogs.
13070			this.document.on( "focusin.ui-dialog", function( event ) {
13071				if ( isOpening ) {
13072					return;
13073				}
13074
13075				var instance = this._trackingInstances()[ 0 ];
13076				if ( !instance._allowInteraction( event ) ) {
13077					event.preventDefault();
13078					instance._focusTabbable();
13079
13080					// Support: jQuery >=3.4 <3.7 only
13081					// In jQuery 3.4-3.6, there are multiple issues with focus/blur
13082					// trigger chains or when triggering is done on a hidden element
13083					// at least once.
13084					// Trigger focus in a delay in addition if needed to avoid the issues.
13085					// See https://github.com/jquery/jquery/issues/4382
13086					// See https://github.com/jquery/jquery/issues/4856
13087					// See https://github.com/jquery/jquery/issues/4950
13088					if ( jqMinor === "3.4." || jqMinor === "3.5." || jqMinor === "3.6." ) {
13089						instance._delay( instance._restoreTabbableFocus );
13090					}
13091				}
13092			}.bind( this ) );
13093		}
13094
13095		this.overlay = $( "<div>" )
13096			.appendTo( this._appendTo() );
13097
13098		this._addClass( this.overlay, null, "ui-widget-overlay ui-front" );
13099		this._on( this.overlay, {
13100			mousedown: "_keepFocus"
13101		} );
13102		this.document.data( "ui-dialog-overlays",
13103			( this.document.data( "ui-dialog-overlays" ) || 0 ) + 1 );
13104	},
13105
13106	_destroyOverlay: function() {
13107		if ( !this.options.modal ) {
13108			return;
13109		}
13110
13111		if ( this.overlay ) {
13112			var overlays = this.document.data( "ui-dialog-overlays" ) - 1;
13113
13114			if ( !overlays ) {
13115				this.document.off( "focusin.ui-dialog" );
13116				this.document.removeData( "ui-dialog-overlays" );
13117			} else {
13118				this.document.data( "ui-dialog-overlays", overlays );
13119			}
13120
13121			this.overlay.remove();
13122			this.overlay = null;
13123		}
13124	}
13125} );
13126
13127// DEPRECATED
13128// TODO: switch return back to widget declaration at top of file when this is removed
13129if ( $.uiBackCompat !== false ) {
13130
13131	// Backcompat for dialogClass option
13132	$.widget( "ui.dialog", $.ui.dialog, {
13133		options: {
13134			dialogClass: ""
13135		},
13136		_createWrapper: function() {
13137			this._super();
13138			this.uiDialog.addClass( this.options.dialogClass );
13139		},
13140		_setOption: function( key, value ) {
13141			if ( key === "dialogClass" ) {
13142				this.uiDialog
13143					.removeClass( this.options.dialogClass )
13144					.addClass( value );
13145			}
13146			this._superApply( arguments );
13147		}
13148	} );
13149}
13150
13151var widgetsDialog = $.ui.dialog;
13152
13153
13154/*!
13155 * jQuery UI Droppable 1.13.3
13156 * https://jqueryui.com
13157 *
13158 * Copyright OpenJS Foundation and other contributors
13159 * Released under the MIT license.
13160 * https://jquery.org/license
13161 */
13162
13163//>>label: Droppable
13164//>>group: Interactions
13165//>>description: Enables drop targets for draggable elements.
13166//>>docs: https://api.jqueryui.com/droppable/
13167//>>demos: https://jqueryui.com/droppable/
13168
13169
13170$.widget( "ui.droppable", {
13171	version: "1.13.3",
13172	widgetEventPrefix: "drop",
13173	options: {
13174		accept: "*",
13175		addClasses: true,
13176		greedy: false,
13177		scope: "default",
13178		tolerance: "intersect",
13179
13180		// Callbacks
13181		activate: null,
13182		deactivate: null,
13183		drop: null,
13184		out: null,
13185		over: null
13186	},
13187	_create: function() {
13188
13189		var proportions,
13190			o = this.options,
13191			accept = o.accept;
13192
13193		this.isover = false;
13194		this.isout = true;
13195
13196		this.accept = typeof accept === "function" ? accept : function( d ) {
13197			return d.is( accept );
13198		};
13199
13200		this.proportions = function( /* valueToWrite */ ) {
13201			if ( arguments.length ) {
13202
13203				// Store the droppable's proportions
13204				proportions = arguments[ 0 ];
13205			} else {
13206
13207				// Retrieve or derive the droppable's proportions
13208				return proportions ?
13209					proportions :
13210					proportions = {
13211						width: this.element[ 0 ].offsetWidth,
13212						height: this.element[ 0 ].offsetHeight
13213					};
13214			}
13215		};
13216
13217		this._addToManager( o.scope );
13218
13219		if ( o.addClasses ) {
13220			this._addClass( "ui-droppable" );
13221		}
13222
13223	},
13224
13225	_addToManager: function( scope ) {
13226
13227		// Add the reference and positions to the manager
13228		$.ui.ddmanager.droppables[ scope ] = $.ui.ddmanager.droppables[ scope ] || [];
13229		$.ui.ddmanager.droppables[ scope ].push( this );
13230	},
13231
13232	_splice: function( drop ) {
13233		var i = 0;
13234		for ( ; i < drop.length; i++ ) {
13235			if ( drop[ i ] === this ) {
13236				drop.splice( i, 1 );
13237			}
13238		}
13239	},
13240
13241	_destroy: function() {
13242		var drop = $.ui.ddmanager.droppables[ this.options.scope ];
13243
13244		this._splice( drop );
13245	},
13246
13247	_setOption: function( key, value ) {
13248
13249		if ( key === "accept" ) {
13250			this.accept = typeof value === "function" ? value : function( d ) {
13251				return d.is( value );
13252			};
13253		} else if ( key === "scope" ) {
13254			var drop = $.ui.ddmanager.droppables[ this.options.scope ];
13255
13256			this._splice( drop );
13257			this._addToManager( value );
13258		}
13259
13260		this._super( key, value );
13261	},
13262
13263	_activate: function( event ) {
13264		var draggable = $.ui.ddmanager.current;
13265
13266		this._addActiveClass();
13267		if ( draggable ) {
13268			this._trigger( "activate", event, this.ui( draggable ) );
13269		}
13270	},
13271
13272	_deactivate: function( event ) {
13273		var draggable = $.ui.ddmanager.current;
13274
13275		this._removeActiveClass();
13276		if ( draggable ) {
13277			this._trigger( "deactivate", event, this.ui( draggable ) );
13278		}
13279	},
13280
13281	_over: function( event ) {
13282
13283		var draggable = $.ui.ddmanager.current;
13284
13285		// Bail if draggable and droppable are same element
13286		if ( !draggable || ( draggable.currentItem ||
13287				draggable.element )[ 0 ] === this.element[ 0 ] ) {
13288			return;
13289		}
13290
13291		if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem ||
13292				draggable.element ) ) ) {
13293			this._addHoverClass();
13294			this._trigger( "over", event, this.ui( draggable ) );
13295		}
13296
13297	},
13298
13299	_out: function( event ) {
13300
13301		var draggable = $.ui.ddmanager.current;
13302
13303		// Bail if draggable and droppable are same element
13304		if ( !draggable || ( draggable.currentItem ||
13305				draggable.element )[ 0 ] === this.element[ 0 ] ) {
13306			return;
13307		}
13308
13309		if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem ||
13310				draggable.element ) ) ) {
13311			this._removeHoverClass();
13312			this._trigger( "out", event, this.ui( draggable ) );
13313		}
13314
13315	},
13316
13317	_drop: function( event, custom ) {
13318
13319		var draggable = custom || $.ui.ddmanager.current,
13320			childrenIntersection = false;
13321
13322		// Bail if draggable and droppable are same element
13323		if ( !draggable || ( draggable.currentItem ||
13324				draggable.element )[ 0 ] === this.element[ 0 ] ) {
13325			return false;
13326		}
13327
13328		this.element
13329			.find( ":data(ui-droppable)" )
13330			.not( ".ui-draggable-dragging" )
13331			.each( function() {
13332				var inst = $( this ).droppable( "instance" );
13333				if (
13334					inst.options.greedy &&
13335					!inst.options.disabled &&
13336					inst.options.scope === draggable.options.scope &&
13337					inst.accept.call(
13338						inst.element[ 0 ], ( draggable.currentItem || draggable.element )
13339					) &&
13340					$.ui.intersect(
13341						draggable,
13342						$.extend( inst, { offset: inst.element.offset() } ),
13343						inst.options.tolerance, event
13344					)
13345				) {
13346					childrenIntersection = true;
13347					return false;
13348				}
13349			} );
13350		if ( childrenIntersection ) {
13351			return false;
13352		}
13353
13354		if ( this.accept.call( this.element[ 0 ],
13355				( draggable.currentItem || draggable.element ) ) ) {
13356			this._removeActiveClass();
13357			this._removeHoverClass();
13358
13359			this._trigger( "drop", event, this.ui( draggable ) );
13360			return this.element;
13361		}
13362
13363		return false;
13364
13365	},
13366
13367	ui: function( c ) {
13368		return {
13369			draggable: ( c.currentItem || c.element ),
13370			helper: c.helper,
13371			position: c.position,
13372			offset: c.positionAbs
13373		};
13374	},
13375
13376	// Extension points just to make backcompat sane and avoid duplicating logic
13377	// TODO: Remove in 1.14 along with call to it below
13378	_addHoverClass: function() {
13379		this._addClass( "ui-droppable-hover" );
13380	},
13381
13382	_removeHoverClass: function() {
13383		this._removeClass( "ui-droppable-hover" );
13384	},
13385
13386	_addActiveClass: function() {
13387		this._addClass( "ui-droppable-active" );
13388	},
13389
13390	_removeActiveClass: function() {
13391		this._removeClass( "ui-droppable-active" );
13392	}
13393} );
13394
13395$.ui.intersect = ( function() {
13396	function isOverAxis( x, reference, size ) {
13397		return ( x >= reference ) && ( x < ( reference + size ) );
13398	}
13399
13400	return function( draggable, droppable, toleranceMode, event ) {
13401
13402		if ( !droppable.offset ) {
13403			return false;
13404		}
13405
13406		var x1 = ( draggable.positionAbs ||
13407				draggable.position.absolute ).left + draggable.margins.left,
13408			y1 = ( draggable.positionAbs ||
13409				draggable.position.absolute ).top + draggable.margins.top,
13410			x2 = x1 + draggable.helperProportions.width,
13411			y2 = y1 + draggable.helperProportions.height,
13412			l = droppable.offset.left,
13413			t = droppable.offset.top,
13414			r = l + droppable.proportions().width,
13415			b = t + droppable.proportions().height;
13416
13417		switch ( toleranceMode ) {
13418		case "fit":
13419			return ( l <= x1 && x2 <= r && t <= y1 && y2 <= b );
13420		case "intersect":
13421			return ( l < x1 + ( draggable.helperProportions.width / 2 ) && // Right Half
13422				x2 - ( draggable.helperProportions.width / 2 ) < r && // Left Half
13423				t < y1 + ( draggable.helperProportions.height / 2 ) && // Bottom Half
13424				y2 - ( draggable.helperProportions.height / 2 ) < b ); // Top Half
13425		case "pointer":
13426			return isOverAxis( event.pageY, t, droppable.proportions().height ) &&
13427				isOverAxis( event.pageX, l, droppable.proportions().width );
13428		case "touch":
13429			return (
13430				( y1 >= t && y1 <= b ) || // Top edge touching
13431				( y2 >= t && y2 <= b ) || // Bottom edge touching
13432				( y1 < t && y2 > b ) // Surrounded vertically
13433			) && (
13434				( x1 >= l && x1 <= r ) || // Left edge touching
13435				( x2 >= l && x2 <= r ) || // Right edge touching
13436				( x1 < l && x2 > r ) // Surrounded horizontally
13437			);
13438		default:
13439			return false;
13440		}
13441	};
13442} )();
13443
13444/*
13445	This manager tracks offsets of draggables and droppables
13446*/
13447$.ui.ddmanager = {
13448	current: null,
13449	droppables: { "default": [] },
13450	prepareOffsets: function( t, event ) {
13451
13452		var i, j,
13453			m = $.ui.ddmanager.droppables[ t.options.scope ] || [],
13454			type = event ? event.type : null, // workaround for #2317
13455			list = ( t.currentItem || t.element ).find( ":data(ui-droppable)" ).addBack();
13456
13457		droppablesLoop: for ( i = 0; i < m.length; i++ ) {
13458
13459			// No disabled and non-accepted
13460			if ( m[ i ].options.disabled || ( t && !m[ i ].accept.call( m[ i ].element[ 0 ],
13461					( t.currentItem || t.element ) ) ) ) {
13462				continue;
13463			}
13464
13465			// Filter out elements in the current dragged item
13466			for ( j = 0; j < list.length; j++ ) {
13467				if ( list[ j ] === m[ i ].element[ 0 ] ) {
13468					m[ i ].proportions().height = 0;
13469					continue droppablesLoop;
13470				}
13471			}
13472
13473			m[ i ].visible = m[ i ].element.css( "display" ) !== "none";
13474			if ( !m[ i ].visible ) {
13475				continue;
13476			}
13477
13478			// Activate the droppable if used directly from draggables
13479			if ( type === "mousedown" ) {
13480				m[ i ]._activate.call( m[ i ], event );
13481			}
13482
13483			m[ i ].offset = m[ i ].element.offset();
13484			m[ i ].proportions( {
13485				width: m[ i ].element[ 0 ].offsetWidth,
13486				height: m[ i ].element[ 0 ].offsetHeight
13487			} );
13488
13489		}
13490
13491	},
13492	drop: function( draggable, event ) {
13493
13494		var dropped = false;
13495
13496		// Create a copy of the droppables in case the list changes during the drop (#9116)
13497		$.each( ( $.ui.ddmanager.droppables[ draggable.options.scope ] || [] ).slice(), function() {
13498
13499			if ( !this.options ) {
13500				return;
13501			}
13502			if ( !this.options.disabled && this.visible &&
13503					$.ui.intersect( draggable, this, this.options.tolerance, event ) ) {
13504				dropped = this._drop.call( this, event ) || dropped;
13505			}
13506
13507			if ( !this.options.disabled && this.visible && this.accept.call( this.element[ 0 ],
13508					( draggable.currentItem || draggable.element ) ) ) {
13509				this.isout = true;
13510				this.isover = false;
13511				this._deactivate.call( this, event );
13512			}
13513
13514		} );
13515		return dropped;
13516
13517	},
13518	dragStart: function( draggable, event ) {
13519
13520		// Listen for scrolling so that if the dragging causes scrolling the position of the
13521		// droppables can be recalculated (see #5003)
13522		draggable.element.parentsUntil( "body" ).on( "scroll.droppable", function() {
13523			if ( !draggable.options.refreshPositions ) {
13524				$.ui.ddmanager.prepareOffsets( draggable, event );
13525			}
13526		} );
13527	},
13528	drag: function( draggable, event ) {
13529
13530		// If you have a highly dynamic page, you might try this option. It renders positions
13531		// every time you move the mouse.
13532		if ( draggable.options.refreshPositions ) {
13533			$.ui.ddmanager.prepareOffsets( draggable, event );
13534		}
13535
13536		// Run through all droppables and check their positions based on specific tolerance options
13537		$.each( $.ui.ddmanager.droppables[ draggable.options.scope ] || [], function() {
13538
13539			if ( this.options.disabled || this.greedyChild || !this.visible ) {
13540				return;
13541			}
13542
13543			var parentInstance, scope, parent,
13544				intersects = $.ui.intersect( draggable, this, this.options.tolerance, event ),
13545				c = !intersects && this.isover ?
13546					"isout" :
13547					( intersects && !this.isover ? "isover" : null );
13548			if ( !c ) {
13549				return;
13550			}
13551
13552			if ( this.options.greedy ) {
13553
13554				// find droppable parents with same scope
13555				scope = this.options.scope;
13556				parent = this.element.parents( ":data(ui-droppable)" ).filter( function() {
13557					return $( this ).droppable( "instance" ).options.scope === scope;
13558				} );
13559
13560				if ( parent.length ) {
13561					parentInstance = $( parent[ 0 ] ).droppable( "instance" );
13562					parentInstance.greedyChild = ( c === "isover" );
13563				}
13564			}
13565
13566			// We just moved into a greedy child
13567			if ( parentInstance && c === "isover" ) {
13568				parentInstance.isover = false;
13569				parentInstance.isout = true;
13570				parentInstance._out.call( parentInstance, event );
13571			}
13572
13573			this[ c ] = true;
13574			this[ c === "isout" ? "isover" : "isout" ] = false;
13575			this[ c === "isover" ? "_over" : "_out" ].call( this, event );
13576
13577			// We just moved out of a greedy child
13578			if ( parentInstance && c === "isout" ) {
13579				parentInstance.isout = false;
13580				parentInstance.isover = true;
13581				parentInstance._over.call( parentInstance, event );
13582			}
13583		} );
13584
13585	},
13586	dragStop: function( draggable, event ) {
13587		draggable.element.parentsUntil( "body" ).off( "scroll.droppable" );
13588
13589		// Call prepareOffsets one final time since IE does not fire return scroll events when
13590		// overflow was caused by drag (see #5003)
13591		if ( !draggable.options.refreshPositions ) {
13592			$.ui.ddmanager.prepareOffsets( draggable, event );
13593		}
13594	}
13595};
13596
13597// DEPRECATED
13598// TODO: switch return back to widget declaration at top of file when this is removed
13599if ( $.uiBackCompat !== false ) {
13600
13601	// Backcompat for activeClass and hoverClass options
13602	$.widget( "ui.droppable", $.ui.droppable, {
13603		options: {
13604			hoverClass: false,
13605			activeClass: false
13606		},
13607		_addActiveClass: function() {
13608			this._super();
13609			if ( this.options.activeClass ) {
13610				this.element.addClass( this.options.activeClass );
13611			}
13612		},
13613		_removeActiveClass: function() {
13614			this._super();
13615			if ( this.options.activeClass ) {
13616				this.element.removeClass( this.options.activeClass );
13617			}
13618		},
13619		_addHoverClass: function() {
13620			this._super();
13621			if ( this.options.hoverClass ) {
13622				this.element.addClass( this.options.hoverClass );
13623			}
13624		},
13625		_removeHoverClass: function() {
13626			this._super();
13627			if ( this.options.hoverClass ) {
13628				this.element.removeClass( this.options.hoverClass );
13629			}
13630		}
13631	} );
13632}
13633
13634var widgetsDroppable = $.ui.droppable;
13635
13636
13637/*!
13638 * jQuery UI Progressbar 1.13.3
13639 * https://jqueryui.com
13640 *
13641 * Copyright OpenJS Foundation and other contributors
13642 * Released under the MIT license.
13643 * https://jquery.org/license
13644 */
13645
13646//>>label: Progressbar
13647//>>group: Widgets
13648/* eslint-disable max-len */
13649//>>description: Displays a status indicator for loading state, standard percentage, and other progress indicators.
13650/* eslint-enable max-len */
13651//>>docs: https://api.jqueryui.com/progressbar/
13652//>>demos: https://jqueryui.com/progressbar/
13653//>>css.structure: ../../themes/base/core.css
13654//>>css.structure: ../../themes/base/progressbar.css
13655//>>css.theme: ../../themes/base/theme.css
13656
13657
13658var widgetsProgressbar = $.widget( "ui.progressbar", {
13659	version: "1.13.3",
13660	options: {
13661		classes: {
13662			"ui-progressbar": "ui-corner-all",
13663			"ui-progressbar-value": "ui-corner-left",
13664			"ui-progressbar-complete": "ui-corner-right"
13665		},
13666		max: 100,
13667		value: 0,
13668
13669		change: null,
13670		complete: null
13671	},
13672
13673	min: 0,
13674
13675	_create: function() {
13676
13677		// Constrain initial value
13678		this.oldValue = this.options.value = this._constrainedValue();
13679
13680		this.element.attr( {
13681
13682			// Only set static values; aria-valuenow and aria-valuemax are
13683			// set inside _refreshValue()
13684			role: "progressbar",
13685			"aria-valuemin": this.min
13686		} );
13687		this._addClass( "ui-progressbar", "ui-widget ui-widget-content" );
13688
13689		this.valueDiv = $( "<div>" ).appendTo( this.element );
13690		this._addClass( this.valueDiv, "ui-progressbar-value", "ui-widget-header" );
13691		this._refreshValue();
13692	},
13693
13694	_destroy: function() {
13695		this.element.removeAttr( "role aria-valuemin aria-valuemax aria-valuenow" );
13696
13697		this.valueDiv.remove();
13698	},
13699
13700	value: function( newValue ) {
13701		if ( newValue === undefined ) {
13702			return this.options.value;
13703		}
13704
13705		this.options.value = this._constrainedValue( newValue );
13706		this._refreshValue();
13707	},
13708
13709	_constrainedValue: function( newValue ) {
13710		if ( newValue === undefined ) {
13711			newValue = this.options.value;
13712		}
13713
13714		this.indeterminate = newValue === false;
13715
13716		// Sanitize value
13717		if ( typeof newValue !== "number" ) {
13718			newValue = 0;
13719		}
13720
13721		return this.indeterminate ? false :
13722			Math.min( this.options.max, Math.max( this.min, newValue ) );
13723	},
13724
13725	_setOptions: function( options ) {
13726
13727		// Ensure "value" option is set after other values (like max)
13728		var value = options.value;
13729		delete options.value;
13730
13731		this._super( options );
13732
13733		this.options.value = this._constrainedValue( value );
13734		this._refreshValue();
13735	},
13736
13737	_setOption: function( key, value ) {
13738		if ( key === "max" ) {
13739
13740			// Don't allow a max less than min
13741			value = Math.max( this.min, value );
13742		}
13743		this._super( key, value );
13744	},
13745
13746	_setOptionDisabled: function( value ) {
13747		this._super( value );
13748
13749		this.element.attr( "aria-disabled", value );
13750		this._toggleClass( null, "ui-state-disabled", !!value );
13751	},
13752
13753	_percentage: function() {
13754		return this.indeterminate ?
13755			100 :
13756			100 * ( this.options.value - this.min ) / ( this.options.max - this.min );
13757	},
13758
13759	_refreshValue: function() {
13760		var value = this.options.value,
13761			percentage = this._percentage();
13762
13763		this.valueDiv
13764			.toggle( this.indeterminate || value > this.min )
13765			.width( percentage.toFixed( 0 ) + "%" );
13766
13767		this
13768			._toggleClass( this.valueDiv, "ui-progressbar-complete", null,
13769				value === this.options.max )
13770			._toggleClass( "ui-progressbar-indeterminate", null, this.indeterminate );
13771
13772		if ( this.indeterminate ) {
13773			this.element.removeAttr( "aria-valuenow" );
13774			if ( !this.overlayDiv ) {
13775				this.overlayDiv = $( "<div>" ).appendTo( this.valueDiv );
13776				this._addClass( this.overlayDiv, "ui-progressbar-overlay" );
13777			}
13778		} else {
13779			this.element.attr( {
13780				"aria-valuemax": this.options.max,
13781				"aria-valuenow": value
13782			} );
13783			if ( this.overlayDiv ) {
13784				this.overlayDiv.remove();
13785				this.overlayDiv = null;
13786			}
13787		}
13788
13789		if ( this.oldValue !== value ) {
13790			this.oldValue = value;
13791			this._trigger( "change" );
13792		}
13793		if ( value === this.options.max ) {
13794			this._trigger( "complete" );
13795		}
13796	}
13797} );
13798
13799
13800/*!
13801 * jQuery UI Selectable 1.13.3
13802 * https://jqueryui.com
13803 *
13804 * Copyright OpenJS Foundation and other contributors
13805 * Released under the MIT license.
13806 * https://jquery.org/license
13807 */
13808
13809//>>label: Selectable
13810//>>group: Interactions
13811//>>description: Allows groups of elements to be selected with the mouse.
13812//>>docs: https://api.jqueryui.com/selectable/
13813//>>demos: https://jqueryui.com/selectable/
13814//>>css.structure: ../../themes/base/selectable.css
13815
13816
13817var widgetsSelectable = $.widget( "ui.selectable", $.ui.mouse, {
13818	version: "1.13.3",
13819	options: {
13820		appendTo: "body",
13821		autoRefresh: true,
13822		distance: 0,
13823		filter: "*",
13824		tolerance: "touch",
13825
13826		// Callbacks
13827		selected: null,
13828		selecting: null,
13829		start: null,
13830		stop: null,
13831		unselected: null,
13832		unselecting: null
13833	},
13834	_create: function() {
13835		var that = this;
13836
13837		this._addClass( "ui-selectable" );
13838
13839		this.dragged = false;
13840
13841		// Cache selectee children based on filter
13842		this.refresh = function() {
13843			that.elementPos = $( that.element[ 0 ] ).offset();
13844			that.selectees = $( that.options.filter, that.element[ 0 ] );
13845			that._addClass( that.selectees, "ui-selectee" );
13846			that.selectees.each( function() {
13847				var $this = $( this ),
13848					selecteeOffset = $this.offset(),
13849					pos = {
13850						left: selecteeOffset.left - that.elementPos.left,
13851						top: selecteeOffset.top - that.elementPos.top
13852					};
13853				$.data( this, "selectable-item", {
13854					element: this,
13855					$element: $this,
13856					left: pos.left,
13857					top: pos.top,
13858					right: pos.left + $this.outerWidth(),
13859					bottom: pos.top + $this.outerHeight(),
13860					startselected: false,
13861					selected: $this.hasClass( "ui-selected" ),
13862					selecting: $this.hasClass( "ui-selecting" ),
13863					unselecting: $this.hasClass( "ui-unselecting" )
13864				} );
13865			} );
13866		};
13867		this.refresh();
13868
13869		this._mouseInit();
13870
13871		this.helper = $( "<div>" );
13872		this._addClass( this.helper, "ui-selectable-helper" );
13873	},
13874
13875	_destroy: function() {
13876		this.selectees.removeData( "selectable-item" );
13877		this._mouseDestroy();
13878	},
13879
13880	_mouseStart: function( event ) {
13881		var that = this,
13882			options = this.options;
13883
13884		this.opos = [ event.pageX, event.pageY ];
13885		this.elementPos = $( this.element[ 0 ] ).offset();
13886
13887		if ( this.options.disabled ) {
13888			return;
13889		}
13890
13891		this.selectees = $( options.filter, this.element[ 0 ] );
13892
13893		this._trigger( "start", event );
13894
13895		$( options.appendTo ).append( this.helper );
13896
13897		// position helper (lasso)
13898		this.helper.css( {
13899			"left": event.pageX,
13900			"top": event.pageY,
13901			"width": 0,
13902			"height": 0
13903		} );
13904
13905		if ( options.autoRefresh ) {
13906			this.refresh();
13907		}
13908
13909		this.selectees.filter( ".ui-selected" ).each( function() {
13910			var selectee = $.data( this, "selectable-item" );
13911			selectee.startselected = true;
13912			if ( !event.metaKey && !event.ctrlKey ) {
13913				that._removeClass( selectee.$element, "ui-selected" );
13914				selectee.selected = false;
13915				that._addClass( selectee.$element, "ui-unselecting" );
13916				selectee.unselecting = true;
13917
13918				// selectable UNSELECTING callback
13919				that._trigger( "unselecting", event, {
13920					unselecting: selectee.element
13921				} );
13922			}
13923		} );
13924
13925		$( event.target ).parents().addBack().each( function() {
13926			var doSelect,
13927				selectee = $.data( this, "selectable-item" );
13928			if ( selectee ) {
13929				doSelect = ( !event.metaKey && !event.ctrlKey ) ||
13930					!selectee.$element.hasClass( "ui-selected" );
13931				that._removeClass( selectee.$element, doSelect ? "ui-unselecting" : "ui-selected" )
13932					._addClass( selectee.$element, doSelect ? "ui-selecting" : "ui-unselecting" );
13933				selectee.unselecting = !doSelect;
13934				selectee.selecting = doSelect;
13935				selectee.selected = doSelect;
13936
13937				// selectable (UN)SELECTING callback
13938				if ( doSelect ) {
13939					that._trigger( "selecting", event, {
13940						selecting: selectee.element
13941					} );
13942				} else {
13943					that._trigger( "unselecting", event, {
13944						unselecting: selectee.element
13945					} );
13946				}
13947				return false;
13948			}
13949		} );
13950
13951	},
13952
13953	_mouseDrag: function( event ) {
13954
13955		this.dragged = true;
13956
13957		if ( this.options.disabled ) {
13958			return;
13959		}
13960
13961		var tmp,
13962			that = this,
13963			options = this.options,
13964			x1 = this.opos[ 0 ],
13965			y1 = this.opos[ 1 ],
13966			x2 = event.pageX,
13967			y2 = event.pageY;
13968
13969		if ( x1 > x2 ) {
13970			tmp = x2; x2 = x1; x1 = tmp;
13971		}
13972		if ( y1 > y2 ) {
13973			tmp = y2; y2 = y1; y1 = tmp;
13974		}
13975		this.helper.css( { left: x1, top: y1, width: x2 - x1, height: y2 - y1 } );
13976
13977		this.selectees.each( function() {
13978			var selectee = $.data( this, "selectable-item" ),
13979				hit = false,
13980				offset = {};
13981
13982			//prevent helper from being selected if appendTo: selectable
13983			if ( !selectee || selectee.element === that.element[ 0 ] ) {
13984				return;
13985			}
13986
13987			offset.left   = selectee.left   + that.elementPos.left;
13988			offset.right  = selectee.right  + that.elementPos.left;
13989			offset.top    = selectee.top    + that.elementPos.top;
13990			offset.bottom = selectee.bottom + that.elementPos.top;
13991
13992			if ( options.tolerance === "touch" ) {
13993				hit = ( !( offset.left > x2 || offset.right < x1 || offset.top > y2 ||
13994                    offset.bottom < y1 ) );
13995			} else if ( options.tolerance === "fit" ) {
13996				hit = ( offset.left > x1 && offset.right < x2 && offset.top > y1 &&
13997                    offset.bottom < y2 );
13998			}
13999
14000			if ( hit ) {
14001
14002				// SELECT
14003				if ( selectee.selected ) {
14004					that._removeClass( selectee.$element, "ui-selected" );
14005					selectee.selected = false;
14006				}
14007				if ( selectee.unselecting ) {
14008					that._removeClass( selectee.$element, "ui-unselecting" );
14009					selectee.unselecting = false;
14010				}
14011				if ( !selectee.selecting ) {
14012					that._addClass( selectee.$element, "ui-selecting" );
14013					selectee.selecting = true;
14014
14015					// selectable SELECTING callback
14016					that._trigger( "selecting", event, {
14017						selecting: selectee.element
14018					} );
14019				}
14020			} else {
14021
14022				// UNSELECT
14023				if ( selectee.selecting ) {
14024					if ( ( event.metaKey || event.ctrlKey ) && selectee.startselected ) {
14025						that._removeClass( selectee.$element, "ui-selecting" );
14026						selectee.selecting = false;
14027						that._addClass( selectee.$element, "ui-selected" );
14028						selectee.selected = true;
14029					} else {
14030						that._removeClass( selectee.$element, "ui-selecting" );
14031						selectee.selecting = false;
14032						if ( selectee.startselected ) {
14033							that._addClass( selectee.$element, "ui-unselecting" );
14034							selectee.unselecting = true;
14035						}
14036
14037						// selectable UNSELECTING callback
14038						that._trigger( "unselecting", event, {
14039							unselecting: selectee.element
14040						} );
14041					}
14042				}
14043				if ( selectee.selected ) {
14044					if ( !event.metaKey && !event.ctrlKey && !selectee.startselected ) {
14045						that._removeClass( selectee.$element, "ui-selected" );
14046						selectee.selected = false;
14047
14048						that._addClass( selectee.$element, "ui-unselecting" );
14049						selectee.unselecting = true;
14050
14051						// selectable UNSELECTING callback
14052						that._trigger( "unselecting", event, {
14053							unselecting: selectee.element
14054						} );
14055					}
14056				}
14057			}
14058		} );
14059
14060		return false;
14061	},
14062
14063	_mouseStop: function( event ) {
14064		var that = this;
14065
14066		this.dragged = false;
14067
14068		$( ".ui-unselecting", this.element[ 0 ] ).each( function() {
14069			var selectee = $.data( this, "selectable-item" );
14070			that._removeClass( selectee.$element, "ui-unselecting" );
14071			selectee.unselecting = false;
14072			selectee.startselected = false;
14073			that._trigger( "unselected", event, {
14074				unselected: selectee.element
14075			} );
14076		} );
14077		$( ".ui-selecting", this.element[ 0 ] ).each( function() {
14078			var selectee = $.data( this, "selectable-item" );
14079			that._removeClass( selectee.$element, "ui-selecting" )
14080				._addClass( selectee.$element, "ui-selected" );
14081			selectee.selecting = false;
14082			selectee.selected = true;
14083			selectee.startselected = true;
14084			that._trigger( "selected", event, {
14085				selected: selectee.element
14086			} );
14087		} );
14088		this._trigger( "stop", event );
14089
14090		this.helper.remove();
14091
14092		return false;
14093	}
14094
14095} );
14096
14097
14098/*!
14099 * jQuery UI Selectmenu 1.13.3
14100 * https://jqueryui.com
14101 *
14102 * Copyright OpenJS Foundation and other contributors
14103 * Released under the MIT license.
14104 * https://jquery.org/license
14105 */
14106
14107//>>label: Selectmenu
14108//>>group: Widgets
14109/* eslint-disable max-len */
14110//>>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.
14111/* eslint-enable max-len */
14112//>>docs: https://api.jqueryui.com/selectmenu/
14113//>>demos: https://jqueryui.com/selectmenu/
14114//>>css.structure: ../../themes/base/core.css
14115//>>css.structure: ../../themes/base/selectmenu.css, ../../themes/base/button.css
14116//>>css.theme: ../../themes/base/theme.css
14117
14118
14119var widgetsSelectmenu = $.widget( "ui.selectmenu", [ $.ui.formResetMixin, {
14120	version: "1.13.3",
14121	defaultElement: "<select>",
14122	options: {
14123		appendTo: null,
14124		classes: {
14125			"ui-selectmenu-button-open": "ui-corner-top",
14126			"ui-selectmenu-button-closed": "ui-corner-all"
14127		},
14128		disabled: null,
14129		icons: {
14130			button: "ui-icon-triangle-1-s"
14131		},
14132		position: {
14133			my: "left top",
14134			at: "left bottom",
14135			collision: "none"
14136		},
14137		width: false,
14138
14139		// Callbacks
14140		change: null,
14141		close: null,
14142		focus: null,
14143		open: null,
14144		select: null
14145	},
14146
14147	_create: function() {
14148		var selectmenuId = this.element.uniqueId().attr( "id" );
14149		this.ids = {
14150			element: selectmenuId,
14151			button: selectmenuId + "-button",
14152			menu: selectmenuId + "-menu"
14153		};
14154
14155		this._drawButton();
14156		this._drawMenu();
14157		this._bindFormResetHandler();
14158
14159		this._rendered = false;
14160		this.menuItems = $();
14161	},
14162
14163	_drawButton: function() {
14164		var icon,
14165			that = this,
14166			item = this._parseOption(
14167				this.element.find( "option:selected" ),
14168				this.element[ 0 ].selectedIndex
14169			);
14170
14171		// Associate existing label with the new button
14172		this.labels = this.element.labels().attr( "for", this.ids.button );
14173		this._on( this.labels, {
14174			click: function( event ) {
14175				this.button.trigger( "focus" );
14176				event.preventDefault();
14177			}
14178		} );
14179
14180		// Hide original select element
14181		this.element.hide();
14182
14183		// Create button
14184		this.button = $( "<span>", {
14185			tabindex: this.options.disabled ? -1 : 0,
14186			id: this.ids.button,
14187			role: "combobox",
14188			"aria-expanded": "false",
14189			"aria-autocomplete": "list",
14190			"aria-owns": this.ids.menu,
14191			"aria-haspopup": "true",
14192			title: this.element.attr( "title" )
14193		} )
14194			.insertAfter( this.element );
14195
14196		this._addClass( this.button, "ui-selectmenu-button ui-selectmenu-button-closed",
14197			"ui-button ui-widget" );
14198
14199		icon = $( "<span>" ).appendTo( this.button );
14200		this._addClass( icon, "ui-selectmenu-icon", "ui-icon " + this.options.icons.button );
14201		this.buttonItem = this._renderButtonItem( item )
14202			.appendTo( this.button );
14203
14204		if ( this.options.width !== false ) {
14205			this._resizeButton();
14206		}
14207
14208		this._on( this.button, this._buttonEvents );
14209		this.button.one( "focusin", function() {
14210
14211			// Delay rendering the menu items until the button receives focus.
14212			// The menu may have already been rendered via a programmatic open.
14213			if ( !that._rendered ) {
14214				that._refreshMenu();
14215			}
14216		} );
14217	},
14218
14219	_drawMenu: function() {
14220		var that = this;
14221
14222		// Create menu
14223		this.menu = $( "<ul>", {
14224			"aria-hidden": "true",
14225			"aria-labelledby": this.ids.button,
14226			id: this.ids.menu
14227		} );
14228
14229		// Wrap menu
14230		this.menuWrap = $( "<div>" ).append( this.menu );
14231		this._addClass( this.menuWrap, "ui-selectmenu-menu", "ui-front" );
14232		this.menuWrap.appendTo( this._appendTo() );
14233
14234		// Initialize menu widget
14235		this.menuInstance = this.menu
14236			.menu( {
14237				classes: {
14238					"ui-menu": "ui-corner-bottom"
14239				},
14240				role: "listbox",
14241				select: function( event, ui ) {
14242					event.preventDefault();
14243
14244					// Support: IE8
14245					// If the item was selected via a click, the text selection
14246					// will be destroyed in IE
14247					that._setSelection();
14248
14249					that._select( ui.item.data( "ui-selectmenu-item" ), event );
14250				},
14251				focus: function( event, ui ) {
14252					var item = ui.item.data( "ui-selectmenu-item" );
14253
14254					// Prevent inital focus from firing and check if its a newly focused item
14255					if ( that.focusIndex != null && item.index !== that.focusIndex ) {
14256						that._trigger( "focus", event, { item: item } );
14257						if ( !that.isOpen ) {
14258							that._select( item, event );
14259						}
14260					}
14261					that.focusIndex = item.index;
14262
14263					that.button.attr( "aria-activedescendant",
14264						that.menuItems.eq( item.index ).attr( "id" ) );
14265				}
14266			} )
14267			.menu( "instance" );
14268
14269		// Don't close the menu on mouseleave
14270		this.menuInstance._off( this.menu, "mouseleave" );
14271
14272		// Cancel the menu's collapseAll on document click
14273		this.menuInstance._closeOnDocumentClick = function() {
14274			return false;
14275		};
14276
14277		// Selects often contain empty items, but never contain dividers
14278		this.menuInstance._isDivider = function() {
14279			return false;
14280		};
14281	},
14282
14283	refresh: function() {
14284		this._refreshMenu();
14285		this.buttonItem.replaceWith(
14286			this.buttonItem = this._renderButtonItem(
14287
14288				// Fall back to an empty object in case there are no options
14289				this._getSelectedItem().data( "ui-selectmenu-item" ) || {}
14290			)
14291		);
14292		if ( this.options.width === null ) {
14293			this._resizeButton();
14294		}
14295	},
14296
14297	_refreshMenu: function() {
14298		var item,
14299			options = this.element.find( "option" );
14300
14301		this.menu.empty();
14302
14303		this._parseOptions( options );
14304		this._renderMenu( this.menu, this.items );
14305
14306		this.menuInstance.refresh();
14307		this.menuItems = this.menu.find( "li" )
14308			.not( ".ui-selectmenu-optgroup" )
14309				.find( ".ui-menu-item-wrapper" );
14310
14311		this._rendered = true;
14312
14313		if ( !options.length ) {
14314			return;
14315		}
14316
14317		item = this._getSelectedItem();
14318
14319		// Update the menu to have the correct item focused
14320		this.menuInstance.focus( null, item );
14321		this._setAria( item.data( "ui-selectmenu-item" ) );
14322
14323		// Set disabled state
14324		this._setOption( "disabled", this.element.prop( "disabled" ) );
14325	},
14326
14327	open: function( event ) {
14328		if ( this.options.disabled ) {
14329			return;
14330		}
14331
14332		// If this is the first time the menu is being opened, render the items
14333		if ( !this._rendered ) {
14334			this._refreshMenu();
14335		} else {
14336
14337			// Menu clears focus on close, reset focus to selected item
14338			this._removeClass( this.menu.find( ".ui-state-active" ), null, "ui-state-active" );
14339			this.menuInstance.focus( null, this._getSelectedItem() );
14340		}
14341
14342		// If there are no options, don't open the menu
14343		if ( !this.menuItems.length ) {
14344			return;
14345		}
14346
14347		this.isOpen = true;
14348		this._toggleAttr();
14349		this._resizeMenu();
14350		this._position();
14351
14352		this._on( this.document, this._documentClick );
14353
14354		this._trigger( "open", event );
14355	},
14356
14357	_position: function() {
14358		this.menuWrap.position( $.extend( { of: this.button }, this.options.position ) );
14359	},
14360
14361	close: function( event ) {
14362		if ( !this.isOpen ) {
14363			return;
14364		}
14365
14366		this.isOpen = false;
14367		this._toggleAttr();
14368
14369		this.range = null;
14370		this._off( this.document );
14371
14372		this._trigger( "close", event );
14373	},
14374
14375	widget: function() {
14376		return this.button;
14377	},
14378
14379	menuWidget: function() {
14380		return this.menu;
14381	},
14382
14383	_renderButtonItem: function( item ) {
14384		var buttonItem = $( "<span>" );
14385
14386		this._setText( buttonItem, item.label );
14387		this._addClass( buttonItem, "ui-selectmenu-text" );
14388
14389		return buttonItem;
14390	},
14391
14392	_renderMenu: function( ul, items ) {
14393		var that = this,
14394			currentOptgroup = "";
14395
14396		$.each( items, function( index, item ) {
14397			var li;
14398
14399			if ( item.optgroup !== currentOptgroup ) {
14400				li = $( "<li>", {
14401					text: item.optgroup
14402				} );
14403				that._addClass( li, "ui-selectmenu-optgroup", "ui-menu-divider" +
14404					( item.element.parent( "optgroup" ).prop( "disabled" ) ?
14405						" ui-state-disabled" :
14406						"" ) );
14407
14408				li.appendTo( ul );
14409
14410				currentOptgroup = item.optgroup;
14411			}
14412
14413			that._renderItemData( ul, item );
14414		} );
14415	},
14416
14417	_renderItemData: function( ul, item ) {
14418		return this._renderItem( ul, item ).data( "ui-selectmenu-item", item );
14419	},
14420
14421	_renderItem: function( ul, item ) {
14422		var li = $( "<li>" ),
14423			wrapper = $( "<div>", {
14424				title: item.element.attr( "title" )
14425			} );
14426
14427		if ( item.disabled ) {
14428			this._addClass( li, null, "ui-state-disabled" );
14429		}
14430
14431		if ( item.hidden ) {
14432			li.prop( "hidden", true );
14433		} else {
14434			this._setText( wrapper, item.label );
14435		}
14436
14437		return li.append( wrapper ).appendTo( ul );
14438	},
14439
14440	_setText: function( element, value ) {
14441		if ( value ) {
14442			element.text( value );
14443		} else {
14444			element.html( "&#160;" );
14445		}
14446	},
14447
14448	_move: function( direction, event ) {
14449		var item, next,
14450			filter = ".ui-menu-item";
14451
14452		if ( this.isOpen ) {
14453			item = this.menuItems.eq( this.focusIndex ).parent( "li" );
14454		} else {
14455			item = this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( "li" );
14456			filter += ":not(.ui-state-disabled)";
14457		}
14458
14459		if ( direction === "first" || direction === "last" ) {
14460			next = item[ direction === "first" ? "prevAll" : "nextAll" ]( filter ).eq( -1 );
14461		} else {
14462			next = item[ direction + "All" ]( filter ).eq( 0 );
14463		}
14464
14465		if ( next.length ) {
14466			this.menuInstance.focus( event, next );
14467		}
14468	},
14469
14470	_getSelectedItem: function() {
14471		return this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( "li" );
14472	},
14473
14474	_toggle: function( event ) {
14475		this[ this.isOpen ? "close" : "open" ]( event );
14476	},
14477
14478	_setSelection: function() {
14479		var selection;
14480
14481		if ( !this.range ) {
14482			return;
14483		}
14484
14485		if ( window.getSelection ) {
14486			selection = window.getSelection();
14487			selection.removeAllRanges();
14488			selection.addRange( this.range );
14489
14490		// Support: IE8
14491		} else {
14492			this.range.select();
14493		}
14494
14495		// Support: IE
14496		// Setting the text selection kills the button focus in IE, but
14497		// restoring the focus doesn't kill the selection.
14498		this.button.trigger( "focus" );
14499	},
14500
14501	_documentClick: {
14502		mousedown: function( event ) {
14503			if ( !this.isOpen ) {
14504				return;
14505			}
14506
14507			if ( !$( event.target ).closest( ".ui-selectmenu-menu, #" +
14508				$.escapeSelector( this.ids.button ) ).length ) {
14509				this.close( event );
14510			}
14511		}
14512	},
14513
14514	_buttonEvents: {
14515
14516		// Prevent text selection from being reset when interacting with the selectmenu (#10144)
14517		mousedown: function() {
14518			var selection;
14519
14520			if ( window.getSelection ) {
14521				selection = window.getSelection();
14522				if ( selection.rangeCount ) {
14523					this.range = selection.getRangeAt( 0 );
14524				}
14525
14526			// Support: IE8
14527			} else {
14528				this.range = document.selection.createRange();
14529			}
14530		},
14531
14532		click: function( event ) {
14533			this._setSelection();
14534			this._toggle( event );
14535		},
14536
14537		keydown: function( event ) {
14538			var preventDefault = true;
14539			switch ( event.keyCode ) {
14540			case $.ui.keyCode.TAB:
14541			case $.ui.keyCode.ESCAPE:
14542				this.close( event );
14543				preventDefault = false;
14544				break;
14545			case $.ui.keyCode.ENTER:
14546				if ( this.isOpen ) {
14547					this._selectFocusedItem( event );
14548				}
14549				break;
14550			case $.ui.keyCode.UP:
14551				if ( event.altKey ) {
14552					this._toggle( event );
14553				} else {
14554					this._move( "prev", event );
14555				}
14556				break;
14557			case $.ui.keyCode.DOWN:
14558				if ( event.altKey ) {
14559					this._toggle( event );
14560				} else {
14561					this._move( "next", event );
14562				}
14563				break;
14564			case $.ui.keyCode.SPACE:
14565				if ( this.isOpen ) {
14566					this._selectFocusedItem( event );
14567				} else {
14568					this._toggle( event );
14569				}
14570				break;
14571			case $.ui.keyCode.LEFT:
14572				this._move( "prev", event );
14573				break;
14574			case $.ui.keyCode.RIGHT:
14575				this._move( "next", event );
14576				break;
14577			case $.ui.keyCode.HOME:
14578			case $.ui.keyCode.PAGE_UP:
14579				this._move( "first", event );
14580				break;
14581			case $.ui.keyCode.END:
14582			case $.ui.keyCode.PAGE_DOWN:
14583				this._move( "last", event );
14584				break;
14585			default:
14586				this.menu.trigger( event );
14587				preventDefault = false;
14588			}
14589
14590			if ( preventDefault ) {
14591				event.preventDefault();
14592			}
14593		}
14594	},
14595
14596	_selectFocusedItem: function( event ) {
14597		var item = this.menuItems.eq( this.focusIndex ).parent( "li" );
14598		if ( !item.hasClass( "ui-state-disabled" ) ) {
14599			this._select( item.data( "ui-selectmenu-item" ), event );
14600		}
14601	},
14602
14603	_select: function( item, event ) {
14604		var oldIndex = this.element[ 0 ].selectedIndex;
14605
14606		// Change native select element
14607		this.element[ 0 ].selectedIndex = item.index;
14608		this.buttonItem.replaceWith( this.buttonItem = this._renderButtonItem( item ) );
14609		this._setAria( item );
14610		this._trigger( "select", event, { item: item } );
14611
14612		if ( item.index !== oldIndex ) {
14613			this._trigger( "change", event, { item: item } );
14614		}
14615
14616		this.close( event );
14617	},
14618
14619	_setAria: function( item ) {
14620		var id = this.menuItems.eq( item.index ).attr( "id" );
14621
14622		this.button.attr( {
14623			"aria-labelledby": id,
14624			"aria-activedescendant": id
14625		} );
14626		this.menu.attr( "aria-activedescendant", id );
14627	},
14628
14629	_setOption: function( key, value ) {
14630		if ( key === "icons" ) {
14631			var icon = this.button.find( "span.ui-icon" );
14632			this._removeClass( icon, null, this.options.icons.button )
14633				._addClass( icon, null, value.button );
14634		}
14635
14636		this._super( key, value );
14637
14638		if ( key === "appendTo" ) {
14639			this.menuWrap.appendTo( this._appendTo() );
14640		}
14641
14642		if ( key === "width" ) {
14643			this._resizeButton();
14644		}
14645	},
14646
14647	_setOptionDisabled: function( value ) {
14648		this._super( value );
14649
14650		this.menuInstance.option( "disabled", value );
14651		this.button.attr( "aria-disabled", value );
14652		this._toggleClass( this.button, null, "ui-state-disabled", value );
14653
14654		this.element.prop( "disabled", value );
14655		if ( value ) {
14656			this.button.attr( "tabindex", -1 );
14657			this.close();
14658		} else {
14659			this.button.attr( "tabindex", 0 );
14660		}
14661	},
14662
14663	_appendTo: function() {
14664		var element = this.options.appendTo;
14665
14666		if ( element ) {
14667			element = element.jquery || element.nodeType ?
14668				$( element ) :
14669				this.document.find( element ).eq( 0 );
14670		}
14671
14672		if ( !element || !element[ 0 ] ) {
14673			element = this.element.closest( ".ui-front, dialog" );
14674		}
14675
14676		if ( !element.length ) {
14677			element = this.document[ 0 ].body;
14678		}
14679
14680		return element;
14681	},
14682
14683	_toggleAttr: function() {
14684		this.button.attr( "aria-expanded", this.isOpen );
14685
14686		// We can't use two _toggleClass() calls here, because we need to make sure
14687		// we always remove classes first and add them second, otherwise if both classes have the
14688		// same theme class, it will be removed after we add it.
14689		this._removeClass( this.button, "ui-selectmenu-button-" +
14690			( this.isOpen ? "closed" : "open" ) )
14691			._addClass( this.button, "ui-selectmenu-button-" +
14692				( this.isOpen ? "open" : "closed" ) )
14693			._toggleClass( this.menuWrap, "ui-selectmenu-open", null, this.isOpen );
14694
14695		this.menu.attr( "aria-hidden", !this.isOpen );
14696	},
14697
14698	_resizeButton: function() {
14699		var width = this.options.width;
14700
14701		// For `width: false`, just remove inline style and stop
14702		if ( width === false ) {
14703			this.button.css( "width", "" );
14704			return;
14705		}
14706
14707		// For `width: null`, match the width of the original element
14708		if ( width === null ) {
14709			width = this.element.show().outerWidth();
14710			this.element.hide();
14711		}
14712
14713		this.button.outerWidth( width );
14714	},
14715
14716	_resizeMenu: function() {
14717		this.menu.outerWidth( Math.max(
14718			this.button.outerWidth(),
14719
14720			// Support: IE10
14721			// IE10 wraps long text (possibly a rounding bug)
14722			// so we add 1px to avoid the wrapping
14723			this.menu.width( "" ).outerWidth() + 1
14724		) );
14725	},
14726
14727	_getCreateOptions: function() {
14728		var options = this._super();
14729
14730		options.disabled = this.element.prop( "disabled" );
14731
14732		return options;
14733	},
14734
14735	_parseOptions: function( options ) {
14736		var that = this,
14737			data = [];
14738		options.each( function( index, item ) {
14739			data.push( that._parseOption( $( item ), index ) );
14740		} );
14741		this.items = data;
14742	},
14743
14744	_parseOption: function( option, index ) {
14745		var optgroup = option.parent( "optgroup" );
14746
14747		return {
14748			element: option,
14749			index: index,
14750			value: option.val(),
14751			label: option.text(),
14752			hidden: optgroup.prop( "hidden" ) || option.prop( "hidden" ),
14753			optgroup: optgroup.attr( "label" ) || "",
14754			disabled: optgroup.prop( "disabled" ) || option.prop( "disabled" )
14755		};
14756	},
14757
14758	_destroy: function() {
14759		this._unbindFormResetHandler();
14760		this.menuWrap.remove();
14761		this.button.remove();
14762		this.element.show();
14763		this.element.removeUniqueId();
14764		this.labels.attr( "for", this.ids.element );
14765	}
14766} ] );
14767
14768
14769/*!
14770 * jQuery UI Slider 1.13.3
14771 * https://jqueryui.com
14772 *
14773 * Copyright OpenJS Foundation and other contributors
14774 * Released under the MIT license.
14775 * https://jquery.org/license
14776 */
14777
14778//>>label: Slider
14779//>>group: Widgets
14780//>>description: Displays a flexible slider with ranges and accessibility via keyboard.
14781//>>docs: https://api.jqueryui.com/slider/
14782//>>demos: https://jqueryui.com/slider/
14783//>>css.structure: ../../themes/base/core.css
14784//>>css.structure: ../../themes/base/slider.css
14785//>>css.theme: ../../themes/base/theme.css
14786
14787
14788var widgetsSlider = $.widget( "ui.slider", $.ui.mouse, {
14789	version: "1.13.3",
14790	widgetEventPrefix: "slide",
14791
14792	options: {
14793		animate: false,
14794		classes: {
14795			"ui-slider": "ui-corner-all",
14796			"ui-slider-handle": "ui-corner-all",
14797
14798			// Note: ui-widget-header isn't the most fittingly semantic framework class for this
14799			// element, but worked best visually with a variety of themes
14800			"ui-slider-range": "ui-corner-all ui-widget-header"
14801		},
14802		distance: 0,
14803		max: 100,
14804		min: 0,
14805		orientation: "horizontal",
14806		range: false,
14807		step: 1,
14808		value: 0,
14809		values: null,
14810
14811		// Callbacks
14812		change: null,
14813		slide: null,
14814		start: null,
14815		stop: null
14816	},
14817
14818	// Number of pages in a slider
14819	// (how many times can you page up/down to go through the whole range)
14820	numPages: 5,
14821
14822	_create: function() {
14823		this._keySliding = false;
14824		this._mouseSliding = false;
14825		this._animateOff = true;
14826		this._handleIndex = null;
14827		this._detectOrientation();
14828		this._mouseInit();
14829		this._calculateNewMax();
14830
14831		this._addClass( "ui-slider ui-slider-" + this.orientation,
14832			"ui-widget ui-widget-content" );
14833
14834		this._refresh();
14835
14836		this._animateOff = false;
14837	},
14838
14839	_refresh: function() {
14840		this._createRange();
14841		this._createHandles();
14842		this._setupEvents();
14843		this._refreshValue();
14844	},
14845
14846	_createHandles: function() {
14847		var i, handleCount,
14848			options = this.options,
14849			existingHandles = this.element.find( ".ui-slider-handle" ),
14850			handle = "<span tabindex='0'></span>",
14851			handles = [];
14852
14853		handleCount = ( options.values && options.values.length ) || 1;
14854
14855		if ( existingHandles.length > handleCount ) {
14856			existingHandles.slice( handleCount ).remove();
14857			existingHandles = existingHandles.slice( 0, handleCount );
14858		}
14859
14860		for ( i = existingHandles.length; i < handleCount; i++ ) {
14861			handles.push( handle );
14862		}
14863
14864		this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) );
14865
14866		this._addClass( this.handles, "ui-slider-handle", "ui-state-default" );
14867
14868		this.handle = this.handles.eq( 0 );
14869
14870		this.handles.each( function( i ) {
14871			$( this )
14872				.data( "ui-slider-handle-index", i )
14873				.attr( "tabIndex", 0 );
14874		} );
14875	},
14876
14877	_createRange: function() {
14878		var options = this.options;
14879
14880		if ( options.range ) {
14881			if ( options.range === true ) {
14882				if ( !options.values ) {
14883					options.values = [ this._valueMin(), this._valueMin() ];
14884				} else if ( options.values.length && options.values.length !== 2 ) {
14885					options.values = [ options.values[ 0 ], options.values[ 0 ] ];
14886				} else if ( Array.isArray( options.values ) ) {
14887					options.values = options.values.slice( 0 );
14888				}
14889			}
14890
14891			if ( !this.range || !this.range.length ) {
14892				this.range = $( "<div>" )
14893					.appendTo( this.element );
14894
14895				this._addClass( this.range, "ui-slider-range" );
14896			} else {
14897				this._removeClass( this.range, "ui-slider-range-min ui-slider-range-max" );
14898
14899				// Handle range switching from true to min/max
14900				this.range.css( {
14901					"left": "",
14902					"bottom": ""
14903				} );
14904			}
14905			if ( options.range === "min" || options.range === "max" ) {
14906				this._addClass( this.range, "ui-slider-range-" + options.range );
14907			}
14908		} else {
14909			if ( this.range ) {
14910				this.range.remove();
14911			}
14912			this.range = null;
14913		}
14914	},
14915
14916	_setupEvents: function() {
14917		this._off( this.handles );
14918		this._on( this.handles, this._handleEvents );
14919		this._hoverable( this.handles );
14920		this._focusable( this.handles );
14921	},
14922
14923	_destroy: function() {
14924		this.handles.remove();
14925		if ( this.range ) {
14926			this.range.remove();
14927		}
14928
14929		this._mouseDestroy();
14930	},
14931
14932	_mouseCapture: function( event ) {
14933		var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle,
14934			that = this,
14935			o = this.options;
14936
14937		if ( o.disabled ) {
14938			return false;
14939		}
14940
14941		this.elementSize = {
14942			width: this.element.outerWidth(),
14943			height: this.element.outerHeight()
14944		};
14945		this.elementOffset = this.element.offset();
14946
14947		position = { x: event.pageX, y: event.pageY };
14948		normValue = this._normValueFromMouse( position );
14949		distance = this._valueMax() - this._valueMin() + 1;
14950		this.handles.each( function( i ) {
14951			var thisDistance = Math.abs( normValue - that.values( i ) );
14952			if ( ( distance > thisDistance ) ||
14953				( distance === thisDistance &&
14954					( i === that._lastChangedValue || that.values( i ) === o.min ) ) ) {
14955				distance = thisDistance;
14956				closestHandle = $( this );
14957				index = i;
14958			}
14959		} );
14960
14961		allowed = this._start( event, index );
14962		if ( allowed === false ) {
14963			return false;
14964		}
14965		this._mouseSliding = true;
14966
14967		this._handleIndex = index;
14968
14969		this._addClass( closestHandle, null, "ui-state-active" );
14970		closestHandle.trigger( "focus" );
14971
14972		offset = closestHandle.offset();
14973		mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" );
14974		this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
14975			left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
14976			top: event.pageY - offset.top -
14977				( closestHandle.height() / 2 ) -
14978				( parseInt( closestHandle.css( "borderTopWidth" ), 10 ) || 0 ) -
14979				( parseInt( closestHandle.css( "borderBottomWidth" ), 10 ) || 0 ) +
14980				( parseInt( closestHandle.css( "marginTop" ), 10 ) || 0 )
14981		};
14982
14983		if ( !this.handles.hasClass( "ui-state-hover" ) ) {
14984			this._slide( event, index, normValue );
14985		}
14986		this._animateOff = true;
14987		return true;
14988	},
14989
14990	_mouseStart: function() {
14991		return true;
14992	},
14993
14994	_mouseDrag: function( event ) {
14995		var position = { x: event.pageX, y: event.pageY },
14996			normValue = this._normValueFromMouse( position );
14997
14998		this._slide( event, this._handleIndex, normValue );
14999
15000		return false;
15001	},
15002
15003	_mouseStop: function( event ) {
15004		this._removeClass( this.handles, null, "ui-state-active" );
15005		this._mouseSliding = false;
15006
15007		this._stop( event, this._handleIndex );
15008		this._change( event, this._handleIndex );
15009
15010		this._handleIndex = null;
15011		this._clickOffset = null;
15012		this._animateOff = false;
15013
15014		return false;
15015	},
15016
15017	_detectOrientation: function() {
15018		this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
15019	},
15020
15021	_normValueFromMouse: function( position ) {
15022		var pixelTotal,
15023			pixelMouse,
15024			percentMouse,
15025			valueTotal,
15026			valueMouse;
15027
15028		if ( this.orientation === "horizontal" ) {
15029			pixelTotal = this.elementSize.width;
15030			pixelMouse = position.x - this.elementOffset.left -
15031				( this._clickOffset ? this._clickOffset.left : 0 );
15032		} else {
15033			pixelTotal = this.elementSize.height;
15034			pixelMouse = position.y - this.elementOffset.top -
15035				( this._clickOffset ? this._clickOffset.top : 0 );
15036		}
15037
15038		percentMouse = ( pixelMouse / pixelTotal );
15039		if ( percentMouse > 1 ) {
15040			percentMouse = 1;
15041		}
15042		if ( percentMouse < 0 ) {
15043			percentMouse = 0;
15044		}
15045		if ( this.orientation === "vertical" ) {
15046			percentMouse = 1 - percentMouse;
15047		}
15048
15049		valueTotal = this._valueMax() - this._valueMin();
15050		valueMouse = this._valueMin() + percentMouse * valueTotal;
15051
15052		return this._trimAlignValue( valueMouse );
15053	},
15054
15055	_uiHash: function( index, value, values ) {
15056		var uiHash = {
15057			handle: this.handles[ index ],
15058			handleIndex: index,
15059			value: value !== undefined ? value : this.value()
15060		};
15061
15062		if ( this._hasMultipleValues() ) {
15063			uiHash.value = value !== undefined ? value : this.values( index );
15064			uiHash.values = values || this.values();
15065		}
15066
15067		return uiHash;
15068	},
15069
15070	_hasMultipleValues: function() {
15071		return this.options.values && this.options.values.length;
15072	},
15073
15074	_start: function( event, index ) {
15075		return this._trigger( "start", event, this._uiHash( index ) );
15076	},
15077
15078	_slide: function( event, index, newVal ) {
15079		var allowed, otherVal,
15080			currentValue = this.value(),
15081			newValues = this.values();
15082
15083		if ( this._hasMultipleValues() ) {
15084			otherVal = this.values( index ? 0 : 1 );
15085			currentValue = this.values( index );
15086
15087			if ( this.options.values.length === 2 && this.options.range === true ) {
15088				newVal =  index === 0 ? Math.min( otherVal, newVal ) : Math.max( otherVal, newVal );
15089			}
15090
15091			newValues[ index ] = newVal;
15092		}
15093
15094		if ( newVal === currentValue ) {
15095			return;
15096		}
15097
15098		allowed = this._trigger( "slide", event, this._uiHash( index, newVal, newValues ) );
15099
15100		// A slide can be canceled by returning false from the slide callback
15101		if ( allowed === false ) {
15102			return;
15103		}
15104
15105		if ( this._hasMultipleValues() ) {
15106			this.values( index, newVal );
15107		} else {
15108			this.value( newVal );
15109		}
15110	},
15111
15112	_stop: function( event, index ) {
15113		this._trigger( "stop", event, this._uiHash( index ) );
15114	},
15115
15116	_change: function( event, index ) {
15117		if ( !this._keySliding && !this._mouseSliding ) {
15118
15119			//store the last changed value index for reference when handles overlap
15120			this._lastChangedValue = index;
15121			this._trigger( "change", event, this._uiHash( index ) );
15122		}
15123	},
15124
15125	value: function( newValue ) {
15126		if ( arguments.length ) {
15127			this.options.value = this._trimAlignValue( newValue );
15128			this._refreshValue();
15129			this._change( null, 0 );
15130			return;
15131		}
15132
15133		return this._value();
15134	},
15135
15136	values: function( index, newValue ) {
15137		var vals,
15138			newValues,
15139			i;
15140
15141		if ( arguments.length > 1 ) {
15142			this.options.values[ index ] = this._trimAlignValue( newValue );
15143			this._refreshValue();
15144			this._change( null, index );
15145			return;
15146		}
15147
15148		if ( arguments.length ) {
15149			if ( Array.isArray( arguments[ 0 ] ) ) {
15150				vals = this.options.values;
15151				newValues = arguments[ 0 ];
15152				for ( i = 0; i < vals.length; i += 1 ) {
15153					vals[ i ] = this._trimAlignValue( newValues[ i ] );
15154					this._change( null, i );
15155				}
15156				this._refreshValue();
15157			} else {
15158				if ( this._hasMultipleValues() ) {
15159					return this._values( index );
15160				} else {
15161					return this.value();
15162				}
15163			}
15164		} else {
15165			return this._values();
15166		}
15167	},
15168
15169	_setOption: function( key, value ) {
15170		var i,
15171			valsLength = 0;
15172
15173		if ( key === "range" && this.options.range === true ) {
15174			if ( value === "min" ) {
15175				this.options.value = this._values( 0 );
15176				this.options.values = null;
15177			} else if ( value === "max" ) {
15178				this.options.value = this._values( this.options.values.length - 1 );
15179				this.options.values = null;
15180			}
15181		}
15182
15183		if ( Array.isArray( this.options.values ) ) {
15184			valsLength = this.options.values.length;
15185		}
15186
15187		this._super( key, value );
15188
15189		switch ( key ) {
15190			case "orientation":
15191				this._detectOrientation();
15192				this._removeClass( "ui-slider-horizontal ui-slider-vertical" )
15193					._addClass( "ui-slider-" + this.orientation );
15194				this._refreshValue();
15195				if ( this.options.range ) {
15196					this._refreshRange( value );
15197				}
15198
15199				// Reset positioning from previous orientation
15200				this.handles.css( value === "horizontal" ? "bottom" : "left", "" );
15201				break;
15202			case "value":
15203				this._animateOff = true;
15204				this._refreshValue();
15205				this._change( null, 0 );
15206				this._animateOff = false;
15207				break;
15208			case "values":
15209				this._animateOff = true;
15210				this._refreshValue();
15211
15212				// Start from the last handle to prevent unreachable handles (#9046)
15213				for ( i = valsLength - 1; i >= 0; i-- ) {
15214					this._change( null, i );
15215				}
15216				this._animateOff = false;
15217				break;
15218			case "step":
15219			case "min":
15220			case "max":
15221				this._animateOff = true;
15222				this._calculateNewMax();
15223				this._refreshValue();
15224				this._animateOff = false;
15225				break;
15226			case "range":
15227				this._animateOff = true;
15228				this._refresh();
15229				this._animateOff = false;
15230				break;
15231		}
15232	},
15233
15234	_setOptionDisabled: function( value ) {
15235		this._super( value );
15236
15237		this._toggleClass( null, "ui-state-disabled", !!value );
15238	},
15239
15240	//internal value getter
15241	// _value() returns value trimmed by min and max, aligned by step
15242	_value: function() {
15243		var val = this.options.value;
15244		val = this._trimAlignValue( val );
15245
15246		return val;
15247	},
15248
15249	//internal values getter
15250	// _values() returns array of values trimmed by min and max, aligned by step
15251	// _values( index ) returns single value trimmed by min and max, aligned by step
15252	_values: function( index ) {
15253		var val,
15254			vals,
15255			i;
15256
15257		if ( arguments.length ) {
15258			val = this.options.values[ index ];
15259			val = this._trimAlignValue( val );
15260
15261			return val;
15262		} else if ( this._hasMultipleValues() ) {
15263
15264			// .slice() creates a copy of the array
15265			// this copy gets trimmed by min and max and then returned
15266			vals = this.options.values.slice();
15267			for ( i = 0; i < vals.length; i += 1 ) {
15268				vals[ i ] = this._trimAlignValue( vals[ i ] );
15269			}
15270
15271			return vals;
15272		} else {
15273			return [];
15274		}
15275	},
15276
15277	// Returns the step-aligned value that val is closest to, between (inclusive) min and max
15278	_trimAlignValue: function( val ) {
15279		if ( val <= this._valueMin() ) {
15280			return this._valueMin();
15281		}
15282		if ( val >= this._valueMax() ) {
15283			return this._valueMax();
15284		}
15285		var step = ( this.options.step > 0 ) ? this.options.step : 1,
15286			valModStep = ( val - this._valueMin() ) % step,
15287			alignValue = val - valModStep;
15288
15289		if ( Math.abs( valModStep ) * 2 >= step ) {
15290			alignValue += ( valModStep > 0 ) ? step : ( -step );
15291		}
15292
15293		// Since JavaScript has problems with large floats, round
15294		// the final value to 5 digits after the decimal point (see #4124)
15295		return parseFloat( alignValue.toFixed( 5 ) );
15296	},
15297
15298	_calculateNewMax: function() {
15299		var max = this.options.max,
15300			min = this._valueMin(),
15301			step = this.options.step,
15302			aboveMin = Math.round( ( max - min ) / step ) * step;
15303		max = aboveMin + min;
15304		if ( max > this.options.max ) {
15305
15306			//If max is not divisible by step, rounding off may increase its value
15307			max -= step;
15308		}
15309		this.max = parseFloat( max.toFixed( this._precision() ) );
15310	},
15311
15312	_precision: function() {
15313		var precision = this._precisionOf( this.options.step );
15314		if ( this.options.min !== null ) {
15315			precision = Math.max( precision, this._precisionOf( this.options.min ) );
15316		}
15317		return precision;
15318	},
15319
15320	_precisionOf: function( num ) {
15321		var str = num.toString(),
15322			decimal = str.indexOf( "." );
15323		return decimal === -1 ? 0 : str.length - decimal - 1;
15324	},
15325
15326	_valueMin: function() {
15327		return this.options.min;
15328	},
15329
15330	_valueMax: function() {
15331		return this.max;
15332	},
15333
15334	_refreshRange: function( orientation ) {
15335		if ( orientation === "vertical" ) {
15336			this.range.css( { "width": "", "left": "" } );
15337		}
15338		if ( orientation === "horizontal" ) {
15339			this.range.css( { "height": "", "bottom": "" } );
15340		}
15341	},
15342
15343	_refreshValue: function() {
15344		var lastValPercent, valPercent, value, valueMin, valueMax,
15345			oRange = this.options.range,
15346			o = this.options,
15347			that = this,
15348			animate = ( !this._animateOff ) ? o.animate : false,
15349			_set = {};
15350
15351		if ( this._hasMultipleValues() ) {
15352			this.handles.each( function( i ) {
15353				valPercent = ( that.values( i ) - that._valueMin() ) / ( that._valueMax() -
15354					that._valueMin() ) * 100;
15355				_set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
15356				$( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
15357				if ( that.options.range === true ) {
15358					if ( that.orientation === "horizontal" ) {
15359						if ( i === 0 ) {
15360							that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15361								left: valPercent + "%"
15362							}, o.animate );
15363						}
15364						if ( i === 1 ) {
15365							that.range[ animate ? "animate" : "css" ]( {
15366								width: ( valPercent - lastValPercent ) + "%"
15367							}, {
15368								queue: false,
15369								duration: o.animate
15370							} );
15371						}
15372					} else {
15373						if ( i === 0 ) {
15374							that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15375								bottom: ( valPercent ) + "%"
15376							}, o.animate );
15377						}
15378						if ( i === 1 ) {
15379							that.range[ animate ? "animate" : "css" ]( {
15380								height: ( valPercent - lastValPercent ) + "%"
15381							}, {
15382								queue: false,
15383								duration: o.animate
15384							} );
15385						}
15386					}
15387				}
15388				lastValPercent = valPercent;
15389			} );
15390		} else {
15391			value = this.value();
15392			valueMin = this._valueMin();
15393			valueMax = this._valueMax();
15394			valPercent = ( valueMax !== valueMin ) ?
15395					( value - valueMin ) / ( valueMax - valueMin ) * 100 :
15396					0;
15397			_set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
15398			this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
15399
15400			if ( oRange === "min" && this.orientation === "horizontal" ) {
15401				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15402					width: valPercent + "%"
15403				}, o.animate );
15404			}
15405			if ( oRange === "max" && this.orientation === "horizontal" ) {
15406				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15407					width: ( 100 - valPercent ) + "%"
15408				}, o.animate );
15409			}
15410			if ( oRange === "min" && this.orientation === "vertical" ) {
15411				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15412					height: valPercent + "%"
15413				}, o.animate );
15414			}
15415			if ( oRange === "max" && this.orientation === "vertical" ) {
15416				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15417					height: ( 100 - valPercent ) + "%"
15418				}, o.animate );
15419			}
15420		}
15421	},
15422
15423	_handleEvents: {
15424		keydown: function( event ) {
15425			var allowed, curVal, newVal, step,
15426				index = $( event.target ).data( "ui-slider-handle-index" );
15427
15428			switch ( event.keyCode ) {
15429				case $.ui.keyCode.HOME:
15430				case $.ui.keyCode.END:
15431				case $.ui.keyCode.PAGE_UP:
15432				case $.ui.keyCode.PAGE_DOWN:
15433				case $.ui.keyCode.UP:
15434				case $.ui.keyCode.RIGHT:
15435				case $.ui.keyCode.DOWN:
15436				case $.ui.keyCode.LEFT:
15437					event.preventDefault();
15438					if ( !this._keySliding ) {
15439						this._keySliding = true;
15440						this._addClass( $( event.target ), null, "ui-state-active" );
15441						allowed = this._start( event, index );
15442						if ( allowed === false ) {
15443							return;
15444						}
15445					}
15446					break;
15447			}
15448
15449			step = this.options.step;
15450			if ( this._hasMultipleValues() ) {
15451				curVal = newVal = this.values( index );
15452			} else {
15453				curVal = newVal = this.value();
15454			}
15455
15456			switch ( event.keyCode ) {
15457				case $.ui.keyCode.HOME:
15458					newVal = this._valueMin();
15459					break;
15460				case $.ui.keyCode.END:
15461					newVal = this._valueMax();
15462					break;
15463				case $.ui.keyCode.PAGE_UP:
15464					newVal = this._trimAlignValue(
15465						curVal + ( ( this._valueMax() - this._valueMin() ) / this.numPages )
15466					);
15467					break;
15468				case $.ui.keyCode.PAGE_DOWN:
15469					newVal = this._trimAlignValue(
15470						curVal - ( ( this._valueMax() - this._valueMin() ) / this.numPages ) );
15471					break;
15472				case $.ui.keyCode.UP:
15473				case $.ui.keyCode.RIGHT:
15474					if ( curVal === this._valueMax() ) {
15475						return;
15476					}
15477					newVal = this._trimAlignValue( curVal + step );
15478					break;
15479				case $.ui.keyCode.DOWN:
15480				case $.ui.keyCode.LEFT:
15481					if ( curVal === this._valueMin() ) {
15482						return;
15483					}
15484					newVal = this._trimAlignValue( curVal - step );
15485					break;
15486			}
15487
15488			this._slide( event, index, newVal );
15489		},
15490		keyup: function( event ) {
15491			var index = $( event.target ).data( "ui-slider-handle-index" );
15492
15493			if ( this._keySliding ) {
15494				this._keySliding = false;
15495				this._stop( event, index );
15496				this._change( event, index );
15497				this._removeClass( $( event.target ), null, "ui-state-active" );
15498			}
15499		}
15500	}
15501} );
15502
15503
15504/*!
15505 * jQuery UI Sortable 1.13.3
15506 * https://jqueryui.com
15507 *
15508 * Copyright OpenJS Foundation and other contributors
15509 * Released under the MIT license.
15510 * https://jquery.org/license
15511 */
15512
15513//>>label: Sortable
15514//>>group: Interactions
15515//>>description: Enables items in a list to be sorted using the mouse.
15516//>>docs: https://api.jqueryui.com/sortable/
15517//>>demos: https://jqueryui.com/sortable/
15518//>>css.structure: ../../themes/base/sortable.css
15519
15520
15521var widgetsSortable = $.widget( "ui.sortable", $.ui.mouse, {
15522	version: "1.13.3",
15523	widgetEventPrefix: "sort",
15524	ready: false,
15525	options: {
15526		appendTo: "parent",
15527		axis: false,
15528		connectWith: false,
15529		containment: false,
15530		cursor: "auto",
15531		cursorAt: false,
15532		dropOnEmpty: true,
15533		forcePlaceholderSize: false,
15534		forceHelperSize: false,
15535		grid: false,
15536		handle: false,
15537		helper: "original",
15538		items: "> *",
15539		opacity: false,
15540		placeholder: false,
15541		revert: false,
15542		scroll: true,
15543		scrollSensitivity: 20,
15544		scrollSpeed: 20,
15545		scope: "default",
15546		tolerance: "intersect",
15547		zIndex: 1000,
15548
15549		// Callbacks
15550		activate: null,
15551		beforeStop: null,
15552		change: null,
15553		deactivate: null,
15554		out: null,
15555		over: null,
15556		receive: null,
15557		remove: null,
15558		sort: null,
15559		start: null,
15560		stop: null,
15561		update: null
15562	},
15563
15564	_isOverAxis: function( x, reference, size ) {
15565		return ( x >= reference ) && ( x < ( reference + size ) );
15566	},
15567
15568	_isFloating: function( item ) {
15569		return ( /left|right/ ).test( item.css( "float" ) ) ||
15570			( /inline|table-cell/ ).test( item.css( "display" ) );
15571	},
15572
15573	_create: function() {
15574		this.containerCache = {};
15575		this._addClass( "ui-sortable" );
15576
15577		//Get the items
15578		this.refresh();
15579
15580		//Let's determine the parent's offset
15581		this.offset = this.element.offset();
15582
15583		//Initialize mouse events for interaction
15584		this._mouseInit();
15585
15586		this._setHandleClassName();
15587
15588		//We're ready to go
15589		this.ready = true;
15590
15591	},
15592
15593	_setOption: function( key, value ) {
15594		this._super( key, value );
15595
15596		if ( key === "handle" ) {
15597			this._setHandleClassName();
15598		}
15599	},
15600
15601	_setHandleClassName: function() {
15602		var that = this;
15603		this._removeClass( this.element.find( ".ui-sortable-handle" ), "ui-sortable-handle" );
15604		$.each( this.items, function() {
15605			that._addClass(
15606				this.instance.options.handle ?
15607					this.item.find( this.instance.options.handle ) :
15608					this.item,
15609				"ui-sortable-handle"
15610			);
15611		} );
15612	},
15613
15614	_destroy: function() {
15615		this._mouseDestroy();
15616
15617		for ( var i = this.items.length - 1; i >= 0; i-- ) {
15618			this.items[ i ].item.removeData( this.widgetName + "-item" );
15619		}
15620
15621		return this;
15622	},
15623
15624	_mouseCapture: function( event, overrideHandle ) {
15625		var currentItem = null,
15626			validHandle = false,
15627			that = this;
15628
15629		if ( this.reverting ) {
15630			return false;
15631		}
15632
15633		if ( this.options.disabled || this.options.type === "static" ) {
15634			return false;
15635		}
15636
15637		//We have to refresh the items data once first
15638		this._refreshItems( event );
15639
15640		//Find out if the clicked node (or one of its parents) is a actual item in this.items
15641		$( event.target ).parents().each( function() {
15642			if ( $.data( this, that.widgetName + "-item" ) === that ) {
15643				currentItem = $( this );
15644				return false;
15645			}
15646		} );
15647		if ( $.data( event.target, that.widgetName + "-item" ) === that ) {
15648			currentItem = $( event.target );
15649		}
15650
15651		if ( !currentItem ) {
15652			return false;
15653		}
15654		if ( this.options.handle && !overrideHandle ) {
15655			$( this.options.handle, currentItem ).find( "*" ).addBack().each( function() {
15656				if ( this === event.target ) {
15657					validHandle = true;
15658				}
15659			} );
15660			if ( !validHandle ) {
15661				return false;
15662			}
15663		}
15664
15665		this.currentItem = currentItem;
15666		this._removeCurrentsFromItems();
15667		return true;
15668
15669	},
15670
15671	_mouseStart: function( event, overrideHandle, noActivation ) {
15672
15673		var i, body,
15674			o = this.options;
15675
15676		this.currentContainer = this;
15677
15678		//We only need to call refreshPositions, because the refreshItems call has been moved to
15679		// mouseCapture
15680		this.refreshPositions();
15681
15682		//Prepare the dragged items parent
15683		this.appendTo = $( o.appendTo !== "parent" ?
15684				o.appendTo :
15685				this.currentItem.parent() );
15686
15687		//Create and append the visible helper
15688		this.helper = this._createHelper( event );
15689
15690		//Cache the helper size
15691		this._cacheHelperProportions();
15692
15693		/*
15694		 * - Position generation -
15695		 * This block generates everything position related - it's the core of draggables.
15696		 */
15697
15698		//Cache the margins of the original element
15699		this._cacheMargins();
15700
15701		//The element's absolute position on the page minus margins
15702		this.offset = this.currentItem.offset();
15703		this.offset = {
15704			top: this.offset.top - this.margins.top,
15705			left: this.offset.left - this.margins.left
15706		};
15707
15708		$.extend( this.offset, {
15709			click: { //Where the click happened, relative to the element
15710				left: event.pageX - this.offset.left,
15711				top: event.pageY - this.offset.top
15712			},
15713
15714			// This is a relative to absolute position minus the actual position calculation -
15715			// only used for relative positioned helper
15716			relative: this._getRelativeOffset()
15717		} );
15718
15719		// After we get the helper offset, but before we get the parent offset we can
15720		// change the helper's position to absolute
15721		// TODO: Still need to figure out a way to make relative sorting possible
15722		this.helper.css( "position", "absolute" );
15723		this.cssPosition = this.helper.css( "position" );
15724
15725		//Adjust the mouse offset relative to the helper if "cursorAt" is supplied
15726		if ( o.cursorAt ) {
15727			this._adjustOffsetFromHelper( o.cursorAt );
15728		}
15729
15730		//Cache the former DOM position
15731		this.domPosition = {
15732			prev: this.currentItem.prev()[ 0 ],
15733			parent: this.currentItem.parent()[ 0 ]
15734		};
15735
15736		// If the helper is not the original, hide the original so it's not playing any role during
15737		// the drag, won't cause anything bad this way
15738		if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {
15739			this.currentItem.hide();
15740		}
15741
15742		//Create the placeholder
15743		this._createPlaceholder();
15744
15745		//Get the next scrolling parent
15746		this.scrollParent = this.placeholder.scrollParent();
15747
15748		$.extend( this.offset, {
15749			parent: this._getParentOffset()
15750		} );
15751
15752		//Set a containment if given in the options
15753		if ( o.containment ) {
15754			this._setContainment();
15755		}
15756
15757		if ( o.cursor && o.cursor !== "auto" ) { // cursor option
15758			body = this.document.find( "body" );
15759
15760			// Support: IE
15761			this.storedCursor = body.css( "cursor" );
15762			body.css( "cursor", o.cursor );
15763
15764			this.storedStylesheet =
15765				$( "<style>*{ cursor: " + o.cursor + " !important; }</style>" ).appendTo( body );
15766		}
15767
15768		// We need to make sure to grab the zIndex before setting the
15769		// opacity, because setting the opacity to anything lower than 1
15770		// causes the zIndex to change from "auto" to 0.
15771		if ( o.zIndex ) { // zIndex option
15772			if ( this.helper.css( "zIndex" ) ) {
15773				this._storedZIndex = this.helper.css( "zIndex" );
15774			}
15775			this.helper.css( "zIndex", o.zIndex );
15776		}
15777
15778		if ( o.opacity ) { // opacity option
15779			if ( this.helper.css( "opacity" ) ) {
15780				this._storedOpacity = this.helper.css( "opacity" );
15781			}
15782			this.helper.css( "opacity", o.opacity );
15783		}
15784
15785		//Prepare scrolling
15786		if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
15787				this.scrollParent[ 0 ].tagName !== "HTML" ) {
15788			this.overflowOffset = this.scrollParent.offset();
15789		}
15790
15791		//Call callbacks
15792		this._trigger( "start", event, this._uiHash() );
15793
15794		//Recache the helper size
15795		if ( !this._preserveHelperProportions ) {
15796			this._cacheHelperProportions();
15797		}
15798
15799		//Post "activate" events to possible containers
15800		if ( !noActivation ) {
15801			for ( i = this.containers.length - 1; i >= 0; i-- ) {
15802				this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) );
15803			}
15804		}
15805
15806		//Prepare possible droppables
15807		if ( $.ui.ddmanager ) {
15808			$.ui.ddmanager.current = this;
15809		}
15810
15811		if ( $.ui.ddmanager && !o.dropBehaviour ) {
15812			$.ui.ddmanager.prepareOffsets( this, event );
15813		}
15814
15815		this.dragging = true;
15816
15817		this._addClass( this.helper, "ui-sortable-helper" );
15818
15819		//Move the helper, if needed
15820		if ( !this.helper.parent().is( this.appendTo ) ) {
15821			this.helper.detach().appendTo( this.appendTo );
15822
15823			//Update position
15824			this.offset.parent = this._getParentOffset();
15825		}
15826
15827		//Generate the original position
15828		this.position = this.originalPosition = this._generatePosition( event );
15829		this.originalPageX = event.pageX;
15830		this.originalPageY = event.pageY;
15831		this.lastPositionAbs = this.positionAbs = this._convertPositionTo( "absolute" );
15832
15833		this._mouseDrag( event );
15834
15835		return true;
15836
15837	},
15838
15839	_scroll: function( event ) {
15840		var o = this.options,
15841			scrolled = false;
15842
15843		if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
15844				this.scrollParent[ 0 ].tagName !== "HTML" ) {
15845
15846			if ( ( this.overflowOffset.top + this.scrollParent[ 0 ].offsetHeight ) -
15847					event.pageY < o.scrollSensitivity ) {
15848				this.scrollParent[ 0 ].scrollTop =
15849					scrolled = this.scrollParent[ 0 ].scrollTop + o.scrollSpeed;
15850			} else if ( event.pageY - this.overflowOffset.top < o.scrollSensitivity ) {
15851				this.scrollParent[ 0 ].scrollTop =
15852					scrolled = this.scrollParent[ 0 ].scrollTop - o.scrollSpeed;
15853			}
15854
15855			if ( ( this.overflowOffset.left + this.scrollParent[ 0 ].offsetWidth ) -
15856					event.pageX < o.scrollSensitivity ) {
15857				this.scrollParent[ 0 ].scrollLeft = scrolled =
15858					this.scrollParent[ 0 ].scrollLeft + o.scrollSpeed;
15859			} else if ( event.pageX - this.overflowOffset.left < o.scrollSensitivity ) {
15860				this.scrollParent[ 0 ].scrollLeft = scrolled =
15861					this.scrollParent[ 0 ].scrollLeft - o.scrollSpeed;
15862			}
15863
15864		} else {
15865
15866			if ( event.pageY - this.document.scrollTop() < o.scrollSensitivity ) {
15867				scrolled = this.document.scrollTop( this.document.scrollTop() - o.scrollSpeed );
15868			} else if ( this.window.height() - ( event.pageY - this.document.scrollTop() ) <
15869					o.scrollSensitivity ) {
15870				scrolled = this.document.scrollTop( this.document.scrollTop() + o.scrollSpeed );
15871			}
15872
15873			if ( event.pageX - this.document.scrollLeft() < o.scrollSensitivity ) {
15874				scrolled = this.document.scrollLeft(
15875					this.document.scrollLeft() - o.scrollSpeed
15876				);
15877			} else if ( this.window.width() - ( event.pageX - this.document.scrollLeft() ) <
15878					o.scrollSensitivity ) {
15879				scrolled = this.document.scrollLeft(
15880					this.document.scrollLeft() + o.scrollSpeed
15881				);
15882			}
15883
15884		}
15885
15886		return scrolled;
15887	},
15888
15889	_mouseDrag: function( event ) {
15890		var i, item, itemElement, intersection,
15891			o = this.options;
15892
15893		//Compute the helpers position
15894		this.position = this._generatePosition( event );
15895		this.positionAbs = this._convertPositionTo( "absolute" );
15896
15897		//Set the helper position
15898		if ( !this.options.axis || this.options.axis !== "y" ) {
15899			this.helper[ 0 ].style.left = this.position.left + "px";
15900		}
15901		if ( !this.options.axis || this.options.axis !== "x" ) {
15902			this.helper[ 0 ].style.top = this.position.top + "px";
15903		}
15904
15905		//Do scrolling
15906		if ( o.scroll ) {
15907			if ( this._scroll( event ) !== false ) {
15908
15909				//Update item positions used in position checks
15910				this._refreshItemPositions( true );
15911
15912				if ( $.ui.ddmanager && !o.dropBehaviour ) {
15913					$.ui.ddmanager.prepareOffsets( this, event );
15914				}
15915			}
15916		}
15917
15918		this.dragDirection = {
15919			vertical: this._getDragVerticalDirection(),
15920			horizontal: this._getDragHorizontalDirection()
15921		};
15922
15923		//Rearrange
15924		for ( i = this.items.length - 1; i >= 0; i-- ) {
15925
15926			//Cache variables and intersection, continue if no intersection
15927			item = this.items[ i ];
15928			itemElement = item.item[ 0 ];
15929			intersection = this._intersectsWithPointer( item );
15930			if ( !intersection ) {
15931				continue;
15932			}
15933
15934			// Only put the placeholder inside the current Container, skip all
15935			// items from other containers. This works because when moving
15936			// an item from one container to another the
15937			// currentContainer is switched before the placeholder is moved.
15938			//
15939			// Without this, moving items in "sub-sortables" can cause
15940			// the placeholder to jitter between the outer and inner container.
15941			if ( item.instance !== this.currentContainer ) {
15942				continue;
15943			}
15944
15945			// Cannot intersect with itself
15946			// no useless actions that have been done before
15947			// no action if the item moved is the parent of the item checked
15948			if ( itemElement !== this.currentItem[ 0 ] &&
15949				this.placeholder[ intersection === 1 ?
15950				"next" : "prev" ]()[ 0 ] !== itemElement &&
15951				!$.contains( this.placeholder[ 0 ], itemElement ) &&
15952				( this.options.type === "semi-dynamic" ?
15953					!$.contains( this.element[ 0 ], itemElement ) :
15954					true
15955				)
15956			) {
15957
15958				this.direction = intersection === 1 ? "down" : "up";
15959
15960				if ( this.options.tolerance === "pointer" ||
15961						this._intersectsWithSides( item ) ) {
15962					this._rearrange( event, item );
15963				} else {
15964					break;
15965				}
15966
15967				this._trigger( "change", event, this._uiHash() );
15968				break;
15969			}
15970		}
15971
15972		//Post events to containers
15973		this._contactContainers( event );
15974
15975		//Interconnect with droppables
15976		if ( $.ui.ddmanager ) {
15977			$.ui.ddmanager.drag( this, event );
15978		}
15979
15980		//Call callbacks
15981		this._trigger( "sort", event, this._uiHash() );
15982
15983		this.lastPositionAbs = this.positionAbs;
15984		return false;
15985
15986	},
15987
15988	_mouseStop: function( event, noPropagation ) {
15989
15990		if ( !event ) {
15991			return;
15992		}
15993
15994		//If we are using droppables, inform the manager about the drop
15995		if ( $.ui.ddmanager && !this.options.dropBehaviour ) {
15996			$.ui.ddmanager.drop( this, event );
15997		}
15998
15999		if ( this.options.revert ) {
16000			var that = this,
16001				cur = this.placeholder.offset(),
16002				axis = this.options.axis,
16003				animation = {};
16004
16005			if ( !axis || axis === "x" ) {
16006				animation.left = cur.left - this.offset.parent.left - this.margins.left +
16007					( this.offsetParent[ 0 ] === this.document[ 0 ].body ?
16008						0 :
16009						this.offsetParent[ 0 ].scrollLeft
16010					);
16011			}
16012			if ( !axis || axis === "y" ) {
16013				animation.top = cur.top - this.offset.parent.top - this.margins.top +
16014					( this.offsetParent[ 0 ] === this.document[ 0 ].body ?
16015						0 :
16016						this.offsetParent[ 0 ].scrollTop
16017					);
16018			}
16019			this.reverting = true;
16020			$( this.helper ).animate(
16021				animation,
16022				parseInt( this.options.revert, 10 ) || 500,
16023				function() {
16024					that._clear( event );
16025				}
16026			);
16027		} else {
16028			this._clear( event, noPropagation );
16029		}
16030
16031		return false;
16032
16033	},
16034
16035	cancel: function() {
16036
16037		if ( this.dragging ) {
16038
16039			this._mouseUp( new $.Event( "mouseup", { target: null } ) );
16040
16041			if ( this.options.helper === "original" ) {
16042				this.currentItem.css( this._storedCSS );
16043				this._removeClass( this.currentItem, "ui-sortable-helper" );
16044			} else {
16045				this.currentItem.show();
16046			}
16047
16048			//Post deactivating events to containers
16049			for ( var i = this.containers.length - 1; i >= 0; i-- ) {
16050				this.containers[ i ]._trigger( "deactivate", null, this._uiHash( this ) );
16051				if ( this.containers[ i ].containerCache.over ) {
16052					this.containers[ i ]._trigger( "out", null, this._uiHash( this ) );
16053					this.containers[ i ].containerCache.over = 0;
16054				}
16055			}
16056
16057		}
16058
16059		if ( this.placeholder ) {
16060
16061			//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately,
16062			// it unbinds ALL events from the original node!
16063			if ( this.placeholder[ 0 ].parentNode ) {
16064				this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] );
16065			}
16066			if ( this.options.helper !== "original" && this.helper &&
16067					this.helper[ 0 ].parentNode ) {
16068				this.helper.remove();
16069			}
16070
16071			$.extend( this, {
16072				helper: null,
16073				dragging: false,
16074				reverting: false,
16075				_noFinalSort: null
16076			} );
16077
16078			if ( this.domPosition.prev ) {
16079				$( this.domPosition.prev ).after( this.currentItem );
16080			} else {
16081				$( this.domPosition.parent ).prepend( this.currentItem );
16082			}
16083		}
16084
16085		return this;
16086
16087	},
16088
16089	serialize: function( o ) {
16090
16091		var items = this._getItemsAsjQuery( o && o.connected ),
16092			str = [];
16093		o = o || {};
16094
16095		$( items ).each( function() {
16096			var res = ( $( o.item || this ).attr( o.attribute || "id" ) || "" )
16097				.match( o.expression || ( /(.+)[\-=_](.+)/ ) );
16098			if ( res ) {
16099				str.push(
16100					( o.key || res[ 1 ] + "[]" ) +
16101					"=" + ( o.key && o.expression ? res[ 1 ] : res[ 2 ] ) );
16102			}
16103		} );
16104
16105		if ( !str.length && o.key ) {
16106			str.push( o.key + "=" );
16107		}
16108
16109		return str.join( "&" );
16110
16111	},
16112
16113	toArray: function( o ) {
16114
16115		var items = this._getItemsAsjQuery( o && o.connected ),
16116			ret = [];
16117
16118		o = o || {};
16119
16120		items.each( function() {
16121			ret.push( $( o.item || this ).attr( o.attribute || "id" ) || "" );
16122		} );
16123		return ret;
16124
16125	},
16126
16127	/* Be careful with the following core functions */
16128	_intersectsWith: function( item ) {
16129
16130		var x1 = this.positionAbs.left,
16131			x2 = x1 + this.helperProportions.width,
16132			y1 = this.positionAbs.top,
16133			y2 = y1 + this.helperProportions.height,
16134			l = item.left,
16135			r = l + item.width,
16136			t = item.top,
16137			b = t + item.height,
16138			dyClick = this.offset.click.top,
16139			dxClick = this.offset.click.left,
16140			isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t &&
16141				( y1 + dyClick ) < b ),
16142			isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l &&
16143				( x1 + dxClick ) < r ),
16144			isOverElement = isOverElementHeight && isOverElementWidth;
16145
16146		if ( this.options.tolerance === "pointer" ||
16147			this.options.forcePointerForContainers ||
16148			( this.options.tolerance !== "pointer" &&
16149				this.helperProportions[ this.floating ? "width" : "height" ] >
16150				item[ this.floating ? "width" : "height" ] )
16151		) {
16152			return isOverElement;
16153		} else {
16154
16155			return ( l < x1 + ( this.helperProportions.width / 2 ) && // Right Half
16156				x2 - ( this.helperProportions.width / 2 ) < r && // Left Half
16157				t < y1 + ( this.helperProportions.height / 2 ) && // Bottom Half
16158				y2 - ( this.helperProportions.height / 2 ) < b ); // Top Half
16159
16160		}
16161	},
16162
16163	_intersectsWithPointer: function( item ) {
16164		var verticalDirection, horizontalDirection,
16165			isOverElementHeight = ( this.options.axis === "x" ) ||
16166				this._isOverAxis(
16167					this.positionAbs.top + this.offset.click.top, item.top, item.height ),
16168			isOverElementWidth = ( this.options.axis === "y" ) ||
16169				this._isOverAxis(
16170					this.positionAbs.left + this.offset.click.left, item.left, item.width ),
16171			isOverElement = isOverElementHeight && isOverElementWidth;
16172
16173		if ( !isOverElement ) {
16174			return false;
16175		}
16176
16177		verticalDirection = this.dragDirection.vertical;
16178		horizontalDirection = this.dragDirection.horizontal;
16179
16180		return this.floating ?
16181			( ( horizontalDirection === "right" || verticalDirection === "down" ) ? 2 : 1 ) :
16182			( verticalDirection && ( verticalDirection === "down" ? 2 : 1 ) );
16183
16184	},
16185
16186	_intersectsWithSides: function( item ) {
16187
16188		var isOverBottomHalf = this._isOverAxis( this.positionAbs.top +
16189				this.offset.click.top, item.top + ( item.height / 2 ), item.height ),
16190			isOverRightHalf = this._isOverAxis( this.positionAbs.left +
16191				this.offset.click.left, item.left + ( item.width / 2 ), item.width ),
16192			verticalDirection = this.dragDirection.vertical,
16193			horizontalDirection = this.dragDirection.horizontal;
16194
16195		if ( this.floating && horizontalDirection ) {
16196			return ( ( horizontalDirection === "right" && isOverRightHalf ) ||
16197				( horizontalDirection === "left" && !isOverRightHalf ) );
16198		} else {
16199			return verticalDirection && ( ( verticalDirection === "down" && isOverBottomHalf ) ||
16200				( verticalDirection === "up" && !isOverBottomHalf ) );
16201		}
16202
16203	},
16204
16205	_getDragVerticalDirection: function() {
16206		var delta = this.positionAbs.top - this.lastPositionAbs.top;
16207		return delta !== 0 && ( delta > 0 ? "down" : "up" );
16208	},
16209
16210	_getDragHorizontalDirection: function() {
16211		var delta = this.positionAbs.left - this.lastPositionAbs.left;
16212		return delta !== 0 && ( delta > 0 ? "right" : "left" );
16213	},
16214
16215	refresh: function( event ) {
16216		this._refreshItems( event );
16217		this._setHandleClassName();
16218		this.refreshPositions();
16219		return this;
16220	},
16221
16222	_connectWith: function() {
16223		var options = this.options;
16224		return options.connectWith.constructor === String ?
16225			[ options.connectWith ] :
16226			options.connectWith;
16227	},
16228
16229	_getItemsAsjQuery: function( connected ) {
16230
16231		var i, j, cur, inst,
16232			items = [],
16233			queries = [],
16234			connectWith = this._connectWith();
16235
16236		if ( connectWith && connected ) {
16237			for ( i = connectWith.length - 1; i >= 0; i-- ) {
16238				cur = $( connectWith[ i ], this.document[ 0 ] );
16239				for ( j = cur.length - 1; j >= 0; j-- ) {
16240					inst = $.data( cur[ j ], this.widgetFullName );
16241					if ( inst && inst !== this && !inst.options.disabled ) {
16242						queries.push( [ typeof inst.options.items === "function" ?
16243							inst.options.items.call( inst.element ) :
16244							$( inst.options.items, inst.element )
16245								.not( ".ui-sortable-helper" )
16246								.not( ".ui-sortable-placeholder" ), inst ] );
16247					}
16248				}
16249			}
16250		}
16251
16252		queries.push( [ typeof this.options.items === "function" ?
16253			this.options.items
16254				.call( this.element, null, { options: this.options, item: this.currentItem } ) :
16255			$( this.options.items, this.element )
16256				.not( ".ui-sortable-helper" )
16257				.not( ".ui-sortable-placeholder" ), this ] );
16258
16259		function addItems() {
16260			items.push( this );
16261		}
16262		for ( i = queries.length - 1; i >= 0; i-- ) {
16263			queries[ i ][ 0 ].each( addItems );
16264		}
16265
16266		return $( items );
16267
16268	},
16269
16270	_removeCurrentsFromItems: function() {
16271
16272		var list = this.currentItem.find( ":data(" + this.widgetName + "-item)" );
16273
16274		this.items = $.grep( this.items, function( item ) {
16275			for ( var j = 0; j < list.length; j++ ) {
16276				if ( list[ j ] === item.item[ 0 ] ) {
16277					return false;
16278				}
16279			}
16280			return true;
16281		} );
16282
16283	},
16284
16285	_refreshItems: function( event ) {
16286
16287		this.items = [];
16288		this.containers = [ this ];
16289
16290		var i, j, cur, inst, targetData, _queries, item, queriesLength,
16291			items = this.items,
16292			queries = [ [ typeof this.options.items === "function" ?
16293				this.options.items.call( this.element[ 0 ], event, { item: this.currentItem } ) :
16294				$( this.options.items, this.element ), this ] ],
16295			connectWith = this._connectWith();
16296
16297		//Shouldn't be run the first time through due to massive slow-down
16298		if ( connectWith && this.ready ) {
16299			for ( i = connectWith.length - 1; i >= 0; i-- ) {
16300				cur = $( connectWith[ i ], this.document[ 0 ] );
16301				for ( j = cur.length - 1; j >= 0; j-- ) {
16302					inst = $.data( cur[ j ], this.widgetFullName );
16303					if ( inst && inst !== this && !inst.options.disabled ) {
16304						queries.push( [ typeof inst.options.items === "function" ?
16305							inst.options.items
16306								.call( inst.element[ 0 ], event, { item: this.currentItem } ) :
16307							$( inst.options.items, inst.element ), inst ] );
16308						this.containers.push( inst );
16309					}
16310				}
16311			}
16312		}
16313
16314		for ( i = queries.length - 1; i >= 0; i-- ) {
16315			targetData = queries[ i ][ 1 ];
16316			_queries = queries[ i ][ 0 ];
16317
16318			for ( j = 0, queriesLength = _queries.length; j < queriesLength; j++ ) {
16319				item = $( _queries[ j ] );
16320
16321				// Data for target checking (mouse manager)
16322				item.data( this.widgetName + "-item", targetData );
16323
16324				items.push( {
16325					item: item,
16326					instance: targetData,
16327					width: 0, height: 0,
16328					left: 0, top: 0
16329				} );
16330			}
16331		}
16332
16333	},
16334
16335	_refreshItemPositions: function( fast ) {
16336		var i, item, t, p;
16337
16338		for ( i = this.items.length - 1; i >= 0; i-- ) {
16339			item = this.items[ i ];
16340
16341			//We ignore calculating positions of all connected containers when we're not over them
16342			if ( this.currentContainer && item.instance !== this.currentContainer &&
16343					item.item[ 0 ] !== this.currentItem[ 0 ] ) {
16344				continue;
16345			}
16346
16347			t = this.options.toleranceElement ?
16348				$( this.options.toleranceElement, item.item ) :
16349				item.item;
16350
16351			if ( !fast ) {
16352				item.width = t.outerWidth();
16353				item.height = t.outerHeight();
16354			}
16355
16356			p = t.offset();
16357			item.left = p.left;
16358			item.top = p.top;
16359		}
16360	},
16361
16362	refreshPositions: function( fast ) {
16363
16364		// Determine whether items are being displayed horizontally
16365		this.floating = this.items.length ?
16366			this.options.axis === "x" || this._isFloating( this.items[ 0 ].item ) :
16367			false;
16368
16369		// This has to be redone because due to the item being moved out/into the offsetParent,
16370		// the offsetParent's position will change
16371		if ( this.offsetParent && this.helper ) {
16372			this.offset.parent = this._getParentOffset();
16373		}
16374
16375		this._refreshItemPositions( fast );
16376
16377		var i, p;
16378
16379		if ( this.options.custom && this.options.custom.refreshContainers ) {
16380			this.options.custom.refreshContainers.call( this );
16381		} else {
16382			for ( i = this.containers.length - 1; i >= 0; i-- ) {
16383				p = this.containers[ i ].element.offset();
16384				this.containers[ i ].containerCache.left = p.left;
16385				this.containers[ i ].containerCache.top = p.top;
16386				this.containers[ i ].containerCache.width =
16387					this.containers[ i ].element.outerWidth();
16388				this.containers[ i ].containerCache.height =
16389					this.containers[ i ].element.outerHeight();
16390			}
16391		}
16392
16393		return this;
16394	},
16395
16396	_createPlaceholder: function( that ) {
16397		that = that || this;
16398		var className, nodeName,
16399			o = that.options;
16400
16401		if ( !o.placeholder || o.placeholder.constructor === String ) {
16402			className = o.placeholder;
16403			nodeName = that.currentItem[ 0 ].nodeName.toLowerCase();
16404			o.placeholder = {
16405				element: function() {
16406
16407					var element = $( "<" + nodeName + ">", that.document[ 0 ] );
16408
16409					that._addClass( element, "ui-sortable-placeholder",
16410							className || that.currentItem[ 0 ].className )
16411						._removeClass( element, "ui-sortable-helper" );
16412
16413					if ( nodeName === "tbody" ) {
16414						that._createTrPlaceholder(
16415							that.currentItem.find( "tr" ).eq( 0 ),
16416							$( "<tr>", that.document[ 0 ] ).appendTo( element )
16417						);
16418					} else if ( nodeName === "tr" ) {
16419						that._createTrPlaceholder( that.currentItem, element );
16420					} else if ( nodeName === "img" ) {
16421						element.attr( "src", that.currentItem.attr( "src" ) );
16422					}
16423
16424					if ( !className ) {
16425						element.css( "visibility", "hidden" );
16426					}
16427
16428					return element;
16429				},
16430				update: function( container, p ) {
16431
16432					// 1. If a className is set as 'placeholder option, we don't force sizes -
16433					// the class is responsible for that
16434					// 2. The option 'forcePlaceholderSize can be enabled to force it even if a
16435					// class name is specified
16436					if ( className && !o.forcePlaceholderSize ) {
16437						return;
16438					}
16439
16440					// If the element doesn't have a actual height or width by itself (without
16441					// styles coming from a stylesheet), it receives the inline height and width
16442					// from the dragged item. Or, if it's a tbody or tr, it's going to have a height
16443					// anyway since we're populating them with <td>s above, but they're unlikely to
16444					// be the correct height on their own if the row heights are dynamic, so we'll
16445					// always assign the height of the dragged item given forcePlaceholderSize
16446					// is true.
16447					if ( !p.height() || ( o.forcePlaceholderSize &&
16448							( nodeName === "tbody" || nodeName === "tr" ) ) ) {
16449						p.height(
16450							that.currentItem.innerHeight() -
16451							parseInt( that.currentItem.css( "paddingTop" ) || 0, 10 ) -
16452							parseInt( that.currentItem.css( "paddingBottom" ) || 0, 10 ) );
16453					}
16454					if ( !p.width() ) {
16455						p.width(
16456							that.currentItem.innerWidth() -
16457							parseInt( that.currentItem.css( "paddingLeft" ) || 0, 10 ) -
16458							parseInt( that.currentItem.css( "paddingRight" ) || 0, 10 ) );
16459					}
16460				}
16461			};
16462		}
16463
16464		//Create the placeholder
16465		that.placeholder = $( o.placeholder.element.call( that.element, that.currentItem ) );
16466
16467		//Append it after the actual current item
16468		that.currentItem.after( that.placeholder );
16469
16470		//Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
16471		o.placeholder.update( that, that.placeholder );
16472
16473	},
16474
16475	_createTrPlaceholder: function( sourceTr, targetTr ) {
16476		var that = this;
16477
16478		sourceTr.children().each( function() {
16479			$( "<td>&#160;</td>", that.document[ 0 ] )
16480				.attr( "colspan", $( this ).attr( "colspan" ) || 1 )
16481				.appendTo( targetTr );
16482		} );
16483	},
16484
16485	_contactContainers: function( event ) {
16486		var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, cur, nearBottom,
16487			floating, axis,
16488			innermostContainer = null,
16489			innermostIndex = null;
16490
16491		// Get innermost container that intersects with item
16492		for ( i = this.containers.length - 1; i >= 0; i-- ) {
16493
16494			// Never consider a container that's located within the item itself
16495			if ( $.contains( this.currentItem[ 0 ], this.containers[ i ].element[ 0 ] ) ) {
16496				continue;
16497			}
16498
16499			if ( this._intersectsWith( this.containers[ i ].containerCache ) ) {
16500
16501				// If we've already found a container and it's more "inner" than this, then continue
16502				if ( innermostContainer &&
16503						$.contains(
16504							this.containers[ i ].element[ 0 ],
16505							innermostContainer.element[ 0 ] ) ) {
16506					continue;
16507				}
16508
16509				innermostContainer = this.containers[ i ];
16510				innermostIndex = i;
16511
16512			} else {
16513
16514				// container doesn't intersect. trigger "out" event if necessary
16515				if ( this.containers[ i ].containerCache.over ) {
16516					this.containers[ i ]._trigger( "out", event, this._uiHash( this ) );
16517					this.containers[ i ].containerCache.over = 0;
16518				}
16519			}
16520
16521		}
16522
16523		// If no intersecting containers found, return
16524		if ( !innermostContainer ) {
16525			return;
16526		}
16527
16528		// Move the item into the container if it's not there already
16529		if ( this.containers.length === 1 ) {
16530			if ( !this.containers[ innermostIndex ].containerCache.over ) {
16531				this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) );
16532				this.containers[ innermostIndex ].containerCache.over = 1;
16533			}
16534		} else {
16535
16536			// When entering a new container, we will find the item with the least distance and
16537			// append our item near it
16538			dist = 10000;
16539			itemWithLeastDistance = null;
16540			floating = innermostContainer.floating || this._isFloating( this.currentItem );
16541			posProperty = floating ? "left" : "top";
16542			sizeProperty = floating ? "width" : "height";
16543			axis = floating ? "pageX" : "pageY";
16544
16545			for ( j = this.items.length - 1; j >= 0; j-- ) {
16546				if ( !$.contains(
16547						this.containers[ innermostIndex ].element[ 0 ], this.items[ j ].item[ 0 ] )
16548				) {
16549					continue;
16550				}
16551				if ( this.items[ j ].item[ 0 ] === this.currentItem[ 0 ] ) {
16552					continue;
16553				}
16554
16555				cur = this.items[ j ].item.offset()[ posProperty ];
16556				nearBottom = false;
16557				if ( event[ axis ] - cur > this.items[ j ][ sizeProperty ] / 2 ) {
16558					nearBottom = true;
16559				}
16560
16561				if ( Math.abs( event[ axis ] - cur ) < dist ) {
16562					dist = Math.abs( event[ axis ] - cur );
16563					itemWithLeastDistance = this.items[ j ];
16564					this.direction = nearBottom ? "up" : "down";
16565				}
16566			}
16567
16568			//Check if dropOnEmpty is enabled
16569			if ( !itemWithLeastDistance && !this.options.dropOnEmpty ) {
16570				return;
16571			}
16572
16573			if ( this.currentContainer === this.containers[ innermostIndex ] ) {
16574				if ( !this.currentContainer.containerCache.over ) {
16575					this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash() );
16576					this.currentContainer.containerCache.over = 1;
16577				}
16578				return;
16579			}
16580
16581			if ( itemWithLeastDistance ) {
16582				this._rearrange( event, itemWithLeastDistance, null, true );
16583			} else {
16584				this._rearrange( event, null, this.containers[ innermostIndex ].element, true );
16585			}
16586			this._trigger( "change", event, this._uiHash() );
16587			this.containers[ innermostIndex ]._trigger( "change", event, this._uiHash( this ) );
16588			this.currentContainer = this.containers[ innermostIndex ];
16589
16590			//Update the placeholder
16591			this.options.placeholder.update( this.currentContainer, this.placeholder );
16592
16593			//Update scrollParent
16594			this.scrollParent = this.placeholder.scrollParent();
16595
16596			//Update overflowOffset
16597			if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
16598					this.scrollParent[ 0 ].tagName !== "HTML" ) {
16599				this.overflowOffset = this.scrollParent.offset();
16600			}
16601
16602			this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) );
16603			this.containers[ innermostIndex ].containerCache.over = 1;
16604		}
16605
16606	},
16607
16608	_createHelper: function( event ) {
16609
16610		var o = this.options,
16611			helper = typeof o.helper === "function" ?
16612				$( o.helper.apply( this.element[ 0 ], [ event, this.currentItem ] ) ) :
16613				( o.helper === "clone" ? this.currentItem.clone() : this.currentItem );
16614
16615		//Add the helper to the DOM if that didn't happen already
16616		if ( !helper.parents( "body" ).length ) {
16617			this.appendTo[ 0 ].appendChild( helper[ 0 ] );
16618		}
16619
16620		if ( helper[ 0 ] === this.currentItem[ 0 ] ) {
16621			this._storedCSS = {
16622				width: this.currentItem[ 0 ].style.width,
16623				height: this.currentItem[ 0 ].style.height,
16624				position: this.currentItem.css( "position" ),
16625				top: this.currentItem.css( "top" ),
16626				left: this.currentItem.css( "left" )
16627			};
16628		}
16629
16630		if ( !helper[ 0 ].style.width || o.forceHelperSize ) {
16631			helper.width( this.currentItem.width() );
16632		}
16633		if ( !helper[ 0 ].style.height || o.forceHelperSize ) {
16634			helper.height( this.currentItem.height() );
16635		}
16636
16637		return helper;
16638
16639	},
16640
16641	_adjustOffsetFromHelper: function( obj ) {
16642		if ( typeof obj === "string" ) {
16643			obj = obj.split( " " );
16644		}
16645		if ( Array.isArray( obj ) ) {
16646			obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 };
16647		}
16648		if ( "left" in obj ) {
16649			this.offset.click.left = obj.left + this.margins.left;
16650		}
16651		if ( "right" in obj ) {
16652			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
16653		}
16654		if ( "top" in obj ) {
16655			this.offset.click.top = obj.top + this.margins.top;
16656		}
16657		if ( "bottom" in obj ) {
16658			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
16659		}
16660	},
16661
16662	_getParentOffset: function() {
16663
16664		//Get the offsetParent and cache its position
16665		this.offsetParent = this.helper.offsetParent();
16666		var po = this.offsetParent.offset();
16667
16668		// This is a special case where we need to modify a offset calculated on start, since the
16669		// following happened:
16670		// 1. The position of the helper is absolute, so it's position is calculated based on the
16671		// next positioned parent
16672		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't
16673		// the document, which means that the scroll is included in the initial calculation of the
16674		// offset of the parent, and never recalculated upon drag
16675		if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== this.document[ 0 ] &&
16676				$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) {
16677			po.left += this.scrollParent.scrollLeft();
16678			po.top += this.scrollParent.scrollTop();
16679		}
16680
16681		// This needs to be actually done for all browsers, since pageX/pageY includes this
16682		// information with an ugly IE fix
16683		if ( this.offsetParent[ 0 ] === this.document[ 0 ].body ||
16684				( this.offsetParent[ 0 ].tagName &&
16685				this.offsetParent[ 0 ].tagName.toLowerCase() === "html" && $.ui.ie ) ) {
16686			po = { top: 0, left: 0 };
16687		}
16688
16689		return {
16690			top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ),
16691			left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 )
16692		};
16693
16694	},
16695
16696	_getRelativeOffset: function() {
16697
16698		if ( this.cssPosition === "relative" ) {
16699			var p = this.currentItem.position();
16700			return {
16701				top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) +
16702					this.scrollParent.scrollTop(),
16703				left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) +
16704					this.scrollParent.scrollLeft()
16705			};
16706		} else {
16707			return { top: 0, left: 0 };
16708		}
16709
16710	},
16711
16712	_cacheMargins: function() {
16713		this.margins = {
16714			left: ( parseInt( this.currentItem.css( "marginLeft" ), 10 ) || 0 ),
16715			top: ( parseInt( this.currentItem.css( "marginTop" ), 10 ) || 0 )
16716		};
16717	},
16718
16719	_cacheHelperProportions: function() {
16720		this.helperProportions = {
16721			width: this.helper.outerWidth(),
16722			height: this.helper.outerHeight()
16723		};
16724	},
16725
16726	_setContainment: function() {
16727
16728		var ce, co, over,
16729			o = this.options;
16730		if ( o.containment === "parent" ) {
16731			o.containment = this.helper[ 0 ].parentNode;
16732		}
16733		if ( o.containment === "document" || o.containment === "window" ) {
16734			this.containment = [
16735				0 - this.offset.relative.left - this.offset.parent.left,
16736				0 - this.offset.relative.top - this.offset.parent.top,
16737				o.containment === "document" ?
16738					this.document.width() :
16739					this.window.width() - this.helperProportions.width - this.margins.left,
16740				( o.containment === "document" ?
16741					( this.document.height() || document.body.parentNode.scrollHeight ) :
16742					this.window.height() || this.document[ 0 ].body.parentNode.scrollHeight
16743				) - this.helperProportions.height - this.margins.top
16744			];
16745		}
16746
16747		if ( !( /^(document|window|parent)$/ ).test( o.containment ) ) {
16748			ce = $( o.containment )[ 0 ];
16749			co = $( o.containment ).offset();
16750			over = ( $( ce ).css( "overflow" ) !== "hidden" );
16751
16752			this.containment = [
16753				co.left + ( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) +
16754					( parseInt( $( ce ).css( "paddingLeft" ), 10 ) || 0 ) - this.margins.left,
16755				co.top + ( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) +
16756					( parseInt( $( ce ).css( "paddingTop" ), 10 ) || 0 ) - this.margins.top,
16757				co.left + ( over ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -
16758					( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) -
16759					( parseInt( $( ce ).css( "paddingRight" ), 10 ) || 0 ) -
16760					this.helperProportions.width - this.margins.left,
16761				co.top + ( over ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -
16762					( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) -
16763					( parseInt( $( ce ).css( "paddingBottom" ), 10 ) || 0 ) -
16764					this.helperProportions.height - this.margins.top
16765			];
16766		}
16767
16768	},
16769
16770	_convertPositionTo: function( d, pos ) {
16771
16772		if ( !pos ) {
16773			pos = this.position;
16774		}
16775		var mod = d === "absolute" ? 1 : -1,
16776			scroll = this.cssPosition === "absolute" &&
16777				!( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
16778				$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ?
16779					this.offsetParent :
16780					this.scrollParent,
16781			scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName );
16782
16783		return {
16784			top: (
16785
16786				// The absolute mouse position
16787				pos.top	+
16788
16789				// Only for relative positioned nodes: Relative offset from element to offset parent
16790				this.offset.relative.top * mod +
16791
16792				// The offsetParent's offset without borders (offset + border)
16793				this.offset.parent.top * mod -
16794				( ( this.cssPosition === "fixed" ?
16795					-this.scrollParent.scrollTop() :
16796					( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod )
16797			),
16798			left: (
16799
16800				// The absolute mouse position
16801				pos.left +
16802
16803				// Only for relative positioned nodes: Relative offset from element to offset parent
16804				this.offset.relative.left * mod +
16805
16806				// The offsetParent's offset without borders (offset + border)
16807				this.offset.parent.left * mod	-
16808				( ( this.cssPosition === "fixed" ?
16809					-this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 :
16810					scroll.scrollLeft() ) * mod )
16811			)
16812		};
16813
16814	},
16815
16816	_generatePosition: function( event ) {
16817
16818		var top, left,
16819			o = this.options,
16820			pageX = event.pageX,
16821			pageY = event.pageY,
16822			scroll = this.cssPosition === "absolute" &&
16823				!( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
16824				$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ?
16825					this.offsetParent :
16826					this.scrollParent,
16827				scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName );
16828
16829		// This is another very weird special case that only happens for relative elements:
16830		// 1. If the css position is relative
16831		// 2. and the scroll parent is the document or similar to the offset parent
16832		// we have to refresh the relative offset during the scroll so there are no jumps
16833		if ( this.cssPosition === "relative" && !( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
16834				this.scrollParent[ 0 ] !== this.offsetParent[ 0 ] ) ) {
16835			this.offset.relative = this._getRelativeOffset();
16836		}
16837
16838		/*
16839		 * - Position constraining -
16840		 * Constrain the position to a mix of grid, containment.
16841		 */
16842
16843		if ( this.originalPosition ) { //If we are not dragging yet, we won't check for options
16844
16845			if ( this.containment ) {
16846				if ( event.pageX - this.offset.click.left < this.containment[ 0 ] ) {
16847					pageX = this.containment[ 0 ] + this.offset.click.left;
16848				}
16849				if ( event.pageY - this.offset.click.top < this.containment[ 1 ] ) {
16850					pageY = this.containment[ 1 ] + this.offset.click.top;
16851				}
16852				if ( event.pageX - this.offset.click.left > this.containment[ 2 ] ) {
16853					pageX = this.containment[ 2 ] + this.offset.click.left;
16854				}
16855				if ( event.pageY - this.offset.click.top > this.containment[ 3 ] ) {
16856					pageY = this.containment[ 3 ] + this.offset.click.top;
16857				}
16858			}
16859
16860			if ( o.grid ) {
16861				top = this.originalPageY + Math.round( ( pageY - this.originalPageY ) /
16862					o.grid[ 1 ] ) * o.grid[ 1 ];
16863				pageY = this.containment ?
16864					( ( top - this.offset.click.top >= this.containment[ 1 ] &&
16865						top - this.offset.click.top <= this.containment[ 3 ] ) ?
16866							top :
16867							( ( top - this.offset.click.top >= this.containment[ 1 ] ) ?
16868								top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) :
16869								top;
16870
16871				left = this.originalPageX + Math.round( ( pageX - this.originalPageX ) /
16872					o.grid[ 0 ] ) * o.grid[ 0 ];
16873				pageX = this.containment ?
16874					( ( left - this.offset.click.left >= this.containment[ 0 ] &&
16875						left - this.offset.click.left <= this.containment[ 2 ] ) ?
16876							left :
16877							( ( left - this.offset.click.left >= this.containment[ 0 ] ) ?
16878								left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) :
16879								left;
16880			}
16881
16882		}
16883
16884		return {
16885			top: (
16886
16887				// The absolute mouse position
16888				pageY -
16889
16890				// Click offset (relative to the element)
16891				this.offset.click.top -
16892
16893				// Only for relative positioned nodes: Relative offset from element to offset parent
16894				this.offset.relative.top -
16895
16896				// The offsetParent's offset without borders (offset + border)
16897				this.offset.parent.top +
16898				( ( this.cssPosition === "fixed" ?
16899					-this.scrollParent.scrollTop() :
16900					( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) )
16901			),
16902			left: (
16903
16904				// The absolute mouse position
16905				pageX -
16906
16907				// Click offset (relative to the element)
16908				this.offset.click.left -
16909
16910				// Only for relative positioned nodes: Relative offset from element to offset parent
16911				this.offset.relative.left -
16912
16913				// The offsetParent's offset without borders (offset + border)
16914				this.offset.parent.left +
16915				( ( this.cssPosition === "fixed" ?
16916					-this.scrollParent.scrollLeft() :
16917					scrollIsRootNode ? 0 : scroll.scrollLeft() ) )
16918			)
16919		};
16920
16921	},
16922
16923	_rearrange: function( event, i, a, hardRefresh ) {
16924
16925		if ( a ) {
16926			a[ 0 ].appendChild( this.placeholder[ 0 ] );
16927		} else {
16928			i.item[ 0 ].parentNode.insertBefore( this.placeholder[ 0 ],
16929				( this.direction === "down" ? i.item[ 0 ] : i.item[ 0 ].nextSibling ) );
16930		}
16931
16932		//Various things done here to improve the performance:
16933		// 1. we create a setTimeout, that calls refreshPositions
16934		// 2. on the instance, we have a counter variable, that get's higher after every append
16935		// 3. on the local scope, we copy the counter variable, and check in the timeout,
16936		// if it's still the same
16937		// 4. this lets only the last addition to the timeout stack through
16938		this.counter = this.counter ? ++this.counter : 1;
16939		var counter = this.counter;
16940
16941		this._delay( function() {
16942			if ( counter === this.counter ) {
16943
16944				//Precompute after each DOM insertion, NOT on mousemove
16945				this.refreshPositions( !hardRefresh );
16946			}
16947		} );
16948
16949	},
16950
16951	_clear: function( event, noPropagation ) {
16952
16953		this.reverting = false;
16954
16955		// We delay all events that have to be triggered to after the point where the placeholder
16956		// has been removed and everything else normalized again
16957		var i,
16958			delayedTriggers = [];
16959
16960		// We first have to update the dom position of the actual currentItem
16961		// Note: don't do it if the current item is already removed (by a user), or it gets
16962		// reappended (see #4088)
16963		if ( !this._noFinalSort && this.currentItem.parent().length ) {
16964			this.placeholder.before( this.currentItem );
16965		}
16966		this._noFinalSort = null;
16967
16968		if ( this.helper[ 0 ] === this.currentItem[ 0 ] ) {
16969			for ( i in this._storedCSS ) {
16970				if ( this._storedCSS[ i ] === "auto" || this._storedCSS[ i ] === "static" ) {
16971					this._storedCSS[ i ] = "";
16972				}
16973			}
16974			this.currentItem.css( this._storedCSS );
16975			this._removeClass( this.currentItem, "ui-sortable-helper" );
16976		} else {
16977			this.currentItem.show();
16978		}
16979
16980		if ( this.fromOutside && !noPropagation ) {
16981			delayedTriggers.push( function( event ) {
16982				this._trigger( "receive", event, this._uiHash( this.fromOutside ) );
16983			} );
16984		}
16985		if ( ( this.fromOutside ||
16986				this.domPosition.prev !==
16987				this.currentItem.prev().not( ".ui-sortable-helper" )[ 0 ] ||
16988				this.domPosition.parent !== this.currentItem.parent()[ 0 ] ) && !noPropagation ) {
16989
16990			// Trigger update callback if the DOM position has changed
16991			delayedTriggers.push( function( event ) {
16992				this._trigger( "update", event, this._uiHash() );
16993			} );
16994		}
16995
16996		// Check if the items Container has Changed and trigger appropriate
16997		// events.
16998		if ( this !== this.currentContainer ) {
16999			if ( !noPropagation ) {
17000				delayedTriggers.push( function( event ) {
17001					this._trigger( "remove", event, this._uiHash() );
17002				} );
17003				delayedTriggers.push( ( function( c ) {
17004					return function( event ) {
17005						c._trigger( "receive", event, this._uiHash( this ) );
17006					};
17007				} ).call( this, this.currentContainer ) );
17008				delayedTriggers.push( ( function( c ) {
17009					return function( event ) {
17010						c._trigger( "update", event, this._uiHash( this ) );
17011					};
17012				} ).call( this, this.currentContainer ) );
17013			}
17014		}
17015
17016		//Post events to containers
17017		function delayEvent( type, instance, container ) {
17018			return function( event ) {
17019				container._trigger( type, event, instance._uiHash( instance ) );
17020			};
17021		}
17022		for ( i = this.containers.length - 1; i >= 0; i-- ) {
17023			if ( !noPropagation ) {
17024				delayedTriggers.push( delayEvent( "deactivate", this, this.containers[ i ] ) );
17025			}
17026			if ( this.containers[ i ].containerCache.over ) {
17027				delayedTriggers.push( delayEvent( "out", this, this.containers[ i ] ) );
17028				this.containers[ i ].containerCache.over = 0;
17029			}
17030		}
17031
17032		//Do what was originally in plugins
17033		if ( this.storedCursor ) {
17034			this.document.find( "body" ).css( "cursor", this.storedCursor );
17035			this.storedStylesheet.remove();
17036		}
17037		if ( this._storedOpacity ) {
17038			this.helper.css( "opacity", this._storedOpacity );
17039		}
17040		if ( this._storedZIndex ) {
17041			this.helper.css( "zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex );
17042		}
17043
17044		this.dragging = false;
17045
17046		if ( !noPropagation ) {
17047			this._trigger( "beforeStop", event, this._uiHash() );
17048		}
17049
17050		//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately,
17051		// it unbinds ALL events from the original node!
17052		this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] );
17053
17054		if ( !this.cancelHelperRemoval ) {
17055			if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {
17056				this.helper.remove();
17057			}
17058			this.helper = null;
17059		}
17060
17061		if ( !noPropagation ) {
17062			for ( i = 0; i < delayedTriggers.length; i++ ) {
17063
17064				// Trigger all delayed events
17065				delayedTriggers[ i ].call( this, event );
17066			}
17067			this._trigger( "stop", event, this._uiHash() );
17068		}
17069
17070		this.fromOutside = false;
17071		return !this.cancelHelperRemoval;
17072
17073	},
17074
17075	_trigger: function() {
17076		if ( $.Widget.prototype._trigger.apply( this, arguments ) === false ) {
17077			this.cancel();
17078		}
17079	},
17080
17081	_uiHash: function( _inst ) {
17082		var inst = _inst || this;
17083		return {
17084			helper: inst.helper,
17085			placeholder: inst.placeholder || $( [] ),
17086			position: inst.position,
17087			originalPosition: inst.originalPosition,
17088			offset: inst.positionAbs,
17089			item: inst.currentItem,
17090			sender: _inst ? _inst.element : null
17091		};
17092	}
17093
17094} );
17095
17096
17097/*!
17098 * jQuery UI Spinner 1.13.3
17099 * https://jqueryui.com
17100 *
17101 * Copyright OpenJS Foundation and other contributors
17102 * Released under the MIT license.
17103 * https://jquery.org/license
17104 */
17105
17106//>>label: Spinner
17107//>>group: Widgets
17108//>>description: Displays buttons to easily input numbers via the keyboard or mouse.
17109//>>docs: https://api.jqueryui.com/spinner/
17110//>>demos: https://jqueryui.com/spinner/
17111//>>css.structure: ../../themes/base/core.css
17112//>>css.structure: ../../themes/base/spinner.css
17113//>>css.theme: ../../themes/base/theme.css
17114
17115
17116function spinnerModifier( fn ) {
17117	return function() {
17118		var previous = this.element.val();
17119		fn.apply( this, arguments );
17120		this._refresh();
17121		if ( previous !== this.element.val() ) {
17122			this._trigger( "change" );
17123		}
17124	};
17125}
17126
17127$.widget( "ui.spinner", {
17128	version: "1.13.3",
17129	defaultElement: "<input>",
17130	widgetEventPrefix: "spin",
17131	options: {
17132		classes: {
17133			"ui-spinner": "ui-corner-all",
17134			"ui-spinner-down": "ui-corner-br",
17135			"ui-spinner-up": "ui-corner-tr"
17136		},
17137		culture: null,
17138		icons: {
17139			down: "ui-icon-triangle-1-s",
17140			up: "ui-icon-triangle-1-n"
17141		},
17142		incremental: true,
17143		max: null,
17144		min: null,
17145		numberFormat: null,
17146		page: 10,
17147		step: 1,
17148
17149		change: null,
17150		spin: null,
17151		start: null,
17152		stop: null
17153	},
17154
17155	_create: function() {
17156
17157		// handle string values that need to be parsed
17158		this._setOption( "max", this.options.max );
17159		this._setOption( "min", this.options.min );
17160		this._setOption( "step", this.options.step );
17161
17162		// Only format if there is a value, prevents the field from being marked
17163		// as invalid in Firefox, see #9573.
17164		if ( this.value() !== "" ) {
17165
17166			// Format the value, but don't constrain.
17167			this._value( this.element.val(), true );
17168		}
17169
17170		this._draw();
17171		this._on( this._events );
17172		this._refresh();
17173
17174		// Turning off autocomplete prevents the browser from remembering the
17175		// value when navigating through history, so we re-enable autocomplete
17176		// if the page is unloaded before the widget is destroyed. #7790
17177		this._on( this.window, {
17178			beforeunload: function() {
17179				this.element.removeAttr( "autocomplete" );
17180			}
17181		} );
17182	},
17183
17184	_getCreateOptions: function() {
17185		var options = this._super();
17186		var element = this.element;
17187
17188		$.each( [ "min", "max", "step" ], function( i, option ) {
17189			var value = element.attr( option );
17190			if ( value != null && value.length ) {
17191				options[ option ] = value;
17192			}
17193		} );
17194
17195		return options;
17196	},
17197
17198	_events: {
17199		keydown: function( event ) {
17200			if ( this._start( event ) && this._keydown( event ) ) {
17201				event.preventDefault();
17202			}
17203		},
17204		keyup: "_stop",
17205		focus: function() {
17206			this.previous = this.element.val();
17207		},
17208		blur: function( event ) {
17209			if ( this.cancelBlur ) {
17210				delete this.cancelBlur;
17211				return;
17212			}
17213
17214			this._stop();
17215			this._refresh();
17216			if ( this.previous !== this.element.val() ) {
17217				this._trigger( "change", event );
17218			}
17219		},
17220		mousewheel: function( event, delta ) {
17221			var activeElement = $.ui.safeActiveElement( this.document[ 0 ] );
17222			var isActive = this.element[ 0 ] === activeElement;
17223
17224			if ( !isActive || !delta ) {
17225				return;
17226			}
17227
17228			if ( !this.spinning && !this._start( event ) ) {
17229				return false;
17230			}
17231
17232			this._spin( ( delta > 0 ? 1 : -1 ) * this.options.step, event );
17233			clearTimeout( this.mousewheelTimer );
17234			this.mousewheelTimer = this._delay( function() {
17235				if ( this.spinning ) {
17236					this._stop( event );
17237				}
17238			}, 100 );
17239			event.preventDefault();
17240		},
17241		"mousedown .ui-spinner-button": function( event ) {
17242			var previous;
17243
17244			// We never want the buttons to have focus; whenever the user is
17245			// interacting with the spinner, the focus should be on the input.
17246			// If the input is focused then this.previous is properly set from
17247			// when the input first received focus. If the input is not focused
17248			// then we need to set this.previous based on the value before spinning.
17249			previous = this.element[ 0 ] === $.ui.safeActiveElement( this.document[ 0 ] ) ?
17250				this.previous : this.element.val();
17251			function checkFocus() {
17252				var isActive = this.element[ 0 ] === $.ui.safeActiveElement( this.document[ 0 ] );
17253				if ( !isActive ) {
17254					this.element.trigger( "focus" );
17255					this.previous = previous;
17256
17257					// support: IE
17258					// IE sets focus asynchronously, so we need to check if focus
17259					// moved off of the input because the user clicked on the button.
17260					this._delay( function() {
17261						this.previous = previous;
17262					} );
17263				}
17264			}
17265
17266			// Ensure focus is on (or stays on) the text field
17267			event.preventDefault();
17268			checkFocus.call( this );
17269
17270			// Support: IE
17271			// IE doesn't prevent moving focus even with event.preventDefault()
17272			// so we set a flag to know when we should ignore the blur event
17273			// and check (again) if focus moved off of the input.
17274			this.cancelBlur = true;
17275			this._delay( function() {
17276				delete this.cancelBlur;
17277				checkFocus.call( this );
17278			} );
17279
17280			if ( this._start( event ) === false ) {
17281				return;
17282			}
17283
17284			this._repeat( null, $( event.currentTarget )
17285				.hasClass( "ui-spinner-up" ) ? 1 : -1, event );
17286		},
17287		"mouseup .ui-spinner-button": "_stop",
17288		"mouseenter .ui-spinner-button": function( event ) {
17289
17290			// button will add ui-state-active if mouse was down while mouseleave and kept down
17291			if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) {
17292				return;
17293			}
17294
17295			if ( this._start( event ) === false ) {
17296				return false;
17297			}
17298			this._repeat( null, $( event.currentTarget )
17299				.hasClass( "ui-spinner-up" ) ? 1 : -1, event );
17300		},
17301
17302		// TODO: do we really want to consider this a stop?
17303		// shouldn't we just stop the repeater and wait until mouseup before
17304		// we trigger the stop event?
17305		"mouseleave .ui-spinner-button": "_stop"
17306	},
17307
17308	// Support mobile enhanced option and make backcompat more sane
17309	_enhance: function() {
17310		this.uiSpinner = this.element
17311			.attr( "autocomplete", "off" )
17312			.wrap( "<span>" )
17313			.parent()
17314
17315				// Add buttons
17316				.append(
17317					"<a></a><a></a>"
17318				);
17319	},
17320
17321	_draw: function() {
17322		this._enhance();
17323
17324		this._addClass( this.uiSpinner, "ui-spinner", "ui-widget ui-widget-content" );
17325		this._addClass( "ui-spinner-input" );
17326
17327		this.element.attr( "role", "spinbutton" );
17328
17329		// Button bindings
17330		this.buttons = this.uiSpinner.children( "a" )
17331			.attr( "tabIndex", -1 )
17332			.attr( "aria-hidden", true )
17333			.button( {
17334				classes: {
17335					"ui-button": ""
17336				}
17337			} );
17338
17339		// TODO: Right now button does not support classes this is already updated in button PR
17340		this._removeClass( this.buttons, "ui-corner-all" );
17341
17342		this._addClass( this.buttons.first(), "ui-spinner-button ui-spinner-up" );
17343		this._addClass( this.buttons.last(), "ui-spinner-button ui-spinner-down" );
17344		this.buttons.first().button( {
17345			"icon": this.options.icons.up,
17346			"showLabel": false
17347		} );
17348		this.buttons.last().button( {
17349			"icon": this.options.icons.down,
17350			"showLabel": false
17351		} );
17352
17353		// IE 6 doesn't understand height: 50% for the buttons
17354		// unless the wrapper has an explicit height
17355		if ( this.buttons.height() > Math.ceil( this.uiSpinner.height() * 0.5 ) &&
17356				this.uiSpinner.height() > 0 ) {
17357			this.uiSpinner.height( this.uiSpinner.height() );
17358		}
17359	},
17360
17361	_keydown: function( event ) {
17362		var options = this.options,
17363			keyCode = $.ui.keyCode;
17364
17365		switch ( event.keyCode ) {
17366		case keyCode.UP:
17367			this._repeat( null, 1, event );
17368			return true;
17369		case keyCode.DOWN:
17370			this._repeat( null, -1, event );
17371			return true;
17372		case keyCode.PAGE_UP:
17373			this._repeat( null, options.page, event );
17374			return true;
17375		case keyCode.PAGE_DOWN:
17376			this._repeat( null, -options.page, event );
17377			return true;
17378		}
17379
17380		return false;
17381	},
17382
17383	_start: function( event ) {
17384		if ( !this.spinning && this._trigger( "start", event ) === false ) {
17385			return false;
17386		}
17387
17388		if ( !this.counter ) {
17389			this.counter = 1;
17390		}
17391		this.spinning = true;
17392		return true;
17393	},
17394
17395	_repeat: function( i, steps, event ) {
17396		i = i || 500;
17397
17398		clearTimeout( this.timer );
17399		this.timer = this._delay( function() {
17400			this._repeat( 40, steps, event );
17401		}, i );
17402
17403		this._spin( steps * this.options.step, event );
17404	},
17405
17406	_spin: function( step, event ) {
17407		var value = this.value() || 0;
17408
17409		if ( !this.counter ) {
17410			this.counter = 1;
17411		}
17412
17413		value = this._adjustValue( value + step * this._increment( this.counter ) );
17414
17415		if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false ) {
17416			this._value( value );
17417			this.counter++;
17418		}
17419	},
17420
17421	_increment: function( i ) {
17422		var incremental = this.options.incremental;
17423
17424		if ( incremental ) {
17425			return typeof incremental === "function" ?
17426				incremental( i ) :
17427				Math.floor( i * i * i / 50000 - i * i / 500 + 17 * i / 200 + 1 );
17428		}
17429
17430		return 1;
17431	},
17432
17433	_precision: function() {
17434		var precision = this._precisionOf( this.options.step );
17435		if ( this.options.min !== null ) {
17436			precision = Math.max( precision, this._precisionOf( this.options.min ) );
17437		}
17438		return precision;
17439	},
17440
17441	_precisionOf: function( num ) {
17442		var str = num.toString(),
17443			decimal = str.indexOf( "." );
17444		return decimal === -1 ? 0 : str.length - decimal - 1;
17445	},
17446
17447	_adjustValue: function( value ) {
17448		var base, aboveMin,
17449			options = this.options;
17450
17451		// Make sure we're at a valid step
17452		// - find out where we are relative to the base (min or 0)
17453		base = options.min !== null ? options.min : 0;
17454		aboveMin = value - base;
17455
17456		// - round to the nearest step
17457		aboveMin = Math.round( aboveMin / options.step ) * options.step;
17458
17459		// - rounding is based on 0, so adjust back to our base
17460		value = base + aboveMin;
17461
17462		// Fix precision from bad JS floating point math
17463		value = parseFloat( value.toFixed( this._precision() ) );
17464
17465		// Clamp the value
17466		if ( options.max !== null && value > options.max ) {
17467			return options.max;
17468		}
17469		if ( options.min !== null && value < options.min ) {
17470			return options.min;
17471		}
17472
17473		return value;
17474	},
17475
17476	_stop: function( event ) {
17477		if ( !this.spinning ) {
17478			return;
17479		}
17480
17481		clearTimeout( this.timer );
17482		clearTimeout( this.mousewheelTimer );
17483		this.counter = 0;
17484		this.spinning = false;
17485		this._trigger( "stop", event );
17486	},
17487
17488	_setOption: function( key, value ) {
17489		var prevValue, first, last;
17490
17491		if ( key === "culture" || key === "numberFormat" ) {
17492			prevValue = this._parse( this.element.val() );
17493			this.options[ key ] = value;
17494			this.element.val( this._format( prevValue ) );
17495			return;
17496		}
17497
17498		if ( key === "max" || key === "min" || key === "step" ) {
17499			if ( typeof value === "string" ) {
17500				value = this._parse( value );
17501			}
17502		}
17503		if ( key === "icons" ) {
17504			first = this.buttons.first().find( ".ui-icon" );
17505			this._removeClass( first, null, this.options.icons.up );
17506			this._addClass( first, null, value.up );
17507			last = this.buttons.last().find( ".ui-icon" );
17508			this._removeClass( last, null, this.options.icons.down );
17509			this._addClass( last, null, value.down );
17510		}
17511
17512		this._super( key, value );
17513	},
17514
17515	_setOptionDisabled: function( value ) {
17516		this._super( value );
17517
17518		this._toggleClass( this.uiSpinner, null, "ui-state-disabled", !!value );
17519		this.element.prop( "disabled", !!value );
17520		this.buttons.button( value ? "disable" : "enable" );
17521	},
17522
17523	_setOptions: spinnerModifier( function( options ) {
17524		this._super( options );
17525	} ),
17526
17527	_parse: function( val ) {
17528		if ( typeof val === "string" && val !== "" ) {
17529			val = window.Globalize && this.options.numberFormat ?
17530				Globalize.parseFloat( val, 10, this.options.culture ) : +val;
17531		}
17532		return val === "" || isNaN( val ) ? null : val;
17533	},
17534
17535	_format: function( value ) {
17536		if ( value === "" ) {
17537			return "";
17538		}
17539		return window.Globalize && this.options.numberFormat ?
17540			Globalize.format( value, this.options.numberFormat, this.options.culture ) :
17541			value;
17542	},
17543
17544	_refresh: function() {
17545		this.element.attr( {
17546			"aria-valuemin": this.options.min,
17547			"aria-valuemax": this.options.max,
17548
17549			// TODO: what should we do with values that can't be parsed?
17550			"aria-valuenow": this._parse( this.element.val() )
17551		} );
17552	},
17553
17554	isValid: function() {
17555		var value = this.value();
17556
17557		// Null is invalid
17558		if ( value === null ) {
17559			return false;
17560		}
17561
17562		// If value gets adjusted, it's invalid
17563		return value === this._adjustValue( value );
17564	},
17565
17566	// Update the value without triggering change
17567	_value: function( value, allowAny ) {
17568		var parsed;
17569		if ( value !== "" ) {
17570			parsed = this._parse( value );
17571			if ( parsed !== null ) {
17572				if ( !allowAny ) {
17573					parsed = this._adjustValue( parsed );
17574				}
17575				value = this._format( parsed );
17576			}
17577		}
17578		this.element.val( value );
17579		this._refresh();
17580	},
17581
17582	_destroy: function() {
17583		this.element
17584			.prop( "disabled", false )
17585			.removeAttr( "autocomplete role aria-valuemin aria-valuemax aria-valuenow" );
17586
17587		this.uiSpinner.replaceWith( this.element );
17588	},
17589
17590	stepUp: spinnerModifier( function( steps ) {
17591		this._stepUp( steps );
17592	} ),
17593	_stepUp: function( steps ) {
17594		if ( this._start() ) {
17595			this._spin( ( steps || 1 ) * this.options.step );
17596			this._stop();
17597		}
17598	},
17599
17600	stepDown: spinnerModifier( function( steps ) {
17601		this._stepDown( steps );
17602	} ),
17603	_stepDown: function( steps ) {
17604		if ( this._start() ) {
17605			this._spin( ( steps || 1 ) * -this.options.step );
17606			this._stop();
17607		}
17608	},
17609
17610	pageUp: spinnerModifier( function( pages ) {
17611		this._stepUp( ( pages || 1 ) * this.options.page );
17612	} ),
17613
17614	pageDown: spinnerModifier( function( pages ) {
17615		this._stepDown( ( pages || 1 ) * this.options.page );
17616	} ),
17617
17618	value: function( newVal ) {
17619		if ( !arguments.length ) {
17620			return this._parse( this.element.val() );
17621		}
17622		spinnerModifier( this._value ).call( this, newVal );
17623	},
17624
17625	widget: function() {
17626		return this.uiSpinner;
17627	}
17628} );
17629
17630// DEPRECATED
17631// TODO: switch return back to widget declaration at top of file when this is removed
17632if ( $.uiBackCompat !== false ) {
17633
17634	// Backcompat for spinner html extension points
17635	$.widget( "ui.spinner", $.ui.spinner, {
17636		_enhance: function() {
17637			this.uiSpinner = this.element
17638				.attr( "autocomplete", "off" )
17639				.wrap( this._uiSpinnerHtml() )
17640				.parent()
17641
17642					// Add buttons
17643					.append( this._buttonHtml() );
17644		},
17645		_uiSpinnerHtml: function() {
17646			return "<span>";
17647		},
17648
17649		_buttonHtml: function() {
17650			return "<a></a><a></a>";
17651		}
17652	} );
17653}
17654
17655var widgetsSpinner = $.ui.spinner;
17656
17657
17658/*!
17659 * jQuery UI Tabs 1.13.3
17660 * https://jqueryui.com
17661 *
17662 * Copyright OpenJS Foundation and other contributors
17663 * Released under the MIT license.
17664 * https://jquery.org/license
17665 */
17666
17667//>>label: Tabs
17668//>>group: Widgets
17669//>>description: Transforms a set of container elements into a tab structure.
17670//>>docs: https://api.jqueryui.com/tabs/
17671//>>demos: https://jqueryui.com/tabs/
17672//>>css.structure: ../../themes/base/core.css
17673//>>css.structure: ../../themes/base/tabs.css
17674//>>css.theme: ../../themes/base/theme.css
17675
17676
17677$.widget( "ui.tabs", {
17678	version: "1.13.3",
17679	delay: 300,
17680	options: {
17681		active: null,
17682		classes: {
17683			"ui-tabs": "ui-corner-all",
17684			"ui-tabs-nav": "ui-corner-all",
17685			"ui-tabs-panel": "ui-corner-bottom",
17686			"ui-tabs-tab": "ui-corner-top"
17687		},
17688		collapsible: false,
17689		event: "click",
17690		heightStyle: "content",
17691		hide: null,
17692		show: null,
17693
17694		// Callbacks
17695		activate: null,
17696		beforeActivate: null,
17697		beforeLoad: null,
17698		load: null
17699	},
17700
17701	_isLocal: ( function() {
17702		var rhash = /#.*$/;
17703
17704		return function( anchor ) {
17705			var anchorUrl, locationUrl;
17706
17707			anchorUrl = anchor.href.replace( rhash, "" );
17708			locationUrl = location.href.replace( rhash, "" );
17709
17710			// Decoding may throw an error if the URL isn't UTF-8 (#9518)
17711			try {
17712				anchorUrl = decodeURIComponent( anchorUrl );
17713			} catch ( error ) {}
17714			try {
17715				locationUrl = decodeURIComponent( locationUrl );
17716			} catch ( error ) {}
17717
17718			return anchor.hash.length > 1 && anchorUrl === locationUrl;
17719		};
17720	} )(),
17721
17722	_create: function() {
17723		var that = this,
17724			options = this.options;
17725
17726		this.running = false;
17727
17728		this._addClass( "ui-tabs", "ui-widget ui-widget-content" );
17729		this._toggleClass( "ui-tabs-collapsible", null, options.collapsible );
17730
17731		this._processTabs();
17732		options.active = this._initialActive();
17733
17734		// Take disabling tabs via class attribute from HTML
17735		// into account and update option properly.
17736		if ( Array.isArray( options.disabled ) ) {
17737			options.disabled = $.uniqueSort( options.disabled.concat(
17738				$.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) {
17739					return that.tabs.index( li );
17740				} )
17741			) ).sort();
17742		}
17743
17744		// Check for length avoids error when initializing empty list
17745		if ( this.options.active !== false && this.anchors.length ) {
17746			this.active = this._findActive( options.active );
17747		} else {
17748			this.active = $();
17749		}
17750
17751		this._refresh();
17752
17753		if ( this.active.length ) {
17754			this.load( options.active );
17755		}
17756	},
17757
17758	_initialActive: function() {
17759		var active = this.options.active,
17760			collapsible = this.options.collapsible,
17761			locationHash = location.hash.substring( 1 );
17762
17763		if ( active === null ) {
17764
17765			// check the fragment identifier in the URL
17766			if ( locationHash ) {
17767				this.tabs.each( function( i, tab ) {
17768					if ( $( tab ).attr( "aria-controls" ) === locationHash ) {
17769						active = i;
17770						return false;
17771					}
17772				} );
17773			}
17774
17775			// Check for a tab marked active via a class
17776			if ( active === null ) {
17777				active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) );
17778			}
17779
17780			// No active tab, set to false
17781			if ( active === null || active === -1 ) {
17782				active = this.tabs.length ? 0 : false;
17783			}
17784		}
17785
17786		// Handle numbers: negative, out of range
17787		if ( active !== false ) {
17788			active = this.tabs.index( this.tabs.eq( active ) );
17789			if ( active === -1 ) {
17790				active = collapsible ? false : 0;
17791			}
17792		}
17793
17794		// Don't allow collapsible: false and active: false
17795		if ( !collapsible && active === false && this.anchors.length ) {
17796			active = 0;
17797		}
17798
17799		return active;
17800	},
17801
17802	_getCreateEventData: function() {
17803		return {
17804			tab: this.active,
17805			panel: !this.active.length ? $() : this._getPanelForTab( this.active )
17806		};
17807	},
17808
17809	_tabKeydown: function( event ) {
17810		var focusedTab = $( $.ui.safeActiveElement( this.document[ 0 ] ) ).closest( "li" ),
17811			selectedIndex = this.tabs.index( focusedTab ),
17812			goingForward = true;
17813
17814		if ( this._handlePageNav( event ) ) {
17815			return;
17816		}
17817
17818		switch ( event.keyCode ) {
17819		case $.ui.keyCode.RIGHT:
17820		case $.ui.keyCode.DOWN:
17821			selectedIndex++;
17822			break;
17823		case $.ui.keyCode.UP:
17824		case $.ui.keyCode.LEFT:
17825			goingForward = false;
17826			selectedIndex--;
17827			break;
17828		case $.ui.keyCode.END:
17829			selectedIndex = this.anchors.length - 1;
17830			break;
17831		case $.ui.keyCode.HOME:
17832			selectedIndex = 0;
17833			break;
17834		case $.ui.keyCode.SPACE:
17835
17836			// Activate only, no collapsing
17837			event.preventDefault();
17838			clearTimeout( this.activating );
17839			this._activate( selectedIndex );
17840			return;
17841		case $.ui.keyCode.ENTER:
17842
17843			// Toggle (cancel delayed activation, allow collapsing)
17844			event.preventDefault();
17845			clearTimeout( this.activating );
17846
17847			// Determine if we should collapse or activate
17848			this._activate( selectedIndex === this.options.active ? false : selectedIndex );
17849			return;
17850		default:
17851			return;
17852		}
17853
17854		// Focus the appropriate tab, based on which key was pressed
17855		event.preventDefault();
17856		clearTimeout( this.activating );
17857		selectedIndex = this._focusNextTab( selectedIndex, goingForward );
17858
17859		// Navigating with control/command key will prevent automatic activation
17860		if ( !event.ctrlKey && !event.metaKey ) {
17861
17862			// Update aria-selected immediately so that AT think the tab is already selected.
17863			// Otherwise AT may confuse the user by stating that they need to activate the tab,
17864			// but the tab will already be activated by the time the announcement finishes.
17865			focusedTab.attr( "aria-selected", "false" );
17866			this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" );
17867
17868			this.activating = this._delay( function() {
17869				this.option( "active", selectedIndex );
17870			}, this.delay );
17871		}
17872	},
17873
17874	_panelKeydown: function( event ) {
17875		if ( this._handlePageNav( event ) ) {
17876			return;
17877		}
17878
17879		// Ctrl+up moves focus to the current tab
17880		if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {
17881			event.preventDefault();
17882			this.active.trigger( "focus" );
17883		}
17884	},
17885
17886	// Alt+page up/down moves focus to the previous/next tab (and activates)
17887	_handlePageNav: function( event ) {
17888		if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {
17889			this._activate( this._focusNextTab( this.options.active - 1, false ) );
17890			return true;
17891		}
17892		if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {
17893			this._activate( this._focusNextTab( this.options.active + 1, true ) );
17894			return true;
17895		}
17896	},
17897
17898	_findNextTab: function( index, goingForward ) {
17899		var lastTabIndex = this.tabs.length - 1;
17900
17901		function constrain() {
17902			if ( index > lastTabIndex ) {
17903				index = 0;
17904			}
17905			if ( index < 0 ) {
17906				index = lastTabIndex;
17907			}
17908			return index;
17909		}
17910
17911		while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {
17912			index = goingForward ? index + 1 : index - 1;
17913		}
17914
17915		return index;
17916	},
17917
17918	_focusNextTab: function( index, goingForward ) {
17919		index = this._findNextTab( index, goingForward );
17920		this.tabs.eq( index ).trigger( "focus" );
17921		return index;
17922	},
17923
17924	_setOption: function( key, value ) {
17925		if ( key === "active" ) {
17926
17927			// _activate() will handle invalid values and update this.options
17928			this._activate( value );
17929			return;
17930		}
17931
17932		this._super( key, value );
17933
17934		if ( key === "collapsible" ) {
17935			this._toggleClass( "ui-tabs-collapsible", null, value );
17936
17937			// Setting collapsible: false while collapsed; open first panel
17938			if ( !value && this.options.active === false ) {
17939				this._activate( 0 );
17940			}
17941		}
17942
17943		if ( key === "event" ) {
17944			this._setupEvents( value );
17945		}
17946
17947		if ( key === "heightStyle" ) {
17948			this._setupHeightStyle( value );
17949		}
17950	},
17951
17952	_sanitizeSelector: function( hash ) {
17953		return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : "";
17954	},
17955
17956	refresh: function() {
17957		var options = this.options,
17958			lis = this.tablist.children( ":has(a[href])" );
17959
17960		// Get disabled tabs from class attribute from HTML
17961		// this will get converted to a boolean if needed in _refresh()
17962		options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) {
17963			return lis.index( tab );
17964		} );
17965
17966		this._processTabs();
17967
17968		// Was collapsed or no tabs
17969		if ( options.active === false || !this.anchors.length ) {
17970			options.active = false;
17971			this.active = $();
17972
17973		// was active, but active tab is gone
17974		} else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {
17975
17976			// all remaining tabs are disabled
17977			if ( this.tabs.length === options.disabled.length ) {
17978				options.active = false;
17979				this.active = $();
17980
17981			// activate previous tab
17982			} else {
17983				this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );
17984			}
17985
17986		// was active, active tab still exists
17987		} else {
17988
17989			// make sure active index is correct
17990			options.active = this.tabs.index( this.active );
17991		}
17992
17993		this._refresh();
17994	},
17995
17996	_refresh: function() {
17997		this._setOptionDisabled( this.options.disabled );
17998		this._setupEvents( this.options.event );
17999		this._setupHeightStyle( this.options.heightStyle );
18000
18001		this.tabs.not( this.active ).attr( {
18002			"aria-selected": "false",
18003			"aria-expanded": "false",
18004			tabIndex: -1
18005		} );
18006		this.panels.not( this._getPanelForTab( this.active ) )
18007			.hide()
18008			.attr( {
18009				"aria-hidden": "true"
18010			} );
18011
18012		// Make sure one tab is in the tab order
18013		if ( !this.active.length ) {
18014			this.tabs.eq( 0 ).attr( "tabIndex", 0 );
18015		} else {
18016			this.active
18017				.attr( {
18018					"aria-selected": "true",
18019					"aria-expanded": "true",
18020					tabIndex: 0
18021				} );
18022			this._addClass( this.active, "ui-tabs-active", "ui-state-active" );
18023			this._getPanelForTab( this.active )
18024				.show()
18025				.attr( {
18026					"aria-hidden": "false"
18027				} );
18028		}
18029	},
18030
18031	_processTabs: function() {
18032		var that = this,
18033			prevTabs = this.tabs,
18034			prevAnchors = this.anchors,
18035			prevPanels = this.panels;
18036
18037		this.tablist = this._getList().attr( "role", "tablist" );
18038		this._addClass( this.tablist, "ui-tabs-nav",
18039			"ui-helper-reset ui-helper-clearfix ui-widget-header" );
18040
18041		// Prevent users from focusing disabled tabs via click
18042		this.tablist
18043			.on( "mousedown" + this.eventNamespace, "> li", function( event ) {
18044				if ( $( this ).is( ".ui-state-disabled" ) ) {
18045					event.preventDefault();
18046				}
18047			} )
18048
18049			// Support: IE <9
18050			// Preventing the default action in mousedown doesn't prevent IE
18051			// from focusing the element, so if the anchor gets focused, blur.
18052			// We don't have to worry about focusing the previously focused
18053			// element since clicking on a non-focusable element should focus
18054			// the body anyway.
18055			.on( "focus" + this.eventNamespace, ".ui-tabs-anchor", function() {
18056				if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) {
18057					this.blur();
18058				}
18059			} );
18060
18061		this.tabs = this.tablist.find( "> li:has(a[href])" )
18062			.attr( {
18063				role: "tab",
18064				tabIndex: -1
18065			} );
18066		this._addClass( this.tabs, "ui-tabs-tab", "ui-state-default" );
18067
18068		this.anchors = this.tabs.map( function() {
18069			return $( "a", this )[ 0 ];
18070		} )
18071			.attr( {
18072				tabIndex: -1
18073			} );
18074		this._addClass( this.anchors, "ui-tabs-anchor" );
18075
18076		this.panels = $();
18077
18078		this.anchors.each( function( i, anchor ) {
18079			var selector, panel, panelId,
18080				anchorId = $( anchor ).uniqueId().attr( "id" ),
18081				tab = $( anchor ).closest( "li" ),
18082				originalAriaControls = tab.attr( "aria-controls" );
18083
18084			// Inline tab
18085			if ( that._isLocal( anchor ) ) {
18086				selector = anchor.hash;
18087				panelId = selector.substring( 1 );
18088				panel = that.element.find( that._sanitizeSelector( selector ) );
18089
18090			// remote tab
18091			} else {
18092
18093				// If the tab doesn't already have aria-controls,
18094				// generate an id by using a throw-away element
18095				panelId = tab.attr( "aria-controls" ) || $( {} ).uniqueId()[ 0 ].id;
18096				selector = "#" + panelId;
18097				panel = that.element.find( selector );
18098				if ( !panel.length ) {
18099					panel = that._createPanel( panelId );
18100					panel.insertAfter( that.panels[ i - 1 ] || that.tablist );
18101				}
18102				panel.attr( "aria-live", "polite" );
18103			}
18104
18105			if ( panel.length ) {
18106				that.panels = that.panels.add( panel );
18107			}
18108			if ( originalAriaControls ) {
18109				tab.data( "ui-tabs-aria-controls", originalAriaControls );
18110			}
18111			tab.attr( {
18112				"aria-controls": panelId,
18113				"aria-labelledby": anchorId
18114			} );
18115			panel.attr( "aria-labelledby", anchorId );
18116		} );
18117
18118		this.panels.attr( "role", "tabpanel" );
18119		this._addClass( this.panels, "ui-tabs-panel", "ui-widget-content" );
18120
18121		// Avoid memory leaks (#10056)
18122		if ( prevTabs ) {
18123			this._off( prevTabs.not( this.tabs ) );
18124			this._off( prevAnchors.not( this.anchors ) );
18125			this._off( prevPanels.not( this.panels ) );
18126		}
18127	},
18128
18129	// Allow overriding how to find the list for rare usage scenarios (#7715)
18130	_getList: function() {
18131		return this.tablist || this.element.find( "ol, ul" ).eq( 0 );
18132	},
18133
18134	_createPanel: function( id ) {
18135		return $( "<div>" )
18136			.attr( "id", id )
18137			.data( "ui-tabs-destroy", true );
18138	},
18139
18140	_setOptionDisabled: function( disabled ) {
18141		var currentItem, li, i;
18142
18143		if ( Array.isArray( disabled ) ) {
18144			if ( !disabled.length ) {
18145				disabled = false;
18146			} else if ( disabled.length === this.anchors.length ) {
18147				disabled = true;
18148			}
18149		}
18150
18151		// Disable tabs
18152		for ( i = 0; ( li = this.tabs[ i ] ); i++ ) {
18153			currentItem = $( li );
18154			if ( disabled === true || $.inArray( i, disabled ) !== -1 ) {
18155				currentItem.attr( "aria-disabled", "true" );
18156				this._addClass( currentItem, null, "ui-state-disabled" );
18157			} else {
18158				currentItem.removeAttr( "aria-disabled" );
18159				this._removeClass( currentItem, null, "ui-state-disabled" );
18160			}
18161		}
18162
18163		this.options.disabled = disabled;
18164
18165		this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null,
18166			disabled === true );
18167	},
18168
18169	_setupEvents: function( event ) {
18170		var events = {};
18171		if ( event ) {
18172			$.each( event.split( " " ), function( index, eventName ) {
18173				events[ eventName ] = "_eventHandler";
18174			} );
18175		}
18176
18177		this._off( this.anchors.add( this.tabs ).add( this.panels ) );
18178
18179		// Always prevent the default action, even when disabled
18180		this._on( true, this.anchors, {
18181			click: function( event ) {
18182				event.preventDefault();
18183			}
18184		} );
18185		this._on( this.anchors, events );
18186		this._on( this.tabs, { keydown: "_tabKeydown" } );
18187		this._on( this.panels, { keydown: "_panelKeydown" } );
18188
18189		this._focusable( this.tabs );
18190		this._hoverable( this.tabs );
18191	},
18192
18193	_setupHeightStyle: function( heightStyle ) {
18194		var maxHeight,
18195			parent = this.element.parent();
18196
18197		if ( heightStyle === "fill" ) {
18198			maxHeight = parent.height();
18199			maxHeight -= this.element.outerHeight() - this.element.height();
18200
18201			this.element.siblings( ":visible" ).each( function() {
18202				var elem = $( this ),
18203					position = elem.css( "position" );
18204
18205				if ( position === "absolute" || position === "fixed" ) {
18206					return;
18207				}
18208				maxHeight -= elem.outerHeight( true );
18209			} );
18210
18211			this.element.children().not( this.panels ).each( function() {
18212				maxHeight -= $( this ).outerHeight( true );
18213			} );
18214
18215			this.panels.each( function() {
18216				$( this ).height( Math.max( 0, maxHeight -
18217					$( this ).innerHeight() + $( this ).height() ) );
18218			} )
18219				.css( "overflow", "auto" );
18220		} else if ( heightStyle === "auto" ) {
18221			maxHeight = 0;
18222			this.panels.each( function() {
18223				maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
18224			} ).height( maxHeight );
18225		}
18226	},
18227
18228	_eventHandler: function( event ) {
18229		var options = this.options,
18230			active = this.active,
18231			anchor = $( event.currentTarget ),
18232			tab = anchor.closest( "li" ),
18233			clickedIsActive = tab[ 0 ] === active[ 0 ],
18234			collapsing = clickedIsActive && options.collapsible,
18235			toShow = collapsing ? $() : this._getPanelForTab( tab ),
18236			toHide = !active.length ? $() : this._getPanelForTab( active ),
18237			eventData = {
18238				oldTab: active,
18239				oldPanel: toHide,
18240				newTab: collapsing ? $() : tab,
18241				newPanel: toShow
18242			};
18243
18244		event.preventDefault();
18245
18246		if ( tab.hasClass( "ui-state-disabled" ) ||
18247
18248				// tab is already loading
18249				tab.hasClass( "ui-tabs-loading" ) ||
18250
18251				// can't switch durning an animation
18252				this.running ||
18253
18254				// click on active header, but not collapsible
18255				( clickedIsActive && !options.collapsible ) ||
18256
18257				// allow canceling activation
18258				( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
18259			return;
18260		}
18261
18262		options.active = collapsing ? false : this.tabs.index( tab );
18263
18264		this.active = clickedIsActive ? $() : tab;
18265		if ( this.xhr ) {
18266			this.xhr.abort();
18267		}
18268
18269		if ( !toHide.length && !toShow.length ) {
18270			$.error( "jQuery UI Tabs: Mismatching fragment identifier." );
18271		}
18272
18273		if ( toShow.length ) {
18274			this.load( this.tabs.index( tab ), event );
18275		}
18276		this._toggle( event, eventData );
18277	},
18278
18279	// Handles show/hide for selecting tabs
18280	_toggle: function( event, eventData ) {
18281		var that = this,
18282			toShow = eventData.newPanel,
18283			toHide = eventData.oldPanel;
18284
18285		this.running = true;
18286
18287		function complete() {
18288			that.running = false;
18289			that._trigger( "activate", event, eventData );
18290		}
18291
18292		function show() {
18293			that._addClass( eventData.newTab.closest( "li" ), "ui-tabs-active", "ui-state-active" );
18294
18295			if ( toShow.length && that.options.show ) {
18296				that._show( toShow, that.options.show, complete );
18297			} else {
18298				toShow.show();
18299				complete();
18300			}
18301		}
18302
18303		// Start out by hiding, then showing, then completing
18304		if ( toHide.length && this.options.hide ) {
18305			this._hide( toHide, this.options.hide, function() {
18306				that._removeClass( eventData.oldTab.closest( "li" ),
18307					"ui-tabs-active", "ui-state-active" );
18308				show();
18309			} );
18310		} else {
18311			this._removeClass( eventData.oldTab.closest( "li" ),
18312				"ui-tabs-active", "ui-state-active" );
18313			toHide.hide();
18314			show();
18315		}
18316
18317		toHide.attr( "aria-hidden", "true" );
18318		eventData.oldTab.attr( {
18319			"aria-selected": "false",
18320			"aria-expanded": "false"
18321		} );
18322
18323		// If we're switching tabs, remove the old tab from the tab order.
18324		// If we're opening from collapsed state, remove the previous tab from the tab order.
18325		// If we're collapsing, then keep the collapsing tab in the tab order.
18326		if ( toShow.length && toHide.length ) {
18327			eventData.oldTab.attr( "tabIndex", -1 );
18328		} else if ( toShow.length ) {
18329			this.tabs.filter( function() {
18330				return $( this ).attr( "tabIndex" ) === 0;
18331			} )
18332				.attr( "tabIndex", -1 );
18333		}
18334
18335		toShow.attr( "aria-hidden", "false" );
18336		eventData.newTab.attr( {
18337			"aria-selected": "true",
18338			"aria-expanded": "true",
18339			tabIndex: 0
18340		} );
18341	},
18342
18343	_activate: function( index ) {
18344		var anchor,
18345			active = this._findActive( index );
18346
18347		// Trying to activate the already active panel
18348		if ( active[ 0 ] === this.active[ 0 ] ) {
18349			return;
18350		}
18351
18352		// Trying to collapse, simulate a click on the current active header
18353		if ( !active.length ) {
18354			active = this.active;
18355		}
18356
18357		anchor = active.find( ".ui-tabs-anchor" )[ 0 ];
18358		this._eventHandler( {
18359			target: anchor,
18360			currentTarget: anchor,
18361			preventDefault: $.noop
18362		} );
18363	},
18364
18365	_findActive: function( index ) {
18366		return index === false ? $() : this.tabs.eq( index );
18367	},
18368
18369	_getIndex: function( index ) {
18370
18371		// meta-function to give users option to provide a href string instead of a numerical index.
18372		if ( typeof index === "string" ) {
18373			index = this.anchors.index( this.anchors.filter( "[href$='" +
18374				$.escapeSelector( index ) + "']" ) );
18375		}
18376
18377		return index;
18378	},
18379
18380	_destroy: function() {
18381		if ( this.xhr ) {
18382			this.xhr.abort();
18383		}
18384
18385		this.tablist
18386			.removeAttr( "role" )
18387			.off( this.eventNamespace );
18388
18389		this.anchors
18390			.removeAttr( "role tabIndex" )
18391			.removeUniqueId();
18392
18393		this.tabs.add( this.panels ).each( function() {
18394			if ( $.data( this, "ui-tabs-destroy" ) ) {
18395				$( this ).remove();
18396			} else {
18397				$( this ).removeAttr( "role tabIndex " +
18398					"aria-live aria-busy aria-selected aria-labelledby aria-hidden aria-expanded" );
18399			}
18400		} );
18401
18402		this.tabs.each( function() {
18403			var li = $( this ),
18404				prev = li.data( "ui-tabs-aria-controls" );
18405			if ( prev ) {
18406				li
18407					.attr( "aria-controls", prev )
18408					.removeData( "ui-tabs-aria-controls" );
18409			} else {
18410				li.removeAttr( "aria-controls" );
18411			}
18412		} );
18413
18414		this.panels.show();
18415
18416		if ( this.options.heightStyle !== "content" ) {
18417			this.panels.css( "height", "" );
18418		}
18419	},
18420
18421	enable: function( index ) {
18422		var disabled = this.options.disabled;
18423		if ( disabled === false ) {
18424			return;
18425		}
18426
18427		if ( index === undefined ) {
18428			disabled = false;
18429		} else {
18430			index = this._getIndex( index );
18431			if ( Array.isArray( disabled ) ) {
18432				disabled = $.map( disabled, function( num ) {
18433					return num !== index ? num : null;
18434				} );
18435			} else {
18436				disabled = $.map( this.tabs, function( li, num ) {
18437					return num !== index ? num : null;
18438				} );
18439			}
18440		}
18441		this._setOptionDisabled( disabled );
18442	},
18443
18444	disable: function( index ) {
18445		var disabled = this.options.disabled;
18446		if ( disabled === true ) {
18447			return;
18448		}
18449
18450		if ( index === undefined ) {
18451			disabled = true;
18452		} else {
18453			index = this._getIndex( index );
18454			if ( $.inArray( index, disabled ) !== -1 ) {
18455				return;
18456			}
18457			if ( Array.isArray( disabled ) ) {
18458				disabled = $.merge( [ index ], disabled ).sort();
18459			} else {
18460				disabled = [ index ];
18461			}
18462		}
18463		this._setOptionDisabled( disabled );
18464	},
18465
18466	load: function( index, event ) {
18467		index = this._getIndex( index );
18468		var that = this,
18469			tab = this.tabs.eq( index ),
18470			anchor = tab.find( ".ui-tabs-anchor" ),
18471			panel = this._getPanelForTab( tab ),
18472			eventData = {
18473				tab: tab,
18474				panel: panel
18475			},
18476			complete = function( jqXHR, status ) {
18477				if ( status === "abort" ) {
18478					that.panels.stop( false, true );
18479				}
18480
18481				that._removeClass( tab, "ui-tabs-loading" );
18482				panel.removeAttr( "aria-busy" );
18483
18484				if ( jqXHR === that.xhr ) {
18485					delete that.xhr;
18486				}
18487			};
18488
18489		// Not remote
18490		if ( this._isLocal( anchor[ 0 ] ) ) {
18491			return;
18492		}
18493
18494		this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );
18495
18496		// Support: jQuery <1.8
18497		// jQuery <1.8 returns false if the request is canceled in beforeSend,
18498		// but as of 1.8, $.ajax() always returns a jqXHR object.
18499		if ( this.xhr && this.xhr.statusText !== "canceled" ) {
18500			this._addClass( tab, "ui-tabs-loading" );
18501			panel.attr( "aria-busy", "true" );
18502
18503			this.xhr
18504				.done( function( response, status, jqXHR ) {
18505
18506					// support: jQuery <1.8
18507					// https://bugs.jquery.com/ticket/11778
18508					setTimeout( function() {
18509						panel.html( response );
18510						that._trigger( "load", event, eventData );
18511
18512						complete( jqXHR, status );
18513					}, 1 );
18514				} )
18515				.fail( function( jqXHR, status ) {
18516
18517					// support: jQuery <1.8
18518					// https://bugs.jquery.com/ticket/11778
18519					setTimeout( function() {
18520						complete( jqXHR, status );
18521					}, 1 );
18522				} );
18523		}
18524	},
18525
18526	_ajaxSettings: function( anchor, event, eventData ) {
18527		var that = this;
18528		return {
18529
18530			// Support: IE <11 only
18531			// Strip any hash that exists to prevent errors with the Ajax request
18532			url: anchor.attr( "href" ).replace( /#.*$/, "" ),
18533			beforeSend: function( jqXHR, settings ) {
18534				return that._trigger( "beforeLoad", event,
18535					$.extend( { jqXHR: jqXHR, ajaxSettings: settings }, eventData ) );
18536			}
18537		};
18538	},
18539
18540	_getPanelForTab: function( tab ) {
18541		var id = $( tab ).attr( "aria-controls" );
18542		return this.element.find( this._sanitizeSelector( "#" + id ) );
18543	}
18544} );
18545
18546// DEPRECATED
18547// TODO: Switch return back to widget declaration at top of file when this is removed
18548if ( $.uiBackCompat !== false ) {
18549
18550	// Backcompat for ui-tab class (now ui-tabs-tab)
18551	$.widget( "ui.tabs", $.ui.tabs, {
18552		_processTabs: function() {
18553			this._superApply( arguments );
18554			this._addClass( this.tabs, "ui-tab" );
18555		}
18556	} );
18557}
18558
18559var widgetsTabs = $.ui.tabs;
18560
18561
18562/*!
18563 * jQuery UI Tooltip 1.13.3
18564 * https://jqueryui.com
18565 *
18566 * Copyright OpenJS Foundation and other contributors
18567 * Released under the MIT license.
18568 * https://jquery.org/license
18569 */
18570
18571//>>label: Tooltip
18572//>>group: Widgets
18573//>>description: Shows additional information for any element on hover or focus.
18574//>>docs: https://api.jqueryui.com/tooltip/
18575//>>demos: https://jqueryui.com/tooltip/
18576//>>css.structure: ../../themes/base/core.css
18577//>>css.structure: ../../themes/base/tooltip.css
18578//>>css.theme: ../../themes/base/theme.css
18579
18580
18581$.widget( "ui.tooltip", {
18582	version: "1.13.3",
18583	options: {
18584		classes: {
18585			"ui-tooltip": "ui-corner-all ui-widget-shadow"
18586		},
18587		content: function() {
18588			var title = $( this ).attr( "title" );
18589
18590			// Escape title, since we're going from an attribute to raw HTML
18591			return $( "<a>" ).text( title ).html();
18592		},
18593		hide: true,
18594
18595		// Disabled elements have inconsistent behavior across browsers (#8661)
18596		items: "[title]:not([disabled])",
18597		position: {
18598			my: "left top+15",
18599			at: "left bottom",
18600			collision: "flipfit flip"
18601		},
18602		show: true,
18603		track: false,
18604
18605		// Callbacks
18606		close: null,
18607		open: null
18608	},
18609
18610	_addDescribedBy: function( elem, id ) {
18611		var describedby = ( elem.attr( "aria-describedby" ) || "" ).split( /\s+/ );
18612		describedby.push( id );
18613		elem
18614			.data( "ui-tooltip-id", id )
18615			.attr( "aria-describedby", String.prototype.trim.call( describedby.join( " " ) ) );
18616	},
18617
18618	_removeDescribedBy: function( elem ) {
18619		var id = elem.data( "ui-tooltip-id" ),
18620			describedby = ( elem.attr( "aria-describedby" ) || "" ).split( /\s+/ ),
18621			index = $.inArray( id, describedby );
18622
18623		if ( index !== -1 ) {
18624			describedby.splice( index, 1 );
18625		}
18626
18627		elem.removeData( "ui-tooltip-id" );
18628		describedby = String.prototype.trim.call( describedby.join( " " ) );
18629		if ( describedby ) {
18630			elem.attr( "aria-describedby", describedby );
18631		} else {
18632			elem.removeAttr( "aria-describedby" );
18633		}
18634	},
18635
18636	_create: function() {
18637		this._on( {
18638			mouseover: "open",
18639			focusin: "open"
18640		} );
18641
18642		// IDs of generated tooltips, needed for destroy
18643		this.tooltips = {};
18644
18645		// IDs of parent tooltips where we removed the title attribute
18646		this.parents = {};
18647
18648		// Append the aria-live region so tooltips announce correctly
18649		this.liveRegion = $( "<div>" )
18650			.attr( {
18651				role: "log",
18652				"aria-live": "assertive",
18653				"aria-relevant": "additions"
18654			} )
18655			.appendTo( this.document[ 0 ].body );
18656		this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" );
18657
18658		this.disabledTitles = $( [] );
18659	},
18660
18661	_setOption: function( key, value ) {
18662		var that = this;
18663
18664		this._super( key, value );
18665
18666		if ( key === "content" ) {
18667			$.each( this.tooltips, function( id, tooltipData ) {
18668				that._updateContent( tooltipData.element );
18669			} );
18670		}
18671	},
18672
18673	_setOptionDisabled: function( value ) {
18674		this[ value ? "_disable" : "_enable" ]();
18675	},
18676
18677	_disable: function() {
18678		var that = this;
18679
18680		// Close open tooltips
18681		$.each( this.tooltips, function( id, tooltipData ) {
18682			var event = $.Event( "blur" );
18683			event.target = event.currentTarget = tooltipData.element[ 0 ];
18684			that.close( event, true );
18685		} );
18686
18687		// Remove title attributes to prevent native tooltips
18688		this.disabledTitles = this.disabledTitles.add(
18689			this.element.find( this.options.items ).addBack()
18690				.filter( function() {
18691					var element = $( this );
18692					if ( element.is( "[title]" ) ) {
18693						return element
18694							.data( "ui-tooltip-title", element.attr( "title" ) )
18695							.removeAttr( "title" );
18696					}
18697				} )
18698		);
18699	},
18700
18701	_enable: function() {
18702
18703		// restore title attributes
18704		this.disabledTitles.each( function() {
18705			var element = $( this );
18706			if ( element.data( "ui-tooltip-title" ) ) {
18707				element.attr( "title", element.data( "ui-tooltip-title" ) );
18708			}
18709		} );
18710		this.disabledTitles = $( [] );
18711	},
18712
18713	open: function( event ) {
18714		var that = this,
18715			target = $( event ? event.target : this.element )
18716
18717				// we need closest here due to mouseover bubbling,
18718				// but always pointing at the same event target
18719				.closest( this.options.items );
18720
18721		// No element to show a tooltip for or the tooltip is already open
18722		if ( !target.length || target.data( "ui-tooltip-id" ) ) {
18723			return;
18724		}
18725
18726		if ( target.attr( "title" ) ) {
18727			target.data( "ui-tooltip-title", target.attr( "title" ) );
18728		}
18729
18730		target.data( "ui-tooltip-open", true );
18731
18732		// Kill parent tooltips, custom or native, for hover
18733		if ( event && event.type === "mouseover" ) {
18734			target.parents().each( function() {
18735				var parent = $( this ),
18736					blurEvent;
18737				if ( parent.data( "ui-tooltip-open" ) ) {
18738					blurEvent = $.Event( "blur" );
18739					blurEvent.target = blurEvent.currentTarget = this;
18740					that.close( blurEvent, true );
18741				}
18742				if ( parent.attr( "title" ) ) {
18743					parent.uniqueId();
18744					that.parents[ this.id ] = {
18745						element: this,
18746						title: parent.attr( "title" )
18747					};
18748					parent.attr( "title", "" );
18749				}
18750			} );
18751		}
18752
18753		this._registerCloseHandlers( event, target );
18754		this._updateContent( target, event );
18755	},
18756
18757	_updateContent: function( target, event ) {
18758		var content,
18759			contentOption = this.options.content,
18760			that = this,
18761			eventType = event ? event.type : null;
18762
18763		if ( typeof contentOption === "string" || contentOption.nodeType ||
18764				contentOption.jquery ) {
18765			return this._open( event, target, contentOption );
18766		}
18767
18768		content = contentOption.call( target[ 0 ], function( response ) {
18769
18770			// IE may instantly serve a cached response for ajax requests
18771			// delay this call to _open so the other call to _open runs first
18772			that._delay( function() {
18773
18774				// Ignore async response if tooltip was closed already
18775				if ( !target.data( "ui-tooltip-open" ) ) {
18776					return;
18777				}
18778
18779				// JQuery creates a special event for focusin when it doesn't
18780				// exist natively. To improve performance, the native event
18781				// object is reused and the type is changed. Therefore, we can't
18782				// rely on the type being correct after the event finished
18783				// bubbling, so we set it back to the previous value. (#8740)
18784				if ( event ) {
18785					event.type = eventType;
18786				}
18787				this._open( event, target, response );
18788			} );
18789		} );
18790		if ( content ) {
18791			this._open( event, target, content );
18792		}
18793	},
18794
18795	_open: function( event, target, content ) {
18796		var tooltipData, tooltip, delayedShow, a11yContent,
18797			positionOption = $.extend( {}, this.options.position );
18798
18799		if ( !content ) {
18800			return;
18801		}
18802
18803		// Content can be updated multiple times. If the tooltip already
18804		// exists, then just update the content and bail.
18805		tooltipData = this._find( target );
18806		if ( tooltipData ) {
18807			tooltipData.tooltip.find( ".ui-tooltip-content" ).html( content );
18808			return;
18809		}
18810
18811		// If we have a title, clear it to prevent the native tooltip
18812		// we have to check first to avoid defining a title if none exists
18813		// (we don't want to cause an element to start matching [title])
18814		//
18815		// We use removeAttr only for key events, to allow IE to export the correct
18816		// accessible attributes. For mouse events, set to empty string to avoid
18817		// native tooltip showing up (happens only when removing inside mouseover).
18818		if ( target.is( "[title]" ) ) {
18819			if ( event && event.type === "mouseover" ) {
18820				target.attr( "title", "" );
18821			} else {
18822				target.removeAttr( "title" );
18823			}
18824		}
18825
18826		tooltipData = this._tooltip( target );
18827		tooltip = tooltipData.tooltip;
18828		this._addDescribedBy( target, tooltip.attr( "id" ) );
18829		tooltip.find( ".ui-tooltip-content" ).html( content );
18830
18831		// Support: Voiceover on OS X, JAWS on IE <= 9
18832		// JAWS announces deletions even when aria-relevant="additions"
18833		// Voiceover will sometimes re-read the entire log region's contents from the beginning
18834		this.liveRegion.children().hide();
18835		a11yContent = $( "<div>" ).html( tooltip.find( ".ui-tooltip-content" ).html() );
18836		a11yContent.removeAttr( "name" ).find( "[name]" ).removeAttr( "name" );
18837		a11yContent.removeAttr( "id" ).find( "[id]" ).removeAttr( "id" );
18838		a11yContent.appendTo( this.liveRegion );
18839
18840		function position( event ) {
18841			positionOption.of = event;
18842			if ( tooltip.is( ":hidden" ) ) {
18843				return;
18844			}
18845			tooltip.position( positionOption );
18846		}
18847		if ( this.options.track && event && /^mouse/.test( event.type ) ) {
18848			this._on( this.document, {
18849				mousemove: position
18850			} );
18851
18852			// trigger once to override element-relative positioning
18853			position( event );
18854		} else {
18855			tooltip.position( $.extend( {
18856				of: target
18857			}, this.options.position ) );
18858		}
18859
18860		tooltip.hide();
18861
18862		this._show( tooltip, this.options.show );
18863
18864		// Handle tracking tooltips that are shown with a delay (#8644). As soon
18865		// as the tooltip is visible, position the tooltip using the most recent
18866		// event.
18867		// Adds the check to add the timers only when both delay and track options are set (#14682)
18868		if ( this.options.track && this.options.show && this.options.show.delay ) {
18869			delayedShow = this.delayedShow = setInterval( function() {
18870				if ( tooltip.is( ":visible" ) ) {
18871					position( positionOption.of );
18872					clearInterval( delayedShow );
18873				}
18874			}, 13 );
18875		}
18876
18877		this._trigger( "open", event, { tooltip: tooltip } );
18878	},
18879
18880	_registerCloseHandlers: function( event, target ) {
18881		var events = {
18882			keyup: function( event ) {
18883				if ( event.keyCode === $.ui.keyCode.ESCAPE ) {
18884					var fakeEvent = $.Event( event );
18885					fakeEvent.currentTarget = target[ 0 ];
18886					this.close( fakeEvent, true );
18887				}
18888			}
18889		};
18890
18891		// Only bind remove handler for delegated targets. Non-delegated
18892		// tooltips will handle this in destroy.
18893		if ( target[ 0 ] !== this.element[ 0 ] ) {
18894			events.remove = function() {
18895				var targetElement = this._find( target );
18896				if ( targetElement ) {
18897					this._removeTooltip( targetElement.tooltip );
18898				}
18899			};
18900		}
18901
18902		if ( !event || event.type === "mouseover" ) {
18903			events.mouseleave = "close";
18904		}
18905		if ( !event || event.type === "focusin" ) {
18906			events.focusout = "close";
18907		}
18908		this._on( true, target, events );
18909	},
18910
18911	close: function( event ) {
18912		var tooltip,
18913			that = this,
18914			target = $( event ? event.currentTarget : this.element ),
18915			tooltipData = this._find( target );
18916
18917		// The tooltip may already be closed
18918		if ( !tooltipData ) {
18919
18920			// We set ui-tooltip-open immediately upon open (in open()), but only set the
18921			// additional data once there's actually content to show (in _open()). So even if the
18922			// tooltip doesn't have full data, we always remove ui-tooltip-open in case we're in
18923			// the period between open() and _open().
18924			target.removeData( "ui-tooltip-open" );
18925			return;
18926		}
18927
18928		tooltip = tooltipData.tooltip;
18929
18930		// Disabling closes the tooltip, so we need to track when we're closing
18931		// to avoid an infinite loop in case the tooltip becomes disabled on close
18932		if ( tooltipData.closing ) {
18933			return;
18934		}
18935
18936		// Clear the interval for delayed tracking tooltips
18937		clearInterval( this.delayedShow );
18938
18939		// Only set title if we had one before (see comment in _open())
18940		// If the title attribute has changed since open(), don't restore
18941		if ( target.data( "ui-tooltip-title" ) && !target.attr( "title" ) ) {
18942			target.attr( "title", target.data( "ui-tooltip-title" ) );
18943		}
18944
18945		this._removeDescribedBy( target );
18946
18947		tooltipData.hiding = true;
18948		tooltip.stop( true );
18949		this._hide( tooltip, this.options.hide, function() {
18950			that._removeTooltip( $( this ) );
18951		} );
18952
18953		target.removeData( "ui-tooltip-open" );
18954		this._off( target, "mouseleave focusout keyup" );
18955
18956		// Remove 'remove' binding only on delegated targets
18957		if ( target[ 0 ] !== this.element[ 0 ] ) {
18958			this._off( target, "remove" );
18959		}
18960		this._off( this.document, "mousemove" );
18961
18962		if ( event && event.type === "mouseleave" ) {
18963			$.each( this.parents, function( id, parent ) {
18964				$( parent.element ).attr( "title", parent.title );
18965				delete that.parents[ id ];
18966			} );
18967		}
18968
18969		tooltipData.closing = true;
18970		this._trigger( "close", event, { tooltip: tooltip } );
18971		if ( !tooltipData.hiding ) {
18972			tooltipData.closing = false;
18973		}
18974	},
18975
18976	_tooltip: function( element ) {
18977		var tooltip = $( "<div>" ).attr( "role", "tooltip" ),
18978			content = $( "<div>" ).appendTo( tooltip ),
18979			id = tooltip.uniqueId().attr( "id" );
18980
18981		this._addClass( content, "ui-tooltip-content" );
18982		this._addClass( tooltip, "ui-tooltip", "ui-widget ui-widget-content" );
18983
18984		tooltip.appendTo( this._appendTo( element ) );
18985
18986		return this.tooltips[ id ] = {
18987			element: element,
18988			tooltip: tooltip
18989		};
18990	},
18991
18992	_find: function( target ) {
18993		var id = target.data( "ui-tooltip-id" );
18994		return id ? this.tooltips[ id ] : null;
18995	},
18996
18997	_removeTooltip: function( tooltip ) {
18998
18999		// Clear the interval for delayed tracking tooltips
19000		clearInterval( this.delayedShow );
19001
19002		tooltip.remove();
19003		delete this.tooltips[ tooltip.attr( "id" ) ];
19004	},
19005
19006	_appendTo: function( target ) {
19007		var element = target.closest( ".ui-front, dialog" );
19008
19009		if ( !element.length ) {
19010			element = this.document[ 0 ].body;
19011		}
19012
19013		return element;
19014	},
19015
19016	_destroy: function() {
19017		var that = this;
19018
19019		// Close open tooltips
19020		$.each( this.tooltips, function( id, tooltipData ) {
19021
19022			// Delegate to close method to handle common cleanup
19023			var event = $.Event( "blur" ),
19024				element = tooltipData.element;
19025			event.target = event.currentTarget = element[ 0 ];
19026			that.close( event, true );
19027
19028			// Remove immediately; destroying an open tooltip doesn't use the
19029			// hide animation
19030			$( "#" + id ).remove();
19031
19032			// Restore the title
19033			if ( element.data( "ui-tooltip-title" ) ) {
19034
19035				// If the title attribute has changed since open(), don't restore
19036				if ( !element.attr( "title" ) ) {
19037					element.attr( "title", element.data( "ui-tooltip-title" ) );
19038				}
19039				element.removeData( "ui-tooltip-title" );
19040			}
19041		} );
19042		this.liveRegion.remove();
19043	}
19044} );
19045
19046// DEPRECATED
19047// TODO: Switch return back to widget declaration at top of file when this is removed
19048if ( $.uiBackCompat !== false ) {
19049
19050	// Backcompat for tooltipClass option
19051	$.widget( "ui.tooltip", $.ui.tooltip, {
19052		options: {
19053			tooltipClass: null
19054		},
19055		_tooltip: function() {
19056			var tooltipData = this._superApply( arguments );
19057			if ( this.options.tooltipClass ) {
19058				tooltipData.tooltip.addClass( this.options.tooltipClass );
19059			}
19060			return tooltipData;
19061		}
19062	} );
19063}
19064
19065var widgetsTooltip = $.ui.tooltip;
19066
19067
19068
19069
19070} );

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.