PageSourceSearch

https://www.kfh.com/.resources/kfh-templates/webresources/kfh-theme/js/jquery-ui.js

js kfh.com collected 2026-09-24 09:04:14 UTC 537,081 bytes, 18,809 lines download raw bytes

vendor: 500,580 bytes, lines 1-17463
1/*! jQuery UI - v1.14.1 - 2024-10-30
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
23	var version = $.ui.version = "1.14.1";
24
25
26	/*!
27 * jQuery UI Widget 1.14.1
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
42	var widgetUuid = 0;
43	var widgetHasOwnProperty = Array.prototype.hasOwnProperty;
44	var 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		if ( name === "__proto__" || name === "constructor" ) {
71			return $.error( "Invalid widget name: " + name );
72		}
73		var fullName = namespace + "-" + name;
74
75		if ( !prototype ) {
76			prototype = base;
77			base = $.Widget;
78		}
79
80		if ( Array.isArray( prototype ) ) {
81			prototype = $.extend.apply( null, [ {} ].concat( prototype ) );
82		}
83
84		// Create selector for plugin
85		$.expr.pseudos[ fullName.toLowerCase() ] = function( elem ) {
86			return !!$.data( elem, fullName );
87		};
88
89		$[ namespace ] = $[ namespace ] || {};
90		existingConstructor = $[ namespace ][ name ];
91		constructor = $[ namespace ][ name ] = function( options, element ) {
92
93			// Allow instantiation without "new" keyword
94			if ( !this || !this._createWidget ) {
95				return new constructor( options, element );
96			}
97
98			// Allow instantiation without initializing for simple inheritance
99			// must use "new" keyword (the code above always passes args)
100			if ( arguments.length ) {
101				this._createWidget( options, element );
102			}
103		};
104
105		// Extend with the existing constructor to carry over any static properties
106		$.extend( constructor, existingConstructor, {
107			version: prototype.version,
108
109			// Copy the object used to create the prototype in case we need to
110			// redefine the widget later
111			_proto: $.extend( {}, prototype ),
112
113			// Track widgets that inherit from this widget in case this widget is
114			// redefined after a widget inherits from it
115			_childConstructors: []
116		} );
117
118		basePrototype = new base();
119
120		// We need to make the options hash a property directly on the new instance
121		// otherwise we'll modify the options hash on the prototype that we're
122		// inheriting from
123		basePrototype.options = $.widget.extend( {}, basePrototype.options );
124		$.each( prototype, function( prop, value ) {
125			if ( typeof value !== "function" ) {
126				proxiedPrototype[ prop ] = value;
127				return;
128			}
129			proxiedPrototype[ prop ] = ( function() {
130				function _super() {
131					return base.prototype[ prop ].apply( this, arguments );
132				}
133
134				function _superApply( args ) {
135					return base.prototype[ prop ].apply( this, args );
136				}
137
138				return function() {
139					var __super = this._super;
140					var __superApply = this._superApply;
141					var returnValue;
142
143					this._super = _super;
144					this._superApply = _superApply;
145
146					returnValue = value.apply( this, arguments );
147
148					this._super = __super;
149					this._superApply = __superApply;
150
151					return returnValue;
152				};
153			} )();
154		} );
155		constructor.prototype = $.widget.extend( basePrototype, {
156
157			// TODO: remove support for widgetEventPrefix
158			// always use the name + a colon as the prefix, e.g., draggable:start
159			// don't prefix for widgets that aren't DOM-based
160			widgetEventPrefix: existingConstructor ? ( basePrototype.widgetEventPrefix || name ) : name
161		}, proxiedPrototype, {
162			constructor: constructor,
163			namespace: namespace,
164			widgetName: name,
165			widgetFullName: fullName
166		} );
167
168		// If this widget is being redefined then we need to find all widgets that
169		// are inheriting from it and redefine all of them so that they inherit from
170		// the new version of this widget. We're essentially trying to replace one
171		// level in the prototype chain.
172		if ( existingConstructor ) {
173			$.each( existingConstructor._childConstructors, function( i, child ) {
174				var childPrototype = child.prototype;
175
176				// Redefine the child widget using the same prototype that was
177				// originally used, but inherit from the new version of the base
178				$.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor,
179					child._proto );
180			} );
181
182			// Remove the list of existing child constructors from the old constructor
183			// so the old child constructors can be garbage collected
184			delete existingConstructor._childConstructors;
185		} else {
186			base._childConstructors.push( constructor );
187		}
188
189		$.widget.bridge( name, constructor );
190
191		return constructor;
192	};
193
194	$.widget.extend = function( target ) {
195		var input = widgetSlice.call( arguments, 1 );
196		var inputIndex = 0;
197		var inputLength = input.length;
198		var key;
199		var value;
200
201		for ( ; inputIndex < inputLength; inputIndex++ ) {
202			for ( key in input[ inputIndex ] ) {
203				value = input[ inputIndex ][ key ];
204				if ( widgetHasOwnProperty.call( input[ inputIndex ], key ) && value !== undefined ) {
205
206					// Clone objects
207					if ( $.isPlainObject( value ) ) {
208						target[ key ] = $.isPlainObject( target[ key ] ) ?
209							$.widget.extend( {}, target[ key ], value ) :
210
211							// Don't extend strings, arrays, etc. with objects
212							$.widget.extend( {}, value );
213
214						// Copy everything else by reference
215					} else {
216						target[ key ] = value;
217					}
218				}
219			}
220		}
221		return target;
222	};
223
224	$.widget.bridge = function( name, object ) {
225		var fullName = object.prototype.widgetFullName || name;
226		$.fn[ name ] = function( options ) {
227			var isMethodCall = typeof options === "string";
228			var args = widgetSlice.call( arguments, 1 );
229			var returnValue = this;
230
231			if ( isMethodCall ) {
232
233				// If this is an empty collection, we need to have the instance method
234				// return undefined instead of the jQuery instance
235				if ( !this.length && options === "instance" ) {
236					returnValue = undefined;
237				} else {
238					this.each( function() {
239						var methodValue;
240						var instance = $.data( this, fullName );
241
242						if ( options === "instance" ) {
243							returnValue = instance;
244							return false;
245						}
246
247						if ( !instance ) {
248							return $.error( "cannot call methods on " + name +
249								" prior to initialization; " +
250								"attempted to call method '" + options + "'" );
251						}
252
253						if ( typeof instance[ options ] !== "function" ||
254							options.charAt( 0 ) === "_" ) {
255							return $.error( "no such method '" + options + "' for " + name +
256								" widget instance" );
257						}
258
259						methodValue = instance[ options ].apply( instance, args );
260
261						if ( methodValue !== instance && methodValue !== undefined ) {
262							returnValue = methodValue && methodValue.jquery ?
263								returnValue.pushStack( methodValue.get() ) :
264								methodValue;
265							return false;
266						}
267					} );
268				}
269			} else {
270
271				// Allow multiple hashes to be passed on init
272				if ( args.length ) {
273					options = $.widget.extend.apply( null, [ options ].concat( args ) );
274				}
275
276				this.each( function() {
277					var instance = $.data( this, fullName );
278					if ( instance ) {
279						instance.option( options || {} );
280						if ( instance._init ) {
281							instance._init();
282						}
283					} else {
284						$.data( this, fullName, new object( options, this ) );
285					}
286				} );
287			}
288
289			return returnValue;
290		};
291	};
292
293	$.Widget = function( /* options, element */ ) {};
294	$.Widget._childConstructors = [];
295
296	$.Widget.prototype = {
297		widgetName: "widget",
298		widgetEventPrefix: "",
299		defaultElement: "<div>",
300
301		options: {
302			classes: {},
303			disabled: false,
304
305			// Callbacks
306			create: null
307		},
308
309		_createWidget: function( options, element ) {
310			element = $( element || this.defaultElement || this )[ 0 ];
311			this.element = $( element );
312			this.uuid = widgetUuid++;
313			this.eventNamespace = "." + this.widgetName + this.uuid;
314
315			this.bindings = $();
316			this.hoverable = $();
317			this.focusable = $();
318			this.classesElementLookup = {};
319
320			if ( element !== this ) {
321				$.data( element, this.widgetFullName, this );
322				this._on( true, this.element, {
323					remove: function( event ) {
324						if ( event.target === element ) {
325							this.destroy();
326						}
327					}
328				} );
329				this.document = $( element.style ?
330
331					// Element within the document
332					element.ownerDocument :
333
334					// Element is window or document
335					element.document || element );
336				this.window = $( this.document[ 0 ].defaultView || this.document[ 0 ].parentWindow );
337			}
338
339			this.options = $.widget.extend( {},
340				this.options,
341				this._getCreateOptions(),
342				options );
343
344			this._create();
345
346			if ( this.options.disabled ) {
347				this._setOptionDisabled( this.options.disabled );
348			}
349
350			this._trigger( "create", null, this._getCreateEventData() );
351			this._init();
352		},
353
354		_getCreateOptions: function() {
355			return {};
356		},
357
358		_getCreateEventData: $.noop,
359
360		_create: $.noop,
361
362		_init: $.noop,
363
364		destroy: function() {
365			var that = this;
366
367			this._destroy();
368			$.each( this.classesElementLookup, function( key, value ) {
369				that._removeClass( value, key );
370			} );
371
372			// We can probably remove the unbind calls in 2.0
373			// all event bindings should go through this._on()
374			this.element
375				.off( this.eventNamespace )
376				.removeData( this.widgetFullName );
377			this.widget()
378				.off( this.eventNamespace )
379				.removeAttr( "aria-disabled" );
380
381			// Clean up events and states
382			this.bindings.off( this.eventNamespace );
383		},
384
385		_destroy: $.noop,
386
387		widget: function() {
388			return this.element;
389		},
390
391		option: function( key, value ) {
392			var options = key;
393			var parts;
394			var curOption;
395			var i;
396
397			if ( arguments.length === 0 ) {
398
399				// Don't return a reference to the internal hash
400				return $.widget.extend( {}, this.options );
401			}
402
403			if ( typeof key === "string" ) {
404
405				// Handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
406				options = {};
407				parts = key.split( "." );
408				key = parts.shift();
409				if ( parts.length ) {
410					curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
411					for ( i = 0; i < parts.length - 1; i++ ) {
412						curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
413						curOption = curOption[ parts[ i ] ];
414					}
415					key = parts.pop();
416					if ( arguments.length === 1 ) {
417						return curOption[ key ] === undefined ? null : curOption[ key ];
418					}
419					curOption[ key ] = value;
420				} else {
421					if ( arguments.length === 1 ) {
422						return this.options[ key ] === undefined ? null : this.options[ key ];
423					}
424					options[ key ] = value;
425				}
426			}
427
428			this._setOptions( options );
429
430			return this;
431		},
432
433		_setOptions: function( options ) {
434			var key;
435
436			for ( key in options ) {
437				this._setOption( key, options[ key ] );
438			}
439
440			return this;
441		},
442
443		_setOption: function( key, value ) {
444			if ( key === "classes" ) {
445				this._setOptionClasses( value );
446			}
447
448			this.options[ key ] = value;
449
450			if ( key === "disabled" ) {
451				this._setOptionDisabled( value );
452			}
453
454			return this;
455		},
456
457		_setOptionClasses: function( value ) {
458			var classKey, elements, currentElements;
459
460			for ( classKey in value ) {
461				currentElements = this.classesElementLookup[ classKey ];
462				if ( value[ classKey ] === this.options.classes[ classKey ] ||
463					!currentElements ||
464					!currentElements.length ) {
465					continue;
466				}
467
468				// We are doing this to create a new jQuery object because the _removeClass() call
469				// on the next line is going to destroy the reference to the current elements being
470				// tracked. We need to save a copy of this collection so that we can add the new classes
471				// below.
472				elements = $( currentElements.get() );
473				this._removeClass( currentElements, classKey );
474
475				// We don't use _addClass() here, because that uses this.options.classes
476				// for generating the string of classes. We want to use the value passed in from
477				// _setOption(), this is the new value of the classes option which was passed to
478				// _setOption(). We pass this value directly to _classes().
479				elements.addClass( this._classes( {
480					element: elements,
481					keys: classKey,
482					classes: value,
483					add: true
484				} ) );
485			}
486		},
487
488		_setOptionDisabled: function( value ) {
489			this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, !!value );
490
491			// If the widget is becoming disabled, then nothing is interactive
492			if ( value ) {
493				this._removeClass( this.hoverable, null, "ui-state-hover" );
494				this._removeClass( this.focusable, null, "ui-state-focus" );
495			}
496		},
497
498		enable: function() {
499			return this._setOptions( { disabled: false } );
500		},
501
502		disable: function() {
503			return this._setOptions( { disabled: true } );
504		},
505
506		_classes: function( options ) {
507			var full = [];
508			var that = this;
509
510			options = $.extend( {
511				element: this.element,
512				classes: this.options.classes || {}
513			}, options );
514
515			function bindRemoveEvent() {
516				var nodesToBind = [];
517
518				options.element.each( function( _, element ) {
519					var isTracked = $.map( that.classesElementLookup, function( elements ) {
520						return elements;
521					} )
522						.some( function( elements ) {
523							return elements.is( element );
524						} );
525
526					if ( !isTracked ) {
527						nodesToBind.push( element );
528					}
529				} );
530
531				that._on( $( nodesToBind ), {
532					remove: "_untrackClassesElement"
533				} );
534			}
535
536			function processClassString( classes, checkOption ) {
537				var current, i;
538				for ( i = 0; i < classes.length; i++ ) {
539					current = that.classesElementLookup[ classes[ i ] ] || $();
540					if ( options.add ) {
541						bindRemoveEvent();
542						current = $( $.uniqueSort( current.get().concat( options.element.get() ) ) );
543					} else {
544						current = $( current.not( options.element ).get() );
545					}
546					that.classesElementLookup[ classes[ i ] ] = current;
547					full.push( classes[ i ] );
548					if ( checkOption && options.classes[ classes[ i ] ] ) {
549						full.push( options.classes[ classes[ i ] ] );
550					}
551				}
552			}
553
554			if ( options.keys ) {
555				processClassString( options.keys.match( /\S+/g ) || [], true );
556			}
557			if ( options.extra ) {
558				processClassString( options.extra.match( /\S+/g ) || [] );
559			}
560
561			return full.join( " " );
562		},
563
564		_untrackClassesElement: function( event ) {
565			var that = this;
566			$.each( that.classesElementLookup, function( key, value ) {
567				if ( $.inArray( event.target, value ) !== -1 ) {
568					that.classesElementLookup[ key ] = $( value.not( event.target ).get() );
569				}
570			} );
571
572			this._off( $( event.target ) );
573		},
574
575		_removeClass: function( element, keys, extra ) {
576			return this._toggleClass( element, keys, extra, false );
577		},
578
579		_addClass: function( element, keys, extra ) {
580			return this._toggleClass( element, keys, extra, true );
581		},
582
583		_toggleClass: function( element, keys, extra, add ) {
584			add = ( typeof add === "boolean" ) ? add : extra;
585			var shift = ( typeof element === "string" || element === null ),
586				options = {
587					extra: shift ? keys : extra,
588					keys: shift ? element : keys,
589					element: shift ? this.element : element,
590					add: add
591				};
592			options.element.toggleClass( this._classes( options ), add );
593			return this;
594		},
595
596		_on: function( suppressDisabledCheck, element, handlers ) {
597			var delegateElement;
598			var instance = this;
599
600			// No suppressDisabledCheck flag, shuffle arguments
601			if ( typeof suppressDisabledCheck !== "boolean" ) {
602				handlers = element;
603				element = suppressDisabledCheck;
604				suppressDisabledCheck = false;
605			}
606
607			// No element argument, shuffle and use this.element
608			if ( !handlers ) {
609				handlers = element;
610				element = this.element;
611				delegateElement = this.widget();
612			} else {
613				element = delegateElement = $( element );
614				this.bindings = this.bindings.add( element );
615			}
616
617			$.each( handlers, function( event, handler ) {
618				function handlerProxy() {
619
620					// Allow widgets to customize the disabled handling
621					// - disabled as an array instead of boolean
622					// - disabled class as method for disabling individual parts
623					if ( !suppressDisabledCheck &&
624						( instance.options.disabled === true ||
625							$( this ).hasClass( "ui-state-disabled" ) ) ) {
626						return;
627					}
628					return ( typeof handler === "string" ? instance[ handler ] : handler )
629						.apply( instance, arguments );
630				}
631
632				// Copy the guid so direct unbinding works
633				if ( typeof handler !== "string" ) {
634					handlerProxy.guid = handler.guid =
635						handler.guid || handlerProxy.guid || $.guid++;
636				}
637
638				var match = event.match( /^([\w:-]*)\s*(.*)$/ );
639				var eventName = match[ 1 ] + instance.eventNamespace;
640				var selector = match[ 2 ];
641
642				if ( selector ) {
643					delegateElement.on( eventName, selector, handlerProxy );
644				} else {
645					element.on( eventName, handlerProxy );
646				}
647			} );
648		},
649
650		_off: function( element, eventName ) {
651			eventName = ( eventName || "" ).split( " " ).join( this.eventNamespace + " " ) +
652				this.eventNamespace;
653			element.off( eventName );
654
655			// Clear the stack to avoid memory leaks (#10056)
656			this.bindings = $( this.bindings.not( element ).get() );
657			this.focusable = $( this.focusable.not( element ).get() );
658			this.hoverable = $( this.hoverable.not( element ).get() );
659		},
660
661		_delay: function( handler, delay ) {
662			function handlerProxy() {
663				return ( typeof handler === "string" ? instance[ handler ] : handler )
664					.apply( instance, arguments );
665			}
666			var instance = this;
667			return setTimeout( handlerProxy, delay || 0 );
668		},
669
670		_hoverable: function( element ) {
671			this.hoverable = this.hoverable.add( element );
672			this._on( element, {
673				mouseenter: function( event ) {
674					this._addClass( $( event.currentTarget ), null, "ui-state-hover" );
675				},
676				mouseleave: function( event ) {
677					this._removeClass( $( event.currentTarget ), null, "ui-state-hover" );
678				}
679			} );
680		},
681
682		_focusable: function( element ) {
683			this.focusable = this.focusable.add( element );
684			this._on( element, {
685				focusin: function( event ) {
686					this._addClass( $( event.currentTarget ), null, "ui-state-focus" );
687				},
688				focusout: function( event ) {
689					this._removeClass( $( event.currentTarget ), null, "ui-state-focus" );
690				}
691			} );
692		},
693
694		_trigger: function( type, event, data ) {
695			var prop, orig;
696			var callback = this.options[ type ];
697
698			data = data || {};
699			event = $.Event( event );
700			event.type = ( type === this.widgetEventPrefix ?
701				type :
702				this.widgetEventPrefix + type ).toLowerCase();
703
704			// The original event may come from any element
705			// so we need to reset the target on the new event
706			event.target = this.element[ 0 ];
707
708			// Copy original event properties over to the new event
709			orig = event.originalEvent;
710			if ( orig ) {
711				for ( prop in orig ) {
712					if ( !( prop in event ) ) {
713						event[ prop ] = orig[ prop ];
714					}
715				}
716			}
717
718			this.element.trigger( event, data );
719			return !( typeof callback === "function" &&
720				callback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false ||
721				event.isDefaultPrevented() );
722		}
723	};
724
725	$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
726		$.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
727			if ( typeof options === "string" ) {
728				options = { effect: options };
729			}
730
731			var hasOptions;
732			var effectName = !options ?
733				method :
734				options === true || typeof options === "number" ?
735					defaultEffect :
736					options.effect || defaultEffect;
737
738			options = options || {};
739			if ( typeof options === "number" ) {
740				options = { duration: options };
741			} else if ( options === true ) {
742				options = {};
743			}
744
745			hasOptions = !$.isEmptyObject( options );
746			options.complete = callback;
747
748			if ( options.delay ) {
749				element.delay( options.delay );
750			}
751
752			if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
753				element[ method ]( options );
754			} else if ( effectName !== method && element[ effectName ] ) {
755				element[ effectName ]( options.duration, options.easing, callback );
756			} else {
757				element.queue( function( next ) {
758					$( this )[ method ]();
759					if ( callback ) {
760						callback.call( element[ 0 ] );
761					}
762					next();
763				} );
764			}
765		};
766	} );
767
768	var widget = $.widget;
769
770
771	/*!
772 * jQuery UI Position 1.14.1
773 * https://jqueryui.com
774 *
775 * Copyright OpenJS Foundation and other contributors
776 * Released under the MIT license.
777 * https://jquery.org/license
778 *
779 * https://api.jqueryui.com/position/
780 */
781
782//>>label: Position
783//>>group: Core
784//>>description: Positions elements relative to other elements.
785//>>docs: https://api.jqueryui.com/position/
786//>>demos: https://jqueryui.com/position/
787
788
789	( function() {
790		var cachedScrollbarWidth,
791			max = Math.max,
792			abs = Math.abs,
793			rhorizontal = /left|center|right/,
794			rvertical = /top|center|bottom/,
795			roffset = /[\+\-]\d+(\.[\d]+)?%?/,
796			rposition = /^\w+/,
797			rpercent = /%$/,
798			_position = $.fn.position;
799
800		function getOffsets( offsets, width, height ) {
801			return [
802				parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
803				parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
804			];
805		}
806
807		function parseCss( element, property ) {
808			return parseInt( $.css( element, property ), 10 ) || 0;
809		}
810
811		function isWindow( obj ) {
812			return obj != null && obj === obj.window;
813		}
814
815		function getDimensions( elem ) {
816			var raw = elem[ 0 ];
817			if ( raw.nodeType === 9 ) {
818				return {
819					width: elem.width(),
820					height: elem.height(),
821					offset: { top: 0, left: 0 }
822				};
823			}
824			if ( isWindow( raw ) ) {
825				return {
826					width: elem.width(),
827					height: elem.height(),
828					offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
829				};
830			}
831			if ( raw.preventDefault ) {
832				return {
833					width: 0,
834					height: 0,
835					offset: { top: raw.pageY, left: raw.pageX }
836				};
837			}
838			return {
839				width: elem.outerWidth(),
840				height: elem.outerHeight(),
841				offset: elem.offset()
842			};
843		}
844
845		$.position = {
846			scrollbarWidth: function() {
847				if ( cachedScrollbarWidth !== undefined ) {
848					return cachedScrollbarWidth;
849				}
850				var w1, w2,
851					div = $( "<div style=" +
852						"'display:block;position:absolute;width:200px;height:200px;overflow:hidden;'>" +
853						"<div style='height:300px;width:auto;'></div></div>" ),
854					innerDiv = div.children()[ 0 ];
855
856				$( "body" ).append( div );
857				w1 = innerDiv.offsetWidth;
858				div.css( "overflow", "scroll" );
859
860				w2 = innerDiv.offsetWidth;
861
862				if ( w1 === w2 ) {
863					w2 = div[ 0 ].clientWidth;
864				}
865
866				div.remove();
867
868				return ( cachedScrollbarWidth = w1 - w2 );
869			},
870			getScrollInfo: function( within ) {
871				var overflowX = within.isWindow || within.isDocument ? "" :
872						within.element.css( "overflow-x" ),
873					overflowY = within.isWindow || within.isDocument ? "" :
874						within.element.css( "overflow-y" ),
875					hasOverflowX = overflowX === "scroll" ||
876						( overflowX === "auto" && within.width < within.element[ 0 ].scrollWidth ),
877					hasOverflowY = overflowY === "scroll" ||
878						( overflowY === "auto" && within.height < within.element[ 0 ].scrollHeight );
879				return {
880					width: hasOverflowY ? $.position.scrollbarWidth() : 0,
881					height: hasOverflowX ? $.position.scrollbarWidth() : 0
882				};
883			},
884			getWithinInfo: function( element ) {
885				var withinElement = $( element || window ),
886					isElemWindow = isWindow( withinElement[ 0 ] ),
887					isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9,
888					hasOffset = !isElemWindow && !isDocument;
889				return {
890					element: withinElement,
891					isWindow: isElemWindow,
892					isDocument: isDocument,
893					offset: hasOffset ? $( element ).offset() : { left: 0, top: 0 },
894					scrollLeft: withinElement.scrollLeft(),
895					scrollTop: withinElement.scrollTop(),
896					width: withinElement.outerWidth(),
897					height: withinElement.outerHeight()
898				};
899			}
900		};
901
902		$.fn.position = function( options ) {
903			if ( !options || !options.of ) {
904				return _position.apply( this, arguments );
905			}
906
907			// Make a copy, we don't want to modify arguments
908			options = $.extend( {}, options );
909
910			var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
911
912				// Make sure string options are treated as CSS selectors
913				target = typeof options.of === "string" ?
914					$( document ).find( options.of ) :
915					$( options.of ),
916
917				within = $.position.getWithinInfo( options.within ),
918				scrollInfo = $.position.getScrollInfo( within ),
919				collision = ( options.collision || "flip" ).split( " " ),
920				offsets = {};
921
922			dimensions = getDimensions( target );
923			if ( target[ 0 ].preventDefault ) {
924
925				// Force left top to allow flipping
926				options.at = "left top";
927			}
928			targetWidth = dimensions.width;
929			targetHeight = dimensions.height;
930			targetOffset = dimensions.offset;
931
932			// Clone to reuse original targetOffset later
933			basePosition = $.extend( {}, targetOffset );
934
935			// Force my and at to have valid horizontal and vertical positions
936			// if a value is missing or invalid, it will be converted to center
937			$.each( [ "my", "at" ], function() {
938				var pos = ( options[ this ] || "" ).split( " " ),
939					horizontalOffset,
940					verticalOffset;
941
942				if ( pos.length === 1 ) {
943					pos = rhorizontal.test( pos[ 0 ] ) ?
944						pos.concat( [ "center" ] ) :
945						rvertical.test( pos[ 0 ] ) ?
946							[ "center" ].concat( pos ) :
947							[ "center", "center" ];
948				}
949				pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
950				pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
951
952				// Calculate offsets
953				horizontalOffset = roffset.exec( pos[ 0 ] );
954				verticalOffset = roffset.exec( pos[ 1 ] );
955				offsets[ this ] = [
956					horizontalOffset ? horizontalOffset[ 0 ] : 0,
957					verticalOffset ? verticalOffset[ 0 ] : 0
958				];
959
960				// Reduce to just the positions without the offsets
961				options[ this ] = [
962					rposition.exec( pos[ 0 ] )[ 0 ],
963					rposition.exec( pos[ 1 ] )[ 0 ]
964				];
965			} );
966
967			// Normalize collision option
968			if ( collision.length === 1 ) {
969				collision[ 1 ] = collision[ 0 ];
970			}
971
972			if ( options.at[ 0 ] === "right" ) {
973				basePosition.left += targetWidth;
974			} else if ( options.at[ 0 ] === "center" ) {
975				basePosition.left += targetWidth / 2;
976			}
977
978			if ( options.at[ 1 ] === "bottom" ) {
979				basePosition.top += targetHeight;
980			} else if ( options.at[ 1 ] === "center" ) {
981				basePosition.top += targetHeight / 2;
982			}
983
984			atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
985			basePosition.left += atOffset[ 0 ];
986			basePosition.top += atOffset[ 1 ];
987
988			return this.each( function() {
989				var collisionPosition, using,
990					elem = $( this ),
991					elemWidth = elem.outerWidth(),
992					elemHeight = elem.outerHeight(),
993					marginLeft = parseCss( this, "marginLeft" ),
994					marginTop = parseCss( this, "marginTop" ),
995					collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) +
996						scrollInfo.width,
997					collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) +
998						scrollInfo.height,
999					position = $.extend( {}, basePosition ),
1000					myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
1001
1002				if ( options.my[ 0 ] === "right" ) {
1003					position.left -= elemWidth;
1004				} else if ( options.my[ 0 ] === "center" ) {
1005					position.left -= elemWidth / 2;
1006				}
1007
1008				if ( options.my[ 1 ] === "bottom" ) {
1009					position.top -= elemHeight;
1010				} else if ( options.my[ 1 ] === "center" ) {
1011					position.top -= elemHeight / 2;
1012				}
1013
1014				position.left += myOffset[ 0 ];
1015				position.top += myOffset[ 1 ];
1016
1017				collisionPosition = {
1018					marginLeft: marginLeft,
1019					marginTop: marginTop
1020				};
1021
1022				$.each( [ "left", "top" ], function( i, dir ) {
1023					if ( $.ui.position[ collision[ i ] ] ) {
1024						$.ui.position[ collision[ i ] ][ dir ]( position, {
1025							targetWidth: targetWidth,
1026							targetHeight: targetHeight,
1027							elemWidth: elemWidth,
1028							elemHeight: elemHeight,
1029							collisionPosition: collisionPosition,
1030							collisionWidth: collisionWidth,
1031							collisionHeight: collisionHeight,
1032							offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
1033							my: options.my,
1034							at: options.at,
1035							within: within,
1036							elem: elem
1037						} );
1038					}
1039				} );
1040
1041				if ( options.using ) {
1042
1043					// Adds feedback as second argument to using callback, if present
1044					using = function( props ) {
1045						var left = targetOffset.left - position.left,
1046							right = left + targetWidth - elemWidth,
1047							top = targetOffset.top - position.top,
1048							bottom = top + targetHeight - elemHeight,
1049							feedback = {
1050								target: {
1051									element: target,
1052									left: targetOffset.left,
1053									top: targetOffset.top,
1054									width: targetWidth,
1055									height: targetHeight
1056								},
1057								element: {
1058									element: elem,
1059									left: position.left,
1060									top: position.top,
1061									width: elemWidth,
1062									height: elemHeight
1063								},
1064								horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
1065								vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
1066							};
1067						if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
1068							feedback.horizontal = "center";
1069						}
1070						if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
1071							feedback.vertical = "middle";
1072						}
1073						if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
1074							feedback.important = "horizontal";
1075						} else {
1076							feedback.important = "vertical";
1077						}
1078						options.using.call( this, props, feedback );
1079					};
1080				}
1081
1082				elem.offset( $.extend( position, { using: using } ) );
1083			} );
1084		};
1085
1086		$.ui.position = {
1087			fit: {
1088				left: function( position, data ) {
1089					var within = data.within,
1090						withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
1091						outerWidth = within.width,
1092						collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1093						overLeft = withinOffset - collisionPosLeft,
1094						overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
1095						newOverRight;
1096
1097					// Element is wider than within
1098					if ( data.collisionWidth > outerWidth ) {
1099
1100						// Element is initially over the left side of within
1101						if ( overLeft > 0 && overRight <= 0 ) {
1102							newOverRight = position.left + overLeft + data.collisionWidth - outerWidth -
1103								withinOffset;
1104							position.left += overLeft - newOverRight;
1105
1106							// Element is initially over right side of within
1107						} else if ( overRight > 0 && overLeft <= 0 ) {
1108							position.left = withinOffset;
1109
1110							// Element is initially over both left and right sides of within
1111						} else {
1112							if ( overLeft > overRight ) {
1113								position.left = withinOffset + outerWidth - data.collisionWidth;
1114							} else {
1115								position.left = withinOffset;
1116							}
1117						}
1118
1119						// Too far left -> align with left edge
1120					} else if ( overLeft > 0 ) {
1121						position.left += overLeft;
1122
1123						// Too far right -> align with right edge
1124					} else if ( overRight > 0 ) {
1125						position.left -= overRight;
1126
1127						// Adjust based on position and margin
1128					} else {
1129						position.left = max( position.left - collisionPosLeft, position.left );
1130					}
1131				},
1132				top: function( position, data ) {
1133					var within = data.within,
1134						withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
1135						outerHeight = data.within.height,
1136						collisionPosTop = position.top - data.collisionPosition.marginTop,
1137						overTop = withinOffset - collisionPosTop,
1138						overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
1139						newOverBottom;
1140
1141					// Element is taller than within
1142					if ( data.collisionHeight > outerHeight ) {
1143
1144						// Element is initially over the top of within
1145						if ( overTop > 0 && overBottom <= 0 ) {
1146							newOverBottom = position.top + overTop + data.collisionHeight - outerHeight -
1147								withinOffset;
1148							position.top += overTop - newOverBottom;
1149
1150							// Element is initially over bottom of within
1151						} else if ( overBottom > 0 && overTop <= 0 ) {
1152							position.top = withinOffset;
1153
1154							// Element is initially over both top and bottom of within
1155						} else {
1156							if ( overTop > overBottom ) {
1157								position.top = withinOffset + outerHeight - data.collisionHeight;
1158							} else {
1159								position.top = withinOffset;
1160							}
1161						}
1162
1163						// Too far up -> align with top
1164					} else if ( overTop > 0 ) {
1165						position.top += overTop;
1166
1167						// Too far down -> align with bottom edge
1168					} else if ( overBottom > 0 ) {
1169						position.top -= overBottom;
1170
1171						// Adjust based on position and margin
1172					} else {
1173						position.top = max( position.top - collisionPosTop, position.top );
1174					}
1175				}
1176			},
1177			flip: {
1178				left: function( position, data ) {
1179					var within = data.within,
1180						withinOffset = within.offset.left + within.scrollLeft,
1181						outerWidth = within.width,
1182						offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
1183						collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1184						overLeft = collisionPosLeft - offsetLeft,
1185						overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
1186						myOffset = data.my[ 0 ] === "left" ?
1187							-data.elemWidth :
1188							data.my[ 0 ] === "right" ?
1189								data.elemWidth :
1190								0,
1191						atOffset = data.at[ 0 ] === "left" ?
1192							data.targetWidth :
1193							data.at[ 0 ] === "right" ?
1194								-data.targetWidth :
1195								0,
1196						offset = -2 * data.offset[ 0 ],
1197						newOverRight,
1198						newOverLeft;
1199
1200					if ( overLeft < 0 ) {
1201						newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth -
1202							outerWidth - withinOffset;
1203						if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
1204							position.left += myOffset + atOffset + offset;
1205						}
1206					} else if ( overRight > 0 ) {
1207						newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset +
1208							atOffset + offset - offsetLeft;
1209						if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
1210							position.left += myOffset + atOffset + offset;
1211						}
1212					}
1213				},
1214				top: function( position, data ) {
1215					var within = data.within,
1216						withinOffset = within.offset.top + within.scrollTop,
1217						outerHeight = within.height,
1218						offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
1219						collisionPosTop = position.top - data.collisionPosition.marginTop,
1220						overTop = collisionPosTop - offsetTop,
1221						overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
1222						top = data.my[ 1 ] === "top",
1223						myOffset = top ?
1224							-data.elemHeight :
1225							data.my[ 1 ] === "bottom" ?
1226								data.elemHeight :
1227								0,
1228						atOffset = data.at[ 1 ] === "top" ?
1229							data.targetHeight :
1230							data.at[ 1 ] === "bottom" ?
1231								-data.targetHeight :
1232								0,
1233						offset = -2 * data.offset[ 1 ],
1234						newOverTop,
1235						newOverBottom;
1236					if ( overTop < 0 ) {
1237						newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight -
1238							outerHeight - withinOffset;
1239						if ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) {
1240							position.top += myOffset + atOffset + offset;
1241						}
1242					} else if ( overBottom > 0 ) {
1243						newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset +
1244							offset - offsetTop;
1245						if ( newOverTop > 0 || abs( newOverTop ) < overBottom ) {
1246							position.top += myOffset + atOffset + offset;
1247						}
1248					}
1249				}
1250			},
1251			flipfit: {
1252				left: function() {
1253					$.ui.position.flip.left.apply( this, arguments );
1254					$.ui.position.fit.left.apply( this, arguments );
1255				},
1256				top: function() {
1257					$.ui.position.flip.top.apply( this, arguments );
1258					$.ui.position.fit.top.apply( this, arguments );
1259				}
1260			}
1261		};
1262
1263	} )();
1264
1265	var position = $.ui.position;
1266
1267
1268	/*!
1269 * jQuery UI :data 1.14.1
1270 * https://jqueryui.com
1271 *
1272 * Copyright OpenJS Foundation and other contributors
1273 * Released under the MIT license.
1274 * https://jquery.org/license
1275 */
1276
1277//>>label: :data Selector
1278//>>group: Core
1279//>>description: Selects elements which have data stored under the specified key.
1280//>>docs: https://api.jqueryui.com/data-selector/
1281
1282
1283	var data = $.extend( $.expr.pseudos, {
1284		data: $.expr.createPseudo( function( dataName ) {
1285			return function( elem ) {
1286				return !!$.data( elem, dataName );
1287			};
1288		} )
1289	} );
1290
1291	/*!
1292 * jQuery UI Disable Selection 1.14.1
1293 * https://jqueryui.com
1294 *
1295 * Copyright OpenJS Foundation and other contributors
1296 * Released under the MIT license.
1297 * https://jquery.org/license
1298 */
1299
1300//>>label: disableSelection
1301//>>group: Core
1302//>>description: Disable selection of text content within the set of matched elements.
1303//>>docs: https://api.jqueryui.com/disableSelection/
1304
1305// This file is deprecated
1306
1307	var disableSelection = $.fn.extend( {
1308		disableSelection: ( function() {
1309			var eventType = "onselectstart" in document.createElement( "div" ) ?
1310				"selectstart" :
1311				"mousedown";
1312
1313			return function() {
1314				return this.on( eventType + ".ui-disableSelection", function( event ) {
1315					event.preventDefault();
1316				} );
1317			};
1318		} )(),
1319
1320		enableSelection: function() {
1321			return this.off( ".ui-disableSelection" );
1322		}
1323	} );
1324
1325
1326
1327// Create a local jQuery because jQuery Color relies on it and the
1328// global may not exist with AMD and a custom build (#10199).
1329// This module is a noop if used as a regular AMD module.
1330// eslint-disable-next-line no-unused-vars
1331	var jQuery = $;
1332
1333
1334	/*!
1335 * jQuery Color Animations v3.0.0
1336 * https://github.com/jquery/jquery-color
1337 *
1338 * Copyright OpenJS Foundation and other contributors
1339 * Released under the MIT license.
1340 * https://jquery.org/license
1341 *
1342 * Date: Wed May 15 16:49:44 2024 +0200
1343 */
1344
1345
1346	var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor " +
1347			"borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",
1348
1349		class2type = {},
1350		toString = class2type.toString,
1351
1352		// plusequals test for += 100 -= 100
1353		rplusequals = /^([\-+])=\s*(\d+\.?\d*)/,
1354
1355		// a set of RE's that can match strings and generate color tuples.
1356		stringParsers = [ {
1357			re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
1358			parse: function( execResult ) {
1359				return [
1360					execResult[ 1 ],
1361					execResult[ 2 ],
1362					execResult[ 3 ],
1363					execResult[ 4 ]
1364				];
1365			}
1366		}, {
1367			re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
1368			parse: function( execResult ) {
1369				return [
1370					execResult[ 1 ] * 2.55,
1371					execResult[ 2 ] * 2.55,
1372					execResult[ 3 ] * 2.55,
1373					execResult[ 4 ]
1374				];
1375			}
1376		}, {
1377
1378			// this regex ignores A-F because it's compared against an already lowercased string
1379			re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})?/,
1380			parse: function( execResult ) {
1381				return [
1382					parseInt( execResult[ 1 ], 16 ),
1383					parseInt( execResult[ 2 ], 16 ),
1384					parseInt( execResult[ 3 ], 16 ),
1385					execResult[ 4 ] ?
1386						( parseInt( execResult[ 4 ], 16 ) / 255 ).toFixed( 2 ) :
1387						1
1388				];
1389			}
1390		}, {
1391
1392			// this regex ignores A-F because it's compared against an already lowercased string
1393			re: /#([a-f0-9])([a-f0-9])([a-f0-9])([a-f0-9])?/,
1394			parse: function( execResult ) {
1395				return [
1396					parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),
1397					parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),
1398					parseInt( execResult[ 3 ] + execResult[ 3 ], 16 ),
1399					execResult[ 4 ] ?
1400						( parseInt( execResult[ 4 ] + execResult[ 4 ], 16 ) / 255 )
1401							.toFixed( 2 ) :
1402						1
1403				];
1404			}
1405		}, {
1406			re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
1407			space: "hsla",
1408			parse: function( execResult ) {
1409				return [
1410					execResult[ 1 ],
1411					execResult[ 2 ] / 100,
1412					execResult[ 3 ] / 100,
1413					execResult[ 4 ]
1414				];
1415			}
1416		} ],
1417
1418		// jQuery.Color( )
1419		color = jQuery.Color = function( color, green, blue, alpha ) {
1420			return new jQuery.Color.fn.parse( color, green, blue, alpha );
1421		},
1422		spaces = {
1423			rgba: {
1424				props: {
1425					red: {
1426						idx: 0,
1427						type: "byte"
1428					},
1429					green: {
1430						idx: 1,
1431						type: "byte"
1432					},
1433					blue: {
1434						idx: 2,
1435						type: "byte"
1436					}
1437				}
1438			},
1439
1440			hsla: {
1441				props: {
1442					hue: {
1443						idx: 0,
1444						type: "degrees"
1445					},
1446					saturation: {
1447						idx: 1,
1448						type: "percent"
1449					},
1450					lightness: {
1451						idx: 2,
1452						type: "percent"
1453					}
1454				}
1455			}
1456		},
1457		propTypes = {
1458			"byte": {
1459				floor: true,
1460				max: 255
1461			},
1462			"percent": {
1463				max: 1
1464			},
1465			"degrees": {
1466				mod: 360,
1467				floor: true
1468			}
1469		},
1470
1471		// colors = jQuery.Color.names
1472		colors,
1473
1474		// local aliases of functions called often
1475		each = jQuery.each;
1476
1477// define cache name and alpha properties
1478// for rgba and hsla spaces
1479	each( spaces, function( spaceName, space ) {
1480		space.cache = "_" + spaceName;
1481		space.props.alpha = {
1482			idx: 3,
1483			type: "percent",
1484			def: 1
1485		};
1486	} );
1487
1488// Populate the class2type map
1489	jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
1490		function( _i, name ) {
1491			class2type[ "[object " + name + "]" ] = name.toLowerCase();
1492		} );
1493
1494	function getType( obj ) {
1495		if ( obj == null ) {
1496			return obj + "";
1497		}
1498
1499		return typeof obj === "object" ?
1500			class2type[ toString.call( obj ) ] || "object" :
1501			typeof obj;
1502	}
1503
1504	function clamp( value, prop, allowEmpty ) {
1505		var type = propTypes[ prop.type ] || {};
1506
1507		if ( value == null ) {
1508			return ( allowEmpty || !prop.def ) ? null : prop.def;
1509		}
1510
1511		// ~~ is an short way of doing floor for positive numbers
1512		value = type.floor ? ~~value : parseFloat( value );
1513
1514		if ( type.mod ) {
1515
1516			// we add mod before modding to make sure that negatives values
1517			// get converted properly: -10 -> 350
1518			return ( value + type.mod ) % type.mod;
1519		}
1520
1521		// for now all property types without mod have min and max
1522		return Math.min( type.max, Math.max( 0, value ) );
1523	}
1524
1525	function stringParse( string ) {
1526		var inst = color(),
1527			rgba = inst._rgba = [];
1528
1529		string = string.toLowerCase();
1530
1531		each( stringParsers, function( _i, parser ) {
1532			var parsed,
1533				match = parser.re.exec( string ),
1534				values = match && parser.parse( match ),
1535				spaceName = parser.space || "rgba";
1536
1537			if ( values ) {
1538				parsed = inst[ spaceName ]( values );
1539
1540				// if this was an rgba parse the assignment might happen twice
1541				// oh well....
1542				inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ];
1543				rgba = inst._rgba = parsed._rgba;
1544
1545				// exit each( stringParsers ) here because we matched
1546				return false;
1547			}
1548		} );
1549
1550		// Found a stringParser that handled it
1551		if ( rgba.length ) {
1552
1553			// if this came from a parsed string, force "transparent" when alpha is 0
1554			// chrome, (and maybe others) return "transparent" as rgba(0,0,0,0)
1555			if ( rgba.join() === "0,0,0,0" ) {
1556				jQuery.extend( rgba, colors.transparent );
1557			}
1558			return inst;
1559		}
1560
1561		// named colors
1562		return colors[ string ];
1563	}
1564
1565	color.fn = jQuery.extend( color.prototype, {
1566		parse: function( red, green, blue, alpha ) {
1567			if ( red === undefined ) {
1568				this._rgba = [ null, null, null, null ];
1569				return this;
1570			}
1571			if ( red.jquery || red.nodeType ) {
1572				red = jQuery( red ).css( green );
1573				green = undefined;
1574			}
1575
1576			var inst = this,
1577				type = getType( red ),
1578				rgba = this._rgba = [];
1579
1580			// more than 1 argument specified - assume ( red, green, blue, alpha )
1581			if ( green !== undefined ) {
1582				red = [ red, green, blue, alpha ];
1583				type = "array";
1584			}
1585
1586			if ( type === "string" ) {
1587				return this.parse( stringParse( red ) || colors._default );
1588			}
1589
1590			if ( type === "array" ) {
1591				each( spaces.rgba.props, function( _key, prop ) {
1592					rgba[ prop.idx ] = clamp( red[ prop.idx ], prop );
1593				} );
1594				return this;
1595			}
1596
1597			if ( type === "object" ) {
1598				if ( red instanceof color ) {
1599					each( spaces, function( _spaceName, space ) {
1600						if ( red[ space.cache ] ) {
1601							inst[ space.cache ] = red[ space.cache ].slice();
1602						}
1603					} );
1604				} else {
1605					each( spaces, function( _spaceName, space ) {
1606						var cache = space.cache;
1607						each( space.props, function( key, prop ) {
1608
1609							// if the cache doesn't exist, and we know how to convert
1610							if ( !inst[ cache ] && space.to ) {
1611
1612								// if the value was null, we don't need to copy it
1613								// if the key was alpha, we don't need to copy it either
1614								if ( key === "alpha" || red[ key ] == null ) {
1615									return;
1616								}
1617								inst[ cache ] = space.to( inst._rgba );
1618							}
1619
1620							// this is the only case where we allow nulls for ALL properties.
1621							// call clamp with alwaysAllowEmpty
1622							inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true );
1623						} );
1624
1625						// everything defined but alpha?
1626						if ( inst[ cache ] && jQuery.inArray(
1627							null,
1628							inst[ cache ].slice( 0, 3 )
1629						) < 0 ) {
1630
1631							// use the default of 1
1632							if ( inst[ cache ][ 3 ] == null ) {
1633								inst[ cache ][ 3 ] = 1;
1634							}
1635
1636							if ( space.from ) {
1637								inst._rgba = space.from( inst[ cache ] );
1638							}
1639						}
1640					} );
1641				}
1642				return this;
1643			}
1644		},
1645		is: function( compare ) {
1646			var is = color( compare ),
1647				same = true,
1648				inst = this;
1649
1650			each( spaces, function( _, space ) {
1651				var localCache,
1652					isCache = is[ space.cache ];
1653				if ( isCache ) {
1654					localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || [];
1655					each( space.props, function( _, prop ) {
1656						if ( isCache[ prop.idx ] != null ) {
1657							same = ( isCache[ prop.idx ] === localCache[ prop.idx ] );
1658							return same;
1659						}
1660					} );
1661				}
1662				return same;
1663			} );
1664			return same;
1665		},
1666		_space: function() {
1667			var used = [],
1668				inst = this;
1669			each( spaces, function( spaceName, space ) {
1670				if ( inst[ space.cache ] ) {
1671					used.push( spaceName );
1672				}
1673			} );
1674			return used.pop();
1675		},
1676		transition: function( other, distance ) {
1677			var end = color( other ),
1678				spaceName = end._space(),
1679				space = spaces[ spaceName ],
1680				startColor = this.alpha() === 0 ? color( "transparent" ) : this,
1681				start = startColor[ space.cache ] || space.to( startColor._rgba ),
1682				result = start.slice();
1683
1684			end = end[ space.cache ];
1685			each( space.props, function( _key, prop ) {
1686				var index = prop.idx,
1687					startValue = start[ index ],
1688					endValue = end[ index ],
1689					type = propTypes[ prop.type ] || {};
1690
1691				// if null, don't override start value
1692				if ( endValue === null ) {
1693					return;
1694				}
1695
1696				// if null - use end
1697				if ( startValue === null ) {
1698					result[ index ] = endValue;
1699				} else {
1700					if ( type.mod ) {
1701						if ( endValue - startValue > type.mod / 2 ) {
1702							startValue += type.mod;
1703						} else if ( startValue - endValue > type.mod / 2 ) {
1704							startValue -= type.mod;
1705						}
1706					}
1707					result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop );
1708				}
1709			} );
1710			return this[ spaceName ]( result );
1711		},
1712		blend: function( opaque ) {
1713
1714			// if we are already opaque - return ourself
1715			if ( this._rgba[ 3 ] === 1 ) {
1716				return this;
1717			}
1718
1719			var rgb = this._rgba.slice(),
1720				a = rgb.pop(),
1721				blend = color( opaque )._rgba;
1722
1723			return color( jQuery.map( rgb, function( v, i ) {
1724				return ( 1 - a ) * blend[ i ] + a * v;
1725			} ) );
1726		},
1727		toRgbaString: function() {
1728			var prefix = "rgba(",
1729				rgba = jQuery.map( this._rgba, function( v, i ) {
1730					if ( v != null ) {
1731						return v;
1732					}
1733					return i > 2 ? 1 : 0;
1734				} );
1735
1736			if ( rgba[ 3 ] === 1 ) {
1737				rgba.pop();
1738				prefix = "rgb(";
1739			}
1740
1741			return prefix + rgba.join( ", " ) + ")";
1742		},
1743		toHslaString: function() {
1744			var prefix = "hsla(",
1745				hsla = jQuery.map( this.hsla(), function( v, i ) {
1746					if ( v == null ) {
1747						v = i > 2 ? 1 : 0;
1748					}
1749
1750					// catch 1 and 2
1751					if ( i && i < 3 ) {
1752						v = Math.round( v * 100 ) + "%";
1753					}
1754					return v;
1755				} );
1756
1757			if ( hsla[ 3 ] === 1 ) {
1758				hsla.pop();
1759				prefix = "hsl(";
1760			}
1761			return prefix + hsla.join( ", " ) + ")";
1762		},
1763		toHexString: function( includeAlpha ) {
1764			var rgba = this._rgba.slice(),
1765				alpha = rgba.pop();
1766
1767			if ( includeAlpha ) {
1768				rgba.push( ~~( alpha * 255 ) );
1769			}
1770
1771			return "#" + jQuery.map( rgba, function( v ) {
1772
1773				// default to 0 when nulls exist
1774				return ( "0" + ( v || 0 ).toString( 16 ) ).substr( -2 );
1775			} ).join( "" );
1776		},
1777		toString: function() {
1778			return this.toRgbaString();
1779		}
1780	} );
1781	color.fn.parse.prototype = color.fn;
1782
1783// hsla conversions adapted from:
1784// https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021
1785
1786	function hue2rgb( p, q, h ) {
1787		h = ( h + 1 ) % 1;
1788		if ( h * 6 < 1 ) {
1789			return p + ( q - p ) * h * 6;
1790		}
1791		if ( h * 2 < 1 ) {
1792			return q;
1793		}
1794		if ( h * 3 < 2 ) {
1795			return p + ( q - p ) * ( ( 2 / 3 ) - h ) * 6;
1796		}
1797		return p;
1798	}
1799
1800	spaces.hsla.to = function( rgba ) {
1801		if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) {
1802			return [ null, null, null, rgba[ 3 ] ];
1803		}
1804		var r = rgba[ 0 ] / 255,
1805			g = rgba[ 1 ] / 255,
1806			b = rgba[ 2 ] / 255,
1807			a = rgba[ 3 ],
1808			max = Math.max( r, g, b ),
1809			min = Math.min( r, g, b ),
1810			diff = max - min,
1811			add = max + min,
1812			l = add * 0.5,
1813			h, s;
1814
1815		if ( min === max ) {
1816			h = 0;
1817		} else if ( r === max ) {
1818			h = ( 60 * ( g - b ) / diff ) + 360;
1819		} else if ( g === max ) {
1820			h = ( 60 * ( b - r ) / diff ) + 120;
1821		} else {
1822			h = ( 60 * ( r - g ) / diff ) + 240;
1823		}
1824
1825		// chroma (diff) == 0 means greyscale which, by definition, saturation = 0%
1826		// otherwise, saturation is based on the ratio of chroma (diff) to lightness (add)
1827		if ( diff === 0 ) {
1828			s = 0;
1829		} else if ( l <= 0.5 ) {
1830			s = diff / add;
1831		} else {
1832			s = diff / ( 2 - add );
1833		}
1834		return [ Math.round( h ) % 360, s, l, a == null ? 1 : a ];
1835	};
1836
1837	spaces.hsla.from = function( hsla ) {
1838		if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) {
1839			return [ null, null, null, hsla[ 3 ] ];
1840		}
1841		var h = hsla[ 0 ] / 360,
1842			s = hsla[ 1 ],
1843			l = hsla[ 2 ],
1844			a = hsla[ 3 ],
1845			q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s,
1846			p = 2 * l - q;
1847
1848		return [
1849			Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ),
1850			Math.round( hue2rgb( p, q, h ) * 255 ),
1851			Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ),
1852			a
1853		];
1854	};
1855
1856
1857	each( spaces, function( spaceName, space ) {
1858		var props = space.props,
1859			cache = space.cache,
1860			to = space.to,
1861			from = space.from;
1862
1863		// makes rgba() and hsla()
1864		color.fn[ spaceName ] = function( value ) {
1865
1866			// generate a cache for this space if it doesn't exist
1867			if ( to && !this[ cache ] ) {
1868				this[ cache ] = to( this._rgba );
1869			}
1870			if ( value === undefined ) {
1871				return this[ cache ].slice();
1872			}
1873
1874			var ret,
1875				type = getType( value ),
1876				arr = ( type === "array" || type === "object" ) ? value : arguments,
1877				local = this[ cache ].slice();
1878
1879			each( props, function( key, prop ) {
1880				var val = arr[ type === "object" ? key : prop.idx ];
1881				if ( val == null ) {
1882					val = local[ prop.idx ];
1883				}
1884				local[ prop.idx ] = clamp( val, prop );
1885			} );
1886
1887			if ( from ) {
1888				ret = color( from( local ) );
1889				ret[ cache ] = local;
1890				return ret;
1891			} else {
1892				return color( local );
1893			}
1894		};
1895
1896		// makes red() green() blue() alpha() hue() saturation() lightness()
1897		each( props, function( key, prop ) {
1898
1899			// alpha is included in more than one space
1900			if ( color.fn[ key ] ) {
1901				return;
1902			}
1903			color.fn[ key ] = function( value ) {
1904				var local, cur, match, fn,
1905					vtype = getType( value );
1906
1907				if ( key === "alpha" ) {
1908					fn = this._hsla ? "hsla" : "rgba";
1909				} else {
1910					fn = spaceName;
1911				}
1912				local = this[ fn ]();
1913				cur = local[ prop.idx ];
1914
1915				if ( vtype === "undefined" ) {
1916					return cur;
1917				}
1918
1919				if ( vtype === "function" ) {
1920					value = value.call( this, cur );
1921					vtype = getType( value );
1922				}
1923				if ( value == null && prop.empty ) {
1924					return this;
1925				}
1926				if ( vtype === "string" ) {
1927					match = rplusequals.exec( value );
1928					if ( match ) {
1929						value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 );
1930					}
1931				}
1932				local[ prop.idx ] = value;
1933				return this[ fn ]( local );
1934			};
1935		} );
1936	} );
1937
1938// add cssHook and .fx.step function for each named hook.
1939// accept a space separated string of properties
1940	color.hook = function( hook ) {
1941		var hooks = hook.split( " " );
1942		each( hooks, function( _i, hook ) {
1943			jQuery.cssHooks[ hook ] = {
1944				set: function( elem, value ) {
1945					var parsed;
1946
1947					if ( value !== "transparent" &&
1948						( getType( value ) !== "string" ||
1949							( parsed = stringParse( value ) ) ) ) {
1950						value = color( parsed || value );
1951						value = value.toRgbaString();
1952					}
1953					elem.style[ hook ] = value;
1954				}
1955			};
1956			jQuery.fx.step[ hook ] = function( fx ) {
1957				if ( !fx.colorInit ) {
1958					fx.start = color( fx.elem, hook );
1959					fx.end = color( fx.end );
1960					fx.colorInit = true;
1961				}
1962				jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) );
1963			};
1964		} );
1965
1966	};
1967
1968	color.hook( stepHooks );
1969
1970	jQuery.cssHooks.borderColor = {
1971		expand: function( value ) {
1972			var expanded = {};
1973
1974			each( [ "Top", "Right", "Bottom", "Left" ], function( _i, part ) {
1975				expanded[ "border" + part + "Color" ] = value;
1976			} );
1977			return expanded;
1978		}
1979	};
1980
1981// Basic color names only.
1982// Usage of any of the other color names requires adding yourself or including
1983// jquery.color.svg-names.js.
1984	colors = jQuery.Color.names = {
1985
1986		// 4.1. Basic color keywords
1987		aqua: "#00ffff",
1988		black: "#000000",
1989		blue: "#0000ff",
1990		fuchsia: "#ff00ff",
1991		gray: "#808080",
1992		green: "#008000",
1993		lime: "#00ff00",
1994		maroon: "#800000",
1995		navy: "#000080",
1996		olive: "#808000",
1997		purple: "#800080",
1998		red: "#ff0000",
1999		silver: "#c0c0c0",
2000		teal: "#008080",
2001		white: "#ffffff",
2002		yellow: "#ffff00",
2003
2004		// 4.2.3. "transparent" color keyword
2005		transparent: [ null, null, null, 0 ],
2006
2007		_default: "#ffffff"
2008	};
2009
2010
2011	/*!
2012 * jQuery UI Effects 1.14.1
2013 * https://jqueryui.com
2014 *
2015 * Copyright OpenJS Foundation and other contributors
2016 * Released under the MIT license.
2017 * https://jquery.org/license
2018 */
2019
2020//>>label: Effects Core
2021//>>group: Effects
2022	/* eslint-disable max-len */
2023//>>description: Extends the internal jQuery effects. Includes morphing and easing. Required by all other effects.
2024	/* eslint-enable max-len */
2025//>>docs: https://api.jqueryui.com/category/effects-core/
2026//>>demos: https://jqueryui.com/effect/
2027
2028
2029	var dataSpace = "ui-effects-",
2030		dataSpaceStyle = "ui-effects-style",
2031		dataSpaceAnimated = "ui-effects-animated";
2032
2033	$.effects = {
2034		effect: {}
2035	};
2036
2037	/******************************************************************************/
2038	/****************************** CLASS ANIMATIONS ******************************/
2039	/******************************************************************************/
2040	( function() {
2041
2042		var classAnimationActions = [ "add", "remove", "toggle" ],
2043			shorthandStyles = {
2044				border: 1,
2045				borderBottom: 1,
2046				borderColor: 1,
2047				borderLeft: 1,
2048				borderRight: 1,
2049				borderTop: 1,
2050				borderWidth: 1,
2051				margin: 1,
2052				padding: 1
2053			};
2054
2055		$.each(
2056			[ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ],
2057			function( _, prop ) {
2058				$.fx.step[ prop ] = function( fx ) {
2059					if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) {
2060						jQuery.style( fx.elem, prop, fx.end );
2061						fx.setAttr = true;
2062					}
2063				};
2064			}
2065		);
2066
2067		function camelCase( string ) {
2068			return string.replace( /-([\da-z])/gi, function( all, letter ) {
2069				return letter.toUpperCase();
2070			} );
2071		}
2072
2073		function getElementStyles( elem ) {
2074			var key, len,
2075				style = elem.ownerDocument.defaultView.getComputedStyle( elem ),
2076				styles = {};
2077
2078			len = style.length;
2079			while ( len-- ) {
2080				key = style[ len ];
2081				if ( typeof style[ key ] === "string" ) {
2082					styles[ camelCase( key ) ] = style[ key ];
2083				}
2084			}
2085
2086			return styles;
2087		}
2088
2089		function styleDifference( oldStyle, newStyle ) {
2090			var diff = {},
2091				name, value;
2092
2093			for ( name in newStyle ) {
2094				value = newStyle[ name ];
2095				if ( oldStyle[ name ] !== value ) {
2096					if ( !shorthandStyles[ name ] ) {
2097						if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) {
2098							diff[ name ] = value;
2099						}
2100					}
2101				}
2102			}
2103
2104			return diff;
2105		}
2106
2107		$.effects.animateClass = function( value, duration, easing, callback ) {
2108			var o = $.speed( duration, easing, callback );
2109
2110			return this.queue( function() {
2111				var animated = $( this ),
2112					baseClass = animated.attr( "class" ) || "",
2113					applyClassChange,
2114					allAnimations = o.children ? animated.find( "*" ).addBack() : animated;
2115
2116				// Map the animated objects to store the original styles.
2117				allAnimations = allAnimations.map( function() {
2118					var el = $( this );
2119					return {
2120						el: el,
2121						start: getElementStyles( this )
2122					};
2123				} );
2124
2125				// Apply class change
2126				applyClassChange = function() {
2127					$.each( classAnimationActions, function( i, action ) {
2128						if ( value[ action ] ) {
2129							animated[ action + "Class" ]( value[ action ] );
2130						}
2131					} );
2132				};
2133				applyClassChange();
2134
2135				// Map all animated objects again - calculate new styles and diff
2136				allAnimations = allAnimations.map( function() {
2137					this.end = getElementStyles( this.el[ 0 ] );
2138					this.diff = styleDifference( this.start, this.end );
2139					return this;
2140				} );
2141
2142				// Apply original class
2143				animated.attr( "class", baseClass );
2144
2145				// Map all animated objects again - this time collecting a promise
2146				allAnimations = allAnimations.map( function() {
2147					var styleInfo = this,
2148						dfd = $.Deferred(),
2149						opts = $.extend( {}, o, {
2150							queue: false,
2151							complete: function() {
2152								dfd.resolve( styleInfo );
2153							}
2154						} );
2155
2156					this.el.animate( this.diff, opts );
2157					return dfd.promise();
2158				} );
2159
2160				// Once all animations have completed:
2161				$.when.apply( $, allAnimations.get() ).done( function() {
2162
2163					// Set the final class
2164					applyClassChange();
2165
2166					// For each animated element,
2167					// clear all css properties that were animated
2168					$.each( arguments, function() {
2169						var el = this.el;
2170						$.each( this.diff, function( key ) {
2171							el.css( key, "" );
2172						} );
2173					} );
2174
2175					// This is guarnteed to be there if you use jQuery.speed()
2176					// it also handles dequeuing the next anim...
2177					o.complete.call( animated[ 0 ] );
2178				} );
2179			} );
2180		};
2181
2182		$.fn.extend( {
2183			addClass: ( function( orig ) {
2184				return function( classNames, speed, easing, callback ) {
2185					return speed ?
2186						$.effects.animateClass.call( this,
2187							{ add: classNames }, speed, easing, callback ) :
2188						orig.apply( this, arguments );
2189				};
2190			} )( $.fn.addClass ),
2191
2192			removeClass: ( function( orig ) {
2193				return function( classNames, speed, easing, callback ) {
2194					return arguments.length > 1 ?
2195						$.effects.animateClass.call( this,
2196							{ remove: classNames }, speed, easing, callback ) :
2197						orig.apply( this, arguments );
2198				};
2199			} )( $.fn.removeClass ),
2200
2201			toggleClass: ( function( orig ) {
2202				return function( classNames, force, speed, easing, callback ) {
2203					if ( typeof force === "boolean" || force === undefined ) {
2204						if ( !speed ) {
2205
2206							// Without speed parameter
2207							return orig.apply( this, arguments );
2208						} else {
2209							return $.effects.animateClass.call( this,
2210								( force ? { add: classNames } : { remove: classNames } ),
2211								speed, easing, callback );
2212						}
2213					} else {
2214
2215						// Without force parameter
2216						return $.effects.animateClass.call( this,
2217							{ toggle: classNames }, force, speed, easing );
2218					}
2219				};
2220			} )( $.fn.toggleClass ),
2221
2222			switchClass: function( remove, add, speed, easing, callback ) {
2223				return $.effects.animateClass.call( this, {
2224					add: add,
2225					remove: remove
2226				}, speed, easing, callback );
2227			}
2228		} );
2229
2230	} )();
2231
2232	/******************************************************************************/
2233	/*********************************** EFFECTS **********************************/
2234	/******************************************************************************/
2235
2236	( function() {
2237
2238		if ( $.expr && $.expr.pseudos && $.expr.pseudos.animated ) {
2239			$.expr.pseudos.animated = ( function( orig ) {
2240				return function( elem ) {
2241					return !!$( elem ).data( dataSpaceAnimated ) || orig( elem );
2242				};
2243			} )( $.expr.pseudos.animated );
2244		}
2245
2246		if ( $.uiBackCompat === true ) {
2247			$.extend( $.effects, {
2248
2249				// Saves a set of properties in a data storage
2250				save: function( element, set ) {
2251					var i = 0, length = set.length;
2252					for ( ; i < length; i++ ) {
2253						if ( set[ i ] !== null ) {
2254							element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] );
2255						}
2256					}
2257				},
2258
2259				// Restores a set of previously saved properties from a data storage
2260				restore: function( element, set ) {
2261					var val, i = 0, length = set.length;
2262					for ( ; i < length; i++ ) {
2263						if ( set[ i ] !== null ) {
2264							val = element.data( dataSpace + set[ i ] );
2265							element.css( set[ i ], val );
2266						}
2267					}
2268				},
2269
2270				setMode: function( el, mode ) {
2271					if ( mode === "toggle" ) {
2272						mode = el.is( ":hidden" ) ? "show" : "hide";
2273					}
2274					return mode;
2275				},
2276
2277				// Wraps the element around a wrapper that copies position properties
2278				createWrapper: function( element ) {
2279
2280					// If the element is already wrapped, return it
2281					if ( element.parent().is( ".ui-effects-wrapper" ) ) {
2282						return element.parent();
2283					}
2284
2285					// Wrap the element
2286					var props = {
2287							width: element.outerWidth( true ),
2288							height: element.outerHeight( true ),
2289							"float": element.css( "float" )
2290						},
2291						wrapper = $( "<div></div>" )
2292							.addClass( "ui-effects-wrapper" )
2293							.css( {
2294								fontSize: "100%",
2295								background: "transparent",
2296								border: "none",
2297								margin: 0,
2298								padding: 0
2299							} ),
2300
2301						// Store the size in case width/height are defined in % - Fixes #5245
2302						size = {
2303							width: element.width(),
2304							height: element.height()
2305						},
2306						active = document.activeElement;
2307
2308					// Support: Firefox
2309					// Firefox incorrectly exposes anonymous content
2310					// https://bugzilla.mozilla.org/show_bug.cgi?id=561664
2311					try {
2312						// eslint-disable-next-line no-unused-expressions
2313						active.id;
2314					} catch ( e ) {
2315						active = document.body;
2316					}
2317
2318					element.wrap( wrapper );
2319
2320					// Fixes #7595 - Elements lose focus when wrapped.
2321					if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
2322						$( active ).trigger( "focus" );
2323					}
2324
2325					// Hotfix for jQuery 1.4 since some change in wrap() seems to actually
2326					// lose the reference to the wrapped element
2327					wrapper = element.parent();
2328
2329					// Transfer positioning properties to the wrapper
2330					if ( element.css( "position" ) === "static" ) {
2331						wrapper.css( { position: "relative" } );
2332						element.css( { position: "relative" } );
2333					} else {
2334						$.extend( props, {
2335							position: element.css( "position" ),
2336							zIndex: element.css( "z-index" )
2337						} );
2338						$.each( [ "top", "left", "bottom", "right" ], function( i, pos ) {
2339							props[ pos ] = element.css( pos );
2340							if ( isNaN( parseInt( props[ pos ], 10 ) ) ) {
2341								props[ pos ] = "auto";
2342							}
2343						} );
2344						element.css( {
2345							position: "relative",
2346							top: 0,
2347							left: 0,
2348							right: "auto",
2349							bottom: "auto"
2350						} );
2351					}
2352					element.css( size );
2353
2354					return wrapper.css( props ).show();
2355				},
2356
2357				removeWrapper: function( element ) {
2358					var active = document.activeElement;
2359
2360					if ( element.parent().is( ".ui-effects-wrapper" ) ) {
2361						element.parent().replaceWith( element );
2362
2363						// Fixes #7595 - Elements lose focus when wrapped.
2364						if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
2365							$( active ).trigger( "focus" );
2366						}
2367					}
2368
2369					return element;
2370				}
2371			} );
2372		}
2373
2374		$.extend( $.effects, {
2375			version: "1.14.1",
2376
2377			define: function( name, mode, effect ) {
2378				if ( !effect ) {
2379					effect = mode;
2380					mode = "effect";
2381				}
2382
2383				$.effects.effect[ name ] = effect;
2384				$.effects.effect[ name ].mode = mode;
2385
2386				return effect;
2387			},
2388
2389			scaledDimensions: function( element, percent, direction ) {
2390				if ( percent === 0 ) {
2391					return {
2392						height: 0,
2393						width: 0,
2394						outerHeight: 0,
2395						outerWidth: 0
2396					};
2397				}
2398
2399				var x = direction !== "horizontal" ? ( ( percent || 100 ) / 100 ) : 1,
2400					y = direction !== "vertical" ? ( ( percent || 100 ) / 100 ) : 1;
2401
2402				return {
2403					height: element.height() * y,
2404					width: element.width() * x,
2405					outerHeight: element.outerHeight() * y,
2406					outerWidth: element.outerWidth() * x
2407				};
2408
2409			},
2410
2411			clipToBox: function( animation ) {
2412				return {
2413					width: animation.clip.right - animation.clip.left,
2414					height: animation.clip.bottom - animation.clip.top,
2415					left: animation.clip.left,
2416					top: animation.clip.top
2417				};
2418			},
2419
2420			// Injects recently queued functions to be first in line (after "inprogress")
2421			unshift: function( element, queueLength, count ) {
2422				var queue = element.queue();
2423
2424				if ( queueLength > 1 ) {
2425					queue.splice.apply( queue,
2426						[ 1, 0 ].concat( queue.splice( queueLength, count ) ) );
2427				}
2428				element.dequeue();
2429			},
2430
2431			saveStyle: function( element ) {
2432				element.data( dataSpaceStyle, element[ 0 ].style.cssText );
2433			},
2434
2435			restoreStyle: function( element ) {
2436				element[ 0 ].style.cssText = element.data( dataSpaceStyle ) || "";
2437				element.removeData( dataSpaceStyle );
2438			},
2439
2440			mode: function( element, mode ) {
2441				var hidden = element.is( ":hidden" );
2442
2443				if ( mode === "toggle" ) {
2444					mode = hidden ? "show" : "hide";
2445				}
2446				if ( hidden ? mode === "hide" : mode === "show" ) {
2447					mode = "none";
2448				}
2449				return mode;
2450			},
2451
2452			// Translates a [top,left] array into a baseline value
2453			getBaseline: function( origin, original ) {
2454				var y, x;
2455
2456				switch ( origin[ 0 ] ) {
2457					case "top":
2458						y = 0;
2459						break;
2460					case "middle":
2461						y = 0.5;
2462						break;
2463					case "bottom":
2464						y = 1;
2465						break;
2466					default:
2467						y = origin[ 0 ] / original.height;
2468				}
2469
2470				switch ( origin[ 1 ] ) {
2471					case "left":
2472						x = 0;
2473						break;
2474					case "center":
2475						x = 0.5;
2476						break;
2477					case "right":
2478						x = 1;
2479						break;
2480					default:
2481						x = origin[ 1 ] / original.width;
2482				}
2483
2484				return {
2485					x: x,
2486					y: y
2487				};
2488			},
2489
2490			// Creates a placeholder element so that the original element can be made absolute
2491			createPlaceholder: function( element ) {
2492				var placeholder,
2493					cssPosition = element.css( "position" ),
2494					position = element.position();
2495
2496				// Lock in margins first to account for form elements, which
2497				// will change margin if you explicitly set height
2498				// see: https://jsfiddle.net/JZSMt/3/ https://bugs.webkit.org/show_bug.cgi?id=107380
2499				// Support: Safari
2500				element.css( {
2501					marginTop: element.css( "marginTop" ),
2502					marginBottom: element.css( "marginBottom" ),
2503					marginLeft: element.css( "marginLeft" ),
2504					marginRight: element.css( "marginRight" )
2505				} )
2506					.outerWidth( element.outerWidth() )
2507					.outerHeight( element.outerHeight() );
2508
2509				if ( /^(static|relative)/.test( cssPosition ) ) {
2510					cssPosition = "absolute";
2511
2512					placeholder = $( "<" + element[ 0 ].nodeName + ">" ).insertAfter( element ).css( {
2513
2514						// Convert inline to inline block to account for inline elements
2515						// that turn to inline block based on content (like img)
2516						display: /^(inline|ruby)/.test( element.css( "display" ) ) ?
2517							"inline-block" :
2518							"block",
2519						visibility: "hidden",
2520
2521						// Margins need to be set to account for margin collapse
2522						marginTop: element.css( "marginTop" ),
2523						marginBottom: element.css( "marginBottom" ),
2524						marginLeft: element.css( "marginLeft" ),
2525						marginRight: element.css( "marginRight" ),
2526						"float": element.css( "float" )
2527					} )
2528						.outerWidth( element.outerWidth() )
2529						.outerHeight( element.outerHeight() )
2530						.addClass( "ui-effects-placeholder" );
2531
2532					element.data( dataSpace + "placeholder", placeholder );
2533				}
2534
2535				element.css( {
2536					position: cssPosition,
2537					left: position.left,
2538					top: position.top
2539				} );
2540
2541				return placeholder;
2542			},
2543
2544			removePlaceholder: function( element ) {
2545				var dataKey = dataSpace + "placeholder",
2546					placeholder = element.data( dataKey );
2547
2548				if ( placeholder ) {
2549					placeholder.remove();
2550					element.removeData( dataKey );
2551				}
2552			},
2553
2554			// Removes a placeholder if it exists and restores
2555			// properties that were modified during placeholder creation
2556			cleanUp: function( element ) {
2557				$.effects.restoreStyle( element );
2558				$.effects.removePlaceholder( element );
2559			},
2560
2561			setTransition: function( element, list, factor, value ) {
2562				value = value || {};
2563				$.each( list, function( i, x ) {
2564					var unit = element.cssUnit( x );
2565					if ( unit[ 0 ] > 0 ) {
2566						value[ x ] = unit[ 0 ] * factor + unit[ 1 ];
2567					}
2568				} );
2569				return value;
2570			}
2571		} );
2572
2573// Return an effect options object for the given parameters:
2574		function _normalizeArguments( effect, options, speed, callback ) {
2575
2576			// Allow passing all options as the first parameter
2577			if ( $.isPlainObject( effect ) ) {
2578				options = effect;
2579				effect = effect.effect;
2580			}
2581
2582			// Convert to an object
2583			effect = { effect: effect };
2584
2585			// Catch (effect, null, ...)
2586			if ( options == null ) {
2587				options = {};
2588			}
2589
2590			// Catch (effect, callback)
2591			if ( typeof options === "function" ) {
2592				callback = options;
2593				speed = null;
2594				options = {};
2595			}
2596
2597			// Catch (effect, speed, ?)
2598			if ( typeof options === "number" || $.fx.speeds[ options ] ) {
2599				callback = speed;
2600				speed = options;
2601				options = {};
2602			}
2603
2604			// Catch (effect, options, callback)
2605			if ( typeof speed === "function" ) {
2606				callback = speed;
2607				speed = null;
2608			}
2609
2610			// Add options to effect
2611			if ( options ) {
2612				$.extend( effect, options );
2613			}
2614
2615			speed = speed || options.duration;
2616			effect.duration = $.fx.off ? 0 :
2617				typeof speed === "number" ? speed :
2618					speed in $.fx.speeds ? $.fx.speeds[ speed ] :
2619						$.fx.speeds._default;
2620
2621			effect.complete = callback || options.complete;
2622
2623			return effect;
2624		}
2625
2626		function standardAnimationOption( option ) {
2627
2628			// Valid standard speeds (nothing, number, named speed)
2629			if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) {
2630				return true;
2631			}
2632
2633			// Invalid strings - treat as "normal" speed
2634			if ( typeof option === "string" && !$.effects.effect[ option ] ) {
2635				return true;
2636			}
2637
2638			// Complete callback
2639			if ( typeof option === "function" ) {
2640				return true;
2641			}
2642
2643			// Options hash (but not naming an effect)
2644			if ( typeof option === "object" && !option.effect ) {
2645				return true;
2646			}
2647
2648			// Didn't match any standard API
2649			return false;
2650		}
2651
2652		$.fn.extend( {
2653			effect: function( /* effect, options, speed, callback */ ) {
2654				var args = _normalizeArguments.apply( this, arguments ),
2655					effectMethod = $.effects.effect[ args.effect ],
2656					defaultMode = effectMethod.mode,
2657					queue = args.queue,
2658					queueName = queue || "fx",
2659					complete = args.complete,
2660					mode = args.mode,
2661					modes = [],
2662					prefilter = function( next ) {
2663						var el = $( this ),
2664							normalizedMode = $.effects.mode( el, mode ) || defaultMode;
2665
2666						// Sentinel for duck-punching the :animated pseudo-selector
2667						el.data( dataSpaceAnimated, true );
2668
2669						// Save effect mode for later use,
2670						// we can't just call $.effects.mode again later,
2671						// as the .show() below destroys the initial state
2672						modes.push( normalizedMode );
2673
2674						// See $.uiBackCompat inside of run() for removal of defaultMode in 1.14
2675						if ( defaultMode && ( normalizedMode === "show" ||
2676							( normalizedMode === defaultMode && normalizedMode === "hide" ) ) ) {
2677							el.show();
2678						}
2679
2680						if ( !defaultMode || normalizedMode !== "none" ) {
2681							$.effects.saveStyle( el );
2682						}
2683
2684						if ( typeof next === "function" ) {
2685							next();
2686						}
2687					};
2688
2689				if ( $.fx.off || !effectMethod ) {
2690
2691					// Delegate to the original method (e.g., .show()) if possible
2692					if ( mode ) {
2693						return this[ mode ]( args.duration, complete );
2694					} else {
2695						return this.each( function() {
2696							if ( complete ) {
2697								complete.call( this );
2698							}
2699						} );
2700					}
2701				}
2702
2703				function run( next ) {
2704					var elem = $( this );
2705
2706					function cleanup() {
2707						elem.removeData( dataSpaceAnimated );
2708
2709						$.effects.cleanUp( elem );
2710
2711						if ( args.mode === "hide" ) {
2712							elem.hide();
2713						}
2714
2715						done();
2716					}
2717
2718					function done() {
2719						if ( typeof complete === "function" ) {
2720							complete.call( elem[ 0 ] );
2721						}
2722
2723						if ( typeof next === "function" ) {
2724							next();
2725						}
2726					}
2727
2728					// Override mode option on a per element basis,
2729					// as toggle can be either show or hide depending on element state
2730					args.mode = modes.shift();
2731
2732					if ( $.uiBackCompat === true && !defaultMode ) {
2733						if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) {
2734
2735							// Call the core method to track "olddisplay" properly
2736							elem[ mode ]();
2737							done();
2738						} else {
2739							effectMethod.call( elem[ 0 ], args, done );
2740						}
2741					} else {
2742						if ( args.mode === "none" ) {
2743
2744							// Call the core method to track "olddisplay" properly
2745							elem[ mode ]();
2746							done();
2747						} else {
2748							effectMethod.call( elem[ 0 ], args, cleanup );
2749						}
2750					}
2751				}
2752
2753				// Run prefilter on all elements first to ensure that
2754				// any showing or hiding happens before placeholder creation,
2755				// which ensures that any layout changes are correctly captured.
2756				return queue === false ?
2757					this.each( prefilter ).each( run ) :
2758					this.queue( queueName, prefilter ).queue( queueName, run );
2759			},
2760
2761			show: ( function( orig ) {
2762				return function( option ) {
2763					if ( standardAnimationOption( option ) ) {
2764						return orig.apply( this, arguments );
2765					} else {
2766						var args = _normalizeArguments.apply( this, arguments );
2767						args.mode = "show";
2768						return this.effect.call( this, args );
2769					}
2770				};
2771			} )( $.fn.show ),
2772
2773			hide: ( function( orig ) {
2774				return function( option ) {
2775					if ( standardAnimationOption( option ) ) {
2776						return orig.apply( this, arguments );
2777					} else {
2778						var args = _normalizeArguments.apply( this, arguments );
2779						args.mode = "hide";
2780						return this.effect.call( this, args );
2781					}
2782				};
2783			} )( $.fn.hide ),
2784
2785			toggle: ( function( orig ) {
2786				return function( option ) {
2787					if ( standardAnimationOption( option ) || typeof option === "boolean" ) {
2788						return orig.apply( this, arguments );
2789					} else {
2790						var args = _normalizeArguments.apply( this, arguments );
2791						args.mode = "toggle";
2792						return this.effect.call( this, args );
2793					}
2794				};
2795			} )( $.fn.toggle ),
2796
2797			cssUnit: function( key ) {
2798				var style = this.css( key ),
2799					val = [];
2800
2801				$.each( [ "em", "px", "%", "pt" ], function( i, unit ) {
2802					if ( style.indexOf( unit ) > 0 ) {
2803						val = [ parseFloat( style ), unit ];
2804					}
2805				} );
2806				return val;
2807			},
2808
2809			cssClip: function( clipObj ) {
2810				if ( clipObj ) {
2811					return this.css( "clip", "rect(" + clipObj.top + "px " + clipObj.right + "px " +
2812						clipObj.bottom + "px " + clipObj.left + "px)" );
2813				}
2814				return parseClip( this.css( "clip" ), this );
2815			},
2816
2817			transfer: function( options, done ) {
2818				var element = $( this ),
2819					target = $( options.to ),
2820					targetFixed = target.css( "position" ) === "fixed",
2821					body = $( "body" ),
2822					fixTop = targetFixed ? body.scrollTop() : 0,
2823					fixLeft = targetFixed ? body.scrollLeft() : 0,
2824					endPosition = target.offset(),
2825					animation = {
2826						top: endPosition.top - fixTop,
2827						left: endPosition.left - fixLeft,
2828						height: target.innerHeight(),
2829						width: target.innerWidth()
2830					},
2831					startPosition = element.offset(),
2832					transfer = $( "<div class='ui-effects-transfer'></div>" );
2833
2834				transfer
2835					.appendTo( "body" )
2836					.addClass( options.className )
2837					.css( {
2838						top: startPosition.top - fixTop,
2839						left: startPosition.left - fixLeft,
2840						height: element.innerHeight(),
2841						width: element.innerWidth(),
2842						position: targetFixed ? "fixed" : "absolute"
2843					} )
2844					.animate( animation, options.duration, options.easing, function() {
2845						transfer.remove();
2846						if ( typeof done === "function" ) {
2847							done();
2848						}
2849					} );
2850			}
2851		} );
2852
2853		function parseClip( str, element ) {
2854			var outerWidth = element.outerWidth(),
2855				outerHeight = element.outerHeight(),
2856				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)\)$/,
2857				values = clipRegex.exec( str ) || [ "", 0, outerWidth, outerHeight, 0 ];
2858
2859			return {
2860				top: parseFloat( values[ 1 ] ) || 0,
2861				right: values[ 2 ] === "auto" ? outerWidth : parseFloat( values[ 2 ] ),
2862				bottom: values[ 3 ] === "auto" ? outerHeight : parseFloat( values[ 3 ] ),
2863				left: parseFloat( values[ 4 ] ) || 0
2864			};
2865		}
2866
2867		$.fx.step.clip = function( fx ) {
2868			if ( !fx.clipInit ) {
2869				fx.start = $( fx.elem ).cssClip();
2870				if ( typeof fx.end === "string" ) {
2871					fx.end = parseClip( fx.end, fx.elem );
2872				}
2873				fx.clipInit = true;
2874			}
2875
2876			$( fx.elem ).cssClip( {
2877				top: fx.pos * ( fx.end.top - fx.start.top ) + fx.start.top,
2878				right: fx.pos * ( fx.end.right - fx.start.right ) + fx.start.right,
2879				bottom: fx.pos * ( fx.end.bottom - fx.start.bottom ) + fx.start.bottom,
2880				left: fx.pos * ( fx.end.left - fx.start.left ) + fx.start.left
2881			} );
2882		};
2883
2884	} )();
2885
2886	/******************************************************************************/
2887	/*********************************** EASING ***********************************/
2888	/******************************************************************************/
2889
2890	( function() {
2891
2892// Based on easing equations from Robert Penner (http://robertpenner.com/easing)
2893
2894		var baseEasings = {};
2895
2896		$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) {
2897			baseEasings[ name ] = function( p ) {
2898				return Math.pow( p, i + 2 );
2899			};
2900		} );
2901
2902		$.extend( baseEasings, {
2903			Sine: function( p ) {
2904				return 1 - Math.cos( p * Math.PI / 2 );
2905			},
2906			Circ: function( p ) {
2907				return 1 - Math.sqrt( 1 - p * p );
2908			},
2909			Elastic: function( p ) {
2910				return p === 0 || p === 1 ? p :
2911					-Math.pow( 2, 8 * ( p - 1 ) ) * Math.sin( ( ( p - 1 ) * 80 - 7.5 ) * Math.PI / 15 );
2912			},
2913			Back: function( p ) {
2914				return p * p * ( 3 * p - 2 );
2915			},
2916			Bounce: function( p ) {
2917				var pow2,
2918					bounce = 4;
2919
2920				while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}
2921				return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 );
2922			}
2923		} );
2924
2925		$.each( baseEasings, function( name, easeIn ) {
2926			$.easing[ "easeIn" + name ] = easeIn;
2927			$.easing[ "easeOut" + name ] = function( p ) {
2928				return 1 - easeIn( 1 - p );
2929			};
2930			$.easing[ "easeInOut" + name ] = function( p ) {
2931				return p < 0.5 ?
2932					easeIn( p * 2 ) / 2 :
2933					1 - easeIn( p * -2 + 2 ) / 2;
2934			};
2935		} );
2936
2937	} )();
2938
2939	var effect = $.effects;
2940
2941
2942	/*!
2943 * jQuery UI Effects Blind 1.14.1
2944 * https://jqueryui.com
2945 *
2946 * Copyright OpenJS Foundation and other contributors
2947 * Released under the MIT license.
2948 * https://jquery.org/license
2949 */
2950
2951//>>label: Blind Effect
2952//>>group: Effects
2953//>>description: Blinds the element.
2954//>>docs: https://api.jqueryui.com/blind-effect/
2955//>>demos: https://jqueryui.com/effect/
2956
2957
2958	var effectsEffectBlind = $.effects.define( "blind", "hide", function( options, done ) {
2959		var map = {
2960				up: [ "bottom", "top" ],
2961				vertical: [ "bottom", "top" ],
2962				down: [ "top", "bottom" ],
2963				left: [ "right", "left" ],
2964				horizontal: [ "right", "left" ],
2965				right: [ "left", "right" ]
2966			},
2967			element = $( this ),
2968			direction = options.direction || "up",
2969			start = element.cssClip(),
2970			animate = { clip: $.extend( {}, start ) },
2971			placeholder = $.effects.createPlaceholder( element );
2972
2973		animate.clip[ map[ direction ][ 0 ] ] = animate.clip[ map[ direction ][ 1 ] ];
2974
2975		if ( options.mode === "show" ) {
2976			element.cssClip( animate.clip );
2977			if ( placeholder ) {
2978				placeholder.css( $.effects.clipToBox( animate ) );
2979			}
2980
2981			animate.clip = start;
2982		}
2983
2984		if ( placeholder ) {
2985			placeholder.animate( $.effects.clipToBox( animate ), options.duration, options.easing );
2986		}
2987
2988		element.animate( animate, {
2989			queue: false,
2990			duration: options.duration,
2991			easing: options.easing,
2992			complete: done
2993		} );
2994	} );
2995
2996
2997	/*!
2998 * jQuery UI Effects Bounce 1.14.1
2999 * https://jqueryui.com
3000 *
3001 * Copyright OpenJS Foundation and other contributors
3002 * Released under the MIT license.
3003 * https://jquery.org/license
3004 */
3005
3006//>>label: Bounce Effect
3007//>>group: Effects
3008//>>description: Bounces an element horizontally or vertically n times.
3009//>>docs: https://api.jqueryui.com/bounce-effect/
3010//>>demos: https://jqueryui.com/effect/
3011
3012
3013	var effectsEffectBounce = $.effects.define( "bounce", function( options, done ) {
3014		var upAnim, downAnim, refValue,
3015			element = $( this ),
3016
3017			// Defaults:
3018			mode = options.mode,
3019			hide = mode === "hide",
3020			show = mode === "show",
3021			direction = options.direction || "up",
3022			distance = options.distance,
3023			times = options.times || 5,
3024
3025			// Number of internal animations
3026			anims = times * 2 + ( show || hide ? 1 : 0 ),
3027			speed = options.duration / anims,
3028			easing = options.easing,
3029
3030			// Utility:
3031			ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
3032			motion = ( direction === "up" || direction === "left" ),
3033			i = 0,
3034
3035			queuelen = element.queue().length;
3036
3037		$.effects.createPlaceholder( element );
3038
3039		refValue = element.css( ref );
3040
3041		// Default distance for the BIGGEST bounce is the outer Distance / 3
3042		if ( !distance ) {
3043			distance = element[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3;
3044		}
3045
3046		if ( show ) {
3047			downAnim = { opacity: 1 };
3048			downAnim[ ref ] = refValue;
3049
3050			// If we are showing, force opacity 0 and set the initial position
3051			// then do the "first" animation
3052			element
3053				.css( "opacity", 0 )
3054				.css( ref, motion ? -distance * 2 : distance * 2 )
3055				.animate( downAnim, speed, easing );
3056		}
3057
3058		// Start at the smallest distance if we are hiding
3059		if ( hide ) {
3060			distance = distance / Math.pow( 2, times - 1 );
3061		}
3062
3063		downAnim = {};
3064		downAnim[ ref ] = refValue;
3065
3066		// Bounces up/down/left/right then back to 0 -- times * 2 animations happen here
3067		for ( ; i < times; i++ ) {
3068			upAnim = {};
3069			upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
3070
3071			element
3072				.animate( upAnim, speed, easing )
3073				.animate( downAnim, speed, easing );
3074
3075			distance = hide ? distance * 2 : distance / 2;
3076		}
3077
3078		// Last Bounce when Hiding
3079		if ( hide ) {
3080			upAnim = { opacity: 0 };
3081			upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
3082
3083			element.animate( upAnim, speed, easing );
3084		}
3085
3086		element.queue( done );
3087
3088		$.effects.unshift( element, queuelen, anims + 1 );
3089	} );
3090
3091
3092	/*!
3093 * jQuery UI Effects Clip 1.14.1
3094 * https://jqueryui.com
3095 *
3096 * Copyright OpenJS Foundation and other contributors
3097 * Released under the MIT license.
3098 * https://jquery.org/license
3099 */
3100
3101//>>label: Clip Effect
3102//>>group: Effects
3103//>>description: Clips the element on and off like an old TV.
3104//>>docs: https://api.jqueryui.com/clip-effect/
3105//>>demos: https://jqueryui.com/effect/
3106
3107
3108	var effectsEffectClip = $.effects.define( "clip", "hide", function( options, done ) {
3109		var start,
3110			animate = {},
3111			element = $( this ),
3112			direction = options.direction || "vertical",
3113			both = direction === "both",
3114			horizontal = both || direction === "horizontal",
3115			vertical = both || direction === "vertical";
3116
3117		start = element.cssClip();
3118		animate.clip = {
3119			top: vertical ? ( start.bottom - start.top ) / 2 : start.top,
3120			right: horizontal ? ( start.right - start.left ) / 2 : start.right,
3121			bottom: vertical ? ( start.bottom - start.top ) / 2 : start.bottom,
3122			left: horizontal ? ( start.right - start.left ) / 2 : start.left
3123		};
3124
3125		$.effects.createPlaceholder( element );
3126
3127		if ( options.mode === "show" ) {
3128			element.cssClip( animate.clip );
3129			animate.clip = start;
3130		}
3131
3132		element.animate( animate, {
3133			queue: false,
3134			duration: options.duration,
3135			easing: options.easing,
3136			complete: done
3137		} );
3138
3139	} );
3140
3141
3142	/*!
3143 * jQuery UI Effects Drop 1.14.1
3144 * https://jqueryui.com
3145 *
3146 * Copyright OpenJS Foundation and other contributors
3147 * Released under the MIT license.
3148 * https://jquery.org/license
3149 */
3150
3151//>>label: Drop Effect
3152//>>group: Effects
3153//>>description: Moves an element in one direction and hides it at the same time.
3154//>>docs: https://api.jqueryui.com/drop-effect/
3155//>>demos: https://jqueryui.com/effect/
3156
3157
3158	var effectsEffectDrop = $.effects.define( "drop", "hide", function( options, done ) {
3159
3160		var distance,
3161			element = $( this ),
3162			mode = options.mode,
3163			show = mode === "show",
3164			direction = options.direction || "left",
3165			ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
3166			motion = ( direction === "up" || direction === "left" ) ? "-=" : "+=",
3167			oppositeMotion = ( motion === "+=" ) ? "-=" : "+=",
3168			animation = {
3169				opacity: 0
3170			};
3171
3172		$.effects.createPlaceholder( element );
3173
3174		distance = options.distance ||
3175			element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ) / 2;
3176
3177		animation[ ref ] = motion + distance;
3178
3179		if ( show ) {
3180			element.css( animation );
3181
3182			animation[ ref ] = oppositeMotion + distance;
3183			animation.opacity = 1;
3184		}
3185
3186		// Animate
3187		element.animate( animation, {
3188			queue: false,
3189			duration: options.duration,
3190			easing: options.easing,
3191			complete: done
3192		} );
3193	} );
3194
3195
3196	/*!
3197 * jQuery UI Effects Explode 1.14.1
3198 * https://jqueryui.com
3199 *
3200 * Copyright OpenJS Foundation and other contributors
3201 * Released under the MIT license.
3202 * https://jquery.org/license
3203 */
3204
3205//>>label: Explode Effect
3206//>>group: Effects
3207	/* eslint-disable max-len */
3208//>>description: Explodes an element in all directions into n pieces. Implodes an element to its original wholeness.
3209	/* eslint-enable max-len */
3210//>>docs: https://api.jqueryui.com/explode-effect/
3211//>>demos: https://jqueryui.com/effect/
3212
3213
3214	var effectsEffectExplode = $.effects.define( "explode", "hide", function( options, done ) {
3215
3216		var i, j, left, top, mx, my,
3217			rows = options.pieces ? Math.round( Math.sqrt( options.pieces ) ) : 3,
3218			cells = rows,
3219			element = $( this ),
3220			mode = options.mode,
3221			show = mode === "show",
3222
3223			// Show and then visibility:hidden the element before calculating offset
3224			offset = element.show().css( "visibility", "hidden" ).offset(),
3225
3226			// Width and height of a piece
3227			width = Math.ceil( element.outerWidth() / cells ),
3228			height = Math.ceil( element.outerHeight() / rows ),
3229			pieces = [];
3230
3231		// Children animate complete:
3232		function childComplete() {
3233			pieces.push( this );
3234			if ( pieces.length === rows * cells ) {
3235				animComplete();
3236			}
3237		}
3238
3239		// Clone the element for each row and cell.
3240		for ( i = 0; i < rows; i++ ) { // ===>
3241			top = offset.top + i * height;
3242			my = i - ( rows - 1 ) / 2;
3243
3244			for ( j = 0; j < cells; j++ ) { // |||
3245				left = offset.left + j * width;
3246				mx = j - ( cells - 1 ) / 2;
3247
3248				// Create a clone of the now hidden main element that will be absolute positioned
3249				// within a wrapper div off the -left and -top equal to size of our pieces
3250				element
3251					.clone()
3252					.appendTo( "body" )
3253					.wrap( "<div></div>" )
3254					.css( {
3255						position: "absolute",
3256						visibility: "visible",
3257						left: -j * width,
3258						top: -i * height
3259					} )
3260
3261					// Select the wrapper - make it overflow: hidden and absolute positioned based on
3262					// where the original was located +left and +top equal to the size of pieces
3263					.parent()
3264					.addClass( "ui-effects-explode" )
3265					.css( {
3266						position: "absolute",
3267						overflow: "hidden",
3268						width: width,
3269						height: height,
3270						left: left + ( show ? mx * width : 0 ),
3271						top: top + ( show ? my * height : 0 ),
3272						opacity: show ? 0 : 1
3273					} )
3274					.animate( {
3275						left: left + ( show ? 0 : mx * width ),
3276						top: top + ( show ? 0 : my * height ),
3277						opacity: show ? 1 : 0
3278					}, options.duration || 500, options.easing, childComplete );
3279			}
3280		}
3281
3282		function animComplete() {
3283			element.css( {
3284				visibility: "visible"
3285			} );
3286			$( pieces ).remove();
3287			done();
3288		}
3289	} );
3290
3291
3292	/*!
3293 * jQuery UI Effects Fade 1.14.1
3294 * https://jqueryui.com
3295 *
3296 * Copyright OpenJS Foundation and other contributors
3297 * Released under the MIT license.
3298 * https://jquery.org/license
3299 */
3300
3301//>>label: Fade Effect
3302//>>group: Effects
3303//>>description: Fades the element.
3304//>>docs: https://api.jqueryui.com/fade-effect/
3305//>>demos: https://jqueryui.com/effect/
3306
3307
3308	var effectsEffectFade = $.effects.define( "fade", "toggle", function( options, done ) {
3309		var show = options.mode === "show";
3310
3311		$( this )
3312			.css( "opacity", show ? 0 : 1 )
3313			.animate( {
3314				opacity: show ? 1 : 0
3315			}, {
3316				queue: false,
3317				duration: options.duration,
3318				easing: options.easing,
3319				complete: done
3320			} );
3321	} );
3322
3323
3324	/*!
3325 * jQuery UI Effects Fold 1.14.1
3326 * https://jqueryui.com
3327 *
3328 * Copyright OpenJS Foundation and other contributors
3329 * Released under the MIT license.
3330 * https://jquery.org/license
3331 */
3332
3333//>>label: Fold Effect
3334//>>group: Effects
3335//>>description: Folds an element first horizontally and then vertically.
3336//>>docs: https://api.jqueryui.com/fold-effect/
3337//>>demos: https://jqueryui.com/effect/
3338
3339
3340	var effectsEffectFold = $.effects.define( "fold", "hide", function( options, done ) {
3341
3342		// Create element
3343		var element = $( this ),
3344			mode = options.mode,
3345			show = mode === "show",
3346			hide = mode === "hide",
3347			size = options.size || 15,
3348			percent = /([0-9]+)%/.exec( size ),
3349			horizFirst = !!options.horizFirst,
3350			ref = horizFirst ? [ "right", "bottom" ] : [ "bottom", "right" ],
3351			duration = options.duration / 2,
3352
3353			placeholder = $.effects.createPlaceholder( element ),
3354
3355			start = element.cssClip(),
3356			animation1 = { clip: $.extend( {}, start ) },
3357			animation2 = { clip: $.extend( {}, start ) },
3358
3359			distance = [ start[ ref[ 0 ] ], start[ ref[ 1 ] ] ],
3360
3361			queuelen = element.queue().length;
3362
3363		if ( percent ) {
3364			size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ];
3365		}
3366		animation1.clip[ ref[ 0 ] ] = size;
3367		animation2.clip[ ref[ 0 ] ] = size;
3368		animation2.clip[ ref[ 1 ] ] = 0;
3369
3370		if ( show ) {
3371			element.cssClip( animation2.clip );
3372			if ( placeholder ) {
3373				placeholder.css( $.effects.clipToBox( animation2 ) );
3374			}
3375
3376			animation2.clip = start;
3377		}
3378
3379		// Animate
3380		element
3381			.queue( function( next ) {
3382				if ( placeholder ) {
3383					placeholder
3384						.animate( $.effects.clipToBox( animation1 ), duration, options.easing )
3385						.animate( $.effects.clipToBox( animation2 ), duration, options.easing );
3386				}
3387
3388				next();
3389			} )
3390			.animate( animation1, duration, options.easing )
3391			.animate( animation2, duration, options.easing )
3392			.queue( done );
3393
3394		$.effects.unshift( element, queuelen, 4 );
3395	} );
3396
3397
3398	/*!
3399 * jQuery UI Effects Highlight 1.14.1
3400 * https://jqueryui.com
3401 *
3402 * Copyright OpenJS Foundation and other contributors
3403 * Released under the MIT license.
3404 * https://jquery.org/license
3405 */
3406
3407//>>label: Highlight Effect
3408//>>group: Effects
3409//>>description: Highlights the background of an element in a defined color for a custom duration.
3410//>>docs: https://api.jqueryui.com/highlight-effect/
3411//>>demos: https://jqueryui.com/effect/
3412
3413
3414	var effectsEffectHighlight = $.effects.define( "highlight", "show", function( options, done ) {
3415		var element = $( this ),
3416			animation = {
3417				backgroundColor: element.css( "backgroundColor" )
3418			};
3419
3420		if ( options.mode === "hide" ) {
3421			animation.opacity = 0;
3422		}
3423
3424		$.effects.saveStyle( element );
3425
3426		element
3427			.css( {
3428				backgroundImage: "none",
3429				backgroundColor: options.color || "#ffff99"
3430			} )
3431			.animate( animation, {
3432				queue: false,
3433				duration: options.duration,
3434				easing: options.easing,
3435				complete: done
3436			} );
3437	} );
3438
3439
3440	/*!
3441 * jQuery UI Effects Size 1.14.1
3442 * https://jqueryui.com
3443 *
3444 * Copyright OpenJS Foundation and other contributors
3445 * Released under the MIT license.
3446 * https://jquery.org/license
3447 */
3448
3449//>>label: Size Effect
3450//>>group: Effects
3451//>>description: Resize an element to a specified width and height.
3452//>>docs: https://api.jqueryui.com/size-effect/
3453//>>demos: https://jqueryui.com/effect/
3454
3455
3456	var effectsEffectSize = $.effects.define( "size", function( options, done ) {
3457
3458		// Create element
3459		var baseline, factor, temp,
3460			element = $( this ),
3461
3462			// Copy for children
3463			cProps = [ "fontSize" ],
3464			vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ],
3465			hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ],
3466
3467			// Set options
3468			mode = options.mode,
3469			restore = mode !== "effect",
3470			scale = options.scale || "both",
3471			origin = options.origin || [ "middle", "center" ],
3472			position = element.css( "position" ),
3473			pos = element.position(),
3474			original = $.effects.scaledDimensions( element ),
3475			from = options.from || original,
3476			to = options.to || $.effects.scaledDimensions( element, 0 );
3477
3478		$.effects.createPlaceholder( element );
3479
3480		if ( mode === "show" ) {
3481			temp = from;
3482			from = to;
3483			to = temp;
3484		}
3485
3486		// Set scaling factor
3487		factor = {
3488			from: {
3489				y: from.height / original.height,
3490				x: from.width / original.width
3491			},
3492			to: {
3493				y: to.height / original.height,
3494				x: to.width / original.width
3495			}
3496		};
3497
3498		// Scale the css box
3499		if ( scale === "box" || scale === "both" ) {
3500
3501			// Vertical props scaling
3502			if ( factor.from.y !== factor.to.y ) {
3503				from = $.effects.setTransition( element, vProps, factor.from.y, from );
3504				to = $.effects.setTransition( element, vProps, factor.to.y, to );
3505			}
3506
3507			// Horizontal props scaling
3508			if ( factor.from.x !== factor.to.x ) {
3509				from = $.effects.setTransition( element, hProps, factor.from.x, from );
3510				to = $.effects.setTransition( element, hProps, factor.to.x, to );
3511			}
3512		}
3513
3514		// Scale the content
3515		if ( scale === "content" || scale === "both" ) {
3516
3517			// Vertical props scaling
3518			if ( factor.from.y !== factor.to.y ) {
3519				from = $.effects.setTransition( element, cProps, factor.from.y, from );
3520				to = $.effects.setTransition( element, cProps, factor.to.y, to );
3521			}
3522		}
3523
3524		// Adjust the position properties based on the provided origin points
3525		if ( origin ) {
3526			baseline = $.effects.getBaseline( origin, original );
3527			from.top = ( original.outerHeight - from.outerHeight ) * baseline.y + pos.top;
3528			from.left = ( original.outerWidth - from.outerWidth ) * baseline.x + pos.left;
3529			to.top = ( original.outerHeight - to.outerHeight ) * baseline.y + pos.top;
3530			to.left = ( original.outerWidth - to.outerWidth ) * baseline.x + pos.left;
3531		}
3532		delete from.outerHeight;
3533		delete from.outerWidth;
3534		element.css( from );
3535
3536		// Animate the children if desired
3537		if ( scale === "content" || scale === "both" ) {
3538
3539			vProps = vProps.concat( [ "marginTop", "marginBottom" ] ).concat( cProps );
3540			hProps = hProps.concat( [ "marginLeft", "marginRight" ] );
3541
3542			// Only animate children with width attributes specified
3543			// TODO: is this right? should we include anything with css width specified as well
3544			element.find( "*[width]" ).each( function() {
3545				var child = $( this ),
3546					childOriginal = $.effects.scaledDimensions( child ),
3547					childFrom = {
3548						height: childOriginal.height * factor.from.y,
3549						width: childOriginal.width * factor.from.x,
3550						outerHeight: childOriginal.outerHeight * factor.from.y,
3551						outerWidth: childOriginal.outerWidth * factor.from.x
3552					},
3553					childTo = {
3554						height: childOriginal.height * factor.to.y,
3555						width: childOriginal.width * factor.to.x,
3556						outerHeight: childOriginal.height * factor.to.y,
3557						outerWidth: childOriginal.width * factor.to.x
3558					};
3559
3560				// Vertical props scaling
3561				if ( factor.from.y !== factor.to.y ) {
3562					childFrom = $.effects.setTransition( child, vProps, factor.from.y, childFrom );
3563					childTo = $.effects.setTransition( child, vProps, factor.to.y, childTo );
3564				}
3565
3566				// Horizontal props scaling
3567				if ( factor.from.x !== factor.to.x ) {
3568					childFrom = $.effects.setTransition( child, hProps, factor.from.x, childFrom );
3569					childTo = $.effects.setTransition( child, hProps, factor.to.x, childTo );
3570				}
3571
3572				if ( restore ) {
3573					$.effects.saveStyle( child );
3574				}
3575
3576				// Animate children
3577				child.css( childFrom );
3578				child.animate( childTo, options.duration, options.easing, function() {
3579
3580					// Restore children
3581					if ( restore ) {
3582						$.effects.restoreStyle( child );
3583					}
3584				} );
3585			} );
3586		}
3587
3588		// Animate
3589		element.animate( to, {
3590			queue: false,
3591			duration: options.duration,
3592			easing: options.easing,
3593			complete: function() {
3594
3595				var offset = element.offset();
3596
3597				if ( to.opacity === 0 ) {
3598					element.css( "opacity", from.opacity );
3599				}
3600
3601				if ( !restore ) {
3602					element
3603						.css( "position", position === "static" ? "relative" : position )
3604						.offset( offset );
3605
3606					// Need to save style here so that automatic style restoration
3607					// doesn't restore to the original styles from before the animation.
3608					$.effects.saveStyle( element );
3609				}
3610
3611				done();
3612			}
3613		} );
3614
3615	} );
3616
3617
3618	/*!
3619 * jQuery UI Effects Scale 1.14.1
3620 * https://jqueryui.com
3621 *
3622 * Copyright OpenJS Foundation and other contributors
3623 * Released under the MIT license.
3624 * https://jquery.org/license
3625 */
3626
3627//>>label: Scale Effect
3628//>>group: Effects
3629//>>description: Grows or shrinks an element and its content.
3630//>>docs: https://api.jqueryui.com/scale-effect/
3631//>>demos: https://jqueryui.com/effect/
3632
3633
3634	var effectsEffectScale = $.effects.define( "scale", function( options, done ) {
3635
3636		// Create element
3637		var el = $( this ),
3638			mode = options.mode,
3639			percent = parseInt( options.percent, 10 ) ||
3640				( parseInt( options.percent, 10 ) === 0 ? 0 : ( mode !== "effect" ? 0 : 100 ) ),
3641
3642			newOptions = $.extend( true, {
3643				from: $.effects.scaledDimensions( el ),
3644				to: $.effects.scaledDimensions( el, percent, options.direction || "both" ),
3645				origin: options.origin || [ "middle", "center" ]
3646			}, options );
3647
3648		// Fade option to support puff
3649		if ( options.fade ) {
3650			newOptions.from.opacity = 1;
3651			newOptions.to.opacity = 0;
3652		}
3653
3654		$.effects.effect.size.call( this, newOptions, done );
3655	} );
3656
3657
3658	/*!
3659 * jQuery UI Effects Puff 1.14.1
3660 * https://jqueryui.com
3661 *
3662 * Copyright OpenJS Foundation and other contributors
3663 * Released under the MIT license.
3664 * https://jquery.org/license
3665 */
3666
3667//>>label: Puff Effect
3668//>>group: Effects
3669//>>description: Creates a puff effect by scaling the element up and hiding it at the same time.
3670//>>docs: https://api.jqueryui.com/puff-effect/
3671//>>demos: https://jqueryui.com/effect/
3672
3673
3674	var effectsEffectPuff = $.effects.define( "puff", "hide", function( options, done ) {
3675		var newOptions = $.extend( true, {}, options, {
3676			fade: true,
3677			percent: parseInt( options.percent, 10 ) || 150
3678		} );
3679
3680		$.effects.effect.scale.call( this, newOptions, done );
3681	} );
3682
3683
3684	/*!
3685 * jQuery UI Effects Pulsate 1.14.1
3686 * https://jqueryui.com
3687 *
3688 * Copyright OpenJS Foundation and other contributors
3689 * Released under the MIT license.
3690 * https://jquery.org/license
3691 */
3692
3693//>>label: Pulsate Effect
3694//>>group: Effects
3695//>>description: Pulsates an element n times by changing the opacity to zero and back.
3696//>>docs: https://api.jqueryui.com/pulsate-effect/
3697//>>demos: https://jqueryui.com/effect/
3698
3699
3700	var effectsEffectPulsate = $.effects.define( "pulsate", "show", function( options, done ) {
3701		var element = $( this ),
3702			mode = options.mode,
3703			show = mode === "show",
3704			hide = mode === "hide",
3705			showhide = show || hide,
3706
3707			// Showing or hiding leaves off the "last" animation
3708			anims = ( ( options.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ),
3709			duration = options.duration / anims,
3710			animateTo = 0,
3711			i = 1,
3712			queuelen = element.queue().length;
3713
3714		if ( show || !element.is( ":visible" ) ) {
3715			element.css( "opacity", 0 ).show();
3716			animateTo = 1;
3717		}
3718
3719		// Anims - 1 opacity "toggles"
3720		for ( ; i < anims; i++ ) {
3721			element.animate( { opacity: animateTo }, duration, options.easing );
3722			animateTo = 1 - animateTo;
3723		}
3724
3725		element.animate( { opacity: animateTo }, duration, options.easing );
3726
3727		element.queue( done );
3728
3729		$.effects.unshift( element, queuelen, anims + 1 );
3730	} );
3731
3732
3733	/*!
3734 * jQuery UI Effects Shake 1.14.1
3735 * https://jqueryui.com
3736 *
3737 * Copyright OpenJS Foundation and other contributors
3738 * Released under the MIT license.
3739 * https://jquery.org/license
3740 */
3741
3742//>>label: Shake Effect
3743//>>group: Effects
3744//>>description: Shakes an element horizontally or vertically n times.
3745//>>docs: https://api.jqueryui.com/shake-effect/
3746//>>demos: https://jqueryui.com/effect/
3747
3748
3749	var effectsEffectShake = $.effects.define( "shake", function( options, done ) {
3750
3751		var i = 1,
3752			element = $( this ),
3753			direction = options.direction || "left",
3754			distance = options.distance || 20,
3755			times = options.times || 3,
3756			anims = times * 2 + 1,
3757			speed = Math.round( options.duration / anims ),
3758			ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
3759			positiveMotion = ( direction === "up" || direction === "left" ),
3760			animation = {},
3761			animation1 = {},
3762			animation2 = {},
3763
3764			queuelen = element.queue().length;
3765
3766		$.effects.createPlaceholder( element );
3767
3768		// Animation
3769		animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance;
3770		animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2;
3771		animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2;
3772
3773		// Animate
3774		element.animate( animation, speed, options.easing );
3775
3776		// Shakes
3777		for ( ; i < times; i++ ) {
3778			element
3779				.animate( animation1, speed, options.easing )
3780				.animate( animation2, speed, options.easing );
3781		}
3782
3783		element
3784			.animate( animation1, speed, options.easing )
3785			.animate( animation, speed / 2, options.easing )
3786			.queue( done );
3787
3788		$.effects.unshift( element, queuelen, anims + 1 );
3789	} );
3790
3791
3792	/*!
3793 * jQuery UI Effects Slide 1.14.1
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: Slide Effect
3802//>>group: Effects
3803//>>description: Slides an element in and out of the viewport.
3804//>>docs: https://api.jqueryui.com/slide-effect/
3805//>>demos: https://jqueryui.com/effect/
3806
3807
3808	var effectsEffectSlide = $.effects.define( "slide", "show", function( options, done ) {
3809		var startClip, startRef,
3810			element = $( this ),
3811			map = {
3812				up: [ "bottom", "top" ],
3813				down: [ "top", "bottom" ],
3814				left: [ "right", "left" ],
3815				right: [ "left", "right" ]
3816			},
3817			mode = options.mode,
3818			direction = options.direction || "left",
3819			ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
3820			positiveMotion = ( direction === "up" || direction === "left" ),
3821			distance = options.distance ||
3822				element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ),
3823			animation = {};
3824
3825		$.effects.createPlaceholder( element );
3826
3827		startClip = element.cssClip();
3828		startRef = element.position()[ ref ];
3829
3830		// Define hide animation
3831		animation[ ref ] = ( positiveMotion ? -1 : 1 ) * distance + startRef;
3832		animation.clip = element.cssClip();
3833		animation.clip[ map[ direction ][ 1 ] ] = animation.clip[ map[ direction ][ 0 ] ];
3834
3835		// Reverse the animation if we're showing
3836		if ( mode === "show" ) {
3837			element.cssClip( animation.clip );
3838			element.css( ref, animation[ ref ] );
3839			animation.clip = startClip;
3840			animation[ ref ] = startRef;
3841		}
3842
3843		// Actually animate
3844		element.animate( animation, {
3845			queue: false,
3846			duration: options.duration,
3847			easing: options.easing,
3848			complete: done
3849		} );
3850	} );
3851
3852
3853	/*!
3854 * jQuery UI Effects Transfer 1.14.1
3855 * https://jqueryui.com
3856 *
3857 * Copyright OpenJS Foundation and other contributors
3858 * Released under the MIT license.
3859 * https://jquery.org/license
3860 */
3861
3862//>>label: Transfer Effect
3863//>>group: Effects
3864//>>description: Displays a transfer effect from one element to another.
3865//>>docs: https://api.jqueryui.com/transfer-effect/
3866//>>demos: https://jqueryui.com/effect/
3867
3868
3869	var effect;
3870	if ( $.uiBackCompat === true ) {
3871		effect = $.effects.define( "transfer", function( options, done ) {
3872			$( this ).transfer( options, done );
3873		} );
3874	}
3875	var effectsEffectTransfer = effect;
3876
3877
3878	/*!
3879 * jQuery UI Focusable 1.14.1
3880 * https://jqueryui.com
3881 *
3882 * Copyright OpenJS Foundation and other contributors
3883 * Released under the MIT license.
3884 * https://jquery.org/license
3885 */
3886
3887//>>label: :focusable Selector
3888//>>group: Core
3889//>>description: Selects elements which can be focused.
3890//>>docs: https://api.jqueryui.com/focusable-selector/
3891
3892
3893// Selectors
3894	$.ui.focusable = function( element, hasTabindex ) {
3895		var map, mapName, img, focusableIfVisible, fieldset,
3896			nodeName = element.nodeName.toLowerCase();
3897
3898		if ( "area" === nodeName ) {
3899			map = element.parentNode;
3900			mapName = map.name;
3901			if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
3902				return false;
3903			}
3904			img = $( "img[usemap='#" + mapName + "']" );
3905			return img.length > 0 && img.is( ":visible" );
3906		}
3907
3908		if ( /^(input|select|textarea|button|object)$/.test( nodeName ) ) {
3909			focusableIfVisible = !element.disabled;
3910
3911			if ( focusableIfVisible ) {
3912
3913				// Form controls within a disabled fieldset are disabled.
3914				// However, controls within the fieldset's legend do not get disabled.
3915				// Since controls generally aren't placed inside legends, we skip
3916				// this portion of the check.
3917				fieldset = $( element ).closest( "fieldset" )[ 0 ];
3918				if ( fieldset ) {
3919					focusableIfVisible = !fieldset.disabled;
3920				}
3921			}
3922		} else if ( "a" === nodeName ) {
3923			focusableIfVisible = element.href || hasTabindex;
3924		} else {
3925			focusableIfVisible = hasTabindex;
3926		}
3927
3928		return focusableIfVisible && $( element ).is( ":visible" ) &&
3929			$( element ).css( "visibility" ) === "visible";
3930	};
3931
3932	$.extend( $.expr.pseudos, {
3933		focusable: function( element ) {
3934			return $.ui.focusable( element, $.attr( element, "tabindex" ) != null );
3935		}
3936	} );
3937
3938	var focusable = $.ui.focusable;
3939
3940
3941	/*!
3942 * jQuery UI Form Reset Mixin 1.14.1
3943 * https://jqueryui.com
3944 *
3945 * Copyright OpenJS Foundation and other contributors
3946 * Released under the MIT license.
3947 * https://jquery.org/license
3948 */
3949
3950//>>label: Form Reset Mixin
3951//>>group: Core
3952//>>description: Refresh input widgets when their form is reset
3953//>>docs: https://api.jqueryui.com/form-reset-mixin/
3954
3955
3956	var formResetMixin = $.ui.formResetMixin = {
3957		_formResetHandler: function() {
3958			var form = $( this );
3959
3960			// Wait for the form reset to actually happen before refreshing
3961			setTimeout( function() {
3962				var instances = form.data( "ui-form-reset-instances" );
3963				$.each( instances, function() {
3964					this.refresh();
3965				} );
3966			} );
3967		},
3968
3969		_bindFormResetHandler: function() {
3970			this.form = $( this.element.prop( "form" ) );
3971			if ( !this.form.length ) {
3972				return;
3973			}
3974
3975			var instances = this.form.data( "ui-form-reset-instances" ) || [];
3976			if ( !instances.length ) {
3977
3978				// We don't use _on() here because we use a single event handler per form
3979				this.form.on( "reset.ui-form-reset", this._formResetHandler );
3980			}
3981			instances.push( this );
3982			this.form.data( "ui-form-reset-instances", instances );
3983		},
3984
3985		_unbindFormResetHandler: function() {
3986			if ( !this.form.length ) {
3987				return;
3988			}
3989
3990			var instances = this.form.data( "ui-form-reset-instances" );
3991			instances.splice( $.inArray( this, instances ), 1 );
3992			if ( instances.length ) {
3993				this.form.data( "ui-form-reset-instances", instances );
3994			} else {
3995				this.form
3996					.removeData( "ui-form-reset-instances" )
3997					.off( "reset.ui-form-reset" );
3998			}
3999		}
4000	};
4001
4002
4003	/*!
4004 * jQuery UI Legacy jQuery Core patches 1.14.1
4005 * https://jqueryui.com
4006 *
4007 * Copyright OpenJS Foundation and other contributors
4008 * Released under the MIT license.
4009 * https://jquery.org/license
4010 *
4011 */
4012
4013//>>label: Legacy jQuery Core patches
4014//>>group: Core
4015//>>description: Backport `.even()`, `.odd()` and `$.escapeSelector` to older jQuery Core versions (deprecated)
4016
4017
4018// Support: jQuery 2.2.x or older.
4019// This method has been defined in jQuery 3.0.0.
4020// Code from https://github.com/jquery/jquery/blob/e539bac79e666bba95bba86d690b4e609dca2286/src/selector/escapeSelector.js
4021	if ( !$.escapeSelector ) {
4022		$.escapeSelector = function( id ) {
4023			return CSS.escape( id + "" );
4024		};
4025	}
4026
4027// Support: jQuery 3.4.x or older
4028// These methods have been defined in jQuery 3.5.0.
4029	if ( !$.fn.even || !$.fn.odd ) {
4030		$.fn.extend( {
4031			even: function() {
4032				return this.filter( function( i ) {
4033					return i % 2 === 0;
4034				} );
4035			},
4036			odd: function() {
4037				return this.filter( function( i ) {
4038					return i % 2 === 1;
4039				} );
4040			}
4041		} );
4042	}
4043
4044	;
4045	/*!
4046 * jQuery UI Keycode 1.14.1
4047 * https://jqueryui.com
4048 *
4049 * Copyright OpenJS Foundation and other contributors
4050 * Released under the MIT license.
4051 * https://jquery.org/license
4052 */
4053
4054//>>label: Keycode
4055//>>group: Core
4056//>>description: Provide keycodes as keynames
4057//>>docs: https://api.jqueryui.com/jQuery.ui.keyCode/
4058
4059
4060	var keycode = $.ui.keyCode = {
4061		BACKSPACE: 8,
4062		COMMA: 188,
4063		DELETE: 46,
4064		DOWN: 40,
4065		END: 35,
4066		ENTER: 13,
4067		ESCAPE: 27,
4068		HOME: 36,
4069		LEFT: 37,
4070		PAGE_DOWN: 34,
4071		PAGE_UP: 33,
4072		PERIOD: 190,
4073		RIGHT: 39,
4074		SPACE: 32,
4075		TAB: 9,
4076		UP: 38
4077	};
4078
4079
4080	/*!
4081 * jQuery UI Labels 1.14.1
4082 * https://jqueryui.com
4083 *
4084 * Copyright OpenJS Foundation and other contributors
4085 * Released under the MIT license.
4086 * https://jquery.org/license
4087 */
4088
4089//>>label: labels
4090//>>group: Core
4091//>>description: Find all the labels associated with a given input
4092//>>docs: https://api.jqueryui.com/labels/
4093
4094
4095	var labels = $.fn.labels = function() {
4096		var ancestor, selector, id, labels, ancestors;
4097
4098		if ( !this.length ) {
4099			return this.pushStack( [] );
4100		}
4101
4102		// Check control.labels first
4103		if ( this[ 0 ].labels && this[ 0 ].labels.length ) {
4104			return this.pushStack( this[ 0 ].labels );
4105		}
4106
4107		// If `control.labels` is empty - e.g. inside of document fragments - find
4108		// the labels manually
4109		labels = this.eq( 0 ).parents( "label" );
4110
4111		// Look for the label based on the id
4112		id = this.attr( "id" );
4113		if ( id ) {
4114
4115			// We don't search against the document in case the element
4116			// is disconnected from the DOM
4117			ancestor = this.eq( 0 ).parents().last();
4118
4119			// Get a full set of top level ancestors
4120			ancestors = ancestor.add( ancestor.length ? ancestor.siblings() : this.siblings() );
4121
4122			// Create a selector for the label based on the id
4123			selector = "label[for='" + CSS.escape( id ) + "']";
4124
4125			labels = labels.add( ancestors.find( selector ).addBack( selector ) );
4126
4127		}
4128
4129		// Return whatever we have found for labels
4130		return this.pushStack( labels );
4131	};
4132
4133
4134	/*!
4135 * jQuery UI Scroll Parent 1.14.1
4136 * https://jqueryui.com
4137 *
4138 * Copyright OpenJS Foundation and other contributors
4139 * Released under the MIT license.
4140 * https://jquery.org/license
4141 */
4142
4143//>>label: scrollParent
4144//>>group: Core
4145//>>description: Get the closest ancestor element that is scrollable.
4146//>>docs: https://api.jqueryui.com/scrollParent/
4147
4148
4149	var scrollParent = $.fn.scrollParent = function( includeHidden ) {
4150		var position = this.css( "position" ),
4151			excludeStaticParent = position === "absolute",
4152			overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/,
4153			scrollParent = this.parents().filter( function() {
4154				var parent = $( this );
4155				if ( excludeStaticParent && parent.css( "position" ) === "static" ) {
4156					return false;
4157				}
4158				return overflowRegex.test( parent.css( "overflow" ) + parent.css( "overflow-y" ) +
4159					parent.css( "overflow-x" ) );
4160			} ).eq( 0 );
4161
4162		return position === "fixed" || !scrollParent.length ?
4163			$( this[ 0 ].ownerDocument || document ) :
4164			scrollParent;
4165	};
4166
4167
4168	/*!
4169 * jQuery UI Tabbable 1.14.1
4170 * https://jqueryui.com
4171 *
4172 * Copyright OpenJS Foundation and other contributors
4173 * Released under the MIT license.
4174 * https://jquery.org/license
4175 */
4176
4177//>>label: :tabbable Selector
4178//>>group: Core
4179//>>description: Selects elements which can be tabbed to.
4180//>>docs: https://api.jqueryui.com/tabbable-selector/
4181
4182
4183	var tabbable = $.extend( $.expr.pseudos, {
4184		tabbable: function( element ) {
4185			var tabIndex = $.attr( element, "tabindex" ),
4186				hasTabindex = tabIndex != null;
4187			return ( !hasTabindex || tabIndex >= 0 ) && $.ui.focusable( element, hasTabindex );
4188		}
4189	} );
4190
4191
4192	/*!
4193 * jQuery UI Unique ID 1.14.1
4194 * https://jqueryui.com
4195 *
4196 * Copyright OpenJS Foundation and other contributors
4197 * Released under the MIT license.
4198 * https://jquery.org/license
4199 */
4200
4201//>>label: uniqueId
4202//>>group: Core
4203//>>description: Functions to generate and remove uniqueId's
4204//>>docs: https://api.jqueryui.com/uniqueId/
4205
4206
4207	var uniqueId = $.fn.extend( {
4208		uniqueId: ( function() {
4209			var uuid = 0;
4210
4211			return function() {
4212				return this.each( function() {
4213					if ( !this.id ) {
4214						this.id = "ui-id-" + ( ++uuid );
4215					}
4216				} );
4217			};
4218		} )(),
4219
4220		removeUniqueId: function() {
4221			return this.each( function() {
4222				if ( /^ui-id-\d+$/.test( this.id ) ) {
4223					$( this ).removeAttr( "id" );
4224				}
4225			} );
4226		}
4227	} );
4228
4229
4230	/*!
4231 * jQuery UI Accordion 1.14.1
4232 * https://jqueryui.com
4233 *
4234 * Copyright OpenJS Foundation and other contributors
4235 * Released under the MIT license.
4236 * https://jquery.org/license
4237 */
4238
4239//>>label: Accordion
4240//>>group: Widgets
4241	/* eslint-disable max-len */
4242//>>description: Displays collapsible content panels for presenting information in a limited amount of space.
4243	/* eslint-enable max-len */
4244//>>docs: https://api.jqueryui.com/accordion/
4245//>>demos: https://jqueryui.com/accordion/
4246//>>css.structure: ../../themes/base/core.css
4247//>>css.structure: ../../themes/base/accordion.css
4248//>>css.theme: ../../themes/base/theme.css
4249
4250
4251	var widgetsAccordion = $.widget( "ui.accordion", {
4252		version: "1.14.1",
4253		options: {
4254			active: 0,
4255			animate: {},
4256			classes: {
4257				"ui-accordion-header": "ui-corner-top",
4258				"ui-accordion-header-collapsed": "ui-corner-all",
4259				"ui-accordion-content": "ui-corner-bottom"
4260			},
4261			collapsible: false,
4262			event: "click",
4263			header: function( elem ) {
4264				return elem
4265					.find( "> li > :first-child" )
4266					.add(
4267						elem.find( "> :not(li)" )
4268
4269							// Support: jQuery <3.5 only
4270							// We could use `.even()` but that's unavailable in older jQuery.
4271							.filter( function( i ) {
4272								return i % 2 === 0;
4273							} )
4274					);
4275			},
4276			heightStyle: "auto",
4277			icons: {
4278				activeHeader: "ui-icon-triangle-1-s",
4279				header: "ui-icon-triangle-1-e"
4280			},
4281
4282			// Callbacks
4283			activate: null,
4284			beforeActivate: null
4285		},
4286
4287		hideProps: {
4288			borderTopWidth: "hide",
4289			borderBottomWidth: "hide",
4290			paddingTop: "hide",
4291			paddingBottom: "hide",
4292			height: "hide"
4293		},
4294
4295		showProps: {
4296			borderTopWidth: "show",
4297			borderBottomWidth: "show",
4298			paddingTop: "show",
4299			paddingBottom: "show",
4300			height: "show"
4301		},
4302
4303		_create: function() {
4304			var options = this.options;
4305
4306			this.prevShow = this.prevHide = $();
4307			this._addClass( "ui-accordion", "ui-widget ui-helper-reset" );
4308			this.element.attr( "role", "tablist" );
4309
4310			// Don't allow collapsible: false and active: false / null
4311			if ( !options.collapsible && ( options.active === false || options.active == null ) ) {
4312				options.active = 0;
4313			}
4314
4315			this._processPanels();
4316
4317			// handle negative values
4318			if ( options.active < 0 ) {
4319				options.active += this.headers.length;
4320			}
4321			this._refresh();
4322		},
4323
4324		_getCreateEventData: function() {
4325			return {
4326				header: this.active,
4327				panel: !this.active.length ? $() : this.active.next()
4328			};
4329		},
4330
4331		_createIcons: function() {
4332			var icon, children,
4333				icons = this.options.icons;
4334
4335			if ( icons ) {
4336				icon = $( "<span>" );
4337				this._addClass( icon, "ui-accordion-header-icon", "ui-icon " + icons.header );
4338				icon.prependTo( this.headers );
4339				children = this.active.children( ".ui-accordion-header-icon" );
4340				this._removeClass( children, icons.header )
4341					._addClass( children, null, icons.activeHeader )
4342					._addClass( this.headers, "ui-accordion-icons" );
4343			}
4344		},
4345
4346		_destroyIcons: function() {
4347			this._removeClass( this.headers, "ui-accordion-icons" );
4348			this.headers.children( ".ui-accordion-header-icon" ).remove();
4349		},
4350
4351		_destroy: function() {
4352			var contents;
4353
4354			// Clean up main element
4355			this.element.removeAttr( "role" );
4356
4357			// Clean up headers
4358			this.headers
4359				.removeAttr( "role aria-expanded aria-selected aria-controls tabIndex" )
4360				.removeUniqueId();
4361
4362			this._destroyIcons();
4363
4364			// Clean up content panels
4365			contents = this.headers.next()
4366				.css( "display", "" )
4367				.removeAttr( "role aria-hidden aria-labelledby" )
4368				.removeUniqueId();
4369
4370			if ( this.options.heightStyle !== "content" ) {
4371				contents.css( "height", "" );
4372			}
4373		},
4374
4375		_setOption: function( key, value ) {
4376			if ( key === "active" ) {
4377
4378				// _activate() will handle invalid values and update this.options
4379				this._activate( value );
4380				return;
4381			}
4382
4383			if ( key === "event" ) {
4384				if ( this.options.event ) {
4385					this._off( this.headers, this.options.event );
4386				}
4387				this._setupEvents( value );
4388			}
4389
4390			this._super( key, value );
4391
4392			// Setting collapsible: false while collapsed; open first panel
4393			if ( key === "collapsible" && !value && this.options.active === false ) {
4394				this._activate( 0 );
4395			}
4396
4397			if ( key === "icons" ) {
4398				this._destroyIcons();
4399				if ( value ) {
4400					this._createIcons();
4401				}
4402			}
4403		},
4404
4405		_setOptionDisabled: function( value ) {
4406			this._super( value );
4407
4408			this.element.attr( "aria-disabled", value );
4409			this._toggleClass( null, "ui-state-disabled", !!value );
4410		},
4411
4412		_keydown: function( event ) {
4413			if ( event.altKey || event.ctrlKey ) {
4414				return;
4415			}
4416
4417			var keyCode = $.ui.keyCode,
4418				length = this.headers.length,
4419				currentIndex = this.headers.index( event.target ),
4420				toFocus = false;
4421
4422			switch ( event.keyCode ) {
4423				case keyCode.RIGHT:
4424				case keyCode.DOWN:
4425					toFocus = this.headers[ ( currentIndex + 1 ) % length ];
4426					break;
4427				case keyCode.LEFT:
4428				case keyCode.UP:
4429					toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
4430					break;
4431				case keyCode.SPACE:
4432				case keyCode.ENTER:
4433					this._eventHandler( event );
4434					break;
4435				case keyCode.HOME:
4436					toFocus = this.headers[ 0 ];
4437					break;
4438				case keyCode.END:
4439					toFocus = this.headers[ length - 1 ];
4440					break;
4441			}
4442
4443			if ( toFocus ) {
4444				$( event.target ).attr( "tabIndex", -1 );
4445				$( toFocus ).attr( "tabIndex", 0 );
4446				$( toFocus ).trigger( "focus" );
4447				event.preventDefault();
4448			}
4449		},
4450
4451		_panelKeyDown: function( event ) {
4452			if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) {
4453				$( event.currentTarget ).prev().trigger( "focus" );
4454			}
4455		},
4456
4457		refresh: function() {
4458			var options = this.options;
4459			this._processPanels();
4460
4461			// Was collapsed or no panel
4462			if ( ( options.active === false && options.collapsible === true ) ||
4463				!this.headers.length ) {
4464				options.active = false;
4465				this.active = $();
4466
4467				// active false only when collapsible is true
4468			} else if ( options.active === false ) {
4469				this._activate( 0 );
4470
4471				// was active, but active panel is gone
4472			} else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
4473
4474				// all remaining panel are disabled
4475				if ( this.headers.length === this.headers.find( ".ui-state-disabled" ).length ) {
4476					options.active = false;
4477					this.active = $();
4478
4479					// activate previous panel
4480				} else {
4481					this._activate( Math.max( 0, options.active - 1 ) );
4482				}
4483
4484				// was active, active panel still exists
4485			} else {
4486
4487				// make sure active index is correct
4488				options.active = this.headers.index( this.active );
4489			}
4490
4491			this._destroyIcons();
4492
4493			this._refresh();
4494		},
4495
4496		_processPanels: function() {
4497			var prevHeaders = this.headers,
4498				prevPanels = this.panels;
4499
4500			if ( typeof this.options.header === "function" ) {
4501				this.headers = this.options.header( this.element );
4502			} else {
4503				this.headers = this.element.find( this.options.header );
4504			}
4505			this._addClass( this.headers, "ui-accordion-header ui-accordion-header-collapsed",
4506				"ui-state-default" );
4507
4508			this.panels = this.headers.next().filter( ":not(.ui-accordion-content-active)" ).hide();
4509			this._addClass( this.panels, "ui-accordion-content", "ui-helper-reset ui-widget-content" );
4510
4511			// Avoid memory leaks (#10056)
4512			if ( prevPanels ) {
4513				this._off( prevHeaders.not( this.headers ) );
4514				this._off( prevPanels.not( this.panels ) );
4515			}
4516		},
4517
4518		_refresh: function() {
4519			var maxHeight,
4520				options = this.options,
4521				heightStyle = options.heightStyle,
4522				parent = this.element.parent();
4523
4524			this.active = this._findActive( options.active );
4525			this._addClass( this.active, "ui-accordion-header-active", "ui-state-active" )
4526				._removeClass( this.active, "ui-accordion-header-collapsed" );
4527			this._addClass( this.active.next(), "ui-accordion-content-active" );
4528			this.active.next().show();
4529
4530			this.headers
4531				.attr( "role", "tab" )
4532				.each( function() {
4533					var header = $( this ),
4534						headerId = header.uniqueId().attr( "id" ),
4535						panel = header.next(),
4536						panelId = panel.uniqueId().attr( "id" );
4537					header.attr( "aria-controls", panelId );
4538					panel.attr( "aria-labelledby", headerId );
4539				} )
4540				.next()
4541				.attr( "role", "tabpanel" );
4542
4543			this.headers
4544				.not( this.active )
4545				.attr( {
4546					"aria-selected": "false",
4547					"aria-expanded": "false",
4548					tabIndex: -1
4549				} )
4550				.next()
4551				.attr( {
4552					"aria-hidden": "true"
4553				} )
4554				.hide();
4555
4556			// Make sure at least one header is in the tab order
4557			if ( !this.active.length ) {
4558				this.headers.eq( 0 ).attr( "tabIndex", 0 );
4559			} else {
4560				this.active.attr( {
4561					"aria-selected": "true",
4562					"aria-expanded": "true",
4563					tabIndex: 0
4564				} )
4565					.next()
4566					.attr( {
4567						"aria-hidden": "false"
4568					} );
4569			}
4570
4571			this._createIcons();
4572
4573			this._setupEvents( options.event );
4574
4575			if ( heightStyle === "fill" ) {
4576				maxHeight = parent.height();
4577				this.element.siblings( ":visible" ).each( function() {
4578					var elem = $( this ),
4579						position = elem.css( "position" );
4580
4581					if ( position === "absolute" || position === "fixed" ) {
4582						return;
4583					}
4584					maxHeight -= elem.outerHeight( true );
4585				} );
4586
4587				this.headers.each( function() {
4588					maxHeight -= $( this ).outerHeight( true );
4589				} );
4590
4591				this.headers.next()
4592					.each( function() {
4593						$( this ).height( Math.max( 0, maxHeight -
4594							$( this ).innerHeight() + $( this ).height() ) );
4595					} )
4596					.css( "overflow", "auto" );
4597			} else if ( heightStyle === "auto" ) {
4598				maxHeight = 0;
4599				this.headers.next()
4600					.each( function() {
4601						var isVisible = $( this ).is( ":visible" );
4602						if ( !isVisible ) {
4603							$( this ).show();
4604						}
4605						maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() );
4606						if ( !isVisible ) {
4607							$( this ).hide();
4608						}
4609					} )
4610					.height( maxHeight );
4611			}
4612		},
4613
4614		_activate: function( index ) {
4615			var active = this._findActive( index )[ 0 ];
4616
4617			// Trying to activate the already active panel
4618			if ( active === this.active[ 0 ] ) {
4619				return;
4620			}
4621
4622			// Trying to collapse, simulate a click on the currently active header
4623			active = active || this.active[ 0 ];
4624
4625			this._eventHandler( {
4626				target: active,
4627				currentTarget: active,
4628				preventDefault: $.noop
4629			} );
4630		},
4631
4632		_findActive: function( selector ) {
4633			return typeof selector === "number" ? this.headers.eq( selector ) : $();
4634		},
4635
4636		_setupEvents: function( event ) {
4637			var events = {
4638				keydown: "_keydown"
4639			};
4640			if ( event ) {
4641				$.each( event.split( " " ), function( index, eventName ) {
4642					events[ eventName ] = "_eventHandler";
4643				} );
4644			}
4645
4646			this._off( this.headers.add( this.headers.next() ) );
4647			this._on( this.headers, events );
4648			this._on( this.headers.next(), { keydown: "_panelKeyDown" } );
4649			this._hoverable( this.headers );
4650			this._focusable( this.headers );
4651		},
4652
4653		_eventHandler: function( event ) {
4654			var activeChildren, clickedChildren,
4655				options = this.options,
4656				active = this.active,
4657				clicked = $( event.currentTarget ),
4658				clickedIsActive = clicked[ 0 ] === active[ 0 ],
4659				collapsing = clickedIsActive && options.collapsible,
4660				toShow = collapsing ? $() : clicked.next(),
4661				toHide = active.next(),
4662				eventData = {
4663					oldHeader: active,
4664					oldPanel: toHide,
4665					newHeader: collapsing ? $() : clicked,
4666					newPanel: toShow
4667				};
4668
4669			event.preventDefault();
4670
4671			if (
4672
4673				// click on active header, but not collapsible
4674				( clickedIsActive && !options.collapsible ) ||
4675
4676				// allow canceling activation
4677				( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
4678				return;
4679			}
4680
4681			options.active = collapsing ? false : this.headers.index( clicked );
4682
4683			// When the call to ._toggle() comes after the class changes
4684			// it causes a very odd bug in IE 8 (see #6720)
4685			this.active = clickedIsActive ? $() : clicked;
4686			this._toggle( eventData );
4687
4688			// Switch classes
4689			// corner classes on the previously active header stay after the animation
4690			this._removeClass( active, "ui-accordion-header-active", "ui-state-active" );
4691			if ( options.icons ) {
4692				activeChildren = active.children( ".ui-accordion-header-icon" );
4693				this._removeClass( activeChildren, null, options.icons.activeHeader )
4694					._addClass( activeChildren, null, options.icons.header );
4695			}
4696
4697			if ( !clickedIsActive ) {
4698				this._removeClass( clicked, "ui-accordion-header-collapsed" )
4699					._addClass( clicked, "ui-accordion-header-active", "ui-state-active" );
4700				if ( options.icons ) {
4701					clickedChildren = clicked.children( ".ui-accordion-header-icon" );
4702					this._removeClass( clickedChildren, null, options.icons.header )
4703						._addClass( clickedChildren, null, options.icons.activeHeader );
4704				}
4705
4706				this._addClass( clicked.next(), "ui-accordion-content-active" );
4707			}
4708		},
4709
4710		_toggle: function( data ) {
4711			var toShow = data.newPanel,
4712				toHide = this.prevShow.length ? this.prevShow : data.oldPanel;
4713
4714			// Handle activating a panel during the animation for another activation
4715			this.prevShow.add( this.prevHide ).stop( true, true );
4716			this.prevShow = toShow;
4717			this.prevHide = toHide;
4718
4719			if ( this.options.animate ) {
4720				this._animate( toShow, toHide, data );
4721			} else {
4722				toHide.hide();
4723				toShow.show();
4724				this._toggleComplete( data );
4725			}
4726
4727			toHide.attr( {
4728				"aria-hidden": "true"
4729			} );
4730			toHide.prev().attr( {
4731				"aria-selected": "false",
4732				"aria-expanded": "false"
4733			} );
4734
4735			// if we're switching panels, remove the old header from the tab order
4736			// if we're opening from collapsed state, remove the previous header from the tab order
4737			// if we're collapsing, then keep the collapsing header in the tab order
4738			if ( toShow.length && toHide.length ) {
4739				toHide.prev().attr( {
4740					"tabIndex": -1,
4741					"aria-expanded": "false"
4742				} );
4743			} else if ( toShow.length ) {
4744				this.headers.filter( function() {
4745					return parseInt( $( this ).attr( "tabIndex" ), 10 ) === 0;
4746				} )
4747					.attr( "tabIndex", -1 );
4748			}
4749
4750			toShow
4751				.attr( "aria-hidden", "false" )
4752				.prev()
4753				.attr( {
4754					"aria-selected": "true",
4755					"aria-expanded": "true",
4756					tabIndex: 0
4757				} );
4758		},
4759
4760		_animate: function( toShow, toHide, data ) {
4761			var total, easing, duration,
4762				that = this,
4763				adjust = 0,
4764				boxSizing = toShow.css( "box-sizing" ),
4765				down = toShow.length &&
4766					( !toHide.length || ( toShow.index() < toHide.index() ) ),
4767				animate = this.options.animate || {},
4768				options = down && animate.down || animate,
4769				complete = function() {
4770					that._toggleComplete( data );
4771				};
4772
4773			if ( typeof options === "number" ) {
4774				duration = options;
4775			}
4776			if ( typeof options === "string" ) {
4777				easing = options;
4778			}
4779
4780			// fall back from options to animation in case of partial down settings
4781			easing = easing || options.easing || animate.easing;
4782			duration = duration || options.duration || animate.duration;
4783
4784			if ( !toHide.length ) {
4785				return toShow.animate( this.showProps, duration, easing, complete );
4786			}
4787			if ( !toShow.length ) {
4788				return toHide.animate( this.hideProps, duration, easing, complete );
4789			}
4790
4791			total = toShow.show().outerHeight();
4792			toHide.animate( this.hideProps, {
4793				duration: duration,
4794				easing: easing,
4795				step: function( now, fx ) {
4796					fx.now = Math.round( now );
4797				}
4798			} );
4799			toShow
4800				.hide()
4801				.animate( this.showProps, {
4802					duration: duration,
4803					easing: easing,
4804					complete: complete,
4805					step: function( now, fx ) {
4806						fx.now = Math.round( now );
4807						if ( fx.prop !== "height" ) {
4808							if ( boxSizing === "content-box" ) {
4809								adjust += fx.now;
4810							}
4811						} else if ( that.options.heightStyle !== "content" ) {
4812							fx.now = Math.round( total - toHide.outerHeight() - adjust );
4813							adjust = 0;
4814						}
4815					}
4816				} );
4817		},
4818
4819		_toggleComplete: function( data ) {
4820			var toHide = data.oldPanel,
4821				prev = toHide.prev();
4822
4823			this._removeClass( toHide, "ui-accordion-content-active" );
4824			this._removeClass( prev, "ui-accordion-header-active" )
4825				._addClass( prev, "ui-accordion-header-collapsed" );
4826
4827			this._trigger( "activate", null, data );
4828		}
4829	} );
4830
4831
4832	/*!
4833 * jQuery UI Menu 1.14.1
4834 * https://jqueryui.com
4835 *
4836 * Copyright OpenJS Foundation and other contributors
4837 * Released under the MIT license.
4838 * https://jquery.org/license
4839 */
4840
4841//>>label: Menu
4842//>>group: Widgets
4843//>>description: Creates nestable menus.
4844//>>docs: https://api.jqueryui.com/menu/
4845//>>demos: https://jqueryui.com/menu/
4846//>>css.structure: ../../themes/base/core.css
4847//>>css.structure: ../../themes/base/menu.css
4848//>>css.theme: ../../themes/base/theme.css
4849
4850
4851	var widgetsMenu = $.widget( "ui.menu", {
4852		version: "1.14.1",
4853		defaultElement: "<ul>",
4854		delay: 300,
4855		options: {
4856			icons: {
4857				submenu: "ui-icon-caret-1-e"
4858			},
4859			items: "> *",
4860			menus: "ul",
4861			position: {
4862				my: "left top",
4863				at: "right top"
4864			},
4865			role: "menu",
4866
4867			// Callbacks
4868			blur: null,
4869			focus: null,
4870			select: null
4871		},
4872
4873		_create: function() {
4874			this.activeMenu = this.element;
4875
4876			// Flag used to prevent firing of the click handler
4877			// as the event bubbles up through nested menus
4878			this.mouseHandled = false;
4879			this.lastMousePosition = { x: null, y: null };
4880			this.element
4881				.uniqueId()
4882				.attr( {
4883					role: this.options.role,
4884					tabIndex: 0
4885				} );
4886
4887			this._addClass( "ui-menu", "ui-widget ui-widget-content" );
4888			this._on( {
4889
4890				// Prevent focus from sticking to links inside menu after clicking
4891				// them (focus should always stay on UL during navigation).
4892				"mousedown .ui-menu-item": function( event ) {
4893					event.preventDefault();
4894
4895					this._activateItem( event );
4896				},
4897				"click .ui-menu-item": function( event ) {
4898					var target = $( event.target );
4899					var active = $( this.document[ 0 ].activeElement );
4900					if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) {
4901						this.select( event );
4902
4903						// Only set the mouseHandled flag if the event will bubble, see #9469.
4904						if ( !event.isPropagationStopped() ) {
4905							this.mouseHandled = true;
4906						}
4907
4908						// Open submenu on click
4909						if ( target.has( ".ui-menu" ).length ) {
4910							this.expand( event );
4911						} else if ( !this.element.is( ":focus" ) &&
4912							active.closest( ".ui-menu" ).length ) {
4913
4914							// Redirect focus to the menu
4915							this.element.trigger( "focus", [ true ] );
4916
4917							// If the active item is on the top level, let it stay active.
4918							// Otherwise, blur the active item since it is no longer visible.
4919							if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) {
4920								clearTimeout( this.timer );
4921							}
4922						}
4923					}
4924				},
4925				"mouseenter .ui-menu-item": "_activateItem",
4926				"mousemove .ui-menu-item": "_activateItem",
4927				mouseleave: "collapseAll",
4928				"mouseleave .ui-menu": "collapseAll",
4929				focus: function( event, keepActiveItem ) {
4930
4931					// If there's already an active item, keep it active
4932					// If not, activate the first item
4933					var item = this.active || this._menuItems().first();
4934
4935					if ( !keepActiveItem ) {
4936						this.focus( event, item );
4937					}
4938				},
4939				blur: function( event ) {
4940					this._delay( function() {
4941						var notContained = !$.contains(
4942							this.element[ 0 ],
4943							this.document[ 0 ].activeElement
4944						);
4945						if ( notContained ) {
4946							this.collapseAll( event );
4947						}
4948					} );
4949				},
4950				keydown: "_keydown"
4951			} );
4952
4953			this.refresh();
4954
4955			// Clicks outside of a menu collapse any open menus
4956			this._on( this.document, {
4957				click: function( event ) {
4958					if ( this._closeOnDocumentClick( event ) ) {
4959						this.collapseAll( event, true );
4960					}
4961
4962					// Reset the mouseHandled flag
4963					this.mouseHandled = false;
4964				}
4965			} );
4966		},
4967
4968		_activateItem: function( event ) {
4969
4970			// Ignore mouse events while typeahead is active, see #10458.
4971			// Prevents focusing the wrong item when typeahead causes a scroll while the mouse
4972			// is over an item in the menu
4973			if ( this.previousFilter ) {
4974				return;
4975			}
4976
4977			// If the mouse didn't actually move, but the page was scrolled, ignore the event (#9356)
4978			if ( event.clientX === this.lastMousePosition.x &&
4979				event.clientY === this.lastMousePosition.y ) {
4980				return;
4981			}
4982
4983			this.lastMousePosition = {
4984				x: event.clientX,
4985				y: event.clientY
4986			};
4987
4988			var actualTarget = $( event.target ).closest( ".ui-menu-item" ),
4989				target = $( event.currentTarget );
4990
4991			// Ignore bubbled events on parent items, see #11641
4992			if ( actualTarget[ 0 ] !== target[ 0 ] ) {
4993				return;
4994			}
4995
4996			// If the item is already active, there's nothing to do
4997			if ( target.is( ".ui-state-active" ) ) {
4998				return;
4999			}
5000
5001			// Remove ui-state-active class from siblings of the newly focused menu item
5002			// to avoid a jump caused by adjacent elements both having a class with a border
5003			this._removeClass( target.siblings().children( ".ui-state-active" ),
5004				null, "ui-state-active" );
5005			this.focus( event, target );
5006		},
5007
5008		_destroy: function() {
5009			var items = this.element.find( ".ui-menu-item" )
5010					.removeAttr( "role aria-disabled" ),
5011				submenus = items.children( ".ui-menu-item-wrapper" )
5012					.removeUniqueId()
5013					.removeAttr( "tabIndex role aria-haspopup" );
5014
5015			// Destroy (sub)menus
5016			this.element
5017				.removeAttr( "aria-activedescendant" )
5018				.find( ".ui-menu" ).addBack()
5019				.removeAttr( "role aria-labelledby aria-expanded aria-hidden aria-disabled " +
5020					"tabIndex" )
5021				.removeUniqueId()
5022				.show();
5023
5024			submenus.children().each( function() {
5025				var elem = $( this );
5026				if ( elem.data( "ui-menu-submenu-caret" ) ) {
5027					elem.remove();
5028				}
5029			} );
5030		},
5031
5032		_keydown: function( event ) {
5033			var match, prev, character, skip,
5034				preventDefault = true;
5035
5036			switch ( event.keyCode ) {
5037				case $.ui.keyCode.PAGE_UP:
5038					this.previousPage( event );
5039					break;
5040				case $.ui.keyCode.PAGE_DOWN:
5041					this.nextPage( event );
5042					break;
5043				case $.ui.keyCode.HOME:
5044					this._move( "first", "first", event );
5045					break;
5046				case $.ui.keyCode.END:
5047					this._move( "last", "last", event );
5048					break;
5049				case $.ui.keyCode.UP:
5050					this.previous( event );
5051					break;
5052				case $.ui.keyCode.DOWN:
5053					this.next( event );
5054					break;
5055				case $.ui.keyCode.LEFT:
5056					this.collapse( event );
5057					break;
5058				case $.ui.keyCode.RIGHT:
5059					if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
5060						this.expand( event );
5061					}
5062					break;
5063				case $.ui.keyCode.ENTER:
5064				case $.ui.keyCode.SPACE:
5065					this._activate( event );
5066					break;
5067				case $.ui.keyCode.ESCAPE:
5068					this.collapse( event );
5069					break;
5070				default:
5071					preventDefault = false;
5072					prev = this.previousFilter || "";
5073					skip = false;
5074
5075					// Support number pad values
5076					character = event.keyCode >= 96 && event.keyCode <= 105 ?
5077						( event.keyCode - 96 ).toString() : String.fromCharCode( event.keyCode );
5078
5079					clearTimeout( this.filterTimer );
5080
5081					if ( character === prev ) {
5082						skip = true;
5083					} else {
5084						character = prev + character;
5085					}
5086
5087					match = this._filterMenuItems( character );
5088					match = skip && match.index( this.active.next() ) !== -1 ?
5089						this.active.nextAll( ".ui-menu-item" ) :
5090						match;
5091
5092					// If no matches on the current filter, reset to the last character pressed
5093					// to move down the menu to the first item that starts with that character
5094					if ( !match.length ) {
5095						character = String.fromCharCode( event.keyCode );
5096						match = this._filterMenuItems( character );
5097					}
5098
5099					if ( match.length ) {
5100						this.focus( event, match );
5101						this.previousFilter = character;
5102						this.filterTimer = this._delay( function() {
5103							delete this.previousFilter;
5104						}, 1000 );
5105					} else {
5106						delete this.previousFilter;
5107					}
5108			}
5109
5110			if ( preventDefault ) {
5111				event.preventDefault();
5112			}
5113		},
5114
5115		_activate: function( event ) {
5116			if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
5117				if ( this.active.children( "[aria-haspopup='true']" ).length ) {
5118					this.expand( event );
5119				} else {
5120					this.select( event );
5121				}
5122			}
5123		},
5124
5125		refresh: function() {
5126			var menus, items, newSubmenus, newItems, newWrappers,
5127				that = this,
5128				icon = this.options.icons.submenu,
5129				submenus = this.element.find( this.options.menus );
5130
5131			this._toggleClass( "ui-menu-icons", null, !!this.element.find( ".ui-icon" ).length );
5132
5133			// Initialize nested menus
5134			newSubmenus = submenus.filter( ":not(.ui-menu)" )
5135				.hide()
5136				.attr( {
5137					role: this.options.role,
5138					"aria-hidden": "true",
5139					"aria-expanded": "false"
5140				} )
5141				.each( function() {
5142					var menu = $( this ),
5143						item = menu.prev(),
5144						submenuCaret = $( "<span>" ).data( "ui-menu-submenu-caret", true );
5145
5146					that._addClass( submenuCaret, "ui-menu-icon", "ui-icon " + icon );
5147					item
5148						.attr( "aria-haspopup", "true" )
5149						.prepend( submenuCaret );
5150					menu.attr( "aria-labelledby", item.attr( "id" ) );
5151				} );
5152
5153			this._addClass( newSubmenus, "ui-menu", "ui-widget ui-widget-content ui-front" );
5154
5155			menus = submenus.add( this.element );
5156			items = menus.find( this.options.items );
5157
5158			// Initialize menu-items containing spaces and/or dashes only as dividers
5159			items.not( ".ui-menu-item" ).each( function() {
5160				var item = $( this );
5161				if ( that._isDivider( item ) ) {
5162					that._addClass( item, "ui-menu-divider", "ui-widget-content" );
5163				}
5164			} );
5165
5166			// Don't refresh list items that are already adapted
5167			newItems = items.not( ".ui-menu-item, .ui-menu-divider" );
5168			newWrappers = newItems.children()
5169				.not( ".ui-menu" )
5170				.uniqueId()
5171				.attr( {
5172					tabIndex: -1,
5173					role: this._itemRole()
5174				} );
5175			this._addClass( newItems, "ui-menu-item" )
5176				._addClass( newWrappers, "ui-menu-item-wrapper" );
5177
5178			// Add aria-disabled attribute to any disabled menu item
5179			items.filter( ".ui-state-disabled" ).attr( "aria-disabled", "true" );
5180
5181			// If the active item has been removed, blur the menu
5182			if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
5183				this.blur();
5184			}
5185		},
5186
5187		_itemRole: function() {
5188			return {
5189				menu: "menuitem",
5190				listbox: "option"
5191			}[ this.options.role ];
5192		},
5193
5194		_setOption: function( key, value ) {
5195			if ( key === "icons" ) {
5196				var icons = this.element.find( ".ui-menu-icon" );
5197				this._removeClass( icons, null, this.options.icons.submenu )
5198					._addClass( icons, null, value.submenu );
5199			}
5200			this._super( key, value );
5201		},
5202
5203		_setOptionDisabled: function( value ) {
5204			this._super( value );
5205
5206			this.element.attr( "aria-disabled", String( value ) );
5207			this._toggleClass( null, "ui-state-disabled", !!value );
5208		},
5209
5210		focus: function( event, item ) {
5211			var nested, focused, activeParent;
5212			this.blur( event, event && event.type === "focus" );
5213
5214			this._scrollIntoView( item );
5215
5216			this.active = item.first();
5217
5218			focused = this.active.children( ".ui-menu-item-wrapper" );
5219			this._addClass( focused, null, "ui-state-active" );
5220
5221			// Only update aria-activedescendant if there's a role
5222			// otherwise we assume focus is managed elsewhere
5223			if ( this.options.role ) {
5224				this.element.attr( "aria-activedescendant", focused.attr( "id" ) );
5225			}
5226
5227			// Highlight active parent menu item, if any
5228			activeParent = this.active
5229				.parent()
5230				.closest( ".ui-menu-item" )
5231				.children( ".ui-menu-item-wrapper" );
5232			this._addClass( activeParent, null, "ui-state-active" );
5233
5234			if ( event && event.type === "keydown" ) {
5235				this._close();
5236			} else {
5237				this.timer = this._delay( function() {
5238					this._close();
5239				}, this.delay );
5240			}
5241
5242			nested = item.children( ".ui-menu" );
5243			if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) {
5244				this._startOpening( nested );
5245			}
5246			this.activeMenu = item.parent();
5247
5248			this._trigger( "focus", event, { item: item } );
5249		},
5250
5251		_scrollIntoView: function( item ) {
5252			var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
5253			if ( this._hasScroll() ) {
5254				borderTop = parseFloat( $.css( this.activeMenu[ 0 ], "borderTopWidth" ) ) || 0;
5255				paddingTop = parseFloat( $.css( this.activeMenu[ 0 ], "paddingTop" ) ) || 0;
5256				offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
5257				scroll = this.activeMenu.scrollTop();
5258				elementHeight = this.activeMenu.height();
5259				itemHeight = item.outerHeight();
5260
5261				if ( offset < 0 ) {
5262					this.activeMenu.scrollTop( scroll + offset );
5263				} else if ( offset + itemHeight > elementHeight ) {
5264					this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );
5265				}
5266			}
5267		},
5268
5269		blur: function( event, fromFocus ) {
5270			if ( !fromFocus ) {
5271				clearTimeout( this.timer );
5272			}
5273
5274			if ( !this.active ) {
5275				return;
5276			}
5277
5278			this._removeClass( this.active.children( ".ui-menu-item-wrapper" ),
5279				null, "ui-state-active" );
5280
5281			this._trigger( "blur", event, { item: this.active } );
5282			this.active = null;
5283		},
5284
5285		_startOpening: function( submenu ) {
5286			clearTimeout( this.timer );
5287
5288			// Don't open if already open fixes a Firefox bug that caused a .5 pixel
5289			// shift in the submenu position when mousing over the caret icon
5290			if ( submenu.attr( "aria-hidden" ) !== "true" ) {
5291				return;
5292			}
5293
5294			this.timer = this._delay( function() {
5295				this._close();
5296				this._open( submenu );
5297			}, this.delay );
5298		},
5299
5300		_open: function( submenu ) {
5301			var position = $.extend( {
5302				of: this.active
5303			}, this.options.position );
5304
5305			clearTimeout( this.timer );
5306			this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) )
5307				.hide()
5308				.attr( "aria-hidden", "true" );
5309
5310			submenu
5311				.show()
5312				.removeAttr( "aria-hidden" )
5313				.attr( "aria-expanded", "true" )
5314				.position( position );
5315		},
5316
5317		collapseAll: function( event, all ) {
5318			clearTimeout( this.timer );
5319			this.timer = this._delay( function() {
5320
5321				// If we were passed an event, look for the submenu that contains the event
5322				var currentMenu = all ? this.element :
5323					$( event && event.target ).closest( this.element.find( ".ui-menu" ) );
5324
5325				// If we found no valid submenu ancestor, use the main menu to close all
5326				// sub menus anyway
5327				if ( !currentMenu.length ) {
5328					currentMenu = this.element;
5329				}
5330
5331				this._close( currentMenu );
5332
5333				this.blur( event );
5334
5335				// Work around active item staying active after menu is blurred
5336				this._removeClass( currentMenu.find( ".ui-state-active" ), null, "ui-state-active" );
5337
5338				this.activeMenu = currentMenu;
5339			}, all ? 0 : this.delay );
5340		},
5341
5342		// With no arguments, closes the currently active menu - if nothing is active
5343		// it closes all menus.  If passed an argument, it will search for menus BELOW
5344		_close: function( startMenu ) {
5345			if ( !startMenu ) {
5346				startMenu = this.active ? this.active.parent() : this.element;
5347			}
5348
5349			startMenu.find( ".ui-menu" )
5350				.hide()
5351				.attr( "aria-hidden", "true" )
5352				.attr( "aria-expanded", "false" );
5353		},
5354
5355		_closeOnDocumentClick: function( event ) {
5356			return !$( event.target ).closest( ".ui-menu" ).length;
5357		},
5358
5359		_isDivider: function( item ) {
5360
5361			// Match hyphen, em dash, en dash
5362			return !/[^\-\u2014\u2013\s]/.test( item.text() );
5363		},
5364
5365		collapse: function( event ) {
5366			var newItem = this.active &&
5367				this.active.parent().closest( ".ui-menu-item", this.element );
5368			if ( newItem && newItem.length ) {
5369				this._close();
5370				this.focus( event, newItem );
5371			}
5372		},
5373
5374		expand: function( event ) {
5375			var newItem = this.active && this._menuItems( this.active.children( ".ui-menu" ) ).first();
5376
5377			if ( newItem && newItem.length ) {
5378				this._open( newItem.parent() );
5379
5380				// Delay so Firefox will not hide activedescendant change in expanding submenu from AT
5381				this._delay( function() {
5382					this.focus( event, newItem );
5383				} );
5384			}
5385		},
5386
5387		next: function( event ) {
5388			this._move( "next", "first", event );
5389		},
5390
5391		previous: function( event ) {
5392			this._move( "prev", "last", event );
5393		},
5394
5395		isFirstItem: function() {
5396			return this.active && !this.active.prevAll( ".ui-menu-item" ).length;
5397		},
5398
5399		isLastItem: function() {
5400			return this.active && !this.active.nextAll( ".ui-menu-item" ).length;
5401		},
5402
5403		_menuItems: function( menu ) {
5404			return ( menu || this.element )
5405				.find( this.options.items )
5406				.filter( ".ui-menu-item" );
5407		},
5408
5409		_move: function( direction, filter, event ) {
5410			var next;
5411			if ( this.active ) {
5412				if ( direction === "first" || direction === "last" ) {
5413					next = this.active
5414						[ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )
5415						.last();
5416				} else {
5417					next = this.active
5418						[ direction + "All" ]( ".ui-menu-item" )
5419						.first();
5420				}
5421			}
5422			if ( !next || !next.length || !this.active ) {
5423				next = this._menuItems( this.activeMenu )[ filter ]();
5424			}
5425
5426			this.focus( event, next );
5427		},
5428
5429		nextPage: function( event ) {
5430			var item, base, height;
5431
5432			if ( !this.active ) {
5433				this.next( event );
5434				return;
5435			}
5436			if ( this.isLastItem() ) {
5437				return;
5438			}
5439			if ( this._hasScroll() ) {
5440				base = this.active.offset().top;
5441				height = this.element.innerHeight();
5442
5443				// jQuery 3.2 doesn't include scrollbars in innerHeight, add it back.
5444				if ( $.fn.jquery.indexOf( "3.2." ) === 0 ) {
5445					height += this.element[ 0 ].offsetHeight - this.element.outerHeight();
5446				}
5447
5448				this.active.nextAll( ".ui-menu-item" ).each( function() {
5449					item = $( this );
5450					return item.offset().top - base - height < 0;
5451				} );
5452
5453				this.focus( event, item );
5454			} else {
5455				this.focus( event, this._menuItems( this.activeMenu )
5456					[ !this.active ? "first" : "last" ]() );
5457			}
5458		},
5459
5460		previousPage: function( event ) {
5461			var item, base, height;
5462			if ( !this.active ) {
5463				this.next( event );
5464				return;
5465			}
5466			if ( this.isFirstItem() ) {
5467				return;
5468			}
5469			if ( this._hasScroll() ) {
5470				base = this.active.offset().top;
5471				height = this.element.innerHeight();
5472
5473				// jQuery 3.2 doesn't include scrollbars in innerHeight, add it back.
5474				if ( $.fn.jquery.indexOf( "3.2." ) === 0 ) {
5475					height += this.element[ 0 ].offsetHeight - this.element.outerHeight();
5476				}
5477
5478				this.active.prevAll( ".ui-menu-item" ).each( function() {
5479					item = $( this );
5480					return item.offset().top - base + height > 0;
5481				} );
5482
5483				this.focus( event, item );
5484			} else {
5485				this.focus( event, this._menuItems( this.activeMenu ).first() );
5486			}
5487		},
5488
5489		_hasScroll: function() {
5490			return this.element.outerHeight() < this.element.prop( "scrollHeight" );
5491		},
5492
5493		select: function( event ) {
5494
5495			// TODO: It should never be possible to not have an active item at this
5496			// point, but the tests don't trigger mouseenter before click.
5497			this.active = this.active || $( event.target ).closest( ".ui-menu-item" );
5498			var ui = { item: this.active };
5499			if ( !this.active.has( ".ui-menu" ).length ) {
5500				this.collapseAll( event, true );
5501			}
5502			this._trigger( "select", event, ui );
5503		},
5504
5505		_filterMenuItems: function( character ) {
5506			var escapedCharacter = character.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ),
5507				regex = new RegExp( "^" + escapedCharacter, "i" );
5508
5509			return this.activeMenu
5510				.find( this.options.items )
5511
5512				// Only match on items, not dividers or other content (#10571)
5513				.filter( ".ui-menu-item" )
5514				.filter( function() {
5515					return regex.test(
5516						String.prototype.trim.call(
5517							$( this ).children( ".ui-menu-item-wrapper" ).text() ) );
5518				} );
5519		}
5520	} );
5521
5522
5523	/*!
5524 * jQuery UI Autocomplete 1.14.1
5525 * https://jqueryui.com
5526 *
5527 * Copyright OpenJS Foundation and other contributors
5528 * Released under the MIT license.
5529 * https://jquery.org/license
5530 */
5531
5532//>>label: Autocomplete
5533//>>group: Widgets
5534//>>description: Lists suggested words as the user is typing.
5535//>>docs: https://api.jqueryui.com/autocomplete/
5536//>>demos: https://jqueryui.com/autocomplete/
5537//>>css.structure: ../../themes/base/core.css
5538//>>css.structure: ../../themes/base/autocomplete.css
5539//>>css.theme: ../../themes/base/theme.css
5540
5541
5542	$.widget( "ui.autocomplete", {
5543		version: "1.14.1",
5544		defaultElement: "<input>",
5545		options: {
5546			appendTo: null,
5547			autoFocus: false,
5548			delay: 300,
5549			minLength: 1,
5550			position: {
5551				my: "left top",
5552				at: "left bottom",
5553				collision: "none"
5554			},
5555			source: null,
5556
5557			// Callbacks
5558			change: null,
5559			close: null,
5560			focus: null,
5561			open: null,
5562			response: null,
5563			search: null,
5564			select: null
5565		},
5566
5567		requestIndex: 0,
5568		pending: 0,
5569		liveRegionTimer: null,
5570
5571		_create: function() {
5572
5573			// Some browsers only repeat keydown events, not keypress events,
5574			// so we use the suppressKeyPress flag to determine if we've already
5575			// handled the keydown event. #7269
5576			// Unfortunately the code for & in keypress is the same as the up arrow,
5577			// so we use the suppressKeyPressRepeat flag to avoid handling keypress
5578			// events when we know the keydown event was used to modify the
5579			// search term. #7799
5580			var suppressKeyPress, suppressKeyPressRepeat, suppressInput,
5581				nodeName = this.element[ 0 ].nodeName.toLowerCase(),
5582				isTextarea = nodeName === "textarea",
5583				isInput = nodeName === "input";
5584
5585			// Textareas are always multi-line
5586			// Inputs are always single-line, even if inside a contentEditable element
5587			// All other element types are determined by whether they're contentEditable
5588			this.isMultiLine = isTextarea ||
5589				!isInput && this.element.prop( "contentEditable" ) === "true";
5590
5591			this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ];
5592			this.isNewMenu = true;
5593
5594			this._addClass( "ui-autocomplete-input" );
5595			this.element.attr( "autocomplete", "off" );
5596
5597			this._on( this.element, {
5598				keydown: function( event ) {
5599					if ( this.element.prop( "readOnly" ) ) {
5600						suppressKeyPress = true;
5601						suppressInput = true;
5602						suppressKeyPressRepeat = true;
5603						return;
5604					}
5605
5606					suppressKeyPress = false;
5607					suppressInput = false;
5608					suppressKeyPressRepeat = false;
5609					var keyCode = $.ui.keyCode;
5610					switch ( event.keyCode ) {
5611						case keyCode.PAGE_UP:
5612							suppressKeyPress = true;
5613							this._move( "previousPage", event );
5614							break;
5615						case keyCode.PAGE_DOWN:
5616							suppressKeyPress = true;
5617							this._move( "nextPage", event );
5618							break;
5619						case keyCode.UP:
5620							suppressKeyPress = true;
5621							this._keyEvent( "previous", event );
5622							break;
5623						case keyCode.DOWN:
5624							suppressKeyPress = true;
5625							this._keyEvent( "next", event );
5626							break;
5627						case keyCode.ENTER:
5628
5629							// when menu is open and has focus
5630							if ( this.menu.active ) {
5631
5632								// #6055 - Opera still allows the keypress to occur
5633								// which causes forms to submit
5634								suppressKeyPress = true;
5635								event.preventDefault();
5636								this.menu.select( event );
5637							}
5638							break;
5639						case keyCode.TAB:
5640							if ( this.menu.active ) {
5641								this.menu.select( event );
5642							}
5643							break;
5644						case keyCode.ESCAPE:
5645							if ( this.menu.element.is( ":visible" ) ) {
5646								if ( !this.isMultiLine ) {
5647									this._value( this.term );
5648								}
5649								this.close( event );
5650
5651								// Different browsers have different default behavior for escape
5652								// Single press can mean undo or clear
5653								event.preventDefault();
5654							}
5655							break;
5656						default:
5657							suppressKeyPressRepeat = true;
5658
5659							// search timeout should be triggered before the input value is changed
5660							this._searchTimeout( event );
5661							break;
5662					}
5663				},
5664				keypress: function( event ) {
5665					if ( suppressKeyPress ) {
5666						suppressKeyPress = false;
5667						if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
5668							event.preventDefault();
5669						}
5670						return;
5671					}
5672					if ( suppressKeyPressRepeat ) {
5673						return;
5674					}
5675
5676					// Replicate some key handlers to allow them to repeat in Firefox and Opera
5677					var keyCode = $.ui.keyCode;
5678					switch ( event.keyCode ) {
5679						case keyCode.PAGE_UP:
5680							this._move( "previousPage", event );
5681							break;
5682						case keyCode.PAGE_DOWN:
5683							this._move( "nextPage", event );
5684							break;
5685						case keyCode.UP:
5686							this._keyEvent( "previous", event );
5687							break;
5688						case keyCode.DOWN:
5689							this._keyEvent( "next", event );
5690							break;
5691					}
5692				},
5693				input: function( event ) {
5694					if ( suppressInput ) {
5695						suppressInput = false;
5696						event.preventDefault();
5697						return;
5698					}
5699					this._searchTimeout( event );
5700				},
5701				focus: function() {
5702					this.selectedItem = null;
5703					this.previous = this._value();
5704				},
5705				blur: function( event ) {
5706					clearTimeout( this.searching );
5707					this.close( event );
5708					this._change( event );
5709				}
5710			} );
5711
5712			this._initSource();
5713			this.menu = $( "<ul>" )
5714				.appendTo( this._appendTo() )
5715				.menu( {
5716
5717					// disable ARIA support, the live region takes care of that
5718					role: null
5719				} )
5720				.hide()
5721				.menu( "instance" );
5722
5723			this._addClass( this.menu.element, "ui-autocomplete", "ui-front" );
5724			this._on( this.menu.element, {
5725				mousedown: function( event ) {
5726
5727					// Prevent moving focus out of the text field
5728					event.preventDefault();
5729				},
5730				menufocus: function( event, ui ) {
5731					var label, item;
5732
5733					// Support: Firefox
5734					// Prevent accidental activation of menu items in Firefox (#7024 #9118)
5735					if ( this.isNewMenu ) {
5736						this.isNewMenu = false;
5737						if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {
5738							this.menu.blur();
5739
5740							this.document.one( "mousemove", function() {
5741								$( event.target ).trigger( event.originalEvent );
5742							} );
5743
5744							return;
5745						}
5746					}
5747
5748					item = ui.item.data( "ui-autocomplete-item" );
5749					if ( false !== this._trigger( "focus", event, { item: item } ) ) {
5750
5751						// use value to match what will end up in the input, if it was a key event
5752						if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
5753							this._value( item.value );
5754						}
5755					}
5756
5757					// Announce the value in the liveRegion
5758					label = ui.item.attr( "aria-label" ) || item.value;
5759					if ( label && String.prototype.trim.call( label ).length ) {
5760						clearTimeout( this.liveRegionTimer );
5761						this.liveRegionTimer = this._delay( function() {
5762							this.liveRegion.html( $( "<div>" ).text( label ) );
5763						}, 100 );
5764					}
5765				},
5766				menuselect: function( event, ui ) {
5767					var item = ui.item.data( "ui-autocomplete-item" ),
5768						previous = this.previous;
5769
5770					// Only trigger when focus was lost (click on menu)
5771					if ( this.element[ 0 ] !== this.document[ 0 ].activeElement ) {
5772						this.element.trigger( "focus" );
5773						this.previous = previous;
5774					}
5775
5776					if ( false !== this._trigger( "select", event, { item: item } ) ) {
5777						this._value( item.value );
5778					}
5779
5780					// reset the term after the select event
5781					// this allows custom select handling to work properly
5782					this.term = this._value();
5783
5784					this.close( event );
5785					this.selectedItem = item;
5786				}
5787			} );
5788
5789			this.liveRegion = $( "<div>", {
5790				role: "status",
5791				"aria-live": "assertive",
5792				"aria-relevant": "additions"
5793			} )
5794				.appendTo( this.document[ 0 ].body );
5795
5796			this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" );
5797
5798			// Turning off autocomplete prevents the browser from remembering the
5799			// value when navigating through history, so we re-enable autocomplete
5800			// if the page is unloaded before the widget is destroyed. #7790
5801			this._on( this.window, {
5802				beforeunload: function() {
5803					this.element.removeAttr( "autocomplete" );
5804				}
5805			} );
5806		},
5807
5808		_destroy: function() {
5809			clearTimeout( this.searching );
5810			this.element.removeAttr( "autocomplete" );
5811			this.menu.element.remove();
5812			this.liveRegion.remove();
5813		},
5814
5815		_setOption: function( key, value ) {
5816			this._super( key, value );
5817			if ( key === "source" ) {
5818				this._initSource();
5819			}
5820			if ( key === "appendTo" ) {
5821				this.menu.element.appendTo( this._appendTo() );
5822			}
5823			if ( key === "disabled" && value && this.xhr ) {
5824				this.xhr.abort();
5825			}
5826		},
5827
5828		_isEventTargetInWidget: function( event ) {
5829			var menuElement = this.menu.element[ 0 ];
5830
5831			return event.target === this.element[ 0 ] ||
5832				event.target === menuElement ||
5833				$.contains( menuElement, event.target );
5834		},
5835
5836		_closeOnClickOutside: function( event ) {
5837			if ( !this._isEventTargetInWidget( event ) ) {
5838				this.close();
5839			}
5840		},
5841
5842		_appendTo: function() {
5843			var element = this.options.appendTo;
5844
5845			if ( element ) {
5846				element = element.jquery || element.nodeType ?
5847					$( element ) :
5848					this.document.find( element ).eq( 0 );
5849			}
5850
5851			if ( !element || !element[ 0 ] ) {
5852				element = this.element.closest( ".ui-front, dialog" );
5853			}
5854
5855			if ( !element.length ) {
5856				element = this.document[ 0 ].body;
5857			}
5858
5859			return element;
5860		},
5861
5862		_initSource: function() {
5863			var array, url,
5864				that = this;
5865			if ( Array.isArray( this.options.source ) ) {
5866				array = this.options.source;
5867				this.source = function( request, response ) {
5868					response( $.ui.autocomplete.filter( array, request.term ) );
5869				};
5870			} else if ( typeof this.options.source === "string" ) {
5871				url = this.options.source;
5872				this.source = function( request, response ) {
5873					if ( that.xhr ) {
5874						that.xhr.abort();
5875					}
5876					that.xhr = $.ajax( {
5877						url: url,
5878						data: request,
5879						dataType: "json",
5880						success: function( data ) {
5881							response( data );
5882						},
5883						error: function() {
5884							response( [] );
5885						}
5886					} );
5887				};
5888			} else {
5889				this.source = this.options.source;
5890			}
5891		},
5892
5893		_searchTimeout: function( event ) {
5894			clearTimeout( this.searching );
5895			this.searching = this._delay( function() {
5896
5897				// Search if the value has changed, or if the user retypes the same value (see #7434)
5898				var equalValues = this.term === this._value(),
5899					menuVisible = this.menu.element.is( ":visible" ),
5900					modifierKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
5901
5902				if ( !equalValues || ( equalValues && !menuVisible && !modifierKey ) ) {
5903					this.selectedItem = null;
5904					this.search( null, event );
5905				}
5906			}, this.options.delay );
5907		},
5908
5909		search: function( value, event ) {
5910			value = value != null ? value : this._value();
5911
5912			// Always save the actual value, not the one passed as an argument
5913			this.term = this._value();
5914
5915			if ( value.length < this.options.minLength ) {
5916				return this.close( event );
5917			}
5918
5919			if ( this._trigger( "search", event ) === false ) {
5920				return;
5921			}
5922
5923			return this._search( value );
5924		},
5925
5926		_search: function( value ) {
5927			this.pending++;
5928			this._addClass( "ui-autocomplete-loading" );
5929			this.cancelSearch = false;
5930
5931			this.source( { term: value }, this._response() );
5932		},
5933
5934		_response: function() {
5935			var index = ++this.requestIndex;
5936
5937			return function( content ) {
5938				if ( index === this.requestIndex ) {
5939					this.__response( content );
5940				}
5941
5942				this.pending--;
5943				if ( !this.pending ) {
5944					this._removeClass( "ui-autocomplete-loading" );
5945				}
5946			}.bind( this );
5947		},
5948
5949		__response: function( content ) {
5950			if ( content ) {
5951				content = this._normalize( content );
5952			}
5953			this._trigger( "response", null, { content: content } );
5954			if ( !this.options.disabled && content && content.length && !this.cancelSearch ) {
5955				this._suggest( content );
5956				this._trigger( "open" );
5957			} else {
5958
5959				// use ._close() instead of .close() so we don't cancel future searches
5960				this._close();
5961			}
5962		},
5963
5964		close: function( event ) {
5965			this.cancelSearch = true;
5966			this._close( event );
5967		},
5968
5969		_close: function( event ) {
5970
5971			// Remove the handler that closes the menu on outside clicks
5972			this._off( this.document, "mousedown" );
5973
5974			if ( this.menu.element.is( ":visible" ) ) {
5975				this.menu.element.hide();
5976				this.menu.blur();
5977				this.isNewMenu = true;
5978				this._trigger( "close", event );
5979			}
5980		},
5981
5982		_change: function( event ) {
5983			if ( this.previous !== this._value() ) {
5984				this._trigger( "change", event, { item: this.selectedItem } );
5985			}
5986		},
5987
5988		_normalize: function( items ) {
5989
5990			// assume all items have the right format when the first item is complete
5991			if ( items.length && items[ 0 ].label && items[ 0 ].value ) {
5992				return items;
5993			}
5994			return $.map( items, function( item ) {
5995				if ( typeof item === "string" ) {
5996					return {
5997						label: item,
5998						value: item
5999					};
6000				}
6001				return $.extend( {}, item, {
6002					label: item.label || item.value,
6003					value: item.value || item.label
6004				} );
6005			} );
6006		},
6007
6008		_suggest: function( items ) {
6009			var ul = this.menu.element.empty();
6010			this._renderMenu( ul, items );
6011			this.isNewMenu = true;
6012			this.menu.refresh();
6013
6014			// Size and position menu
6015			ul.show();
6016			this._resizeMenu();
6017			ul.position( $.extend( {
6018				of: this.element
6019			}, this.options.position ) );
6020
6021			if ( this.options.autoFocus ) {
6022				this.menu.next();
6023			}
6024
6025			// Listen for interactions outside of the widget (#6642)
6026			this._on( this.document, {
6027				mousedown: "_closeOnClickOutside"
6028			} );
6029		},
6030
6031		_resizeMenu: function() {
6032			var ul = this.menu.element;
6033			ul.outerWidth( Math.max(
6034
6035				// Firefox wraps long text (possibly a rounding bug)
6036				// so we add 1px to avoid the wrapping (#7513)
6037				ul.width( "" ).outerWidth() + 1,
6038				this.element.outerWidth()
6039			) );
6040		},
6041
6042		_renderMenu: function( ul, items ) {
6043			var that = this;
6044			$.each( items, function( index, item ) {
6045				that._renderItemData( ul, item );
6046			} );
6047		},
6048
6049		_renderItemData: function( ul, item ) {
6050			return this._renderItem( ul, item ).data( "ui-autocomplete-item", item );
6051		},
6052
6053		_renderItem: function( ul, item ) {
6054			return $( "<li>" )
6055				.append( $( "<div>" ).text( item.label ) )
6056				.appendTo( ul );
6057		},
6058
6059		_move: function( direction, event ) {
6060			if ( !this.menu.element.is( ":visible" ) ) {
6061				this.search( null, event );
6062				return;
6063			}
6064			if ( this.menu.isFirstItem() && /^previous/.test( direction ) ||
6065				this.menu.isLastItem() && /^next/.test( direction ) ) {
6066
6067				if ( !this.isMultiLine ) {
6068					this._value( this.term );
6069				}
6070
6071				this.menu.blur();
6072				return;
6073			}
6074			this.menu[ direction ]( event );
6075		},
6076
6077		widget: function() {
6078			return this.menu.element;
6079		},
6080
6081		_value: function() {
6082			return this.valueMethod.apply( this.element, arguments );
6083		},
6084
6085		_keyEvent: function( keyEvent, event ) {
6086			if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
6087				this._move( keyEvent, event );
6088
6089				// Prevents moving cursor to beginning/end of the text field in some browsers
6090				event.preventDefault();
6091			}
6092		}
6093	} );
6094
6095	$.extend( $.ui.autocomplete, {
6096		escapeRegex: function( value ) {
6097			return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
6098		},
6099		filter: function( array, term ) {
6100			var matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), "i" );
6101			return $.grep( array, function( value ) {
6102				return matcher.test( value.label || value.value || value );
6103			} );
6104		}
6105	} );
6106
6107// Live region extension, adding a `messages` option
6108// NOTE: This is an experimental API. We are still investigating
6109// a full solution for string manipulation and internationalization.
6110	$.widget( "ui.autocomplete", $.ui.autocomplete, {
6111		options: {
6112			messages: {
6113				noResults: "No search results.",
6114				results: function( amount ) {
6115					return amount + ( amount > 1 ? " results are" : " result is" ) +
6116						" available, use up and down arrow keys to navigate.";
6117				}
6118			}
6119		},
6120
6121		__response: function( content ) {
6122			var message;
6123			this._superApply( arguments );
6124			if ( this.options.disabled || this.cancelSearch ) {
6125				return;
6126			}
6127			if ( content && content.length ) {
6128				message = this.options.messages.results( content.length );
6129			} else {
6130				message = this.options.messages.noResults;
6131			}
6132			clearTimeout( this.liveRegionTimer );
6133			this.liveRegionTimer = this._delay( function() {
6134				this.liveRegion.html( $( "<div>" ).text( message ) );
6135			}, 100 );
6136		}
6137	} );
6138
6139	var widgetsAutocomplete = $.ui.autocomplete;
6140
6141
6142	/*!
6143 * jQuery UI Controlgroup 1.14.1
6144 * https://jqueryui.com
6145 *
6146 * Copyright OpenJS Foundation and other contributors
6147 * Released under the MIT license.
6148 * https://jquery.org/license
6149 */
6150
6151//>>label: Controlgroup
6152//>>group: Widgets
6153//>>description: Visually groups form control widgets
6154//>>docs: https://api.jqueryui.com/controlgroup/
6155//>>demos: https://jqueryui.com/controlgroup/
6156//>>css.structure: ../../themes/base/core.css
6157//>>css.structure: ../../themes/base/controlgroup.css
6158//>>css.theme: ../../themes/base/theme.css
6159
6160
6161	var controlgroupCornerRegex = /ui-corner-([a-z]){2,6}/g;
6162
6163	var widgetsControlgroup = $.widget( "ui.controlgroup", {
6164		version: "1.14.1",
6165		defaultElement: "<div>",
6166		options: {
6167			direction: "horizontal",
6168			disabled: null,
6169			onlyVisible: true,
6170			items: {
6171				"button": "input[type=button], input[type=submit], input[type=reset], button, a",
6172				"controlgroupLabel": ".ui-controlgroup-label",
6173				"checkboxradio": "input[type='checkbox'], input[type='radio']",
6174				"selectmenu": "select",
6175				"spinner": ".ui-spinner-input"
6176			}
6177		},
6178
6179		_create: function() {
6180			this._enhance();
6181		},
6182
6183		// To support the enhanced option in jQuery Mobile, we isolate DOM manipulation
6184		_enhance: function() {
6185			this.element.attr( "role", "toolbar" );
6186			this.refresh();
6187		},
6188
6189		_destroy: function() {
6190			this._callChildMethod( "destroy" );
6191			this.childWidgets.removeData( "ui-controlgroup-data" );
6192			this.element.removeAttr( "role" );
6193			if ( this.options.items.controlgroupLabel ) {
6194				this.element
6195					.find( this.options.items.controlgroupLabel )
6196					.find( ".ui-controlgroup-label-contents" )
6197					.contents().unwrap();
6198			}
6199		},
6200
6201		_initWidgets: function() {
6202			var that = this,
6203				childWidgets = [];
6204
6205			// First we iterate over each of the items options
6206			$.each( this.options.items, function( widget, selector ) {
6207				var labels;
6208				var options = {};
6209
6210				// Make sure the widget has a selector set
6211				if ( !selector ) {
6212					return;
6213				}
6214
6215				if ( widget === "controlgroupLabel" ) {
6216					labels = that.element.find( selector );
6217					labels.each( function() {
6218						var element = $( this );
6219
6220						if ( element.children( ".ui-controlgroup-label-contents" ).length ) {
6221							return;
6222						}
6223						element.contents()
6224							.wrapAll( "<span class='ui-controlgroup-label-contents'></span>" );
6225					} );
6226					that._addClass( labels, null, "ui-widget ui-widget-content ui-state-default" );
6227					childWidgets = childWidgets.concat( labels.get() );
6228					return;
6229				}
6230
6231				// Make sure the widget actually exists
6232				if ( !$.fn[ widget ] ) {
6233					return;
6234				}
6235
6236				// We assume everything is in the middle to start because we can't determine
6237				// first / last elements until all enhancments are done.
6238				if ( that[ "_" + widget + "Options" ] ) {
6239					options = that[ "_" + widget + "Options" ]( "middle" );
6240				} else {
6241					options = { classes: {} };
6242				}
6243
6244				// Find instances of this widget inside controlgroup and init them
6245				that.element
6246					.find( selector )
6247					.each( function() {
6248						var element = $( this );
6249						var instance = element[ widget ]( "instance" );
6250
6251						// We need to clone the default options for this type of widget to avoid
6252						// polluting the variable options which has a wider scope than a single widget.
6253						var instanceOptions = $.widget.extend( {}, options );
6254
6255						// If the button is the child of a spinner ignore it
6256						// TODO: Find a more generic solution
6257						if ( widget === "button" && element.parent( ".ui-spinner" ).length ) {
6258							return;
6259						}
6260
6261						// Create the widget if it doesn't exist
6262						if ( !instance ) {
6263							instance = element[ widget ]()[ widget ]( "instance" );
6264						}
6265						if ( instance ) {
6266							instanceOptions.classes =
6267								that._resolveClassesValues( instanceOptions.classes, instance );
6268						}
6269						element[ widget ]( instanceOptions );
6270
6271						// Store an instance of the controlgroup to be able to reference
6272						// from the outermost element for changing options and refresh
6273						var widgetElement = element[ widget ]( "widget" );
6274						$.data( widgetElement[ 0 ], "ui-controlgroup-data",
6275							instance ? instance : element[ widget ]( "instance" ) );
6276
6277						childWidgets.push( widgetElement[ 0 ] );
6278					} );
6279			} );
6280
6281			this.childWidgets = $( $.uniqueSort( childWidgets ) );
6282			this._addClass( this.childWidgets, "ui-controlgroup-item" );
6283		},
6284
6285		_callChildMethod: function( method ) {
6286			this.childWidgets.each( function() {
6287				var element = $( this ),
6288					data = element.data( "ui-controlgroup-data" );
6289				if ( data && data[ method ] ) {
6290					data[ method ]();
6291				}
6292			} );
6293		},
6294
6295		_updateCornerClass: function( element, position ) {
6296			var remove = "ui-corner-top ui-corner-bottom ui-corner-left ui-corner-right ui-corner-all";
6297			var add = this._buildSimpleOptions( position, "label" ).classes.label;
6298
6299			this._removeClass( element, null, remove );
6300			this._addClass( element, null, add );
6301		},
6302
6303		_buildSimpleOptions: function( position, key ) {
6304			var direction = this.options.direction === "vertical";
6305			var result = {
6306				classes: {}
6307			};
6308			result.classes[ key ] = {
6309				"middle": "",
6310				"first": "ui-corner-" + ( direction ? "top" : "left" ),
6311				"last": "ui-corner-" + ( direction ? "bottom" : "right" ),
6312				"only": "ui-corner-all"
6313			}[ position ];
6314
6315			return result;
6316		},
6317
6318		_spinnerOptions: function( position ) {
6319			var options = this._buildSimpleOptions( position, "ui-spinner" );
6320
6321			options.classes[ "ui-spinner-up" ] = "";
6322			options.classes[ "ui-spinner-down" ] = "";
6323
6324			return options;
6325		},
6326
6327		_buttonOptions: function( position ) {
6328			return this._buildSimpleOptions( position, "ui-button" );
6329		},
6330
6331		_checkboxradioOptions: function( position ) {
6332			return this._buildSimpleOptions( position, "ui-checkboxradio-label" );
6333		},
6334
6335		_selectmenuOptions: function( position ) {
6336			var direction = this.options.direction === "vertical";
6337			return {
6338				width: direction ? "auto" : false,
6339				classes: {
6340					middle: {
6341						"ui-selectmenu-button-open": "",
6342						"ui-selectmenu-button-closed": ""
6343					},
6344					first: {
6345						"ui-selectmenu-button-open": "ui-corner-" + ( direction ? "top" : "tl" ),
6346						"ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "top" : "left" )
6347					},
6348					last: {
6349						"ui-selectmenu-button-open": direction ? "" : "ui-corner-tr",
6350						"ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "bottom" : "right" )
6351					},
6352					only: {
6353						"ui-selectmenu-button-open": "ui-corner-top",
6354						"ui-selectmenu-button-closed": "ui-corner-all"
6355					}
6356
6357				}[ position ]
6358			};
6359		},
6360
6361		_resolveClassesValues: function( classes, instance ) {
6362			var result = {};
6363			$.each( classes, function( key ) {
6364				var current = instance.options.classes[ key ] || "";
6365				current = String.prototype.trim.call( current.replace( controlgroupCornerRegex, "" ) );
6366				result[ key ] = ( current + " " + classes[ key ] ).replace( /\s+/g, " " );
6367			} );
6368			return result;
6369		},
6370
6371		_setOption: function( key, value ) {
6372			if ( key === "direction" ) {
6373				this._removeClass( "ui-controlgroup-" + this.options.direction );
6374			}
6375
6376			this._super( key, value );
6377			if ( key === "disabled" ) {
6378				this._callChildMethod( value ? "disable" : "enable" );
6379				return;
6380			}
6381
6382			this.refresh();
6383		},
6384
6385		refresh: function() {
6386			var children,
6387				that = this;
6388
6389			this._addClass( "ui-controlgroup ui-controlgroup-" + this.options.direction );
6390
6391			if ( this.options.direction === "horizontal" ) {
6392				this._addClass( null, "ui-helper-clearfix" );
6393			}
6394			this._initWidgets();
6395
6396			children = this.childWidgets;
6397
6398			// We filter here because we need to track all childWidgets not just the visible ones
6399			if ( this.options.onlyVisible ) {
6400				children = children.filter( ":visible" );
6401			}
6402
6403			if ( children.length ) {
6404
6405				// We do this last because we need to make sure all enhancment is done
6406				// before determining first and last
6407				$.each( [ "first", "last" ], function( index, value ) {
6408					var instance = children[ value ]().data( "ui-controlgroup-data" );
6409
6410					if ( instance && that[ "_" + instance.widgetName + "Options" ] ) {
6411						var options = that[ "_" + instance.widgetName + "Options" ](
6412							children.length === 1 ? "only" : value
6413						);
6414						options.classes = that._resolveClassesValues( options.classes, instance );
6415						instance.element[ instance.widgetName ]( options );
6416					} else {
6417						that._updateCornerClass( children[ value ](), value );
6418					}
6419				} );
6420
6421				// Finally call the refresh method on each of the child widgets.
6422				this._callChildMethod( "refresh" );
6423			}
6424		}
6425	} );
6426
6427	/*!
6428 * jQuery UI Checkboxradio 1.14.1
6429 * https://jqueryui.com
6430 *
6431 * Copyright OpenJS Foundation and other contributors
6432 * Released under the MIT license.
6433 * https://jquery.org/license
6434 */
6435
6436//>>label: Checkboxradio
6437//>>group: Widgets
6438//>>description: Enhances a form with multiple themeable checkboxes or radio buttons.
6439//>>docs: https://api.jqueryui.com/checkboxradio/
6440//>>demos: https://jqueryui.com/checkboxradio/
6441//>>css.structure: ../../themes/base/core.css
6442//>>css.structure: ../../themes/base/button.css
6443//>>css.structure: ../../themes/base/checkboxradio.css
6444//>>css.theme: ../../themes/base/theme.css
6445
6446
6447	$.widget( "ui.checkboxradio", [ $.ui.formResetMixin, {
6448		version: "1.14.1",
6449		options: {
6450			disabled: null,
6451			label: null,
6452			icon: true,
6453			classes: {
6454				"ui-checkboxradio-label": "ui-corner-all",
6455				"ui-checkboxradio-icon": "ui-corner-all"
6456			}
6457		},
6458
6459		_getCreateOptions: function() {
6460			var disabled, labels, labelContents;
6461			var options = this._super() || {};
6462
6463			// We read the type here, because it makes more sense to throw a element type error first,
6464			// rather then the error for lack of a label. Often if its the wrong type, it
6465			// won't have a label (e.g. calling on a div, btn, etc)
6466			this._readType();
6467
6468			labels = this.element.labels();
6469
6470			// If there are multiple labels, use the last one
6471			this.label = $( labels[ labels.length - 1 ] );
6472			if ( !this.label.length ) {
6473				$.error( "No label found for checkboxradio widget" );
6474			}
6475
6476			this.originalLabel = "";
6477
6478			// We need to get the label text but this may also need to make sure it does not contain the
6479			// input itself.
6480			// The label contents could be text, html, or a mix. We wrap all elements
6481			// and read the wrapper's `innerHTML` to get a string representation of
6482			// the label, without the input as part of it.
6483			labelContents = this.label.contents().not( this.element[ 0 ] );
6484
6485			if ( labelContents.length ) {
6486				this.originalLabel += labelContents
6487					.clone()
6488					.wrapAll( "<div></div>" )
6489					.parent()
6490					.html();
6491			}
6492
6493			// Set the label option if we found label text
6494			if ( this.originalLabel ) {
6495				options.label = this.originalLabel;
6496			}
6497
6498			disabled = this.element[ 0 ].disabled;
6499			if ( disabled != null ) {
6500				options.disabled = disabled;
6501			}
6502			return options;
6503		},
6504
6505		_create: function() {
6506			var checked = this.element[ 0 ].checked;
6507
6508			this._bindFormResetHandler();
6509
6510			if ( this.options.disabled == null ) {
6511				this.options.disabled = this.element[ 0 ].disabled;
6512			}
6513
6514			this._setOption( "disabled", this.options.disabled );
6515			this._addClass( "ui-checkboxradio", "ui-helper-hidden-accessible" );
6516			this._addClass( this.label, "ui-checkboxradio-label", "ui-button ui-widget" );
6517
6518			if ( this.type === "radio" ) {
6519				this._addClass( this.label, "ui-checkboxradio-radio-label" );
6520			}
6521
6522			if ( this.options.label && this.options.label !== this.originalLabel ) {
6523				this._updateLabel();
6524			} else if ( this.originalLabel ) {
6525				this.options.label = this.originalLabel;
6526			}
6527
6528			this._enhance();
6529
6530			if ( checked ) {
6531				this._addClass( this.label, "ui-checkboxradio-checked", "ui-state-active" );
6532			}
6533
6534			this._on( {
6535				change: "_toggleClasses",
6536				focus: function() {
6537					this._addClass( this.label, null, "ui-state-focus ui-visual-focus" );
6538				},
6539				blur: function() {
6540					this._removeClass( this.label, null, "ui-state-focus ui-visual-focus" );
6541				}
6542			} );
6543		},
6544
6545		_readType: function() {
6546			var nodeName = this.element[ 0 ].nodeName.toLowerCase();
6547			this.type = this.element[ 0 ].type;
6548			if ( nodeName !== "input" || !/radio|checkbox/.test( this.type ) ) {
6549				$.error( "Can't create checkboxradio on element.nodeName=" + nodeName +
6550					" and element.type=" + this.type );
6551			}
6552		},
6553
6554		// Support jQuery Mobile enhanced option
6555		_enhance: function() {
6556			this._updateIcon( this.element[ 0 ].checked );
6557		},
6558
6559		widget: function() {
6560			return this.label;
6561		},
6562
6563		_getRadioGroup: function() {
6564			var group;
6565			var name = this.element[ 0 ].name;
6566			var nameSelector = "input[name='" + CSS.escape( name ) + "']";
6567
6568			if ( !name ) {
6569				return $( [] );
6570			}
6571
6572			if ( this.form.length ) {
6573				group = $( this.form[ 0 ].elements ).filter( nameSelector );
6574			} else {
6575
6576				// Not inside a form, check all inputs that also are not inside a form
6577				group = $( nameSelector ).filter( function() {
6578					return $( $( this ).prop( "form" ) ).length === 0;
6579				} );
6580			}
6581
6582			return group.not( this.element );
6583		},
6584
6585		_toggleClasses: function() {
6586			var checked = this.element[ 0 ].checked;
6587			this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked );
6588
6589			if ( this.options.icon && this.type === "checkbox" ) {
6590				this._toggleClass( this.icon, null, "ui-icon-check ui-state-checked", checked )
6591					._toggleClass( this.icon, null, "ui-icon-blank", !checked );
6592			}
6593
6594			if ( this.type === "radio" ) {
6595				this._getRadioGroup()
6596					.each( function() {
6597						var instance = $( this ).checkboxradio( "instance" );
6598
6599						if ( instance ) {
6600							instance._removeClass( instance.label,
6601								"ui-checkboxradio-checked", "ui-state-active" );
6602						}
6603					} );
6604			}
6605		},
6606
6607		_destroy: function() {
6608			this._unbindFormResetHandler();
6609
6610			if ( this.icon ) {
6611				this.icon.remove();
6612				this.iconSpace.remove();
6613			}
6614		},
6615
6616		_setOption: function( key, value ) {
6617
6618			// We don't allow the value to be set to nothing
6619			if ( key === "label" && !value ) {
6620				return;
6621			}
6622
6623			this._super( key, value );
6624
6625			if ( key === "disabled" ) {
6626				this._toggleClass( this.label, null, "ui-state-disabled", value );
6627				this.element[ 0 ].disabled = value;
6628
6629				// Don't refresh when setting disabled
6630				return;
6631			}
6632			this.refresh();
6633		},
6634
6635		_updateIcon: function( checked ) {
6636			var toAdd = "ui-icon ui-icon-background ";
6637
6638			if ( this.options.icon ) {
6639				if ( !this.icon ) {
6640					this.icon = $( "<span>" );
6641					this.iconSpace = $( "<span> </span>" );
6642					this._addClass( this.iconSpace, "ui-checkboxradio-icon-space" );
6643				}
6644
6645				if ( this.type === "checkbox" ) {
6646					toAdd += checked ? "ui-icon-check ui-state-checked" : "ui-icon-blank";
6647					this._removeClass( this.icon, null, checked ? "ui-icon-blank" : "ui-icon-check" );
6648				} else {
6649					toAdd += "ui-icon-blank";
6650				}
6651				this._addClass( this.icon, "ui-checkboxradio-icon", toAdd );
6652				if ( !checked ) {
6653					this._removeClass( this.icon, null, "ui-icon-check ui-state-checked" );
6654				}
6655				this.icon.prependTo( this.label ).after( this.iconSpace );
6656			} else if ( this.icon !== undefined ) {
6657				this.icon.remove();
6658				this.iconSpace.remove();
6659				delete this.icon;
6660			}
6661		},
6662
6663		_updateLabel: function() {
6664
6665			// Remove the contents of the label ( minus the icon, icon space, and input )
6666			var contents = this.label.contents().not( this.element[ 0 ] );
6667			if ( this.icon ) {
6668				contents = contents.not( this.icon[ 0 ] );
6669			}
6670			if ( this.iconSpace ) {
6671				contents = contents.not( this.iconSpace[ 0 ] );
6672			}
6673			contents.remove();
6674
6675			this.label.append( this.options.label );
6676		},
6677
6678		refresh: function() {
6679			var checked = this.element[ 0 ].checked,
6680				isDisabled = this.element[ 0 ].disabled;
6681
6682			this._updateIcon( checked );
6683			this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked );
6684			if ( this.options.label !== null ) {
6685				this._updateLabel();
6686			}
6687
6688			if ( isDisabled !== this.options.disabled ) {
6689				this._setOptions( { "disabled": isDisabled } );
6690			}
6691		}
6692
6693	} ] );
6694
6695	var widgetsCheckboxradio = $.ui.checkboxradio;
6696
6697
6698	/*!
6699 * jQuery UI Button 1.14.1
6700 * https://jqueryui.com
6701 *
6702 * Copyright OpenJS Foundation and other contributors
6703 * Released under the MIT license.
6704 * https://jquery.org/license
6705 */
6706
6707//>>label: Button
6708//>>group: Widgets
6709//>>description: Enhances a form with themeable buttons.
6710//>>docs: https://api.jqueryui.com/button/
6711//>>demos: https://jqueryui.com/button/
6712//>>css.structure: ../../themes/base/core.css
6713//>>css.structure: ../../themes/base/button.css
6714//>>css.theme: ../../themes/base/theme.css
6715
6716
6717	$.widget( "ui.button", {
6718		version: "1.14.1",
6719		defaultElement: "<button>",
6720		options: {
6721			classes: {
6722				"ui-button": "ui-corner-all"
6723			},
6724			disabled: null,
6725			icon: null,
6726			iconPosition: "beginning",
6727			label: null,
6728			showLabel: true
6729		},
6730
6731		_getCreateOptions: function() {
6732			var disabled,
6733
6734				// This is to support cases like in jQuery Mobile where the base widget does have
6735				// an implementation of _getCreateOptions
6736				options = this._super() || {};
6737
6738			this.isInput = this.element.is( "input" );
6739
6740			disabled = this.element[ 0 ].disabled;
6741			if ( disabled != null ) {
6742				options.disabled = disabled;
6743			}
6744
6745			this.originalLabel = this.isInput ? this.element.val() : this.element.html();
6746			if ( this.originalLabel ) {
6747				options.label = this.originalLabel;
6748			}
6749
6750			return options;
6751		},
6752
6753		_create: function() {
6754			if ( !this.option.showLabel & !this.options.icon ) {
6755				this.options.showLabel = true;
6756			}
6757
6758			// We have to check the option again here even though we did in _getCreateOptions,
6759			// because null may have been passed on init which would override what was set in
6760			// _getCreateOptions
6761			if ( this.options.disabled == null ) {
6762				this.options.disabled = this.element[ 0 ].disabled || false;
6763			}
6764
6765			this.hasTitle = !!this.element.attr( "title" );
6766
6767			// Check to see if the label needs to be set or if its already correct
6768			if ( this.options.label && this.options.label !== this.originalLabel ) {
6769				if ( this.isInput ) {
6770					this.element.val( this.options.label );
6771				} else {
6772					this.element.html( this.options.label );
6773				}
6774			}
6775			this._addClass( "ui-button", "ui-widget" );
6776			this._setOption( "disabled", this.options.disabled );
6777			this._enhance();
6778
6779			if ( this.element.is( "a" ) ) {
6780				this._on( {
6781					"keyup": function( event ) {
6782						if ( event.keyCode === $.ui.keyCode.SPACE ) {
6783							event.preventDefault();
6784
6785							// If a native click is available use it, so we
6786							// actually cause navigation. Otherwise, just trigger
6787							// a click event.
6788							if ( this.element[ 0 ].click ) {
6789								this.element[ 0 ].click();
6790							} else {
6791								this.element.trigger( "click" );
6792							}
6793						}
6794					}
6795				} );
6796			}
6797		},
6798
6799		_enhance: function() {
6800			if ( !this.element.is( "button" ) ) {
6801				this.element.attr( "role", "button" );
6802			}
6803
6804			if ( this.options.icon ) {
6805				this._updateIcon( "icon", this.options.icon );
6806				this._updateTooltip();
6807			}
6808		},
6809
6810		_updateTooltip: function() {
6811			this.title = this.element.attr( "title" );
6812
6813			if ( !this.options.showLabel && !this.title ) {
6814				this.element.attr( "title", this.options.label );
6815			}
6816		},
6817
6818		_updateIcon: function( option, value ) {
6819			var icon = option !== "iconPosition",
6820				position = icon ? this.options.iconPosition : value,
6821				displayBlock = position === "top" || position === "bottom";
6822
6823			// Create icon
6824			if ( !this.icon ) {
6825				this.icon = $( "<span>" );
6826
6827				this._addClass( this.icon, "ui-button-icon", "ui-icon" );
6828
6829				if ( !this.options.showLabel ) {
6830					this._addClass( "ui-button-icon-only" );
6831				}
6832			} else if ( icon ) {
6833
6834				// If we are updating the icon remove the old icon class
6835				this._removeClass( this.icon, null, this.options.icon );
6836			}
6837
6838			// If we are updating the icon add the new icon class
6839			if ( icon ) {
6840				this._addClass( this.icon, null, value );
6841			}
6842
6843			this._attachIcon( position );
6844
6845			// If the icon is on top or bottom we need to add the ui-widget-icon-block class and remove
6846			// the iconSpace if there is one.
6847			if ( displayBlock ) {
6848				this._addClass( this.icon, null, "ui-widget-icon-block" );
6849				if ( this.iconSpace ) {
6850					this.iconSpace.remove();
6851				}
6852			} else {
6853
6854				// Position is beginning or end so remove the ui-widget-icon-block class and add the
6855				// space if it does not exist
6856				if ( !this.iconSpace ) {
6857					this.iconSpace = $( "<span> </span>" );
6858					this._addClass( this.iconSpace, "ui-button-icon-space" );
6859				}
6860				this._removeClass( this.icon, null, "ui-wiget-icon-block" );
6861				this._attachIconSpace( position );
6862			}
6863		},
6864
6865		_destroy: function() {
6866			this.element.removeAttr( "role" );
6867
6868			if ( this.icon ) {
6869				this.icon.remove();
6870			}
6871			if ( this.iconSpace ) {
6872				this.iconSpace.remove();
6873			}
6874			if ( !this.hasTitle ) {
6875				this.element.removeAttr( "title" );
6876			}
6877		},
6878
6879		_attachIconSpace: function( iconPosition ) {
6880			this.icon[ /^(?:end|bottom)/.test( iconPosition ) ? "before" : "after" ]( this.iconSpace );
6881		},
6882
6883		_attachIcon: function( iconPosition ) {
6884			this.element[ /^(?:end|bottom)/.test( iconPosition ) ? "append" : "prepend" ]( this.icon );
6885		},
6886
6887		_setOptions: function( options ) {
6888			var newShowLabel = options.showLabel === undefined ?
6889					this.options.showLabel :
6890					options.showLabel,
6891				newIcon = options.icon === undefined ? this.options.icon : options.icon;
6892
6893			if ( !newShowLabel && !newIcon ) {
6894				options.showLabel = true;
6895			}
6896			this._super( options );
6897		},
6898
6899		_setOption: function( key, value ) {
6900			if ( key === "icon" ) {
6901				if ( value ) {
6902					this._updateIcon( key, value );
6903				} else if ( this.icon ) {
6904					this.icon.remove();
6905					if ( this.iconSpace ) {
6906						this.iconSpace.remove();
6907					}
6908				}
6909			}
6910
6911			if ( key === "iconPosition" ) {
6912				this._updateIcon( key, value );
6913			}
6914
6915			// Make sure we can't end up with a button that has neither text nor icon
6916			if ( key === "showLabel" ) {
6917				this._toggleClass( "ui-button-icon-only", null, !value );
6918				this._updateTooltip();
6919			}
6920
6921			if ( key === "label" ) {
6922				if ( this.isInput ) {
6923					this.element.val( value );
6924				} else {
6925
6926					// If there is an icon, append it, else nothing then append the value
6927					// this avoids removal of the icon when setting label text
6928					this.element.html( value );
6929					if ( this.icon ) {
6930						this._attachIcon( this.options.iconPosition );
6931						this._attachIconSpace( this.options.iconPosition );
6932					}
6933				}
6934			}
6935
6936			this._super( key, value );
6937
6938			if ( key === "disabled" ) {
6939				this._toggleClass( null, "ui-state-disabled", value );
6940				this.element[ 0 ].disabled = value;
6941				if ( value ) {
6942					this.element.trigger( "blur" );
6943				}
6944			}
6945		},
6946
6947		refresh: function() {
6948
6949			// Make sure to only check disabled if its an element that supports this otherwise
6950			// check for the disabled class to determine state
6951			var isDisabled = this.element.is( "input, button" ) ?
6952				this.element[ 0 ].disabled : this.element.hasClass( "ui-button-disabled" );
6953
6954			if ( isDisabled !== this.options.disabled ) {
6955				this._setOptions( { disabled: isDisabled } );
6956			}
6957
6958			this._updateTooltip();
6959		}
6960	} );
6961
6962// DEPRECATED
6963	if ( $.uiBackCompat === true ) {
6964
6965		// Text and Icons options
6966		$.widget( "ui.button", $.ui.button, {
6967			options: {
6968				text: true,
6969				icons: {
6970					primary: null,
6971					secondary: null
6972				}
6973			},
6974
6975			_create: function() {
6976				if ( this.options.showLabel && !this.options.text ) {
6977					this.options.showLabel = this.options.text;
6978				}
6979				if ( !this.options.showLabel && this.options.text ) {
6980					this.options.text = this.options.showLabel;
6981				}
6982				if ( !this.options.icon && ( this.options.icons.primary ||
6983					this.options.icons.secondary ) ) {
6984					if ( this.options.icons.primary ) {
6985						this.options.icon = this.options.icons.primary;
6986					} else {
6987						this.options.icon = this.options.icons.secondary;
6988						this.options.iconPosition = "end";
6989					}
6990				} else if ( this.options.icon ) {
6991					this.options.icons.primary = this.options.icon;
6992				}
6993				this._super();
6994			},
6995
6996			_setOption: function( key, value ) {
6997				if ( key === "text" ) {
6998					this._super( "showLabel", value );
6999					return;
7000				}
7001				if ( key === "showLabel" ) {
7002					this.options.text = value;
7003				}
7004				if ( key === "icon" ) {
7005					this.options.icons.primary = value;
7006				}
7007				if ( key === "icons" ) {
7008					if ( value.primary ) {
7009						this._super( "icon", value.primary );
7010						this._super( "iconPosition", "beginning" );
7011					} else if ( value.secondary ) {
7012						this._super( "icon", value.secondary );
7013						this._super( "iconPosition", "end" );
7014					}
7015				}
7016				this._superApply( arguments );
7017			}
7018		} );
7019
7020		$.fn.button = ( function( orig ) {
7021			return function( options ) {
7022				var isMethodCall = typeof options === "string";
7023				var args = Array.prototype.slice.call( arguments, 1 );
7024				var returnValue = this;
7025
7026				if ( isMethodCall ) {
7027
7028					// If this is an empty collection, we need to have the instance method
7029					// return undefined instead of the jQuery instance
7030					if ( !this.length && options === "instance" ) {
7031						returnValue = undefined;
7032					} else {
7033						this.each( function() {
7034							var methodValue;
7035							var type = $( this ).attr( "type" );
7036							var name = type !== "checkbox" && type !== "radio" ?
7037								"button" :
7038								"checkboxradio";
7039							var instance = $.data( this, "ui-" + name );
7040
7041							if ( options === "instance" ) {
7042								returnValue = instance;
7043								return false;
7044							}
7045
7046							if ( !instance ) {
7047								return $.error( "cannot call methods on button" +
7048									" prior to initialization; " +
7049									"attempted to call method '" + options + "'" );
7050							}
7051
7052							if ( typeof instance[ options ] !== "function" ||
7053								options.charAt( 0 ) === "_" ) {
7054								return $.error( "no such method '" + options + "' for button" +
7055									" widget instance" );
7056							}
7057
7058							methodValue = instance[ options ].apply( instance, args );
7059
7060							if ( methodValue !== instance && methodValue !== undefined ) {
7061								returnValue = methodValue && methodValue.jquery ?
7062									returnValue.pushStack( methodValue.get() ) :
7063									methodValue;
7064								return false;
7065							}
7066						} );
7067					}
7068				} else {
7069
7070					// Allow multiple hashes to be passed on init
7071					if ( args.length ) {
7072						options = $.widget.extend.apply( null, [ options ].concat( args ) );
7073					}
7074
7075					this.each( function() {
7076						var type = $( this ).attr( "type" );
7077						var name = type !== "checkbox" && type !== "radio" ? "button" : "checkboxradio";
7078						var instance = $.data( this, "ui-" + name );
7079
7080						if ( instance ) {
7081							instance.option( options || {} );
7082							if ( instance._init ) {
7083								instance._init();
7084							}
7085						} else {
7086							if ( name === "button" ) {
7087								orig.call( $( this ), options );
7088								return;
7089							}
7090
7091							$( this ).checkboxradio( $.extend( { icon: false }, options ) );
7092						}
7093					} );
7094				}
7095
7096				return returnValue;
7097			};
7098		} )( $.fn.button );
7099
7100		$.fn.buttonset = function() {
7101			if ( !$.ui.controlgroup ) {
7102				$.error( "Controlgroup widget missing" );
7103			}
7104			if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" && arguments[ 2 ] ) {
7105				return this.controlgroup.apply( this,
7106					[ arguments[ 0 ], "items.button", arguments[ 2 ] ] );
7107			}
7108			if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" ) {
7109				return this.controlgroup.apply( this, [ arguments[ 0 ], "items.button" ] );
7110			}
7111			if ( typeof arguments[ 0 ] === "object" && arguments[ 0 ].items ) {
7112				arguments[ 0 ].items = {
7113					button: arguments[ 0 ].items
7114				};
7115			}
7116			return this.controlgroup.apply( this, arguments );
7117		};
7118	}
7119
7120	var widgetsButton = $.ui.button;
7121
7122
7123	/* eslint-disable max-len, camelcase */
7124	/*!
7125 * jQuery UI Datepicker 1.14.1
7126 * https://jqueryui.com
7127 *
7128 * Copyright OpenJS Foundation and other contributors
7129 * Released under the MIT license.
7130 * https://jquery.org/license
7131 */
7132
7133//>>label: Datepicker
7134//>>group: Widgets
7135//>>description: Displays a calendar from an input or inline for selecting dates.
7136//>>docs: https://api.jqueryui.com/datepicker/
7137//>>demos: https://jqueryui.com/datepicker/
7138//>>css.structure: ../../themes/base/core.css
7139//>>css.structure: ../../themes/base/datepicker.css
7140//>>css.theme: ../../themes/base/theme.css
7141
7142
7143	$.extend( $.ui, { datepicker: { version: "1.14.1" } } );
7144
7145	var datepicker_instActive;
7146
7147	function datepicker_getZindex( elem ) {
7148		var position, value;
7149		while ( elem.length && elem[ 0 ] !== document ) {
7150
7151			// Ignore z-index if position is set to a value where z-index is ignored by the browser
7152			// This makes behavior of this function consistent across browsers
7153			// WebKit always returns auto if the element is positioned
7154			position = elem.css( "position" );
7155			if ( position === "absolute" || position === "relative" || position === "fixed" ) {
7156
7157				// IE returns 0 when zIndex is not specified
7158				// other browsers return a string
7159				// we ignore the case of nested elements with an explicit value of 0
7160				// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
7161				value = parseInt( elem.css( "zIndex" ), 10 );
7162				if ( !isNaN( value ) && value !== 0 ) {
7163					return value;
7164				}
7165			}
7166			elem = elem.parent();
7167		}
7168
7169		return 0;
7170	}
7171
7172	/* Date picker manager.
7173   Use the singleton instance of this class, $.datepicker, to interact with the date picker.
7174   Settings for (groups of) date pickers are maintained in an instance object,
7175   allowing multiple different settings on the same page. */
7176
7177	function Datepicker() {
7178		this._curInst = null; // The current instance in use
7179		this._keyEvent = false; // If the last event was a key event
7180		this._disabledInputs = []; // List of date picker inputs that have been disabled
7181		this._datepickerShowing = false; // True if the popup picker is showing , false if not
7182		this._inDialog = false; // True if showing within a "dialog", false if not
7183		this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division
7184		this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class
7185		this._appendClass = "ui-datepicker-append"; // The name of the append marker class
7186		this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class
7187		this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class
7188		this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class
7189		this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class
7190		this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class
7191		this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class
7192		this.regional = []; // Available regional settings, indexed by language code
7193		this.regional[ "" ] = { // Default regional settings
7194			closeText: "Done", // Display text for close link
7195			prevText: "Prev", // Display text for previous month link
7196			nextText: "Next", // Display text for next month link
7197			currentText: "Today", // Display text for current month link
7198			monthNames: [ "January", "February", "March", "April", "May", "June",
7199				"July", "August", "September", "October", "November", "December" ], // Names of months for drop-down and formatting
7200			monthNamesShort: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ], // For formatting
7201			dayNames: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], // For formatting
7202			dayNamesShort: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], // For formatting
7203			dayNamesMin: [ "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" ], // Column headings for days starting at Sunday
7204			weekHeader: "Wk", // Column header for week of the year
7205			dateFormat: "mm/dd/yy", // See format options on parseDate
7206			firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
7207			isRTL: false, // True if right-to-left language, false if left-to-right
7208			showMonthAfterYear: false, // True if the year select precedes month, false for month then year
7209			yearSuffix: "", // Additional text to append to the year in the month headers,
7210			selectMonthLabel: "Select month", // Invisible label for month selector
7211			selectYearLabel: "Select year" // Invisible label for year selector
7212		};
7213		this._defaults = { // Global defaults for all the date picker instances
7214			showOn: "focus", // "focus" for popup on focus,
7215			// "button" for trigger button, or "both" for either
7216			showAnim: "fadeIn", // Name of jQuery animation for popup
7217			showOptions: {}, // Options for enhanced animations
7218			defaultDate: null, // Used when field is blank: actual date,
7219			// +/-number for offset from today, null for today
7220			appendText: "", // Display text following the input box, e.g. showing the format
7221			buttonText: "...", // Text for trigger button
7222			buttonImage: "", // URL for trigger button image
7223			buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
7224			hideIfNoPrevNext: false, // True to hide next/previous month links
7225			// if not applicable, false to just disable them
7226			navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
7227			gotoCurrent: false, // True if today link goes back to current selection instead
7228			changeMonth: false, // True if month can be selected directly, false if only prev/next
7229			changeYear: false, // True if year can be selected directly, false if only prev/next
7230			yearRange: "c-10:c+10", // Range of years to display in drop-down,
7231			// either relative to today's year (-nn:+nn), relative to currently displayed year
7232			// (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
7233			showOtherMonths: false, // True to show dates in other months, false to leave blank
7234			selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
7235			showWeek: false, // True to show week of the year, false to not show it
7236			calculateWeek: this.iso8601Week, // How to calculate the week of the year,
7237			// takes a Date and returns the number of the week for it
7238			shortYearCutoff: "+10", // Short year values < this are in the current century,
7239			// > this are in the previous century,
7240			// string value starting with "+" for current year + value
7241			minDate: null, // The earliest selectable date, or null for no limit
7242			maxDate: null, // The latest selectable date, or null for no limit
7243			duration: "fast", // Duration of display/closure
7244			beforeShowDay: null, // Function that takes a date and returns an array with
7245			// [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "",
7246			// [2] = cell title (optional), e.g. $.datepicker.noWeekends
7247			beforeShow: null, // Function that takes an input field and
7248			// returns a set of custom settings for the date picker
7249			onSelect: null, // Define a callback function when a date is selected
7250			onChangeMonthYear: null, // Define a callback function when the month or year is changed
7251			onClose: null, // Define a callback function when the datepicker is closed
7252			onUpdateDatepicker: null, // Define a callback function when the datepicker is updated
7253			numberOfMonths: 1, // Number of months to show at a time
7254			showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
7255			stepMonths: 1, // Number of months to step back/forward
7256			stepBigMonths: 12, // Number of months to step back/forward for the big links
7257			altField: "", // Selector for an alternate field to store selected dates into
7258			altFormat: "", // The date format to use for the alternate field
7259			constrainInput: true, // The input is constrained by the current date format
7260			showButtonPanel: false, // True to show button panel, false to not show it
7261			autoSize: false, // True to size the input for the date format, false to leave as is
7262			disabled: false // The initial disabled state
7263		};
7264		$.extend( this._defaults, this.regional[ "" ] );
7265		this.regional.en = $.extend( true, {}, this.regional[ "" ] );
7266		this.regional[ "en-US" ] = $.extend( true, {}, this.regional.en );
7267		this.dpDiv = datepicker_bindHover( $( "<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) );
7268	}
7269
7270	$.extend( Datepicker.prototype, {
7271
7272		/* Class name added to elements to indicate already configured with a date picker. */
7273		markerClassName: "hasDatepicker",
7274
7275		//Keep track of the maximum number of rows displayed (see #7043)
7276		maxRows: 4,
7277
7278		// TODO rename to "widget" when switching to widget factory
7279		_widgetDatepicker: function() {
7280			return this.dpDiv;
7281		},
7282
7283		/* Override the default settings for all instances of the date picker.
7284	 * @param  settings  object - the new settings to use as defaults (anonymous object)
7285	 * @return the manager object
7286	 */
7287		setDefaults: function( settings ) {
7288			datepicker_extendRemove( this._defaults, settings || {} );
7289			return this;
7290		},
7291
7292		/* Attach the date picker to a jQuery selection.
7293	 * @param  target	element - the target input field or division or span
7294	 * @param  settings  object - the new settings to use for this date picker instance (anonymous)
7295	 */
7296		_attachDatepicker: function( target, settings ) {
7297			var nodeName, inline, inst;
7298			nodeName = target.nodeName.toLowerCase();
7299			inline = ( nodeName === "div" || nodeName === "span" );
7300			if ( !target.id ) {
7301				this.uuid += 1;
7302				target.id = "dp" + this.uuid;
7303			}
7304			inst = this._newInst( $( target ), inline );
7305			inst.settings = $.extend( {}, settings || {} );
7306			if ( nodeName === "input" ) {
7307				this._connectDatepicker( target, inst );
7308			} else if ( inline ) {
7309				this._inlineDatepicker( target, inst );
7310			}
7311		},
7312
7313		/* Create a new instance object. */
7314		_newInst: function( target, inline ) {
7315			var id = target[ 0 ].id.replace( /([^A-Za-z0-9_\-])/g, "\\\\$1" ); // escape jQuery meta chars
7316			return { id: id, input: target, // associated target
7317				selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
7318				drawMonth: 0, drawYear: 0, // month being drawn
7319				inline: inline, // is datepicker inline or not
7320				dpDiv: ( !inline ? this.dpDiv : // presentation div
7321					datepicker_bindHover( $( "<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) ) ) };
7322		},
7323
7324		/* Attach the date picker to an input field. */
7325		_connectDatepicker: function( target, inst ) {
7326			var input = $( target );
7327			inst.append = $( [] );
7328			inst.trigger = $( [] );
7329			if ( input.hasClass( this.markerClassName ) ) {
7330				return;
7331			}
7332			this._attachments( input, inst );
7333			input.addClass( this.markerClassName ).on( "keydown", this._doKeyDown ).
7334			on( "keypress", this._doKeyPress ).on( "keyup", this._doKeyUp );
7335			this._autoSize( inst );
7336			$.data( target, "datepicker", inst );
7337
7338			//If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
7339			if ( inst.settings.disabled ) {
7340				this._disableDatepicker( target );
7341			}
7342		},
7343
7344		/* Make attachments based on settings. */
7345		_attachments: function( input, inst ) {
7346			var showOn, buttonText, buttonImage,
7347				appendText = this._get( inst, "appendText" ),
7348				isRTL = this._get( inst, "isRTL" );
7349
7350			if ( inst.append ) {
7351				inst.append.remove();
7352			}
7353			if ( appendText ) {
7354				inst.append = $( "<span>" )
7355					.addClass( this._appendClass )
7356					.text( appendText );
7357				input[ isRTL ? "before" : "after" ]( inst.append );
7358			}
7359
7360			input.off( "focus", this._showDatepicker );
7361
7362			if ( inst.trigger ) {
7363				inst.trigger.remove();
7364			}
7365
7366			showOn = this._get( inst, "showOn" );
7367			if ( showOn === "focus" || showOn === "both" ) { // pop-up date picker when in the marked field
7368				input.on( "focus", this._showDatepicker );
7369			}
7370			if ( showOn === "button" || showOn === "both" ) { // pop-up date picker when button clicked
7371				buttonText = this._get( inst, "buttonText" );
7372				buttonImage = this._get( inst, "buttonImage" );
7373
7374				if ( this._get( inst, "buttonImageOnly" ) ) {
7375					inst.trigger = $( "<img>" )
7376						.addClass( this._triggerClass )
7377						.attr( {
7378							src: buttonImage,
7379							alt: buttonText,
7380							title: buttonText
7381						} );
7382				} else {
7383					inst.trigger = $( "<button type='button'>" )
7384						.addClass( this._triggerClass );
7385					if ( buttonImage ) {
7386						inst.trigger.html(
7387							$( "<img>" )
7388								.attr( {
7389									src: buttonImage,
7390									alt: buttonText,
7391									title: buttonText
7392								} )
7393						);
7394					} else {
7395						inst.trigger.text( buttonText );
7396					}
7397				}
7398
7399				input[ isRTL ? "before" : "after" ]( inst.trigger );
7400				inst.trigger.on( "click", function() {
7401					if ( $.datepicker._datepickerShowing && $.datepicker._lastInput === input[ 0 ] ) {
7402						$.datepicker._hideDatepicker();
7403					} else if ( $.datepicker._datepickerShowing && $.datepicker._lastInput !== input[ 0 ] ) {
7404						$.datepicker._hideDatepicker();
7405						$.datepicker._showDatepicker( input[ 0 ] );
7406					} else {
7407						$.datepicker._showDatepicker( input[ 0 ] );
7408					}
7409					return false;
7410				} );
7411			}
7412		},
7413
7414		/* Apply the maximum length for the date format. */
7415		_autoSize: function( inst ) {
7416			if ( this._get( inst, "autoSize" ) && !inst.inline ) {
7417				var findMax, max, maxI, i,
7418					date = new Date( 2009, 12 - 1, 20 ), // Ensure double digits
7419					dateFormat = this._get( inst, "dateFormat" );
7420
7421				if ( dateFormat.match( /[DM]/ ) ) {
7422					findMax = function( names ) {
7423						max = 0;
7424						maxI = 0;
7425						for ( i = 0; i < names.length; i++ ) {
7426							if ( names[ i ].length > max ) {
7427								max = names[ i ].length;
7428								maxI = i;
7429							}
7430						}
7431						return maxI;
7432					};
7433					date.setMonth( findMax( this._get( inst, ( dateFormat.match( /MM/ ) ?
7434						"monthNames" : "monthNamesShort" ) ) ) );
7435					date.setDate( findMax( this._get( inst, ( dateFormat.match( /DD/ ) ?
7436						"dayNames" : "dayNamesShort" ) ) ) + 20 - date.getDay() );
7437				}
7438				inst.input.attr( "size", this._formatDate( inst, date ).length );
7439			}
7440		},
7441
7442		/* Attach an inline date picker to a div. */
7443		_inlineDatepicker: function( target, inst ) {
7444			var divSpan = $( target );
7445			if ( divSpan.hasClass( this.markerClassName ) ) {
7446				return;
7447			}
7448			divSpan.addClass( this.markerClassName ).append( inst.dpDiv );
7449			$.data( target, "datepicker", inst );
7450			this._setDate( inst, this._getDefaultDate( inst ), true );
7451			this._updateDatepicker( inst );
7452			this._updateAlternate( inst );
7453
7454			//If disabled option is true, disable the datepicker before showing it (see ticket #5665)
7455			if ( inst.settings.disabled ) {
7456				this._disableDatepicker( target );
7457			}
7458
7459			// Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
7460			// https://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
7461			inst.dpDiv.css( "display", "block" );
7462		},
7463
7464		/* Pop-up the date picker in a "dialog" box.
7465	 * @param  input element - ignored
7466	 * @param  date	string or Date - the initial date to display
7467	 * @param  onSelect  function - the function to call when a date is selected
7468	 * @param  settings  object - update the dialog date picker instance's settings (anonymous object)
7469	 * @param  pos int[2] - coordinates for the dialog's position within the screen or
7470	 *					event - with x/y coordinates or
7471	 *					leave empty for default (screen centre)
7472	 * @return the manager object
7473	 */
7474		_dialogDatepicker: function( input, date, onSelect, settings, pos ) {
7475			var id, browserWidth, browserHeight, scrollX, scrollY,
7476				inst = this._dialogInst; // internal instance
7477
7478			if ( !inst ) {
7479				this.uuid += 1;
7480				id = "dp" + this.uuid;
7481				this._dialogInput = $( "<input type='text' id='" + id +
7482					"' style='position: absolute; top: -100px; width: 0px;'/>" );
7483				this._dialogInput.on( "keydown", this._doKeyDown );
7484				$( "body" ).append( this._dialogInput );
7485				inst = this._dialogInst = this._newInst( this._dialogInput, false );
7486				inst.settings = {};
7487				$.data( this._dialogInput[ 0 ], "datepicker", inst );
7488			}
7489			datepicker_extendRemove( inst.settings, settings || {} );
7490			date = ( date && date.constructor === Date ? this._formatDate( inst, date ) : date );
7491			this._dialogInput.val( date );
7492
7493			this._pos = ( pos ? ( pos.length ? pos : [ pos.pageX, pos.pageY ] ) : null );
7494			if ( !this._pos ) {
7495				browserWidth = document.documentElement.clientWidth;
7496				browserHeight = document.documentElement.clientHeight;
7497				scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
7498				scrollY = document.documentElement.scrollTop || document.body.scrollTop;
7499				this._pos = // should use actual width/height below
7500					[ ( browserWidth / 2 ) - 100 + scrollX, ( browserHeight / 2 ) - 150 + scrollY ];
7501			}
7502
7503			// Move input on screen for focus, but hidden behind dialog
7504			this._dialogInput.css( "left", ( this._pos[ 0 ] + 20 ) + "px" ).css( "top", this._pos[ 1 ] + "px" );
7505			inst.settings.onSelect = onSelect;
7506			this._inDialog = true;
7507			this.dpDiv.addClass( this._dialogClass );
7508			this._showDatepicker( this._dialogInput[ 0 ] );
7509			if ( $.blockUI ) {
7510				$.blockUI( this.dpDiv );
7511			}
7512			$.data( this._dialogInput[ 0 ], "datepicker", inst );
7513			return this;
7514		},
7515
7516		/* Detach a datepicker from its control.
7517	 * @param  target	element - the target input field or division or span
7518	 */
7519		_destroyDatepicker: function( target ) {
7520			var nodeName,
7521				$target = $( target ),
7522				inst = $.data( target, "datepicker" );
7523
7524			if ( !$target.hasClass( this.markerClassName ) ) {
7525				return;
7526			}
7527
7528			nodeName = target.nodeName.toLowerCase();
7529			$.removeData( target, "datepicker" );
7530			if ( nodeName === "input" ) {
7531				inst.append.remove();
7532				inst.trigger.remove();
7533				$target.removeClass( this.markerClassName ).
7534				off( "focus", this._showDatepicker ).
7535				off( "keydown", this._doKeyDown ).
7536				off( "keypress", this._doKeyPress ).
7537				off( "keyup", this._doKeyUp );
7538			} else if ( nodeName === "div" || nodeName === "span" ) {
7539				$target.removeClass( this.markerClassName ).empty();
7540			}
7541
7542			$.datepicker._hideDatepicker();
7543			if ( datepicker_instActive === inst ) {
7544				datepicker_instActive = null;
7545				this._curInst = null;
7546			}
7547		},
7548
7549		/* Enable the date picker to a jQuery selection.
7550	 * @param  target	element - the target input field or division or span
7551	 */
7552		_enableDatepicker: function( target ) {
7553			var nodeName, inline,
7554				$target = $( target ),
7555				inst = $.data( target, "datepicker" );
7556
7557			if ( !$target.hasClass( this.markerClassName ) ) {
7558				return;
7559			}
7560
7561			nodeName = target.nodeName.toLowerCase();
7562			if ( nodeName === "input" ) {
7563				target.disabled = false;
7564				inst.trigger.filter( "button" ).
7565				each( function() {
7566					this.disabled = false;
7567				} ).end().
7568				filter( "img" ).css( { opacity: "1.0", cursor: "" } );
7569			} else if ( nodeName === "div" || nodeName === "span" ) {
7570				inline = $target.children( "." + this._inlineClass );
7571				inline.children().removeClass( "ui-state-disabled" );
7572				inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ).
7573				prop( "disabled", false );
7574			}
7575			this._disabledInputs = $.map( this._disabledInputs,
7576
7577				// Delete entry
7578				function( value ) {
7579					return ( value === target ? null : value );
7580				} );
7581		},
7582
7583		/* Disable the date picker to a jQuery selection.
7584	 * @param  target	element - the target input field or division or span
7585	 */
7586		_disableDatepicker: function( target ) {
7587			var nodeName, inline,
7588				$target = $( target ),
7589				inst = $.data( target, "datepicker" );
7590
7591			if ( !$target.hasClass( this.markerClassName ) ) {
7592				return;
7593			}
7594
7595			nodeName = target.nodeName.toLowerCase();
7596			if ( nodeName === "input" ) {
7597				target.disabled = true;
7598				inst.trigger.filter( "button" ).
7599				each( function() {
7600					this.disabled = true;
7601				} ).end().
7602				filter( "img" ).css( { opacity: "0.5", cursor: "default" } );
7603			} else if ( nodeName === "div" || nodeName === "span" ) {
7604				inline = $target.children( "." + this._inlineClass );
7605				inline.children().addClass( "ui-state-disabled" );
7606				inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ).
7607				prop( "disabled", true );
7608			}
7609			this._disabledInputs = $.map( this._disabledInputs,
7610
7611				// Delete entry
7612				function( value ) {
7613					return ( value === target ? null : value );
7614				} );
7615			this._disabledInputs[ this._disabledInputs.length ] = target;
7616		},
7617
7618		/* Is the first field in a jQuery collection disabled as a datepicker?
7619	 * @param  target	element - the target input field or division or span
7620	 * @return boolean - true if disabled, false if enabled
7621	 */
7622		_isDisabledDatepicker: function( target ) {
7623			if ( !target ) {
7624				return false;
7625			}
7626			for ( var i = 0; i < this._disabledInputs.length; i++ ) {
7627				if ( this._disabledInputs[ i ] === target ) {
7628					return true;
7629				}
7630			}
7631			return false;
7632		},
7633
7634		/* Retrieve the instance data for the target control.
7635	 * @param  target  element - the target input field or division or span
7636	 * @return  object - the associated instance data
7637	 * @throws  error if a jQuery problem getting data
7638	 */
7639		_getInst: function( target ) {
7640			try {
7641				return $.data( target, "datepicker" );
7642			} catch ( err ) {
7643				throw "Missing instance data for this datepicker";
7644			}
7645		},
7646
7647		/* Update or retrieve the settings for a date picker attached to an input field or division.
7648	 * @param  target  element - the target input field or division or span
7649	 * @param  name	object - the new settings to update or
7650	 *				string - the name of the setting to change or retrieve,
7651	 *				when retrieving also "all" for all instance settings or
7652	 *				"defaults" for all global defaults
7653	 * @param  value   any - the new value for the setting
7654	 *				(omit if above is an object or to retrieve a value)
7655	 */
7656		_optionDatepicker: function( target, name, value ) {
7657			var settings, date, minDate, maxDate,
7658				inst = this._getInst( target );
7659
7660			if ( arguments.length === 2 && typeof name === "string" ) {
7661				return ( name === "defaults" ? $.extend( {}, $.datepicker._defaults ) :
7662					( inst ? ( name === "all" ? $.extend( {}, inst.settings ) :
7663						this._get( inst, name ) ) : null ) );
7664			}
7665
7666			settings = name || {};
7667			if ( typeof name === "string" ) {
7668				settings = {};
7669				settings[ name ] = value;
7670			}
7671
7672			if ( inst ) {
7673				if ( this._curInst === inst ) {
7674					this._hideDatepicker();
7675				}
7676
7677				date = this._getDateDatepicker( target, true );
7678				minDate = this._getMinMaxDate( inst, "min" );
7679				maxDate = this._getMinMaxDate( inst, "max" );
7680				datepicker_extendRemove( inst.settings, settings );
7681
7682				// reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
7683				if ( minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined ) {
7684					inst.settings.minDate = this._formatDate( inst, minDate );
7685				}
7686				if ( maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined ) {
7687					inst.settings.maxDate = this._formatDate( inst, maxDate );
7688				}
7689				if ( "disabled" in settings ) {
7690					if ( settings.disabled ) {
7691						this._disableDatepicker( target );
7692					} else {
7693						this._enableDatepicker( target );
7694					}
7695				}
7696				this._attachments( $( target ), inst );
7697				this._autoSize( inst );
7698				this._setDate( inst, date );
7699				this._updateAlternate( inst );
7700				this._updateDatepicker( inst );
7701			}
7702		},
7703
7704		// Change method deprecated
7705		_changeDatepicker: function( target, name, value ) {
7706			this._optionDatepicker( target, name, value );
7707		},
7708
7709		/* Redraw the date picker attached to an input field or division.
7710	 * @param  target  element - the target input field or division or span
7711	 */
7712		_refreshDatepicker: function( target ) {
7713			var inst = this._getInst( target );
7714			if ( inst ) {
7715				this._updateDatepicker( inst );
7716			}
7717		},
7718
7719		/* Set the dates for a jQuery selection.
7720	 * @param  target element - the target input field or division or span
7721	 * @param  date	Date - the new date
7722	 */
7723		_setDateDatepicker: function( target, date ) {
7724			var inst = this._getInst( target );
7725			if ( inst ) {
7726				this._setDate( inst, date );
7727				this._updateDatepicker( inst );
7728				this._updateAlternate( inst );
7729			}
7730		},
7731
7732		/* Get the date(s) for the first entry in a jQuery selection.
7733	 * @param  target element - the target input field or division or span
7734	 * @param  noDefault boolean - true if no default date is to be used
7735	 * @return Date - the current date
7736	 */
7737		_getDateDatepicker: function( target, noDefault ) {
7738			var inst = this._getInst( target );
7739			if ( inst && !inst.inline ) {
7740				this._setDateFromField( inst, noDefault );
7741			}
7742			return ( inst ? this._getDate( inst ) : null );
7743		},
7744
7745		/* Handle keystrokes. */
7746		_doKeyDown: function( event ) {
7747			var onSelect, dateStr, sel,
7748				inst = $.datepicker._getInst( event.target ),
7749				handled = true,
7750				isRTL = inst.dpDiv.is( ".ui-datepicker-rtl" );
7751
7752			inst._keyEvent = true;
7753			if ( $.datepicker._datepickerShowing ) {
7754				switch ( event.keyCode ) {
7755					case 9: $.datepicker._hideDatepicker();
7756						handled = false;
7757						break; // hide on tab out
7758					case 13: sel = $( "td." + $.datepicker._dayOverClass + ":not(." +
7759						$.datepicker._currentClass + ")", inst.dpDiv );
7760						if ( sel[ 0 ] ) {
7761							$.datepicker._selectDay( event.target, inst.selectedMonth, inst.selectedYear, sel[ 0 ] );
7762						}
7763
7764						onSelect = $.datepicker._get( inst, "onSelect" );
7765						if ( onSelect ) {
7766							dateStr = $.datepicker._formatDate( inst );
7767
7768							// Trigger custom callback
7769							onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] );
7770						} else {
7771							$.datepicker._hideDatepicker();
7772						}
7773
7774						return false; // don't submit the form
7775					case 27: $.datepicker._hideDatepicker();
7776						break; // hide on escape
7777					case 33: $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
7778						-$.datepicker._get( inst, "stepBigMonths" ) :
7779						-$.datepicker._get( inst, "stepMonths" ) ), "M" );
7780						break; // previous month/year on page up/+ ctrl
7781					case 34: $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
7782						+$.datepicker._get( inst, "stepBigMonths" ) :
7783						+$.datepicker._get( inst, "stepMonths" ) ), "M" );
7784						break; // next month/year on page down/+ ctrl
7785					case 35: if ( event.ctrlKey || event.metaKey ) {
7786						$.datepicker._clearDate( event.target );
7787					}
7788						handled = event.ctrlKey || event.metaKey;
7789						break; // clear on ctrl or command +end
7790					case 36: if ( event.ctrlKey || event.metaKey ) {
7791						$.datepicker._gotoToday( event.target );
7792					}
7793						handled = event.ctrlKey || event.metaKey;
7794						break; // current on ctrl or command +home
7795					case 37: if ( event.ctrlKey || event.metaKey ) {
7796						$.datepicker._adjustDate( event.target, ( isRTL ? +1 : -1 ), "D" );
7797					}
7798						handled = event.ctrlKey || event.metaKey;
7799
7800						// -1 day on ctrl or command +left
7801						if ( event.originalEvent.altKey ) {
7802							$.datepicker._adjustDate( event.target, ( event.ctrlKey ?
7803								-$.datepicker._get( inst, "stepBigMonths" ) :
7804								-$.datepicker._get( inst, "stepMonths" ) ), "M" );
7805						}
7806
7807						// next month/year on alt +left on Mac
7808						break;
7809					case 38: if ( event.ctrlKey || event.metaKey ) {
7810						$.datepicker._adjustDate( event.target, -7, "D" );
7811					}
7812						handled = event.ctrlKey || event.metaKey;
7813						break; // -1 week on ctrl or command +up
7814					case 39: if ( event.ctrlKey || event.metaKey ) {
7815						$.datepicker._adjustDate( event.target, ( isRTL ? -1 : +1 ), "D" );
7816					}
7817						handled = event.ctrlKey || event.metaKey;
7818
7819						// +1 day on ctrl or command +right
7820						if ( event.originalEvent.altKey ) {
7821							$.datepicker._adjustDate( event.target, ( event.ctrlKey ?
7822								+$.datepicker._get( inst, "stepBigMonths" ) :
7823								+$.datepicker._get( inst, "stepMonths" ) ), "M" );
7824						}
7825
7826						// next month/year on alt +right
7827						break;
7828					case 40: if ( event.ctrlKey || event.metaKey ) {
7829						$.datepicker._adjustDate( event.target, +7, "D" );
7830					}
7831						handled = event.ctrlKey || event.metaKey;
7832						break; // +1 week on ctrl or command +down
7833					default: handled = false;
7834				}
7835			} else if ( event.keyCode === 36 && event.ctrlKey ) { // display the date picker on ctrl+home
7836				$.datepicker._showDatepicker( this );
7837			} else {
7838				handled = false;
7839			}
7840
7841			if ( handled ) {
7842				event.preventDefault();
7843				event.stopPropagation();
7844			}
7845		},
7846
7847		/* Filter entered characters - based on date format. */
7848		_doKeyPress: function( event ) {
7849			var chars, chr,
7850				inst = $.datepicker._getInst( event.target );
7851
7852			if ( $.datepicker._get( inst, "constrainInput" ) ) {
7853				chars = $.datepicker._possibleChars( $.datepicker._get( inst, "dateFormat" ) );
7854				chr = String.fromCharCode( event.charCode == null ? event.keyCode : event.charCode );
7855				return event.ctrlKey || event.metaKey || ( chr < " " || !chars || chars.indexOf( chr ) > -1 );
7856			}
7857		},
7858
7859		/* Synchronise manual entry and field/alternate field. */
7860		_doKeyUp: function( event ) {
7861			var date,
7862				inst = $.datepicker._getInst( event.target );
7863
7864			if ( inst.input.val() !== inst.lastVal ) {
7865				try {
7866					date = $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ),
7867						( inst.input ? inst.input.val() : null ),
7868						$.datepicker._getFormatConfig( inst ) );
7869
7870					if ( date ) { // only if valid
7871						$.datepicker._setDateFromField( inst );
7872						$.datepicker._updateAlternate( inst );
7873						$.datepicker._updateDatepicker( inst );
7874					}
7875				} catch ( err ) {
7876				}
7877			}
7878			return true;
7879		},
7880
7881		/* Pop-up the date picker for a given input field.
7882	 * If false returned from beforeShow event handler do not show.
7883	 * @param  input  element - the input field attached to the date picker or
7884	 *					event - if triggered by focus
7885	 */
7886		_showDatepicker: function( input ) {
7887			input = input.target || input;
7888			if ( input.nodeName.toLowerCase() !== "input" ) { // find from button/image trigger
7889				input = $( "input", input.parentNode )[ 0 ];
7890			}
7891
7892			if ( $.datepicker._isDisabledDatepicker( input ) || $.datepicker._lastInput === input ) { // already here
7893				return;
7894			}
7895
7896			var inst, beforeShow, beforeShowSettings, isFixed,
7897				offset, showAnim, duration;
7898
7899			inst = $.datepicker._getInst( input );
7900			if ( $.datepicker._curInst && $.datepicker._curInst !== inst ) {
7901				$.datepicker._curInst.dpDiv.stop( true, true );
7902				if ( inst && $.datepicker._datepickerShowing ) {
7903					$.datepicker._hideDatepicker( $.datepicker._curInst.input[ 0 ] );
7904				}
7905			}
7906
7907			beforeShow = $.datepicker._get( inst, "beforeShow" );
7908			beforeShowSettings = beforeShow ? beforeShow.apply( input, [ input, inst ] ) : {};
7909			if ( beforeShowSettings === false ) {
7910				return;
7911			}
7912			datepicker_extendRemove( inst.settings, beforeShowSettings );
7913
7914			inst.lastVal = null;
7915			$.datepicker._lastInput = input;
7916			$.datepicker._setDateFromField( inst );
7917
7918			if ( $.datepicker._inDialog ) { // hide cursor
7919				input.value = "";
7920			}
7921			if ( !$.datepicker._pos ) { // position below input
7922				$.datepicker._pos = $.datepicker._findPos( input );
7923				$.datepicker._pos[ 1 ] += input.offsetHeight; // add the height
7924			}
7925
7926			isFixed = false;
7927			$( input ).parents().each( function() {
7928				isFixed |= $( this ).css( "position" ) === "fixed";
7929				return !isFixed;
7930			} );
7931
7932			offset = { left: $.datepicker._pos[ 0 ], top: $.datepicker._pos[ 1 ] };
7933			$.datepicker._pos = null;
7934
7935			//to avoid flashes on Firefox
7936			inst.dpDiv.empty();
7937
7938			// determine sizing offscreen
7939			inst.dpDiv.css( { position: "absolute", display: "block", top: "-1000px" } );
7940			$.datepicker._updateDatepicker( inst );
7941
7942			// fix width for dynamic number of date pickers
7943			// and adjust position before showing
7944			offset = $.datepicker._checkOffset( inst, offset, isFixed );
7945			inst.dpDiv.css( { position: ( $.datepicker._inDialog && $.blockUI ?
7946					"static" : ( isFixed ? "fixed" : "absolute" ) ), display: "none",
7947				left: offset.left + "px", top: offset.top + "px" } );
7948
7949			if ( !inst.inline ) {
7950				showAnim = $.datepicker._get( inst, "showAnim" );
7951				duration = $.datepicker._get( inst, "duration" );
7952				inst.dpDiv.css( "z-index", datepicker_getZindex( $( input ) ) + 1 );
7953				$.datepicker._datepickerShowing = true;
7954
7955				if ( $.effects && $.effects.effect[ showAnim ] ) {
7956					inst.dpDiv.show( showAnim, $.datepicker._get( inst, "showOptions" ), duration );
7957				} else {
7958					inst.dpDiv[ showAnim || "show" ]( showAnim ? duration : null );
7959				}
7960
7961				if ( $.datepicker._shouldFocusInput( inst ) ) {
7962					inst.input.trigger( "focus" );
7963				}
7964
7965				$.datepicker._curInst = inst;
7966			}
7967		},
7968
7969		/* Generate the date picker content. */
7970		_updateDatepicker: function( inst ) {
7971			this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
7972			datepicker_instActive = inst; // for delegate hover events
7973			inst.dpDiv.empty().append( this._generateHTML( inst ) );
7974			this._attachHandlers( inst );
7975
7976			var origyearshtml,
7977				numMonths = this._getNumberOfMonths( inst ),
7978				cols = numMonths[ 1 ],
7979				width = 17,
7980				activeCell = inst.dpDiv.find( "." + this._dayOverClass + " a" ),
7981				onUpdateDatepicker = $.datepicker._get( inst, "onUpdateDatepicker" );
7982
7983			if ( activeCell.length > 0 ) {
7984				datepicker_handleMouseover.apply( activeCell.get( 0 ) );
7985			}
7986
7987			inst.dpDiv.removeClass( "ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4" ).width( "" );
7988			if ( cols > 1 ) {
7989				inst.dpDiv.addClass( "ui-datepicker-multi-" + cols ).css( "width", ( width * cols ) + "em" );
7990			}
7991			inst.dpDiv[ ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ? "add" : "remove" ) +
7992			"Class" ]( "ui-datepicker-multi" );
7993			inst.dpDiv[ ( this._get( inst, "isRTL" ) ? "add" : "remove" ) +
7994			"Class" ]( "ui-datepicker-rtl" );
7995
7996			if ( inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {
7997				inst.input.trigger( "focus" );
7998			}
7999
8000			// Deffered render of the years select (to avoid flashes on Firefox)
8001			if ( inst.yearshtml ) {
8002				origyearshtml = inst.yearshtml;
8003				setTimeout( function() {
8004
8005					//assure that inst.yearshtml didn't change.
8006					if ( origyearshtml === inst.yearshtml && inst.yearshtml ) {
8007						inst.dpDiv.find( "select.ui-datepicker-year" ).first().replaceWith( inst.yearshtml );
8008					}
8009					origyearshtml = inst.yearshtml = null;
8010				}, 0 );
8011			}
8012
8013			if ( onUpdateDatepicker ) {
8014				onUpdateDatepicker.apply( ( inst.input ? inst.input[ 0 ] : null ), [ inst ] );
8015			}
8016		},
8017
8018		_shouldFocusInput: function( inst ) {
8019			return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" );
8020		},
8021
8022		/* Check positioning to remain on screen. */
8023		_checkOffset: function( inst, offset, isFixed ) {
8024			var dpWidth = inst.dpDiv.outerWidth(),
8025				dpHeight = inst.dpDiv.outerHeight(),
8026				inputWidth = inst.input ? inst.input.outerWidth() : 0,
8027				inputHeight = inst.input ? inst.input.outerHeight() : 0,
8028				viewWidth = document.documentElement.clientWidth + ( isFixed ? 0 : $( document ).scrollLeft() ),
8029				viewHeight = document.documentElement.clientHeight + ( isFixed ? 0 : $( document ).scrollTop() );
8030
8031			offset.left -= ( this._get( inst, "isRTL" ) ? ( dpWidth - inputWidth ) : 0 );
8032			offset.left -= ( isFixed && offset.left === inst.input.offset().left ) ? $( document ).scrollLeft() : 0;
8033			offset.top -= ( isFixed && offset.top === ( inst.input.offset().top + inputHeight ) ) ? $( document ).scrollTop() : 0;
8034
8035			// Now check if datepicker is showing outside window viewport - move to a better place if so.
8036			offset.left -= Math.min( offset.left, ( offset.left + dpWidth > viewWidth && viewWidth > dpWidth ) ?
8037				Math.abs( offset.left + dpWidth - viewWidth ) : 0 );
8038			offset.top -= Math.min( offset.top, ( offset.top + dpHeight > viewHeight && viewHeight > dpHeight ) ?
8039				Math.abs( dpHeight + inputHeight ) : 0 );
8040
8041			return offset;
8042		},
8043
8044		/* Find an object's position on the screen. */
8045		_findPos: function( obj ) {
8046			var position,
8047				inst = this._getInst( obj ),
8048				isRTL = this._get( inst, "isRTL" );
8049
8050			while ( obj && ( obj.type === "hidden" || obj.nodeType !== 1 || $.expr.pseudos.hidden( obj ) ) ) {
8051				obj = obj[ isRTL ? "previousSibling" : "nextSibling" ];
8052			}
8053
8054			position = $( obj ).offset();
8055			return [ position.left, position.top ];
8056		},
8057
8058		/* Hide the date picker from view.
8059	 * @param  input  element - the input field attached to the date picker
8060	 */
8061		_hideDatepicker: function( input ) {
8062			var showAnim, duration, postProcess, onClose,
8063				inst = this._curInst;
8064
8065			if ( !inst || ( input && inst !== $.data( input, "datepicker" ) ) ) {
8066				return;
8067			}
8068
8069			if ( this._datepickerShowing ) {
8070				showAnim = this._get( inst, "showAnim" );
8071				duration = this._get( inst, "duration" );
8072				postProcess = function() {
8073					$.datepicker._tidyDialog( inst );
8074				};
8075
8076				if ( $.effects && ( $.effects.effect[ showAnim ] ) ) {
8077					inst.dpDiv.hide( showAnim, $.datepicker._get( inst, "showOptions" ), duration, postProcess );
8078				} else {
8079					inst.dpDiv[ ( showAnim === "slideDown" ? "slideUp" :
8080						( showAnim === "fadeIn" ? "fadeOut" : "hide" ) ) ]( ( showAnim ? duration : null ), postProcess );
8081				}
8082
8083				if ( !showAnim ) {
8084					postProcess();
8085				}
8086				this._datepickerShowing = false;
8087
8088				onClose = this._get( inst, "onClose" );
8089				if ( onClose ) {
8090					onClose.apply( ( inst.input ? inst.input[ 0 ] : null ), [ ( inst.input ? inst.input.val() : "" ), inst ] );
8091				}
8092
8093				this._lastInput = null;
8094				if ( this._inDialog ) {
8095					this._dialogInput.css( { position: "absolute", left: "0", top: "-100px" } );
8096					if ( $.blockUI ) {
8097						$.unblockUI();
8098						$( "body" ).append( this.dpDiv );
8099					}
8100				}
8101				this._inDialog = false;
8102			}
8103		},
8104
8105		/* Tidy up after a dialog display. */
8106		_tidyDialog: function( inst ) {
8107			inst.dpDiv.removeClass( this._dialogClass ).off( ".ui-datepicker-calendar" );
8108		},
8109
8110		/* Close date picker if clicked elsewhere. */
8111		_checkExternalClick: function( event ) {
8112			if ( !$.datepicker._curInst ) {
8113				return;
8114			}
8115
8116			var $target = $( event.target ),
8117				inst = $.datepicker._getInst( $target[ 0 ] );
8118
8119			if ( ( ( $target[ 0 ].id !== $.datepicker._mainDivId &&
8120					$target.parents( "#" + $.datepicker._mainDivId ).length === 0 &&
8121					!$target.hasClass( $.datepicker.markerClassName ) &&
8122					!$target.closest( "." + $.datepicker._triggerClass ).length &&
8123					$.datepicker._datepickerShowing && !( $.datepicker._inDialog && $.blockUI ) ) ) ||
8124				( $target.hasClass( $.datepicker.markerClassName ) && $.datepicker._curInst !== inst ) ) {
8125				$.datepicker._hideDatepicker();
8126			}
8127		},
8128
8129		/* Adjust one of the date sub-fields. */
8130		_adjustDate: function( id, offset, period ) {
8131			var target = $( id ),
8132				inst = this._getInst( target[ 0 ] );
8133
8134			if ( this._isDisabledDatepicker( target[ 0 ] ) ) {
8135				return;
8136			}
8137			this._adjustInstDate( inst, offset, period );
8138			this._updateDatepicker( inst );
8139		},
8140
8141		/* Action for current link. */
8142		_gotoToday: function( id ) {
8143			var date,
8144				target = $( id ),
8145				inst = this._getInst( target[ 0 ] );
8146
8147			if ( this._get( inst, "gotoCurrent" ) && inst.currentDay ) {
8148				inst.selectedDay = inst.currentDay;
8149				inst.drawMonth = inst.selectedMonth = inst.currentMonth;
8150				inst.drawYear = inst.selectedYear = inst.currentYear;
8151			} else {
8152				date = new Date();
8153				inst.selectedDay = date.getDate();
8154				inst.drawMonth = inst.selectedMonth = date.getMonth();
8155				inst.drawYear = inst.selectedYear = date.getFullYear();
8156			}
8157			this._notifyChange( inst );
8158			this._adjustDate( target );
8159		},
8160
8161		/* Action for selecting a new month/year. */
8162		_selectMonthYear: function( id, select, period ) {
8163			var target = $( id ),
8164				inst = this._getInst( target[ 0 ] );
8165
8166			inst[ "selected" + ( period === "M" ? "Month" : "Year" ) ] =
8167				inst[ "draw" + ( period === "M" ? "Month" : "Year" ) ] =
8168					parseInt( select.options[ select.selectedIndex ].value, 10 );
8169
8170			this._notifyChange( inst );
8171			this._adjustDate( target );
8172		},
8173
8174		/* Action for selecting a day. */
8175		_selectDay: function( id, month, year, td ) {
8176			var inst,
8177				target = $( id );
8178
8179			if ( $( td ).hasClass( this._unselectableClass ) || this._isDisabledDatepicker( target[ 0 ] ) ) {
8180				return;
8181			}
8182
8183			inst = this._getInst( target[ 0 ] );
8184			inst.selectedDay = inst.currentDay = parseInt( $( "a", td ).attr( "data-date" ) );
8185			inst.selectedMonth = inst.currentMonth = month;
8186			inst.selectedYear = inst.currentYear = year;
8187			this._selectDate( id, this._formatDate( inst,
8188				inst.currentDay, inst.currentMonth, inst.currentYear ) );
8189		},
8190
8191		/* Erase the input field and hide the date picker. */
8192		_clearDate: function( id ) {
8193			var target = $( id );
8194			this._selectDate( target, "" );
8195		},
8196
8197		/* Update the input field with the selected date. */
8198		_selectDate: function( id, dateStr ) {
8199			var onSelect,
8200				target = $( id ),
8201				inst = this._getInst( target[ 0 ] );
8202
8203			dateStr = ( dateStr != null ? dateStr : this._formatDate( inst ) );
8204			if ( inst.input ) {
8205				inst.input.val( dateStr );
8206			}
8207			this._updateAlternate( inst );
8208
8209			onSelect = this._get( inst, "onSelect" );
8210			if ( onSelect ) {
8211				onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] );  // trigger custom callback
8212			} else if ( inst.input ) {
8213				inst.input.trigger( "change" ); // fire the change event
8214			}
8215
8216			if ( inst.inline ) {
8217				this._updateDatepicker( inst );
8218			} else {
8219				this._hideDatepicker();
8220				this._lastInput = inst.input[ 0 ];
8221				if ( typeof( inst.input[ 0 ] ) !== "object" ) {
8222					inst.input.trigger( "focus" ); // restore focus
8223				}
8224				this._lastInput = null;
8225			}
8226		},
8227
8228		/* Update any alternate field to synchronise with the main field. */
8229		_updateAlternate: function( inst ) {
8230			var altFormat, date, dateStr,
8231				altField = this._get( inst, "altField" );
8232
8233			if ( altField ) { // update alternate field too
8234				altFormat = this._get( inst, "altFormat" ) || this._get( inst, "dateFormat" );
8235				date = this._getDate( inst );
8236				dateStr = this.formatDate( altFormat, date, this._getFormatConfig( inst ) );
8237				$( document ).find( altField ).val( dateStr );
8238			}
8239		},
8240
8241		/* Set as beforeShowDay function to prevent selection of weekends.
8242	 * @param  date  Date - the date to customise
8243	 * @return [boolean, string] - is this date selectable?, what is its CSS class?
8244	 */
8245		noWeekends: function( date ) {
8246			var day = date.getDay();
8247			return [ ( day > 0 && day < 6 ), "" ];
8248		},
8249
8250		/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
8251	 * @param  date  Date - the date to get the week for
8252	 * @return  number - the number of the week within the year that contains this date
8253	 */
8254		iso8601Week: function( date ) {
8255			var time,
8256				checkDate = new Date( date.getTime() );
8257
8258			// Find Thursday of this week starting on Monday
8259			checkDate.setDate( checkDate.getDate() + 4 - ( checkDate.getDay() || 7 ) );
8260
8261			time = checkDate.getTime();
8262			checkDate.setMonth( 0 ); // Compare with Jan 1
8263			checkDate.setDate( 1 );
8264			return Math.floor( Math.round( ( time - checkDate ) / 86400000 ) / 7 ) + 1;
8265		},
8266
8267		/* Parse a string value into a date object.
8268	 * See formatDate below for the possible formats.
8269	 *
8270	 * @param  format string - the expected format of the date
8271	 * @param  value string - the date in the above format
8272	 * @param  settings Object - attributes include:
8273	 *					shortYearCutoff  number - the cutoff year for determining the century (optional)
8274	 *					dayNamesShort	string[7] - abbreviated names of the days from Sunday (optional)
8275	 *					dayNames		string[7] - names of the days from Sunday (optional)
8276	 *					monthNamesShort string[12] - abbreviated names of the months (optional)
8277	 *					monthNames		string[12] - names of the months (optional)
8278	 * @return  Date - the extracted date value or null if value is blank
8279	 */
8280		parseDate: function( format, value, settings ) {
8281			if ( format == null || value == null ) {
8282				throw "Invalid arguments";
8283			}
8284
8285			value = ( typeof value === "object" ? value.toString() : value + "" );
8286			if ( value === "" ) {
8287				return null;
8288			}
8289
8290			var iFormat, dim, extra,
8291				iValue = 0,
8292				shortYearCutoffTemp = ( settings ? settings.shortYearCutoff : null ) || this._defaults.shortYearCutoff,
8293				shortYearCutoff = ( typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp :
8294					new Date().getFullYear() % 100 + parseInt( shortYearCutoffTemp, 10 ) ),
8295				dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort,
8296				dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames,
8297				monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort,
8298				monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames,
8299				year = -1,
8300				month = -1,
8301				day = -1,
8302				doy = -1,
8303				literal = false,
8304				date,
8305
8306				// Check whether a format character is doubled
8307				lookAhead = function( match ) {
8308					var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
8309					if ( matches ) {
8310						iFormat++;
8311					}
8312					return matches;
8313				},
8314
8315				// Extract a number from the string value
8316				getNumber = function( match ) {
8317					var isDoubled = lookAhead( match ),
8318						size = ( match === "@" ? 14 : ( match === "!" ? 20 :
8319							( match === "y" && isDoubled ? 4 : ( match === "o" ? 3 : 2 ) ) ) ),
8320						minSize = ( match === "y" ? size : 1 ),
8321						digits = new RegExp( "^\\d{" + minSize + "," + size + "}" ),
8322						num = value.substring( iValue ).match( digits );
8323					if ( !num ) {
8324						throw "Missing number at position " + iValue;
8325					}
8326					iValue += num[ 0 ].length;
8327					return parseInt( num[ 0 ], 10 );
8328				},
8329
8330				// Extract a name from the string value and convert to an index
8331				getName = function( match, shortNames, longNames ) {
8332					var index = -1,
8333						names = $.map( lookAhead( match ) ? longNames : shortNames, function( v, k ) {
8334							return [ [ k, v ] ];
8335						} ).sort( function( a, b ) {
8336							return -( a[ 1 ].length - b[ 1 ].length );
8337						} );
8338
8339					$.each( names, function( i, pair ) {
8340						var name = pair[ 1 ];
8341						if ( value.substr( iValue, name.length ).toLowerCase() === name.toLowerCase() ) {
8342							index = pair[ 0 ];
8343							iValue += name.length;
8344							return false;
8345						}
8346					} );
8347					if ( index !== -1 ) {
8348						return index + 1;
8349					} else {
8350						throw "Unknown name at position " + iValue;
8351					}
8352				},
8353
8354				// Confirm that a literal character matches the string value
8355				checkLiteral = function() {
8356					if ( value.charAt( iValue ) !== format.charAt( iFormat ) ) {
8357						throw "Unexpected literal at position " + iValue;
8358					}
8359					iValue++;
8360				};
8361
8362			for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
8363				if ( literal ) {
8364					if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
8365						literal = false;
8366					} else {
8367						checkLiteral();
8368					}
8369				} else {
8370					switch ( format.charAt( iFormat ) ) {
8371						case "d":
8372							day = getNumber( "d" );
8373							break;
8374						case "D":
8375							getName( "D", dayNamesShort, dayNames );
8376							break;
8377						case "o":
8378							doy = getNumber( "o" );
8379							break;
8380						case "m":
8381							month = getNumber( "m" );
8382							break;
8383						case "M":
8384							month = getName( "M", monthNamesShort, monthNames );
8385							break;
8386						case "y":
8387							year = getNumber( "y" );
8388							break;
8389						case "@":
8390							date = new Date( getNumber( "@" ) );
8391							year = date.getFullYear();
8392							month = date.getMonth() + 1;
8393							day = date.getDate();
8394							break;
8395						case "!":
8396							date = new Date( ( getNumber( "!" ) - this._ticksTo1970 ) / 10000 );
8397							year = date.getFullYear();
8398							month = date.getMonth() + 1;
8399							day = date.getDate();
8400							break;
8401						case "'":
8402							if ( lookAhead( "'" ) ) {
8403								checkLiteral();
8404							} else {
8405								literal = true;
8406							}
8407							break;
8408						default:
8409							checkLiteral();
8410					}
8411				}
8412			}
8413
8414			if ( iValue < value.length ) {
8415				extra = value.substr( iValue );
8416				if ( !/^\s+/.test( extra ) ) {
8417					throw "Extra/unparsed characters found in date: " + extra;
8418				}
8419			}
8420
8421			if ( year === -1 ) {
8422				year = new Date().getFullYear();
8423			} else if ( year < 100 ) {
8424				year += new Date().getFullYear() - new Date().getFullYear() % 100 +
8425					( year <= shortYearCutoff ? 0 : -100 );
8426			}
8427
8428			if ( doy > -1 ) {
8429				month = 1;
8430				day = doy;
8431				do {
8432					dim = this._getDaysInMonth( year, month - 1 );
8433					if ( day <= dim ) {
8434						break;
8435					}
8436					month++;
8437					day -= dim;
8438				} while ( true );
8439			}
8440
8441			date = this._daylightSavingAdjust( new Date( year, month - 1, day ) );
8442			if ( date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day ) {
8443				throw "Invalid date"; // E.g. 31/02/00
8444			}
8445			return date;
8446		},
8447
8448		/* Standard date formats. */
8449		ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601)
8450		COOKIE: "D, dd M yy",
8451		ISO_8601: "yy-mm-dd",
8452		RFC_822: "D, d M y",
8453		RFC_850: "DD, dd-M-y",
8454		RFC_1036: "D, d M y",
8455		RFC_1123: "D, d M yy",
8456		RFC_2822: "D, d M yy",
8457		RSS: "D, d M y", // RFC 822
8458		TICKS: "!",
8459		TIMESTAMP: "@",
8460		W3C: "yy-mm-dd", // ISO 8601
8461
8462		_ticksTo1970: ( ( ( 1970 - 1 ) * 365 + Math.floor( 1970 / 4 ) - Math.floor( 1970 / 100 ) +
8463			Math.floor( 1970 / 400 ) ) * 24 * 60 * 60 * 10000000 ),
8464
8465		/* Format a date object into a string value.
8466	 * The format can be combinations of the following:
8467	 * d  - day of month (no leading zero)
8468	 * dd - day of month (two digit)
8469	 * o  - day of year (no leading zeros)
8470	 * oo - day of year (three digit)
8471	 * D  - day name short
8472	 * DD - day name long
8473	 * m  - month of year (no leading zero)
8474	 * mm - month of year (two digit)
8475	 * M  - month name short
8476	 * MM - month name long
8477	 * y  - year (two digit)
8478	 * yy - year (four digit)
8479	 * @ - Unix timestamp (ms since 01/01/1970)
8480	 * ! - Windows ticks (100ns since 01/01/0001)
8481	 * "..." - literal text
8482	 * '' - single quote
8483	 *
8484	 * @param  format string - the desired format of the date
8485	 * @param  date Date - the date value to format
8486	 * @param  settings Object - attributes include:
8487	 *					dayNamesShort	string[7] - abbreviated names of the days from Sunday (optional)
8488	 *					dayNames		string[7] - names of the days from Sunday (optional)
8489	 *					monthNamesShort string[12] - abbreviated names of the months (optional)
8490	 *					monthNames		string[12] - names of the months (optional)
8491	 * @return  string - the date in the above format
8492	 */
8493		formatDate: function( format, date, settings ) {
8494			if ( !date ) {
8495				return "";
8496			}
8497
8498			var iFormat,
8499				dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort,
8500				dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames,
8501				monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort,
8502				monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames,
8503
8504				// Check whether a format character is doubled
8505				lookAhead = function( match ) {
8506					var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
8507					if ( matches ) {
8508						iFormat++;
8509					}
8510					return matches;
8511				},
8512
8513				// Format a number, with leading zero if necessary
8514				formatNumber = function( match, value, len ) {
8515					var num = "" + value;
8516					if ( lookAhead( match ) ) {
8517						while ( num.length < len ) {
8518							num = "0" + num;
8519						}
8520					}
8521					return num;
8522				},
8523
8524				// Format a name, short or long as requested
8525				formatName = function( match, value, shortNames, longNames ) {
8526					return ( lookAhead( match ) ? longNames[ value ] : shortNames[ value ] );
8527				},
8528				output = "",
8529				literal = false;
8530
8531			if ( date ) {
8532				for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
8533					if ( literal ) {
8534						if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
8535							literal = false;
8536						} else {
8537							output += format.charAt( iFormat );
8538						}
8539					} else {
8540						switch ( format.charAt( iFormat ) ) {
8541							case "d":
8542								output += formatNumber( "d", date.getDate(), 2 );
8543								break;
8544							case "D":
8545								output += formatName( "D", date.getDay(), dayNamesShort, dayNames );
8546								break;
8547							case "o":
8548								output += formatNumber( "o",
8549									Math.round( ( new Date( date.getFullYear(), date.getMonth(), date.getDate() ).getTime() - new Date( date.getFullYear(), 0, 0 ).getTime() ) / 86400000 ), 3 );
8550								break;
8551							case "m":
8552								output += formatNumber( "m", date.getMonth() + 1, 2 );
8553								break;
8554							case "M":
8555								output += formatName( "M", date.getMonth(), monthNamesShort, monthNames );
8556								break;
8557							case "y":
8558								output += ( lookAhead( "y" ) ? date.getFullYear() :
8559									( date.getFullYear() % 100 < 10 ? "0" : "" ) + date.getFullYear() % 100 );
8560								break;
8561							case "@":
8562								output += date.getTime();
8563								break;
8564							case "!":
8565								output += date.getTime() * 10000 + this._ticksTo1970;
8566								break;
8567							case "'":
8568								if ( lookAhead( "'" ) ) {
8569									output += "'";
8570								} else {
8571									literal = true;
8572								}
8573								break;
8574							default:
8575								output += format.charAt( iFormat );
8576						}
8577					}
8578				}
8579			}
8580			return output;
8581		},
8582
8583		/* Extract all possible characters from the date format. */
8584		_possibleChars: function( format ) {
8585			var iFormat,
8586				chars = "",
8587				literal = false,
8588
8589				// Check whether a format character is doubled
8590				lookAhead = function( match ) {
8591					var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
8592					if ( matches ) {
8593						iFormat++;
8594					}
8595					return matches;
8596				};
8597
8598			for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
8599				if ( literal ) {
8600					if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
8601						literal = false;
8602					} else {
8603						chars += format.charAt( iFormat );
8604					}
8605				} else {
8606					switch ( format.charAt( iFormat ) ) {
8607						case "d": case "m": case "y": case "@":
8608							chars += "0123456789";
8609							break;
8610						case "D": case "M":
8611							return null; // Accept anything
8612						case "'":
8613							if ( lookAhead( "'" ) ) {
8614								chars += "'";
8615							} else {
8616								literal = true;
8617							}
8618							break;
8619						default:
8620							chars += format.charAt( iFormat );
8621					}
8622				}
8623			}
8624			return chars;
8625		},
8626
8627		/* Get a setting value, defaulting if necessary. */
8628		_get: function( inst, name ) {
8629			return inst.settings[ name ] !== undefined ?
8630				inst.settings[ name ] : this._defaults[ name ];
8631		},
8632
8633		/* Parse existing date and initialise date picker. */
8634		_setDateFromField: function( inst, noDefault ) {
8635			if ( inst.input.val() === inst.lastVal ) {
8636				return;
8637			}
8638
8639			var dateFormat = this._get( inst, "dateFormat" ),
8640				dates = inst.lastVal = inst.input ? inst.input.val() : null,
8641				defaultDate = this._getDefaultDate( inst ),
8642				date = defaultDate,
8643				settings = this._getFormatConfig( inst );
8644
8645			try {
8646				date = this.parseDate( dateFormat, dates, settings ) || defaultDate;
8647			} catch ( event ) {
8648				dates = ( noDefault ? "" : dates );
8649			}
8650			inst.selectedDay = date.getDate();
8651			inst.drawMonth = inst.selectedMonth = date.getMonth();
8652			inst.drawYear = inst.selectedYear = date.getFullYear();
8653			inst.currentDay = ( dates ? date.getDate() : 0 );
8654			inst.currentMonth = ( dates ? date.getMonth() : 0 );
8655			inst.currentYear = ( dates ? date.getFullYear() : 0 );
8656			this._adjustInstDate( inst );
8657		},
8658
8659		/* Retrieve the default date shown on opening. */
8660		_getDefaultDate: function( inst ) {
8661			return this._restrictMinMax( inst,
8662				this._determineDate( inst, this._get( inst, "defaultDate" ), new Date() ) );
8663		},
8664
8665		/* A date may be specified as an exact value or a relative one. */
8666		_determineDate: function( inst, date, defaultDate ) {
8667			var offsetNumeric = function( offset ) {
8668					var date = new Date();
8669					date.setDate( date.getDate() + offset );
8670					return date;
8671				},
8672				offsetString = function( offset ) {
8673					try {
8674						return $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ),
8675							offset, $.datepicker._getFormatConfig( inst ) );
8676					} catch ( e ) {
8677
8678						// Ignore
8679					}
8680
8681					var date = ( offset.toLowerCase().match( /^c/ ) ?
8682							$.datepicker._getDate( inst ) : null ) || new Date(),
8683						year = date.getFullYear(),
8684						month = date.getMonth(),
8685						day = date.getDate(),
8686						pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,
8687						matches = pattern.exec( offset );
8688
8689					while ( matches ) {
8690						switch ( matches[ 2 ] || "d" ) {
8691							case "d" : case "D" :
8692								day += parseInt( matches[ 1 ], 10 ); break;
8693							case "w" : case "W" :
8694								day += parseInt( matches[ 1 ], 10 ) * 7; break;
8695							case "m" : case "M" :
8696								month += parseInt( matches[ 1 ], 10 );
8697								day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) );
8698								break;
8699							case "y": case "Y" :
8700								year += parseInt( matches[ 1 ], 10 );
8701								day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) );
8702								break;
8703						}
8704						matches = pattern.exec( offset );
8705					}
8706					return new Date( year, month, day );
8707				},
8708				newDate = ( date == null || date === "" ? defaultDate : ( typeof date === "string" ? offsetString( date ) :
8709					( typeof date === "number" ? ( isNaN( date ) ? defaultDate : offsetNumeric( date ) ) : new Date( date.getTime() ) ) ) );
8710
8711			newDate = ( newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate );
8712			if ( newDate ) {
8713				newDate.setHours( 0 );
8714				newDate.setMinutes( 0 );
8715				newDate.setSeconds( 0 );
8716				newDate.setMilliseconds( 0 );
8717			}
8718			return this._daylightSavingAdjust( newDate );
8719		},
8720
8721		/* Handle switch to/from daylight saving.
8722	 * Hours may be non-zero on daylight saving cut-over:
8723	 * > 12 when midnight changeover, but then cannot generate
8724	 * midnight datetime, so jump to 1AM, otherwise reset.
8725	 * @param  date  (Date) the date to check
8726	 * @return  (Date) the corrected date
8727	 */
8728		_daylightSavingAdjust: function( date ) {
8729			if ( !date ) {
8730				return null;
8731			}
8732			date.setHours( date.getHours() > 12 ? date.getHours() + 2 : 0 );
8733			return date;
8734		},
8735
8736		/* Set the date(s) directly. */
8737		_setDate: function( inst, date, noChange ) {
8738			var clear = !date,
8739				origMonth = inst.selectedMonth,
8740				origYear = inst.selectedYear,
8741				newDate = this._restrictMinMax( inst, this._determineDate( inst, date, new Date() ) );
8742
8743			inst.selectedDay = inst.currentDay = newDate.getDate();
8744			inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
8745			inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
8746			if ( ( origMonth !== inst.selectedMonth || origYear !== inst.selectedYear ) && !noChange ) {
8747				this._notifyChange( inst );
8748			}
8749			this._adjustInstDate( inst );
8750			if ( inst.input ) {
8751				inst.input.val( clear ? "" : this._formatDate( inst ) );
8752			}
8753		},
8754
8755		/* Retrieve the date(s) directly. */
8756		_getDate: function( inst ) {
8757			var startDate = ( !inst.currentYear || ( inst.input && inst.input.val() === "" ) ? null :
8758				this._daylightSavingAdjust( new Date(
8759					inst.currentYear, inst.currentMonth, inst.currentDay ) ) );
8760			return startDate;
8761		},
8762
8763		/* Attach the onxxx handlers.  These are declared statically so
8764	 * they work with static code transformers like Caja.
8765	 */
8766		_attachHandlers: function( inst ) {
8767			var stepMonths = this._get( inst, "stepMonths" ),
8768				id = "#" + inst.id.replace( /\\\\/g, "\\" );
8769			inst.dpDiv.find( "[data-handler]" ).map( function() {
8770				var handler = {
8771					prev: function() {
8772						$.datepicker._adjustDate( id, -stepMonths, "M" );
8773					},
8774					next: function() {
8775						$.datepicker._adjustDate( id, +stepMonths, "M" );
8776					},
8777					hide: function() {
8778						$.datepicker._hideDatepicker();
8779					},
8780					today: function() {
8781						$.datepicker._gotoToday( id );
8782					},
8783					selectDay: function() {
8784						$.datepicker._selectDay( id, +this.getAttribute( "data-month" ), +this.getAttribute( "data-year" ), this );
8785						return false;
8786					},
8787					selectMonth: function() {
8788						$.datepicker._selectMonthYear( id, this, "M" );
8789						return false;
8790					},
8791					selectYear: function() {
8792						$.datepicker._selectMonthYear( id, this, "Y" );
8793						return false;
8794					}
8795				};
8796				$( this ).on( this.getAttribute( "data-event" ), handler[ this.getAttribute( "data-handler" ) ] );
8797			} );
8798		},
8799
8800		/* Generate the HTML for the current state of the date picker. */
8801		_generateHTML: function( inst ) {
8802			var maxDraw, prevText, prev, nextText, next, currentText, gotoDate,
8803				controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,
8804				monthNames, monthNamesShort, beforeShowDay, showOtherMonths,
8805				selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,
8806				cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,
8807				printDate, dRow, tbody, daySettings, otherMonth, unselectable,
8808				tempDate = new Date(),
8809				today = this._daylightSavingAdjust(
8810					new Date( tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate() ) ), // clear time
8811				isRTL = this._get( inst, "isRTL" ),
8812				showButtonPanel = this._get( inst, "showButtonPanel" ),
8813				hideIfNoPrevNext = this._get( inst, "hideIfNoPrevNext" ),
8814				navigationAsDateFormat = this._get( inst, "navigationAsDateFormat" ),
8815				numMonths = this._getNumberOfMonths( inst ),
8816				showCurrentAtPos = this._get( inst, "showCurrentAtPos" ),
8817				stepMonths = this._get( inst, "stepMonths" ),
8818				isMultiMonth = ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ),
8819				currentDate = this._daylightSavingAdjust( ( !inst.currentDay ? new Date( 9999, 9, 9 ) :
8820					new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) ),
8821				minDate = this._getMinMaxDate( inst, "min" ),
8822				maxDate = this._getMinMaxDate( inst, "max" ),
8823				drawMonth = inst.drawMonth - showCurrentAtPos,
8824				drawYear = inst.drawYear;
8825
8826			if ( drawMonth < 0 ) {
8827				drawMonth += 12;
8828				drawYear--;
8829			}
8830			if ( maxDate ) {
8831				maxDraw = this._daylightSavingAdjust( new Date( maxDate.getFullYear(),
8832					maxDate.getMonth() - ( numMonths[ 0 ] * numMonths[ 1 ] ) + 1, maxDate.getDate() ) );
8833				maxDraw = ( minDate && maxDraw < minDate ? minDate : maxDraw );
8834				while ( this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 ) ) > maxDraw ) {
8835					drawMonth--;
8836					if ( drawMonth < 0 ) {
8837						drawMonth = 11;
8838						drawYear--;
8839					}
8840				}
8841			}
8842			inst.drawMonth = drawMonth;
8843			inst.drawYear = drawYear;
8844
8845			prevText = this._get( inst, "prevText" );
8846			prevText = ( !navigationAsDateFormat ? prevText : this.formatDate( prevText,
8847				this._daylightSavingAdjust( new Date( drawYear, drawMonth - stepMonths, 1 ) ),
8848				this._getFormatConfig( inst ) ) );
8849
8850			if ( this._canAdjustMonth( inst, -1, drawYear, drawMonth ) ) {
8851				prev = $( "<a>" )
8852					.attr( {
8853						"class": "ui-datepicker-prev ui-corner-all",
8854						"data-handler": "prev",
8855						"data-event": "click",
8856						title: prevText
8857					} )
8858					.append(
8859						$( "<span>" )
8860							.addClass( "ui-icon ui-icon-circle-triangle-" +
8861								( isRTL ? "e" : "w" ) )
8862							.text( prevText )
8863					)[ 0 ].outerHTML;
8864			} else if ( hideIfNoPrevNext ) {
8865				prev = "";
8866			} else {
8867				prev = $( "<a>" )
8868					.attr( {
8869						"class": "ui-datepicker-prev ui-corner-all ui-state-disabled",
8870						title: prevText
8871					} )
8872					.append(
8873						$( "<span>" )
8874							.addClass( "ui-icon ui-icon-circle-triangle-" +
8875								( isRTL ? "e" : "w" ) )
8876							.text( prevText )
8877					)[ 0 ].outerHTML;
8878			}
8879
8880			nextText = this._get( inst, "nextText" );
8881			nextText = ( !navigationAsDateFormat ? nextText : this.formatDate( nextText,
8882				this._daylightSavingAdjust( new Date( drawYear, drawMonth + stepMonths, 1 ) ),
8883				this._getFormatConfig( inst ) ) );
8884
8885			if ( this._canAdjustMonth( inst, +1, drawYear, drawMonth ) ) {
8886				next = $( "<a>" )
8887					.attr( {
8888						"class": "ui-datepicker-next ui-corner-all",
8889						"data-handler": "next",
8890						"data-event": "click",
8891						title: nextText
8892					} )
8893					.append(
8894						$( "<span>" )
8895							.addClass( "ui-icon ui-icon-circle-triangle-" +
8896								( isRTL ? "w" : "e" ) )
8897							.text( nextText )
8898					)[ 0 ].outerHTML;
8899			} else if ( hideIfNoPrevNext ) {
8900				next = "";
8901			} else {
8902				next = $( "<a>" )
8903					.attr( {
8904						"class": "ui-datepicker-next ui-corner-all ui-state-disabled",
8905						title: nextText
8906					} )
8907					.append(
8908						$( "<span>" )
8909							.attr( "class", "ui-icon ui-icon-circle-triangle-" +
8910								( isRTL ? "w" : "e" ) )
8911							.text( nextText )
8912					)[ 0 ].outerHTML;
8913			}
8914
8915			currentText = this._get( inst, "currentText" );
8916			gotoDate = ( this._get( inst, "gotoCurrent" ) && inst.currentDay ? currentDate : today );
8917			currentText = ( !navigationAsDateFormat ? currentText :
8918				this.formatDate( currentText, gotoDate, this._getFormatConfig( inst ) ) );
8919
8920			controls = "";
8921			if ( !inst.inline ) {
8922				controls = $( "<button>" )
8923					.attr( {
8924						type: "button",
8925						"class": "ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all",
8926						"data-handler": "hide",
8927						"data-event": "click"
8928					} )
8929					.text( this._get( inst, "closeText" ) )[ 0 ].outerHTML;
8930			}
8931
8932			buttonPanel = "";
8933			if ( showButtonPanel ) {
8934				buttonPanel = $( "<div class='ui-datepicker-buttonpane ui-widget-content'>" )
8935					.append( isRTL ? controls : "" )
8936					.append( this._isInRange( inst, gotoDate ) ?
8937						$( "<button>" )
8938							.attr( {
8939								type: "button",
8940								"class": "ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all",
8941								"data-handler": "today",
8942								"data-event": "click"
8943							} )
8944							.text( currentText ) :
8945						"" )
8946					.append( isRTL ? "" : controls )[ 0 ].outerHTML;
8947			}
8948
8949			firstDay = parseInt( this._get( inst, "firstDay" ), 10 );
8950			firstDay = ( isNaN( firstDay ) ? 0 : firstDay );
8951
8952			showWeek = this._get( inst, "showWeek" );
8953			dayNames = this._get( inst, "dayNames" );
8954			dayNamesMin = this._get( inst, "dayNamesMin" );
8955			monthNames = this._get( inst, "monthNames" );
8956			monthNamesShort = this._get( inst, "monthNamesShort" );
8957			beforeShowDay = this._get( inst, "beforeShowDay" );
8958			showOtherMonths = this._get( inst, "showOtherMonths" );
8959			selectOtherMonths = this._get( inst, "selectOtherMonths" );
8960			defaultDate = this._getDefaultDate( inst );
8961			html = "";
8962
8963			for ( row = 0; row < numMonths[ 0 ]; row++ ) {
8964				group = "";
8965				this.maxRows = 4;
8966				for ( col = 0; col < numMonths[ 1 ]; col++ ) {
8967					selectedDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, inst.selectedDay ) );
8968					cornerClass = " ui-corner-all";
8969					calender = "";
8970					if ( isMultiMonth ) {
8971						calender += "<div class='ui-datepicker-group";
8972						if ( numMonths[ 1 ] > 1 ) {
8973							switch ( col ) {
8974								case 0: calender += " ui-datepicker-group-first";
8975									cornerClass = " ui-corner-" + ( isRTL ? "right" : "left" ); break;
8976								case numMonths[ 1 ] - 1: calender += " ui-datepicker-group-last";
8977									cornerClass = " ui-corner-" + ( isRTL ? "left" : "right" ); break;
8978								default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break;
8979							}
8980						}
8981						calender += "'>";
8982					}
8983					calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" +
8984						( /all|left/.test( cornerClass ) && row === 0 ? ( isRTL ? next : prev ) : "" ) +
8985						( /all|right/.test( cornerClass ) && row === 0 ? ( isRTL ? prev : next ) : "" ) +
8986						this._generateMonthYearHeader( inst, drawMonth, drawYear, minDate, maxDate,
8987							row > 0 || col > 0, monthNames, monthNamesShort ) + // draw month headers
8988						"</div><table class='ui-datepicker-calendar'><thead>" +
8989						"<tr>";
8990					thead = ( showWeek ? "<th class='ui-datepicker-week-col'>" + this._get( inst, "weekHeader" ) + "</th>" : "" );
8991					for ( dow = 0; dow < 7; dow++ ) { // days of the week
8992						day = ( dow + firstDay ) % 7;
8993						thead += "<th scope='col'" + ( ( dow + firstDay + 6 ) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "" ) + ">" +
8994							"<span title='" + dayNames[ day ] + "'>" + dayNamesMin[ day ] + "</span></th>";
8995					}
8996					calender += thead + "</tr></thead><tbody>";
8997					daysInMonth = this._getDaysInMonth( drawYear, drawMonth );
8998					if ( drawYear === inst.selectedYear && drawMonth === inst.selectedMonth ) {
8999						inst.selectedDay = Math.min( inst.selectedDay, daysInMonth );
9000					}
9001					leadDays = ( this._getFirstDayOfMonth( drawYear, drawMonth ) - firstDay + 7 ) % 7;
9002					curRows = Math.ceil( ( leadDays + daysInMonth ) / 7 ); // calculate the number of rows to generate
9003					numRows = ( isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows ); //If multiple months, use the higher number of rows (see #7043)
9004					this.maxRows = numRows;
9005					printDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 - leadDays ) );
9006					for ( dRow = 0; dRow < numRows; dRow++ ) { // create date picker rows
9007						calender += "<tr>";
9008						tbody = ( !showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
9009							this._get( inst, "calculateWeek" )( printDate ) + "</td>" );
9010						for ( dow = 0; dow < 7; dow++ ) { // create date picker days
9011							daySettings = ( beforeShowDay ?
9012								beforeShowDay.apply( ( inst.input ? inst.input[ 0 ] : null ), [ printDate ] ) : [ true, "" ] );
9013							otherMonth = ( printDate.getMonth() !== drawMonth );
9014							unselectable = ( otherMonth && !selectOtherMonths ) || !daySettings[ 0 ] ||
9015								( minDate && printDate < minDate ) || ( maxDate && printDate > maxDate );
9016							tbody += "<td class='" +
9017								( ( dow + firstDay + 6 ) % 7 >= 5 ? " ui-datepicker-week-end" : "" ) + // highlight weekends
9018								( otherMonth ? " ui-datepicker-other-month" : "" ) + // highlight days from other months
9019								( ( printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent ) || // user pressed key
9020								( defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime() ) ?
9021
9022									// or defaultDate is current printedDate and defaultDate is selectedDate
9023									" " + this._dayOverClass : "" ) + // highlight selected day
9024								( unselectable ? " " + this._unselectableClass + " ui-state-disabled" : "" ) +  // highlight unselectable days
9025								( otherMonth && !showOtherMonths ? "" : " " + daySettings[ 1 ] + // highlight custom dates
9026									( printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "" ) + // highlight selected day
9027									( printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "" ) ) + "'" + // highlight today (if different)
9028								( ( !otherMonth || showOtherMonths ) && daySettings[ 2 ] ? " title='" + daySettings[ 2 ].replace( /'/g, "&#39;" ) + "'" : "" ) + // cell title
9029								( unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'" ) + ">" + // actions
9030								( otherMonth && !showOtherMonths ? "&#xa0;" : // display for other months
9031									( unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" +
9032										( printDate.getTime() === today.getTime() ? " ui-state-highlight" : "" ) +
9033										( printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "" ) + // highlight selected day
9034										( otherMonth ? " ui-priority-secondary" : "" ) + // distinguish dates from other months
9035										"' href='#' aria-current='" + ( printDate.getTime() === currentDate.getTime() ? "true" : "false" ) + // mark date as selected for screen reader
9036										"' data-date='" + printDate.getDate() + // store date as data
9037										"'>" + printDate.getDate() + "</a>" ) ) + "</td>"; // display selectable date
9038							printDate.setDate( printDate.getDate() + 1 );
9039							printDate = this._daylightSavingAdjust( printDate );
9040						}
9041						calender += tbody + "</tr>";
9042					}
9043					drawMonth++;
9044					if ( drawMonth > 11 ) {
9045						drawMonth = 0;
9046						drawYear++;
9047					}
9048					calender += "</tbody></table>" + ( isMultiMonth ? "</div>" +
9049						( ( numMonths[ 0 ] > 0 && col === numMonths[ 1 ] - 1 ) ? "<div class='ui-datepicker-row-break'></div>" : "" ) : "" );
9050					group += calender;
9051				}
9052				html += group;
9053			}
9054			html += buttonPanel;
9055			inst._keyEvent = false;
9056			return html;
9057		},
9058
9059		/* Generate the month and year header. */
9060		_generateMonthYearHeader: function( inst, drawMonth, drawYear, minDate, maxDate,
9061											secondary, monthNames, monthNamesShort ) {
9062
9063			var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,
9064				changeMonth = this._get( inst, "changeMonth" ),
9065				changeYear = this._get( inst, "changeYear" ),
9066				showMonthAfterYear = this._get( inst, "showMonthAfterYear" ),
9067				selectMonthLabel = this._get( inst, "selectMonthLabel" ),
9068				selectYearLabel = this._get( inst, "selectYearLabel" ),
9069				html = "<div class='ui-datepicker-title'>",
9070				monthHtml = "";
9071
9072			// Month selection
9073			if ( secondary || !changeMonth ) {
9074				monthHtml += "<span class='ui-datepicker-month'>" + monthNames[ drawMonth ] + "</span>";
9075			} else {
9076				inMinYear = ( minDate && minDate.getFullYear() === drawYear );
9077				inMaxYear = ( maxDate && maxDate.getFullYear() === drawYear );
9078				monthHtml += "<select class='ui-datepicker-month' aria-label='" + selectMonthLabel + "' data-handler='selectMonth' data-event='change'>";
9079				for ( month = 0; month < 12; month++ ) {
9080					if ( ( !inMinYear || month >= minDate.getMonth() ) && ( !inMaxYear || month <= maxDate.getMonth() ) ) {
9081						monthHtml += "<option value='" + month + "'" +
9082							( month === drawMonth ? " selected='selected'" : "" ) +
9083							">" + monthNamesShort[ month ] + "</option>";
9084					}
9085				}
9086				monthHtml += "</select>";
9087			}
9088
9089			if ( !showMonthAfterYear ) {
9090				html += monthHtml + ( secondary || !( changeMonth && changeYear ) ? "&#xa0;" : "" );
9091			}
9092
9093			// Year selection
9094			if ( !inst.yearshtml ) {
9095				inst.yearshtml = "";
9096				if ( secondary || !changeYear ) {
9097					html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
9098				} else {
9099
9100					// determine range of years to display
9101					years = this._get( inst, "yearRange" ).split( ":" );
9102					thisYear = new Date().getFullYear();
9103					determineYear = function( value ) {
9104						var year = ( value.match( /c[+\-].*/ ) ? drawYear + parseInt( value.substring( 1 ), 10 ) :
9105							( value.match( /[+\-].*/ ) ? thisYear + parseInt( value, 10 ) :
9106								parseInt( value, 10 ) ) );
9107						return ( isNaN( year ) ? thisYear : year );
9108					};
9109					year = determineYear( years[ 0 ] );
9110					endYear = Math.max( year, determineYear( years[ 1 ] || "" ) );
9111					year = ( minDate ? Math.max( year, minDate.getFullYear() ) : year );
9112					endYear = ( maxDate ? Math.min( endYear, maxDate.getFullYear() ) : endYear );
9113					inst.yearshtml += "<select class='ui-datepicker-year' aria-label='" + selectYearLabel + "' data-handler='selectYear' data-event='change'>";
9114					for ( ; year <= endYear; year++ ) {
9115						inst.yearshtml += "<option value='" + year + "'" +
9116							( year === drawYear ? " selected='selected'" : "" ) +
9117							">" + year + "</option>";
9118					}
9119					inst.yearshtml += "</select>";
9120
9121					html += inst.yearshtml;
9122					inst.yearshtml = null;
9123				}
9124			}
9125
9126			html += this._get( inst, "yearSuffix" );
9127			if ( showMonthAfterYear ) {
9128				html += ( secondary || !( changeMonth && changeYear ) ? "&#xa0;" : "" ) + monthHtml;
9129			}
9130			html += "</div>"; // Close datepicker_header
9131			return html;
9132		},
9133
9134		/* Adjust one of the date sub-fields. */
9135		_adjustInstDate: function( inst, offset, period ) {
9136			var year = inst.selectedYear + ( period === "Y" ? offset : 0 ),
9137				month = inst.selectedMonth + ( period === "M" ? offset : 0 ),
9138				day = Math.min( inst.selectedDay, this._getDaysInMonth( year, month ) ) + ( period === "D" ? offset : 0 ),
9139				date = this._restrictMinMax( inst, this._daylightSavingAdjust( new Date( year, month, day ) ) );
9140
9141			inst.selectedDay = date.getDate();
9142			inst.drawMonth = inst.selectedMonth = date.getMonth();
9143			inst.drawYear = inst.selectedYear = date.getFullYear();
9144			if ( period === "M" || period === "Y" ) {
9145				this._notifyChange( inst );
9146			}
9147		},
9148
9149		/* Ensure a date is within any min/max bounds. */
9150		_restrictMinMax: function( inst, date ) {
9151			var minDate = this._getMinMaxDate( inst, "min" ),
9152				maxDate = this._getMinMaxDate( inst, "max" ),
9153				newDate = ( minDate && date < minDate ? minDate : date );
9154			return ( maxDate && newDate > maxDate ? maxDate : newDate );
9155		},
9156
9157		/* Notify change of month/year. */
9158		_notifyChange: function( inst ) {
9159			var onChange = this._get( inst, "onChangeMonthYear" );
9160			if ( onChange ) {
9161				onChange.apply( ( inst.input ? inst.input[ 0 ] : null ),
9162					[ inst.selectedYear, inst.selectedMonth + 1, inst ] );
9163			}
9164		},
9165
9166		/* Determine the number of months to show. */
9167		_getNumberOfMonths: function( inst ) {
9168			var numMonths = this._get( inst, "numberOfMonths" );
9169			return ( numMonths == null ? [ 1, 1 ] : ( typeof numMonths === "number" ? [ 1, numMonths ] : numMonths ) );
9170		},
9171
9172		/* Determine the current maximum date - ensure no time components are set. */
9173		_getMinMaxDate: function( inst, minMax ) {
9174			return this._determineDate( inst, this._get( inst, minMax + "Date" ), null );
9175		},
9176
9177		/* Find the number of days in a given month. */
9178		_getDaysInMonth: function( year, month ) {
9179			return 32 - this._daylightSavingAdjust( new Date( year, month, 32 ) ).getDate();
9180		},
9181
9182		/* Find the day of the week of the first of a month. */
9183		_getFirstDayOfMonth: function( year, month ) {
9184			return new Date( year, month, 1 ).getDay();
9185		},
9186
9187		/* Determines if we should allow a "next/prev" month display change. */
9188		_canAdjustMonth: function( inst, offset, curYear, curMonth ) {
9189			var numMonths = this._getNumberOfMonths( inst ),
9190				date = this._daylightSavingAdjust( new Date( curYear,
9191					curMonth + ( offset < 0 ? offset : numMonths[ 0 ] * numMonths[ 1 ] ), 1 ) );
9192
9193			if ( offset < 0 ) {
9194				date.setDate( this._getDaysInMonth( date.getFullYear(), date.getMonth() ) );
9195			}
9196			return this._isInRange( inst, date );
9197		},
9198
9199		/* Is the given date in the accepted range? */
9200		_isInRange: function( inst, date ) {
9201			var yearSplit, currentYear,
9202				minDate = this._getMinMaxDate( inst, "min" ),
9203				maxDate = this._getMinMaxDate( inst, "max" ),
9204				minYear = null,
9205				maxYear = null,
9206				years = this._get( inst, "yearRange" );
9207			if ( years ) {
9208				yearSplit = years.split( ":" );
9209				currentYear = new Date().getFullYear();
9210				minYear = parseInt( yearSplit[ 0 ], 10 );
9211				maxYear = parseInt( yearSplit[ 1 ], 10 );
9212				if ( yearSplit[ 0 ].match( /[+\-].*/ ) ) {
9213					minYear += currentYear;
9214				}
9215				if ( yearSplit[ 1 ].match( /[+\-].*/ ) ) {
9216					maxYear += currentYear;
9217				}
9218			}
9219
9220			return ( ( !minDate || date.getTime() >= minDate.getTime() ) &&
9221				( !maxDate || date.getTime() <= maxDate.getTime() ) &&
9222				( !minYear || date.getFullYear() >= minYear ) &&
9223				( !maxYear || date.getFullYear() <= maxYear ) );
9224		},
9225
9226		/* Provide the configuration settings for formatting/parsing. */
9227		_getFormatConfig: function( inst ) {
9228			var shortYearCutoff = this._get( inst, "shortYearCutoff" );
9229			shortYearCutoff = ( typeof shortYearCutoff !== "string" ? shortYearCutoff :
9230				new Date().getFullYear() % 100 + parseInt( shortYearCutoff, 10 ) );
9231			return { shortYearCutoff: shortYearCutoff,
9232				dayNamesShort: this._get( inst, "dayNamesShort" ), dayNames: this._get( inst, "dayNames" ),
9233				monthNamesShort: this._get( inst, "monthNamesShort" ), monthNames: this._get( inst, "monthNames" ) };
9234		},
9235
9236		/* Format the given date for display. */
9237		_formatDate: function( inst, day, month, year ) {
9238			if ( !day ) {
9239				inst.currentDay = inst.selectedDay;
9240				inst.currentMonth = inst.selectedMonth;
9241				inst.currentYear = inst.selectedYear;
9242			}
9243			var date = ( day ? ( typeof day === "object" ? day :
9244					this._daylightSavingAdjust( new Date( year, month, day ) ) ) :
9245				this._daylightSavingAdjust( new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) );
9246			return this.formatDate( this._get( inst, "dateFormat" ), date, this._getFormatConfig( inst ) );
9247		}
9248	} );
9249
9250	/*
9251 * Bind hover events for datepicker elements.
9252 * Done via delegate so the binding only occurs once in the lifetime of the parent div.
9253 * Global datepicker_instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
9254 */
9255	function datepicker_bindHover( dpDiv ) {
9256		var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";
9257		return dpDiv.on( "mouseout", selector, function() {
9258			$( this ).removeClass( "ui-state-hover" );
9259			if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) {
9260				$( this ).removeClass( "ui-datepicker-prev-hover" );
9261			}
9262			if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) {
9263				$( this ).removeClass( "ui-datepicker-next-hover" );
9264			}
9265		} )
9266			.on( "mouseover", selector, datepicker_handleMouseover );
9267	}
9268
9269	function datepicker_handleMouseover() {
9270		if ( !$.datepicker._isDisabledDatepicker( datepicker_instActive.inline ? datepicker_instActive.dpDiv.parent()[ 0 ] : datepicker_instActive.input[ 0 ] ) ) {
9271			$( this ).parents( ".ui-datepicker-calendar" ).find( "a" ).removeClass( "ui-state-hover" );
9272			$( this ).addClass( "ui-state-hover" );
9273			if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) {
9274				$( this ).addClass( "ui-datepicker-prev-hover" );
9275			}
9276			if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) {
9277				$( this ).addClass( "ui-datepicker-next-hover" );
9278			}
9279		}
9280	}
9281
9282	/* jQuery extend now ignores nulls! */
9283	function datepicker_extendRemove( target, props ) {
9284		$.extend( target, props );
9285		for ( var name in props ) {
9286			if ( props[ name ] == null ) {
9287				target[ name ] = props[ name ];
9288			}
9289		}
9290		return target;
9291	}
9292
9293	/* Invoke the datepicker functionality.
9294   @param  options  string - a command, optionally followed by additional parameters or
9295					Object - settings for attaching new datepicker functionality
9296   @return  jQuery object */
9297	$.fn.datepicker = function( options ) {
9298
9299		/* Verify an empty collection wasn't passed - Fixes #6976 */
9300		if ( !this.length ) {
9301			return this;
9302		}
9303
9304		/* Initialise the date picker. */
9305		if ( !$.datepicker.initialized ) {
9306			$( document ).on( "mousedown", $.datepicker._checkExternalClick );
9307			$.datepicker.initialized = true;
9308		}
9309
9310		/* Append datepicker main container to body if not exist. */
9311		if ( $( "#" + $.datepicker._mainDivId ).length === 0 ) {
9312			$( "body" ).append( $.datepicker.dpDiv );
9313		}
9314
9315		var otherArgs = Array.prototype.slice.call( arguments, 1 );
9316		if ( typeof options === "string" && ( options === "isDisabled" || options === "getDate" || options === "widget" ) ) {
9317			return $.datepicker[ "_" + options + "Datepicker" ].
9318			apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) );
9319		}
9320		if ( options === "option" && arguments.length === 2 && typeof arguments[ 1 ] === "string" ) {
9321			return $.datepicker[ "_" + options + "Datepicker" ].
9322			apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) );
9323		}
9324		return this.each( function() {
9325			if ( typeof options === "string" ) {
9326				$.datepicker[ "_" + options + "Datepicker" ]
9327					.apply( $.datepicker, [ this ].concat( otherArgs ) );
9328			} else {
9329				$.datepicker._attachDatepicker( this, options );
9330			}
9331		} );
9332	};
9333
9334	$.datepicker = new Datepicker(); // singleton instance
9335	$.datepicker.initialized = false;
9336	$.datepicker.uuid = new Date().getTime();
9337	$.datepicker.version = "1.14.1";
9338
9339	var widgetsDatepicker = $.datepicker;
9340
9341
9342	/*!
9343 * jQuery UI Mouse 1.14.1
9344 * https://jqueryui.com
9345 *
9346 * Copyright OpenJS Foundation and other contributors
9347 * Released under the MIT license.
9348 * https://jquery.org/license
9349 */
9350
9351//>>label: Mouse
9352//>>group: Widgets
9353//>>description: Abstracts mouse-based interactions to assist in creating certain widgets.
9354//>>docs: https://api.jqueryui.com/mouse/
9355
9356
9357	var mouseHandled = false;
9358	$( document ).on( "mouseup", function() {
9359		mouseHandled = false;
9360	} );
9361
9362	var widgetsMouse = $.widget( "ui.mouse", {
9363		version: "1.14.1",
9364		options: {
9365			cancel: "input, textarea, button, select, option",
9366			distance: 1,
9367			delay: 0
9368		},
9369		_mouseInit: function() {
9370			var that = this;
9371
9372			this.element
9373				.on( "mousedown." + this.widgetName, function( event ) {
9374					return that._mouseDown( event );
9375				} )
9376				.on( "click." + this.widgetName, function( event ) {
9377					if ( true === $.data( event.target, that.widgetName + ".preventClickEvent" ) ) {
9378						$.removeData( event.target, that.widgetName + ".preventClickEvent" );
9379						event.stopImmediatePropagation();
9380						return false;
9381					}
9382				} );
9383
9384			this.started = false;
9385		},
9386
9387		// TODO: make sure destroying one instance of mouse doesn't mess with
9388		// other instances of mouse
9389		_mouseDestroy: function() {
9390			this.element.off( "." + this.widgetName );
9391			if ( this._mouseMoveDelegate ) {
9392				this.document
9393					.off( "mousemove." + this.widgetName, this._mouseMoveDelegate )
9394					.off( "mouseup." + this.widgetName, this._mouseUpDelegate );
9395			}
9396		},
9397
9398		_mouseDown: function( event ) {
9399
9400			// don't let more than one widget handle mouseStart
9401			if ( mouseHandled ) {
9402				return;
9403			}
9404
9405			this._mouseMoved = false;
9406
9407			// We may have missed mouseup (out of window)
9408			if ( this._mouseStarted ) {
9409				this._mouseUp( event );
9410			}
9411
9412			this._mouseDownEvent = event;
9413
9414			var that = this,
9415				btnIsLeft = event.which === 1,
9416				elIsCancel = typeof this.options.cancel === "string" ?
9417					$( event.target ).closest( this.options.cancel ).length :
9418					false;
9419			if ( !btnIsLeft || elIsCancel || !this._mouseCapture( event ) ) {
9420				return true;
9421			}
9422
9423			this.mouseDelayMet = !this.options.delay;
9424			if ( !this.mouseDelayMet ) {
9425				this._mouseDelayTimer = setTimeout( function() {
9426					that.mouseDelayMet = true;
9427				}, this.options.delay );
9428			}
9429
9430			if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) {
9431				this._mouseStarted = ( this._mouseStart( event ) !== false );
9432				if ( !this._mouseStarted ) {
9433					event.preventDefault();
9434					return true;
9435				}
9436			}
9437
9438			// Click event may never have fired (Gecko & Opera)
9439			if ( true === $.data( event.target, this.widgetName + ".preventClickEvent" ) ) {
9440				$.removeData( event.target, this.widgetName + ".preventClickEvent" );
9441			}
9442
9443			// These delegates are required to keep context
9444			this._mouseMoveDelegate = function( event ) {
9445				return that._mouseMove( event );
9446			};
9447			this._mouseUpDelegate = function( event ) {
9448				return that._mouseUp( event );
9449			};
9450
9451			this.document
9452				.on( "mousemove." + this.widgetName, this._mouseMoveDelegate )
9453				.on( "mouseup." + this.widgetName, this._mouseUpDelegate );
9454
9455			event.preventDefault();
9456
9457			mouseHandled = true;
9458			return true;
9459		},
9460
9461		_mouseMove: function( event ) {
9462
9463			// Only check for mouseups outside the document if you've moved inside the document
9464			// at least once.
9465			if ( this._mouseMoved && !event.which ) {
9466
9467				// Support: Safari <=8 - 9
9468				// Safari sets which to 0 if you press any of the following keys
9469				// during a drag (#14461)
9470				if ( event.originalEvent.altKey || event.originalEvent.ctrlKey ||
9471					event.originalEvent.metaKey || event.originalEvent.shiftKey ) {
9472					this.ignoreMissingWhich = true;
9473				} else if ( !this.ignoreMissingWhich ) {
9474					return this._mouseUp( event );
9475				}
9476			}
9477
9478			if ( event.which || event.button ) {
9479				this._mouseMoved = true;
9480			}
9481
9482			if ( this._mouseStarted ) {
9483				this._mouseDrag( event );
9484				return event.preventDefault();
9485			}
9486
9487			if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) {
9488				this._mouseStarted =
9489					( this._mouseStart( this._mouseDownEvent, event ) !== false );
9490				if ( this._mouseStarted ) {
9491					this._mouseDrag( event );
9492				} else {
9493					this._mouseUp( event );
9494				}
9495			}
9496
9497			return !this._mouseStarted;
9498		},
9499
9500		_mouseUp: function( event ) {
9501			this.document
9502				.off( "mousemove." + this.widgetName, this._mouseMoveDelegate )
9503				.off( "mouseup." + this.widgetName, this._mouseUpDelegate );
9504
9505			if ( this._mouseStarted ) {
9506				this._mouseStarted = false;
9507
9508				if ( event.target === this._mouseDownEvent.target ) {
9509					$.data( event.target, this.widgetName + ".preventClickEvent", true );
9510				}
9511
9512				this._mouseStop( event );
9513			}
9514
9515			if ( this._mouseDelayTimer ) {
9516				clearTimeout( this._mouseDelayTimer );
9517				delete this._mouseDelayTimer;
9518			}
9519
9520			this.ignoreMissingWhich = false;
9521			mouseHandled = false;
9522			event.preventDefault();
9523		},
9524
9525		_mouseDistanceMet: function( event ) {
9526			return ( Math.max(
9527					Math.abs( this._mouseDownEvent.pageX - event.pageX ),
9528					Math.abs( this._mouseDownEvent.pageY - event.pageY )
9529				) >= this.options.distance
9530			);
9531		},
9532
9533		_mouseDelayMet: function( /* event */ ) {
9534			return this.mouseDelayMet;
9535		},
9536
9537		// These are placeholder methods, to be overriden by extending plugin
9538		_mouseStart: function( /* event */ ) {},
9539		_mouseDrag: function( /* event */ ) {},
9540		_mouseStop: function( /* event */ ) {},
9541		_mouseCapture: function( /* event */ ) {
9542			return true;
9543		}
9544	} );
9545
9546
9547
9548// $.ui.plugin is deprecated. Use $.widget() extensions instead.
9549	var plugin = $.ui.plugin = {
9550		add: function( module, option, set ) {
9551			var i,
9552				proto = $.ui[ module ].prototype;
9553			for ( i in set ) {
9554				proto.plugins[ i ] = proto.plugins[ i ] || [];
9555				proto.plugins[ i ].push( [ option, set[ i ] ] );
9556			}
9557		},
9558		call: function( instance, name, args, allowDisconnected ) {
9559			var i,
9560				set = instance.plugins[ name ];
9561
9562			if ( !set ) {
9563				return;
9564			}
9565
9566			if ( !allowDisconnected && ( !instance.element[ 0 ].parentNode ||
9567				instance.element[ 0 ].parentNode.nodeType === 11 ) ) {
9568				return;
9569			}
9570
9571			for ( i = 0; i < set.length; i++ ) {
9572				if ( instance.options[ set[ i ][ 0 ] ] ) {
9573					set[ i ][ 1 ].apply( instance.element, args );
9574				}
9575			}
9576		}
9577	};
9578
9579
9580	/*!
9581 * jQuery UI Draggable 1.14.1
9582 * https://jqueryui.com
9583 *
9584 * Copyright OpenJS Foundation and other contributors
9585 * Released under the MIT license.
9586 * https://jquery.org/license
9587 */
9588
9589//>>label: Draggable
9590//>>group: Interactions
9591//>>description: Enables dragging functionality for any element.
9592//>>docs: https://api.jqueryui.com/draggable/
9593//>>demos: https://jqueryui.com/draggable/
9594//>>css.structure: ../../themes/base/draggable.css
9595
9596
9597	$.widget( "ui.draggable", $.ui.mouse, {
9598		version: "1.14.1",
9599		widgetEventPrefix: "drag",
9600		options: {
9601			addClasses: true,
9602			appendTo: "parent",
9603			axis: false,
9604			connectToSortable: false,
9605			containment: false,
9606			cursor: "auto",
9607			cursorAt: false,
9608			grid: false,
9609			handle: false,
9610			helper: "original",
9611			iframeFix: false,
9612			opacity: false,
9613			refreshPositions: false,
9614			revert: false,
9615			revertDuration: 500,
9616			scope: "default",
9617			scroll: true,
9618			scrollSensitivity: 20,
9619			scrollSpeed: 20,
9620			snap: false,
9621			snapMode: "both",
9622			snapTolerance: 20,
9623			stack: false,
9624			zIndex: false,
9625
9626			// Callbacks
9627			drag: null,
9628			start: null,
9629			stop: null
9630		},
9631		_create: function() {
9632
9633			if ( this.options.helper === "original" ) {
9634				this._setPositionRelative();
9635			}
9636			if ( this.options.addClasses ) {
9637				this._addClass( "ui-draggable" );
9638			}
9639			this._setHandleClassName();
9640
9641			this._mouseInit();
9642		},
9643
9644		_setOption: function( key, value ) {
9645			this._super( key, value );
9646			if ( key === "handle" ) {
9647				this._removeHandleClassName();
9648				this._setHandleClassName();
9649			}
9650		},
9651
9652		_destroy: function() {
9653			if ( ( this.helper || this.element ).is( ".ui-draggable-dragging" ) ) {
9654				this.destroyOnClear = true;
9655				return;
9656			}
9657			this._removeHandleClassName();
9658			this._mouseDestroy();
9659		},
9660
9661		_mouseCapture: function( event ) {
9662			var o = this.options;
9663
9664			// Among others, prevent a drag on a resizable-handle
9665			if ( this.helper || o.disabled ||
9666				$( event.target ).closest( ".ui-resizable-handle" ).length > 0 ) {
9667				return false;
9668			}
9669
9670			//Quit if we're not on a valid handle
9671			this.handle = this._getHandle( event );
9672			if ( !this.handle ) {
9673				return false;
9674			}
9675
9676			this._blurActiveElement( event );
9677
9678			this._blockFrames( o.iframeFix === true ? "iframe" : o.iframeFix );
9679
9680			return true;
9681
9682		},
9683
9684		_blockFrames: function( selector ) {
9685			this.iframeBlocks = this.document.find( selector ).map( function() {
9686				var iframe = $( this );
9687
9688				return $( "<div>" )
9689					.css( "position", "absolute" )
9690					.appendTo( iframe.parent() )
9691					.outerWidth( iframe.outerWidth() )
9692					.outerHeight( iframe.outerHeight() )
9693					.offset( iframe.offset() )[ 0 ];
9694			} );
9695		},
9696
9697		_unblockFrames: function() {
9698			if ( this.iframeBlocks ) {
9699				this.iframeBlocks.remove();
9700				delete this.iframeBlocks;
9701			}
9702		},
9703
9704		_blurActiveElement: function( event ) {
9705			var activeElement = this.document[ 0 ].activeElement,
9706				target = $( event.target );
9707
9708			// Don't blur if the event occurred on an element that is within
9709			// the currently focused element
9710			// See #10527, #12472
9711			if ( target.closest( activeElement ).length ) {
9712				return;
9713			}
9714
9715			// Blur any element that currently has focus, see #4261
9716			$( activeElement ).trigger( "blur" );
9717		},
9718
9719		_mouseStart: function( event ) {
9720
9721			var o = this.options;
9722
9723			//Create and append the visible helper
9724			this.helper = this._createHelper( event );
9725
9726			this._addClass( this.helper, "ui-draggable-dragging" );
9727
9728			//Cache the helper size
9729			this._cacheHelperProportions();
9730
9731			//If ddmanager is used for droppables, set the global draggable
9732			if ( $.ui.ddmanager ) {
9733				$.ui.ddmanager.current = this;
9734			}
9735
9736			/*
9737		 * - Position generation -
9738		 * This block generates everything position related - it's the core of draggables.
9739		 */
9740
9741			//Cache the margins of the original element
9742			this._cacheMargins();
9743
9744			//Store the helper's css position
9745			this.cssPosition = this.helper.css( "position" );
9746			this.scrollParent = this.helper.scrollParent( true );
9747			this.offsetParent = this.helper.offsetParent();
9748			this.hasFixedAncestor = this.helper.parents().filter( function() {
9749				return $( this ).css( "position" ) === "fixed";
9750			} ).length > 0;
9751
9752			//The element's absolute position on the page minus margins
9753			this.positionAbs = this.element.offset();
9754			this._refreshOffsets( event );
9755
9756			//Generate the original position
9757			this.originalPosition = this.position = this._generatePosition( event, false );
9758			this.originalPageX = event.pageX;
9759			this.originalPageY = event.pageY;
9760
9761			//Adjust the mouse offset relative to the helper if "cursorAt" is supplied
9762			if ( o.cursorAt ) {
9763				this._adjustOffsetFromHelper( o.cursorAt );
9764			}
9765
9766			//Set a containment if given in the options
9767			this._setContainment();
9768
9769			//Trigger event + callbacks
9770			if ( this._trigger( "start", event ) === false ) {
9771				this._clear();
9772				return false;
9773			}
9774
9775			//Recache the helper size
9776			this._cacheHelperProportions();
9777
9778			//Prepare the droppable offsets
9779			if ( $.ui.ddmanager && !o.dropBehaviour ) {
9780				$.ui.ddmanager.prepareOffsets( this, event );
9781			}
9782
9783			// Execute the drag once - this causes the helper not to be visible before getting its
9784			// correct position
9785			this._mouseDrag( event, true );
9786
9787			// If the ddmanager is used for droppables, inform the manager that dragging has started
9788			// (see #5003)
9789			if ( $.ui.ddmanager ) {
9790				$.ui.ddmanager.dragStart( this, event );
9791			}
9792
9793			return true;
9794		},
9795
9796		_refreshOffsets: function( event ) {
9797			this.offset = {
9798				top: this.positionAbs.top - this.margins.top,
9799				left: this.positionAbs.left - this.margins.left,
9800				scroll: false,
9801				parent: this._getParentOffset(),
9802				relative: this._getRelativeOffset()
9803			};
9804
9805			this.offset.click = {
9806				left: event.pageX - this.offset.left,
9807				top: event.pageY - this.offset.top
9808			};
9809		},
9810
9811		_mouseDrag: function( event, noPropagation ) {
9812
9813			// reset any necessary cached properties (see #5009)
9814			if ( this.hasFixedAncestor ) {
9815				this.offset.parent = this._getParentOffset();
9816			}
9817
9818			//Compute the helpers position
9819			this.position = this._generatePosition( event, true );
9820			this.positionAbs = this._convertPositionTo( "absolute" );
9821
9822			//Call plugins and callbacks and use the resulting position if something is returned
9823			if ( !noPropagation ) {
9824				var ui = this._uiHash();
9825				if ( this._trigger( "drag", event, ui ) === false ) {
9826					this._mouseUp( new $.Event( "mouseup", event ) );
9827					return false;
9828				}
9829				this.position = ui.position;
9830			}
9831
9832			this.helper[ 0 ].style.left = this.position.left + "px";
9833			this.helper[ 0 ].style.top = this.position.top + "px";
9834
9835			if ( $.ui.ddmanager ) {
9836				$.ui.ddmanager.drag( this, event );
9837			}
9838
9839			return false;
9840		},
9841
9842		_mouseStop: function( event ) {
9843
9844			//If we are using droppables, inform the manager about the drop
9845			var that = this,
9846				dropped = false;
9847			if ( $.ui.ddmanager && !this.options.dropBehaviour ) {
9848				dropped = $.ui.ddmanager.drop( this, event );
9849			}
9850
9851			//if a drop comes from outside (a sortable)
9852			if ( this.dropped ) {
9853				dropped = this.dropped;
9854				this.dropped = false;
9855			}
9856
9857			if ( ( this.options.revert === "invalid" && !dropped ) ||
9858				( this.options.revert === "valid" && dropped ) ||
9859				this.options.revert === true || ( typeof this.options.revert === "function" &&
9860					this.options.revert.call( this.element, dropped ) )
9861			) {
9862				$( this.helper ).animate(
9863					this.originalPosition,
9864					parseInt( this.options.revertDuration, 10 ),
9865					function() {
9866						if ( that._trigger( "stop", event ) !== false ) {
9867							that._clear();
9868						}
9869					}
9870				);
9871			} else {
9872				if ( this._trigger( "stop", event ) !== false ) {
9873					this._clear();
9874				}
9875			}
9876
9877			return false;
9878		},
9879
9880		_mouseUp: function( event ) {
9881			this._unblockFrames();
9882
9883			// If the ddmanager is used for droppables, inform the manager that dragging has stopped
9884			// (see #5003)
9885			if ( $.ui.ddmanager ) {
9886				$.ui.ddmanager.dragStop( this, event );
9887			}
9888
9889			// Only need to focus if the event occurred on the draggable itself, see #10527
9890			if ( this.handleElement.is( event.target ) ) {
9891
9892				// The interaction is over; whether or not the click resulted in a drag,
9893				// focus the element
9894				this.element.trigger( "focus" );
9895			}
9896
9897			return $.ui.mouse.prototype._mouseUp.call( this, event );
9898		},
9899
9900		cancel: function() {
9901
9902			if ( this.helper.is( ".ui-draggable-dragging" ) ) {
9903				this._mouseUp( new $.Event( "mouseup", { target: this.element[ 0 ] } ) );
9904			} else {
9905				this._clear();
9906			}
9907
9908			return this;
9909
9910		},
9911
9912		_getHandle: function( event ) {
9913			return this.options.handle ?
9914				!!$( event.target ).closest( this.element.find( this.options.handle ) ).length :
9915				true;
9916		},
9917
9918		_setHandleClassName: function() {
9919			this.handleElement = this.options.handle ?
9920				this.element.find( this.options.handle ) : this.element;
9921			this._addClass( this.handleElement, "ui-draggable-handle" );
9922		},
9923
9924		_removeHandleClassName: function() {
9925			this._removeClass( this.handleElement, "ui-draggable-handle" );
9926		},
9927
9928		_createHelper: function( event ) {
9929
9930			var o = this.options,
9931				helperIsFunction = typeof o.helper === "function",
9932				helper = helperIsFunction ?
9933					$( o.helper.apply( this.element[ 0 ], [ event ] ) ) :
9934					( o.helper === "clone" ?
9935						this.element.clone().removeAttr( "id" ) :
9936						this.element );
9937
9938			if ( !helper.parents( "body" ).length ) {
9939				helper.appendTo( ( o.appendTo === "parent" ?
9940					this.element[ 0 ].parentNode :
9941					o.appendTo ) );
9942			}
9943
9944			// https://bugs.jqueryui.com/ticket/9446
9945			// a helper function can return the original element
9946			// which wouldn't have been set to relative in _create
9947			if ( helperIsFunction && helper[ 0 ] === this.element[ 0 ] ) {
9948				this._setPositionRelative();
9949			}
9950
9951			if ( helper[ 0 ] !== this.element[ 0 ] &&
9952				!( /(fixed|absolute)/ ).test( helper.css( "position" ) ) ) {
9953				helper.css( "position", "absolute" );
9954			}
9955
9956			return helper;
9957
9958		},
9959
9960		_setPositionRelative: function() {
9961			if ( !( /^(?:r|a|f)/ ).test( this.element.css( "position" ) ) ) {
9962				this.element[ 0 ].style.position = "relative";
9963			}
9964		},
9965
9966		_adjustOffsetFromHelper: function( obj ) {
9967			if ( typeof obj === "string" ) {
9968				obj = obj.split( " " );
9969			}
9970			if ( Array.isArray( obj ) ) {
9971				obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 };
9972			}
9973			if ( "left" in obj ) {
9974				this.offset.click.left = obj.left + this.margins.left;
9975			}
9976			if ( "right" in obj ) {
9977				this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
9978			}
9979			if ( "top" in obj ) {
9980				this.offset.click.top = obj.top + this.margins.top;
9981			}
9982			if ( "bottom" in obj ) {
9983				this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
9984			}
9985		},
9986
9987		_isRootNode: function( element ) {
9988			return ( /(html|body)/i ).test( element.tagName ) || element === this.document[ 0 ];
9989		},
9990
9991		_getParentOffset: function() {
9992
9993			//Get the offsetParent and cache its position
9994			var po = this.offsetParent.offset(),
9995				document = this.document[ 0 ];
9996
9997			// This is a special case where we need to modify a offset calculated on start, since the
9998			// following happened:
9999			// 1. The position of the helper is absolute, so it's position is calculated based on the
10000			// next positioned parent
10001			// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't
10002			// the document, which means that the scroll is included in the initial calculation of the
10003			// offset of the parent, and never recalculated upon drag
10004			if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== document &&
10005				$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) {
10006				po.left += this.scrollParent.scrollLeft();
10007				po.top += this.scrollParent.scrollTop();
10008			}
10009
10010			if ( this._isRootNode( this.offsetParent[ 0 ] ) ) {
10011				po = { top: 0, left: 0 };
10012			}
10013
10014			return {
10015				top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ),
10016				left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 )
10017			};
10018
10019		},
10020
10021		_getRelativeOffset: function() {
10022			if ( this.cssPosition !== "relative" ) {
10023				return { top: 0, left: 0 };
10024			}
10025
10026			var p = this.element.position(),
10027				scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
10028
10029			return {
10030				top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) +
10031					( !scrollIsRootNode ? this.scrollParent.scrollTop() : 0 ),
10032				left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) +
10033					( !scrollIsRootNode ? this.scrollParent.scrollLeft() : 0 )
10034			};
10035
10036		},
10037
10038		_cacheMargins: function() {
10039			this.margins = {
10040				left: ( parseInt( this.element.css( "marginLeft" ), 10 ) || 0 ),
10041				top: ( parseInt( this.element.css( "marginTop" ), 10 ) || 0 ),
10042				right: ( parseInt( this.element.css( "marginRight" ), 10 ) || 0 ),
10043				bottom: ( parseInt( this.element.css( "marginBottom" ), 10 ) || 0 )
10044			};
10045		},
10046
10047		_cacheHelperProportions: function() {
10048			this.helperProportions = {
10049				width: this.helper.outerWidth(),
10050				height: this.helper.outerHeight()
10051			};
10052		},
10053
10054		_setContainment: function() {
10055
10056			var isUserScrollable, c, ce,
10057				o = this.options,
10058				document = this.document[ 0 ];
10059
10060			this.relativeContainer = null;
10061
10062			if ( !o.containment ) {
10063				this.containment = null;
10064				return;
10065			}
10066
10067			if ( o.containment === "window" ) {
10068				this.containment = [
10069					$( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
10070					$( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top,
10071					$( window ).scrollLeft() + $( window ).width() -
10072					this.helperProportions.width - this.margins.left,
10073					$( window ).scrollTop() +
10074					( $( window ).height() || document.body.parentNode.scrollHeight ) -
10075					this.helperProportions.height - this.margins.top
10076				];
10077				return;
10078			}
10079
10080			if ( o.containment === "document" ) {
10081				this.containment = [
10082					0,
10083					0,
10084					$( document ).width() - this.helperProportions.width - this.margins.left,
10085					( $( document ).height() || document.body.parentNode.scrollHeight ) -
10086					this.helperProportions.height - this.margins.top
10087				];
10088				return;
10089			}
10090
10091			if ( o.containment.constructor === Array ) {
10092				this.containment = o.containment;
10093				return;
10094			}
10095
10096			if ( o.containment === "parent" ) {
10097				o.containment = this.helper[ 0 ].parentNode;
10098			}
10099
10100			c = $( o.containment );
10101			ce = c[ 0 ];
10102
10103			if ( !ce ) {
10104				return;
10105			}
10106
10107			isUserScrollable = /(scroll|auto)/.test( c.css( "overflow" ) );
10108
10109			this.containment = [
10110				( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) +
10111				( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ),
10112				( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) +
10113				( parseInt( c.css( "paddingTop" ), 10 ) || 0 ),
10114				( isUserScrollable ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -
10115				( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) -
10116				( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) -
10117				this.helperProportions.width -
10118				this.margins.left -
10119				this.margins.right,
10120				( isUserScrollable ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -
10121				( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) -
10122				( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) -
10123				this.helperProportions.height -
10124				this.margins.top -
10125				this.margins.bottom
10126			];
10127			this.relativeContainer = c;
10128		},
10129
10130		_convertPositionTo: function( d, pos ) {
10131
10132			if ( !pos ) {
10133				pos = this.position;
10134			}
10135
10136			var mod = d === "absolute" ? 1 : -1,
10137				scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
10138
10139			return {
10140				top: (
10141
10142					// The absolute mouse position
10143					pos.top	+
10144
10145					// Only for relative positioned nodes: Relative offset from element to offset parent
10146					this.offset.relative.top * mod +
10147
10148					// The offsetParent's offset without borders (offset + border)
10149					this.offset.parent.top * mod -
10150					( ( this.cssPosition === "fixed" ?
10151						-this.offset.scroll.top :
10152						( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) * mod )
10153				),
10154				left: (
10155
10156					// The absolute mouse position
10157					pos.left +
10158
10159					// Only for relative positioned nodes: Relative offset from element to offset parent
10160					this.offset.relative.left * mod +
10161
10162					// The offsetParent's offset without borders (offset + border)
10163					this.offset.parent.left * mod	-
10164					( ( this.cssPosition === "fixed" ?
10165						-this.offset.scroll.left :
10166						( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) * mod )
10167				)
10168			};
10169
10170		},
10171
10172		_generatePosition: function( event, constrainPosition ) {
10173
10174			var containment, co, top, left,
10175				o = this.options,
10176				scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ),
10177				pageX = event.pageX,
10178				pageY = event.pageY;
10179
10180			// Cache the scroll
10181			if ( !scrollIsRootNode || !this.offset.scroll ) {
10182				this.offset.scroll = {
10183					top: this.scrollParent.scrollTop(),
10184					left: this.scrollParent.scrollLeft()
10185				};
10186			}
10187
10188			/*
10189		 * - Position constraining -
10190		 * Constrain the position to a mix of grid, containment.
10191		 */
10192
10193			// If we are not dragging yet, we won't check for options
10194			if ( constrainPosition ) {
10195				if ( this.containment ) {
10196					if ( this.relativeContainer ) {
10197						co = this.relativeContainer.offset();
10198						containment = [
10199							this.containment[ 0 ] + co.left,
10200							this.containment[ 1 ] + co.top,
10201							this.containment[ 2 ] + co.left,
10202							this.containment[ 3 ] + co.top
10203						];
10204					} else {
10205						containment = this.containment;
10206					}
10207
10208					if ( event.pageX - this.offset.click.left < containment[ 0 ] ) {
10209						pageX = containment[ 0 ] + this.offset.click.left;
10210					}
10211					if ( event.pageY - this.offset.click.top < containment[ 1 ] ) {
10212						pageY = containment[ 1 ] + this.offset.click.top;
10213					}
10214					if ( event.pageX - this.offset.click.left > containment[ 2 ] ) {
10215						pageX = containment[ 2 ] + this.offset.click.left;
10216					}
10217					if ( event.pageY - this.offset.click.top > containment[ 3 ] ) {
10218						pageY = containment[ 3 ] + this.offset.click.top;
10219					}
10220				}
10221
10222				if ( o.grid ) {
10223
10224					//Check for grid elements set to 0 to prevent divide by 0 error causing invalid
10225					// argument errors in IE (see ticket #6950)
10226					top = o.grid[ 1 ] ? this.originalPageY + Math.round( ( pageY -
10227						this.originalPageY ) / o.grid[ 1 ] ) * o.grid[ 1 ] : this.originalPageY;
10228					pageY = containment ? ( ( top - this.offset.click.top >= containment[ 1 ] ||
10229						top - this.offset.click.top > containment[ 3 ] ) ?
10230						top :
10231						( ( top - this.offset.click.top >= containment[ 1 ] ) ?
10232							top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) : top;
10233
10234					left = o.grid[ 0 ] ? this.originalPageX +
10235						Math.round( ( pageX - this.originalPageX ) / o.grid[ 0 ] ) * o.grid[ 0 ] :
10236						this.originalPageX;
10237					pageX = containment ? ( ( left - this.offset.click.left >= containment[ 0 ] ||
10238						left - this.offset.click.left > containment[ 2 ] ) ?
10239						left :
10240						( ( left - this.offset.click.left >= containment[ 0 ] ) ?
10241							left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) : left;
10242				}
10243
10244				if ( o.axis === "y" ) {
10245					pageX = this.originalPageX;
10246				}
10247
10248				if ( o.axis === "x" ) {
10249					pageY = this.originalPageY;
10250				}
10251			}
10252
10253			return {
10254				top: (
10255
10256					// The absolute mouse position
10257					pageY -
10258
10259					// Click offset (relative to the element)
10260					this.offset.click.top -
10261
10262					// Only for relative positioned nodes: Relative offset from element to offset parent
10263					this.offset.relative.top -
10264
10265					// The offsetParent's offset without borders (offset + border)
10266					this.offset.parent.top +
10267					( this.cssPosition === "fixed" ?
10268						-this.offset.scroll.top :
10269						( scrollIsRootNode ? 0 : this.offset.scroll.top ) )
10270				),
10271				left: (
10272
10273					// The absolute mouse position
10274					pageX -
10275
10276					// Click offset (relative to the element)
10277					this.offset.click.left -
10278
10279					// Only for relative positioned nodes: Relative offset from element to offset parent
10280					this.offset.relative.left -
10281
10282					// The offsetParent's offset without borders (offset + border)
10283					this.offset.parent.left +
10284					( this.cssPosition === "fixed" ?
10285						-this.offset.scroll.left :
10286						( scrollIsRootNode ? 0 : this.offset.scroll.left ) )
10287				)
10288			};
10289
10290		},
10291
10292		_clear: function() {
10293			this._removeClass( this.helper, "ui-draggable-dragging" );
10294			if ( this.helper[ 0 ] !== this.element[ 0 ] && !this.cancelHelperRemoval ) {
10295				this.helper.remove();
10296			}
10297			this.helper = null;
10298			this.cancelHelperRemoval = false;
10299			if ( this.destroyOnClear ) {
10300				this.destroy();
10301			}
10302		},
10303
10304		// From now on bulk stuff - mainly helpers
10305
10306		_trigger: function( type, event, ui ) {
10307			ui = ui || this._uiHash();
10308			$.ui.plugin.call( this, type, [ event, ui, this ], true );
10309
10310			// Absolute position and offset (see #6884 ) have to be recalculated after plugins
10311			if ( /^(drag|start|stop)/.test( type ) ) {
10312				this.positionAbs = this._convertPositionTo( "absolute" );
10313				ui.offset = this.positionAbs;
10314			}
10315			return $.Widget.prototype._trigger.call( this, type, event, ui );
10316		},
10317
10318		plugins: {},
10319
10320		_uiHash: function() {
10321			return {
10322				helper: this.helper,
10323				position: this.position,
10324				originalPosition: this.originalPosition,
10325				offset: this.positionAbs
10326			};
10327		}
10328
10329	} );
10330
10331	$.ui.plugin.add( "draggable", "connectToSortable", {
10332		start: function( event, ui, draggable ) {
10333			var uiSortable = $.extend( {}, ui, {
10334				item: draggable.element
10335			} );
10336
10337			draggable.sortables = [];
10338			$( draggable.options.connectToSortable ).each( function() {
10339				var sortable = $( this ).sortable( "instance" );
10340
10341				if ( sortable && !sortable.options.disabled ) {
10342					draggable.sortables.push( sortable );
10343
10344					// RefreshPositions is called at drag start to refresh the containerCache
10345					// which is used in drag. This ensures it's initialized and synchronized
10346					// with any changes that might have happened on the page since initialization.
10347					sortable.refreshPositions();
10348					sortable._trigger( "activate", event, uiSortable );
10349				}
10350			} );
10351		},
10352		stop: function( event, ui, draggable ) {
10353			var uiSortable = $.extend( {}, ui, {
10354				item: draggable.element
10355			} );
10356
10357			draggable.cancelHelperRemoval = false;
10358
10359			$.each( draggable.sortables, function() {
10360				var sortable = this;
10361
10362				if ( sortable.isOver ) {
10363					sortable.isOver = 0;
10364
10365					// Allow this sortable to handle removing the helper
10366					draggable.cancelHelperRemoval = true;
10367					sortable.cancelHelperRemoval = false;
10368
10369					// Use _storedCSS To restore properties in the sortable,
10370					// as this also handles revert (#9675) since the draggable
10371					// may have modified them in unexpected ways (#8809)
10372					sortable._storedCSS = {
10373						position: sortable.placeholder.css( "position" ),
10374						top: sortable.placeholder.css( "top" ),
10375						left: sortable.placeholder.css( "left" )
10376					};
10377
10378					sortable._mouseStop( event );
10379
10380					// Once drag has ended, the sortable should return to using
10381					// its original helper, not the shared helper from draggable
10382					sortable.options.helper = sortable.options._helper;
10383				} else {
10384
10385					// Prevent this Sortable from removing the helper.
10386					// However, don't set the draggable to remove the helper
10387					// either as another connected Sortable may yet handle the removal.
10388					sortable.cancelHelperRemoval = true;
10389
10390					sortable._trigger( "deactivate", event, uiSortable );
10391				}
10392			} );
10393		},
10394		drag: function( event, ui, draggable ) {
10395			$.each( draggable.sortables, function() {
10396				var innermostIntersecting = false,
10397					sortable = this;
10398
10399				// Copy over variables that sortable's _intersectsWith uses
10400				sortable.positionAbs = draggable.positionAbs;
10401				sortable.helperProportions = draggable.helperProportions;
10402				sortable.offset.click = draggable.offset.click;
10403
10404				if ( sortable._intersectsWith( sortable.containerCache ) ) {
10405					innermostIntersecting = true;
10406
10407					$.each( draggable.sortables, function() {
10408
10409						// Copy over variables that sortable's _intersectsWith uses
10410						this.positionAbs = draggable.positionAbs;
10411						this.helperProportions = draggable.helperProportions;
10412						this.offset.click = draggable.offset.click;
10413
10414						if ( this !== sortable &&
10415							this._intersectsWith( this.containerCache ) &&
10416							$.contains( sortable.element[ 0 ], this.element[ 0 ] ) ) {
10417							innermostIntersecting = false;
10418						}
10419
10420						return innermostIntersecting;
10421					} );
10422				}
10423
10424				if ( innermostIntersecting ) {
10425
10426					// If it intersects, we use a little isOver variable and set it once,
10427					// so that the move-in stuff gets fired only once.
10428					if ( !sortable.isOver ) {
10429						sortable.isOver = 1;
10430
10431						// Store draggable's parent in case we need to reappend to it later.
10432						draggable._parent = ui.helper.parent();
10433
10434						sortable.currentItem = ui.helper
10435							.appendTo( sortable.element )
10436							.data( "ui-sortable-item", true );
10437
10438						// Store helper option to later restore it
10439						sortable.options._helper = sortable.options.helper;
10440
10441						sortable.options.helper = function() {
10442							return ui.helper[ 0 ];
10443						};
10444
10445						// Fire the start events of the sortable with our passed browser event,
10446						// and our own helper (so it doesn't create a new one)
10447						event.target = sortable.currentItem[ 0 ];
10448						sortable._mouseCapture( event, true );
10449						sortable._mouseStart( event, true, true );
10450
10451						// Because the browser event is way off the new appended portlet,
10452						// modify necessary variables to reflect the changes
10453						sortable.offset.click.top = draggable.offset.click.top;
10454						sortable.offset.click.left = draggable.offset.click.left;
10455						sortable.offset.parent.left -= draggable.offset.parent.left -
10456							sortable.offset.parent.left;
10457						sortable.offset.parent.top -= draggable.offset.parent.top -
10458							sortable.offset.parent.top;
10459
10460						draggable._trigger( "toSortable", event );
10461
10462						// Inform draggable that the helper is in a valid drop zone,
10463						// used solely in the revert option to handle "valid/invalid".
10464						draggable.dropped = sortable.element;
10465
10466						// Need to refreshPositions of all sortables in the case that
10467						// adding to one sortable changes the location of the other sortables (#9675)
10468						$.each( draggable.sortables, function() {
10469							this.refreshPositions();
10470						} );
10471
10472						// Hack so receive/update callbacks work (mostly)
10473						draggable.currentItem = draggable.element;
10474						sortable.fromOutside = draggable;
10475					}
10476
10477					if ( sortable.currentItem ) {
10478						sortable._mouseDrag( event );
10479
10480						// Copy the sortable's position because the draggable's can potentially reflect
10481						// a relative position, while sortable is always absolute, which the dragged
10482						// element has now become. (#8809)
10483						ui.position = sortable.position;
10484					}
10485				} else {
10486
10487					// If it doesn't intersect with the sortable, and it intersected before,
10488					// we fake the drag stop of the sortable, but make sure it doesn't remove
10489					// the helper by using cancelHelperRemoval.
10490					if ( sortable.isOver ) {
10491
10492						sortable.isOver = 0;
10493						sortable.cancelHelperRemoval = true;
10494
10495						// Calling sortable's mouseStop would trigger a revert,
10496						// so revert must be temporarily false until after mouseStop is called.
10497						sortable.options._revert = sortable.options.revert;
10498						sortable.options.revert = false;
10499
10500						sortable._trigger( "out", event, sortable._uiHash( sortable ) );
10501						sortable._mouseStop( event, true );
10502
10503						// Restore sortable behaviors that were modfied
10504						// when the draggable entered the sortable area (#9481)
10505						sortable.options.revert = sortable.options._revert;
10506						sortable.options.helper = sortable.options._helper;
10507
10508						if ( sortable.placeholder ) {
10509							sortable.placeholder.remove();
10510						}
10511
10512						// Restore and recalculate the draggable's offset considering the sortable
10513						// may have modified them in unexpected ways. (#8809, #10669)
10514						ui.helper.appendTo( draggable._parent );
10515						draggable._refreshOffsets( event );
10516						ui.position = draggable._generatePosition( event, true );
10517
10518						draggable._trigger( "fromSortable", event );
10519
10520						// Inform draggable that the helper is no longer in a valid drop zone
10521						draggable.dropped = false;
10522
10523						// Need to refreshPositions of all sortables just in case removing
10524						// from one sortable changes the location of other sortables (#9675)
10525						$.each( draggable.sortables, function() {
10526							this.refreshPositions();
10527						} );
10528					}
10529				}
10530			} );
10531		}
10532	} );
10533
10534	$.ui.plugin.add( "draggable", "cursor", {
10535		start: function( event, ui, instance ) {
10536			var t = $( "body" ),
10537				o = instance.options;
10538
10539			if ( t.css( "cursor" ) ) {
10540				o._cursor = t.css( "cursor" );
10541			}
10542			t.css( "cursor", o.cursor );
10543		},
10544		stop: function( event, ui, instance ) {
10545			var o = instance.options;
10546			if ( o._cursor ) {
10547				$( "body" ).css( "cursor", o._cursor );
10548			}
10549		}
10550	} );
10551
10552	$.ui.plugin.add( "draggable", "opacity", {
10553		start: function( event, ui, instance ) {
10554			var t = $( ui.helper ),
10555				o = instance.options;
10556			if ( t.css( "opacity" ) ) {
10557				o._opacity = t.css( "opacity" );
10558			}
10559			t.css( "opacity", o.opacity );
10560		},
10561		stop: function( event, ui, instance ) {
10562			var o = instance.options;
10563			if ( o._opacity ) {
10564				$( ui.helper ).css( "opacity", o._opacity );
10565			}
10566		}
10567	} );
10568
10569	$.ui.plugin.add( "draggable", "scroll", {
10570		start: function( event, ui, i ) {
10571			if ( !i.scrollParentNotHidden ) {
10572				i.scrollParentNotHidden = i.helper.scrollParent( false );
10573			}
10574
10575			if ( i.scrollParentNotHidden[ 0 ] !== i.document[ 0 ] &&
10576				i.scrollParentNotHidden[ 0 ].tagName !== "HTML" ) {
10577				i.overflowOffset = i.scrollParentNotHidden.offset();
10578			}
10579		},
10580		drag: function( event, ui, i  ) {
10581
10582			var o = i.options,
10583				scrolled = false,
10584				scrollParent = i.scrollParentNotHidden[ 0 ],
10585				document = i.document[ 0 ];
10586
10587			if ( scrollParent !== document && scrollParent.tagName !== "HTML" ) {
10588				if ( !o.axis || o.axis !== "x" ) {
10589					if ( ( i.overflowOffset.top + scrollParent.offsetHeight ) - event.pageY <
10590						o.scrollSensitivity ) {
10591						scrollParent.scrollTop = scrolled = scrollParent.scrollTop + o.scrollSpeed;
10592					} else if ( event.pageY - i.overflowOffset.top < o.scrollSensitivity ) {
10593						scrollParent.scrollTop = scrolled = scrollParent.scrollTop - o.scrollSpeed;
10594					}
10595				}
10596
10597				if ( !o.axis || o.axis !== "y" ) {
10598					if ( ( i.overflowOffset.left + scrollParent.offsetWidth ) - event.pageX <
10599						o.scrollSensitivity ) {
10600						scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft + o.scrollSpeed;
10601					} else if ( event.pageX - i.overflowOffset.left < o.scrollSensitivity ) {
10602						scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft - o.scrollSpeed;
10603					}
10604				}
10605
10606			} else {
10607
10608				if ( !o.axis || o.axis !== "x" ) {
10609					if ( event.pageY - $( document ).scrollTop() < o.scrollSensitivity ) {
10610						scrolled = $( document ).scrollTop( $( document ).scrollTop() - o.scrollSpeed );
10611					} else if ( $( window ).height() - ( event.pageY - $( document ).scrollTop() ) <
10612						o.scrollSensitivity ) {
10613						scrolled = $( document ).scrollTop( $( document ).scrollTop() + o.scrollSpeed );
10614					}
10615				}
10616
10617				if ( !o.axis || o.axis !== "y" ) {
10618					if ( event.pageX - $( document ).scrollLeft() < o.scrollSensitivity ) {
10619						scrolled = $( document ).scrollLeft(
10620							$( document ).scrollLeft() - o.scrollSpeed
10621						);
10622					} else if ( $( window ).width() - ( event.pageX - $( document ).scrollLeft() ) <
10623						o.scrollSensitivity ) {
10624						scrolled = $( document ).scrollLeft(
10625							$( document ).scrollLeft() + o.scrollSpeed
10626						);
10627					}
10628				}
10629
10630			}
10631
10632			if ( scrolled !== false && $.ui.ddmanager && !o.dropBehaviour ) {
10633				$.ui.ddmanager.prepareOffsets( i, event );
10634			}
10635
10636		}
10637	} );
10638
10639	$.ui.plugin.add( "draggable", "snap", {
10640		start: function( event, ui, i ) {
10641
10642			var o = i.options;
10643
10644			i.snapElements = [];
10645
10646			$( o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap )
10647				.each( function() {
10648					var $t = $( this ),
10649						$o = $t.offset();
10650					if ( this !== i.element[ 0 ] ) {
10651						i.snapElements.push( {
10652							item: this,
10653							width: $t.outerWidth(), height: $t.outerHeight(),
10654							top: $o.top, left: $o.left
10655						} );
10656					}
10657				} );
10658
10659		},
10660		drag: function( event, ui, inst ) {
10661
10662			var ts, bs, ls, rs, l, r, t, b, i, first,
10663				o = inst.options,
10664				d = o.snapTolerance,
10665				x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
10666				y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
10667
10668			for ( i = inst.snapElements.length - 1; i >= 0; i-- ) {
10669
10670				l = inst.snapElements[ i ].left - inst.margins.left;
10671				r = l + inst.snapElements[ i ].width;
10672				t = inst.snapElements[ i ].top - inst.margins.top;
10673				b = t + inst.snapElements[ i ].height;
10674
10675				if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d ||
10676					!$.contains( inst.snapElements[ i ].item.ownerDocument,
10677						inst.snapElements[ i ].item ) ) {
10678					if ( inst.snapElements[ i ].snapping ) {
10679						if ( inst.options.snap.release ) {
10680							inst.options.snap.release.call(
10681								inst.element,
10682								event,
10683								$.extend( inst._uiHash(), { snapItem: inst.snapElements[ i ].item } )
10684							);
10685						}
10686					}
10687					inst.snapElements[ i ].snapping = false;
10688					continue;
10689				}
10690
10691				if ( o.snapMode !== "inner" ) {
10692					ts = Math.abs( t - y2 ) <= d;
10693					bs = Math.abs( b - y1 ) <= d;
10694					ls = Math.abs( l - x2 ) <= d;
10695					rs = Math.abs( r - x1 ) <= d;
10696					if ( ts ) {
10697						ui.position.top = inst._convertPositionTo( "relative", {
10698							top: t - inst.helperProportions.height,
10699							left: 0
10700						} ).top;
10701					}
10702					if ( bs ) {
10703						ui.position.top = inst._convertPositionTo( "relative", {
10704							top: b,
10705							left: 0
10706						} ).top;
10707					}
10708					if ( ls ) {
10709						ui.position.left = inst._convertPositionTo( "relative", {
10710							top: 0,
10711							left: l - inst.helperProportions.width
10712						} ).left;
10713					}
10714					if ( rs ) {
10715						ui.position.left = inst._convertPositionTo( "relative", {
10716							top: 0,
10717							left: r
10718						} ).left;
10719					}
10720				}
10721
10722				first = ( ts || bs || ls || rs );
10723
10724				if ( o.snapMode !== "outer" ) {
10725					ts = Math.abs( t - y1 ) <= d;
10726					bs = Math.abs( b - y2 ) <= d;
10727					ls = Math.abs( l - x1 ) <= d;
10728					rs = Math.abs( r - x2 ) <= d;
10729					if ( ts ) {
10730						ui.position.top = inst._convertPositionTo( "relative", {
10731							top: t,
10732							left: 0
10733						} ).top;
10734					}
10735					if ( bs ) {
10736						ui.position.top = inst._convertPositionTo( "relative", {
10737							top: b - inst.helperProportions.height,
10738							left: 0
10739						} ).top;
10740					}
10741					if ( ls ) {
10742						ui.position.left = inst._convertPositionTo( "relative", {
10743							top: 0,
10744							left: l
10745						} ).left;
10746					}
10747					if ( rs ) {
10748						ui.position.left = inst._convertPositionTo( "relative", {
10749							top: 0,
10750							left: r - inst.helperProportions.width
10751						} ).left;
10752					}
10753				}
10754
10755				if ( !inst.snapElements[ i ].snapping && ( ts || bs || ls || rs || first ) ) {
10756					if ( inst.options.snap.snap ) {
10757						inst.options.snap.snap.call(
10758							inst.element,
10759							event,
10760							$.extend( inst._uiHash(), {
10761								snapItem: inst.snapElements[ i ].item
10762							} ) );
10763					}
10764				}
10765				inst.snapElements[ i ].snapping = ( ts || bs || ls || rs || first );
10766
10767			}
10768
10769		}
10770	} );
10771
10772	$.ui.plugin.add( "draggable", "stack", {
10773		start: function( event, ui, instance ) {
10774			var min,
10775				o = instance.options,
10776				group = $.makeArray( $( o.stack ) ).sort( function( a, b ) {
10777					return ( parseInt( $( a ).css( "zIndex" ), 10 ) || 0 ) -
10778						( parseInt( $( b ).css( "zIndex" ), 10 ) || 0 );
10779				} );
10780
10781			if ( !group.length ) {
10782				return;
10783			}
10784
10785			min = parseInt( $( group[ 0 ] ).css( "zIndex" ), 10 ) || 0;
10786			$( group ).each( function( i ) {
10787				$( this ).css( "zIndex", min + i );
10788			} );
10789			this.css( "zIndex", ( min + group.length ) );
10790		}
10791	} );
10792
10793	$.ui.plugin.add( "draggable", "zIndex", {
10794		start: function( event, ui, instance ) {
10795			var t = $( ui.helper ),
10796				o = instance.options;
10797
10798			if ( t.css( "zIndex" ) ) {
10799				o._zIndex = t.css( "zIndex" );
10800			}
10801			t.css( "zIndex", o.zIndex );
10802		},
10803		stop: function( event, ui, instance ) {
10804			var o = instance.options;
10805
10806			if ( o._zIndex ) {
10807				$( ui.helper ).css( "zIndex", o._zIndex );
10808			}
10809		}
10810	} );
10811
10812	var widgetsDraggable = $.ui.draggable;
10813
10814
10815	/*!
10816 * jQuery UI Resizable 1.14.1
10817 * https://jqueryui.com
10818 *
10819 * Copyright OpenJS Foundation and other contributors
10820 * Released under the MIT license.
10821 * https://jquery.org/license
10822 */
10823
10824//>>label: Resizable
10825//>>group: Interactions
10826//>>description: Enables resize functionality for any element.
10827//>>docs: https://api.jqueryui.com/resizable/
10828//>>demos: https://jqueryui.com/resizable/
10829//>>css.structure: ../../themes/base/core.css
10830//>>css.structure: ../../themes/base/resizable.css
10831//>>css.theme: ../../themes/base/theme.css
10832
10833
10834	$.widget( "ui.resizable", $.ui.mouse, {
10835		version: "1.14.1",
10836		widgetEventPrefix: "resize",
10837		options: {
10838			alsoResize: false,
10839			animate: false,
10840			animateDuration: "slow",
10841			animateEasing: "swing",
10842			aspectRatio: false,
10843			autoHide: false,
10844			classes: {
10845				"ui-resizable-se": "ui-icon ui-icon-gripsmall-diagonal-se"
10846			},
10847			containment: false,
10848			ghost: false,
10849			grid: false,
10850			handles: "e,s,se",
10851			helper: false,
10852			maxHeight: null,
10853			maxWidth: null,
10854			minHeight: 10,
10855			minWidth: 10,
10856
10857			// See #7960
10858			zIndex: 90,
10859
10860			// Callbacks
10861			resize: null,
10862			start: null,
10863			stop: null
10864		},
10865
10866		_num: function( value ) {
10867			return parseFloat( value ) || 0;
10868		},
10869
10870		_isNumber: function( value ) {
10871			return !isNaN( parseFloat( value ) );
10872		},
10873
10874		_hasScroll: function( el, a ) {
10875
10876			var scroll,
10877				has = false,
10878				overflow = $( el ).css( "overflow" );
10879
10880			if ( overflow === "hidden" ) {
10881				return false;
10882			}
10883			if ( overflow === "scroll" ) {
10884				return true;
10885			}
10886
10887			scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop";
10888
10889			if ( el[ scroll ] > 0 ) {
10890				return true;
10891			}
10892
10893			// TODO: determine which cases actually cause this to happen
10894			// if the element doesn't have the scroll set, see if it's possible to
10895			// set the scroll
10896			try {
10897				el[ scroll ] = 1;
10898				has = ( el[ scroll ] > 0 );
10899				el[ scroll ] = 0;
10900			} catch ( e ) {
10901
10902				// `el` might be a string, then setting `scroll` will throw
10903				// an error in strict mode; ignore it.
10904			}
10905			return has;
10906		},
10907
10908		_create: function() {
10909
10910			var margins,
10911				o = this.options,
10912				that = this;
10913			this._addClass( "ui-resizable" );
10914
10915			$.extend( this, {
10916				_aspectRatio: !!( o.aspectRatio ),
10917				aspectRatio: o.aspectRatio,
10918				originalElement: this.element,
10919				_proportionallyResizeElements: [],
10920				_helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null
10921			} );
10922
10923			// Wrap the element if it cannot hold child nodes
10924			if ( this.element[ 0 ].nodeName.match( /^(canvas|textarea|input|select|button|img)$/i ) ) {
10925
10926				this.element.wrap(
10927					$( "<div class='ui-wrapper'></div>" ).css( {
10928						overflow: "hidden",
10929						position: this.element.css( "position" ),
10930						width: this.element.outerWidth(),
10931						height: this.element.outerHeight(),
10932						top: this.element.css( "top" ),
10933						left: this.element.css( "left" )
10934					} )
10935				);
10936
10937				this.element = this.element.parent().data(
10938					"ui-resizable", this.element.resizable( "instance" )
10939				);
10940
10941				this.elementIsWrapper = true;
10942
10943				margins = {
10944					marginTop: this.originalElement.css( "marginTop" ),
10945					marginRight: this.originalElement.css( "marginRight" ),
10946					marginBottom: this.originalElement.css( "marginBottom" ),
10947					marginLeft: this.originalElement.css( "marginLeft" )
10948				};
10949
10950				this.element.css( margins );
10951
10952				// Support: Safari
10953				// Prevent Safari textarea resize
10954				this.originalResizeStyle = this.originalElement.css( "resize" );
10955				this.originalElement.css( "resize", "none" );
10956
10957				this._proportionallyResizeElements.push( this.originalElement.css( {
10958					position: "static",
10959					zoom: 1,
10960					display: "block"
10961				} ) );
10962
10963				this._proportionallyResize();
10964			}
10965
10966			this._setupHandles();
10967
10968			if ( o.autoHide ) {
10969				$( this.element )
10970					.on( "mouseenter", function() {
10971						if ( o.disabled ) {
10972							return;
10973						}
10974						that._removeClass( "ui-resizable-autohide" );
10975						that._handles.show();
10976					} )
10977					.on( "mouseleave", function() {
10978						if ( o.disabled ) {
10979							return;
10980						}
10981						if ( !that.resizing ) {
10982							that._addClass( "ui-resizable-autohide" );
10983							that._handles.hide();
10984						}
10985					} );
10986			}
10987
10988			this._mouseInit();
10989		},
10990
10991		_destroy: function() {
10992
10993			this._mouseDestroy();
10994			this._addedHandles.remove();
10995
10996			var wrapper,
10997				_destroy = function( exp ) {
10998					$( exp )
10999						.removeData( "resizable" )
11000						.removeData( "ui-resizable" )
11001						.off( ".resizable" );
11002				};
11003
11004			// TODO: Unwrap at same DOM position
11005			if ( this.elementIsWrapper ) {
11006				_destroy( this.element );
11007				wrapper = this.element;
11008				this.originalElement.css( {
11009					position: wrapper.css( "position" ),
11010					width: wrapper.outerWidth(),
11011					height: wrapper.outerHeight(),
11012					top: wrapper.css( "top" ),
11013					left: wrapper.css( "left" )
11014				} ).insertAfter( wrapper );
11015				wrapper.remove();
11016			}
11017
11018			this.originalElement.css( "resize", this.originalResizeStyle );
11019			_destroy( this.originalElement );
11020
11021			return this;
11022		},
11023
11024		_setOption: function( key, value ) {
11025			this._super( key, value );
11026
11027			switch ( key ) {
11028				case "handles":
11029					this._removeHandles();
11030					this._setupHandles();
11031					break;
11032				case "aspectRatio":
11033					this._aspectRatio = !!value;
11034					break;
11035				default:
11036					break;
11037			}
11038		},
11039
11040		_setupHandles: function() {
11041			var o = this.options, handle, i, n, hname, axis, that = this;
11042			this.handles = o.handles ||
11043				( !$( ".ui-resizable-handle", this.element ).length ?
11044					"e,s,se" : {
11045						n: ".ui-resizable-n",
11046						e: ".ui-resizable-e",
11047						s: ".ui-resizable-s",
11048						w: ".ui-resizable-w",
11049						se: ".ui-resizable-se",
11050						sw: ".ui-resizable-sw",
11051						ne: ".ui-resizable-ne",
11052						nw: ".ui-resizable-nw"
11053					} );
11054
11055			this._handles = $();
11056			this._addedHandles = $();
11057			if ( this.handles.constructor === String ) {
11058
11059				if ( this.handles === "all" ) {
11060					this.handles = "n,e,s,w,se,sw,ne,nw";
11061				}
11062
11063				n = this.handles.split( "," );
11064				this.handles = {};
11065
11066				for ( i = 0; i < n.length; i++ ) {
11067
11068					handle = String.prototype.trim.call( n[ i ] );
11069					hname = "ui-resizable-" + handle;
11070					axis = $( "<div>" );
11071					this._addClass( axis, "ui-resizable-handle " + hname );
11072
11073					axis.css( { zIndex: o.zIndex } );
11074
11075					this.handles[ handle ] = ".ui-resizable-" + handle;
11076					if ( !this.element.children( this.handles[ handle ] ).length ) {
11077						this.element.append( axis );
11078						this._addedHandles = this._addedHandles.add( axis );
11079					}
11080				}
11081
11082			}
11083
11084			this._renderAxis = function( target ) {
11085
11086				var i, axis, padPos, padWrapper;
11087
11088				target = target || this.element;
11089
11090				for ( i in this.handles ) {
11091
11092					if ( this.handles[ i ].constructor === String ) {
11093						this.handles[ i ] = this.element.children( this.handles[ i ] ).first().show();
11094					} else if ( this.handles[ i ].jquery || this.handles[ i ].nodeType ) {
11095						this.handles[ i ] = $( this.handles[ i ] );
11096						this._on( this.handles[ i ], { "mousedown": that._mouseDown } );
11097					}
11098
11099					if ( this.elementIsWrapper &&
11100						this.originalElement[ 0 ]
11101							.nodeName
11102							.match( /^(textarea|input|select|button)$/i ) ) {
11103						axis = $( this.handles[ i ], this.element );
11104
11105						padWrapper = /sw|ne|nw|se|n|s/.test( i ) ?
11106							axis.outerHeight() :
11107							axis.outerWidth();
11108
11109						padPos = [ "padding",
11110							/ne|nw|n/.test( i ) ? "Top" :
11111								/se|sw|s/.test( i ) ? "Bottom" :
11112									/^e$/.test( i ) ? "Right" : "Left" ].join( "" );
11113
11114						target.css( padPos, padWrapper );
11115
11116						this._proportionallyResize();
11117					}
11118
11119					this._handles = this._handles.add( this.handles[ i ] );
11120				}
11121			};
11122
11123			// TODO: make renderAxis a prototype function
11124			this._renderAxis( this.element );
11125
11126			this._handles = this._handles.add( this.element.find( ".ui-resizable-handle" ) );
11127			this._handles.disableSelection();
11128
11129			this._handles.on( "mouseover", function() {
11130				if ( !that.resizing ) {
11131					if ( this.className ) {
11132						axis = this.className.match( /ui-resizable-(se|sw|ne|nw|n|e|s|w)/i );
11133					}
11134					that.axis = axis && axis[ 1 ] ? axis[ 1 ] : "se";
11135				}
11136			} );
11137
11138			if ( o.autoHide ) {
11139				this._handles.hide();
11140				this._addClass( "ui-resizable-autohide" );
11141			}
11142		},
11143
11144		_removeHandles: function() {
11145			this._addedHandles.remove();
11146		},
11147
11148		_mouseCapture: function( event ) {
11149			var i, handle,
11150				capture = false;
11151
11152			for ( i in this.handles ) {
11153				handle = $( this.handles[ i ] )[ 0 ];
11154				if ( handle === event.target || $.contains( handle, event.target ) ) {
11155					capture = true;
11156				}
11157			}
11158
11159			return !this.options.disabled && capture;
11160		},
11161
11162		_mouseStart: function( event ) {
11163
11164			var curleft, curtop, cursor, calculatedSize,
11165				o = this.options,
11166				el = this.element;
11167
11168			this.resizing = true;
11169
11170			this._renderProxy();
11171
11172			curleft = this._num( this.helper.css( "left" ) );
11173			curtop = this._num( this.helper.css( "top" ) );
11174
11175			if ( o.containment ) {
11176				curleft += $( o.containment ).scrollLeft() || 0;
11177				curtop += $( o.containment ).scrollTop() || 0;
11178			}
11179
11180			this.offset = this.helper.offset();
11181			this.position = { left: curleft, top: curtop };
11182
11183			if ( !this._helper ) {
11184				calculatedSize = this._calculateAdjustedElementDimensions( el );
11185			}
11186
11187			this.size = this._helper ? {
11188				width: this.helper.width(),
11189				height: this.helper.height()
11190			} : {
11191				width: calculatedSize.width,
11192				height: calculatedSize.height
11193			};
11194
11195			this.originalSize = this._helper ? {
11196				width: el.outerWidth(),
11197				height: el.outerHeight()
11198			} : {
11199				width: calculatedSize.width,
11200				height: calculatedSize.height
11201			};
11202
11203			this.sizeDiff = {
11204				width: el.outerWidth() - el.width(),
11205				height: el.outerHeight() - el.height()
11206			};
11207
11208			this.originalPosition = { left: curleft, top: curtop };
11209			this.originalMousePosition = { left: event.pageX, top: event.pageY };
11210
11211			this.aspectRatio = ( typeof o.aspectRatio === "number" ) ?
11212				o.aspectRatio :
11213				( ( this.originalSize.width / this.originalSize.height ) || 1 );
11214
11215			cursor = $( ".ui-resizable-" + this.axis ).css( "cursor" );
11216			$( "body" ).css( "cursor", cursor === "auto" ? this.axis + "-resize" : cursor );
11217
11218			this._addClass( "ui-resizable-resizing" );
11219			this._propagate( "start", event );
11220			return true;
11221		},
11222
11223		_mouseDrag: function( event ) {
11224
11225			var data, props,
11226				smp = this.originalMousePosition,
11227				a = this.axis,
11228				dx = ( event.pageX - smp.left ) || 0,
11229				dy = ( event.pageY - smp.top ) || 0,
11230				trigger = this._change[ a ];
11231
11232			this._updatePrevProperties();
11233
11234			if ( !trigger ) {
11235				return false;
11236			}
11237
11238			data = trigger.apply( this, [ event, dx, dy ] );
11239
11240			this._updateVirtualBoundaries( event.shiftKey );
11241			if ( this._aspectRatio || event.shiftKey ) {
11242				data = this._updateRatio( data, event );
11243			}
11244
11245			data = this._respectSize( data, event );
11246
11247			this._updateCache( data );
11248
11249			this._propagate( "resize", event );
11250
11251			props = this._applyChanges();
11252
11253			if ( !this._helper && this._proportionallyResizeElements.length ) {
11254				this._proportionallyResize();
11255			}
11256
11257			if ( !$.isEmptyObject( props ) ) {
11258				this._updatePrevProperties();
11259				this._trigger( "resize", event, this.ui() );
11260				this._applyChanges();
11261			}
11262
11263			return false;
11264		},
11265
11266		_mouseStop: function( event ) {
11267
11268			this.resizing = false;
11269			var pr, ista, soffseth, soffsetw, s, left, top,
11270				o = this.options, that = this;
11271
11272			if ( this._helper ) {
11273
11274				pr = this._proportionallyResizeElements;
11275				ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName );
11276				soffseth = ista && this._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height;
11277				soffsetw = ista ? 0 : that.sizeDiff.width;
11278
11279				s = {
11280					width: ( that.helper.width()  - soffsetw ),
11281					height: ( that.helper.height() - soffseth )
11282				};
11283				left = ( parseFloat( that.element.css( "left" ) ) +
11284					( that.position.left - that.originalPosition.left ) ) || null;
11285				top = ( parseFloat( that.element.css( "top" ) ) +
11286					( that.position.top - that.originalPosition.top ) ) || null;
11287
11288				if ( !o.animate ) {
11289					this.element.css( $.extend( s, { top: top, left: left } ) );
11290				}
11291
11292				that.helper.height( that.size.height );
11293				that.helper.width( that.size.width );
11294
11295				if ( this._helper && !o.animate ) {
11296					this._proportionallyResize();
11297				}
11298			}
11299
11300			$( "body" ).css( "cursor", "auto" );
11301
11302			this._removeClass( "ui-resizable-resizing" );
11303
11304			this._propagate( "stop", event );
11305
11306			if ( this._helper ) {
11307				this.helper.remove();
11308			}
11309
11310			return false;
11311
11312		},
11313
11314		_updatePrevProperties: function() {
11315			this.prevPosition = {
11316				top: this.position.top,
11317				left: this.position.left
11318			};
11319			this.prevSize = {
11320				width: this.size.width,
11321				height: this.size.height
11322			};
11323		},
11324
11325		_applyChanges: function() {
11326			var props = {};
11327
11328			if ( this.position.top !== this.prevPosition.top ) {
11329				props.top = this.position.top + "px";
11330			}
11331			if ( this.position.left !== this.prevPosition.left ) {
11332				props.left = this.position.left + "px";
11333			}
11334
11335			this.helper.css( props );
11336
11337			if ( this.size.width !== this.prevSize.width ) {
11338				props.width = this.size.width + "px";
11339				this.helper.width( props.width );
11340			}
11341			if ( this.size.height !== this.prevSize.height ) {
11342				props.height = this.size.height + "px";
11343				this.helper.height( props.height );
11344			}
11345
11346			return props;
11347		},
11348
11349		_updateVirtualBoundaries: function( forceAspectRatio ) {
11350			var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b,
11351				o = this.options;
11352
11353			b = {
11354				minWidth: this._isNumber( o.minWidth ) ? o.minWidth : 0,
11355				maxWidth: this._isNumber( o.maxWidth ) ? o.maxWidth : Infinity,
11356				minHeight: this._isNumber( o.minHeight ) ? o.minHeight : 0,
11357				maxHeight: this._isNumber( o.maxHeight ) ? o.maxHeight : Infinity
11358			};
11359
11360			if ( this._aspectRatio || forceAspectRatio ) {
11361				pMinWidth = b.minHeight * this.aspectRatio;
11362				pMinHeight = b.minWidth / this.aspectRatio;
11363				pMaxWidth = b.maxHeight * this.aspectRatio;
11364				pMaxHeight = b.maxWidth / this.aspectRatio;
11365
11366				if ( pMinWidth > b.minWidth ) {
11367					b.minWidth = pMinWidth;
11368				}
11369				if ( pMinHeight > b.minHeight ) {
11370					b.minHeight = pMinHeight;
11371				}
11372				if ( pMaxWidth < b.maxWidth ) {
11373					b.maxWidth = pMaxWidth;
11374				}
11375				if ( pMaxHeight < b.maxHeight ) {
11376					b.maxHeight = pMaxHeight;
11377				}
11378			}
11379			this._vBoundaries = b;
11380		},
11381
11382		_updateCache: function( data ) {
11383			this.offset = this.helper.offset();
11384			if ( this._isNumber( data.left ) ) {
11385				this.position.left = data.left;
11386			}
11387			if ( this._isNumber( data.top ) ) {
11388				this.position.top = data.top;
11389			}
11390			if ( this._isNumber( data.height ) ) {
11391				this.size.height = data.height;
11392			}
11393			if ( this._isNumber( data.width ) ) {
11394				this.size.width = data.width;
11395			}
11396		},
11397
11398		_updateRatio: function( data ) {
11399
11400			var cpos = this.position,
11401				csize = this.size,
11402				a = this.axis;
11403
11404			if ( this._isNumber( data.height ) ) {
11405				data.width = ( data.height * this.aspectRatio );
11406			} else if ( this._isNumber( data.width ) ) {
11407				data.height = ( data.width / this.aspectRatio );
11408			}
11409
11410			if ( a === "sw" ) {
11411				data.left = cpos.left + ( csize.width - data.width );
11412				data.top = null;
11413			}
11414			if ( a === "nw" ) {
11415				data.top = cpos.top + ( csize.height - data.height );
11416				data.left = cpos.left + ( csize.width - data.width );
11417			}
11418
11419			return data;
11420		},
11421
11422		_respectSize: function( data ) {
11423
11424			var o = this._vBoundaries,
11425				a = this.axis,
11426				ismaxw = this._isNumber( data.width ) && o.maxWidth && ( o.maxWidth < data.width ),
11427				ismaxh = this._isNumber( data.height ) && o.maxHeight && ( o.maxHeight < data.height ),
11428				isminw = this._isNumber( data.width ) && o.minWidth && ( o.minWidth > data.width ),
11429				isminh = this._isNumber( data.height ) && o.minHeight && ( o.minHeight > data.height ),
11430				dw = this.originalPosition.left + this.originalSize.width,
11431				dh = this.originalPosition.top + this.originalSize.height,
11432				cw = /sw|nw|w/.test( a ), ch = /nw|ne|n/.test( a );
11433			if ( isminw ) {
11434				data.width = o.minWidth;
11435			}
11436			if ( isminh ) {
11437				data.height = o.minHeight;
11438			}
11439			if ( ismaxw ) {
11440				data.width = o.maxWidth;
11441			}
11442			if ( ismaxh ) {
11443				data.height = o.maxHeight;
11444			}
11445
11446			if ( isminw && cw ) {
11447				data.left = dw - o.minWidth;
11448			}
11449			if ( ismaxw && cw ) {
11450				data.left = dw - o.maxWidth;
11451			}
11452			if ( isminh && ch ) {
11453				data.top = dh - o.minHeight;
11454			}
11455			if ( ismaxh && ch ) {
11456				data.top = dh - o.maxHeight;
11457			}
11458
11459			// Fixing jump error on top/left - bug #2330
11460			if ( !data.width && !data.height && !data.left && data.top ) {
11461				data.top = null;
11462			} else if ( !data.width && !data.height && !data.top && data.left ) {
11463				data.left = null;
11464			}
11465
11466			return data;
11467		},
11468
11469		_getPaddingPlusBorderDimensions: function( element ) {
11470			var i = 0,
11471				widths = [],
11472				borders = [
11473					element.css( "borderTopWidth" ),
11474					element.css( "borderRightWidth" ),
11475					element.css( "borderBottomWidth" ),
11476					element.css( "borderLeftWidth" )
11477				],
11478				paddings = [
11479					element.css( "paddingTop" ),
11480					element.css( "paddingRight" ),
11481					element.css( "paddingBottom" ),
11482					element.css( "paddingLeft" )
11483				];
11484
11485			for ( ; i < 4; i++ ) {
11486				widths[ i ] = ( parseFloat( borders[ i ] ) || 0 );
11487				widths[ i ] += ( parseFloat( paddings[ i ] ) || 0 );
11488			}
11489
11490			return {
11491				height: widths[ 0 ] + widths[ 2 ],
11492				width: widths[ 1 ] + widths[ 3 ]
11493			};
11494		},
11495
11496		_calculateAdjustedElementDimensions: function( element ) {
11497			var elWidth, elHeight, paddingBorder,
11498				ce = element.get( 0 );
11499
11500			if ( element.css( "box-sizing" ) !== "content-box" ||
11501				( !this._hasScroll( ce ) && !this._hasScroll( ce, "left" ) ) ) {
11502				return {
11503					height: parseFloat( element.css( "height" ) ),
11504					width: parseFloat( element.css( "width" ) )
11505				};
11506			}
11507
11508			// Check if CSS inline styles are set and use those (usually from previous resizes)
11509			elWidth = parseFloat( ce.style.width );
11510			elHeight = parseFloat( ce.style.height );
11511
11512			paddingBorder = this._getPaddingPlusBorderDimensions( element );
11513			elWidth = isNaN( elWidth ) ?
11514				this._getElementTheoreticalSize( element, paddingBorder, "width" ) :
11515				elWidth;
11516			elHeight = isNaN( elHeight ) ?
11517				this._getElementTheoreticalSize( element, paddingBorder, "height" ) :
11518				elHeight;
11519
11520			return {
11521				height: elHeight,
11522				width: elWidth
11523			};
11524		},
11525
11526		_getElementTheoreticalSize: function( element, extraSize, dimension ) {
11527
11528			// offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border
11529			var size = Math.max( 0, Math.ceil(
11530				element.get( 0 )[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] -
11531				extraSize[ dimension ] -
11532				0.5
11533
11534				// If offsetWidth/offsetHeight is unknown, then we can't determine theoretical size.
11535				// Use an explicit zero to avoid NaN.
11536				// See https://github.com/jquery/jquery/issues/3964
11537			) ) || 0;
11538
11539			return size;
11540		},
11541
11542		_proportionallyResize: function() {
11543
11544			if ( !this._proportionallyResizeElements.length ) {
11545				return;
11546			}
11547
11548			var prel,
11549				i = 0,
11550				element = this.helper || this.element;
11551
11552			for ( ; i < this._proportionallyResizeElements.length; i++ ) {
11553
11554				prel = this._proportionallyResizeElements[ i ];
11555
11556				// TODO: Seems like a bug to cache this.outerDimensions
11557				// considering that we are in a loop.
11558				if ( !this.outerDimensions ) {
11559					this.outerDimensions = this._getPaddingPlusBorderDimensions( prel );
11560				}
11561
11562				prel.css( {
11563					height: ( element.height() - this.outerDimensions.height ) || 0,
11564					width: ( element.width() - this.outerDimensions.width ) || 0
11565				} );
11566
11567			}
11568
11569		},
11570
11571		_renderProxy: function() {
11572
11573			var el = this.element, o = this.options;
11574			this.elementOffset = el.offset();
11575
11576			if ( this._helper ) {
11577
11578				this.helper = this.helper || $( "<div></div>" ).css( { overflow: "hidden" } );
11579
11580				this._addClass( this.helper, this._helper );
11581				this.helper.css( {
11582					width: this.element.outerWidth(),
11583					height: this.element.outerHeight(),
11584					position: "absolute",
11585					left: this.elementOffset.left + "px",
11586					top: this.elementOffset.top + "px",
11587					zIndex: ++o.zIndex //TODO: Don't modify option
11588				} );
11589
11590				this.helper
11591					.appendTo( "body" )
11592					.disableSelection();
11593
11594			} else {
11595				this.helper = this.element;
11596			}
11597
11598		},
11599
11600		_change: {
11601			e: function( event, dx ) {
11602				return { width: this.originalSize.width + dx };
11603			},
11604			w: function( event, dx ) {
11605				var cs = this.originalSize, sp = this.originalPosition;
11606				return { left: sp.left + dx, width: cs.width - dx };
11607			},
11608			n: function( event, dx, dy ) {
11609				var cs = this.originalSize, sp = this.originalPosition;
11610				return { top: sp.top + dy, height: cs.height - dy };
11611			},
11612			s: function( event, dx, dy ) {
11613				return { height: this.originalSize.height + dy };
11614			},
11615			se: function( event, dx, dy ) {
11616				return $.extend( this._change.s.apply( this, arguments ),
11617					this._change.e.apply( this, [ event, dx, dy ] ) );
11618			},
11619			sw: function( event, dx, dy ) {
11620				return $.extend( this._change.s.apply( this, arguments ),
11621					this._change.w.apply( this, [ event, dx, dy ] ) );
11622			},
11623			ne: function( event, dx, dy ) {
11624				return $.extend( this._change.n.apply( this, arguments ),
11625					this._change.e.apply( this, [ event, dx, dy ] ) );
11626			},
11627			nw: function( event, dx, dy ) {
11628				return $.extend( this._change.n.apply( this, arguments ),
11629					this._change.w.apply( this, [ event, dx, dy ] ) );
11630			}
11631		},
11632
11633		_propagate: function( n, event ) {
11634			$.ui.plugin.call( this, n, [ event, this.ui() ] );
11635			if ( n !== "resize" ) {
11636				this._trigger( n, event, this.ui() );
11637			}
11638		},
11639
11640		plugins: {},
11641
11642		ui: function() {
11643			return {
11644				originalElement: this.originalElement,
11645				element: this.element,
11646				helper: this.helper,
11647				position: this.position,
11648				size: this.size,
11649				originalSize: this.originalSize,
11650				originalPosition: this.originalPosition
11651			};
11652		}
11653
11654	} );
11655
11656	/*
11657 * Resizable Extensions
11658 */
11659
11660	$.ui.plugin.add( "resizable", "animate", {
11661
11662		stop: function( event ) {
11663			var that = $( this ).resizable( "instance" ),
11664				o = that.options,
11665				pr = that._proportionallyResizeElements,
11666				ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName ),
11667				soffseth = ista && that._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height,
11668				soffsetw = ista ? 0 : that.sizeDiff.width,
11669				style = {
11670					width: ( that.size.width - soffsetw ),
11671					height: ( that.size.height - soffseth )
11672				},
11673				left = ( parseFloat( that.element.css( "left" ) ) +
11674					( that.position.left - that.originalPosition.left ) ) || null,
11675				top = ( parseFloat( that.element.css( "top" ) ) +
11676					( that.position.top - that.originalPosition.top ) ) || null;
11677
11678			that.element.animate(
11679				$.extend( style, top && left ? { top: top, left: left } : {} ), {
11680					duration: o.animateDuration,
11681					easing: o.animateEasing,
11682					step: function() {
11683
11684						var data = {
11685							width: parseFloat( that.element.css( "width" ) ),
11686							height: parseFloat( that.element.css( "height" ) ),
11687							top: parseFloat( that.element.css( "top" ) ),
11688							left: parseFloat( that.element.css( "left" ) )
11689						};
11690
11691						if ( pr && pr.length ) {
11692							$( pr[ 0 ] ).css( { width: data.width, height: data.height } );
11693						}
11694
11695						// Propagating resize, and updating values for each animation step
11696						that._updateCache( data );
11697						that._propagate( "resize", event );
11698
11699					}
11700				}
11701			);
11702		}
11703
11704	} );
11705
11706	$.ui.plugin.add( "resizable", "containment", {
11707
11708		start: function() {
11709			var element, p, co, ch, cw, width, height,
11710				that = $( this ).resizable( "instance" ),
11711				o = that.options,
11712				el = that.element,
11713				oc = o.containment,
11714				ce = ( oc instanceof $ ) ?
11715					oc.get( 0 ) :
11716					( /parent/.test( oc ) ) ? el.parent().get( 0 ) : oc;
11717
11718			if ( !ce ) {
11719				return;
11720			}
11721
11722			that.containerElement = $( ce );
11723
11724			if ( /document/.test( oc ) || oc === document ) {
11725				that.containerOffset = {
11726					left: 0,
11727					top: 0
11728				};
11729				that.containerPosition = {
11730					left: 0,
11731					top: 0
11732				};
11733
11734				that.parentData = {
11735					element: $( document ),
11736					left: 0,
11737					top: 0,
11738					width: $( document ).width(),
11739					height: $( document ).height() || document.body.parentNode.scrollHeight
11740				};
11741			} else {
11742				element = $( ce );
11743				p = [];
11744				$( [ "Top", "Right", "Left", "Bottom" ] ).each( function( i, name ) {
11745					p[ i ] = that._num( element.css( "padding" + name ) );
11746				} );
11747
11748				that.containerOffset = element.offset();
11749				that.containerPosition = element.position();
11750				that.containerSize = {
11751					height: ( element.innerHeight() - p[ 3 ] ),
11752					width: ( element.innerWidth() - p[ 1 ] )
11753				};
11754
11755				co = that.containerOffset;
11756				ch = that.containerSize.height;
11757				cw = that.containerSize.width;
11758				width = ( that._hasScroll( ce, "left" ) ? ce.scrollWidth : cw );
11759				height = ( that._hasScroll( ce ) ? ce.scrollHeight : ch );
11760
11761				that.parentData = {
11762					element: ce,
11763					left: co.left,
11764					top: co.top,
11765					width: width,
11766					height: height
11767				};
11768			}
11769		},
11770
11771		resize: function( event ) {
11772			var woset, hoset, isParent, isOffsetRelative,
11773				that = $( this ).resizable( "instance" ),
11774				o = that.options,
11775				co = that.containerOffset,
11776				cp = that.position,
11777				pRatio = that._aspectRatio || event.shiftKey,
11778				cop = {
11779					top: 0,
11780					left: 0
11781				},
11782				ce = that.containerElement,
11783				continueResize = true;
11784
11785			if ( ce[ 0 ] !== document && ( /static/ ).test( ce.css( "position" ) ) ) {
11786				cop = co;
11787			}
11788
11789			if ( cp.left < ( that._helper ? co.left : 0 ) ) {
11790				that.size.width = that.size.width +
11791					( that._helper ?
11792						( that.position.left - co.left ) :
11793						( that.position.left - cop.left ) );
11794
11795				if ( pRatio ) {
11796					that.size.height = that.size.width / that.aspectRatio;
11797					continueResize = false;
11798				}
11799				that.position.left = o.helper ? co.left : 0;
11800			}
11801
11802			if ( cp.top < ( that._helper ? co.top : 0 ) ) {
11803				that.size.height = that.size.height +
11804					( that._helper ?
11805						( that.position.top - co.top ) :
11806						that.position.top );
11807
11808				if ( pRatio ) {
11809					that.size.width = that.size.height * that.aspectRatio;
11810					continueResize = false;
11811				}
11812				that.position.top = that._helper ? co.top : 0;
11813			}
11814
11815			isParent = that.containerElement.get( 0 ) === that.element.parent().get( 0 );
11816			isOffsetRelative = /relative|absolute/.test( that.containerElement.css( "position" ) );
11817
11818			if ( isParent && isOffsetRelative ) {
11819				that.offset.left = that.parentData.left + that.position.left;
11820				that.offset.top = that.parentData.top + that.position.top;
11821			} else {
11822				that.offset.left = that.element.offset().left;
11823				that.offset.top = that.element.offset().top;
11824			}
11825
11826			woset = Math.abs( that.sizeDiff.width +
11827				( that._helper ?
11828					that.offset.left - cop.left :
11829					( that.offset.left - co.left ) ) );
11830
11831			hoset = Math.abs( that.sizeDiff.height +
11832				( that._helper ?
11833					that.offset.top - cop.top :
11834					( that.offset.top - co.top ) ) );
11835
11836			if ( woset + that.size.width >= that.parentData.width ) {
11837				that.size.width = that.parentData.width - woset;
11838				if ( pRatio ) {
11839					that.size.height = that.size.width / that.aspectRatio;
11840					continueResize = false;
11841				}
11842			}
11843
11844			if ( hoset + that.size.height >= that.parentData.height ) {
11845				that.size.height = that.parentData.height - hoset;
11846				if ( pRatio ) {
11847					that.size.width = that.size.height * that.aspectRatio;
11848					continueResize = false;
11849				}
11850			}
11851
11852			if ( !continueResize ) {
11853				that.position.left = that.prevPosition.left;
11854				that.position.top = that.prevPosition.top;
11855				that.size.width = that.prevSize.width;
11856				that.size.height = that.prevSize.height;
11857			}
11858		},
11859
11860		stop: function() {
11861			var that = $( this ).resizable( "instance" ),
11862				o = that.options,
11863				co = that.containerOffset,
11864				cop = that.containerPosition,
11865				ce = that.containerElement,
11866				helper = $( that.helper ),
11867				ho = helper.offset(),
11868				w = helper.outerWidth() - that.sizeDiff.width,
11869				h = helper.outerHeight() - that.sizeDiff.height;
11870
11871			if ( that._helper && !o.animate && ( /relative/ ).test( ce.css( "position" ) ) ) {
11872				$( this ).css( {
11873					left: ho.left - cop.left - co.left,
11874					width: w,
11875					height: h
11876				} );
11877			}
11878
11879			if ( that._helper && !o.animate && ( /static/ ).test( ce.css( "position" ) ) ) {
11880				$( this ).css( {
11881					left: ho.left - cop.left - co.left,
11882					width: w,
11883					height: h
11884				} );
11885			}
11886		}
11887	} );
11888
11889	$.ui.plugin.add( "resizable", "alsoResize", {
11890
11891		start: function() {
11892			var that = $( this ).resizable( "instance" ),
11893				o = that.options;
11894
11895			$( o.alsoResize ).each( function() {
11896				var el = $( this ),
11897					elSize = that._calculateAdjustedElementDimensions( el );
11898
11899				el.data( "ui-resizable-alsoresize", {
11900					width: elSize.width, height: elSize.height,
11901					left: parseFloat( el.css( "left" ) ), top: parseFloat( el.css( "top" ) )
11902				} );
11903			} );
11904		},
11905
11906		resize: function( event, ui ) {
11907			var that = $( this ).resizable( "instance" ),
11908				o = that.options,
11909				os = that.originalSize,
11910				op = that.originalPosition,
11911				delta = {
11912					height: ( that.size.height - os.height ) || 0,
11913					width: ( that.size.width - os.width ) || 0,
11914					top: ( that.position.top - op.top ) || 0,
11915					left: ( that.position.left - op.left ) || 0
11916				};
11917
11918			$( o.alsoResize ).each( function() {
11919				var el = $( this ), start = $( this ).data( "ui-resizable-alsoresize" ), style = {},
11920					css = el.parents( ui.originalElement[ 0 ] ).length ?
11921						[ "width", "height" ] :
11922						[ "width", "height", "top", "left" ];
11923
11924				$.each( css, function( i, prop ) {
11925					var sum = ( start[ prop ] || 0 ) + ( delta[ prop ] || 0 );
11926					if ( sum && sum >= 0 ) {
11927						style[ prop ] = sum || null;
11928					}
11929				} );
11930
11931				el.css( style );
11932			} );
11933		},
11934
11935		stop: function() {
11936			$( this ).removeData( "ui-resizable-alsoresize" );
11937		}
11938	} );
11939
11940	$.ui.plugin.add( "resizable", "ghost", {
11941
11942		start: function() {
11943
11944			var that = $( this ).resizable( "instance" ), cs = that.size;
11945
11946			that.ghost = that.originalElement.clone();
11947			that.ghost.css( {
11948				opacity: 0.25,
11949				display: "block",
11950				position: "relative",
11951				height: cs.height,
11952				width: cs.width,
11953				margin: 0,
11954				left: 0,
11955				top: 0
11956			} );
11957
11958			that._addClass( that.ghost, "ui-resizable-ghost" );
11959
11960			// DEPRECATED
11961			// TODO: remove after 1.12
11962			if ( $.uiBackCompat === true && typeof that.options.ghost === "string" ) {
11963
11964				// Ghost option
11965				that.ghost.addClass( this.options.ghost );
11966			}
11967
11968			that.ghost.appendTo( that.helper );
11969
11970		},
11971
11972		resize: function() {
11973			var that = $( this ).resizable( "instance" );
11974			if ( that.ghost ) {
11975				that.ghost.css( {
11976					position: "relative",
11977					height: that.size.height,
11978					width: that.size.width
11979				} );
11980			}
11981		},
11982
11983		stop: function() {
11984			var that = $( this ).resizable( "instance" );
11985			if ( that.ghost && that.helper ) {
11986				that.helper.get( 0 ).removeChild( that.ghost.get( 0 ) );
11987			}
11988		}
11989
11990	} );
11991
11992	$.ui.plugin.add( "resizable", "grid", {
11993
11994		resize: function() {
11995			var outerDimensions,
11996				that = $( this ).resizable( "instance" ),
11997				o = that.options,
11998				cs = that.size,
11999				os = that.originalSize,
12000				op = that.originalPosition,
12001				a = that.axis,
12002				grid = typeof o.grid === "number" ? [ o.grid, o.grid ] : o.grid,
12003				gridX = ( grid[ 0 ] || 1 ),
12004				gridY = ( grid[ 1 ] || 1 ),
12005				ox = Math.round( ( cs.width - os.width ) / gridX ) * gridX,
12006				oy = Math.round( ( cs.height - os.height ) / gridY ) * gridY,
12007				newWidth = os.width + ox,
12008				newHeight = os.height + oy,
12009				isMaxWidth = o.maxWidth && ( o.maxWidth < newWidth ),
12010				isMaxHeight = o.maxHeight && ( o.maxHeight < newHeight ),
12011				isMinWidth = o.minWidth && ( o.minWidth > newWidth ),
12012				isMinHeight = o.minHeight && ( o.minHeight > newHeight );
12013
12014			o.grid = grid;
12015
12016			if ( isMinWidth ) {
12017				newWidth += gridX;
12018			}
12019			if ( isMinHeight ) {
12020				newHeight += gridY;
12021			}
12022			if ( isMaxWidth ) {
12023				newWidth -= gridX;
12024			}
12025			if ( isMaxHeight ) {
12026				newHeight -= gridY;
12027			}
12028
12029			if ( /^(se|s|e)$/.test( a ) ) {
12030				that.size.width = newWidth;
12031				that.size.height = newHeight;
12032			} else if ( /^(ne)$/.test( a ) ) {
12033				that.size.width = newWidth;
12034				that.size.height = newHeight;
12035				that.position.top = op.top - oy;
12036			} else if ( /^(sw)$/.test( a ) ) {
12037				that.size.width = newWidth;
12038				that.size.height = newHeight;
12039				that.position.left = op.left - ox;
12040			} else {
12041				if ( newHeight - gridY <= 0 || newWidth - gridX <= 0 ) {
12042					outerDimensions = that._getPaddingPlusBorderDimensions( this );
12043				}
12044
12045				if ( newHeight - gridY > 0 ) {
12046					that.size.height = newHeight;
12047					that.position.top = op.top - oy;
12048				} else {
12049					newHeight = gridY - outerDimensions.height;
12050					that.size.height = newHeight;
12051					that.position.top = op.top + os.height - newHeight;
12052				}
12053				if ( newWidth - gridX > 0 ) {
12054					that.size.width = newWidth;
12055					that.position.left = op.left - ox;
12056				} else {
12057					newWidth = gridX - outerDimensions.width;
12058					that.size.width = newWidth;
12059					that.position.left = op.left + os.width - newWidth;
12060				}
12061			}
12062		}
12063
12064	} );
12065
12066	var widgetsResizable = $.ui.resizable;
12067
12068
12069	/*!
12070 * jQuery UI Dialog 1.14.1
12071 * https://jqueryui.com
12072 *
12073 * Copyright OpenJS Foundation and other contributors
12074 * Released under the MIT license.
12075 * https://jquery.org/license
12076 */
12077
12078//>>label: Dialog
12079//>>group: Widgets
12080//>>description: Displays customizable dialog windows.
12081//>>docs: https://api.jqueryui.com/dialog/
12082//>>demos: https://jqueryui.com/dialog/
12083//>>css.structure: ../../themes/base/core.css
12084//>>css.structure: ../../themes/base/dialog.css
12085//>>css.theme: ../../themes/base/theme.css
12086
12087
12088	$.widget( "ui.dialog", {
12089		version: "1.14.1",
12090		options: {
12091			appendTo: "body",
12092			autoOpen: true,
12093			buttons: [],
12094			classes: {
12095				"ui-dialog": "ui-corner-all",
12096				"ui-dialog-titlebar": "ui-corner-all"
12097			},
12098			closeOnEscape: true,
12099			closeText: "Close",
12100			draggable: true,
12101			hide: null,
12102			height: "auto",
12103			maxHeight: null,
12104			maxWidth: null,
12105			minHeight: 150,
12106			minWidth: 150,
12107			modal: false,
12108			position: {
12109				my: "center",
12110				at: "center",
12111				of: window,
12112				collision: "fit",
12113
12114				// Ensure the titlebar is always visible
12115				using: function( pos ) {
12116					var topOffset = $( this ).css( pos ).offset().top;
12117					if ( topOffset < 0 ) {
12118						$( this ).css( "top", pos.top - topOffset );
12119					}
12120				}
12121			},
12122			resizable: true,
12123			show: null,
12124			title: null,
12125			uiDialogTitleHeadingLevel: 0,
12126			width: 300,
12127
12128			// Callbacks
12129			beforeClose: null,
12130			close: null,
12131			drag: null,
12132			dragStart: null,
12133			dragStop: null,
12134			focus: null,
12135			open: null,
12136			resize: null,
12137			resizeStart: null,
12138			resizeStop: null
12139		},
12140
12141		sizeRelatedOptions: {
12142			buttons: true,
12143			height: true,
12144			maxHeight: true,
12145			maxWidth: true,
12146			minHeight: true,
12147			minWidth: true,
12148			width: true
12149		},
12150
12151		resizableRelatedOptions: {
12152			maxHeight: true,
12153			maxWidth: true,
12154			minHeight: true,
12155			minWidth: true
12156		},
12157
12158		_create: function() {
12159			this.originalCss = {
12160				display: this.element[ 0 ].style.display,
12161				width: this.element[ 0 ].style.width,
12162				minHeight: this.element[ 0 ].style.minHeight,
12163				maxHeight: this.element[ 0 ].style.maxHeight,
12164				height: this.element[ 0 ].style.height
12165			};
12166			this.originalPosition = {
12167				parent: this.element.parent(),
12168				index: this.element.parent().children().index( this.element )
12169			};
12170			this.originalTitle = this.element.attr( "title" );
12171			if ( this.options.title == null && this.originalTitle != null ) {
12172				this.options.title = this.originalTitle;
12173			}
12174
12175			// Dialogs can't be disabled
12176			if ( this.options.disabled ) {
12177				this.options.disabled = false;
12178			}
12179
12180			this._createWrapper();
12181
12182			this.element
12183				.show()
12184				.removeAttr( "title" )
12185				.appendTo( this.uiDialog );
12186
12187			this._addClass( "ui-dialog-content", "ui-widget-content" );
12188
12189			this._createTitlebar();
12190			this._createButtonPane();
12191
12192			if ( this.options.draggable && $.fn.draggable ) {
12193				this._makeDraggable();
12194			}
12195			if ( this.options.resizable && $.fn.resizable ) {
12196				this._makeResizable();
12197			}
12198
12199			this._isOpen = false;
12200
12201			this._trackFocus();
12202		},
12203
12204		_init: function() {
12205			if ( this.options.autoOpen ) {
12206				this.open();
12207			}
12208		},
12209
12210		_appendTo: function() {
12211			var element = this.options.appendTo;
12212			if ( element && ( element.jquery || element.nodeType ) ) {
12213				return $( element );
12214			}
12215			return this.document.find( element || "body" ).eq( 0 );
12216		},
12217
12218		_destroy: function() {
12219			var next,
12220				originalPosition = this.originalPosition;
12221
12222			this._untrackInstance();
12223			this._destroyOverlay();
12224
12225			this.element
12226				.removeUniqueId()
12227				.css( this.originalCss )
12228
12229				// Without detaching first, the following becomes really slow
12230				.detach();
12231
12232			this.uiDialog.remove();
12233
12234			if ( this.originalTitle ) {
12235				this.element.attr( "title", this.originalTitle );
12236			}
12237
12238			next = originalPosition.parent.children().eq( originalPosition.index );
12239
12240			// Don't try to place the dialog next to itself (#8613)
12241			if ( next.length && next[ 0 ] !== this.element[ 0 ] ) {
12242				next.before( this.element );
12243			} else {
12244				originalPosition.parent.append( this.element );
12245			}
12246		},
12247
12248		widget: function() {
12249			return this.uiDialog;
12250		},
12251
12252		disable: $.noop,
12253		enable: $.noop,
12254
12255		close: function( event ) {
12256			var that = this;
12257
12258			if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) {
12259				return;
12260			}
12261
12262			this._isOpen = false;
12263			this._focusedElement = null;
12264			this._destroyOverlay();
12265			this._untrackInstance();
12266
12267			if ( !this.opener.filter( ":focusable" ).trigger( "focus" ).length ) {
12268
12269				// Hiding a focused element doesn't trigger blur in WebKit
12270				// so in case we have nothing to focus on, explicitly blur the active element
12271				// https://bugs.webkit.org/show_bug.cgi?id=47182
12272				$( this.document[ 0 ].activeElement ).trigger( "blur" );
12273			}
12274
12275			this._hide( this.uiDialog, this.options.hide, function() {
12276				that._trigger( "close", event );
12277			} );
12278		},
12279
12280		isOpen: function() {
12281			return this._isOpen;
12282		},
12283
12284		moveToTop: function() {
12285			this._moveToTop();
12286		},
12287
12288		_moveToTop: function( event, silent ) {
12289			var moved = false,
12290				zIndices = this.uiDialog.siblings( ".ui-front:visible" ).map( function() {
12291					return +$( this ).css( "z-index" );
12292				} ).get(),
12293				zIndexMax = Math.max.apply( null, zIndices );
12294
12295			if ( zIndexMax >= +this.uiDialog.css( "z-index" ) ) {
12296				this.uiDialog.css( "z-index", zIndexMax + 1 );
12297				moved = true;
12298			}
12299
12300			if ( moved && !silent ) {
12301				this._trigger( "focus", event );
12302			}
12303			return moved;
12304		},
12305
12306		open: function() {
12307			var that = this;
12308			if ( this._isOpen ) {
12309				if ( this._moveToTop() ) {
12310					this._focusTabbable();
12311				}
12312				return;
12313			}
12314
12315			this._isOpen = true;
12316			this.opener = $( this.document[ 0 ].activeElement );
12317
12318			this._size();
12319			this._position();
12320			this._createOverlay();
12321			this._moveToTop( null, true );
12322
12323			// Ensure the overlay is moved to the top with the dialog, but only when
12324			// opening. The overlay shouldn't move after the dialog is open so that
12325			// modeless dialogs opened after the modal dialog stack properly.
12326			if ( this.overlay ) {
12327				this.overlay.css( "z-index", this.uiDialog.css( "z-index" ) - 1 );
12328			}
12329
12330			this._show( this.uiDialog, this.options.show, function() {
12331				that._focusTabbable();
12332				that._trigger( "focus" );
12333			} );
12334
12335			// Track the dialog immediately upon opening in case a focus event
12336			// somehow occurs outside of the dialog before an element inside the
12337			// dialog is focused (#10152)
12338			this._makeFocusTarget();
12339
12340			this._trigger( "open" );
12341		},
12342
12343		_focusTabbable: function() {
12344
12345			// Set focus to the first match:
12346			// 1. An element that was focused previously
12347			// 2. First element inside the dialog matching [autofocus]
12348			// 3. Tabbable element inside the content element
12349			// 4. Tabbable element inside the buttonpane
12350			// 5. The close button
12351			// 6. The dialog itself
12352			var hasFocus = this._focusedElement;
12353			if ( !hasFocus ) {
12354				hasFocus = this.element.find( "[autofocus]" );
12355			}
12356			if ( !hasFocus.length ) {
12357				hasFocus = this.element.find( ":tabbable" );
12358			}
12359			if ( !hasFocus.length ) {
12360				hasFocus = this.uiDialogButtonPane.find( ":tabbable" );
12361			}
12362			if ( !hasFocus.length ) {
12363				hasFocus = this.uiDialogTitlebarClose.filter( ":tabbable" );
12364			}
12365			if ( !hasFocus.length ) {
12366				hasFocus = this.uiDialog;
12367			}
12368			hasFocus.eq( 0 ).trigger( "focus" );
12369		},
12370
12371		_restoreTabbableFocus: function() {
12372			var activeElement = this.document[ 0 ].activeElement,
12373				isActive = this.uiDialog[ 0 ] === activeElement ||
12374					$.contains( this.uiDialog[ 0 ], activeElement );
12375			if ( !isActive ) {
12376				this._focusTabbable();
12377			}
12378		},
12379
12380		_keepFocus: function( event ) {
12381			event.preventDefault();
12382			this._restoreTabbableFocus();
12383		},
12384
12385		_createWrapper: function() {
12386			this.uiDialog = $( "<div>" )
12387				.hide()
12388				.attr( {
12389
12390					// Setting tabIndex makes the div focusable
12391					tabIndex: -1,
12392					role: "dialog",
12393					"aria-modal": this.options.modal ? "true" : null
12394				} )
12395				.appendTo( this._appendTo() );
12396
12397			this._addClass( this.uiDialog, "ui-dialog", "ui-widget ui-widget-content ui-front" );
12398			this._on( this.uiDialog, {
12399				keydown: function( event ) {
12400					if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
12401						event.keyCode === $.ui.keyCode.ESCAPE ) {
12402						event.preventDefault();
12403						this.close( event );
12404						return;
12405					}
12406
12407					// Prevent tabbing out of dialogs
12408					if ( event.keyCode !== $.ui.keyCode.TAB || event.isDefaultPrevented() ) {
12409						return;
12410					}
12411					var tabbables = this.uiDialog.find( ":tabbable" ),
12412						first = tabbables.first(),
12413						last = tabbables.last();
12414
12415					if ( ( event.target === last[ 0 ] || event.target === this.uiDialog[ 0 ] ) &&
12416						!event.shiftKey ) {
12417						this._delay( function() {
12418							first.trigger( "focus" );
12419						} );
12420						event.preventDefault();
12421					} else if ( ( event.target === first[ 0 ] ||
12422						event.target === this.uiDialog[ 0 ] ) && event.shiftKey ) {
12423						this._delay( function() {
12424							last.trigger( "focus" );
12425						} );
12426						event.preventDefault();
12427					}
12428				},
12429				mousedown: function( event ) {
12430					if ( this._moveToTop( event ) ) {
12431						this._focusTabbable();
12432					}
12433				}
12434			} );
12435
12436			// We assume that any existing aria-describedby attribute means
12437			// that the dialog content is marked up properly
12438			// otherwise we brute force the content as the description
12439			if ( !this.element.find( "[aria-describedby]" ).length ) {
12440				this.uiDialog.attr( {
12441					"aria-describedby": this.element.uniqueId().attr( "id" )
12442				} );
12443			}
12444		},
12445
12446		_createTitlebar: function() {
12447			var uiDialogTitle;
12448
12449			this.uiDialogTitlebar = $( "<div>" );
12450			this._addClass( this.uiDialogTitlebar,
12451				"ui-dialog-titlebar", "ui-widget-header ui-helper-clearfix" );
12452			this._on( this.uiDialogTitlebar, {
12453				mousedown: function( event ) {
12454
12455					// Don't prevent click on close button (#8838)
12456					// Focusing a dialog that is partially scrolled out of view
12457					// causes the browser to scroll it into view, preventing the click event
12458					if ( !$( event.target ).closest( ".ui-dialog-titlebar-close" ) ) {
12459
12460						// Dialog isn't getting focus when dragging (#8063)
12461						this.uiDialog.trigger( "focus" );
12462					}
12463				}
12464			} );
12465
12466			this.uiDialogTitlebarClose = $( "<button type='button'></button>" )
12467				.button( {
12468					label: $( "<a>" ).text( this.options.closeText ).html(),
12469					icon: "ui-icon-closethick",
12470					showLabel: false
12471				} )
12472				.appendTo( this.uiDialogTitlebar );
12473
12474			this._addClass( this.uiDialogTitlebarClose, "ui-dialog-titlebar-close" );
12475			this._on( this.uiDialogTitlebarClose, {
12476				click: function( event ) {
12477					event.preventDefault();
12478					this.close( event );
12479				}
12480			} );
12481
12482			var uiDialogHeadingLevel = Number.isInteger( this.options.uiDialogTitleHeadingLevel ) &&
12483			this.options.uiDialogTitleHeadingLevel > 0 &&
12484			this.options.uiDialogTitleHeadingLevel <= 6 ?
12485				"h" + this.options.uiDialogTitleHeadingLevel : "span";
12486
12487			uiDialogTitle = $( "<" + uiDialogHeadingLevel + ">" )
12488				.uniqueId().prependTo( this.uiDialogTitlebar );
12489			this._addClass( uiDialogTitle, "ui-dialog-title" );
12490			this._title( uiDialogTitle );
12491
12492			this.uiDialogTitlebar.prependTo( this.uiDialog );
12493
12494			this.uiDialog.attr( {
12495				"aria-labelledby": uiDialogTitle.attr( "id" )
12496			} );
12497		},
12498
12499		_title: function( title ) {
12500			if ( this.options.title ) {
12501				title.text( this.options.title );
12502			} else {
12503				title.html( "&#160;" );
12504			}
12505		},
12506
12507		_createButtonPane: function() {
12508			this.uiDialogButtonPane = $( "<div>" );
12509			this._addClass( this.uiDialogButtonPane, "ui-dialog-buttonpane",
12510				"ui-widget-content ui-helper-clearfix" );
12511
12512			this.uiButtonSet = $( "<div>" )
12513				.appendTo( this.uiDialogButtonPane );
12514			this._addClass( this.uiButtonSet, "ui-dialog-buttonset" );
12515
12516			this._createButtons();
12517		},
12518
12519		_createButtons: function() {
12520			var that = this,
12521				buttons = this.options.buttons;
12522
12523			// If we already have a button pane, remove it
12524			this.uiDialogButtonPane.remove();
12525			this.uiButtonSet.empty();
12526
12527			if ( $.isEmptyObject( buttons ) || ( Array.isArray( buttons ) && !buttons.length ) ) {
12528				this._removeClass( this.uiDialog, "ui-dialog-buttons" );
12529				return;
12530			}
12531
12532			$.each( buttons, function( name, props ) {
12533				var click, buttonOptions;
12534				props = typeof props === "function" ?
12535					{ click: props, text: name } :
12536					props;
12537
12538				// Default to a non-submitting button
12539				props = $.extend( { type: "button" }, props );
12540
12541				// Change the context for the click callback to be the main element
12542				click = props.click;
12543				buttonOptions = {
12544					icon: props.icon,
12545					iconPosition: props.iconPosition,
12546					showLabel: props.showLabel,
12547
12548					// Deprecated options
12549					icons: props.icons,
12550					text: props.text
12551				};
12552
12553				delete props.click;
12554				delete props.icon;
12555				delete props.iconPosition;
12556				delete props.showLabel;
12557
12558				// Deprecated options
12559				delete props.icons;
12560				if ( typeof props.text === "boolean" ) {
12561					delete props.text;
12562				}
12563
12564				$( "<button></button>", props )
12565					.button( buttonOptions )
12566					.appendTo( that.uiButtonSet )
12567					.on( "click", function() {
12568						click.apply( that.element[ 0 ], arguments );
12569					} );
12570			} );
12571			this._addClass( this.uiDialog, "ui-dialog-buttons" );
12572			this.uiDialogButtonPane.appendTo( this.uiDialog );
12573		},
12574
12575		_makeDraggable: function() {
12576			var that = this,
12577				options = this.options;
12578
12579			function filteredUi( ui ) {
12580				return {
12581					position: ui.position,
12582					offset: ui.offset
12583				};
12584			}
12585
12586			this.uiDialog.draggable( {
12587				cancel: ".ui-dialog-content, .ui-dialog-titlebar-close",
12588				handle: ".ui-dialog-titlebar",
12589				containment: "document",
12590				start: function( event, ui ) {
12591					that._addClass( $( this ), "ui-dialog-dragging" );
12592					that._blockFrames();
12593					that._trigger( "dragStart", event, filteredUi( ui ) );
12594				},
12595				drag: function( event, ui ) {
12596					that._trigger( "drag", event, filteredUi( ui ) );
12597				},
12598				stop: function( event, ui ) {
12599					var left = ui.offset.left - that.document.scrollLeft(),
12600						top = ui.offset.top - that.document.scrollTop();
12601
12602					options.position = {
12603						my: "left top",
12604						at: "left" + ( left >= 0 ? "+" : "" ) + left + " " +
12605							"top" + ( top >= 0 ? "+" : "" ) + top,
12606						of: that.window
12607					};
12608					that._removeClass( $( this ), "ui-dialog-dragging" );
12609					that._unblockFrames();
12610					that._trigger( "dragStop", event, filteredUi( ui ) );
12611				}
12612			} );
12613		},
12614
12615		_makeResizable: function() {
12616			var that = this,
12617				options = this.options,
12618				handles = options.resizable,
12619
12620				// .ui-resizable has position: relative defined in the stylesheet
12621				// but dialogs have to use absolute or fixed positioning
12622				position = this.uiDialog.css( "position" ),
12623				resizeHandles = typeof handles === "string" ?
12624					handles :
12625					"n,e,s,w,se,sw,ne,nw";
12626
12627			function filteredUi( ui ) {
12628				return {
12629					originalPosition: ui.originalPosition,
12630					originalSize: ui.originalSize,
12631					position: ui.position,
12632					size: ui.size
12633				};
12634			}
12635
12636			this.uiDialog.resizable( {
12637				cancel: ".ui-dialog-content",
12638				containment: "document",
12639				alsoResize: this.element,
12640				maxWidth: options.maxWidth,
12641				maxHeight: options.maxHeight,
12642				minWidth: options.minWidth,
12643				minHeight: this._minHeight(),
12644				handles: resizeHandles,
12645				start: function( event, ui ) {
12646					that._addClass( $( this ), "ui-dialog-resizing" );
12647					that._blockFrames();
12648					that._trigger( "resizeStart", event, filteredUi( ui ) );
12649				},
12650				resize: function( event, ui ) {
12651					that._trigger( "resize", event, filteredUi( ui ) );
12652				},
12653				stop: function( event, ui ) {
12654					var offset = that.uiDialog.offset(),
12655						left = offset.left - that.document.scrollLeft(),
12656						top = offset.top - that.document.scrollTop();
12657
12658					options.height = that.uiDialog.height();
12659					options.width = that.uiDialog.width();
12660					options.position = {
12661						my: "left top",
12662						at: "left" + ( left >= 0 ? "+" : "" ) + left + " " +
12663							"top" + ( top >= 0 ? "+" : "" ) + top,
12664						of: that.window
12665					};
12666					that._removeClass( $( this ), "ui-dialog-resizing" );
12667					that._unblockFrames();
12668					that._trigger( "resizeStop", event, filteredUi( ui ) );
12669				}
12670			} )
12671				.css( "position", position );
12672		},
12673
12674		_trackFocus: function() {
12675			this._on( this.widget(), {
12676				focusin: function( event ) {
12677					this._makeFocusTarget();
12678					this._focusedElement = $( event.target );
12679				}
12680			} );
12681		},
12682
12683		_makeFocusTarget: function() {
12684			this._untrackInstance();
12685			this._trackingInstances().unshift( this );
12686		},
12687
12688		_untrackInstance: function() {
12689			var instances = this._trackingInstances(),
12690				exists = $.inArray( this, instances );
12691			if ( exists !== -1 ) {
12692				instances.splice( exists, 1 );
12693			}
12694		},
12695
12696		_trackingInstances: function() {
12697			var instances = this.document.data( "ui-dialog-instances" );
12698			if ( !instances ) {
12699				instances = [];
12700				this.document.data( "ui-dialog-instances", instances );
12701			}
12702			return instances;
12703		},
12704
12705		_minHeight: function() {
12706			var options = this.options;
12707
12708			return options.height === "auto" ?
12709				options.minHeight :
12710				Math.min( options.minHeight, options.height );
12711		},
12712
12713		_position: function() {
12714
12715			// Need to show the dialog to get the actual offset in the position plugin
12716			var isVisible = this.uiDialog.is( ":visible" );
12717			if ( !isVisible ) {
12718				this.uiDialog.show();
12719			}
12720			this.uiDialog.position( this.options.position );
12721			if ( !isVisible ) {
12722				this.uiDialog.hide();
12723			}
12724		},
12725
12726		_setOptions: function( options ) {
12727			var that = this,
12728				resize = false,
12729				resizableOptions = {};
12730
12731			$.each( options, function( key, value ) {
12732				that._setOption( key, value );
12733
12734				if ( key in that.sizeRelatedOptions ) {
12735					resize = true;
12736				}
12737				if ( key in that.resizableRelatedOptions ) {
12738					resizableOptions[ key ] = value;
12739				}
12740			} );
12741
12742			if ( resize ) {
12743				this._size();
12744				this._position();
12745			}
12746			if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
12747				this.uiDialog.resizable( "option", resizableOptions );
12748			}
12749		},
12750
12751		_setOption: function( key, value ) {
12752			var isDraggable, isResizable,
12753				uiDialog = this.uiDialog;
12754
12755			if ( key === "disabled" ) {
12756				return;
12757			}
12758
12759			this._super( key, value );
12760
12761			if ( key === "appendTo" ) {
12762				this.uiDialog.appendTo( this._appendTo() );
12763			}
12764
12765			if ( key === "buttons" ) {
12766				this._createButtons();
12767			}
12768
12769			if ( key === "closeText" ) {
12770				this.uiDialogTitlebarClose.button( {
12771
12772					// Ensure that we always pass a string
12773					label: $( "<a>" ).text( "" + this.options.closeText ).html()
12774				} );
12775			}
12776
12777			if ( key === "draggable" ) {
12778				isDraggable = uiDialog.is( ":data(ui-draggable)" );
12779				if ( isDraggable && !value ) {
12780					uiDialog.draggable( "destroy" );
12781				}
12782
12783				if ( !isDraggable && value ) {
12784					this._makeDraggable();
12785				}
12786			}
12787
12788			if ( key === "position" ) {
12789				this._position();
12790			}
12791
12792			if ( key === "resizable" ) {
12793
12794				// currently resizable, becoming non-resizable
12795				isResizable = uiDialog.is( ":data(ui-resizable)" );
12796				if ( isResizable && !value ) {
12797					uiDialog.resizable( "destroy" );
12798				}
12799
12800				// Currently resizable, changing handles
12801				if ( isResizable && typeof value === "string" ) {
12802					uiDialog.resizable( "option", "handles", value );
12803				}
12804
12805				// Currently non-resizable, becoming resizable
12806				if ( !isResizable && value !== false ) {
12807					this._makeResizable();
12808				}
12809			}
12810
12811			if ( key === "title" ) {
12812				this._title( this.uiDialogTitlebar.find( ".ui-dialog-title" ) );
12813			}
12814
12815			if ( key === "modal" ) {
12816				uiDialog.attr( "aria-modal", value ? "true" : null );
12817			}
12818		},
12819
12820		_size: function() {
12821
12822			// If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
12823			// divs will both have width and height set, so we need to reset them
12824			var nonContentHeight, minContentHeight, maxContentHeight,
12825				options = this.options;
12826
12827			// Reset content sizing
12828			this.element.show().css( {
12829				width: "auto",
12830				minHeight: 0,
12831				maxHeight: "none",
12832				height: 0
12833			} );
12834
12835			if ( options.minWidth > options.width ) {
12836				options.width = options.minWidth;
12837			}
12838
12839			// Reset wrapper sizing
12840			// determine the height of all the non-content elements
12841			nonContentHeight = this.uiDialog.css( {
12842				height: "auto",
12843				width: options.width
12844			} )
12845				.outerHeight();
12846			minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
12847			maxContentHeight = typeof options.maxHeight === "number" ?
12848				Math.max( 0, options.maxHeight - nonContentHeight ) :
12849				"none";
12850
12851			if ( options.height === "auto" ) {
12852				this.element.css( {
12853					minHeight: minContentHeight,
12854					maxHeight: maxContentHeight,
12855					height: "auto"
12856				} );
12857			} else {
12858				this.element.height( Math.max( 0, options.height - nonContentHeight ) );
12859			}
12860
12861			if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
12862				this.uiDialog.resizable( "option", "minHeight", this._minHeight() );
12863			}
12864		},
12865
12866		_blockFrames: function() {
12867			this.iframeBlocks = this.document.find( "iframe" ).map( function() {
12868				var iframe = $( this );
12869
12870				return $( "<div>" )
12871					.css( {
12872						position: "absolute",
12873						width: iframe.outerWidth(),
12874						height: iframe.outerHeight()
12875					} )
12876					.appendTo( iframe.parent() )
12877					.offset( iframe.offset() )[ 0 ];
12878			} );
12879		},
12880
12881		_unblockFrames: function() {
12882			if ( this.iframeBlocks ) {
12883				this.iframeBlocks.remove();
12884				delete this.iframeBlocks;
12885			}
12886		},
12887
12888		_allowInteraction: function( event ) {
12889			if ( $( event.target ).closest( ".ui-dialog" ).length ) {
12890				return true;
12891			}
12892
12893			// TODO: Remove hack when datepicker implements
12894			// the .ui-front logic (#8989)
12895			return !!$( event.target ).closest( ".ui-datepicker" ).length;
12896		},
12897
12898		_createOverlay: function() {
12899			if ( !this.options.modal ) {
12900				return;
12901			}
12902
12903			// We use a delay in case the overlay is created from an
12904			// event that we're going to be cancelling (#2804)
12905			var isOpening = true;
12906			this._delay( function() {
12907				isOpening = false;
12908			} );
12909
12910			if ( !this.document.data( "ui-dialog-overlays" ) ) {
12911
12912				// Prevent use of anchors and inputs
12913				// This doesn't use `_on()` because it is a shared event handler
12914				// across all open modal dialogs.
12915				this.document.on( "focusin.ui-dialog", function( event ) {
12916					if ( isOpening ) {
12917						return;
12918					}
12919
12920					var instance = this._trackingInstances()[ 0 ];
12921					if ( !instance._allowInteraction( event ) ) {
12922						event.preventDefault();
12923						instance._focusTabbable();
12924					}
12925				}.bind( this ) );
12926			}
12927
12928			this.overlay = $( "<div>" )
12929				.appendTo( this._appendTo() );
12930
12931			this._addClass( this.overlay, null, "ui-widget-overlay ui-front" );
12932			this._on( this.overlay, {
12933				mousedown: "_keepFocus"
12934			} );
12935			this.document.data( "ui-dialog-overlays",
12936				( this.document.data( "ui-dialog-overlays" ) || 0 ) + 1 );
12937		},
12938
12939		_destroyOverlay: function() {
12940			if ( !this.options.modal ) {
12941				return;
12942			}
12943
12944			if ( this.overlay ) {
12945				var overlays = this.document.data( "ui-dialog-overlays" ) - 1;
12946
12947				if ( !overlays ) {
12948					this.document.off( "focusin.ui-dialog" );
12949					this.document.removeData( "ui-dialog-overlays" );
12950				} else {
12951					this.document.data( "ui-dialog-overlays", overlays );
12952				}
12953
12954				this.overlay.remove();
12955				this.overlay = null;
12956			}
12957		}
12958	} );
12959
12960// DEPRECATED
12961// TODO: switch return back to widget declaration at top of file when this is removed
12962	if ( $.uiBackCompat === true ) {
12963
12964		// Backcompat for dialogClass option
12965		$.widget( "ui.dialog", $.ui.dialog, {
12966			options: {
12967				dialogClass: ""
12968			},
12969			_createWrapper: function() {
12970				this._super();
12971				this.uiDialog.addClass( this.options.dialogClass );
12972			},
12973			_setOption: function( key, value ) {
12974				if ( key === "dialogClass" ) {
12975					this.uiDialog
12976						.removeClass( this.options.dialogClass )
12977						.addClass( value );
12978				}
12979				this._superApply( arguments );
12980			}
12981		} );
12982	}
12983
12984	var widgetsDialog = $.ui.dialog;
12985
12986
12987	/*!
12988 * jQuery UI Droppable 1.14.1
12989 * https://jqueryui.com
12990 *
12991 * Copyright OpenJS Foundation and other contributors
12992 * Released under the MIT license.
12993 * https://jquery.org/license
12994 */
12995
12996//>>label: Droppable
12997//>>group: Interactions
12998//>>description: Enables drop targets for draggable elements.
12999//>>docs: https://api.jqueryui.com/droppable/
13000//>>demos: https://jqueryui.com/droppable/
13001
13002
13003	$.widget( "ui.droppable", {
13004		version: "1.14.1",
13005		widgetEventPrefix: "drop",
13006		options: {
13007			accept: "*",
13008			addClasses: true,
13009			greedy: false,
13010			scope: "default",
13011			tolerance: "intersect",
13012
13013			// Callbacks
13014			activate: null,
13015			deactivate: null,
13016			drop: null,
13017			out: null,
13018			over: null
13019		},
13020		_create: function() {
13021
13022			var proportions,
13023				o = this.options,
13024				accept = o.accept;
13025
13026			this.isover = false;
13027			this.isout = true;
13028
13029			this.accept = typeof accept === "function" ? accept : function( d ) {
13030				return d.is( accept );
13031			};
13032
13033			this.proportions = function( /* valueToWrite */ ) {
13034				if ( arguments.length ) {
13035
13036					// Store the droppable's proportions
13037					proportions = arguments[ 0 ];
13038				} else {
13039
13040					// Retrieve or derive the droppable's proportions
13041					return proportions ?
13042						proportions :
13043						proportions = {
13044							width: this.element[ 0 ].offsetWidth,
13045							height: this.element[ 0 ].offsetHeight
13046						};
13047				}
13048			};
13049
13050			this._addToManager( o.scope );
13051
13052			if ( o.addClasses ) {
13053				this._addClass( "ui-droppable" );
13054			}
13055
13056		},
13057
13058		_addToManager: function( scope ) {
13059
13060			// Add the reference and positions to the manager
13061			$.ui.ddmanager.droppables[ scope ] = $.ui.ddmanager.droppables[ scope ] || [];
13062			$.ui.ddmanager.droppables[ scope ].push( this );
13063		},
13064
13065		_splice: function( drop ) {
13066			var i = 0;
13067			for ( ; i < drop.length; i++ ) {
13068				if ( drop[ i ] === this ) {
13069					drop.splice( i, 1 );
13070				}
13071			}
13072		},
13073
13074		_destroy: function() {
13075			var drop = $.ui.ddmanager.droppables[ this.options.scope ];
13076
13077			this._splice( drop );
13078		},
13079
13080		_setOption: function( key, value ) {
13081
13082			if ( key === "accept" ) {
13083				this.accept = typeof value === "function" ? value : function( d ) {
13084					return d.is( value );
13085				};
13086			} else if ( key === "scope" ) {
13087				var drop = $.ui.ddmanager.droppables[ this.options.scope ];
13088
13089				this._splice( drop );
13090				this._addToManager( value );
13091			}
13092
13093			this._super( key, value );
13094		},
13095
13096		_activate: function( event ) {
13097			var draggable = $.ui.ddmanager.current;
13098
13099			this._addActiveClass();
13100			if ( draggable ) {
13101				this._trigger( "activate", event, this.ui( draggable ) );
13102			}
13103		},
13104
13105		_deactivate: function( event ) {
13106			var draggable = $.ui.ddmanager.current;
13107
13108			this._removeActiveClass();
13109			if ( draggable ) {
13110				this._trigger( "deactivate", event, this.ui( draggable ) );
13111			}
13112		},
13113
13114		_over: function( event ) {
13115
13116			var draggable = $.ui.ddmanager.current;
13117
13118			// Bail if draggable and droppable are same element
13119			if ( !draggable || ( draggable.currentItem ||
13120				draggable.element )[ 0 ] === this.element[ 0 ] ) {
13121				return;
13122			}
13123
13124			if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem ||
13125				draggable.element ) ) ) {
13126				this._addHoverClass();
13127				this._trigger( "over", event, this.ui( draggable ) );
13128			}
13129
13130		},
13131
13132		_out: function( event ) {
13133
13134			var draggable = $.ui.ddmanager.current;
13135
13136			// Bail if draggable and droppable are same element
13137			if ( !draggable || ( draggable.currentItem ||
13138				draggable.element )[ 0 ] === this.element[ 0 ] ) {
13139				return;
13140			}
13141
13142			if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem ||
13143				draggable.element ) ) ) {
13144				this._removeHoverClass();
13145				this._trigger( "out", event, this.ui( draggable ) );
13146			}
13147
13148		},
13149
13150		_drop: function( event, custom ) {
13151
13152			var draggable = custom || $.ui.ddmanager.current,
13153				childrenIntersection = false;
13154
13155			// Bail if draggable and droppable are same element
13156			if ( !draggable || ( draggable.currentItem ||
13157				draggable.element )[ 0 ] === this.element[ 0 ] ) {
13158				return false;
13159			}
13160
13161			this.element
13162				.find( ":data(ui-droppable)" )
13163				.not( ".ui-draggable-dragging" )
13164				.each( function() {
13165					var inst = $( this ).droppable( "instance" );
13166					if (
13167						inst.options.greedy &&
13168						!inst.options.disabled &&
13169						inst.options.scope === draggable.options.scope &&
13170						inst.accept.call(
13171							inst.element[ 0 ], ( draggable.currentItem || draggable.element )
13172						) &&
13173						$.ui.intersect(
13174							draggable,
13175							$.extend( inst, { offset: inst.element.offset() } ),
13176							inst.options.tolerance, event
13177						)
13178					) {
13179						childrenIntersection = true;
13180						return false;
13181					}
13182				} );
13183			if ( childrenIntersection ) {
13184				return false;
13185			}
13186
13187			if ( this.accept.call( this.element[ 0 ],
13188				( draggable.currentItem || draggable.element ) ) ) {
13189				this._removeActiveClass();
13190				this._removeHoverClass();
13191
13192				this._trigger( "drop", event, this.ui( draggable ) );
13193				return this.element;
13194			}
13195
13196			return false;
13197
13198		},
13199
13200		ui: function( c ) {
13201			return {
13202				draggable: ( c.currentItem || c.element ),
13203				helper: c.helper,
13204				position: c.position,
13205				offset: c.positionAbs
13206			};
13207		},
13208
13209		// Extension points just to make backcompat sane and avoid duplicating logic
13210		// TODO: Remove in 1.14 along with call to it below
13211		_addHoverClass: function() {
13212			this._addClass( "ui-droppable-hover" );
13213		},
13214
13215		_removeHoverClass: function() {
13216			this._removeClass( "ui-droppable-hover" );
13217		},
13218
13219		_addActiveClass: function() {
13220			this._addClass( "ui-droppable-active" );
13221		},
13222
13223		_removeActiveClass: function() {
13224			this._removeClass( "ui-droppable-active" );
13225		}
13226	} );
13227
13228	$.ui.intersect = ( function() {
13229		function isOverAxis( x, reference, size ) {
13230			return ( x >= reference ) && ( x < ( reference + size ) );
13231		}
13232
13233		return function( draggable, droppable, toleranceMode, event ) {
13234
13235			if ( !droppable.offset ) {
13236				return false;
13237			}
13238
13239			var x1 = ( draggable.positionAbs ||
13240					draggable.position.absolute ).left + draggable.margins.left,
13241				y1 = ( draggable.positionAbs ||
13242					draggable.position.absolute ).top + draggable.margins.top,
13243				x2 = x1 + draggable.helperProportions.width,
13244				y2 = y1 + draggable.helperProportions.height,
13245				l = droppable.offset.left,
13246				t = droppable.offset.top,
13247				r = l + droppable.proportions().width,
13248				b = t + droppable.proportions().height;
13249
13250			switch ( toleranceMode ) {
13251				case "fit":
13252					return ( l <= x1 && x2 <= r && t <= y1 && y2 <= b );
13253				case "intersect":
13254					return ( l < x1 + ( draggable.helperProportions.width / 2 ) && // Right Half
13255						x2 - ( draggable.helperProportions.width / 2 ) < r && // Left Half
13256						t < y1 + ( draggable.helperProportions.height / 2 ) && // Bottom Half
13257						y2 - ( draggable.helperProportions.height / 2 ) < b ); // Top Half
13258				case "pointer":
13259					return isOverAxis( event.pageY, t, droppable.proportions().height ) &&
13260						isOverAxis( event.pageX, l, droppable.proportions().width );
13261				case "touch":
13262					return (
13263						( y1 >= t && y1 <= b ) || // Top edge touching
13264						( y2 >= t && y2 <= b ) || // Bottom edge touching
13265						( y1 < t && y2 > b ) // Surrounded vertically
13266					) && (
13267						( x1 >= l && x1 <= r ) || // Left edge touching
13268						( x2 >= l && x2 <= r ) || // Right edge touching
13269						( x1 < l && x2 > r ) // Surrounded horizontally
13270					);
13271				default:
13272					return false;
13273			}
13274		};
13275	} )();
13276
13277	/*
13278	This manager tracks offsets of draggables and droppables
13279*/
13280	$.ui.ddmanager = {
13281		current: null,
13282		droppables: { "default": [] },
13283		prepareOffsets: function( t, event ) {
13284
13285			var i, j,
13286				m = $.ui.ddmanager.droppables[ t.options.scope ] || [],
13287				type = event ? event.type : null, // workaround for #2317
13288				list = ( t.currentItem || t.element ).find( ":data(ui-droppable)" ).addBack();
13289
13290			droppablesLoop: for ( i = 0; i < m.length; i++ ) {
13291
13292				// No disabled and non-accepted
13293				if ( m[ i ].options.disabled || ( t && !m[ i ].accept.call( m[ i ].element[ 0 ],
13294					( t.currentItem || t.element ) ) ) ) {
13295					continue;
13296				}
13297
13298				// Filter out elements in the current dragged item
13299				for ( j = 0; j < list.length; j++ ) {
13300					if ( list[ j ] === m[ i ].element[ 0 ] ) {
13301						m[ i ].proportions().height = 0;
13302						continue droppablesLoop;
13303					}
13304				}
13305
13306				m[ i ].visible = m[ i ].element.css( "display" ) !== "none";
13307				if ( !m[ i ].visible ) {
13308					continue;
13309				}
13310
13311				// Activate the droppable if used directly from draggables
13312				if ( type === "mousedown" ) {
13313					m[ i ]._activate.call( m[ i ], event );
13314				}
13315
13316				m[ i ].offset = m[ i ].element.offset();
13317				m[ i ].proportions( {
13318					width: m[ i ].element[ 0 ].offsetWidth,
13319					height: m[ i ].element[ 0 ].offsetHeight
13320				} );
13321
13322			}
13323
13324		},
13325		drop: function( draggable, event ) {
13326
13327			var dropped = false;
13328
13329			// Create a copy of the droppables in case the list changes during the drop (#9116)
13330			$.each( ( $.ui.ddmanager.droppables[ draggable.options.scope ] || [] ).slice(), function() {
13331
13332				if ( !this.options ) {
13333					return;
13334				}
13335				if ( !this.options.disabled && this.visible &&
13336					$.ui.intersect( draggable, this, this.options.tolerance, event ) ) {
13337					dropped = this._drop.call( this, event ) || dropped;
13338				}
13339
13340				if ( !this.options.disabled && this.visible && this.accept.call( this.element[ 0 ],
13341					( draggable.currentItem || draggable.element ) ) ) {
13342					this.isout = true;
13343					this.isover = false;
13344					this._deactivate.call( this, event );
13345				}
13346
13347			} );
13348			return dropped;
13349
13350		},
13351		dragStart: function( draggable, event ) {
13352
13353			// Listen for scrolling so that if the dragging causes scrolling the position of the
13354			// droppables can be recalculated (see #5003)
13355			draggable.element.parentsUntil( "body" ).on( "scroll.droppable", function() {
13356				if ( !draggable.options.refreshPositions ) {
13357					$.ui.ddmanager.prepareOffsets( draggable, event );
13358				}
13359			} );
13360		},
13361		drag: function( draggable, event ) {
13362
13363			// If you have a highly dynamic page, you might try this option. It renders positions
13364			// every time you move the mouse.
13365			if ( draggable.options.refreshPositions ) {
13366				$.ui.ddmanager.prepareOffsets( draggable, event );
13367			}
13368
13369			// Run through all droppables and check their positions based on specific tolerance options
13370			$.each( $.ui.ddmanager.droppables[ draggable.options.scope ] || [], function() {
13371
13372				if ( this.options.disabled || this.greedyChild || !this.visible ) {
13373					return;
13374				}
13375
13376				var parentInstance, scope, parent,
13377					intersects = $.ui.intersect( draggable, this, this.options.tolerance, event ),
13378					c = !intersects && this.isover ?
13379						"isout" :
13380						( intersects && !this.isover ? "isover" : null );
13381				if ( !c ) {
13382					return;
13383				}
13384
13385				if ( this.options.greedy ) {
13386
13387					// find droppable parents with same scope
13388					scope = this.options.scope;
13389					parent = this.element.parents( ":data(ui-droppable)" ).filter( function() {
13390						return $( this ).droppable( "instance" ).options.scope === scope;
13391					} );
13392
13393					if ( parent.length ) {
13394						parentInstance = $( parent[ 0 ] ).droppable( "instance" );
13395						parentInstance.greedyChild = ( c === "isover" );
13396					}
13397				}
13398
13399				// We just moved into a greedy child
13400				if ( parentInstance && c === "isover" ) {
13401					parentInstance.isover = false;
13402					parentInstance.isout = true;
13403					parentInstance._out.call( parentInstance, event );
13404				}
13405
13406				this[ c ] = true;
13407				this[ c === "isout" ? "isover" : "isout" ] = false;
13408				this[ c === "isover" ? "_over" : "_out" ].call( this, event );
13409
13410				// We just moved out of a greedy child
13411				if ( parentInstance && c === "isout" ) {
13412					parentInstance.isout = false;
13413					parentInstance.isover = true;
13414					parentInstance._over.call( parentInstance, event );
13415				}
13416			} );
13417
13418		},
13419		dragStop: function( draggable, event ) {
13420			draggable.element.parentsUntil( "body" ).off( "scroll.droppable" );
13421
13422			// Call prepareOffsets one final time since IE does not fire return scroll events when
13423			// overflow was caused by drag (see #5003)
13424			if ( !draggable.options.refreshPositions ) {
13425				$.ui.ddmanager.prepareOffsets( draggable, event );
13426			}
13427		}
13428	};
13429
13430// DEPRECATED
13431// TODO: switch return back to widget declaration at top of file when this is removed
13432	if ( $.uiBackCompat === true ) {
13433
13434		// Backcompat for activeClass and hoverClass options
13435		$.widget( "ui.droppable", $.ui.droppable, {
13436			options: {
13437				hoverClass: false,
13438				activeClass: false
13439			},
13440			_addActiveClass: function() {
13441				this._super();
13442				if ( this.options.activeClass ) {
13443					this.element.addClass( this.options.activeClass );
13444				}
13445			},
13446			_removeActiveClass: function() {
13447				this._super();
13448				if ( this.options.activeClass ) {
13449					this.element.removeClass( this.options.activeClass );
13450				}
13451			},
13452			_addHoverClass: function() {
13453				this._super();
13454				if ( this.options.hoverClass ) {
13455					this.element.addClass( this.options.hoverClass );
13456				}
13457			},
13458			_removeHoverClass: function() {
13459				this._super();
13460				if ( this.options.hoverClass ) {
13461					this.element.removeClass( this.options.hoverClass );
13462				}
13463			}
13464		} );
13465	}
13466
13467	var widgetsDroppable = $.ui.droppable;
13468
13469
13470	/*!
13471 * jQuery UI Progressbar 1.14.1
13472 * https://jqueryui.com
13473 *
13474 * Copyright OpenJS Foundation and other contributors
13475 * Released under the MIT license.
13476 * https://jquery.org/license
13477 */
13478
13479//>>label: Progressbar
13480//>>group: Widgets
13481	/* eslint-disable max-len */
13482//>>description: Displays a status indicator for loading state, standard percentage, and other progress indicators.
13483	/* eslint-enable max-len */
13484//>>docs: https://api.jqueryui.com/progressbar/
13485//>>demos: https://jqueryui.com/progressbar/
13486//>>css.structure: ../../themes/base/core.css
13487//>>css.structure: ../../themes/base/progressbar.css
13488//>>css.theme: ../../themes/base/theme.css
13489
13490
13491	var widgetsProgressbar = $.widget( "ui.progressbar", {
13492		version: "1.14.1",
13493		options: {
13494			classes: {
13495				"ui-progressbar": "ui-corner-all",
13496				"ui-progressbar-value": "ui-corner-left",
13497				"ui-progressbar-complete": "ui-corner-right"
13498			},
13499			max: 100,
13500			value: 0,
13501
13502			change: null,
13503			complete: null
13504		},
13505
13506		min: 0,
13507
13508		_create: function() {
13509
13510			// Constrain initial value
13511			this.oldValue = this.options.value = this._constrainedValue();
13512
13513			this.element.attr( {
13514
13515				// Only set static values; aria-valuenow and aria-valuemax are
13516				// set inside _refreshValue()
13517				role: "progressbar",
13518				"aria-valuemin": this.min
13519			} );
13520			this._addClass( "ui-progressbar", "ui-widget ui-widget-content" );
13521
13522			this.valueDiv = $( "<div>" ).appendTo( this.element );
13523			this._addClass( this.valueDiv, "ui-progressbar-value", "ui-widget-header" );
13524			this._refreshValue();
13525		},
13526
13527		_destroy: function() {
13528			this.element.removeAttr( "role aria-valuemin aria-valuemax aria-valuenow" );
13529
13530			this.valueDiv.remove();
13531		},
13532
13533		value: function( newValue ) {
13534			if ( newValue === undefined ) {
13535				return this.options.value;
13536			}
13537
13538			this.options.value = this._constrainedValue( newValue );
13539			this._refreshValue();
13540		},
13541
13542		_constrainedValue: function( newValue ) {
13543			if ( newValue === undefined ) {
13544				newValue = this.options.value;
13545			}
13546
13547			this.indeterminate = newValue === false;
13548
13549			// Sanitize value
13550			if ( typeof newValue !== "number" ) {
13551				newValue = 0;
13552			}
13553
13554			return this.indeterminate ? false :
13555				Math.min( this.options.max, Math.max( this.min, newValue ) );
13556		},
13557
13558		_setOptions: function( options ) {
13559
13560			// Ensure "value" option is set after other values (like max)
13561			var value = options.value;
13562			delete options.value;
13563
13564			this._super( options );
13565
13566			this.options.value = this._constrainedValue( value );
13567			this._refreshValue();
13568		},
13569
13570		_setOption: function( key, value ) {
13571			if ( key === "max" ) {
13572
13573				// Don't allow a max less than min
13574				value = Math.max( this.min, value );
13575			}
13576			this._super( key, value );
13577		},
13578
13579		_setOptionDisabled: function( value ) {
13580			this._super( value );
13581
13582			this.element.attr( "aria-disabled", value );
13583			this._toggleClass( null, "ui-state-disabled", !!value );
13584		},
13585
13586		_percentage: function() {
13587			return this.indeterminate ?
13588				100 :
13589				100 * ( this.options.value - this.min ) / ( this.options.max - this.min );
13590		},
13591
13592		_refreshValue: function() {
13593			var value = this.options.value,
13594				percentage = this._percentage();
13595
13596			this.valueDiv
13597				.toggle( this.indeterminate || value > this.min )
13598				.width( percentage.toFixed( 0 ) + "%" );
13599
13600			this
13601				._toggleClass( this.valueDiv, "ui-progressbar-complete", null,
13602					value === this.options.max )
13603				._toggleClass( "ui-progressbar-indeterminate", null, this.indeterminate );
13604
13605			if ( this.indeterminate ) {
13606				this.element.removeAttr( "aria-valuenow" );
13607				if ( !this.overlayDiv ) {
13608					this.overlayDiv = $( "<div>" ).appendTo( this.valueDiv );
13609					this._addClass( this.overlayDiv, "ui-progressbar-overlay" );
13610				}
13611			} else {
13612				this.element.attr( {
13613					"aria-valuemax": this.options.max,
13614					"aria-valuenow": value
13615				} );
13616				if ( this.overlayDiv ) {
13617					this.overlayDiv.remove();
13618					this.overlayDiv = null;
13619				}
13620			}
13621
13622			if ( this.oldValue !== value ) {
13623				this.oldValue = value;
13624				this._trigger( "change" );
13625			}
13626			if ( value === this.options.max ) {
13627				this._trigger( "complete" );
13628			}
13629		}
13630	} );
13631
13632
13633	/*!
13634 * jQuery UI Selectable 1.14.1
13635 * https://jqueryui.com
13636 *
13637 * Copyright OpenJS Foundation and other contributors
13638 * Released under the MIT license.
13639 * https://jquery.org/license
13640 */
13641
13642//>>label: Selectable
13643//>>group: Interactions
13644//>>description: Allows groups of elements to be selected with the mouse.
13645//>>docs: https://api.jqueryui.com/selectable/
13646//>>demos: https://jqueryui.com/selectable/
13647//>>css.structure: ../../themes/base/selectable.css
13648
13649
13650	var widgetsSelectable = $.widget( "ui.selectable", $.ui.mouse, {
13651		version: "1.14.1",
13652		options: {
13653			appendTo: "body",
13654			autoRefresh: true,
13655			distance: 0,
13656			filter: "*",
13657			tolerance: "touch",
13658
13659			// Callbacks
13660			selected: null,
13661			selecting: null,
13662			start: null,
13663			stop: null,
13664			unselected: null,
13665			unselecting: null
13666		},
13667		_create: function() {
13668			var that = this;
13669
13670			this._addClass( "ui-selectable" );
13671
13672			this.dragged = false;
13673
13674			// Cache selectee children based on filter
13675			this.refresh = function() {
13676				that.elementPos = $( that.element[ 0 ] ).offset();
13677				that.selectees = $( that.options.filter, that.element[ 0 ] );
13678				that._addClass( that.selectees, "ui-selectee" );
13679				that.selectees.each( function() {
13680					var $this = $( this ),
13681						selecteeOffset = $this.offset(),
13682						pos = {
13683							left: selecteeOffset.left - that.elementPos.left,
13684							top: selecteeOffset.top - that.elementPos.top
13685						};
13686					$.data( this, "selectable-item", {
13687						element: this,
13688						$element: $this,
13689						left: pos.left,
13690						top: pos.top,
13691						right: pos.left + $this.outerWidth(),
13692						bottom: pos.top + $this.outerHeight(),
13693						startselected: false,
13694						selected: $this.hasClass( "ui-selected" ),
13695						selecting: $this.hasClass( "ui-selecting" ),
13696						unselecting: $this.hasClass( "ui-unselecting" )
13697					} );
13698				} );
13699			};
13700			this.refresh();
13701
13702			this._mouseInit();
13703
13704			this.helper = $( "<div>" );
13705			this._addClass( this.helper, "ui-selectable-helper" );
13706		},
13707
13708		_destroy: function() {
13709			this.selectees.removeData( "selectable-item" );
13710			this._mouseDestroy();
13711		},
13712
13713		_mouseStart: function( event ) {
13714			var that = this,
13715				options = this.options;
13716
13717			this.opos = [ event.pageX, event.pageY ];
13718			this.elementPos = $( this.element[ 0 ] ).offset();
13719
13720			if ( this.options.disabled ) {
13721				return;
13722			}
13723
13724			this.selectees = $( options.filter, this.element[ 0 ] );
13725
13726			this._trigger( "start", event );
13727
13728			$( options.appendTo ).append( this.helper );
13729
13730			// position helper (lasso)
13731			this.helper.css( {
13732				"left": event.pageX,
13733				"top": event.pageY,
13734				"width": 0,
13735				"height": 0
13736			} );
13737
13738			if ( options.autoRefresh ) {
13739				this.refresh();
13740			}
13741
13742			this.selectees.filter( ".ui-selected" ).each( function() {
13743				var selectee = $.data( this, "selectable-item" );
13744				selectee.startselected = true;
13745				if ( !event.metaKey && !event.ctrlKey ) {
13746					that._removeClass( selectee.$element, "ui-selected" );
13747					selectee.selected = false;
13748					that._addClass( selectee.$element, "ui-unselecting" );
13749					selectee.unselecting = true;
13750
13751					// selectable UNSELECTING callback
13752					that._trigger( "unselecting", event, {
13753						unselecting: selectee.element
13754					} );
13755				}
13756			} );
13757
13758			$( event.target ).parents().addBack().each( function() {
13759				var doSelect,
13760					selectee = $.data( this, "selectable-item" );
13761				if ( selectee ) {
13762					doSelect = ( !event.metaKey && !event.ctrlKey ) ||
13763						!selectee.$element.hasClass( "ui-selected" );
13764					that._removeClass( selectee.$element, doSelect ? "ui-unselecting" : "ui-selected" )
13765						._addClass( selectee.$element, doSelect ? "ui-selecting" : "ui-unselecting" );
13766					selectee.unselecting = !doSelect;
13767					selectee.selecting = doSelect;
13768					selectee.selected = doSelect;
13769
13770					// selectable (UN)SELECTING callback
13771					if ( doSelect ) {
13772						that._trigger( "selecting", event, {
13773							selecting: selectee.element
13774						} );
13775					} else {
13776						that._trigger( "unselecting", event, {
13777							unselecting: selectee.element
13778						} );
13779					}
13780					return false;
13781				}
13782			} );
13783
13784		},
13785
13786		_mouseDrag: function( event ) {
13787
13788			this.dragged = true;
13789
13790			if ( this.options.disabled ) {
13791				return;
13792			}
13793
13794			var tmp,
13795				that = this,
13796				options = this.options,
13797				x1 = this.opos[ 0 ],
13798				y1 = this.opos[ 1 ],
13799				x2 = event.pageX,
13800				y2 = event.pageY;
13801
13802			if ( x1 > x2 ) {
13803				tmp = x2; x2 = x1; x1 = tmp;
13804			}
13805			if ( y1 > y2 ) {
13806				tmp = y2; y2 = y1; y1 = tmp;
13807			}
13808			this.helper.css( { left: x1, top: y1, width: x2 - x1, height: y2 - y1 } );
13809
13810			this.selectees.each( function() {
13811				var selectee = $.data( this, "selectable-item" ),
13812					hit = false,
13813					offset = {};
13814
13815				//prevent helper from being selected if appendTo: selectable
13816				if ( !selectee || selectee.element === that.element[ 0 ] ) {
13817					return;
13818				}
13819
13820				offset.left   = selectee.left   + that.elementPos.left;
13821				offset.right  = selectee.right  + that.elementPos.left;
13822				offset.top    = selectee.top    + that.elementPos.top;
13823				offset.bottom = selectee.bottom + that.elementPos.top;
13824
13825				if ( options.tolerance === "touch" ) {
13826					hit = ( !( offset.left > x2 || offset.right < x1 || offset.top > y2 ||
13827						offset.bottom < y1 ) );
13828				} else if ( options.tolerance === "fit" ) {
13829					hit = ( offset.left > x1 && offset.right < x2 && offset.top > y1 &&
13830						offset.bottom < y2 );
13831				}
13832
13833				if ( hit ) {
13834
13835					// SELECT
13836					if ( selectee.selected ) {
13837						that._removeClass( selectee.$element, "ui-selected" );
13838						selectee.selected = false;
13839					}
13840					if ( selectee.unselecting ) {
13841						that._removeClass( selectee.$element, "ui-unselecting" );
13842						selectee.unselecting = false;
13843					}
13844					if ( !selectee.selecting ) {
13845						that._addClass( selectee.$element, "ui-selecting" );
13846						selectee.selecting = true;
13847
13848						// selectable SELECTING callback
13849						that._trigger( "selecting", event, {
13850							selecting: selectee.element
13851						} );
13852					}
13853				} else {
13854
13855					// UNSELECT
13856					if ( selectee.selecting ) {
13857						if ( ( event.metaKey || event.ctrlKey ) && selectee.startselected ) {
13858							that._removeClass( selectee.$element, "ui-selecting" );
13859							selectee.selecting = false;
13860							that._addClass( selectee.$element, "ui-selected" );
13861							selectee.selected = true;
13862						} else {
13863							that._removeClass( selectee.$element, "ui-selecting" );
13864							selectee.selecting = false;
13865							if ( selectee.startselected ) {
13866								that._addClass( selectee.$element, "ui-unselecting" );
13867								selectee.unselecting = true;
13868							}
13869
13870							// selectable UNSELECTING callback
13871							that._trigger( "unselecting", event, {
13872								unselecting: selectee.element
13873							} );
13874						}
13875					}
13876					if ( selectee.selected ) {
13877						if ( !event.metaKey && !event.ctrlKey && !selectee.startselected ) {
13878							that._removeClass( selectee.$element, "ui-selected" );
13879							selectee.selected = false;
13880
13881							that._addClass( selectee.$element, "ui-unselecting" );
13882							selectee.unselecting = true;
13883
13884							// selectable UNSELECTING callback
13885							that._trigger( "unselecting", event, {
13886								unselecting: selectee.element
13887							} );
13888						}
13889					}
13890				}
13891			} );
13892
13893			return false;
13894		},
13895
13896		_mouseStop: function( event ) {
13897			var that = this;
13898
13899			this.dragged = false;
13900
13901			$( ".ui-unselecting", this.element[ 0 ] ).each( function() {
13902				var selectee = $.data( this, "selectable-item" );
13903				that._removeClass( selectee.$element, "ui-unselecting" );
13904				selectee.unselecting = false;
13905				selectee.startselected = false;
13906				that._trigger( "unselected", event, {
13907					unselected: selectee.element
13908				} );
13909			} );
13910			$( ".ui-selecting", this.element[ 0 ] ).each( function() {
13911				var selectee = $.data( this, "selectable-item" );
13912				that._removeClass( selectee.$element, "ui-selecting" )
13913					._addClass( selectee.$element, "ui-selected" );
13914				selectee.selecting = false;
13915				selectee.selected = true;
13916				selectee.startselected = true;
13917				that._trigger( "selected", event, {
13918					selected: selectee.element
13919				} );
13920			} );
13921			this._trigger( "stop", event );
13922
13923			this.helper.remove();
13924
13925			return false;
13926		}
13927
13928	} );
13929
13930
13931	/*!
13932 * jQuery UI Selectmenu 1.14.1
13933 * https://jqueryui.com
13934 *
13935 * Copyright OpenJS Foundation and other contributors
13936 * Released under the MIT license.
13937 * https://jquery.org/license
13938 */
13939
13940//>>label: Selectmenu
13941//>>group: Widgets
13942	/* eslint-disable max-len */
13943//>>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.
13944	/* eslint-enable max-len */
13945//>>docs: https://api.jqueryui.com/selectmenu/
13946//>>demos: https://jqueryui.com/selectmenu/
13947//>>css.structure: ../../themes/base/core.css
13948//>>css.structure: ../../themes/base/selectmenu.css, ../../themes/base/button.css
13949//>>css.theme: ../../themes/base/theme.css
13950
13951
13952	var widgetsSelectmenu = $.widget( "ui.selectmenu", [ $.ui.formResetMixin, {
13953		version: "1.14.1",
13954		defaultElement: "<select>",
13955		options: {
13956			appendTo: null,
13957			classes: {
13958				"ui-selectmenu-button-open": "ui-corner-top",
13959				"ui-selectmenu-button-closed": "ui-corner-all"
13960			},
13961			disabled: null,
13962			icons: {
13963				button: "ui-icon-triangle-1-s"
13964			},
13965			position: {
13966				my: "left top",
13967				at: "left bottom",
13968				collision: "none"
13969			},
13970			width: false,
13971
13972			// Callbacks
13973			change: null,
13974			close: null,
13975			focus: null,
13976			open: null,
13977			select: null
13978		},
13979
13980		_create: function() {
13981			var selectmenuId = this.element.uniqueId().attr( "id" );
13982			this.ids = {
13983				element: selectmenuId,
13984				button: selectmenuId + "-button",
13985				menu: selectmenuId + "-menu"
13986			};
13987
13988			this._drawButton();
13989			this._drawMenu();
13990			this._bindFormResetHandler();
13991
13992			this._rendered = false;
13993			this.menuItems = $();
13994		},
13995
13996		_drawButton: function() {
13997			var icon,
13998				that = this,
13999				item = this._parseOption(
14000					this.element.find( "option:selected" ),
14001					this.element[ 0 ].selectedIndex
14002				);
14003
14004			// Associate existing label with the new button
14005			this.labels = this.element.labels().attr( "for", this.ids.button );
14006			this._on( this.labels, {
14007				click: function( event ) {
14008					this.button.trigger( "focus" );
14009					event.preventDefault();
14010				}
14011			} );
14012
14013			// Hide original select element
14014			this.element.hide();
14015
14016			// Create button
14017			this.button = $( "<span>", {
14018				tabindex: this.options.disabled ? -1 : 0,
14019				id: this.ids.button,
14020				role: "combobox",
14021				"aria-expanded": "false",
14022				"aria-autocomplete": "list",
14023				"aria-owns": this.ids.menu,
14024				"aria-haspopup": "true",
14025				title: this.element.attr( "title" )
14026			} )
14027				.insertAfter( this.element );
14028
14029			this._addClass( this.button, "ui-selectmenu-button ui-selectmenu-button-closed",
14030				"ui-button ui-widget" );
14031
14032			icon = $( "<span>" ).appendTo( this.button );
14033			this._addClass( icon, "ui-selectmenu-icon", "ui-icon " + this.options.icons.button );
14034			this.buttonItem = this._renderButtonItem( item )
14035				.appendTo( this.button );
14036
14037			if ( this.options.width !== false ) {
14038				this._resizeButton();
14039			}
14040
14041			this._on( this.button, this._buttonEvents );
14042			this.button.one( "focusin", function() {
14043
14044				// Delay rendering the menu items until the button receives focus.
14045				// The menu may have already been rendered via a programmatic open.
14046				if ( !that._rendered ) {
14047					that._refreshMenu();
14048				}
14049			} );
14050		},
14051
14052		_drawMenu: function() {
14053			var that = this;
14054
14055			// Create menu
14056			this.menu = $( "<ul>", {
14057				"aria-hidden": "true",
14058				"aria-labelledby": this.ids.button,
14059				id: this.ids.menu
14060			} );
14061
14062			// Wrap menu
14063			this.menuWrap = $( "<div>" ).append( this.menu );
14064			this._addClass( this.menuWrap, "ui-selectmenu-menu", "ui-front" );
14065			this.menuWrap.appendTo( this._appendTo() );
14066
14067			// Initialize menu widget
14068			this.menuInstance = this.menu
14069				.menu( {
14070					classes: {
14071						"ui-menu": "ui-corner-bottom"
14072					},
14073					role: "listbox",
14074					select: function( event, ui ) {
14075						event.preventDefault();
14076						that._select( ui.item.data( "ui-selectmenu-item" ), event );
14077					},
14078					focus: function( event, ui ) {
14079						var item = ui.item.data( "ui-selectmenu-item" );
14080
14081						// Prevent inital focus from firing and check if its a newly focused item
14082						if ( that.focusIndex != null && item.index !== that.focusIndex ) {
14083							that._trigger( "focus", event, { item: item } );
14084							if ( !that.isOpen ) {
14085								that._select( item, event );
14086							}
14087						}
14088						that.focusIndex = item.index;
14089
14090						that.button.attr( "aria-activedescendant",
14091							that.menuItems.eq( item.index ).attr( "id" ) );
14092					}
14093				} )
14094				.menu( "instance" );
14095
14096			// Don't close the menu on mouseleave
14097			this.menuInstance._off( this.menu, "mouseleave" );
14098
14099			// Cancel the menu's collapseAll on document click
14100			this.menuInstance._closeOnDocumentClick = function() {
14101				return false;
14102			};
14103
14104			// Selects often contain empty items, but never contain dividers
14105			this.menuInstance._isDivider = function() {
14106				return false;
14107			};
14108		},
14109
14110		refresh: function() {
14111			this._refreshMenu();
14112			this.buttonItem.replaceWith(
14113				this.buttonItem = this._renderButtonItem(
14114
14115					// Fall back to an empty object in case there are no options
14116					this._getSelectedItem().data( "ui-selectmenu-item" ) || {}
14117				)
14118			);
14119			if ( this.options.width === null ) {
14120				this._resizeButton();
14121			}
14122		},
14123
14124		_refreshMenu: function() {
14125			var item,
14126				options = this.element.find( "option" );
14127
14128			this.menu.empty();
14129
14130			this._parseOptions( options );
14131			this._renderMenu( this.menu, this.items );
14132
14133			this.menuInstance.refresh();
14134			this.menuItems = this.menu.find( "li" )
14135				.not( ".ui-selectmenu-optgroup" )
14136				.find( ".ui-menu-item-wrapper" );
14137
14138			this._rendered = true;
14139
14140			if ( !options.length ) {
14141				return;
14142			}
14143
14144			item = this._getSelectedItem();
14145
14146			// Update the menu to have the correct item focused
14147			this.menuInstance.focus( null, item );
14148			this._setAria( item.data( "ui-selectmenu-item" ) );
14149
14150			// Set disabled state
14151			this._setOption( "disabled", this.element.prop( "disabled" ) );
14152		},
14153
14154		open: function( event ) {
14155			if ( this.options.disabled ) {
14156				return;
14157			}
14158
14159			// If this is the first time the menu is being opened, render the items
14160			if ( !this._rendered ) {
14161				this._refreshMenu();
14162			} else {
14163
14164				// Menu clears focus on close, reset focus to selected item
14165				this._removeClass( this.menu.find( ".ui-state-active" ), null, "ui-state-active" );
14166				this.menuInstance.focus( null, this._getSelectedItem() );
14167			}
14168
14169			// If there are no options, don't open the menu
14170			if ( !this.menuItems.length ) {
14171				return;
14172			}
14173
14174			this.isOpen = true;
14175			this._toggleAttr();
14176			this._resizeMenu();
14177			this._position();
14178
14179			this._on( this.document, this._documentClick );
14180
14181			this._trigger( "open", event );
14182		},
14183
14184		_position: function() {
14185			this.menuWrap.position( $.extend( { of: this.button }, this.options.position ) );
14186		},
14187
14188		close: function( event ) {
14189			if ( !this.isOpen ) {
14190				return;
14191			}
14192
14193			this.isOpen = false;
14194			this._toggleAttr();
14195
14196			this.range = null;
14197			this._off( this.document );
14198
14199			this._trigger( "close", event );
14200		},
14201
14202		widget: function() {
14203			return this.button;
14204		},
14205
14206		menuWidget: function() {
14207			return this.menu;
14208		},
14209
14210		_renderButtonItem: function( item ) {
14211			var buttonItem = $( "<span>" );
14212
14213			this._setText( buttonItem, item.label );
14214			this._addClass( buttonItem, "ui-selectmenu-text" );
14215
14216			return buttonItem;
14217		},
14218
14219		_renderMenu: function( ul, items ) {
14220			var that = this,
14221				currentOptgroup = "";
14222
14223			$.each( items, function( index, item ) {
14224				var li;
14225
14226				if ( item.optgroup !== currentOptgroup ) {
14227					li = $( "<li>", {
14228						text: item.optgroup
14229					} );
14230					that._addClass( li, "ui-selectmenu-optgroup", "ui-menu-divider" +
14231						( item.element.parent( "optgroup" ).prop( "disabled" ) ?
14232							" ui-state-disabled" :
14233							"" ) );
14234
14235					li.appendTo( ul );
14236
14237					currentOptgroup = item.optgroup;
14238				}
14239
14240				that._renderItemData( ul, item );
14241			} );
14242		},
14243
14244		_renderItemData: function( ul, item ) {
14245			return this._renderItem( ul, item ).data( "ui-selectmenu-item", item );
14246		},
14247
14248		_renderItem: function( ul, item ) {
14249			var li = $( "<li>" ),
14250				wrapper = $( "<div>", {
14251					title: item.element.attr( "title" )
14252				} );
14253
14254			if ( item.disabled ) {
14255				this._addClass( li, null, "ui-state-disabled" );
14256			}
14257
14258			if ( item.hidden ) {
14259				li.prop( "hidden", true );
14260			} else {
14261				this._setText( wrapper, item.label );
14262			}
14263
14264			return li.append( wrapper ).appendTo( ul );
14265		},
14266
14267		_setText: function( element, value ) {
14268			if ( value ) {
14269				element.text( value );
14270			} else {
14271				element.html( "&#160;" );
14272			}
14273		},
14274
14275		_move: function( direction, event ) {
14276			var item, next,
14277				filter = ".ui-menu-item";
14278
14279			if ( this.isOpen ) {
14280				item = this.menuItems.eq( this.focusIndex ).parent( "li" );
14281			} else {
14282				item = this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( "li" );
14283				filter += ":not(.ui-state-disabled)";
14284			}
14285
14286			if ( direction === "first" || direction === "last" ) {
14287				next = item[ direction === "first" ? "prevAll" : "nextAll" ]( filter ).eq( -1 );
14288			} else {
14289				next = item[ direction + "All" ]( filter ).eq( 0 );
14290			}
14291
14292			if ( next.length ) {
14293				this.menuInstance.focus( event, next );
14294			}
14295		},
14296
14297		_getSelectedItem: function() {
14298			return this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( "li" );
14299		},
14300
14301		_toggle: function( event ) {
14302			this[ this.isOpen ? "close" : "open" ]( event );
14303		},
14304
14305		_setSelection: function() {
14306			var selection;
14307
14308			if ( !this.range ) {
14309				return;
14310			}
14311
14312			selection = window.getSelection();
14313			selection.removeAllRanges();
14314			selection.addRange( this.range );
14315		},
14316
14317		_documentClick: {
14318			mousedown: function( event ) {
14319				if ( !this.isOpen ) {
14320					return;
14321				}
14322
14323				if ( !$( event.target ).closest( ".ui-selectmenu-menu, #" +
14324					CSS.escape( this.ids.button ) ).length ) {
14325					this.close( event );
14326				}
14327			}
14328		},
14329
14330		_buttonEvents: {
14331
14332			// Prevent text selection from being reset when interacting with the selectmenu (#10144)
14333			mousedown: function() {
14334				var selection = window.getSelection();
14335				if ( selection.rangeCount ) {
14336					this.range = selection.getRangeAt( 0 );
14337				}
14338			},
14339
14340			click: function( event ) {
14341				this._setSelection();
14342				this._toggle( event );
14343			},
14344
14345			keydown: function( event ) {
14346				var preventDefault = true;
14347				switch ( event.keyCode ) {
14348					case $.ui.keyCode.TAB:
14349					case $.ui.keyCode.ESCAPE:
14350						this.close( event );
14351						preventDefault = false;
14352						break;
14353					case $.ui.keyCode.ENTER:
14354						if ( this.isOpen ) {
14355							this._selectFocusedItem( event );
14356						}
14357						break;
14358					case $.ui.keyCode.UP:
14359						if ( event.altKey ) {
14360							this._toggle( event );
14361						} else {
14362							this._move( "prev", event );
14363						}
14364						break;
14365					case $.ui.keyCode.DOWN:
14366						if ( event.altKey ) {
14367							this._toggle( event );
14368						} else {
14369							this._move( "next", event );
14370						}
14371						break;
14372					case $.ui.keyCode.SPACE:
14373						if ( this.isOpen ) {
14374							this._selectFocusedItem( event );
14375						} else {
14376							this._toggle( event );
14377						}
14378						break;
14379					case $.ui.keyCode.LEFT:
14380						this._move( "prev", event );
14381						break;
14382					case $.ui.keyCode.RIGHT:
14383						this._move( "next", event );
14384						break;
14385					case $.ui.keyCode.HOME:
14386					case $.ui.keyCode.PAGE_UP:
14387						this._move( "first", event );
14388						break;
14389					case $.ui.keyCode.END:
14390					case $.ui.keyCode.PAGE_DOWN:
14391						this._move( "last", event );
14392						break;
14393					default:
14394						this.menu.trigger( event );
14395						preventDefault = false;
14396				}
14397
14398				if ( preventDefault ) {
14399					event.preventDefault();
14400				}
14401			}
14402		},
14403
14404		_selectFocusedItem: function( event ) {
14405			var item = this.menuItems.eq( this.focusIndex ).parent( "li" );
14406			if ( !item.hasClass( "ui-state-disabled" ) ) {
14407				this._select( item.data( "ui-selectmenu-item" ), event );
14408			}
14409		},
14410
14411		_select: function( item, event ) {
14412			var oldIndex = this.element[ 0 ].selectedIndex;
14413
14414			// Change native select element
14415			this.element[ 0 ].selectedIndex = item.index;
14416			this.buttonItem.replaceWith( this.buttonItem = this._renderButtonItem( item ) );
14417			this._setAria( item );
14418			this._trigger( "select", event, { item: item } );
14419
14420			if ( item.index !== oldIndex ) {
14421				this._trigger( "change", event, { item: item } );
14422			}
14423
14424			this.close( event );
14425		},
14426
14427		_setAria: function( item ) {
14428			var id = this.menuItems.eq( item.index ).attr( "id" );
14429
14430			this.button.attr( {
14431				"aria-labelledby": id,
14432				"aria-activedescendant": id
14433			} );
14434			this.menu.attr( "aria-activedescendant", id );
14435		},
14436
14437		_setOption: function( key, value ) {
14438			if ( key === "icons" ) {
14439				var icon = this.button.find( "span.ui-icon" );
14440				this._removeClass( icon, null, this.options.icons.button )
14441					._addClass( icon, null, value.button );
14442			}
14443
14444			this._super( key, value );
14445
14446			if ( key === "appendTo" ) {
14447				this.menuWrap.appendTo( this._appendTo() );
14448			}
14449
14450			if ( key === "width" ) {
14451				this._resizeButton();
14452			}
14453		},
14454
14455		_setOptionDisabled: function( value ) {
14456			this._super( value );
14457
14458			this.menuInstance.option( "disabled", value );
14459			this.button.attr( "aria-disabled", value );
14460			this._toggleClass( this.button, null, "ui-state-disabled", value );
14461
14462			this.element.prop( "disabled", value );
14463			if ( value ) {
14464				this.button.attr( "tabindex", -1 );
14465				this.close();
14466			} else {
14467				this.button.attr( "tabindex", 0 );
14468			}
14469		},
14470
14471		_appendTo: function() {
14472			var element = this.options.appendTo;
14473
14474			if ( element ) {
14475				element = element.jquery || element.nodeType ?
14476					$( element ) :
14477					this.document.find( element ).eq( 0 );
14478			}
14479
14480			if ( !element || !element[ 0 ] ) {
14481				element = this.element.closest( ".ui-front, dialog" );
14482			}
14483
14484			if ( !element.length ) {
14485				element = this.document[ 0 ].body;
14486			}
14487
14488			return element;
14489		},
14490
14491		_toggleAttr: function() {
14492			this.button.attr( "aria-expanded", this.isOpen );
14493
14494			// We can't use two _toggleClass() calls here, because we need to make sure
14495			// we always remove classes first and add them second, otherwise if both classes have the
14496			// same theme class, it will be removed after we add it.
14497			this._removeClass( this.button, "ui-selectmenu-button-" +
14498				( this.isOpen ? "closed" : "open" ) )
14499				._addClass( this.button, "ui-selectmenu-button-" +
14500					( this.isOpen ? "open" : "closed" ) )
14501				._toggleClass( this.menuWrap, "ui-selectmenu-open", null, this.isOpen );
14502
14503			this.menu.attr( "aria-hidden", !this.isOpen );
14504		},
14505
14506		_resizeButton: function() {
14507			var width = this.options.width;
14508
14509			// For `width: false`, just remove inline style and stop
14510			if ( width === false ) {
14511				this.button.css( "width", "" );
14512				return;
14513			}
14514
14515			// For `width: null`, match the width of the original element
14516			if ( width === null ) {
14517				width = this.element.show().outerWidth();
14518				this.element.hide();
14519			}
14520
14521			this.button.outerWidth( width );
14522		},
14523
14524		_resizeMenu: function() {
14525			this.menu.outerWidth( Math.max(
14526				this.button.outerWidth(),
14527				this.menu.width( "" ).outerWidth()
14528			) );
14529		},
14530
14531		_getCreateOptions: function() {
14532			var options = this._super();
14533
14534			options.disabled = this.element.prop( "disabled" );
14535
14536			return options;
14537		},
14538
14539		_parseOptions: function( options ) {
14540			var that = this,
14541				data = [];
14542			options.each( function( index, item ) {
14543				data.push( that._parseOption( $( item ), index ) );
14544			} );
14545			this.items = data;
14546		},
14547
14548		_parseOption: function( option, index ) {
14549			var optgroup = option.parent( "optgroup" );
14550
14551			return {
14552				element: option,
14553				index: index,
14554				value: option.val(),
14555				label: option.text(),
14556				hidden: optgroup.prop( "hidden" ) || option.prop( "hidden" ),
14557				optgroup: optgroup.attr( "label" ) || "",
14558				disabled: optgroup.prop( "disabled" ) || option.prop( "disabled" )
14559			};
14560		},
14561
14562		_destroy: function() {
14563			this._unbindFormResetHandler();
14564			this.menuWrap.remove();
14565			this.button.remove();
14566			this.element.show();
14567			this.element.removeUniqueId();
14568			this.labels.attr( "for", this.ids.element );
14569		}
14570	} ] );
14571
14572
14573	/*!
14574 * jQuery UI Slider 1.14.1
14575 * https://jqueryui.com
14576 *
14577 * Copyright OpenJS Foundation and other contributors
14578 * Released under the MIT license.
14579 * https://jquery.org/license
14580 */
14581
14582//>>label: Slider
14583//>>group: Widgets
14584//>>description: Displays a flexible slider with ranges and accessibility via keyboard.
14585//>>docs: https://api.jqueryui.com/slider/
14586//>>demos: https://jqueryui.com/slider/
14587//>>css.structure: ../../themes/base/core.css
14588//>>css.structure: ../../themes/base/slider.css
14589//>>css.theme: ../../themes/base/theme.css
14590
14591
14592	var widgetsSlider = $.widget( "ui.slider", $.ui.mouse, {
14593		version: "1.14.1",
14594		widgetEventPrefix: "slide",
14595
14596		options: {
14597			animate: false,
14598			classes: {
14599				"ui-slider": "ui-corner-all",
14600				"ui-slider-handle": "ui-corner-all",
14601
14602				// Note: ui-widget-header isn't the most fittingly semantic framework class for this
14603				// element, but worked best visually with a variety of themes
14604				"ui-slider-range": "ui-corner-all ui-widget-header"
14605			},
14606			distance: 0,
14607			max: 100,
14608			min: 0,
14609			orientation: "horizontal",
14610			range: false,
14611			step: 1,
14612			value: 0,
14613			values: null,
14614
14615			// Callbacks
14616			change: null,
14617			slide: null,
14618			start: null,
14619			stop: null
14620		},
14621
14622		// Number of pages in a slider
14623		// (how many times can you page up/down to go through the whole range)
14624		numPages: 5,
14625
14626		_create: function() {
14627			this._keySliding = false;
14628			this._mouseSliding = false;
14629			this._animateOff = true;
14630			this._handleIndex = null;
14631			this._detectOrientation();
14632			this._mouseInit();
14633			this._calculateNewMax();
14634
14635			this._addClass( "ui-slider ui-slider-" + this.orientation,
14636				"ui-widget ui-widget-content" );
14637
14638			this._refresh();
14639
14640			this._animateOff = false;
14641		},
14642
14643		_refresh: function() {
14644			this._createRange();
14645			this._createHandles();
14646			this._setupEvents();
14647			this._refreshValue();
14648		},
14649
14650		_createHandles: function() {
14651			var i, handleCount,
14652				options = this.options,
14653				existingHandles = this.element.find( ".ui-slider-handle" ),
14654				handle = "<span tabindex='0'></span>",
14655				handles = [];
14656
14657			handleCount = ( options.values && options.values.length ) || 1;
14658
14659			if ( existingHandles.length > handleCount ) {
14660				existingHandles.slice( handleCount ).remove();
14661				existingHandles = existingHandles.slice( 0, handleCount );
14662			}
14663
14664			for ( i = existingHandles.length; i < handleCount; i++ ) {
14665				handles.push( handle );
14666			}
14667
14668			this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) );
14669
14670			this._addClass( this.handles, "ui-slider-handle", "ui-state-default" );
14671
14672			this.handle = this.handles.eq( 0 );
14673
14674			this.handles.each( function( i ) {
14675				$( this )
14676					.data( "ui-slider-handle-index", i )
14677					.attr( "tabIndex", 0 );
14678			} );
14679		},
14680
14681		_createRange: function() {
14682			var options = this.options;
14683
14684			if ( options.range ) {
14685				if ( options.range === true ) {
14686					if ( !options.values ) {
14687						options.values = [ this._valueMin(), this._valueMin() ];
14688					} else if ( options.values.length && options.values.length !== 2 ) {
14689						options.values = [ options.values[ 0 ], options.values[ 0 ] ];
14690					} else if ( Array.isArray( options.values ) ) {
14691						options.values = options.values.slice( 0 );
14692					}
14693				}
14694
14695				if ( !this.range || !this.range.length ) {
14696					this.range = $( "<div>" )
14697						.appendTo( this.element );
14698
14699					this._addClass( this.range, "ui-slider-range" );
14700				} else {
14701					this._removeClass( this.range, "ui-slider-range-min ui-slider-range-max" );
14702
14703					// Handle range switching from true to min/max
14704					this.range.css( {
14705						"left": "",
14706						"bottom": ""
14707					} );
14708				}
14709				if ( options.range === "min" || options.range === "max" ) {
14710					this._addClass( this.range, "ui-slider-range-" + options.range );
14711				}
14712			} else {
14713				if ( this.range ) {
14714					this.range.remove();
14715				}
14716				this.range = null;
14717			}
14718		},
14719
14720		_setupEvents: function() {
14721			this._off( this.handles );
14722			this._on( this.handles, this._handleEvents );
14723			this._hoverable( this.handles );
14724			this._focusable( this.handles );
14725		},
14726
14727		_destroy: function() {
14728			this.handles.remove();
14729			if ( this.range ) {
14730				this.range.remove();
14731			}
14732
14733			this._mouseDestroy();
14734		},
14735
14736		_mouseCapture: function( event ) {
14737			var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle,
14738				that = this,
14739				o = this.options;
14740
14741			if ( o.disabled ) {
14742				return false;
14743			}
14744
14745			this.elementSize = {
14746				width: this.element.outerWidth(),
14747				height: this.element.outerHeight()
14748			};
14749			this.elementOffset = this.element.offset();
14750
14751			position = { x: event.pageX, y: event.pageY };
14752			normValue = this._normValueFromMouse( position );
14753			distance = this._valueMax() - this._valueMin() + 1;
14754			this.handles.each( function( i ) {
14755				var thisDistance = Math.abs( normValue - that.values( i ) );
14756				if ( ( distance > thisDistance ) ||
14757					( distance === thisDistance &&
14758						( i === that._lastChangedValue || that.values( i ) === o.min ) ) ) {
14759					distance = thisDistance;
14760					closestHandle = $( this );
14761					index = i;
14762				}
14763			} );
14764
14765			allowed = this._start( event, index );
14766			if ( allowed === false ) {
14767				return false;
14768			}
14769			this._mouseSliding = true;
14770
14771			this._handleIndex = index;
14772
14773			this._addClass( closestHandle, null, "ui-state-active" );
14774			closestHandle.trigger( "focus" );
14775
14776			offset = closestHandle.offset();
14777			mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" );
14778			this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
14779				left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
14780				top: event.pageY - offset.top -
14781					( closestHandle.height() / 2 ) -
14782					( parseInt( closestHandle.css( "borderTopWidth" ), 10 ) || 0 ) -
14783					( parseInt( closestHandle.css( "borderBottomWidth" ), 10 ) || 0 ) +
14784					( parseInt( closestHandle.css( "marginTop" ), 10 ) || 0 )
14785			};
14786
14787			if ( !this.handles.hasClass( "ui-state-hover" ) ) {
14788				this._slide( event, index, normValue );
14789			}
14790			this._animateOff = true;
14791			return true;
14792		},
14793
14794		_mouseStart: function() {
14795			return true;
14796		},
14797
14798		_mouseDrag: function( event ) {
14799			var position = { x: event.pageX, y: event.pageY },
14800				normValue = this._normValueFromMouse( position );
14801
14802			this._slide( event, this._handleIndex, normValue );
14803
14804			return false;
14805		},
14806
14807		_mouseStop: function( event ) {
14808			this._removeClass( this.handles, null, "ui-state-active" );
14809			this._mouseSliding = false;
14810
14811			this._stop( event, this._handleIndex );
14812			this._change( event, this._handleIndex );
14813
14814			this._handleIndex = null;
14815			this._clickOffset = null;
14816			this._animateOff = false;
14817
14818			return false;
14819		},
14820
14821		_detectOrientation: function() {
14822			this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
14823		},
14824
14825		_normValueFromMouse: function( position ) {
14826			var pixelTotal,
14827				pixelMouse,
14828				percentMouse,
14829				valueTotal,
14830				valueMouse;
14831
14832			if ( this.orientation === "horizontal" ) {
14833				pixelTotal = this.elementSize.width;
14834				pixelMouse = position.x - this.elementOffset.left -
14835					( this._clickOffset ? this._clickOffset.left : 0 );
14836			} else {
14837				pixelTotal = this.elementSize.height;
14838				pixelMouse = position.y - this.elementOffset.top -
14839					( this._clickOffset ? this._clickOffset.top : 0 );
14840			}
14841
14842			percentMouse = ( pixelMouse / pixelTotal );
14843			if ( percentMouse > 1 ) {
14844				percentMouse = 1;
14845			}
14846			if ( percentMouse < 0 ) {
14847				percentMouse = 0;
14848			}
14849			if ( this.orientation === "vertical" ) {
14850				percentMouse = 1 - percentMouse;
14851			}
14852
14853			valueTotal = this._valueMax() - this._valueMin();
14854			valueMouse = this._valueMin() + percentMouse * valueTotal;
14855
14856			return this._trimAlignValue( valueMouse );
14857		},
14858
14859		_uiHash: function( index, value, values ) {
14860			var uiHash = {
14861				handle: this.handles[ index ],
14862				handleIndex: index,
14863				value: value !== undefined ? value : this.value()
14864			};
14865
14866			if ( this._hasMultipleValues() ) {
14867				uiHash.value = value !== undefined ? value : this.values( index );
14868				uiHash.values = values || this.values();
14869			}
14870
14871			return uiHash;
14872		},
14873
14874		_hasMultipleValues: function() {
14875			return this.options.values && this.options.values.length;
14876		},
14877
14878		_start: function( event, index ) {
14879			return this._trigger( "start", event, this._uiHash( index ) );
14880		},
14881
14882		_slide: function( event, index, newVal ) {
14883			var allowed, otherVal,
14884				currentValue = this.value(),
14885				newValues = this.values();
14886
14887			if ( this._hasMultipleValues() ) {
14888				otherVal = this.values( index ? 0 : 1 );
14889				currentValue = this.values( index );
14890
14891				if ( this.options.values.length === 2 && this.options.range === true ) {
14892					newVal =  index === 0 ? Math.min( otherVal, newVal ) : Math.max( otherVal, newVal );
14893				}
14894
14895				newValues[ index ] = newVal;
14896			}
14897
14898			if ( newVal === currentValue ) {
14899				return;
14900			}
14901
14902			allowed = this._trigger( "slide", event, this._uiHash( index, newVal, newValues ) );
14903
14904			// A slide can be canceled by returning false from the slide callback
14905			if ( allowed === false ) {
14906				return;
14907			}
14908
14909			if ( this._hasMultipleValues() ) {
14910				this.values( index, newVal );
14911			} else {
14912				this.value( newVal );
14913			}
14914		},
14915
14916		_stop: function( event, index ) {
14917			this._trigger( "stop", event, this._uiHash( index ) );
14918		},
14919
14920		_change: function( event, index ) {
14921			if ( !this._keySliding && !this._mouseSliding ) {
14922
14923				//store the last changed value index for reference when handles overlap
14924				this._lastChangedValue = index;
14925				this._trigger( "change", event, this._uiHash( index ) );
14926			}
14927		},
14928
14929		value: function( newValue ) {
14930			if ( arguments.length ) {
14931				this.options.value = this._trimAlignValue( newValue );
14932				this._refreshValue();
14933				this._change( null, 0 );
14934				return;
14935			}
14936
14937			return this._value();
14938		},
14939
14940		values: function( index, newValue ) {
14941			var vals,
14942				newValues,
14943				i;
14944
14945			if ( arguments.length > 1 ) {
14946				this.options.values[ index ] = this._trimAlignValue( newValue );
14947				this._refreshValue();
14948				this._change( null, index );
14949				return;
14950			}
14951
14952			if ( arguments.length ) {
14953				if ( Array.isArray( arguments[ 0 ] ) ) {
14954					vals = this.options.values;
14955					newValues = arguments[ 0 ];
14956					for ( i = 0; i < vals.length; i += 1 ) {
14957						vals[ i ] = this._trimAlignValue( newValues[ i ] );
14958						this._change( null, i );
14959					}
14960					this._refreshValue();
14961				} else {
14962					if ( this._hasMultipleValues() ) {
14963						return this._values( index );
14964					} else {
14965						return this.value();
14966					}
14967				}
14968			} else {
14969				return this._values();
14970			}
14971		},
14972
14973		_setOption: function( key, value ) {
14974			var i,
14975				valsLength = 0;
14976
14977			if ( key === "range" && this.options.range === true ) {
14978				if ( value === "min" ) {
14979					this.options.value = this._values( 0 );
14980					this.options.values = null;
14981				} else if ( value === "max" ) {
14982					this.options.value = this._values( this.options.values.length - 1 );
14983					this.options.values = null;
14984				}
14985			}
14986
14987			if ( Array.isArray( this.options.values ) ) {
14988				valsLength = this.options.values.length;
14989			}
14990
14991			this._super( key, value );
14992
14993			switch ( key ) {
14994				case "orientation":
14995					this._detectOrientation();
14996					this._removeClass( "ui-slider-horizontal ui-slider-vertical" )
14997						._addClass( "ui-slider-" + this.orientation );
14998					this._refreshValue();
14999					if ( this.options.range ) {
15000						this._refreshRange( value );
15001					}
15002
15003					// Reset positioning from previous orientation
15004					this.handles.css( value === "horizontal" ? "bottom" : "left", "" );
15005					break;
15006				case "value":
15007					this._animateOff = true;
15008					this._refreshValue();
15009					this._change( null, 0 );
15010					this._animateOff = false;
15011					break;
15012				case "values":
15013					this._animateOff = true;
15014					this._refreshValue();
15015
15016					// Start from the last handle to prevent unreachable handles (#9046)
15017					for ( i = valsLength - 1; i >= 0; i-- ) {
15018						this._change( null, i );
15019					}
15020					this._animateOff = false;
15021					break;
15022				case "step":
15023				case "min":
15024				case "max":
15025					this._animateOff = true;
15026					this._calculateNewMax();
15027					this._refreshValue();
15028					this._animateOff = false;
15029					break;
15030				case "range":
15031					this._animateOff = true;
15032					this._refresh();
15033					this._animateOff = false;
15034					break;
15035			}
15036		},
15037
15038		_setOptionDisabled: function( value ) {
15039			this._super( value );
15040
15041			this._toggleClass( null, "ui-state-disabled", !!value );
15042		},
15043
15044		//internal value getter
15045		// _value() returns value trimmed by min and max, aligned by step
15046		_value: function() {
15047			var val = this.options.value;
15048			val = this._trimAlignValue( val );
15049
15050			return val;
15051		},
15052
15053		//internal values getter
15054		// _values() returns array of values trimmed by min and max, aligned by step
15055		// _values( index ) returns single value trimmed by min and max, aligned by step
15056		_values: function( index ) {
15057			var val,
15058				vals,
15059				i;
15060
15061			if ( arguments.length ) {
15062				val = this.options.values[ index ];
15063				val = this._trimAlignValue( val );
15064
15065				return val;
15066			} else if ( this._hasMultipleValues() ) {
15067
15068				// .slice() creates a copy of the array
15069				// this copy gets trimmed by min and max and then returned
15070				vals = this.options.values.slice();
15071				for ( i = 0; i < vals.length; i += 1 ) {
15072					vals[ i ] = this._trimAlignValue( vals[ i ] );
15073				}
15074
15075				return vals;
15076			} else {
15077				return [];
15078			}
15079		},
15080
15081		// Returns the step-aligned value that val is closest to, between (inclusive) min and max
15082		_trimAlignValue: function( val ) {
15083			if ( val <= this._valueMin() ) {
15084				return this._valueMin();
15085			}
15086			if ( val >= this._valueMax() ) {
15087				return this._valueMax();
15088			}
15089			var step = ( this.options.step > 0 ) ? this.options.step : 1,
15090				valModStep = ( val - this._valueMin() ) % step,
15091				alignValue = val - valModStep;
15092
15093			if ( Math.abs( valModStep ) * 2 >= step ) {
15094				alignValue += ( valModStep > 0 ) ? step : ( -step );
15095			}
15096
15097			// Since JavaScript has problems with large floats, round
15098			// the final value to 5 digits after the decimal point (see #4124)
15099			return parseFloat( alignValue.toFixed( 5 ) );
15100		},
15101
15102		_calculateNewMax: function() {
15103			var max = this.options.max,
15104				min = this._valueMin(),
15105				step = this.options.step,
15106				aboveMin = Math.round( ( max - min ) / step ) * step;
15107			max = aboveMin + min;
15108			if ( max > this.options.max ) {
15109
15110				//If max is not divisible by step, rounding off may increase its value
15111				max -= step;
15112			}
15113			this.max = parseFloat( max.toFixed( this._precision() ) );
15114		},
15115
15116		_precision: function() {
15117			var precision = this._precisionOf( this.options.step );
15118			if ( this.options.min !== null ) {
15119				precision = Math.max( precision, this._precisionOf( this.options.min ) );
15120			}
15121			return precision;
15122		},
15123
15124		_precisionOf: function( num ) {
15125			var str = num.toString(),
15126				decimal = str.indexOf( "." );
15127			return decimal === -1 ? 0 : str.length - decimal - 1;
15128		},
15129
15130		_valueMin: function() {
15131			return this.options.min;
15132		},
15133
15134		_valueMax: function() {
15135			return this.max;
15136		},
15137
15138		_refreshRange: function( orientation ) {
15139			if ( orientation === "vertical" ) {
15140				this.range.css( { "width": "", "left": "" } );
15141			}
15142			if ( orientation === "horizontal" ) {
15143				this.range.css( { "height": "", "bottom": "" } );
15144			}
15145		},
15146
15147		_refreshValue: function() {
15148			var lastValPercent, valPercent, value, valueMin, valueMax,
15149				oRange = this.options.range,
15150				o = this.options,
15151				that = this,
15152				animate = ( !this._animateOff ) ? o.animate : false,
15153				_set = {};
15154
15155			if ( this._hasMultipleValues() ) {
15156				this.handles.each( function( i ) {
15157					valPercent = ( that.values( i ) - that._valueMin() ) / ( that._valueMax() -
15158						that._valueMin() ) * 100;
15159					_set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
15160					$( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
15161					if ( that.options.range === true ) {
15162						if ( that.orientation === "horizontal" ) {
15163							if ( i === 0 ) {
15164								that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15165									left: valPercent + "%"
15166								}, o.animate );
15167							}
15168							if ( i === 1 ) {
15169								that.range[ animate ? "animate" : "css" ]( {
15170									width: ( valPercent - lastValPercent ) + "%"
15171								}, {
15172									queue: false,
15173									duration: o.animate
15174								} );
15175							}
15176						} else {
15177							if ( i === 0 ) {
15178								that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15179									bottom: ( valPercent ) + "%"
15180								}, o.animate );
15181							}
15182							if ( i === 1 ) {
15183								that.range[ animate ? "animate" : "css" ]( {
15184									height: ( valPercent - lastValPercent ) + "%"
15185								}, {
15186									queue: false,
15187									duration: o.animate
15188								} );
15189							}
15190						}
15191					}
15192					lastValPercent = valPercent;
15193				} );
15194			} else {
15195				value = this.value();
15196				valueMin = this._valueMin();
15197				valueMax = this._valueMax();
15198				valPercent = ( valueMax !== valueMin ) ?
15199					( value - valueMin ) / ( valueMax - valueMin ) * 100 :
15200					0;
15201				_set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
15202				this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
15203
15204				if ( oRange === "min" && this.orientation === "horizontal" ) {
15205					this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15206						width: valPercent + "%"
15207					}, o.animate );
15208				}
15209				if ( oRange === "max" && this.orientation === "horizontal" ) {
15210					this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15211						width: ( 100 - valPercent ) + "%"
15212					}, o.animate );
15213				}
15214				if ( oRange === "min" && this.orientation === "vertical" ) {
15215					this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15216						height: valPercent + "%"
15217					}, o.animate );
15218				}
15219				if ( oRange === "max" && this.orientation === "vertical" ) {
15220					this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15221						height: ( 100 - valPercent ) + "%"
15222					}, o.animate );
15223				}
15224			}
15225		},
15226
15227		_handleEvents: {
15228			keydown: function( event ) {
15229				var allowed, curVal, newVal, step,
15230					index = $( event.target ).data( "ui-slider-handle-index" );
15231
15232				switch ( event.keyCode ) {
15233					case $.ui.keyCode.HOME:
15234					case $.ui.keyCode.END:
15235					case $.ui.keyCode.PAGE_UP:
15236					case $.ui.keyCode.PAGE_DOWN:
15237					case $.ui.keyCode.UP:
15238					case $.ui.keyCode.RIGHT:
15239					case $.ui.keyCode.DOWN:
15240					case $.ui.keyCode.LEFT:
15241						event.preventDefault();
15242						if ( !this._keySliding ) {
15243							this._keySliding = true;
15244							this._addClass( $( event.target ), null, "ui-state-active" );
15245							allowed = this._start( event, index );
15246							if ( allowed === false ) {
15247								return;
15248							}
15249						}
15250						break;
15251				}
15252
15253				step = this.options.step;
15254				if ( this._hasMultipleValues() ) {
15255					curVal = newVal = this.values( index );
15256				} else {
15257					curVal = newVal = this.value();
15258				}
15259
15260				switch ( event.keyCode ) {
15261					case $.ui.keyCode.HOME:
15262						newVal = this._valueMin();
15263						break;
15264					case $.ui.keyCode.END:
15265						newVal = this._valueMax();
15266						break;
15267					case $.ui.keyCode.PAGE_UP:
15268						newVal = this._trimAlignValue(
15269							curVal + ( ( this._valueMax() - this._valueMin() ) / this.numPages )
15270						);
15271						break;
15272					case $.ui.keyCode.PAGE_DOWN:
15273						newVal = this._trimAlignValue(
15274							curVal - ( ( this._valueMax() - this._valueMin() ) / this.numPages ) );
15275						break;
15276					case $.ui.keyCode.UP:
15277					case $.ui.keyCode.RIGHT:
15278						if ( curVal === this._valueMax() ) {
15279							return;
15280						}
15281						newVal = this._trimAlignValue( curVal + step );
15282						break;
15283					case $.ui.keyCode.DOWN:
15284					case $.ui.keyCode.LEFT:
15285						if ( curVal === this._valueMin() ) {
15286							return;
15287						}
15288						newVal = this._trimAlignValue( curVal - step );
15289						break;
15290				}
15291
15292				this._slide( event, index, newVal );
15293			},
15294			keyup: function( event ) {
15295				var index = $( event.target ).data( "ui-slider-handle-index" );
15296
15297				if ( this._keySliding ) {
15298					this._keySliding = false;
15299					this._stop( event, index );
15300					this._change( event, index );
15301					this._removeClass( $( event.target ), null, "ui-state-active" );
15302				}
15303			}
15304		}
15305	} );
15306
15307
15308	/*!
15309 * jQuery UI Sortable 1.14.1
15310 * https://jqueryui.com
15311 *
15312 * Copyright OpenJS Foundation and other contributors
15313 * Released under the MIT license.
15314 * https://jquery.org/license
15315 */
15316
15317//>>label: Sortable
15318//>>group: Interactions
15319//>>description: Enables items in a list to be sorted using the mouse.
15320//>>docs: https://api.jqueryui.com/sortable/
15321//>>demos: https://jqueryui.com/sortable/
15322//>>css.structure: ../../themes/base/sortable.css
15323
15324
15325	var widgetsSortable = $.widget( "ui.sortable", $.ui.mouse, {
15326		version: "1.14.1",
15327		widgetEventPrefix: "sort",
15328		ready: false,
15329		options: {
15330			appendTo: "parent",
15331			axis: false,
15332			connectWith: false,
15333			containment: false,
15334			cursor: "auto",
15335			cursorAt: false,
15336			dropOnEmpty: true,
15337			forcePlaceholderSize: false,
15338			forceHelperSize: false,
15339			grid: false,
15340			handle: false,
15341			helper: "original",
15342			items: "> *",
15343			opacity: false,
15344			placeholder: false,
15345			revert: false,
15346			scroll: true,
15347			scrollSensitivity: 20,
15348			scrollSpeed: 20,
15349			scope: "default",
15350			tolerance: "intersect",
15351			zIndex: 1000,
15352
15353			// Callbacks
15354			activate: null,
15355			beforeStop: null,
15356			change: null,
15357			deactivate: null,
15358			out: null,
15359			over: null,
15360			receive: null,
15361			remove: null,
15362			sort: null,
15363			start: null,
15364			stop: null,
15365			update: null
15366		},
15367
15368		_isOverAxis: function( x, reference, size ) {
15369			return ( x >= reference ) && ( x < ( reference + size ) );
15370		},
15371
15372		_isFloating: function( item ) {
15373			return ( /left|right/ ).test( item.css( "float" ) ) ||
15374				( /inline|table-cell/ ).test( item.css( "display" ) );
15375		},
15376
15377		_create: function() {
15378			this.containerCache = {};
15379			this._addClass( "ui-sortable" );
15380
15381			//Get the items
15382			this.refresh();
15383
15384			//Let's determine the parent's offset
15385			this.offset = this.element.offset();
15386
15387			//Initialize mouse events for interaction
15388			this._mouseInit();
15389
15390			this._setHandleClassName();
15391
15392			//We're ready to go
15393			this.ready = true;
15394
15395		},
15396
15397		_setOption: function( key, value ) {
15398			this._super( key, value );
15399
15400			if ( key === "handle" ) {
15401				this._setHandleClassName();
15402			}
15403		},
15404
15405		_setHandleClassName: function() {
15406			var that = this;
15407			this._removeClass( this.element.find( ".ui-sortable-handle" ), "ui-sortable-handle" );
15408			$.each( this.items, function() {
15409				that._addClass(
15410					this.instance.options.handle ?
15411						this.item.find( this.instance.options.handle ) :
15412						this.item,
15413					"ui-sortable-handle"
15414				);
15415			} );
15416		},
15417
15418		_destroy: function() {
15419			this._mouseDestroy();
15420
15421			for ( var i = this.items.length - 1; i >= 0; i-- ) {
15422				this.items[ i ].item.removeData( this.widgetName + "-item" );
15423			}
15424
15425			return this;
15426		},
15427
15428		_mouseCapture: function( event, overrideHandle ) {
15429			var currentItem = null,
15430				validHandle = false,
15431				that = this;
15432
15433			if ( this.reverting ) {
15434				return false;
15435			}
15436
15437			if ( this.options.disabled || this.options.type === "static" ) {
15438				return false;
15439			}
15440
15441			//We have to refresh the items data once first
15442			this._refreshItems( event );
15443
15444			//Find out if the clicked node (or one of its parents) is a actual item in this.items
15445			$( event.target ).parents().each( function() {
15446				if ( $.data( this, that.widgetName + "-item" ) === that ) {
15447					currentItem = $( this );
15448					return false;
15449				}
15450			} );
15451			if ( $.data( event.target, that.widgetName + "-item" ) === that ) {
15452				currentItem = $( event.target );
15453			}
15454
15455			if ( !currentItem ) {
15456				return false;
15457			}
15458			if ( this.options.handle && !overrideHandle ) {
15459				$( this.options.handle, currentItem ).find( "*" ).addBack().each( function() {
15460					if ( this === event.target ) {
15461						validHandle = true;
15462					}
15463				} );
15464				if ( !validHandle ) {
15465					return false;
15466				}
15467			}
15468
15469			this.currentItem = currentItem;
15470			this._removeCurrentsFromItems();
15471			return true;
15472
15473		},
15474
15475		_mouseStart: function( event, overrideHandle, noActivation ) {
15476
15477			var i, body,
15478				o = this.options;
15479
15480			this.currentContainer = this;
15481
15482			//We only need to call refreshPositions, because the refreshItems call has been moved to
15483			// mouseCapture
15484			this.refreshPositions();
15485
15486			//Prepare the dragged items parent
15487			this.appendTo = $( o.appendTo !== "parent" ?
15488				o.appendTo :
15489				this.currentItem.parent() );
15490
15491			//Create and append the visible helper
15492			this.helper = this._createHelper( event );
15493
15494			//Cache the helper size
15495			this._cacheHelperProportions();
15496
15497			/*
15498		 * - Position generation -
15499		 * This block generates everything position related - it's the core of draggables.
15500		 */
15501
15502			//Cache the margins of the original element
15503			this._cacheMargins();
15504
15505			//The element's absolute position on the page minus margins
15506			this.offset = this.currentItem.offset();
15507			this.offset = {
15508				top: this.offset.top - this.margins.top,
15509				left: this.offset.left - this.margins.left
15510			};
15511
15512			$.extend( this.offset, {
15513				click: { //Where the click happened, relative to the element
15514					left: event.pageX - this.offset.left,
15515					top: event.pageY - this.offset.top
15516				},
15517
15518				// This is a relative to absolute position minus the actual position calculation -
15519				// only used for relative positioned helper
15520				relative: this._getRelativeOffset()
15521			} );
15522
15523			// After we get the helper offset, but before we get the parent offset we can
15524			// change the helper's position to absolute
15525			// TODO: Still need to figure out a way to make relative sorting possible
15526			this.helper.css( "position", "absolute" );
15527			this.cssPosition = this.helper.css( "position" );
15528
15529			//Adjust the mouse offset relative to the helper if "cursorAt" is supplied
15530			if ( o.cursorAt ) {
15531				this._adjustOffsetFromHelper( o.cursorAt );
15532			}
15533
15534			//Cache the former DOM position
15535			this.domPosition = {
15536				prev: this.currentItem.prev()[ 0 ],
15537				parent: this.currentItem.parent()[ 0 ]
15538			};
15539
15540			// If the helper is not the original, hide the original so it's not playing any role during
15541			// the drag, won't cause anything bad this way
15542			if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {
15543				this.currentItem.hide();
15544			}
15545
15546			//Create the placeholder
15547			this._createPlaceholder();
15548
15549			//Get the next scrolling parent
15550			this.scrollParent = this.placeholder.scrollParent();
15551
15552			$.extend( this.offset, {
15553				parent: this._getParentOffset()
15554			} );
15555
15556			//Set a containment if given in the options
15557			if ( o.containment ) {
15558				this._setContainment();
15559			}
15560
15561			if ( o.cursor && o.cursor !== "auto" ) { // cursor option
15562				body = this.document.find( "body" );
15563
15564				this._storedStylesheet =
15565					$( "<style>*{ cursor: " + o.cursor + " !important; }</style>" ).appendTo( body );
15566			}
15567
15568			// We need to make sure to grab the zIndex before setting the
15569			// opacity, because setting the opacity to anything lower than 1
15570			// causes the zIndex to change from "auto" to 0.
15571			if ( o.zIndex ) { // zIndex option
15572				if ( this.helper.css( "zIndex" ) ) {
15573					this._storedZIndex = this.helper.css( "zIndex" );
15574				}
15575				this.helper.css( "zIndex", o.zIndex );
15576			}
15577
15578			if ( o.opacity ) { // opacity option
15579				if ( this.helper.css( "opacity" ) ) {
15580					this._storedOpacity = this.helper.css( "opacity" );
15581				}
15582				this.helper.css( "opacity", o.opacity );
15583			}
15584
15585			//Prepare scrolling
15586			if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
15587				this.scrollParent[ 0 ].tagName !== "HTML" ) {
15588				this.overflowOffset = this.scrollParent.offset();
15589			}
15590
15591			//Call callbacks
15592			this._trigger( "start", event, this._uiHash() );
15593
15594			//Recache the helper size
15595			if ( !this._preserveHelperProportions ) {
15596				this._cacheHelperProportions();
15597			}
15598
15599			//Post "activate" events to possible containers
15600			if ( !noActivation ) {
15601				for ( i = this.containers.length - 1; i >= 0; i-- ) {
15602					this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) );
15603				}
15604			}
15605
15606			//Prepare possible droppables
15607			if ( $.ui.ddmanager ) {
15608				$.ui.ddmanager.current = this;
15609			}
15610
15611			if ( $.ui.ddmanager && !o.dropBehaviour ) {
15612				$.ui.ddmanager.prepareOffsets( this, event );
15613			}
15614
15615			this.dragging = true;
15616
15617			this._addClass( this.helper, "ui-sortable-helper" );
15618
15619			//Move the helper, if needed
15620			if ( !this.helper.parent().is( this.appendTo ) ) {
15621				this.helper.detach().appendTo( this.appendTo );
15622
15623				//Update position
15624				this.offset.parent = this._getParentOffset();
15625			}
15626
15627			//Generate the original position
15628			this.position = this.originalPosition = this._generatePosition( event );
15629			this.originalPageX = event.pageX;
15630			this.originalPageY = event.pageY;
15631			this.lastPositionAbs = this.positionAbs = this._convertPositionTo( "absolute" );
15632
15633			this._mouseDrag( event );
15634
15635			return true;
15636
15637		},
15638
15639		_scroll: function( event ) {
15640			var o = this.options,
15641				scrolled = false;
15642
15643			if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
15644				this.scrollParent[ 0 ].tagName !== "HTML" ) {
15645
15646				if ( ( this.overflowOffset.top + this.scrollParent[ 0 ].offsetHeight ) -
15647					event.pageY < o.scrollSensitivity ) {
15648					this.scrollParent[ 0 ].scrollTop =
15649						scrolled = this.scrollParent[ 0 ].scrollTop + o.scrollSpeed;
15650				} else if ( event.pageY - this.overflowOffset.top < o.scrollSensitivity ) {
15651					this.scrollParent[ 0 ].scrollTop =
15652						scrolled = this.scrollParent[ 0 ].scrollTop - o.scrollSpeed;
15653				}
15654
15655				if ( ( this.overflowOffset.left + this.scrollParent[ 0 ].offsetWidth ) -
15656					event.pageX < o.scrollSensitivity ) {
15657					this.scrollParent[ 0 ].scrollLeft = scrolled =
15658						this.scrollParent[ 0 ].scrollLeft + o.scrollSpeed;
15659				} else if ( event.pageX - this.overflowOffset.left < o.scrollSensitivity ) {
15660					this.scrollParent[ 0 ].scrollLeft = scrolled =
15661						this.scrollParent[ 0 ].scrollLeft - o.scrollSpeed;
15662				}
15663
15664			} else {
15665
15666				if ( event.pageY - this.document.scrollTop() < o.scrollSensitivity ) {
15667					scrolled = this.document.scrollTop( this.document.scrollTop() - o.scrollSpeed );
15668				} else if ( this.window.height() - ( event.pageY - this.document.scrollTop() ) <
15669					o.scrollSensitivity ) {
15670					scrolled = this.document.scrollTop( this.document.scrollTop() + o.scrollSpeed );
15671				}
15672
15673				if ( event.pageX - this.document.scrollLeft() < o.scrollSensitivity ) {
15674					scrolled = this.document.scrollLeft(
15675						this.document.scrollLeft() - o.scrollSpeed
15676					);
15677				} else if ( this.window.width() - ( event.pageX - this.document.scrollLeft() ) <
15678					o.scrollSensitivity ) {
15679					scrolled = this.document.scrollLeft(
15680						this.document.scrollLeft() + o.scrollSpeed
15681					);
15682				}
15683
15684			}
15685
15686			return scrolled;
15687		},
15688
15689		_mouseDrag: function( event ) {
15690			var i, item, itemElement, intersection,
15691				o = this.options;
15692
15693			//Compute the helpers position
15694			this.position = this._generatePosition( event );
15695			this.positionAbs = this._convertPositionTo( "absolute" );
15696
15697			//Set the helper position
15698			if ( !this.options.axis || this.options.axis !== "y" ) {
15699				this.helper[ 0 ].style.left = this.position.left + "px";
15700			}
15701			if ( !this.options.axis || this.options.axis !== "x" ) {
15702				this.helper[ 0 ].style.top = this.position.top + "px";
15703			}
15704
15705			//Do scrolling
15706			if ( o.scroll ) {
15707				if ( this._scroll( event ) !== false ) {
15708
15709					//Update item positions used in position checks
15710					this._refreshItemPositions( true );
15711
15712					if ( $.ui.ddmanager && !o.dropBehaviour ) {
15713						$.ui.ddmanager.prepareOffsets( this, event );
15714					}
15715				}
15716			}
15717
15718			this.dragDirection = {
15719				vertical: this._getDragVerticalDirection(),
15720				horizontal: this._getDragHorizontalDirection()
15721			};
15722
15723			//Rearrange
15724			for ( i = this.items.length - 1; i >= 0; i-- ) {
15725
15726				//Cache variables and intersection, continue if no intersection
15727				item = this.items[ i ];
15728				itemElement = item.item[ 0 ];
15729				intersection = this._intersectsWithPointer( item );
15730				if ( !intersection ) {
15731					continue;
15732				}
15733
15734				// Only put the placeholder inside the current Container, skip all
15735				// items from other containers. This works because when moving
15736				// an item from one container to another the
15737				// currentContainer is switched before the placeholder is moved.
15738				//
15739				// Without this, moving items in "sub-sortables" can cause
15740				// the placeholder to jitter between the outer and inner container.
15741				if ( item.instance !== this.currentContainer ) {
15742					continue;
15743				}
15744
15745				// Cannot intersect with itself
15746				// no useless actions that have been done before
15747				// no action if the item moved is the parent of the item checked
15748				if ( itemElement !== this.currentItem[ 0 ] &&
15749					this.placeholder[ intersection === 1 ?
15750						"next" : "prev" ]()[ 0 ] !== itemElement &&
15751					!$.contains( this.placeholder[ 0 ], itemElement ) &&
15752					( this.options.type === "semi-dynamic" ?
15753							!$.contains( this.element[ 0 ], itemElement ) :
15754							true
15755					)
15756				) {
15757
15758					this.direction = intersection === 1 ? "down" : "up";
15759
15760					if ( this.options.tolerance === "pointer" ||
15761						this._intersectsWithSides( item ) ) {
15762						this._rearrange( event, item );
15763					} else {
15764						break;
15765					}
15766
15767					this._trigger( "change", event, this._uiHash() );
15768					break;
15769				}
15770			}
15771
15772			//Post events to containers
15773			this._contactContainers( event );
15774
15775			//Interconnect with droppables
15776			if ( $.ui.ddmanager ) {
15777				$.ui.ddmanager.drag( this, event );
15778			}
15779
15780			//Call callbacks
15781			this._trigger( "sort", event, this._uiHash() );
15782
15783			this.lastPositionAbs = this.positionAbs;
15784			return false;
15785
15786		},
15787
15788		_mouseStop: function( event, noPropagation ) {
15789
15790			if ( !event ) {
15791				return;
15792			}
15793
15794			//If we are using droppables, inform the manager about the drop
15795			if ( $.ui.ddmanager && !this.options.dropBehaviour ) {
15796				$.ui.ddmanager.drop( this, event );
15797			}
15798
15799			if ( this.options.revert ) {
15800				var that = this,
15801					cur = this.placeholder.offset(),
15802					axis = this.options.axis,
15803					animation = {};
15804
15805				if ( !axis || axis === "x" ) {
15806					animation.left = cur.left - this.offset.parent.left - this.margins.left +
15807						( this.offsetParent[ 0 ] === this.document[ 0 ].body ?
15808								0 :
15809								this.offsetParent[ 0 ].scrollLeft
15810						);
15811				}
15812				if ( !axis || axis === "y" ) {
15813					animation.top = cur.top - this.offset.parent.top - this.margins.top +
15814						( this.offsetParent[ 0 ] === this.document[ 0 ].body ?
15815								0 :
15816								this.offsetParent[ 0 ].scrollTop
15817						);
15818				}
15819				this.reverting = true;
15820				$( this.helper ).animate(
15821					animation,
15822					parseInt( this.options.revert, 10 ) || 500,
15823					function() {
15824						that._clear( event );
15825					}
15826				);
15827			} else {
15828				this._clear( event, noPropagation );
15829			}
15830
15831			return false;
15832
15833		},
15834
15835		cancel: function() {
15836
15837			if ( this.dragging ) {
15838
15839				this._mouseUp( new $.Event( "mouseup", { target: null } ) );
15840
15841				if ( this.options.helper === "original" ) {
15842					this.currentItem.css( this._storedCSS );
15843					this._removeClass( this.currentItem, "ui-sortable-helper" );
15844				} else {
15845					this.currentItem.show();
15846				}
15847
15848				//Post deactivating events to containers
15849				for ( var i = this.containers.length - 1; i >= 0; i-- ) {
15850					this.containers[ i ]._trigger( "deactivate", null, this._uiHash( this ) );
15851					if ( this.containers[ i ].containerCache.over ) {
15852						this.containers[ i ]._trigger( "out", null, this._uiHash( this ) );
15853						this.containers[ i ].containerCache.over = 0;
15854					}
15855				}
15856
15857			}
15858
15859			if ( this.placeholder ) {
15860
15861				//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately,
15862				// it unbinds ALL events from the original node!
15863				if ( this.placeholder[ 0 ].parentNode ) {
15864					this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] );
15865				}
15866				if ( this.options.helper !== "original" && this.helper &&
15867					this.helper[ 0 ].parentNode ) {
15868					this.helper.remove();
15869				}
15870
15871				$.extend( this, {
15872					helper: null,
15873					dragging: false,
15874					reverting: false,
15875					_noFinalSort: null
15876				} );
15877
15878				if ( this.domPosition.prev ) {
15879					$( this.domPosition.prev ).after( this.currentItem );
15880				} else {
15881					$( this.domPosition.parent ).prepend( this.currentItem );
15882				}
15883			}
15884
15885			return this;
15886
15887		},
15888
15889		serialize: function( o ) {
15890
15891			var items = this._getItemsAsjQuery( o && o.connected ),
15892				str = [];
15893			o = o || {};
15894
15895			$( items ).each( function() {
15896				var res = ( $( o.item || this ).attr( o.attribute || "id" ) || "" )
15897					.match( o.expression || ( /(.+)[\-=_](.+)/ ) );
15898				if ( res ) {
15899					str.push(
15900						( o.key || res[ 1 ] + "[]" ) +
15901						"=" + ( o.key && o.expression ? res[ 1 ] : res[ 2 ] ) );
15902				}
15903			} );
15904
15905			if ( !str.length && o.key ) {
15906				str.push( o.key + "=" );
15907			}
15908
15909			return str.join( "&" );
15910
15911		},
15912
15913		toArray: function( o ) {
15914
15915			var items = this._getItemsAsjQuery( o && o.connected ),
15916				ret = [];
15917
15918			o = o || {};
15919
15920			items.each( function() {
15921				ret.push( $( o.item || this ).attr( o.attribute || "id" ) || "" );
15922			} );
15923			return ret;
15924
15925		},
15926
15927		/* Be careful with the following core functions */
15928		_intersectsWith: function( item ) {
15929
15930			var x1 = this.positionAbs.left,
15931				x2 = x1 + this.helperProportions.width,
15932				y1 = this.positionAbs.top,
15933				y2 = y1 + this.helperProportions.height,
15934				l = item.left,
15935				r = l + item.width,
15936				t = item.top,
15937				b = t + item.height,
15938				dyClick = this.offset.click.top,
15939				dxClick = this.offset.click.left,
15940				isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t &&
15941					( y1 + dyClick ) < b ),
15942				isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l &&
15943					( x1 + dxClick ) < r ),
15944				isOverElement = isOverElementHeight && isOverElementWidth;
15945
15946			if ( this.options.tolerance === "pointer" ||
15947				this.options.forcePointerForContainers ||
15948				( this.options.tolerance !== "pointer" &&
15949					this.helperProportions[ this.floating ? "width" : "height" ] >
15950					item[ this.floating ? "width" : "height" ] )
15951			) {
15952				return isOverElement;
15953			} else {
15954
15955				return ( l < x1 + ( this.helperProportions.width / 2 ) && // Right Half
15956					x2 - ( this.helperProportions.width / 2 ) < r && // Left Half
15957					t < y1 + ( this.helperProportions.height / 2 ) && // Bottom Half
15958					y2 - ( this.helperProportions.height / 2 ) < b ); // Top Half
15959
15960			}
15961		},
15962
15963		_intersectsWithPointer: function( item ) {
15964			var verticalDirection, horizontalDirection,
15965				isOverElementHeight = ( this.options.axis === "x" ) ||
15966					this._isOverAxis(
15967						this.positionAbs.top + this.offset.click.top, item.top, item.height ),
15968				isOverElementWidth = ( this.options.axis === "y" ) ||
15969					this._isOverAxis(
15970						this.positionAbs.left + this.offset.click.left, item.left, item.width ),
15971				isOverElement = isOverElementHeight && isOverElementWidth;
15972
15973			if ( !isOverElement ) {
15974				return false;
15975			}
15976
15977			verticalDirection = this.dragDirection.vertical;
15978			horizontalDirection = this.dragDirection.horizontal;
15979
15980			return this.floating ?
15981				( ( horizontalDirection === "right" || verticalDirection === "down" ) ? 2 : 1 ) :
15982				( verticalDirection && ( verticalDirection === "down" ? 2 : 1 ) );
15983
15984		},
15985
15986		_intersectsWithSides: function( item ) {
15987
15988			var isOverBottomHalf = this._isOverAxis( this.positionAbs.top +
15989					this.offset.click.top, item.top + ( item.height / 2 ), item.height ),
15990				isOverRightHalf = this._isOverAxis( this.positionAbs.left +
15991					this.offset.click.left, item.left + ( item.width / 2 ), item.width ),
15992				verticalDirection = this.dragDirection.vertical,
15993				horizontalDirection = this.dragDirection.horizontal;
15994
15995			if ( this.floating && horizontalDirection ) {
15996				return ( ( horizontalDirection === "right" && isOverRightHalf ) ||
15997					( horizontalDirection === "left" && !isOverRightHalf ) );
15998			} else {
15999				return verticalDirection && ( ( verticalDirection === "down" && isOverBottomHalf ) ||
16000					( verticalDirection === "up" && !isOverBottomHalf ) );
16001			}
16002
16003		},
16004
16005		_getDragVerticalDirection: function() {
16006			var delta = this.positionAbs.top - this.lastPositionAbs.top;
16007			return delta !== 0 && ( delta > 0 ? "down" : "up" );
16008		},
16009
16010		_getDragHorizontalDirection: function() {
16011			var delta = this.positionAbs.left - this.lastPositionAbs.left;
16012			return delta !== 0 && ( delta > 0 ? "right" : "left" );
16013		},
16014
16015		refresh: function( event ) {
16016			this._refreshItems( event );
16017			this._setHandleClassName();
16018			this.refreshPositions();
16019			return this;
16020		},
16021
16022		_connectWith: function() {
16023			var options = this.options;
16024			return options.connectWith.constructor === String ?
16025				[ options.connectWith ] :
16026				options.connectWith;
16027		},
16028
16029		_getItemsAsjQuery: function( connected ) {
16030
16031			var i, j, cur, inst,
16032				items = [],
16033				queries = [],
16034				connectWith = this._connectWith();
16035
16036			if ( connectWith && connected ) {
16037				for ( i = connectWith.length - 1; i >= 0; i-- ) {
16038					cur = $( connectWith[ i ], this.document[ 0 ] );
16039					for ( j = cur.length - 1; j >= 0; j-- ) {
16040						inst = $.data( cur[ j ], this.widgetFullName );
16041						if ( inst && inst !== this && !inst.options.disabled ) {
16042							queries.push( [ typeof inst.options.items === "function" ?
16043								inst.options.items.call( inst.element ) :
16044								$( inst.options.items, inst.element )
16045									.not( ".ui-sortable-helper" )
16046									.not( ".ui-sortable-placeholder" ), inst ] );
16047						}
16048					}
16049				}
16050			}
16051
16052			queries.push( [ typeof this.options.items === "function" ?
16053				this.options.items
16054					.call( this.element, null, { options: this.options, item: this.currentItem } ) :
16055				$( this.options.items, this.element )
16056					.not( ".ui-sortable-helper" )
16057					.not( ".ui-sortable-placeholder" ), this ] );
16058
16059			function addItems() {
16060				items.push( this );
16061			}
16062			for ( i = queries.length - 1; i >= 0; i-- ) {
16063				queries[ i ][ 0 ].each( addItems );
16064			}
16065
16066			return $( items );
16067
16068		},
16069
16070		_removeCurrentsFromItems: function() {
16071
16072			var list = this.currentItem.find( ":data(" + this.widgetName + "-item)" );
16073
16074			this.items = $.grep( this.items, function( item ) {
16075				for ( var j = 0; j < list.length; j++ ) {
16076					if ( list[ j ] === item.item[ 0 ] ) {
16077						return false;
16078					}
16079				}
16080				return true;
16081			} );
16082
16083		},
16084
16085		_refreshItems: function( event ) {
16086
16087			this.items = [];
16088			this.containers = [ this ];
16089
16090			var i, j, cur, inst, targetData, _queries, item, queriesLength,
16091				items = this.items,
16092				queries = [ [ typeof this.options.items === "function" ?
16093					this.options.items.call( this.element[ 0 ], event, { item: this.currentItem } ) :
16094					$( this.options.items, this.element ), this ] ],
16095				connectWith = this._connectWith();
16096
16097			//Shouldn't be run the first time through due to massive slow-down
16098			if ( connectWith && this.ready ) {
16099				for ( i = connectWith.length - 1; i >= 0; i-- ) {
16100					cur = $( connectWith[ i ], this.document[ 0 ] );
16101					for ( j = cur.length - 1; j >= 0; j-- ) {
16102						inst = $.data( cur[ j ], this.widgetFullName );
16103						if ( inst && inst !== this && !inst.options.disabled ) {
16104							queries.push( [ typeof inst.options.items === "function" ?
16105								inst.options.items
16106									.call( inst.element[ 0 ], event, { item: this.currentItem } ) :
16107								$( inst.options.items, inst.element ), inst ] );
16108							this.containers.push( inst );
16109						}
16110					}
16111				}
16112			}
16113
16114			for ( i = queries.length - 1; i >= 0; i-- ) {
16115				targetData = queries[ i ][ 1 ];
16116				_queries = queries[ i ][ 0 ];
16117
16118				for ( j = 0, queriesLength = _queries.length; j < queriesLength; j++ ) {
16119					item = $( _queries[ j ] );
16120
16121					// Data for target checking (mouse manager)
16122					item.data( this.widgetName + "-item", targetData );
16123
16124					items.push( {
16125						item: item,
16126						instance: targetData,
16127						width: 0, height: 0,
16128						left: 0, top: 0
16129					} );
16130				}
16131			}
16132
16133		},
16134
16135		_refreshItemPositions: function( fast ) {
16136			var i, item, t, p;
16137
16138			for ( i = this.items.length - 1; i >= 0; i-- ) {
16139				item = this.items[ i ];
16140
16141				//We ignore calculating positions of all connected containers when we're not over them
16142				if ( this.currentContainer && item.instance !== this.currentContainer &&
16143					item.item[ 0 ] !== this.currentItem[ 0 ] ) {
16144					continue;
16145				}
16146
16147				t = this.options.toleranceElement ?
16148					$( this.options.toleranceElement, item.item ) :
16149					item.item;
16150
16151				if ( !fast ) {
16152					item.width = t.outerWidth();
16153					item.height = t.outerHeight();
16154				}
16155
16156				p = t.offset();
16157				item.left = p.left;
16158				item.top = p.top;
16159			}
16160		},
16161
16162		refreshPositions: function( fast ) {
16163
16164			// Determine whether items are being displayed horizontally
16165			this.floating = this.items.length ?
16166				this.options.axis === "x" || this._isFloating( this.items[ 0 ].item ) :
16167				false;
16168
16169			// This has to be redone because due to the item being moved out/into the offsetParent,
16170			// the offsetParent's position will change
16171			if ( this.offsetParent && this.helper ) {
16172				this.offset.parent = this._getParentOffset();
16173			}
16174
16175			this._refreshItemPositions( fast );
16176
16177			var i, p;
16178
16179			if ( this.options.custom && this.options.custom.refreshContainers ) {
16180				this.options.custom.refreshContainers.call( this );
16181			} else {
16182				for ( i = this.containers.length - 1; i >= 0; i-- ) {
16183					p = this.containers[ i ].element.offset();
16184					this.containers[ i ].containerCache.left = p.left;
16185					this.containers[ i ].containerCache.top = p.top;
16186					this.containers[ i ].containerCache.width =
16187						this.containers[ i ].element.outerWidth();
16188					this.containers[ i ].containerCache.height =
16189						this.containers[ i ].element.outerHeight();
16190				}
16191			}
16192
16193			return this;
16194		},
16195
16196		_createPlaceholder: function( that ) {
16197			that = that || this;
16198			var className, nodeName,
16199				o = that.options;
16200
16201			if ( !o.placeholder || o.placeholder.constructor === String ) {
16202				className = o.placeholder;
16203				nodeName = that.currentItem[ 0 ].nodeName.toLowerCase();
16204				o.placeholder = {
16205					element: function() {
16206
16207						var element = $( "<" + nodeName + ">", that.document[ 0 ] );
16208
16209						that._addClass( element, "ui-sortable-placeholder",
16210							className || that.currentItem[ 0 ].className )
16211							._removeClass( element, "ui-sortable-helper" );
16212
16213						if ( nodeName === "tbody" ) {
16214							that._createTrPlaceholder(
16215								that.currentItem.find( "tr" ).eq( 0 ),
16216								$( "<tr>", that.document[ 0 ] ).appendTo( element )
16217							);
16218						} else if ( nodeName === "tr" ) {
16219							that._createTrPlaceholder( that.currentItem, element );
16220						} else if ( nodeName === "img" ) {
16221							element.attr( "src", that.currentItem.attr( "src" ) );
16222						}
16223
16224						if ( !className ) {
16225							element.css( "visibility", "hidden" );
16226						}
16227
16228						return element;
16229					},
16230					update: function( container, p ) {
16231
16232						// 1. If a className is set as 'placeholder option, we don't force sizes -
16233						// the class is responsible for that
16234						// 2. The option 'forcePlaceholderSize can be enabled to force it even if a
16235						// class name is specified
16236						if ( className && !o.forcePlaceholderSize ) {
16237							return;
16238						}
16239
16240						// If the element doesn't have a actual height or width by itself (without
16241						// styles coming from a stylesheet), it receives the inline height and width
16242						// from the dragged item. Or, if it's a tbody or tr, it's going to have a height
16243						// anyway since we're populating them with <td>s above, but they're unlikely to
16244						// be the correct height on their own if the row heights are dynamic, so we'll
16245						// always assign the height of the dragged item given forcePlaceholderSize
16246						// is true.
16247						if ( !p.height() || ( o.forcePlaceholderSize &&
16248							( nodeName === "tbody" || nodeName === "tr" ) ) ) {
16249							p.height(
16250								that.currentItem.innerHeight() -
16251								parseInt( that.currentItem.css( "paddingTop" ) || 0, 10 ) -
16252								parseInt( that.currentItem.css( "paddingBottom" ) || 0, 10 ) );
16253						}
16254						if ( !p.width() ) {
16255							p.width(
16256								that.currentItem.innerWidth() -
16257								parseInt( that.currentItem.css( "paddingLeft" ) || 0, 10 ) -
16258								parseInt( that.currentItem.css( "paddingRight" ) || 0, 10 ) );
16259						}
16260					}
16261				};
16262			}
16263
16264			//Create the placeholder
16265			that.placeholder = $( o.placeholder.element.call( that.element, that.currentItem ) );
16266
16267			//Append it after the actual current item
16268			that.currentItem.after( that.placeholder );
16269
16270			//Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
16271			o.placeholder.update( that, that.placeholder );
16272
16273		},
16274
16275		_createTrPlaceholder: function( sourceTr, targetTr ) {
16276			var that = this;
16277
16278			sourceTr.children().each( function() {
16279				$( "<td>&#160;</td>", that.document[ 0 ] )
16280					.attr( "colspan", $( this ).attr( "colspan" ) || 1 )
16281					.appendTo( targetTr );
16282			} );
16283		},
16284
16285		_contactContainers: function( event ) {
16286			var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, cur, nearBottom,
16287				floating, axis,
16288				innermostContainer = null,
16289				innermostIndex = null;
16290
16291			// Get innermost container that intersects with item
16292			for ( i = this.containers.length - 1; i >= 0; i-- ) {
16293
16294				// Never consider a container that's located within the item itself
16295				if ( $.contains( this.currentItem[ 0 ], this.containers[ i ].element[ 0 ] ) ) {
16296					continue;
16297				}
16298
16299				if ( this._intersectsWith( this.containers[ i ].containerCache ) ) {
16300
16301					// If we've already found a container and it's more "inner" than this, then continue
16302					if ( innermostContainer &&
16303						$.contains(
16304							this.containers[ i ].element[ 0 ],
16305							innermostContainer.element[ 0 ] ) ) {
16306						continue;
16307					}
16308
16309					innermostContainer = this.containers[ i ];
16310					innermostIndex = i;
16311
16312				} else {
16313
16314					// container doesn't intersect. trigger "out" event if necessary
16315					if ( this.containers[ i ].containerCache.over ) {
16316						this.containers[ i ]._trigger( "out", event, this._uiHash( this ) );
16317						this.containers[ i ].containerCache.over = 0;
16318					}
16319				}
16320
16321			}
16322
16323			// If no intersecting containers found, return
16324			if ( !innermostContainer ) {
16325				return;
16326			}
16327
16328			// Move the item into the container if it's not there already
16329			if ( this.containers.length === 1 ) {
16330				if ( !this.containers[ innermostIndex ].containerCache.over ) {
16331					this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) );
16332					this.containers[ innermostIndex ].containerCache.over = 1;
16333				}
16334			} else {
16335
16336				// When entering a new container, we will find the item with the least distance and
16337				// append our item near it
16338				dist = 10000;
16339				itemWithLeastDistance = null;
16340				floating = innermostContainer.floating || this._isFloating( this.currentItem );
16341				posProperty = floating ? "left" : "top";
16342				sizeProperty = floating ? "width" : "height";
16343				axis = floating ? "pageX" : "pageY";
16344
16345				for ( j = this.items.length - 1; j >= 0; j-- ) {
16346					if ( !$.contains(
16347						this.containers[ innermostIndex ].element[ 0 ], this.items[ j ].item[ 0 ] )
16348					) {
16349						continue;
16350					}
16351					if ( this.items[ j ].item[ 0 ] === this.currentItem[ 0 ] ) {
16352						continue;
16353					}
16354
16355					cur = this.items[ j ].item.offset()[ posProperty ];
16356					nearBottom = false;
16357					if ( event[ axis ] - cur > this.items[ j ][ sizeProperty ] / 2 ) {
16358						nearBottom = true;
16359					}
16360
16361					if ( Math.abs( event[ axis ] - cur ) < dist ) {
16362						dist = Math.abs( event[ axis ] - cur );
16363						itemWithLeastDistance = this.items[ j ];
16364						this.direction = nearBottom ? "up" : "down";
16365					}
16366				}
16367
16368				//Check if dropOnEmpty is enabled
16369				if ( !itemWithLeastDistance && !this.options.dropOnEmpty ) {
16370					return;
16371				}
16372
16373				if ( this.currentContainer === this.containers[ innermostIndex ] ) {
16374					if ( !this.currentContainer.containerCache.over ) {
16375						this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash() );
16376						this.currentContainer.containerCache.over = 1;
16377					}
16378					return;
16379				}
16380
16381				if ( itemWithLeastDistance ) {
16382					this._rearrange( event, itemWithLeastDistance, null, true );
16383				} else {
16384					this._rearrange( event, null, this.containers[ innermostIndex ].element, true );
16385				}
16386				this._trigger( "change", event, this._uiHash() );
16387				this.containers[ innermostIndex ]._trigger( "change", event, this._uiHash( this ) );
16388				this.currentContainer = this.containers[ innermostIndex ];
16389
16390				//Update the placeholder
16391				this.options.placeholder.update( this.currentContainer, this.placeholder );
16392
16393				//Update scrollParent
16394				this.scrollParent = this.placeholder.scrollParent();
16395
16396				//Update overflowOffset
16397				if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
16398					this.scrollParent[ 0 ].tagName !== "HTML" ) {
16399					this.overflowOffset = this.scrollParent.offset();
16400				}
16401
16402				this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) );
16403				this.containers[ innermostIndex ].containerCache.over = 1;
16404			}
16405
16406		},
16407
16408		_createHelper: function( event ) {
16409
16410			var o = this.options,
16411				helper = typeof o.helper === "function" ?
16412					$( o.helper.apply( this.element[ 0 ], [ event, this.currentItem ] ) ) :
16413					( o.helper === "clone" ? this.currentItem.clone() : this.currentItem );
16414
16415			//Add the helper to the DOM if that didn't happen already
16416			if ( !helper.parents( "body" ).length ) {
16417				this.appendTo[ 0 ].appendChild( helper[ 0 ] );
16418			}
16419
16420			if ( helper[ 0 ] === this.currentItem[ 0 ] ) {
16421				this._storedCSS = {
16422					width: this.currentItem[ 0 ].style.width,
16423					height: this.currentItem[ 0 ].style.height,
16424					position: this.currentItem.css( "position" ),
16425					top: this.currentItem.css( "top" ),
16426					left: this.currentItem.css( "left" )
16427				};
16428			}
16429
16430			if ( !helper[ 0 ].style.width || o.forceHelperSize ) {
16431				helper.width( this.currentItem.width() );
16432			}
16433			if ( !helper[ 0 ].style.height || o.forceHelperSize ) {
16434				helper.height( this.currentItem.height() );
16435			}
16436
16437			return helper;
16438
16439		},
16440
16441		_adjustOffsetFromHelper: function( obj ) {
16442			if ( typeof obj === "string" ) {
16443				obj = obj.split( " " );
16444			}
16445			if ( Array.isArray( obj ) ) {
16446				obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 };
16447			}
16448			if ( "left" in obj ) {
16449				this.offset.click.left = obj.left + this.margins.left;
16450			}
16451			if ( "right" in obj ) {
16452				this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
16453			}
16454			if ( "top" in obj ) {
16455				this.offset.click.top = obj.top + this.margins.top;
16456			}
16457			if ( "bottom" in obj ) {
16458				this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
16459			}
16460		},
16461
16462		_getParentOffset: function() {
16463
16464			//Get the offsetParent and cache its position
16465			this.offsetParent = this.helper.offsetParent();
16466			var po = this.offsetParent.offset();
16467
16468			// This is a special case where we need to modify a offset calculated on start, since the
16469			// following happened:
16470			// 1. The position of the helper is absolute, so it's position is calculated based on the
16471			// next positioned parent
16472			// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't
16473			// the document, which means that the scroll is included in the initial calculation of the
16474			// offset of the parent, and never recalculated upon drag
16475			if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== this.document[ 0 ] &&
16476				$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) {
16477				po.left += this.scrollParent.scrollLeft();
16478				po.top += this.scrollParent.scrollTop();
16479			}
16480
16481			// This needs to be actually done for all browsers, since pageX/pageY includes
16482			// this information.
16483			if ( this.offsetParent[ 0 ] === this.document[ 0 ].body ) {
16484				po = { top: 0, left: 0 };
16485			}
16486
16487			return {
16488				top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ),
16489				left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 )
16490			};
16491
16492		},
16493
16494		_getRelativeOffset: function() {
16495
16496			if ( this.cssPosition === "relative" ) {
16497				var p = this.currentItem.position();
16498				return {
16499					top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) +
16500						this.scrollParent.scrollTop(),
16501					left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) +
16502						this.scrollParent.scrollLeft()
16503				};
16504			} else {
16505				return { top: 0, left: 0 };
16506			}
16507
16508		},
16509
16510		_cacheMargins: function() {
16511			this.margins = {
16512				left: ( parseInt( this.currentItem.css( "marginLeft" ), 10 ) || 0 ),
16513				top: ( parseInt( this.currentItem.css( "marginTop" ), 10 ) || 0 )
16514			};
16515		},
16516
16517		_cacheHelperProportions: function() {
16518			this.helperProportions = {
16519				width: this.helper.outerWidth(),
16520				height: this.helper.outerHeight()
16521			};
16522		},
16523
16524		_setContainment: function() {
16525
16526			var ce, co, over,
16527				o = this.options;
16528			if ( o.containment === "parent" ) {
16529				o.containment = this.helper[ 0 ].parentNode;
16530			}
16531			if ( o.containment === "document" || o.containment === "window" ) {
16532				this.containment = [
16533					0 - this.offset.relative.left - this.offset.parent.left,
16534					0 - this.offset.relative.top - this.offset.parent.top,
16535					o.containment === "document" ?
16536						this.document.width() :
16537						this.window.width() - this.helperProportions.width - this.margins.left,
16538					( o.containment === "document" ?
16539							( this.document.height() || document.body.parentNode.scrollHeight ) :
16540							this.window.height() || this.document[ 0 ].body.parentNode.scrollHeight
16541					) - this.helperProportions.height - this.margins.top
16542				];
16543			}
16544
16545			if ( !( /^(document|window|parent)$/ ).test( o.containment ) ) {
16546				ce = $( o.containment )[ 0 ];
16547				co = $( o.containment ).offset();
16548				over = ( $( ce ).css( "overflow" ) !== "hidden" );
16549
16550				this.containment = [
16551					co.left + ( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) +
16552					( parseInt( $( ce ).css( "paddingLeft" ), 10 ) || 0 ) - this.margins.left,
16553					co.top + ( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) +
16554					( parseInt( $( ce ).css( "paddingTop" ), 10 ) || 0 ) - this.margins.top,
16555					co.left + ( over ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -
16556					( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) -
16557					( parseInt( $( ce ).css( "paddingRight" ), 10 ) || 0 ) -
16558					this.helperProportions.width - this.margins.left,
16559					co.top + ( over ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -
16560					( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) -
16561					( parseInt( $( ce ).css( "paddingBottom" ), 10 ) || 0 ) -
16562					this.helperProportions.height - this.margins.top
16563				];
16564			}
16565
16566		},
16567
16568		_convertPositionTo: function( d, pos ) {
16569
16570			if ( !pos ) {
16571				pos = this.position;
16572			}
16573			var mod = d === "absolute" ? 1 : -1,
16574				scroll = this.cssPosition === "absolute" &&
16575				!( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
16576					$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ?
16577					this.offsetParent :
16578					this.scrollParent,
16579				scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName );
16580
16581			return {
16582				top: (
16583
16584					// The absolute mouse position
16585					pos.top	+
16586
16587					// Only for relative positioned nodes: Relative offset from element to offset parent
16588					this.offset.relative.top * mod +
16589
16590					// The offsetParent's offset without borders (offset + border)
16591					this.offset.parent.top * mod -
16592					( ( this.cssPosition === "fixed" ?
16593						-this.scrollParent.scrollTop() :
16594						( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod )
16595				),
16596				left: (
16597
16598					// The absolute mouse position
16599					pos.left +
16600
16601					// Only for relative positioned nodes: Relative offset from element to offset parent
16602					this.offset.relative.left * mod +
16603
16604					// The offsetParent's offset without borders (offset + border)
16605					this.offset.parent.left * mod	-
16606					( ( this.cssPosition === "fixed" ?
16607						-this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 :
16608							scroll.scrollLeft() ) * mod )
16609				)
16610			};
16611
16612		},
16613
16614		_generatePosition: function( event ) {
16615
16616			var top, left,
16617				o = this.options,
16618				pageX = event.pageX,
16619				pageY = event.pageY,
16620				scroll = this.cssPosition === "absolute" &&
16621				!( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
16622					$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ?
16623					this.offsetParent :
16624					this.scrollParent,
16625				scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName );
16626
16627			// This is another very weird special case that only happens for relative elements:
16628			// 1. If the css position is relative
16629			// 2. and the scroll parent is the document or similar to the offset parent
16630			// we have to refresh the relative offset during the scroll so there are no jumps
16631			if ( this.cssPosition === "relative" && !( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
16632				this.scrollParent[ 0 ] !== this.offsetParent[ 0 ] ) ) {
16633				this.offset.relative = this._getRelativeOffset();
16634			}
16635
16636			/*
16637		 * - Position constraining -
16638		 * Constrain the position to a mix of grid, containment.
16639		 */
16640
16641			if ( this.originalPosition ) { //If we are not dragging yet, we won't check for options
16642
16643				if ( this.containment ) {
16644					if ( event.pageX - this.offset.click.left < this.containment[ 0 ] ) {
16645						pageX = this.containment[ 0 ] + this.offset.click.left;
16646					}
16647					if ( event.pageY - this.offset.click.top < this.containment[ 1 ] ) {
16648						pageY = this.containment[ 1 ] + this.offset.click.top;
16649					}
16650					if ( event.pageX - this.offset.click.left > this.containment[ 2 ] ) {
16651						pageX = this.containment[ 2 ] + this.offset.click.left;
16652					}
16653					if ( event.pageY - this.offset.click.top > this.containment[ 3 ] ) {
16654						pageY = this.containment[ 3 ] + this.offset.click.top;
16655					}
16656				}
16657
16658				if ( o.grid ) {
16659					top = this.originalPageY + Math.round( ( pageY - this.originalPageY ) /
16660						o.grid[ 1 ] ) * o.grid[ 1 ];
16661					pageY = this.containment ?
16662						( ( top - this.offset.click.top >= this.containment[ 1 ] &&
16663							top - this.offset.click.top <= this.containment[ 3 ] ) ?
16664							top :
16665							( ( top - this.offset.click.top >= this.containment[ 1 ] ) ?
16666								top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) :
16667						top;
16668
16669					left = this.originalPageX + Math.round( ( pageX - this.originalPageX ) /
16670						o.grid[ 0 ] ) * o.grid[ 0 ];
16671					pageX = this.containment ?
16672						( ( left - this.offset.click.left >= this.containment[ 0 ] &&
16673							left - this.offset.click.left <= this.containment[ 2 ] ) ?
16674							left :
16675							( ( left - this.offset.click.left >= this.containment[ 0 ] ) ?
16676								left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) :
16677						left;
16678				}
16679
16680			}
16681
16682			return {
16683				top: (
16684
16685					// The absolute mouse position
16686					pageY -
16687
16688					// Click offset (relative to the element)
16689					this.offset.click.top -
16690
16691					// Only for relative positioned nodes: Relative offset from element to offset parent
16692					this.offset.relative.top -
16693
16694					// The offsetParent's offset without borders (offset + border)
16695					this.offset.parent.top +
16696					( ( this.cssPosition === "fixed" ?
16697						-this.scrollParent.scrollTop() :
16698						( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) )
16699				),
16700				left: (
16701
16702					// The absolute mouse position
16703					pageX -
16704
16705					// Click offset (relative to the element)
16706					this.offset.click.left -
16707
16708					// Only for relative positioned nodes: Relative offset from element to offset parent
16709					this.offset.relative.left -
16710
16711					// The offsetParent's offset without borders (offset + border)
16712					this.offset.parent.left +
16713					( ( this.cssPosition === "fixed" ?
16714						-this.scrollParent.scrollLeft() :
16715						scrollIsRootNode ? 0 : scroll.scrollLeft() ) )
16716				)
16717			};
16718
16719		},
16720
16721		_rearrange: function( event, i, a, hardRefresh ) {
16722
16723			if ( a ) {
16724				a[ 0 ].appendChild( this.placeholder[ 0 ] );
16725			} else {
16726				i.item[ 0 ].parentNode.insertBefore( this.placeholder[ 0 ],
16727					( this.direction === "down" ? i.item[ 0 ] : i.item[ 0 ].nextSibling ) );
16728			}
16729
16730			//Various things done here to improve the performance:
16731			// 1. we create a setTimeout, that calls refreshPositions
16732			// 2. on the instance, we have a counter variable, that get's higher after every append
16733			// 3. on the local scope, we copy the counter variable, and check in the timeout,
16734			// if it's still the same
16735			// 4. this lets only the last addition to the timeout stack through
16736			this.counter = this.counter ? ++this.counter : 1;
16737			var counter = this.counter;
16738
16739			this._delay( function() {
16740				if ( counter === this.counter ) {
16741
16742					//Precompute after each DOM insertion, NOT on mousemove
16743					this.refreshPositions( !hardRefresh );
16744				}
16745			} );
16746
16747		},
16748
16749		_clear: function( event, noPropagation ) {
16750
16751			this.reverting = false;
16752
16753			// We delay all events that have to be triggered to after the point where the placeholder
16754			// has been removed and everything else normalized again
16755			var i,
16756				delayedTriggers = [];
16757
16758			// We first have to update the dom position of the actual currentItem
16759			// Note: don't do it if the current item is already removed (by a user), or it gets
16760			// reappended (see #4088)
16761			if ( !this._noFinalSort && this.currentItem.parent().length ) {
16762				this.placeholder.before( this.currentItem );
16763			}
16764			this._noFinalSort = null;
16765
16766			if ( this.helper[ 0 ] === this.currentItem[ 0 ] ) {
16767				for ( i in this._storedCSS ) {
16768					if ( this._storedCSS[ i ] === "auto" || this._storedCSS[ i ] === "static" ) {
16769						this._storedCSS[ i ] = "";
16770					}
16771				}
16772				this.currentItem.css( this._storedCSS );
16773				this._removeClass( this.currentItem, "ui-sortable-helper" );
16774			} else {
16775				this.currentItem.show();
16776			}
16777
16778			if ( this.fromOutside && !noPropagation ) {
16779				delayedTriggers.push( function( event ) {
16780					this._trigger( "receive", event, this._uiHash( this.fromOutside ) );
16781				} );
16782			}
16783			if ( ( this.fromOutside ||
16784				this.domPosition.prev !==
16785				this.currentItem.prev().not( ".ui-sortable-helper" )[ 0 ] ||
16786				this.domPosition.parent !== this.currentItem.parent()[ 0 ] ) && !noPropagation ) {
16787
16788				// Trigger update callback if the DOM position has changed
16789				delayedTriggers.push( function( event ) {
16790					this._trigger( "update", event, this._uiHash() );
16791				} );
16792			}
16793
16794			// Check if the items Container has Changed and trigger appropriate
16795			// events.
16796			if ( this !== this.currentContainer ) {
16797				if ( !noPropagation ) {
16798					delayedTriggers.push( function( event ) {
16799						this._trigger( "remove", event, this._uiHash() );
16800					} );
16801					delayedTriggers.push( ( function( c ) {
16802						return function( event ) {
16803							c._trigger( "receive", event, this._uiHash( this ) );
16804						};
16805					} ).call( this, this.currentContainer ) );
16806					delayedTriggers.push( ( function( c ) {
16807						return function( event ) {
16808							c._trigger( "update", event, this._uiHash( this ) );
16809						};
16810					} ).call( this, this.currentContainer ) );
16811				}
16812			}
16813
16814			//Post events to containers
16815			function delayEvent( type, instance, container ) {
16816				return function( event ) {
16817					container._trigger( type, event, instance._uiHash( instance ) );
16818				};
16819			}
16820			for ( i = this.containers.length - 1; i >= 0; i-- ) {
16821				if ( !noPropagation ) {
16822					delayedTriggers.push( delayEvent( "deactivate", this, this.containers[ i ] ) );
16823				}
16824				if ( this.containers[ i ].containerCache.over ) {
16825					delayedTriggers.push( delayEvent( "out", this, this.containers[ i ] ) );
16826					this.containers[ i ].containerCache.over = 0;
16827				}
16828			}
16829
16830			//Do what was originally in plugins
16831			if ( this._storedStylesheet ) {
16832				this._storedStylesheet.remove();
16833				this._storedStylesheet = null;
16834			}
16835			if ( this._storedOpacity ) {
16836				this.helper.css( "opacity", this._storedOpacity );
16837			}
16838			if ( this._storedZIndex ) {
16839				this.helper.css( "zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex );
16840			}
16841
16842			this.dragging = false;
16843
16844			if ( !noPropagation ) {
16845				this._trigger( "beforeStop", event, this._uiHash() );
16846			}
16847
16848			//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately,
16849			// it unbinds ALL events from the original node!
16850			this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] );
16851
16852			if ( !this.cancelHelperRemoval ) {
16853				if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {
16854					this.helper.remove();
16855				}
16856				this.helper = null;
16857			}
16858
16859			if ( !noPropagation ) {
16860				for ( i = 0; i < delayedTriggers.length; i++ ) {
16861
16862					// Trigger all delayed events
16863					delayedTriggers[ i ].call( this, event );
16864				}
16865				this._trigger( "stop", event, this._uiHash() );
16866			}
16867
16868			this.fromOutside = false;
16869			return !this.cancelHelperRemoval;
16870
16871		},
16872
16873		_trigger: function() {
16874			if ( $.Widget.prototype._trigger.apply( this, arguments ) === false ) {
16875				this.cancel();
16876			}
16877		},
16878
16879		_uiHash: function( _inst ) {
16880			var inst = _inst || this;
16881			return {
16882				helper: inst.helper,
16883				placeholder: inst.placeholder || $( [] ),
16884				position: inst.position,
16885				originalPosition: inst.originalPosition,
16886				offset: inst.positionAbs,
16887				item: inst.currentItem,
16888				sender: _inst ? _inst.element : null
16889			};
16890		}
16891
16892	} );
16893
16894
16895	/*!
16896 * jQuery UI Spinner 1.14.1
16897 * https://jqueryui.com
16898 *
16899 * Copyright OpenJS Foundation and other contributors
16900 * Released under the MIT license.
16901 * https://jquery.org/license
16902 */
16903
16904//>>label: Spinner
16905//>>group: Widgets
16906//>>description: Displays buttons to easily input numbers via the keyboard or mouse.
16907//>>docs: https://api.jqueryui.com/spinner/
16908//>>demos: https://jqueryui.com/spinner/
16909//>>css.structure: ../../themes/base/core.css
16910//>>css.structure: ../../themes/base/spinner.css
16911//>>css.theme: ../../themes/base/theme.css
16912
16913
16914	function spinnerModifier( fn ) {
16915		return function() {
16916			var previous = this.element.val();
16917			fn.apply( this, arguments );
16918			this._refresh();
16919			if ( previous !== this.element.val() ) {
16920				this._trigger( "change" );
16921			}
16922		};
16923	}
16924
16925	$.widget( "ui.spinner", {
16926		version: "1.14.1",
16927		defaultElement: "<input>",
16928		widgetEventPrefix: "spin",
16929		options: {
16930			classes: {
16931				"ui-spinner": "ui-corner-all",
16932				"ui-spinner-down": "ui-corner-br",
16933				"ui-spinner-up": "ui-corner-tr"
16934			},
16935			culture: null,
16936			icons: {
16937				down: "ui-icon-triangle-1-s",
16938				up: "ui-icon-triangle-1-n"
16939			},
16940			incremental: true,
16941			max: null,
16942			min: null,
16943			numberFormat: null,
16944			page: 10,
16945			step: 1,
16946
16947			change: null,
16948			spin: null,
16949			start: null,
16950			stop: null
16951		},
16952
16953		_create: function() {
16954
16955			// handle string values that need to be parsed
16956			this._setOption( "max", this.options.max );
16957			this._setOption( "min", this.options.min );
16958			this._setOption( "step", this.options.step );
16959
16960			// Only format if there is a value, prevents the field from being marked
16961			// as invalid in Firefox, see #9573.
16962			if ( this.value() !== "" ) {
16963
16964				// Format the value, but don't constrain.
16965				this._value( this.element.val(), true );
16966			}
16967
16968			this._draw();
16969			this._on( this._events );
16970			this._refresh();
16971
16972			// Turning off autocomplete prevents the browser from remembering the
16973			// value when navigating through history, so we re-enable autocomplete
16974			// if the page is unloaded before the widget is destroyed. #7790
16975			this._on( this.window, {
16976				beforeunload: function() {
16977					this.element.removeAttr( "autocomplete" );
16978				}
16979			} );
16980		},
16981
16982		_getCreateOptions: function() {
16983			var options = this._super();
16984			var element = this.element;
16985
16986			$.each( [ "min", "max", "step" ], function( i, option ) {
16987				var value = element.attr( option );
16988				if ( value != null && value.length ) {
16989					options[ option ] = value;
16990				}
16991			} );
16992
16993			return options;
16994		},
16995
16996		_events: {
16997			keydown: function( event ) {
16998				if ( this._start( event ) && this._keydown( event ) ) {
16999					event.preventDefault();
17000				}
17001			},
17002			keyup: "_stop",
17003			focus: function() {
17004				this.previous = this.element.val();
17005			},
17006			blur: function( event ) {
17007				this._stop();
17008				this._refresh();
17009				if ( this.previous !== this.element.val() ) {
17010					this._trigger( "change", event );
17011				}
17012			},
17013			mousewheel: function( event, delta ) {
17014				var activeElement = this.document[ 0 ].activeElement;
17015				var isActive = this.element[ 0 ] === activeElement;
17016
17017				if ( !isActive || !delta ) {
17018					return;
17019				}
17020
17021				if ( !this.spinning && !this._start( event ) ) {
17022					return false;
17023				}
17024
17025				this._spin( ( delta > 0 ? 1 : -1 ) * this.options.step, event );
17026				clearTimeout( this.mousewheelTimer );
17027				this.mousewheelTimer = this._delay( function() {
17028					if ( this.spinning ) {
17029						this._stop( event );
17030					}
17031				}, 100 );
17032				event.preventDefault();
17033			},
17034			"mousedown .ui-spinner-button": function( event ) {
17035				var previous;
17036
17037				// We never want the buttons to have focus; whenever the user is
17038				// interacting with the spinner, the focus should be on the input.
17039				// If the input is focused then this.previous is properly set from
17040				// when the input first received focus. If the input is not focused
17041				// then we need to set this.previous based on the value before spinning.
17042				previous = this.element[ 0 ] === this.document[ 0 ].activeElement ?
17043					this.previous : this.element.val();
17044				function checkFocus() {
17045					var isActive = this.element[ 0 ] === this.document[ 0 ].activeElement;
17046					if ( !isActive ) {
17047						this.element.trigger( "focus" );
17048						this.previous = previous;
17049					}
17050				}
17051
17052				// Ensure focus is on (or stays on) the text field
17053				event.preventDefault();
17054				checkFocus.call( this );
17055
17056				if ( this._start( event ) === false ) {
17057					return;
17058				}
17059
17060				this._repeat( null, $( event.currentTarget )
17061					.hasClass( "ui-spinner-up" ) ? 1 : -1, event );
17062			},
17063			"mouseup .ui-spinner-button": "_stop",
17064			"mouseenter .ui-spinner-button": function( event ) {
17065
17066				// button will add ui-state-active if mouse was down while mouseleave and kept down
17067				if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) {
17068					return;
17069				}
17070
17071				if ( this._start( event ) === false ) {
17072					return false;
17073				}
17074				this._repeat( null, $( event.currentTarget )
17075					.hasClass( "ui-spinner-up" ) ? 1 : -1, event );
17076			},
17077
17078			// TODO: do we really want to consider this a stop?
17079			// shouldn't we just stop the repeater and wait until mouseup before
17080			// we trigger the stop event?
17081			"mouseleave .ui-spinner-button": "_stop"
17082		},
17083
17084		// Support mobile enhanced option and make backcompat more sane
17085		_enhance: function() {
17086			this.uiSpinner = this.element
17087				.attr( "autocomplete", "off" )
17088				.wrap( "<span>" )
17089				.parent()
17090
17091				// Add buttons
17092				.append(
17093					"<a></a><a></a>"
17094				);
17095		},
17096
17097		_draw: function() {
17098			this._enhance();
17099
17100			this._addClass( this.uiSpinner, "ui-spinner", "ui-widget ui-widget-content" );
17101			this._addClass( "ui-spinner-input" );
17102
17103			this.element.attr( "role", "spinbutton" );
17104
17105			// Button bindings
17106			this.buttons = this.uiSpinner.children( "a" )
17107				.attr( "tabIndex", -1 )
17108				.attr( "aria-hidden", true )
17109				.button( {
17110					classes: {
17111						"ui-button": ""
17112					}
17113				} );
17114
17115			// TODO: Right now button does not support classes this is already updated in button PR
17116			this._removeClass( this.buttons, "ui-corner-all" );
17117
17118			this._addClass( this.buttons.first(), "ui-spinner-button ui-spinner-up" );
17119			this._addClass( this.buttons.last(), "ui-spinner-button ui-spinner-down" );
17120			this.buttons.first().button( {
17121				"icon": this.options.icons.up,
17122				"showLabel": false
17123			} );
17124			this.buttons.last().button( {
17125				"icon": this.options.icons.down,
17126				"showLabel": false
17127			} );
17128
17129			// IE 6 doesn't understand height: 50% for the buttons
17130			// unless the wrapper has an explicit height
17131			if ( this.buttons.height() > Math.ceil( this.uiSpinner.height() * 0.5 ) &&
17132				this.uiSpinner.height() > 0 ) {
17133				this.uiSpinner.height( this.uiSpinner.height() );
17134			}
17135		},
17136
17137		_keydown: function( event ) {
17138			var options = this.options,
17139				keyCode = $.ui.keyCode;
17140
17141			switch ( event.keyCode ) {
17142				case keyCode.UP:
17143					this._repeat( null, 1, event );
17144					return true;
17145				case keyCode.DOWN:
17146					this._repeat( null, -1, event );
17147					return true;
17148				case keyCode.PAGE_UP:
17149					this._repeat( null, options.page, event );
17150					return true;
17151				case keyCode.PAGE_DOWN:
17152					this._repeat( null, -options.page, event );
17153					return true;
17154			}
17155
17156			return false;
17157		},
17158
17159		_start: function( event ) {
17160			if ( !this.spinning && this._trigger( "start", event ) === false ) {
17161				return false;
17162			}
17163
17164			if ( !this.counter ) {
17165				this.counter = 1;
17166			}
17167			this.spinning = true;
17168			return true;
17169		},
17170
17171		_repeat: function( i, steps, event ) {
17172			i = i || 500;
17173
17174			clearTimeout( this.timer );
17175			this.timer = this._delay( function() {
17176				this._repeat( 40, steps, event );
17177			}, i );
17178
17179			this._spin( steps * this.options.step, event );
17180		},
17181
17182		_spin: function( step, event ) {
17183			var value = this.value() || 0;
17184
17185			if ( !this.counter ) {
17186				this.counter = 1;
17187			}
17188
17189			value = this._adjustValue( value + step * this._increment( this.counter ) );
17190
17191			if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false ) {
17192				this._value( value );
17193				this.counter++;
17194			}
17195		},
17196
17197		_increment: function( i ) {
17198			var incremental = this.options.incremental;
17199
17200			if ( incremental ) {
17201				return typeof incremental === "function" ?
17202					incremental( i ) :
17203					Math.floor( i * i * i / 50000 - i * i / 500 + 17 * i / 200 + 1 );
17204			}
17205
17206			return 1;
17207		},
17208
17209		_precision: function() {
17210			var precision = this._precisionOf( this.options.step );
17211			if ( this.options.min !== null ) {
17212				precision = Math.max( precision, this._precisionOf( this.options.min ) );
17213			}
17214			return precision;
17215		},
17216
17217		_precisionOf: function( num ) {
17218			var str = num.toString(),
17219				decimal = str.indexOf( "." );
17220			return decimal === -1 ? 0 : str.length - decimal - 1;
17221		},
17222
17223		_adjustValue: function( value ) {
17224			var base, aboveMin,
17225				options = this.options;
17226
17227			// Make sure we're at a valid step
17228			// - find out where we are relative to the base (min or 0)
17229			base = options.min !== null ? options.min : 0;
17230			aboveMin = value - base;
17231
17232			// - round to the nearest step
17233			aboveMin = Math.round( aboveMin / options.step ) * options.step;
17234
17235			// - rounding is based on 0, so adjust back to our base
17236			value = base + aboveMin;
17237
17238			// Fix precision from bad JS floating point math
17239			value = parseFloat( value.toFixed( this._precision() ) );
17240
17241			// Clamp the value
17242			if ( options.max !== null && value > options.max ) {
17243				return options.max;
17244			}
17245			if ( options.min !== null && value < options.min ) {
17246				return options.min;
17247			}
17248
17249			return value;
17250		},
17251
17252		_stop: function( event ) {
17253			if ( !this.spinning ) {
17254				return;
17255			}
17256
17257			clearTimeout( this.timer );
17258			clearTimeout( this.mousewheelTimer );
17259			this.counter = 0;
17260			this.spinning = false;
17261			this._trigger( "stop", event );
17262		},
17263
17264		_setOption: function( key, value ) {
17265			var prevValue, first, last;
17266
17267			if ( key === "culture" || key === "numberFormat" ) {
17268				prevValue = this._parse( this.element.val() );
17269				this.options[ key ] = value;
17270				this.element.val( this._format( prevValue ) );
17271				return;
17272			}
17273
17274			if ( key === "max" || key === "min" || key === "step" ) {
17275				if ( typeof value === "string" ) {
17276					value = this._parse( value );
17277				}
17278			}
17279			if ( key === "icons" ) {
17280				first = this.buttons.first().find( ".ui-icon" );
17281				this._removeClass( first, null, this.options.icons.up );
17282				this._addClass( first, null, value.up );
17283				last = this.buttons.last().find( ".ui-icon" );
17284				this._removeClass( last, null, this.options.icons.down );
17285				this._addClass( last, null, value.down );
17286			}
17287
17288			this._super( key, value );
17289		},
17290
17291		_setOptionDisabled: function( value ) {
17292			this._super( value );
17293
17294			this._toggleClass( this.uiSpinner, null, "ui-state-disabled", !!value );
17295			this.element.prop( "disabled", !!value );
17296			this.buttons.button( value ? "disable" : "enable" );
17297		},
17298
17299		_setOptions: spinnerModifier( function( options ) {
17300			this._super( options );
17301		} ),
17302
17303		_parse: function( val ) {
17304			if ( typeof val === "string" && val !== "" ) {
17305				val = window.Globalize && this.options.numberFormat ?
17306					Globalize.parseFloat( val, 10, this.options.culture ) : +val;
17307			}
17308			return val === "" || isNaN( val ) ? null : val;
17309		},
17310
17311		_format: function( value ) {
17312			if ( value === "" ) {
17313				return "";
17314			}
17315			return window.Globalize && this.options.numberFormat ?
17316				Globalize.format( value, this.options.numberFormat, this.options.culture ) :
17317				value;
17318		},
17319
17320		_refresh: function() {
17321			this.element.attr( {
17322				"aria-valuemin": this.options.min,
17323				"aria-valuemax": this.options.max,
17324
17325				// TODO: what should we do with values that can't be parsed?
17326				"aria-valuenow": this._parse( this.element.val() )
17327			} );
17328		},
17329
17330		isValid: function() {
17331			var value = this.value();
17332
17333			// Null is invalid
17334			if ( value === null ) {
17335				return false;
17336			}
17337
17338			// If value gets adjusted, it's invalid
17339			return value === this._adjustValue( value );
17340		},
17341
17342		// Update the value without triggering change
17343		_value: function( value, allowAny ) {
17344			var parsed;
17345			if ( value !== "" ) {
17346				parsed = this._parse( value );
17347				if ( parsed !== null ) {
17348					if ( !allowAny ) {
17349						parsed = this._adjustValue( parsed );
17350					}
17351					value = this._format( parsed );
17352				}
17353			}
17354			this.element.val( value );
17355			this._refresh();
17356		},
17357
17358		_destroy: function() {
17359			this.element
17360				.prop( "disabled", false )
17361				.removeAttr( "autocomplete role aria-valuemin aria-valuemax aria-valuenow" );
17362
17363			this.uiSpinner.replaceWith( this.element );
17364		},
17365
17366		stepUp: spinnerModifier( function( steps ) {
17367			this._stepUp( steps );
17368		} ),
17369		_stepUp: function( steps ) {
17370			if ( this._start() ) {
17371				this._spin( ( steps || 1 ) * this.options.step );
17372				this._stop();
17373			}
17374		},
17375
17376		stepDown: spinnerModifier( function( steps ) {
17377			this._stepDown( steps );
17378		} ),
17379		_stepDown: function( steps ) {
17380			if ( this._start() ) {
17381				this._spin( ( steps || 1 ) * -this.options.step );
17382				this._stop();
17383			}
17384		},
17385
17386		pageUp: spinnerModifier( function( pages ) {
17387			this._stepUp( ( pages || 1 ) * this.options.page );
17388		} ),
17389
17390		pageDown: spinnerModifier( function( pages ) {
17391			this._stepDown( ( pages || 1 ) * this.options.page );
17392		} ),
17393
17394		value: function( newVal ) {
17395			if ( !arguments.length ) {
17396				return this._parse( this.element.val() );
17397			}
17398			spinnerModifier( this._value ).call( this, newVal );
17399		},
17400
17401		widget: function() {
17402			return this.uiSpinner;
17403		}
17404	} );
17405
17406// DEPRECATED
17407// TODO: switch return back to widget declaration at top of file when this is removed
17408	if ( $.uiBackCompat === true ) {
17409
17410		// Backcompat for spinner html extension points
17411		$.widget( "ui.spinner", $.ui.spinner, {
17412			_enhance: function() {
17413				this.uiSpinner = this.element
17414					.attr( "autocomplete", "off" )
17415					.wrap( this._uiSpinnerHtml() )
17416					.parent()
17417
17418					// Add buttons
17419					.append( this._buttonHtml() );
17420			},
17421			_uiSpinnerHtml: function() {
17422				return "<span>";
17423			},
17424
17425			_buttonHtml: function() {
17426				return "<a></a><a></a>";
17427			}
17428		} );
17429	}
17430
17431	var widgetsSpinner = $.ui.spinner;
17432
17433
17434	/*!
17435 * jQuery UI Tabs 1.14.1
17436 * https://jqueryui.com
17437 *
17438 * Copyright OpenJS Foundation and other contributors
17439 * Released under the MIT license.
17440 * https://jquery.org/license
17441 */
17442
17443//>>label: Tabs
17444//>>group: Widgets
17445//>>description: Transforms a set of container elements into a tab structure.
17446//>>docs: https://api.jqueryui.com/tabs/
17447//>>demos: https://jqueryui.com/tabs/
17448//>>css.structure: ../../themes/base/core.css
17449//>>css.structure: ../../themes/base/tabs.css
17450//>>css.theme: ../../themes/base/theme.css
17451
17452
17453	$.widget( "ui.tabs", {
17454		version: "1.14.1",
17455		delay: 300,
17456		options: {
17457			active: null,
17458			classes: {
17459				"ui-tabs": "ui-corner-all",
17460				"ui-tabs-nav": "ui-corner-all",
17461				"ui-tabs-panel": "ui-corner-bottom",
17462				"ui-tabs-tab": "ui-corner-top"
17463			},
vendor: 7,426 bytes, lines 17464-17742
17464			collapsible: false,
17465			event: "click",
17466			heightStyle: "content",
17467			hide: null,
17468			show: null,
17469
17470			// Callbacks
17471			activate: null,
17472			beforeActivate: null,
17473			beforeLoad: null,
17474			load: null
17475		},
17476
17477		_isLocal: ( function() {
17478			var rhash = /#.*$/;
17479
17480			return function( anchor ) {
17481				var anchorUrl, locationUrl;
17482
17483				anchorUrl = anchor.href.replace( rhash, "" );
17484				locationUrl = location.href.replace( rhash, "" );
17485
17486				// Decoding may throw an error if the URL isn't UTF-8 (#9518)
17487				try {
17488					anchorUrl = decodeURIComponent( anchorUrl );
17489				} catch ( error ) {}
17490				try {
17491					locationUrl = decodeURIComponent( locationUrl );
17492				} catch ( error ) {}
17493
17494				return anchor.hash.length > 1 && anchorUrl === locationUrl;
17495			};
17496		} )(),
17497
17498		_create: function() {
17499			var that = this,
17500				options = this.options;
17501
17502			this.running = false;
17503
17504			this._addClass( "ui-tabs", "ui-widget ui-widget-content" );
17505			this._toggleClass( "ui-tabs-collapsible", null, options.collapsible );
17506
17507			this._processTabs();
17508			options.active = this._initialActive();
17509
17510			// Take disabling tabs via class attribute from HTML
17511			// into account and update option properly.
17512			if ( Array.isArray( options.disabled ) ) {
17513				options.disabled = $.uniqueSort( options.disabled.concat(
17514					$.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) {
17515						return that.tabs.index( li );
17516					} )
17517				) ).sort();
17518			}
17519
17520			// Check for length avoids error when initializing empty list
17521			if ( this.options.active !== false && this.anchors.length ) {
17522				this.active = this._findActive( options.active );
17523			} else {
17524				this.active = $();
17525			}
17526
17527			this._refresh();
17528
17529			if ( this.active.length ) {
17530				this.load( options.active );
17531			}
17532		},
17533
17534		_initialActive: function() {
17535			var active = this.options.active,
17536				collapsible = this.options.collapsible,
17537				locationHashDecoded = decodeURIComponent( location.hash.substring( 1 ) );
17538
17539			if ( active === null ) {
17540
17541				// check the fragment identifier in the URL
17542				if ( locationHashDecoded ) {
17543					this.tabs.each( function( i, tab ) {
17544						if ( $( tab ).attr( "aria-controls" ) === locationHashDecoded ) {
17545							active = i;
17546							return false;
17547						}
17548					} );
17549				}
17550
17551				// Check for a tab marked active via a class
17552				if ( active === null ) {
17553					active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) );
17554				}
17555
17556				// No active tab, set to false
17557				if ( active === null || active === -1 ) {
17558					active = this.tabs.length ? 0 : false;
17559				}
17560			}
17561
17562			// Handle numbers: negative, out of range
17563			if ( active !== false ) {
17564				active = this.tabs.index( this.tabs.eq( active ) );
17565				if ( active === -1 ) {
17566					active = collapsible ? false : 0;
17567				}
17568			}
17569
17570			// Don't allow collapsible: false and active: false
17571			if ( !collapsible && active === false && this.anchors.length ) {
17572				active = 0;
17573			}
17574
17575			return active;
17576		},
17577
17578		_getCreateEventData: function() {
17579			return {
17580				tab: this.active,
17581				panel: !this.active.length ? $() : this._getPanelForTab( this.active )
17582			};
17583		},
17584
17585		_tabKeydown: function( event ) {
17586			var focusedTab = $( this.document[ 0 ].activeElement ).closest( "li" ),
17587				selectedIndex = this.tabs.index( focusedTab ),
17588				goingForward = true;
17589
17590			if ( this._handlePageNav( event ) ) {
17591				return;
17592			}
17593
17594			switch ( event.keyCode ) {
17595				case $.ui.keyCode.RIGHT:
17596				case $.ui.keyCode.DOWN:
17597					selectedIndex++;
17598					break;
17599				case $.ui.keyCode.UP:
17600				case $.ui.keyCode.LEFT:
17601					goingForward = false;
17602					selectedIndex--;
17603					break;
17604				case $.ui.keyCode.END:
17605					selectedIndex = this.anchors.length - 1;
17606					break;
17607				case $.ui.keyCode.HOME:
17608					selectedIndex = 0;
17609					break;
17610				case $.ui.keyCode.SPACE:
17611
17612					// Activate only, no collapsing
17613					event.preventDefault();
17614					clearTimeout( this.activating );
17615					this._activate( selectedIndex );
17616					return;
17617				case $.ui.keyCode.ENTER:
17618
17619					// Toggle (cancel delayed activation, allow collapsing)
17620					event.preventDefault();
17621					clearTimeout( this.activating );
17622
17623					// Determine if we should collapse or activate
17624					this._activate( selectedIndex === this.options.active ? false : selectedIndex );
17625					return;
17626				default:
17627					return;
17628			}
17629
17630			// Focus the appropriate tab, based on which key was pressed
17631			event.preventDefault();
17632			clearTimeout( this.activating );
17633			selectedIndex = this._focusNextTab( selectedIndex, goingForward );
17634
17635			// Navigating with control/command key will prevent automatic activation
17636			if ( !event.ctrlKey && !event.metaKey ) {
17637
17638				// Update aria-selected immediately so that AT think the tab is already selected.
17639				// Otherwise AT may confuse the user by stating that they need to activate the tab,
17640				// but the tab will already be activated by the time the announcement finishes.
17641				focusedTab.attr( "aria-selected", "false" );
17642				this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" );
17643
17644				this.activating = this._delay( function() {
17645					this.option( "active", selectedIndex );
17646				}, this.delay );
17647			}
17648		},
17649
17650		_panelKeydown: function( event ) {
17651			if ( this._handlePageNav( event ) ) {
17652				return;
17653			}
17654
17655			// Ctrl+up moves focus to the current tab
17656			if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {
17657				event.preventDefault();
17658				this.active.trigger( "focus" );
17659			}
17660		},
17661
17662		// Alt+page up/down moves focus to the previous/next tab (and activates)
17663		_handlePageNav: function( event ) {
17664			if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {
17665				this._activate( this._focusNextTab( this.options.active - 1, false ) );
17666				return true;
17667			}
17668			if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {
17669				this._activate( this._focusNextTab( this.options.active + 1, true ) );
17670				return true;
17671			}
17672		},
17673
17674		_findNextTab: function( index, goingForward ) {
17675			var lastTabIndex = this.tabs.length - 1;
17676
17677			function constrain() {
17678				if ( index > lastTabIndex ) {
17679					index = 0;
17680				}
17681				if ( index < 0 ) {
17682					index = lastTabIndex;
17683				}
17684				return index;
17685			}
17686
17687			while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {
17688				index = goingForward ? index + 1 : index - 1;
17689			}
17690
17691			return index;
17692		},
17693
17694		_focusNextTab: function( index, goingForward ) {
17695			index = this._findNextTab( index, goingForward );
17696			this.tabs.eq( index ).trigger( "focus" );
17697			return index;
17698		},
17699
17700		_setOption: function( key, value ) {
17701			if ( key === "active" ) {
17702
17703				// _activate() will handle invalid values and update this.options
17704				this._activate( value );
17705				return;
17706			}
17707
17708			this._super( key, value );
17709
17710			if ( key === "collapsible" ) {
17711				this._toggleClass( "ui-tabs-collapsible", null, value );
17712
17713				// Setting collapsible: false while collapsed; open first panel
17714				if ( !value && this.options.active === false ) {
17715					this._activate( 0 );
17716				}
17717			}
17718
17719			if ( key === "event" ) {
17720				this._setupEvents( value );
17721			}
17722
17723			if ( key === "heightStyle" ) {
17724				this._setupHeightStyle( value );
17725			}
17726		},
17727
17728		refresh: function() {
17729			var options = this.options,
17730				lis = this.tablist.children( ":has(a[href])" );
17731
17732			// Get disabled tabs from class attribute from HTML
17733			// this will get converted to a boolean if needed in _refresh()
17734			options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) {
17735				return lis.index( tab );
17736			} );
17737
17738			this._processTabs();
17739
17740			// Was collapsed or no tabs
17741			if ( options.active === false || !this.anchors.length ) {
17742				options.active = false;
vendor: 29,075 bytes, lines 17743-18809
17743				this.active = $();
17744
17745				// was active, but active tab is gone
17746			} else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {
17747
17748				// all remaining tabs are disabled
17749				if ( this.tabs.length === options.disabled.length ) {
17750					options.active = false;
17751					this.active = $();
17752
17753					// activate previous tab
17754				} else {
17755					this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );
17756				}
17757
17758				// was active, active tab still exists
17759			} else {
17760
17761				// make sure active index is correct
17762				options.active = this.tabs.index( this.active );
17763			}
17764
17765			this._refresh();
17766		},
17767
17768		_refresh: function() {
17769			this._setOptionDisabled( this.options.disabled );
17770			this._setupEvents( this.options.event );
17771			this._setupHeightStyle( this.options.heightStyle );
17772
17773			this.tabs.not( this.active ).attr( {
17774				"aria-selected": "false",
17775				"aria-expanded": "false",
17776				tabIndex: -1
17777			} );
17778			this.panels.not( this._getPanelForTab( this.active ) )
17779				.hide()
17780				.attr( {
17781					"aria-hidden": "true"
17782				} );
17783
17784			// Make sure one tab is in the tab order
17785			if ( !this.active.length ) {
17786				this.tabs.eq( 0 ).attr( "tabIndex", 0 );
17787			} else {
17788				this.active
17789					.attr( {
17790						"aria-selected": "true",
17791						"aria-expanded": "true",
17792						tabIndex: 0
17793					} );
17794				this._addClass( this.active, "ui-tabs-active", "ui-state-active" );
17795				this._getPanelForTab( this.active )
17796					.show()
17797					.attr( {
17798						"aria-hidden": "false"
17799					} );
17800			}
17801		},
17802
17803		_processTabs: function() {
17804			var that = this,
17805				prevTabs = this.tabs,
17806				prevAnchors = this.anchors,
17807				prevPanels = this.panels;
17808
17809			this.tablist = this._getList().attr( "role", "tablist" );
17810			this._addClass( this.tablist, "ui-tabs-nav",
17811				"ui-helper-reset ui-helper-clearfix ui-widget-header" );
17812
17813			// Prevent users from focusing disabled tabs via click
17814			this.tablist
17815				.on( "mousedown" + this.eventNamespace, "> li", function( event ) {
17816					if ( $( this ).is( ".ui-state-disabled" ) ) {
17817						event.preventDefault();
17818					}
17819				} );
17820
17821			this.tabs = this.tablist.find( "> li:has(a[href])" )
17822				.attr( {
17823					role: "tab",
17824					tabIndex: -1
17825				} );
17826			this._addClass( this.tabs, "ui-tabs-tab", "ui-state-default" );
17827
17828			this.anchors = this.tabs.map( function() {
17829				return $( "a", this )[ 0 ];
17830			} )
17831				.attr( {
17832					tabIndex: -1
17833				} );
17834			this._addClass( this.anchors, "ui-tabs-anchor" );
17835
17836			this.panels = $();
17837
17838			this.anchors.each( function( i, anchor ) {
17839				var selector, panel, panelId,
17840					anchorId = $( anchor ).uniqueId().attr( "id" ),
17841					tab = $( anchor ).closest( "li" ),
17842					originalAriaControls = tab.attr( "aria-controls" );
17843
17844				// Inline tab
17845				if ( that._isLocal( anchor ) ) {
17846					selector = decodeURIComponent( anchor.hash );
17847					panelId = selector.substring( 1 );
17848					panel = that.element.find( "#" + CSS.escape( panelId ) );
17849
17850					// remote tab
17851				} else {
17852
17853					// If the tab doesn't already have aria-controls,
17854					// generate an id by using a throw-away element
17855					panelId = tab.attr( "aria-controls" ) || $( {} ).uniqueId()[ 0 ].id;
17856					selector = "#" + panelId;
17857					panel = that.element.find( selector );
17858					if ( !panel.length ) {
17859						panel = that._createPanel( panelId );
17860						panel.insertAfter( that.panels[ i - 1 ] || that.tablist );
17861					}
17862					panel.attr( "aria-live", "polite" );
17863				}
17864
17865				if ( panel.length ) {
17866					that.panels = that.panels.add( panel );
17867				}
17868				if ( originalAriaControls ) {
17869					tab.data( "ui-tabs-aria-controls", originalAriaControls );
17870				}
17871				tab.attr( {
17872					"aria-controls": panelId,
17873					"aria-labelledby": anchorId
17874				} );
17875				panel.attr( "aria-labelledby", anchorId );
17876			} );
17877
17878			this.panels.attr( "role", "tabpanel" );
17879			this._addClass( this.panels, "ui-tabs-panel", "ui-widget-content" );
17880
17881			// Avoid memory leaks (#10056)
17882			if ( prevTabs ) {
17883				this._off( prevTabs.not( this.tabs ) );
17884				this._off( prevAnchors.not( this.anchors ) );
17885				this._off( prevPanels.not( this.panels ) );
17886			}
17887		},
17888
17889		// Allow overriding how to find the list for rare usage scenarios (#7715)
17890		_getList: function() {
17891			return this.tablist || this.element.find( "ol, ul" ).eq( 0 );
17892		},
17893
17894		_createPanel: function( id ) {
17895			return $( "<div>" )
17896				.attr( "id", id )
17897				.data( "ui-tabs-destroy", true );
17898		},
17899
17900		_setOptionDisabled: function( disabled ) {
17901			var currentItem, li, i;
17902
17903			if ( Array.isArray( disabled ) ) {
17904				if ( !disabled.length ) {
17905					disabled = false;
17906				} else if ( disabled.length === this.anchors.length ) {
17907					disabled = true;
17908				}
17909			}
17910
17911			// Disable tabs
17912			for ( i = 0; ( li = this.tabs[ i ] ); i++ ) {
17913				currentItem = $( li );
17914				if ( disabled === true || $.inArray( i, disabled ) !== -1 ) {
17915					currentItem.attr( "aria-disabled", "true" );
17916					this._addClass( currentItem, null, "ui-state-disabled" );
17917				} else {
17918					currentItem.removeAttr( "aria-disabled" );
17919					this._removeClass( currentItem, null, "ui-state-disabled" );
17920				}
17921			}
17922
17923			this.options.disabled = disabled;
17924
17925			this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null,
17926				disabled === true );
17927		},
17928
17929		_setupEvents: function( event ) {
17930			var events = {};
17931			if ( event ) {
17932				$.each( event.split( " " ), function( index, eventName ) {
17933					events[ eventName ] = "_eventHandler";
17934				} );
17935			}
17936
17937			this._off( this.anchors.add( this.tabs ).add( this.panels ) );
17938
17939			// Always prevent the default action, even when disabled
17940			this._on( true, this.anchors, {
17941				click: function( event ) {
17942					event.preventDefault();
17943				}
17944			} );
17945			this._on( this.anchors, events );
17946			this._on( this.tabs, { keydown: "_tabKeydown" } );
17947			this._on( this.panels, { keydown: "_panelKeydown" } );
17948
17949			this._focusable( this.tabs );
17950			this._hoverable( this.tabs );
17951		},
17952
17953		_setupHeightStyle: function( heightStyle ) {
17954			var maxHeight,
17955				parent = this.element.parent();
17956
17957			if ( heightStyle === "fill" ) {
17958				maxHeight = parent.height();
17959				maxHeight -= this.element.outerHeight() - this.element.height();
17960
17961				this.element.siblings( ":visible" ).each( function() {
17962					var elem = $( this ),
17963						position = elem.css( "position" );
17964
17965					if ( position === "absolute" || position === "fixed" ) {
17966						return;
17967					}
17968					maxHeight -= elem.outerHeight( true );
17969				} );
17970
17971				this.element.children().not( this.panels ).each( function() {
17972					maxHeight -= $( this ).outerHeight( true );
17973				} );
17974
17975				this.panels.each( function() {
17976					$( this ).height( Math.max( 0, maxHeight -
17977						$( this ).innerHeight() + $( this ).height() ) );
17978				} )
17979					.css( "overflow", "auto" );
17980			} else if ( heightStyle === "auto" ) {
17981				maxHeight = 0;
17982				this.panels.each( function() {
17983					maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
17984				} ).height( maxHeight );
17985			}
17986		},
17987
17988		_eventHandler: function( event ) {
17989			var options = this.options,
17990				active = this.active,
17991				anchor = $( event.currentTarget ),
17992				tab = anchor.closest( "li" ),
17993				clickedIsActive = tab[ 0 ] === active[ 0 ],
17994				collapsing = clickedIsActive && options.collapsible,
17995				toShow = collapsing ? $() : this._getPanelForTab( tab ),
17996				toHide = !active.length ? $() : this._getPanelForTab( active ),
17997				eventData = {
17998					oldTab: active,
17999					oldPanel: toHide,
18000					newTab: collapsing ? $() : tab,
18001					newPanel: toShow
18002				};
18003
18004			event.preventDefault();
18005
18006			if ( tab.hasClass( "ui-state-disabled" ) ||
18007
18008				// tab is already loading
18009				tab.hasClass( "ui-tabs-loading" ) ||
18010
18011				// can't switch durning an animation
18012				this.running ||
18013
18014				// click on active header, but not collapsible
18015				( clickedIsActive && !options.collapsible ) ||
18016
18017				// allow canceling activation
18018				( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
18019				return;
18020			}
18021
18022			options.active = collapsing ? false : this.tabs.index( tab );
18023
18024			this.active = clickedIsActive ? $() : tab;
18025			if ( this.xhr ) {
18026				this.xhr.abort();
18027			}
18028
18029			if ( !toHide.length && !toShow.length ) {
18030				$.error( "jQuery UI Tabs: Mismatching fragment identifier." );
18031			}
18032
18033			if ( toShow.length ) {
18034				this.load( this.tabs.index( tab ), event );
18035			}
18036			this._toggle( event, eventData );
18037		},
18038
18039		// Handles show/hide for selecting tabs
18040		_toggle: function( event, eventData ) {
18041			var that = this,
18042				toShow = eventData.newPanel,
18043				toHide = eventData.oldPanel;
18044
18045			this.running = true;
18046
18047			function complete() {
18048				that.running = false;
18049				that._trigger( "activate", event, eventData );
18050			}
18051
18052			function show() {
18053				that._addClass( eventData.newTab.closest( "li" ), "ui-tabs-active", "ui-state-active" );
18054
18055				if ( toShow.length && that.options.show ) {
18056					that._show( toShow, that.options.show, complete );
18057				} else {
18058					toShow.show();
18059					complete();
18060				}
18061			}
18062
18063			// Start out by hiding, then showing, then completing
18064			if ( toHide.length && this.options.hide ) {
18065				this._hide( toHide, this.options.hide, function() {
18066					that._removeClass( eventData.oldTab.closest( "li" ),
18067						"ui-tabs-active", "ui-state-active" );
18068					show();
18069				} );
18070			} else {
18071				this._removeClass( eventData.oldTab.closest( "li" ),
18072					"ui-tabs-active", "ui-state-active" );
18073				toHide.hide();
18074				show();
18075			}
18076
18077			toHide.attr( "aria-hidden", "true" );
18078			eventData.oldTab.attr( {
18079				"aria-selected": "false",
18080				"aria-expanded": "false"
18081			} );
18082
18083			// If we're switching tabs, remove the old tab from the tab order.
18084			// If we're opening from collapsed state, remove the previous tab from the tab order.
18085			// If we're collapsing, then keep the collapsing tab in the tab order.
18086			if ( toShow.length && toHide.length ) {
18087				eventData.oldTab.attr( "tabIndex", -1 );
18088			} else if ( toShow.length ) {
18089				this.tabs.filter( function() {
18090					return $( this ).attr( "tabIndex" ) === 0;
18091				} )
18092					.attr( "tabIndex", -1 );
18093			}
18094
18095			toShow.attr( "aria-hidden", "false" );
18096			eventData.newTab.attr( {
18097				"aria-selected": "true",
18098				"aria-expanded": "true",
18099				tabIndex: 0
18100			} );
18101		},
18102
18103		_activate: function( index ) {
18104			var anchor,
18105				active = this._findActive( index );
18106
18107			// Trying to activate the already active panel
18108			if ( active[ 0 ] === this.active[ 0 ] ) {
18109				return;
18110			}
18111
18112			// Trying to collapse, simulate a click on the current active header
18113			if ( !active.length ) {
18114				active = this.active;
18115			}
18116
18117			anchor = active.find( ".ui-tabs-anchor" )[ 0 ];
18118			this._eventHandler( {
18119				target: anchor,
18120				currentTarget: anchor,
18121				preventDefault: $.noop
18122			} );
18123		},
18124
18125		_findActive: function( index ) {
18126			return index === false ? $() : this.tabs.eq( index );
18127		},
18128
18129		_getIndex: function( index ) {
18130
18131			// meta-function to give users option to provide a href string instead of a numerical index.
18132			if ( typeof index === "string" ) {
18133				index = this.anchors.index( this.anchors.filter( "[href$='" +
18134					CSS.escape( index ) + "']" ) );
18135			}
18136
18137			return index;
18138		},
18139
18140		_destroy: function() {
18141			if ( this.xhr ) {
18142				this.xhr.abort();
18143			}
18144
18145			this.tablist
18146				.removeAttr( "role" )
18147				.off( this.eventNamespace );
18148
18149			this.anchors
18150				.removeAttr( "role tabIndex" )
18151				.removeUniqueId();
18152
18153			this.tabs.add( this.panels ).each( function() {
18154				if ( $.data( this, "ui-tabs-destroy" ) ) {
18155					$( this ).remove();
18156				} else {
18157					$( this ).removeAttr( "role tabIndex " +
18158						"aria-live aria-busy aria-selected aria-labelledby aria-hidden aria-expanded" );
18159				}
18160			} );
18161
18162			this.tabs.each( function() {
18163				var li = $( this ),
18164					prev = li.data( "ui-tabs-aria-controls" );
18165				if ( prev ) {
18166					li
18167						.attr( "aria-controls", prev )
18168						.removeData( "ui-tabs-aria-controls" );
18169				} else {
18170					li.removeAttr( "aria-controls" );
18171				}
18172			} );
18173
18174			this.panels.show();
18175
18176			if ( this.options.heightStyle !== "content" ) {
18177				this.panels.css( "height", "" );
18178			}
18179		},
18180
18181		enable: function( index ) {
18182			var disabled = this.options.disabled;
18183			if ( disabled === false ) {
18184				return;
18185			}
18186
18187			if ( index === undefined ) {
18188				disabled = false;
18189			} else {
18190				index = this._getIndex( index );
18191				if ( Array.isArray( disabled ) ) {
18192					disabled = $.map( disabled, function( num ) {
18193						return num !== index ? num : null;
18194					} );
18195				} else {
18196					disabled = $.map( this.tabs, function( li, num ) {
18197						return num !== index ? num : null;
18198					} );
18199				}
18200			}
18201			this._setOptionDisabled( disabled );
18202		},
18203
18204		disable: function( index ) {
18205			var disabled = this.options.disabled;
18206			if ( disabled === true ) {
18207				return;
18208			}
18209
18210			if ( index === undefined ) {
18211				disabled = true;
18212			} else {
18213				index = this._getIndex( index );
18214				if ( $.inArray( index, disabled ) !== -1 ) {
18215					return;
18216				}
18217				if ( Array.isArray( disabled ) ) {
18218					disabled = $.merge( [ index ], disabled ).sort();
18219				} else {
18220					disabled = [ index ];
18221				}
18222			}
18223			this._setOptionDisabled( disabled );
18224		},
18225
18226		load: function( index, event ) {
18227			index = this._getIndex( index );
18228			var that = this,
18229				tab = this.tabs.eq( index ),
18230				anchor = tab.find( ".ui-tabs-anchor" ),
18231				panel = this._getPanelForTab( tab ),
18232				eventData = {
18233					tab: tab,
18234					panel: panel
18235				},
18236				complete = function( jqXHR, status ) {
18237					if ( status === "abort" ) {
18238						that.panels.stop( false, true );
18239					}
18240
18241					that._removeClass( tab, "ui-tabs-loading" );
18242					panel.removeAttr( "aria-busy" );
18243
18244					if ( jqXHR === that.xhr ) {
18245						delete that.xhr;
18246					}
18247				};
18248
18249			// Not remote
18250			if ( this._isLocal( anchor[ 0 ] ) ) {
18251				return;
18252			}
18253
18254			this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );
18255
18256			if ( this.xhr.statusText !== "canceled" ) {
18257				this._addClass( tab, "ui-tabs-loading" );
18258				panel.attr( "aria-busy", "true" );
18259
18260				this.xhr
18261					.done( function( response, status, jqXHR ) {
18262						panel.html( response );
18263						that._trigger( "load", event, eventData );
18264
18265						complete( jqXHR, status );
18266					} )
18267					.fail( function( jqXHR, status ) {
18268						complete( jqXHR, status );
18269					} );
18270			}
18271		},
18272
18273		_ajaxSettings: function( anchor, event, eventData ) {
18274			var that = this;
18275			return {
18276				url: anchor.attr( "href" ),
18277				beforeSend: function( jqXHR, settings ) {
18278					return that._trigger( "beforeLoad", event,
18279						$.extend( { jqXHR: jqXHR, ajaxSettings: settings }, eventData ) );
18280				}
18281			};
18282		},
18283
18284		_getPanelForTab: function( tab ) {
18285			var id = $( tab ).attr( "aria-controls" );
18286			return this.element.find( "#" + CSS.escape( id ) );
18287		}
18288	} );
18289
18290// DEPRECATED
18291// TODO: Switch return back to widget declaration at top of file when this is removed
18292	if ( $.uiBackCompat === true ) {
18293
18294		// Backcompat for ui-tab class (now ui-tabs-tab)
18295		$.widget( "ui.tabs", $.ui.tabs, {
18296			_processTabs: function() {
18297				this._superApply( arguments );
18298				this._addClass( this.tabs, "ui-tab" );
18299			}
18300		} );
18301	}
18302
18303	var widgetsTabs = $.ui.tabs;
18304
18305
18306	/*!
18307 * jQuery UI Tooltip 1.14.1
18308 * https://jqueryui.com
18309 *
18310 * Copyright OpenJS Foundation and other contributors
18311 * Released under the MIT license.
18312 * https://jquery.org/license
18313 */
18314
18315//>>label: Tooltip
18316//>>group: Widgets
18317//>>description: Shows additional information for any element on hover or focus.
18318//>>docs: https://api.jqueryui.com/tooltip/
18319//>>demos: https://jqueryui.com/tooltip/
18320//>>css.structure: ../../themes/base/core.css
18321//>>css.structure: ../../themes/base/tooltip.css
18322//>>css.theme: ../../themes/base/theme.css
18323
18324
18325	$.widget( "ui.tooltip", {
18326		version: "1.14.1",
18327		options: {
18328			classes: {
18329				"ui-tooltip": "ui-corner-all ui-widget-shadow"
18330			},
18331			content: function() {
18332				var title = $( this ).attr( "title" );
18333
18334				// Escape title, since we're going from an attribute to raw HTML
18335				return $( "<a>" ).text( title ).html();
18336			},
18337			hide: true,
18338
18339			// Disabled elements have inconsistent behavior across browsers (#8661)
18340			items: "[title]:not([disabled])",
18341			position: {
18342				my: "left top+15",
18343				at: "left bottom",
18344				collision: "flipfit flip"
18345			},
18346			show: true,
18347			track: false,
18348
18349			// Callbacks
18350			close: null,
18351			open: null
18352		},
18353
18354		_addDescribedBy: function( elem, id ) {
18355			var describedby = ( elem.attr( "aria-describedby" ) || "" ).split( /\s+/ );
18356			describedby.push( id );
18357			elem
18358				.data( "ui-tooltip-id", id )
18359				.attr( "aria-describedby", String.prototype.trim.call( describedby.join( " " ) ) );
18360		},
18361
18362		_removeDescribedBy: function( elem ) {
18363			var id = elem.data( "ui-tooltip-id" ),
18364				describedby = ( elem.attr( "aria-describedby" ) || "" ).split( /\s+/ ),
18365				index = $.inArray( id, describedby );
18366
18367			if ( index !== -1 ) {
18368				describedby.splice( index, 1 );
18369			}
18370
18371			elem.removeData( "ui-tooltip-id" );
18372			describedby = String.prototype.trim.call( describedby.join( " " ) );
18373			if ( describedby ) {
18374				elem.attr( "aria-describedby", describedby );
18375			} else {
18376				elem.removeAttr( "aria-describedby" );
18377			}
18378		},
18379
18380		_create: function() {
18381			this._on( {
18382				mouseover: "open",
18383				focusin: "open"
18384			} );
18385
18386			// IDs of generated tooltips, needed for destroy
18387			this.tooltips = {};
18388
18389			// IDs of parent tooltips where we removed the title attribute
18390			this.parents = {};
18391
18392			// Append the aria-live region so tooltips announce correctly
18393			this.liveRegion = $( "<div>" )
18394				.attr( {
18395					role: "log",
18396					"aria-live": "assertive",
18397					"aria-relevant": "additions"
18398				} )
18399				.appendTo( this.document[ 0 ].body );
18400			this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" );
18401
18402			this.disabledTitles = $( [] );
18403		},
18404
18405		_setOption: function( key, value ) {
18406			var that = this;
18407
18408			this._super( key, value );
18409
18410			if ( key === "content" ) {
18411				$.each( this.tooltips, function( id, tooltipData ) {
18412					that._updateContent( tooltipData.element );
18413				} );
18414			}
18415		},
18416
18417		_setOptionDisabled: function( value ) {
18418			this[ value ? "_disable" : "_enable" ]();
18419		},
18420
18421		_disable: function() {
18422			var that = this;
18423
18424			// Close open tooltips
18425			$.each( this.tooltips, function( id, tooltipData ) {
18426				var event = $.Event( "blur" );
18427				event.target = event.currentTarget = tooltipData.element[ 0 ];
18428				that.close( event, true );
18429			} );
18430
18431			// Remove title attributes to prevent native tooltips
18432			this.disabledTitles = this.disabledTitles.add(
18433				this.element.find( this.options.items ).addBack()
18434					.filter( function() {
18435						var element = $( this );
18436						if ( element.is( "[title]" ) ) {
18437							return element
18438								.data( "ui-tooltip-title", element.attr( "title" ) )
18439								.removeAttr( "title" );
18440						}
18441					} )
18442			);
18443		},
18444
18445		_enable: function() {
18446
18447			// restore title attributes
18448			this.disabledTitles.each( function() {
18449				var element = $( this );
18450				if ( element.data( "ui-tooltip-title" ) ) {
18451					element.attr( "title", element.data( "ui-tooltip-title" ) );
18452				}
18453			} );
18454			this.disabledTitles = $( [] );
18455		},
18456
18457		open: function( event ) {
18458			var that = this,
18459				target = $( event ? event.target : this.element )
18460
18461					// we need closest here due to mouseover bubbling,
18462					// but always pointing at the same event target
18463					.closest( this.options.items );
18464
18465			// No element to show a tooltip for or the tooltip is already open
18466			if ( !target.length || target.data( "ui-tooltip-id" ) ) {
18467				return;
18468			}
18469
18470			if ( target.attr( "title" ) ) {
18471				target.data( "ui-tooltip-title", target.attr( "title" ) );
18472			}
18473
18474			target.data( "ui-tooltip-open", true );
18475
18476			// Kill parent tooltips, custom or native, for hover
18477			if ( event && event.type === "mouseover" ) {
18478				target.parents().each( function() {
18479					var parent = $( this ),
18480						blurEvent;
18481					if ( parent.data( "ui-tooltip-open" ) ) {
18482						blurEvent = $.Event( "blur" );
18483						blurEvent.target = blurEvent.currentTarget = this;
18484						that.close( blurEvent, true );
18485					}
18486					if ( parent.attr( "title" ) ) {
18487						parent.uniqueId();
18488						that.parents[ this.id ] = {
18489							element: this,
18490							title: parent.attr( "title" )
18491						};
18492						parent.attr( "title", "" );
18493					}
18494				} );
18495			}
18496
18497			this._registerCloseHandlers( event, target );
18498			this._updateContent( target, event );
18499		},
18500
18501		_updateContent: function( target, event ) {
18502			var content,
18503				contentOption = this.options.content,
18504				that = this,
18505				eventType = event ? event.type : null;
18506
18507			if ( typeof contentOption === "string" || contentOption.nodeType ||
18508				contentOption.jquery ) {
18509				return this._open( event, target, contentOption );
18510			}
18511
18512			content = contentOption.call( target[ 0 ], function( response ) {
18513
18514				// Ignore async response if tooltip was closed already
18515				if ( !target.data( "ui-tooltip-open" ) ) {
18516					return;
18517				}
18518
18519				// JQuery creates a special event for focusin when it doesn't
18520				// exist natively. To improve performance, the native event
18521				// object is reused and the type is changed. Therefore, we can't
18522				// rely on the type being correct after the event finished
18523				// bubbling, so we set it back to the previous value. (#8740)
18524				if ( event ) {
18525					event.type = eventType;
18526				}
18527				that._open( event, target, response );
18528			} );
18529			if ( content ) {
18530				this._open( event, target, content );
18531			}
18532		},
18533
18534		_open: function( event, target, content ) {
18535			var tooltipData, tooltip, delayedShow, a11yContent,
18536				positionOption = $.extend( {}, this.options.position );
18537
18538			if ( !content ) {
18539				return;
18540			}
18541
18542			// Content can be updated multiple times. If the tooltip already
18543			// exists, then just update the content and bail.
18544			tooltipData = this._find( target );
18545			if ( tooltipData ) {
18546				tooltipData.tooltip.find( ".ui-tooltip-content" ).html( content );
18547				return;
18548			}
18549
18550			// If we have a title, clear it to prevent the native tooltip
18551			// we have to check first to avoid defining a title if none exists
18552			// (we don't want to cause an element to start matching [title])
18553			//
18554			// We use removeAttr only for key events, to allow IE to export the correct
18555			// accessible attributes. For mouse events, set to empty string to avoid
18556			// native tooltip showing up (happens only when removing inside mouseover).
18557			if ( target.is( "[title]" ) ) {
18558				if ( event && event.type === "mouseover" ) {
18559					target.attr( "title", "" );
18560				} else {
18561					target.removeAttr( "title" );
18562				}
18563			}
18564
18565			tooltipData = this._tooltip( target );
18566			tooltip = tooltipData.tooltip;
18567			this._addDescribedBy( target, tooltip.attr( "id" ) );
18568			tooltip.find( ".ui-tooltip-content" ).html( content );
18569
18570			// Support: Voiceover on OS X, JAWS on IE <= 9
18571			// JAWS announces deletions even when aria-relevant="additions"
18572			// Voiceover will sometimes re-read the entire log region's contents from the beginning
18573			this.liveRegion.children().hide();
18574			a11yContent = $( "<div>" ).html( tooltip.find( ".ui-tooltip-content" ).html() );
18575			a11yContent.removeAttr( "name" ).find( "[name]" ).removeAttr( "name" );
18576			a11yContent.removeAttr( "id" ).find( "[id]" ).removeAttr( "id" );
18577			a11yContent.appendTo( this.liveRegion );
18578
18579			function position( event ) {
18580				positionOption.of = event;
18581				if ( tooltip.is( ":hidden" ) ) {
18582					return;
18583				}
18584				tooltip.position( positionOption );
18585			}
18586			if ( this.options.track && event && /^mouse/.test( event.type ) ) {
18587				this._on( this.document, {
18588					mousemove: position
18589				} );
18590
18591				// trigger once to override element-relative positioning
18592				position( event );
18593			} else {
18594				tooltip.position( $.extend( {
18595					of: target
18596				}, this.options.position ) );
18597			}
18598
18599			tooltip.hide();
18600
18601			this._show( tooltip, this.options.show );
18602
18603			// Handle tracking tooltips that are shown with a delay (#8644). As soon
18604			// as the tooltip is visible, position the tooltip using the most recent
18605			// event.
18606			// Adds the check to add the timers only when both delay and track options are set (#14682)
18607			if ( this.options.track && this.options.show && this.options.show.delay ) {
18608				delayedShow = this.delayedShow = setInterval( function() {
18609					if ( tooltip.is( ":visible" ) ) {
18610						position( positionOption.of );
18611						clearInterval( delayedShow );
18612					}
18613				}, 13 );
18614			}
18615
18616			this._trigger( "open", event, { tooltip: tooltip } );
18617		},
18618
18619		_registerCloseHandlers: function( event, target ) {
18620			var events = {
18621				keyup: function( event ) {
18622					if ( event.keyCode === $.ui.keyCode.ESCAPE ) {
18623						var fakeEvent = $.Event( event );
18624						fakeEvent.currentTarget = target[ 0 ];
18625						this.close( fakeEvent, true );
18626					}
18627				}
18628			};
18629
18630			// Only bind remove handler for delegated targets. Non-delegated
18631			// tooltips will handle this in destroy.
18632			if ( target[ 0 ] !== this.element[ 0 ] ) {
18633				events.remove = function() {
18634					var targetElement = this._find( target );
18635					if ( targetElement ) {
18636						this._removeTooltip( targetElement.tooltip );
18637					}
18638				};
18639			}
18640
18641			if ( !event || event.type === "mouseover" ) {
18642				events.mouseleave = "close";
18643			}
18644			if ( !event || event.type === "focusin" ) {
18645				events.focusout = "close";
18646			}
18647			this._on( true, target, events );
18648		},
18649
18650		close: function( event ) {
18651			var tooltip,
18652				that = this,
18653				target = $( event ? event.currentTarget : this.element ),
18654				tooltipData = this._find( target );
18655
18656			// The tooltip may already be closed
18657			if ( !tooltipData ) {
18658
18659				// We set ui-tooltip-open immediately upon open (in open()), but only set the
18660				// additional data once there's actually content to show (in _open()). So even if the
18661				// tooltip doesn't have full data, we always remove ui-tooltip-open in case we're in
18662				// the period between open() and _open().
18663				target.removeData( "ui-tooltip-open" );
18664				return;
18665			}
18666
18667			tooltip = tooltipData.tooltip;
18668
18669			// Disabling closes the tooltip, so we need to track when we're closing
18670			// to avoid an infinite loop in case the tooltip becomes disabled on close
18671			if ( tooltipData.closing ) {
18672				return;
18673			}
18674
18675			// Clear the interval for delayed tracking tooltips
18676			clearInterval( this.delayedShow );
18677
18678			// Only set title if we had one before (see comment in _open())
18679			// If the title attribute has changed since open(), don't restore
18680			if ( target.data( "ui-tooltip-title" ) && !target.attr( "title" ) ) {
18681				target.attr( "title", target.data( "ui-tooltip-title" ) );
18682			}
18683
18684			this._removeDescribedBy( target );
18685
18686			tooltipData.hiding = true;
18687			tooltip.stop( true );
18688			this._hide( tooltip, this.options.hide, function() {
18689				that._removeTooltip( $( this ) );
18690			} );
18691
18692			target.removeData( "ui-tooltip-open" );
18693			this._off( target, "mouseleave focusout keyup" );
18694
18695			// Remove 'remove' binding only on delegated targets
18696			if ( target[ 0 ] !== this.element[ 0 ] ) {
18697				this._off( target, "remove" );
18698			}
18699			this._off( this.document, "mousemove" );
18700
18701			if ( event && event.type === "mouseleave" ) {
18702				$.each( this.parents, function( id, parent ) {
18703					$( parent.element ).attr( "title", parent.title );
18704					delete that.parents[ id ];
18705				} );
18706			}
18707
18708			tooltipData.closing = true;
18709			this._trigger( "close", event, { tooltip: tooltip } );
18710			if ( !tooltipData.hiding ) {
18711				tooltipData.closing = false;
18712			}
18713		},
18714
18715		_tooltip: function( element ) {
18716			var tooltip = $( "<div>" ).attr( "role", "tooltip" ),
18717				content = $( "<div>" ).appendTo( tooltip ),
18718				id = tooltip.uniqueId().attr( "id" );
18719
18720			this._addClass( content, "ui-tooltip-content" );
18721			this._addClass( tooltip, "ui-tooltip", "ui-widget ui-widget-content" );
18722
18723			tooltip.appendTo( this._appendTo( element ) );
18724
18725			return this.tooltips[ id ] = {
18726				element: element,
18727				tooltip: tooltip
18728			};
18729		},
18730
18731		_find: function( target ) {
18732			var id = target.data( "ui-tooltip-id" );
18733			return id ? this.tooltips[ id ] : null;
18734		},
18735
18736		_removeTooltip: function( tooltip ) {
18737
18738			// Clear the interval for delayed tracking tooltips
18739			clearInterval( this.delayedShow );
18740
18741			tooltip.remove();
18742			delete this.tooltips[ tooltip.attr( "id" ) ];
18743		},
18744
18745		_appendTo: function( target ) {
18746			var element = target.closest( ".ui-front, dialog" );
18747
18748			if ( !element.length ) {
18749				element = this.document[ 0 ].body;
18750			}
18751
18752			return element;
18753		},
18754
18755		_destroy: function() {
18756			var that = this;
18757
18758			// Close open tooltips
18759			$.each( this.tooltips, function( id, tooltipData ) {
18760
18761				// Delegate to close method to handle common cleanup
18762				var event = $.Event( "blur" ),
18763					element = tooltipData.element;
18764				event.target = event.currentTarget = element[ 0 ];
18765				that.close( event, true );
18766
18767				// Remove immediately; destroying an open tooltip doesn't use the
18768				// hide animation
18769				$( "#" + id ).remove();
18770
18771				// Restore the title
18772				if ( element.data( "ui-tooltip-title" ) ) {
18773
18774					// If the title attribute has changed since open(), don't restore
18775					if ( !element.attr( "title" ) ) {
18776						element.attr( "title", element.data( "ui-tooltip-title" ) );
18777					}
18778					element.removeData( "ui-tooltip-title" );
18779				}
18780			} );
18781			this.liveRegion.remove();
18782		}
18783	} );
18784
18785// DEPRECATED
18786// TODO: Switch return back to widget declaration at top of file when this is removed
18787	if ( $.uiBackCompat === true ) {
18788
18789		// Backcompat for tooltipClass option
18790		$.widget( "ui.tooltip", $.ui.tooltip, {
18791			options: {
18792				tooltipClass: null
18793			},
18794			_tooltip: function() {
18795				var tooltipData = this._superApply( arguments );
18796				if ( this.options.tooltipClass ) {
18797					tooltipData.tooltip.addClass( this.options.tooltipClass );
18798				}
18799				return tooltipData;
18800			}
18801		} );
18802	}
18803
18804	var widgetsTooltip = $.ui.tooltip;
18805
18806
18807
18808
18809} );

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.