PageSourceSearch

https://www.virtualbelfastmuraltour.com/lib/jquery-ui/jquery-ui.js

js virtualbelfastmuraltour.com collected 2026-10-02 21:11:46 UTC 537,739 bytes, 18,745 lines download raw bytes

vendor: 4,941 bytes, lines 1-142
1/*! jQuery UI - v1.14.0 - 2024-08-05
2* https://jqueryui.com
3* Includes: widget.js, position.js, data.js, disable-selection.js, effect.js, effects/effect-blind.js, effects/effect-bounce.js, effects/effect-clip.js, effects/effect-drop.js, effects/effect-explode.js, effects/effect-fade.js, effects/effect-fold.js, effects/effect-highlight.js, effects/effect-puff.js, effects/effect-pulsate.js, effects/effect-scale.js, effects/effect-shake.js, effects/effect-size.js, effects/effect-slide.js, effects/effect-transfer.js, focusable.js, form-reset-mixin.js, jquery-patch.js, keycode.js, labels.js, scroll-parent.js, tabbable.js, unique-id.js, widgets/accordion.js, widgets/autocomplete.js, widgets/button.js, widgets/checkboxradio.js, widgets/controlgroup.js, widgets/datepicker.js, widgets/dialog.js, widgets/draggable.js, widgets/droppable.js, widgets/menu.js, widgets/mouse.js, widgets/progressbar.js, widgets/resizable.js, widgets/selectable.js, widgets/selectmenu.js, widgets/slider.js, widgets/sortable.js, widgets/spinner.js, widgets/tabs.js, widgets/tooltip.js
4* Copyright OpenJS Foundation and other contributors; Licensed MIT */
5
6( function( factory ) {
7	"use strict";
8
9	if ( typeof define === "function" && define.amd ) {
10
11		// AMD. Register as an anonymous module.
12		define( [ "jquery" ], factory );
13	} else {
14
15		// Browser globals
16		factory( jQuery );
17	}
18} )( function( $ ) {
19"use strict";
20
21$.ui = $.ui || {};
22
23var version = $.ui.version = "1.14.0";
24
25
26/*!
27 * jQuery UI Widget 1.14.0
28 * https://jqueryui.com
29 *
30 * Copyright OpenJS Foundation and other contributors
31 * Released under the MIT license.
32 * https://jquery.org/license
33 */
34
35//>>label: Widget
36//>>group: Core
37//>>description: Provides a factory for creating stateful widgets with a common API.
38//>>docs: https://api.jqueryui.com/jQuery.widget/
39//>>demos: https://jqueryui.com/widget/
40
41
42var widgetUuid = 0;
43var widgetHasOwnProperty = Array.prototype.hasOwnProperty;
44var widgetSlice = Array.prototype.slice;
45
46$.cleanData = ( function( orig ) {
47	return function( elems ) {
48		var events, elem, i;
49		for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) {
50
51			// Only trigger remove when necessary to save time
52			events = $._data( elem, "events" );
53			if ( events && events.remove ) {
54				$( elem ).triggerHandler( "remove" );
55			}
56		}
57		orig( elems );
58	};
59} )( $.cleanData );
60
61$.widget = function( name, base, prototype ) {
62	var existingConstructor, constructor, basePrototype;
63
64	// ProxiedPrototype allows the provided prototype to remain unmodified
65	// so that it can be used as a mixin for multiple widgets (#8876)
66	var proxiedPrototype = {};
67
68	var namespace = name.split( "." )[ 0 ];
69	name = name.split( "." )[ 1 ];
70	var fullName = namespace + "-" + name;
71
72	if ( !prototype ) {
73		prototype = base;
74		base = $.Widget;
75	}
76
77	if ( Array.isArray( prototype ) ) {
78		prototype = $.extend.apply( null, [ {} ].concat( prototype ) );
79	}
80
81	// Create selector for plugin
82	$.expr.pseudos[ fullName.toLowerCase() ] = function( elem ) {
83		return !!$.data( elem, fullName );
84	};
85
86	$[ namespace ] = $[ namespace ] || {};
87	existingConstructor = $[ namespace ][ name ];
88	constructor = $[ namespace ][ name ] = function( options, element ) {
89
90		// Allow instantiation without "new" keyword
91		if ( !this || !this._createWidget ) {
92			return new constructor( options, element );
93		}
94
95		// Allow instantiation without initializing for simple inheritance
96		// must use "new" keyword (the code above always passes args)
97		if ( arguments.length ) {
98			this._createWidget( options, element );
99		}
100	};
101
102	// Extend with the existing constructor to carry over any static properties
103	$.extend( constructor, existingConstructor, {
104		version: prototype.version,
105
106		// Copy the object used to create the prototype in case we need to
107		// redefine the widget later
108		_proto: $.extend( {}, prototype ),
109
110		// Track widgets that inherit from this widget in case this widget is
111		// redefined after a widget inherits from it
112		_childConstructors: []
113	} );
114
115	basePrototype = new base();
116
117	// We need to make the options hash a property directly on the new instance
118	// otherwise we'll modify the options hash on the prototype that we're
119	// inheriting from
120	basePrototype.options = $.widget.extend( {}, basePrototype.options );
121	$.each( prototype, function( prop, value ) {
122		if ( typeof value !== "function" ) {
123			proxiedPrototype[ prop ] = value;
124			return;
125		}
126		proxiedPrototype[ prop ] = ( function() {
127			function _super() {
128				return base.prototype[ prop ].apply( this, arguments );
129			}
130
131			function _superApply( args ) {
132				return base.prototype[ prop ].apply( this, args );
133			}
134
135			return function() {
136				var __super = this._super;
137				var __superApply = this._superApply;
138				var returnValue;
139
140				this._super = _super;
141				this._superApply = _superApply;
142
vendor: 316,795 bytes, lines 143-10814
143				returnValue = value.apply( this, arguments );
144
145				this._super = __super;
146				this._superApply = __superApply;
147
148				return returnValue;
149			};
150		} )();
151	} );
152	constructor.prototype = $.widget.extend( basePrototype, {
153
154		// TODO: remove support for widgetEventPrefix
155		// always use the name + a colon as the prefix, e.g., draggable:start
156		// don't prefix for widgets that aren't DOM-based
157		widgetEventPrefix: existingConstructor ? ( basePrototype.widgetEventPrefix || name ) : name
158	}, proxiedPrototype, {
159		constructor: constructor,
160		namespace: namespace,
161		widgetName: name,
162		widgetFullName: fullName
163	} );
164
165	// If this widget is being redefined then we need to find all widgets that
166	// are inheriting from it and redefine all of them so that they inherit from
167	// the new version of this widget. We're essentially trying to replace one
168	// level in the prototype chain.
169	if ( existingConstructor ) {
170		$.each( existingConstructor._childConstructors, function( i, child ) {
171			var childPrototype = child.prototype;
172
173			// Redefine the child widget using the same prototype that was
174			// originally used, but inherit from the new version of the base
175			$.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor,
176				child._proto );
177		} );
178
179		// Remove the list of existing child constructors from the old constructor
180		// so the old child constructors can be garbage collected
181		delete existingConstructor._childConstructors;
182	} else {
183		base._childConstructors.push( constructor );
184	}
185
186	$.widget.bridge( name, constructor );
187
188	return constructor;
189};
190
191$.widget.extend = function( target ) {
192	var input = widgetSlice.call( arguments, 1 );
193	var inputIndex = 0;
194	var inputLength = input.length;
195	var key;
196	var value;
197
198	for ( ; inputIndex < inputLength; inputIndex++ ) {
199		for ( key in input[ inputIndex ] ) {
200			value = input[ inputIndex ][ key ];
201			if ( widgetHasOwnProperty.call( input[ inputIndex ], key ) && value !== undefined ) {
202
203				// Clone objects
204				if ( $.isPlainObject( value ) ) {
205					target[ key ] = $.isPlainObject( target[ key ] ) ?
206						$.widget.extend( {}, target[ key ], value ) :
207
208						// Don't extend strings, arrays, etc. with objects
209						$.widget.extend( {}, value );
210
211				// Copy everything else by reference
212				} else {
213					target[ key ] = value;
214				}
215			}
216		}
217	}
218	return target;
219};
220
221$.widget.bridge = function( name, object ) {
222	var fullName = object.prototype.widgetFullName || name;
223	$.fn[ name ] = function( options ) {
224		var isMethodCall = typeof options === "string";
225		var args = widgetSlice.call( arguments, 1 );
226		var returnValue = this;
227
228		if ( isMethodCall ) {
229
230			// If this is an empty collection, we need to have the instance method
231			// return undefined instead of the jQuery instance
232			if ( !this.length && options === "instance" ) {
233				returnValue = undefined;
234			} else {
235				this.each( function() {
236					var methodValue;
237					var instance = $.data( this, fullName );
238
239					if ( options === "instance" ) {
240						returnValue = instance;
241						return false;
242					}
243
244					if ( !instance ) {
245						return $.error( "cannot call methods on " + name +
246							" prior to initialization; " +
247							"attempted to call method '" + options + "'" );
248					}
249
250					if ( typeof instance[ options ] !== "function" ||
251						options.charAt( 0 ) === "_" ) {
252						return $.error( "no such method '" + options + "' for " + name +
253							" widget instance" );
254					}
255
256					methodValue = instance[ options ].apply( instance, args );
257
258					if ( methodValue !== instance && methodValue !== undefined ) {
259						returnValue = methodValue && methodValue.jquery ?
260							returnValue.pushStack( methodValue.get() ) :
261							methodValue;
262						return false;
263					}
264				} );
265			}
266		} else {
267
268			// Allow multiple hashes to be passed on init
269			if ( args.length ) {
270				options = $.widget.extend.apply( null, [ options ].concat( args ) );
271			}
272
273			this.each( function() {
274				var instance = $.data( this, fullName );
275				if ( instance ) {
276					instance.option( options || {} );
277					if ( instance._init ) {
278						instance._init();
279					}
280				} else {
281					$.data( this, fullName, new object( options, this ) );
282				}
283			} );
284		}
285
286		return returnValue;
287	};
288};
289
290$.Widget = function( /* options, element */ ) {};
291$.Widget._childConstructors = [];
292
293$.Widget.prototype = {
294	widgetName: "widget",
295	widgetEventPrefix: "",
296	defaultElement: "<div>",
297
298	options: {
299		classes: {},
300		disabled: false,
301
302		// Callbacks
303		create: null
304	},
305
306	_createWidget: function( options, element ) {
307		element = $( element || this.defaultElement || this )[ 0 ];
308		this.element = $( element );
309		this.uuid = widgetUuid++;
310		this.eventNamespace = "." + this.widgetName + this.uuid;
311
312		this.bindings = $();
313		this.hoverable = $();
314		this.focusable = $();
315		this.classesElementLookup = {};
316
317		if ( element !== this ) {
318			$.data( element, this.widgetFullName, this );
319			this._on( true, this.element, {
320				remove: function( event ) {
321					if ( event.target === element ) {
322						this.destroy();
323					}
324				}
325			} );
326			this.document = $( element.style ?
327
328				// Element within the document
329				element.ownerDocument :
330
331				// Element is window or document
332				element.document || element );
333			this.window = $( this.document[ 0 ].defaultView || this.document[ 0 ].parentWindow );
334		}
335
336		this.options = $.widget.extend( {},
337			this.options,
338			this._getCreateOptions(),
339			options );
340
341		this._create();
342
343		if ( this.options.disabled ) {
344			this._setOptionDisabled( this.options.disabled );
345		}
346
347		this._trigger( "create", null, this._getCreateEventData() );
348		this._init();
349	},
350
351	_getCreateOptions: function() {
352		return {};
353	},
354
355	_getCreateEventData: $.noop,
356
357	_create: $.noop,
358
359	_init: $.noop,
360
361	destroy: function() {
362		var that = this;
363
364		this._destroy();
365		$.each( this.classesElementLookup, function( key, value ) {
366			that._removeClass( value, key );
367		} );
368
369		// We can probably remove the unbind calls in 2.0
370		// all event bindings should go through this._on()
371		this.element
372			.off( this.eventNamespace )
373			.removeData( this.widgetFullName );
374		this.widget()
375			.off( this.eventNamespace )
376			.removeAttr( "aria-disabled" );
377
378		// Clean up events and states
379		this.bindings.off( this.eventNamespace );
380	},
381
382	_destroy: $.noop,
383
384	widget: function() {
385		return this.element;
386	},
387
388	option: function( key, value ) {
389		var options = key;
390		var parts;
391		var curOption;
392		var i;
393
394		if ( arguments.length === 0 ) {
395
396			// Don't return a reference to the internal hash
397			return $.widget.extend( {}, this.options );
398		}
399
400		if ( typeof key === "string" ) {
401
402			// Handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
403			options = {};
404			parts = key.split( "." );
405			key = parts.shift();
406			if ( parts.length ) {
407				curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
408				for ( i = 0; i < parts.length - 1; i++ ) {
409					curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
410					curOption = curOption[ parts[ i ] ];
411				}
412				key = parts.pop();
413				if ( arguments.length === 1 ) {
414					return curOption[ key ] === undefined ? null : curOption[ key ];
415				}
416				curOption[ key ] = value;
417			} else {
418				if ( arguments.length === 1 ) {
419					return this.options[ key ] === undefined ? null : this.options[ key ];
420				}
421				options[ key ] = value;
422			}
423		}
424
425		this._setOptions( options );
426
427		return this;
428	},
429
430	_setOptions: function( options ) {
431		var key;
432
433		for ( key in options ) {
434			this._setOption( key, options[ key ] );
435		}
436
437		return this;
438	},
439
440	_setOption: function( key, value ) {
441		if ( key === "classes" ) {
442			this._setOptionClasses( value );
443		}
444
445		this.options[ key ] = value;
446
447		if ( key === "disabled" ) {
448			this._setOptionDisabled( value );
449		}
450
451		return this;
452	},
453
454	_setOptionClasses: function( value ) {
455		var classKey, elements, currentElements;
456
457		for ( classKey in value ) {
458			currentElements = this.classesElementLookup[ classKey ];
459			if ( value[ classKey ] === this.options.classes[ classKey ] ||
460					!currentElements ||
461					!currentElements.length ) {
462				continue;
463			}
464
465			// We are doing this to create a new jQuery object because the _removeClass() call
466			// on the next line is going to destroy the reference to the current elements being
467			// tracked. We need to save a copy of this collection so that we can add the new classes
468			// below.
469			elements = $( currentElements.get() );
470			this._removeClass( currentElements, classKey );
471
472			// We don't use _addClass() here, because that uses this.options.classes
473			// for generating the string of classes. We want to use the value passed in from
474			// _setOption(), this is the new value of the classes option which was passed to
475			// _setOption(). We pass this value directly to _classes().
476			elements.addClass( this._classes( {
477				element: elements,
478				keys: classKey,
479				classes: value,
480				add: true
481			} ) );
482		}
483	},
484
485	_setOptionDisabled: function( value ) {
486		this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, !!value );
487
488		// If the widget is becoming disabled, then nothing is interactive
489		if ( value ) {
490			this._removeClass( this.hoverable, null, "ui-state-hover" );
491			this._removeClass( this.focusable, null, "ui-state-focus" );
492		}
493	},
494
495	enable: function() {
496		return this._setOptions( { disabled: false } );
497	},
498
499	disable: function() {
500		return this._setOptions( { disabled: true } );
501	},
502
503	_classes: function( options ) {
504		var full = [];
505		var that = this;
506
507		options = $.extend( {
508			element: this.element,
509			classes: this.options.classes || {}
510		}, options );
511
512		function bindRemoveEvent() {
513			var nodesToBind = [];
514
515			options.element.each( function( _, element ) {
516				var isTracked = $.map( that.classesElementLookup, function( elements ) {
517					return elements;
518				} )
519					.some( function( elements ) {
520						return elements.is( element );
521					} );
522
523				if ( !isTracked ) {
524					nodesToBind.push( element );
525				}
526			} );
527
528			that._on( $( nodesToBind ), {
529				remove: "_untrackClassesElement"
530			} );
531		}
532
533		function processClassString( classes, checkOption ) {
534			var current, i;
535			for ( i = 0; i < classes.length; i++ ) {
536				current = that.classesElementLookup[ classes[ i ] ] || $();
537				if ( options.add ) {
538					bindRemoveEvent();
539					current = $( $.uniqueSort( current.get().concat( options.element.get() ) ) );
540				} else {
541					current = $( current.not( options.element ).get() );
542				}
543				that.classesElementLookup[ classes[ i ] ] = current;
544				full.push( classes[ i ] );
545				if ( checkOption && options.classes[ classes[ i ] ] ) {
546					full.push( options.classes[ classes[ i ] ] );
547				}
548			}
549		}
550
551		if ( options.keys ) {
552			processClassString( options.keys.match( /\S+/g ) || [], true );
553		}
554		if ( options.extra ) {
555			processClassString( options.extra.match( /\S+/g ) || [] );
556		}
557
558		return full.join( " " );
559	},
560
561	_untrackClassesElement: function( event ) {
562		var that = this;
563		$.each( that.classesElementLookup, function( key, value ) {
564			if ( $.inArray( event.target, value ) !== -1 ) {
565				that.classesElementLookup[ key ] = $( value.not( event.target ).get() );
566			}
567		} );
568
569		this._off( $( event.target ) );
570	},
571
572	_removeClass: function( element, keys, extra ) {
573		return this._toggleClass( element, keys, extra, false );
574	},
575
576	_addClass: function( element, keys, extra ) {
577		return this._toggleClass( element, keys, extra, true );
578	},
579
580	_toggleClass: function( element, keys, extra, add ) {
581		add = ( typeof add === "boolean" ) ? add : extra;
582		var shift = ( typeof element === "string" || element === null ),
583			options = {
584				extra: shift ? keys : extra,
585				keys: shift ? element : keys,
586				element: shift ? this.element : element,
587				add: add
588			};
589		options.element.toggleClass( this._classes( options ), add );
590		return this;
591	},
592
593	_on: function( suppressDisabledCheck, element, handlers ) {
594		var delegateElement;
595		var instance = this;
596
597		// No suppressDisabledCheck flag, shuffle arguments
598		if ( typeof suppressDisabledCheck !== "boolean" ) {
599			handlers = element;
600			element = suppressDisabledCheck;
601			suppressDisabledCheck = false;
602		}
603
604		// No element argument, shuffle and use this.element
605		if ( !handlers ) {
606			handlers = element;
607			element = this.element;
608			delegateElement = this.widget();
609		} else {
610			element = delegateElement = $( element );
611			this.bindings = this.bindings.add( element );
612		}
613
614		$.each( handlers, function( event, handler ) {
615			function handlerProxy() {
616
617				// Allow widgets to customize the disabled handling
618				// - disabled as an array instead of boolean
619				// - disabled class as method for disabling individual parts
620				if ( !suppressDisabledCheck &&
621						( instance.options.disabled === true ||
622						$( this ).hasClass( "ui-state-disabled" ) ) ) {
623					return;
624				}
625				return ( typeof handler === "string" ? instance[ handler ] : handler )
626					.apply( instance, arguments );
627			}
628
629			// Copy the guid so direct unbinding works
630			if ( typeof handler !== "string" ) {
631				handlerProxy.guid = handler.guid =
632					handler.guid || handlerProxy.guid || $.guid++;
633			}
634
635			var match = event.match( /^([\w:-]*)\s*(.*)$/ );
636			var eventName = match[ 1 ] + instance.eventNamespace;
637			var selector = match[ 2 ];
638
639			if ( selector ) {
640				delegateElement.on( eventName, selector, handlerProxy );
641			} else {
642				element.on( eventName, handlerProxy );
643			}
644		} );
645	},
646
647	_off: function( element, eventName ) {
648		eventName = ( eventName || "" ).split( " " ).join( this.eventNamespace + " " ) +
649			this.eventNamespace;
650		element.off( eventName );
651
652		// Clear the stack to avoid memory leaks (#10056)
653		this.bindings = $( this.bindings.not( element ).get() );
654		this.focusable = $( this.focusable.not( element ).get() );
655		this.hoverable = $( this.hoverable.not( element ).get() );
656	},
657
658	_delay: function( handler, delay ) {
659		function handlerProxy() {
660			return ( typeof handler === "string" ? instance[ handler ] : handler )
661				.apply( instance, arguments );
662		}
663		var instance = this;
664		return setTimeout( handlerProxy, delay || 0 );
665	},
666
667	_hoverable: function( element ) {
668		this.hoverable = this.hoverable.add( element );
669		this._on( element, {
670			mouseenter: function( event ) {
671				this._addClass( $( event.currentTarget ), null, "ui-state-hover" );
672			},
673			mouseleave: function( event ) {
674				this._removeClass( $( event.currentTarget ), null, "ui-state-hover" );
675			}
676		} );
677	},
678
679	_focusable: function( element ) {
680		this.focusable = this.focusable.add( element );
681		this._on( element, {
682			focusin: function( event ) {
683				this._addClass( $( event.currentTarget ), null, "ui-state-focus" );
684			},
685			focusout: function( event ) {
686				this._removeClass( $( event.currentTarget ), null, "ui-state-focus" );
687			}
688		} );
689	},
690
691	_trigger: function( type, event, data ) {
692		var prop, orig;
693		var callback = this.options[ type ];
694
695		data = data || {};
696		event = $.Event( event );
697		event.type = ( type === this.widgetEventPrefix ?
698			type :
699			this.widgetEventPrefix + type ).toLowerCase();
700
701		// The original event may come from any element
702		// so we need to reset the target on the new event
703		event.target = this.element[ 0 ];
704
705		// Copy original event properties over to the new event
706		orig = event.originalEvent;
707		if ( orig ) {
708			for ( prop in orig ) {
709				if ( !( prop in event ) ) {
710					event[ prop ] = orig[ prop ];
711				}
712			}
713		}
714
715		this.element.trigger( event, data );
716		return !( typeof callback === "function" &&
717			callback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false ||
718			event.isDefaultPrevented() );
719	}
720};
721
722$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
723	$.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
724		if ( typeof options === "string" ) {
725			options = { effect: options };
726		}
727
728		var hasOptions;
729		var effectName = !options ?
730			method :
731			options === true || typeof options === "number" ?
732				defaultEffect :
733				options.effect || defaultEffect;
734
735		options = options || {};
736		if ( typeof options === "number" ) {
737			options = { duration: options };
738		} else if ( options === true ) {
739			options = {};
740		}
741
742		hasOptions = !$.isEmptyObject( options );
743		options.complete = callback;
744
745		if ( options.delay ) {
746			element.delay( options.delay );
747		}
748
749		if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
750			element[ method ]( options );
751		} else if ( effectName !== method && element[ effectName ] ) {
752			element[ effectName ]( options.duration, options.easing, callback );
753		} else {
754			element.queue( function( next ) {
755				$( this )[ method ]();
756				if ( callback ) {
757					callback.call( element[ 0 ] );
758				}
759				next();
760			} );
761		}
762	};
763} );
764
765var widget = $.widget;
766
767
768/*!
769 * jQuery UI Position 1.14.0
770 * https://jqueryui.com
771 *
772 * Copyright OpenJS Foundation and other contributors
773 * Released under the MIT license.
774 * https://jquery.org/license
775 *
776 * https://api.jqueryui.com/position/
777 */
778
779//>>label: Position
780//>>group: Core
781//>>description: Positions elements relative to other elements.
782//>>docs: https://api.jqueryui.com/position/
783//>>demos: https://jqueryui.com/position/
784
785
786( function() {
787var cachedScrollbarWidth,
788	max = Math.max,
789	abs = Math.abs,
790	rhorizontal = /left|center|right/,
791	rvertical = /top|center|bottom/,
792	roffset = /[\+\-]\d+(\.[\d]+)?%?/,
793	rposition = /^\w+/,
794	rpercent = /%$/,
795	_position = $.fn.position;
796
797function getOffsets( offsets, width, height ) {
798	return [
799		parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
800		parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
801	];
802}
803
804function parseCss( element, property ) {
805	return parseInt( $.css( element, property ), 10 ) || 0;
806}
807
808function isWindow( obj ) {
809	return obj != null && obj === obj.window;
810}
811
812function getDimensions( elem ) {
813	var raw = elem[ 0 ];
814	if ( raw.nodeType === 9 ) {
815		return {
816			width: elem.width(),
817			height: elem.height(),
818			offset: { top: 0, left: 0 }
819		};
820	}
821	if ( isWindow( raw ) ) {
822		return {
823			width: elem.width(),
824			height: elem.height(),
825			offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
826		};
827	}
828	if ( raw.preventDefault ) {
829		return {
830			width: 0,
831			height: 0,
832			offset: { top: raw.pageY, left: raw.pageX }
833		};
834	}
835	return {
836		width: elem.outerWidth(),
837		height: elem.outerHeight(),
838		offset: elem.offset()
839	};
840}
841
842$.position = {
843	scrollbarWidth: function() {
844		if ( cachedScrollbarWidth !== undefined ) {
845			return cachedScrollbarWidth;
846		}
847		var w1, w2,
848			div = $( "<div style=" +
849				"'display:block;position:absolute;width:200px;height:200px;overflow:hidden;'>" +
850				"<div style='height:300px;width:auto;'></div></div>" ),
851			innerDiv = div.children()[ 0 ];
852
853		$( "body" ).append( div );
854		w1 = innerDiv.offsetWidth;
855		div.css( "overflow", "scroll" );
856
857		w2 = innerDiv.offsetWidth;
858
859		if ( w1 === w2 ) {
860			w2 = div[ 0 ].clientWidth;
861		}
862
863		div.remove();
864
865		return ( cachedScrollbarWidth = w1 - w2 );
866	},
867	getScrollInfo: function( within ) {
868		var overflowX = within.isWindow || within.isDocument ? "" :
869				within.element.css( "overflow-x" ),
870			overflowY = within.isWindow || within.isDocument ? "" :
871				within.element.css( "overflow-y" ),
872			hasOverflowX = overflowX === "scroll" ||
873				( overflowX === "auto" && within.width < within.element[ 0 ].scrollWidth ),
874			hasOverflowY = overflowY === "scroll" ||
875				( overflowY === "auto" && within.height < within.element[ 0 ].scrollHeight );
876		return {
877			width: hasOverflowY ? $.position.scrollbarWidth() : 0,
878			height: hasOverflowX ? $.position.scrollbarWidth() : 0
879		};
880	},
881	getWithinInfo: function( element ) {
882		var withinElement = $( element || window ),
883			isElemWindow = isWindow( withinElement[ 0 ] ),
884			isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9,
885			hasOffset = !isElemWindow && !isDocument;
886		return {
887			element: withinElement,
888			isWindow: isElemWindow,
889			isDocument: isDocument,
890			offset: hasOffset ? $( element ).offset() : { left: 0, top: 0 },
891			scrollLeft: withinElement.scrollLeft(),
892			scrollTop: withinElement.scrollTop(),
893			width: withinElement.outerWidth(),
894			height: withinElement.outerHeight()
895		};
896	}
897};
898
899$.fn.position = function( options ) {
900	if ( !options || !options.of ) {
901		return _position.apply( this, arguments );
902	}
903
904	// Make a copy, we don't want to modify arguments
905	options = $.extend( {}, options );
906
907	var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
908
909		// Make sure string options are treated as CSS selectors
910		target = typeof options.of === "string" ?
911			$( document ).find( options.of ) :
912			$( options.of ),
913
914		within = $.position.getWithinInfo( options.within ),
915		scrollInfo = $.position.getScrollInfo( within ),
916		collision = ( options.collision || "flip" ).split( " " ),
917		offsets = {};
918
919	dimensions = getDimensions( target );
920	if ( target[ 0 ].preventDefault ) {
921
922		// Force left top to allow flipping
923		options.at = "left top";
924	}
925	targetWidth = dimensions.width;
926	targetHeight = dimensions.height;
927	targetOffset = dimensions.offset;
928
929	// Clone to reuse original targetOffset later
930	basePosition = $.extend( {}, targetOffset );
931
932	// Force my and at to have valid horizontal and vertical positions
933	// if a value is missing or invalid, it will be converted to center
934	$.each( [ "my", "at" ], function() {
935		var pos = ( options[ this ] || "" ).split( " " ),
936			horizontalOffset,
937			verticalOffset;
938
939		if ( pos.length === 1 ) {
940			pos = rhorizontal.test( pos[ 0 ] ) ?
941				pos.concat( [ "center" ] ) :
942				rvertical.test( pos[ 0 ] ) ?
943					[ "center" ].concat( pos ) :
944					[ "center", "center" ];
945		}
946		pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
947		pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
948
949		// Calculate offsets
950		horizontalOffset = roffset.exec( pos[ 0 ] );
951		verticalOffset = roffset.exec( pos[ 1 ] );
952		offsets[ this ] = [
953			horizontalOffset ? horizontalOffset[ 0 ] : 0,
954			verticalOffset ? verticalOffset[ 0 ] : 0
955		];
956
957		// Reduce to just the positions without the offsets
958		options[ this ] = [
959			rposition.exec( pos[ 0 ] )[ 0 ],
960			rposition.exec( pos[ 1 ] )[ 0 ]
961		];
962	} );
963
964	// Normalize collision option
965	if ( collision.length === 1 ) {
966		collision[ 1 ] = collision[ 0 ];
967	}
968
969	if ( options.at[ 0 ] === "right" ) {
970		basePosition.left += targetWidth;
971	} else if ( options.at[ 0 ] === "center" ) {
972		basePosition.left += targetWidth / 2;
973	}
974
975	if ( options.at[ 1 ] === "bottom" ) {
976		basePosition.top += targetHeight;
977	} else if ( options.at[ 1 ] === "center" ) {
978		basePosition.top += targetHeight / 2;
979	}
980
981	atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
982	basePosition.left += atOffset[ 0 ];
983	basePosition.top += atOffset[ 1 ];
984
985	return this.each( function() {
986		var collisionPosition, using,
987			elem = $( this ),
988			elemWidth = elem.outerWidth(),
989			elemHeight = elem.outerHeight(),
990			marginLeft = parseCss( this, "marginLeft" ),
991			marginTop = parseCss( this, "marginTop" ),
992			collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) +
993				scrollInfo.width,
994			collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) +
995				scrollInfo.height,
996			position = $.extend( {}, basePosition ),
997			myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
998
999		if ( options.my[ 0 ] === "right" ) {
1000			position.left -= elemWidth;
1001		} else if ( options.my[ 0 ] === "center" ) {
1002			position.left -= elemWidth / 2;
1003		}
1004
1005		if ( options.my[ 1 ] === "bottom" ) {
1006			position.top -= elemHeight;
1007		} else if ( options.my[ 1 ] === "center" ) {
1008			position.top -= elemHeight / 2;
1009		}
1010
1011		position.left += myOffset[ 0 ];
1012		position.top += myOffset[ 1 ];
1013
1014		collisionPosition = {
1015			marginLeft: marginLeft,
1016			marginTop: marginTop
1017		};
1018
1019		$.each( [ "left", "top" ], function( i, dir ) {
1020			if ( $.ui.position[ collision[ i ] ] ) {
1021				$.ui.position[ collision[ i ] ][ dir ]( position, {
1022					targetWidth: targetWidth,
1023					targetHeight: targetHeight,
1024					elemWidth: elemWidth,
1025					elemHeight: elemHeight,
1026					collisionPosition: collisionPosition,
1027					collisionWidth: collisionWidth,
1028					collisionHeight: collisionHeight,
1029					offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
1030					my: options.my,
1031					at: options.at,
1032					within: within,
1033					elem: elem
1034				} );
1035			}
1036		} );
1037
1038		if ( options.using ) {
1039
1040			// Adds feedback as second argument to using callback, if present
1041			using = function( props ) {
1042				var left = targetOffset.left - position.left,
1043					right = left + targetWidth - elemWidth,
1044					top = targetOffset.top - position.top,
1045					bottom = top + targetHeight - elemHeight,
1046					feedback = {
1047						target: {
1048							element: target,
1049							left: targetOffset.left,
1050							top: targetOffset.top,
1051							width: targetWidth,
1052							height: targetHeight
1053						},
1054						element: {
1055							element: elem,
1056							left: position.left,
1057							top: position.top,
1058							width: elemWidth,
1059							height: elemHeight
1060						},
1061						horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
1062						vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
1063					};
1064				if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
1065					feedback.horizontal = "center";
1066				}
1067				if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
1068					feedback.vertical = "middle";
1069				}
1070				if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
1071					feedback.important = "horizontal";
1072				} else {
1073					feedback.important = "vertical";
1074				}
1075				options.using.call( this, props, feedback );
1076			};
1077		}
1078
1079		elem.offset( $.extend( position, { using: using } ) );
1080	} );
1081};
1082
1083$.ui.position = {
1084	fit: {
1085		left: function( position, data ) {
1086			var within = data.within,
1087				withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
1088				outerWidth = within.width,
1089				collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1090				overLeft = withinOffset - collisionPosLeft,
1091				overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
1092				newOverRight;
1093
1094			// Element is wider than within
1095			if ( data.collisionWidth > outerWidth ) {
1096
1097				// Element is initially over the left side of within
1098				if ( overLeft > 0 && overRight <= 0 ) {
1099					newOverRight = position.left + overLeft + data.collisionWidth - outerWidth -
1100						withinOffset;
1101					position.left += overLeft - newOverRight;
1102
1103				// Element is initially over right side of within
1104				} else if ( overRight > 0 && overLeft <= 0 ) {
1105					position.left = withinOffset;
1106
1107				// Element is initially over both left and right sides of within
1108				} else {
1109					if ( overLeft > overRight ) {
1110						position.left = withinOffset + outerWidth - data.collisionWidth;
1111					} else {
1112						position.left = withinOffset;
1113					}
1114				}
1115
1116			// Too far left -> align with left edge
1117			} else if ( overLeft > 0 ) {
1118				position.left += overLeft;
1119
1120			// Too far right -> align with right edge
1121			} else if ( overRight > 0 ) {
1122				position.left -= overRight;
1123
1124			// Adjust based on position and margin
1125			} else {
1126				position.left = max( position.left - collisionPosLeft, position.left );
1127			}
1128		},
1129		top: function( position, data ) {
1130			var within = data.within,
1131				withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
1132				outerHeight = data.within.height,
1133				collisionPosTop = position.top - data.collisionPosition.marginTop,
1134				overTop = withinOffset - collisionPosTop,
1135				overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
1136				newOverBottom;
1137
1138			// Element is taller than within
1139			if ( data.collisionHeight > outerHeight ) {
1140
1141				// Element is initially over the top of within
1142				if ( overTop > 0 && overBottom <= 0 ) {
1143					newOverBottom = position.top + overTop + data.collisionHeight - outerHeight -
1144						withinOffset;
1145					position.top += overTop - newOverBottom;
1146
1147				// Element is initially over bottom of within
1148				} else if ( overBottom > 0 && overTop <= 0 ) {
1149					position.top = withinOffset;
1150
1151				// Element is initially over both top and bottom of within
1152				} else {
1153					if ( overTop > overBottom ) {
1154						position.top = withinOffset + outerHeight - data.collisionHeight;
1155					} else {
1156						position.top = withinOffset;
1157					}
1158				}
1159
1160			// Too far up -> align with top
1161			} else if ( overTop > 0 ) {
1162				position.top += overTop;
1163
1164			// Too far down -> align with bottom edge
1165			} else if ( overBottom > 0 ) {
1166				position.top -= overBottom;
1167
1168			// Adjust based on position and margin
1169			} else {
1170				position.top = max( position.top - collisionPosTop, position.top );
1171			}
1172		}
1173	},
1174	flip: {
1175		left: function( position, data ) {
1176			var within = data.within,
1177				withinOffset = within.offset.left + within.scrollLeft,
1178				outerWidth = within.width,
1179				offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
1180				collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1181				overLeft = collisionPosLeft - offsetLeft,
1182				overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
1183				myOffset = data.my[ 0 ] === "left" ?
1184					-data.elemWidth :
1185					data.my[ 0 ] === "right" ?
1186						data.elemWidth :
1187						0,
1188				atOffset = data.at[ 0 ] === "left" ?
1189					data.targetWidth :
1190					data.at[ 0 ] === "right" ?
1191						-data.targetWidth :
1192						0,
1193				offset = -2 * data.offset[ 0 ],
1194				newOverRight,
1195				newOverLeft;
1196
1197			if ( overLeft < 0 ) {
1198				newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth -
1199					outerWidth - withinOffset;
1200				if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
1201					position.left += myOffset + atOffset + offset;
1202				}
1203			} else if ( overRight > 0 ) {
1204				newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset +
1205					atOffset + offset - offsetLeft;
1206				if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
1207					position.left += myOffset + atOffset + offset;
1208				}
1209			}
1210		},
1211		top: function( position, data ) {
1212			var within = data.within,
1213				withinOffset = within.offset.top + within.scrollTop,
1214				outerHeight = within.height,
1215				offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
1216				collisionPosTop = position.top - data.collisionPosition.marginTop,
1217				overTop = collisionPosTop - offsetTop,
1218				overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
1219				top = data.my[ 1 ] === "top",
1220				myOffset = top ?
1221					-data.elemHeight :
1222					data.my[ 1 ] === "bottom" ?
1223						data.elemHeight :
1224						0,
1225				atOffset = data.at[ 1 ] === "top" ?
1226					data.targetHeight :
1227					data.at[ 1 ] === "bottom" ?
1228						-data.targetHeight :
1229						0,
1230				offset = -2 * data.offset[ 1 ],
1231				newOverTop,
1232				newOverBottom;
1233			if ( overTop < 0 ) {
1234				newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight -
1235					outerHeight - withinOffset;
1236				if ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) {
1237					position.top += myOffset + atOffset + offset;
1238				}
1239			} else if ( overBottom > 0 ) {
1240				newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset +
1241					offset - offsetTop;
1242				if ( newOverTop > 0 || abs( newOverTop ) < overBottom ) {
1243					position.top += myOffset + atOffset + offset;
1244				}
1245			}
1246		}
1247	},
1248	flipfit: {
1249		left: function() {
1250			$.ui.position.flip.left.apply( this, arguments );
1251			$.ui.position.fit.left.apply( this, arguments );
1252		},
1253		top: function() {
1254			$.ui.position.flip.top.apply( this, arguments );
1255			$.ui.position.fit.top.apply( this, arguments );
1256		}
1257	}
1258};
1259
1260} )();
1261
1262var position = $.ui.position;
1263
1264
1265/*!
1266 * jQuery UI :data 1.14.0
1267 * https://jqueryui.com
1268 *
1269 * Copyright OpenJS Foundation and other contributors
1270 * Released under the MIT license.
1271 * https://jquery.org/license
1272 */
1273
1274//>>label: :data Selector
1275//>>group: Core
1276//>>description: Selects elements which have data stored under the specified key.
1277//>>docs: https://api.jqueryui.com/data-selector/
1278
1279
1280var data = $.extend( $.expr.pseudos, {
1281	data: $.expr.createPseudo( function( dataName ) {
1282		return function( elem ) {
1283			return !!$.data( elem, dataName );
1284		};
1285	} )
1286} );
1287
1288/*!
1289 * jQuery UI Disable Selection 1.14.0
1290 * https://jqueryui.com
1291 *
1292 * Copyright OpenJS Foundation and other contributors
1293 * Released under the MIT license.
1294 * https://jquery.org/license
1295 */
1296
1297//>>label: disableSelection
1298//>>group: Core
1299//>>description: Disable selection of text content within the set of matched elements.
1300//>>docs: https://api.jqueryui.com/disableSelection/
1301
1302// This file is deprecated
1303
1304var disableSelection = $.fn.extend( {
1305	disableSelection: ( function() {
1306		var eventType = "onselectstart" in document.createElement( "div" ) ?
1307			"selectstart" :
1308			"mousedown";
1309
1310		return function() {
1311			return this.on( eventType + ".ui-disableSelection", function( event ) {
1312				event.preventDefault();
1313			} );
1314		};
1315	} )(),
1316
1317	enableSelection: function() {
1318		return this.off( ".ui-disableSelection" );
1319	}
1320} );
1321
1322
1323
1324// Create a local jQuery because jQuery Color relies on it and the
1325// global may not exist with AMD and a custom build (#10199).
1326// This module is a noop if used as a regular AMD module.
1327// eslint-disable-next-line no-unused-vars
1328var jQuery = $;
1329
1330
1331/*!
1332 * jQuery Color Animations v3.0.0
1333 * https://github.com/jquery/jquery-color
1334 *
1335 * Copyright OpenJS Foundation and other contributors
1336 * Released under the MIT license.
1337 * https://jquery.org/license
1338 *
1339 * Date: Wed May 15 16:49:44 2024 +0200
1340 */
1341
1342
1343	var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor " +
1344		"borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",
1345
1346	class2type = {},
1347	toString = class2type.toString,
1348
1349	// plusequals test for += 100 -= 100
1350	rplusequals = /^([\-+])=\s*(\d+\.?\d*)/,
1351
1352	// a set of RE's that can match strings and generate color tuples.
1353	stringParsers = [ {
1354			re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
1355			parse: function( execResult ) {
1356				return [
1357					execResult[ 1 ],
1358					execResult[ 2 ],
1359					execResult[ 3 ],
1360					execResult[ 4 ]
1361				];
1362			}
1363		}, {
1364			re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
1365			parse: function( execResult ) {
1366				return [
1367					execResult[ 1 ] * 2.55,
1368					execResult[ 2 ] * 2.55,
1369					execResult[ 3 ] * 2.55,
1370					execResult[ 4 ]
1371				];
1372			}
1373		}, {
1374
1375			// this regex ignores A-F because it's compared against an already lowercased string
1376			re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})?/,
1377			parse: function( execResult ) {
1378				return [
1379					parseInt( execResult[ 1 ], 16 ),
1380					parseInt( execResult[ 2 ], 16 ),
1381					parseInt( execResult[ 3 ], 16 ),
1382					execResult[ 4 ] ?
1383						( parseInt( execResult[ 4 ], 16 ) / 255 ).toFixed( 2 ) :
1384						1
1385				];
1386			}
1387		}, {
1388
1389			// this regex ignores A-F because it's compared against an already lowercased string
1390			re: /#([a-f0-9])([a-f0-9])([a-f0-9])([a-f0-9])?/,
1391			parse: function( execResult ) {
1392				return [
1393					parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),
1394					parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),
1395					parseInt( execResult[ 3 ] + execResult[ 3 ], 16 ),
1396					execResult[ 4 ] ?
1397						( parseInt( execResult[ 4 ] + execResult[ 4 ], 16 ) / 255 )
1398							.toFixed( 2 ) :
1399						1
1400				];
1401			}
1402		}, {
1403			re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
1404			space: "hsla",
1405			parse: function( execResult ) {
1406				return [
1407					execResult[ 1 ],
1408					execResult[ 2 ] / 100,
1409					execResult[ 3 ] / 100,
1410					execResult[ 4 ]
1411				];
1412			}
1413		} ],
1414
1415	// jQuery.Color( )
1416	color = jQuery.Color = function( color, green, blue, alpha ) {
1417		return new jQuery.Color.fn.parse( color, green, blue, alpha );
1418	},
1419	spaces = {
1420		rgba: {
1421			props: {
1422				red: {
1423					idx: 0,
1424					type: "byte"
1425				},
1426				green: {
1427					idx: 1,
1428					type: "byte"
1429				},
1430				blue: {
1431					idx: 2,
1432					type: "byte"
1433				}
1434			}
1435		},
1436
1437		hsla: {
1438			props: {
1439				hue: {
1440					idx: 0,
1441					type: "degrees"
1442				},
1443				saturation: {
1444					idx: 1,
1445					type: "percent"
1446				},
1447				lightness: {
1448					idx: 2,
1449					type: "percent"
1450				}
1451			}
1452		}
1453	},
1454	propTypes = {
1455		"byte": {
1456			floor: true,
1457			max: 255
1458		},
1459		"percent": {
1460			max: 1
1461		},
1462		"degrees": {
1463			mod: 360,
1464			floor: true
1465		}
1466	},
1467
1468	// colors = jQuery.Color.names
1469	colors,
1470
1471	// local aliases of functions called often
1472	each = jQuery.each;
1473
1474// define cache name and alpha properties
1475// for rgba and hsla spaces
1476each( spaces, function( spaceName, space ) {
1477	space.cache = "_" + spaceName;
1478	space.props.alpha = {
1479		idx: 3,
1480		type: "percent",
1481		def: 1
1482	};
1483} );
1484
1485// Populate the class2type map
1486jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
1487	function( _i, name ) {
1488		class2type[ "[object " + name + "]" ] = name.toLowerCase();
1489	} );
1490
1491function getType( obj ) {
1492	if ( obj == null ) {
1493		return obj + "";
1494	}
1495
1496	return typeof obj === "object" ?
1497		class2type[ toString.call( obj ) ] || "object" :
1498		typeof obj;
1499}
1500
1501function clamp( value, prop, allowEmpty ) {
1502	var type = propTypes[ prop.type ] || {};
1503
1504	if ( value == null ) {
1505		return ( allowEmpty || !prop.def ) ? null : prop.def;
1506	}
1507
1508	// ~~ is an short way of doing floor for positive numbers
1509	value = type.floor ? ~~value : parseFloat( value );
1510
1511	if ( type.mod ) {
1512
1513		// we add mod before modding to make sure that negatives values
1514		// get converted properly: -10 -> 350
1515		return ( value + type.mod ) % type.mod;
1516	}
1517
1518	// for now all property types without mod have min and max
1519	return Math.min( type.max, Math.max( 0, value ) );
1520}
1521
1522function stringParse( string ) {
1523	var inst = color(),
1524		rgba = inst._rgba = [];
1525
1526	string = string.toLowerCase();
1527
1528	each( stringParsers, function( _i, parser ) {
1529		var parsed,
1530			match = parser.re.exec( string ),
1531			values = match && parser.parse( match ),
1532			spaceName = parser.space || "rgba";
1533
1534		if ( values ) {
1535			parsed = inst[ spaceName ]( values );
1536
1537			// if this was an rgba parse the assignment might happen twice
1538			// oh well....
1539			inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ];
1540			rgba = inst._rgba = parsed._rgba;
1541
1542			// exit each( stringParsers ) here because we matched
1543			return false;
1544		}
1545	} );
1546
1547	// Found a stringParser that handled it
1548	if ( rgba.length ) {
1549
1550		// if this came from a parsed string, force "transparent" when alpha is 0
1551		// chrome, (and maybe others) return "transparent" as rgba(0,0,0,0)
1552		if ( rgba.join() === "0,0,0,0" ) {
1553			jQuery.extend( rgba, colors.transparent );
1554		}
1555		return inst;
1556	}
1557
1558	// named colors
1559	return colors[ string ];
1560}
1561
1562color.fn = jQuery.extend( color.prototype, {
1563	parse: function( red, green, blue, alpha ) {
1564		if ( red === undefined ) {
1565			this._rgba = [ null, null, null, null ];
1566			return this;
1567		}
1568		if ( red.jquery || red.nodeType ) {
1569			red = jQuery( red ).css( green );
1570			green = undefined;
1571		}
1572
1573		var inst = this,
1574			type = getType( red ),
1575			rgba = this._rgba = [];
1576
1577		// more than 1 argument specified - assume ( red, green, blue, alpha )
1578		if ( green !== undefined ) {
1579			red = [ red, green, blue, alpha ];
1580			type = "array";
1581		}
1582
1583		if ( type === "string" ) {
1584			return this.parse( stringParse( red ) || colors._default );
1585		}
1586
1587		if ( type === "array" ) {
1588			each( spaces.rgba.props, function( _key, prop ) {
1589				rgba[ prop.idx ] = clamp( red[ prop.idx ], prop );
1590			} );
1591			return this;
1592		}
1593
1594		if ( type === "object" ) {
1595			if ( red instanceof color ) {
1596				each( spaces, function( _spaceName, space ) {
1597					if ( red[ space.cache ] ) {
1598						inst[ space.cache ] = red[ space.cache ].slice();
1599					}
1600				} );
1601			} else {
1602				each( spaces, function( _spaceName, space ) {
1603					var cache = space.cache;
1604					each( space.props, function( key, prop ) {
1605
1606						// if the cache doesn't exist, and we know how to convert
1607						if ( !inst[ cache ] && space.to ) {
1608
1609							// if the value was null, we don't need to copy it
1610							// if the key was alpha, we don't need to copy it either
1611							if ( key === "alpha" || red[ key ] == null ) {
1612								return;
1613							}
1614							inst[ cache ] = space.to( inst._rgba );
1615						}
1616
1617						// this is the only case where we allow nulls for ALL properties.
1618						// call clamp with alwaysAllowEmpty
1619						inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true );
1620					} );
1621
1622					// everything defined but alpha?
1623					if ( inst[ cache ] && jQuery.inArray(
1624						null,
1625						inst[ cache ].slice( 0, 3 )
1626					) < 0 ) {
1627
1628						// use the default of 1
1629						if ( inst[ cache ][ 3 ] == null ) {
1630							inst[ cache ][ 3 ] = 1;
1631						}
1632
1633						if ( space.from ) {
1634							inst._rgba = space.from( inst[ cache ] );
1635						}
1636					}
1637				} );
1638			}
1639			return this;
1640		}
1641	},
1642	is: function( compare ) {
1643		var is = color( compare ),
1644			same = true,
1645			inst = this;
1646
1647		each( spaces, function( _, space ) {
1648			var localCache,
1649				isCache = is[ space.cache ];
1650			if ( isCache ) {
1651				localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || [];
1652				each( space.props, function( _, prop ) {
1653					if ( isCache[ prop.idx ] != null ) {
1654						same = ( isCache[ prop.idx ] === localCache[ prop.idx ] );
1655						return same;
1656					}
1657				} );
1658			}
1659			return same;
1660		} );
1661		return same;
1662	},
1663	_space: function() {
1664		var used = [],
1665			inst = this;
1666		each( spaces, function( spaceName, space ) {
1667			if ( inst[ space.cache ] ) {
1668				used.push( spaceName );
1669			}
1670		} );
1671		return used.pop();
1672	},
1673	transition: function( other, distance ) {
1674		var end = color( other ),
1675			spaceName = end._space(),
1676			space = spaces[ spaceName ],
1677			startColor = this.alpha() === 0 ? color( "transparent" ) : this,
1678			start = startColor[ space.cache ] || space.to( startColor._rgba ),
1679			result = start.slice();
1680
1681		end = end[ space.cache ];
1682		each( space.props, function( _key, prop ) {
1683			var index = prop.idx,
1684				startValue = start[ index ],
1685				endValue = end[ index ],
1686				type = propTypes[ prop.type ] || {};
1687
1688			// if null, don't override start value
1689			if ( endValue === null ) {
1690				return;
1691			}
1692
1693			// if null - use end
1694			if ( startValue === null ) {
1695				result[ index ] = endValue;
1696			} else {
1697				if ( type.mod ) {
1698					if ( endValue - startValue > type.mod / 2 ) {
1699						startValue += type.mod;
1700					} else if ( startValue - endValue > type.mod / 2 ) {
1701						startValue -= type.mod;
1702					}
1703				}
1704				result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop );
1705			}
1706		} );
1707		return this[ spaceName ]( result );
1708	},
1709	blend: function( opaque ) {
1710
1711		// if we are already opaque - return ourself
1712		if ( this._rgba[ 3 ] === 1 ) {
1713			return this;
1714		}
1715
1716		var rgb = this._rgba.slice(),
1717			a = rgb.pop(),
1718			blend = color( opaque )._rgba;
1719
1720		return color( jQuery.map( rgb, function( v, i ) {
1721			return ( 1 - a ) * blend[ i ] + a * v;
1722		} ) );
1723	},
1724	toRgbaString: function() {
1725		var prefix = "rgba(",
1726			rgba = jQuery.map( this._rgba, function( v, i ) {
1727				if ( v != null ) {
1728					return v;
1729				}
1730				return i > 2 ? 1 : 0;
1731			} );
1732
1733		if ( rgba[ 3 ] === 1 ) {
1734			rgba.pop();
1735			prefix = "rgb(";
1736		}
1737
1738		return prefix + rgba.join( ", " ) + ")";
1739	},
1740	toHslaString: function() {
1741		var prefix = "hsla(",
1742			hsla = jQuery.map( this.hsla(), function( v, i ) {
1743				if ( v == null ) {
1744					v = i > 2 ? 1 : 0;
1745				}
1746
1747				// catch 1 and 2
1748				if ( i && i < 3 ) {
1749					v = Math.round( v * 100 ) + "%";
1750				}
1751				return v;
1752			} );
1753
1754		if ( hsla[ 3 ] === 1 ) {
1755			hsla.pop();
1756			prefix = "hsl(";
1757		}
1758		return prefix + hsla.join( ", " ) + ")";
1759	},
1760	toHexString: function( includeAlpha ) {
1761		var rgba = this._rgba.slice(),
1762			alpha = rgba.pop();
1763
1764		if ( includeAlpha ) {
1765			rgba.push( ~~( alpha * 255 ) );
1766		}
1767
1768		return "#" + jQuery.map( rgba, function( v ) {
1769
1770			// default to 0 when nulls exist
1771			return ( "0" + ( v || 0 ).toString( 16 ) ).substr( -2 );
1772		} ).join( "" );
1773	},
1774	toString: function() {
1775		return this.toRgbaString();
1776	}
1777} );
1778color.fn.parse.prototype = color.fn;
1779
1780// hsla conversions adapted from:
1781// https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021
1782
1783function hue2rgb( p, q, h ) {
1784	h = ( h + 1 ) % 1;
1785	if ( h * 6 < 1 ) {
1786		return p + ( q - p ) * h * 6;
1787	}
1788	if ( h * 2 < 1 ) {
1789		return q;
1790	}
1791	if ( h * 3 < 2 ) {
1792		return p + ( q - p ) * ( ( 2 / 3 ) - h ) * 6;
1793	}
1794	return p;
1795}
1796
1797spaces.hsla.to = function( rgba ) {
1798	if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) {
1799		return [ null, null, null, rgba[ 3 ] ];
1800	}
1801	var r = rgba[ 0 ] / 255,
1802		g = rgba[ 1 ] / 255,
1803		b = rgba[ 2 ] / 255,
1804		a = rgba[ 3 ],
1805		max = Math.max( r, g, b ),
1806		min = Math.min( r, g, b ),
1807		diff = max - min,
1808		add = max + min,
1809		l = add * 0.5,
1810		h, s;
1811
1812	if ( min === max ) {
1813		h = 0;
1814	} else if ( r === max ) {
1815		h = ( 60 * ( g - b ) / diff ) + 360;
1816	} else if ( g === max ) {
1817		h = ( 60 * ( b - r ) / diff ) + 120;
1818	} else {
1819		h = ( 60 * ( r - g ) / diff ) + 240;
1820	}
1821
1822	// chroma (diff) == 0 means greyscale which, by definition, saturation = 0%
1823	// otherwise, saturation is based on the ratio of chroma (diff) to lightness (add)
1824	if ( diff === 0 ) {
1825		s = 0;
1826	} else if ( l <= 0.5 ) {
1827		s = diff / add;
1828	} else {
1829		s = diff / ( 2 - add );
1830	}
1831	return [ Math.round( h ) % 360, s, l, a == null ? 1 : a ];
1832};
1833
1834spaces.hsla.from = function( hsla ) {
1835	if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) {
1836		return [ null, null, null, hsla[ 3 ] ];
1837	}
1838	var h = hsla[ 0 ] / 360,
1839		s = hsla[ 1 ],
1840		l = hsla[ 2 ],
1841		a = hsla[ 3 ],
1842		q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s,
1843		p = 2 * l - q;
1844
1845	return [
1846		Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ),
1847		Math.round( hue2rgb( p, q, h ) * 255 ),
1848		Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ),
1849		a
1850	];
1851};
1852
1853
1854each( spaces, function( spaceName, space ) {
1855	var props = space.props,
1856		cache = space.cache,
1857		to = space.to,
1858		from = space.from;
1859
1860	// makes rgba() and hsla()
1861	color.fn[ spaceName ] = function( value ) {
1862
1863		// generate a cache for this space if it doesn't exist
1864		if ( to && !this[ cache ] ) {
1865			this[ cache ] = to( this._rgba );
1866		}
1867		if ( value === undefined ) {
1868			return this[ cache ].slice();
1869		}
1870
1871		var ret,
1872			type = getType( value ),
1873			arr = ( type === "array" || type === "object" ) ? value : arguments,
1874			local = this[ cache ].slice();
1875
1876		each( props, function( key, prop ) {
1877			var val = arr[ type === "object" ? key : prop.idx ];
1878			if ( val == null ) {
1879				val = local[ prop.idx ];
1880			}
1881			local[ prop.idx ] = clamp( val, prop );
1882		} );
1883
1884		if ( from ) {
1885			ret = color( from( local ) );
1886			ret[ cache ] = local;
1887			return ret;
1888		} else {
1889			return color( local );
1890		}
1891	};
1892
1893	// makes red() green() blue() alpha() hue() saturation() lightness()
1894	each( props, function( key, prop ) {
1895
1896		// alpha is included in more than one space
1897		if ( color.fn[ key ] ) {
1898			return;
1899		}
1900		color.fn[ key ] = function( value ) {
1901			var local, cur, match, fn,
1902				vtype = getType( value );
1903
1904			if ( key === "alpha" ) {
1905				fn = this._hsla ? "hsla" : "rgba";
1906			} else {
1907				fn = spaceName;
1908			}
1909			local = this[ fn ]();
1910			cur = local[ prop.idx ];
1911
1912			if ( vtype === "undefined" ) {
1913				return cur;
1914			}
1915
1916			if ( vtype === "function" ) {
1917				value = value.call( this, cur );
1918				vtype = getType( value );
1919			}
1920			if ( value == null && prop.empty ) {
1921				return this;
1922			}
1923			if ( vtype === "string" ) {
1924				match = rplusequals.exec( value );
1925				if ( match ) {
1926					value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 );
1927				}
1928			}
1929			local[ prop.idx ] = value;
1930			return this[ fn ]( local );
1931		};
1932	} );
1933} );
1934
1935// add cssHook and .fx.step function for each named hook.
1936// accept a space separated string of properties
1937color.hook = function( hook ) {
1938	var hooks = hook.split( " " );
1939	each( hooks, function( _i, hook ) {
1940		jQuery.cssHooks[ hook ] = {
1941			set: function( elem, value ) {
1942				var parsed;
1943
1944				if ( value !== "transparent" &&
1945					( getType( value ) !== "string" ||
1946						( parsed = stringParse( value ) ) ) ) {
1947					value = color( parsed || value );
1948					value = value.toRgbaString();
1949				}
1950				elem.style[ hook ] = value;
1951			}
1952		};
1953		jQuery.fx.step[ hook ] = function( fx ) {
1954			if ( !fx.colorInit ) {
1955				fx.start = color( fx.elem, hook );
1956				fx.end = color( fx.end );
1957				fx.colorInit = true;
1958			}
1959			jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) );
1960		};
1961	} );
1962
1963};
1964
1965color.hook( stepHooks );
1966
1967jQuery.cssHooks.borderColor = {
1968	expand: function( value ) {
1969		var expanded = {};
1970
1971		each( [ "Top", "Right", "Bottom", "Left" ], function( _i, part ) {
1972			expanded[ "border" + part + "Color" ] = value;
1973		} );
1974		return expanded;
1975	}
1976};
1977
1978// Basic color names only.
1979// Usage of any of the other color names requires adding yourself or including
1980// jquery.color.svg-names.js.
1981colors = jQuery.Color.names = {
1982
1983	// 4.1. Basic color keywords
1984	aqua: "#00ffff",
1985	black: "#000000",
1986	blue: "#0000ff",
1987	fuchsia: "#ff00ff",
1988	gray: "#808080",
1989	green: "#008000",
1990	lime: "#00ff00",
1991	maroon: "#800000",
1992	navy: "#000080",
1993	olive: "#808000",
1994	purple: "#800080",
1995	red: "#ff0000",
1996	silver: "#c0c0c0",
1997	teal: "#008080",
1998	white: "#ffffff",
1999	yellow: "#ffff00",
2000
2001	// 4.2.3. "transparent" color keyword
2002	transparent: [ null, null, null, 0 ],
2003
2004	_default: "#ffffff"
2005};
2006
2007
2008/*!
2009 * jQuery UI Effects 1.14.0
2010 * https://jqueryui.com
2011 *
2012 * Copyright OpenJS Foundation and other contributors
2013 * Released under the MIT license.
2014 * https://jquery.org/license
2015 */
2016
2017//>>label: Effects Core
2018//>>group: Effects
2019/* eslint-disable max-len */
2020//>>description: Extends the internal jQuery effects. Includes morphing and easing. Required by all other effects.
2021/* eslint-enable max-len */
2022//>>docs: https://api.jqueryui.com/category/effects-core/
2023//>>demos: https://jqueryui.com/effect/
2024
2025
2026var dataSpace = "ui-effects-",
2027	dataSpaceStyle = "ui-effects-style",
2028	dataSpaceAnimated = "ui-effects-animated";
2029
2030$.effects = {
2031	effect: {}
2032};
2033
2034/******************************************************************************/
2035/****************************** CLASS ANIMATIONS ******************************/
2036/******************************************************************************/
2037( function() {
2038
2039var classAnimationActions = [ "add", "remove", "toggle" ],
2040	shorthandStyles = {
2041		border: 1,
2042		borderBottom: 1,
2043		borderColor: 1,
2044		borderLeft: 1,
2045		borderRight: 1,
2046		borderTop: 1,
2047		borderWidth: 1,
2048		margin: 1,
2049		padding: 1
2050	};
2051
2052$.each(
2053	[ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ],
2054	function( _, prop ) {
2055		$.fx.step[ prop ] = function( fx ) {
2056			if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) {
2057				jQuery.style( fx.elem, prop, fx.end );
2058				fx.setAttr = true;
2059			}
2060		};
2061	}
2062);
2063
2064function camelCase( string ) {
2065	return string.replace( /-([\da-z])/gi, function( all, letter ) {
2066		return letter.toUpperCase();
2067	} );
2068}
2069
2070function getElementStyles( elem ) {
2071	var key, len,
2072		style = elem.ownerDocument.defaultView.getComputedStyle( elem ),
2073		styles = {};
2074
2075	len = style.length;
2076	while ( len-- ) {
2077		key = style[ len ];
2078		if ( typeof style[ key ] === "string" ) {
2079			styles[ camelCase( key ) ] = style[ key ];
2080		}
2081	}
2082
2083	return styles;
2084}
2085
2086function styleDifference( oldStyle, newStyle ) {
2087	var diff = {},
2088		name, value;
2089
2090	for ( name in newStyle ) {
2091		value = newStyle[ name ];
2092		if ( oldStyle[ name ] !== value ) {
2093			if ( !shorthandStyles[ name ] ) {
2094				if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) {
2095					diff[ name ] = value;
2096				}
2097			}
2098		}
2099	}
2100
2101	return diff;
2102}
2103
2104$.effects.animateClass = function( value, duration, easing, callback ) {
2105	var o = $.speed( duration, easing, callback );
2106
2107	return this.queue( function() {
2108		var animated = $( this ),
2109			baseClass = animated.attr( "class" ) || "",
2110			applyClassChange,
2111			allAnimations = o.children ? animated.find( "*" ).addBack() : animated;
2112
2113		// Map the animated objects to store the original styles.
2114		allAnimations = allAnimations.map( function() {
2115			var el = $( this );
2116			return {
2117				el: el,
2118				start: getElementStyles( this )
2119			};
2120		} );
2121
2122		// Apply class change
2123		applyClassChange = function() {
2124			$.each( classAnimationActions, function( i, action ) {
2125				if ( value[ action ] ) {
2126					animated[ action + "Class" ]( value[ action ] );
2127				}
2128			} );
2129		};
2130		applyClassChange();
2131
2132		// Map all animated objects again - calculate new styles and diff
2133		allAnimations = allAnimations.map( function() {
2134			this.end = getElementStyles( this.el[ 0 ] );
2135			this.diff = styleDifference( this.start, this.end );
2136			return this;
2137		} );
2138
2139		// Apply original class
2140		animated.attr( "class", baseClass );
2141
2142		// Map all animated objects again - this time collecting a promise
2143		allAnimations = allAnimations.map( function() {
2144			var styleInfo = this,
2145				dfd = $.Deferred(),
2146				opts = $.extend( {}, o, {
2147					queue: false,
2148					complete: function() {
2149						dfd.resolve( styleInfo );
2150					}
2151				} );
2152
2153			this.el.animate( this.diff, opts );
2154			return dfd.promise();
2155		} );
2156
2157		// Once all animations have completed:
2158		$.when.apply( $, allAnimations.get() ).done( function() {
2159
2160			// Set the final class
2161			applyClassChange();
2162
2163			// For each animated element,
2164			// clear all css properties that were animated
2165			$.each( arguments, function() {
2166				var el = this.el;
2167				$.each( this.diff, function( key ) {
2168					el.css( key, "" );
2169				} );
2170			} );
2171
2172			// This is guarnteed to be there if you use jQuery.speed()
2173			// it also handles dequeuing the next anim...
2174			o.complete.call( animated[ 0 ] );
2175		} );
2176	} );
2177};
2178
2179$.fn.extend( {
2180	addClass: ( function( orig ) {
2181		return function( classNames, speed, easing, callback ) {
2182			return speed ?
2183				$.effects.animateClass.call( this,
2184					{ add: classNames }, speed, easing, callback ) :
2185				orig.apply( this, arguments );
2186		};
2187	} )( $.fn.addClass ),
2188
2189	removeClass: ( function( orig ) {
2190		return function( classNames, speed, easing, callback ) {
2191			return arguments.length > 1 ?
2192				$.effects.animateClass.call( this,
2193					{ remove: classNames }, speed, easing, callback ) :
2194				orig.apply( this, arguments );
2195		};
2196	} )( $.fn.removeClass ),
2197
2198	toggleClass: ( function( orig ) {
2199		return function( classNames, force, speed, easing, callback ) {
2200			if ( typeof force === "boolean" || force === undefined ) {
2201				if ( !speed ) {
2202
2203					// Without speed parameter
2204					return orig.apply( this, arguments );
2205				} else {
2206					return $.effects.animateClass.call( this,
2207						( force ? { add: classNames } : { remove: classNames } ),
2208						speed, easing, callback );
2209				}
2210			} else {
2211
2212				// Without force parameter
2213				return $.effects.animateClass.call( this,
2214					{ toggle: classNames }, force, speed, easing );
2215			}
2216		};
2217	} )( $.fn.toggleClass ),
2218
2219	switchClass: function( remove, add, speed, easing, callback ) {
2220		return $.effects.animateClass.call( this, {
2221			add: add,
2222			remove: remove
2223		}, speed, easing, callback );
2224	}
2225} );
2226
2227} )();
2228
2229/******************************************************************************/
2230/*********************************** EFFECTS **********************************/
2231/******************************************************************************/
2232
2233( function() {
2234
2235if ( $.expr && $.expr.pseudos && $.expr.pseudos.animated ) {
2236	$.expr.pseudos.animated = ( function( orig ) {
2237		return function( elem ) {
2238			return !!$( elem ).data( dataSpaceAnimated ) || orig( elem );
2239		};
2240	} )( $.expr.pseudos.animated );
2241}
2242
2243if ( $.uiBackCompat === true ) {
2244	$.extend( $.effects, {
2245
2246		// Saves a set of properties in a data storage
2247		save: function( element, set ) {
2248			var i = 0, length = set.length;
2249			for ( ; i < length; i++ ) {
2250				if ( set[ i ] !== null ) {
2251					element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] );
2252				}
2253			}
2254		},
2255
2256		// Restores a set of previously saved properties from a data storage
2257		restore: function( element, set ) {
2258			var val, i = 0, length = set.length;
2259			for ( ; i < length; i++ ) {
2260				if ( set[ i ] !== null ) {
2261					val = element.data( dataSpace + set[ i ] );
2262					element.css( set[ i ], val );
2263				}
2264			}
2265		},
2266
2267		setMode: function( el, mode ) {
2268			if ( mode === "toggle" ) {
2269				mode = el.is( ":hidden" ) ? "show" : "hide";
2270			}
2271			return mode;
2272		},
2273
2274		// Wraps the element around a wrapper that copies position properties
2275		createWrapper: function( element ) {
2276
2277			// If the element is already wrapped, return it
2278			if ( element.parent().is( ".ui-effects-wrapper" ) ) {
2279				return element.parent();
2280			}
2281
2282			// Wrap the element
2283			var props = {
2284					width: element.outerWidth( true ),
2285					height: element.outerHeight( true ),
2286					"float": element.css( "float" )
2287				},
2288				wrapper = $( "<div></div>" )
2289					.addClass( "ui-effects-wrapper" )
2290					.css( {
2291						fontSize: "100%",
2292						background: "transparent",
2293						border: "none",
2294						margin: 0,
2295						padding: 0
2296					} ),
2297
2298				// Store the size in case width/height are defined in % - Fixes #5245
2299				size = {
2300					width: element.width(),
2301					height: element.height()
2302				},
2303				active = document.activeElement;
2304
2305			// Support: Firefox
2306			// Firefox incorrectly exposes anonymous content
2307			// https://bugzilla.mozilla.org/show_bug.cgi?id=561664
2308			try {
2309				// eslint-disable-next-line no-unused-expressions
2310				active.id;
2311			} catch ( e ) {
2312				active = document.body;
2313			}
2314
2315			element.wrap( wrapper );
2316
2317			// Fixes #7595 - Elements lose focus when wrapped.
2318			if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
2319				$( active ).trigger( "focus" );
2320			}
2321
2322			// Hotfix for jQuery 1.4 since some change in wrap() seems to actually
2323			// lose the reference to the wrapped element
2324			wrapper = element.parent();
2325
2326			// Transfer positioning properties to the wrapper
2327			if ( element.css( "position" ) === "static" ) {
2328				wrapper.css( { position: "relative" } );
2329				element.css( { position: "relative" } );
2330			} else {
2331				$.extend( props, {
2332					position: element.css( "position" ),
2333					zIndex: element.css( "z-index" )
2334				} );
2335				$.each( [ "top", "left", "bottom", "right" ], function( i, pos ) {
2336					props[ pos ] = element.css( pos );
2337					if ( isNaN( parseInt( props[ pos ], 10 ) ) ) {
2338						props[ pos ] = "auto";
2339					}
2340				} );
2341				element.css( {
2342					position: "relative",
2343					top: 0,
2344					left: 0,
2345					right: "auto",
2346					bottom: "auto"
2347				} );
2348			}
2349			element.css( size );
2350
2351			return wrapper.css( props ).show();
2352		},
2353
2354		removeWrapper: function( element ) {
2355			var active = document.activeElement;
2356
2357			if ( element.parent().is( ".ui-effects-wrapper" ) ) {
2358				element.parent().replaceWith( element );
2359
2360				// Fixes #7595 - Elements lose focus when wrapped.
2361				if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
2362					$( active ).trigger( "focus" );
2363				}
2364			}
2365
2366			return element;
2367		}
2368	} );
2369}
2370
2371$.extend( $.effects, {
2372	version: "1.14.0",
2373
2374	define: function( name, mode, effect ) {
2375		if ( !effect ) {
2376			effect = mode;
2377			mode = "effect";
2378		}
2379
2380		$.effects.effect[ name ] = effect;
2381		$.effects.effect[ name ].mode = mode;
2382
2383		return effect;
2384	},
2385
2386	scaledDimensions: function( element, percent, direction ) {
2387		if ( percent === 0 ) {
2388			return {
2389				height: 0,
2390				width: 0,
2391				outerHeight: 0,
2392				outerWidth: 0
2393			};
2394		}
2395
2396		var x = direction !== "horizontal" ? ( ( percent || 100 ) / 100 ) : 1,
2397			y = direction !== "vertical" ? ( ( percent || 100 ) / 100 ) : 1;
2398
2399		return {
2400			height: element.height() * y,
2401			width: element.width() * x,
2402			outerHeight: element.outerHeight() * y,
2403			outerWidth: element.outerWidth() * x
2404		};
2405
2406	},
2407
2408	clipToBox: function( animation ) {
2409		return {
2410			width: animation.clip.right - animation.clip.left,
2411			height: animation.clip.bottom - animation.clip.top,
2412			left: animation.clip.left,
2413			top: animation.clip.top
2414		};
2415	},
2416
2417	// Injects recently queued functions to be first in line (after "inprogress")
2418	unshift: function( element, queueLength, count ) {
2419		var queue = element.queue();
2420
2421		if ( queueLength > 1 ) {
2422			queue.splice.apply( queue,
2423				[ 1, 0 ].concat( queue.splice( queueLength, count ) ) );
2424		}
2425		element.dequeue();
2426	},
2427
2428	saveStyle: function( element ) {
2429		element.data( dataSpaceStyle, element[ 0 ].style.cssText );
2430	},
2431
2432	restoreStyle: function( element ) {
2433		element[ 0 ].style.cssText = element.data( dataSpaceStyle ) || "";
2434		element.removeData( dataSpaceStyle );
2435	},
2436
2437	mode: function( element, mode ) {
2438		var hidden = element.is( ":hidden" );
2439
2440		if ( mode === "toggle" ) {
2441			mode = hidden ? "show" : "hide";
2442		}
2443		if ( hidden ? mode === "hide" : mode === "show" ) {
2444			mode = "none";
2445		}
2446		return mode;
2447	},
2448
2449	// Translates a [top,left] array into a baseline value
2450	getBaseline: function( origin, original ) {
2451		var y, x;
2452
2453		switch ( origin[ 0 ] ) {
2454		case "top":
2455			y = 0;
2456			break;
2457		case "middle":
2458			y = 0.5;
2459			break;
2460		case "bottom":
2461			y = 1;
2462			break;
2463		default:
2464			y = origin[ 0 ] / original.height;
2465		}
2466
2467		switch ( origin[ 1 ] ) {
2468		case "left":
2469			x = 0;
2470			break;
2471		case "center":
2472			x = 0.5;
2473			break;
2474		case "right":
2475			x = 1;
2476			break;
2477		default:
2478			x = origin[ 1 ] / original.width;
2479		}
2480
2481		return {
2482			x: x,
2483			y: y
2484		};
2485	},
2486
2487	// Creates a placeholder element so that the original element can be made absolute
2488	createPlaceholder: function( element ) {
2489		var placeholder,
2490			cssPosition = element.css( "position" ),
2491			position = element.position();
2492
2493		// Lock in margins first to account for form elements, which
2494		// will change margin if you explicitly set height
2495		// see: https://jsfiddle.net/JZSMt/3/ https://bugs.webkit.org/show_bug.cgi?id=107380
2496		// Support: Safari
2497		element.css( {
2498			marginTop: element.css( "marginTop" ),
2499			marginBottom: element.css( "marginBottom" ),
2500			marginLeft: element.css( "marginLeft" ),
2501			marginRight: element.css( "marginRight" )
2502		} )
2503		.outerWidth( element.outerWidth() )
2504		.outerHeight( element.outerHeight() );
2505
2506		if ( /^(static|relative)/.test( cssPosition ) ) {
2507			cssPosition = "absolute";
2508
2509			placeholder = $( "<" + element[ 0 ].nodeName + ">" ).insertAfter( element ).css( {
2510
2511				// Convert inline to inline block to account for inline elements
2512				// that turn to inline block based on content (like img)
2513				display: /^(inline|ruby)/.test( element.css( "display" ) ) ?
2514					"inline-block" :
2515					"block",
2516				visibility: "hidden",
2517
2518				// Margins need to be set to account for margin collapse
2519				marginTop: element.css( "marginTop" ),
2520				marginBottom: element.css( "marginBottom" ),
2521				marginLeft: element.css( "marginLeft" ),
2522				marginRight: element.css( "marginRight" ),
2523				"float": element.css( "float" )
2524			} )
2525			.outerWidth( element.outerWidth() )
2526			.outerHeight( element.outerHeight() )
2527			.addClass( "ui-effects-placeholder" );
2528
2529			element.data( dataSpace + "placeholder", placeholder );
2530		}
2531
2532		element.css( {
2533			position: cssPosition,
2534			left: position.left,
2535			top: position.top
2536		} );
2537
2538		return placeholder;
2539	},
2540
2541	removePlaceholder: function( element ) {
2542		var dataKey = dataSpace + "placeholder",
2543				placeholder = element.data( dataKey );
2544
2545		if ( placeholder ) {
2546			placeholder.remove();
2547			element.removeData( dataKey );
2548		}
2549	},
2550
2551	// Removes a placeholder if it exists and restores
2552	// properties that were modified during placeholder creation
2553	cleanUp: function( element ) {
2554		$.effects.restoreStyle( element );
2555		$.effects.removePlaceholder( element );
2556	},
2557
2558	setTransition: function( element, list, factor, value ) {
2559		value = value || {};
2560		$.each( list, function( i, x ) {
2561			var unit = element.cssUnit( x );
2562			if ( unit[ 0 ] > 0 ) {
2563				value[ x ] = unit[ 0 ] * factor + unit[ 1 ];
2564			}
2565		} );
2566		return value;
2567	}
2568} );
2569
2570// Return an effect options object for the given parameters:
2571function _normalizeArguments( effect, options, speed, callback ) {
2572
2573	// Allow passing all options as the first parameter
2574	if ( $.isPlainObject( effect ) ) {
2575		options = effect;
2576		effect = effect.effect;
2577	}
2578
2579	// Convert to an object
2580	effect = { effect: effect };
2581
2582	// Catch (effect, null, ...)
2583	if ( options == null ) {
2584		options = {};
2585	}
2586
2587	// Catch (effect, callback)
2588	if ( typeof options === "function" ) {
2589		callback = options;
2590		speed = null;
2591		options = {};
2592	}
2593
2594	// Catch (effect, speed, ?)
2595	if ( typeof options === "number" || $.fx.speeds[ options ] ) {
2596		callback = speed;
2597		speed = options;
2598		options = {};
2599	}
2600
2601	// Catch (effect, options, callback)
2602	if ( typeof speed === "function" ) {
2603		callback = speed;
2604		speed = null;
2605	}
2606
2607	// Add options to effect
2608	if ( options ) {
2609		$.extend( effect, options );
2610	}
2611
2612	speed = speed || options.duration;
2613	effect.duration = $.fx.off ? 0 :
2614		typeof speed === "number" ? speed :
2615		speed in $.fx.speeds ? $.fx.speeds[ speed ] :
2616		$.fx.speeds._default;
2617
2618	effect.complete = callback || options.complete;
2619
2620	return effect;
2621}
2622
2623function standardAnimationOption( option ) {
2624
2625	// Valid standard speeds (nothing, number, named speed)
2626	if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) {
2627		return true;
2628	}
2629
2630	// Invalid strings - treat as "normal" speed
2631	if ( typeof option === "string" && !$.effects.effect[ option ] ) {
2632		return true;
2633	}
2634
2635	// Complete callback
2636	if ( typeof option === "function" ) {
2637		return true;
2638	}
2639
2640	// Options hash (but not naming an effect)
2641	if ( typeof option === "object" && !option.effect ) {
2642		return true;
2643	}
2644
2645	// Didn't match any standard API
2646	return false;
2647}
2648
2649$.fn.extend( {
2650	effect: function( /* effect, options, speed, callback */ ) {
2651		var args = _normalizeArguments.apply( this, arguments ),
2652			effectMethod = $.effects.effect[ args.effect ],
2653			defaultMode = effectMethod.mode,
2654			queue = args.queue,
2655			queueName = queue || "fx",
2656			complete = args.complete,
2657			mode = args.mode,
2658			modes = [],
2659			prefilter = function( next ) {
2660				var el = $( this ),
2661					normalizedMode = $.effects.mode( el, mode ) || defaultMode;
2662
2663				// Sentinel for duck-punching the :animated pseudo-selector
2664				el.data( dataSpaceAnimated, true );
2665
2666				// Save effect mode for later use,
2667				// we can't just call $.effects.mode again later,
2668				// as the .show() below destroys the initial state
2669				modes.push( normalizedMode );
2670
2671				// See $.uiBackCompat inside of run() for removal of defaultMode in 1.14
2672				if ( defaultMode && ( normalizedMode === "show" ||
2673						( normalizedMode === defaultMode && normalizedMode === "hide" ) ) ) {
2674					el.show();
2675				}
2676
2677				if ( !defaultMode || normalizedMode !== "none" ) {
2678					$.effects.saveStyle( el );
2679				}
2680
2681				if ( typeof next === "function" ) {
2682					next();
2683				}
2684			};
2685
2686		if ( $.fx.off || !effectMethod ) {
2687
2688			// Delegate to the original method (e.g., .show()) if possible
2689			if ( mode ) {
2690				return this[ mode ]( args.duration, complete );
2691			} else {
2692				return this.each( function() {
2693					if ( complete ) {
2694						complete.call( this );
2695					}
2696				} );
2697			}
2698		}
2699
2700		function run( next ) {
2701			var elem = $( this );
2702
2703			function cleanup() {
2704				elem.removeData( dataSpaceAnimated );
2705
2706				$.effects.cleanUp( elem );
2707
2708				if ( args.mode === "hide" ) {
2709					elem.hide();
2710				}
2711
2712				done();
2713			}
2714
2715			function done() {
2716				if ( typeof complete === "function" ) {
2717					complete.call( elem[ 0 ] );
2718				}
2719
2720				if ( typeof next === "function" ) {
2721					next();
2722				}
2723			}
2724
2725			// Override mode option on a per element basis,
2726			// as toggle can be either show or hide depending on element state
2727			args.mode = modes.shift();
2728
2729			if ( $.uiBackCompat === true && !defaultMode ) {
2730				if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) {
2731
2732					// Call the core method to track "olddisplay" properly
2733					elem[ mode ]();
2734					done();
2735				} else {
2736					effectMethod.call( elem[ 0 ], args, done );
2737				}
2738			} else {
2739				if ( args.mode === "none" ) {
2740
2741					// Call the core method to track "olddisplay" properly
2742					elem[ mode ]();
2743					done();
2744				} else {
2745					effectMethod.call( elem[ 0 ], args, cleanup );
2746				}
2747			}
2748		}
2749
2750		// Run prefilter on all elements first to ensure that
2751		// any showing or hiding happens before placeholder creation,
2752		// which ensures that any layout changes are correctly captured.
2753		return queue === false ?
2754			this.each( prefilter ).each( run ) :
2755			this.queue( queueName, prefilter ).queue( queueName, run );
2756	},
2757
2758	show: ( function( orig ) {
2759		return function( option ) {
2760			if ( standardAnimationOption( option ) ) {
2761				return orig.apply( this, arguments );
2762			} else {
2763				var args = _normalizeArguments.apply( this, arguments );
2764				args.mode = "show";
2765				return this.effect.call( this, args );
2766			}
2767		};
2768	} )( $.fn.show ),
2769
2770	hide: ( function( orig ) {
2771		return function( option ) {
2772			if ( standardAnimationOption( option ) ) {
2773				return orig.apply( this, arguments );
2774			} else {
2775				var args = _normalizeArguments.apply( this, arguments );
2776				args.mode = "hide";
2777				return this.effect.call( this, args );
2778			}
2779		};
2780	} )( $.fn.hide ),
2781
2782	toggle: ( function( orig ) {
2783		return function( option ) {
2784			if ( standardAnimationOption( option ) || typeof option === "boolean" ) {
2785				return orig.apply( this, arguments );
2786			} else {
2787				var args = _normalizeArguments.apply( this, arguments );
2788				args.mode = "toggle";
2789				return this.effect.call( this, args );
2790			}
2791		};
2792	} )( $.fn.toggle ),
2793
2794	cssUnit: function( key ) {
2795		var style = this.css( key ),
2796			val = [];
2797
2798		$.each( [ "em", "px", "%", "pt" ], function( i, unit ) {
2799			if ( style.indexOf( unit ) > 0 ) {
2800				val = [ parseFloat( style ), unit ];
2801			}
2802		} );
2803		return val;
2804	},
2805
2806	cssClip: function( clipObj ) {
2807		if ( clipObj ) {
2808			return this.css( "clip", "rect(" + clipObj.top + "px " + clipObj.right + "px " +
2809				clipObj.bottom + "px " + clipObj.left + "px)" );
2810		}
2811		return parseClip( this.css( "clip" ), this );
2812	},
2813
2814	transfer: function( options, done ) {
2815		var element = $( this ),
2816			target = $( options.to ),
2817			targetFixed = target.css( "position" ) === "fixed",
2818			body = $( "body" ),
2819			fixTop = targetFixed ? body.scrollTop() : 0,
2820			fixLeft = targetFixed ? body.scrollLeft() : 0,
2821			endPosition = target.offset(),
2822			animation = {
2823				top: endPosition.top - fixTop,
2824				left: endPosition.left - fixLeft,
2825				height: target.innerHeight(),
2826				width: target.innerWidth()
2827			},
2828			startPosition = element.offset(),
2829			transfer = $( "<div class='ui-effects-transfer'></div>" );
2830
2831		transfer
2832			.appendTo( "body" )
2833			.addClass( options.className )
2834			.css( {
2835				top: startPosition.top - fixTop,
2836				left: startPosition.left - fixLeft,
2837				height: element.innerHeight(),
2838				width: element.innerWidth(),
2839				position: targetFixed ? "fixed" : "absolute"
2840			} )
2841			.animate( animation, options.duration, options.easing, function() {
2842				transfer.remove();
2843				if ( typeof done === "function" ) {
2844					done();
2845				}
2846			} );
2847	}
2848} );
2849
2850function parseClip( str, element ) {
2851		var outerWidth = element.outerWidth(),
2852			outerHeight = element.outerHeight(),
2853			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)\)$/,
2854			values = clipRegex.exec( str ) || [ "", 0, outerWidth, outerHeight, 0 ];
2855
2856		return {
2857			top: parseFloat( values[ 1 ] ) || 0,
2858			right: values[ 2 ] === "auto" ? outerWidth : parseFloat( values[ 2 ] ),
2859			bottom: values[ 3 ] === "auto" ? outerHeight : parseFloat( values[ 3 ] ),
2860			left: parseFloat( values[ 4 ] ) || 0
2861		};
2862}
2863
2864$.fx.step.clip = function( fx ) {
2865	if ( !fx.clipInit ) {
2866		fx.start = $( fx.elem ).cssClip();
2867		if ( typeof fx.end === "string" ) {
2868			fx.end = parseClip( fx.end, fx.elem );
2869		}
2870		fx.clipInit = true;
2871	}
2872
2873	$( fx.elem ).cssClip( {
2874		top: fx.pos * ( fx.end.top - fx.start.top ) + fx.start.top,
2875		right: fx.pos * ( fx.end.right - fx.start.right ) + fx.start.right,
2876		bottom: fx.pos * ( fx.end.bottom - fx.start.bottom ) + fx.start.bottom,
2877		left: fx.pos * ( fx.end.left - fx.start.left ) + fx.start.left
2878	} );
2879};
2880
2881} )();
2882
2883/******************************************************************************/
2884/*********************************** EASING ***********************************/
2885/******************************************************************************/
2886
2887( function() {
2888
2889// Based on easing equations from Robert Penner (http://robertpenner.com/easing)
2890
2891var baseEasings = {};
2892
2893$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) {
2894	baseEasings[ name ] = function( p ) {
2895		return Math.pow( p, i + 2 );
2896	};
2897} );
2898
2899$.extend( baseEasings, {
2900	Sine: function( p ) {
2901		return 1 - Math.cos( p * Math.PI / 2 );
2902	},
2903	Circ: function( p ) {
2904		return 1 - Math.sqrt( 1 - p * p );
2905	},
2906	Elastic: function( p ) {
2907		return p === 0 || p === 1 ? p :
2908			-Math.pow( 2, 8 * ( p - 1 ) ) * Math.sin( ( ( p - 1 ) * 80 - 7.5 ) * Math.PI / 15 );
2909	},
2910	Back: function( p ) {
2911		return p * p * ( 3 * p - 2 );
2912	},
2913	Bounce: function( p ) {
2914		var pow2,
2915			bounce = 4;
2916
2917		while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}
2918		return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 );
2919	}
2920} );
2921
2922$.each( baseEasings, function( name, easeIn ) {
2923	$.easing[ "easeIn" + name ] = easeIn;
2924	$.easing[ "easeOut" + name ] = function( p ) {
2925		return 1 - easeIn( 1 - p );
2926	};
2927	$.easing[ "easeInOut" + name ] = function( p ) {
2928		return p < 0.5 ?
2929			easeIn( p * 2 ) / 2 :
2930			1 - easeIn( p * -2 + 2 ) / 2;
2931	};
2932} );
2933
2934} )();
2935
2936var effect = $.effects;
2937
2938
2939/*!
2940 * jQuery UI Effects Blind 1.14.0
2941 * https://jqueryui.com
2942 *
2943 * Copyright OpenJS Foundation and other contributors
2944 * Released under the MIT license.
2945 * https://jquery.org/license
2946 */
2947
2948//>>label: Blind Effect
2949//>>group: Effects
2950//>>description: Blinds the element.
2951//>>docs: https://api.jqueryui.com/blind-effect/
2952//>>demos: https://jqueryui.com/effect/
2953
2954
2955var effectsEffectBlind = $.effects.define( "blind", "hide", function( options, done ) {
2956	var map = {
2957			up: [ "bottom", "top" ],
2958			vertical: [ "bottom", "top" ],
2959			down: [ "top", "bottom" ],
2960			left: [ "right", "left" ],
2961			horizontal: [ "right", "left" ],
2962			right: [ "left", "right" ]
2963		},
2964		element = $( this ),
2965		direction = options.direction || "up",
2966		start = element.cssClip(),
2967		animate = { clip: $.extend( {}, start ) },
2968		placeholder = $.effects.createPlaceholder( element );
2969
2970	animate.clip[ map[ direction ][ 0 ] ] = animate.clip[ map[ direction ][ 1 ] ];
2971
2972	if ( options.mode === "show" ) {
2973		element.cssClip( animate.clip );
2974		if ( placeholder ) {
2975			placeholder.css( $.effects.clipToBox( animate ) );
2976		}
2977
2978		animate.clip = start;
2979	}
2980
2981	if ( placeholder ) {
2982		placeholder.animate( $.effects.clipToBox( animate ), options.duration, options.easing );
2983	}
2984
2985	element.animate( animate, {
2986		queue: false,
2987		duration: options.duration,
2988		easing: options.easing,
2989		complete: done
2990	} );
2991} );
2992
2993
2994/*!
2995 * jQuery UI Effects Bounce 1.14.0
2996 * https://jqueryui.com
2997 *
2998 * Copyright OpenJS Foundation and other contributors
2999 * Released under the MIT license.
3000 * https://jquery.org/license
3001 */
3002
3003//>>label: Bounce Effect
3004//>>group: Effects
3005//>>description: Bounces an element horizontally or vertically n times.
3006//>>docs: https://api.jqueryui.com/bounce-effect/
3007//>>demos: https://jqueryui.com/effect/
3008
3009
3010var effectsEffectBounce = $.effects.define( "bounce", function( options, done ) {
3011	var upAnim, downAnim, refValue,
3012		element = $( this ),
3013
3014		// Defaults:
3015		mode = options.mode,
3016		hide = mode === "hide",
3017		show = mode === "show",
3018		direction = options.direction || "up",
3019		distance = options.distance,
3020		times = options.times || 5,
3021
3022		// Number of internal animations
3023		anims = times * 2 + ( show || hide ? 1 : 0 ),
3024		speed = options.duration / anims,
3025		easing = options.easing,
3026
3027		// Utility:
3028		ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
3029		motion = ( direction === "up" || direction === "left" ),
3030		i = 0,
3031
3032		queuelen = element.queue().length;
3033
3034	$.effects.createPlaceholder( element );
3035
3036	refValue = element.css( ref );
3037
3038	// Default distance for the BIGGEST bounce is the outer Distance / 3
3039	if ( !distance ) {
3040		distance = element[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3;
3041	}
3042
3043	if ( show ) {
3044		downAnim = { opacity: 1 };
3045		downAnim[ ref ] = refValue;
3046
3047		// If we are showing, force opacity 0 and set the initial position
3048		// then do the "first" animation
3049		element
3050			.css( "opacity", 0 )
3051			.css( ref, motion ? -distance * 2 : distance * 2 )
3052			.animate( downAnim, speed, easing );
3053	}
3054
3055	// Start at the smallest distance if we are hiding
3056	if ( hide ) {
3057		distance = distance / Math.pow( 2, times - 1 );
3058	}
3059
3060	downAnim = {};
3061	downAnim[ ref ] = refValue;
3062
3063	// Bounces up/down/left/right then back to 0 -- times * 2 animations happen here
3064	for ( ; i < times; i++ ) {
3065		upAnim = {};
3066		upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
3067
3068		element
3069			.animate( upAnim, speed, easing )
3070			.animate( downAnim, speed, easing );
3071
3072		distance = hide ? distance * 2 : distance / 2;
3073	}
3074
3075	// Last Bounce when Hiding
3076	if ( hide ) {
3077		upAnim = { opacity: 0 };
3078		upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
3079
3080		element.animate( upAnim, speed, easing );
3081	}
3082
3083	element.queue( done );
3084
3085	$.effects.unshift( element, queuelen, anims + 1 );
3086} );
3087
3088
3089/*!
3090 * jQuery UI Effects Clip 1.14.0
3091 * https://jqueryui.com
3092 *
3093 * Copyright OpenJS Foundation and other contributors
3094 * Released under the MIT license.
3095 * https://jquery.org/license
3096 */
3097
3098//>>label: Clip Effect
3099//>>group: Effects
3100//>>description: Clips the element on and off like an old TV.
3101//>>docs: https://api.jqueryui.com/clip-effect/
3102//>>demos: https://jqueryui.com/effect/
3103
3104
3105var effectsEffectClip = $.effects.define( "clip", "hide", function( options, done ) {
3106	var start,
3107		animate = {},
3108		element = $( this ),
3109		direction = options.direction || "vertical",
3110		both = direction === "both",
3111		horizontal = both || direction === "horizontal",
3112		vertical = both || direction === "vertical";
3113
3114	start = element.cssClip();
3115	animate.clip = {
3116		top: vertical ? ( start.bottom - start.top ) / 2 : start.top,
3117		right: horizontal ? ( start.right - start.left ) / 2 : start.right,
3118		bottom: vertical ? ( start.bottom - start.top ) / 2 : start.bottom,
3119		left: horizontal ? ( start.right - start.left ) / 2 : start.left
3120	};
3121
3122	$.effects.createPlaceholder( element );
3123
3124	if ( options.mode === "show" ) {
3125		element.cssClip( animate.clip );
3126		animate.clip = start;
3127	}
3128
3129	element.animate( animate, {
3130		queue: false,
3131		duration: options.duration,
3132		easing: options.easing,
3133		complete: done
3134	} );
3135
3136} );
3137
3138
3139/*!
3140 * jQuery UI Effects Drop 1.14.0
3141 * https://jqueryui.com
3142 *
3143 * Copyright OpenJS Foundation and other contributors
3144 * Released under the MIT license.
3145 * https://jquery.org/license
3146 */
3147
3148//>>label: Drop Effect
3149//>>group: Effects
3150//>>description: Moves an element in one direction and hides it at the same time.
3151//>>docs: https://api.jqueryui.com/drop-effect/
3152//>>demos: https://jqueryui.com/effect/
3153
3154
3155var effectsEffectDrop = $.effects.define( "drop", "hide", function( options, done ) {
3156
3157	var distance,
3158		element = $( this ),
3159		mode = options.mode,
3160		show = mode === "show",
3161		direction = options.direction || "left",
3162		ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
3163		motion = ( direction === "up" || direction === "left" ) ? "-=" : "+=",
3164		oppositeMotion = ( motion === "+=" ) ? "-=" : "+=",
3165		animation = {
3166			opacity: 0
3167		};
3168
3169	$.effects.createPlaceholder( element );
3170
3171	distance = options.distance ||
3172		element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ) / 2;
3173
3174	animation[ ref ] = motion + distance;
3175
3176	if ( show ) {
3177		element.css( animation );
3178
3179		animation[ ref ] = oppositeMotion + distance;
3180		animation.opacity = 1;
3181	}
3182
3183	// Animate
3184	element.animate( animation, {
3185		queue: false,
3186		duration: options.duration,
3187		easing: options.easing,
3188		complete: done
3189	} );
3190} );
3191
3192
3193/*!
3194 * jQuery UI Effects Explode 1.14.0
3195 * https://jqueryui.com
3196 *
3197 * Copyright OpenJS Foundation and other contributors
3198 * Released under the MIT license.
3199 * https://jquery.org/license
3200 */
3201
3202//>>label: Explode Effect
3203//>>group: Effects
3204/* eslint-disable max-len */
3205//>>description: Explodes an element in all directions into n pieces. Implodes an element to its original wholeness.
3206/* eslint-enable max-len */
3207//>>docs: https://api.jqueryui.com/explode-effect/
3208//>>demos: https://jqueryui.com/effect/
3209
3210
3211var effectsEffectExplode = $.effects.define( "explode", "hide", function( options, done ) {
3212
3213	var i, j, left, top, mx, my,
3214		rows = options.pieces ? Math.round( Math.sqrt( options.pieces ) ) : 3,
3215		cells = rows,
3216		element = $( this ),
3217		mode = options.mode,
3218		show = mode === "show",
3219
3220		// Show and then visibility:hidden the element before calculating offset
3221		offset = element.show().css( "visibility", "hidden" ).offset(),
3222
3223		// Width and height of a piece
3224		width = Math.ceil( element.outerWidth() / cells ),
3225		height = Math.ceil( element.outerHeight() / rows ),
3226		pieces = [];
3227
3228	// Children animate complete:
3229	function childComplete() {
3230		pieces.push( this );
3231		if ( pieces.length === rows * cells ) {
3232			animComplete();
3233		}
3234	}
3235
3236	// Clone the element for each row and cell.
3237	for ( i = 0; i < rows; i++ ) { // ===>
3238		top = offset.top + i * height;
3239		my = i - ( rows - 1 ) / 2;
3240
3241		for ( j = 0; j < cells; j++ ) { // |||
3242			left = offset.left + j * width;
3243			mx = j - ( cells - 1 ) / 2;
3244
3245			// Create a clone of the now hidden main element that will be absolute positioned
3246			// within a wrapper div off the -left and -top equal to size of our pieces
3247			element
3248				.clone()
3249				.appendTo( "body" )
3250				.wrap( "<div></div>" )
3251				.css( {
3252					position: "absolute",
3253					visibility: "visible",
3254					left: -j * width,
3255					top: -i * height
3256				} )
3257
3258				// Select the wrapper - make it overflow: hidden and absolute positioned based on
3259				// where the original was located +left and +top equal to the size of pieces
3260				.parent()
3261					.addClass( "ui-effects-explode" )
3262					.css( {
3263						position: "absolute",
3264						overflow: "hidden",
3265						width: width,
3266						height: height,
3267						left: left + ( show ? mx * width : 0 ),
3268						top: top + ( show ? my * height : 0 ),
3269						opacity: show ? 0 : 1
3270					} )
3271					.animate( {
3272						left: left + ( show ? 0 : mx * width ),
3273						top: top + ( show ? 0 : my * height ),
3274						opacity: show ? 1 : 0
3275					}, options.duration || 500, options.easing, childComplete );
3276		}
3277	}
3278
3279	function animComplete() {
3280		element.css( {
3281			visibility: "visible"
3282		} );
3283		$( pieces ).remove();
3284		done();
3285	}
3286} );
3287
3288
3289/*!
3290 * jQuery UI Effects Fade 1.14.0
3291 * https://jqueryui.com
3292 *
3293 * Copyright OpenJS Foundation and other contributors
3294 * Released under the MIT license.
3295 * https://jquery.org/license
3296 */
3297
3298//>>label: Fade Effect
3299//>>group: Effects
3300//>>description: Fades the element.
3301//>>docs: https://api.jqueryui.com/fade-effect/
3302//>>demos: https://jqueryui.com/effect/
3303
3304
3305var effectsEffectFade = $.effects.define( "fade", "toggle", function( options, done ) {
3306	var show = options.mode === "show";
3307
3308	$( this )
3309		.css( "opacity", show ? 0 : 1 )
3310		.animate( {
3311			opacity: show ? 1 : 0
3312		}, {
3313			queue: false,
3314			duration: options.duration,
3315			easing: options.easing,
3316			complete: done
3317		} );
3318} );
3319
3320
3321/*!
3322 * jQuery UI Effects Fold 1.14.0
3323 * https://jqueryui.com
3324 *
3325 * Copyright OpenJS Foundation and other contributors
3326 * Released under the MIT license.
3327 * https://jquery.org/license
3328 */
3329
3330//>>label: Fold Effect
3331//>>group: Effects
3332//>>description: Folds an element first horizontally and then vertically.
3333//>>docs: https://api.jqueryui.com/fold-effect/
3334//>>demos: https://jqueryui.com/effect/
3335
3336
3337var effectsEffectFold = $.effects.define( "fold", "hide", function( options, done ) {
3338
3339	// Create element
3340	var element = $( this ),
3341		mode = options.mode,
3342		show = mode === "show",
3343		hide = mode === "hide",
3344		size = options.size || 15,
3345		percent = /([0-9]+)%/.exec( size ),
3346		horizFirst = !!options.horizFirst,
3347		ref = horizFirst ? [ "right", "bottom" ] : [ "bottom", "right" ],
3348		duration = options.duration / 2,
3349
3350		placeholder = $.effects.createPlaceholder( element ),
3351
3352		start = element.cssClip(),
3353		animation1 = { clip: $.extend( {}, start ) },
3354		animation2 = { clip: $.extend( {}, start ) },
3355
3356		distance = [ start[ ref[ 0 ] ], start[ ref[ 1 ] ] ],
3357
3358		queuelen = element.queue().length;
3359
3360	if ( percent ) {
3361		size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ];
3362	}
3363	animation1.clip[ ref[ 0 ] ] = size;
3364	animation2.clip[ ref[ 0 ] ] = size;
3365	animation2.clip[ ref[ 1 ] ] = 0;
3366
3367	if ( show ) {
3368		element.cssClip( animation2.clip );
3369		if ( placeholder ) {
3370			placeholder.css( $.effects.clipToBox( animation2 ) );
3371		}
3372
3373		animation2.clip = start;
3374	}
3375
3376	// Animate
3377	element
3378		.queue( function( next ) {
3379			if ( placeholder ) {
3380				placeholder
3381					.animate( $.effects.clipToBox( animation1 ), duration, options.easing )
3382					.animate( $.effects.clipToBox( animation2 ), duration, options.easing );
3383			}
3384
3385			next();
3386		} )
3387		.animate( animation1, duration, options.easing )
3388		.animate( animation2, duration, options.easing )
3389		.queue( done );
3390
3391	$.effects.unshift( element, queuelen, 4 );
3392} );
3393
3394
3395/*!
3396 * jQuery UI Effects Highlight 1.14.0
3397 * https://jqueryui.com
3398 *
3399 * Copyright OpenJS Foundation and other contributors
3400 * Released under the MIT license.
3401 * https://jquery.org/license
3402 */
3403
3404//>>label: Highlight Effect
3405//>>group: Effects
3406//>>description: Highlights the background of an element in a defined color for a custom duration.
3407//>>docs: https://api.jqueryui.com/highlight-effect/
3408//>>demos: https://jqueryui.com/effect/
3409
3410
3411var effectsEffectHighlight = $.effects.define( "highlight", "show", function( options, done ) {
3412	var element = $( this ),
3413		animation = {
3414			backgroundColor: element.css( "backgroundColor" )
3415		};
3416
3417	if ( options.mode === "hide" ) {
3418		animation.opacity = 0;
3419	}
3420
3421	$.effects.saveStyle( element );
3422
3423	element
3424		.css( {
3425			backgroundImage: "none",
3426			backgroundColor: options.color || "#ffff99"
3427		} )
3428		.animate( animation, {
3429			queue: false,
3430			duration: options.duration,
3431			easing: options.easing,
3432			complete: done
3433		} );
3434} );
3435
3436
3437/*!
3438 * jQuery UI Effects Size 1.14.0
3439 * https://jqueryui.com
3440 *
3441 * Copyright OpenJS Foundation and other contributors
3442 * Released under the MIT license.
3443 * https://jquery.org/license
3444 */
3445
3446//>>label: Size Effect
3447//>>group: Effects
3448//>>description: Resize an element to a specified width and height.
3449//>>docs: https://api.jqueryui.com/size-effect/
3450//>>demos: https://jqueryui.com/effect/
3451
3452
3453var effectsEffectSize = $.effects.define( "size", function( options, done ) {
3454
3455	// Create element
3456	var baseline, factor, temp,
3457		element = $( this ),
3458
3459		// Copy for children
3460		cProps = [ "fontSize" ],
3461		vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ],
3462		hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ],
3463
3464		// Set options
3465		mode = options.mode,
3466		restore = mode !== "effect",
3467		scale = options.scale || "both",
3468		origin = options.origin || [ "middle", "center" ],
3469		position = element.css( "position" ),
3470		pos = element.position(),
3471		original = $.effects.scaledDimensions( element ),
3472		from = options.from || original,
3473		to = options.to || $.effects.scaledDimensions( element, 0 );
3474
3475	$.effects.createPlaceholder( element );
3476
3477	if ( mode === "show" ) {
3478		temp = from;
3479		from = to;
3480		to = temp;
3481	}
3482
3483	// Set scaling factor
3484	factor = {
3485		from: {
3486			y: from.height / original.height,
3487			x: from.width / original.width
3488		},
3489		to: {
3490			y: to.height / original.height,
3491			x: to.width / original.width
3492		}
3493	};
3494
3495	// Scale the css box
3496	if ( scale === "box" || scale === "both" ) {
3497
3498		// Vertical props scaling
3499		if ( factor.from.y !== factor.to.y ) {
3500			from = $.effects.setTransition( element, vProps, factor.from.y, from );
3501			to = $.effects.setTransition( element, vProps, factor.to.y, to );
3502		}
3503
3504		// Horizontal props scaling
3505		if ( factor.from.x !== factor.to.x ) {
3506			from = $.effects.setTransition( element, hProps, factor.from.x, from );
3507			to = $.effects.setTransition( element, hProps, factor.to.x, to );
3508		}
3509	}
3510
3511	// Scale the content
3512	if ( scale === "content" || scale === "both" ) {
3513
3514		// Vertical props scaling
3515		if ( factor.from.y !== factor.to.y ) {
3516			from = $.effects.setTransition( element, cProps, factor.from.y, from );
3517			to = $.effects.setTransition( element, cProps, factor.to.y, to );
3518		}
3519	}
3520
3521	// Adjust the position properties based on the provided origin points
3522	if ( origin ) {
3523		baseline = $.effects.getBaseline( origin, original );
3524		from.top = ( original.outerHeight - from.outerHeight ) * baseline.y + pos.top;
3525		from.left = ( original.outerWidth - from.outerWidth ) * baseline.x + pos.left;
3526		to.top = ( original.outerHeight - to.outerHeight ) * baseline.y + pos.top;
3527		to.left = ( original.outerWidth - to.outerWidth ) * baseline.x + pos.left;
3528	}
3529	delete from.outerHeight;
3530	delete from.outerWidth;
3531	element.css( from );
3532
3533	// Animate the children if desired
3534	if ( scale === "content" || scale === "both" ) {
3535
3536		vProps = vProps.concat( [ "marginTop", "marginBottom" ] ).concat( cProps );
3537		hProps = hProps.concat( [ "marginLeft", "marginRight" ] );
3538
3539		// Only animate children with width attributes specified
3540		// TODO: is this right? should we include anything with css width specified as well
3541		element.find( "*[width]" ).each( function() {
3542			var child = $( this ),
3543				childOriginal = $.effects.scaledDimensions( child ),
3544				childFrom = {
3545					height: childOriginal.height * factor.from.y,
3546					width: childOriginal.width * factor.from.x,
3547					outerHeight: childOriginal.outerHeight * factor.from.y,
3548					outerWidth: childOriginal.outerWidth * factor.from.x
3549				},
3550				childTo = {
3551					height: childOriginal.height * factor.to.y,
3552					width: childOriginal.width * factor.to.x,
3553					outerHeight: childOriginal.height * factor.to.y,
3554					outerWidth: childOriginal.width * factor.to.x
3555				};
3556
3557			// Vertical props scaling
3558			if ( factor.from.y !== factor.to.y ) {
3559				childFrom = $.effects.setTransition( child, vProps, factor.from.y, childFrom );
3560				childTo = $.effects.setTransition( child, vProps, factor.to.y, childTo );
3561			}
3562
3563			// Horizontal props scaling
3564			if ( factor.from.x !== factor.to.x ) {
3565				childFrom = $.effects.setTransition( child, hProps, factor.from.x, childFrom );
3566				childTo = $.effects.setTransition( child, hProps, factor.to.x, childTo );
3567			}
3568
3569			if ( restore ) {
3570				$.effects.saveStyle( child );
3571			}
3572
3573			// Animate children
3574			child.css( childFrom );
3575			child.animate( childTo, options.duration, options.easing, function() {
3576
3577				// Restore children
3578				if ( restore ) {
3579					$.effects.restoreStyle( child );
3580				}
3581			} );
3582		} );
3583	}
3584
3585	// Animate
3586	element.animate( to, {
3587		queue: false,
3588		duration: options.duration,
3589		easing: options.easing,
3590		complete: function() {
3591
3592			var offset = element.offset();
3593
3594			if ( to.opacity === 0 ) {
3595				element.css( "opacity", from.opacity );
3596			}
3597
3598			if ( !restore ) {
3599				element
3600					.css( "position", position === "static" ? "relative" : position )
3601					.offset( offset );
3602
3603				// Need to save style here so that automatic style restoration
3604				// doesn't restore to the original styles from before the animation.
3605				$.effects.saveStyle( element );
3606			}
3607
3608			done();
3609		}
3610	} );
3611
3612} );
3613
3614
3615/*!
3616 * jQuery UI Effects Scale 1.14.0
3617 * https://jqueryui.com
3618 *
3619 * Copyright OpenJS Foundation and other contributors
3620 * Released under the MIT license.
3621 * https://jquery.org/license
3622 */
3623
3624//>>label: Scale Effect
3625//>>group: Effects
3626//>>description: Grows or shrinks an element and its content.
3627//>>docs: https://api.jqueryui.com/scale-effect/
3628//>>demos: https://jqueryui.com/effect/
3629
3630
3631var effectsEffectScale = $.effects.define( "scale", function( options, done ) {
3632
3633	// Create element
3634	var el = $( this ),
3635		mode = options.mode,
3636		percent = parseInt( options.percent, 10 ) ||
3637			( parseInt( options.percent, 10 ) === 0 ? 0 : ( mode !== "effect" ? 0 : 100 ) ),
3638
3639		newOptions = $.extend( true, {
3640			from: $.effects.scaledDimensions( el ),
3641			to: $.effects.scaledDimensions( el, percent, options.direction || "both" ),
3642			origin: options.origin || [ "middle", "center" ]
3643		}, options );
3644
3645	// Fade option to support puff
3646	if ( options.fade ) {
3647		newOptions.from.opacity = 1;
3648		newOptions.to.opacity = 0;
3649	}
3650
3651	$.effects.effect.size.call( this, newOptions, done );
3652} );
3653
3654
3655/*!
3656 * jQuery UI Effects Puff 1.14.0
3657 * https://jqueryui.com
3658 *
3659 * Copyright OpenJS Foundation and other contributors
3660 * Released under the MIT license.
3661 * https://jquery.org/license
3662 */
3663
3664//>>label: Puff Effect
3665//>>group: Effects
3666//>>description: Creates a puff effect by scaling the element up and hiding it at the same time.
3667//>>docs: https://api.jqueryui.com/puff-effect/
3668//>>demos: https://jqueryui.com/effect/
3669
3670
3671var effectsEffectPuff = $.effects.define( "puff", "hide", function( options, done ) {
3672	var newOptions = $.extend( true, {}, options, {
3673		fade: true,
3674		percent: parseInt( options.percent, 10 ) || 150
3675	} );
3676
3677	$.effects.effect.scale.call( this, newOptions, done );
3678} );
3679
3680
3681/*!
3682 * jQuery UI Effects Pulsate 1.14.0
3683 * https://jqueryui.com
3684 *
3685 * Copyright OpenJS Foundation and other contributors
3686 * Released under the MIT license.
3687 * https://jquery.org/license
3688 */
3689
3690//>>label: Pulsate Effect
3691//>>group: Effects
3692//>>description: Pulsates an element n times by changing the opacity to zero and back.
3693//>>docs: https://api.jqueryui.com/pulsate-effect/
3694//>>demos: https://jqueryui.com/effect/
3695
3696
3697var effectsEffectPulsate = $.effects.define( "pulsate", "show", function( options, done ) {
3698	var element = $( this ),
3699		mode = options.mode,
3700		show = mode === "show",
3701		hide = mode === "hide",
3702		showhide = show || hide,
3703
3704		// Showing or hiding leaves off the "last" animation
3705		anims = ( ( options.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ),
3706		duration = options.duration / anims,
3707		animateTo = 0,
3708		i = 1,
3709		queuelen = element.queue().length;
3710
3711	if ( show || !element.is( ":visible" ) ) {
3712		element.css( "opacity", 0 ).show();
3713		animateTo = 1;
3714	}
3715
3716	// Anims - 1 opacity "toggles"
3717	for ( ; i < anims; i++ ) {
3718		element.animate( { opacity: animateTo }, duration, options.easing );
3719		animateTo = 1 - animateTo;
3720	}
3721
3722	element.animate( { opacity: animateTo }, duration, options.easing );
3723
3724	element.queue( done );
3725
3726	$.effects.unshift( element, queuelen, anims + 1 );
3727} );
3728
3729
3730/*!
3731 * jQuery UI Effects Shake 1.14.0
3732 * https://jqueryui.com
3733 *
3734 * Copyright OpenJS Foundation and other contributors
3735 * Released under the MIT license.
3736 * https://jquery.org/license
3737 */
3738
3739//>>label: Shake Effect
3740//>>group: Effects
3741//>>description: Shakes an element horizontally or vertically n times.
3742//>>docs: https://api.jqueryui.com/shake-effect/
3743//>>demos: https://jqueryui.com/effect/
3744
3745
3746var effectsEffectShake = $.effects.define( "shake", function( options, done ) {
3747
3748	var i = 1,
3749		element = $( this ),
3750		direction = options.direction || "left",
3751		distance = options.distance || 20,
3752		times = options.times || 3,
3753		anims = times * 2 + 1,
3754		speed = Math.round( options.duration / anims ),
3755		ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
3756		positiveMotion = ( direction === "up" || direction === "left" ),
3757		animation = {},
3758		animation1 = {},
3759		animation2 = {},
3760
3761		queuelen = element.queue().length;
3762
3763	$.effects.createPlaceholder( element );
3764
3765	// Animation
3766	animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance;
3767	animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2;
3768	animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2;
3769
3770	// Animate
3771	element.animate( animation, speed, options.easing );
3772
3773	// Shakes
3774	for ( ; i < times; i++ ) {
3775		element
3776			.animate( animation1, speed, options.easing )
3777			.animate( animation2, speed, options.easing );
3778	}
3779
3780	element
3781		.animate( animation1, speed, options.easing )
3782		.animate( animation, speed / 2, options.easing )
3783		.queue( done );
3784
3785	$.effects.unshift( element, queuelen, anims + 1 );
3786} );
3787
3788
3789/*!
3790 * jQuery UI Effects Slide 1.14.0
3791 * https://jqueryui.com
3792 *
3793 * Copyright OpenJS Foundation and other contributors
3794 * Released under the MIT license.
3795 * https://jquery.org/license
3796 */
3797
3798//>>label: Slide Effect
3799//>>group: Effects
3800//>>description: Slides an element in and out of the viewport.
3801//>>docs: https://api.jqueryui.com/slide-effect/
3802//>>demos: https://jqueryui.com/effect/
3803
3804
3805var effectsEffectSlide = $.effects.define( "slide", "show", function( options, done ) {
3806	var startClip, startRef,
3807		element = $( this ),
3808		map = {
3809			up: [ "bottom", "top" ],
3810			down: [ "top", "bottom" ],
3811			left: [ "right", "left" ],
3812			right: [ "left", "right" ]
3813		},
3814		mode = options.mode,
3815		direction = options.direction || "left",
3816		ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
3817		positiveMotion = ( direction === "up" || direction === "left" ),
3818		distance = options.distance ||
3819			element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ),
3820		animation = {};
3821
3822	$.effects.createPlaceholder( element );
3823
3824	startClip = element.cssClip();
3825	startRef = element.position()[ ref ];
3826
3827	// Define hide animation
3828	animation[ ref ] = ( positiveMotion ? -1 : 1 ) * distance + startRef;
3829	animation.clip = element.cssClip();
3830	animation.clip[ map[ direction ][ 1 ] ] = animation.clip[ map[ direction ][ 0 ] ];
3831
3832	// Reverse the animation if we're showing
3833	if ( mode === "show" ) {
3834		element.cssClip( animation.clip );
3835		element.css( ref, animation[ ref ] );
3836		animation.clip = startClip;
3837		animation[ ref ] = startRef;
3838	}
3839
3840	// Actually animate
3841	element.animate( animation, {
3842		queue: false,
3843		duration: options.duration,
3844		easing: options.easing,
3845		complete: done
3846	} );
3847} );
3848
3849
3850/*!
3851 * jQuery UI Effects Transfer 1.14.0
3852 * https://jqueryui.com
3853 *
3854 * Copyright OpenJS Foundation and other contributors
3855 * Released under the MIT license.
3856 * https://jquery.org/license
3857 */
3858
3859//>>label: Transfer Effect
3860//>>group: Effects
3861//>>description: Displays a transfer effect from one element to another.
3862//>>docs: https://api.jqueryui.com/transfer-effect/
3863//>>demos: https://jqueryui.com/effect/
3864
3865
3866var effect;
3867if ( $.uiBackCompat === true ) {
3868	effect = $.effects.define( "transfer", function( options, done ) {
3869		$( this ).transfer( options, done );
3870	} );
3871}
3872var effectsEffectTransfer = effect;
3873
3874
3875/*!
3876 * jQuery UI Focusable 1.14.0
3877 * https://jqueryui.com
3878 *
3879 * Copyright OpenJS Foundation and other contributors
3880 * Released under the MIT license.
3881 * https://jquery.org/license
3882 */
3883
3884//>>label: :focusable Selector
3885//>>group: Core
3886//>>description: Selects elements which can be focused.
3887//>>docs: https://api.jqueryui.com/focusable-selector/
3888
3889
3890// Selectors
3891$.ui.focusable = function( element, hasTabindex ) {
3892	var map, mapName, img, focusableIfVisible, fieldset,
3893		nodeName = element.nodeName.toLowerCase();
3894
3895	if ( "area" === nodeName ) {
3896		map = element.parentNode;
3897		mapName = map.name;
3898		if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
3899			return false;
3900		}
3901		img = $( "img[usemap='#" + mapName + "']" );
3902		return img.length > 0 && img.is( ":visible" );
3903	}
3904
3905	if ( /^(input|select|textarea|button|object)$/.test( nodeName ) ) {
3906		focusableIfVisible = !element.disabled;
3907
3908		if ( focusableIfVisible ) {
3909
3910			// Form controls within a disabled fieldset are disabled.
3911			// However, controls within the fieldset's legend do not get disabled.
3912			// Since controls generally aren't placed inside legends, we skip
3913			// this portion of the check.
3914			fieldset = $( element ).closest( "fieldset" )[ 0 ];
3915			if ( fieldset ) {
3916				focusableIfVisible = !fieldset.disabled;
3917			}
3918		}
3919	} else if ( "a" === nodeName ) {
3920		focusableIfVisible = element.href || hasTabindex;
3921	} else {
3922		focusableIfVisible = hasTabindex;
3923	}
3924
3925	return focusableIfVisible && $( element ).is( ":visible" ) &&
3926		$( element ).css( "visibility" ) === "visible";
3927};
3928
3929$.extend( $.expr.pseudos, {
3930	focusable: function( element ) {
3931		return $.ui.focusable( element, $.attr( element, "tabindex" ) != null );
3932	}
3933} );
3934
3935var focusable = $.ui.focusable;
3936
3937
3938/*!
3939 * jQuery UI Form Reset Mixin 1.14.0
3940 * https://jqueryui.com
3941 *
3942 * Copyright OpenJS Foundation and other contributors
3943 * Released under the MIT license.
3944 * https://jquery.org/license
3945 */
3946
3947//>>label: Form Reset Mixin
3948//>>group: Core
3949//>>description: Refresh input widgets when their form is reset
3950//>>docs: https://api.jqueryui.com/form-reset-mixin/
3951
3952
3953var formResetMixin = $.ui.formResetMixin = {
3954	_formResetHandler: function() {
3955		var form = $( this );
3956
3957		// Wait for the form reset to actually happen before refreshing
3958		setTimeout( function() {
3959			var instances = form.data( "ui-form-reset-instances" );
3960			$.each( instances, function() {
3961				this.refresh();
3962			} );
3963		} );
3964	},
3965
3966	_bindFormResetHandler: function() {
3967		this.form = $( this.element.prop( "form" ) );
3968		if ( !this.form.length ) {
3969			return;
3970		}
3971
3972		var instances = this.form.data( "ui-form-reset-instances" ) || [];
3973		if ( !instances.length ) {
3974
3975			// We don't use _on() here because we use a single event handler per form
3976			this.form.on( "reset.ui-form-reset", this._formResetHandler );
3977		}
3978		instances.push( this );
3979		this.form.data( "ui-form-reset-instances", instances );
3980	},
3981
3982	_unbindFormResetHandler: function() {
3983		if ( !this.form.length ) {
3984			return;
3985		}
3986
3987		var instances = this.form.data( "ui-form-reset-instances" );
3988		instances.splice( $.inArray( this, instances ), 1 );
3989		if ( instances.length ) {
3990			this.form.data( "ui-form-reset-instances", instances );
3991		} else {
3992			this.form
3993				.removeData( "ui-form-reset-instances" )
3994				.off( "reset.ui-form-reset" );
3995		}
3996	}
3997};
3998
3999
4000/*!
4001 * jQuery UI Legacy jQuery Core patches 1.14.0
4002 * https://jqueryui.com
4003 *
4004 * Copyright OpenJS Foundation and other contributors
4005 * Released under the MIT license.
4006 * https://jquery.org/license
4007 *
4008 */
4009
4010//>>label: Legacy jQuery Core patches
4011//>>group: Core
4012//>>description: Backport `.even()`, `.odd()` and `$.escapeSelector` to older jQuery Core versions (deprecated)
4013
4014
4015// Support: jQuery 2.2.x or older.
4016// This method has been defined in jQuery 3.0.0.
4017// Code from https://github.com/jquery/jquery/blob/e539bac79e666bba95bba86d690b4e609dca2286/src/selector/escapeSelector.js
4018if ( !$.escapeSelector ) {
4019	$.escapeSelector = function( id ) {
4020		return CSS.escape( id + "" );
4021	};
4022}
4023
4024// Support: jQuery 3.4.x or older
4025// These methods have been defined in jQuery 3.5.0.
4026if ( !$.fn.even || !$.fn.odd ) {
4027	$.fn.extend( {
4028		even: function() {
4029			return this.filter( function( i ) {
4030				return i % 2 === 0;
4031			} );
4032		},
4033		odd: function() {
4034			return this.filter( function( i ) {
4035				return i % 2 === 1;
4036			} );
4037		}
4038	} );
4039}
4040
4041;
4042/*!
4043 * jQuery UI Keycode 1.14.0
4044 * https://jqueryui.com
4045 *
4046 * Copyright OpenJS Foundation and other contributors
4047 * Released under the MIT license.
4048 * https://jquery.org/license
4049 */
4050
4051//>>label: Keycode
4052//>>group: Core
4053//>>description: Provide keycodes as keynames
4054//>>docs: https://api.jqueryui.com/jQuery.ui.keyCode/
4055
4056
4057var keycode = $.ui.keyCode = {
4058	BACKSPACE: 8,
4059	COMMA: 188,
4060	DELETE: 46,
4061	DOWN: 40,
4062	END: 35,
4063	ENTER: 13,
4064	ESCAPE: 27,
4065	HOME: 36,
4066	LEFT: 37,
4067	PAGE_DOWN: 34,
4068	PAGE_UP: 33,
4069	PERIOD: 190,
4070	RIGHT: 39,
4071	SPACE: 32,
4072	TAB: 9,
4073	UP: 38
4074};
4075
4076
4077/*!
4078 * jQuery UI Labels 1.14.0
4079 * https://jqueryui.com
4080 *
4081 * Copyright OpenJS Foundation and other contributors
4082 * Released under the MIT license.
4083 * https://jquery.org/license
4084 */
4085
4086//>>label: labels
4087//>>group: Core
4088//>>description: Find all the labels associated with a given input
4089//>>docs: https://api.jqueryui.com/labels/
4090
4091
4092var labels = $.fn.labels = function() {
4093	var ancestor, selector, id, labels, ancestors;
4094
4095	if ( !this.length ) {
4096		return this.pushStack( [] );
4097	}
4098
4099	// Check control.labels first
4100	if ( this[ 0 ].labels && this[ 0 ].labels.length ) {
4101		return this.pushStack( this[ 0 ].labels );
4102	}
4103
4104	// If `control.labels` is empty - e.g. inside of document fragments - find
4105	// the labels manually
4106	labels = this.eq( 0 ).parents( "label" );
4107
4108	// Look for the label based on the id
4109	id = this.attr( "id" );
4110	if ( id ) {
4111
4112		// We don't search against the document in case the element
4113		// is disconnected from the DOM
4114		ancestor = this.eq( 0 ).parents().last();
4115
4116		// Get a full set of top level ancestors
4117		ancestors = ancestor.add( ancestor.length ? ancestor.siblings() : this.siblings() );
4118
4119		// Create a selector for the label based on the id
4120		selector = "label[for='" + CSS.escape( id ) + "']";
4121
4122		labels = labels.add( ancestors.find( selector ).addBack( selector ) );
4123
4124	}
4125
4126	// Return whatever we have found for labels
4127	return this.pushStack( labels );
4128};
4129
4130
4131/*!
4132 * jQuery UI Scroll Parent 1.14.0
4133 * https://jqueryui.com
4134 *
4135 * Copyright OpenJS Foundation and other contributors
4136 * Released under the MIT license.
4137 * https://jquery.org/license
4138 */
4139
4140//>>label: scrollParent
4141//>>group: Core
4142//>>description: Get the closest ancestor element that is scrollable.
4143//>>docs: https://api.jqueryui.com/scrollParent/
4144
4145
4146var scrollParent = $.fn.scrollParent = function( includeHidden ) {
4147	var position = this.css( "position" ),
4148		excludeStaticParent = position === "absolute",
4149		overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/,
4150		scrollParent = this.parents().filter( function() {
4151			var parent = $( this );
4152			if ( excludeStaticParent && parent.css( "position" ) === "static" ) {
4153				return false;
4154			}
4155			return overflowRegex.test( parent.css( "overflow" ) + parent.css( "overflow-y" ) +
4156				parent.css( "overflow-x" ) );
4157		} ).eq( 0 );
4158
4159	return position === "fixed" || !scrollParent.length ?
4160		$( this[ 0 ].ownerDocument || document ) :
4161		scrollParent;
4162};
4163
4164
4165/*!
4166 * jQuery UI Tabbable 1.14.0
4167 * https://jqueryui.com
4168 *
4169 * Copyright OpenJS Foundation and other contributors
4170 * Released under the MIT license.
4171 * https://jquery.org/license
4172 */
4173
4174//>>label: :tabbable Selector
4175//>>group: Core
4176//>>description: Selects elements which can be tabbed to.
4177//>>docs: https://api.jqueryui.com/tabbable-selector/
4178
4179
4180var tabbable = $.extend( $.expr.pseudos, {
4181	tabbable: function( element ) {
4182		var tabIndex = $.attr( element, "tabindex" ),
4183			hasTabindex = tabIndex != null;
4184		return ( !hasTabindex || tabIndex >= 0 ) && $.ui.focusable( element, hasTabindex );
4185	}
4186} );
4187
4188
4189/*!
4190 * jQuery UI Unique ID 1.14.0
4191 * https://jqueryui.com
4192 *
4193 * Copyright OpenJS Foundation and other contributors
4194 * Released under the MIT license.
4195 * https://jquery.org/license
4196 */
4197
4198//>>label: uniqueId
4199//>>group: Core
4200//>>description: Functions to generate and remove uniqueId's
4201//>>docs: https://api.jqueryui.com/uniqueId/
4202
4203
4204var uniqueId = $.fn.extend( {
4205	uniqueId: ( function() {
4206		var uuid = 0;
4207
4208		return function() {
4209			return this.each( function() {
4210				if ( !this.id ) {
4211					this.id = "ui-id-" + ( ++uuid );
4212				}
4213			} );
4214		};
4215	} )(),
4216
4217	removeUniqueId: function() {
4218		return this.each( function() {
4219			if ( /^ui-id-\d+$/.test( this.id ) ) {
4220				$( this ).removeAttr( "id" );
4221			}
4222		} );
4223	}
4224} );
4225
4226
4227/*!
4228 * jQuery UI Accordion 1.14.0
4229 * https://jqueryui.com
4230 *
4231 * Copyright OpenJS Foundation and other contributors
4232 * Released under the MIT license.
4233 * https://jquery.org/license
4234 */
4235
4236//>>label: Accordion
4237//>>group: Widgets
4238/* eslint-disable max-len */
4239//>>description: Displays collapsible content panels for presenting information in a limited amount of space.
4240/* eslint-enable max-len */
4241//>>docs: https://api.jqueryui.com/accordion/
4242//>>demos: https://jqueryui.com/accordion/
4243//>>css.structure: ../../themes/base/core.css
4244//>>css.structure: ../../themes/base/accordion.css
4245//>>css.theme: ../../themes/base/theme.css
4246
4247
4248var widgetsAccordion = $.widget( "ui.accordion", {
4249	version: "1.14.0",
4250	options: {
4251		active: 0,
4252		animate: {},
4253		classes: {
4254			"ui-accordion-header": "ui-corner-top",
4255			"ui-accordion-header-collapsed": "ui-corner-all",
4256			"ui-accordion-content": "ui-corner-bottom"
4257		},
4258		collapsible: false,
4259		event: "click",
4260		header: function( elem ) {
4261			return elem
4262				.find( "> li > :first-child" )
4263				.add(
4264					elem.find( "> :not(li)" )
4265
4266						// Support: jQuery <3.5 only
4267						// We could use `.even()` but that's unavailable in older jQuery.
4268						.filter( function( i ) {
4269							return i % 2 === 0;
4270						} )
4271				);
4272		},
4273		heightStyle: "auto",
4274		icons: {
4275			activeHeader: "ui-icon-triangle-1-s",
4276			header: "ui-icon-triangle-1-e"
4277		},
4278
4279		// Callbacks
4280		activate: null,
4281		beforeActivate: null
4282	},
4283
4284	hideProps: {
4285		borderTopWidth: "hide",
4286		borderBottomWidth: "hide",
4287		paddingTop: "hide",
4288		paddingBottom: "hide",
4289		height: "hide"
4290	},
4291
4292	showProps: {
4293		borderTopWidth: "show",
4294		borderBottomWidth: "show",
4295		paddingTop: "show",
4296		paddingBottom: "show",
4297		height: "show"
4298	},
4299
4300	_create: function() {
4301		var options = this.options;
4302
4303		this.prevShow = this.prevHide = $();
4304		this._addClass( "ui-accordion", "ui-widget ui-helper-reset" );
4305		this.element.attr( "role", "tablist" );
4306
4307		// Don't allow collapsible: false and active: false / null
4308		if ( !options.collapsible && ( options.active === false || options.active == null ) ) {
4309			options.active = 0;
4310		}
4311
4312		this._processPanels();
4313
4314		// handle negative values
4315		if ( options.active < 0 ) {
4316			options.active += this.headers.length;
4317		}
4318		this._refresh();
4319	},
4320
4321	_getCreateEventData: function() {
4322		return {
4323			header: this.active,
4324			panel: !this.active.length ? $() : this.active.next()
4325		};
4326	},
4327
4328	_createIcons: function() {
4329		var icon, children,
4330			icons = this.options.icons;
4331
4332		if ( icons ) {
4333			icon = $( "<span>" );
4334			this._addClass( icon, "ui-accordion-header-icon", "ui-icon " + icons.header );
4335			icon.prependTo( this.headers );
4336			children = this.active.children( ".ui-accordion-header-icon" );
4337			this._removeClass( children, icons.header )
4338				._addClass( children, null, icons.activeHeader )
4339				._addClass( this.headers, "ui-accordion-icons" );
4340		}
4341	},
4342
4343	_destroyIcons: function() {
4344		this._removeClass( this.headers, "ui-accordion-icons" );
4345		this.headers.children( ".ui-accordion-header-icon" ).remove();
4346	},
4347
4348	_destroy: function() {
4349		var contents;
4350
4351		// Clean up main element
4352		this.element.removeAttr( "role" );
4353
4354		// Clean up headers
4355		this.headers
4356			.removeAttr( "role aria-expanded aria-selected aria-controls tabIndex" )
4357			.removeUniqueId();
4358
4359		this._destroyIcons();
4360
4361		// Clean up content panels
4362		contents = this.headers.next()
4363			.css( "display", "" )
4364			.removeAttr( "role aria-hidden aria-labelledby" )
4365			.removeUniqueId();
4366
4367		if ( this.options.heightStyle !== "content" ) {
4368			contents.css( "height", "" );
4369		}
4370	},
4371
4372	_setOption: function( key, value ) {
4373		if ( key === "active" ) {
4374
4375			// _activate() will handle invalid values and update this.options
4376			this._activate( value );
4377			return;
4378		}
4379
4380		if ( key === "event" ) {
4381			if ( this.options.event ) {
4382				this._off( this.headers, this.options.event );
4383			}
4384			this._setupEvents( value );
4385		}
4386
4387		this._super( key, value );
4388
4389		// Setting collapsible: false while collapsed; open first panel
4390		if ( key === "collapsible" && !value && this.options.active === false ) {
4391			this._activate( 0 );
4392		}
4393
4394		if ( key === "icons" ) {
4395			this._destroyIcons();
4396			if ( value ) {
4397				this._createIcons();
4398			}
4399		}
4400	},
4401
4402	_setOptionDisabled: function( value ) {
4403		this._super( value );
4404
4405		this.element.attr( "aria-disabled", value );
4406		this._toggleClass( null, "ui-state-disabled", !!value );
4407	},
4408
4409	_keydown: function( event ) {
4410		if ( event.altKey || event.ctrlKey ) {
4411			return;
4412		}
4413
4414		var keyCode = $.ui.keyCode,
4415			length = this.headers.length,
4416			currentIndex = this.headers.index( event.target ),
4417			toFocus = false;
4418
4419		switch ( event.keyCode ) {
4420		case keyCode.RIGHT:
4421		case keyCode.DOWN:
4422			toFocus = this.headers[ ( currentIndex + 1 ) % length ];
4423			break;
4424		case keyCode.LEFT:
4425		case keyCode.UP:
4426			toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
4427			break;
4428		case keyCode.SPACE:
4429		case keyCode.ENTER:
4430			this._eventHandler( event );
4431			break;
4432		case keyCode.HOME:
4433			toFocus = this.headers[ 0 ];
4434			break;
4435		case keyCode.END:
4436			toFocus = this.headers[ length - 1 ];
4437			break;
4438		}
4439
4440		if ( toFocus ) {
4441			$( event.target ).attr( "tabIndex", -1 );
4442			$( toFocus ).attr( "tabIndex", 0 );
4443			$( toFocus ).trigger( "focus" );
4444			event.preventDefault();
4445		}
4446	},
4447
4448	_panelKeyDown: function( event ) {
4449		if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) {
4450			$( event.currentTarget ).prev().trigger( "focus" );
4451		}
4452	},
4453
4454	refresh: function() {
4455		var options = this.options;
4456		this._processPanels();
4457
4458		// Was collapsed or no panel
4459		if ( ( options.active === false && options.collapsible === true ) ||
4460				!this.headers.length ) {
4461			options.active = false;
4462			this.active = $();
4463
4464		// active false only when collapsible is true
4465		} else if ( options.active === false ) {
4466			this._activate( 0 );
4467
4468		// was active, but active panel is gone
4469		} else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
4470
4471			// all remaining panel are disabled
4472			if ( this.headers.length === this.headers.find( ".ui-state-disabled" ).length ) {
4473				options.active = false;
4474				this.active = $();
4475
4476			// activate previous panel
4477			} else {
4478				this._activate( Math.max( 0, options.active - 1 ) );
4479			}
4480
4481		// was active, active panel still exists
4482		} else {
4483
4484			// make sure active index is correct
4485			options.active = this.headers.index( this.active );
4486		}
4487
4488		this._destroyIcons();
4489
4490		this._refresh();
4491	},
4492
4493	_processPanels: function() {
4494		var prevHeaders = this.headers,
4495			prevPanels = this.panels;
4496
4497		if ( typeof this.options.header === "function" ) {
4498			this.headers = this.options.header( this.element );
4499		} else {
4500			this.headers = this.element.find( this.options.header );
4501		}
4502		this._addClass( this.headers, "ui-accordion-header ui-accordion-header-collapsed",
4503			"ui-state-default" );
4504
4505		this.panels = this.headers.next().filter( ":not(.ui-accordion-content-active)" ).hide();
4506		this._addClass( this.panels, "ui-accordion-content", "ui-helper-reset ui-widget-content" );
4507
4508		// Avoid memory leaks (#10056)
4509		if ( prevPanels ) {
4510			this._off( prevHeaders.not( this.headers ) );
4511			this._off( prevPanels.not( this.panels ) );
4512		}
4513	},
4514
4515	_refresh: function() {
4516		var maxHeight,
4517			options = this.options,
4518			heightStyle = options.heightStyle,
4519			parent = this.element.parent();
4520
4521		this.active = this._findActive( options.active );
4522		this._addClass( this.active, "ui-accordion-header-active", "ui-state-active" )
4523			._removeClass( this.active, "ui-accordion-header-collapsed" );
4524		this._addClass( this.active.next(), "ui-accordion-content-active" );
4525		this.active.next().show();
4526
4527		this.headers
4528			.attr( "role", "tab" )
4529			.each( function() {
4530				var header = $( this ),
4531					headerId = header.uniqueId().attr( "id" ),
4532					panel = header.next(),
4533					panelId = panel.uniqueId().attr( "id" );
4534				header.attr( "aria-controls", panelId );
4535				panel.attr( "aria-labelledby", headerId );
4536			} )
4537			.next()
4538				.attr( "role", "tabpanel" );
4539
4540		this.headers
4541			.not( this.active )
4542				.attr( {
4543					"aria-selected": "false",
4544					"aria-expanded": "false",
4545					tabIndex: -1
4546				} )
4547				.next()
4548					.attr( {
4549						"aria-hidden": "true"
4550					} )
4551					.hide();
4552
4553		// Make sure at least one header is in the tab order
4554		if ( !this.active.length ) {
4555			this.headers.eq( 0 ).attr( "tabIndex", 0 );
4556		} else {
4557			this.active.attr( {
4558				"aria-selected": "true",
4559				"aria-expanded": "true",
4560				tabIndex: 0
4561			} )
4562				.next()
4563					.attr( {
4564						"aria-hidden": "false"
4565					} );
4566		}
4567
4568		this._createIcons();
4569
4570		this._setupEvents( options.event );
4571
4572		if ( heightStyle === "fill" ) {
4573			maxHeight = parent.height();
4574			this.element.siblings( ":visible" ).each( function() {
4575				var elem = $( this ),
4576					position = elem.css( "position" );
4577
4578				if ( position === "absolute" || position === "fixed" ) {
4579					return;
4580				}
4581				maxHeight -= elem.outerHeight( true );
4582			} );
4583
4584			this.headers.each( function() {
4585				maxHeight -= $( this ).outerHeight( true );
4586			} );
4587
4588			this.headers.next()
4589				.each( function() {
4590					$( this ).height( Math.max( 0, maxHeight -
4591						$( this ).innerHeight() + $( this ).height() ) );
4592				} )
4593				.css( "overflow", "auto" );
4594		} else if ( heightStyle === "auto" ) {
4595			maxHeight = 0;
4596			this.headers.next()
4597				.each( function() {
4598					var isVisible = $( this ).is( ":visible" );
4599					if ( !isVisible ) {
4600						$( this ).show();
4601					}
4602					maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() );
4603					if ( !isVisible ) {
4604						$( this ).hide();
4605					}
4606				} )
4607				.height( maxHeight );
4608		}
4609	},
4610
4611	_activate: function( index ) {
4612		var active = this._findActive( index )[ 0 ];
4613
4614		// Trying to activate the already active panel
4615		if ( active === this.active[ 0 ] ) {
4616			return;
4617		}
4618
4619		// Trying to collapse, simulate a click on the currently active header
4620		active = active || this.active[ 0 ];
4621
4622		this._eventHandler( {
4623			target: active,
4624			currentTarget: active,
4625			preventDefault: $.noop
4626		} );
4627	},
4628
4629	_findActive: function( selector ) {
4630		return typeof selector === "number" ? this.headers.eq( selector ) : $();
4631	},
4632
4633	_setupEvents: function( event ) {
4634		var events = {
4635			keydown: "_keydown"
4636		};
4637		if ( event ) {
4638			$.each( event.split( " " ), function( index, eventName ) {
4639				events[ eventName ] = "_eventHandler";
4640			} );
4641		}
4642
4643		this._off( this.headers.add( this.headers.next() ) );
4644		this._on( this.headers, events );
4645		this._on( this.headers.next(), { keydown: "_panelKeyDown" } );
4646		this._hoverable( this.headers );
4647		this._focusable( this.headers );
4648	},
4649
4650	_eventHandler: function( event ) {
4651		var activeChildren, clickedChildren,
4652			options = this.options,
4653			active = this.active,
4654			clicked = $( event.currentTarget ),
4655			clickedIsActive = clicked[ 0 ] === active[ 0 ],
4656			collapsing = clickedIsActive && options.collapsible,
4657			toShow = collapsing ? $() : clicked.next(),
4658			toHide = active.next(),
4659			eventData = {
4660				oldHeader: active,
4661				oldPanel: toHide,
4662				newHeader: collapsing ? $() : clicked,
4663				newPanel: toShow
4664			};
4665
4666		event.preventDefault();
4667
4668		if (
4669
4670				// click on active header, but not collapsible
4671				( clickedIsActive && !options.collapsible ) ||
4672
4673				// allow canceling activation
4674				( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
4675			return;
4676		}
4677
4678		options.active = collapsing ? false : this.headers.index( clicked );
4679
4680		// When the call to ._toggle() comes after the class changes
4681		// it causes a very odd bug in IE 8 (see #6720)
4682		this.active = clickedIsActive ? $() : clicked;
4683		this._toggle( eventData );
4684
4685		// Switch classes
4686		// corner classes on the previously active header stay after the animation
4687		this._removeClass( active, "ui-accordion-header-active", "ui-state-active" );
4688		if ( options.icons ) {
4689			activeChildren = active.children( ".ui-accordion-header-icon" );
4690			this._removeClass( activeChildren, null, options.icons.activeHeader )
4691				._addClass( activeChildren, null, options.icons.header );
4692		}
4693
4694		if ( !clickedIsActive ) {
4695			this._removeClass( clicked, "ui-accordion-header-collapsed" )
4696				._addClass( clicked, "ui-accordion-header-active", "ui-state-active" );
4697			if ( options.icons ) {
4698				clickedChildren = clicked.children( ".ui-accordion-header-icon" );
4699				this._removeClass( clickedChildren, null, options.icons.header )
4700					._addClass( clickedChildren, null, options.icons.activeHeader );
4701			}
4702
4703			this._addClass( clicked.next(), "ui-accordion-content-active" );
4704		}
4705	},
4706
4707	_toggle: function( data ) {
4708		var toShow = data.newPanel,
4709			toHide = this.prevShow.length ? this.prevShow : data.oldPanel;
4710
4711		// Handle activating a panel during the animation for another activation
4712		this.prevShow.add( this.prevHide ).stop( true, true );
4713		this.prevShow = toShow;
4714		this.prevHide = toHide;
4715
4716		if ( this.options.animate ) {
4717			this._animate( toShow, toHide, data );
4718		} else {
4719			toHide.hide();
4720			toShow.show();
4721			this._toggleComplete( data );
4722		}
4723
4724		toHide.attr( {
4725			"aria-hidden": "true"
4726		} );
4727		toHide.prev().attr( {
4728			"aria-selected": "false",
4729			"aria-expanded": "false"
4730		} );
4731
4732		// if we're switching panels, remove the old header from the tab order
4733		// if we're opening from collapsed state, remove the previous header from the tab order
4734		// if we're collapsing, then keep the collapsing header in the tab order
4735		if ( toShow.length && toHide.length ) {
4736			toHide.prev().attr( {
4737				"tabIndex": -1,
4738				"aria-expanded": "false"
4739			} );
4740		} else if ( toShow.length ) {
4741			this.headers.filter( function() {
4742				return parseInt( $( this ).attr( "tabIndex" ), 10 ) === 0;
4743			} )
4744				.attr( "tabIndex", -1 );
4745		}
4746
4747		toShow
4748			.attr( "aria-hidden", "false" )
4749			.prev()
4750				.attr( {
4751					"aria-selected": "true",
4752					"aria-expanded": "true",
4753					tabIndex: 0
4754				} );
4755	},
4756
4757	_animate: function( toShow, toHide, data ) {
4758		var total, easing, duration,
4759			that = this,
4760			adjust = 0,
4761			boxSizing = toShow.css( "box-sizing" ),
4762			down = toShow.length &&
4763				( !toHide.length || ( toShow.index() < toHide.index() ) ),
4764			animate = this.options.animate || {},
4765			options = down && animate.down || animate,
4766			complete = function() {
4767				that._toggleComplete( data );
4768			};
4769
4770		if ( typeof options === "number" ) {
4771			duration = options;
4772		}
4773		if ( typeof options === "string" ) {
4774			easing = options;
4775		}
4776
4777		// fall back from options to animation in case of partial down settings
4778		easing = easing || options.easing || animate.easing;
4779		duration = duration || options.duration || animate.duration;
4780
4781		if ( !toHide.length ) {
4782			return toShow.animate( this.showProps, duration, easing, complete );
4783		}
4784		if ( !toShow.length ) {
4785			return toHide.animate( this.hideProps, duration, easing, complete );
4786		}
4787
4788		total = toShow.show().outerHeight();
4789		toHide.animate( this.hideProps, {
4790			duration: duration,
4791			easing: easing,
4792			step: function( now, fx ) {
4793				fx.now = Math.round( now );
4794			}
4795		} );
4796		toShow
4797			.hide()
4798			.animate( this.showProps, {
4799				duration: duration,
4800				easing: easing,
4801				complete: complete,
4802				step: function( now, fx ) {
4803					fx.now = Math.round( now );
4804					if ( fx.prop !== "height" ) {
4805						if ( boxSizing === "content-box" ) {
4806							adjust += fx.now;
4807						}
4808					} else if ( that.options.heightStyle !== "content" ) {
4809						fx.now = Math.round( total - toHide.outerHeight() - adjust );
4810						adjust = 0;
4811					}
4812				}
4813			} );
4814	},
4815
4816	_toggleComplete: function( data ) {
4817		var toHide = data.oldPanel,
4818			prev = toHide.prev();
4819
4820		this._removeClass( toHide, "ui-accordion-content-active" );
4821		this._removeClass( prev, "ui-accordion-header-active" )
4822			._addClass( prev, "ui-accordion-header-collapsed" );
4823
4824		this._trigger( "activate", null, data );
4825	}
4826} );
4827
4828
4829/*!
4830 * jQuery UI Menu 1.14.0
4831 * https://jqueryui.com
4832 *
4833 * Copyright OpenJS Foundation and other contributors
4834 * Released under the MIT license.
4835 * https://jquery.org/license
4836 */
4837
4838//>>label: Menu
4839//>>group: Widgets
4840//>>description: Creates nestable menus.
4841//>>docs: https://api.jqueryui.com/menu/
4842//>>demos: https://jqueryui.com/menu/
4843//>>css.structure: ../../themes/base/core.css
4844//>>css.structure: ../../themes/base/menu.css
4845//>>css.theme: ../../themes/base/theme.css
4846
4847
4848var widgetsMenu = $.widget( "ui.menu", {
4849	version: "1.14.0",
4850	defaultElement: "<ul>",
4851	delay: 300,
4852	options: {
4853		icons: {
4854			submenu: "ui-icon-caret-1-e"
4855		},
4856		items: "> *",
4857		menus: "ul",
4858		position: {
4859			my: "left top",
4860			at: "right top"
4861		},
4862		role: "menu",
4863
4864		// Callbacks
4865		blur: null,
4866		focus: null,
4867		select: null
4868	},
4869
4870	_create: function() {
4871		this.activeMenu = this.element;
4872
4873		// Flag used to prevent firing of the click handler
4874		// as the event bubbles up through nested menus
4875		this.mouseHandled = false;
4876		this.lastMousePosition = { x: null, y: null };
4877		this.element
4878			.uniqueId()
4879			.attr( {
4880				role: this.options.role,
4881				tabIndex: 0
4882			} );
4883
4884		this._addClass( "ui-menu", "ui-widget ui-widget-content" );
4885		this._on( {
4886
4887			// Prevent focus from sticking to links inside menu after clicking
4888			// them (focus should always stay on UL during navigation).
4889			"mousedown .ui-menu-item": function( event ) {
4890				event.preventDefault();
4891
4892				this._activateItem( event );
4893			},
4894			"click .ui-menu-item": function( event ) {
4895				var target = $( event.target );
4896				var active = $( this.document[ 0 ].activeElement );
4897				if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) {
4898					this.select( event );
4899
4900					// Only set the mouseHandled flag if the event will bubble, see #9469.
4901					if ( !event.isPropagationStopped() ) {
4902						this.mouseHandled = true;
4903					}
4904
4905					// Open submenu on click
4906					if ( target.has( ".ui-menu" ).length ) {
4907						this.expand( event );
4908					} else if ( !this.element.is( ":focus" ) &&
4909							active.closest( ".ui-menu" ).length ) {
4910
4911						// Redirect focus to the menu
4912						this.element.trigger( "focus", [ true ] );
4913
4914						// If the active item is on the top level, let it stay active.
4915						// Otherwise, blur the active item since it is no longer visible.
4916						if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) {
4917							clearTimeout( this.timer );
4918						}
4919					}
4920				}
4921			},
4922			"mouseenter .ui-menu-item": "_activateItem",
4923			"mousemove .ui-menu-item": "_activateItem",
4924			mouseleave: "collapseAll",
4925			"mouseleave .ui-menu": "collapseAll",
4926			focus: function( event, keepActiveItem ) {
4927
4928				// If there's already an active item, keep it active
4929				// If not, activate the first item
4930				var item = this.active || this._menuItems().first();
4931
4932				if ( !keepActiveItem ) {
4933					this.focus( event, item );
4934				}
4935			},
4936			blur: function( event ) {
4937				this._delay( function() {
4938					var notContained = !$.contains(
4939						this.element[ 0 ],
4940						this.document[ 0 ].activeElement
4941					);
4942					if ( notContained ) {
4943						this.collapseAll( event );
4944					}
4945				} );
4946			},
4947			keydown: "_keydown"
4948		} );
4949
4950		this.refresh();
4951
4952		// Clicks outside of a menu collapse any open menus
4953		this._on( this.document, {
4954			click: function( event ) {
4955				if ( this._closeOnDocumentClick( event ) ) {
4956					this.collapseAll( event, true );
4957				}
4958
4959				// Reset the mouseHandled flag
4960				this.mouseHandled = false;
4961			}
4962		} );
4963	},
4964
4965	_activateItem: function( event ) {
4966
4967		// Ignore mouse events while typeahead is active, see #10458.
4968		// Prevents focusing the wrong item when typeahead causes a scroll while the mouse
4969		// is over an item in the menu
4970		if ( this.previousFilter ) {
4971			return;
4972		}
4973
4974		// If the mouse didn't actually move, but the page was scrolled, ignore the event (#9356)
4975		if ( event.clientX === this.lastMousePosition.x &&
4976				event.clientY === this.lastMousePosition.y ) {
4977			return;
4978		}
4979
4980		this.lastMousePosition = {
4981			x: event.clientX,
4982			y: event.clientY
4983		};
4984
4985		var actualTarget = $( event.target ).closest( ".ui-menu-item" ),
4986			target = $( event.currentTarget );
4987
4988		// Ignore bubbled events on parent items, see #11641
4989		if ( actualTarget[ 0 ] !== target[ 0 ] ) {
4990			return;
4991		}
4992
4993		// If the item is already active, there's nothing to do
4994		if ( target.is( ".ui-state-active" ) ) {
4995			return;
4996		}
4997
4998		// Remove ui-state-active class from siblings of the newly focused menu item
4999		// to avoid a jump caused by adjacent elements both having a class with a border
5000		this._removeClass( target.siblings().children( ".ui-state-active" ),
5001			null, "ui-state-active" );
5002		this.focus( event, target );
5003	},
5004
5005	_destroy: function() {
5006		var items = this.element.find( ".ui-menu-item" )
5007				.removeAttr( "role aria-disabled" ),
5008			submenus = items.children( ".ui-menu-item-wrapper" )
5009				.removeUniqueId()
5010				.removeAttr( "tabIndex role aria-haspopup" );
5011
5012		// Destroy (sub)menus
5013		this.element
5014			.removeAttr( "aria-activedescendant" )
5015			.find( ".ui-menu" ).addBack()
5016				.removeAttr( "role aria-labelledby aria-expanded aria-hidden aria-disabled " +
5017					"tabIndex" )
5018				.removeUniqueId()
5019				.show();
5020
5021		submenus.children().each( function() {
5022			var elem = $( this );
5023			if ( elem.data( "ui-menu-submenu-caret" ) ) {
5024				elem.remove();
5025			}
5026		} );
5027	},
5028
5029	_keydown: function( event ) {
5030		var match, prev, character, skip,
5031			preventDefault = true;
5032
5033		switch ( event.keyCode ) {
5034		case $.ui.keyCode.PAGE_UP:
5035			this.previousPage( event );
5036			break;
5037		case $.ui.keyCode.PAGE_DOWN:
5038			this.nextPage( event );
5039			break;
5040		case $.ui.keyCode.HOME:
5041			this._move( "first", "first", event );
5042			break;
5043		case $.ui.keyCode.END:
5044			this._move( "last", "last", event );
5045			break;
5046		case $.ui.keyCode.UP:
5047			this.previous( event );
5048			break;
5049		case $.ui.keyCode.DOWN:
5050			this.next( event );
5051			break;
5052		case $.ui.keyCode.LEFT:
5053			this.collapse( event );
5054			break;
5055		case $.ui.keyCode.RIGHT:
5056			if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
5057				this.expand( event );
5058			}
5059			break;
5060		case $.ui.keyCode.ENTER:
5061		case $.ui.keyCode.SPACE:
5062			this._activate( event );
5063			break;
5064		case $.ui.keyCode.ESCAPE:
5065			this.collapse( event );
5066			break;
5067		default:
5068			preventDefault = false;
5069			prev = this.previousFilter || "";
5070			skip = false;
5071
5072			// Support number pad values
5073			character = event.keyCode >= 96 && event.keyCode <= 105 ?
5074				( event.keyCode - 96 ).toString() : String.fromCharCode( event.keyCode );
5075
5076			clearTimeout( this.filterTimer );
5077
5078			if ( character === prev ) {
5079				skip = true;
5080			} else {
5081				character = prev + character;
5082			}
5083
5084			match = this._filterMenuItems( character );
5085			match = skip && match.index( this.active.next() ) !== -1 ?
5086				this.active.nextAll( ".ui-menu-item" ) :
5087				match;
5088
5089			// If no matches on the current filter, reset to the last character pressed
5090			// to move down the menu to the first item that starts with that character
5091			if ( !match.length ) {
5092				character = String.fromCharCode( event.keyCode );
5093				match = this._filterMenuItems( character );
5094			}
5095
5096			if ( match.length ) {
5097				this.focus( event, match );
5098				this.previousFilter = character;
5099				this.filterTimer = this._delay( function() {
5100					delete this.previousFilter;
5101				}, 1000 );
5102			} else {
5103				delete this.previousFilter;
5104			}
5105		}
5106
5107		if ( preventDefault ) {
5108			event.preventDefault();
5109		}
5110	},
5111
5112	_activate: function( event ) {
5113		if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
5114			if ( this.active.children( "[aria-haspopup='true']" ).length ) {
5115				this.expand( event );
5116			} else {
5117				this.select( event );
5118			}
5119		}
5120	},
5121
5122	refresh: function() {
5123		var menus, items, newSubmenus, newItems, newWrappers,
5124			that = this,
5125			icon = this.options.icons.submenu,
5126			submenus = this.element.find( this.options.menus );
5127
5128		this._toggleClass( "ui-menu-icons", null, !!this.element.find( ".ui-icon" ).length );
5129
5130		// Initialize nested menus
5131		newSubmenus = submenus.filter( ":not(.ui-menu)" )
5132			.hide()
5133			.attr( {
5134				role: this.options.role,
5135				"aria-hidden": "true",
5136				"aria-expanded": "false"
5137			} )
5138			.each( function() {
5139				var menu = $( this ),
5140					item = menu.prev(),
5141					submenuCaret = $( "<span>" ).data( "ui-menu-submenu-caret", true );
5142
5143				that._addClass( submenuCaret, "ui-menu-icon", "ui-icon " + icon );
5144				item
5145					.attr( "aria-haspopup", "true" )
5146					.prepend( submenuCaret );
5147				menu.attr( "aria-labelledby", item.attr( "id" ) );
5148			} );
5149
5150		this._addClass( newSubmenus, "ui-menu", "ui-widget ui-widget-content ui-front" );
5151
5152		menus = submenus.add( this.element );
5153		items = menus.find( this.options.items );
5154
5155		// Initialize menu-items containing spaces and/or dashes only as dividers
5156		items.not( ".ui-menu-item" ).each( function() {
5157			var item = $( this );
5158			if ( that._isDivider( item ) ) {
5159				that._addClass( item, "ui-menu-divider", "ui-widget-content" );
5160			}
5161		} );
5162
5163		// Don't refresh list items that are already adapted
5164		newItems = items.not( ".ui-menu-item, .ui-menu-divider" );
5165		newWrappers = newItems.children()
5166			.not( ".ui-menu" )
5167				.uniqueId()
5168				.attr( {
5169					tabIndex: -1,
5170					role: this._itemRole()
5171				} );
5172		this._addClass( newItems, "ui-menu-item" )
5173			._addClass( newWrappers, "ui-menu-item-wrapper" );
5174
5175		// Add aria-disabled attribute to any disabled menu item
5176		items.filter( ".ui-state-disabled" ).attr( "aria-disabled", "true" );
5177
5178		// If the active item has been removed, blur the menu
5179		if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
5180			this.blur();
5181		}
5182	},
5183
5184	_itemRole: function() {
5185		return {
5186			menu: "menuitem",
5187			listbox: "option"
5188		}[ this.options.role ];
5189	},
5190
5191	_setOption: function( key, value ) {
5192		if ( key === "icons" ) {
5193			var icons = this.element.find( ".ui-menu-icon" );
5194			this._removeClass( icons, null, this.options.icons.submenu )
5195				._addClass( icons, null, value.submenu );
5196		}
5197		this._super( key, value );
5198	},
5199
5200	_setOptionDisabled: function( value ) {
5201		this._super( value );
5202
5203		this.element.attr( "aria-disabled", String( value ) );
5204		this._toggleClass( null, "ui-state-disabled", !!value );
5205	},
5206
5207	focus: function( event, item ) {
5208		var nested, focused, activeParent;
5209		this.blur( event, event && event.type === "focus" );
5210
5211		this._scrollIntoView( item );
5212
5213		this.active = item.first();
5214
5215		focused = this.active.children( ".ui-menu-item-wrapper" );
5216		this._addClass( focused, null, "ui-state-active" );
5217
5218		// Only update aria-activedescendant if there's a role
5219		// otherwise we assume focus is managed elsewhere
5220		if ( this.options.role ) {
5221			this.element.attr( "aria-activedescendant", focused.attr( "id" ) );
5222		}
5223
5224		// Highlight active parent menu item, if any
5225		activeParent = this.active
5226			.parent()
5227				.closest( ".ui-menu-item" )
5228					.children( ".ui-menu-item-wrapper" );
5229		this._addClass( activeParent, null, "ui-state-active" );
5230
5231		if ( event && event.type === "keydown" ) {
5232			this._close();
5233		} else {
5234			this.timer = this._delay( function() {
5235				this._close();
5236			}, this.delay );
5237		}
5238
5239		nested = item.children( ".ui-menu" );
5240		if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) {
5241			this._startOpening( nested );
5242		}
5243		this.activeMenu = item.parent();
5244
5245		this._trigger( "focus", event, { item: item } );
5246	},
5247
5248	_scrollIntoView: function( item ) {
5249		var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
5250		if ( this._hasScroll() ) {
5251			borderTop = parseFloat( $.css( this.activeMenu[ 0 ], "borderTopWidth" ) ) || 0;
5252			paddingTop = parseFloat( $.css( this.activeMenu[ 0 ], "paddingTop" ) ) || 0;
5253			offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
5254			scroll = this.activeMenu.scrollTop();
5255			elementHeight = this.activeMenu.height();
5256			itemHeight = item.outerHeight();
5257
5258			if ( offset < 0 ) {
5259				this.activeMenu.scrollTop( scroll + offset );
5260			} else if ( offset + itemHeight > elementHeight ) {
5261				this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );
5262			}
5263		}
5264	},
5265
5266	blur: function( event, fromFocus ) {
5267		if ( !fromFocus ) {
5268			clearTimeout( this.timer );
5269		}
5270
5271		if ( !this.active ) {
5272			return;
5273		}
5274
5275		this._removeClass( this.active.children( ".ui-menu-item-wrapper" ),
5276			null, "ui-state-active" );
5277
5278		this._trigger( "blur", event, { item: this.active } );
5279		this.active = null;
5280	},
5281
5282	_startOpening: function( submenu ) {
5283		clearTimeout( this.timer );
5284
5285		// Don't open if already open fixes a Firefox bug that caused a .5 pixel
5286		// shift in the submenu position when mousing over the caret icon
5287		if ( submenu.attr( "aria-hidden" ) !== "true" ) {
5288			return;
5289		}
5290
5291		this.timer = this._delay( function() {
5292			this._close();
5293			this._open( submenu );
5294		}, this.delay );
5295	},
5296
5297	_open: function( submenu ) {
5298		var position = $.extend( {
5299			of: this.active
5300		}, this.options.position );
5301
5302		clearTimeout( this.timer );
5303		this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) )
5304			.hide()
5305			.attr( "aria-hidden", "true" );
5306
5307		submenu
5308			.show()
5309			.removeAttr( "aria-hidden" )
5310			.attr( "aria-expanded", "true" )
5311			.position( position );
5312	},
5313
5314	collapseAll: function( event, all ) {
5315		clearTimeout( this.timer );
5316		this.timer = this._delay( function() {
5317
5318			// If we were passed an event, look for the submenu that contains the event
5319			var currentMenu = all ? this.element :
5320				$( event && event.target ).closest( this.element.find( ".ui-menu" ) );
5321
5322			// If we found no valid submenu ancestor, use the main menu to close all
5323			// sub menus anyway
5324			if ( !currentMenu.length ) {
5325				currentMenu = this.element;
5326			}
5327
5328			this._close( currentMenu );
5329
5330			this.blur( event );
5331
5332			// Work around active item staying active after menu is blurred
5333			this._removeClass( currentMenu.find( ".ui-state-active" ), null, "ui-state-active" );
5334
5335			this.activeMenu = currentMenu;
5336		}, all ? 0 : this.delay );
5337	},
5338
5339	// With no arguments, closes the currently active menu - if nothing is active
5340	// it closes all menus.  If passed an argument, it will search for menus BELOW
5341	_close: function( startMenu ) {
5342		if ( !startMenu ) {
5343			startMenu = this.active ? this.active.parent() : this.element;
5344		}
5345
5346		startMenu.find( ".ui-menu" )
5347			.hide()
5348			.attr( "aria-hidden", "true" )
5349			.attr( "aria-expanded", "false" );
5350	},
5351
5352	_closeOnDocumentClick: function( event ) {
5353		return !$( event.target ).closest( ".ui-menu" ).length;
5354	},
5355
5356	_isDivider: function( item ) {
5357
5358		// Match hyphen, em dash, en dash
5359		return !/[^\-\u2014\u2013\s]/.test( item.text() );
5360	},
5361
5362	collapse: function( event ) {
5363		var newItem = this.active &&
5364			this.active.parent().closest( ".ui-menu-item", this.element );
5365		if ( newItem && newItem.length ) {
5366			this._close();
5367			this.focus( event, newItem );
5368		}
5369	},
5370
5371	expand: function( event ) {
5372		var newItem = this.active && this._menuItems( this.active.children( ".ui-menu" ) ).first();
5373
5374		if ( newItem && newItem.length ) {
5375			this._open( newItem.parent() );
5376
5377			// Delay so Firefox will not hide activedescendant change in expanding submenu from AT
5378			this._delay( function() {
5379				this.focus( event, newItem );
5380			} );
5381		}
5382	},
5383
5384	next: function( event ) {
5385		this._move( "next", "first", event );
5386	},
5387
5388	previous: function( event ) {
5389		this._move( "prev", "last", event );
5390	},
5391
5392	isFirstItem: function() {
5393		return this.active && !this.active.prevAll( ".ui-menu-item" ).length;
5394	},
5395
5396	isLastItem: function() {
5397		return this.active && !this.active.nextAll( ".ui-menu-item" ).length;
5398	},
5399
5400	_menuItems: function( menu ) {
5401		return ( menu || this.element )
5402			.find( this.options.items )
5403			.filter( ".ui-menu-item" );
5404	},
5405
5406	_move: function( direction, filter, event ) {
5407		var next;
5408		if ( this.active ) {
5409			if ( direction === "first" || direction === "last" ) {
5410				next = this.active
5411					[ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )
5412					.last();
5413			} else {
5414				next = this.active
5415					[ direction + "All" ]( ".ui-menu-item" )
5416					.first();
5417			}
5418		}
5419		if ( !next || !next.length || !this.active ) {
5420			next = this._menuItems( this.activeMenu )[ filter ]();
5421		}
5422
5423		this.focus( event, next );
5424	},
5425
5426	nextPage: function( event ) {
5427		var item, base, height;
5428
5429		if ( !this.active ) {
5430			this.next( event );
5431			return;
5432		}
5433		if ( this.isLastItem() ) {
5434			return;
5435		}
5436		if ( this._hasScroll() ) {
5437			base = this.active.offset().top;
5438			height = this.element.innerHeight();
5439
5440			// jQuery 3.2 doesn't include scrollbars in innerHeight, add it back.
5441			if ( $.fn.jquery.indexOf( "3.2." ) === 0 ) {
5442				height += this.element[ 0 ].offsetHeight - this.element.outerHeight();
5443			}
5444
5445			this.active.nextAll( ".ui-menu-item" ).each( function() {
5446				item = $( this );
5447				return item.offset().top - base - height < 0;
5448			} );
5449
5450			this.focus( event, item );
5451		} else {
5452			this.focus( event, this._menuItems( this.activeMenu )
5453				[ !this.active ? "first" : "last" ]() );
5454		}
5455	},
5456
5457	previousPage: function( event ) {
5458		var item, base, height;
5459		if ( !this.active ) {
5460			this.next( event );
5461			return;
5462		}
5463		if ( this.isFirstItem() ) {
5464			return;
5465		}
5466		if ( this._hasScroll() ) {
5467			base = this.active.offset().top;
5468			height = this.element.innerHeight();
5469
5470			// jQuery 3.2 doesn't include scrollbars in innerHeight, add it back.
5471			if ( $.fn.jquery.indexOf( "3.2." ) === 0 ) {
5472				height += this.element[ 0 ].offsetHeight - this.element.outerHeight();
5473			}
5474
5475			this.active.prevAll( ".ui-menu-item" ).each( function() {
5476				item = $( this );
5477				return item.offset().top - base + height > 0;
5478			} );
5479
5480			this.focus( event, item );
5481		} else {
5482			this.focus( event, this._menuItems( this.activeMenu ).first() );
5483		}
5484	},
5485
5486	_hasScroll: function() {
5487		return this.element.outerHeight() < this.element.prop( "scrollHeight" );
5488	},
5489
5490	select: function( event ) {
5491
5492		// TODO: It should never be possible to not have an active item at this
5493		// point, but the tests don't trigger mouseenter before click.
5494		this.active = this.active || $( event.target ).closest( ".ui-menu-item" );
5495		var ui = { item: this.active };
5496		if ( !this.active.has( ".ui-menu" ).length ) {
5497			this.collapseAll( event, true );
5498		}
5499		this._trigger( "select", event, ui );
5500	},
5501
5502	_filterMenuItems: function( character ) {
5503		var escapedCharacter = character.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ),
5504			regex = new RegExp( "^" + escapedCharacter, "i" );
5505
5506		return this.activeMenu
5507			.find( this.options.items )
5508
5509				// Only match on items, not dividers or other content (#10571)
5510				.filter( ".ui-menu-item" )
5511					.filter( function() {
5512						return regex.test(
5513							String.prototype.trim.call(
5514								$( this ).children( ".ui-menu-item-wrapper" ).text() ) );
5515					} );
5516	}
5517} );
5518
5519
5520/*!
5521 * jQuery UI Autocomplete 1.14.0
5522 * https://jqueryui.com
5523 *
5524 * Copyright OpenJS Foundation and other contributors
5525 * Released under the MIT license.
5526 * https://jquery.org/license
5527 */
5528
5529//>>label: Autocomplete
5530//>>group: Widgets
5531//>>description: Lists suggested words as the user is typing.
5532//>>docs: https://api.jqueryui.com/autocomplete/
5533//>>demos: https://jqueryui.com/autocomplete/
5534//>>css.structure: ../../themes/base/core.css
5535//>>css.structure: ../../themes/base/autocomplete.css
5536//>>css.theme: ../../themes/base/theme.css
5537
5538
5539$.widget( "ui.autocomplete", {
5540	version: "1.14.0",
5541	defaultElement: "<input>",
5542	options: {
5543		appendTo: null,
5544		autoFocus: false,
5545		delay: 300,
5546		minLength: 1,
5547		position: {
5548			my: "left top",
5549			at: "left bottom",
5550			collision: "none"
5551		},
5552		source: null,
5553
5554		// Callbacks
5555		change: null,
5556		close: null,
5557		focus: null,
5558		open: null,
5559		response: null,
5560		search: null,
5561		select: null
5562	},
5563
5564	requestIndex: 0,
5565	pending: 0,
5566	liveRegionTimer: null,
5567
5568	_create: function() {
5569
5570		// Some browsers only repeat keydown events, not keypress events,
5571		// so we use the suppressKeyPress flag to determine if we've already
5572		// handled the keydown event. #7269
5573		// Unfortunately the code for & in keypress is the same as the up arrow,
5574		// so we use the suppressKeyPressRepeat flag to avoid handling keypress
5575		// events when we know the keydown event was used to modify the
5576		// search term. #7799
5577		var suppressKeyPress, suppressKeyPressRepeat, suppressInput,
5578			nodeName = this.element[ 0 ].nodeName.toLowerCase(),
5579			isTextarea = nodeName === "textarea",
5580			isInput = nodeName === "input";
5581
5582		// Textareas are always multi-line
5583		// Inputs are always single-line, even if inside a contentEditable element
5584		// All other element types are determined by whether they're contentEditable
5585		this.isMultiLine = isTextarea ||
5586			!isInput && this.element.prop( "contentEditable" ) === "true";
5587
5588		this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ];
5589		this.isNewMenu = true;
5590
5591		this._addClass( "ui-autocomplete-input" );
5592		this.element.attr( "autocomplete", "off" );
5593
5594		this._on( this.element, {
5595			keydown: function( event ) {
5596				if ( this.element.prop( "readOnly" ) ) {
5597					suppressKeyPress = true;
5598					suppressInput = true;
5599					suppressKeyPressRepeat = true;
5600					return;
5601				}
5602
5603				suppressKeyPress = false;
5604				suppressInput = false;
5605				suppressKeyPressRepeat = false;
5606				var keyCode = $.ui.keyCode;
5607				switch ( event.keyCode ) {
5608				case keyCode.PAGE_UP:
5609					suppressKeyPress = true;
5610					this._move( "previousPage", event );
5611					break;
5612				case keyCode.PAGE_DOWN:
5613					suppressKeyPress = true;
5614					this._move( "nextPage", event );
5615					break;
5616				case keyCode.UP:
5617					suppressKeyPress = true;
5618					this._keyEvent( "previous", event );
5619					break;
5620				case keyCode.DOWN:
5621					suppressKeyPress = true;
5622					this._keyEvent( "next", event );
5623					break;
5624				case keyCode.ENTER:
5625
5626					// when menu is open and has focus
5627					if ( this.menu.active ) {
5628
5629						// #6055 - Opera still allows the keypress to occur
5630						// which causes forms to submit
5631						suppressKeyPress = true;
5632						event.preventDefault();
5633						this.menu.select( event );
5634					}
5635					break;
5636				case keyCode.TAB:
5637					if ( this.menu.active ) {
5638						this.menu.select( event );
5639					}
5640					break;
5641				case keyCode.ESCAPE:
5642					if ( this.menu.element.is( ":visible" ) ) {
5643						if ( !this.isMultiLine ) {
5644							this._value( this.term );
5645						}
5646						this.close( event );
5647
5648						// Different browsers have different default behavior for escape
5649						// Single press can mean undo or clear
5650						event.preventDefault();
5651					}
5652					break;
5653				default:
5654					suppressKeyPressRepeat = true;
5655
5656					// search timeout should be triggered before the input value is changed
5657					this._searchTimeout( event );
5658					break;
5659				}
5660			},
5661			keypress: function( event ) {
5662				if ( suppressKeyPress ) {
5663					suppressKeyPress = false;
5664					if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
5665						event.preventDefault();
5666					}
5667					return;
5668				}
5669				if ( suppressKeyPressRepeat ) {
5670					return;
5671				}
5672
5673				// Replicate some key handlers to allow them to repeat in Firefox and Opera
5674				var keyCode = $.ui.keyCode;
5675				switch ( event.keyCode ) {
5676				case keyCode.PAGE_UP:
5677					this._move( "previousPage", event );
5678					break;
5679				case keyCode.PAGE_DOWN:
5680					this._move( "nextPage", event );
5681					break;
5682				case keyCode.UP:
5683					this._keyEvent( "previous", event );
5684					break;
5685				case keyCode.DOWN:
5686					this._keyEvent( "next", event );
5687					break;
5688				}
5689			},
5690			input: function( event ) {
5691				if ( suppressInput ) {
5692					suppressInput = false;
5693					event.preventDefault();
5694					return;
5695				}
5696				this._searchTimeout( event );
5697			},
5698			focus: function() {
5699				this.selectedItem = null;
5700				this.previous = this._value();
5701			},
5702			blur: function( event ) {
5703				clearTimeout( this.searching );
5704				this.close( event );
5705				this._change( event );
5706			}
5707		} );
5708
5709		this._initSource();
5710		this.menu = $( "<ul>" )
5711			.appendTo( this._appendTo() )
5712			.menu( {
5713
5714				// disable ARIA support, the live region takes care of that
5715				role: null
5716			} )
5717			.hide()
5718			.menu( "instance" );
5719
5720		this._addClass( this.menu.element, "ui-autocomplete", "ui-front" );
5721		this._on( this.menu.element, {
5722			mousedown: function( event ) {
5723
5724				// Prevent moving focus out of the text field
5725				event.preventDefault();
5726			},
5727			menufocus: function( event, ui ) {
5728				var label, item;
5729
5730				// Support: Firefox
5731				// Prevent accidental activation of menu items in Firefox (#7024 #9118)
5732				if ( this.isNewMenu ) {
5733					this.isNewMenu = false;
5734					if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {
5735						this.menu.blur();
5736
5737						this.document.one( "mousemove", function() {
5738							$( event.target ).trigger( event.originalEvent );
5739						} );
5740
5741						return;
5742					}
5743				}
5744
5745				item = ui.item.data( "ui-autocomplete-item" );
5746				if ( false !== this._trigger( "focus", event, { item: item } ) ) {
5747
5748					// use value to match what will end up in the input, if it was a key event
5749					if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
5750						this._value( item.value );
5751					}
5752				}
5753
5754				// Announce the value in the liveRegion
5755				label = ui.item.attr( "aria-label" ) || item.value;
5756				if ( label && String.prototype.trim.call( label ).length ) {
5757					clearTimeout( this.liveRegionTimer );
5758					this.liveRegionTimer = this._delay( function() {
5759						this.liveRegion.html( $( "<div>" ).text( label ) );
5760					}, 100 );
5761				}
5762			},
5763			menuselect: function( event, ui ) {
5764				var item = ui.item.data( "ui-autocomplete-item" ),
5765					previous = this.previous;
5766
5767				// Only trigger when focus was lost (click on menu)
5768				if ( this.element[ 0 ] !== this.document[ 0 ].activeElement ) {
5769					this.element.trigger( "focus" );
5770					this.previous = previous;
5771				}
5772
5773				if ( false !== this._trigger( "select", event, { item: item } ) ) {
5774					this._value( item.value );
5775				}
5776
5777				// reset the term after the select event
5778				// this allows custom select handling to work properly
5779				this.term = this._value();
5780
5781				this.close( event );
5782				this.selectedItem = item;
5783			}
5784		} );
5785
5786		this.liveRegion = $( "<div>", {
5787			role: "status",
5788			"aria-live": "assertive",
5789			"aria-relevant": "additions"
5790		} )
5791			.appendTo( this.document[ 0 ].body );
5792
5793		this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" );
5794
5795		// Turning off autocomplete prevents the browser from remembering the
5796		// value when navigating through history, so we re-enable autocomplete
5797		// if the page is unloaded before the widget is destroyed. #7790
5798		this._on( this.window, {
5799			beforeunload: function() {
5800				this.element.removeAttr( "autocomplete" );
5801			}
5802		} );
5803	},
5804
5805	_destroy: function() {
5806		clearTimeout( this.searching );
5807		this.element.removeAttr( "autocomplete" );
5808		this.menu.element.remove();
5809		this.liveRegion.remove();
5810	},
5811
5812	_setOption: function( key, value ) {
5813		this._super( key, value );
5814		if ( key === "source" ) {
5815			this._initSource();
5816		}
5817		if ( key === "appendTo" ) {
5818			this.menu.element.appendTo( this._appendTo() );
5819		}
5820		if ( key === "disabled" && value && this.xhr ) {
5821			this.xhr.abort();
5822		}
5823	},
5824
5825	_isEventTargetInWidget: function( event ) {
5826		var menuElement = this.menu.element[ 0 ];
5827
5828		return event.target === this.element[ 0 ] ||
5829			event.target === menuElement ||
5830			$.contains( menuElement, event.target );
5831	},
5832
5833	_closeOnClickOutside: function( event ) {
5834		if ( !this._isEventTargetInWidget( event ) ) {
5835			this.close();
5836		}
5837	},
5838
5839	_appendTo: function() {
5840		var element = this.options.appendTo;
5841
5842		if ( element ) {
5843			element = element.jquery || element.nodeType ?
5844				$( element ) :
5845				this.document.find( element ).eq( 0 );
5846		}
5847
5848		if ( !element || !element[ 0 ] ) {
5849			element = this.element.closest( ".ui-front, dialog" );
5850		}
5851
5852		if ( !element.length ) {
5853			element = this.document[ 0 ].body;
5854		}
5855
5856		return element;
5857	},
5858
5859	_initSource: function() {
5860		var array, url,
5861			that = this;
5862		if ( Array.isArray( this.options.source ) ) {
5863			array = this.options.source;
5864			this.source = function( request, response ) {
5865				response( $.ui.autocomplete.filter( array, request.term ) );
5866			};
5867		} else if ( typeof this.options.source === "string" ) {
5868			url = this.options.source;
5869			this.source = function( request, response ) {
5870				if ( that.xhr ) {
5871					that.xhr.abort();
5872				}
5873				that.xhr = $.ajax( {
5874					url: url,
5875					data: request,
5876					dataType: "json",
5877					success: function( data ) {
5878						response( data );
5879					},
5880					error: function() {
5881						response( [] );
5882					}
5883				} );
5884			};
5885		} else {
5886			this.source = this.options.source;
5887		}
5888	},
5889
5890	_searchTimeout: function( event ) {
5891		clearTimeout( this.searching );
5892		this.searching = this._delay( function() {
5893
5894			// Search if the value has changed, or if the user retypes the same value (see #7434)
5895			var equalValues = this.term === this._value(),
5896				menuVisible = this.menu.element.is( ":visible" ),
5897				modifierKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
5898
5899			if ( !equalValues || ( equalValues && !menuVisible && !modifierKey ) ) {
5900				this.selectedItem = null;
5901				this.search( null, event );
5902			}
5903		}, this.options.delay );
5904	},
5905
5906	search: function( value, event ) {
5907		value = value != null ? value : this._value();
5908
5909		// Always save the actual value, not the one passed as an argument
5910		this.term = this._value();
5911
5912		if ( value.length < this.options.minLength ) {
5913			return this.close( event );
5914		}
5915
5916		if ( this._trigger( "search", event ) === false ) {
5917			return;
5918		}
5919
5920		return this._search( value );
5921	},
5922
5923	_search: function( value ) {
5924		this.pending++;
5925		this._addClass( "ui-autocomplete-loading" );
5926		this.cancelSearch = false;
5927
5928		this.source( { term: value }, this._response() );
5929	},
5930
5931	_response: function() {
5932		var index = ++this.requestIndex;
5933
5934		return function( content ) {
5935			if ( index === this.requestIndex ) {
5936				this.__response( content );
5937			}
5938
5939			this.pending--;
5940			if ( !this.pending ) {
5941				this._removeClass( "ui-autocomplete-loading" );
5942			}
5943		}.bind( this );
5944	},
5945
5946	__response: function( content ) {
5947		if ( content ) {
5948			content = this._normalize( content );
5949		}
5950		this._trigger( "response", null, { content: content } );
5951		if ( !this.options.disabled && content && content.length && !this.cancelSearch ) {
5952			this._suggest( content );
5953			this._trigger( "open" );
5954		} else {
5955
5956			// use ._close() instead of .close() so we don't cancel future searches
5957			this._close();
5958		}
5959	},
5960
5961	close: function( event ) {
5962		this.cancelSearch = true;
5963		this._close( event );
5964	},
5965
5966	_close: function( event ) {
5967
5968		// Remove the handler that closes the menu on outside clicks
5969		this._off( this.document, "mousedown" );
5970
5971		if ( this.menu.element.is( ":visible" ) ) {
5972			this.menu.element.hide();
5973			this.menu.blur();
5974			this.isNewMenu = true;
5975			this._trigger( "close", event );
5976		}
5977	},
5978
5979	_change: function( event ) {
5980		if ( this.previous !== this._value() ) {
5981			this._trigger( "change", event, { item: this.selectedItem } );
5982		}
5983	},
5984
5985	_normalize: function( items ) {
5986
5987		// assume all items have the right format when the first item is complete
5988		if ( items.length && items[ 0 ].label && items[ 0 ].value ) {
5989			return items;
5990		}
5991		return $.map( items, function( item ) {
5992			if ( typeof item === "string" ) {
5993				return {
5994					label: item,
5995					value: item
5996				};
5997			}
5998			return $.extend( {}, item, {
5999				label: item.label || item.value,
6000				value: item.value || item.label
6001			} );
6002		} );
6003	},
6004
6005	_suggest: function( items ) {
6006		var ul = this.menu.element.empty();
6007		this._renderMenu( ul, items );
6008		this.isNewMenu = true;
6009		this.menu.refresh();
6010
6011		// Size and position menu
6012		ul.show();
6013		this._resizeMenu();
6014		ul.position( $.extend( {
6015			of: this.element
6016		}, this.options.position ) );
6017
6018		if ( this.options.autoFocus ) {
6019			this.menu.next();
6020		}
6021
6022		// Listen for interactions outside of the widget (#6642)
6023		this._on( this.document, {
6024			mousedown: "_closeOnClickOutside"
6025		} );
6026	},
6027
6028	_resizeMenu: function() {
6029		var ul = this.menu.element;
6030		ul.outerWidth( Math.max(
6031
6032			// Firefox wraps long text (possibly a rounding bug)
6033			// so we add 1px to avoid the wrapping (#7513)
6034			ul.width( "" ).outerWidth() + 1,
6035			this.element.outerWidth()
6036		) );
6037	},
6038
6039	_renderMenu: function( ul, items ) {
6040		var that = this;
6041		$.each( items, function( index, item ) {
6042			that._renderItemData( ul, item );
6043		} );
6044	},
6045
6046	_renderItemData: function( ul, item ) {
6047		return this._renderItem( ul, item ).data( "ui-autocomplete-item", item );
6048	},
6049
6050	_renderItem: function( ul, item ) {
6051		return $( "<li>" )
6052			.append( $( "<div>" ).text( item.label ) )
6053			.appendTo( ul );
6054	},
6055
6056	_move: function( direction, event ) {
6057		if ( !this.menu.element.is( ":visible" ) ) {
6058			this.search( null, event );
6059			return;
6060		}
6061		if ( this.menu.isFirstItem() && /^previous/.test( direction ) ||
6062				this.menu.isLastItem() && /^next/.test( direction ) ) {
6063
6064			if ( !this.isMultiLine ) {
6065				this._value( this.term );
6066			}
6067
6068			this.menu.blur();
6069			return;
6070		}
6071		this.menu[ direction ]( event );
6072	},
6073
6074	widget: function() {
6075		return this.menu.element;
6076	},
6077
6078	_value: function() {
6079		return this.valueMethod.apply( this.element, arguments );
6080	},
6081
6082	_keyEvent: function( keyEvent, event ) {
6083		if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
6084			this._move( keyEvent, event );
6085
6086			// Prevents moving cursor to beginning/end of the text field in some browsers
6087			event.preventDefault();
6088		}
6089	}
6090} );
6091
6092$.extend( $.ui.autocomplete, {
6093	escapeRegex: function( value ) {
6094		return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
6095	},
6096	filter: function( array, term ) {
6097		var matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), "i" );
6098		return $.grep( array, function( value ) {
6099			return matcher.test( value.label || value.value || value );
6100		} );
6101	}
6102} );
6103
6104// Live region extension, adding a `messages` option
6105// NOTE: This is an experimental API. We are still investigating
6106// a full solution for string manipulation and internationalization.
6107$.widget( "ui.autocomplete", $.ui.autocomplete, {
6108	options: {
6109		messages: {
6110			noResults: "No search results.",
6111			results: function( amount ) {
6112				return amount + ( amount > 1 ? " results are" : " result is" ) +
6113					" available, use up and down arrow keys to navigate.";
6114			}
6115		}
6116	},
6117
6118	__response: function( content ) {
6119		var message;
6120		this._superApply( arguments );
6121		if ( this.options.disabled || this.cancelSearch ) {
6122			return;
6123		}
6124		if ( content && content.length ) {
6125			message = this.options.messages.results( content.length );
6126		} else {
6127			message = this.options.messages.noResults;
6128		}
6129		clearTimeout( this.liveRegionTimer );
6130		this.liveRegionTimer = this._delay( function() {
6131			this.liveRegion.html( $( "<div>" ).text( message ) );
6132		}, 100 );
6133	}
6134} );
6135
6136var widgetsAutocomplete = $.ui.autocomplete;
6137
6138
6139/*!
6140 * jQuery UI Controlgroup 1.14.0
6141 * https://jqueryui.com
6142 *
6143 * Copyright OpenJS Foundation and other contributors
6144 * Released under the MIT license.
6145 * https://jquery.org/license
6146 */
6147
6148//>>label: Controlgroup
6149//>>group: Widgets
6150//>>description: Visually groups form control widgets
6151//>>docs: https://api.jqueryui.com/controlgroup/
6152//>>demos: https://jqueryui.com/controlgroup/
6153//>>css.structure: ../../themes/base/core.css
6154//>>css.structure: ../../themes/base/controlgroup.css
6155//>>css.theme: ../../themes/base/theme.css
6156
6157
6158var controlgroupCornerRegex = /ui-corner-([a-z]){2,6}/g;
6159
6160var widgetsControlgroup = $.widget( "ui.controlgroup", {
6161	version: "1.14.0",
6162	defaultElement: "<div>",
6163	options: {
6164		direction: "horizontal",
6165		disabled: null,
6166		onlyVisible: true,
6167		items: {
6168			"button": "input[type=button], input[type=submit], input[type=reset], button, a",
6169			"controlgroupLabel": ".ui-controlgroup-label",
6170			"checkboxradio": "input[type='checkbox'], input[type='radio']",
6171			"selectmenu": "select",
6172			"spinner": ".ui-spinner-input"
6173		}
6174	},
6175
6176	_create: function() {
6177		this._enhance();
6178	},
6179
6180	// To support the enhanced option in jQuery Mobile, we isolate DOM manipulation
6181	_enhance: function() {
6182		this.element.attr( "role", "toolbar" );
6183		this.refresh();
6184	},
6185
6186	_destroy: function() {
6187		this._callChildMethod( "destroy" );
6188		this.childWidgets.removeData( "ui-controlgroup-data" );
6189		this.element.removeAttr( "role" );
6190		if ( this.options.items.controlgroupLabel ) {
6191			this.element
6192				.find( this.options.items.controlgroupLabel )
6193				.find( ".ui-controlgroup-label-contents" )
6194				.contents().unwrap();
6195		}
6196	},
6197
6198	_initWidgets: function() {
6199		var that = this,
6200			childWidgets = [];
6201
6202		// First we iterate over each of the items options
6203		$.each( this.options.items, function( widget, selector ) {
6204			var labels;
6205			var options = {};
6206
6207			// Make sure the widget has a selector set
6208			if ( !selector ) {
6209				return;
6210			}
6211
6212			if ( widget === "controlgroupLabel" ) {
6213				labels = that.element.find( selector );
6214				labels.each( function() {
6215					var element = $( this );
6216
6217					if ( element.children( ".ui-controlgroup-label-contents" ).length ) {
6218						return;
6219					}
6220					element.contents()
6221						.wrapAll( "<span class='ui-controlgroup-label-contents'></span>" );
6222				} );
6223				that._addClass( labels, null, "ui-widget ui-widget-content ui-state-default" );
6224				childWidgets = childWidgets.concat( labels.get() );
6225				return;
6226			}
6227
6228			// Make sure the widget actually exists
6229			if ( !$.fn[ widget ] ) {
6230				return;
6231			}
6232
6233			// We assume everything is in the middle to start because we can't determine
6234			// first / last elements until all enhancments are done.
6235			if ( that[ "_" + widget + "Options" ] ) {
6236				options = that[ "_" + widget + "Options" ]( "middle" );
6237			} else {
6238				options = { classes: {} };
6239			}
6240
6241			// Find instances of this widget inside controlgroup and init them
6242			that.element
6243				.find( selector )
6244				.each( function() {
6245					var element = $( this );
6246					var instance = element[ widget ]( "instance" );
6247
6248					// We need to clone the default options for this type of widget to avoid
6249					// polluting the variable options which has a wider scope than a single widget.
6250					var instanceOptions = $.widget.extend( {}, options );
6251
6252					// If the button is the child of a spinner ignore it
6253					// TODO: Find a more generic solution
6254					if ( widget === "button" && element.parent( ".ui-spinner" ).length ) {
6255						return;
6256					}
6257
6258					// Create the widget if it doesn't exist
6259					if ( !instance ) {
6260						instance = element[ widget ]()[ widget ]( "instance" );
6261					}
6262					if ( instance ) {
6263						instanceOptions.classes =
6264							that._resolveClassesValues( instanceOptions.classes, instance );
6265					}
6266					element[ widget ]( instanceOptions );
6267
6268					// Store an instance of the controlgroup to be able to reference
6269					// from the outermost element for changing options and refresh
6270					var widgetElement = element[ widget ]( "widget" );
6271					$.data( widgetElement[ 0 ], "ui-controlgroup-data",
6272						instance ? instance : element[ widget ]( "instance" ) );
6273
6274					childWidgets.push( widgetElement[ 0 ] );
6275				} );
6276		} );
6277
6278		this.childWidgets = $( $.uniqueSort( childWidgets ) );
6279		this._addClass( this.childWidgets, "ui-controlgroup-item" );
6280	},
6281
6282	_callChildMethod: function( method ) {
6283		this.childWidgets.each( function() {
6284			var element = $( this ),
6285				data = element.data( "ui-controlgroup-data" );
6286			if ( data && data[ method ] ) {
6287				data[ method ]();
6288			}
6289		} );
6290	},
6291
6292	_updateCornerClass: function( element, position ) {
6293		var remove = "ui-corner-top ui-corner-bottom ui-corner-left ui-corner-right ui-corner-all";
6294		var add = this._buildSimpleOptions( position, "label" ).classes.label;
6295
6296		this._removeClass( element, null, remove );
6297		this._addClass( element, null, add );
6298	},
6299
6300	_buildSimpleOptions: function( position, key ) {
6301		var direction = this.options.direction === "vertical";
6302		var result = {
6303			classes: {}
6304		};
6305		result.classes[ key ] = {
6306			"middle": "",
6307			"first": "ui-corner-" + ( direction ? "top" : "left" ),
6308			"last": "ui-corner-" + ( direction ? "bottom" : "right" ),
6309			"only": "ui-corner-all"
6310		}[ position ];
6311
6312		return result;
6313	},
6314
6315	_spinnerOptions: function( position ) {
6316		var options = this._buildSimpleOptions( position, "ui-spinner" );
6317
6318		options.classes[ "ui-spinner-up" ] = "";
6319		options.classes[ "ui-spinner-down" ] = "";
6320
6321		return options;
6322	},
6323
6324	_buttonOptions: function( position ) {
6325		return this._buildSimpleOptions( position, "ui-button" );
6326	},
6327
6328	_checkboxradioOptions: function( position ) {
6329		return this._buildSimpleOptions( position, "ui-checkboxradio-label" );
6330	},
6331
6332	_selectmenuOptions: function( position ) {
6333		var direction = this.options.direction === "vertical";
6334		return {
6335			width: direction ? "auto" : false,
6336			classes: {
6337				middle: {
6338					"ui-selectmenu-button-open": "",
6339					"ui-selectmenu-button-closed": ""
6340				},
6341				first: {
6342					"ui-selectmenu-button-open": "ui-corner-" + ( direction ? "top" : "tl" ),
6343					"ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "top" : "left" )
6344				},
6345				last: {
6346					"ui-selectmenu-button-open": direction ? "" : "ui-corner-tr",
6347					"ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "bottom" : "right" )
6348				},
6349				only: {
6350					"ui-selectmenu-button-open": "ui-corner-top",
6351					"ui-selectmenu-button-closed": "ui-corner-all"
6352				}
6353
6354			}[ position ]
6355		};
6356	},
6357
6358	_resolveClassesValues: function( classes, instance ) {
6359		var result = {};
6360		$.each( classes, function( key ) {
6361			var current = instance.options.classes[ key ] || "";
6362			current = String.prototype.trim.call( current.replace( controlgroupCornerRegex, "" ) );
6363			result[ key ] = ( current + " " + classes[ key ] ).replace( /\s+/g, " " );
6364		} );
6365		return result;
6366	},
6367
6368	_setOption: function( key, value ) {
6369		if ( key === "direction" ) {
6370			this._removeClass( "ui-controlgroup-" + this.options.direction );
6371		}
6372
6373		this._super( key, value );
6374		if ( key === "disabled" ) {
6375			this._callChildMethod( value ? "disable" : "enable" );
6376			return;
6377		}
6378
6379		this.refresh();
6380	},
6381
6382	refresh: function() {
6383		var children,
6384			that = this;
6385
6386		this._addClass( "ui-controlgroup ui-controlgroup-" + this.options.direction );
6387
6388		if ( this.options.direction === "horizontal" ) {
6389			this._addClass( null, "ui-helper-clearfix" );
6390		}
6391		this._initWidgets();
6392
6393		children = this.childWidgets;
6394
6395		// We filter here because we need to track all childWidgets not just the visible ones
6396		if ( this.options.onlyVisible ) {
6397			children = children.filter( ":visible" );
6398		}
6399
6400		if ( children.length ) {
6401
6402			// We do this last because we need to make sure all enhancment is done
6403			// before determining first and last
6404			$.each( [ "first", "last" ], function( index, value ) {
6405				var instance = children[ value ]().data( "ui-controlgroup-data" );
6406
6407				if ( instance && that[ "_" + instance.widgetName + "Options" ] ) {
6408					var options = that[ "_" + instance.widgetName + "Options" ](
6409						children.length === 1 ? "only" : value
6410					);
6411					options.classes = that._resolveClassesValues( options.classes, instance );
6412					instance.element[ instance.widgetName ]( options );
6413				} else {
6414					that._updateCornerClass( children[ value ](), value );
6415				}
6416			} );
6417
6418			// Finally call the refresh method on each of the child widgets.
6419			this._callChildMethod( "refresh" );
6420		}
6421	}
6422} );
6423
6424/*!
6425 * jQuery UI Checkboxradio 1.14.0
6426 * https://jqueryui.com
6427 *
6428 * Copyright OpenJS Foundation and other contributors
6429 * Released under the MIT license.
6430 * https://jquery.org/license
6431 */
6432
6433//>>label: Checkboxradio
6434//>>group: Widgets
6435//>>description: Enhances a form with multiple themeable checkboxes or radio buttons.
6436//>>docs: https://api.jqueryui.com/checkboxradio/
6437//>>demos: https://jqueryui.com/checkboxradio/
6438//>>css.structure: ../../themes/base/core.css
6439//>>css.structure: ../../themes/base/button.css
6440//>>css.structure: ../../themes/base/checkboxradio.css
6441//>>css.theme: ../../themes/base/theme.css
6442
6443
6444$.widget( "ui.checkboxradio", [ $.ui.formResetMixin, {
6445	version: "1.14.0",
6446	options: {
6447		disabled: null,
6448		label: null,
6449		icon: true,
6450		classes: {
6451			"ui-checkboxradio-label": "ui-corner-all",
6452			"ui-checkboxradio-icon": "ui-corner-all"
6453		}
6454	},
6455
6456	_getCreateOptions: function() {
6457		var disabled, labels, labelContents;
6458		var options = this._super() || {};
6459
6460		// We read the type here, because it makes more sense to throw a element type error first,
6461		// rather then the error for lack of a label. Often if its the wrong type, it
6462		// won't have a label (e.g. calling on a div, btn, etc)
6463		this._readType();
6464
6465		labels = this.element.labels();
6466
6467		// If there are multiple labels, use the last one
6468		this.label = $( labels[ labels.length - 1 ] );
6469		if ( !this.label.length ) {
6470			$.error( "No label found for checkboxradio widget" );
6471		}
6472
6473		this.originalLabel = "";
6474
6475		// We need to get the label text but this may also need to make sure it does not contain the
6476		// input itself.
6477		// The label contents could be text, html, or a mix. We wrap all elements
6478		// and read the wrapper's `innerHTML` to get a string representation of
6479		// the label, without the input as part of it.
6480		labelContents = this.label.contents().not( this.element[ 0 ] );
6481
6482		if ( labelContents.length ) {
6483			this.originalLabel += labelContents
6484				.clone()
6485				.wrapAll( "<div></div>" )
6486				.parent()
6487				.html();
6488		}
6489
6490		// Set the label option if we found label text
6491		if ( this.originalLabel ) {
6492			options.label = this.originalLabel;
6493		}
6494
6495		disabled = this.element[ 0 ].disabled;
6496		if ( disabled != null ) {
6497			options.disabled = disabled;
6498		}
6499		return options;
6500	},
6501
6502	_create: function() {
6503		var checked = this.element[ 0 ].checked;
6504
6505		this._bindFormResetHandler();
6506
6507		if ( this.options.disabled == null ) {
6508			this.options.disabled = this.element[ 0 ].disabled;
6509		}
6510
6511		this._setOption( "disabled", this.options.disabled );
6512		this._addClass( "ui-checkboxradio", "ui-helper-hidden-accessible" );
6513		this._addClass( this.label, "ui-checkboxradio-label", "ui-button ui-widget" );
6514
6515		if ( this.type === "radio" ) {
6516			this._addClass( this.label, "ui-checkboxradio-radio-label" );
6517		}
6518
6519		if ( this.options.label && this.options.label !== this.originalLabel ) {
6520			this._updateLabel();
6521		} else if ( this.originalLabel ) {
6522			this.options.label = this.originalLabel;
6523		}
6524
6525		this._enhance();
6526
6527		if ( checked ) {
6528			this._addClass( this.label, "ui-checkboxradio-checked", "ui-state-active" );
6529		}
6530
6531		this._on( {
6532			change: "_toggleClasses",
6533			focus: function() {
6534				this._addClass( this.label, null, "ui-state-focus ui-visual-focus" );
6535			},
6536			blur: function() {
6537				this._removeClass( this.label, null, "ui-state-focus ui-visual-focus" );
6538			}
6539		} );
6540	},
6541
6542	_readType: function() {
6543		var nodeName = this.element[ 0 ].nodeName.toLowerCase();
6544		this.type = this.element[ 0 ].type;
6545		if ( nodeName !== "input" || !/radio|checkbox/.test( this.type ) ) {
6546			$.error( "Can't create checkboxradio on element.nodeName=" + nodeName +
6547				" and element.type=" + this.type );
6548		}
6549	},
6550
6551	// Support jQuery Mobile enhanced option
6552	_enhance: function() {
6553		this._updateIcon( this.element[ 0 ].checked );
6554	},
6555
6556	widget: function() {
6557		return this.label;
6558	},
6559
6560	_getRadioGroup: function() {
6561		var group;
6562		var name = this.element[ 0 ].name;
6563		var nameSelector = "input[name='" + CSS.escape( name ) + "']";
6564
6565		if ( !name ) {
6566			return $( [] );
6567		}
6568
6569		if ( this.form.length ) {
6570			group = $( this.form[ 0 ].elements ).filter( nameSelector );
6571		} else {
6572
6573			// Not inside a form, check all inputs that also are not inside a form
6574			group = $( nameSelector ).filter( function() {
6575				return $( $( this ).prop( "form" ) ).length === 0;
6576			} );
6577		}
6578
6579		return group.not( this.element );
6580	},
6581
6582	_toggleClasses: function() {
6583		var checked = this.element[ 0 ].checked;
6584		this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked );
6585
6586		if ( this.options.icon && this.type === "checkbox" ) {
6587			this._toggleClass( this.icon, null, "ui-icon-check ui-state-checked", checked )
6588				._toggleClass( this.icon, null, "ui-icon-blank", !checked );
6589		}
6590
6591		if ( this.type === "radio" ) {
6592			this._getRadioGroup()
6593				.each( function() {
6594					var instance = $( this ).checkboxradio( "instance" );
6595
6596					if ( instance ) {
6597						instance._removeClass( instance.label,
6598							"ui-checkboxradio-checked", "ui-state-active" );
6599					}
6600				} );
6601		}
6602	},
6603
6604	_destroy: function() {
6605		this._unbindFormResetHandler();
6606
6607		if ( this.icon ) {
6608			this.icon.remove();
6609			this.iconSpace.remove();
6610		}
6611	},
6612
6613	_setOption: function( key, value ) {
6614
6615		// We don't allow the value to be set to nothing
6616		if ( key === "label" && !value ) {
6617			return;
6618		}
6619
6620		this._super( key, value );
6621
6622		if ( key === "disabled" ) {
6623			this._toggleClass( this.label, null, "ui-state-disabled", value );
6624			this.element[ 0 ].disabled = value;
6625
6626			// Don't refresh when setting disabled
6627			return;
6628		}
6629		this.refresh();
6630	},
6631
6632	_updateIcon: function( checked ) {
6633		var toAdd = "ui-icon ui-icon-background ";
6634
6635		if ( this.options.icon ) {
6636			if ( !this.icon ) {
6637				this.icon = $( "<span>" );
6638				this.iconSpace = $( "<span> </span>" );
6639				this._addClass( this.iconSpace, "ui-checkboxradio-icon-space" );
6640			}
6641
6642			if ( this.type === "checkbox" ) {
6643				toAdd += checked ? "ui-icon-check ui-state-checked" : "ui-icon-blank";
6644				this._removeClass( this.icon, null, checked ? "ui-icon-blank" : "ui-icon-check" );
6645			} else {
6646				toAdd += "ui-icon-blank";
6647			}
6648			this._addClass( this.icon, "ui-checkboxradio-icon", toAdd );
6649			if ( !checked ) {
6650				this._removeClass( this.icon, null, "ui-icon-check ui-state-checked" );
6651			}
6652			this.icon.prependTo( this.label ).after( this.iconSpace );
6653		} else if ( this.icon !== undefined ) {
6654			this.icon.remove();
6655			this.iconSpace.remove();
6656			delete this.icon;
6657		}
6658	},
6659
6660	_updateLabel: function() {
6661
6662		// Remove the contents of the label ( minus the icon, icon space, and input )
6663		var contents = this.label.contents().not( this.element[ 0 ] );
6664		if ( this.icon ) {
6665			contents = contents.not( this.icon[ 0 ] );
6666		}
6667		if ( this.iconSpace ) {
6668			contents = contents.not( this.iconSpace[ 0 ] );
6669		}
6670		contents.remove();
6671
6672		this.label.append( this.options.label );
6673	},
6674
6675	refresh: function() {
6676		var checked = this.element[ 0 ].checked,
6677			isDisabled = this.element[ 0 ].disabled;
6678
6679		this._updateIcon( checked );
6680		this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked );
6681		if ( this.options.label !== null ) {
6682			this._updateLabel();
6683		}
6684
6685		if ( isDisabled !== this.options.disabled ) {
6686			this._setOptions( { "disabled": isDisabled } );
6687		}
6688	}
6689
6690} ] );
6691
6692var widgetsCheckboxradio = $.ui.checkboxradio;
6693
6694
6695/*!
6696 * jQuery UI Button 1.14.0
6697 * https://jqueryui.com
6698 *
6699 * Copyright OpenJS Foundation and other contributors
6700 * Released under the MIT license.
6701 * https://jquery.org/license
6702 */
6703
6704//>>label: Button
6705//>>group: Widgets
6706//>>description: Enhances a form with themeable buttons.
6707//>>docs: https://api.jqueryui.com/button/
6708//>>demos: https://jqueryui.com/button/
6709//>>css.structure: ../../themes/base/core.css
6710//>>css.structure: ../../themes/base/button.css
6711//>>css.theme: ../../themes/base/theme.css
6712
6713
6714$.widget( "ui.button", {
6715	version: "1.14.0",
6716	defaultElement: "<button>",
6717	options: {
6718		classes: {
6719			"ui-button": "ui-corner-all"
6720		},
6721		disabled: null,
6722		icon: null,
6723		iconPosition: "beginning",
6724		label: null,
6725		showLabel: true
6726	},
6727
6728	_getCreateOptions: function() {
6729		var disabled,
6730
6731			// This is to support cases like in jQuery Mobile where the base widget does have
6732			// an implementation of _getCreateOptions
6733			options = this._super() || {};
6734
6735		this.isInput = this.element.is( "input" );
6736
6737		disabled = this.element[ 0 ].disabled;
6738		if ( disabled != null ) {
6739			options.disabled = disabled;
6740		}
6741
6742		this.originalLabel = this.isInput ? this.element.val() : this.element.html();
6743		if ( this.originalLabel ) {
6744			options.label = this.originalLabel;
6745		}
6746
6747		return options;
6748	},
6749
6750	_create: function() {
6751		if ( !this.option.showLabel & !this.options.icon ) {
6752			this.options.showLabel = true;
6753		}
6754
6755		// We have to check the option again here even though we did in _getCreateOptions,
6756		// because null may have been passed on init which would override what was set in
6757		// _getCreateOptions
6758		if ( this.options.disabled == null ) {
6759			this.options.disabled = this.element[ 0 ].disabled || false;
6760		}
6761
6762		this.hasTitle = !!this.element.attr( "title" );
6763
6764		// Check to see if the label needs to be set or if its already correct
6765		if ( this.options.label && this.options.label !== this.originalLabel ) {
6766			if ( this.isInput ) {
6767				this.element.val( this.options.label );
6768			} else {
6769				this.element.html( this.options.label );
6770			}
6771		}
6772		this._addClass( "ui-button", "ui-widget" );
6773		this._setOption( "disabled", this.options.disabled );
6774		this._enhance();
6775
6776		if ( this.element.is( "a" ) ) {
6777			this._on( {
6778				"keyup": function( event ) {
6779					if ( event.keyCode === $.ui.keyCode.SPACE ) {
6780						event.preventDefault();
6781
6782						// If a native click is available use it, so we
6783						// actually cause navigation. Otherwise, just trigger
6784						// a click event.
6785						if ( this.element[ 0 ].click ) {
6786							this.element[ 0 ].click();
6787						} else {
6788							this.element.trigger( "click" );
6789						}
6790					}
6791				}
6792			} );
6793		}
6794	},
6795
6796	_enhance: function() {
6797		if ( !this.element.is( "button" ) ) {
6798			this.element.attr( "role", "button" );
6799		}
6800
6801		if ( this.options.icon ) {
6802			this._updateIcon( "icon", this.options.icon );
6803			this._updateTooltip();
6804		}
6805	},
6806
6807	_updateTooltip: function() {
6808		this.title = this.element.attr( "title" );
6809
6810		if ( !this.options.showLabel && !this.title ) {
6811			this.element.attr( "title", this.options.label );
6812		}
6813	},
6814
6815	_updateIcon: function( option, value ) {
6816		var icon = option !== "iconPosition",
6817			position = icon ? this.options.iconPosition : value,
6818			displayBlock = position === "top" || position === "bottom";
6819
6820		// Create icon
6821		if ( !this.icon ) {
6822			this.icon = $( "<span>" );
6823
6824			this._addClass( this.icon, "ui-button-icon", "ui-icon" );
6825
6826			if ( !this.options.showLabel ) {
6827				this._addClass( "ui-button-icon-only" );
6828			}
6829		} else if ( icon ) {
6830
6831			// If we are updating the icon remove the old icon class
6832			this._removeClass( this.icon, null, this.options.icon );
6833		}
6834
6835		// If we are updating the icon add the new icon class
6836		if ( icon ) {
6837			this._addClass( this.icon, null, value );
6838		}
6839
6840		this._attachIcon( position );
6841
6842		// If the icon is on top or bottom we need to add the ui-widget-icon-block class and remove
6843		// the iconSpace if there is one.
6844		if ( displayBlock ) {
6845			this._addClass( this.icon, null, "ui-widget-icon-block" );
6846			if ( this.iconSpace ) {
6847				this.iconSpace.remove();
6848			}
6849		} else {
6850
6851			// Position is beginning or end so remove the ui-widget-icon-block class and add the
6852			// space if it does not exist
6853			if ( !this.iconSpace ) {
6854				this.iconSpace = $( "<span> </span>" );
6855				this._addClass( this.iconSpace, "ui-button-icon-space" );
6856			}
6857			this._removeClass( this.icon, null, "ui-wiget-icon-block" );
6858			this._attachIconSpace( position );
6859		}
6860	},
6861
6862	_destroy: function() {
6863		this.element.removeAttr( "role" );
6864
6865		if ( this.icon ) {
6866			this.icon.remove();
6867		}
6868		if ( this.iconSpace ) {
6869			this.iconSpace.remove();
6870		}
6871		if ( !this.hasTitle ) {
6872			this.element.removeAttr( "title" );
6873		}
6874	},
6875
6876	_attachIconSpace: function( iconPosition ) {
6877		this.icon[ /^(?:end|bottom)/.test( iconPosition ) ? "before" : "after" ]( this.iconSpace );
6878	},
6879
6880	_attachIcon: function( iconPosition ) {
6881		this.element[ /^(?:end|bottom)/.test( iconPosition ) ? "append" : "prepend" ]( this.icon );
6882	},
6883
6884	_setOptions: function( options ) {
6885		var newShowLabel = options.showLabel === undefined ?
6886				this.options.showLabel :
6887				options.showLabel,
6888			newIcon = options.icon === undefined ? this.options.icon : options.icon;
6889
6890		if ( !newShowLabel && !newIcon ) {
6891			options.showLabel = true;
6892		}
6893		this._super( options );
6894	},
6895
6896	_setOption: function( key, value ) {
6897		if ( key === "icon" ) {
6898			if ( value ) {
6899				this._updateIcon( key, value );
6900			} else if ( this.icon ) {
6901				this.icon.remove();
6902				if ( this.iconSpace ) {
6903					this.iconSpace.remove();
6904				}
6905			}
6906		}
6907
6908		if ( key === "iconPosition" ) {
6909			this._updateIcon( key, value );
6910		}
6911
6912		// Make sure we can't end up with a button that has neither text nor icon
6913		if ( key === "showLabel" ) {
6914				this._toggleClass( "ui-button-icon-only", null, !value );
6915				this._updateTooltip();
6916		}
6917
6918		if ( key === "label" ) {
6919			if ( this.isInput ) {
6920				this.element.val( value );
6921			} else {
6922
6923				// If there is an icon, append it, else nothing then append the value
6924				// this avoids removal of the icon when setting label text
6925				this.element.html( value );
6926				if ( this.icon ) {
6927					this._attachIcon( this.options.iconPosition );
6928					this._attachIconSpace( this.options.iconPosition );
6929				}
6930			}
6931		}
6932
6933		this._super( key, value );
6934
6935		if ( key === "disabled" ) {
6936			this._toggleClass( null, "ui-state-disabled", value );
6937			this.element[ 0 ].disabled = value;
6938			if ( value ) {
6939				this.element.trigger( "blur" );
6940			}
6941		}
6942	},
6943
6944	refresh: function() {
6945
6946		// Make sure to only check disabled if its an element that supports this otherwise
6947		// check for the disabled class to determine state
6948		var isDisabled = this.element.is( "input, button" ) ?
6949			this.element[ 0 ].disabled : this.element.hasClass( "ui-button-disabled" );
6950
6951		if ( isDisabled !== this.options.disabled ) {
6952			this._setOptions( { disabled: isDisabled } );
6953		}
6954
6955		this._updateTooltip();
6956	}
6957} );
6958
6959// DEPRECATED
6960if ( $.uiBackCompat === true ) {
6961
6962	// Text and Icons options
6963	$.widget( "ui.button", $.ui.button, {
6964		options: {
6965			text: true,
6966			icons: {
6967				primary: null,
6968				secondary: null
6969			}
6970		},
6971
6972		_create: function() {
6973			if ( this.options.showLabel && !this.options.text ) {
6974				this.options.showLabel = this.options.text;
6975			}
6976			if ( !this.options.showLabel && this.options.text ) {
6977				this.options.text = this.options.showLabel;
6978			}
6979			if ( !this.options.icon && ( this.options.icons.primary ||
6980					this.options.icons.secondary ) ) {
6981				if ( this.options.icons.primary ) {
6982					this.options.icon = this.options.icons.primary;
6983				} else {
6984					this.options.icon = this.options.icons.secondary;
6985					this.options.iconPosition = "end";
6986				}
6987			} else if ( this.options.icon ) {
6988				this.options.icons.primary = this.options.icon;
6989			}
6990			this._super();
6991		},
6992
6993		_setOption: function( key, value ) {
6994			if ( key === "text" ) {
6995				this._super( "showLabel", value );
6996				return;
6997			}
6998			if ( key === "showLabel" ) {
6999				this.options.text = value;
7000			}
7001			if ( key === "icon" ) {
7002				this.options.icons.primary = value;
7003			}
7004			if ( key === "icons" ) {
7005				if ( value.primary ) {
7006					this._super( "icon", value.primary );
7007					this._super( "iconPosition", "beginning" );
7008				} else if ( value.secondary ) {
7009					this._super( "icon", value.secondary );
7010					this._super( "iconPosition", "end" );
7011				}
7012			}
7013			this._superApply( arguments );
7014		}
7015	} );
7016
7017	$.fn.button = ( function( orig ) {
7018		return function( options ) {
7019			var isMethodCall = typeof options === "string";
7020			var args = Array.prototype.slice.call( arguments, 1 );
7021			var returnValue = this;
7022
7023			if ( isMethodCall ) {
7024
7025				// If this is an empty collection, we need to have the instance method
7026				// return undefined instead of the jQuery instance
7027				if ( !this.length && options === "instance" ) {
7028					returnValue = undefined;
7029				} else {
7030					this.each( function() {
7031						var methodValue;
7032						var type = $( this ).attr( "type" );
7033						var name = type !== "checkbox" && type !== "radio" ?
7034							"button" :
7035							"checkboxradio";
7036						var instance = $.data( this, "ui-" + name );
7037
7038						if ( options === "instance" ) {
7039							returnValue = instance;
7040							return false;
7041						}
7042
7043						if ( !instance ) {
7044							return $.error( "cannot call methods on button" +
7045								" prior to initialization; " +
7046								"attempted to call method '" + options + "'" );
7047						}
7048
7049						if ( typeof instance[ options ] !== "function" ||
7050							options.charAt( 0 ) === "_" ) {
7051							return $.error( "no such method '" + options + "' for button" +
7052								" widget instance" );
7053						}
7054
7055						methodValue = instance[ options ].apply( instance, args );
7056
7057						if ( methodValue !== instance && methodValue !== undefined ) {
7058							returnValue = methodValue && methodValue.jquery ?
7059								returnValue.pushStack( methodValue.get() ) :
7060								methodValue;
7061							return false;
7062						}
7063					} );
7064				}
7065			} else {
7066
7067				// Allow multiple hashes to be passed on init
7068				if ( args.length ) {
7069					options = $.widget.extend.apply( null, [ options ].concat( args ) );
7070				}
7071
7072				this.each( function() {
7073					var type = $( this ).attr( "type" );
7074					var name = type !== "checkbox" && type !== "radio" ? "button" : "checkboxradio";
7075					var instance = $.data( this, "ui-" + name );
7076
7077					if ( instance ) {
7078						instance.option( options || {} );
7079						if ( instance._init ) {
7080							instance._init();
7081						}
7082					} else {
7083						if ( name === "button" ) {
7084							orig.call( $( this ), options );
7085							return;
7086						}
7087
7088						$( this ).checkboxradio( $.extend( { icon: false }, options ) );
7089					}
7090				} );
7091			}
7092
7093			return returnValue;
7094		};
7095	} )( $.fn.button );
7096
7097	$.fn.buttonset = function() {
7098		if ( !$.ui.controlgroup ) {
7099			$.error( "Controlgroup widget missing" );
7100		}
7101		if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" && arguments[ 2 ] ) {
7102			return this.controlgroup.apply( this,
7103				[ arguments[ 0 ], "items.button", arguments[ 2 ] ] );
7104		}
7105		if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" ) {
7106			return this.controlgroup.apply( this, [ arguments[ 0 ], "items.button" ] );
7107		}
7108		if ( typeof arguments[ 0 ] === "object" && arguments[ 0 ].items ) {
7109			arguments[ 0 ].items = {
7110				button: arguments[ 0 ].items
7111			};
7112		}
7113		return this.controlgroup.apply( this, arguments );
7114	};
7115}
7116
7117var widgetsButton = $.ui.button;
7118
7119
7120/* eslint-disable max-len, camelcase */
7121/*!
7122 * jQuery UI Datepicker 1.14.0
7123 * https://jqueryui.com
7124 *
7125 * Copyright OpenJS Foundation and other contributors
7126 * Released under the MIT license.
7127 * https://jquery.org/license
7128 */
7129
7130//>>label: Datepicker
7131//>>group: Widgets
7132//>>description: Displays a calendar from an input or inline for selecting dates.
7133//>>docs: https://api.jqueryui.com/datepicker/
7134//>>demos: https://jqueryui.com/datepicker/
7135//>>css.structure: ../../themes/base/core.css
7136//>>css.structure: ../../themes/base/datepicker.css
7137//>>css.theme: ../../themes/base/theme.css
7138
7139
7140$.extend( $.ui, { datepicker: { version: "1.14.0" } } );
7141
7142var datepicker_instActive;
7143
7144function datepicker_getZindex( elem ) {
7145	var position, value;
7146	while ( elem.length && elem[ 0 ] !== document ) {
7147
7148		// Ignore z-index if position is set to a value where z-index is ignored by the browser
7149		// This makes behavior of this function consistent across browsers
7150		// WebKit always returns auto if the element is positioned
7151		position = elem.css( "position" );
7152		if ( position === "absolute" || position === "relative" || position === "fixed" ) {
7153
7154			// IE returns 0 when zIndex is not specified
7155			// other browsers return a string
7156			// we ignore the case of nested elements with an explicit value of 0
7157			// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
7158			value = parseInt( elem.css( "zIndex" ), 10 );
7159			if ( !isNaN( value ) && value !== 0 ) {
7160				return value;
7161			}
7162		}
7163		elem = elem.parent();
7164	}
7165
7166	return 0;
7167}
7168
7169/* Date picker manager.
7170   Use the singleton instance of this class, $.datepicker, to interact with the date picker.
7171   Settings for (groups of) date pickers are maintained in an instance object,
7172   allowing multiple different settings on the same page. */
7173
7174function Datepicker() {
7175	this._curInst = null; // The current instance in use
7176	this._keyEvent = false; // If the last event was a key event
7177	this._disabledInputs = []; // List of date picker inputs that have been disabled
7178	this._datepickerShowing = false; // True if the popup picker is showing , false if not
7179	this._inDialog = false; // True if showing within a "dialog", false if not
7180	this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division
7181	this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class
7182	this._appendClass = "ui-datepicker-append"; // The name of the append marker class
7183	this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class
7184	this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class
7185	this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class
7186	this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class
7187	this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class
7188	this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class
7189	this.regional = []; // Available regional settings, indexed by language code
7190	this.regional[ "" ] = { // Default regional settings
7191		closeText: "Done", // Display text for close link
7192		prevText: "Prev", // Display text for previous month link
7193		nextText: "Next", // Display text for next month link
7194		currentText: "Today", // Display text for current month link
7195		monthNames: [ "January", "February", "March", "April", "May", "June",
7196			"July", "August", "September", "October", "November", "December" ], // Names of months for drop-down and formatting
7197		monthNamesShort: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ], // For formatting
7198		dayNames: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], // For formatting
7199		dayNamesShort: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], // For formatting
7200		dayNamesMin: [ "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" ], // Column headings for days starting at Sunday
7201		weekHeader: "Wk", // Column header for week of the year
7202		dateFormat: "mm/dd/yy", // See format options on parseDate
7203		firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
7204		isRTL: false, // True if right-to-left language, false if left-to-right
7205		showMonthAfterYear: false, // True if the year select precedes month, false for month then year
7206		yearSuffix: "", // Additional text to append to the year in the month headers,
7207		selectMonthLabel: "Select month", // Invisible label for month selector
7208		selectYearLabel: "Select year" // Invisible label for year selector
7209	};
7210	this._defaults = { // Global defaults for all the date picker instances
7211		showOn: "focus", // "focus" for popup on focus,
7212			// "button" for trigger button, or "both" for either
7213		showAnim: "fadeIn", // Name of jQuery animation for popup
7214		showOptions: {}, // Options for enhanced animations
7215		defaultDate: null, // Used when field is blank: actual date,
7216			// +/-number for offset from today, null for today
7217		appendText: "", // Display text following the input box, e.g. showing the format
7218		buttonText: "...", // Text for trigger button
7219		buttonImage: "", // URL for trigger button image
7220		buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
7221		hideIfNoPrevNext: false, // True to hide next/previous month links
7222			// if not applicable, false to just disable them
7223		navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
7224		gotoCurrent: false, // True if today link goes back to current selection instead
7225		changeMonth: false, // True if month can be selected directly, false if only prev/next
7226		changeYear: false, // True if year can be selected directly, false if only prev/next
7227		yearRange: "c-10:c+10", // Range of years to display in drop-down,
7228			// either relative to today's year (-nn:+nn), relative to currently displayed year
7229			// (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
7230		showOtherMonths: false, // True to show dates in other months, false to leave blank
7231		selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
7232		showWeek: false, // True to show week of the year, false to not show it
7233		calculateWeek: this.iso8601Week, // How to calculate the week of the year,
7234			// takes a Date and returns the number of the week for it
7235		shortYearCutoff: "+10", // Short year values < this are in the current century,
7236			// > this are in the previous century,
7237			// string value starting with "+" for current year + value
7238		minDate: null, // The earliest selectable date, or null for no limit
7239		maxDate: null, // The latest selectable date, or null for no limit
7240		duration: "fast", // Duration of display/closure
7241		beforeShowDay: null, // Function that takes a date and returns an array with
7242			// [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "",
7243			// [2] = cell title (optional), e.g. $.datepicker.noWeekends
7244		beforeShow: null, // Function that takes an input field and
7245			// returns a set of custom settings for the date picker
7246		onSelect: null, // Define a callback function when a date is selected
7247		onChangeMonthYear: null, // Define a callback function when the month or year is changed
7248		onClose: null, // Define a callback function when the datepicker is closed
7249		onUpdateDatepicker: null, // Define a callback function when the datepicker is updated
7250		numberOfMonths: 1, // Number of months to show at a time
7251		showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
7252		stepMonths: 1, // Number of months to step back/forward
7253		stepBigMonths: 12, // Number of months to step back/forward for the big links
7254		altField: "", // Selector for an alternate field to store selected dates into
7255		altFormat: "", // The date format to use for the alternate field
7256		constrainInput: true, // The input is constrained by the current date format
7257		showButtonPanel: false, // True to show button panel, false to not show it
7258		autoSize: false, // True to size the input for the date format, false to leave as is
7259		disabled: false // The initial disabled state
7260	};
7261	$.extend( this._defaults, this.regional[ "" ] );
7262	this.regional.en = $.extend( true, {}, this.regional[ "" ] );
7263	this.regional[ "en-US" ] = $.extend( true, {}, this.regional.en );
7264	this.dpDiv = datepicker_bindHover( $( "<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) );
7265}
7266
7267$.extend( Datepicker.prototype, {
7268
7269	/* Class name added to elements to indicate already configured with a date picker. */
7270	markerClassName: "hasDatepicker",
7271
7272	//Keep track of the maximum number of rows displayed (see #7043)
7273	maxRows: 4,
7274
7275	// TODO rename to "widget" when switching to widget factory
7276	_widgetDatepicker: function() {
7277		return this.dpDiv;
7278	},
7279
7280	/* Override the default settings for all instances of the date picker.
7281	 * @param  settings  object - the new settings to use as defaults (anonymous object)
7282	 * @return the manager object
7283	 */
7284	setDefaults: function( settings ) {
7285		datepicker_extendRemove( this._defaults, settings || {} );
7286		return this;
7287	},
7288
7289	/* Attach the date picker to a jQuery selection.
7290	 * @param  target	element - the target input field or division or span
7291	 * @param  settings  object - the new settings to use for this date picker instance (anonymous)
7292	 */
7293	_attachDatepicker: function( target, settings ) {
7294		var nodeName, inline, inst;
7295		nodeName = target.nodeName.toLowerCase();
7296		inline = ( nodeName === "div" || nodeName === "span" );
7297		if ( !target.id ) {
7298			this.uuid += 1;
7299			target.id = "dp" + this.uuid;
7300		}
7301		inst = this._newInst( $( target ), inline );
7302		inst.settings = $.extend( {}, settings || {} );
7303		if ( nodeName === "input" ) {
7304			this._connectDatepicker( target, inst );
7305		} else if ( inline ) {
7306			this._inlineDatepicker( target, inst );
7307		}
7308	},
7309
7310	/* Create a new instance object. */
7311	_newInst: function( target, inline ) {
7312		var id = target[ 0 ].id.replace( /([^A-Za-z0-9_\-])/g, "\\\\$1" ); // escape jQuery meta chars
7313		return { id: id, input: target, // associated target
7314			selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
7315			drawMonth: 0, drawYear: 0, // month being drawn
7316			inline: inline, // is datepicker inline or not
7317			dpDiv: ( !inline ? this.dpDiv : // presentation div
7318			datepicker_bindHover( $( "<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) ) ) };
7319	},
7320
7321	/* Attach the date picker to an input field. */
7322	_connectDatepicker: function( target, inst ) {
7323		var input = $( target );
7324		inst.append = $( [] );
7325		inst.trigger = $( [] );
7326		if ( input.hasClass( this.markerClassName ) ) {
7327			return;
7328		}
7329		this._attachments( input, inst );
7330		input.addClass( this.markerClassName ).on( "keydown", this._doKeyDown ).
7331			on( "keypress", this._doKeyPress ).on( "keyup", this._doKeyUp );
7332		this._autoSize( inst );
7333		$.data( target, "datepicker", inst );
7334
7335		//If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
7336		if ( inst.settings.disabled ) {
7337			this._disableDatepicker( target );
7338		}
7339	},
7340
7341	/* Make attachments based on settings. */
7342	_attachments: function( input, inst ) {
7343		var showOn, buttonText, buttonImage,
7344			appendText = this._get( inst, "appendText" ),
7345			isRTL = this._get( inst, "isRTL" );
7346
7347		if ( inst.append ) {
7348			inst.append.remove();
7349		}
7350		if ( appendText ) {
7351			inst.append = $( "<span>" )
7352				.addClass( this._appendClass )
7353				.text( appendText );
7354			input[ isRTL ? "before" : "after" ]( inst.append );
7355		}
7356
7357		input.off( "focus", this._showDatepicker );
7358
7359		if ( inst.trigger ) {
7360			inst.trigger.remove();
7361		}
7362
7363		showOn = this._get( inst, "showOn" );
7364		if ( showOn === "focus" || showOn === "both" ) { // pop-up date picker when in the marked field
7365			input.on( "focus", this._showDatepicker );
7366		}
7367		if ( showOn === "button" || showOn === "both" ) { // pop-up date picker when button clicked
7368			buttonText = this._get( inst, "buttonText" );
7369			buttonImage = this._get( inst, "buttonImage" );
7370
7371			if ( this._get( inst, "buttonImageOnly" ) ) {
7372				inst.trigger = $( "<img>" )
7373					.addClass( this._triggerClass )
7374					.attr( {
7375						src: buttonImage,
7376						alt: buttonText,
7377						title: buttonText
7378					} );
7379			} else {
7380				inst.trigger = $( "<button type='button'>" )
7381					.addClass( this._triggerClass );
7382				if ( buttonImage ) {
7383					inst.trigger.html(
7384						$( "<img>" )
7385							.attr( {
7386								src: buttonImage,
7387								alt: buttonText,
7388								title: buttonText
7389							} )
7390					);
7391				} else {
7392					inst.trigger.text( buttonText );
7393				}
7394			}
7395
7396			input[ isRTL ? "before" : "after" ]( inst.trigger );
7397			inst.trigger.on( "click", function() {
7398				if ( $.datepicker._datepickerShowing && $.datepicker._lastInput === input[ 0 ] ) {
7399					$.datepicker._hideDatepicker();
7400				} else if ( $.datepicker._datepickerShowing && $.datepicker._lastInput !== input[ 0 ] ) {
7401					$.datepicker._hideDatepicker();
7402					$.datepicker._showDatepicker( input[ 0 ] );
7403				} else {
7404					$.datepicker._showDatepicker( input[ 0 ] );
7405				}
7406				return false;
7407			} );
7408		}
7409	},
7410
7411	/* Apply the maximum length for the date format. */
7412	_autoSize: function( inst ) {
7413		if ( this._get( inst, "autoSize" ) && !inst.inline ) {
7414			var findMax, max, maxI, i,
7415				date = new Date( 2009, 12 - 1, 20 ), // Ensure double digits
7416				dateFormat = this._get( inst, "dateFormat" );
7417
7418			if ( dateFormat.match( /[DM]/ ) ) {
7419				findMax = function( names ) {
7420					max = 0;
7421					maxI = 0;
7422					for ( i = 0; i < names.length; i++ ) {
7423						if ( names[ i ].length > max ) {
7424							max = names[ i ].length;
7425							maxI = i;
7426						}
7427					}
7428					return maxI;
7429				};
7430				date.setMonth( findMax( this._get( inst, ( dateFormat.match( /MM/ ) ?
7431					"monthNames" : "monthNamesShort" ) ) ) );
7432				date.setDate( findMax( this._get( inst, ( dateFormat.match( /DD/ ) ?
7433					"dayNames" : "dayNamesShort" ) ) ) + 20 - date.getDay() );
7434			}
7435			inst.input.attr( "size", this._formatDate( inst, date ).length );
7436		}
7437	},
7438
7439	/* Attach an inline date picker to a div. */
7440	_inlineDatepicker: function( target, inst ) {
7441		var divSpan = $( target );
7442		if ( divSpan.hasClass( this.markerClassName ) ) {
7443			return;
7444		}
7445		divSpan.addClass( this.markerClassName ).append( inst.dpDiv );
7446		$.data( target, "datepicker", inst );
7447		this._setDate( inst, this._getDefaultDate( inst ), true );
7448		this._updateDatepicker( inst );
7449		this._updateAlternate( inst );
7450
7451		//If disabled option is true, disable the datepicker before showing it (see ticket #5665)
7452		if ( inst.settings.disabled ) {
7453			this._disableDatepicker( target );
7454		}
7455
7456		// Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
7457		// https://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
7458		inst.dpDiv.css( "display", "block" );
7459	},
7460
7461	/* Pop-up the date picker in a "dialog" box.
7462	 * @param  input element - ignored
7463	 * @param  date	string or Date - the initial date to display
7464	 * @param  onSelect  function - the function to call when a date is selected
7465	 * @param  settings  object - update the dialog date picker instance's settings (anonymous object)
7466	 * @param  pos int[2] - coordinates for the dialog's position within the screen or
7467	 *					event - with x/y coordinates or
7468	 *					leave empty for default (screen centre)
7469	 * @return the manager object
7470	 */
7471	_dialogDatepicker: function( input, date, onSelect, settings, pos ) {
7472		var id, browserWidth, browserHeight, scrollX, scrollY,
7473			inst = this._dialogInst; // internal instance
7474
7475		if ( !inst ) {
7476			this.uuid += 1;
7477			id = "dp" + this.uuid;
7478			this._dialogInput = $( "<input type='text' id='" + id +
7479				"' style='position: absolute; top: -100px; width: 0px;'/>" );
7480			this._dialogInput.on( "keydown", this._doKeyDown );
7481			$( "body" ).append( this._dialogInput );
7482			inst = this._dialogInst = this._newInst( this._dialogInput, false );
7483			inst.settings = {};
7484			$.data( this._dialogInput[ 0 ], "datepicker", inst );
7485		}
7486		datepicker_extendRemove( inst.settings, settings || {} );
7487		date = ( date && date.constructor === Date ? this._formatDate( inst, date ) : date );
7488		this._dialogInput.val( date );
7489
7490		this._pos = ( pos ? ( pos.length ? pos : [ pos.pageX, pos.pageY ] ) : null );
7491		if ( !this._pos ) {
7492			browserWidth = document.documentElement.clientWidth;
7493			browserHeight = document.documentElement.clientHeight;
7494			scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
7495			scrollY = document.documentElement.scrollTop || document.body.scrollTop;
7496			this._pos = // should use actual width/height below
7497				[ ( browserWidth / 2 ) - 100 + scrollX, ( browserHeight / 2 ) - 150 + scrollY ];
7498		}
7499
7500		// Move input on screen for focus, but hidden behind dialog
7501		this._dialogInput.css( "left", ( this._pos[ 0 ] + 20 ) + "px" ).css( "top", this._pos[ 1 ] + "px" );
7502		inst.settings.onSelect = onSelect;
7503		this._inDialog = true;
7504		this.dpDiv.addClass( this._dialogClass );
7505		this._showDatepicker( this._dialogInput[ 0 ] );
7506		if ( $.blockUI ) {
7507			$.blockUI( this.dpDiv );
7508		}
7509		$.data( this._dialogInput[ 0 ], "datepicker", inst );
7510		return this;
7511	},
7512
7513	/* Detach a datepicker from its control.
7514	 * @param  target	element - the target input field or division or span
7515	 */
7516	_destroyDatepicker: function( target ) {
7517		var nodeName,
7518			$target = $( target ),
7519			inst = $.data( target, "datepicker" );
7520
7521		if ( !$target.hasClass( this.markerClassName ) ) {
7522			return;
7523		}
7524
7525		nodeName = target.nodeName.toLowerCase();
7526		$.removeData( target, "datepicker" );
7527		if ( nodeName === "input" ) {
7528			inst.append.remove();
7529			inst.trigger.remove();
7530			$target.removeClass( this.markerClassName ).
7531				off( "focus", this._showDatepicker ).
7532				off( "keydown", this._doKeyDown ).
7533				off( "keypress", this._doKeyPress ).
7534				off( "keyup", this._doKeyUp );
7535		} else if ( nodeName === "div" || nodeName === "span" ) {
7536			$target.removeClass( this.markerClassName ).empty();
7537		}
7538
7539		$.datepicker._hideDatepicker();
7540		if ( datepicker_instActive === inst ) {
7541			datepicker_instActive = null;
7542			this._curInst = null;
7543		}
7544	},
7545
7546	/* Enable the date picker to a jQuery selection.
7547	 * @param  target	element - the target input field or division or span
7548	 */
7549	_enableDatepicker: function( target ) {
7550		var nodeName, inline,
7551			$target = $( target ),
7552			inst = $.data( target, "datepicker" );
7553
7554		if ( !$target.hasClass( this.markerClassName ) ) {
7555			return;
7556		}
7557
7558		nodeName = target.nodeName.toLowerCase();
7559		if ( nodeName === "input" ) {
7560			target.disabled = false;
7561			inst.trigger.filter( "button" ).
7562				each( function() {
7563					this.disabled = false;
7564				} ).end().
7565				filter( "img" ).css( { opacity: "1.0", cursor: "" } );
7566		} else if ( nodeName === "div" || nodeName === "span" ) {
7567			inline = $target.children( "." + this._inlineClass );
7568			inline.children().removeClass( "ui-state-disabled" );
7569			inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ).
7570				prop( "disabled", false );
7571		}
7572		this._disabledInputs = $.map( this._disabledInputs,
7573
7574			// Delete entry
7575			function( value ) {
7576				return ( value === target ? null : value );
7577			} );
7578	},
7579
7580	/* Disable the date picker to a jQuery selection.
7581	 * @param  target	element - the target input field or division or span
7582	 */
7583	_disableDatepicker: function( target ) {
7584		var nodeName, inline,
7585			$target = $( target ),
7586			inst = $.data( target, "datepicker" );
7587
7588		if ( !$target.hasClass( this.markerClassName ) ) {
7589			return;
7590		}
7591
7592		nodeName = target.nodeName.toLowerCase();
7593		if ( nodeName === "input" ) {
7594			target.disabled = true;
7595			inst.trigger.filter( "button" ).
7596				each( function() {
7597					this.disabled = true;
7598				} ).end().
7599				filter( "img" ).css( { opacity: "0.5", cursor: "default" } );
7600		} else if ( nodeName === "div" || nodeName === "span" ) {
7601			inline = $target.children( "." + this._inlineClass );
7602			inline.children().addClass( "ui-state-disabled" );
7603			inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ).
7604				prop( "disabled", true );
7605		}
7606		this._disabledInputs = $.map( this._disabledInputs,
7607
7608			// Delete entry
7609			function( value ) {
7610				return ( value === target ? null : value );
7611			} );
7612		this._disabledInputs[ this._disabledInputs.length ] = target;
7613	},
7614
7615	/* Is the first field in a jQuery collection disabled as a datepicker?
7616	 * @param  target	element - the target input field or division or span
7617	 * @return boolean - true if disabled, false if enabled
7618	 */
7619	_isDisabledDatepicker: function( target ) {
7620		if ( !target ) {
7621			return false;
7622		}
7623		for ( var i = 0; i < this._disabledInputs.length; i++ ) {
7624			if ( this._disabledInputs[ i ] === target ) {
7625				return true;
7626			}
7627		}
7628		return false;
7629	},
7630
7631	/* Retrieve the instance data for the target control.
7632	 * @param  target  element - the target input field or division or span
7633	 * @return  object - the associated instance data
7634	 * @throws  error if a jQuery problem getting data
7635	 */
7636	_getInst: function( target ) {
7637		try {
7638			return $.data( target, "datepicker" );
7639		} catch ( err ) {
7640			throw "Missing instance data for this datepicker";
7641		}
7642	},
7643
7644	/* Update or retrieve the settings for a date picker attached to an input field or division.
7645	 * @param  target  element - the target input field or division or span
7646	 * @param  name	object - the new settings to update or
7647	 *				string - the name of the setting to change or retrieve,
7648	 *				when retrieving also "all" for all instance settings or
7649	 *				"defaults" for all global defaults
7650	 * @param  value   any - the new value for the setting
7651	 *				(omit if above is an object or to retrieve a value)
7652	 */
7653	_optionDatepicker: function( target, name, value ) {
7654		var settings, date, minDate, maxDate,
7655			inst = this._getInst( target );
7656
7657		if ( arguments.length === 2 && typeof name === "string" ) {
7658			return ( name === "defaults" ? $.extend( {}, $.datepicker._defaults ) :
7659				( inst ? ( name === "all" ? $.extend( {}, inst.settings ) :
7660				this._get( inst, name ) ) : null ) );
7661		}
7662
7663		settings = name || {};
7664		if ( typeof name === "string" ) {
7665			settings = {};
7666			settings[ name ] = value;
7667		}
7668
7669		if ( inst ) {
7670			if ( this._curInst === inst ) {
7671				this._hideDatepicker();
7672			}
7673
7674			date = this._getDateDatepicker( target, true );
7675			minDate = this._getMinMaxDate( inst, "min" );
7676			maxDate = this._getMinMaxDate( inst, "max" );
7677			datepicker_extendRemove( inst.settings, settings );
7678
7679			// reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
7680			if ( minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined ) {
7681				inst.settings.minDate = this._formatDate( inst, minDate );
7682			}
7683			if ( maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined ) {
7684				inst.settings.maxDate = this._formatDate( inst, maxDate );
7685			}
7686			if ( "disabled" in settings ) {
7687				if ( settings.disabled ) {
7688					this._disableDatepicker( target );
7689				} else {
7690					this._enableDatepicker( target );
7691				}
7692			}
7693			this._attachments( $( target ), inst );
7694			this._autoSize( inst );
7695			this._setDate( inst, date );
7696			this._updateAlternate( inst );
7697			this._updateDatepicker( inst );
7698		}
7699	},
7700
7701	// Change method deprecated
7702	_changeDatepicker: function( target, name, value ) {
7703		this._optionDatepicker( target, name, value );
7704	},
7705
7706	/* Redraw the date picker attached to an input field or division.
7707	 * @param  target  element - the target input field or division or span
7708	 */
7709	_refreshDatepicker: function( target ) {
7710		var inst = this._getInst( target );
7711		if ( inst ) {
7712			this._updateDatepicker( inst );
7713		}
7714	},
7715
7716	/* Set the dates for a jQuery selection.
7717	 * @param  target element - the target input field or division or span
7718	 * @param  date	Date - the new date
7719	 */
7720	_setDateDatepicker: function( target, date ) {
7721		var inst = this._getInst( target );
7722		if ( inst ) {
7723			this._setDate( inst, date );
7724			this._updateDatepicker( inst );
7725			this._updateAlternate( inst );
7726		}
7727	},
7728
7729	/* Get the date(s) for the first entry in a jQuery selection.
7730	 * @param  target element - the target input field or division or span
7731	 * @param  noDefault boolean - true if no default date is to be used
7732	 * @return Date - the current date
7733	 */
7734	_getDateDatepicker: function( target, noDefault ) {
7735		var inst = this._getInst( target );
7736		if ( inst && !inst.inline ) {
7737			this._setDateFromField( inst, noDefault );
7738		}
7739		return ( inst ? this._getDate( inst ) : null );
7740	},
7741
7742	/* Handle keystrokes. */
7743	_doKeyDown: function( event ) {
7744		var onSelect, dateStr, sel,
7745			inst = $.datepicker._getInst( event.target ),
7746			handled = true,
7747			isRTL = inst.dpDiv.is( ".ui-datepicker-rtl" );
7748
7749		inst._keyEvent = true;
7750		if ( $.datepicker._datepickerShowing ) {
7751			switch ( event.keyCode ) {
7752				case 9: $.datepicker._hideDatepicker();
7753						handled = false;
7754						break; // hide on tab out
7755				case 13: sel = $( "td." + $.datepicker._dayOverClass + ":not(." +
7756									$.datepicker._currentClass + ")", inst.dpDiv );
7757						if ( sel[ 0 ] ) {
7758							$.datepicker._selectDay( event.target, inst.selectedMonth, inst.selectedYear, sel[ 0 ] );
7759						}
7760
7761						onSelect = $.datepicker._get( inst, "onSelect" );
7762						if ( onSelect ) {
7763							dateStr = $.datepicker._formatDate( inst );
7764
7765							// Trigger custom callback
7766							onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] );
7767						} else {
7768							$.datepicker._hideDatepicker();
7769						}
7770
7771						return false; // don't submit the form
7772				case 27: $.datepicker._hideDatepicker();
7773						break; // hide on escape
7774				case 33: $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
7775							-$.datepicker._get( inst, "stepBigMonths" ) :
7776							-$.datepicker._get( inst, "stepMonths" ) ), "M" );
7777						break; // previous month/year on page up/+ ctrl
7778				case 34: $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
7779							+$.datepicker._get( inst, "stepBigMonths" ) :
7780							+$.datepicker._get( inst, "stepMonths" ) ), "M" );
7781						break; // next month/year on page down/+ ctrl
7782				case 35: if ( event.ctrlKey || event.metaKey ) {
7783							$.datepicker._clearDate( event.target );
7784						}
7785						handled = event.ctrlKey || event.metaKey;
7786						break; // clear on ctrl or command +end
7787				case 36: if ( event.ctrlKey || event.metaKey ) {
7788							$.datepicker._gotoToday( event.target );
7789						}
7790						handled = event.ctrlKey || event.metaKey;
7791						break; // current on ctrl or command +home
7792				case 37: if ( event.ctrlKey || event.metaKey ) {
7793							$.datepicker._adjustDate( event.target, ( isRTL ? +1 : -1 ), "D" );
7794						}
7795						handled = event.ctrlKey || event.metaKey;
7796
7797						// -1 day on ctrl or command +left
7798						if ( event.originalEvent.altKey ) {
7799							$.datepicker._adjustDate( event.target, ( event.ctrlKey ?
7800								-$.datepicker._get( inst, "stepBigMonths" ) :
7801								-$.datepicker._get( inst, "stepMonths" ) ), "M" );
7802						}
7803
7804						// next month/year on alt +left on Mac
7805						break;
7806				case 38: if ( event.ctrlKey || event.metaKey ) {
7807							$.datepicker._adjustDate( event.target, -7, "D" );
7808						}
7809						handled = event.ctrlKey || event.metaKey;
7810						break; // -1 week on ctrl or command +up
7811				case 39: if ( event.ctrlKey || event.metaKey ) {
7812							$.datepicker._adjustDate( event.target, ( isRTL ? -1 : +1 ), "D" );
7813						}
7814						handled = event.ctrlKey || event.metaKey;
7815
7816						// +1 day on ctrl or command +right
7817						if ( event.originalEvent.altKey ) {
7818							$.datepicker._adjustDate( event.target, ( event.ctrlKey ?
7819								+$.datepicker._get( inst, "stepBigMonths" ) :
7820								+$.datepicker._get( inst, "stepMonths" ) ), "M" );
7821						}
7822
7823						// next month/year on alt +right
7824						break;
7825				case 40: if ( event.ctrlKey || event.metaKey ) {
7826							$.datepicker._adjustDate( event.target, +7, "D" );
7827						}
7828						handled = event.ctrlKey || event.metaKey;
7829						break; // +1 week on ctrl or command +down
7830				default: handled = false;
7831			}
7832		} else if ( event.keyCode === 36 && event.ctrlKey ) { // display the date picker on ctrl+home
7833			$.datepicker._showDatepicker( this );
7834		} else {
7835			handled = false;
7836		}
7837
7838		if ( handled ) {
7839			event.preventDefault();
7840			event.stopPropagation();
7841		}
7842	},
7843
7844	/* Filter entered characters - based on date format. */
7845	_doKeyPress: function( event ) {
7846		var chars, chr,
7847			inst = $.datepicker._getInst( event.target );
7848
7849		if ( $.datepicker._get( inst, "constrainInput" ) ) {
7850			chars = $.datepicker._possibleChars( $.datepicker._get( inst, "dateFormat" ) );
7851			chr = String.fromCharCode( event.charCode == null ? event.keyCode : event.charCode );
7852			return event.ctrlKey || event.metaKey || ( chr < " " || !chars || chars.indexOf( chr ) > -1 );
7853		}
7854	},
7855
7856	/* Synchronise manual entry and field/alternate field. */
7857	_doKeyUp: function( event ) {
7858		var date,
7859			inst = $.datepicker._getInst( event.target );
7860
7861		if ( inst.input.val() !== inst.lastVal ) {
7862			try {
7863				date = $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ),
7864					( inst.input ? inst.input.val() : null ),
7865					$.datepicker._getFormatConfig( inst ) );
7866
7867				if ( date ) { // only if valid
7868					$.datepicker._setDateFromField( inst );
7869					$.datepicker._updateAlternate( inst );
7870					$.datepicker._updateDatepicker( inst );
7871				}
7872			} catch ( err ) {
7873			}
7874		}
7875		return true;
7876	},
7877
7878	/* Pop-up the date picker for a given input field.
7879	 * If false returned from beforeShow event handler do not show.
7880	 * @param  input  element - the input field attached to the date picker or
7881	 *					event - if triggered by focus
7882	 */
7883	_showDatepicker: function( input ) {
7884		input = input.target || input;
7885		if ( input.nodeName.toLowerCase() !== "input" ) { // find from button/image trigger
7886			input = $( "input", input.parentNode )[ 0 ];
7887		}
7888
7889		if ( $.datepicker._isDisabledDatepicker( input ) || $.datepicker._lastInput === input ) { // already here
7890			return;
7891		}
7892
7893		var inst, beforeShow, beforeShowSettings, isFixed,
7894			offset, showAnim, duration;
7895
7896		inst = $.datepicker._getInst( input );
7897		if ( $.datepicker._curInst && $.datepicker._curInst !== inst ) {
7898			$.datepicker._curInst.dpDiv.stop( true, true );
7899			if ( inst && $.datepicker._datepickerShowing ) {
7900				$.datepicker._hideDatepicker( $.datepicker._curInst.input[ 0 ] );
7901			}
7902		}
7903
7904		beforeShow = $.datepicker._get( inst, "beforeShow" );
7905		beforeShowSettings = beforeShow ? beforeShow.apply( input, [ input, inst ] ) : {};
7906		if ( beforeShowSettings === false ) {
7907			return;
7908		}
7909		datepicker_extendRemove( inst.settings, beforeShowSettings );
7910
7911		inst.lastVal = null;
7912		$.datepicker._lastInput = input;
7913		$.datepicker._setDateFromField( inst );
7914
7915		if ( $.datepicker._inDialog ) { // hide cursor
7916			input.value = "";
7917		}
7918		if ( !$.datepicker._pos ) { // position below input
7919			$.datepicker._pos = $.datepicker._findPos( input );
7920			$.datepicker._pos[ 1 ] += input.offsetHeight; // add the height
7921		}
7922
7923		isFixed = false;
7924		$( input ).parents().each( function() {
7925			isFixed |= $( this ).css( "position" ) === "fixed";
7926			return !isFixed;
7927		} );
7928
7929		offset = { left: $.datepicker._pos[ 0 ], top: $.datepicker._pos[ 1 ] };
7930		$.datepicker._pos = null;
7931
7932		//to avoid flashes on Firefox
7933		inst.dpDiv.empty();
7934
7935		// determine sizing offscreen
7936		inst.dpDiv.css( { position: "absolute", display: "block", top: "-1000px" } );
7937		$.datepicker._updateDatepicker( inst );
7938
7939		// fix width for dynamic number of date pickers
7940		// and adjust position before showing
7941		offset = $.datepicker._checkOffset( inst, offset, isFixed );
7942		inst.dpDiv.css( { position: ( $.datepicker._inDialog && $.blockUI ?
7943			"static" : ( isFixed ? "fixed" : "absolute" ) ), display: "none",
7944			left: offset.left + "px", top: offset.top + "px" } );
7945
7946		if ( !inst.inline ) {
7947			showAnim = $.datepicker._get( inst, "showAnim" );
7948			duration = $.datepicker._get( inst, "duration" );
7949			inst.dpDiv.css( "z-index", datepicker_getZindex( $( input ) ) + 1 );
7950			$.datepicker._datepickerShowing = true;
7951
7952			if ( $.effects && $.effects.effect[ showAnim ] ) {
7953				inst.dpDiv.show( showAnim, $.datepicker._get( inst, "showOptions" ), duration );
7954			} else {
7955				inst.dpDiv[ showAnim || "show" ]( showAnim ? duration : null );
7956			}
7957
7958			if ( $.datepicker._shouldFocusInput( inst ) ) {
7959				inst.input.trigger( "focus" );
7960			}
7961
7962			$.datepicker._curInst = inst;
7963		}
7964	},
7965
7966	/* Generate the date picker content. */
7967	_updateDatepicker: function( inst ) {
7968		this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
7969		datepicker_instActive = inst; // for delegate hover events
7970		inst.dpDiv.empty().append( this._generateHTML( inst ) );
7971		this._attachHandlers( inst );
7972
7973		var origyearshtml,
7974			numMonths = this._getNumberOfMonths( inst ),
7975			cols = numMonths[ 1 ],
7976			width = 17,
7977			activeCell = inst.dpDiv.find( "." + this._dayOverClass + " a" ),
7978			onUpdateDatepicker = $.datepicker._get( inst, "onUpdateDatepicker" );
7979
7980		if ( activeCell.length > 0 ) {
7981			datepicker_handleMouseover.apply( activeCell.get( 0 ) );
7982		}
7983
7984		inst.dpDiv.removeClass( "ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4" ).width( "" );
7985		if ( cols > 1 ) {
7986			inst.dpDiv.addClass( "ui-datepicker-multi-" + cols ).css( "width", ( width * cols ) + "em" );
7987		}
7988		inst.dpDiv[ ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ? "add" : "remove" ) +
7989			"Class" ]( "ui-datepicker-multi" );
7990		inst.dpDiv[ ( this._get( inst, "isRTL" ) ? "add" : "remove" ) +
7991			"Class" ]( "ui-datepicker-rtl" );
7992
7993		if ( inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {
7994			inst.input.trigger( "focus" );
7995		}
7996
7997		// Deffered render of the years select (to avoid flashes on Firefox)
7998		if ( inst.yearshtml ) {
7999			origyearshtml = inst.yearshtml;
8000			setTimeout( function() {
8001
8002				//assure that inst.yearshtml didn't change.
8003				if ( origyearshtml === inst.yearshtml && inst.yearshtml ) {
8004					inst.dpDiv.find( "select.ui-datepicker-year" ).first().replaceWith( inst.yearshtml );
8005				}
8006				origyearshtml = inst.yearshtml = null;
8007			}, 0 );
8008		}
8009
8010		if ( onUpdateDatepicker ) {
8011			onUpdateDatepicker.apply( ( inst.input ? inst.input[ 0 ] : null ), [ inst ] );
8012		}
8013	},
8014
8015	_shouldFocusInput: function( inst ) {
8016		return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" );
8017	},
8018
8019	/* Check positioning to remain on screen. */
8020	_checkOffset: function( inst, offset, isFixed ) {
8021		var dpWidth = inst.dpDiv.outerWidth(),
8022			dpHeight = inst.dpDiv.outerHeight(),
8023			inputWidth = inst.input ? inst.input.outerWidth() : 0,
8024			inputHeight = inst.input ? inst.input.outerHeight() : 0,
8025			viewWidth = document.documentElement.clientWidth + ( isFixed ? 0 : $( document ).scrollLeft() ),
8026			viewHeight = document.documentElement.clientHeight + ( isFixed ? 0 : $( document ).scrollTop() );
8027
8028		offset.left -= ( this._get( inst, "isRTL" ) ? ( dpWidth - inputWidth ) : 0 );
8029		offset.left -= ( isFixed && offset.left === inst.input.offset().left ) ? $( document ).scrollLeft() : 0;
8030		offset.top -= ( isFixed && offset.top === ( inst.input.offset().top + inputHeight ) ) ? $( document ).scrollTop() : 0;
8031
8032		// Now check if datepicker is showing outside window viewport - move to a better place if so.
8033		offset.left -= Math.min( offset.left, ( offset.left + dpWidth > viewWidth && viewWidth > dpWidth ) ?
8034			Math.abs( offset.left + dpWidth - viewWidth ) : 0 );
8035		offset.top -= Math.min( offset.top, ( offset.top + dpHeight > viewHeight && viewHeight > dpHeight ) ?
8036			Math.abs( dpHeight + inputHeight ) : 0 );
8037
8038		return offset;
8039	},
8040
8041	/* Find an object's position on the screen. */
8042	_findPos: function( obj ) {
8043		var position,
8044			inst = this._getInst( obj ),
8045			isRTL = this._get( inst, "isRTL" );
8046
8047		while ( obj && ( obj.type === "hidden" || obj.nodeType !== 1 || $.expr.pseudos.hidden( obj ) ) ) {
8048			obj = obj[ isRTL ? "previousSibling" : "nextSibling" ];
8049		}
8050
8051		position = $( obj ).offset();
8052		return [ position.left, position.top ];
8053	},
8054
8055	/* Hide the date picker from view.
8056	 * @param  input  element - the input field attached to the date picker
8057	 */
8058	_hideDatepicker: function( input ) {
8059		var showAnim, duration, postProcess, onClose,
8060			inst = this._curInst;
8061
8062		if ( !inst || ( input && inst !== $.data( input, "datepicker" ) ) ) {
8063			return;
8064		}
8065
8066		if ( this._datepickerShowing ) {
8067			showAnim = this._get( inst, "showAnim" );
8068			duration = this._get( inst, "duration" );
8069			postProcess = function() {
8070				$.datepicker._tidyDialog( inst );
8071			};
8072
8073			if ( $.effects && ( $.effects.effect[ showAnim ] ) ) {
8074				inst.dpDiv.hide( showAnim, $.datepicker._get( inst, "showOptions" ), duration, postProcess );
8075			} else {
8076				inst.dpDiv[ ( showAnim === "slideDown" ? "slideUp" :
8077					( showAnim === "fadeIn" ? "fadeOut" : "hide" ) ) ]( ( showAnim ? duration : null ), postProcess );
8078			}
8079
8080			if ( !showAnim ) {
8081				postProcess();
8082			}
8083			this._datepickerShowing = false;
8084
8085			onClose = this._get( inst, "onClose" );
8086			if ( onClose ) {
8087				onClose.apply( ( inst.input ? inst.input[ 0 ] : null ), [ ( inst.input ? inst.input.val() : "" ), inst ] );
8088			}
8089
8090			this._lastInput = null;
8091			if ( this._inDialog ) {
8092				this._dialogInput.css( { position: "absolute", left: "0", top: "-100px" } );
8093				if ( $.blockUI ) {
8094					$.unblockUI();
8095					$( "body" ).append( this.dpDiv );
8096				}
8097			}
8098			this._inDialog = false;
8099		}
8100	},
8101
8102	/* Tidy up after a dialog display. */
8103	_tidyDialog: function( inst ) {
8104		inst.dpDiv.removeClass( this._dialogClass ).off( ".ui-datepicker-calendar" );
8105	},
8106
8107	/* Close date picker if clicked elsewhere. */
8108	_checkExternalClick: function( event ) {
8109		if ( !$.datepicker._curInst ) {
8110			return;
8111		}
8112
8113		var $target = $( event.target ),
8114			inst = $.datepicker._getInst( $target[ 0 ] );
8115
8116		if ( ( ( $target[ 0 ].id !== $.datepicker._mainDivId &&
8117				$target.parents( "#" + $.datepicker._mainDivId ).length === 0 &&
8118				!$target.hasClass( $.datepicker.markerClassName ) &&
8119				!$target.closest( "." + $.datepicker._triggerClass ).length &&
8120				$.datepicker._datepickerShowing && !( $.datepicker._inDialog && $.blockUI ) ) ) ||
8121			( $target.hasClass( $.datepicker.markerClassName ) && $.datepicker._curInst !== inst ) ) {
8122				$.datepicker._hideDatepicker();
8123		}
8124	},
8125
8126	/* Adjust one of the date sub-fields. */
8127	_adjustDate: function( id, offset, period ) {
8128		var target = $( id ),
8129			inst = this._getInst( target[ 0 ] );
8130
8131		if ( this._isDisabledDatepicker( target[ 0 ] ) ) {
8132			return;
8133		}
8134		this._adjustInstDate( inst, offset, period );
8135		this._updateDatepicker( inst );
8136	},
8137
8138	/* Action for current link. */
8139	_gotoToday: function( id ) {
8140		var date,
8141			target = $( id ),
8142			inst = this._getInst( target[ 0 ] );
8143
8144		if ( this._get( inst, "gotoCurrent" ) && inst.currentDay ) {
8145			inst.selectedDay = inst.currentDay;
8146			inst.drawMonth = inst.selectedMonth = inst.currentMonth;
8147			inst.drawYear = inst.selectedYear = inst.currentYear;
8148		} else {
8149			date = new Date();
8150			inst.selectedDay = date.getDate();
8151			inst.drawMonth = inst.selectedMonth = date.getMonth();
8152			inst.drawYear = inst.selectedYear = date.getFullYear();
8153		}
8154		this._notifyChange( inst );
8155		this._adjustDate( target );
8156	},
8157
8158	/* Action for selecting a new month/year. */
8159	_selectMonthYear: function( id, select, period ) {
8160		var target = $( id ),
8161			inst = this._getInst( target[ 0 ] );
8162
8163		inst[ "selected" + ( period === "M" ? "Month" : "Year" ) ] =
8164		inst[ "draw" + ( period === "M" ? "Month" : "Year" ) ] =
8165			parseInt( select.options[ select.selectedIndex ].value, 10 );
8166
8167		this._notifyChange( inst );
8168		this._adjustDate( target );
8169	},
8170
8171	/* Action for selecting a day. */
8172	_selectDay: function( id, month, year, td ) {
8173		var inst,
8174			target = $( id );
8175
8176		if ( $( td ).hasClass( this._unselectableClass ) || this._isDisabledDatepicker( target[ 0 ] ) ) {
8177			return;
8178		}
8179
8180		inst = this._getInst( target[ 0 ] );
8181		inst.selectedDay = inst.currentDay = parseInt( $( "a", td ).attr( "data-date" ) );
8182		inst.selectedMonth = inst.currentMonth = month;
8183		inst.selectedYear = inst.currentYear = year;
8184		this._selectDate( id, this._formatDate( inst,
8185			inst.currentDay, inst.currentMonth, inst.currentYear ) );
8186	},
8187
8188	/* Erase the input field and hide the date picker. */
8189	_clearDate: function( id ) {
8190		var target = $( id );
8191		this._selectDate( target, "" );
8192	},
8193
8194	/* Update the input field with the selected date. */
8195	_selectDate: function( id, dateStr ) {
8196		var onSelect,
8197			target = $( id ),
8198			inst = this._getInst( target[ 0 ] );
8199
8200		dateStr = ( dateStr != null ? dateStr : this._formatDate( inst ) );
8201		if ( inst.input ) {
8202			inst.input.val( dateStr );
8203		}
8204		this._updateAlternate( inst );
8205
8206		onSelect = this._get( inst, "onSelect" );
8207		if ( onSelect ) {
8208			onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] );  // trigger custom callback
8209		} else if ( inst.input ) {
8210			inst.input.trigger( "change" ); // fire the change event
8211		}
8212
8213		if ( inst.inline ) {
8214			this._updateDatepicker( inst );
8215		} else {
8216			this._hideDatepicker();
8217			this._lastInput = inst.input[ 0 ];
8218			if ( typeof( inst.input[ 0 ] ) !== "object" ) {
8219				inst.input.trigger( "focus" ); // restore focus
8220			}
8221			this._lastInput = null;
8222		}
8223	},
8224
8225	/* Update any alternate field to synchronise with the main field. */
8226	_updateAlternate: function( inst ) {
8227		var altFormat, date, dateStr,
8228			altField = this._get( inst, "altField" );
8229
8230		if ( altField ) { // update alternate field too
8231			altFormat = this._get( inst, "altFormat" ) || this._get( inst, "dateFormat" );
8232			date = this._getDate( inst );
8233			dateStr = this.formatDate( altFormat, date, this._getFormatConfig( inst ) );
8234			$( document ).find( altField ).val( dateStr );
8235		}
8236	},
8237
8238	/* Set as beforeShowDay function to prevent selection of weekends.
8239	 * @param  date  Date - the date to customise
8240	 * @return [boolean, string] - is this date selectable?, what is its CSS class?
8241	 */
8242	noWeekends: function( date ) {
8243		var day = date.getDay();
8244		return [ ( day > 0 && day < 6 ), "" ];
8245	},
8246
8247	/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
8248	 * @param  date  Date - the date to get the week for
8249	 * @return  number - the number of the week within the year that contains this date
8250	 */
8251	iso8601Week: function( date ) {
8252		var time,
8253			checkDate = new Date( date.getTime() );
8254
8255		// Find Thursday of this week starting on Monday
8256		checkDate.setDate( checkDate.getDate() + 4 - ( checkDate.getDay() || 7 ) );
8257
8258		time = checkDate.getTime();
8259		checkDate.setMonth( 0 ); // Compare with Jan 1
8260		checkDate.setDate( 1 );
8261		return Math.floor( Math.round( ( time - checkDate ) / 86400000 ) / 7 ) + 1;
8262	},
8263
8264	/* Parse a string value into a date object.
8265	 * See formatDate below for the possible formats.
8266	 *
8267	 * @param  format string - the expected format of the date
8268	 * @param  value string - the date in the above format
8269	 * @param  settings Object - attributes include:
8270	 *					shortYearCutoff  number - the cutoff year for determining the century (optional)
8271	 *					dayNamesShort	string[7] - abbreviated names of the days from Sunday (optional)
8272	 *					dayNames		string[7] - names of the days from Sunday (optional)
8273	 *					monthNamesShort string[12] - abbreviated names of the months (optional)
8274	 *					monthNames		string[12] - names of the months (optional)
8275	 * @return  Date - the extracted date value or null if value is blank
8276	 */
8277	parseDate: function( format, value, settings ) {
8278		if ( format == null || value == null ) {
8279			throw "Invalid arguments";
8280		}
8281
8282		value = ( typeof value === "object" ? value.toString() : value + "" );
8283		if ( value === "" ) {
8284			return null;
8285		}
8286
8287		var iFormat, dim, extra,
8288			iValue = 0,
8289			shortYearCutoffTemp = ( settings ? settings.shortYearCutoff : null ) || this._defaults.shortYearCutoff,
8290			shortYearCutoff = ( typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp :
8291				new Date().getFullYear() % 100 + parseInt( shortYearCutoffTemp, 10 ) ),
8292			dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort,
8293			dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames,
8294			monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort,
8295			monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames,
8296			year = -1,
8297			month = -1,
8298			day = -1,
8299			doy = -1,
8300			literal = false,
8301			date,
8302
8303			// Check whether a format character is doubled
8304			lookAhead = function( match ) {
8305				var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
8306				if ( matches ) {
8307					iFormat++;
8308				}
8309				return matches;
8310			},
8311
8312			// Extract a number from the string value
8313			getNumber = function( match ) {
8314				var isDoubled = lookAhead( match ),
8315					size = ( match === "@" ? 14 : ( match === "!" ? 20 :
8316					( match === "y" && isDoubled ? 4 : ( match === "o" ? 3 : 2 ) ) ) ),
8317					minSize = ( match === "y" ? size : 1 ),
8318					digits = new RegExp( "^\\d{" + minSize + "," + size + "}" ),
8319					num = value.substring( iValue ).match( digits );
8320				if ( !num ) {
8321					throw "Missing number at position " + iValue;
8322				}
8323				iValue += num[ 0 ].length;
8324				return parseInt( num[ 0 ], 10 );
8325			},
8326
8327			// Extract a name from the string value and convert to an index
8328			getName = function( match, shortNames, longNames ) {
8329				var index = -1,
8330					names = $.map( lookAhead( match ) ? longNames : shortNames, function( v, k ) {
8331						return [ [ k, v ] ];
8332					} ).sort( function( a, b ) {
8333						return -( a[ 1 ].length - b[ 1 ].length );
8334					} );
8335
8336				$.each( names, function( i, pair ) {
8337					var name = pair[ 1 ];
8338					if ( value.substr( iValue, name.length ).toLowerCase() === name.toLowerCase() ) {
8339						index = pair[ 0 ];
8340						iValue += name.length;
8341						return false;
8342					}
8343				} );
8344				if ( index !== -1 ) {
8345					return index + 1;
8346				} else {
8347					throw "Unknown name at position " + iValue;
8348				}
8349			},
8350
8351			// Confirm that a literal character matches the string value
8352			checkLiteral = function() {
8353				if ( value.charAt( iValue ) !== format.charAt( iFormat ) ) {
8354					throw "Unexpected literal at position " + iValue;
8355				}
8356				iValue++;
8357			};
8358
8359		for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
8360			if ( literal ) {
8361				if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
8362					literal = false;
8363				} else {
8364					checkLiteral();
8365				}
8366			} else {
8367				switch ( format.charAt( iFormat ) ) {
8368					case "d":
8369						day = getNumber( "d" );
8370						break;
8371					case "D":
8372						getName( "D", dayNamesShort, dayNames );
8373						break;
8374					case "o":
8375						doy = getNumber( "o" );
8376						break;
8377					case "m":
8378						month = getNumber( "m" );
8379						break;
8380					case "M":
8381						month = getName( "M", monthNamesShort, monthNames );
8382						break;
8383					case "y":
8384						year = getNumber( "y" );
8385						break;
8386					case "@":
8387						date = new Date( getNumber( "@" ) );
8388						year = date.getFullYear();
8389						month = date.getMonth() + 1;
8390						day = date.getDate();
8391						break;
8392					case "!":
8393						date = new Date( ( getNumber( "!" ) - this._ticksTo1970 ) / 10000 );
8394						year = date.getFullYear();
8395						month = date.getMonth() + 1;
8396						day = date.getDate();
8397						break;
8398					case "'":
8399						if ( lookAhead( "'" ) ) {
8400							checkLiteral();
8401						} else {
8402							literal = true;
8403						}
8404						break;
8405					default:
8406						checkLiteral();
8407				}
8408			}
8409		}
8410
8411		if ( iValue < value.length ) {
8412			extra = value.substr( iValue );
8413			if ( !/^\s+/.test( extra ) ) {
8414				throw "Extra/unparsed characters found in date: " + extra;
8415			}
8416		}
8417
8418		if ( year === -1 ) {
8419			year = new Date().getFullYear();
8420		} else if ( year < 100 ) {
8421			year += new Date().getFullYear() - new Date().getFullYear() % 100 +
8422				( year <= shortYearCutoff ? 0 : -100 );
8423		}
8424
8425		if ( doy > -1 ) {
8426			month = 1;
8427			day = doy;
8428			do {
8429				dim = this._getDaysInMonth( year, month - 1 );
8430				if ( day <= dim ) {
8431					break;
8432				}
8433				month++;
8434				day -= dim;
8435			} while ( true );
8436		}
8437
8438		date = this._daylightSavingAdjust( new Date( year, month - 1, day ) );
8439		if ( date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day ) {
8440			throw "Invalid date"; // E.g. 31/02/00
8441		}
8442		return date;
8443	},
8444
8445	/* Standard date formats. */
8446	ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601)
8447	COOKIE: "D, dd M yy",
8448	ISO_8601: "yy-mm-dd",
8449	RFC_822: "D, d M y",
8450	RFC_850: "DD, dd-M-y",
8451	RFC_1036: "D, d M y",
8452	RFC_1123: "D, d M yy",
8453	RFC_2822: "D, d M yy",
8454	RSS: "D, d M y", // RFC 822
8455	TICKS: "!",
8456	TIMESTAMP: "@",
8457	W3C: "yy-mm-dd", // ISO 8601
8458
8459	_ticksTo1970: ( ( ( 1970 - 1 ) * 365 + Math.floor( 1970 / 4 ) - Math.floor( 1970 / 100 ) +
8460		Math.floor( 1970 / 400 ) ) * 24 * 60 * 60 * 10000000 ),
8461
8462	/* Format a date object into a string value.
8463	 * The format can be combinations of the following:
8464	 * d  - day of month (no leading zero)
8465	 * dd - day of month (two digit)
8466	 * o  - day of year (no leading zeros)
8467	 * oo - day of year (three digit)
8468	 * D  - day name short
8469	 * DD - day name long
8470	 * m  - month of year (no leading zero)
8471	 * mm - month of year (two digit)
8472	 * M  - month name short
8473	 * MM - month name long
8474	 * y  - year (two digit)
8475	 * yy - year (four digit)
8476	 * @ - Unix timestamp (ms since 01/01/1970)
8477	 * ! - Windows ticks (100ns since 01/01/0001)
8478	 * "..." - literal text
8479	 * '' - single quote
8480	 *
8481	 * @param  format string - the desired format of the date
8482	 * @param  date Date - the date value to format
8483	 * @param  settings Object - attributes include:
8484	 *					dayNamesShort	string[7] - abbreviated names of the days from Sunday (optional)
8485	 *					dayNames		string[7] - names of the days from Sunday (optional)
8486	 *					monthNamesShort string[12] - abbreviated names of the months (optional)
8487	 *					monthNames		string[12] - names of the months (optional)
8488	 * @return  string - the date in the above format
8489	 */
8490	formatDate: function( format, date, settings ) {
8491		if ( !date ) {
8492			return "";
8493		}
8494
8495		var iFormat,
8496			dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort,
8497			dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames,
8498			monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort,
8499			monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames,
8500
8501			// Check whether a format character is doubled
8502			lookAhead = function( match ) {
8503				var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
8504				if ( matches ) {
8505					iFormat++;
8506				}
8507				return matches;
8508			},
8509
8510			// Format a number, with leading zero if necessary
8511			formatNumber = function( match, value, len ) {
8512				var num = "" + value;
8513				if ( lookAhead( match ) ) {
8514					while ( num.length < len ) {
8515						num = "0" + num;
8516					}
8517				}
8518				return num;
8519			},
8520
8521			// Format a name, short or long as requested
8522			formatName = function( match, value, shortNames, longNames ) {
8523				return ( lookAhead( match ) ? longNames[ value ] : shortNames[ value ] );
8524			},
8525			output = "",
8526			literal = false;
8527
8528		if ( date ) {
8529			for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
8530				if ( literal ) {
8531					if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
8532						literal = false;
8533					} else {
8534						output += format.charAt( iFormat );
8535					}
8536				} else {
8537					switch ( format.charAt( iFormat ) ) {
8538						case "d":
8539							output += formatNumber( "d", date.getDate(), 2 );
8540							break;
8541						case "D":
8542							output += formatName( "D", date.getDay(), dayNamesShort, dayNames );
8543							break;
8544						case "o":
8545							output += formatNumber( "o",
8546								Math.round( ( new Date( date.getFullYear(), date.getMonth(), date.getDate() ).getTime() - new Date( date.getFullYear(), 0, 0 ).getTime() ) / 86400000 ), 3 );
8547							break;
8548						case "m":
8549							output += formatNumber( "m", date.getMonth() + 1, 2 );
8550							break;
8551						case "M":
8552							output += formatName( "M", date.getMonth(), monthNamesShort, monthNames );
8553							break;
8554						case "y":
8555							output += ( lookAhead( "y" ) ? date.getFullYear() :
8556								( date.getFullYear() % 100 < 10 ? "0" : "" ) + date.getFullYear() % 100 );
8557							break;
8558						case "@":
8559							output += date.getTime();
8560							break;
8561						case "!":
8562							output += date.getTime() * 10000 + this._ticksTo1970;
8563							break;
8564						case "'":
8565							if ( lookAhead( "'" ) ) {
8566								output += "'";
8567							} else {
8568								literal = true;
8569							}
8570							break;
8571						default:
8572							output += format.charAt( iFormat );
8573					}
8574				}
8575			}
8576		}
8577		return output;
8578	},
8579
8580	/* Extract all possible characters from the date format. */
8581	_possibleChars: function( format ) {
8582		var iFormat,
8583			chars = "",
8584			literal = false,
8585
8586			// Check whether a format character is doubled
8587			lookAhead = function( match ) {
8588				var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
8589				if ( matches ) {
8590					iFormat++;
8591				}
8592				return matches;
8593			};
8594
8595		for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
8596			if ( literal ) {
8597				if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
8598					literal = false;
8599				} else {
8600					chars += format.charAt( iFormat );
8601				}
8602			} else {
8603				switch ( format.charAt( iFormat ) ) {
8604					case "d": case "m": case "y": case "@":
8605						chars += "0123456789";
8606						break;
8607					case "D": case "M":
8608						return null; // Accept anything
8609					case "'":
8610						if ( lookAhead( "'" ) ) {
8611							chars += "'";
8612						} else {
8613							literal = true;
8614						}
8615						break;
8616					default:
8617						chars += format.charAt( iFormat );
8618				}
8619			}
8620		}
8621		return chars;
8622	},
8623
8624	/* Get a setting value, defaulting if necessary. */
8625	_get: function( inst, name ) {
8626		return inst.settings[ name ] !== undefined ?
8627			inst.settings[ name ] : this._defaults[ name ];
8628	},
8629
8630	/* Parse existing date and initialise date picker. */
8631	_setDateFromField: function( inst, noDefault ) {
8632		if ( inst.input.val() === inst.lastVal ) {
8633			return;
8634		}
8635
8636		var dateFormat = this._get( inst, "dateFormat" ),
8637			dates = inst.lastVal = inst.input ? inst.input.val() : null,
8638			defaultDate = this._getDefaultDate( inst ),
8639			date = defaultDate,
8640			settings = this._getFormatConfig( inst );
8641
8642		try {
8643			date = this.parseDate( dateFormat, dates, settings ) || defaultDate;
8644		} catch ( event ) {
8645			dates = ( noDefault ? "" : dates );
8646		}
8647		inst.selectedDay = date.getDate();
8648		inst.drawMonth = inst.selectedMonth = date.getMonth();
8649		inst.drawYear = inst.selectedYear = date.getFullYear();
8650		inst.currentDay = ( dates ? date.getDate() : 0 );
8651		inst.currentMonth = ( dates ? date.getMonth() : 0 );
8652		inst.currentYear = ( dates ? date.getFullYear() : 0 );
8653		this._adjustInstDate( inst );
8654	},
8655
8656	/* Retrieve the default date shown on opening. */
8657	_getDefaultDate: function( inst ) {
8658		return this._restrictMinMax( inst,
8659			this._determineDate( inst, this._get( inst, "defaultDate" ), new Date() ) );
8660	},
8661
8662	/* A date may be specified as an exact value or a relative one. */
8663	_determineDate: function( inst, date, defaultDate ) {
8664		var offsetNumeric = function( offset ) {
8665				var date = new Date();
8666				date.setDate( date.getDate() + offset );
8667				return date;
8668			},
8669			offsetString = function( offset ) {
8670				try {
8671					return $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ),
8672						offset, $.datepicker._getFormatConfig( inst ) );
8673				} catch ( e ) {
8674
8675					// Ignore
8676				}
8677
8678				var date = ( offset.toLowerCase().match( /^c/ ) ?
8679					$.datepicker._getDate( inst ) : null ) || new Date(),
8680					year = date.getFullYear(),
8681					month = date.getMonth(),
8682					day = date.getDate(),
8683					pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,
8684					matches = pattern.exec( offset );
8685
8686				while ( matches ) {
8687					switch ( matches[ 2 ] || "d" ) {
8688						case "d" : case "D" :
8689							day += parseInt( matches[ 1 ], 10 ); break;
8690						case "w" : case "W" :
8691							day += parseInt( matches[ 1 ], 10 ) * 7; break;
8692						case "m" : case "M" :
8693							month += parseInt( matches[ 1 ], 10 );
8694							day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) );
8695							break;
8696						case "y": case "Y" :
8697							year += parseInt( matches[ 1 ], 10 );
8698							day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) );
8699							break;
8700					}
8701					matches = pattern.exec( offset );
8702				}
8703				return new Date( year, month, day );
8704			},
8705			newDate = ( date == null || date === "" ? defaultDate : ( typeof date === "string" ? offsetString( date ) :
8706				( typeof date === "number" ? ( isNaN( date ) ? defaultDate : offsetNumeric( date ) ) : new Date( date.getTime() ) ) ) );
8707
8708		newDate = ( newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate );
8709		if ( newDate ) {
8710			newDate.setHours( 0 );
8711			newDate.setMinutes( 0 );
8712			newDate.setSeconds( 0 );
8713			newDate.setMilliseconds( 0 );
8714		}
8715		return this._daylightSavingAdjust( newDate );
8716	},
8717
8718	/* Handle switch to/from daylight saving.
8719	 * Hours may be non-zero on daylight saving cut-over:
8720	 * > 12 when midnight changeover, but then cannot generate
8721	 * midnight datetime, so jump to 1AM, otherwise reset.
8722	 * @param  date  (Date) the date to check
8723	 * @return  (Date) the corrected date
8724	 */
8725	_daylightSavingAdjust: function( date ) {
8726		if ( !date ) {
8727			return null;
8728		}
8729		date.setHours( date.getHours() > 12 ? date.getHours() + 2 : 0 );
8730		return date;
8731	},
8732
8733	/* Set the date(s) directly. */
8734	_setDate: function( inst, date, noChange ) {
8735		var clear = !date,
8736			origMonth = inst.selectedMonth,
8737			origYear = inst.selectedYear,
8738			newDate = this._restrictMinMax( inst, this._determineDate( inst, date, new Date() ) );
8739
8740		inst.selectedDay = inst.currentDay = newDate.getDate();
8741		inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
8742		inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
8743		if ( ( origMonth !== inst.selectedMonth || origYear !== inst.selectedYear ) && !noChange ) {
8744			this._notifyChange( inst );
8745		}
8746		this._adjustInstDate( inst );
8747		if ( inst.input ) {
8748			inst.input.val( clear ? "" : this._formatDate( inst ) );
8749		}
8750	},
8751
8752	/* Retrieve the date(s) directly. */
8753	_getDate: function( inst ) {
8754		var startDate = ( !inst.currentYear || ( inst.input && inst.input.val() === "" ) ? null :
8755			this._daylightSavingAdjust( new Date(
8756			inst.currentYear, inst.currentMonth, inst.currentDay ) ) );
8757			return startDate;
8758	},
8759
8760	/* Attach the onxxx handlers.  These are declared statically so
8761	 * they work with static code transformers like Caja.
8762	 */
8763	_attachHandlers: function( inst ) {
8764		var stepMonths = this._get( inst, "stepMonths" ),
8765			id = "#" + inst.id.replace( /\\\\/g, "\\" );
8766		inst.dpDiv.find( "[data-handler]" ).map( function() {
8767			var handler = {
8768				prev: function() {
8769					$.datepicker._adjustDate( id, -stepMonths, "M" );
8770				},
8771				next: function() {
8772					$.datepicker._adjustDate( id, +stepMonths, "M" );
8773				},
8774				hide: function() {
8775					$.datepicker._hideDatepicker();
8776				},
8777				today: function() {
8778					$.datepicker._gotoToday( id );
8779				},
8780				selectDay: function() {
8781					$.datepicker._selectDay( id, +this.getAttribute( "data-month" ), +this.getAttribute( "data-year" ), this );
8782					return false;
8783				},
8784				selectMonth: function() {
8785					$.datepicker._selectMonthYear( id, this, "M" );
8786					return false;
8787				},
8788				selectYear: function() {
8789					$.datepicker._selectMonthYear( id, this, "Y" );
8790					return false;
8791				}
8792			};
8793			$( this ).on( this.getAttribute( "data-event" ), handler[ this.getAttribute( "data-handler" ) ] );
8794		} );
8795	},
8796
8797	/* Generate the HTML for the current state of the date picker. */
8798	_generateHTML: function( inst ) {
8799		var maxDraw, prevText, prev, nextText, next, currentText, gotoDate,
8800			controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,
8801			monthNames, monthNamesShort, beforeShowDay, showOtherMonths,
8802			selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,
8803			cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,
8804			printDate, dRow, tbody, daySettings, otherMonth, unselectable,
8805			tempDate = new Date(),
8806			today = this._daylightSavingAdjust(
8807				new Date( tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate() ) ), // clear time
8808			isRTL = this._get( inst, "isRTL" ),
8809			showButtonPanel = this._get( inst, "showButtonPanel" ),
8810			hideIfNoPrevNext = this._get( inst, "hideIfNoPrevNext" ),
8811			navigationAsDateFormat = this._get( inst, "navigationAsDateFormat" ),
8812			numMonths = this._getNumberOfMonths( inst ),
8813			showCurrentAtPos = this._get( inst, "showCurrentAtPos" ),
8814			stepMonths = this._get( inst, "stepMonths" ),
8815			isMultiMonth = ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ),
8816			currentDate = this._daylightSavingAdjust( ( !inst.currentDay ? new Date( 9999, 9, 9 ) :
8817				new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) ),
8818			minDate = this._getMinMaxDate( inst, "min" ),
8819			maxDate = this._getMinMaxDate( inst, "max" ),
8820			drawMonth = inst.drawMonth - showCurrentAtPos,
8821			drawYear = inst.drawYear;
8822
8823		if ( drawMonth < 0 ) {
8824			drawMonth += 12;
8825			drawYear--;
8826		}
8827		if ( maxDate ) {
8828			maxDraw = this._daylightSavingAdjust( new Date( maxDate.getFullYear(),
8829				maxDate.getMonth() - ( numMonths[ 0 ] * numMonths[ 1 ] ) + 1, maxDate.getDate() ) );
8830			maxDraw = ( minDate && maxDraw < minDate ? minDate : maxDraw );
8831			while ( this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 ) ) > maxDraw ) {
8832				drawMonth--;
8833				if ( drawMonth < 0 ) {
8834					drawMonth = 11;
8835					drawYear--;
8836				}
8837			}
8838		}
8839		inst.drawMonth = drawMonth;
8840		inst.drawYear = drawYear;
8841
8842		prevText = this._get( inst, "prevText" );
8843		prevText = ( !navigationAsDateFormat ? prevText : this.formatDate( prevText,
8844			this._daylightSavingAdjust( new Date( drawYear, drawMonth - stepMonths, 1 ) ),
8845			this._getFormatConfig( inst ) ) );
8846
8847		if ( this._canAdjustMonth( inst, -1, drawYear, drawMonth ) ) {
8848			prev = $( "<a>" )
8849				.attr( {
8850					"class": "ui-datepicker-prev ui-corner-all",
8851					"data-handler": "prev",
8852					"data-event": "click",
8853					title: prevText
8854				} )
8855				.append(
8856					$( "<span>" )
8857						.addClass( "ui-icon ui-icon-circle-triangle-" +
8858							( isRTL ? "e" : "w" ) )
8859						.text( prevText )
8860				)[ 0 ].outerHTML;
8861		} else if ( hideIfNoPrevNext ) {
8862			prev = "";
8863		} else {
8864			prev = $( "<a>" )
8865				.attr( {
8866					"class": "ui-datepicker-prev ui-corner-all ui-state-disabled",
8867					title: prevText
8868				} )
8869				.append(
8870					$( "<span>" )
8871						.addClass( "ui-icon ui-icon-circle-triangle-" +
8872							( isRTL ? "e" : "w" ) )
8873						.text( prevText )
8874				)[ 0 ].outerHTML;
8875		}
8876
8877		nextText = this._get( inst, "nextText" );
8878		nextText = ( !navigationAsDateFormat ? nextText : this.formatDate( nextText,
8879			this._daylightSavingAdjust( new Date( drawYear, drawMonth + stepMonths, 1 ) ),
8880			this._getFormatConfig( inst ) ) );
8881
8882		if ( this._canAdjustMonth( inst, +1, drawYear, drawMonth ) ) {
8883			next = $( "<a>" )
8884				.attr( {
8885					"class": "ui-datepicker-next ui-corner-all",
8886					"data-handler": "next",
8887					"data-event": "click",
8888					title: nextText
8889				} )
8890				.append(
8891					$( "<span>" )
8892						.addClass( "ui-icon ui-icon-circle-triangle-" +
8893							( isRTL ? "w" : "e" ) )
8894						.text( nextText )
8895				)[ 0 ].outerHTML;
8896		} else if ( hideIfNoPrevNext ) {
8897			next = "";
8898		} else {
8899			next = $( "<a>" )
8900				.attr( {
8901					"class": "ui-datepicker-next ui-corner-all ui-state-disabled",
8902					title: nextText
8903				} )
8904				.append(
8905					$( "<span>" )
8906						.attr( "class", "ui-icon ui-icon-circle-triangle-" +
8907							( isRTL ? "w" : "e" ) )
8908						.text( nextText )
8909				)[ 0 ].outerHTML;
8910		}
8911
8912		currentText = this._get( inst, "currentText" );
8913		gotoDate = ( this._get( inst, "gotoCurrent" ) && inst.currentDay ? currentDate : today );
8914		currentText = ( !navigationAsDateFormat ? currentText :
8915			this.formatDate( currentText, gotoDate, this._getFormatConfig( inst ) ) );
8916
8917		controls = "";
8918		if ( !inst.inline ) {
8919			controls = $( "<button>" )
8920				.attr( {
8921					type: "button",
8922					"class": "ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all",
8923					"data-handler": "hide",
8924					"data-event": "click"
8925				} )
8926				.text( this._get( inst, "closeText" ) )[ 0 ].outerHTML;
8927		}
8928
8929		buttonPanel = "";
8930		if ( showButtonPanel ) {
8931			buttonPanel = $( "<div class='ui-datepicker-buttonpane ui-widget-content'>" )
8932				.append( isRTL ? controls : "" )
8933				.append( this._isInRange( inst, gotoDate ) ?
8934					$( "<button>" )
8935						.attr( {
8936							type: "button",
8937							"class": "ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all",
8938							"data-handler": "today",
8939							"data-event": "click"
8940						} )
8941						.text( currentText ) :
8942					"" )
8943				.append( isRTL ? "" : controls )[ 0 ].outerHTML;
8944		}
8945
8946		firstDay = parseInt( this._get( inst, "firstDay" ), 10 );
8947		firstDay = ( isNaN( firstDay ) ? 0 : firstDay );
8948
8949		showWeek = this._get( inst, "showWeek" );
8950		dayNames = this._get( inst, "dayNames" );
8951		dayNamesMin = this._get( inst, "dayNamesMin" );
8952		monthNames = this._get( inst, "monthNames" );
8953		monthNamesShort = this._get( inst, "monthNamesShort" );
8954		beforeShowDay = this._get( inst, "beforeShowDay" );
8955		showOtherMonths = this._get( inst, "showOtherMonths" );
8956		selectOtherMonths = this._get( inst, "selectOtherMonths" );
8957		defaultDate = this._getDefaultDate( inst );
8958		html = "";
8959
8960		for ( row = 0; row < numMonths[ 0 ]; row++ ) {
8961			group = "";
8962			this.maxRows = 4;
8963			for ( col = 0; col < numMonths[ 1 ]; col++ ) {
8964				selectedDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, inst.selectedDay ) );
8965				cornerClass = " ui-corner-all";
8966				calender = "";
8967				if ( isMultiMonth ) {
8968					calender += "<div class='ui-datepicker-group";
8969					if ( numMonths[ 1 ] > 1 ) {
8970						switch ( col ) {
8971							case 0: calender += " ui-datepicker-group-first";
8972								cornerClass = " ui-corner-" + ( isRTL ? "right" : "left" ); break;
8973							case numMonths[ 1 ] - 1: calender += " ui-datepicker-group-last";
8974								cornerClass = " ui-corner-" + ( isRTL ? "left" : "right" ); break;
8975							default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break;
8976						}
8977					}
8978					calender += "'>";
8979				}
8980				calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" +
8981					( /all|left/.test( cornerClass ) && row === 0 ? ( isRTL ? next : prev ) : "" ) +
8982					( /all|right/.test( cornerClass ) && row === 0 ? ( isRTL ? prev : next ) : "" ) +
8983					this._generateMonthYearHeader( inst, drawMonth, drawYear, minDate, maxDate,
8984					row > 0 || col > 0, monthNames, monthNamesShort ) + // draw month headers
8985					"</div><table class='ui-datepicker-calendar'><thead>" +
8986					"<tr>";
8987				thead = ( showWeek ? "<th class='ui-datepicker-week-col'>" + this._get( inst, "weekHeader" ) + "</th>" : "" );
8988				for ( dow = 0; dow < 7; dow++ ) { // days of the week
8989					day = ( dow + firstDay ) % 7;
8990					thead += "<th scope='col'" + ( ( dow + firstDay + 6 ) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "" ) + ">" +
8991						"<span title='" + dayNames[ day ] + "'>" + dayNamesMin[ day ] + "</span></th>";
8992				}
8993				calender += thead + "</tr></thead><tbody>";
8994				daysInMonth = this._getDaysInMonth( drawYear, drawMonth );
8995				if ( drawYear === inst.selectedYear && drawMonth === inst.selectedMonth ) {
8996					inst.selectedDay = Math.min( inst.selectedDay, daysInMonth );
8997				}
8998				leadDays = ( this._getFirstDayOfMonth( drawYear, drawMonth ) - firstDay + 7 ) % 7;
8999				curRows = Math.ceil( ( leadDays + daysInMonth ) / 7 ); // calculate the number of rows to generate
9000				numRows = ( isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows ); //If multiple months, use the higher number of rows (see #7043)
9001				this.maxRows = numRows;
9002				printDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 - leadDays ) );
9003				for ( dRow = 0; dRow < numRows; dRow++ ) { // create date picker rows
9004					calender += "<tr>";
9005					tbody = ( !showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
9006						this._get( inst, "calculateWeek" )( printDate ) + "</td>" );
9007					for ( dow = 0; dow < 7; dow++ ) { // create date picker days
9008						daySettings = ( beforeShowDay ?
9009							beforeShowDay.apply( ( inst.input ? inst.input[ 0 ] : null ), [ printDate ] ) : [ true, "" ] );
9010						otherMonth = ( printDate.getMonth() !== drawMonth );
9011						unselectable = ( otherMonth && !selectOtherMonths ) || !daySettings[ 0 ] ||
9012							( minDate && printDate < minDate ) || ( maxDate && printDate > maxDate );
9013						tbody += "<td class='" +
9014							( ( dow + firstDay + 6 ) % 7 >= 5 ? " ui-datepicker-week-end" : "" ) + // highlight weekends
9015							( otherMonth ? " ui-datepicker-other-month" : "" ) + // highlight days from other months
9016							( ( printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent ) || // user pressed key
9017							( defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime() ) ?
9018
9019							// or defaultDate is current printedDate and defaultDate is selectedDate
9020							" " + this._dayOverClass : "" ) + // highlight selected day
9021							( unselectable ? " " + this._unselectableClass + " ui-state-disabled" : "" ) +  // highlight unselectable days
9022							( otherMonth && !showOtherMonths ? "" : " " + daySettings[ 1 ] + // highlight custom dates
9023							( printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "" ) + // highlight selected day
9024							( printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "" ) ) + "'" + // highlight today (if different)
9025							( ( !otherMonth || showOtherMonths ) && daySettings[ 2 ] ? " title='" + daySettings[ 2 ].replace( /'/g, "&#39;" ) + "'" : "" ) + // cell title
9026							( unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'" ) + ">" + // actions
9027							( otherMonth && !showOtherMonths ? "&#xa0;" : // display for other months
9028							( unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" +
9029							( printDate.getTime() === today.getTime() ? " ui-state-highlight" : "" ) +
9030							( printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "" ) + // highlight selected day
9031							( otherMonth ? " ui-priority-secondary" : "" ) + // distinguish dates from other months
9032							"' href='#' aria-current='" + ( printDate.getTime() === currentDate.getTime() ? "true" : "false" ) + // mark date as selected for screen reader
9033							"' data-date='" + printDate.getDate() + // store date as data
9034							"'>" + printDate.getDate() + "</a>" ) ) + "</td>"; // display selectable date
9035						printDate.setDate( printDate.getDate() + 1 );
9036						printDate = this._daylightSavingAdjust( printDate );
9037					}
9038					calender += tbody + "</tr>";
9039				}
9040				drawMonth++;
9041				if ( drawMonth > 11 ) {
9042					drawMonth = 0;
9043					drawYear++;
9044				}
9045				calender += "</tbody></table>" + ( isMultiMonth ? "</div>" +
9046							( ( numMonths[ 0 ] > 0 && col === numMonths[ 1 ] - 1 ) ? "<div class='ui-datepicker-row-break'></div>" : "" ) : "" );
9047				group += calender;
9048			}
9049			html += group;
9050		}
9051		html += buttonPanel;
9052		inst._keyEvent = false;
9053		return html;
9054	},
9055
9056	/* Generate the month and year header. */
9057	_generateMonthYearHeader: function( inst, drawMonth, drawYear, minDate, maxDate,
9058			secondary, monthNames, monthNamesShort ) {
9059
9060		var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,
9061			changeMonth = this._get( inst, "changeMonth" ),
9062			changeYear = this._get( inst, "changeYear" ),
9063			showMonthAfterYear = this._get( inst, "showMonthAfterYear" ),
9064			selectMonthLabel = this._get( inst, "selectMonthLabel" ),
9065			selectYearLabel = this._get( inst, "selectYearLabel" ),
9066			html = "<div class='ui-datepicker-title'>",
9067			monthHtml = "";
9068
9069		// Month selection
9070		if ( secondary || !changeMonth ) {
9071			monthHtml += "<span class='ui-datepicker-month'>" + monthNames[ drawMonth ] + "</span>";
9072		} else {
9073			inMinYear = ( minDate && minDate.getFullYear() === drawYear );
9074			inMaxYear = ( maxDate && maxDate.getFullYear() === drawYear );
9075			monthHtml += "<select class='ui-datepicker-month' aria-label='" + selectMonthLabel + "' data-handler='selectMonth' data-event='change'>";
9076			for ( month = 0; month < 12; month++ ) {
9077				if ( ( !inMinYear || month >= minDate.getMonth() ) && ( !inMaxYear || month <= maxDate.getMonth() ) ) {
9078					monthHtml += "<option value='" + month + "'" +
9079						( month === drawMonth ? " selected='selected'" : "" ) +
9080						">" + monthNamesShort[ month ] + "</option>";
9081				}
9082			}
9083			monthHtml += "</select>";
9084		}
9085
9086		if ( !showMonthAfterYear ) {
9087			html += monthHtml + ( secondary || !( changeMonth && changeYear ) ? "&#xa0;" : "" );
9088		}
9089
9090		// Year selection
9091		if ( !inst.yearshtml ) {
9092			inst.yearshtml = "";
9093			if ( secondary || !changeYear ) {
9094				html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
9095			} else {
9096
9097				// determine range of years to display
9098				years = this._get( inst, "yearRange" ).split( ":" );
9099				thisYear = new Date().getFullYear();
9100				determineYear = function( value ) {
9101					var year = ( value.match( /c[+\-].*/ ) ? drawYear + parseInt( value.substring( 1 ), 10 ) :
9102						( value.match( /[+\-].*/ ) ? thisYear + parseInt( value, 10 ) :
9103						parseInt( value, 10 ) ) );
9104					return ( isNaN( year ) ? thisYear : year );
9105				};
9106				year = determineYear( years[ 0 ] );
9107				endYear = Math.max( year, determineYear( years[ 1 ] || "" ) );
9108				year = ( minDate ? Math.max( year, minDate.getFullYear() ) : year );
9109				endYear = ( maxDate ? Math.min( endYear, maxDate.getFullYear() ) : endYear );
9110				inst.yearshtml += "<select class='ui-datepicker-year' aria-label='" + selectYearLabel + "' data-handler='selectYear' data-event='change'>";
9111				for ( ; year <= endYear; year++ ) {
9112					inst.yearshtml += "<option value='" + year + "'" +
9113						( year === drawYear ? " selected='selected'" : "" ) +
9114						">" + year + "</option>";
9115				}
9116				inst.yearshtml += "</select>";
9117
9118				html += inst.yearshtml;
9119				inst.yearshtml = null;
9120			}
9121		}
9122
9123		html += this._get( inst, "yearSuffix" );
9124		if ( showMonthAfterYear ) {
9125			html += ( secondary || !( changeMonth && changeYear ) ? "&#xa0;" : "" ) + monthHtml;
9126		}
9127		html += "</div>"; // Close datepicker_header
9128		return html;
9129	},
9130
9131	/* Adjust one of the date sub-fields. */
9132	_adjustInstDate: function( inst, offset, period ) {
9133		var year = inst.selectedYear + ( period === "Y" ? offset : 0 ),
9134			month = inst.selectedMonth + ( period === "M" ? offset : 0 ),
9135			day = Math.min( inst.selectedDay, this._getDaysInMonth( year, month ) ) + ( period === "D" ? offset : 0 ),
9136			date = this._restrictMinMax( inst, this._daylightSavingAdjust( new Date( year, month, day ) ) );
9137
9138		inst.selectedDay = date.getDate();
9139		inst.drawMonth = inst.selectedMonth = date.getMonth();
9140		inst.drawYear = inst.selectedYear = date.getFullYear();
9141		if ( period === "M" || period === "Y" ) {
9142			this._notifyChange( inst );
9143		}
9144	},
9145
9146	/* Ensure a date is within any min/max bounds. */
9147	_restrictMinMax: function( inst, date ) {
9148		var minDate = this._getMinMaxDate( inst, "min" ),
9149			maxDate = this._getMinMaxDate( inst, "max" ),
9150			newDate = ( minDate && date < minDate ? minDate : date );
9151		return ( maxDate && newDate > maxDate ? maxDate : newDate );
9152	},
9153
9154	/* Notify change of month/year. */
9155	_notifyChange: function( inst ) {
9156		var onChange = this._get( inst, "onChangeMonthYear" );
9157		if ( onChange ) {
9158			onChange.apply( ( inst.input ? inst.input[ 0 ] : null ),
9159				[ inst.selectedYear, inst.selectedMonth + 1, inst ] );
9160		}
9161	},
9162
9163	/* Determine the number of months to show. */
9164	_getNumberOfMonths: function( inst ) {
9165		var numMonths = this._get( inst, "numberOfMonths" );
9166		return ( numMonths == null ? [ 1, 1 ] : ( typeof numMonths === "number" ? [ 1, numMonths ] : numMonths ) );
9167	},
9168
9169	/* Determine the current maximum date - ensure no time components are set. */
9170	_getMinMaxDate: function( inst, minMax ) {
9171		return this._determineDate( inst, this._get( inst, minMax + "Date" ), null );
9172	},
9173
9174	/* Find the number of days in a given month. */
9175	_getDaysInMonth: function( year, month ) {
9176		return 32 - this._daylightSavingAdjust( new Date( year, month, 32 ) ).getDate();
9177	},
9178
9179	/* Find the day of the week of the first of a month. */
9180	_getFirstDayOfMonth: function( year, month ) {
9181		return new Date( year, month, 1 ).getDay();
9182	},
9183
9184	/* Determines if we should allow a "next/prev" month display change. */
9185	_canAdjustMonth: function( inst, offset, curYear, curMonth ) {
9186		var numMonths = this._getNumberOfMonths( inst ),
9187			date = this._daylightSavingAdjust( new Date( curYear,
9188			curMonth + ( offset < 0 ? offset : numMonths[ 0 ] * numMonths[ 1 ] ), 1 ) );
9189
9190		if ( offset < 0 ) {
9191			date.setDate( this._getDaysInMonth( date.getFullYear(), date.getMonth() ) );
9192		}
9193		return this._isInRange( inst, date );
9194	},
9195
9196	/* Is the given date in the accepted range? */
9197	_isInRange: function( inst, date ) {
9198		var yearSplit, currentYear,
9199			minDate = this._getMinMaxDate( inst, "min" ),
9200			maxDate = this._getMinMaxDate( inst, "max" ),
9201			minYear = null,
9202			maxYear = null,
9203			years = this._get( inst, "yearRange" );
9204			if ( years ) {
9205				yearSplit = years.split( ":" );
9206				currentYear = new Date().getFullYear();
9207				minYear = parseInt( yearSplit[ 0 ], 10 );
9208				maxYear = parseInt( yearSplit[ 1 ], 10 );
9209				if ( yearSplit[ 0 ].match( /[+\-].*/ ) ) {
9210					minYear += currentYear;
9211				}
9212				if ( yearSplit[ 1 ].match( /[+\-].*/ ) ) {
9213					maxYear += currentYear;
9214				}
9215			}
9216
9217		return ( ( !minDate || date.getTime() >= minDate.getTime() ) &&
9218			( !maxDate || date.getTime() <= maxDate.getTime() ) &&
9219			( !minYear || date.getFullYear() >= minYear ) &&
9220			( !maxYear || date.getFullYear() <= maxYear ) );
9221	},
9222
9223	/* Provide the configuration settings for formatting/parsing. */
9224	_getFormatConfig: function( inst ) {
9225		var shortYearCutoff = this._get( inst, "shortYearCutoff" );
9226		shortYearCutoff = ( typeof shortYearCutoff !== "string" ? shortYearCutoff :
9227			new Date().getFullYear() % 100 + parseInt( shortYearCutoff, 10 ) );
9228		return { shortYearCutoff: shortYearCutoff,
9229			dayNamesShort: this._get( inst, "dayNamesShort" ), dayNames: this._get( inst, "dayNames" ),
9230			monthNamesShort: this._get( inst, "monthNamesShort" ), monthNames: this._get( inst, "monthNames" ) };
9231	},
9232
9233	/* Format the given date for display. */
9234	_formatDate: function( inst, day, month, year ) {
9235		if ( !day ) {
9236			inst.currentDay = inst.selectedDay;
9237			inst.currentMonth = inst.selectedMonth;
9238			inst.currentYear = inst.selectedYear;
9239		}
9240		var date = ( day ? ( typeof day === "object" ? day :
9241			this._daylightSavingAdjust( new Date( year, month, day ) ) ) :
9242			this._daylightSavingAdjust( new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) );
9243		return this.formatDate( this._get( inst, "dateFormat" ), date, this._getFormatConfig( inst ) );
9244	}
9245} );
9246
9247/*
9248 * Bind hover events for datepicker elements.
9249 * Done via delegate so the binding only occurs once in the lifetime of the parent div.
9250 * Global datepicker_instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
9251 */
9252function datepicker_bindHover( dpDiv ) {
9253	var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";
9254	return dpDiv.on( "mouseout", selector, function() {
9255			$( this ).removeClass( "ui-state-hover" );
9256			if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) {
9257				$( this ).removeClass( "ui-datepicker-prev-hover" );
9258			}
9259			if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) {
9260				$( this ).removeClass( "ui-datepicker-next-hover" );
9261			}
9262		} )
9263		.on( "mouseover", selector, datepicker_handleMouseover );
9264}
9265
9266function datepicker_handleMouseover() {
9267	if ( !$.datepicker._isDisabledDatepicker( datepicker_instActive.inline ? datepicker_instActive.dpDiv.parent()[ 0 ] : datepicker_instActive.input[ 0 ] ) ) {
9268		$( this ).parents( ".ui-datepicker-calendar" ).find( "a" ).removeClass( "ui-state-hover" );
9269		$( this ).addClass( "ui-state-hover" );
9270		if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) {
9271			$( this ).addClass( "ui-datepicker-prev-hover" );
9272		}
9273		if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) {
9274			$( this ).addClass( "ui-datepicker-next-hover" );
9275		}
9276	}
9277}
9278
9279/* jQuery extend now ignores nulls! */
9280function datepicker_extendRemove( target, props ) {
9281	$.extend( target, props );
9282	for ( var name in props ) {
9283		if ( props[ name ] == null ) {
9284			target[ name ] = props[ name ];
9285		}
9286	}
9287	return target;
9288}
9289
9290/* Invoke the datepicker functionality.
9291   @param  options  string - a command, optionally followed by additional parameters or
9292					Object - settings for attaching new datepicker functionality
9293   @return  jQuery object */
9294$.fn.datepicker = function( options ) {
9295
9296	/* Verify an empty collection wasn't passed - Fixes #6976 */
9297	if ( !this.length ) {
9298		return this;
9299	}
9300
9301	/* Initialise the date picker. */
9302	if ( !$.datepicker.initialized ) {
9303		$( document ).on( "mousedown", $.datepicker._checkExternalClick );
9304		$.datepicker.initialized = true;
9305	}
9306
9307	/* Append datepicker main container to body if not exist. */
9308	if ( $( "#" + $.datepicker._mainDivId ).length === 0 ) {
9309		$( "body" ).append( $.datepicker.dpDiv );
9310	}
9311
9312	var otherArgs = Array.prototype.slice.call( arguments, 1 );
9313	if ( typeof options === "string" && ( options === "isDisabled" || options === "getDate" || options === "widget" ) ) {
9314		return $.datepicker[ "_" + options + "Datepicker" ].
9315			apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) );
9316	}
9317	if ( options === "option" && arguments.length === 2 && typeof arguments[ 1 ] === "string" ) {
9318		return $.datepicker[ "_" + options + "Datepicker" ].
9319			apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) );
9320	}
9321	return this.each( function() {
9322		if ( typeof options === "string" ) {
9323			$.datepicker[ "_" + options + "Datepicker" ]
9324				.apply( $.datepicker, [ this ].concat( otherArgs ) );
9325		} else {
9326			$.datepicker._attachDatepicker( this, options );
9327		}
9328	} );
9329};
9330
9331$.datepicker = new Datepicker(); // singleton instance
9332$.datepicker.initialized = false;
9333$.datepicker.uuid = new Date().getTime();
9334$.datepicker.version = "1.14.0";
9335
9336var widgetsDatepicker = $.datepicker;
9337
9338
9339/*!
9340 * jQuery UI Mouse 1.14.0
9341 * https://jqueryui.com
9342 *
9343 * Copyright OpenJS Foundation and other contributors
9344 * Released under the MIT license.
9345 * https://jquery.org/license
9346 */
9347
9348//>>label: Mouse
9349//>>group: Widgets
9350//>>description: Abstracts mouse-based interactions to assist in creating certain widgets.
9351//>>docs: https://api.jqueryui.com/mouse/
9352
9353
9354var mouseHandled = false;
9355$( document ).on( "mouseup", function() {
9356	mouseHandled = false;
9357} );
9358
9359var widgetsMouse = $.widget( "ui.mouse", {
9360	version: "1.14.0",
9361	options: {
9362		cancel: "input, textarea, button, select, option",
9363		distance: 1,
9364		delay: 0
9365	},
9366	_mouseInit: function() {
9367		var that = this;
9368
9369		this.element
9370			.on( "mousedown." + this.widgetName, function( event ) {
9371				return that._mouseDown( event );
9372			} )
9373			.on( "click." + this.widgetName, function( event ) {
9374				if ( true === $.data( event.target, that.widgetName + ".preventClickEvent" ) ) {
9375					$.removeData( event.target, that.widgetName + ".preventClickEvent" );
9376					event.stopImmediatePropagation();
9377					return false;
9378				}
9379			} );
9380
9381		this.started = false;
9382	},
9383
9384	// TODO: make sure destroying one instance of mouse doesn't mess with
9385	// other instances of mouse
9386	_mouseDestroy: function() {
9387		this.element.off( "." + this.widgetName );
9388		if ( this._mouseMoveDelegate ) {
9389			this.document
9390				.off( "mousemove." + this.widgetName, this._mouseMoveDelegate )
9391				.off( "mouseup." + this.widgetName, this._mouseUpDelegate );
9392		}
9393	},
9394
9395	_mouseDown: function( event ) {
9396
9397		// don't let more than one widget handle mouseStart
9398		if ( mouseHandled ) {
9399			return;
9400		}
9401
9402		this._mouseMoved = false;
9403
9404		// We may have missed mouseup (out of window)
9405		if ( this._mouseStarted ) {
9406			this._mouseUp( event );
9407		}
9408
9409		this._mouseDownEvent = event;
9410
9411		var that = this,
9412			btnIsLeft = event.which === 1,
9413			elIsCancel = typeof this.options.cancel === "string" ?
9414				$( event.target ).closest( this.options.cancel ).length :
9415				false;
9416		if ( !btnIsLeft || elIsCancel || !this._mouseCapture( event ) ) {
9417			return true;
9418		}
9419
9420		this.mouseDelayMet = !this.options.delay;
9421		if ( !this.mouseDelayMet ) {
9422			this._mouseDelayTimer = setTimeout( function() {
9423				that.mouseDelayMet = true;
9424			}, this.options.delay );
9425		}
9426
9427		if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) {
9428			this._mouseStarted = ( this._mouseStart( event ) !== false );
9429			if ( !this._mouseStarted ) {
9430				event.preventDefault();
9431				return true;
9432			}
9433		}
9434
9435		// Click event may never have fired (Gecko & Opera)
9436		if ( true === $.data( event.target, this.widgetName + ".preventClickEvent" ) ) {
9437			$.removeData( event.target, this.widgetName + ".preventClickEvent" );
9438		}
9439
9440		// These delegates are required to keep context
9441		this._mouseMoveDelegate = function( event ) {
9442			return that._mouseMove( event );
9443		};
9444		this._mouseUpDelegate = function( event ) {
9445			return that._mouseUp( event );
9446		};
9447
9448		this.document
9449			.on( "mousemove." + this.widgetName, this._mouseMoveDelegate )
9450			.on( "mouseup." + this.widgetName, this._mouseUpDelegate );
9451
9452		event.preventDefault();
9453
9454		mouseHandled = true;
9455		return true;
9456	},
9457
9458	_mouseMove: function( event ) {
9459
9460		// Only check for mouseups outside the document if you've moved inside the document
9461		// at least once.
9462		if ( this._mouseMoved && !event.which ) {
9463
9464			// Support: Safari <=8 - 9
9465			// Safari sets which to 0 if you press any of the following keys
9466			// during a drag (#14461)
9467			if ( event.originalEvent.altKey || event.originalEvent.ctrlKey ||
9468					event.originalEvent.metaKey || event.originalEvent.shiftKey ) {
9469				this.ignoreMissingWhich = true;
9470			} else if ( !this.ignoreMissingWhich ) {
9471				return this._mouseUp( event );
9472			}
9473		}
9474
9475		if ( event.which || event.button ) {
9476			this._mouseMoved = true;
9477		}
9478
9479		if ( this._mouseStarted ) {
9480			this._mouseDrag( event );
9481			return event.preventDefault();
9482		}
9483
9484		if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) {
9485			this._mouseStarted =
9486				( this._mouseStart( this._mouseDownEvent, event ) !== false );
9487			if ( this._mouseStarted ) {
9488				this._mouseDrag( event );
9489			} else {
9490				this._mouseUp( event );
9491			}
9492		}
9493
9494		return !this._mouseStarted;
9495	},
9496
9497	_mouseUp: function( event ) {
9498		this.document
9499			.off( "mousemove." + this.widgetName, this._mouseMoveDelegate )
9500			.off( "mouseup." + this.widgetName, this._mouseUpDelegate );
9501
9502		if ( this._mouseStarted ) {
9503			this._mouseStarted = false;
9504
9505			if ( event.target === this._mouseDownEvent.target ) {
9506				$.data( event.target, this.widgetName + ".preventClickEvent", true );
9507			}
9508
9509			this._mouseStop( event );
9510		}
9511
9512		if ( this._mouseDelayTimer ) {
9513			clearTimeout( this._mouseDelayTimer );
9514			delete this._mouseDelayTimer;
9515		}
9516
9517		this.ignoreMissingWhich = false;
9518		mouseHandled = false;
9519		event.preventDefault();
9520	},
9521
9522	_mouseDistanceMet: function( event ) {
9523		return ( Math.max(
9524				Math.abs( this._mouseDownEvent.pageX - event.pageX ),
9525				Math.abs( this._mouseDownEvent.pageY - event.pageY )
9526			) >= this.options.distance
9527		);
9528	},
9529
9530	_mouseDelayMet: function( /* event */ ) {
9531		return this.mouseDelayMet;
9532	},
9533
9534	// These are placeholder methods, to be overriden by extending plugin
9535	_mouseStart: function( /* event */ ) {},
9536	_mouseDrag: function( /* event */ ) {},
9537	_mouseStop: function( /* event */ ) {},
9538	_mouseCapture: function( /* event */ ) {
9539		return true;
9540	}
9541} );
9542
9543
9544
9545// $.ui.plugin is deprecated. Use $.widget() extensions instead.
9546var plugin = $.ui.plugin = {
9547	add: function( module, option, set ) {
9548		var i,
9549			proto = $.ui[ module ].prototype;
9550		for ( i in set ) {
9551			proto.plugins[ i ] = proto.plugins[ i ] || [];
9552			proto.plugins[ i ].push( [ option, set[ i ] ] );
9553		}
9554	},
9555	call: function( instance, name, args, allowDisconnected ) {
9556		var i,
9557			set = instance.plugins[ name ];
9558
9559		if ( !set ) {
9560			return;
9561		}
9562
9563		if ( !allowDisconnected && ( !instance.element[ 0 ].parentNode ||
9564				instance.element[ 0 ].parentNode.nodeType === 11 ) ) {
9565			return;
9566		}
9567
9568		for ( i = 0; i < set.length; i++ ) {
9569			if ( instance.options[ set[ i ][ 0 ] ] ) {
9570				set[ i ][ 1 ].apply( instance.element, args );
9571			}
9572		}
9573	}
9574};
9575
9576
9577/*!
9578 * jQuery UI Draggable 1.14.0
9579 * https://jqueryui.com
9580 *
9581 * Copyright OpenJS Foundation and other contributors
9582 * Released under the MIT license.
9583 * https://jquery.org/license
9584 */
9585
9586//>>label: Draggable
9587//>>group: Interactions
9588//>>description: Enables dragging functionality for any element.
9589//>>docs: https://api.jqueryui.com/draggable/
9590//>>demos: https://jqueryui.com/draggable/
9591//>>css.structure: ../../themes/base/draggable.css
9592
9593
9594$.widget( "ui.draggable", $.ui.mouse, {
9595	version: "1.14.0",
9596	widgetEventPrefix: "drag",
9597	options: {
9598		addClasses: true,
9599		appendTo: "parent",
9600		axis: false,
9601		connectToSortable: false,
9602		containment: false,
9603		cursor: "auto",
9604		cursorAt: false,
9605		grid: false,
9606		handle: false,
9607		helper: "original",
9608		iframeFix: false,
9609		opacity: false,
9610		refreshPositions: false,
9611		revert: false,
9612		revertDuration: 500,
9613		scope: "default",
9614		scroll: true,
9615		scrollSensitivity: 20,
9616		scrollSpeed: 20,
9617		snap: false,
9618		snapMode: "both",
9619		snapTolerance: 20,
9620		stack: false,
9621		zIndex: false,
9622
9623		// Callbacks
9624		drag: null,
9625		start: null,
9626		stop: null
9627	},
9628	_create: function() {
9629
9630		if ( this.options.helper === "original" ) {
9631			this._setPositionRelative();
9632		}
9633		if ( this.options.addClasses ) {
9634			this._addClass( "ui-draggable" );
9635		}
9636		this._setHandleClassName();
9637
9638		this._mouseInit();
9639	},
9640
9641	_setOption: function( key, value ) {
9642		this._super( key, value );
9643		if ( key === "handle" ) {
9644			this._removeHandleClassName();
9645			this._setHandleClassName();
9646		}
9647	},
9648
9649	_destroy: function() {
9650		if ( ( this.helper || this.element ).is( ".ui-draggable-dragging" ) ) {
9651			this.destroyOnClear = true;
9652			return;
9653		}
9654		this._removeHandleClassName();
9655		this._mouseDestroy();
9656	},
9657
9658	_mouseCapture: function( event ) {
9659		var o = this.options;
9660
9661		// Among others, prevent a drag on a resizable-handle
9662		if ( this.helper || o.disabled ||
9663				$( event.target ).closest( ".ui-resizable-handle" ).length > 0 ) {
9664			return false;
9665		}
9666
9667		//Quit if we're not on a valid handle
9668		this.handle = this._getHandle( event );
9669		if ( !this.handle ) {
9670			return false;
9671		}
9672
9673		this._blurActiveElement( event );
9674
9675		this._blockFrames( o.iframeFix === true ? "iframe" : o.iframeFix );
9676
9677		return true;
9678
9679	},
9680
9681	_blockFrames: function( selector ) {
9682		this.iframeBlocks = this.document.find( selector ).map( function() {
9683			var iframe = $( this );
9684
9685			return $( "<div>" )
9686				.css( "position", "absolute" )
9687				.appendTo( iframe.parent() )
9688				.outerWidth( iframe.outerWidth() )
9689				.outerHeight( iframe.outerHeight() )
9690				.offset( iframe.offset() )[ 0 ];
9691		} );
9692	},
9693
9694	_unblockFrames: function() {
9695		if ( this.iframeBlocks ) {
9696			this.iframeBlocks.remove();
9697			delete this.iframeBlocks;
9698		}
9699	},
9700
9701	_blurActiveElement: function( event ) {
9702		var activeElement = this.document[ 0 ].activeElement,
9703			target = $( event.target );
9704
9705		// Don't blur if the event occurred on an element that is within
9706		// the currently focused element
9707		// See #10527, #12472
9708		if ( target.closest( activeElement ).length ) {
9709			return;
9710		}
9711
9712		// Blur any element that currently has focus, see #4261
9713		$( activeElement ).trigger( "blur" );
9714	},
9715
9716	_mouseStart: function( event ) {
9717
9718		var o = this.options;
9719
9720		//Create and append the visible helper
9721		this.helper = this._createHelper( event );
9722
9723		this._addClass( this.helper, "ui-draggable-dragging" );
9724
9725		//Cache the helper size
9726		this._cacheHelperProportions();
9727
9728		//If ddmanager is used for droppables, set the global draggable
9729		if ( $.ui.ddmanager ) {
9730			$.ui.ddmanager.current = this;
9731		}
9732
9733		/*
9734		 * - Position generation -
9735		 * This block generates everything position related - it's the core of draggables.
9736		 */
9737
9738		//Cache the margins of the original element
9739		this._cacheMargins();
9740
9741		//Store the helper's css position
9742		this.cssPosition = this.helper.css( "position" );
9743		this.scrollParent = this.helper.scrollParent( true );
9744		this.offsetParent = this.helper.offsetParent();
9745		this.hasFixedAncestor = this.helper.parents().filter( function() {
9746				return $( this ).css( "position" ) === "fixed";
9747			} ).length > 0;
9748
9749		//The element's absolute position on the page minus margins
9750		this.positionAbs = this.element.offset();
9751		this._refreshOffsets( event );
9752
9753		//Generate the original position
9754		this.originalPosition = this.position = this._generatePosition( event, false );
9755		this.originalPageX = event.pageX;
9756		this.originalPageY = event.pageY;
9757
9758		//Adjust the mouse offset relative to the helper if "cursorAt" is supplied
9759		if ( o.cursorAt ) {
9760			this._adjustOffsetFromHelper( o.cursorAt );
9761		}
9762
9763		//Set a containment if given in the options
9764		this._setContainment();
9765
9766		//Trigger event + callbacks
9767		if ( this._trigger( "start", event ) === false ) {
9768			this._clear();
9769			return false;
9770		}
9771
9772		//Recache the helper size
9773		this._cacheHelperProportions();
9774
9775		//Prepare the droppable offsets
9776		if ( $.ui.ddmanager && !o.dropBehaviour ) {
9777			$.ui.ddmanager.prepareOffsets( this, event );
9778		}
9779
9780		// Execute the drag once - this causes the helper not to be visible before getting its
9781		// correct position
9782		this._mouseDrag( event, true );
9783
9784		// If the ddmanager is used for droppables, inform the manager that dragging has started
9785		// (see #5003)
9786		if ( $.ui.ddmanager ) {
9787			$.ui.ddmanager.dragStart( this, event );
9788		}
9789
9790		return true;
9791	},
9792
9793	_refreshOffsets: function( event ) {
9794		this.offset = {
9795			top: this.positionAbs.top - this.margins.top,
9796			left: this.positionAbs.left - this.margins.left,
9797			scroll: false,
9798			parent: this._getParentOffset(),
9799			relative: this._getRelativeOffset()
9800		};
9801
9802		this.offset.click = {
9803			left: event.pageX - this.offset.left,
9804			top: event.pageY - this.offset.top
9805		};
9806	},
9807
9808	_mouseDrag: function( event, noPropagation ) {
9809
9810		// reset any necessary cached properties (see #5009)
9811		if ( this.hasFixedAncestor ) {
9812			this.offset.parent = this._getParentOffset();
9813		}
9814
9815		//Compute the helpers position
9816		this.position = this._generatePosition( event, true );
9817		this.positionAbs = this._convertPositionTo( "absolute" );
9818
9819		//Call plugins and callbacks and use the resulting position if something is returned
9820		if ( !noPropagation ) {
9821			var ui = this._uiHash();
9822			if ( this._trigger( "drag", event, ui ) === false ) {
9823				this._mouseUp( new $.Event( "mouseup", event ) );
9824				return false;
9825			}
9826			this.position = ui.position;
9827		}
9828
9829		this.helper[ 0 ].style.left = this.position.left + "px";
9830		this.helper[ 0 ].style.top = this.position.top + "px";
9831
9832		if ( $.ui.ddmanager ) {
9833			$.ui.ddmanager.drag( this, event );
9834		}
9835
9836		return false;
9837	},
9838
9839	_mouseStop: function( event ) {
9840
9841		//If we are using droppables, inform the manager about the drop
9842		var that = this,
9843			dropped = false;
9844		if ( $.ui.ddmanager && !this.options.dropBehaviour ) {
9845			dropped = $.ui.ddmanager.drop( this, event );
9846		}
9847
9848		//if a drop comes from outside (a sortable)
9849		if ( this.dropped ) {
9850			dropped = this.dropped;
9851			this.dropped = false;
9852		}
9853
9854		if ( ( this.options.revert === "invalid" && !dropped ) ||
9855				( this.options.revert === "valid" && dropped ) ||
9856				this.options.revert === true || ( typeof this.options.revert === "function" &&
9857				this.options.revert.call( this.element, dropped ) )
9858		) {
9859			$( this.helper ).animate(
9860				this.originalPosition,
9861				parseInt( this.options.revertDuration, 10 ),
9862				function() {
9863					if ( that._trigger( "stop", event ) !== false ) {
9864						that._clear();
9865					}
9866				}
9867			);
9868		} else {
9869			if ( this._trigger( "stop", event ) !== false ) {
9870				this._clear();
9871			}
9872		}
9873
9874		return false;
9875	},
9876
9877	_mouseUp: function( event ) {
9878		this._unblockFrames();
9879
9880		// If the ddmanager is used for droppables, inform the manager that dragging has stopped
9881		// (see #5003)
9882		if ( $.ui.ddmanager ) {
9883			$.ui.ddmanager.dragStop( this, event );
9884		}
9885
9886		// Only need to focus if the event occurred on the draggable itself, see #10527
9887		if ( this.handleElement.is( event.target ) ) {
9888
9889			// The interaction is over; whether or not the click resulted in a drag,
9890			// focus the element
9891			this.element.trigger( "focus" );
9892		}
9893
9894		return $.ui.mouse.prototype._mouseUp.call( this, event );
9895	},
9896
9897	cancel: function() {
9898
9899		if ( this.helper.is( ".ui-draggable-dragging" ) ) {
9900			this._mouseUp( new $.Event( "mouseup", { target: this.element[ 0 ] } ) );
9901		} else {
9902			this._clear();
9903		}
9904
9905		return this;
9906
9907	},
9908
9909	_getHandle: function( event ) {
9910		return this.options.handle ?
9911			!!$( event.target ).closest( this.element.find( this.options.handle ) ).length :
9912			true;
9913	},
9914
9915	_setHandleClassName: function() {
9916		this.handleElement = this.options.handle ?
9917			this.element.find( this.options.handle ) : this.element;
9918		this._addClass( this.handleElement, "ui-draggable-handle" );
9919	},
9920
9921	_removeHandleClassName: function() {
9922		this._removeClass( this.handleElement, "ui-draggable-handle" );
9923	},
9924
9925	_createHelper: function( event ) {
9926
9927		var o = this.options,
9928			helperIsFunction = typeof o.helper === "function",
9929			helper = helperIsFunction ?
9930				$( o.helper.apply( this.element[ 0 ], [ event ] ) ) :
9931				( o.helper === "clone" ?
9932					this.element.clone().removeAttr( "id" ) :
9933					this.element );
9934
9935		if ( !helper.parents( "body" ).length ) {
9936			helper.appendTo( ( o.appendTo === "parent" ?
9937				this.element[ 0 ].parentNode :
9938				o.appendTo ) );
9939		}
9940
9941		// https://bugs.jqueryui.com/ticket/9446
9942		// a helper function can return the original element
9943		// which wouldn't have been set to relative in _create
9944		if ( helperIsFunction && helper[ 0 ] === this.element[ 0 ] ) {
9945			this._setPositionRelative();
9946		}
9947
9948		if ( helper[ 0 ] !== this.element[ 0 ] &&
9949				!( /(fixed|absolute)/ ).test( helper.css( "position" ) ) ) {
9950			helper.css( "position", "absolute" );
9951		}
9952
9953		return helper;
9954
9955	},
9956
9957	_setPositionRelative: function() {
9958		if ( !( /^(?:r|a|f)/ ).test( this.element.css( "position" ) ) ) {
9959			this.element[ 0 ].style.position = "relative";
9960		}
9961	},
9962
9963	_adjustOffsetFromHelper: function( obj ) {
9964		if ( typeof obj === "string" ) {
9965			obj = obj.split( " " );
9966		}
9967		if ( Array.isArray( obj ) ) {
9968			obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 };
9969		}
9970		if ( "left" in obj ) {
9971			this.offset.click.left = obj.left + this.margins.left;
9972		}
9973		if ( "right" in obj ) {
9974			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
9975		}
9976		if ( "top" in obj ) {
9977			this.offset.click.top = obj.top + this.margins.top;
9978		}
9979		if ( "bottom" in obj ) {
9980			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
9981		}
9982	},
9983
9984	_isRootNode: function( element ) {
9985		return ( /(html|body)/i ).test( element.tagName ) || element === this.document[ 0 ];
9986	},
9987
9988	_getParentOffset: function() {
9989
9990		//Get the offsetParent and cache its position
9991		var po = this.offsetParent.offset(),
9992			document = this.document[ 0 ];
9993
9994		// This is a special case where we need to modify a offset calculated on start, since the
9995		// following happened:
9996		// 1. The position of the helper is absolute, so it's position is calculated based on the
9997		// next positioned parent
9998		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't
9999		// the document, which means that the scroll is included in the initial calculation of the
10000		// offset of the parent, and never recalculated upon drag
10001		if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== document &&
10002				$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) {
10003			po.left += this.scrollParent.scrollLeft();
10004			po.top += this.scrollParent.scrollTop();
10005		}
10006
10007		if ( this._isRootNode( this.offsetParent[ 0 ] ) ) {
10008			po = { top: 0, left: 0 };
10009		}
10010
10011		return {
10012			top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ),
10013			left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 )
10014		};
10015
10016	},
10017
10018	_getRelativeOffset: function() {
10019		if ( this.cssPosition !== "relative" ) {
10020			return { top: 0, left: 0 };
10021		}
10022
10023		var p = this.element.position(),
10024			scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
10025
10026		return {
10027			top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) +
10028				( !scrollIsRootNode ? this.scrollParent.scrollTop() : 0 ),
10029			left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) +
10030				( !scrollIsRootNode ? this.scrollParent.scrollLeft() : 0 )
10031		};
10032
10033	},
10034
10035	_cacheMargins: function() {
10036		this.margins = {
10037			left: ( parseInt( this.element.css( "marginLeft" ), 10 ) || 0 ),
10038			top: ( parseInt( this.element.css( "marginTop" ), 10 ) || 0 ),
10039			right: ( parseInt( this.element.css( "marginRight" ), 10 ) || 0 ),
10040			bottom: ( parseInt( this.element.css( "marginBottom" ), 10 ) || 0 )
10041		};
10042	},
10043
10044	_cacheHelperProportions: function() {
10045		this.helperProportions = {
10046			width: this.helper.outerWidth(),
10047			height: this.helper.outerHeight()
10048		};
10049	},
10050
10051	_setContainment: function() {
10052
10053		var isUserScrollable, c, ce,
10054			o = this.options,
10055			document = this.document[ 0 ];
10056
10057		this.relativeContainer = null;
10058
10059		if ( !o.containment ) {
10060			this.containment = null;
10061			return;
10062		}
10063
10064		if ( o.containment === "window" ) {
10065			this.containment = [
10066				$( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
10067				$( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top,
10068				$( window ).scrollLeft() + $( window ).width() -
10069					this.helperProportions.width - this.margins.left,
10070				$( window ).scrollTop() +
10071					( $( window ).height() || document.body.parentNode.scrollHeight ) -
10072					this.helperProportions.height - this.margins.top
10073			];
10074			return;
10075		}
10076
10077		if ( o.containment === "document" ) {
10078			this.containment = [
10079				0,
10080				0,
10081				$( document ).width() - this.helperProportions.width - this.margins.left,
10082				( $( document ).height() || document.body.parentNode.scrollHeight ) -
10083					this.helperProportions.height - this.margins.top
10084			];
10085			return;
10086		}
10087
10088		if ( o.containment.constructor === Array ) {
10089			this.containment = o.containment;
10090			return;
10091		}
10092
10093		if ( o.containment === "parent" ) {
10094			o.containment = this.helper[ 0 ].parentNode;
10095		}
10096
10097		c = $( o.containment );
10098		ce = c[ 0 ];
10099
10100		if ( !ce ) {
10101			return;
10102		}
10103
10104		isUserScrollable = /(scroll|auto)/.test( c.css( "overflow" ) );
10105
10106		this.containment = [
10107			( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) +
10108				( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ),
10109			( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) +
10110				( parseInt( c.css( "paddingTop" ), 10 ) || 0 ),
10111			( isUserScrollable ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -
10112				( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) -
10113				( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) -
10114				this.helperProportions.width -
10115				this.margins.left -
10116				this.margins.right,
10117			( isUserScrollable ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -
10118				( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) -
10119				( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) -
10120				this.helperProportions.height -
10121				this.margins.top -
10122				this.margins.bottom
10123		];
10124		this.relativeContainer = c;
10125	},
10126
10127	_convertPositionTo: function( d, pos ) {
10128
10129		if ( !pos ) {
10130			pos = this.position;
10131		}
10132
10133		var mod = d === "absolute" ? 1 : -1,
10134			scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
10135
10136		return {
10137			top: (
10138
10139				// The absolute mouse position
10140				pos.top	+
10141
10142				// Only for relative positioned nodes: Relative offset from element to offset parent
10143				this.offset.relative.top * mod +
10144
10145				// The offsetParent's offset without borders (offset + border)
10146				this.offset.parent.top * mod -
10147				( ( this.cssPosition === "fixed" ?
10148					-this.offset.scroll.top :
10149					( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) * mod )
10150			),
10151			left: (
10152
10153				// The absolute mouse position
10154				pos.left +
10155
10156				// Only for relative positioned nodes: Relative offset from element to offset parent
10157				this.offset.relative.left * mod +
10158
10159				// The offsetParent's offset without borders (offset + border)
10160				this.offset.parent.left * mod	-
10161				( ( this.cssPosition === "fixed" ?
10162					-this.offset.scroll.left :
10163					( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) * mod )
10164			)
10165		};
10166
10167	},
10168
10169	_generatePosition: function( event, constrainPosition ) {
10170
10171		var containment, co, top, left,
10172			o = this.options,
10173			scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ),
10174			pageX = event.pageX,
10175			pageY = event.pageY;
10176
10177		// Cache the scroll
10178		if ( !scrollIsRootNode || !this.offset.scroll ) {
10179			this.offset.scroll = {
10180				top: this.scrollParent.scrollTop(),
10181				left: this.scrollParent.scrollLeft()
10182			};
10183		}
10184
10185		/*
10186		 * - Position constraining -
10187		 * Constrain the position to a mix of grid, containment.
10188		 */
10189
10190		// If we are not dragging yet, we won't check for options
10191		if ( constrainPosition ) {
10192			if ( this.containment ) {
10193				if ( this.relativeContainer ) {
10194					co = this.relativeContainer.offset();
10195					containment = [
10196						this.containment[ 0 ] + co.left,
10197						this.containment[ 1 ] + co.top,
10198						this.containment[ 2 ] + co.left,
10199						this.containment[ 3 ] + co.top
10200					];
10201				} else {
10202					containment = this.containment;
10203				}
10204
10205				if ( event.pageX - this.offset.click.left < containment[ 0 ] ) {
10206					pageX = containment[ 0 ] + this.offset.click.left;
10207				}
10208				if ( event.pageY - this.offset.click.top < containment[ 1 ] ) {
10209					pageY = containment[ 1 ] + this.offset.click.top;
10210				}
10211				if ( event.pageX - this.offset.click.left > containment[ 2 ] ) {
10212					pageX = containment[ 2 ] + this.offset.click.left;
10213				}
10214				if ( event.pageY - this.offset.click.top > containment[ 3 ] ) {
10215					pageY = containment[ 3 ] + this.offset.click.top;
10216				}
10217			}
10218
10219			if ( o.grid ) {
10220
10221				//Check for grid elements set to 0 to prevent divide by 0 error causing invalid
10222				// argument errors in IE (see ticket #6950)
10223				top = o.grid[ 1 ] ? this.originalPageY + Math.round( ( pageY -
10224					this.originalPageY ) / o.grid[ 1 ] ) * o.grid[ 1 ] : this.originalPageY;
10225				pageY = containment ? ( ( top - this.offset.click.top >= containment[ 1 ] ||
10226					top - this.offset.click.top > containment[ 3 ] ) ?
10227						top :
10228						( ( top - this.offset.click.top >= containment[ 1 ] ) ?
10229							top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) : top;
10230
10231				left = o.grid[ 0 ] ? this.originalPageX +
10232					Math.round( ( pageX - this.originalPageX ) / o.grid[ 0 ] ) * o.grid[ 0 ] :
10233					this.originalPageX;
10234				pageX = containment ? ( ( left - this.offset.click.left >= containment[ 0 ] ||
10235					left - this.offset.click.left > containment[ 2 ] ) ?
10236						left :
10237						( ( left - this.offset.click.left >= containment[ 0 ] ) ?
10238							left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) : left;
10239			}
10240
10241			if ( o.axis === "y" ) {
10242				pageX = this.originalPageX;
10243			}
10244
10245			if ( o.axis === "x" ) {
10246				pageY = this.originalPageY;
10247			}
10248		}
10249
10250		return {
10251			top: (
10252
10253				// The absolute mouse position
10254				pageY -
10255
10256				// Click offset (relative to the element)
10257				this.offset.click.top -
10258
10259				// Only for relative positioned nodes: Relative offset from element to offset parent
10260				this.offset.relative.top -
10261
10262				// The offsetParent's offset without borders (offset + border)
10263				this.offset.parent.top +
10264				( this.cssPosition === "fixed" ?
10265					-this.offset.scroll.top :
10266					( scrollIsRootNode ? 0 : this.offset.scroll.top ) )
10267			),
10268			left: (
10269
10270				// The absolute mouse position
10271				pageX -
10272
10273				// Click offset (relative to the element)
10274				this.offset.click.left -
10275
10276				// Only for relative positioned nodes: Relative offset from element to offset parent
10277				this.offset.relative.left -
10278
10279				// The offsetParent's offset without borders (offset + border)
10280				this.offset.parent.left +
10281				( this.cssPosition === "fixed" ?
10282					-this.offset.scroll.left :
10283					( scrollIsRootNode ? 0 : this.offset.scroll.left ) )
10284			)
10285		};
10286
10287	},
10288
10289	_clear: function() {
10290		this._removeClass( this.helper, "ui-draggable-dragging" );
10291		if ( this.helper[ 0 ] !== this.element[ 0 ] && !this.cancelHelperRemoval ) {
10292			this.helper.remove();
10293		}
10294		this.helper = null;
10295		this.cancelHelperRemoval = false;
10296		if ( this.destroyOnClear ) {
10297			this.destroy();
10298		}
10299	},
10300
10301	// From now on bulk stuff - mainly helpers
10302
10303	_trigger: function( type, event, ui ) {
10304		ui = ui || this._uiHash();
10305		$.ui.plugin.call( this, type, [ event, ui, this ], true );
10306
10307		// Absolute position and offset (see #6884 ) have to be recalculated after plugins
10308		if ( /^(drag|start|stop)/.test( type ) ) {
10309			this.positionAbs = this._convertPositionTo( "absolute" );
10310			ui.offset = this.positionAbs;
10311		}
10312		return $.Widget.prototype._trigger.call( this, type, event, ui );
10313	},
10314
10315	plugins: {},
10316
10317	_uiHash: function() {
10318		return {
10319			helper: this.helper,
10320			position: this.position,
10321			originalPosition: this.originalPosition,
10322			offset: this.positionAbs
10323		};
10324	}
10325
10326} );
10327
10328$.ui.plugin.add( "draggable", "connectToSortable", {
10329	start: function( event, ui, draggable ) {
10330		var uiSortable = $.extend( {}, ui, {
10331			item: draggable.element
10332		} );
10333
10334		draggable.sortables = [];
10335		$( draggable.options.connectToSortable ).each( function() {
10336			var sortable = $( this ).sortable( "instance" );
10337
10338			if ( sortable && !sortable.options.disabled ) {
10339				draggable.sortables.push( sortable );
10340
10341				// RefreshPositions is called at drag start to refresh the containerCache
10342				// which is used in drag. This ensures it's initialized and synchronized
10343				// with any changes that might have happened on the page since initialization.
10344				sortable.refreshPositions();
10345				sortable._trigger( "activate", event, uiSortable );
10346			}
10347		} );
10348	},
10349	stop: function( event, ui, draggable ) {
10350		var uiSortable = $.extend( {}, ui, {
10351			item: draggable.element
10352		} );
10353
10354		draggable.cancelHelperRemoval = false;
10355
10356		$.each( draggable.sortables, function() {
10357			var sortable = this;
10358
10359			if ( sortable.isOver ) {
10360				sortable.isOver = 0;
10361
10362				// Allow this sortable to handle removing the helper
10363				draggable.cancelHelperRemoval = true;
10364				sortable.cancelHelperRemoval = false;
10365
10366				// Use _storedCSS To restore properties in the sortable,
10367				// as this also handles revert (#9675) since the draggable
10368				// may have modified them in unexpected ways (#8809)
10369				sortable._storedCSS = {
10370					position: sortable.placeholder.css( "position" ),
10371					top: sortable.placeholder.css( "top" ),
10372					left: sortable.placeholder.css( "left" )
10373				};
10374
10375				sortable._mouseStop( event );
10376
10377				// Once drag has ended, the sortable should return to using
10378				// its original helper, not the shared helper from draggable
10379				sortable.options.helper = sortable.options._helper;
10380			} else {
10381
10382				// Prevent this Sortable from removing the helper.
10383				// However, don't set the draggable to remove the helper
10384				// either as another connected Sortable may yet handle the removal.
10385				sortable.cancelHelperRemoval = true;
10386
10387				sortable._trigger( "deactivate", event, uiSortable );
10388			}
10389		} );
10390	},
10391	drag: function( event, ui, draggable ) {
10392		$.each( draggable.sortables, function() {
10393			var innermostIntersecting = false,
10394				sortable = this;
10395
10396			// Copy over variables that sortable's _intersectsWith uses
10397			sortable.positionAbs = draggable.positionAbs;
10398			sortable.helperProportions = draggable.helperProportions;
10399			sortable.offset.click = draggable.offset.click;
10400
10401			if ( sortable._intersectsWith( sortable.containerCache ) ) {
10402				innermostIntersecting = true;
10403
10404				$.each( draggable.sortables, function() {
10405
10406					// Copy over variables that sortable's _intersectsWith uses
10407					this.positionAbs = draggable.positionAbs;
10408					this.helperProportions = draggable.helperProportions;
10409					this.offset.click = draggable.offset.click;
10410
10411					if ( this !== sortable &&
10412							this._intersectsWith( this.containerCache ) &&
10413							$.contains( sortable.element[ 0 ], this.element[ 0 ] ) ) {
10414						innermostIntersecting = false;
10415					}
10416
10417					return innermostIntersecting;
10418				} );
10419			}
10420
10421			if ( innermostIntersecting ) {
10422
10423				// If it intersects, we use a little isOver variable and set it once,
10424				// so that the move-in stuff gets fired only once.
10425				if ( !sortable.isOver ) {
10426					sortable.isOver = 1;
10427
10428					// Store draggable's parent in case we need to reappend to it later.
10429					draggable._parent = ui.helper.parent();
10430
10431					sortable.currentItem = ui.helper
10432						.appendTo( sortable.element )
10433						.data( "ui-sortable-item", true );
10434
10435					// Store helper option to later restore it
10436					sortable.options._helper = sortable.options.helper;
10437
10438					sortable.options.helper = function() {
10439						return ui.helper[ 0 ];
10440					};
10441
10442					// Fire the start events of the sortable with our passed browser event,
10443					// and our own helper (so it doesn't create a new one)
10444					event.target = sortable.currentItem[ 0 ];
10445					sortable._mouseCapture( event, true );
10446					sortable._mouseStart( event, true, true );
10447
10448					// Because the browser event is way off the new appended portlet,
10449					// modify necessary variables to reflect the changes
10450					sortable.offset.click.top = draggable.offset.click.top;
10451					sortable.offset.click.left = draggable.offset.click.left;
10452					sortable.offset.parent.left -= draggable.offset.parent.left -
10453						sortable.offset.parent.left;
10454					sortable.offset.parent.top -= draggable.offset.parent.top -
10455						sortable.offset.parent.top;
10456
10457					draggable._trigger( "toSortable", event );
10458
10459					// Inform draggable that the helper is in a valid drop zone,
10460					// used solely in the revert option to handle "valid/invalid".
10461					draggable.dropped = sortable.element;
10462
10463					// Need to refreshPositions of all sortables in the case that
10464					// adding to one sortable changes the location of the other sortables (#9675)
10465					$.each( draggable.sortables, function() {
10466						this.refreshPositions();
10467					} );
10468
10469					// Hack so receive/update callbacks work (mostly)
10470					draggable.currentItem = draggable.element;
10471					sortable.fromOutside = draggable;
10472				}
10473
10474				if ( sortable.currentItem ) {
10475					sortable._mouseDrag( event );
10476
10477					// Copy the sortable's position because the draggable's can potentially reflect
10478					// a relative position, while sortable is always absolute, which the dragged
10479					// element has now become. (#8809)
10480					ui.position = sortable.position;
10481				}
10482			} else {
10483
10484				// If it doesn't intersect with the sortable, and it intersected before,
10485				// we fake the drag stop of the sortable, but make sure it doesn't remove
10486				// the helper by using cancelHelperRemoval.
10487				if ( sortable.isOver ) {
10488
10489					sortable.isOver = 0;
10490					sortable.cancelHelperRemoval = true;
10491
10492					// Calling sortable's mouseStop would trigger a revert,
10493					// so revert must be temporarily false until after mouseStop is called.
10494					sortable.options._revert = sortable.options.revert;
10495					sortable.options.revert = false;
10496
10497					sortable._trigger( "out", event, sortable._uiHash( sortable ) );
10498					sortable._mouseStop( event, true );
10499
10500					// Restore sortable behaviors that were modfied
10501					// when the draggable entered the sortable area (#9481)
10502					sortable.options.revert = sortable.options._revert;
10503					sortable.options.helper = sortable.options._helper;
10504
10505					if ( sortable.placeholder ) {
10506						sortable.placeholder.remove();
10507					}
10508
10509					// Restore and recalculate the draggable's offset considering the sortable
10510					// may have modified them in unexpected ways. (#8809, #10669)
10511					ui.helper.appendTo( draggable._parent );
10512					draggable._refreshOffsets( event );
10513					ui.position = draggable._generatePosition( event, true );
10514
10515					draggable._trigger( "fromSortable", event );
10516
10517					// Inform draggable that the helper is no longer in a valid drop zone
10518					draggable.dropped = false;
10519
10520					// Need to refreshPositions of all sortables just in case removing
10521					// from one sortable changes the location of other sortables (#9675)
10522					$.each( draggable.sortables, function() {
10523						this.refreshPositions();
10524					} );
10525				}
10526			}
10527		} );
10528	}
10529} );
10530
10531$.ui.plugin.add( "draggable", "cursor", {
10532	start: function( event, ui, instance ) {
10533		var t = $( "body" ),
10534			o = instance.options;
10535
10536		if ( t.css( "cursor" ) ) {
10537			o._cursor = t.css( "cursor" );
10538		}
10539		t.css( "cursor", o.cursor );
10540	},
10541	stop: function( event, ui, instance ) {
10542		var o = instance.options;
10543		if ( o._cursor ) {
10544			$( "body" ).css( "cursor", o._cursor );
10545		}
10546	}
10547} );
10548
10549$.ui.plugin.add( "draggable", "opacity", {
10550	start: function( event, ui, instance ) {
10551		var t = $( ui.helper ),
10552			o = instance.options;
10553		if ( t.css( "opacity" ) ) {
10554			o._opacity = t.css( "opacity" );
10555		}
10556		t.css( "opacity", o.opacity );
10557	},
10558	stop: function( event, ui, instance ) {
10559		var o = instance.options;
10560		if ( o._opacity ) {
10561			$( ui.helper ).css( "opacity", o._opacity );
10562		}
10563	}
10564} );
10565
10566$.ui.plugin.add( "draggable", "scroll", {
10567	start: function( event, ui, i ) {
10568		if ( !i.scrollParentNotHidden ) {
10569			i.scrollParentNotHidden = i.helper.scrollParent( false );
10570		}
10571
10572		if ( i.scrollParentNotHidden[ 0 ] !== i.document[ 0 ] &&
10573				i.scrollParentNotHidden[ 0 ].tagName !== "HTML" ) {
10574			i.overflowOffset = i.scrollParentNotHidden.offset();
10575		}
10576	},
10577	drag: function( event, ui, i  ) {
10578
10579		var o = i.options,
10580			scrolled = false,
10581			scrollParent = i.scrollParentNotHidden[ 0 ],
10582			document = i.document[ 0 ];
10583
10584		if ( scrollParent !== document && scrollParent.tagName !== "HTML" ) {
10585			if ( !o.axis || o.axis !== "x" ) {
10586				if ( ( i.overflowOffset.top + scrollParent.offsetHeight ) - event.pageY <
10587						o.scrollSensitivity ) {
10588					scrollParent.scrollTop = scrolled = scrollParent.scrollTop + o.scrollSpeed;
10589				} else if ( event.pageY - i.overflowOffset.top < o.scrollSensitivity ) {
10590					scrollParent.scrollTop = scrolled = scrollParent.scrollTop - o.scrollSpeed;
10591				}
10592			}
10593
10594			if ( !o.axis || o.axis !== "y" ) {
10595				if ( ( i.overflowOffset.left + scrollParent.offsetWidth ) - event.pageX <
10596						o.scrollSensitivity ) {
10597					scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft + o.scrollSpeed;
10598				} else if ( event.pageX - i.overflowOffset.left < o.scrollSensitivity ) {
10599					scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft - o.scrollSpeed;
10600				}
10601			}
10602
10603		} else {
10604
10605			if ( !o.axis || o.axis !== "x" ) {
10606				if ( event.pageY - $( document ).scrollTop() < o.scrollSensitivity ) {
10607					scrolled = $( document ).scrollTop( $( document ).scrollTop() - o.scrollSpeed );
10608				} else if ( $( window ).height() - ( event.pageY - $( document ).scrollTop() ) <
10609						o.scrollSensitivity ) {
10610					scrolled = $( document ).scrollTop( $( document ).scrollTop() + o.scrollSpeed );
10611				}
10612			}
10613
10614			if ( !o.axis || o.axis !== "y" ) {
10615				if ( event.pageX - $( document ).scrollLeft() < o.scrollSensitivity ) {
10616					scrolled = $( document ).scrollLeft(
10617						$( document ).scrollLeft() - o.scrollSpeed
10618					);
10619				} else if ( $( window ).width() - ( event.pageX - $( document ).scrollLeft() ) <
10620						o.scrollSensitivity ) {
10621					scrolled = $( document ).scrollLeft(
10622						$( document ).scrollLeft() + o.scrollSpeed
10623					);
10624				}
10625			}
10626
10627		}
10628
10629		if ( scrolled !== false && $.ui.ddmanager && !o.dropBehaviour ) {
10630			$.ui.ddmanager.prepareOffsets( i, event );
10631		}
10632
10633	}
10634} );
10635
10636$.ui.plugin.add( "draggable", "snap", {
10637	start: function( event, ui, i ) {
10638
10639		var o = i.options;
10640
10641		i.snapElements = [];
10642
10643		$( o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap )
10644			.each( function() {
10645				var $t = $( this ),
10646					$o = $t.offset();
10647				if ( this !== i.element[ 0 ] ) {
10648					i.snapElements.push( {
10649						item: this,
10650						width: $t.outerWidth(), height: $t.outerHeight(),
10651						top: $o.top, left: $o.left
10652					} );
10653				}
10654			} );
10655
10656	},
10657	drag: function( event, ui, inst ) {
10658
10659		var ts, bs, ls, rs, l, r, t, b, i, first,
10660			o = inst.options,
10661			d = o.snapTolerance,
10662			x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
10663			y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
10664
10665		for ( i = inst.snapElements.length - 1; i >= 0; i-- ) {
10666
10667			l = inst.snapElements[ i ].left - inst.margins.left;
10668			r = l + inst.snapElements[ i ].width;
10669			t = inst.snapElements[ i ].top - inst.margins.top;
10670			b = t + inst.snapElements[ i ].height;
10671
10672			if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d ||
10673					!$.contains( inst.snapElements[ i ].item.ownerDocument,
10674					inst.snapElements[ i ].item ) ) {
10675				if ( inst.snapElements[ i ].snapping ) {
10676					if ( inst.options.snap.release ) {
10677						inst.options.snap.release.call(
10678							inst.element,
10679							event,
10680							$.extend( inst._uiHash(), { snapItem: inst.snapElements[ i ].item } )
10681						);
10682					}
10683				}
10684				inst.snapElements[ i ].snapping = false;
10685				continue;
10686			}
10687
10688			if ( o.snapMode !== "inner" ) {
10689				ts = Math.abs( t - y2 ) <= d;
10690				bs = Math.abs( b - y1 ) <= d;
10691				ls = Math.abs( l - x2 ) <= d;
10692				rs = Math.abs( r - x1 ) <= d;
10693				if ( ts ) {
10694					ui.position.top = inst._convertPositionTo( "relative", {
10695						top: t - inst.helperProportions.height,
10696						left: 0
10697					} ).top;
10698				}
10699				if ( bs ) {
10700					ui.position.top = inst._convertPositionTo( "relative", {
10701						top: b,
10702						left: 0
10703					} ).top;
10704				}
10705				if ( ls ) {
10706					ui.position.left = inst._convertPositionTo( "relative", {
10707						top: 0,
10708						left: l - inst.helperProportions.width
10709					} ).left;
10710				}
10711				if ( rs ) {
10712					ui.position.left = inst._convertPositionTo( "relative", {
10713						top: 0,
10714						left: r
10715					} ).left;
10716				}
10717			}
10718
10719			first = ( ts || bs || ls || rs );
10720
10721			if ( o.snapMode !== "outer" ) {
10722				ts = Math.abs( t - y1 ) <= d;
10723				bs = Math.abs( b - y2 ) <= d;
10724				ls = Math.abs( l - x1 ) <= d;
10725				rs = Math.abs( r - x2 ) <= d;
10726				if ( ts ) {
10727					ui.position.top = inst._convertPositionTo( "relative", {
10728						top: t,
10729						left: 0
10730					} ).top;
10731				}
10732				if ( bs ) {
10733					ui.position.top = inst._convertPositionTo( "relative", {
10734						top: b - inst.helperProportions.height,
10735						left: 0
10736					} ).top;
10737				}
10738				if ( ls ) {
10739					ui.position.left = inst._convertPositionTo( "relative", {
10740						top: 0,
10741						left: l
10742					} ).left;
10743				}
10744				if ( rs ) {
10745					ui.position.left = inst._convertPositionTo( "relative", {
10746						top: 0,
10747						left: r - inst.helperProportions.width
10748					} ).left;
10749				}
10750			}
10751
10752			if ( !inst.snapElements[ i ].snapping && ( ts || bs || ls || rs || first ) ) {
10753				if ( inst.options.snap.snap ) {
10754					inst.options.snap.snap.call(
10755						inst.element,
10756						event,
10757						$.extend( inst._uiHash(), {
10758							snapItem: inst.snapElements[ i ].item
10759						} ) );
10760				}
10761			}
10762			inst.snapElements[ i ].snapping = ( ts || bs || ls || rs || first );
10763
10764		}
10765
10766	}
10767} );
10768
10769$.ui.plugin.add( "draggable", "stack", {
10770	start: function( event, ui, instance ) {
10771		var min,
10772			o = instance.options,
10773			group = $.makeArray( $( o.stack ) ).sort( function( a, b ) {
10774				return ( parseInt( $( a ).css( "zIndex" ), 10 ) || 0 ) -
10775					( parseInt( $( b ).css( "zIndex" ), 10 ) || 0 );
10776			} );
10777
10778		if ( !group.length ) {
10779			return;
10780		}
10781
10782		min = parseInt( $( group[ 0 ] ).css( "zIndex" ), 10 ) || 0;
10783		$( group ).each( function( i ) {
10784			$( this ).css( "zIndex", min + i );
10785		} );
10786		this.css( "zIndex", ( min + group.length ) );
10787	}
10788} );
10789
10790$.ui.plugin.add( "draggable", "zIndex", {
10791	start: function( event, ui, instance ) {
10792		var t = $( ui.helper ),
10793			o = instance.options;
10794
10795		if ( t.css( "zIndex" ) ) {
10796			o._zIndex = t.css( "zIndex" );
10797		}
10798		t.css( "zIndex", o.zIndex );
10799	},
10800	stop: function( event, ui, instance ) {
10801		var o = instance.options;
10802
10803		if ( o._zIndex ) {
10804			$( ui.helper ).css( "zIndex", o._zIndex );
10805		}
10806	}
10807} );
10808
10809var widgetsDraggable = $.ui.draggable;
10810
10811
10812/*!
10813 * jQuery UI Resizable 1.14.0
10814 * https://jqueryui.com
vendor: 18,093 bytes, lines 10815-11525
10815 *
10816 * Copyright OpenJS Foundation and other contributors
10817 * Released under the MIT license.
10818 * https://jquery.org/license
10819 */
10820
10821//>>label: Resizable
10822//>>group: Interactions
10823//>>description: Enables resize functionality for any element.
10824//>>docs: https://api.jqueryui.com/resizable/
10825//>>demos: https://jqueryui.com/resizable/
10826//>>css.structure: ../../themes/base/core.css
10827//>>css.structure: ../../themes/base/resizable.css
10828//>>css.theme: ../../themes/base/theme.css
10829
10830
10831$.widget( "ui.resizable", $.ui.mouse, {
10832	version: "1.14.0",
10833	widgetEventPrefix: "resize",
10834	options: {
10835		alsoResize: false,
10836		animate: false,
10837		animateDuration: "slow",
10838		animateEasing: "swing",
10839		aspectRatio: false,
10840		autoHide: false,
10841		classes: {
10842			"ui-resizable-se": "ui-icon ui-icon-gripsmall-diagonal-se"
10843		},
10844		containment: false,
10845		ghost: false,
10846		grid: false,
10847		handles: "e,s,se",
10848		helper: false,
10849		maxHeight: null,
10850		maxWidth: null,
10851		minHeight: 10,
10852		minWidth: 10,
10853
10854		// See #7960
10855		zIndex: 90,
10856
10857		// Callbacks
10858		resize: null,
10859		start: null,
10860		stop: null
10861	},
10862
10863	_num: function( value ) {
10864		return parseFloat( value ) || 0;
10865	},
10866
10867	_isNumber: function( value ) {
10868		return !isNaN( parseFloat( value ) );
10869	},
10870
10871	_hasScroll: function( el, a ) {
10872
10873		if ( $( el ).css( "overflow" ) === "hidden" ) {
10874			return false;
10875		}
10876
10877		var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
10878			has = false;
10879
10880		if ( el[ scroll ] > 0 ) {
10881			return true;
10882		}
10883
10884		// TODO: determine which cases actually cause this to happen
10885		// if the element doesn't have the scroll set, see if it's possible to
10886		// set the scroll
10887		try {
10888			el[ scroll ] = 1;
10889			has = ( el[ scroll ] > 0 );
10890			el[ scroll ] = 0;
10891		} catch ( e ) {
10892
10893			// `el` might be a string, then setting `scroll` will throw
10894			// an error in strict mode; ignore it.
10895		}
10896		return has;
10897	},
10898
10899	_create: function() {
10900
10901		var margins,
10902			o = this.options,
10903			that = this;
10904		this._addClass( "ui-resizable" );
10905
10906		$.extend( this, {
10907			_aspectRatio: !!( o.aspectRatio ),
10908			aspectRatio: o.aspectRatio,
10909			originalElement: this.element,
10910			_proportionallyResizeElements: [],
10911			_helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null
10912		} );
10913
10914		// Wrap the element if it cannot hold child nodes
10915		if ( this.element[ 0 ].nodeName.match( /^(canvas|textarea|input|select|button|img)$/i ) ) {
10916
10917			this.element.wrap(
10918				$( "<div class='ui-wrapper'></div>" ).css( {
10919					overflow: "hidden",
10920					position: this.element.css( "position" ),
10921					width: this.element.outerWidth(),
10922					height: this.element.outerHeight(),
10923					top: this.element.css( "top" ),
10924					left: this.element.css( "left" )
10925				} )
10926			);
10927
10928			this.element = this.element.parent().data(
10929				"ui-resizable", this.element.resizable( "instance" )
10930			);
10931
10932			this.elementIsWrapper = true;
10933
10934			margins = {
10935				marginTop: this.originalElement.css( "marginTop" ),
10936				marginRight: this.originalElement.css( "marginRight" ),
10937				marginBottom: this.originalElement.css( "marginBottom" ),
10938				marginLeft: this.originalElement.css( "marginLeft" )
10939			};
10940
10941			this.element.css( margins );
10942
10943			// Support: Safari
10944			// Prevent Safari textarea resize
10945			this.originalResizeStyle = this.originalElement.css( "resize" );
10946			this.originalElement.css( "resize", "none" );
10947
10948			this._proportionallyResizeElements.push( this.originalElement.css( {
10949				position: "static",
10950				zoom: 1,
10951				display: "block"
10952			} ) );
10953
10954			this._proportionallyResize();
10955		}
10956
10957		this._setupHandles();
10958
10959		if ( o.autoHide ) {
10960			$( this.element )
10961				.on( "mouseenter", function() {
10962					if ( o.disabled ) {
10963						return;
10964					}
10965					that._removeClass( "ui-resizable-autohide" );
10966					that._handles.show();
10967				} )
10968				.on( "mouseleave", function() {
10969					if ( o.disabled ) {
10970						return;
10971					}
10972					if ( !that.resizing ) {
10973						that._addClass( "ui-resizable-autohide" );
10974						that._handles.hide();
10975					}
10976				} );
10977		}
10978
10979		this._mouseInit();
10980	},
10981
10982	_destroy: function() {
10983
10984		this._mouseDestroy();
10985		this._addedHandles.remove();
10986
10987		var wrapper,
10988			_destroy = function( exp ) {
10989				$( exp )
10990					.removeData( "resizable" )
10991					.removeData( "ui-resizable" )
10992					.off( ".resizable" );
10993			};
10994
10995		// TODO: Unwrap at same DOM position
10996		if ( this.elementIsWrapper ) {
10997			_destroy( this.element );
10998			wrapper = this.element;
10999			this.originalElement.css( {
11000				position: wrapper.css( "position" ),
11001				width: wrapper.outerWidth(),
11002				height: wrapper.outerHeight(),
11003				top: wrapper.css( "top" ),
11004				left: wrapper.css( "left" )
11005			} ).insertAfter( wrapper );
11006			wrapper.remove();
11007		}
11008
11009		this.originalElement.css( "resize", this.originalResizeStyle );
11010		_destroy( this.originalElement );
11011
11012		return this;
11013	},
11014
11015	_setOption: function( key, value ) {
11016		this._super( key, value );
11017
11018		switch ( key ) {
11019		case "handles":
11020			this._removeHandles();
11021			this._setupHandles();
11022			break;
11023		case "aspectRatio":
11024			this._aspectRatio = !!value;
11025			break;
11026		default:
11027			break;
11028		}
11029	},
11030
11031	_setupHandles: function() {
11032		var o = this.options, handle, i, n, hname, axis, that = this;
11033		this.handles = o.handles ||
11034			( !$( ".ui-resizable-handle", this.element ).length ?
11035				"e,s,se" : {
11036					n: ".ui-resizable-n",
11037					e: ".ui-resizable-e",
11038					s: ".ui-resizable-s",
11039					w: ".ui-resizable-w",
11040					se: ".ui-resizable-se",
11041					sw: ".ui-resizable-sw",
11042					ne: ".ui-resizable-ne",
11043					nw: ".ui-resizable-nw"
11044				} );
11045
11046		this._handles = $();
11047		this._addedHandles = $();
11048		if ( this.handles.constructor === String ) {
11049
11050			if ( this.handles === "all" ) {
11051				this.handles = "n,e,s,w,se,sw,ne,nw";
11052			}
11053
11054			n = this.handles.split( "," );
11055			this.handles = {};
11056
11057			for ( i = 0; i < n.length; i++ ) {
11058
11059				handle = String.prototype.trim.call( n[ i ] );
11060				hname = "ui-resizable-" + handle;
11061				axis = $( "<div>" );
11062				this._addClass( axis, "ui-resizable-handle " + hname );
11063
11064				axis.css( { zIndex: o.zIndex } );
11065
11066				this.handles[ handle ] = ".ui-resizable-" + handle;
11067				if ( !this.element.children( this.handles[ handle ] ).length ) {
11068					this.element.append( axis );
11069					this._addedHandles = this._addedHandles.add( axis );
11070				}
11071			}
11072
11073		}
11074
11075		this._renderAxis = function( target ) {
11076
11077			var i, axis, padPos, padWrapper;
11078
11079			target = target || this.element;
11080
11081			for ( i in this.handles ) {
11082
11083				if ( this.handles[ i ].constructor === String ) {
11084					this.handles[ i ] = this.element.children( this.handles[ i ] ).first().show();
11085				} else if ( this.handles[ i ].jquery || this.handles[ i ].nodeType ) {
11086					this.handles[ i ] = $( this.handles[ i ] );
11087					this._on( this.handles[ i ], { "mousedown": that._mouseDown } );
11088				}
11089
11090				if ( this.elementIsWrapper &&
11091						this.originalElement[ 0 ]
11092							.nodeName
11093							.match( /^(textarea|input|select|button)$/i ) ) {
11094					axis = $( this.handles[ i ], this.element );
11095
11096					padWrapper = /sw|ne|nw|se|n|s/.test( i ) ?
11097						axis.outerHeight() :
11098						axis.outerWidth();
11099
11100					padPos = [ "padding",
11101						/ne|nw|n/.test( i ) ? "Top" :
11102						/se|sw|s/.test( i ) ? "Bottom" :
11103						/^e$/.test( i ) ? "Right" : "Left" ].join( "" );
11104
11105					target.css( padPos, padWrapper );
11106
11107					this._proportionallyResize();
11108				}
11109
11110				this._handles = this._handles.add( this.handles[ i ] );
11111			}
11112		};
11113
11114		// TODO: make renderAxis a prototype function
11115		this._renderAxis( this.element );
11116
11117		this._handles = this._handles.add( this.element.find( ".ui-resizable-handle" ) );
11118		this._handles.disableSelection();
11119
11120		this._handles.on( "mouseover", function() {
11121			if ( !that.resizing ) {
11122				if ( this.className ) {
11123					axis = this.className.match( /ui-resizable-(se|sw|ne|nw|n|e|s|w)/i );
11124				}
11125				that.axis = axis && axis[ 1 ] ? axis[ 1 ] : "se";
11126			}
11127		} );
11128
11129		if ( o.autoHide ) {
11130			this._handles.hide();
11131			this._addClass( "ui-resizable-autohide" );
11132		}
11133	},
11134
11135	_removeHandles: function() {
11136		this._addedHandles.remove();
11137	},
11138
11139	_mouseCapture: function( event ) {
11140		var i, handle,
11141			capture = false;
11142
11143		for ( i in this.handles ) {
11144			handle = $( this.handles[ i ] )[ 0 ];
11145			if ( handle === event.target || $.contains( handle, event.target ) ) {
11146				capture = true;
11147			}
11148		}
11149
11150		return !this.options.disabled && capture;
11151	},
11152
11153	_mouseStart: function( event ) {
11154
11155		var curleft, curtop, cursor,
11156			o = this.options,
11157			el = this.element;
11158
11159		this.resizing = true;
11160
11161		this._renderProxy();
11162
11163		curleft = this._num( this.helper.css( "left" ) );
11164		curtop = this._num( this.helper.css( "top" ) );
11165
11166		if ( o.containment ) {
11167			curleft += $( o.containment ).scrollLeft() || 0;
11168			curtop += $( o.containment ).scrollTop() || 0;
11169		}
11170
11171		this.offset = this.helper.offset();
11172		this.position = { left: curleft, top: curtop };
11173
11174		this.size = this._helper ? {
11175				width: this.helper.width(),
11176				height: this.helper.height()
11177			} : {
11178				width: el.width(),
11179				height: el.height()
11180			};
11181
11182		this.originalSize = this._helper ? {
11183				width: el.outerWidth(),
11184				height: el.outerHeight()
11185			} : {
11186				width: el.width(),
11187				height: el.height()
11188			};
11189
11190		this.sizeDiff = {
11191			width: el.outerWidth() - el.width(),
11192			height: el.outerHeight() - el.height()
11193		};
11194
11195		this.originalPosition = { left: curleft, top: curtop };
11196		this.originalMousePosition = { left: event.pageX, top: event.pageY };
11197
11198		this.aspectRatio = ( typeof o.aspectRatio === "number" ) ?
11199			o.aspectRatio :
11200			( ( this.originalSize.width / this.originalSize.height ) || 1 );
11201
11202		cursor = $( ".ui-resizable-" + this.axis ).css( "cursor" );
11203		$( "body" ).css( "cursor", cursor === "auto" ? this.axis + "-resize" : cursor );
11204
11205		this._addClass( "ui-resizable-resizing" );
11206		this._propagate( "start", event );
11207		return true;
11208	},
11209
11210	_mouseDrag: function( event ) {
11211
11212		var data, props,
11213			smp = this.originalMousePosition,
11214			a = this.axis,
11215			dx = ( event.pageX - smp.left ) || 0,
11216			dy = ( event.pageY - smp.top ) || 0,
11217			trigger = this._change[ a ];
11218
11219		this._updatePrevProperties();
11220
11221		if ( !trigger ) {
11222			return false;
11223		}
11224
11225		data = trigger.apply( this, [ event, dx, dy ] );
11226
11227		this._updateVirtualBoundaries( event.shiftKey );
11228		if ( this._aspectRatio || event.shiftKey ) {
11229			data = this._updateRatio( data, event );
11230		}
11231
11232		data = this._respectSize( data, event );
11233
11234		this._updateCache( data );
11235
11236		this._propagate( "resize", event );
11237
11238		props = this._applyChanges();
11239
11240		if ( !this._helper && this._proportionallyResizeElements.length ) {
11241			this._proportionallyResize();
11242		}
11243
11244		if ( !$.isEmptyObject( props ) ) {
11245			this._updatePrevProperties();
11246			this._trigger( "resize", event, this.ui() );
11247			this._applyChanges();
11248		}
11249
11250		return false;
11251	},
11252
11253	_mouseStop: function( event ) {
11254
11255		this.resizing = false;
11256		var pr, ista, soffseth, soffsetw, s, left, top,
11257			o = this.options, that = this;
11258
11259		if ( this._helper ) {
11260
11261			pr = this._proportionallyResizeElements;
11262			ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName );
11263			soffseth = ista && this._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height;
11264			soffsetw = ista ? 0 : that.sizeDiff.width;
11265
11266			s = {
11267				width: ( that.helper.width()  - soffsetw ),
11268				height: ( that.helper.height() - soffseth )
11269			};
11270			left = ( parseFloat( that.element.css( "left" ) ) +
11271				( that.position.left - that.originalPosition.left ) ) || null;
11272			top = ( parseFloat( that.element.css( "top" ) ) +
11273				( that.position.top - that.originalPosition.top ) ) || null;
11274
11275			if ( !o.animate ) {
11276				this.element.css( $.extend( s, { top: top, left: left } ) );
11277			}
11278
11279			that.helper.height( that.size.height );
11280			that.helper.width( that.size.width );
11281
11282			if ( this._helper && !o.animate ) {
11283				this._proportionallyResize();
11284			}
11285		}
11286
11287		$( "body" ).css( "cursor", "auto" );
11288
11289		this._removeClass( "ui-resizable-resizing" );
11290
11291		this._propagate( "stop", event );
11292
11293		if ( this._helper ) {
11294			this.helper.remove();
11295		}
11296
11297		return false;
11298
11299	},
11300
11301	_updatePrevProperties: function() {
11302		this.prevPosition = {
11303			top: this.position.top,
11304			left: this.position.left
11305		};
11306		this.prevSize = {
11307			width: this.size.width,
11308			height: this.size.height
11309		};
11310	},
11311
11312	_applyChanges: function() {
11313		var props = {};
11314
11315		if ( this.position.top !== this.prevPosition.top ) {
11316			props.top = this.position.top + "px";
11317		}
11318		if ( this.position.left !== this.prevPosition.left ) {
11319			props.left = this.position.left + "px";
11320		}
11321
11322		this.helper.css( props );
11323
11324		if ( this.size.width !== this.prevSize.width ) {
11325			props.width = this.size.width + "px";
11326			this.helper.width( props.width );
11327		}
11328		if ( this.size.height !== this.prevSize.height ) {
11329			props.height = this.size.height + "px";
11330			this.helper.height( props.height );
11331		}
11332
11333		return props;
11334	},
11335
11336	_updateVirtualBoundaries: function( forceAspectRatio ) {
11337		var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b,
11338			o = this.options;
11339
11340		b = {
11341			minWidth: this._isNumber( o.minWidth ) ? o.minWidth : 0,
11342			maxWidth: this._isNumber( o.maxWidth ) ? o.maxWidth : Infinity,
11343			minHeight: this._isNumber( o.minHeight ) ? o.minHeight : 0,
11344			maxHeight: this._isNumber( o.maxHeight ) ? o.maxHeight : Infinity
11345		};
11346
11347		if ( this._aspectRatio || forceAspectRatio ) {
11348			pMinWidth = b.minHeight * this.aspectRatio;
11349			pMinHeight = b.minWidth / this.aspectRatio;
11350			pMaxWidth = b.maxHeight * this.aspectRatio;
11351			pMaxHeight = b.maxWidth / this.aspectRatio;
11352
11353			if ( pMinWidth > b.minWidth ) {
11354				b.minWidth = pMinWidth;
11355			}
11356			if ( pMinHeight > b.minHeight ) {
11357				b.minHeight = pMinHeight;
11358			}
11359			if ( pMaxWidth < b.maxWidth ) {
11360				b.maxWidth = pMaxWidth;
11361			}
11362			if ( pMaxHeight < b.maxHeight ) {
11363				b.maxHeight = pMaxHeight;
11364			}
11365		}
11366		this._vBoundaries = b;
11367	},
11368
11369	_updateCache: function( data ) {
11370		this.offset = this.helper.offset();
11371		if ( this._isNumber( data.left ) ) {
11372			this.position.left = data.left;
11373		}
11374		if ( this._isNumber( data.top ) ) {
11375			this.position.top = data.top;
11376		}
11377		if ( this._isNumber( data.height ) ) {
11378			this.size.height = data.height;
11379		}
11380		if ( this._isNumber( data.width ) ) {
11381			this.size.width = data.width;
11382		}
11383	},
11384
11385	_updateRatio: function( data ) {
11386
11387		var cpos = this.position,
11388			csize = this.size,
11389			a = this.axis;
11390
11391		if ( this._isNumber( data.height ) ) {
11392			data.width = ( data.height * this.aspectRatio );
11393		} else if ( this._isNumber( data.width ) ) {
11394			data.height = ( data.width / this.aspectRatio );
11395		}
11396
11397		if ( a === "sw" ) {
11398			data.left = cpos.left + ( csize.width - data.width );
11399			data.top = null;
11400		}
11401		if ( a === "nw" ) {
11402			data.top = cpos.top + ( csize.height - data.height );
11403			data.left = cpos.left + ( csize.width - data.width );
11404		}
11405
11406		return data;
11407	},
11408
11409	_respectSize: function( data ) {
11410
11411		var o = this._vBoundaries,
11412			a = this.axis,
11413			ismaxw = this._isNumber( data.width ) && o.maxWidth && ( o.maxWidth < data.width ),
11414			ismaxh = this._isNumber( data.height ) && o.maxHeight && ( o.maxHeight < data.height ),
11415			isminw = this._isNumber( data.width ) && o.minWidth && ( o.minWidth > data.width ),
11416			isminh = this._isNumber( data.height ) && o.minHeight && ( o.minHeight > data.height ),
11417			dw = this.originalPosition.left + this.originalSize.width,
11418			dh = this.originalPosition.top + this.originalSize.height,
11419			cw = /sw|nw|w/.test( a ), ch = /nw|ne|n/.test( a );
11420		if ( isminw ) {
11421			data.width = o.minWidth;
11422		}
11423		if ( isminh ) {
11424			data.height = o.minHeight;
11425		}
11426		if ( ismaxw ) {
11427			data.width = o.maxWidth;
11428		}
11429		if ( ismaxh ) {
11430			data.height = o.maxHeight;
11431		}
11432
11433		if ( isminw && cw ) {
11434			data.left = dw - o.minWidth;
11435		}
11436		if ( ismaxw && cw ) {
11437			data.left = dw - o.maxWidth;
11438		}
11439		if ( isminh && ch ) {
11440			data.top = dh - o.minHeight;
11441		}
11442		if ( ismaxh && ch ) {
11443			data.top = dh - o.maxHeight;
11444		}
11445
11446		// Fixing jump error on top/left - bug #2330
11447		if ( !data.width && !data.height && !data.left && data.top ) {
11448			data.top = null;
11449		} else if ( !data.width && !data.height && !data.top && data.left ) {
11450			data.left = null;
11451		}
11452
11453		return data;
11454	},
11455
11456	_getPaddingPlusBorderDimensions: function( element ) {
11457		var i = 0,
11458			widths = [],
11459			borders = [
11460				element.css( "borderTopWidth" ),
11461				element.css( "borderRightWidth" ),
11462				element.css( "borderBottomWidth" ),
11463				element.css( "borderLeftWidth" )
11464			],
11465			paddings = [
11466				element.css( "paddingTop" ),
11467				element.css( "paddingRight" ),
11468				element.css( "paddingBottom" ),
11469				element.css( "paddingLeft" )
11470			];
11471
11472		for ( ; i < 4; i++ ) {
11473			widths[ i ] = ( parseFloat( borders[ i ] ) || 0 );
11474			widths[ i ] += ( parseFloat( paddings[ i ] ) || 0 );
11475		}
11476
11477		return {
11478			height: widths[ 0 ] + widths[ 2 ],
11479			width: widths[ 1 ] + widths[ 3 ]
11480		};
11481	},
11482
11483	_proportionallyResize: function() {
11484
11485		if ( !this._proportionallyResizeElements.length ) {
11486			return;
11487		}
11488
11489		var prel,
11490			i = 0,
11491			element = this.helper || this.element;
11492
11493		for ( ; i < this._proportionallyResizeElements.length; i++ ) {
11494
11495			prel = this._proportionallyResizeElements[ i ];
11496
11497			// TODO: Seems like a bug to cache this.outerDimensions
11498			// considering that we are in a loop.
11499			if ( !this.outerDimensions ) {
11500				this.outerDimensions = this._getPaddingPlusBorderDimensions( prel );
11501			}
11502
11503			prel.css( {
11504				height: ( element.height() - this.outerDimensions.height ) || 0,
11505				width: ( element.width() - this.outerDimensions.width ) || 0
11506			} );
11507
11508		}
11509
11510	},
11511
11512	_renderProxy: function() {
11513
11514		var el = this.element, o = this.options;
11515		this.elementOffset = el.offset();
11516
11517		if ( this._helper ) {
11518
11519			this.helper = this.helper || $( "<div></div>" ).css( { overflow: "hidden" } );
11520
11521			this._addClass( this.helper, this._helper );
11522			this.helper.css( {
11523				width: this.element.outerWidth(),
11524				height: this.element.outerHeight(),
11525				position: "absolute",
vendor: 6,636 bytes, lines 11526-11766
11526				left: this.elementOffset.left + "px",
11527				top: this.elementOffset.top + "px",
11528				zIndex: ++o.zIndex //TODO: Don't modify option
11529			} );
11530
11531			this.helper
11532				.appendTo( "body" )
11533				.disableSelection();
11534
11535		} else {
11536			this.helper = this.element;
11537		}
11538
11539	},
11540
11541	_change: {
11542		e: function( event, dx ) {
11543			return { width: this.originalSize.width + dx };
11544		},
11545		w: function( event, dx ) {
11546			var cs = this.originalSize, sp = this.originalPosition;
11547			return { left: sp.left + dx, width: cs.width - dx };
11548		},
11549		n: function( event, dx, dy ) {
11550			var cs = this.originalSize, sp = this.originalPosition;
11551			return { top: sp.top + dy, height: cs.height - dy };
11552		},
11553		s: function( event, dx, dy ) {
11554			return { height: this.originalSize.height + dy };
11555		},
11556		se: function( event, dx, dy ) {
11557			return $.extend( this._change.s.apply( this, arguments ),
11558				this._change.e.apply( this, [ event, dx, dy ] ) );
11559		},
11560		sw: function( event, dx, dy ) {
11561			return $.extend( this._change.s.apply( this, arguments ),
11562				this._change.w.apply( this, [ event, dx, dy ] ) );
11563		},
11564		ne: function( event, dx, dy ) {
11565			return $.extend( this._change.n.apply( this, arguments ),
11566				this._change.e.apply( this, [ event, dx, dy ] ) );
11567		},
11568		nw: function( event, dx, dy ) {
11569			return $.extend( this._change.n.apply( this, arguments ),
11570				this._change.w.apply( this, [ event, dx, dy ] ) );
11571		}
11572	},
11573
11574	_propagate: function( n, event ) {
11575		$.ui.plugin.call( this, n, [ event, this.ui() ] );
11576		if ( n !== "resize" ) {
11577			this._trigger( n, event, this.ui() );
11578		}
11579	},
11580
11581	plugins: {},
11582
11583	ui: function() {
11584		return {
11585			originalElement: this.originalElement,
11586			element: this.element,
11587			helper: this.helper,
11588			position: this.position,
11589			size: this.size,
11590			originalSize: this.originalSize,
11591			originalPosition: this.originalPosition
11592		};
11593	}
11594
11595} );
11596
11597/*
11598 * Resizable Extensions
11599 */
11600
11601$.ui.plugin.add( "resizable", "animate", {
11602
11603	stop: function( event ) {
11604		var that = $( this ).resizable( "instance" ),
11605			o = that.options,
11606			pr = that._proportionallyResizeElements,
11607			ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName ),
11608			soffseth = ista && that._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height,
11609			soffsetw = ista ? 0 : that.sizeDiff.width,
11610			style = {
11611				width: ( that.size.width - soffsetw ),
11612				height: ( that.size.height - soffseth )
11613			},
11614			left = ( parseFloat( that.element.css( "left" ) ) +
11615				( that.position.left - that.originalPosition.left ) ) || null,
11616			top = ( parseFloat( that.element.css( "top" ) ) +
11617				( that.position.top - that.originalPosition.top ) ) || null;
11618
11619		that.element.animate(
11620			$.extend( style, top && left ? { top: top, left: left } : {} ), {
11621				duration: o.animateDuration,
11622				easing: o.animateEasing,
11623				step: function() {
11624
11625					var data = {
11626						width: parseFloat( that.element.css( "width" ) ),
11627						height: parseFloat( that.element.css( "height" ) ),
11628						top: parseFloat( that.element.css( "top" ) ),
11629						left: parseFloat( that.element.css( "left" ) )
11630					};
11631
11632					if ( pr && pr.length ) {
11633						$( pr[ 0 ] ).css( { width: data.width, height: data.height } );
11634					}
11635
11636					// Propagating resize, and updating values for each animation step
11637					that._updateCache( data );
11638					that._propagate( "resize", event );
11639
11640				}
11641			}
11642		);
11643	}
11644
11645} );
11646
11647$.ui.plugin.add( "resizable", "containment", {
11648
11649	start: function() {
11650		var element, p, co, ch, cw, width, height,
11651			that = $( this ).resizable( "instance" ),
11652			o = that.options,
11653			el = that.element,
11654			oc = o.containment,
11655			ce = ( oc instanceof $ ) ?
11656				oc.get( 0 ) :
11657				( /parent/.test( oc ) ) ? el.parent().get( 0 ) : oc;
11658
11659		if ( !ce ) {
11660			return;
11661		}
11662
11663		that.containerElement = $( ce );
11664
11665		if ( /document/.test( oc ) || oc === document ) {
11666			that.containerOffset = {
11667				left: 0,
11668				top: 0
11669			};
11670			that.containerPosition = {
11671				left: 0,
11672				top: 0
11673			};
11674
11675			that.parentData = {
11676				element: $( document ),
11677				left: 0,
11678				top: 0,
11679				width: $( document ).width(),
11680				height: $( document ).height() || document.body.parentNode.scrollHeight
11681			};
11682		} else {
11683			element = $( ce );
11684			p = [];
11685			$( [ "Top", "Right", "Left", "Bottom" ] ).each( function( i, name ) {
11686				p[ i ] = that._num( element.css( "padding" + name ) );
11687			} );
11688
11689			that.containerOffset = element.offset();
11690			that.containerPosition = element.position();
11691			that.containerSize = {
11692				height: ( element.innerHeight() - p[ 3 ] ),
11693				width: ( element.innerWidth() - p[ 1 ] )
11694			};
11695
11696			co = that.containerOffset;
11697			ch = that.containerSize.height;
11698			cw = that.containerSize.width;
11699			width = ( that._hasScroll( ce, "left" ) ? ce.scrollWidth : cw );
11700			height = ( that._hasScroll( ce ) ? ce.scrollHeight : ch );
11701
11702			that.parentData = {
11703				element: ce,
11704				left: co.left,
11705				top: co.top,
11706				width: width,
11707				height: height
11708			};
11709		}
11710	},
11711
11712	resize: function( event ) {
11713		var woset, hoset, isParent, isOffsetRelative,
11714			that = $( this ).resizable( "instance" ),
11715			o = that.options,
11716			co = that.containerOffset,
11717			cp = that.position,
11718			pRatio = that._aspectRatio || event.shiftKey,
11719			cop = {
11720				top: 0,
11721				left: 0
11722			},
11723			ce = that.containerElement,
11724			continueResize = true;
11725
11726		if ( ce[ 0 ] !== document && ( /static/ ).test( ce.css( "position" ) ) ) {
11727			cop = co;
11728		}
11729
11730		if ( cp.left < ( that._helper ? co.left : 0 ) ) {
11731			that.size.width = that.size.width +
11732				( that._helper ?
11733					( that.position.left - co.left ) :
11734					( that.position.left - cop.left ) );
11735
11736			if ( pRatio ) {
11737				that.size.height = that.size.width / that.aspectRatio;
11738				continueResize = false;
11739			}
11740			that.position.left = o.helper ? co.left : 0;
11741		}
11742
11743		if ( cp.top < ( that._helper ? co.top : 0 ) ) {
11744			that.size.height = that.size.height +
11745				( that._helper ?
11746					( that.position.top - co.top ) :
11747					that.position.top );
11748
11749			if ( pRatio ) {
11750				that.size.width = that.size.height * that.aspectRatio;
11751				continueResize = false;
11752			}
11753			that.position.top = that._helper ? co.top : 0;
11754		}
11755
11756		isParent = that.containerElement.get( 0 ) === that.element.parent().get( 0 );
11757		isOffsetRelative = /relative|absolute/.test( that.containerElement.css( "position" ) );
11758
11759		if ( isParent && isOffsetRelative ) {
11760			that.offset.left = that.parentData.left + that.position.left;
11761			that.offset.top = that.parentData.top + that.position.top;
11762		} else {
11763			that.offset.left = that.element.offset().left;
11764			that.offset.top = that.element.offset().top;
11765		}
11766
vendor: 4,546 bytes, lines 11767-11941
11767		woset = Math.abs( that.sizeDiff.width +
11768			( that._helper ?
11769				that.offset.left - cop.left :
11770				( that.offset.left - co.left ) ) );
11771
11772		hoset = Math.abs( that.sizeDiff.height +
11773			( that._helper ?
11774				that.offset.top - cop.top :
11775				( that.offset.top - co.top ) ) );
11776
11777		if ( woset + that.size.width >= that.parentData.width ) {
11778			that.size.width = that.parentData.width - woset;
11779			if ( pRatio ) {
11780				that.size.height = that.size.width / that.aspectRatio;
11781				continueResize = false;
11782			}
11783		}
11784
11785		if ( hoset + that.size.height >= that.parentData.height ) {
11786			that.size.height = that.parentData.height - hoset;
11787			if ( pRatio ) {
11788				that.size.width = that.size.height * that.aspectRatio;
11789				continueResize = false;
11790			}
11791		}
11792
11793		if ( !continueResize ) {
11794			that.position.left = that.prevPosition.left;
11795			that.position.top = that.prevPosition.top;
11796			that.size.width = that.prevSize.width;
11797			that.size.height = that.prevSize.height;
11798		}
11799	},
11800
11801	stop: function() {
11802		var that = $( this ).resizable( "instance" ),
11803			o = that.options,
11804			co = that.containerOffset,
11805			cop = that.containerPosition,
11806			ce = that.containerElement,
11807			helper = $( that.helper ),
11808			ho = helper.offset(),
11809			w = helper.outerWidth() - that.sizeDiff.width,
11810			h = helper.outerHeight() - that.sizeDiff.height;
11811
11812		if ( that._helper && !o.animate && ( /relative/ ).test( ce.css( "position" ) ) ) {
11813			$( this ).css( {
11814				left: ho.left - cop.left - co.left,
11815				width: w,
11816				height: h
11817			} );
11818		}
11819
11820		if ( that._helper && !o.animate && ( /static/ ).test( ce.css( "position" ) ) ) {
11821			$( this ).css( {
11822				left: ho.left - cop.left - co.left,
11823				width: w,
11824				height: h
11825			} );
11826		}
11827	}
11828} );
11829
11830$.ui.plugin.add( "resizable", "alsoResize", {
11831
11832	start: function() {
11833		var that = $( this ).resizable( "instance" ),
11834			o = that.options;
11835
11836		$( o.alsoResize ).each( function() {
11837			var el = $( this );
11838			el.data( "ui-resizable-alsoresize", {
11839				width: parseFloat( el.css( "width" ) ), height: parseFloat( el.css( "height" ) ),
11840				left: parseFloat( el.css( "left" ) ), top: parseFloat( el.css( "top" ) )
11841			} );
11842		} );
11843	},
11844
11845	resize: function( event, ui ) {
11846		var that = $( this ).resizable( "instance" ),
11847			o = that.options,
11848			os = that.originalSize,
11849			op = that.originalPosition,
11850			delta = {
11851				height: ( that.size.height - os.height ) || 0,
11852				width: ( that.size.width - os.width ) || 0,
11853				top: ( that.position.top - op.top ) || 0,
11854				left: ( that.position.left - op.left ) || 0
11855			};
11856
11857			$( o.alsoResize ).each( function() {
11858				var el = $( this ), start = $( this ).data( "ui-resizable-alsoresize" ), style = {},
11859					css = el.parents( ui.originalElement[ 0 ] ).length ?
11860							[ "width", "height" ] :
11861							[ "width", "height", "top", "left" ];
11862
11863				$.each( css, function( i, prop ) {
11864					var sum = ( start[ prop ] || 0 ) + ( delta[ prop ] || 0 );
11865					if ( sum && sum >= 0 ) {
11866						style[ prop ] = sum || null;
11867					}
11868				} );
11869
11870				el.css( style );
11871			} );
11872	},
11873
11874	stop: function() {
11875		$( this ).removeData( "ui-resizable-alsoresize" );
11876	}
11877} );
11878
11879$.ui.plugin.add( "resizable", "ghost", {
11880
11881	start: function() {
11882
11883		var that = $( this ).resizable( "instance" ), cs = that.size;
11884
11885		that.ghost = that.originalElement.clone();
11886		that.ghost.css( {
11887			opacity: 0.25,
11888			display: "block",
11889			position: "relative",
11890			height: cs.height,
11891			width: cs.width,
11892			margin: 0,
11893			left: 0,
11894			top: 0
11895		} );
11896
11897		that._addClass( that.ghost, "ui-resizable-ghost" );
11898
11899		// DEPRECATED
11900		// TODO: remove after 1.12
11901		if ( $.uiBackCompat === true && typeof that.options.ghost === "string" ) {
11902
11903			// Ghost option
11904			that.ghost.addClass( this.options.ghost );
11905		}
11906
11907		that.ghost.appendTo( that.helper );
11908
11909	},
11910
11911	resize: function() {
11912		var that = $( this ).resizable( "instance" );
11913		if ( that.ghost ) {
11914			that.ghost.css( {
11915				position: "relative",
11916				height: that.size.height,
11917				width: that.size.width
11918			} );
11919		}
11920	},
11921
11922	stop: function() {
11923		var that = $( this ).resizable( "instance" );
11924		if ( that.ghost && that.helper ) {
11925			that.helper.get( 0 ).removeChild( that.ghost.get( 0 ) );
11926		}
11927	}
11928
11929} );
11930
11931$.ui.plugin.add( "resizable", "grid", {
11932
11933	resize: function() {
11934		var outerDimensions,
11935			that = $( this ).resizable( "instance" ),
11936			o = that.options,
11937			cs = that.size,
11938			os = that.originalSize,
11939			op = that.originalPosition,
11940			a = that.axis,
11941			grid = typeof o.grid === "number" ? [ o.grid, o.grid ] : o.grid,
vendor: 10,346 bytes, lines 11942-12350
11942			gridX = ( grid[ 0 ] || 1 ),
11943			gridY = ( grid[ 1 ] || 1 ),
11944			ox = Math.round( ( cs.width - os.width ) / gridX ) * gridX,
11945			oy = Math.round( ( cs.height - os.height ) / gridY ) * gridY,
11946			newWidth = os.width + ox,
11947			newHeight = os.height + oy,
11948			isMaxWidth = o.maxWidth && ( o.maxWidth < newWidth ),
11949			isMaxHeight = o.maxHeight && ( o.maxHeight < newHeight ),
11950			isMinWidth = o.minWidth && ( o.minWidth > newWidth ),
11951			isMinHeight = o.minHeight && ( o.minHeight > newHeight );
11952
11953		o.grid = grid;
11954
11955		if ( isMinWidth ) {
11956			newWidth += gridX;
11957		}
11958		if ( isMinHeight ) {
11959			newHeight += gridY;
11960		}
11961		if ( isMaxWidth ) {
11962			newWidth -= gridX;
11963		}
11964		if ( isMaxHeight ) {
11965			newHeight -= gridY;
11966		}
11967
11968		if ( /^(se|s|e)$/.test( a ) ) {
11969			that.size.width = newWidth;
11970			that.size.height = newHeight;
11971		} else if ( /^(ne)$/.test( a ) ) {
11972			that.size.width = newWidth;
11973			that.size.height = newHeight;
11974			that.position.top = op.top - oy;
11975		} else if ( /^(sw)$/.test( a ) ) {
11976			that.size.width = newWidth;
11977			that.size.height = newHeight;
11978			that.position.left = op.left - ox;
11979		} else {
11980			if ( newHeight - gridY <= 0 || newWidth - gridX <= 0 ) {
11981				outerDimensions = that._getPaddingPlusBorderDimensions( this );
11982			}
11983
11984			if ( newHeight - gridY > 0 ) {
11985				that.size.height = newHeight;
11986				that.position.top = op.top - oy;
11987			} else {
11988				newHeight = gridY - outerDimensions.height;
11989				that.size.height = newHeight;
11990				that.position.top = op.top + os.height - newHeight;
11991			}
11992			if ( newWidth - gridX > 0 ) {
11993				that.size.width = newWidth;
11994				that.position.left = op.left - ox;
11995			} else {
11996				newWidth = gridX - outerDimensions.width;
11997				that.size.width = newWidth;
11998				that.position.left = op.left + os.width - newWidth;
11999			}
12000		}
12001	}
12002
12003} );
12004
12005var widgetsResizable = $.ui.resizable;
12006
12007
12008/*!
12009 * jQuery UI Dialog 1.14.0
12010 * https://jqueryui.com
12011 *
12012 * Copyright OpenJS Foundation and other contributors
12013 * Released under the MIT license.
12014 * https://jquery.org/license
12015 */
12016
12017//>>label: Dialog
12018//>>group: Widgets
12019//>>description: Displays customizable dialog windows.
12020//>>docs: https://api.jqueryui.com/dialog/
12021//>>demos: https://jqueryui.com/dialog/
12022//>>css.structure: ../../themes/base/core.css
12023//>>css.structure: ../../themes/base/dialog.css
12024//>>css.theme: ../../themes/base/theme.css
12025
12026
12027$.widget( "ui.dialog", {
12028	version: "1.14.0",
12029	options: {
12030		appendTo: "body",
12031		autoOpen: true,
12032		buttons: [],
12033		classes: {
12034			"ui-dialog": "ui-corner-all",
12035			"ui-dialog-titlebar": "ui-corner-all"
12036		},
12037		closeOnEscape: true,
12038		closeText: "Close",
12039		draggable: true,
12040		hide: null,
12041		height: "auto",
12042		maxHeight: null,
12043		maxWidth: null,
12044		minHeight: 150,
12045		minWidth: 150,
12046		modal: false,
12047		position: {
12048			my: "center",
12049			at: "center",
12050			of: window,
12051			collision: "fit",
12052
12053			// Ensure the titlebar is always visible
12054			using: function( pos ) {
12055				var topOffset = $( this ).css( pos ).offset().top;
12056				if ( topOffset < 0 ) {
12057					$( this ).css( "top", pos.top - topOffset );
12058				}
12059			}
12060		},
12061		resizable: true,
12062		show: null,
12063		title: null,
12064		width: 300,
12065
12066		// Callbacks
12067		beforeClose: null,
12068		close: null,
12069		drag: null,
12070		dragStart: null,
12071		dragStop: null,
12072		focus: null,
12073		open: null,
12074		resize: null,
12075		resizeStart: null,
12076		resizeStop: null
12077	},
12078
12079	sizeRelatedOptions: {
12080		buttons: true,
12081		height: true,
12082		maxHeight: true,
12083		maxWidth: true,
12084		minHeight: true,
12085		minWidth: true,
12086		width: true
12087	},
12088
12089	resizableRelatedOptions: {
12090		maxHeight: true,
12091		maxWidth: true,
12092		minHeight: true,
12093		minWidth: true
12094	},
12095
12096	_create: function() {
12097		this.originalCss = {
12098			display: this.element[ 0 ].style.display,
12099			width: this.element[ 0 ].style.width,
12100			minHeight: this.element[ 0 ].style.minHeight,
12101			maxHeight: this.element[ 0 ].style.maxHeight,
12102			height: this.element[ 0 ].style.height
12103		};
12104		this.originalPosition = {
12105			parent: this.element.parent(),
12106			index: this.element.parent().children().index( this.element )
12107		};
12108		this.originalTitle = this.element.attr( "title" );
12109		if ( this.options.title == null && this.originalTitle != null ) {
12110			this.options.title = this.originalTitle;
12111		}
12112
12113		// Dialogs can't be disabled
12114		if ( this.options.disabled ) {
12115			this.options.disabled = false;
12116		}
12117
12118		this._createWrapper();
12119
12120		this.element
12121			.show()
12122			.removeAttr( "title" )
12123			.appendTo( this.uiDialog );
12124
12125		this._addClass( "ui-dialog-content", "ui-widget-content" );
12126
12127		this._createTitlebar();
12128		this._createButtonPane();
12129
12130		if ( this.options.draggable && $.fn.draggable ) {
12131			this._makeDraggable();
12132		}
12133		if ( this.options.resizable && $.fn.resizable ) {
12134			this._makeResizable();
12135		}
12136
12137		this._isOpen = false;
12138
12139		this._trackFocus();
12140	},
12141
12142	_init: function() {
12143		if ( this.options.autoOpen ) {
12144			this.open();
12145		}
12146	},
12147
12148	_appendTo: function() {
12149		var element = this.options.appendTo;
12150		if ( element && ( element.jquery || element.nodeType ) ) {
12151			return $( element );
12152		}
12153		return this.document.find( element || "body" ).eq( 0 );
12154	},
12155
12156	_destroy: function() {
12157		var next,
12158			originalPosition = this.originalPosition;
12159
12160		this._untrackInstance();
12161		this._destroyOverlay();
12162
12163		this.element
12164			.removeUniqueId()
12165			.css( this.originalCss )
12166
12167			// Without detaching first, the following becomes really slow
12168			.detach();
12169
12170		this.uiDialog.remove();
12171
12172		if ( this.originalTitle ) {
12173			this.element.attr( "title", this.originalTitle );
12174		}
12175
12176		next = originalPosition.parent.children().eq( originalPosition.index );
12177
12178		// Don't try to place the dialog next to itself (#8613)
12179		if ( next.length && next[ 0 ] !== this.element[ 0 ] ) {
12180			next.before( this.element );
12181		} else {
12182			originalPosition.parent.append( this.element );
12183		}
12184	},
12185
12186	widget: function() {
12187		return this.uiDialog;
12188	},
12189
12190	disable: $.noop,
12191	enable: $.noop,
12192
12193	close: function( event ) {
12194		var that = this;
12195
12196		if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) {
12197			return;
12198		}
12199
12200		this._isOpen = false;
12201		this._focusedElement = null;
12202		this._destroyOverlay();
12203		this._untrackInstance();
12204
12205		if ( !this.opener.filter( ":focusable" ).trigger( "focus" ).length ) {
12206
12207			// Hiding a focused element doesn't trigger blur in WebKit
12208			// so in case we have nothing to focus on, explicitly blur the active element
12209			// https://bugs.webkit.org/show_bug.cgi?id=47182
12210			$( this.document[ 0 ].activeElement ).trigger( "blur" );
12211		}
12212
12213		this._hide( this.uiDialog, this.options.hide, function() {
12214			that._trigger( "close", event );
12215		} );
12216	},
12217
12218	isOpen: function() {
12219		return this._isOpen;
12220	},
12221
12222	moveToTop: function() {
12223		this._moveToTop();
12224	},
12225
12226	_moveToTop: function( event, silent ) {
12227		var moved = false,
12228			zIndices = this.uiDialog.siblings( ".ui-front:visible" ).map( function() {
12229				return +$( this ).css( "z-index" );
12230			} ).get(),
12231			zIndexMax = Math.max.apply( null, zIndices );
12232
12233		if ( zIndexMax >= +this.uiDialog.css( "z-index" ) ) {
12234			this.uiDialog.css( "z-index", zIndexMax + 1 );
12235			moved = true;
12236		}
12237
12238		if ( moved && !silent ) {
12239			this._trigger( "focus", event );
12240		}
12241		return moved;
12242	},
12243
12244	open: function() {
12245		var that = this;
12246		if ( this._isOpen ) {
12247			if ( this._moveToTop() ) {
12248				this._focusTabbable();
12249			}
12250			return;
12251		}
12252
12253		this._isOpen = true;
12254		this.opener = $( this.document[ 0 ].activeElement );
12255
12256		this._size();
12257		this._position();
12258		this._createOverlay();
12259		this._moveToTop( null, true );
12260
12261		// Ensure the overlay is moved to the top with the dialog, but only when
12262		// opening. The overlay shouldn't move after the dialog is open so that
12263		// modeless dialogs opened after the modal dialog stack properly.
12264		if ( this.overlay ) {
12265			this.overlay.css( "z-index", this.uiDialog.css( "z-index" ) - 1 );
12266		}
12267
12268		this._show( this.uiDialog, this.options.show, function() {
12269			that._focusTabbable();
12270			that._trigger( "focus" );
12271		} );
12272
12273		// Track the dialog immediately upon opening in case a focus event
12274		// somehow occurs outside of the dialog before an element inside the
12275		// dialog is focused (#10152)
12276		this._makeFocusTarget();
12277
12278		this._trigger( "open" );
12279	},
12280
12281	_focusTabbable: function() {
12282
12283		// Set focus to the first match:
12284		// 1. An element that was focused previously
12285		// 2. First element inside the dialog matching [autofocus]
12286		// 3. Tabbable element inside the content element
12287		// 4. Tabbable element inside the buttonpane
12288		// 5. The close button
12289		// 6. The dialog itself
12290		var hasFocus = this._focusedElement;
12291		if ( !hasFocus ) {
12292			hasFocus = this.element.find( "[autofocus]" );
12293		}
12294		if ( !hasFocus.length ) {
12295			hasFocus = this.element.find( ":tabbable" );
12296		}
12297		if ( !hasFocus.length ) {
12298			hasFocus = this.uiDialogButtonPane.find( ":tabbable" );
12299		}
12300		if ( !hasFocus.length ) {
12301			hasFocus = this.uiDialogTitlebarClose.filter( ":tabbable" );
12302		}
12303		if ( !hasFocus.length ) {
12304			hasFocus = this.uiDialog;
12305		}
12306		hasFocus.eq( 0 ).trigger( "focus" );
12307	},
12308
12309	_restoreTabbableFocus: function() {
12310		var activeElement = this.document[ 0 ].activeElement,
12311			isActive = this.uiDialog[ 0 ] === activeElement ||
12312				$.contains( this.uiDialog[ 0 ], activeElement );
12313		if ( !isActive ) {
12314			this._focusTabbable();
12315		}
12316	},
12317
12318	_keepFocus: function( event ) {
12319		event.preventDefault();
12320		this._restoreTabbableFocus();
12321	},
12322
12323	_createWrapper: function() {
12324		this.uiDialog = $( "<div>" )
12325			.hide()
12326			.attr( {
12327
12328				// Setting tabIndex makes the div focusable
12329				tabIndex: -1,
12330				role: "dialog",
12331				"aria-modal": this.options.modal ? "true" : null
12332			} )
12333			.appendTo( this._appendTo() );
12334
12335		this._addClass( this.uiDialog, "ui-dialog", "ui-widget ui-widget-content ui-front" );
12336		this._on( this.uiDialog, {
12337			keydown: function( event ) {
12338				if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
12339						event.keyCode === $.ui.keyCode.ESCAPE ) {
12340					event.preventDefault();
12341					this.close( event );
12342					return;
12343				}
12344
12345				// Prevent tabbing out of dialogs
12346				if ( event.keyCode !== $.ui.keyCode.TAB || event.isDefaultPrevented() ) {
12347					return;
12348				}
12349				var tabbables = this.uiDialog.find( ":tabbable" ),
12350					first = tabbables.first(),
vendor: 12,216 bytes, lines 12351-12804
12351					last = tabbables.last();
12352
12353				if ( ( event.target === last[ 0 ] || event.target === this.uiDialog[ 0 ] ) &&
12354						!event.shiftKey ) {
12355					this._delay( function() {
12356						first.trigger( "focus" );
12357					} );
12358					event.preventDefault();
12359				} else if ( ( event.target === first[ 0 ] ||
12360						event.target === this.uiDialog[ 0 ] ) && event.shiftKey ) {
12361					this._delay( function() {
12362						last.trigger( "focus" );
12363					} );
12364					event.preventDefault();
12365				}
12366			},
12367			mousedown: function( event ) {
12368				if ( this._moveToTop( event ) ) {
12369					this._focusTabbable();
12370				}
12371			}
12372		} );
12373
12374		// We assume that any existing aria-describedby attribute means
12375		// that the dialog content is marked up properly
12376		// otherwise we brute force the content as the description
12377		if ( !this.element.find( "[aria-describedby]" ).length ) {
12378			this.uiDialog.attr( {
12379				"aria-describedby": this.element.uniqueId().attr( "id" )
12380			} );
12381		}
12382	},
12383
12384	_createTitlebar: function() {
12385		var uiDialogTitle;
12386
12387		this.uiDialogTitlebar = $( "<div>" );
12388		this._addClass( this.uiDialogTitlebar,
12389			"ui-dialog-titlebar", "ui-widget-header ui-helper-clearfix" );
12390		this._on( this.uiDialogTitlebar, {
12391			mousedown: function( event ) {
12392
12393				// Don't prevent click on close button (#8838)
12394				// Focusing a dialog that is partially scrolled out of view
12395				// causes the browser to scroll it into view, preventing the click event
12396				if ( !$( event.target ).closest( ".ui-dialog-titlebar-close" ) ) {
12397
12398					// Dialog isn't getting focus when dragging (#8063)
12399					this.uiDialog.trigger( "focus" );
12400				}
12401			}
12402		} );
12403
12404		this.uiDialogTitlebarClose = $( "<button type='button'></button>" )
12405			.button( {
12406				label: $( "<a>" ).text( this.options.closeText ).html(),
12407				icon: "ui-icon-closethick",
12408				showLabel: false
12409			} )
12410			.appendTo( this.uiDialogTitlebar );
12411
12412		this._addClass( this.uiDialogTitlebarClose, "ui-dialog-titlebar-close" );
12413		this._on( this.uiDialogTitlebarClose, {
12414			click: function( event ) {
12415				event.preventDefault();
12416				this.close( event );
12417			}
12418		} );
12419
12420		uiDialogTitle = $( "<span>" ).uniqueId().prependTo( this.uiDialogTitlebar );
12421		this._addClass( uiDialogTitle, "ui-dialog-title" );
12422		this._title( uiDialogTitle );
12423
12424		this.uiDialogTitlebar.prependTo( this.uiDialog );
12425
12426		this.uiDialog.attr( {
12427			"aria-labelledby": uiDialogTitle.attr( "id" )
12428		} );
12429	},
12430
12431	_title: function( title ) {
12432		if ( this.options.title ) {
12433			title.text( this.options.title );
12434		} else {
12435			title.html( "&#160;" );
12436		}
12437	},
12438
12439	_createButtonPane: function() {
12440		this.uiDialogButtonPane = $( "<div>" );
12441		this._addClass( this.uiDialogButtonPane, "ui-dialog-buttonpane",
12442			"ui-widget-content ui-helper-clearfix" );
12443
12444		this.uiButtonSet = $( "<div>" )
12445			.appendTo( this.uiDialogButtonPane );
12446		this._addClass( this.uiButtonSet, "ui-dialog-buttonset" );
12447
12448		this._createButtons();
12449	},
12450
12451	_createButtons: function() {
12452		var that = this,
12453			buttons = this.options.buttons;
12454
12455		// If we already have a button pane, remove it
12456		this.uiDialogButtonPane.remove();
12457		this.uiButtonSet.empty();
12458
12459		if ( $.isEmptyObject( buttons ) || ( Array.isArray( buttons ) && !buttons.length ) ) {
12460			this._removeClass( this.uiDialog, "ui-dialog-buttons" );
12461			return;
12462		}
12463
12464		$.each( buttons, function( name, props ) {
12465			var click, buttonOptions;
12466			props = typeof props === "function" ?
12467				{ click: props, text: name } :
12468				props;
12469
12470			// Default to a non-submitting button
12471			props = $.extend( { type: "button" }, props );
12472
12473			// Change the context for the click callback to be the main element
12474			click = props.click;
12475			buttonOptions = {
12476				icon: props.icon,
12477				iconPosition: props.iconPosition,
12478				showLabel: props.showLabel,
12479
12480				// Deprecated options
12481				icons: props.icons,
12482				text: props.text
12483			};
12484
12485			delete props.click;
12486			delete props.icon;
12487			delete props.iconPosition;
12488			delete props.showLabel;
12489
12490			// Deprecated options
12491			delete props.icons;
12492			if ( typeof props.text === "boolean" ) {
12493				delete props.text;
12494			}
12495
12496			$( "<button></button>", props )
12497				.button( buttonOptions )
12498				.appendTo( that.uiButtonSet )
12499				.on( "click", function() {
12500					click.apply( that.element[ 0 ], arguments );
12501				} );
12502		} );
12503		this._addClass( this.uiDialog, "ui-dialog-buttons" );
12504		this.uiDialogButtonPane.appendTo( this.uiDialog );
12505	},
12506
12507	_makeDraggable: function() {
12508		var that = this,
12509			options = this.options;
12510
12511		function filteredUi( ui ) {
12512			return {
12513				position: ui.position,
12514				offset: ui.offset
12515			};
12516		}
12517
12518		this.uiDialog.draggable( {
12519			cancel: ".ui-dialog-content, .ui-dialog-titlebar-close",
12520			handle: ".ui-dialog-titlebar",
12521			containment: "document",
12522			start: function( event, ui ) {
12523				that._addClass( $( this ), "ui-dialog-dragging" );
12524				that._blockFrames();
12525				that._trigger( "dragStart", event, filteredUi( ui ) );
12526			},
12527			drag: function( event, ui ) {
12528				that._trigger( "drag", event, filteredUi( ui ) );
12529			},
12530			stop: function( event, ui ) {
12531				var left = ui.offset.left - that.document.scrollLeft(),
12532					top = ui.offset.top - that.document.scrollTop();
12533
12534				options.position = {
12535					my: "left top",
12536					at: "left" + ( left >= 0 ? "+" : "" ) + left + " " +
12537						"top" + ( top >= 0 ? "+" : "" ) + top,
12538					of: that.window
12539				};
12540				that._removeClass( $( this ), "ui-dialog-dragging" );
12541				that._unblockFrames();
12542				that._trigger( "dragStop", event, filteredUi( ui ) );
12543			}
12544		} );
12545	},
12546
12547	_makeResizable: function() {
12548		var that = this,
12549			options = this.options,
12550			handles = options.resizable,
12551
12552			// .ui-resizable has position: relative defined in the stylesheet
12553			// but dialogs have to use absolute or fixed positioning
12554			position = this.uiDialog.css( "position" ),
12555			resizeHandles = typeof handles === "string" ?
12556				handles :
12557				"n,e,s,w,se,sw,ne,nw";
12558
12559		function filteredUi( ui ) {
12560			return {
12561				originalPosition: ui.originalPosition,
12562				originalSize: ui.originalSize,
12563				position: ui.position,
12564				size: ui.size
12565			};
12566		}
12567
12568		this.uiDialog.resizable( {
12569			cancel: ".ui-dialog-content",
12570			containment: "document",
12571			alsoResize: this.element,
12572			maxWidth: options.maxWidth,
12573			maxHeight: options.maxHeight,
12574			minWidth: options.minWidth,
12575			minHeight: this._minHeight(),
12576			handles: resizeHandles,
12577			start: function( event, ui ) {
12578				that._addClass( $( this ), "ui-dialog-resizing" );
12579				that._blockFrames();
12580				that._trigger( "resizeStart", event, filteredUi( ui ) );
12581			},
12582			resize: function( event, ui ) {
12583				that._trigger( "resize", event, filteredUi( ui ) );
12584			},
12585			stop: function( event, ui ) {
12586				var offset = that.uiDialog.offset(),
12587					left = offset.left - that.document.scrollLeft(),
12588					top = offset.top - that.document.scrollTop();
12589
12590				options.height = that.uiDialog.height();
12591				options.width = that.uiDialog.width();
12592				options.position = {
12593					my: "left top",
12594					at: "left" + ( left >= 0 ? "+" : "" ) + left + " " +
12595						"top" + ( top >= 0 ? "+" : "" ) + top,
12596					of: that.window
12597				};
12598				that._removeClass( $( this ), "ui-dialog-resizing" );
12599				that._unblockFrames();
12600				that._trigger( "resizeStop", event, filteredUi( ui ) );
12601			}
12602		} )
12603			.css( "position", position );
12604	},
12605
12606	_trackFocus: function() {
12607		this._on( this.widget(), {
12608			focusin: function( event ) {
12609				this._makeFocusTarget();
12610				this._focusedElement = $( event.target );
12611			}
12612		} );
12613	},
12614
12615	_makeFocusTarget: function() {
12616		this._untrackInstance();
12617		this._trackingInstances().unshift( this );
12618	},
12619
12620	_untrackInstance: function() {
12621		var instances = this._trackingInstances(),
12622			exists = $.inArray( this, instances );
12623		if ( exists !== -1 ) {
12624			instances.splice( exists, 1 );
12625		}
12626	},
12627
12628	_trackingInstances: function() {
12629		var instances = this.document.data( "ui-dialog-instances" );
12630		if ( !instances ) {
12631			instances = [];
12632			this.document.data( "ui-dialog-instances", instances );
12633		}
12634		return instances;
12635	},
12636
12637	_minHeight: function() {
12638		var options = this.options;
12639
12640		return options.height === "auto" ?
12641			options.minHeight :
12642			Math.min( options.minHeight, options.height );
12643	},
12644
12645	_position: function() {
12646
12647		// Need to show the dialog to get the actual offset in the position plugin
12648		var isVisible = this.uiDialog.is( ":visible" );
12649		if ( !isVisible ) {
12650			this.uiDialog.show();
12651		}
12652		this.uiDialog.position( this.options.position );
12653		if ( !isVisible ) {
12654			this.uiDialog.hide();
12655		}
12656	},
12657
12658	_setOptions: function( options ) {
12659		var that = this,
12660			resize = false,
12661			resizableOptions = {};
12662
12663		$.each( options, function( key, value ) {
12664			that._setOption( key, value );
12665
12666			if ( key in that.sizeRelatedOptions ) {
12667				resize = true;
12668			}
12669			if ( key in that.resizableRelatedOptions ) {
12670				resizableOptions[ key ] = value;
12671			}
12672		} );
12673
12674		if ( resize ) {
12675			this._size();
12676			this._position();
12677		}
12678		if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
12679			this.uiDialog.resizable( "option", resizableOptions );
12680		}
12681	},
12682
12683	_setOption: function( key, value ) {
12684		var isDraggable, isResizable,
12685			uiDialog = this.uiDialog;
12686
12687		if ( key === "disabled" ) {
12688			return;
12689		}
12690
12691		this._super( key, value );
12692
12693		if ( key === "appendTo" ) {
12694			this.uiDialog.appendTo( this._appendTo() );
12695		}
12696
12697		if ( key === "buttons" ) {
12698			this._createButtons();
12699		}
12700
12701		if ( key === "closeText" ) {
12702			this.uiDialogTitlebarClose.button( {
12703
12704				// Ensure that we always pass a string
12705				label: $( "<a>" ).text( "" + this.options.closeText ).html()
12706			} );
12707		}
12708
12709		if ( key === "draggable" ) {
12710			isDraggable = uiDialog.is( ":data(ui-draggable)" );
12711			if ( isDraggable && !value ) {
12712				uiDialog.draggable( "destroy" );
12713			}
12714
12715			if ( !isDraggable && value ) {
12716				this._makeDraggable();
12717			}
12718		}
12719
12720		if ( key === "position" ) {
12721			this._position();
12722		}
12723
12724		if ( key === "resizable" ) {
12725
12726			// currently resizable, becoming non-resizable
12727			isResizable = uiDialog.is( ":data(ui-resizable)" );
12728			if ( isResizable && !value ) {
12729				uiDialog.resizable( "destroy" );
12730			}
12731
12732			// Currently resizable, changing handles
12733			if ( isResizable && typeof value === "string" ) {
12734				uiDialog.resizable( "option", "handles", value );
12735			}
12736
12737			// Currently non-resizable, becoming resizable
12738			if ( !isResizable && value !== false ) {
12739				this._makeResizable();
12740			}
12741		}
12742
12743		if ( key === "title" ) {
12744			this._title( this.uiDialogTitlebar.find( ".ui-dialog-title" ) );
12745		}
12746
12747		if ( key === "modal" ) {
12748			uiDialog.attr( "aria-modal", value ? "true" : null );
12749		}
12750	},
12751
12752	_size: function() {
12753
12754		// If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
12755		// divs will both have width and height set, so we need to reset them
12756		var nonContentHeight, minContentHeight, maxContentHeight,
12757			options = this.options;
12758
12759		// Reset content sizing
12760		this.element.show().css( {
12761			width: "auto",
12762			minHeight: 0,
12763			maxHeight: "none",
12764			height: 0
12765		} );
12766
12767		if ( options.minWidth > options.width ) {
12768			options.width = options.minWidth;
12769		}
12770
12771		// Reset wrapper sizing
12772		// determine the height of all the non-content elements
12773		nonContentHeight = this.uiDialog.css( {
12774			height: "auto",
12775			width: options.width
12776		} )
12777			.outerHeight();
12778		minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
12779		maxContentHeight = typeof options.maxHeight === "number" ?
12780			Math.max( 0, options.maxHeight - nonContentHeight ) :
12781			"none";
12782
12783		if ( options.height === "auto" ) {
12784			this.element.css( {
12785				minHeight: minContentHeight,
12786				maxHeight: maxContentHeight,
12787				height: "auto"
12788			} );
12789		} else {
12790			this.element.height( Math.max( 0, options.height - nonContentHeight ) );
12791		}
12792
12793		if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
12794			this.uiDialog.resizable( "option", "minHeight", this._minHeight() );
12795		}
12796	},
12797
12798	_blockFrames: function() {
12799		this.iframeBlocks = this.document.find( "iframe" ).map( function() {
12800			var iframe = $( this );
12801
12802			return $( "<div>" )
12803				.css( {
12804					position: "absolute",
vendor: 122,591 bytes, lines 12805-17205
12805					width: iframe.outerWidth(),
12806					height: iframe.outerHeight()
12807				} )
12808				.appendTo( iframe.parent() )
12809				.offset( iframe.offset() )[ 0 ];
12810		} );
12811	},
12812
12813	_unblockFrames: function() {
12814		if ( this.iframeBlocks ) {
12815			this.iframeBlocks.remove();
12816			delete this.iframeBlocks;
12817		}
12818	},
12819
12820	_allowInteraction: function( event ) {
12821		if ( $( event.target ).closest( ".ui-dialog" ).length ) {
12822			return true;
12823		}
12824
12825		// TODO: Remove hack when datepicker implements
12826		// the .ui-front logic (#8989)
12827		return !!$( event.target ).closest( ".ui-datepicker" ).length;
12828	},
12829
12830	_createOverlay: function() {
12831		if ( !this.options.modal ) {
12832			return;
12833		}
12834
12835		// We use a delay in case the overlay is created from an
12836		// event that we're going to be cancelling (#2804)
12837		var isOpening = true;
12838		this._delay( function() {
12839			isOpening = false;
12840		} );
12841
12842		if ( !this.document.data( "ui-dialog-overlays" ) ) {
12843
12844			// Prevent use of anchors and inputs
12845			// This doesn't use `_on()` because it is a shared event handler
12846			// across all open modal dialogs.
12847			this.document.on( "focusin.ui-dialog", function( event ) {
12848				if ( isOpening ) {
12849					return;
12850				}
12851
12852				var instance = this._trackingInstances()[ 0 ];
12853				if ( !instance._allowInteraction( event ) ) {
12854					event.preventDefault();
12855					instance._focusTabbable();
12856				}
12857			}.bind( this ) );
12858		}
12859
12860		this.overlay = $( "<div>" )
12861			.appendTo( this._appendTo() );
12862
12863		this._addClass( this.overlay, null, "ui-widget-overlay ui-front" );
12864		this._on( this.overlay, {
12865			mousedown: "_keepFocus"
12866		} );
12867		this.document.data( "ui-dialog-overlays",
12868			( this.document.data( "ui-dialog-overlays" ) || 0 ) + 1 );
12869	},
12870
12871	_destroyOverlay: function() {
12872		if ( !this.options.modal ) {
12873			return;
12874		}
12875
12876		if ( this.overlay ) {
12877			var overlays = this.document.data( "ui-dialog-overlays" ) - 1;
12878
12879			if ( !overlays ) {
12880				this.document.off( "focusin.ui-dialog" );
12881				this.document.removeData( "ui-dialog-overlays" );
12882			} else {
12883				this.document.data( "ui-dialog-overlays", overlays );
12884			}
12885
12886			this.overlay.remove();
12887			this.overlay = null;
12888		}
12889	}
12890} );
12891
12892// DEPRECATED
12893// TODO: switch return back to widget declaration at top of file when this is removed
12894if ( $.uiBackCompat === true ) {
12895
12896	// Backcompat for dialogClass option
12897	$.widget( "ui.dialog", $.ui.dialog, {
12898		options: {
12899			dialogClass: ""
12900		},
12901		_createWrapper: function() {
12902			this._super();
12903			this.uiDialog.addClass( this.options.dialogClass );
12904		},
12905		_setOption: function( key, value ) {
12906			if ( key === "dialogClass" ) {
12907				this.uiDialog
12908					.removeClass( this.options.dialogClass )
12909					.addClass( value );
12910			}
12911			this._superApply( arguments );
12912		}
12913	} );
12914}
12915
12916var widgetsDialog = $.ui.dialog;
12917
12918
12919/*!
12920 * jQuery UI Droppable 1.14.0
12921 * https://jqueryui.com
12922 *
12923 * Copyright OpenJS Foundation and other contributors
12924 * Released under the MIT license.
12925 * https://jquery.org/license
12926 */
12927
12928//>>label: Droppable
12929//>>group: Interactions
12930//>>description: Enables drop targets for draggable elements.
12931//>>docs: https://api.jqueryui.com/droppable/
12932//>>demos: https://jqueryui.com/droppable/
12933
12934
12935$.widget( "ui.droppable", {
12936	version: "1.14.0",
12937	widgetEventPrefix: "drop",
12938	options: {
12939		accept: "*",
12940		addClasses: true,
12941		greedy: false,
12942		scope: "default",
12943		tolerance: "intersect",
12944
12945		// Callbacks
12946		activate: null,
12947		deactivate: null,
12948		drop: null,
12949		out: null,
12950		over: null
12951	},
12952	_create: function() {
12953
12954		var proportions,
12955			o = this.options,
12956			accept = o.accept;
12957
12958		this.isover = false;
12959		this.isout = true;
12960
12961		this.accept = typeof accept === "function" ? accept : function( d ) {
12962			return d.is( accept );
12963		};
12964
12965		this.proportions = function( /* valueToWrite */ ) {
12966			if ( arguments.length ) {
12967
12968				// Store the droppable's proportions
12969				proportions = arguments[ 0 ];
12970			} else {
12971
12972				// Retrieve or derive the droppable's proportions
12973				return proportions ?
12974					proportions :
12975					proportions = {
12976						width: this.element[ 0 ].offsetWidth,
12977						height: this.element[ 0 ].offsetHeight
12978					};
12979			}
12980		};
12981
12982		this._addToManager( o.scope );
12983
12984		if ( o.addClasses ) {
12985			this._addClass( "ui-droppable" );
12986		}
12987
12988	},
12989
12990	_addToManager: function( scope ) {
12991
12992		// Add the reference and positions to the manager
12993		$.ui.ddmanager.droppables[ scope ] = $.ui.ddmanager.droppables[ scope ] || [];
12994		$.ui.ddmanager.droppables[ scope ].push( this );
12995	},
12996
12997	_splice: function( drop ) {
12998		var i = 0;
12999		for ( ; i < drop.length; i++ ) {
13000			if ( drop[ i ] === this ) {
13001				drop.splice( i, 1 );
13002			}
13003		}
13004	},
13005
13006	_destroy: function() {
13007		var drop = $.ui.ddmanager.droppables[ this.options.scope ];
13008
13009		this._splice( drop );
13010	},
13011
13012	_setOption: function( key, value ) {
13013
13014		if ( key === "accept" ) {
13015			this.accept = typeof value === "function" ? value : function( d ) {
13016				return d.is( value );
13017			};
13018		} else if ( key === "scope" ) {
13019			var drop = $.ui.ddmanager.droppables[ this.options.scope ];
13020
13021			this._splice( drop );
13022			this._addToManager( value );
13023		}
13024
13025		this._super( key, value );
13026	},
13027
13028	_activate: function( event ) {
13029		var draggable = $.ui.ddmanager.current;
13030
13031		this._addActiveClass();
13032		if ( draggable ) {
13033			this._trigger( "activate", event, this.ui( draggable ) );
13034		}
13035	},
13036
13037	_deactivate: function( event ) {
13038		var draggable = $.ui.ddmanager.current;
13039
13040		this._removeActiveClass();
13041		if ( draggable ) {
13042			this._trigger( "deactivate", event, this.ui( draggable ) );
13043		}
13044	},
13045
13046	_over: function( event ) {
13047
13048		var draggable = $.ui.ddmanager.current;
13049
13050		// Bail if draggable and droppable are same element
13051		if ( !draggable || ( draggable.currentItem ||
13052				draggable.element )[ 0 ] === this.element[ 0 ] ) {
13053			return;
13054		}
13055
13056		if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem ||
13057				draggable.element ) ) ) {
13058			this._addHoverClass();
13059			this._trigger( "over", event, this.ui( draggable ) );
13060		}
13061
13062	},
13063
13064	_out: function( event ) {
13065
13066		var draggable = $.ui.ddmanager.current;
13067
13068		// Bail if draggable and droppable are same element
13069		if ( !draggable || ( draggable.currentItem ||
13070				draggable.element )[ 0 ] === this.element[ 0 ] ) {
13071			return;
13072		}
13073
13074		if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem ||
13075				draggable.element ) ) ) {
13076			this._removeHoverClass();
13077			this._trigger( "out", event, this.ui( draggable ) );
13078		}
13079
13080	},
13081
13082	_drop: function( event, custom ) {
13083
13084		var draggable = custom || $.ui.ddmanager.current,
13085			childrenIntersection = false;
13086
13087		// Bail if draggable and droppable are same element
13088		if ( !draggable || ( draggable.currentItem ||
13089				draggable.element )[ 0 ] === this.element[ 0 ] ) {
13090			return false;
13091		}
13092
13093		this.element
13094			.find( ":data(ui-droppable)" )
13095			.not( ".ui-draggable-dragging" )
13096			.each( function() {
13097				var inst = $( this ).droppable( "instance" );
13098				if (
13099					inst.options.greedy &&
13100					!inst.options.disabled &&
13101					inst.options.scope === draggable.options.scope &&
13102					inst.accept.call(
13103						inst.element[ 0 ], ( draggable.currentItem || draggable.element )
13104					) &&
13105					$.ui.intersect(
13106						draggable,
13107						$.extend( inst, { offset: inst.element.offset() } ),
13108						inst.options.tolerance, event
13109					)
13110				) {
13111					childrenIntersection = true;
13112					return false;
13113				}
13114			} );
13115		if ( childrenIntersection ) {
13116			return false;
13117		}
13118
13119		if ( this.accept.call( this.element[ 0 ],
13120				( draggable.currentItem || draggable.element ) ) ) {
13121			this._removeActiveClass();
13122			this._removeHoverClass();
13123
13124			this._trigger( "drop", event, this.ui( draggable ) );
13125			return this.element;
13126		}
13127
13128		return false;
13129
13130	},
13131
13132	ui: function( c ) {
13133		return {
13134			draggable: ( c.currentItem || c.element ),
13135			helper: c.helper,
13136			position: c.position,
13137			offset: c.positionAbs
13138		};
13139	},
13140
13141	// Extension points just to make backcompat sane and avoid duplicating logic
13142	// TODO: Remove in 1.14 along with call to it below
13143	_addHoverClass: function() {
13144		this._addClass( "ui-droppable-hover" );
13145	},
13146
13147	_removeHoverClass: function() {
13148		this._removeClass( "ui-droppable-hover" );
13149	},
13150
13151	_addActiveClass: function() {
13152		this._addClass( "ui-droppable-active" );
13153	},
13154
13155	_removeActiveClass: function() {
13156		this._removeClass( "ui-droppable-active" );
13157	}
13158} );
13159
13160$.ui.intersect = ( function() {
13161	function isOverAxis( x, reference, size ) {
13162		return ( x >= reference ) && ( x < ( reference + size ) );
13163	}
13164
13165	return function( draggable, droppable, toleranceMode, event ) {
13166
13167		if ( !droppable.offset ) {
13168			return false;
13169		}
13170
13171		var x1 = ( draggable.positionAbs ||
13172				draggable.position.absolute ).left + draggable.margins.left,
13173			y1 = ( draggable.positionAbs ||
13174				draggable.position.absolute ).top + draggable.margins.top,
13175			x2 = x1 + draggable.helperProportions.width,
13176			y2 = y1 + draggable.helperProportions.height,
13177			l = droppable.offset.left,
13178			t = droppable.offset.top,
13179			r = l + droppable.proportions().width,
13180			b = t + droppable.proportions().height;
13181
13182		switch ( toleranceMode ) {
13183		case "fit":
13184			return ( l <= x1 && x2 <= r && t <= y1 && y2 <= b );
13185		case "intersect":
13186			return ( l < x1 + ( draggable.helperProportions.width / 2 ) && // Right Half
13187				x2 - ( draggable.helperProportions.width / 2 ) < r && // Left Half
13188				t < y1 + ( draggable.helperProportions.height / 2 ) && // Bottom Half
13189				y2 - ( draggable.helperProportions.height / 2 ) < b ); // Top Half
13190		case "pointer":
13191			return isOverAxis( event.pageY, t, droppable.proportions().height ) &&
13192				isOverAxis( event.pageX, l, droppable.proportions().width );
13193		case "touch":
13194			return (
13195				( y1 >= t && y1 <= b ) || // Top edge touching
13196				( y2 >= t && y2 <= b ) || // Bottom edge touching
13197				( y1 < t && y2 > b ) // Surrounded vertically
13198			) && (
13199				( x1 >= l && x1 <= r ) || // Left edge touching
13200				( x2 >= l && x2 <= r ) || // Right edge touching
13201				( x1 < l && x2 > r ) // Surrounded horizontally
13202			);
13203		default:
13204			return false;
13205		}
13206	};
13207} )();
13208
13209/*
13210	This manager tracks offsets of draggables and droppables
13211*/
13212$.ui.ddmanager = {
13213	current: null,
13214	droppables: { "default": [] },
13215	prepareOffsets: function( t, event ) {
13216
13217		var i, j,
13218			m = $.ui.ddmanager.droppables[ t.options.scope ] || [],
13219			type = event ? event.type : null, // workaround for #2317
13220			list = ( t.currentItem || t.element ).find( ":data(ui-droppable)" ).addBack();
13221
13222		droppablesLoop: for ( i = 0; i < m.length; i++ ) {
13223
13224			// No disabled and non-accepted
13225			if ( m[ i ].options.disabled || ( t && !m[ i ].accept.call( m[ i ].element[ 0 ],
13226					( t.currentItem || t.element ) ) ) ) {
13227				continue;
13228			}
13229
13230			// Filter out elements in the current dragged item
13231			for ( j = 0; j < list.length; j++ ) {
13232				if ( list[ j ] === m[ i ].element[ 0 ] ) {
13233					m[ i ].proportions().height = 0;
13234					continue droppablesLoop;
13235				}
13236			}
13237
13238			m[ i ].visible = m[ i ].element.css( "display" ) !== "none";
13239			if ( !m[ i ].visible ) {
13240				continue;
13241			}
13242
13243			// Activate the droppable if used directly from draggables
13244			if ( type === "mousedown" ) {
13245				m[ i ]._activate.call( m[ i ], event );
13246			}
13247
13248			m[ i ].offset = m[ i ].element.offset();
13249			m[ i ].proportions( {
13250				width: m[ i ].element[ 0 ].offsetWidth,
13251				height: m[ i ].element[ 0 ].offsetHeight
13252			} );
13253
13254		}
13255
13256	},
13257	drop: function( draggable, event ) {
13258
13259		var dropped = false;
13260
13261		// Create a copy of the droppables in case the list changes during the drop (#9116)
13262		$.each( ( $.ui.ddmanager.droppables[ draggable.options.scope ] || [] ).slice(), function() {
13263
13264			if ( !this.options ) {
13265				return;
13266			}
13267			if ( !this.options.disabled && this.visible &&
13268					$.ui.intersect( draggable, this, this.options.tolerance, event ) ) {
13269				dropped = this._drop.call( this, event ) || dropped;
13270			}
13271
13272			if ( !this.options.disabled && this.visible && this.accept.call( this.element[ 0 ],
13273					( draggable.currentItem || draggable.element ) ) ) {
13274				this.isout = true;
13275				this.isover = false;
13276				this._deactivate.call( this, event );
13277			}
13278
13279		} );
13280		return dropped;
13281
13282	},
13283	dragStart: function( draggable, event ) {
13284
13285		// Listen for scrolling so that if the dragging causes scrolling the position of the
13286		// droppables can be recalculated (see #5003)
13287		draggable.element.parentsUntil( "body" ).on( "scroll.droppable", function() {
13288			if ( !draggable.options.refreshPositions ) {
13289				$.ui.ddmanager.prepareOffsets( draggable, event );
13290			}
13291		} );
13292	},
13293	drag: function( draggable, event ) {
13294
13295		// If you have a highly dynamic page, you might try this option. It renders positions
13296		// every time you move the mouse.
13297		if ( draggable.options.refreshPositions ) {
13298			$.ui.ddmanager.prepareOffsets( draggable, event );
13299		}
13300
13301		// Run through all droppables and check their positions based on specific tolerance options
13302		$.each( $.ui.ddmanager.droppables[ draggable.options.scope ] || [], function() {
13303
13304			if ( this.options.disabled || this.greedyChild || !this.visible ) {
13305				return;
13306			}
13307
13308			var parentInstance, scope, parent,
13309				intersects = $.ui.intersect( draggable, this, this.options.tolerance, event ),
13310				c = !intersects && this.isover ?
13311					"isout" :
13312					( intersects && !this.isover ? "isover" : null );
13313			if ( !c ) {
13314				return;
13315			}
13316
13317			if ( this.options.greedy ) {
13318
13319				// find droppable parents with same scope
13320				scope = this.options.scope;
13321				parent = this.element.parents( ":data(ui-droppable)" ).filter( function() {
13322					return $( this ).droppable( "instance" ).options.scope === scope;
13323				} );
13324
13325				if ( parent.length ) {
13326					parentInstance = $( parent[ 0 ] ).droppable( "instance" );
13327					parentInstance.greedyChild = ( c === "isover" );
13328				}
13329			}
13330
13331			// We just moved into a greedy child
13332			if ( parentInstance && c === "isover" ) {
13333				parentInstance.isover = false;
13334				parentInstance.isout = true;
13335				parentInstance._out.call( parentInstance, event );
13336			}
13337
13338			this[ c ] = true;
13339			this[ c === "isout" ? "isover" : "isout" ] = false;
13340			this[ c === "isover" ? "_over" : "_out" ].call( this, event );
13341
13342			// We just moved out of a greedy child
13343			if ( parentInstance && c === "isout" ) {
13344				parentInstance.isout = false;
13345				parentInstance.isover = true;
13346				parentInstance._over.call( parentInstance, event );
13347			}
13348		} );
13349
13350	},
13351	dragStop: function( draggable, event ) {
13352		draggable.element.parentsUntil( "body" ).off( "scroll.droppable" );
13353
13354		// Call prepareOffsets one final time since IE does not fire return scroll events when
13355		// overflow was caused by drag (see #5003)
13356		if ( !draggable.options.refreshPositions ) {
13357			$.ui.ddmanager.prepareOffsets( draggable, event );
13358		}
13359	}
13360};
13361
13362// DEPRECATED
13363// TODO: switch return back to widget declaration at top of file when this is removed
13364if ( $.uiBackCompat === true ) {
13365
13366	// Backcompat for activeClass and hoverClass options
13367	$.widget( "ui.droppable", $.ui.droppable, {
13368		options: {
13369			hoverClass: false,
13370			activeClass: false
13371		},
13372		_addActiveClass: function() {
13373			this._super();
13374			if ( this.options.activeClass ) {
13375				this.element.addClass( this.options.activeClass );
13376			}
13377		},
13378		_removeActiveClass: function() {
13379			this._super();
13380			if ( this.options.activeClass ) {
13381				this.element.removeClass( this.options.activeClass );
13382			}
13383		},
13384		_addHoverClass: function() {
13385			this._super();
13386			if ( this.options.hoverClass ) {
13387				this.element.addClass( this.options.hoverClass );
13388			}
13389		},
13390		_removeHoverClass: function() {
13391			this._super();
13392			if ( this.options.hoverClass ) {
13393				this.element.removeClass( this.options.hoverClass );
13394			}
13395		}
13396	} );
13397}
13398
13399var widgetsDroppable = $.ui.droppable;
13400
13401
13402/*!
13403 * jQuery UI Progressbar 1.14.0
13404 * https://jqueryui.com
13405 *
13406 * Copyright OpenJS Foundation and other contributors
13407 * Released under the MIT license.
13408 * https://jquery.org/license
13409 */
13410
13411//>>label: Progressbar
13412//>>group: Widgets
13413/* eslint-disable max-len */
13414//>>description: Displays a status indicator for loading state, standard percentage, and other progress indicators.
13415/* eslint-enable max-len */
13416//>>docs: https://api.jqueryui.com/progressbar/
13417//>>demos: https://jqueryui.com/progressbar/
13418//>>css.structure: ../../themes/base/core.css
13419//>>css.structure: ../../themes/base/progressbar.css
13420//>>css.theme: ../../themes/base/theme.css
13421
13422
13423var widgetsProgressbar = $.widget( "ui.progressbar", {
13424	version: "1.14.0",
13425	options: {
13426		classes: {
13427			"ui-progressbar": "ui-corner-all",
13428			"ui-progressbar-value": "ui-corner-left",
13429			"ui-progressbar-complete": "ui-corner-right"
13430		},
13431		max: 100,
13432		value: 0,
13433
13434		change: null,
13435		complete: null
13436	},
13437
13438	min: 0,
13439
13440	_create: function() {
13441
13442		// Constrain initial value
13443		this.oldValue = this.options.value = this._constrainedValue();
13444
13445		this.element.attr( {
13446
13447			// Only set static values; aria-valuenow and aria-valuemax are
13448			// set inside _refreshValue()
13449			role: "progressbar",
13450			"aria-valuemin": this.min
13451		} );
13452		this._addClass( "ui-progressbar", "ui-widget ui-widget-content" );
13453
13454		this.valueDiv = $( "<div>" ).appendTo( this.element );
13455		this._addClass( this.valueDiv, "ui-progressbar-value", "ui-widget-header" );
13456		this._refreshValue();
13457	},
13458
13459	_destroy: function() {
13460		this.element.removeAttr( "role aria-valuemin aria-valuemax aria-valuenow" );
13461
13462		this.valueDiv.remove();
13463	},
13464
13465	value: function( newValue ) {
13466		if ( newValue === undefined ) {
13467			return this.options.value;
13468		}
13469
13470		this.options.value = this._constrainedValue( newValue );
13471		this._refreshValue();
13472	},
13473
13474	_constrainedValue: function( newValue ) {
13475		if ( newValue === undefined ) {
13476			newValue = this.options.value;
13477		}
13478
13479		this.indeterminate = newValue === false;
13480
13481		// Sanitize value
13482		if ( typeof newValue !== "number" ) {
13483			newValue = 0;
13484		}
13485
13486		return this.indeterminate ? false :
13487			Math.min( this.options.max, Math.max( this.min, newValue ) );
13488	},
13489
13490	_setOptions: function( options ) {
13491
13492		// Ensure "value" option is set after other values (like max)
13493		var value = options.value;
13494		delete options.value;
13495
13496		this._super( options );
13497
13498		this.options.value = this._constrainedValue( value );
13499		this._refreshValue();
13500	},
13501
13502	_setOption: function( key, value ) {
13503		if ( key === "max" ) {
13504
13505			// Don't allow a max less than min
13506			value = Math.max( this.min, value );
13507		}
13508		this._super( key, value );
13509	},
13510
13511	_setOptionDisabled: function( value ) {
13512		this._super( value );
13513
13514		this.element.attr( "aria-disabled", value );
13515		this._toggleClass( null, "ui-state-disabled", !!value );
13516	},
13517
13518	_percentage: function() {
13519		return this.indeterminate ?
13520			100 :
13521			100 * ( this.options.value - this.min ) / ( this.options.max - this.min );
13522	},
13523
13524	_refreshValue: function() {
13525		var value = this.options.value,
13526			percentage = this._percentage();
13527
13528		this.valueDiv
13529			.toggle( this.indeterminate || value > this.min )
13530			.width( percentage.toFixed( 0 ) + "%" );
13531
13532		this
13533			._toggleClass( this.valueDiv, "ui-progressbar-complete", null,
13534				value === this.options.max )
13535			._toggleClass( "ui-progressbar-indeterminate", null, this.indeterminate );
13536
13537		if ( this.indeterminate ) {
13538			this.element.removeAttr( "aria-valuenow" );
13539			if ( !this.overlayDiv ) {
13540				this.overlayDiv = $( "<div>" ).appendTo( this.valueDiv );
13541				this._addClass( this.overlayDiv, "ui-progressbar-overlay" );
13542			}
13543		} else {
13544			this.element.attr( {
13545				"aria-valuemax": this.options.max,
13546				"aria-valuenow": value
13547			} );
13548			if ( this.overlayDiv ) {
13549				this.overlayDiv.remove();
13550				this.overlayDiv = null;
13551			}
13552		}
13553
13554		if ( this.oldValue !== value ) {
13555			this.oldValue = value;
13556			this._trigger( "change" );
13557		}
13558		if ( value === this.options.max ) {
13559			this._trigger( "complete" );
13560		}
13561	}
13562} );
13563
13564
13565/*!
13566 * jQuery UI Selectable 1.14.0
13567 * https://jqueryui.com
13568 *
13569 * Copyright OpenJS Foundation and other contributors
13570 * Released under the MIT license.
13571 * https://jquery.org/license
13572 */
13573
13574//>>label: Selectable
13575//>>group: Interactions
13576//>>description: Allows groups of elements to be selected with the mouse.
13577//>>docs: https://api.jqueryui.com/selectable/
13578//>>demos: https://jqueryui.com/selectable/
13579//>>css.structure: ../../themes/base/selectable.css
13580
13581
13582var widgetsSelectable = $.widget( "ui.selectable", $.ui.mouse, {
13583	version: "1.14.0",
13584	options: {
13585		appendTo: "body",
13586		autoRefresh: true,
13587		distance: 0,
13588		filter: "*",
13589		tolerance: "touch",
13590
13591		// Callbacks
13592		selected: null,
13593		selecting: null,
13594		start: null,
13595		stop: null,
13596		unselected: null,
13597		unselecting: null
13598	},
13599	_create: function() {
13600		var that = this;
13601
13602		this._addClass( "ui-selectable" );
13603
13604		this.dragged = false;
13605
13606		// Cache selectee children based on filter
13607		this.refresh = function() {
13608			that.elementPos = $( that.element[ 0 ] ).offset();
13609			that.selectees = $( that.options.filter, that.element[ 0 ] );
13610			that._addClass( that.selectees, "ui-selectee" );
13611			that.selectees.each( function() {
13612				var $this = $( this ),
13613					selecteeOffset = $this.offset(),
13614					pos = {
13615						left: selecteeOffset.left - that.elementPos.left,
13616						top: selecteeOffset.top - that.elementPos.top
13617					};
13618				$.data( this, "selectable-item", {
13619					element: this,
13620					$element: $this,
13621					left: pos.left,
13622					top: pos.top,
13623					right: pos.left + $this.outerWidth(),
13624					bottom: pos.top + $this.outerHeight(),
13625					startselected: false,
13626					selected: $this.hasClass( "ui-selected" ),
13627					selecting: $this.hasClass( "ui-selecting" ),
13628					unselecting: $this.hasClass( "ui-unselecting" )
13629				} );
13630			} );
13631		};
13632		this.refresh();
13633
13634		this._mouseInit();
13635
13636		this.helper = $( "<div>" );
13637		this._addClass( this.helper, "ui-selectable-helper" );
13638	},
13639
13640	_destroy: function() {
13641		this.selectees.removeData( "selectable-item" );
13642		this._mouseDestroy();
13643	},
13644
13645	_mouseStart: function( event ) {
13646		var that = this,
13647			options = this.options;
13648
13649		this.opos = [ event.pageX, event.pageY ];
13650		this.elementPos = $( this.element[ 0 ] ).offset();
13651
13652		if ( this.options.disabled ) {
13653			return;
13654		}
13655
13656		this.selectees = $( options.filter, this.element[ 0 ] );
13657
13658		this._trigger( "start", event );
13659
13660		$( options.appendTo ).append( this.helper );
13661
13662		// position helper (lasso)
13663		this.helper.css( {
13664			"left": event.pageX,
13665			"top": event.pageY,
13666			"width": 0,
13667			"height": 0
13668		} );
13669
13670		if ( options.autoRefresh ) {
13671			this.refresh();
13672		}
13673
13674		this.selectees.filter( ".ui-selected" ).each( function() {
13675			var selectee = $.data( this, "selectable-item" );
13676			selectee.startselected = true;
13677			if ( !event.metaKey && !event.ctrlKey ) {
13678				that._removeClass( selectee.$element, "ui-selected" );
13679				selectee.selected = false;
13680				that._addClass( selectee.$element, "ui-unselecting" );
13681				selectee.unselecting = true;
13682
13683				// selectable UNSELECTING callback
13684				that._trigger( "unselecting", event, {
13685					unselecting: selectee.element
13686				} );
13687			}
13688		} );
13689
13690		$( event.target ).parents().addBack().each( function() {
13691			var doSelect,
13692				selectee = $.data( this, "selectable-item" );
13693			if ( selectee ) {
13694				doSelect = ( !event.metaKey && !event.ctrlKey ) ||
13695					!selectee.$element.hasClass( "ui-selected" );
13696				that._removeClass( selectee.$element, doSelect ? "ui-unselecting" : "ui-selected" )
13697					._addClass( selectee.$element, doSelect ? "ui-selecting" : "ui-unselecting" );
13698				selectee.unselecting = !doSelect;
13699				selectee.selecting = doSelect;
13700				selectee.selected = doSelect;
13701
13702				// selectable (UN)SELECTING callback
13703				if ( doSelect ) {
13704					that._trigger( "selecting", event, {
13705						selecting: selectee.element
13706					} );
13707				} else {
13708					that._trigger( "unselecting", event, {
13709						unselecting: selectee.element
13710					} );
13711				}
13712				return false;
13713			}
13714		} );
13715
13716	},
13717
13718	_mouseDrag: function( event ) {
13719
13720		this.dragged = true;
13721
13722		if ( this.options.disabled ) {
13723			return;
13724		}
13725
13726		var tmp,
13727			that = this,
13728			options = this.options,
13729			x1 = this.opos[ 0 ],
13730			y1 = this.opos[ 1 ],
13731			x2 = event.pageX,
13732			y2 = event.pageY;
13733
13734		if ( x1 > x2 ) {
13735			tmp = x2; x2 = x1; x1 = tmp;
13736		}
13737		if ( y1 > y2 ) {
13738			tmp = y2; y2 = y1; y1 = tmp;
13739		}
13740		this.helper.css( { left: x1, top: y1, width: x2 - x1, height: y2 - y1 } );
13741
13742		this.selectees.each( function() {
13743			var selectee = $.data( this, "selectable-item" ),
13744				hit = false,
13745				offset = {};
13746
13747			//prevent helper from being selected if appendTo: selectable
13748			if ( !selectee || selectee.element === that.element[ 0 ] ) {
13749				return;
13750			}
13751
13752			offset.left   = selectee.left   + that.elementPos.left;
13753			offset.right  = selectee.right  + that.elementPos.left;
13754			offset.top    = selectee.top    + that.elementPos.top;
13755			offset.bottom = selectee.bottom + that.elementPos.top;
13756
13757			if ( options.tolerance === "touch" ) {
13758				hit = ( !( offset.left > x2 || offset.right < x1 || offset.top > y2 ||
13759                    offset.bottom < y1 ) );
13760			} else if ( options.tolerance === "fit" ) {
13761				hit = ( offset.left > x1 && offset.right < x2 && offset.top > y1 &&
13762                    offset.bottom < y2 );
13763			}
13764
13765			if ( hit ) {
13766
13767				// SELECT
13768				if ( selectee.selected ) {
13769					that._removeClass( selectee.$element, "ui-selected" );
13770					selectee.selected = false;
13771				}
13772				if ( selectee.unselecting ) {
13773					that._removeClass( selectee.$element, "ui-unselecting" );
13774					selectee.unselecting = false;
13775				}
13776				if ( !selectee.selecting ) {
13777					that._addClass( selectee.$element, "ui-selecting" );
13778					selectee.selecting = true;
13779
13780					// selectable SELECTING callback
13781					that._trigger( "selecting", event, {
13782						selecting: selectee.element
13783					} );
13784				}
13785			} else {
13786
13787				// UNSELECT
13788				if ( selectee.selecting ) {
13789					if ( ( event.metaKey || event.ctrlKey ) && selectee.startselected ) {
13790						that._removeClass( selectee.$element, "ui-selecting" );
13791						selectee.selecting = false;
13792						that._addClass( selectee.$element, "ui-selected" );
13793						selectee.selected = true;
13794					} else {
13795						that._removeClass( selectee.$element, "ui-selecting" );
13796						selectee.selecting = false;
13797						if ( selectee.startselected ) {
13798							that._addClass( selectee.$element, "ui-unselecting" );
13799							selectee.unselecting = true;
13800						}
13801
13802						// selectable UNSELECTING callback
13803						that._trigger( "unselecting", event, {
13804							unselecting: selectee.element
13805						} );
13806					}
13807				}
13808				if ( selectee.selected ) {
13809					if ( !event.metaKey && !event.ctrlKey && !selectee.startselected ) {
13810						that._removeClass( selectee.$element, "ui-selected" );
13811						selectee.selected = false;
13812
13813						that._addClass( selectee.$element, "ui-unselecting" );
13814						selectee.unselecting = true;
13815
13816						// selectable UNSELECTING callback
13817						that._trigger( "unselecting", event, {
13818							unselecting: selectee.element
13819						} );
13820					}
13821				}
13822			}
13823		} );
13824
13825		return false;
13826	},
13827
13828	_mouseStop: function( event ) {
13829		var that = this;
13830
13831		this.dragged = false;
13832
13833		$( ".ui-unselecting", this.element[ 0 ] ).each( function() {
13834			var selectee = $.data( this, "selectable-item" );
13835			that._removeClass( selectee.$element, "ui-unselecting" );
13836			selectee.unselecting = false;
13837			selectee.startselected = false;
13838			that._trigger( "unselected", event, {
13839				unselected: selectee.element
13840			} );
13841		} );
13842		$( ".ui-selecting", this.element[ 0 ] ).each( function() {
13843			var selectee = $.data( this, "selectable-item" );
13844			that._removeClass( selectee.$element, "ui-selecting" )
13845				._addClass( selectee.$element, "ui-selected" );
13846			selectee.selecting = false;
13847			selectee.selected = true;
13848			selectee.startselected = true;
13849			that._trigger( "selected", event, {
13850				selected: selectee.element
13851			} );
13852		} );
13853		this._trigger( "stop", event );
13854
13855		this.helper.remove();
13856
13857		return false;
13858	}
13859
13860} );
13861
13862
13863/*!
13864 * jQuery UI Selectmenu 1.14.0
13865 * https://jqueryui.com
13866 *
13867 * Copyright OpenJS Foundation and other contributors
13868 * Released under the MIT license.
13869 * https://jquery.org/license
13870 */
13871
13872//>>label: Selectmenu
13873//>>group: Widgets
13874/* eslint-disable max-len */
13875//>>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.
13876/* eslint-enable max-len */
13877//>>docs: https://api.jqueryui.com/selectmenu/
13878//>>demos: https://jqueryui.com/selectmenu/
13879//>>css.structure: ../../themes/base/core.css
13880//>>css.structure: ../../themes/base/selectmenu.css, ../../themes/base/button.css
13881//>>css.theme: ../../themes/base/theme.css
13882
13883
13884var widgetsSelectmenu = $.widget( "ui.selectmenu", [ $.ui.formResetMixin, {
13885	version: "1.14.0",
13886	defaultElement: "<select>",
13887	options: {
13888		appendTo: null,
13889		classes: {
13890			"ui-selectmenu-button-open": "ui-corner-top",
13891			"ui-selectmenu-button-closed": "ui-corner-all"
13892		},
13893		disabled: null,
13894		icons: {
13895			button: "ui-icon-triangle-1-s"
13896		},
13897		position: {
13898			my: "left top",
13899			at: "left bottom",
13900			collision: "none"
13901		},
13902		width: false,
13903
13904		// Callbacks
13905		change: null,
13906		close: null,
13907		focus: null,
13908		open: null,
13909		select: null
13910	},
13911
13912	_create: function() {
13913		var selectmenuId = this.element.uniqueId().attr( "id" );
13914		this.ids = {
13915			element: selectmenuId,
13916			button: selectmenuId + "-button",
13917			menu: selectmenuId + "-menu"
13918		};
13919
13920		this._drawButton();
13921		this._drawMenu();
13922		this._bindFormResetHandler();
13923
13924		this._rendered = false;
13925		this.menuItems = $();
13926	},
13927
13928	_drawButton: function() {
13929		var icon,
13930			that = this,
13931			item = this._parseOption(
13932				this.element.find( "option:selected" ),
13933				this.element[ 0 ].selectedIndex
13934			);
13935
13936		// Associate existing label with the new button
13937		this.labels = this.element.labels().attr( "for", this.ids.button );
13938		this._on( this.labels, {
13939			click: function( event ) {
13940				this.button.trigger( "focus" );
13941				event.preventDefault();
13942			}
13943		} );
13944
13945		// Hide original select element
13946		this.element.hide();
13947
13948		// Create button
13949		this.button = $( "<span>", {
13950			tabindex: this.options.disabled ? -1 : 0,
13951			id: this.ids.button,
13952			role: "combobox",
13953			"aria-expanded": "false",
13954			"aria-autocomplete": "list",
13955			"aria-owns": this.ids.menu,
13956			"aria-haspopup": "true",
13957			title: this.element.attr( "title" )
13958		} )
13959			.insertAfter( this.element );
13960
13961		this._addClass( this.button, "ui-selectmenu-button ui-selectmenu-button-closed",
13962			"ui-button ui-widget" );
13963
13964		icon = $( "<span>" ).appendTo( this.button );
13965		this._addClass( icon, "ui-selectmenu-icon", "ui-icon " + this.options.icons.button );
13966		this.buttonItem = this._renderButtonItem( item )
13967			.appendTo( this.button );
13968
13969		if ( this.options.width !== false ) {
13970			this._resizeButton();
13971		}
13972
13973		this._on( this.button, this._buttonEvents );
13974		this.button.one( "focusin", function() {
13975
13976			// Delay rendering the menu items until the button receives focus.
13977			// The menu may have already been rendered via a programmatic open.
13978			if ( !that._rendered ) {
13979				that._refreshMenu();
13980			}
13981		} );
13982	},
13983
13984	_drawMenu: function() {
13985		var that = this;
13986
13987		// Create menu
13988		this.menu = $( "<ul>", {
13989			"aria-hidden": "true",
13990			"aria-labelledby": this.ids.button,
13991			id: this.ids.menu
13992		} );
13993
13994		// Wrap menu
13995		this.menuWrap = $( "<div>" ).append( this.menu );
13996		this._addClass( this.menuWrap, "ui-selectmenu-menu", "ui-front" );
13997		this.menuWrap.appendTo( this._appendTo() );
13998
13999		// Initialize menu widget
14000		this.menuInstance = this.menu
14001			.menu( {
14002				classes: {
14003					"ui-menu": "ui-corner-bottom"
14004				},
14005				role: "listbox",
14006				select: function( event, ui ) {
14007					event.preventDefault();
14008					that._select( ui.item.data( "ui-selectmenu-item" ), event );
14009				},
14010				focus: function( event, ui ) {
14011					var item = ui.item.data( "ui-selectmenu-item" );
14012
14013					// Prevent inital focus from firing and check if its a newly focused item
14014					if ( that.focusIndex != null && item.index !== that.focusIndex ) {
14015						that._trigger( "focus", event, { item: item } );
14016						if ( !that.isOpen ) {
14017							that._select( item, event );
14018						}
14019					}
14020					that.focusIndex = item.index;
14021
14022					that.button.attr( "aria-activedescendant",
14023						that.menuItems.eq( item.index ).attr( "id" ) );
14024				}
14025			} )
14026			.menu( "instance" );
14027
14028		// Don't close the menu on mouseleave
14029		this.menuInstance._off( this.menu, "mouseleave" );
14030
14031		// Cancel the menu's collapseAll on document click
14032		this.menuInstance._closeOnDocumentClick = function() {
14033			return false;
14034		};
14035
14036		// Selects often contain empty items, but never contain dividers
14037		this.menuInstance._isDivider = function() {
14038			return false;
14039		};
14040	},
14041
14042	refresh: function() {
14043		this._refreshMenu();
14044		this.buttonItem.replaceWith(
14045			this.buttonItem = this._renderButtonItem(
14046
14047				// Fall back to an empty object in case there are no options
14048				this._getSelectedItem().data( "ui-selectmenu-item" ) || {}
14049			)
14050		);
14051		if ( this.options.width === null ) {
14052			this._resizeButton();
14053		}
14054	},
14055
14056	_refreshMenu: function() {
14057		var item,
14058			options = this.element.find( "option" );
14059
14060		this.menu.empty();
14061
14062		this._parseOptions( options );
14063		this._renderMenu( this.menu, this.items );
14064
14065		this.menuInstance.refresh();
14066		this.menuItems = this.menu.find( "li" )
14067			.not( ".ui-selectmenu-optgroup" )
14068				.find( ".ui-menu-item-wrapper" );
14069
14070		this._rendered = true;
14071
14072		if ( !options.length ) {
14073			return;
14074		}
14075
14076		item = this._getSelectedItem();
14077
14078		// Update the menu to have the correct item focused
14079		this.menuInstance.focus( null, item );
14080		this._setAria( item.data( "ui-selectmenu-item" ) );
14081
14082		// Set disabled state
14083		this._setOption( "disabled", this.element.prop( "disabled" ) );
14084	},
14085
14086	open: function( event ) {
14087		if ( this.options.disabled ) {
14088			return;
14089		}
14090
14091		// If this is the first time the menu is being opened, render the items
14092		if ( !this._rendered ) {
14093			this._refreshMenu();
14094		} else {
14095
14096			// Menu clears focus on close, reset focus to selected item
14097			this._removeClass( this.menu.find( ".ui-state-active" ), null, "ui-state-active" );
14098			this.menuInstance.focus( null, this._getSelectedItem() );
14099		}
14100
14101		// If there are no options, don't open the menu
14102		if ( !this.menuItems.length ) {
14103			return;
14104		}
14105
14106		this.isOpen = true;
14107		this._toggleAttr();
14108		this._resizeMenu();
14109		this._position();
14110
14111		this._on( this.document, this._documentClick );
14112
14113		this._trigger( "open", event );
14114	},
14115
14116	_position: function() {
14117		this.menuWrap.position( $.extend( { of: this.button }, this.options.position ) );
14118	},
14119
14120	close: function( event ) {
14121		if ( !this.isOpen ) {
14122			return;
14123		}
14124
14125		this.isOpen = false;
14126		this._toggleAttr();
14127
14128		this.range = null;
14129		this._off( this.document );
14130
14131		this._trigger( "close", event );
14132	},
14133
14134	widget: function() {
14135		return this.button;
14136	},
14137
14138	menuWidget: function() {
14139		return this.menu;
14140	},
14141
14142	_renderButtonItem: function( item ) {
14143		var buttonItem = $( "<span>" );
14144
14145		this._setText( buttonItem, item.label );
14146		this._addClass( buttonItem, "ui-selectmenu-text" );
14147
14148		return buttonItem;
14149	},
14150
14151	_renderMenu: function( ul, items ) {
14152		var that = this,
14153			currentOptgroup = "";
14154
14155		$.each( items, function( index, item ) {
14156			var li;
14157
14158			if ( item.optgroup !== currentOptgroup ) {
14159				li = $( "<li>", {
14160					text: item.optgroup
14161				} );
14162				that._addClass( li, "ui-selectmenu-optgroup", "ui-menu-divider" +
14163					( item.element.parent( "optgroup" ).prop( "disabled" ) ?
14164						" ui-state-disabled" :
14165						"" ) );
14166
14167				li.appendTo( ul );
14168
14169				currentOptgroup = item.optgroup;
14170			}
14171
14172			that._renderItemData( ul, item );
14173		} );
14174	},
14175
14176	_renderItemData: function( ul, item ) {
14177		return this._renderItem( ul, item ).data( "ui-selectmenu-item", item );
14178	},
14179
14180	_renderItem: function( ul, item ) {
14181		var li = $( "<li>" ),
14182			wrapper = $( "<div>", {
14183				title: item.element.attr( "title" )
14184			} );
14185
14186		if ( item.disabled ) {
14187			this._addClass( li, null, "ui-state-disabled" );
14188		}
14189
14190		if ( item.hidden ) {
14191			li.prop( "hidden", true );
14192		} else {
14193			this._setText( wrapper, item.label );
14194		}
14195
14196		return li.append( wrapper ).appendTo( ul );
14197	},
14198
14199	_setText: function( element, value ) {
14200		if ( value ) {
14201			element.text( value );
14202		} else {
14203			element.html( "&#160;" );
14204		}
14205	},
14206
14207	_move: function( direction, event ) {
14208		var item, next,
14209			filter = ".ui-menu-item";
14210
14211		if ( this.isOpen ) {
14212			item = this.menuItems.eq( this.focusIndex ).parent( "li" );
14213		} else {
14214			item = this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( "li" );
14215			filter += ":not(.ui-state-disabled)";
14216		}
14217
14218		if ( direction === "first" || direction === "last" ) {
14219			next = item[ direction === "first" ? "prevAll" : "nextAll" ]( filter ).eq( -1 );
14220		} else {
14221			next = item[ direction + "All" ]( filter ).eq( 0 );
14222		}
14223
14224		if ( next.length ) {
14225			this.menuInstance.focus( event, next );
14226		}
14227	},
14228
14229	_getSelectedItem: function() {
14230		return this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( "li" );
14231	},
14232
14233	_toggle: function( event ) {
14234		this[ this.isOpen ? "close" : "open" ]( event );
14235	},
14236
14237	_setSelection: function() {
14238		var selection;
14239
14240		if ( !this.range ) {
14241			return;
14242		}
14243
14244		selection = window.getSelection();
14245		selection.removeAllRanges();
14246		selection.addRange( this.range );
14247	},
14248
14249	_documentClick: {
14250		mousedown: function( event ) {
14251			if ( !this.isOpen ) {
14252				return;
14253			}
14254
14255			if ( !$( event.target ).closest( ".ui-selectmenu-menu, #" +
14256				CSS.escape( this.ids.button ) ).length ) {
14257				this.close( event );
14258			}
14259		}
14260	},
14261
14262	_buttonEvents: {
14263
14264		// Prevent text selection from being reset when interacting with the selectmenu (#10144)
14265		mousedown: function() {
14266			var selection = window.getSelection();
14267			if ( selection.rangeCount ) {
14268				this.range = selection.getRangeAt( 0 );
14269			}
14270		},
14271
14272		click: function( event ) {
14273			this._setSelection();
14274			this._toggle( event );
14275		},
14276
14277		keydown: function( event ) {
14278			var preventDefault = true;
14279			switch ( event.keyCode ) {
14280			case $.ui.keyCode.TAB:
14281			case $.ui.keyCode.ESCAPE:
14282				this.close( event );
14283				preventDefault = false;
14284				break;
14285			case $.ui.keyCode.ENTER:
14286				if ( this.isOpen ) {
14287					this._selectFocusedItem( event );
14288				}
14289				break;
14290			case $.ui.keyCode.UP:
14291				if ( event.altKey ) {
14292					this._toggle( event );
14293				} else {
14294					this._move( "prev", event );
14295				}
14296				break;
14297			case $.ui.keyCode.DOWN:
14298				if ( event.altKey ) {
14299					this._toggle( event );
14300				} else {
14301					this._move( "next", event );
14302				}
14303				break;
14304			case $.ui.keyCode.SPACE:
14305				if ( this.isOpen ) {
14306					this._selectFocusedItem( event );
14307				} else {
14308					this._toggle( event );
14309				}
14310				break;
14311			case $.ui.keyCode.LEFT:
14312				this._move( "prev", event );
14313				break;
14314			case $.ui.keyCode.RIGHT:
14315				this._move( "next", event );
14316				break;
14317			case $.ui.keyCode.HOME:
14318			case $.ui.keyCode.PAGE_UP:
14319				this._move( "first", event );
14320				break;
14321			case $.ui.keyCode.END:
14322			case $.ui.keyCode.PAGE_DOWN:
14323				this._move( "last", event );
14324				break;
14325			default:
14326				this.menu.trigger( event );
14327				preventDefault = false;
14328			}
14329
14330			if ( preventDefault ) {
14331				event.preventDefault();
14332			}
14333		}
14334	},
14335
14336	_selectFocusedItem: function( event ) {
14337		var item = this.menuItems.eq( this.focusIndex ).parent( "li" );
14338		if ( !item.hasClass( "ui-state-disabled" ) ) {
14339			this._select( item.data( "ui-selectmenu-item" ), event );
14340		}
14341	},
14342
14343	_select: function( item, event ) {
14344		var oldIndex = this.element[ 0 ].selectedIndex;
14345
14346		// Change native select element
14347		this.element[ 0 ].selectedIndex = item.index;
14348		this.buttonItem.replaceWith( this.buttonItem = this._renderButtonItem( item ) );
14349		this._setAria( item );
14350		this._trigger( "select", event, { item: item } );
14351
14352		if ( item.index !== oldIndex ) {
14353			this._trigger( "change", event, { item: item } );
14354		}
14355
14356		this.close( event );
14357	},
14358
14359	_setAria: function( item ) {
14360		var id = this.menuItems.eq( item.index ).attr( "id" );
14361
14362		this.button.attr( {
14363			"aria-labelledby": id,
14364			"aria-activedescendant": id
14365		} );
14366		this.menu.attr( "aria-activedescendant", id );
14367	},
14368
14369	_setOption: function( key, value ) {
14370		if ( key === "icons" ) {
14371			var icon = this.button.find( "span.ui-icon" );
14372			this._removeClass( icon, null, this.options.icons.button )
14373				._addClass( icon, null, value.button );
14374		}
14375
14376		this._super( key, value );
14377
14378		if ( key === "appendTo" ) {
14379			this.menuWrap.appendTo( this._appendTo() );
14380		}
14381
14382		if ( key === "width" ) {
14383			this._resizeButton();
14384		}
14385	},
14386
14387	_setOptionDisabled: function( value ) {
14388		this._super( value );
14389
14390		this.menuInstance.option( "disabled", value );
14391		this.button.attr( "aria-disabled", value );
14392		this._toggleClass( this.button, null, "ui-state-disabled", value );
14393
14394		this.element.prop( "disabled", value );
14395		if ( value ) {
14396			this.button.attr( "tabindex", -1 );
14397			this.close();
14398		} else {
14399			this.button.attr( "tabindex", 0 );
14400		}
14401	},
14402
14403	_appendTo: function() {
14404		var element = this.options.appendTo;
14405
14406		if ( element ) {
14407			element = element.jquery || element.nodeType ?
14408				$( element ) :
14409				this.document.find( element ).eq( 0 );
14410		}
14411
14412		if ( !element || !element[ 0 ] ) {
14413			element = this.element.closest( ".ui-front, dialog" );
14414		}
14415
14416		if ( !element.length ) {
14417			element = this.document[ 0 ].body;
14418		}
14419
14420		return element;
14421	},
14422
14423	_toggleAttr: function() {
14424		this.button.attr( "aria-expanded", this.isOpen );
14425
14426		// We can't use two _toggleClass() calls here, because we need to make sure
14427		// we always remove classes first and add them second, otherwise if both classes have the
14428		// same theme class, it will be removed after we add it.
14429		this._removeClass( this.button, "ui-selectmenu-button-" +
14430			( this.isOpen ? "closed" : "open" ) )
14431			._addClass( this.button, "ui-selectmenu-button-" +
14432				( this.isOpen ? "open" : "closed" ) )
14433			._toggleClass( this.menuWrap, "ui-selectmenu-open", null, this.isOpen );
14434
14435		this.menu.attr( "aria-hidden", !this.isOpen );
14436	},
14437
14438	_resizeButton: function() {
14439		var width = this.options.width;
14440
14441		// For `width: false`, just remove inline style and stop
14442		if ( width === false ) {
14443			this.button.css( "width", "" );
14444			return;
14445		}
14446
14447		// For `width: null`, match the width of the original element
14448		if ( width === null ) {
14449			width = this.element.show().outerWidth();
14450			this.element.hide();
14451		}
14452
14453		this.button.outerWidth( width );
14454	},
14455
14456	_resizeMenu: function() {
14457		this.menu.outerWidth( Math.max(
14458			this.button.outerWidth(),
14459			this.menu.width( "" ).outerWidth()
14460		) );
14461	},
14462
14463	_getCreateOptions: function() {
14464		var options = this._super();
14465
14466		options.disabled = this.element.prop( "disabled" );
14467
14468		return options;
14469	},
14470
14471	_parseOptions: function( options ) {
14472		var that = this,
14473			data = [];
14474		options.each( function( index, item ) {
14475			data.push( that._parseOption( $( item ), index ) );
14476		} );
14477		this.items = data;
14478	},
14479
14480	_parseOption: function( option, index ) {
14481		var optgroup = option.parent( "optgroup" );
14482
14483		return {
14484			element: option,
14485			index: index,
14486			value: option.val(),
14487			label: option.text(),
14488			hidden: optgroup.prop( "hidden" ) || option.prop( "hidden" ),
14489			optgroup: optgroup.attr( "label" ) || "",
14490			disabled: optgroup.prop( "disabled" ) || option.prop( "disabled" )
14491		};
14492	},
14493
14494	_destroy: function() {
14495		this._unbindFormResetHandler();
14496		this.menuWrap.remove();
14497		this.button.remove();
14498		this.element.show();
14499		this.element.removeUniqueId();
14500		this.labels.attr( "for", this.ids.element );
14501	}
14502} ] );
14503
14504
14505/*!
14506 * jQuery UI Slider 1.14.0
14507 * https://jqueryui.com
14508 *
14509 * Copyright OpenJS Foundation and other contributors
14510 * Released under the MIT license.
14511 * https://jquery.org/license
14512 */
14513
14514//>>label: Slider
14515//>>group: Widgets
14516//>>description: Displays a flexible slider with ranges and accessibility via keyboard.
14517//>>docs: https://api.jqueryui.com/slider/
14518//>>demos: https://jqueryui.com/slider/
14519//>>css.structure: ../../themes/base/core.css
14520//>>css.structure: ../../themes/base/slider.css
14521//>>css.theme: ../../themes/base/theme.css
14522
14523
14524var widgetsSlider = $.widget( "ui.slider", $.ui.mouse, {
14525	version: "1.14.0",
14526	widgetEventPrefix: "slide",
14527
14528	options: {
14529		animate: false,
14530		classes: {
14531			"ui-slider": "ui-corner-all",
14532			"ui-slider-handle": "ui-corner-all",
14533
14534			// Note: ui-widget-header isn't the most fittingly semantic framework class for this
14535			// element, but worked best visually with a variety of themes
14536			"ui-slider-range": "ui-corner-all ui-widget-header"
14537		},
14538		distance: 0,
14539		max: 100,
14540		min: 0,
14541		orientation: "horizontal",
14542		range: false,
14543		step: 1,
14544		value: 0,
14545		values: null,
14546
14547		// Callbacks
14548		change: null,
14549		slide: null,
14550		start: null,
14551		stop: null
14552	},
14553
14554	// Number of pages in a slider
14555	// (how many times can you page up/down to go through the whole range)
14556	numPages: 5,
14557
14558	_create: function() {
14559		this._keySliding = false;
14560		this._mouseSliding = false;
14561		this._animateOff = true;
14562		this._handleIndex = null;
14563		this._detectOrientation();
14564		this._mouseInit();
14565		this._calculateNewMax();
14566
14567		this._addClass( "ui-slider ui-slider-" + this.orientation,
14568			"ui-widget ui-widget-content" );
14569
14570		this._refresh();
14571
14572		this._animateOff = false;
14573	},
14574
14575	_refresh: function() {
14576		this._createRange();
14577		this._createHandles();
14578		this._setupEvents();
14579		this._refreshValue();
14580	},
14581
14582	_createHandles: function() {
14583		var i, handleCount,
14584			options = this.options,
14585			existingHandles = this.element.find( ".ui-slider-handle" ),
14586			handle = "<span tabindex='0'></span>",
14587			handles = [];
14588
14589		handleCount = ( options.values && options.values.length ) || 1;
14590
14591		if ( existingHandles.length > handleCount ) {
14592			existingHandles.slice( handleCount ).remove();
14593			existingHandles = existingHandles.slice( 0, handleCount );
14594		}
14595
14596		for ( i = existingHandles.length; i < handleCount; i++ ) {
14597			handles.push( handle );
14598		}
14599
14600		this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) );
14601
14602		this._addClass( this.handles, "ui-slider-handle", "ui-state-default" );
14603
14604		this.handle = this.handles.eq( 0 );
14605
14606		this.handles.each( function( i ) {
14607			$( this )
14608				.data( "ui-slider-handle-index", i )
14609				.attr( "tabIndex", 0 );
14610		} );
14611	},
14612
14613	_createRange: function() {
14614		var options = this.options;
14615
14616		if ( options.range ) {
14617			if ( options.range === true ) {
14618				if ( !options.values ) {
14619					options.values = [ this._valueMin(), this._valueMin() ];
14620				} else if ( options.values.length && options.values.length !== 2 ) {
14621					options.values = [ options.values[ 0 ], options.values[ 0 ] ];
14622				} else if ( Array.isArray( options.values ) ) {
14623					options.values = options.values.slice( 0 );
14624				}
14625			}
14626
14627			if ( !this.range || !this.range.length ) {
14628				this.range = $( "<div>" )
14629					.appendTo( this.element );
14630
14631				this._addClass( this.range, "ui-slider-range" );
14632			} else {
14633				this._removeClass( this.range, "ui-slider-range-min ui-slider-range-max" );
14634
14635				// Handle range switching from true to min/max
14636				this.range.css( {
14637					"left": "",
14638					"bottom": ""
14639				} );
14640			}
14641			if ( options.range === "min" || options.range === "max" ) {
14642				this._addClass( this.range, "ui-slider-range-" + options.range );
14643			}
14644		} else {
14645			if ( this.range ) {
14646				this.range.remove();
14647			}
14648			this.range = null;
14649		}
14650	},
14651
14652	_setupEvents: function() {
14653		this._off( this.handles );
14654		this._on( this.handles, this._handleEvents );
14655		this._hoverable( this.handles );
14656		this._focusable( this.handles );
14657	},
14658
14659	_destroy: function() {
14660		this.handles.remove();
14661		if ( this.range ) {
14662			this.range.remove();
14663		}
14664
14665		this._mouseDestroy();
14666	},
14667
14668	_mouseCapture: function( event ) {
14669		var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle,
14670			that = this,
14671			o = this.options;
14672
14673		if ( o.disabled ) {
14674			return false;
14675		}
14676
14677		this.elementSize = {
14678			width: this.element.outerWidth(),
14679			height: this.element.outerHeight()
14680		};
14681		this.elementOffset = this.element.offset();
14682
14683		position = { x: event.pageX, y: event.pageY };
14684		normValue = this._normValueFromMouse( position );
14685		distance = this._valueMax() - this._valueMin() + 1;
14686		this.handles.each( function( i ) {
14687			var thisDistance = Math.abs( normValue - that.values( i ) );
14688			if ( ( distance > thisDistance ) ||
14689				( distance === thisDistance &&
14690					( i === that._lastChangedValue || that.values( i ) === o.min ) ) ) {
14691				distance = thisDistance;
14692				closestHandle = $( this );
14693				index = i;
14694			}
14695		} );
14696
14697		allowed = this._start( event, index );
14698		if ( allowed === false ) {
14699			return false;
14700		}
14701		this._mouseSliding = true;
14702
14703		this._handleIndex = index;
14704
14705		this._addClass( closestHandle, null, "ui-state-active" );
14706		closestHandle.trigger( "focus" );
14707
14708		offset = closestHandle.offset();
14709		mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" );
14710		this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
14711			left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
14712			top: event.pageY - offset.top -
14713				( closestHandle.height() / 2 ) -
14714				( parseInt( closestHandle.css( "borderTopWidth" ), 10 ) || 0 ) -
14715				( parseInt( closestHandle.css( "borderBottomWidth" ), 10 ) || 0 ) +
14716				( parseInt( closestHandle.css( "marginTop" ), 10 ) || 0 )
14717		};
14718
14719		if ( !this.handles.hasClass( "ui-state-hover" ) ) {
14720			this._slide( event, index, normValue );
14721		}
14722		this._animateOff = true;
14723		return true;
14724	},
14725
14726	_mouseStart: function() {
14727		return true;
14728	},
14729
14730	_mouseDrag: function( event ) {
14731		var position = { x: event.pageX, y: event.pageY },
14732			normValue = this._normValueFromMouse( position );
14733
14734		this._slide( event, this._handleIndex, normValue );
14735
14736		return false;
14737	},
14738
14739	_mouseStop: function( event ) {
14740		this._removeClass( this.handles, null, "ui-state-active" );
14741		this._mouseSliding = false;
14742
14743		this._stop( event, this._handleIndex );
14744		this._change( event, this._handleIndex );
14745
14746		this._handleIndex = null;
14747		this._clickOffset = null;
14748		this._animateOff = false;
14749
14750		return false;
14751	},
14752
14753	_detectOrientation: function() {
14754		this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
14755	},
14756
14757	_normValueFromMouse: function( position ) {
14758		var pixelTotal,
14759			pixelMouse,
14760			percentMouse,
14761			valueTotal,
14762			valueMouse;
14763
14764		if ( this.orientation === "horizontal" ) {
14765			pixelTotal = this.elementSize.width;
14766			pixelMouse = position.x - this.elementOffset.left -
14767				( this._clickOffset ? this._clickOffset.left : 0 );
14768		} else {
14769			pixelTotal = this.elementSize.height;
14770			pixelMouse = position.y - this.elementOffset.top -
14771				( this._clickOffset ? this._clickOffset.top : 0 );
14772		}
14773
14774		percentMouse = ( pixelMouse / pixelTotal );
14775		if ( percentMouse > 1 ) {
14776			percentMouse = 1;
14777		}
14778		if ( percentMouse < 0 ) {
14779			percentMouse = 0;
14780		}
14781		if ( this.orientation === "vertical" ) {
14782			percentMouse = 1 - percentMouse;
14783		}
14784
14785		valueTotal = this._valueMax() - this._valueMin();
14786		valueMouse = this._valueMin() + percentMouse * valueTotal;
14787
14788		return this._trimAlignValue( valueMouse );
14789	},
14790
14791	_uiHash: function( index, value, values ) {
14792		var uiHash = {
14793			handle: this.handles[ index ],
14794			handleIndex: index,
14795			value: value !== undefined ? value : this.value()
14796		};
14797
14798		if ( this._hasMultipleValues() ) {
14799			uiHash.value = value !== undefined ? value : this.values( index );
14800			uiHash.values = values || this.values();
14801		}
14802
14803		return uiHash;
14804	},
14805
14806	_hasMultipleValues: function() {
14807		return this.options.values && this.options.values.length;
14808	},
14809
14810	_start: function( event, index ) {
14811		return this._trigger( "start", event, this._uiHash( index ) );
14812	},
14813
14814	_slide: function( event, index, newVal ) {
14815		var allowed, otherVal,
14816			currentValue = this.value(),
14817			newValues = this.values();
14818
14819		if ( this._hasMultipleValues() ) {
14820			otherVal = this.values( index ? 0 : 1 );
14821			currentValue = this.values( index );
14822
14823			if ( this.options.values.length === 2 && this.options.range === true ) {
14824				newVal =  index === 0 ? Math.min( otherVal, newVal ) : Math.max( otherVal, newVal );
14825			}
14826
14827			newValues[ index ] = newVal;
14828		}
14829
14830		if ( newVal === currentValue ) {
14831			return;
14832		}
14833
14834		allowed = this._trigger( "slide", event, this._uiHash( index, newVal, newValues ) );
14835
14836		// A slide can be canceled by returning false from the slide callback
14837		if ( allowed === false ) {
14838			return;
14839		}
14840
14841		if ( this._hasMultipleValues() ) {
14842			this.values( index, newVal );
14843		} else {
14844			this.value( newVal );
14845		}
14846	},
14847
14848	_stop: function( event, index ) {
14849		this._trigger( "stop", event, this._uiHash( index ) );
14850	},
14851
14852	_change: function( event, index ) {
14853		if ( !this._keySliding && !this._mouseSliding ) {
14854
14855			//store the last changed value index for reference when handles overlap
14856			this._lastChangedValue = index;
14857			this._trigger( "change", event, this._uiHash( index ) );
14858		}
14859	},
14860
14861	value: function( newValue ) {
14862		if ( arguments.length ) {
14863			this.options.value = this._trimAlignValue( newValue );
14864			this._refreshValue();
14865			this._change( null, 0 );
14866			return;
14867		}
14868
14869		return this._value();
14870	},
14871
14872	values: function( index, newValue ) {
14873		var vals,
14874			newValues,
14875			i;
14876
14877		if ( arguments.length > 1 ) {
14878			this.options.values[ index ] = this._trimAlignValue( newValue );
14879			this._refreshValue();
14880			this._change( null, index );
14881			return;
14882		}
14883
14884		if ( arguments.length ) {
14885			if ( Array.isArray( arguments[ 0 ] ) ) {
14886				vals = this.options.values;
14887				newValues = arguments[ 0 ];
14888				for ( i = 0; i < vals.length; i += 1 ) {
14889					vals[ i ] = this._trimAlignValue( newValues[ i ] );
14890					this._change( null, i );
14891				}
14892				this._refreshValue();
14893			} else {
14894				if ( this._hasMultipleValues() ) {
14895					return this._values( index );
14896				} else {
14897					return this.value();
14898				}
14899			}
14900		} else {
14901			return this._values();
14902		}
14903	},
14904
14905	_setOption: function( key, value ) {
14906		var i,
14907			valsLength = 0;
14908
14909		if ( key === "range" && this.options.range === true ) {
14910			if ( value === "min" ) {
14911				this.options.value = this._values( 0 );
14912				this.options.values = null;
14913			} else if ( value === "max" ) {
14914				this.options.value = this._values( this.options.values.length - 1 );
14915				this.options.values = null;
14916			}
14917		}
14918
14919		if ( Array.isArray( this.options.values ) ) {
14920			valsLength = this.options.values.length;
14921		}
14922
14923		this._super( key, value );
14924
14925		switch ( key ) {
14926			case "orientation":
14927				this._detectOrientation();
14928				this._removeClass( "ui-slider-horizontal ui-slider-vertical" )
14929					._addClass( "ui-slider-" + this.orientation );
14930				this._refreshValue();
14931				if ( this.options.range ) {
14932					this._refreshRange( value );
14933				}
14934
14935				// Reset positioning from previous orientation
14936				this.handles.css( value === "horizontal" ? "bottom" : "left", "" );
14937				break;
14938			case "value":
14939				this._animateOff = true;
14940				this._refreshValue();
14941				this._change( null, 0 );
14942				this._animateOff = false;
14943				break;
14944			case "values":
14945				this._animateOff = true;
14946				this._refreshValue();
14947
14948				// Start from the last handle to prevent unreachable handles (#9046)
14949				for ( i = valsLength - 1; i >= 0; i-- ) {
14950					this._change( null, i );
14951				}
14952				this._animateOff = false;
14953				break;
14954			case "step":
14955			case "min":
14956			case "max":
14957				this._animateOff = true;
14958				this._calculateNewMax();
14959				this._refreshValue();
14960				this._animateOff = false;
14961				break;
14962			case "range":
14963				this._animateOff = true;
14964				this._refresh();
14965				this._animateOff = false;
14966				break;
14967		}
14968	},
14969
14970	_setOptionDisabled: function( value ) {
14971		this._super( value );
14972
14973		this._toggleClass( null, "ui-state-disabled", !!value );
14974	},
14975
14976	//internal value getter
14977	// _value() returns value trimmed by min and max, aligned by step
14978	_value: function() {
14979		var val = this.options.value;
14980		val = this._trimAlignValue( val );
14981
14982		return val;
14983	},
14984
14985	//internal values getter
14986	// _values() returns array of values trimmed by min and max, aligned by step
14987	// _values( index ) returns single value trimmed by min and max, aligned by step
14988	_values: function( index ) {
14989		var val,
14990			vals,
14991			i;
14992
14993		if ( arguments.length ) {
14994			val = this.options.values[ index ];
14995			val = this._trimAlignValue( val );
14996
14997			return val;
14998		} else if ( this._hasMultipleValues() ) {
14999
15000			// .slice() creates a copy of the array
15001			// this copy gets trimmed by min and max and then returned
15002			vals = this.options.values.slice();
15003			for ( i = 0; i < vals.length; i += 1 ) {
15004				vals[ i ] = this._trimAlignValue( vals[ i ] );
15005			}
15006
15007			return vals;
15008		} else {
15009			return [];
15010		}
15011	},
15012
15013	// Returns the step-aligned value that val is closest to, between (inclusive) min and max
15014	_trimAlignValue: function( val ) {
15015		if ( val <= this._valueMin() ) {
15016			return this._valueMin();
15017		}
15018		if ( val >= this._valueMax() ) {
15019			return this._valueMax();
15020		}
15021		var step = ( this.options.step > 0 ) ? this.options.step : 1,
15022			valModStep = ( val - this._valueMin() ) % step,
15023			alignValue = val - valModStep;
15024
15025		if ( Math.abs( valModStep ) * 2 >= step ) {
15026			alignValue += ( valModStep > 0 ) ? step : ( -step );
15027		}
15028
15029		// Since JavaScript has problems with large floats, round
15030		// the final value to 5 digits after the decimal point (see #4124)
15031		return parseFloat( alignValue.toFixed( 5 ) );
15032	},
15033
15034	_calculateNewMax: function() {
15035		var max = this.options.max,
15036			min = this._valueMin(),
15037			step = this.options.step,
15038			aboveMin = Math.round( ( max - min ) / step ) * step;
15039		max = aboveMin + min;
15040		if ( max > this.options.max ) {
15041
15042			//If max is not divisible by step, rounding off may increase its value
15043			max -= step;
15044		}
15045		this.max = parseFloat( max.toFixed( this._precision() ) );
15046	},
15047
15048	_precision: function() {
15049		var precision = this._precisionOf( this.options.step );
15050		if ( this.options.min !== null ) {
15051			precision = Math.max( precision, this._precisionOf( this.options.min ) );
15052		}
15053		return precision;
15054	},
15055
15056	_precisionOf: function( num ) {
15057		var str = num.toString(),
15058			decimal = str.indexOf( "." );
15059		return decimal === -1 ? 0 : str.length - decimal - 1;
15060	},
15061
15062	_valueMin: function() {
15063		return this.options.min;
15064	},
15065
15066	_valueMax: function() {
15067		return this.max;
15068	},
15069
15070	_refreshRange: function( orientation ) {
15071		if ( orientation === "vertical" ) {
15072			this.range.css( { "width": "", "left": "" } );
15073		}
15074		if ( orientation === "horizontal" ) {
15075			this.range.css( { "height": "", "bottom": "" } );
15076		}
15077	},
15078
15079	_refreshValue: function() {
15080		var lastValPercent, valPercent, value, valueMin, valueMax,
15081			oRange = this.options.range,
15082			o = this.options,
15083			that = this,
15084			animate = ( !this._animateOff ) ? o.animate : false,
15085			_set = {};
15086
15087		if ( this._hasMultipleValues() ) {
15088			this.handles.each( function( i ) {
15089				valPercent = ( that.values( i ) - that._valueMin() ) / ( that._valueMax() -
15090					that._valueMin() ) * 100;
15091				_set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
15092				$( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
15093				if ( that.options.range === true ) {
15094					if ( that.orientation === "horizontal" ) {
15095						if ( i === 0 ) {
15096							that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15097								left: valPercent + "%"
15098							}, o.animate );
15099						}
15100						if ( i === 1 ) {
15101							that.range[ animate ? "animate" : "css" ]( {
15102								width: ( valPercent - lastValPercent ) + "%"
15103							}, {
15104								queue: false,
15105								duration: o.animate
15106							} );
15107						}
15108					} else {
15109						if ( i === 0 ) {
15110							that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15111								bottom: ( valPercent ) + "%"
15112							}, o.animate );
15113						}
15114						if ( i === 1 ) {
15115							that.range[ animate ? "animate" : "css" ]( {
15116								height: ( valPercent - lastValPercent ) + "%"
15117							}, {
15118								queue: false,
15119								duration: o.animate
15120							} );
15121						}
15122					}
15123				}
15124				lastValPercent = valPercent;
15125			} );
15126		} else {
15127			value = this.value();
15128			valueMin = this._valueMin();
15129			valueMax = this._valueMax();
15130			valPercent = ( valueMax !== valueMin ) ?
15131					( value - valueMin ) / ( valueMax - valueMin ) * 100 :
15132					0;
15133			_set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
15134			this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
15135
15136			if ( oRange === "min" && this.orientation === "horizontal" ) {
15137				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15138					width: valPercent + "%"
15139				}, o.animate );
15140			}
15141			if ( oRange === "max" && this.orientation === "horizontal" ) {
15142				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15143					width: ( 100 - valPercent ) + "%"
15144				}, o.animate );
15145			}
15146			if ( oRange === "min" && this.orientation === "vertical" ) {
15147				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15148					height: valPercent + "%"
15149				}, o.animate );
15150			}
15151			if ( oRange === "max" && this.orientation === "vertical" ) {
15152				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15153					height: ( 100 - valPercent ) + "%"
15154				}, o.animate );
15155			}
15156		}
15157	},
15158
15159	_handleEvents: {
15160		keydown: function( event ) {
15161			var allowed, curVal, newVal, step,
15162				index = $( event.target ).data( "ui-slider-handle-index" );
15163
15164			switch ( event.keyCode ) {
15165				case $.ui.keyCode.HOME:
15166				case $.ui.keyCode.END:
15167				case $.ui.keyCode.PAGE_UP:
15168				case $.ui.keyCode.PAGE_DOWN:
15169				case $.ui.keyCode.UP:
15170				case $.ui.keyCode.RIGHT:
15171				case $.ui.keyCode.DOWN:
15172				case $.ui.keyCode.LEFT:
15173					event.preventDefault();
15174					if ( !this._keySliding ) {
15175						this._keySliding = true;
15176						this._addClass( $( event.target ), null, "ui-state-active" );
15177						allowed = this._start( event, index );
15178						if ( allowed === false ) {
15179							return;
15180						}
15181					}
15182					break;
15183			}
15184
15185			step = this.options.step;
15186			if ( this._hasMultipleValues() ) {
15187				curVal = newVal = this.values( index );
15188			} else {
15189				curVal = newVal = this.value();
15190			}
15191
15192			switch ( event.keyCode ) {
15193				case $.ui.keyCode.HOME:
15194					newVal = this._valueMin();
15195					break;
15196				case $.ui.keyCode.END:
15197					newVal = this._valueMax();
15198					break;
15199				case $.ui.keyCode.PAGE_UP:
15200					newVal = this._trimAlignValue(
15201						curVal + ( ( this._valueMax() - this._valueMin() ) / this.numPages )
15202					);
15203					break;
15204				case $.ui.keyCode.PAGE_DOWN:
15205					newVal = this._trimAlignValue(
15206						curVal - ( ( this._valueMax() - this._valueMin() ) / this.numPages ) );
15207					break;
15208				case $.ui.keyCode.UP:
15209				case $.ui.keyCode.RIGHT:
15210					if ( curVal === this._valueMax() ) {
15211						return;
15212					}
15213					newVal = this._trimAlignValue( curVal + step );
15214					break;
15215				case $.ui.keyCode.DOWN:
15216				case $.ui.keyCode.LEFT:
15217					if ( curVal === this._valueMin() ) {
15218						return;
15219					}
15220					newVal = this._trimAlignValue( curVal - step );
15221					break;
15222			}
15223
15224			this._slide( event, index, newVal );
15225		},
15226		keyup: function( event ) {
15227			var index = $( event.target ).data( "ui-slider-handle-index" );
15228
15229			if ( this._keySliding ) {
15230				this._keySliding = false;
15231				this._stop( event, index );
15232				this._change( event, index );
15233				this._removeClass( $( event.target ), null, "ui-state-active" );
15234			}
15235		}
15236	}
15237} );
15238
15239
15240/*!
15241 * jQuery UI Sortable 1.14.0
15242 * https://jqueryui.com
15243 *
15244 * Copyright OpenJS Foundation and other contributors
15245 * Released under the MIT license.
15246 * https://jquery.org/license
15247 */
15248
15249//>>label: Sortable
15250//>>group: Interactions
15251//>>description: Enables items in a list to be sorted using the mouse.
15252//>>docs: https://api.jqueryui.com/sortable/
15253//>>demos: https://jqueryui.com/sortable/
15254//>>css.structure: ../../themes/base/sortable.css
15255
15256
15257var widgetsSortable = $.widget( "ui.sortable", $.ui.mouse, {
15258	version: "1.14.0",
15259	widgetEventPrefix: "sort",
15260	ready: false,
15261	options: {
15262		appendTo: "parent",
15263		axis: false,
15264		connectWith: false,
15265		containment: false,
15266		cursor: "auto",
15267		cursorAt: false,
15268		dropOnEmpty: true,
15269		forcePlaceholderSize: false,
15270		forceHelperSize: false,
15271		grid: false,
15272		handle: false,
15273		helper: "original",
15274		items: "> *",
15275		opacity: false,
15276		placeholder: false,
15277		revert: false,
15278		scroll: true,
15279		scrollSensitivity: 20,
15280		scrollSpeed: 20,
15281		scope: "default",
15282		tolerance: "intersect",
15283		zIndex: 1000,
15284
15285		// Callbacks
15286		activate: null,
15287		beforeStop: null,
15288		change: null,
15289		deactivate: null,
15290		out: null,
15291		over: null,
15292		receive: null,
15293		remove: null,
15294		sort: null,
15295		start: null,
15296		stop: null,
15297		update: null
15298	},
15299
15300	_isOverAxis: function( x, reference, size ) {
15301		return ( x >= reference ) && ( x < ( reference + size ) );
15302	},
15303
15304	_isFloating: function( item ) {
15305		return ( /left|right/ ).test( item.css( "float" ) ) ||
15306			( /inline|table-cell/ ).test( item.css( "display" ) );
15307	},
15308
15309	_create: function() {
15310		this.containerCache = {};
15311		this._addClass( "ui-sortable" );
15312
15313		//Get the items
15314		this.refresh();
15315
15316		//Let's determine the parent's offset
15317		this.offset = this.element.offset();
15318
15319		//Initialize mouse events for interaction
15320		this._mouseInit();
15321
15322		this._setHandleClassName();
15323
15324		//We're ready to go
15325		this.ready = true;
15326
15327	},
15328
15329	_setOption: function( key, value ) {
15330		this._super( key, value );
15331
15332		if ( key === "handle" ) {
15333			this._setHandleClassName();
15334		}
15335	},
15336
15337	_setHandleClassName: function() {
15338		var that = this;
15339		this._removeClass( this.element.find( ".ui-sortable-handle" ), "ui-sortable-handle" );
15340		$.each( this.items, function() {
15341			that._addClass(
15342				this.instance.options.handle ?
15343					this.item.find( this.instance.options.handle ) :
15344					this.item,
15345				"ui-sortable-handle"
15346			);
15347		} );
15348	},
15349
15350	_destroy: function() {
15351		this._mouseDestroy();
15352
15353		for ( var i = this.items.length - 1; i >= 0; i-- ) {
15354			this.items[ i ].item.removeData( this.widgetName + "-item" );
15355		}
15356
15357		return this;
15358	},
15359
15360	_mouseCapture: function( event, overrideHandle ) {
15361		var currentItem = null,
15362			validHandle = false,
15363			that = this;
15364
15365		if ( this.reverting ) {
15366			return false;
15367		}
15368
15369		if ( this.options.disabled || this.options.type === "static" ) {
15370			return false;
15371		}
15372
15373		//We have to refresh the items data once first
15374		this._refreshItems( event );
15375
15376		//Find out if the clicked node (or one of its parents) is a actual item in this.items
15377		$( event.target ).parents().each( function() {
15378			if ( $.data( this, that.widgetName + "-item" ) === that ) {
15379				currentItem = $( this );
15380				return false;
15381			}
15382		} );
15383		if ( $.data( event.target, that.widgetName + "-item" ) === that ) {
15384			currentItem = $( event.target );
15385		}
15386
15387		if ( !currentItem ) {
15388			return false;
15389		}
15390		if ( this.options.handle && !overrideHandle ) {
15391			$( this.options.handle, currentItem ).find( "*" ).addBack().each( function() {
15392				if ( this === event.target ) {
15393					validHandle = true;
15394				}
15395			} );
15396			if ( !validHandle ) {
15397				return false;
15398			}
15399		}
15400
15401		this.currentItem = currentItem;
15402		this._removeCurrentsFromItems();
15403		return true;
15404
15405	},
15406
15407	_mouseStart: function( event, overrideHandle, noActivation ) {
15408
15409		var i, body,
15410			o = this.options;
15411
15412		this.currentContainer = this;
15413
15414		//We only need to call refreshPositions, because the refreshItems call has been moved to
15415		// mouseCapture
15416		this.refreshPositions();
15417
15418		//Prepare the dragged items parent
15419		this.appendTo = $( o.appendTo !== "parent" ?
15420				o.appendTo :
15421				this.currentItem.parent() );
15422
15423		//Create and append the visible helper
15424		this.helper = this._createHelper( event );
15425
15426		//Cache the helper size
15427		this._cacheHelperProportions();
15428
15429		/*
15430		 * - Position generation -
15431		 * This block generates everything position related - it's the core of draggables.
15432		 */
15433
15434		//Cache the margins of the original element
15435		this._cacheMargins();
15436
15437		//The element's absolute position on the page minus margins
15438		this.offset = this.currentItem.offset();
15439		this.offset = {
15440			top: this.offset.top - this.margins.top,
15441			left: this.offset.left - this.margins.left
15442		};
15443
15444		$.extend( this.offset, {
15445			click: { //Where the click happened, relative to the element
15446				left: event.pageX - this.offset.left,
15447				top: event.pageY - this.offset.top
15448			},
15449
15450			// This is a relative to absolute position minus the actual position calculation -
15451			// only used for relative positioned helper
15452			relative: this._getRelativeOffset()
15453		} );
15454
15455		// After we get the helper offset, but before we get the parent offset we can
15456		// change the helper's position to absolute
15457		// TODO: Still need to figure out a way to make relative sorting possible
15458		this.helper.css( "position", "absolute" );
15459		this.cssPosition = this.helper.css( "position" );
15460
15461		//Adjust the mouse offset relative to the helper if "cursorAt" is supplied
15462		if ( o.cursorAt ) {
15463			this._adjustOffsetFromHelper( o.cursorAt );
15464		}
15465
15466		//Cache the former DOM position
15467		this.domPosition = {
15468			prev: this.currentItem.prev()[ 0 ],
15469			parent: this.currentItem.parent()[ 0 ]
15470		};
15471
15472		// If the helper is not the original, hide the original so it's not playing any role during
15473		// the drag, won't cause anything bad this way
15474		if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {
15475			this.currentItem.hide();
15476		}
15477
15478		//Create the placeholder
15479		this._createPlaceholder();
15480
15481		//Get the next scrolling parent
15482		this.scrollParent = this.placeholder.scrollParent();
15483
15484		$.extend( this.offset, {
15485			parent: this._getParentOffset()
15486		} );
15487
15488		//Set a containment if given in the options
15489		if ( o.containment ) {
15490			this._setContainment();
15491		}
15492
15493		if ( o.cursor && o.cursor !== "auto" ) { // cursor option
15494			body = this.document.find( "body" );
15495
15496			this._storedStylesheet =
15497				$( "<style>*{ cursor: " + o.cursor + " !important; }</style>" ).appendTo( body );
15498		}
15499
15500		// We need to make sure to grab the zIndex before setting the
15501		// opacity, because setting the opacity to anything lower than 1
15502		// causes the zIndex to change from "auto" to 0.
15503		if ( o.zIndex ) { // zIndex option
15504			if ( this.helper.css( "zIndex" ) ) {
15505				this._storedZIndex = this.helper.css( "zIndex" );
15506			}
15507			this.helper.css( "zIndex", o.zIndex );
15508		}
15509
15510		if ( o.opacity ) { // opacity option
15511			if ( this.helper.css( "opacity" ) ) {
15512				this._storedOpacity = this.helper.css( "opacity" );
15513			}
15514			this.helper.css( "opacity", o.opacity );
15515		}
15516
15517		//Prepare scrolling
15518		if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
15519				this.scrollParent[ 0 ].tagName !== "HTML" ) {
15520			this.overflowOffset = this.scrollParent.offset();
15521		}
15522
15523		//Call callbacks
15524		this._trigger( "start", event, this._uiHash() );
15525
15526		//Recache the helper size
15527		if ( !this._preserveHelperProportions ) {
15528			this._cacheHelperProportions();
15529		}
15530
15531		//Post "activate" events to possible containers
15532		if ( !noActivation ) {
15533			for ( i = this.containers.length - 1; i >= 0; i-- ) {
15534				this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) );
15535			}
15536		}
15537
15538		//Prepare possible droppables
15539		if ( $.ui.ddmanager ) {
15540			$.ui.ddmanager.current = this;
15541		}
15542
15543		if ( $.ui.ddmanager && !o.dropBehaviour ) {
15544			$.ui.ddmanager.prepareOffsets( this, event );
15545		}
15546
15547		this.dragging = true;
15548
15549		this._addClass( this.helper, "ui-sortable-helper" );
15550
15551		//Move the helper, if needed
15552		if ( !this.helper.parent().is( this.appendTo ) ) {
15553			this.helper.detach().appendTo( this.appendTo );
15554
15555			//Update position
15556			this.offset.parent = this._getParentOffset();
15557		}
15558
15559		//Generate the original position
15560		this.position = this.originalPosition = this._generatePosition( event );
15561		this.originalPageX = event.pageX;
15562		this.originalPageY = event.pageY;
15563		this.lastPositionAbs = this.positionAbs = this._convertPositionTo( "absolute" );
15564
15565		this._mouseDrag( event );
15566
15567		return true;
15568
15569	},
15570
15571	_scroll: function( event ) {
15572		var o = this.options,
15573			scrolled = false;
15574
15575		if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
15576				this.scrollParent[ 0 ].tagName !== "HTML" ) {
15577
15578			if ( ( this.overflowOffset.top + this.scrollParent[ 0 ].offsetHeight ) -
15579					event.pageY < o.scrollSensitivity ) {
15580				this.scrollParent[ 0 ].scrollTop =
15581					scrolled = this.scrollParent[ 0 ].scrollTop + o.scrollSpeed;
15582			} else if ( event.pageY - this.overflowOffset.top < o.scrollSensitivity ) {
15583				this.scrollParent[ 0 ].scrollTop =
15584					scrolled = this.scrollParent[ 0 ].scrollTop - o.scrollSpeed;
15585			}
15586
15587			if ( ( this.overflowOffset.left + this.scrollParent[ 0 ].offsetWidth ) -
15588					event.pageX < o.scrollSensitivity ) {
15589				this.scrollParent[ 0 ].scrollLeft = scrolled =
15590					this.scrollParent[ 0 ].scrollLeft + o.scrollSpeed;
15591			} else if ( event.pageX - this.overflowOffset.left < o.scrollSensitivity ) {
15592				this.scrollParent[ 0 ].scrollLeft = scrolled =
15593					this.scrollParent[ 0 ].scrollLeft - o.scrollSpeed;
15594			}
15595
15596		} else {
15597
15598			if ( event.pageY - this.document.scrollTop() < o.scrollSensitivity ) {
15599				scrolled = this.document.scrollTop( this.document.scrollTop() - o.scrollSpeed );
15600			} else if ( this.window.height() - ( event.pageY - this.document.scrollTop() ) <
15601					o.scrollSensitivity ) {
15602				scrolled = this.document.scrollTop( this.document.scrollTop() + o.scrollSpeed );
15603			}
15604
15605			if ( event.pageX - this.document.scrollLeft() < o.scrollSensitivity ) {
15606				scrolled = this.document.scrollLeft(
15607					this.document.scrollLeft() - o.scrollSpeed
15608				);
15609			} else if ( this.window.width() - ( event.pageX - this.document.scrollLeft() ) <
15610					o.scrollSensitivity ) {
15611				scrolled = this.document.scrollLeft(
15612					this.document.scrollLeft() + o.scrollSpeed
15613				);
15614			}
15615
15616		}
15617
15618		return scrolled;
15619	},
15620
15621	_mouseDrag: function( event ) {
15622		var i, item, itemElement, intersection,
15623			o = this.options;
15624
15625		//Compute the helpers position
15626		this.position = this._generatePosition( event );
15627		this.positionAbs = this._convertPositionTo( "absolute" );
15628
15629		//Set the helper position
15630		if ( !this.options.axis || this.options.axis !== "y" ) {
15631			this.helper[ 0 ].style.left = this.position.left + "px";
15632		}
15633		if ( !this.options.axis || this.options.axis !== "x" ) {
15634			this.helper[ 0 ].style.top = this.position.top + "px";
15635		}
15636
15637		//Do scrolling
15638		if ( o.scroll ) {
15639			if ( this._scroll( event ) !== false ) {
15640
15641				//Update item positions used in position checks
15642				this._refreshItemPositions( true );
15643
15644				if ( $.ui.ddmanager && !o.dropBehaviour ) {
15645					$.ui.ddmanager.prepareOffsets( this, event );
15646				}
15647			}
15648		}
15649
15650		this.dragDirection = {
15651			vertical: this._getDragVerticalDirection(),
15652			horizontal: this._getDragHorizontalDirection()
15653		};
15654
15655		//Rearrange
15656		for ( i = this.items.length - 1; i >= 0; i-- ) {
15657
15658			//Cache variables and intersection, continue if no intersection
15659			item = this.items[ i ];
15660			itemElement = item.item[ 0 ];
15661			intersection = this._intersectsWithPointer( item );
15662			if ( !intersection ) {
15663				continue;
15664			}
15665
15666			// Only put the placeholder inside the current Container, skip all
15667			// items from other containers. This works because when moving
15668			// an item from one container to another the
15669			// currentContainer is switched before the placeholder is moved.
15670			//
15671			// Without this, moving items in "sub-sortables" can cause
15672			// the placeholder to jitter between the outer and inner container.
15673			if ( item.instance !== this.currentContainer ) {
15674				continue;
15675			}
15676
15677			// Cannot intersect with itself
15678			// no useless actions that have been done before
15679			// no action if the item moved is the parent of the item checked
15680			if ( itemElement !== this.currentItem[ 0 ] &&
15681				this.placeholder[ intersection === 1 ?
15682				"next" : "prev" ]()[ 0 ] !== itemElement &&
15683				!$.contains( this.placeholder[ 0 ], itemElement ) &&
15684				( this.options.type === "semi-dynamic" ?
15685					!$.contains( this.element[ 0 ], itemElement ) :
15686					true
15687				)
15688			) {
15689
15690				this.direction = intersection === 1 ? "down" : "up";
15691
15692				if ( this.options.tolerance === "pointer" ||
15693						this._intersectsWithSides( item ) ) {
15694					this._rearrange( event, item );
15695				} else {
15696					break;
15697				}
15698
15699				this._trigger( "change", event, this._uiHash() );
15700				break;
15701			}
15702		}
15703
15704		//Post events to containers
15705		this._contactContainers( event );
15706
15707		//Interconnect with droppables
15708		if ( $.ui.ddmanager ) {
15709			$.ui.ddmanager.drag( this, event );
15710		}
15711
15712		//Call callbacks
15713		this._trigger( "sort", event, this._uiHash() );
15714
15715		this.lastPositionAbs = this.positionAbs;
15716		return false;
15717
15718	},
15719
15720	_mouseStop: function( event, noPropagation ) {
15721
15722		if ( !event ) {
15723			return;
15724		}
15725
15726		//If we are using droppables, inform the manager about the drop
15727		if ( $.ui.ddmanager && !this.options.dropBehaviour ) {
15728			$.ui.ddmanager.drop( this, event );
15729		}
15730
15731		if ( this.options.revert ) {
15732			var that = this,
15733				cur = this.placeholder.offset(),
15734				axis = this.options.axis,
15735				animation = {};
15736
15737			if ( !axis || axis === "x" ) {
15738				animation.left = cur.left - this.offset.parent.left - this.margins.left +
15739					( this.offsetParent[ 0 ] === this.document[ 0 ].body ?
15740						0 :
15741						this.offsetParent[ 0 ].scrollLeft
15742					);
15743			}
15744			if ( !axis || axis === "y" ) {
15745				animation.top = cur.top - this.offset.parent.top - this.margins.top +
15746					( this.offsetParent[ 0 ] === this.document[ 0 ].body ?
15747						0 :
15748						this.offsetParent[ 0 ].scrollTop
15749					);
15750			}
15751			this.reverting = true;
15752			$( this.helper ).animate(
15753				animation,
15754				parseInt( this.options.revert, 10 ) || 500,
15755				function() {
15756					that._clear( event );
15757				}
15758			);
15759		} else {
15760			this._clear( event, noPropagation );
15761		}
15762
15763		return false;
15764
15765	},
15766
15767	cancel: function() {
15768
15769		if ( this.dragging ) {
15770
15771			this._mouseUp( new $.Event( "mouseup", { target: null } ) );
15772
15773			if ( this.options.helper === "original" ) {
15774				this.currentItem.css( this._storedCSS );
15775				this._removeClass( this.currentItem, "ui-sortable-helper" );
15776			} else {
15777				this.currentItem.show();
15778			}
15779
15780			//Post deactivating events to containers
15781			for ( var i = this.containers.length - 1; i >= 0; i-- ) {
15782				this.containers[ i ]._trigger( "deactivate", null, this._uiHash( this ) );
15783				if ( this.containers[ i ].containerCache.over ) {
15784					this.containers[ i ]._trigger( "out", null, this._uiHash( this ) );
15785					this.containers[ i ].containerCache.over = 0;
15786				}
15787			}
15788
15789		}
15790
15791		if ( this.placeholder ) {
15792
15793			//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately,
15794			// it unbinds ALL events from the original node!
15795			if ( this.placeholder[ 0 ].parentNode ) {
15796				this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] );
15797			}
15798			if ( this.options.helper !== "original" && this.helper &&
15799					this.helper[ 0 ].parentNode ) {
15800				this.helper.remove();
15801			}
15802
15803			$.extend( this, {
15804				helper: null,
15805				dragging: false,
15806				reverting: false,
15807				_noFinalSort: null
15808			} );
15809
15810			if ( this.domPosition.prev ) {
15811				$( this.domPosition.prev ).after( this.currentItem );
15812			} else {
15813				$( this.domPosition.parent ).prepend( this.currentItem );
15814			}
15815		}
15816
15817		return this;
15818
15819	},
15820
15821	serialize: function( o ) {
15822
15823		var items = this._getItemsAsjQuery( o && o.connected ),
15824			str = [];
15825		o = o || {};
15826
15827		$( items ).each( function() {
15828			var res = ( $( o.item || this ).attr( o.attribute || "id" ) || "" )
15829				.match( o.expression || ( /(.+)[\-=_](.+)/ ) );
15830			if ( res ) {
15831				str.push(
15832					( o.key || res[ 1 ] + "[]" ) +
15833					"=" + ( o.key && o.expression ? res[ 1 ] : res[ 2 ] ) );
15834			}
15835		} );
15836
15837		if ( !str.length && o.key ) {
15838			str.push( o.key + "=" );
15839		}
15840
15841		return str.join( "&" );
15842
15843	},
15844
15845	toArray: function( o ) {
15846
15847		var items = this._getItemsAsjQuery( o && o.connected ),
15848			ret = [];
15849
15850		o = o || {};
15851
15852		items.each( function() {
15853			ret.push( $( o.item || this ).attr( o.attribute || "id" ) || "" );
15854		} );
15855		return ret;
15856
15857	},
15858
15859	/* Be careful with the following core functions */
15860	_intersectsWith: function( item ) {
15861
15862		var x1 = this.positionAbs.left,
15863			x2 = x1 + this.helperProportions.width,
15864			y1 = this.positionAbs.top,
15865			y2 = y1 + this.helperProportions.height,
15866			l = item.left,
15867			r = l + item.width,
15868			t = item.top,
15869			b = t + item.height,
15870			dyClick = this.offset.click.top,
15871			dxClick = this.offset.click.left,
15872			isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t &&
15873				( y1 + dyClick ) < b ),
15874			isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l &&
15875				( x1 + dxClick ) < r ),
15876			isOverElement = isOverElementHeight && isOverElementWidth;
15877
15878		if ( this.options.tolerance === "pointer" ||
15879			this.options.forcePointerForContainers ||
15880			( this.options.tolerance !== "pointer" &&
15881				this.helperProportions[ this.floating ? "width" : "height" ] >
15882				item[ this.floating ? "width" : "height" ] )
15883		) {
15884			return isOverElement;
15885		} else {
15886
15887			return ( l < x1 + ( this.helperProportions.width / 2 ) && // Right Half
15888				x2 - ( this.helperProportions.width / 2 ) < r && // Left Half
15889				t < y1 + ( this.helperProportions.height / 2 ) && // Bottom Half
15890				y2 - ( this.helperProportions.height / 2 ) < b ); // Top Half
15891
15892		}
15893	},
15894
15895	_intersectsWithPointer: function( item ) {
15896		var verticalDirection, horizontalDirection,
15897			isOverElementHeight = ( this.options.axis === "x" ) ||
15898				this._isOverAxis(
15899					this.positionAbs.top + this.offset.click.top, item.top, item.height ),
15900			isOverElementWidth = ( this.options.axis === "y" ) ||
15901				this._isOverAxis(
15902					this.positionAbs.left + this.offset.click.left, item.left, item.width ),
15903			isOverElement = isOverElementHeight && isOverElementWidth;
15904
15905		if ( !isOverElement ) {
15906			return false;
15907		}
15908
15909		verticalDirection = this.dragDirection.vertical;
15910		horizontalDirection = this.dragDirection.horizontal;
15911
15912		return this.floating ?
15913			( ( horizontalDirection === "right" || verticalDirection === "down" ) ? 2 : 1 ) :
15914			( verticalDirection && ( verticalDirection === "down" ? 2 : 1 ) );
15915
15916	},
15917
15918	_intersectsWithSides: function( item ) {
15919
15920		var isOverBottomHalf = this._isOverAxis( this.positionAbs.top +
15921				this.offset.click.top, item.top + ( item.height / 2 ), item.height ),
15922			isOverRightHalf = this._isOverAxis( this.positionAbs.left +
15923				this.offset.click.left, item.left + ( item.width / 2 ), item.width ),
15924			verticalDirection = this.dragDirection.vertical,
15925			horizontalDirection = this.dragDirection.horizontal;
15926
15927		if ( this.floating && horizontalDirection ) {
15928			return ( ( horizontalDirection === "right" && isOverRightHalf ) ||
15929				( horizontalDirection === "left" && !isOverRightHalf ) );
15930		} else {
15931			return verticalDirection && ( ( verticalDirection === "down" && isOverBottomHalf ) ||
15932				( verticalDirection === "up" && !isOverBottomHalf ) );
15933		}
15934
15935	},
15936
15937	_getDragVerticalDirection: function() {
15938		var delta = this.positionAbs.top - this.lastPositionAbs.top;
15939		return delta !== 0 && ( delta > 0 ? "down" : "up" );
15940	},
15941
15942	_getDragHorizontalDirection: function() {
15943		var delta = this.positionAbs.left - this.lastPositionAbs.left;
15944		return delta !== 0 && ( delta > 0 ? "right" : "left" );
15945	},
15946
15947	refresh: function( event ) {
15948		this._refreshItems( event );
15949		this._setHandleClassName();
15950		this.refreshPositions();
15951		return this;
15952	},
15953
15954	_connectWith: function() {
15955		var options = this.options;
15956		return options.connectWith.constructor === String ?
15957			[ options.connectWith ] :
15958			options.connectWith;
15959	},
15960
15961	_getItemsAsjQuery: function( connected ) {
15962
15963		var i, j, cur, inst,
15964			items = [],
15965			queries = [],
15966			connectWith = this._connectWith();
15967
15968		if ( connectWith && connected ) {
15969			for ( i = connectWith.length - 1; i >= 0; i-- ) {
15970				cur = $( connectWith[ i ], this.document[ 0 ] );
15971				for ( j = cur.length - 1; j >= 0; j-- ) {
15972					inst = $.data( cur[ j ], this.widgetFullName );
15973					if ( inst && inst !== this && !inst.options.disabled ) {
15974						queries.push( [ typeof inst.options.items === "function" ?
15975							inst.options.items.call( inst.element ) :
15976							$( inst.options.items, inst.element )
15977								.not( ".ui-sortable-helper" )
15978								.not( ".ui-sortable-placeholder" ), inst ] );
15979					}
15980				}
15981			}
15982		}
15983
15984		queries.push( [ typeof this.options.items === "function" ?
15985			this.options.items
15986				.call( this.element, null, { options: this.options, item: this.currentItem } ) :
15987			$( this.options.items, this.element )
15988				.not( ".ui-sortable-helper" )
15989				.not( ".ui-sortable-placeholder" ), this ] );
15990
15991		function addItems() {
15992			items.push( this );
15993		}
15994		for ( i = queries.length - 1; i >= 0; i-- ) {
15995			queries[ i ][ 0 ].each( addItems );
15996		}
15997
15998		return $( items );
15999
16000	},
16001
16002	_removeCurrentsFromItems: function() {
16003
16004		var list = this.currentItem.find( ":data(" + this.widgetName + "-item)" );
16005
16006		this.items = $.grep( this.items, function( item ) {
16007			for ( var j = 0; j < list.length; j++ ) {
16008				if ( list[ j ] === item.item[ 0 ] ) {
16009					return false;
16010				}
16011			}
16012			return true;
16013		} );
16014
16015	},
16016
16017	_refreshItems: function( event ) {
16018
16019		this.items = [];
16020		this.containers = [ this ];
16021
16022		var i, j, cur, inst, targetData, _queries, item, queriesLength,
16023			items = this.items,
16024			queries = [ [ typeof this.options.items === "function" ?
16025				this.options.items.call( this.element[ 0 ], event, { item: this.currentItem } ) :
16026				$( this.options.items, this.element ), this ] ],
16027			connectWith = this._connectWith();
16028
16029		//Shouldn't be run the first time through due to massive slow-down
16030		if ( connectWith && this.ready ) {
16031			for ( i = connectWith.length - 1; i >= 0; i-- ) {
16032				cur = $( connectWith[ i ], this.document[ 0 ] );
16033				for ( j = cur.length - 1; j >= 0; j-- ) {
16034					inst = $.data( cur[ j ], this.widgetFullName );
16035					if ( inst && inst !== this && !inst.options.disabled ) {
16036						queries.push( [ typeof inst.options.items === "function" ?
16037							inst.options.items
16038								.call( inst.element[ 0 ], event, { item: this.currentItem } ) :
16039							$( inst.options.items, inst.element ), inst ] );
16040						this.containers.push( inst );
16041					}
16042				}
16043			}
16044		}
16045
16046		for ( i = queries.length - 1; i >= 0; i-- ) {
16047			targetData = queries[ i ][ 1 ];
16048			_queries = queries[ i ][ 0 ];
16049
16050			for ( j = 0, queriesLength = _queries.length; j < queriesLength; j++ ) {
16051				item = $( _queries[ j ] );
16052
16053				// Data for target checking (mouse manager)
16054				item.data( this.widgetName + "-item", targetData );
16055
16056				items.push( {
16057					item: item,
16058					instance: targetData,
16059					width: 0, height: 0,
16060					left: 0, top: 0
16061				} );
16062			}
16063		}
16064
16065	},
16066
16067	_refreshItemPositions: function( fast ) {
16068		var i, item, t, p;
16069
16070		for ( i = this.items.length - 1; i >= 0; i-- ) {
16071			item = this.items[ i ];
16072
16073			//We ignore calculating positions of all connected containers when we're not over them
16074			if ( this.currentContainer && item.instance !== this.currentContainer &&
16075					item.item[ 0 ] !== this.currentItem[ 0 ] ) {
16076				continue;
16077			}
16078
16079			t = this.options.toleranceElement ?
16080				$( this.options.toleranceElement, item.item ) :
16081				item.item;
16082
16083			if ( !fast ) {
16084				item.width = t.outerWidth();
16085				item.height = t.outerHeight();
16086			}
16087
16088			p = t.offset();
16089			item.left = p.left;
16090			item.top = p.top;
16091		}
16092	},
16093
16094	refreshPositions: function( fast ) {
16095
16096		// Determine whether items are being displayed horizontally
16097		this.floating = this.items.length ?
16098			this.options.axis === "x" || this._isFloating( this.items[ 0 ].item ) :
16099			false;
16100
16101		// This has to be redone because due to the item being moved out/into the offsetParent,
16102		// the offsetParent's position will change
16103		if ( this.offsetParent && this.helper ) {
16104			this.offset.parent = this._getParentOffset();
16105		}
16106
16107		this._refreshItemPositions( fast );
16108
16109		var i, p;
16110
16111		if ( this.options.custom && this.options.custom.refreshContainers ) {
16112			this.options.custom.refreshContainers.call( this );
16113		} else {
16114			for ( i = this.containers.length - 1; i >= 0; i-- ) {
16115				p = this.containers[ i ].element.offset();
16116				this.containers[ i ].containerCache.left = p.left;
16117				this.containers[ i ].containerCache.top = p.top;
16118				this.containers[ i ].containerCache.width =
16119					this.containers[ i ].element.outerWidth();
16120				this.containers[ i ].containerCache.height =
16121					this.containers[ i ].element.outerHeight();
16122			}
16123		}
16124
16125		return this;
16126	},
16127
16128	_createPlaceholder: function( that ) {
16129		that = that || this;
16130		var className, nodeName,
16131			o = that.options;
16132
16133		if ( !o.placeholder || o.placeholder.constructor === String ) {
16134			className = o.placeholder;
16135			nodeName = that.currentItem[ 0 ].nodeName.toLowerCase();
16136			o.placeholder = {
16137				element: function() {
16138
16139					var element = $( "<" + nodeName + ">", that.document[ 0 ] );
16140
16141					that._addClass( element, "ui-sortable-placeholder",
16142							className || that.currentItem[ 0 ].className )
16143						._removeClass( element, "ui-sortable-helper" );
16144
16145					if ( nodeName === "tbody" ) {
16146						that._createTrPlaceholder(
16147							that.currentItem.find( "tr" ).eq( 0 ),
16148							$( "<tr>", that.document[ 0 ] ).appendTo( element )
16149						);
16150					} else if ( nodeName === "tr" ) {
16151						that._createTrPlaceholder( that.currentItem, element );
16152					} else if ( nodeName === "img" ) {
16153						element.attr( "src", that.currentItem.attr( "src" ) );
16154					}
16155
16156					if ( !className ) {
16157						element.css( "visibility", "hidden" );
16158					}
16159
16160					return element;
16161				},
16162				update: function( container, p ) {
16163
16164					// 1. If a className is set as 'placeholder option, we don't force sizes -
16165					// the class is responsible for that
16166					// 2. The option 'forcePlaceholderSize can be enabled to force it even if a
16167					// class name is specified
16168					if ( className && !o.forcePlaceholderSize ) {
16169						return;
16170					}
16171
16172					// If the element doesn't have a actual height or width by itself (without
16173					// styles coming from a stylesheet), it receives the inline height and width
16174					// from the dragged item. Or, if it's a tbody or tr, it's going to have a height
16175					// anyway since we're populating them with <td>s above, but they're unlikely to
16176					// be the correct height on their own if the row heights are dynamic, so we'll
16177					// always assign the height of the dragged item given forcePlaceholderSize
16178					// is true.
16179					if ( !p.height() || ( o.forcePlaceholderSize &&
16180							( nodeName === "tbody" || nodeName === "tr" ) ) ) {
16181						p.height(
16182							that.currentItem.innerHeight() -
16183							parseInt( that.currentItem.css( "paddingTop" ) || 0, 10 ) -
16184							parseInt( that.currentItem.css( "paddingBottom" ) || 0, 10 ) );
16185					}
16186					if ( !p.width() ) {
16187						p.width(
16188							that.currentItem.innerWidth() -
16189							parseInt( that.currentItem.css( "paddingLeft" ) || 0, 10 ) -
16190							parseInt( that.currentItem.css( "paddingRight" ) || 0, 10 ) );
16191					}
16192				}
16193			};
16194		}
16195
16196		//Create the placeholder
16197		that.placeholder = $( o.placeholder.element.call( that.element, that.currentItem ) );
16198
16199		//Append it after the actual current item
16200		that.currentItem.after( that.placeholder );
16201
16202		//Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
16203		o.placeholder.update( that, that.placeholder );
16204
16205	},
16206
16207	_createTrPlaceholder: function( sourceTr, targetTr ) {
16208		var that = this;
16209
16210		sourceTr.children().each( function() {
16211			$( "<td>&#160;</td>", that.document[ 0 ] )
16212				.attr( "colspan", $( this ).attr( "colspan" ) || 1 )
16213				.appendTo( targetTr );
16214		} );
16215	},
16216
16217	_contactContainers: function( event ) {
16218		var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, cur, nearBottom,
16219			floating, axis,
16220			innermostContainer = null,
16221			innermostIndex = null;
16222
16223		// Get innermost container that intersects with item
16224		for ( i = this.containers.length - 1; i >= 0; i-- ) {
16225
16226			// Never consider a container that's located within the item itself
16227			if ( $.contains( this.currentItem[ 0 ], this.containers[ i ].element[ 0 ] ) ) {
16228				continue;
16229			}
16230
16231			if ( this._intersectsWith( this.containers[ i ].containerCache ) ) {
16232
16233				// If we've already found a container and it's more "inner" than this, then continue
16234				if ( innermostContainer &&
16235						$.contains(
16236							this.containers[ i ].element[ 0 ],
16237							innermostContainer.element[ 0 ] ) ) {
16238					continue;
16239				}
16240
16241				innermostContainer = this.containers[ i ];
16242				innermostIndex = i;
16243
16244			} else {
16245
16246				// container doesn't intersect. trigger "out" event if necessary
16247				if ( this.containers[ i ].containerCache.over ) {
16248					this.containers[ i ]._trigger( "out", event, this._uiHash( this ) );
16249					this.containers[ i ].containerCache.over = 0;
16250				}
16251			}
16252
16253		}
16254
16255		// If no intersecting containers found, return
16256		if ( !innermostContainer ) {
16257			return;
16258		}
16259
16260		// Move the item into the container if it's not there already
16261		if ( this.containers.length === 1 ) {
16262			if ( !this.containers[ innermostIndex ].containerCache.over ) {
16263				this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) );
16264				this.containers[ innermostIndex ].containerCache.over = 1;
16265			}
16266		} else {
16267
16268			// When entering a new container, we will find the item with the least distance and
16269			// append our item near it
16270			dist = 10000;
16271			itemWithLeastDistance = null;
16272			floating = innermostContainer.floating || this._isFloating( this.currentItem );
16273			posProperty = floating ? "left" : "top";
16274			sizeProperty = floating ? "width" : "height";
16275			axis = floating ? "pageX" : "pageY";
16276
16277			for ( j = this.items.length - 1; j >= 0; j-- ) {
16278				if ( !$.contains(
16279						this.containers[ innermostIndex ].element[ 0 ], this.items[ j ].item[ 0 ] )
16280				) {
16281					continue;
16282				}
16283				if ( this.items[ j ].item[ 0 ] === this.currentItem[ 0 ] ) {
16284					continue;
16285				}
16286
16287				cur = this.items[ j ].item.offset()[ posProperty ];
16288				nearBottom = false;
16289				if ( event[ axis ] - cur > this.items[ j ][ sizeProperty ] / 2 ) {
16290					nearBottom = true;
16291				}
16292
16293				if ( Math.abs( event[ axis ] - cur ) < dist ) {
16294					dist = Math.abs( event[ axis ] - cur );
16295					itemWithLeastDistance = this.items[ j ];
16296					this.direction = nearBottom ? "up" : "down";
16297				}
16298			}
16299
16300			//Check if dropOnEmpty is enabled
16301			if ( !itemWithLeastDistance && !this.options.dropOnEmpty ) {
16302				return;
16303			}
16304
16305			if ( this.currentContainer === this.containers[ innermostIndex ] ) {
16306				if ( !this.currentContainer.containerCache.over ) {
16307					this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash() );
16308					this.currentContainer.containerCache.over = 1;
16309				}
16310				return;
16311			}
16312
16313			if ( itemWithLeastDistance ) {
16314				this._rearrange( event, itemWithLeastDistance, null, true );
16315			} else {
16316				this._rearrange( event, null, this.containers[ innermostIndex ].element, true );
16317			}
16318			this._trigger( "change", event, this._uiHash() );
16319			this.containers[ innermostIndex ]._trigger( "change", event, this._uiHash( this ) );
16320			this.currentContainer = this.containers[ innermostIndex ];
16321
16322			//Update the placeholder
16323			this.options.placeholder.update( this.currentContainer, this.placeholder );
16324
16325			//Update scrollParent
16326			this.scrollParent = this.placeholder.scrollParent();
16327
16328			//Update overflowOffset
16329			if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
16330					this.scrollParent[ 0 ].tagName !== "HTML" ) {
16331				this.overflowOffset = this.scrollParent.offset();
16332			}
16333
16334			this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) );
16335			this.containers[ innermostIndex ].containerCache.over = 1;
16336		}
16337
16338	},
16339
16340	_createHelper: function( event ) {
16341
16342		var o = this.options,
16343			helper = typeof o.helper === "function" ?
16344				$( o.helper.apply( this.element[ 0 ], [ event, this.currentItem ] ) ) :
16345				( o.helper === "clone" ? this.currentItem.clone() : this.currentItem );
16346
16347		//Add the helper to the DOM if that didn't happen already
16348		if ( !helper.parents( "body" ).length ) {
16349			this.appendTo[ 0 ].appendChild( helper[ 0 ] );
16350		}
16351
16352		if ( helper[ 0 ] === this.currentItem[ 0 ] ) {
16353			this._storedCSS = {
16354				width: this.currentItem[ 0 ].style.width,
16355				height: this.currentItem[ 0 ].style.height,
16356				position: this.currentItem.css( "position" ),
16357				top: this.currentItem.css( "top" ),
16358				left: this.currentItem.css( "left" )
16359			};
16360		}
16361
16362		if ( !helper[ 0 ].style.width || o.forceHelperSize ) {
16363			helper.width( this.currentItem.width() );
16364		}
16365		if ( !helper[ 0 ].style.height || o.forceHelperSize ) {
16366			helper.height( this.currentItem.height() );
16367		}
16368
16369		return helper;
16370
16371	},
16372
16373	_adjustOffsetFromHelper: function( obj ) {
16374		if ( typeof obj === "string" ) {
16375			obj = obj.split( " " );
16376		}
16377		if ( Array.isArray( obj ) ) {
16378			obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 };
16379		}
16380		if ( "left" in obj ) {
16381			this.offset.click.left = obj.left + this.margins.left;
16382		}
16383		if ( "right" in obj ) {
16384			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
16385		}
16386		if ( "top" in obj ) {
16387			this.offset.click.top = obj.top + this.margins.top;
16388		}
16389		if ( "bottom" in obj ) {
16390			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
16391		}
16392	},
16393
16394	_getParentOffset: function() {
16395
16396		//Get the offsetParent and cache its position
16397		this.offsetParent = this.helper.offsetParent();
16398		var po = this.offsetParent.offset();
16399
16400		// This is a special case where we need to modify a offset calculated on start, since the
16401		// following happened:
16402		// 1. The position of the helper is absolute, so it's position is calculated based on the
16403		// next positioned parent
16404		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't
16405		// the document, which means that the scroll is included in the initial calculation of the
16406		// offset of the parent, and never recalculated upon drag
16407		if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== this.document[ 0 ] &&
16408				$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) {
16409			po.left += this.scrollParent.scrollLeft();
16410			po.top += this.scrollParent.scrollTop();
16411		}
16412
16413		// This needs to be actually done for all browsers, since pageX/pageY includes
16414		// this information.
16415		if ( this.offsetParent[ 0 ] === this.document[ 0 ].body ) {
16416			po = { top: 0, left: 0 };
16417		}
16418
16419		return {
16420			top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ),
16421			left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 )
16422		};
16423
16424	},
16425
16426	_getRelativeOffset: function() {
16427
16428		if ( this.cssPosition === "relative" ) {
16429			var p = this.currentItem.position();
16430			return {
16431				top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) +
16432					this.scrollParent.scrollTop(),
16433				left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) +
16434					this.scrollParent.scrollLeft()
16435			};
16436		} else {
16437			return { top: 0, left: 0 };
16438		}
16439
16440	},
16441
16442	_cacheMargins: function() {
16443		this.margins = {
16444			left: ( parseInt( this.currentItem.css( "marginLeft" ), 10 ) || 0 ),
16445			top: ( parseInt( this.currentItem.css( "marginTop" ), 10 ) || 0 )
16446		};
16447	},
16448
16449	_cacheHelperProportions: function() {
16450		this.helperProportions = {
16451			width: this.helper.outerWidth(),
16452			height: this.helper.outerHeight()
16453		};
16454	},
16455
16456	_setContainment: function() {
16457
16458		var ce, co, over,
16459			o = this.options;
16460		if ( o.containment === "parent" ) {
16461			o.containment = this.helper[ 0 ].parentNode;
16462		}
16463		if ( o.containment === "document" || o.containment === "window" ) {
16464			this.containment = [
16465				0 - this.offset.relative.left - this.offset.parent.left,
16466				0 - this.offset.relative.top - this.offset.parent.top,
16467				o.containment === "document" ?
16468					this.document.width() :
16469					this.window.width() - this.helperProportions.width - this.margins.left,
16470				( o.containment === "document" ?
16471					( this.document.height() || document.body.parentNode.scrollHeight ) :
16472					this.window.height() || this.document[ 0 ].body.parentNode.scrollHeight
16473				) - this.helperProportions.height - this.margins.top
16474			];
16475		}
16476
16477		if ( !( /^(document|window|parent)$/ ).test( o.containment ) ) {
16478			ce = $( o.containment )[ 0 ];
16479			co = $( o.containment ).offset();
16480			over = ( $( ce ).css( "overflow" ) !== "hidden" );
16481
16482			this.containment = [
16483				co.left + ( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) +
16484					( parseInt( $( ce ).css( "paddingLeft" ), 10 ) || 0 ) - this.margins.left,
16485				co.top + ( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) +
16486					( parseInt( $( ce ).css( "paddingTop" ), 10 ) || 0 ) - this.margins.top,
16487				co.left + ( over ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -
16488					( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) -
16489					( parseInt( $( ce ).css( "paddingRight" ), 10 ) || 0 ) -
16490					this.helperProportions.width - this.margins.left,
16491				co.top + ( over ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -
16492					( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) -
16493					( parseInt( $( ce ).css( "paddingBottom" ), 10 ) || 0 ) -
16494					this.helperProportions.height - this.margins.top
16495			];
16496		}
16497
16498	},
16499
16500	_convertPositionTo: function( d, pos ) {
16501
16502		if ( !pos ) {
16503			pos = this.position;
16504		}
16505		var mod = d === "absolute" ? 1 : -1,
16506			scroll = this.cssPosition === "absolute" &&
16507				!( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
16508				$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ?
16509					this.offsetParent :
16510					this.scrollParent,
16511			scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName );
16512
16513		return {
16514			top: (
16515
16516				// The absolute mouse position
16517				pos.top	+
16518
16519				// Only for relative positioned nodes: Relative offset from element to offset parent
16520				this.offset.relative.top * mod +
16521
16522				// The offsetParent's offset without borders (offset + border)
16523				this.offset.parent.top * mod -
16524				( ( this.cssPosition === "fixed" ?
16525					-this.scrollParent.scrollTop() :
16526					( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod )
16527			),
16528			left: (
16529
16530				// The absolute mouse position
16531				pos.left +
16532
16533				// Only for relative positioned nodes: Relative offset from element to offset parent
16534				this.offset.relative.left * mod +
16535
16536				// The offsetParent's offset without borders (offset + border)
16537				this.offset.parent.left * mod	-
16538				( ( this.cssPosition === "fixed" ?
16539					-this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 :
16540					scroll.scrollLeft() ) * mod )
16541			)
16542		};
16543
16544	},
16545
16546	_generatePosition: function( event ) {
16547
16548		var top, left,
16549			o = this.options,
16550			pageX = event.pageX,
16551			pageY = event.pageY,
16552			scroll = this.cssPosition === "absolute" &&
16553				!( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
16554				$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ?
16555					this.offsetParent :
16556					this.scrollParent,
16557				scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName );
16558
16559		// This is another very weird special case that only happens for relative elements:
16560		// 1. If the css position is relative
16561		// 2. and the scroll parent is the document or similar to the offset parent
16562		// we have to refresh the relative offset during the scroll so there are no jumps
16563		if ( this.cssPosition === "relative" && !( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
16564				this.scrollParent[ 0 ] !== this.offsetParent[ 0 ] ) ) {
16565			this.offset.relative = this._getRelativeOffset();
16566		}
16567
16568		/*
16569		 * - Position constraining -
16570		 * Constrain the position to a mix of grid, containment.
16571		 */
16572
16573		if ( this.originalPosition ) { //If we are not dragging yet, we won't check for options
16574
16575			if ( this.containment ) {
16576				if ( event.pageX - this.offset.click.left < this.containment[ 0 ] ) {
16577					pageX = this.containment[ 0 ] + this.offset.click.left;
16578				}
16579				if ( event.pageY - this.offset.click.top < this.containment[ 1 ] ) {
16580					pageY = this.containment[ 1 ] + this.offset.click.top;
16581				}
16582				if ( event.pageX - this.offset.click.left > this.containment[ 2 ] ) {
16583					pageX = this.containment[ 2 ] + this.offset.click.left;
16584				}
16585				if ( event.pageY - this.offset.click.top > this.containment[ 3 ] ) {
16586					pageY = this.containment[ 3 ] + this.offset.click.top;
16587				}
16588			}
16589
16590			if ( o.grid ) {
16591				top = this.originalPageY + Math.round( ( pageY - this.originalPageY ) /
16592					o.grid[ 1 ] ) * o.grid[ 1 ];
16593				pageY = this.containment ?
16594					( ( top - this.offset.click.top >= this.containment[ 1 ] &&
16595						top - this.offset.click.top <= this.containment[ 3 ] ) ?
16596							top :
16597							( ( top - this.offset.click.top >= this.containment[ 1 ] ) ?
16598								top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) :
16599								top;
16600
16601				left = this.originalPageX + Math.round( ( pageX - this.originalPageX ) /
16602					o.grid[ 0 ] ) * o.grid[ 0 ];
16603				pageX = this.containment ?
16604					( ( left - this.offset.click.left >= this.containment[ 0 ] &&
16605						left - this.offset.click.left <= this.containment[ 2 ] ) ?
16606							left :
16607							( ( left - this.offset.click.left >= this.containment[ 0 ] ) ?
16608								left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) :
16609								left;
16610			}
16611
16612		}
16613
16614		return {
16615			top: (
16616
16617				// The absolute mouse position
16618				pageY -
16619
16620				// Click offset (relative to the element)
16621				this.offset.click.top -
16622
16623				// Only for relative positioned nodes: Relative offset from element to offset parent
16624				this.offset.relative.top -
16625
16626				// The offsetParent's offset without borders (offset + border)
16627				this.offset.parent.top +
16628				( ( this.cssPosition === "fixed" ?
16629					-this.scrollParent.scrollTop() :
16630					( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) )
16631			),
16632			left: (
16633
16634				// The absolute mouse position
16635				pageX -
16636
16637				// Click offset (relative to the element)
16638				this.offset.click.left -
16639
16640				// Only for relative positioned nodes: Relative offset from element to offset parent
16641				this.offset.relative.left -
16642
16643				// The offsetParent's offset without borders (offset + border)
16644				this.offset.parent.left +
16645				( ( this.cssPosition === "fixed" ?
16646					-this.scrollParent.scrollLeft() :
16647					scrollIsRootNode ? 0 : scroll.scrollLeft() ) )
16648			)
16649		};
16650
16651	},
16652
16653	_rearrange: function( event, i, a, hardRefresh ) {
16654
16655		if ( a ) {
16656			a[ 0 ].appendChild( this.placeholder[ 0 ] );
16657		} else {
16658			i.item[ 0 ].parentNode.insertBefore( this.placeholder[ 0 ],
16659				( this.direction === "down" ? i.item[ 0 ] : i.item[ 0 ].nextSibling ) );
16660		}
16661
16662		//Various things done here to improve the performance:
16663		// 1. we create a setTimeout, that calls refreshPositions
16664		// 2. on the instance, we have a counter variable, that get's higher after every append
16665		// 3. on the local scope, we copy the counter variable, and check in the timeout,
16666		// if it's still the same
16667		// 4. this lets only the last addition to the timeout stack through
16668		this.counter = this.counter ? ++this.counter : 1;
16669		var counter = this.counter;
16670
16671		this._delay( function() {
16672			if ( counter === this.counter ) {
16673
16674				//Precompute after each DOM insertion, NOT on mousemove
16675				this.refreshPositions( !hardRefresh );
16676			}
16677		} );
16678
16679	},
16680
16681	_clear: function( event, noPropagation ) {
16682
16683		this.reverting = false;
16684
16685		// We delay all events that have to be triggered to after the point where the placeholder
16686		// has been removed and everything else normalized again
16687		var i,
16688			delayedTriggers = [];
16689
16690		// We first have to update the dom position of the actual currentItem
16691		// Note: don't do it if the current item is already removed (by a user), or it gets
16692		// reappended (see #4088)
16693		if ( !this._noFinalSort && this.currentItem.parent().length ) {
16694			this.placeholder.before( this.currentItem );
16695		}
16696		this._noFinalSort = null;
16697
16698		if ( this.helper[ 0 ] === this.currentItem[ 0 ] ) {
16699			for ( i in this._storedCSS ) {
16700				if ( this._storedCSS[ i ] === "auto" || this._storedCSS[ i ] === "static" ) {
16701					this._storedCSS[ i ] = "";
16702				}
16703			}
16704			this.currentItem.css( this._storedCSS );
16705			this._removeClass( this.currentItem, "ui-sortable-helper" );
16706		} else {
16707			this.currentItem.show();
16708		}
16709
16710		if ( this.fromOutside && !noPropagation ) {
16711			delayedTriggers.push( function( event ) {
16712				this._trigger( "receive", event, this._uiHash( this.fromOutside ) );
16713			} );
16714		}
16715		if ( ( this.fromOutside ||
16716				this.domPosition.prev !==
16717				this.currentItem.prev().not( ".ui-sortable-helper" )[ 0 ] ||
16718				this.domPosition.parent !== this.currentItem.parent()[ 0 ] ) && !noPropagation ) {
16719
16720			// Trigger update callback if the DOM position has changed
16721			delayedTriggers.push( function( event ) {
16722				this._trigger( "update", event, this._uiHash() );
16723			} );
16724		}
16725
16726		// Check if the items Container has Changed and trigger appropriate
16727		// events.
16728		if ( this !== this.currentContainer ) {
16729			if ( !noPropagation ) {
16730				delayedTriggers.push( function( event ) {
16731					this._trigger( "remove", event, this._uiHash() );
16732				} );
16733				delayedTriggers.push( ( function( c ) {
16734					return function( event ) {
16735						c._trigger( "receive", event, this._uiHash( this ) );
16736					};
16737				} ).call( this, this.currentContainer ) );
16738				delayedTriggers.push( ( function( c ) {
16739					return function( event ) {
16740						c._trigger( "update", event, this._uiHash( this ) );
16741					};
16742				} ).call( this, this.currentContainer ) );
16743			}
16744		}
16745
16746		//Post events to containers
16747		function delayEvent( type, instance, container ) {
16748			return function( event ) {
16749				container._trigger( type, event, instance._uiHash( instance ) );
16750			};
16751		}
16752		for ( i = this.containers.length - 1; i >= 0; i-- ) {
16753			if ( !noPropagation ) {
16754				delayedTriggers.push( delayEvent( "deactivate", this, this.containers[ i ] ) );
16755			}
16756			if ( this.containers[ i ].containerCache.over ) {
16757				delayedTriggers.push( delayEvent( "out", this, this.containers[ i ] ) );
16758				this.containers[ i ].containerCache.over = 0;
16759			}
16760		}
16761
16762		//Do what was originally in plugins
16763		if ( this._storedStylesheet ) {
16764			this._storedStylesheet.remove();
16765			this._storedStylesheet = null;
16766		}
16767		if ( this._storedOpacity ) {
16768			this.helper.css( "opacity", this._storedOpacity );
16769		}
16770		if ( this._storedZIndex ) {
16771			this.helper.css( "zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex );
16772		}
16773
16774		this.dragging = false;
16775
16776		if ( !noPropagation ) {
16777			this._trigger( "beforeStop", event, this._uiHash() );
16778		}
16779
16780		//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately,
16781		// it unbinds ALL events from the original node!
16782		this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] );
16783
16784		if ( !this.cancelHelperRemoval ) {
16785			if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {
16786				this.helper.remove();
16787			}
16788			this.helper = null;
16789		}
16790
16791		if ( !noPropagation ) {
16792			for ( i = 0; i < delayedTriggers.length; i++ ) {
16793
16794				// Trigger all delayed events
16795				delayedTriggers[ i ].call( this, event );
16796			}
16797			this._trigger( "stop", event, this._uiHash() );
16798		}
16799
16800		this.fromOutside = false;
16801		return !this.cancelHelperRemoval;
16802
16803	},
16804
16805	_trigger: function() {
16806		if ( $.Widget.prototype._trigger.apply( this, arguments ) === false ) {
16807			this.cancel();
16808		}
16809	},
16810
16811	_uiHash: function( _inst ) {
16812		var inst = _inst || this;
16813		return {
16814			helper: inst.helper,
16815			placeholder: inst.placeholder || $( [] ),
16816			position: inst.position,
16817			originalPosition: inst.originalPosition,
16818			offset: inst.positionAbs,
16819			item: inst.currentItem,
16820			sender: _inst ? _inst.element : null
16821		};
16822	}
16823
16824} );
16825
16826
16827/*!
16828 * jQuery UI Spinner 1.14.0
16829 * https://jqueryui.com
16830 *
16831 * Copyright OpenJS Foundation and other contributors
16832 * Released under the MIT license.
16833 * https://jquery.org/license
16834 */
16835
16836//>>label: Spinner
16837//>>group: Widgets
16838//>>description: Displays buttons to easily input numbers via the keyboard or mouse.
16839//>>docs: https://api.jqueryui.com/spinner/
16840//>>demos: https://jqueryui.com/spinner/
16841//>>css.structure: ../../themes/base/core.css
16842//>>css.structure: ../../themes/base/spinner.css
16843//>>css.theme: ../../themes/base/theme.css
16844
16845
16846function spinnerModifier( fn ) {
16847	return function() {
16848		var previous = this.element.val();
16849		fn.apply( this, arguments );
16850		this._refresh();
16851		if ( previous !== this.element.val() ) {
16852			this._trigger( "change" );
16853		}
16854	};
16855}
16856
16857$.widget( "ui.spinner", {
16858	version: "1.14.0",
16859	defaultElement: "<input>",
16860	widgetEventPrefix: "spin",
16861	options: {
16862		classes: {
16863			"ui-spinner": "ui-corner-all",
16864			"ui-spinner-down": "ui-corner-br",
16865			"ui-spinner-up": "ui-corner-tr"
16866		},
16867		culture: null,
16868		icons: {
16869			down: "ui-icon-triangle-1-s",
16870			up: "ui-icon-triangle-1-n"
16871		},
16872		incremental: true,
16873		max: null,
16874		min: null,
16875		numberFormat: null,
16876		page: 10,
16877		step: 1,
16878
16879		change: null,
16880		spin: null,
16881		start: null,
16882		stop: null
16883	},
16884
16885	_create: function() {
16886
16887		// handle string values that need to be parsed
16888		this._setOption( "max", this.options.max );
16889		this._setOption( "min", this.options.min );
16890		this._setOption( "step", this.options.step );
16891
16892		// Only format if there is a value, prevents the field from being marked
16893		// as invalid in Firefox, see #9573.
16894		if ( this.value() !== "" ) {
16895
16896			// Format the value, but don't constrain.
16897			this._value( this.element.val(), true );
16898		}
16899
16900		this._draw();
16901		this._on( this._events );
16902		this._refresh();
16903
16904		// Turning off autocomplete prevents the browser from remembering the
16905		// value when navigating through history, so we re-enable autocomplete
16906		// if the page is unloaded before the widget is destroyed. #7790
16907		this._on( this.window, {
16908			beforeunload: function() {
16909				this.element.removeAttr( "autocomplete" );
16910			}
16911		} );
16912	},
16913
16914	_getCreateOptions: function() {
16915		var options = this._super();
16916		var element = this.element;
16917
16918		$.each( [ "min", "max", "step" ], function( i, option ) {
16919			var value = element.attr( option );
16920			if ( value != null && value.length ) {
16921				options[ option ] = value;
16922			}
16923		} );
16924
16925		return options;
16926	},
16927
16928	_events: {
16929		keydown: function( event ) {
16930			if ( this._start( event ) && this._keydown( event ) ) {
16931				event.preventDefault();
16932			}
16933		},
16934		keyup: "_stop",
16935		focus: function() {
16936			this.previous = this.element.val();
16937		},
16938		blur: function( event ) {
16939			this._stop();
16940			this._refresh();
16941			if ( this.previous !== this.element.val() ) {
16942				this._trigger( "change", event );
16943			}
16944		},
16945		mousewheel: function( event, delta ) {
16946			var activeElement = this.document[ 0 ].activeElement;
16947			var isActive = this.element[ 0 ] === activeElement;
16948
16949			if ( !isActive || !delta ) {
16950				return;
16951			}
16952
16953			if ( !this.spinning && !this._start( event ) ) {
16954				return false;
16955			}
16956
16957			this._spin( ( delta > 0 ? 1 : -1 ) * this.options.step, event );
16958			clearTimeout( this.mousewheelTimer );
16959			this.mousewheelTimer = this._delay( function() {
16960				if ( this.spinning ) {
16961					this._stop( event );
16962				}
16963			}, 100 );
16964			event.preventDefault();
16965		},
16966		"mousedown .ui-spinner-button": function( event ) {
16967			var previous;
16968
16969			// We never want the buttons to have focus; whenever the user is
16970			// interacting with the spinner, the focus should be on the input.
16971			// If the input is focused then this.previous is properly set from
16972			// when the input first received focus. If the input is not focused
16973			// then we need to set this.previous based on the value before spinning.
16974			previous = this.element[ 0 ] === this.document[ 0 ].activeElement ?
16975				this.previous : this.element.val();
16976			function checkFocus() {
16977				var isActive = this.element[ 0 ] === this.document[ 0 ].activeElement;
16978				if ( !isActive ) {
16979					this.element.trigger( "focus" );
16980					this.previous = previous;
16981				}
16982			}
16983
16984			// Ensure focus is on (or stays on) the text field
16985			event.preventDefault();
16986			checkFocus.call( this );
16987
16988			if ( this._start( event ) === false ) {
16989				return;
16990			}
16991
16992			this._repeat( null, $( event.currentTarget )
16993				.hasClass( "ui-spinner-up" ) ? 1 : -1, event );
16994		},
16995		"mouseup .ui-spinner-button": "_stop",
16996		"mouseenter .ui-spinner-button": function( event ) {
16997
16998			// button will add ui-state-active if mouse was down while mouseleave and kept down
16999			if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) {
17000				return;
17001			}
17002
17003			if ( this._start( event ) === false ) {
17004				return false;
17005			}
17006			this._repeat( null, $( event.currentTarget )
17007				.hasClass( "ui-spinner-up" ) ? 1 : -1, event );
17008		},
17009
17010		// TODO: do we really want to consider this a stop?
17011		// shouldn't we just stop the repeater and wait until mouseup before
17012		// we trigger the stop event?
17013		"mouseleave .ui-spinner-button": "_stop"
17014	},
17015
17016	// Support mobile enhanced option and make backcompat more sane
17017	_enhance: function() {
17018		this.uiSpinner = this.element
17019			.attr( "autocomplete", "off" )
17020			.wrap( "<span>" )
17021			.parent()
17022
17023				// Add buttons
17024				.append(
17025					"<a></a><a></a>"
17026				);
17027	},
17028
17029	_draw: function() {
17030		this._enhance();
17031
17032		this._addClass( this.uiSpinner, "ui-spinner", "ui-widget ui-widget-content" );
17033		this._addClass( "ui-spinner-input" );
17034
17035		this.element.attr( "role", "spinbutton" );
17036
17037		// Button bindings
17038		this.buttons = this.uiSpinner.children( "a" )
17039			.attr( "tabIndex", -1 )
17040			.attr( "aria-hidden", true )
17041			.button( {
17042				classes: {
17043					"ui-button": ""
17044				}
17045			} );
17046
17047		// TODO: Right now button does not support classes this is already updated in button PR
17048		this._removeClass( this.buttons, "ui-corner-all" );
17049
17050		this._addClass( this.buttons.first(), "ui-spinner-button ui-spinner-up" );
17051		this._addClass( this.buttons.last(), "ui-spinner-button ui-spinner-down" );
17052		this.buttons.first().button( {
17053			"icon": this.options.icons.up,
17054			"showLabel": false
17055		} );
17056		this.buttons.last().button( {
17057			"icon": this.options.icons.down,
17058			"showLabel": false
17059		} );
17060
17061		// IE 6 doesn't understand height: 50% for the buttons
17062		// unless the wrapper has an explicit height
17063		if ( this.buttons.height() > Math.ceil( this.uiSpinner.height() * 0.5 ) &&
17064				this.uiSpinner.height() > 0 ) {
17065			this.uiSpinner.height( this.uiSpinner.height() );
17066		}
17067	},
17068
17069	_keydown: function( event ) {
17070		var options = this.options,
17071			keyCode = $.ui.keyCode;
17072
17073		switch ( event.keyCode ) {
17074		case keyCode.UP:
17075			this._repeat( null, 1, event );
17076			return true;
17077		case keyCode.DOWN:
17078			this._repeat( null, -1, event );
17079			return true;
17080		case keyCode.PAGE_UP:
17081			this._repeat( null, options.page, event );
17082			return true;
17083		case keyCode.PAGE_DOWN:
17084			this._repeat( null, -options.page, event );
17085			return true;
17086		}
17087
17088		return false;
17089	},
17090
17091	_start: function( event ) {
17092		if ( !this.spinning && this._trigger( "start", event ) === false ) {
17093			return false;
17094		}
17095
17096		if ( !this.counter ) {
17097			this.counter = 1;
17098		}
17099		this.spinning = true;
17100		return true;
17101	},
17102
17103	_repeat: function( i, steps, event ) {
17104		i = i || 500;
17105
17106		clearTimeout( this.timer );
17107		this.timer = this._delay( function() {
17108			this._repeat( 40, steps, event );
17109		}, i );
17110
17111		this._spin( steps * this.options.step, event );
17112	},
17113
17114	_spin: function( step, event ) {
17115		var value = this.value() || 0;
17116
17117		if ( !this.counter ) {
17118			this.counter = 1;
17119		}
17120
17121		value = this._adjustValue( value + step * this._increment( this.counter ) );
17122
17123		if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false ) {
17124			this._value( value );
17125			this.counter++;
17126		}
17127	},
17128
17129	_increment: function( i ) {
17130		var incremental = this.options.incremental;
17131
17132		if ( incremental ) {
17133			return typeof incremental === "function" ?
17134				incremental( i ) :
17135				Math.floor( i * i * i / 50000 - i * i / 500 + 17 * i / 200 + 1 );
17136		}
17137
17138		return 1;
17139	},
17140
17141	_precision: function() {
17142		var precision = this._precisionOf( this.options.step );
17143		if ( this.options.min !== null ) {
17144			precision = Math.max( precision, this._precisionOf( this.options.min ) );
17145		}
17146		return precision;
17147	},
17148
17149	_precisionOf: function( num ) {
17150		var str = num.toString(),
17151			decimal = str.indexOf( "." );
17152		return decimal === -1 ? 0 : str.length - decimal - 1;
17153	},
17154
17155	_adjustValue: function( value ) {
17156		var base, aboveMin,
17157			options = this.options;
17158
17159		// Make sure we're at a valid step
17160		// - find out where we are relative to the base (min or 0)
17161		base = options.min !== null ? options.min : 0;
17162		aboveMin = value - base;
17163
17164		// - round to the nearest step
17165		aboveMin = Math.round( aboveMin / options.step ) * options.step;
17166
17167		// - rounding is based on 0, so adjust back to our base
17168		value = base + aboveMin;
17169
17170		// Fix precision from bad JS floating point math
17171		value = parseFloat( value.toFixed( this._precision() ) );
17172
17173		// Clamp the value
17174		if ( options.max !== null && value > options.max ) {
17175			return options.max;
17176		}
17177		if ( options.min !== null && value < options.min ) {
17178			return options.min;
17179		}
17180
17181		return value;
17182	},
17183
17184	_stop: function( event ) {
17185		if ( !this.spinning ) {
17186			return;
17187		}
17188
17189		clearTimeout( this.timer );
17190		clearTimeout( this.mousewheelTimer );
17191		this.counter = 0;
17192		this.spinning = false;
17193		this._trigger( "stop", event );
17194	},
17195
17196	_setOption: function( key, value ) {
17197		var prevValue, first, last;
17198
17199		if ( key === "culture" || key === "numberFormat" ) {
17200			prevValue = this._parse( this.element.val() );
17201			this.options[ key ] = value;
17202			this.element.val( this._format( prevValue ) );
17203			return;
17204		}
17205
vendor: 12,923 bytes, lines 17206-17701
17206		if ( key === "max" || key === "min" || key === "step" ) {
17207			if ( typeof value === "string" ) {
17208				value = this._parse( value );
17209			}
17210		}
17211		if ( key === "icons" ) {
17212			first = this.buttons.first().find( ".ui-icon" );
17213			this._removeClass( first, null, this.options.icons.up );
17214			this._addClass( first, null, value.up );
17215			last = this.buttons.last().find( ".ui-icon" );
17216			this._removeClass( last, null, this.options.icons.down );
17217			this._addClass( last, null, value.down );
17218		}
17219
17220		this._super( key, value );
17221	},
17222
17223	_setOptionDisabled: function( value ) {
17224		this._super( value );
17225
17226		this._toggleClass( this.uiSpinner, null, "ui-state-disabled", !!value );
17227		this.element.prop( "disabled", !!value );
17228		this.buttons.button( value ? "disable" : "enable" );
17229	},
17230
17231	_setOptions: spinnerModifier( function( options ) {
17232		this._super( options );
17233	} ),
17234
17235	_parse: function( val ) {
17236		if ( typeof val === "string" && val !== "" ) {
17237			val = window.Globalize && this.options.numberFormat ?
17238				Globalize.parseFloat( val, 10, this.options.culture ) : +val;
17239		}
17240		return val === "" || isNaN( val ) ? null : val;
17241	},
17242
17243	_format: function( value ) {
17244		if ( value === "" ) {
17245			return "";
17246		}
17247		return window.Globalize && this.options.numberFormat ?
17248			Globalize.format( value, this.options.numberFormat, this.options.culture ) :
17249			value;
17250	},
17251
17252	_refresh: function() {
17253		this.element.attr( {
17254			"aria-valuemin": this.options.min,
17255			"aria-valuemax": this.options.max,
17256
17257			// TODO: what should we do with values that can't be parsed?
17258			"aria-valuenow": this._parse( this.element.val() )
17259		} );
17260	},
17261
17262	isValid: function() {
17263		var value = this.value();
17264
17265		// Null is invalid
17266		if ( value === null ) {
17267			return false;
17268		}
17269
17270		// If value gets adjusted, it's invalid
17271		return value === this._adjustValue( value );
17272	},
17273
17274	// Update the value without triggering change
17275	_value: function( value, allowAny ) {
17276		var parsed;
17277		if ( value !== "" ) {
17278			parsed = this._parse( value );
17279			if ( parsed !== null ) {
17280				if ( !allowAny ) {
17281					parsed = this._adjustValue( parsed );
17282				}
17283				value = this._format( parsed );
17284			}
17285		}
17286		this.element.val( value );
17287		this._refresh();
17288	},
17289
17290	_destroy: function() {
17291		this.element
17292			.prop( "disabled", false )
17293			.removeAttr( "autocomplete role aria-valuemin aria-valuemax aria-valuenow" );
17294
17295		this.uiSpinner.replaceWith( this.element );
17296	},
17297
17298	stepUp: spinnerModifier( function( steps ) {
17299		this._stepUp( steps );
17300	} ),
17301	_stepUp: function( steps ) {
17302		if ( this._start() ) {
17303			this._spin( ( steps || 1 ) * this.options.step );
17304			this._stop();
17305		}
17306	},
17307
17308	stepDown: spinnerModifier( function( steps ) {
17309		this._stepDown( steps );
17310	} ),
17311	_stepDown: function( steps ) {
17312		if ( this._start() ) {
17313			this._spin( ( steps || 1 ) * -this.options.step );
17314			this._stop();
17315		}
17316	},
17317
17318	pageUp: spinnerModifier( function( pages ) {
17319		this._stepUp( ( pages || 1 ) * this.options.page );
17320	} ),
17321
17322	pageDown: spinnerModifier( function( pages ) {
17323		this._stepDown( ( pages || 1 ) * this.options.page );
17324	} ),
17325
17326	value: function( newVal ) {
17327		if ( !arguments.length ) {
17328			return this._parse( this.element.val() );
17329		}
17330		spinnerModifier( this._value ).call( this, newVal );
17331	},
17332
17333	widget: function() {
17334		return this.uiSpinner;
17335	}
17336} );
17337
17338// DEPRECATED
17339// TODO: switch return back to widget declaration at top of file when this is removed
17340if ( $.uiBackCompat === true ) {
17341
17342	// Backcompat for spinner html extension points
17343	$.widget( "ui.spinner", $.ui.spinner, {
17344		_enhance: function() {
17345			this.uiSpinner = this.element
17346				.attr( "autocomplete", "off" )
17347				.wrap( this._uiSpinnerHtml() )
17348				.parent()
17349
17350					// Add buttons
17351					.append( this._buttonHtml() );
17352		},
17353		_uiSpinnerHtml: function() {
17354			return "<span>";
17355		},
17356
17357		_buttonHtml: function() {
17358			return "<a></a><a></a>";
17359		}
17360	} );
17361}
17362
17363var widgetsSpinner = $.ui.spinner;
17364
17365
17366/*!
17367 * jQuery UI Tabs 1.14.0
17368 * https://jqueryui.com
17369 *
17370 * Copyright OpenJS Foundation and other contributors
17371 * Released under the MIT license.
17372 * https://jquery.org/license
17373 */
17374
17375//>>label: Tabs
17376//>>group: Widgets
17377//>>description: Transforms a set of container elements into a tab structure.
17378//>>docs: https://api.jqueryui.com/tabs/
17379//>>demos: https://jqueryui.com/tabs/
17380//>>css.structure: ../../themes/base/core.css
17381//>>css.structure: ../../themes/base/tabs.css
17382//>>css.theme: ../../themes/base/theme.css
17383
17384
17385$.widget( "ui.tabs", {
17386	version: "1.14.0",
17387	delay: 300,
17388	options: {
17389		active: null,
17390		classes: {
17391			"ui-tabs": "ui-corner-all",
17392			"ui-tabs-nav": "ui-corner-all",
17393			"ui-tabs-panel": "ui-corner-bottom",
17394			"ui-tabs-tab": "ui-corner-top"
17395		},
17396		collapsible: false,
17397		event: "click",
17398		heightStyle: "content",
17399		hide: null,
17400		show: null,
17401
17402		// Callbacks
17403		activate: null,
17404		beforeActivate: null,
17405		beforeLoad: null,
17406		load: null
17407	},
17408
17409	_isLocal: ( function() {
17410		var rhash = /#.*$/;
17411
17412		return function( anchor ) {
17413			var anchorUrl, locationUrl;
17414
17415			anchorUrl = anchor.href.replace( rhash, "" );
17416			locationUrl = location.href.replace( rhash, "" );
17417
17418			// Decoding may throw an error if the URL isn't UTF-8 (#9518)
17419			try {
17420				anchorUrl = decodeURIComponent( anchorUrl );
17421			} catch ( error ) {}
17422			try {
17423				locationUrl = decodeURIComponent( locationUrl );
17424			} catch ( error ) {}
17425
17426			return anchor.hash.length > 1 && anchorUrl === locationUrl;
17427		};
17428	} )(),
17429
17430	_create: function() {
17431		var that = this,
17432			options = this.options;
17433
17434		this.running = false;
17435
17436		this._addClass( "ui-tabs", "ui-widget ui-widget-content" );
17437		this._toggleClass( "ui-tabs-collapsible", null, options.collapsible );
17438
17439		this._processTabs();
17440		options.active = this._initialActive();
17441
17442		// Take disabling tabs via class attribute from HTML
17443		// into account and update option properly.
17444		if ( Array.isArray( options.disabled ) ) {
17445			options.disabled = $.uniqueSort( options.disabled.concat(
17446				$.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) {
17447					return that.tabs.index( li );
17448				} )
17449			) ).sort();
17450		}
17451
17452		// Check for length avoids error when initializing empty list
17453		if ( this.options.active !== false && this.anchors.length ) {
17454			this.active = this._findActive( options.active );
17455		} else {
17456			this.active = $();
17457		}
17458
17459		this._refresh();
17460
17461		if ( this.active.length ) {
17462			this.load( options.active );
17463		}
17464	},
17465
17466	_initialActive: function() {
17467		var active = this.options.active,
17468			collapsible = this.options.collapsible,
17469			locationHash = location.hash.substring( 1 );
17470
17471		if ( active === null ) {
17472
17473			// check the fragment identifier in the URL
17474			if ( locationHash ) {
17475				this.tabs.each( function( i, tab ) {
17476					if ( $( tab ).attr( "aria-controls" ) === locationHash ) {
17477						active = i;
17478						return false;
17479					}
17480				} );
17481			}
17482
17483			// Check for a tab marked active via a class
17484			if ( active === null ) {
17485				active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) );
17486			}
17487
17488			// No active tab, set to false
17489			if ( active === null || active === -1 ) {
17490				active = this.tabs.length ? 0 : false;
17491			}
17492		}
17493
17494		// Handle numbers: negative, out of range
17495		if ( active !== false ) {
17496			active = this.tabs.index( this.tabs.eq( active ) );
17497			if ( active === -1 ) {
17498				active = collapsible ? false : 0;
17499			}
17500		}
17501
17502		// Don't allow collapsible: false and active: false
17503		if ( !collapsible && active === false && this.anchors.length ) {
17504			active = 0;
17505		}
17506
17507		return active;
17508	},
17509
17510	_getCreateEventData: function() {
17511		return {
17512			tab: this.active,
17513			panel: !this.active.length ? $() : this._getPanelForTab( this.active )
17514		};
17515	},
17516
17517	_tabKeydown: function( event ) {
17518		var focusedTab = $( this.document[ 0 ].activeElement ).closest( "li" ),
17519			selectedIndex = this.tabs.index( focusedTab ),
17520			goingForward = true;
17521
17522		if ( this._handlePageNav( event ) ) {
17523			return;
17524		}
17525
17526		switch ( event.keyCode ) {
17527		case $.ui.keyCode.RIGHT:
17528		case $.ui.keyCode.DOWN:
17529			selectedIndex++;
17530			break;
17531		case $.ui.keyCode.UP:
17532		case $.ui.keyCode.LEFT:
17533			goingForward = false;
17534			selectedIndex--;
17535			break;
17536		case $.ui.keyCode.END:
17537			selectedIndex = this.anchors.length - 1;
17538			break;
17539		case $.ui.keyCode.HOME:
17540			selectedIndex = 0;
17541			break;
17542		case $.ui.keyCode.SPACE:
17543
17544			// Activate only, no collapsing
17545			event.preventDefault();
17546			clearTimeout( this.activating );
17547			this._activate( selectedIndex );
17548			return;
17549		case $.ui.keyCode.ENTER:
17550
17551			// Toggle (cancel delayed activation, allow collapsing)
17552			event.preventDefault();
17553			clearTimeout( this.activating );
17554
17555			// Determine if we should collapse or activate
17556			this._activate( selectedIndex === this.options.active ? false : selectedIndex );
17557			return;
17558		default:
17559			return;
17560		}
17561
17562		// Focus the appropriate tab, based on which key was pressed
17563		event.preventDefault();
17564		clearTimeout( this.activating );
17565		selectedIndex = this._focusNextTab( selectedIndex, goingForward );
17566
17567		// Navigating with control/command key will prevent automatic activation
17568		if ( !event.ctrlKey && !event.metaKey ) {
17569
17570			// Update aria-selected immediately so that AT think the tab is already selected.
17571			// Otherwise AT may confuse the user by stating that they need to activate the tab,
17572			// but the tab will already be activated by the time the announcement finishes.
17573			focusedTab.attr( "aria-selected", "false" );
17574			this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" );
17575
17576			this.activating = this._delay( function() {
17577				this.option( "active", selectedIndex );
17578			}, this.delay );
17579		}
17580	},
17581
17582	_panelKeydown: function( event ) {
17583		if ( this._handlePageNav( event ) ) {
17584			return;
17585		}
17586
17587		// Ctrl+up moves focus to the current tab
17588		if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {
17589			event.preventDefault();
17590			this.active.trigger( "focus" );
17591		}
17592	},
17593
17594	// Alt+page up/down moves focus to the previous/next tab (and activates)
17595	_handlePageNav: function( event ) {
17596		if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {
17597			this._activate( this._focusNextTab( this.options.active - 1, false ) );
17598			return true;
17599		}
17600		if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {
17601			this._activate( this._focusNextTab( this.options.active + 1, true ) );
17602			return true;
17603		}
17604	},
17605
17606	_findNextTab: function( index, goingForward ) {
17607		var lastTabIndex = this.tabs.length - 1;
17608
17609		function constrain() {
17610			if ( index > lastTabIndex ) {
17611				index = 0;
17612			}
17613			if ( index < 0 ) {
17614				index = lastTabIndex;
17615			}
17616			return index;
17617		}
17618
17619		while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {
17620			index = goingForward ? index + 1 : index - 1;
17621		}
17622
17623		return index;
17624	},
17625
17626	_focusNextTab: function( index, goingForward ) {
17627		index = this._findNextTab( index, goingForward );
17628		this.tabs.eq( index ).trigger( "focus" );
17629		return index;
17630	},
17631
17632	_setOption: function( key, value ) {
17633		if ( key === "active" ) {
17634
17635			// _activate() will handle invalid values and update this.options
17636			this._activate( value );
17637			return;
17638		}
17639
17640		this._super( key, value );
17641
17642		if ( key === "collapsible" ) {
17643			this._toggleClass( "ui-tabs-collapsible", null, value );
17644
17645			// Setting collapsible: false while collapsed; open first panel
17646			if ( !value && this.options.active === false ) {
17647				this._activate( 0 );
17648			}
17649		}
17650
17651		if ( key === "event" ) {
17652			this._setupEvents( value );
17653		}
17654
17655		if ( key === "heightStyle" ) {
17656			this._setupHeightStyle( value );
17657		}
17658	},
17659
17660	_sanitizeSelector: function( hash ) {
17661		return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : "";
17662	},
17663
17664	refresh: function() {
17665		var options = this.options,
17666			lis = this.tablist.children( ":has(a[href])" );
17667
17668		// Get disabled tabs from class attribute from HTML
17669		// this will get converted to a boolean if needed in _refresh()
17670		options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) {
17671			return lis.index( tab );
17672		} );
17673
17674		this._processTabs();
17675
17676		// Was collapsed or no tabs
17677		if ( options.active === false || !this.anchors.length ) {
17678			options.active = false;
17679			this.active = $();
17680
17681		// was active, but active tab is gone
17682		} else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {
17683
17684			// all remaining tabs are disabled
17685			if ( this.tabs.length === options.disabled.length ) {
17686				options.active = false;
17687				this.active = $();
17688
17689			// activate previous tab
17690			} else {
17691				this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );
17692			}
17693
17694		// was active, active tab still exists
17695		} else {
17696
17697			// make sure active index is correct
17698			options.active = this.tabs.index( this.active );
17699		}
17700
17701		this._refresh();
vendor: 28,652 bytes, lines 17702-18745
17702	},
17703
17704	_refresh: function() {
17705		this._setOptionDisabled( this.options.disabled );
17706		this._setupEvents( this.options.event );
17707		this._setupHeightStyle( this.options.heightStyle );
17708
17709		this.tabs.not( this.active ).attr( {
17710			"aria-selected": "false",
17711			"aria-expanded": "false",
17712			tabIndex: -1
17713		} );
17714		this.panels.not( this._getPanelForTab( this.active ) )
17715			.hide()
17716			.attr( {
17717				"aria-hidden": "true"
17718			} );
17719
17720		// Make sure one tab is in the tab order
17721		if ( !this.active.length ) {
17722			this.tabs.eq( 0 ).attr( "tabIndex", 0 );
17723		} else {
17724			this.active
17725				.attr( {
17726					"aria-selected": "true",
17727					"aria-expanded": "true",
17728					tabIndex: 0
17729				} );
17730			this._addClass( this.active, "ui-tabs-active", "ui-state-active" );
17731			this._getPanelForTab( this.active )
17732				.show()
17733				.attr( {
17734					"aria-hidden": "false"
17735				} );
17736		}
17737	},
17738
17739	_processTabs: function() {
17740		var that = this,
17741			prevTabs = this.tabs,
17742			prevAnchors = this.anchors,
17743			prevPanels = this.panels;
17744
17745		this.tablist = this._getList().attr( "role", "tablist" );
17746		this._addClass( this.tablist, "ui-tabs-nav",
17747			"ui-helper-reset ui-helper-clearfix ui-widget-header" );
17748
17749		// Prevent users from focusing disabled tabs via click
17750		this.tablist
17751			.on( "mousedown" + this.eventNamespace, "> li", function( event ) {
17752				if ( $( this ).is( ".ui-state-disabled" ) ) {
17753					event.preventDefault();
17754				}
17755			} );
17756
17757		this.tabs = this.tablist.find( "> li:has(a[href])" )
17758			.attr( {
17759				role: "tab",
17760				tabIndex: -1
17761			} );
17762		this._addClass( this.tabs, "ui-tabs-tab", "ui-state-default" );
17763
17764		this.anchors = this.tabs.map( function() {
17765			return $( "a", this )[ 0 ];
17766		} )
17767			.attr( {
17768				tabIndex: -1
17769			} );
17770		this._addClass( this.anchors, "ui-tabs-anchor" );
17771
17772		this.panels = $();
17773
17774		this.anchors.each( function( i, anchor ) {
17775			var selector, panel, panelId,
17776				anchorId = $( anchor ).uniqueId().attr( "id" ),
17777				tab = $( anchor ).closest( "li" ),
17778				originalAriaControls = tab.attr( "aria-controls" );
17779
17780			// Inline tab
17781			if ( that._isLocal( anchor ) ) {
17782				selector = anchor.hash;
17783				panelId = selector.substring( 1 );
17784				panel = that.element.find( that._sanitizeSelector( selector ) );
17785
17786			// remote tab
17787			} else {
17788
17789				// If the tab doesn't already have aria-controls,
17790				// generate an id by using a throw-away element
17791				panelId = tab.attr( "aria-controls" ) || $( {} ).uniqueId()[ 0 ].id;
17792				selector = "#" + panelId;
17793				panel = that.element.find( selector );
17794				if ( !panel.length ) {
17795					panel = that._createPanel( panelId );
17796					panel.insertAfter( that.panels[ i - 1 ] || that.tablist );
17797				}
17798				panel.attr( "aria-live", "polite" );
17799			}
17800
17801			if ( panel.length ) {
17802				that.panels = that.panels.add( panel );
17803			}
17804			if ( originalAriaControls ) {
17805				tab.data( "ui-tabs-aria-controls", originalAriaControls );
17806			}
17807			tab.attr( {
17808				"aria-controls": panelId,
17809				"aria-labelledby": anchorId
17810			} );
17811			panel.attr( "aria-labelledby", anchorId );
17812		} );
17813
17814		this.panels.attr( "role", "tabpanel" );
17815		this._addClass( this.panels, "ui-tabs-panel", "ui-widget-content" );
17816
17817		// Avoid memory leaks (#10056)
17818		if ( prevTabs ) {
17819			this._off( prevTabs.not( this.tabs ) );
17820			this._off( prevAnchors.not( this.anchors ) );
17821			this._off( prevPanels.not( this.panels ) );
17822		}
17823	},
17824
17825	// Allow overriding how to find the list for rare usage scenarios (#7715)
17826	_getList: function() {
17827		return this.tablist || this.element.find( "ol, ul" ).eq( 0 );
17828	},
17829
17830	_createPanel: function( id ) {
17831		return $( "<div>" )
17832			.attr( "id", id )
17833			.data( "ui-tabs-destroy", true );
17834	},
17835
17836	_setOptionDisabled: function( disabled ) {
17837		var currentItem, li, i;
17838
17839		if ( Array.isArray( disabled ) ) {
17840			if ( !disabled.length ) {
17841				disabled = false;
17842			} else if ( disabled.length === this.anchors.length ) {
17843				disabled = true;
17844			}
17845		}
17846
17847		// Disable tabs
17848		for ( i = 0; ( li = this.tabs[ i ] ); i++ ) {
17849			currentItem = $( li );
17850			if ( disabled === true || $.inArray( i, disabled ) !== -1 ) {
17851				currentItem.attr( "aria-disabled", "true" );
17852				this._addClass( currentItem, null, "ui-state-disabled" );
17853			} else {
17854				currentItem.removeAttr( "aria-disabled" );
17855				this._removeClass( currentItem, null, "ui-state-disabled" );
17856			}
17857		}
17858
17859		this.options.disabled = disabled;
17860
17861		this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null,
17862			disabled === true );
17863	},
17864
17865	_setupEvents: function( event ) {
17866		var events = {};
17867		if ( event ) {
17868			$.each( event.split( " " ), function( index, eventName ) {
17869				events[ eventName ] = "_eventHandler";
17870			} );
17871		}
17872
17873		this._off( this.anchors.add( this.tabs ).add( this.panels ) );
17874
17875		// Always prevent the default action, even when disabled
17876		this._on( true, this.anchors, {
17877			click: function( event ) {
17878				event.preventDefault();
17879			}
17880		} );
17881		this._on( this.anchors, events );
17882		this._on( this.tabs, { keydown: "_tabKeydown" } );
17883		this._on( this.panels, { keydown: "_panelKeydown" } );
17884
17885		this._focusable( this.tabs );
17886		this._hoverable( this.tabs );
17887	},
17888
17889	_setupHeightStyle: function( heightStyle ) {
17890		var maxHeight,
17891			parent = this.element.parent();
17892
17893		if ( heightStyle === "fill" ) {
17894			maxHeight = parent.height();
17895			maxHeight -= this.element.outerHeight() - this.element.height();
17896
17897			this.element.siblings( ":visible" ).each( function() {
17898				var elem = $( this ),
17899					position = elem.css( "position" );
17900
17901				if ( position === "absolute" || position === "fixed" ) {
17902					return;
17903				}
17904				maxHeight -= elem.outerHeight( true );
17905			} );
17906
17907			this.element.children().not( this.panels ).each( function() {
17908				maxHeight -= $( this ).outerHeight( true );
17909			} );
17910
17911			this.panels.each( function() {
17912				$( this ).height( Math.max( 0, maxHeight -
17913					$( this ).innerHeight() + $( this ).height() ) );
17914			} )
17915				.css( "overflow", "auto" );
17916		} else if ( heightStyle === "auto" ) {
17917			maxHeight = 0;
17918			this.panels.each( function() {
17919				maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
17920			} ).height( maxHeight );
17921		}
17922	},
17923
17924	_eventHandler: function( event ) {
17925		var options = this.options,
17926			active = this.active,
17927			anchor = $( event.currentTarget ),
17928			tab = anchor.closest( "li" ),
17929			clickedIsActive = tab[ 0 ] === active[ 0 ],
17930			collapsing = clickedIsActive && options.collapsible,
17931			toShow = collapsing ? $() : this._getPanelForTab( tab ),
17932			toHide = !active.length ? $() : this._getPanelForTab( active ),
17933			eventData = {
17934				oldTab: active,
17935				oldPanel: toHide,
17936				newTab: collapsing ? $() : tab,
17937				newPanel: toShow
17938			};
17939
17940		event.preventDefault();
17941
17942		if ( tab.hasClass( "ui-state-disabled" ) ||
17943
17944				// tab is already loading
17945				tab.hasClass( "ui-tabs-loading" ) ||
17946
17947				// can't switch durning an animation
17948				this.running ||
17949
17950				// click on active header, but not collapsible
17951				( clickedIsActive && !options.collapsible ) ||
17952
17953				// allow canceling activation
17954				( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
17955			return;
17956		}
17957
17958		options.active = collapsing ? false : this.tabs.index( tab );
17959
17960		this.active = clickedIsActive ? $() : tab;
17961		if ( this.xhr ) {
17962			this.xhr.abort();
17963		}
17964
17965		if ( !toHide.length && !toShow.length ) {
17966			$.error( "jQuery UI Tabs: Mismatching fragment identifier." );
17967		}
17968
17969		if ( toShow.length ) {
17970			this.load( this.tabs.index( tab ), event );
17971		}
17972		this._toggle( event, eventData );
17973	},
17974
17975	// Handles show/hide for selecting tabs
17976	_toggle: function( event, eventData ) {
17977		var that = this,
17978			toShow = eventData.newPanel,
17979			toHide = eventData.oldPanel;
17980
17981		this.running = true;
17982
17983		function complete() {
17984			that.running = false;
17985			that._trigger( "activate", event, eventData );
17986		}
17987
17988		function show() {
17989			that._addClass( eventData.newTab.closest( "li" ), "ui-tabs-active", "ui-state-active" );
17990
17991			if ( toShow.length && that.options.show ) {
17992				that._show( toShow, that.options.show, complete );
17993			} else {
17994				toShow.show();
17995				complete();
17996			}
17997		}
17998
17999		// Start out by hiding, then showing, then completing
18000		if ( toHide.length && this.options.hide ) {
18001			this._hide( toHide, this.options.hide, function() {
18002				that._removeClass( eventData.oldTab.closest( "li" ),
18003					"ui-tabs-active", "ui-state-active" );
18004				show();
18005			} );
18006		} else {
18007			this._removeClass( eventData.oldTab.closest( "li" ),
18008				"ui-tabs-active", "ui-state-active" );
18009			toHide.hide();
18010			show();
18011		}
18012
18013		toHide.attr( "aria-hidden", "true" );
18014		eventData.oldTab.attr( {
18015			"aria-selected": "false",
18016			"aria-expanded": "false"
18017		} );
18018
18019		// If we're switching tabs, remove the old tab from the tab order.
18020		// If we're opening from collapsed state, remove the previous tab from the tab order.
18021		// If we're collapsing, then keep the collapsing tab in the tab order.
18022		if ( toShow.length && toHide.length ) {
18023			eventData.oldTab.attr( "tabIndex", -1 );
18024		} else if ( toShow.length ) {
18025			this.tabs.filter( function() {
18026				return $( this ).attr( "tabIndex" ) === 0;
18027			} )
18028				.attr( "tabIndex", -1 );
18029		}
18030
18031		toShow.attr( "aria-hidden", "false" );
18032		eventData.newTab.attr( {
18033			"aria-selected": "true",
18034			"aria-expanded": "true",
18035			tabIndex: 0
18036		} );
18037	},
18038
18039	_activate: function( index ) {
18040		var anchor,
18041			active = this._findActive( index );
18042
18043		// Trying to activate the already active panel
18044		if ( active[ 0 ] === this.active[ 0 ] ) {
18045			return;
18046		}
18047
18048		// Trying to collapse, simulate a click on the current active header
18049		if ( !active.length ) {
18050			active = this.active;
18051		}
18052
18053		anchor = active.find( ".ui-tabs-anchor" )[ 0 ];
18054		this._eventHandler( {
18055			target: anchor,
18056			currentTarget: anchor,
18057			preventDefault: $.noop
18058		} );
18059	},
18060
18061	_findActive: function( index ) {
18062		return index === false ? $() : this.tabs.eq( index );
18063	},
18064
18065	_getIndex: function( index ) {
18066
18067		// meta-function to give users option to provide a href string instead of a numerical index.
18068		if ( typeof index === "string" ) {
18069			index = this.anchors.index( this.anchors.filter( "[href$='" +
18070				CSS.escape( index ) + "']" ) );
18071		}
18072
18073		return index;
18074	},
18075
18076	_destroy: function() {
18077		if ( this.xhr ) {
18078			this.xhr.abort();
18079		}
18080
18081		this.tablist
18082			.removeAttr( "role" )
18083			.off( this.eventNamespace );
18084
18085		this.anchors
18086			.removeAttr( "role tabIndex" )
18087			.removeUniqueId();
18088
18089		this.tabs.add( this.panels ).each( function() {
18090			if ( $.data( this, "ui-tabs-destroy" ) ) {
18091				$( this ).remove();
18092			} else {
18093				$( this ).removeAttr( "role tabIndex " +
18094					"aria-live aria-busy aria-selected aria-labelledby aria-hidden aria-expanded" );
18095			}
18096		} );
18097
18098		this.tabs.each( function() {
18099			var li = $( this ),
18100				prev = li.data( "ui-tabs-aria-controls" );
18101			if ( prev ) {
18102				li
18103					.attr( "aria-controls", prev )
18104					.removeData( "ui-tabs-aria-controls" );
18105			} else {
18106				li.removeAttr( "aria-controls" );
18107			}
18108		} );
18109
18110		this.panels.show();
18111
18112		if ( this.options.heightStyle !== "content" ) {
18113			this.panels.css( "height", "" );
18114		}
18115	},
18116
18117	enable: function( index ) {
18118		var disabled = this.options.disabled;
18119		if ( disabled === false ) {
18120			return;
18121		}
18122
18123		if ( index === undefined ) {
18124			disabled = false;
18125		} else {
18126			index = this._getIndex( index );
18127			if ( Array.isArray( disabled ) ) {
18128				disabled = $.map( disabled, function( num ) {
18129					return num !== index ? num : null;
18130				} );
18131			} else {
18132				disabled = $.map( this.tabs, function( li, num ) {
18133					return num !== index ? num : null;
18134				} );
18135			}
18136		}
18137		this._setOptionDisabled( disabled );
18138	},
18139
18140	disable: function( index ) {
18141		var disabled = this.options.disabled;
18142		if ( disabled === true ) {
18143			return;
18144		}
18145
18146		if ( index === undefined ) {
18147			disabled = true;
18148		} else {
18149			index = this._getIndex( index );
18150			if ( $.inArray( index, disabled ) !== -1 ) {
18151				return;
18152			}
18153			if ( Array.isArray( disabled ) ) {
18154				disabled = $.merge( [ index ], disabled ).sort();
18155			} else {
18156				disabled = [ index ];
18157			}
18158		}
18159		this._setOptionDisabled( disabled );
18160	},
18161
18162	load: function( index, event ) {
18163		index = this._getIndex( index );
18164		var that = this,
18165			tab = this.tabs.eq( index ),
18166			anchor = tab.find( ".ui-tabs-anchor" ),
18167			panel = this._getPanelForTab( tab ),
18168			eventData = {
18169				tab: tab,
18170				panel: panel
18171			},
18172			complete = function( jqXHR, status ) {
18173				if ( status === "abort" ) {
18174					that.panels.stop( false, true );
18175				}
18176
18177				that._removeClass( tab, "ui-tabs-loading" );
18178				panel.removeAttr( "aria-busy" );
18179
18180				if ( jqXHR === that.xhr ) {
18181					delete that.xhr;
18182				}
18183			};
18184
18185		// Not remote
18186		if ( this._isLocal( anchor[ 0 ] ) ) {
18187			return;
18188		}
18189
18190		this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );
18191
18192		if ( this.xhr.statusText !== "canceled" ) {
18193			this._addClass( tab, "ui-tabs-loading" );
18194			panel.attr( "aria-busy", "true" );
18195
18196			this.xhr
18197				.done( function( response, status, jqXHR ) {
18198					panel.html( response );
18199					that._trigger( "load", event, eventData );
18200
18201					complete( jqXHR, status );
18202				} )
18203				.fail( function( jqXHR, status ) {
18204					complete( jqXHR, status );
18205				} );
18206		}
18207	},
18208
18209	_ajaxSettings: function( anchor, event, eventData ) {
18210		var that = this;
18211		return {
18212			url: anchor.attr( "href" ),
18213			beforeSend: function( jqXHR, settings ) {
18214				return that._trigger( "beforeLoad", event,
18215					$.extend( { jqXHR: jqXHR, ajaxSettings: settings }, eventData ) );
18216			}
18217		};
18218	},
18219
18220	_getPanelForTab: function( tab ) {
18221		var id = $( tab ).attr( "aria-controls" );
18222		return this.element.find( this._sanitizeSelector( "#" + id ) );
18223	}
18224} );
18225
18226// DEPRECATED
18227// TODO: Switch return back to widget declaration at top of file when this is removed
18228if ( $.uiBackCompat === true ) {
18229
18230	// Backcompat for ui-tab class (now ui-tabs-tab)
18231	$.widget( "ui.tabs", $.ui.tabs, {
18232		_processTabs: function() {
18233			this._superApply( arguments );
18234			this._addClass( this.tabs, "ui-tab" );
18235		}
18236	} );
18237}
18238
18239var widgetsTabs = $.ui.tabs;
18240
18241
18242/*!
18243 * jQuery UI Tooltip 1.14.0
18244 * https://jqueryui.com
18245 *
18246 * Copyright OpenJS Foundation and other contributors
18247 * Released under the MIT license.
18248 * https://jquery.org/license
18249 */
18250
18251//>>label: Tooltip
18252//>>group: Widgets
18253//>>description: Shows additional information for any element on hover or focus.
18254//>>docs: https://api.jqueryui.com/tooltip/
18255//>>demos: https://jqueryui.com/tooltip/
18256//>>css.structure: ../../themes/base/core.css
18257//>>css.structure: ../../themes/base/tooltip.css
18258//>>css.theme: ../../themes/base/theme.css
18259
18260
18261$.widget( "ui.tooltip", {
18262	version: "1.14.0",
18263	options: {
18264		classes: {
18265			"ui-tooltip": "ui-corner-all ui-widget-shadow"
18266		},
18267		content: function() {
18268			var title = $( this ).attr( "title" );
18269
18270			// Escape title, since we're going from an attribute to raw HTML
18271			return $( "<a>" ).text( title ).html();
18272		},
18273		hide: true,
18274
18275		// Disabled elements have inconsistent behavior across browsers (#8661)
18276		items: "[title]:not([disabled])",
18277		position: {
18278			my: "left top+15",
18279			at: "left bottom",
18280			collision: "flipfit flip"
18281		},
18282		show: true,
18283		track: false,
18284
18285		// Callbacks
18286		close: null,
18287		open: null
18288	},
18289
18290	_addDescribedBy: function( elem, id ) {
18291		var describedby = ( elem.attr( "aria-describedby" ) || "" ).split( /\s+/ );
18292		describedby.push( id );
18293		elem
18294			.data( "ui-tooltip-id", id )
18295			.attr( "aria-describedby", String.prototype.trim.call( describedby.join( " " ) ) );
18296	},
18297
18298	_removeDescribedBy: function( elem ) {
18299		var id = elem.data( "ui-tooltip-id" ),
18300			describedby = ( elem.attr( "aria-describedby" ) || "" ).split( /\s+/ ),
18301			index = $.inArray( id, describedby );
18302
18303		if ( index !== -1 ) {
18304			describedby.splice( index, 1 );
18305		}
18306
18307		elem.removeData( "ui-tooltip-id" );
18308		describedby = String.prototype.trim.call( describedby.join( " " ) );
18309		if ( describedby ) {
18310			elem.attr( "aria-describedby", describedby );
18311		} else {
18312			elem.removeAttr( "aria-describedby" );
18313		}
18314	},
18315
18316	_create: function() {
18317		this._on( {
18318			mouseover: "open",
18319			focusin: "open"
18320		} );
18321
18322		// IDs of generated tooltips, needed for destroy
18323		this.tooltips = {};
18324
18325		// IDs of parent tooltips where we removed the title attribute
18326		this.parents = {};
18327
18328		// Append the aria-live region so tooltips announce correctly
18329		this.liveRegion = $( "<div>" )
18330			.attr( {
18331				role: "log",
18332				"aria-live": "assertive",
18333				"aria-relevant": "additions"
18334			} )
18335			.appendTo( this.document[ 0 ].body );
18336		this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" );
18337
18338		this.disabledTitles = $( [] );
18339	},
18340
18341	_setOption: function( key, value ) {
18342		var that = this;
18343
18344		this._super( key, value );
18345
18346		if ( key === "content" ) {
18347			$.each( this.tooltips, function( id, tooltipData ) {
18348				that._updateContent( tooltipData.element );
18349			} );
18350		}
18351	},
18352
18353	_setOptionDisabled: function( value ) {
18354		this[ value ? "_disable" : "_enable" ]();
18355	},
18356
18357	_disable: function() {
18358		var that = this;
18359
18360		// Close open tooltips
18361		$.each( this.tooltips, function( id, tooltipData ) {
18362			var event = $.Event( "blur" );
18363			event.target = event.currentTarget = tooltipData.element[ 0 ];
18364			that.close( event, true );
18365		} );
18366
18367		// Remove title attributes to prevent native tooltips
18368		this.disabledTitles = this.disabledTitles.add(
18369			this.element.find( this.options.items ).addBack()
18370				.filter( function() {
18371					var element = $( this );
18372					if ( element.is( "[title]" ) ) {
18373						return element
18374							.data( "ui-tooltip-title", element.attr( "title" ) )
18375							.removeAttr( "title" );
18376					}
18377				} )
18378		);
18379	},
18380
18381	_enable: function() {
18382
18383		// restore title attributes
18384		this.disabledTitles.each( function() {
18385			var element = $( this );
18386			if ( element.data( "ui-tooltip-title" ) ) {
18387				element.attr( "title", element.data( "ui-tooltip-title" ) );
18388			}
18389		} );
18390		this.disabledTitles = $( [] );
18391	},
18392
18393	open: function( event ) {
18394		var that = this,
18395			target = $( event ? event.target : this.element )
18396
18397				// we need closest here due to mouseover bubbling,
18398				// but always pointing at the same event target
18399				.closest( this.options.items );
18400
18401		// No element to show a tooltip for or the tooltip is already open
18402		if ( !target.length || target.data( "ui-tooltip-id" ) ) {
18403			return;
18404		}
18405
18406		if ( target.attr( "title" ) ) {
18407			target.data( "ui-tooltip-title", target.attr( "title" ) );
18408		}
18409
18410		target.data( "ui-tooltip-open", true );
18411
18412		// Kill parent tooltips, custom or native, for hover
18413		if ( event && event.type === "mouseover" ) {
18414			target.parents().each( function() {
18415				var parent = $( this ),
18416					blurEvent;
18417				if ( parent.data( "ui-tooltip-open" ) ) {
18418					blurEvent = $.Event( "blur" );
18419					blurEvent.target = blurEvent.currentTarget = this;
18420					that.close( blurEvent, true );
18421				}
18422				if ( parent.attr( "title" ) ) {
18423					parent.uniqueId();
18424					that.parents[ this.id ] = {
18425						element: this,
18426						title: parent.attr( "title" )
18427					};
18428					parent.attr( "title", "" );
18429				}
18430			} );
18431		}
18432
18433		this._registerCloseHandlers( event, target );
18434		this._updateContent( target, event );
18435	},
18436
18437	_updateContent: function( target, event ) {
18438		var content,
18439			contentOption = this.options.content,
18440			that = this,
18441			eventType = event ? event.type : null;
18442
18443		if ( typeof contentOption === "string" || contentOption.nodeType ||
18444				contentOption.jquery ) {
18445			return this._open( event, target, contentOption );
18446		}
18447
18448		content = contentOption.call( target[ 0 ], function( response ) {
18449
18450			// Ignore async response if tooltip was closed already
18451			if ( !target.data( "ui-tooltip-open" ) ) {
18452				return;
18453			}
18454
18455			// JQuery creates a special event for focusin when it doesn't
18456			// exist natively. To improve performance, the native event
18457			// object is reused and the type is changed. Therefore, we can't
18458			// rely on the type being correct after the event finished
18459			// bubbling, so we set it back to the previous value. (#8740)
18460			if ( event ) {
18461				event.type = eventType;
18462			}
18463			that._open( event, target, response );
18464		} );
18465		if ( content ) {
18466			this._open( event, target, content );
18467		}
18468	},
18469
18470	_open: function( event, target, content ) {
18471		var tooltipData, tooltip, delayedShow, a11yContent,
18472			positionOption = $.extend( {}, this.options.position );
18473
18474		if ( !content ) {
18475			return;
18476		}
18477
18478		// Content can be updated multiple times. If the tooltip already
18479		// exists, then just update the content and bail.
18480		tooltipData = this._find( target );
18481		if ( tooltipData ) {
18482			tooltipData.tooltip.find( ".ui-tooltip-content" ).html( content );
18483			return;
18484		}
18485
18486		// If we have a title, clear it to prevent the native tooltip
18487		// we have to check first to avoid defining a title if none exists
18488		// (we don't want to cause an element to start matching [title])
18489		//
18490		// We use removeAttr only for key events, to allow IE to export the correct
18491		// accessible attributes. For mouse events, set to empty string to avoid
18492		// native tooltip showing up (happens only when removing inside mouseover).
18493		if ( target.is( "[title]" ) ) {
18494			if ( event && event.type === "mouseover" ) {
18495				target.attr( "title", "" );
18496			} else {
18497				target.removeAttr( "title" );
18498			}
18499		}
18500
18501		tooltipData = this._tooltip( target );
18502		tooltip = tooltipData.tooltip;
18503		this._addDescribedBy( target, tooltip.attr( "id" ) );
18504		tooltip.find( ".ui-tooltip-content" ).html( content );
18505
18506		// Support: Voiceover on OS X, JAWS on IE <= 9
18507		// JAWS announces deletions even when aria-relevant="additions"
18508		// Voiceover will sometimes re-read the entire log region's contents from the beginning
18509		this.liveRegion.children().hide();
18510		a11yContent = $( "<div>" ).html( tooltip.find( ".ui-tooltip-content" ).html() );
18511		a11yContent.removeAttr( "name" ).find( "[name]" ).removeAttr( "name" );
18512		a11yContent.removeAttr( "id" ).find( "[id]" ).removeAttr( "id" );
18513		a11yContent.appendTo( this.liveRegion );
18514
18515		function position( event ) {
18516			positionOption.of = event;
18517			if ( tooltip.is( ":hidden" ) ) {
18518				return;
18519			}
18520			tooltip.position( positionOption );
18521		}
18522		if ( this.options.track && event && /^mouse/.test( event.type ) ) {
18523			this._on( this.document, {
18524				mousemove: position
18525			} );
18526
18527			// trigger once to override element-relative positioning
18528			position( event );
18529		} else {
18530			tooltip.position( $.extend( {
18531				of: target
18532			}, this.options.position ) );
18533		}
18534
18535		tooltip.hide();
18536
18537		this._show( tooltip, this.options.show );
18538
18539		// Handle tracking tooltips that are shown with a delay (#8644). As soon
18540		// as the tooltip is visible, position the tooltip using the most recent
18541		// event.
18542		// Adds the check to add the timers only when both delay and track options are set (#14682)
18543		if ( this.options.track && this.options.show && this.options.show.delay ) {
18544			delayedShow = this.delayedShow = setInterval( function() {
18545				if ( tooltip.is( ":visible" ) ) {
18546					position( positionOption.of );
18547					clearInterval( delayedShow );
18548				}
18549			}, 13 );
18550		}
18551
18552		this._trigger( "open", event, { tooltip: tooltip } );
18553	},
18554
18555	_registerCloseHandlers: function( event, target ) {
18556		var events = {
18557			keyup: function( event ) {
18558				if ( event.keyCode === $.ui.keyCode.ESCAPE ) {
18559					var fakeEvent = $.Event( event );
18560					fakeEvent.currentTarget = target[ 0 ];
18561					this.close( fakeEvent, true );
18562				}
18563			}
18564		};
18565
18566		// Only bind remove handler for delegated targets. Non-delegated
18567		// tooltips will handle this in destroy.
18568		if ( target[ 0 ] !== this.element[ 0 ] ) {
18569			events.remove = function() {
18570				var targetElement = this._find( target );
18571				if ( targetElement ) {
18572					this._removeTooltip( targetElement.tooltip );
18573				}
18574			};
18575		}
18576
18577		if ( !event || event.type === "mouseover" ) {
18578			events.mouseleave = "close";
18579		}
18580		if ( !event || event.type === "focusin" ) {
18581			events.focusout = "close";
18582		}
18583		this._on( true, target, events );
18584	},
18585
18586	close: function( event ) {
18587		var tooltip,
18588			that = this,
18589			target = $( event ? event.currentTarget : this.element ),
18590			tooltipData = this._find( target );
18591
18592		// The tooltip may already be closed
18593		if ( !tooltipData ) {
18594
18595			// We set ui-tooltip-open immediately upon open (in open()), but only set the
18596			// additional data once there's actually content to show (in _open()). So even if the
18597			// tooltip doesn't have full data, we always remove ui-tooltip-open in case we're in
18598			// the period between open() and _open().
18599			target.removeData( "ui-tooltip-open" );
18600			return;
18601		}
18602
18603		tooltip = tooltipData.tooltip;
18604
18605		// Disabling closes the tooltip, so we need to track when we're closing
18606		// to avoid an infinite loop in case the tooltip becomes disabled on close
18607		if ( tooltipData.closing ) {
18608			return;
18609		}
18610
18611		// Clear the interval for delayed tracking tooltips
18612		clearInterval( this.delayedShow );
18613
18614		// Only set title if we had one before (see comment in _open())
18615		// If the title attribute has changed since open(), don't restore
18616		if ( target.data( "ui-tooltip-title" ) && !target.attr( "title" ) ) {
18617			target.attr( "title", target.data( "ui-tooltip-title" ) );
18618		}
18619
18620		this._removeDescribedBy( target );
18621
18622		tooltipData.hiding = true;
18623		tooltip.stop( true );
18624		this._hide( tooltip, this.options.hide, function() {
18625			that._removeTooltip( $( this ) );
18626		} );
18627
18628		target.removeData( "ui-tooltip-open" );
18629		this._off( target, "mouseleave focusout keyup" );
18630
18631		// Remove 'remove' binding only on delegated targets
18632		if ( target[ 0 ] !== this.element[ 0 ] ) {
18633			this._off( target, "remove" );
18634		}
18635		this._off( this.document, "mousemove" );
18636
18637		if ( event && event.type === "mouseleave" ) {
18638			$.each( this.parents, function( id, parent ) {
18639				$( parent.element ).attr( "title", parent.title );
18640				delete that.parents[ id ];
18641			} );
18642		}
18643
18644		tooltipData.closing = true;
18645		this._trigger( "close", event, { tooltip: tooltip } );
18646		if ( !tooltipData.hiding ) {
18647			tooltipData.closing = false;
18648		}
18649	},
18650
18651	_tooltip: function( element ) {
18652		var tooltip = $( "<div>" ).attr( "role", "tooltip" ),
18653			content = $( "<div>" ).appendTo( tooltip ),
18654			id = tooltip.uniqueId().attr( "id" );
18655
18656		this._addClass( content, "ui-tooltip-content" );
18657		this._addClass( tooltip, "ui-tooltip", "ui-widget ui-widget-content" );
18658
18659		tooltip.appendTo( this._appendTo( element ) );
18660
18661		return this.tooltips[ id ] = {
18662			element: element,
18663			tooltip: tooltip
18664		};
18665	},
18666
18667	_find: function( target ) {
18668		var id = target.data( "ui-tooltip-id" );
18669		return id ? this.tooltips[ id ] : null;
18670	},
18671
18672	_removeTooltip: function( tooltip ) {
18673
18674		// Clear the interval for delayed tracking tooltips
18675		clearInterval( this.delayedShow );
18676
18677		tooltip.remove();
18678		delete this.tooltips[ tooltip.attr( "id" ) ];
18679	},
18680
18681	_appendTo: function( target ) {
18682		var element = target.closest( ".ui-front, dialog" );
18683
18684		if ( !element.length ) {
18685			element = this.document[ 0 ].body;
18686		}
18687
18688		return element;
18689	},
18690
18691	_destroy: function() {
18692		var that = this;
18693
18694		// Close open tooltips
18695		$.each( this.tooltips, function( id, tooltipData ) {
18696
18697			// Delegate to close method to handle common cleanup
18698			var event = $.Event( "blur" ),
18699				element = tooltipData.element;
18700			event.target = event.currentTarget = element[ 0 ];
18701			that.close( event, true );
18702
18703			// Remove immediately; destroying an open tooltip doesn't use the
18704			// hide animation
18705			$( "#" + id ).remove();
18706
18707			// Restore the title
18708			if ( element.data( "ui-tooltip-title" ) ) {
18709
18710				// If the title attribute has changed since open(), don't restore
18711				if ( !element.attr( "title" ) ) {
18712					element.attr( "title", element.data( "ui-tooltip-title" ) );
18713				}
18714				element.removeData( "ui-tooltip-title" );
18715			}
18716		} );
18717		this.liveRegion.remove();
18718	}
18719} );
18720
18721// DEPRECATED
18722// TODO: Switch return back to widget declaration at top of file when this is removed
18723if ( $.uiBackCompat === true ) {
18724
18725	// Backcompat for tooltipClass option
18726	$.widget( "ui.tooltip", $.ui.tooltip, {
18727		options: {
18728			tooltipClass: null
18729		},
18730		_tooltip: function() {
18731			var tooltipData = this._superApply( arguments );
18732			if ( this.options.tooltipClass ) {
18733				tooltipData.tooltip.addClass( this.options.tooltipClass );
18734			}
18735			return tooltipData;
18736		}
18737	} );
18738}
18739
18740var widgetsTooltip = $.ui.tooltip;
18741
18742
18743
18744
18745} );

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.