PageSourceSearch

https://skynyx.ai/js/jquery-ui.js

js skynyx.ai collected 2026-10-05 15:19:19 UTC 394,843 bytes, 13,937 lines download raw bytes

vendor: 394,837 bytes, lines 1-13934
1/*! jQuery UI - v1.12.1 - 2016-09-14
2* http://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-1-7.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 jQuery Foundation and other contributors; Licensed MIT */
5
6(function( factory ) {
7	if ( typeof define === "function" && define.amd ) {
8
9		// AMD. Register as an anonymous module.
10		define([ "jquery" ], factory );
11	} else {
12
13		// Browser globals
14		factory( jQuery );
15	}
16}(function( $ ) {
17
18$.ui = $.ui || {};
19
20var version = $.ui.version = "1.12.1";
21
22
23/*!
24 * jQuery UI Widget 1.12.1
25 * http://jqueryui.com
26 *
27 * Copyright jQuery Foundation and other contributors
28 * Released under the MIT license.
29 * http://jquery.org/license
30 */
31
32//>>label: Widget
33//>>group: Core
34//>>description: Provides a factory for creating stateful widgets with a common API.
35//>>docs: http://api.jqueryui.com/jQuery.widget/
36//>>demos: http://jqueryui.com/widget/
37
38
39
40var widgetUuid = 0;
41var widgetSlice = Array.prototype.slice;
42
43$.cleanData = ( function( orig ) {
44	return function( elems ) {
45		var events, elem, i;
46		for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) {
47			try {
48
49				// Only trigger remove when necessary to save time
50				events = $._data( elem, "events" );
51				if ( events && events.remove ) {
52					$( elem ).triggerHandler( "remove" );
53				}
54
55			// Http://bugs.jquery.com/ticket/8235
56			} catch ( e ) {}
57		}
58		orig( elems );
59	};
60} )( $.cleanData );
61
62$.widget = function( name, base, prototype ) {
63	var existingConstructor, constructor, basePrototype;
64
65	// ProxiedPrototype allows the provided prototype to remain unmodified
66	// so that it can be used as a mixin for multiple widgets (#8876)
67	var proxiedPrototype = {};
68
69	var namespace = name.split( "." )[ 0 ];
70	name = name.split( "." )[ 1 ];
71	var fullName = namespace + "-" + name;
72
73	if ( !prototype ) {
74		prototype = base;
75		base = $.Widget;
76	}
77
78	if ( $.isArray( prototype ) ) {
79		prototype = $.extend.apply( null, [ {} ].concat( prototype ) );
80	}
81
82	// Create selector for plugin
83	$.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
84		return !!$.data( elem, fullName );
85	};
86
87	$[ namespace ] = $[ namespace ] || {};
88	existingConstructor = $[ namespace ][ name ];
89	constructor = $[ namespace ][ name ] = function( options, element ) {
90
91		// Allow instantiation without "new" keyword
92		if ( !this._createWidget ) {
93			return new constructor( options, element );
94		}
95
96		// Allow instantiation without initializing for simple inheritance
97		// must use "new" keyword (the code above always passes args)
98		if ( arguments.length ) {
99			this._createWidget( options, element );
100		}
101	};
102
103	// Extend with the existing constructor to carry over any static properties
104	$.extend( constructor, existingConstructor, {
105		version: prototype.version,
106
107		// Copy the object used to create the prototype in case we need to
108		// redefine the widget later
109		_proto: $.extend( {}, prototype ),
110
111		// Track widgets that inherit from this widget in case this widget is
112		// redefined after a widget inherits from it
113		_childConstructors: []
114	} );
115
116	basePrototype = new base();
117
118	// We need to make the options hash a property directly on the new instance
119	// otherwise we'll modify the options hash on the prototype that we're
120	// inheriting from
121	basePrototype.options = $.widget.extend( {}, basePrototype.options );
122	$.each( prototype, function( prop, value ) {
123		if ( !$.isFunction( value ) ) {
124			proxiedPrototype[ prop ] = value;
125			return;
126		}
127		proxiedPrototype[ prop ] = ( function() {
128			function _super() {
129				return base.prototype[ prop ].apply( this, arguments );
130			}
131
132			function _superApply( args ) {
133				return base.prototype[ prop ].apply( this, args );
134			}
135
136			return function() {
137				var __super = this._super;
138				var __superApply = this._superApply;
139				var returnValue;
140
141				this._super = _super;
142				this._superApply = _superApply;
143
144				returnValue = value.apply( this, arguments );
145
146				this._super = __super;
147				this._superApply = __superApply;
148
149				return returnValue;
150			};
151		} )();
152	} );
153	constructor.prototype = $.widget.extend( basePrototype, {
154
155		// TODO: remove support for widgetEventPrefix
156		// always use the name + a colon as the prefix, e.g., draggable:start
157		// don't prefix for widgets that aren't DOM-based
158		widgetEventPrefix: existingConstructor ? ( basePrototype.widgetEventPrefix || name ) : name
159	}, proxiedPrototype, {
160		constructor: constructor,
161		namespace: namespace,
162		widgetName: name,
163		widgetFullName: fullName
164	} );
165
166	// If this widget is being redefined then we need to find all widgets that
167	// are inheriting from it and redefine all of them so that they inherit from
168	// the new version of this widget. We're essentially trying to replace one
169	// level in the prototype chain.
170	if ( existingConstructor ) {
171		$.each( existingConstructor._childConstructors, function( i, child ) {
172			var childPrototype = child.prototype;
173
174			// Redefine the child widget using the same prototype that was
175			// originally used, but inherit from the new version of the base
176			$.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor,
177				child._proto );
178		} );
179
180		// Remove the list of existing child constructors from the old constructor
181		// so the old child constructors can be garbage collected
182		delete existingConstructor._childConstructors;
183	} else {
184		base._childConstructors.push( constructor );
185	}
186
187	$.widget.bridge( name, constructor );
188
189	return constructor;
190};
191
192$.widget.extend = function( target ) {
193	var input = widgetSlice.call( arguments, 1 );
194	var inputIndex = 0;
195	var inputLength = input.length;
196	var key;
197	var value;
198
199	for ( ; inputIndex < inputLength; inputIndex++ ) {
200		for ( key in input[ inputIndex ] ) {
201			value = input[ inputIndex ][ key ];
202			if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
203
204				// Clone objects
205				if ( $.isPlainObject( value ) ) {
206					target[ key ] = $.isPlainObject( target[ key ] ) ?
207						$.widget.extend( {}, target[ key ], value ) :
208
209						// Don't extend strings, arrays, etc. with objects
210						$.widget.extend( {}, value );
211
212				// Copy everything else by reference
213				} else {
214					target[ key ] = value;
215				}
216			}
217		}
218	}
219	return target;
220};
221
222$.widget.bridge = function( name, object ) {
223	var fullName = object.prototype.widgetFullName || name;
224	$.fn[ name ] = function( options ) {
225		var isMethodCall = typeof options === "string";
226		var args = widgetSlice.call( arguments, 1 );
227		var returnValue = this;
228
229		if ( isMethodCall ) {
230
231			// If this is an empty collection, we need to have the instance method
232			// return undefined instead of the jQuery instance
233			if ( !this.length && options === "instance" ) {
234				returnValue = undefined;
235			} else {
236				this.each( function() {
237					var methodValue;
238					var instance = $.data( this, fullName );
239
240					if ( options === "instance" ) {
241						returnValue = instance;
242						return false;
243					}
244
245					if ( !instance ) {
246						return $.error( "cannot call methods on " + name +
247							" prior to initialization; " +
248							"attempted to call method '" + options + "'" );
249					}
250
251					if ( !$.isFunction( instance[ options ] ) || 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 processClassString( classes, checkOption ) {
513			var current, i;
514			for ( i = 0; i < classes.length; i++ ) {
515				current = that.classesElementLookup[ classes[ i ] ] || $();
516				if ( options.add ) {
517					current = $( $.unique( current.get().concat( options.element.get() ) ) );
518				} else {
519					current = $( current.not( options.element ).get() );
520				}
521				that.classesElementLookup[ classes[ i ] ] = current;
522				full.push( classes[ i ] );
523				if ( checkOption && options.classes[ classes[ i ] ] ) {
524					full.push( options.classes[ classes[ i ] ] );
525				}
526			}
527		}
528
529		this._on( options.element, {
530			"remove": "_untrackClassesElement"
531		} );
532
533		if ( options.keys ) {
534			processClassString( options.keys.match( /\S+/g ) || [], true );
535		}
536		if ( options.extra ) {
537			processClassString( options.extra.match( /\S+/g ) || [] );
538		}
539
540		return full.join( " " );
541	},
542
543	_untrackClassesElement: function( event ) {
544		var that = this;
545		$.each( that.classesElementLookup, function( key, value ) {
546			if ( $.inArray( event.target, value ) !== -1 ) {
547				that.classesElementLookup[ key ] = $( value.not( event.target ).get() );
548			}
549		} );
550	},
551
552	_removeClass: function( element, keys, extra ) {
553		return this._toggleClass( element, keys, extra, false );
554	},
555
556	_addClass: function( element, keys, extra ) {
557		return this._toggleClass( element, keys, extra, true );
558	},
559
560	_toggleClass: function( element, keys, extra, add ) {
561		add = ( typeof add === "boolean" ) ? add : extra;
562		var shift = ( typeof element === "string" || element === null ),
563			options = {
564				extra: shift ? keys : extra,
565				keys: shift ? element : keys,
566				element: shift ? this.element : element,
567				add: add
568			};
569		options.element.toggleClass( this._classes( options ), add );
570		return this;
571	},
572
573	_on: function( suppressDisabledCheck, element, handlers ) {
574		var delegateElement;
575		var instance = this;
576
577		// No suppressDisabledCheck flag, shuffle arguments
578		if ( typeof suppressDisabledCheck !== "boolean" ) {
579			handlers = element;
580			element = suppressDisabledCheck;
581			suppressDisabledCheck = false;
582		}
583
584		// No element argument, shuffle and use this.element
585		if ( !handlers ) {
586			handlers = element;
587			element = this.element;
588			delegateElement = this.widget();
589		} else {
590			element = delegateElement = $( element );
591			this.bindings = this.bindings.add( element );
592		}
593
594		$.each( handlers, function( event, handler ) {
595			function handlerProxy() {
596
597				// Allow widgets to customize the disabled handling
598				// - disabled as an array instead of boolean
599				// - disabled class as method for disabling individual parts
600				if ( !suppressDisabledCheck &&
601						( instance.options.disabled === true ||
602						$( this ).hasClass( "ui-state-disabled" ) ) ) {
603					return;
604				}
605				return ( typeof handler === "string" ? instance[ handler ] : handler )
606					.apply( instance, arguments );
607			}
608
609			// Copy the guid so direct unbinding works
610			if ( typeof handler !== "string" ) {
611				handlerProxy.guid = handler.guid =
612					handler.guid || handlerProxy.guid || $.guid++;
613			}
614
615			var match = event.match( /^([\w:-]*)\s*(.*)$/ );
616			var eventName = match[ 1 ] + instance.eventNamespace;
617			var selector = match[ 2 ];
618
619			if ( selector ) {
620				delegateElement.on( eventName, selector, handlerProxy );
621			} else {
622				element.on( eventName, handlerProxy );
623			}
624		} );
625	},
626
627	_off: function( element, eventName ) {
628		eventName = ( eventName || "" ).split( " " ).join( this.eventNamespace + " " ) +
629			this.eventNamespace;
630		element.off( eventName ).off( eventName );
631
632		// Clear the stack to avoid memory leaks (#10056)
633		this.bindings = $( this.bindings.not( element ).get() );
634		this.focusable = $( this.focusable.not( element ).get() );
635		this.hoverable = $( this.hoverable.not( element ).get() );
636	},
637
638	_delay: function( handler, delay ) {
639		function handlerProxy() {
640			return ( typeof handler === "string" ? instance[ handler ] : handler )
641				.apply( instance, arguments );
642		}
643		var instance = this;
644		return setTimeout( handlerProxy, delay || 0 );
645	},
646
647	_hoverable: function( element ) {
648		this.hoverable = this.hoverable.add( element );
649		this._on( element, {
650			mouseenter: function( event ) {
651				this._addClass( $( event.currentTarget ), null, "ui-state-hover" );
652			},
653			mouseleave: function( event ) {
654				this._removeClass( $( event.currentTarget ), null, "ui-state-hover" );
655			}
656		} );
657	},
658
659	_focusable: function( element ) {
660		this.focusable = this.focusable.add( element );
661		this._on( element, {
662			focusin: function( event ) {
663				this._addClass( $( event.currentTarget ), null, "ui-state-focus" );
664			},
665			focusout: function( event ) {
666				this._removeClass( $( event.currentTarget ), null, "ui-state-focus" );
667			}
668		} );
669	},
670
671	_trigger: function( type, event, data ) {
672		var prop, orig;
673		var callback = this.options[ type ];
674
675		data = data || {};
676		event = $.Event( event );
677		event.type = ( type === this.widgetEventPrefix ?
678			type :
679			this.widgetEventPrefix + type ).toLowerCase();
680
681		// The original event may come from any element
682		// so we need to reset the target on the new event
683		event.target = this.element[ 0 ];
684
685		// Copy original event properties over to the new event
686		orig = event.originalEvent;
687		if ( orig ) {
688			for ( prop in orig ) {
689				if ( !( prop in event ) ) {
690					event[ prop ] = orig[ prop ];
691				}
692			}
693		}
694
695		this.element.trigger( event, data );
696		return !( $.isFunction( callback ) &&
697			callback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false ||
698			event.isDefaultPrevented() );
699	}
700};
701
702$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
703	$.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
704		if ( typeof options === "string" ) {
705			options = { effect: options };
706		}
707
708		var hasOptions;
709		var effectName = !options ?
710			method :
711			options === true || typeof options === "number" ?
712				defaultEffect :
713				options.effect || defaultEffect;
714
715		options = options || {};
716		if ( typeof options === "number" ) {
717			options = { duration: options };
718		}
719
720		hasOptions = !$.isEmptyObject( options );
721		options.complete = callback;
722
723		if ( options.delay ) {
724			element.delay( options.delay );
725		}
726
727		if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
728			element[ method ]( options );
729		} else if ( effectName !== method && element[ effectName ] ) {
730			element[ effectName ]( options.duration, options.easing, callback );
731		} else {
732			element.queue( function( next ) {
733				$( this )[ method ]();
734				if ( callback ) {
735					callback.call( element[ 0 ] );
736				}
737				next();
738			} );
739		}
740	};
741} );
742
743var widget = $.widget;
744
745
746/*!
747 * jQuery UI Position 1.12.1
748 * http://jqueryui.com
749 *
750 * Copyright jQuery Foundation and other contributors
751 * Released under the MIT license.
752 * http://jquery.org/license
753 *
754 * http://api.jqueryui.com/position/
755 */
756
757//>>label: Position
758//>>group: Core
759//>>description: Positions elements relative to other elements.
760//>>docs: http://api.jqueryui.com/position/
761//>>demos: http://jqueryui.com/position/
762
763
764( function() {
765var cachedScrollbarWidth,
766	max = Math.max,
767	abs = Math.abs,
768	rhorizontal = /left|center|right/,
769	rvertical = /top|center|bottom/,
770	roffset = /[\+\-]\d+(\.[\d]+)?%?/,
771	rposition = /^\w+/,
772	rpercent = /%$/,
773	_position = $.fn.position;
774
775function getOffsets( offsets, width, height ) {
776	return [
777		parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
778		parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
779	];
780}
781
782function parseCss( element, property ) {
783	return parseInt( $.css( element, property ), 10 ) || 0;
784}
785
786function getDimensions( elem ) {
787	var raw = elem[ 0 ];
788	if ( raw.nodeType === 9 ) {
789		return {
790			width: elem.width(),
791			height: elem.height(),
792			offset: { top: 0, left: 0 }
793		};
794	}
795	if ( $.isWindow( raw ) ) {
796		return {
797			width: elem.width(),
798			height: elem.height(),
799			offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
800		};
801	}
802	if ( raw.preventDefault ) {
803		return {
804			width: 0,
805			height: 0,
806			offset: { top: raw.pageY, left: raw.pageX }
807		};
808	}
809	return {
810		width: elem.outerWidth(),
811		height: elem.outerHeight(),
812		offset: elem.offset()
813	};
814}
815
816$.position = {
817	scrollbarWidth: function() {
818		if ( cachedScrollbarWidth !== undefined ) {
819			return cachedScrollbarWidth;
820		}
821		var w1, w2,
822			div = $( "<div " +
823				"style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'>" +
824				"<div style='height:100px;width:auto;'></div></div>" ),
825			innerDiv = div.children()[ 0 ];
826
827		$( "body" ).append( div );
828		w1 = innerDiv.offsetWidth;
829		div.css( "overflow", "scroll" );
830
831		w2 = innerDiv.offsetWidth;
832
833		if ( w1 === w2 ) {
834			w2 = div[ 0 ].clientWidth;
835		}
836
837		div.remove();
838
839		return ( cachedScrollbarWidth = w1 - w2 );
840	},
841	getScrollInfo: function( within ) {
842		var overflowX = within.isWindow || within.isDocument ? "" :
843				within.element.css( "overflow-x" ),
844			overflowY = within.isWindow || within.isDocument ? "" :
845				within.element.css( "overflow-y" ),
846			hasOverflowX = overflowX === "scroll" ||
847				( overflowX === "auto" && within.width < within.element[ 0 ].scrollWidth ),
848			hasOverflowY = overflowY === "scroll" ||
849				( overflowY === "auto" && within.height < within.element[ 0 ].scrollHeight );
850		return {
851			width: hasOverflowY ? $.position.scrollbarWidth() : 0,
852			height: hasOverflowX ? $.position.scrollbarWidth() : 0
853		};
854	},
855	getWithinInfo: function( element ) {
856		var withinElement = $( element || window ),
857			isWindow = $.isWindow( withinElement[ 0 ] ),
858			isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9,
859			hasOffset = !isWindow && !isDocument;
860		return {
861			element: withinElement,
862			isWindow: isWindow,
863			isDocument: isDocument,
864			offset: hasOffset ? $( element ).offset() : { left: 0, top: 0 },
865			scrollLeft: withinElement.scrollLeft(),
866			scrollTop: withinElement.scrollTop(),
867			width: withinElement.outerWidth(),
868			height: withinElement.outerHeight()
869		};
870	}
871};
872
873$.fn.position = function( options ) {
874	if ( !options || !options.of ) {
875		return _position.apply( this, arguments );
876	}
877
878	// Make a copy, we don't want to modify arguments
879	options = $.extend( {}, options );
880
881	var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
882		target = $( options.of ),
883		within = $.position.getWithinInfo( options.within ),
884		scrollInfo = $.position.getScrollInfo( within ),
885		collision = ( options.collision || "flip" ).split( " " ),
886		offsets = {};
887
888	dimensions = getDimensions( target );
889	if ( target[ 0 ].preventDefault ) {
890
891		// Force left top to allow flipping
892		options.at = "left top";
893	}
894	targetWidth = dimensions.width;
895	targetHeight = dimensions.height;
896	targetOffset = dimensions.offset;
897
898	// Clone to reuse original targetOffset later
899	basePosition = $.extend( {}, targetOffset );
900
901	// Force my and at to have valid horizontal and vertical positions
902	// if a value is missing or invalid, it will be converted to center
903	$.each( [ "my", "at" ], function() {
904		var pos = ( options[ this ] || "" ).split( " " ),
905			horizontalOffset,
906			verticalOffset;
907
908		if ( pos.length === 1 ) {
909			pos = rhorizontal.test( pos[ 0 ] ) ?
910				pos.concat( [ "center" ] ) :
911				rvertical.test( pos[ 0 ] ) ?
912					[ "center" ].concat( pos ) :
913					[ "center", "center" ];
914		}
915		pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
916		pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
917
918		// Calculate offsets
919		horizontalOffset = roffset.exec( pos[ 0 ] );
920		verticalOffset = roffset.exec( pos[ 1 ] );
921		offsets[ this ] = [
922			horizontalOffset ? horizontalOffset[ 0 ] : 0,
923			verticalOffset ? verticalOffset[ 0 ] : 0
924		];
925
926		// Reduce to just the positions without the offsets
927		options[ this ] = [
928			rposition.exec( pos[ 0 ] )[ 0 ],
929			rposition.exec( pos[ 1 ] )[ 0 ]
930		];
931	} );
932
933	// Normalize collision option
934	if ( collision.length === 1 ) {
935		collision[ 1 ] = collision[ 0 ];
936	}
937
938	if ( options.at[ 0 ] === "right" ) {
939		basePosition.left += targetWidth;
940	} else if ( options.at[ 0 ] === "center" ) {
941		basePosition.left += targetWidth / 2;
942	}
943
944	if ( options.at[ 1 ] === "bottom" ) {
945		basePosition.top += targetHeight;
946	} else if ( options.at[ 1 ] === "center" ) {
947		basePosition.top += targetHeight / 2;
948	}
949
950	atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
951	basePosition.left += atOffset[ 0 ];
952	basePosition.top += atOffset[ 1 ];
953
954	return this.each( function() {
955		var collisionPosition, using,
956			elem = $( this ),
957			elemWidth = elem.outerWidth(),
958			elemHeight = elem.outerHeight(),
959			marginLeft = parseCss( this, "marginLeft" ),
960			marginTop = parseCss( this, "marginTop" ),
961			collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) +
962				scrollInfo.width,
963			collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) +
964				scrollInfo.height,
965			position = $.extend( {}, basePosition ),
966			myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
967
968		if ( options.my[ 0 ] === "right" ) {
969			position.left -= elemWidth;
970		} else if ( options.my[ 0 ] === "center" ) {
971			position.left -= elemWidth / 2;
972		}
973
974		if ( options.my[ 1 ] === "bottom" ) {
975			position.top -= elemHeight;
976		} else if ( options.my[ 1 ] === "center" ) {
977			position.top -= elemHeight / 2;
978		}
979
980		position.left += myOffset[ 0 ];
981		position.top += myOffset[ 1 ];
982
983		collisionPosition = {
984			marginLeft: marginLeft,
985			marginTop: marginTop
986		};
987
988		$.each( [ "left", "top" ], function( i, dir ) {
989			if ( $.ui.position[ collision[ i ] ] ) {
990				$.ui.position[ collision[ i ] ][ dir ]( position, {
991					targetWidth: targetWidth,
992					targetHeight: targetHeight,
993					elemWidth: elemWidth,
994					elemHeight: elemHeight,
995					collisionPosition: collisionPosition,
996					collisionWidth: collisionWidth,
997					collisionHeight: collisionHeight,
998					offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
999					my: options.my,
1000					at: options.at,
1001					within: within,
1002					elem: elem
1003				} );
1004			}
1005		} );
1006
1007		if ( options.using ) {
1008
1009			// Adds feedback as second argument to using callback, if present
1010			using = function( props ) {
1011				var left = targetOffset.left - position.left,
1012					right = left + targetWidth - elemWidth,
1013					top = targetOffset.top - position.top,
1014					bottom = top + targetHeight - elemHeight,
1015					feedback = {
1016						target: {
1017							element: target,
1018							left: targetOffset.left,
1019							top: targetOffset.top,
1020							width: targetWidth,
1021							height: targetHeight
1022						},
1023						element: {
1024							element: elem,
1025							left: position.left,
1026							top: position.top,
1027							width: elemWidth,
1028							height: elemHeight
1029						},
1030						horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
1031						vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
1032					};
1033				if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
1034					feedback.horizontal = "center";
1035				}
1036				if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
1037					feedback.vertical = "middle";
1038				}
1039				if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
1040					feedback.important = "horizontal";
1041				} else {
1042					feedback.important = "vertical";
1043				}
1044				options.using.call( this, props, feedback );
1045			};
1046		}
1047
1048		elem.offset( $.extend( position, { using: using } ) );
1049	} );
1050};
1051
1052$.ui.position = {
1053	fit: {
1054		left: function( position, data ) {
1055			var within = data.within,
1056				withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
1057				outerWidth = within.width,
1058				collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1059				overLeft = withinOffset - collisionPosLeft,
1060				overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
1061				newOverRight;
1062
1063			// Element is wider than within
1064			if ( data.collisionWidth > outerWidth ) {
1065
1066				// Element is initially over the left side of within
1067				if ( overLeft > 0 && overRight <= 0 ) {
1068					newOverRight = position.left + overLeft + data.collisionWidth - outerWidth -
1069						withinOffset;
1070					position.left += overLeft - newOverRight;
1071
1072				// Element is initially over right side of within
1073				} else if ( overRight > 0 && overLeft <= 0 ) {
1074					position.left = withinOffset;
1075
1076				// Element is initially over both left and right sides of within
1077				} else {
1078					if ( overLeft > overRight ) {
1079						position.left = withinOffset + outerWidth - data.collisionWidth;
1080					} else {
1081						position.left = withinOffset;
1082					}
1083				}
1084
1085			// Too far left -> align with left edge
1086			} else if ( overLeft > 0 ) {
1087				position.left += overLeft;
1088
1089			// Too far right -> align with right edge
1090			} else if ( overRight > 0 ) {
1091				position.left -= overRight;
1092
1093			// Adjust based on position and margin
1094			} else {
1095				position.left = max( position.left - collisionPosLeft, position.left );
1096			}
1097		},
1098		top: function( position, data ) {
1099			var within = data.within,
1100				withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
1101				outerHeight = data.within.height,
1102				collisionPosTop = position.top - data.collisionPosition.marginTop,
1103				overTop = withinOffset - collisionPosTop,
1104				overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
1105				newOverBottom;
1106
1107			// Element is taller than within
1108			if ( data.collisionHeight > outerHeight ) {
1109
1110				// Element is initially over the top of within
1111				if ( overTop > 0 && overBottom <= 0 ) {
1112					newOverBottom = position.top + overTop + data.collisionHeight - outerHeight -
1113						withinOffset;
1114					position.top += overTop - newOverBottom;
1115
1116				// Element is initially over bottom of within
1117				} else if ( overBottom > 0 && overTop <= 0 ) {
1118					position.top = withinOffset;
1119
1120				// Element is initially over both top and bottom of within
1121				} else {
1122					if ( overTop > overBottom ) {
1123						position.top = withinOffset + outerHeight - data.collisionHeight;
1124					} else {
1125						position.top = withinOffset;
1126					}
1127				}
1128
1129			// Too far up -> align with top
1130			} else if ( overTop > 0 ) {
1131				position.top += overTop;
1132
1133			// Too far down -> align with bottom edge
1134			} else if ( overBottom > 0 ) {
1135				position.top -= overBottom;
1136
1137			// Adjust based on position and margin
1138			} else {
1139				position.top = max( position.top - collisionPosTop, position.top );
1140			}
1141		}
1142	},
1143	flip: {
1144		left: function( position, data ) {
1145			var within = data.within,
1146				withinOffset = within.offset.left + within.scrollLeft,
1147				outerWidth = within.width,
1148				offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
1149				collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1150				overLeft = collisionPosLeft - offsetLeft,
1151				overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
1152				myOffset = data.my[ 0 ] === "left" ?
1153					-data.elemWidth :
1154					data.my[ 0 ] === "right" ?
1155						data.elemWidth :
1156						0,
1157				atOffset = data.at[ 0 ] === "left" ?
1158					data.targetWidth :
1159					data.at[ 0 ] === "right" ?
1160						-data.targetWidth :
1161						0,
1162				offset = -2 * data.offset[ 0 ],
1163				newOverRight,
1164				newOverLeft;
1165
1166			if ( overLeft < 0 ) {
1167				newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth -
1168					outerWidth - withinOffset;
1169				if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
1170					position.left += myOffset + atOffset + offset;
1171				}
1172			} else if ( overRight > 0 ) {
1173				newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset +
1174					atOffset + offset - offsetLeft;
1175				if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
1176					position.left += myOffset + atOffset + offset;
1177				}
1178			}
1179		},
1180		top: function( position, data ) {
1181			var within = data.within,
1182				withinOffset = within.offset.top + within.scrollTop,
1183				outerHeight = within.height,
1184				offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
1185				collisionPosTop = position.top - data.collisionPosition.marginTop,
1186				overTop = collisionPosTop - offsetTop,
1187				overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
1188				top = data.my[ 1 ] === "top",
1189				myOffset = top ?
1190					-data.elemHeight :
1191					data.my[ 1 ] === "bottom" ?
1192						data.elemHeight :
1193						0,
1194				atOffset = data.at[ 1 ] === "top" ?
1195					data.targetHeight :
1196					data.at[ 1 ] === "bottom" ?
1197						-data.targetHeight :
1198						0,
1199				offset = -2 * data.offset[ 1 ],
1200				newOverTop,
1201				newOverBottom;
1202			if ( overTop < 0 ) {
1203				newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight -
1204					outerHeight - withinOffset;
1205				if ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) {
1206					position.top += myOffset + atOffset + offset;
1207				}
1208			} else if ( overBottom > 0 ) {
1209				newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset +
1210					offset - offsetTop;
1211				if ( newOverTop > 0 || abs( newOverTop ) < overBottom ) {
1212					position.top += myOffset + atOffset + offset;
1213				}
1214			}
1215		}
1216	},
1217	flipfit: {
1218		left: function() {
1219			$.ui.position.flip.left.apply( this, arguments );
1220			$.ui.position.fit.left.apply( this, arguments );
1221		},
1222		top: function() {
1223			$.ui.position.flip.top.apply( this, arguments );
1224			$.ui.position.fit.top.apply( this, arguments );
1225		}
1226	}
1227};
1228
1229} )();
1230
1231var position = $.ui.position;
1232
1233
1234/*!
1235 * jQuery UI :data 1.12.1
1236 * http://jqueryui.com
1237 *
1238 * Copyright jQuery Foundation and other contributors
1239 * Released under the MIT license.
1240 * http://jquery.org/license
1241 */
1242
1243//>>label: :data Selector
1244//>>group: Core
1245//>>description: Selects elements which have data stored under the specified key.
1246//>>docs: http://api.jqueryui.com/data-selector/
1247
1248
1249var data = $.extend( $.expr[ ":" ], {
1250	data: $.expr.createPseudo ?
1251		$.expr.createPseudo( function( dataName ) {
1252			return function( elem ) {
1253				return !!$.data( elem, dataName );
1254			};
1255		} ) :
1256
1257		// Support: jQuery <1.8
1258		function( elem, i, match ) {
1259			return !!$.data( elem, match[ 3 ] );
1260		}
1261} );
1262
1263/*!
1264 * jQuery UI Disable Selection 1.12.1
1265 * http://jqueryui.com
1266 *
1267 * Copyright jQuery Foundation and other contributors
1268 * Released under the MIT license.
1269 * http://jquery.org/license
1270 */
1271
1272//>>label: disableSelection
1273//>>group: Core
1274//>>description: Disable selection of text content within the set of matched elements.
1275//>>docs: http://api.jqueryui.com/disableSelection/
1276
1277// This file is deprecated
1278
1279
1280var disableSelection = $.fn.extend( {
1281	disableSelection: ( function() {
1282		var eventType = "onselectstart" in document.createElement( "div" ) ?
1283			"selectstart" :
1284			"mousedown";
1285
1286		return function() {
1287			return this.on( eventType + ".ui-disableSelection", function( event ) {
1288				event.preventDefault();
1289			} );
1290		};
1291	} )(),
1292
1293	enableSelection: function() {
1294		return this.off( ".ui-disableSelection" );
1295	}
1296} );
1297
1298
1299/*!
1300 * jQuery UI Effects 1.12.1
1301 * http://jqueryui.com
1302 *
1303 * Copyright jQuery Foundation and other contributors
1304 * Released under the MIT license.
1305 * http://jquery.org/license
1306 */
1307
1308//>>label: Effects Core
1309//>>group: Effects
1310// jscs:disable maximumLineLength
1311//>>description: Extends the internal jQuery effects. Includes morphing and easing. Required by all other effects.
1312// jscs:enable maximumLineLength
1313//>>docs: http://api.jqueryui.com/category/effects-core/
1314//>>demos: http://jqueryui.com/effect/
1315
1316
1317
1318var dataSpace = "ui-effects-",
1319	dataSpaceStyle = "ui-effects-style",
1320	dataSpaceAnimated = "ui-effects-animated",
1321
1322	// Create a local jQuery because jQuery Color relies on it and the
1323	// global may not exist with AMD and a custom build (#10199)
1324	jQuery = $;
1325
1326$.effects = {
1327	effect: {}
1328};
1329
1330/*!
1331 * jQuery Color Animations v2.1.2
1332 * https://github.com/jquery/jquery-color
1333 *
1334 * Copyright 2014 jQuery Foundation and other contributors
1335 * Released under the MIT license.
1336 * http://jquery.org/license
1337 *
1338 * Date: Wed Jan 16 08:47:09 2013 -0600
1339 */
1340( function( jQuery, undefined ) {
1341
1342	var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor " +
1343		"borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",
1344
1345	// Plusequals test for += 100 -= 100
1346	rplusequals = /^([\-+])=\s*(\d+\.?\d*)/,
1347
1348	// A set of RE's that can match strings and generate color tuples.
1349	stringParsers = [ {
1350			re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
1351			parse: function( execResult ) {
1352				return [
1353					execResult[ 1 ],
1354					execResult[ 2 ],
1355					execResult[ 3 ],
1356					execResult[ 4 ]
1357				];
1358			}
1359		}, {
1360			re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
1361			parse: function( execResult ) {
1362				return [
1363					execResult[ 1 ] * 2.55,
1364					execResult[ 2 ] * 2.55,
1365					execResult[ 3 ] * 2.55,
1366					execResult[ 4 ]
1367				];
1368			}
1369		}, {
1370
1371			// This regex ignores A-F because it's compared against an already lowercased string
1372			re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,
1373			parse: function( execResult ) {
1374				return [
1375					parseInt( execResult[ 1 ], 16 ),
1376					parseInt( execResult[ 2 ], 16 ),
1377					parseInt( execResult[ 3 ], 16 )
1378				];
1379			}
1380		}, {
1381
1382			// This regex ignores A-F because it's compared against an already lowercased string
1383			re: /#([a-f0-9])([a-f0-9])([a-f0-9])/,
1384			parse: function( execResult ) {
1385				return [
1386					parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),
1387					parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),
1388					parseInt( execResult[ 3 ] + execResult[ 3 ], 16 )
1389				];
1390			}
1391		}, {
1392			re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
1393			space: "hsla",
1394			parse: function( execResult ) {
1395				return [
1396					execResult[ 1 ],
1397					execResult[ 2 ] / 100,
1398					execResult[ 3 ] / 100,
1399					execResult[ 4 ]
1400				];
1401			}
1402		} ],
1403
1404	// JQuery.Color( )
1405	color = jQuery.Color = function( color, green, blue, alpha ) {
1406		return new jQuery.Color.fn.parse( color, green, blue, alpha );
1407	},
1408	spaces = {
1409		rgba: {
1410			props: {
1411				red: {
1412					idx: 0,
1413					type: "byte"
1414				},
1415				green: {
1416					idx: 1,
1417					type: "byte"
1418				},
1419				blue: {
1420					idx: 2,
1421					type: "byte"
1422				}
1423			}
1424		},
1425
1426		hsla: {
1427			props: {
1428				hue: {
1429					idx: 0,
1430					type: "degrees"
1431				},
1432				saturation: {
1433					idx: 1,
1434					type: "percent"
1435				},
1436				lightness: {
1437					idx: 2,
1438					type: "percent"
1439				}
1440			}
1441		}
1442	},
1443	propTypes = {
1444		"byte": {
1445			floor: true,
1446			max: 255
1447		},
1448		"percent": {
1449			max: 1
1450		},
1451		"degrees": {
1452			mod: 360,
1453			floor: true
1454		}
1455	},
1456	support = color.support = {},
1457
1458	// Element for support tests
1459	supportElem = jQuery( "<p>" )[ 0 ],
1460
1461	// Colors = jQuery.Color.names
1462	colors,
1463
1464	// Local aliases of functions called often
1465	each = jQuery.each;
1466
1467// Determine rgba support immediately
1468supportElem.style.cssText = "background-color:rgba(1,1,1,.5)";
1469support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1;
1470
1471// Define cache name and alpha properties
1472// for rgba and hsla spaces
1473each( spaces, function( spaceName, space ) {
1474	space.cache = "_" + spaceName;
1475	space.props.alpha = {
1476		idx: 3,
1477		type: "percent",
1478		def: 1
1479	};
1480} );
1481
1482function clamp( value, prop, allowEmpty ) {
1483	var type = propTypes[ prop.type ] || {};
1484
1485	if ( value == null ) {
1486		return ( allowEmpty || !prop.def ) ? null : prop.def;
1487	}
1488
1489	// ~~ is an short way of doing floor for positive numbers
1490	value = type.floor ? ~~value : parseFloat( value );
1491
1492	// IE will pass in empty strings as value for alpha,
1493	// which will hit this case
1494	if ( isNaN( value ) ) {
1495		return prop.def;
1496	}
1497
1498	if ( type.mod ) {
1499
1500		// We add mod before modding to make sure that negatives values
1501		// get converted properly: -10 -> 350
1502		return ( value + type.mod ) % type.mod;
1503	}
1504
1505	// For now all property types without mod have min and max
1506	return 0 > value ? 0 : type.max < value ? type.max : value;
1507}
1508
1509function stringParse( string ) {
1510	var inst = color(),
1511		rgba = inst._rgba = [];
1512
1513	string = string.toLowerCase();
1514
1515	each( stringParsers, function( i, parser ) {
1516		var parsed,
1517			match = parser.re.exec( string ),
1518			values = match && parser.parse( match ),
1519			spaceName = parser.space || "rgba";
1520
1521		if ( values ) {
1522			parsed = inst[ spaceName ]( values );
1523
1524			// If this was an rgba parse the assignment might happen twice
1525			// oh well....
1526			inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ];
1527			rgba = inst._rgba = parsed._rgba;
1528
1529			// Exit each( stringParsers ) here because we matched
1530			return false;
1531		}
1532	} );
1533
1534	// Found a stringParser that handled it
1535	if ( rgba.length ) {
1536
1537		// If this came from a parsed string, force "transparent" when alpha is 0
1538		// chrome, (and maybe others) return "transparent" as rgba(0,0,0,0)
1539		if ( rgba.join() === "0,0,0,0" ) {
1540			jQuery.extend( rgba, colors.transparent );
1541		}
1542		return inst;
1543	}
1544
1545	// Named colors
1546	return colors[ string ];
1547}
1548
1549color.fn = jQuery.extend( color.prototype, {
1550	parse: function( red, green, blue, alpha ) {
1551		if ( red === undefined ) {
1552			this._rgba = [ null, null, null, null ];
1553			return this;
1554		}
1555		if ( red.jquery || red.nodeType ) {
1556			red = jQuery( red ).css( green );
1557			green = undefined;
1558		}
1559
1560		var inst = this,
1561			type = jQuery.type( red ),
1562			rgba = this._rgba = [];
1563
1564		// More than 1 argument specified - assume ( red, green, blue, alpha )
1565		if ( green !== undefined ) {
1566			red = [ red, green, blue, alpha ];
1567			type = "array";
1568		}
1569
1570		if ( type === "string" ) {
1571			return this.parse( stringParse( red ) || colors._default );
1572		}
1573
1574		if ( type === "array" ) {
1575			each( spaces.rgba.props, function( key, prop ) {
1576				rgba[ prop.idx ] = clamp( red[ prop.idx ], prop );
1577			} );
1578			return this;
1579		}
1580
1581		if ( type === "object" ) {
1582			if ( red instanceof color ) {
1583				each( spaces, function( spaceName, space ) {
1584					if ( red[ space.cache ] ) {
1585						inst[ space.cache ] = red[ space.cache ].slice();
1586					}
1587				} );
1588			} else {
1589				each( spaces, function( spaceName, space ) {
1590					var cache = space.cache;
1591					each( space.props, function( key, prop ) {
1592
1593						// If the cache doesn't exist, and we know how to convert
1594						if ( !inst[ cache ] && space.to ) {
1595
1596							// If the value was null, we don't need to copy it
1597							// if the key was alpha, we don't need to copy it either
1598							if ( key === "alpha" || red[ key ] == null ) {
1599								return;
1600							}
1601							inst[ cache ] = space.to( inst._rgba );
1602						}
1603
1604						// This is the only case where we allow nulls for ALL properties.
1605						// call clamp with alwaysAllowEmpty
1606						inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true );
1607					} );
1608
1609					// Everything defined but alpha?
1610					if ( inst[ cache ] &&
1611							jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) {
1612
1613						// Use the default of 1
1614						inst[ cache ][ 3 ] = 1;
1615						if ( space.from ) {
1616							inst._rgba = space.from( inst[ cache ] );
1617						}
1618					}
1619				} );
1620			}
1621			return this;
1622		}
1623	},
1624	is: function( compare ) {
1625		var is = color( compare ),
1626			same = true,
1627			inst = this;
1628
1629		each( spaces, function( _, space ) {
1630			var localCache,
1631				isCache = is[ space.cache ];
1632			if ( isCache ) {
1633				localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || [];
1634				each( space.props, function( _, prop ) {
1635					if ( isCache[ prop.idx ] != null ) {
1636						same = ( isCache[ prop.idx ] === localCache[ prop.idx ] );
1637						return same;
1638					}
1639				} );
1640			}
1641			return same;
1642		} );
1643		return same;
1644	},
1645	_space: function() {
1646		var used = [],
1647			inst = this;
1648		each( spaces, function( spaceName, space ) {
1649			if ( inst[ space.cache ] ) {
1650				used.push( spaceName );
1651			}
1652		} );
1653		return used.pop();
1654	},
1655	transition: function( other, distance ) {
1656		var end = color( other ),
1657			spaceName = end._space(),
1658			space = spaces[ spaceName ],
1659			startColor = this.alpha() === 0 ? color( "transparent" ) : this,
1660			start = startColor[ space.cache ] || space.to( startColor._rgba ),
1661			result = start.slice();
1662
1663		end = end[ space.cache ];
1664		each( space.props, function( key, prop ) {
1665			var index = prop.idx,
1666				startValue = start[ index ],
1667				endValue = end[ index ],
1668				type = propTypes[ prop.type ] || {};
1669
1670			// If null, don't override start value
1671			if ( endValue === null ) {
1672				return;
1673			}
1674
1675			// If null - use end
1676			if ( startValue === null ) {
1677				result[ index ] = endValue;
1678			} else {
1679				if ( type.mod ) {
1680					if ( endValue - startValue > type.mod / 2 ) {
1681						startValue += type.mod;
1682					} else if ( startValue - endValue > type.mod / 2 ) {
1683						startValue -= type.mod;
1684					}
1685				}
1686				result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop );
1687			}
1688		} );
1689		return this[ spaceName ]( result );
1690	},
1691	blend: function( opaque ) {
1692
1693		// If we are already opaque - return ourself
1694		if ( this._rgba[ 3 ] === 1 ) {
1695			return this;
1696		}
1697
1698		var rgb = this._rgba.slice(),
1699			a = rgb.pop(),
1700			blend = color( opaque )._rgba;
1701
1702		return color( jQuery.map( rgb, function( v, i ) {
1703			return ( 1 - a ) * blend[ i ] + a * v;
1704		} ) );
1705	},
1706	toRgbaString: function() {
1707		var prefix = "rgba(",
1708			rgba = jQuery.map( this._rgba, function( v, i ) {
1709				return v == null ? ( i > 2 ? 1 : 0 ) : v;
1710			} );
1711
1712		if ( rgba[ 3 ] === 1 ) {
1713			rgba.pop();
1714			prefix = "rgb(";
1715		}
1716
1717		return prefix + rgba.join() + ")";
1718	},
1719	toHslaString: function() {
1720		var prefix = "hsla(",
1721			hsla = jQuery.map( this.hsla(), function( v, i ) {
1722				if ( v == null ) {
1723					v = i > 2 ? 1 : 0;
1724				}
1725
1726				// Catch 1 and 2
1727				if ( i && i < 3 ) {
1728					v = Math.round( v * 100 ) + "%";
1729				}
1730				return v;
1731			} );
1732
1733		if ( hsla[ 3 ] === 1 ) {
1734			hsla.pop();
1735			prefix = "hsl(";
1736		}
1737		return prefix + hsla.join() + ")";
1738	},
1739	toHexString: function( includeAlpha ) {
1740		var rgba = this._rgba.slice(),
1741			alpha = rgba.pop();
1742
1743		if ( includeAlpha ) {
1744			rgba.push( ~~( alpha * 255 ) );
1745		}
1746
1747		return "#" + jQuery.map( rgba, function( v ) {
1748
1749			// Default to 0 when nulls exist
1750			v = ( v || 0 ).toString( 16 );
1751			return v.length === 1 ? "0" + v : v;
1752		} ).join( "" );
1753	},
1754	toString: function() {
1755		return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString();
1756	}
1757} );
1758color.fn.parse.prototype = color.fn;
1759
1760// Hsla conversions adapted from:
1761// https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021
1762
1763function hue2rgb( p, q, h ) {
1764	h = ( h + 1 ) % 1;
1765	if ( h * 6 < 1 ) {
1766		return p + ( q - p ) * h * 6;
1767	}
1768	if ( h * 2 < 1 ) {
1769		return q;
1770	}
1771	if ( h * 3 < 2 ) {
1772		return p + ( q - p ) * ( ( 2 / 3 ) - h ) * 6;
1773	}
1774	return p;
1775}
1776
1777spaces.hsla.to = function( rgba ) {
1778	if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) {
1779		return [ null, null, null, rgba[ 3 ] ];
1780	}
1781	var r = rgba[ 0 ] / 255,
1782		g = rgba[ 1 ] / 255,
1783		b = rgba[ 2 ] / 255,
1784		a = rgba[ 3 ],
1785		max = Math.max( r, g, b ),
1786		min = Math.min( r, g, b ),
1787		diff = max - min,
1788		add = max + min,
1789		l = add * 0.5,
1790		h, s;
1791
1792	if ( min === max ) {
1793		h = 0;
1794	} else if ( r === max ) {
1795		h = ( 60 * ( g - b ) / diff ) + 360;
1796	} else if ( g === max ) {
1797		h = ( 60 * ( b - r ) / diff ) + 120;
1798	} else {
1799		h = ( 60 * ( r - g ) / diff ) + 240;
1800	}
1801
1802	// Chroma (diff) == 0 means greyscale which, by definition, saturation = 0%
1803	// otherwise, saturation is based on the ratio of chroma (diff) to lightness (add)
1804	if ( diff === 0 ) {
1805		s = 0;
1806	} else if ( l <= 0.5 ) {
1807		s = diff / add;
1808	} else {
1809		s = diff / ( 2 - add );
1810	}
1811	return [ Math.round( h ) % 360, s, l, a == null ? 1 : a ];
1812};
1813
1814spaces.hsla.from = function( hsla ) {
1815	if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) {
1816		return [ null, null, null, hsla[ 3 ] ];
1817	}
1818	var h = hsla[ 0 ] / 360,
1819		s = hsla[ 1 ],
1820		l = hsla[ 2 ],
1821		a = hsla[ 3 ],
1822		q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s,
1823		p = 2 * l - q;
1824
1825	return [
1826		Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ),
1827		Math.round( hue2rgb( p, q, h ) * 255 ),
1828		Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ),
1829		a
1830	];
1831};
1832
1833each( spaces, function( spaceName, space ) {
1834	var props = space.props,
1835		cache = space.cache,
1836		to = space.to,
1837		from = space.from;
1838
1839	// Makes rgba() and hsla()
1840	color.fn[ spaceName ] = function( value ) {
1841
1842		// Generate a cache for this space if it doesn't exist
1843		if ( to && !this[ cache ] ) {
1844			this[ cache ] = to( this._rgba );
1845		}
1846		if ( value === undefined ) {
1847			return this[ cache ].slice();
1848		}
1849
1850		var ret,
1851			type = jQuery.type( value ),
1852			arr = ( type === "array" || type === "object" ) ? value : arguments,
1853			local = this[ cache ].slice();
1854
1855		each( props, function( key, prop ) {
1856			var val = arr[ type === "object" ? key : prop.idx ];
1857			if ( val == null ) {
1858				val = local[ prop.idx ];
1859			}
1860			local[ prop.idx ] = clamp( val, prop );
1861		} );
1862
1863		if ( from ) {
1864			ret = color( from( local ) );
1865			ret[ cache ] = local;
1866			return ret;
1867		} else {
1868			return color( local );
1869		}
1870	};
1871
1872	// Makes red() green() blue() alpha() hue() saturation() lightness()
1873	each( props, function( key, prop ) {
1874
1875		// Alpha is included in more than one space
1876		if ( color.fn[ key ] ) {
1877			return;
1878		}
1879		color.fn[ key ] = function( value ) {
1880			var vtype = jQuery.type( value ),
1881				fn = ( key === "alpha" ? ( this._hsla ? "hsla" : "rgba" ) : spaceName ),
1882				local = this[ fn ](),
1883				cur = local[ prop.idx ],
1884				match;
1885
1886			if ( vtype === "undefined" ) {
1887				return cur;
1888			}
1889
1890			if ( vtype === "function" ) {
1891				value = value.call( this, cur );
1892				vtype = jQuery.type( value );
1893			}
1894			if ( value == null && prop.empty ) {
1895				return this;
1896			}
1897			if ( vtype === "string" ) {
1898				match = rplusequals.exec( value );
1899				if ( match ) {
1900					value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 );
1901				}
1902			}
1903			local[ prop.idx ] = value;
1904			return this[ fn ]( local );
1905		};
1906	} );
1907} );
1908
1909// Add cssHook and .fx.step function for each named hook.
1910// accept a space separated string of properties
1911color.hook = function( hook ) {
1912	var hooks = hook.split( " " );
1913	each( hooks, function( i, hook ) {
1914		jQuery.cssHooks[ hook ] = {
1915			set: function( elem, value ) {
1916				var parsed, curElem,
1917					backgroundColor = "";
1918
1919				if ( value !== "transparent" && ( jQuery.type( value ) !== "string" ||
1920						( parsed = stringParse( value ) ) ) ) {
1921					value = color( parsed || value );
1922					if ( !support.rgba && value._rgba[ 3 ] !== 1 ) {
1923						curElem = hook === "backgroundColor" ? elem.parentNode : elem;
1924						while (
1925							( backgroundColor === "" || backgroundColor === "transparent" ) &&
1926							curElem && curElem.style
1927						) {
1928							try {
1929								backgroundColor = jQuery.css( curElem, "backgroundColor" );
1930								curElem = curElem.parentNode;
1931							} catch ( e ) {
1932							}
1933						}
1934
1935						value = value.blend( backgroundColor && backgroundColor !== "transparent" ?
1936							backgroundColor :
1937							"_default" );
1938					}
1939
1940					value = value.toRgbaString();
1941				}
1942				try {
1943					elem.style[ hook ] = value;
1944				} catch ( e ) {
1945
1946					// Wrapped to prevent IE from throwing errors on "invalid" values like
1947					// 'auto' or 'inherit'
1948				}
1949			}
1950		};
1951		jQuery.fx.step[ hook ] = function( fx ) {
1952			if ( !fx.colorInit ) {
1953				fx.start = color( fx.elem, hook );
1954				fx.end = color( fx.end );
1955				fx.colorInit = true;
1956			}
1957			jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) );
1958		};
1959	} );
1960
1961};
1962
1963color.hook( stepHooks );
1964
1965jQuery.cssHooks.borderColor = {
1966	expand: function( value ) {
1967		var expanded = {};
1968
1969		each( [ "Top", "Right", "Bottom", "Left" ], function( i, part ) {
1970			expanded[ "border" + part + "Color" ] = value;
1971		} );
1972		return expanded;
1973	}
1974};
1975
1976// Basic color names only.
1977// Usage of any of the other color names requires adding yourself or including
1978// jquery.color.svg-names.js.
1979colors = jQuery.Color.names = {
1980
1981	// 4.1. Basic color keywords
1982	aqua: "#00ffff",
1983	black: "#000000",
1984	blue: "#0000ff",
1985	fuchsia: "#ff00ff",
1986	gray: "#808080",
1987	green: "#008000",
1988	lime: "#00ff00",
1989	maroon: "#800000",
1990	navy: "#000080",
1991	olive: "#808000",
1992	purple: "#800080",
1993	red: "#ff0000",
1994	silver: "#c0c0c0",
1995	teal: "#008080",
1996	white: "#ffffff",
1997	yellow: "#ffff00",
1998
1999	// 4.2.3. "transparent" color keyword
2000	transparent: [ null, null, null, 0 ],
2001
2002	_default: "#ffffff"
2003};
2004
2005} )( jQuery );
2006
2007/******************************************************************************/
2008/****************************** CLASS ANIMATIONS ******************************/
2009/******************************************************************************/
2010( function() {
2011
2012var classAnimationActions = [ "add", "remove", "toggle" ],
2013	shorthandStyles = {
2014		border: 1,
2015		borderBottom: 1,
2016		borderColor: 1,
2017		borderLeft: 1,
2018		borderRight: 1,
2019		borderTop: 1,
2020		borderWidth: 1,
2021		margin: 1,
2022		padding: 1
2023	};
2024
2025$.each(
2026	[ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ],
2027	function( _, prop ) {
2028		$.fx.step[ prop ] = function( fx ) {
2029			if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) {
2030				jQuery.style( fx.elem, prop, fx.end );
2031				fx.setAttr = true;
2032			}
2033		};
2034	}
2035);
2036
2037function getElementStyles( elem ) {
2038	var key, len,
2039		style = elem.ownerDocument.defaultView ?
2040			elem.ownerDocument.defaultView.getComputedStyle( elem, null ) :
2041			elem.currentStyle,
2042		styles = {};
2043
2044	if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) {
2045		len = style.length;
2046		while ( len-- ) {
2047			key = style[ len ];
2048			if ( typeof style[ key ] === "string" ) {
2049				styles[ $.camelCase( key ) ] = style[ key ];
2050			}
2051		}
2052
2053	// Support: Opera, IE <9
2054	} else {
2055		for ( key in style ) {
2056			if ( typeof style[ key ] === "string" ) {
2057				styles[ key ] = style[ key ];
2058			}
2059		}
2060	}
2061
2062	return styles;
2063}
2064
2065function styleDifference( oldStyle, newStyle ) {
2066	var diff = {},
2067		name, value;
2068
2069	for ( name in newStyle ) {
2070		value = newStyle[ name ];
2071		if ( oldStyle[ name ] !== value ) {
2072			if ( !shorthandStyles[ name ] ) {
2073				if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) {
2074					diff[ name ] = value;
2075				}
2076			}
2077		}
2078	}
2079
2080	return diff;
2081}
2082
2083// Support: jQuery <1.8
2084if ( !$.fn.addBack ) {
2085	$.fn.addBack = function( selector ) {
2086		return this.add( selector == null ?
2087			this.prevObject : this.prevObject.filter( selector )
2088		);
2089	};
2090}
2091
2092$.effects.animateClass = function( value, duration, easing, callback ) {
2093	var o = $.speed( duration, easing, callback );
2094
2095	return this.queue( function() {
2096		var animated = $( this ),
2097			baseClass = animated.attr( "class" ) || "",
2098			applyClassChange,
2099			allAnimations = o.children ? animated.find( "*" ).addBack() : animated;
2100
2101		// Map the animated objects to store the original styles.
2102		allAnimations = allAnimations.map( function() {
2103			var el = $( this );
2104			return {
2105				el: el,
2106				start: getElementStyles( this )
2107			};
2108		} );
2109
2110		// Apply class change
2111		applyClassChange = function() {
2112			$.each( classAnimationActions, function( i, action ) {
2113				if ( value[ action ] ) {
2114					animated[ action + "Class" ]( value[ action ] );
2115				}
2116			} );
2117		};
2118		applyClassChange();
2119
2120		// Map all animated objects again - calculate new styles and diff
2121		allAnimations = allAnimations.map( function() {
2122			this.end = getElementStyles( this.el[ 0 ] );
2123			this.diff = styleDifference( this.start, this.end );
2124			return this;
2125		} );
2126
2127		// Apply original class
2128		animated.attr( "class", baseClass );
2129
2130		// Map all animated objects again - this time collecting a promise
2131		allAnimations = allAnimations.map( function() {
2132			var styleInfo = this,
2133				dfd = $.Deferred(),
2134				opts = $.extend( {}, o, {
2135					queue: false,
2136					complete: function() {
2137						dfd.resolve( styleInfo );
2138					}
2139				} );
2140
2141			this.el.animate( this.diff, opts );
2142			return dfd.promise();
2143		} );
2144
2145		// Once all animations have completed:
2146		$.when.apply( $, allAnimations.get() ).done( function() {
2147
2148			// Set the final class
2149			applyClassChange();
2150
2151			// For each animated element,
2152			// clear all css properties that were animated
2153			$.each( arguments, function() {
2154				var el = this.el;
2155				$.each( this.diff, function( key ) {
2156					el.css( key, "" );
2157				} );
2158			} );
2159
2160			// This is guarnteed to be there if you use jQuery.speed()
2161			// it also handles dequeuing the next anim...
2162			o.complete.call( animated[ 0 ] );
2163		} );
2164	} );
2165};
2166
2167$.fn.extend( {
2168	addClass: ( function( orig ) {
2169		return function( classNames, speed, easing, callback ) {
2170			return speed ?
2171				$.effects.animateClass.call( this,
2172					{ add: classNames }, speed, easing, callback ) :
2173				orig.apply( this, arguments );
2174		};
2175	} )( $.fn.addClass ),
2176
2177	removeClass: ( function( orig ) {
2178		return function( classNames, speed, easing, callback ) {
2179			return arguments.length > 1 ?
2180				$.effects.animateClass.call( this,
2181					{ remove: classNames }, speed, easing, callback ) :
2182				orig.apply( this, arguments );
2183		};
2184	} )( $.fn.removeClass ),
2185
2186	toggleClass: ( function( orig ) {
2187		return function( classNames, force, speed, easing, callback ) {
2188			if ( typeof force === "boolean" || force === undefined ) {
2189				if ( !speed ) {
2190
2191					// Without speed parameter
2192					return orig.apply( this, arguments );
2193				} else {
2194					return $.effects.animateClass.call( this,
2195						( force ? { add: classNames } : { remove: classNames } ),
2196						speed, easing, callback );
2197				}
2198			} else {
2199
2200				// Without force parameter
2201				return $.effects.animateClass.call( this,
2202					{ toggle: classNames }, force, speed, easing );
2203			}
2204		};
2205	} )( $.fn.toggleClass ),
2206
2207	switchClass: function( remove, add, speed, easing, callback ) {
2208		return $.effects.animateClass.call( this, {
2209			add: add,
2210			remove: remove
2211		}, speed, easing, callback );
2212	}
2213} );
2214
2215} )();
2216
2217/******************************************************************************/
2218/*********************************** EFFECTS **********************************/
2219/******************************************************************************/
2220
2221( function() {
2222
2223if ( $.expr && $.expr.filters && $.expr.filters.animated ) {
2224	$.expr.filters.animated = ( function( orig ) {
2225		return function( elem ) {
2226			return !!$( elem ).data( dataSpaceAnimated ) || orig( elem );
2227		};
2228	} )( $.expr.filters.animated );
2229}
2230
2231if ( $.uiBackCompat !== false ) {
2232	$.extend( $.effects, {
2233
2234		// Saves a set of properties in a data storage
2235		save: function( element, set ) {
2236			var i = 0, length = set.length;
2237			for ( ; i < length; i++ ) {
2238				if ( set[ i ] !== null ) {
2239					element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] );
2240				}
2241			}
2242		},
2243
2244		// Restores a set of previously saved properties from a data storage
2245		restore: function( element, set ) {
2246			var val, i = 0, length = set.length;
2247			for ( ; i < length; i++ ) {
2248				if ( set[ i ] !== null ) {
2249					val = element.data( dataSpace + set[ i ] );
2250					element.css( set[ i ], val );
2251				}
2252			}
2253		},
2254
2255		setMode: function( el, mode ) {
2256			if ( mode === "toggle" ) {
2257				mode = el.is( ":hidden" ) ? "show" : "hide";
2258			}
2259			return mode;
2260		},
2261
2262		// Wraps the element around a wrapper that copies position properties
2263		createWrapper: function( element ) {
2264
2265			// If the element is already wrapped, return it
2266			if ( element.parent().is( ".ui-effects-wrapper" ) ) {
2267				return element.parent();
2268			}
2269
2270			// Wrap the element
2271			var props = {
2272					width: element.outerWidth( true ),
2273					height: element.outerHeight( true ),
2274					"float": element.css( "float" )
2275				},
2276				wrapper = $( "<div></div>" )
2277					.addClass( "ui-effects-wrapper" )
2278					.css( {
2279						fontSize: "100%",
2280						background: "transparent",
2281						border: "none",
2282						margin: 0,
2283						padding: 0
2284					} ),
2285
2286				// Store the size in case width/height are defined in % - Fixes #5245
2287				size = {
2288					width: element.width(),
2289					height: element.height()
2290				},
2291				active = document.activeElement;
2292
2293			// Support: Firefox
2294			// Firefox incorrectly exposes anonymous content
2295			// https://bugzilla.mozilla.org/show_bug.cgi?id=561664
2296			try {
2297				active.id;
2298			} catch ( e ) {
2299				active = document.body;
2300			}
2301
2302			element.wrap( wrapper );
2303
2304			// Fixes #7595 - Elements lose focus when wrapped.
2305			if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
2306				$( active ).trigger( "focus" );
2307			}
2308
2309			// Hotfix for jQuery 1.4 since some change in wrap() seems to actually
2310			// lose the reference to the wrapped element
2311			wrapper = element.parent();
2312
2313			// Transfer positioning properties to the wrapper
2314			if ( element.css( "position" ) === "static" ) {
2315				wrapper.css( { position: "relative" } );
2316				element.css( { position: "relative" } );
2317			} else {
2318				$.extend( props, {
2319					position: element.css( "position" ),
2320					zIndex: element.css( "z-index" )
2321				} );
2322				$.each( [ "top", "left", "bottom", "right" ], function( i, pos ) {
2323					props[ pos ] = element.css( pos );
2324					if ( isNaN( parseInt( props[ pos ], 10 ) ) ) {
2325						props[ pos ] = "auto";
2326					}
2327				} );
2328				element.css( {
2329					position: "relative",
2330					top: 0,
2331					left: 0,
2332					right: "auto",
2333					bottom: "auto"
2334				} );
2335			}
2336			element.css( size );
2337
2338			return wrapper.css( props ).show();
2339		},
2340
2341		removeWrapper: function( element ) {
2342			var active = document.activeElement;
2343
2344			if ( element.parent().is( ".ui-effects-wrapper" ) ) {
2345				element.parent().replaceWith( element );
2346
2347				// Fixes #7595 - Elements lose focus when wrapped.
2348				if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
2349					$( active ).trigger( "focus" );
2350				}
2351			}
2352
2353			return element;
2354		}
2355	} );
2356}
2357
2358$.extend( $.effects, {
2359	version: "1.12.1",
2360
2361	define: function( name, mode, effect ) {
2362		if ( !effect ) {
2363			effect = mode;
2364			mode = "effect";
2365		}
2366
2367		$.effects.effect[ name ] = effect;
2368		$.effects.effect[ name ].mode = mode;
2369
2370		return effect;
2371	},
2372
2373	scaledDimensions: function( element, percent, direction ) {
2374		if ( percent === 0 ) {
2375			return {
2376				height: 0,
2377				width: 0,
2378				outerHeight: 0,
2379				outerWidth: 0
2380			};
2381		}
2382
2383		var x = direction !== "horizontal" ? ( ( percent || 100 ) / 100 ) : 1,
2384			y = direction !== "vertical" ? ( ( percent || 100 ) / 100 ) : 1;
2385
2386		return {
2387			height: element.height() * y,
2388			width: element.width() * x,
2389			outerHeight: element.outerHeight() * y,
2390			outerWidth: element.outerWidth() * x
2391		};
2392
2393	},
2394
2395	clipToBox: function( animation ) {
2396		return {
2397			width: animation.clip.right - animation.clip.left,
2398			height: animation.clip.bottom - animation.clip.top,
2399			left: animation.clip.left,
2400			top: animation.clip.top
2401		};
2402	},
2403
2404	// Injects recently queued functions to be first in line (after "inprogress")
2405	unshift: function( element, queueLength, count ) {
2406		var queue = element.queue();
2407
2408		if ( queueLength > 1 ) {
2409			queue.splice.apply( queue,
2410				[ 1, 0 ].concat( queue.splice( queueLength, count ) ) );
2411		}
2412		element.dequeue();
2413	},
2414
2415	saveStyle: function( element ) {
2416		element.data( dataSpaceStyle, element[ 0 ].style.cssText );
2417	},
2418
2419	restoreStyle: function( element ) {
2420		element[ 0 ].style.cssText = element.data( dataSpaceStyle ) || "";
2421		element.removeData( dataSpaceStyle );
2422	},
2423
2424	mode: function( element, mode ) {
2425		var hidden = element.is( ":hidden" );
2426
2427		if ( mode === "toggle" ) {
2428			mode = hidden ? "show" : "hide";
2429		}
2430		if ( hidden ? mode === "hide" : mode === "show" ) {
2431			mode = "none";
2432		}
2433		return mode;
2434	},
2435
2436	// Translates a [top,left] array into a baseline value
2437	getBaseline: function( origin, original ) {
2438		var y, x;
2439
2440		switch ( origin[ 0 ] ) {
2441		case "top":
2442			y = 0;
2443			break;
2444		case "middle":
2445			y = 0.5;
2446			break;
2447		case "bottom":
2448			y = 1;
2449			break;
2450		default:
2451			y = origin[ 0 ] / original.height;
2452		}
2453
2454		switch ( origin[ 1 ] ) {
2455		case "left":
2456			x = 0;
2457			break;
2458		case "center":
2459			x = 0.5;
2460			break;
2461		case "right":
2462			x = 1;
2463			break;
2464		default:
2465			x = origin[ 1 ] / original.width;
2466		}
2467
2468		return {
2469			x: x,
2470			y: y
2471		};
2472	},
2473
2474	// Creates a placeholder element so that the original element can be made absolute
2475	createPlaceholder: function( element ) {
2476		var placeholder,
2477			cssPosition = element.css( "position" ),
2478			position = element.position();
2479
2480		// Lock in margins first to account for form elements, which
2481		// will change margin if you explicitly set height
2482		// see: http://jsfiddle.net/JZSMt/3/ https://bugs.webkit.org/show_bug.cgi?id=107380
2483		// Support: Safari
2484		element.css( {
2485			marginTop: element.css( "marginTop" ),
2486			marginBottom: element.css( "marginBottom" ),
2487			marginLeft: element.css( "marginLeft" ),
2488			marginRight: element.css( "marginRight" )
2489		} )
2490		.outerWidth( element.outerWidth() )
2491		.outerHeight( element.outerHeight() );
2492
2493		if ( /^(static|relative)/.test( cssPosition ) ) {
2494			cssPosition = "absolute";
2495
2496			placeholder = $( "<" + element[ 0 ].nodeName + ">" ).insertAfter( element ).css( {
2497
2498				// Convert inline to inline block to account for inline elements
2499				// that turn to inline block based on content (like img)
2500				display: /^(inline|ruby)/.test( element.css( "display" ) ) ?
2501					"inline-block" :
2502					"block",
2503				visibility: "hidden",
2504
2505				// Margins need to be set to account for margin collapse
2506				marginTop: element.css( "marginTop" ),
2507				marginBottom: element.css( "marginBottom" ),
2508				marginLeft: element.css( "marginLeft" ),
2509				marginRight: element.css( "marginRight" ),
2510				"float": element.css( "float" )
2511			} )
2512			.outerWidth( element.outerWidth() )
2513			.outerHeight( element.outerHeight() )
2514			.addClass( "ui-effects-placeholder" );
2515
2516			element.data( dataSpace + "placeholder", placeholder );
2517		}
2518
2519		element.css( {
2520			position: cssPosition,
2521			left: position.left,
2522			top: position.top
2523		} );
2524
2525		return placeholder;
2526	},
2527
2528	removePlaceholder: function( element ) {
2529		var dataKey = dataSpace + "placeholder",
2530				placeholder = element.data( dataKey );
2531
2532		if ( placeholder ) {
2533			placeholder.remove();
2534			element.removeData( dataKey );
2535		}
2536	},
2537
2538	// Removes a placeholder if it exists and restores
2539	// properties that were modified during placeholder creation
2540	cleanUp: function( element ) {
2541		$.effects.restoreStyle( element );
2542		$.effects.removePlaceholder( element );
2543	},
2544
2545	setTransition: function( element, list, factor, value ) {
2546		value = value || {};
2547		$.each( list, function( i, x ) {
2548			var unit = element.cssUnit( x );
2549			if ( unit[ 0 ] > 0 ) {
2550				value[ x ] = unit[ 0 ] * factor + unit[ 1 ];
2551			}
2552		} );
2553		return value;
2554	}
2555} );
2556
2557// Return an effect options object for the given parameters:
2558function _normalizeArguments( effect, options, speed, callback ) {
2559
2560	// Allow passing all options as the first parameter
2561	if ( $.isPlainObject( effect ) ) {
2562		options = effect;
2563		effect = effect.effect;
2564	}
2565
2566	// Convert to an object
2567	effect = { effect: effect };
2568
2569	// Catch (effect, null, ...)
2570	if ( options == null ) {
2571		options = {};
2572	}
2573
2574	// Catch (effect, callback)
2575	if ( $.isFunction( options ) ) {
2576		callback = options;
2577		speed = null;
2578		options = {};
2579	}
2580
2581	// Catch (effect, speed, ?)
2582	if ( typeof options === "number" || $.fx.speeds[ options ] ) {
2583		callback = speed;
2584		speed = options;
2585		options = {};
2586	}
2587
2588	// Catch (effect, options, callback)
2589	if ( $.isFunction( speed ) ) {
2590		callback = speed;
2591		speed = null;
2592	}
2593
2594	// Add options to effect
2595	if ( options ) {
2596		$.extend( effect, options );
2597	}
2598
2599	speed = speed || options.duration;
2600	effect.duration = $.fx.off ? 0 :
2601		typeof speed === "number" ? speed :
2602		speed in $.fx.speeds ? $.fx.speeds[ speed ] :
2603		$.fx.speeds._default;
2604
2605	effect.complete = callback || options.complete;
2606
2607	return effect;
2608}
2609
2610function standardAnimationOption( option ) {
2611
2612	// Valid standard speeds (nothing, number, named speed)
2613	if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) {
2614		return true;
2615	}
2616
2617	// Invalid strings - treat as "normal" speed
2618	if ( typeof option === "string" && !$.effects.effect[ option ] ) {
2619		return true;
2620	}
2621
2622	// Complete callback
2623	if ( $.isFunction( option ) ) {
2624		return true;
2625	}
2626
2627	// Options hash (but not naming an effect)
2628	if ( typeof option === "object" && !option.effect ) {
2629		return true;
2630	}
2631
2632	// Didn't match any standard API
2633	return false;
2634}
2635
2636$.fn.extend( {
2637	effect: function( /* effect, options, speed, callback */ ) {
2638		var args = _normalizeArguments.apply( this, arguments ),
2639			effectMethod = $.effects.effect[ args.effect ],
2640			defaultMode = effectMethod.mode,
2641			queue = args.queue,
2642			queueName = queue || "fx",
2643			complete = args.complete,
2644			mode = args.mode,
2645			modes = [],
2646			prefilter = function( next ) {
2647				var el = $( this ),
2648					normalizedMode = $.effects.mode( el, mode ) || defaultMode;
2649
2650				// Sentinel for duck-punching the :animated psuedo-selector
2651				el.data( dataSpaceAnimated, true );
2652
2653				// Save effect mode for later use,
2654				// we can't just call $.effects.mode again later,
2655				// as the .show() below destroys the initial state
2656				modes.push( normalizedMode );
2657
2658				// See $.uiBackCompat inside of run() for removal of defaultMode in 1.13
2659				if ( defaultMode && ( normalizedMode === "show" ||
2660						( normalizedMode === defaultMode && normalizedMode === "hide" ) ) ) {
2661					el.show();
2662				}
2663
2664				if ( !defaultMode || normalizedMode !== "none" ) {
2665					$.effects.saveStyle( el );
2666				}
2667
2668				if ( $.isFunction( next ) ) {
2669					next();
2670				}
2671			};
2672
2673		if ( $.fx.off || !effectMethod ) {
2674
2675			// Delegate to the original method (e.g., .show()) if possible
2676			if ( mode ) {
2677				return this[ mode ]( args.duration, complete );
2678			} else {
2679				return this.each( function() {
2680					if ( complete ) {
2681						complete.call( this );
2682					}
2683				} );
2684			}
2685		}
2686
2687		function run( next ) {
2688			var elem = $( this );
2689
2690			function cleanup() {
2691				elem.removeData( dataSpaceAnimated );
2692
2693				$.effects.cleanUp( elem );
2694
2695				if ( args.mode === "hide" ) {
2696					elem.hide();
2697				}
2698
2699				done();
2700			}
2701
2702			function done() {
2703				if ( $.isFunction( complete ) ) {
2704					complete.call( elem[ 0 ] );
2705				}
2706
2707				if ( $.isFunction( next ) ) {
2708					next();
2709				}
2710			}
2711
2712			// Override mode option on a per element basis,
2713			// as toggle can be either show or hide depending on element state
2714			args.mode = modes.shift();
2715
2716			if ( $.uiBackCompat !== false && !defaultMode ) {
2717				if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) {
2718
2719					// Call the core method to track "olddisplay" properly
2720					elem[ mode ]();
2721					done();
2722				} else {
2723					effectMethod.call( elem[ 0 ], args, done );
2724				}
2725			} else {
2726				if ( args.mode === "none" ) {
2727
2728					// Call the core method to track "olddisplay" properly
2729					elem[ mode ]();
2730					done();
2731				} else {
2732					effectMethod.call( elem[ 0 ], args, cleanup );
2733				}
2734			}
2735		}
2736
2737		// Run prefilter on all elements first to ensure that
2738		// any showing or hiding happens before placeholder creation,
2739		// which ensures that any layout changes are correctly captured.
2740		return queue === false ?
2741			this.each( prefilter ).each( run ) :
2742			this.queue( queueName, prefilter ).queue( queueName, run );
2743	},
2744
2745	show: ( function( orig ) {
2746		return function( option ) {
2747			if ( standardAnimationOption( option ) ) {
2748				return orig.apply( this, arguments );
2749			} else {
2750				var args = _normalizeArguments.apply( this, arguments );
2751				args.mode = "show";
2752				return this.effect.call( this, args );
2753			}
2754		};
2755	} )( $.fn.show ),
2756
2757	hide: ( function( orig ) {
2758		return function( option ) {
2759			if ( standardAnimationOption( option ) ) {
2760				return orig.apply( this, arguments );
2761			} else {
2762				var args = _normalizeArguments.apply( this, arguments );
2763				args.mode = "hide";
2764				return this.effect.call( this, args );
2765			}
2766		};
2767	} )( $.fn.hide ),
2768
2769	toggle: ( function( orig ) {
2770		return function( option ) {
2771			if ( standardAnimationOption( option ) || typeof option === "boolean" ) {
2772				return orig.apply( this, arguments );
2773			} else {
2774				var args = _normalizeArguments.apply( this, arguments );
2775				args.mode = "toggle";
2776				return this.effect.call( this, args );
2777			}
2778		};
2779	} )( $.fn.toggle ),
2780
2781	cssUnit: function( key ) {
2782		var style = this.css( key ),
2783			val = [];
2784
2785		$.each( [ "em", "px", "%", "pt" ], function( i, unit ) {
2786			if ( style.indexOf( unit ) > 0 ) {
2787				val = [ parseFloat( style ), unit ];
2788			}
2789		} );
2790		return val;
2791	},
2792
2793	cssClip: function( clipObj ) {
2794		if ( clipObj ) {
2795			return this.css( "clip", "rect(" + clipObj.top + "px " + clipObj.right + "px " +
2796				clipObj.bottom + "px " + clipObj.left + "px)" );
2797		}
2798		return parseClip( this.css( "clip" ), this );
2799	},
2800
2801	transfer: function( options, done ) {
2802		var element = $( this ),
2803			target = $( options.to ),
2804			targetFixed = target.css( "position" ) === "fixed",
2805			body = $( "body" ),
2806			fixTop = targetFixed ? body.scrollTop() : 0,
2807			fixLeft = targetFixed ? body.scrollLeft() : 0,
2808			endPosition = target.offset(),
2809			animation = {
2810				top: endPosition.top - fixTop,
2811				left: endPosition.left - fixLeft,
2812				height: target.innerHeight(),
2813				width: target.innerWidth()
2814			},
2815			startPosition = element.offset(),
2816			transfer = $( "<div class='ui-effects-transfer'></div>" )
2817				.appendTo( "body" )
2818				.addClass( options.className )
2819				.css( {
2820					top: startPosition.top - fixTop,
2821					left: startPosition.left - fixLeft,
2822					height: element.innerHeight(),
2823					width: element.innerWidth(),
2824					position: targetFixed ? "fixed" : "absolute"
2825				} )
2826				.animate( animation, options.duration, options.easing, function() {
2827					transfer.remove();
2828					if ( $.isFunction( done ) ) {
2829						done();
2830					}
2831
2832				} );
2833	}
2834} );
2835
2836function parseClip( str, element ) {
2837		var outerWidth = element.outerWidth(),
2838			outerHeight = element.outerHeight(),
2839			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)\)$/,
2840			values = clipRegex.exec( str ) || [ "", 0, outerWidth, outerHeight, 0 ];
2841
2842		return {
2843			top: parseFloat( values[ 1 ] ) || 0,
2844			right: values[ 2 ] === "auto" ? outerWidth : parseFloat( values[ 2 ] ),
2845			bottom: values[ 3 ] === "auto" ? outerHeight : parseFloat( values[ 3 ] ),
2846			left: parseFloat( values[ 4 ] ) || 0
2847		};
2848}
2849
2850$.fx.step.clip = function( fx ) {
2851	if ( !fx.clipInit ) {
2852		fx.start = $( fx.elem ).cssClip();
2853		if ( typeof fx.end === "string" ) {
2854			fx.end = parseClip( fx.end, fx.elem );
2855		}
2856		fx.clipInit = true;
2857	}
2858
2859	$( fx.elem ).cssClip( {
2860		top: fx.pos * ( fx.end.top - fx.start.top ) + fx.start.top,
2861		right: fx.pos * ( fx.end.right - fx.start.right ) + fx.start.right,
2862		bottom: fx.pos * ( fx.end.bottom - fx.start.bottom ) + fx.start.bottom,
2863		left: fx.pos * ( fx.end.left - fx.start.left ) + fx.start.left
2864	} );
2865};
2866
2867} )();
2868
2869/******************************************************************************/
2870/*********************************** EASING ***********************************/
2871/******************************************************************************/
2872
2873( function() {
2874
2875// Based on easing equations from Robert Penner (http://www.robertpenner.com/easing)
2876
2877var baseEasings = {};
2878
2879$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) {
2880	baseEasings[ name ] = function( p ) {
2881		return Math.pow( p, i + 2 );
2882	};
2883} );
2884
2885$.extend( baseEasings, {
2886	Sine: function( p ) {
2887		return 1 - Math.cos( p * Math.PI / 2 );
2888	},
2889	Circ: function( p ) {
2890		return 1 - Math.sqrt( 1 - p * p );
2891	},
2892	Elastic: function( p ) {
2893		return p === 0 || p === 1 ? p :
2894			-Math.pow( 2, 8 * ( p - 1 ) ) * Math.sin( ( ( p - 1 ) * 80 - 7.5 ) * Math.PI / 15 );
2895	},
2896	Back: function( p ) {
2897		return p * p * ( 3 * p - 2 );
2898	},
2899	Bounce: function( p ) {
2900		var pow2,
2901			bounce = 4;
2902
2903		while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}
2904		return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 );
2905	}
2906} );
2907
2908$.each( baseEasings, function( name, easeIn ) {
2909	$.easing[ "easeIn" + name ] = easeIn;
2910	$.easing[ "easeOut" + name ] = function( p ) {
2911		return 1 - easeIn( 1 - p );
2912	};
2913	$.easing[ "easeInOut" + name ] = function( p ) {
2914		return p < 0.5 ?
2915			easeIn( p * 2 ) / 2 :
2916			1 - easeIn( p * -2 + 2 ) / 2;
2917	};
2918} );
2919
2920} )();
2921
2922var effect = $.effects;
2923
2924
2925/*!
2926 * jQuery UI Effects Blind 1.12.1
2927 * http://jqueryui.com
2928 *
2929 * Copyright jQuery Foundation and other contributors
2930 * Released under the MIT license.
2931 * http://jquery.org/license
2932 */
2933
2934//>>label: Blind Effect
2935//>>group: Effects
2936//>>description: Blinds the element.
2937//>>docs: http://api.jqueryui.com/blind-effect/
2938//>>demos: http://jqueryui.com/effect/
2939
2940
2941
2942var effectsEffectBlind = $.effects.define( "blind", "hide", function( options, done ) {
2943	var map = {
2944			up: [ "bottom", "top" ],
2945			vertical: [ "bottom", "top" ],
2946			down: [ "top", "bottom" ],
2947			left: [ "right", "left" ],
2948			horizontal: [ "right", "left" ],
2949			right: [ "left", "right" ]
2950		},
2951		element = $( this ),
2952		direction = options.direction || "up",
2953		start = element.cssClip(),
2954		animate = { clip: $.extend( {}, start ) },
2955		placeholder = $.effects.createPlaceholder( element );
2956
2957	animate.clip[ map[ direction ][ 0 ] ] = animate.clip[ map[ direction ][ 1 ] ];
2958
2959	if ( options.mode === "show" ) {
2960		element.cssClip( animate.clip );
2961		if ( placeholder ) {
2962			placeholder.css( $.effects.clipToBox( animate ) );
2963		}
2964
2965		animate.clip = start;
2966	}
2967
2968	if ( placeholder ) {
2969		placeholder.animate( $.effects.clipToBox( animate ), options.duration, options.easing );
2970	}
2971
2972	element.animate( animate, {
2973		queue: false,
2974		duration: options.duration,
2975		easing: options.easing,
2976		complete: done
2977	} );
2978} );
2979
2980
2981/*!
2982 * jQuery UI Effects Bounce 1.12.1
2983 * http://jqueryui.com
2984 *
2985 * Copyright jQuery Foundation and other contributors
2986 * Released under the MIT license.
2987 * http://jquery.org/license
2988 */
2989
2990//>>label: Bounce Effect
2991//>>group: Effects
2992//>>description: Bounces an element horizontally or vertically n times.
2993//>>docs: http://api.jqueryui.com/bounce-effect/
2994//>>demos: http://jqueryui.com/effect/
2995
2996
2997
2998var effectsEffectBounce = $.effects.define( "bounce", function( options, done ) {
2999	var upAnim, downAnim, refValue,
3000		element = $( this ),
3001
3002		// Defaults:
3003		mode = options.mode,
3004		hide = mode === "hide",
3005		show = mode === "show",
3006		direction = options.direction || "up",
3007		distance = options.distance,
3008		times = options.times || 5,
3009
3010		// Number of internal animations
3011		anims = times * 2 + ( show || hide ? 1 : 0 ),
3012		speed = options.duration / anims,
3013		easing = options.easing,
3014
3015		// Utility:
3016		ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
3017		motion = ( direction === "up" || direction === "left" ),
3018		i = 0,
3019
3020		queuelen = element.queue().length;
3021
3022	$.effects.createPlaceholder( element );
3023
3024	refValue = element.css( ref );
3025
3026	// Default distance for the BIGGEST bounce is the outer Distance / 3
3027	if ( !distance ) {
3028		distance = element[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3;
3029	}
3030
3031	if ( show ) {
3032		downAnim = { opacity: 1 };
3033		downAnim[ ref ] = refValue;
3034
3035		// If we are showing, force opacity 0 and set the initial position
3036		// then do the "first" animation
3037		element
3038			.css( "opacity", 0 )
3039			.css( ref, motion ? -distance * 2 : distance * 2 )
3040			.animate( downAnim, speed, easing );
3041	}
3042
3043	// Start at the smallest distance if we are hiding
3044	if ( hide ) {
3045		distance = distance / Math.pow( 2, times - 1 );
3046	}
3047
3048	downAnim = {};
3049	downAnim[ ref ] = refValue;
3050
3051	// Bounces up/down/left/right then back to 0 -- times * 2 animations happen here
3052	for ( ; i < times; i++ ) {
3053		upAnim = {};
3054		upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
3055
3056		element
3057			.animate( upAnim, speed, easing )
3058			.animate( downAnim, speed, easing );
3059
3060		distance = hide ? distance * 2 : distance / 2;
3061	}
3062
3063	// Last Bounce when Hiding
3064	if ( hide ) {
3065		upAnim = { opacity: 0 };
3066		upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
3067
3068		element.animate( upAnim, speed, easing );
3069	}
3070
3071	element.queue( done );
3072
3073	$.effects.unshift( element, queuelen, anims + 1 );
3074} );
3075
3076
3077/*!
3078 * jQuery UI Effects Clip 1.12.1
3079 * http://jqueryui.com
3080 *
3081 * Copyright jQuery Foundation and other contributors
3082 * Released under the MIT license.
3083 * http://jquery.org/license
3084 */
3085
3086//>>label: Clip Effect
3087//>>group: Effects
3088//>>description: Clips the element on and off like an old TV.
3089//>>docs: http://api.jqueryui.com/clip-effect/
3090//>>demos: http://jqueryui.com/effect/
3091
3092
3093
3094var effectsEffectClip = $.effects.define( "clip", "hide", function( options, done ) {
3095	var start,
3096		animate = {},
3097		element = $( this ),
3098		direction = options.direction || "vertical",
3099		both = direction === "both",
3100		horizontal = both || direction === "horizontal",
3101		vertical = both || direction === "vertical";
3102
3103	start = element.cssClip();
3104	animate.clip = {
3105		top: vertical ? ( start.bottom - start.top ) / 2 : start.top,
3106		right: horizontal ? ( start.right - start.left ) / 2 : start.right,
3107		bottom: vertical ? ( start.bottom - start.top ) / 2 : start.bottom,
3108		left: horizontal ? ( start.right - start.left ) / 2 : start.left
3109	};
3110
3111	$.effects.createPlaceholder( element );
3112
3113	if ( options.mode === "show" ) {
3114		element.cssClip( animate.clip );
3115		animate.clip = start;
3116	}
3117
3118	element.animate( animate, {
3119		queue: false,
3120		duration: options.duration,
3121		easing: options.easing,
3122		complete: done
3123	} );
3124
3125} );
3126
3127
3128/*!
3129 * jQuery UI Effects Drop 1.12.1
3130 * http://jqueryui.com
3131 *
3132 * Copyright jQuery Foundation and other contributors
3133 * Released under the MIT license.
3134 * http://jquery.org/license
3135 */
3136
3137//>>label: Drop Effect
3138//>>group: Effects
3139//>>description: Moves an element in one direction and hides it at the same time.
3140//>>docs: http://api.jqueryui.com/drop-effect/
3141//>>demos: http://jqueryui.com/effect/
3142
3143
3144
3145var effectsEffectDrop = $.effects.define( "drop", "hide", function( options, done ) {
3146
3147	var distance,
3148		element = $( this ),
3149		mode = options.mode,
3150		show = mode === "show",
3151		direction = options.direction || "left",
3152		ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
3153		motion = ( direction === "up" || direction === "left" ) ? "-=" : "+=",
3154		oppositeMotion = ( motion === "+=" ) ? "-=" : "+=",
3155		animation = {
3156			opacity: 0
3157		};
3158
3159	$.effects.createPlaceholder( element );
3160
3161	distance = options.distance ||
3162		element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ) / 2;
3163
3164	animation[ ref ] = motion + distance;
3165
3166	if ( show ) {
3167		element.css( animation );
3168
3169		animation[ ref ] = oppositeMotion + distance;
3170		animation.opacity = 1;
3171	}
3172
3173	// Animate
3174	element.animate( animation, {
3175		queue: false,
3176		duration: options.duration,
3177		easing: options.easing,
3178		complete: done
3179	} );
3180} );
3181
3182
3183/*!
3184 * jQuery UI Effects Explode 1.12.1
3185 * http://jqueryui.com
3186 *
3187 * Copyright jQuery Foundation and other contributors
3188 * Released under the MIT license.
3189 * http://jquery.org/license
3190 */
3191
3192//>>label: Explode Effect
3193//>>group: Effects
3194// jscs:disable maximumLineLength
3195//>>description: Explodes an element in all directions into n pieces. Implodes an element to its original wholeness.
3196// jscs:enable maximumLineLength
3197//>>docs: http://api.jqueryui.com/explode-effect/
3198//>>demos: http://jqueryui.com/effect/
3199
3200
3201
3202var effectsEffectExplode = $.effects.define( "explode", "hide", function( options, done ) {
3203
3204	var i, j, left, top, mx, my,
3205		rows = options.pieces ? Math.round( Math.sqrt( options.pieces ) ) : 3,
3206		cells = rows,
3207		element = $( this ),
3208		mode = options.mode,
3209		show = mode === "show",
3210
3211		// Show and then visibility:hidden the element before calculating offset
3212		offset = element.show().css( "visibility", "hidden" ).offset(),
3213
3214		// Width and height of a piece
3215		width = Math.ceil( element.outerWidth() / cells ),
3216		height = Math.ceil( element.outerHeight() / rows ),
3217		pieces = [];
3218
3219	// Children animate complete:
3220	function childComplete() {
3221		pieces.push( this );
3222		if ( pieces.length === rows * cells ) {
3223			animComplete();
3224		}
3225	}
3226
3227	// Clone the element for each row and cell.
3228	for ( i = 0; i < rows; i++ ) { // ===>
3229		top = offset.top + i * height;
3230		my = i - ( rows - 1 ) / 2;
3231
3232		for ( j = 0; j < cells; j++ ) { // |||
3233			left = offset.left + j * width;
3234			mx = j - ( cells - 1 ) / 2;
3235
3236			// Create a clone of the now hidden main element that will be absolute positioned
3237			// within a wrapper div off the -left and -top equal to size of our pieces
3238			element
3239				.clone()
3240				.appendTo( "body" )
3241				.wrap( "<div></div>" )
3242				.css( {
3243					position: "absolute",
3244					visibility: "visible",
3245					left: -j * width,
3246					top: -i * height
3247				} )
3248
3249				// Select the wrapper - make it overflow: hidden and absolute positioned based on
3250				// where the original was located +left and +top equal to the size of pieces
3251				.parent()
3252					.addClass( "ui-effects-explode" )
3253					.css( {
3254						position: "absolute",
3255						overflow: "hidden",
3256						width: width,
3257						height: height,
3258						left: left + ( show ? mx * width : 0 ),
3259						top: top + ( show ? my * height : 0 ),
3260						opacity: show ? 0 : 1
3261					} )
3262					.animate( {
3263						left: left + ( show ? 0 : mx * width ),
3264						top: top + ( show ? 0 : my * height ),
3265						opacity: show ? 1 : 0
3266					}, options.duration || 500, options.easing, childComplete );
3267		}
3268	}
3269
3270	function animComplete() {
3271		element.css( {
3272			visibility: "visible"
3273		} );
3274		$( pieces ).remove();
3275		done();
3276	}
3277} );
3278
3279
3280/*!
3281 * jQuery UI Effects Fade 1.12.1
3282 * http://jqueryui.com
3283 *
3284 * Copyright jQuery Foundation and other contributors
3285 * Released under the MIT license.
3286 * http://jquery.org/license
3287 */
3288
3289//>>label: Fade Effect
3290//>>group: Effects
3291//>>description: Fades the element.
3292//>>docs: http://api.jqueryui.com/fade-effect/
3293//>>demos: http://jqueryui.com/effect/
3294
3295
3296
3297var effectsEffectFade = $.effects.define( "fade", "toggle", function( options, done ) {
3298	var show = options.mode === "show";
3299
3300	$( this )
3301		.css( "opacity", show ? 0 : 1 )
3302		.animate( {
3303			opacity: show ? 1 : 0
3304		}, {
3305			queue: false,
3306			duration: options.duration,
3307			easing: options.easing,
3308			complete: done
3309		} );
3310} );
3311
3312
3313/*!
3314 * jQuery UI Effects Fold 1.12.1
3315 * http://jqueryui.com
3316 *
3317 * Copyright jQuery Foundation and other contributors
3318 * Released under the MIT license.
3319 * http://jquery.org/license
3320 */
3321
3322//>>label: Fold Effect
3323//>>group: Effects
3324//>>description: Folds an element first horizontally and then vertically.
3325//>>docs: http://api.jqueryui.com/fold-effect/
3326//>>demos: http://jqueryui.com/effect/
3327
3328
3329
3330var effectsEffectFold = $.effects.define( "fold", "hide", function( options, done ) {
3331
3332	// Create element
3333	var element = $( this ),
3334		mode = options.mode,
3335		show = mode === "show",
3336		hide = mode === "hide",
3337		size = options.size || 15,
3338		percent = /([0-9]+)%/.exec( size ),
3339		horizFirst = !!options.horizFirst,
3340		ref = horizFirst ? [ "right", "bottom" ] : [ "bottom", "right" ],
3341		duration = options.duration / 2,
3342
3343		placeholder = $.effects.createPlaceholder( element ),
3344
3345		start = element.cssClip(),
3346		animation1 = { clip: $.extend( {}, start ) },
3347		animation2 = { clip: $.extend( {}, start ) },
3348
3349		distance = [ start[ ref[ 0 ] ], start[ ref[ 1 ] ] ],
3350
3351		queuelen = element.queue().length;
3352
3353	if ( percent ) {
3354		size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ];
3355	}
3356	animation1.clip[ ref[ 0 ] ] = size;
3357	animation2.clip[ ref[ 0 ] ] = size;
3358	animation2.clip[ ref[ 1 ] ] = 0;
3359
3360	if ( show ) {
3361		element.cssClip( animation2.clip );
3362		if ( placeholder ) {
3363			placeholder.css( $.effects.clipToBox( animation2 ) );
3364		}
3365
3366		animation2.clip = start;
3367	}
3368
3369	// Animate
3370	element
3371		.queue( function( next ) {
3372			if ( placeholder ) {
3373				placeholder
3374					.animate( $.effects.clipToBox( animation1 ), duration, options.easing )
3375					.animate( $.effects.clipToBox( animation2 ), duration, options.easing );
3376			}
3377
3378			next();
3379		} )
3380		.animate( animation1, duration, options.easing )
3381		.animate( animation2, duration, options.easing )
3382		.queue( done );
3383
3384	$.effects.unshift( element, queuelen, 4 );
3385} );
3386
3387
3388/*!
3389 * jQuery UI Effects Highlight 1.12.1
3390 * http://jqueryui.com
3391 *
3392 * Copyright jQuery Foundation and other contributors
3393 * Released under the MIT license.
3394 * http://jquery.org/license
3395 */
3396
3397//>>label: Highlight Effect
3398//>>group: Effects
3399//>>description: Highlights the background of an element in a defined color for a custom duration.
3400//>>docs: http://api.jqueryui.com/highlight-effect/
3401//>>demos: http://jqueryui.com/effect/
3402
3403
3404
3405var effectsEffectHighlight = $.effects.define( "highlight", "show", function( options, done ) {
3406	var element = $( this ),
3407		animation = {
3408			backgroundColor: element.css( "backgroundColor" )
3409		};
3410
3411	if ( options.mode === "hide" ) {
3412		animation.opacity = 0;
3413	}
3414
3415	$.effects.saveStyle( element );
3416
3417	element
3418		.css( {
3419			backgroundImage: "none",
3420			backgroundColor: options.color || "#ffff99"
3421		} )
3422		.animate( animation, {
3423			queue: false,
3424			duration: options.duration,
3425			easing: options.easing,
3426			complete: done
3427		} );
3428} );
3429
3430
3431/*!
3432 * jQuery UI Effects Size 1.12.1
3433 * http://jqueryui.com
3434 *
3435 * Copyright jQuery Foundation and other contributors
3436 * Released under the MIT license.
3437 * http://jquery.org/license
3438 */
3439
3440//>>label: Size Effect
3441//>>group: Effects
3442//>>description: Resize an element to a specified width and height.
3443//>>docs: http://api.jqueryui.com/size-effect/
3444//>>demos: http://jqueryui.com/effect/
3445
3446
3447
3448var effectsEffectSize = $.effects.define( "size", function( options, done ) {
3449
3450	// Create element
3451	var baseline, factor, temp,
3452		element = $( this ),
3453
3454		// Copy for children
3455		cProps = [ "fontSize" ],
3456		vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ],
3457		hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ],
3458
3459		// Set options
3460		mode = options.mode,
3461		restore = mode !== "effect",
3462		scale = options.scale || "both",
3463		origin = options.origin || [ "middle", "center" ],
3464		position = element.css( "position" ),
3465		pos = element.position(),
3466		original = $.effects.scaledDimensions( element ),
3467		from = options.from || original,
3468		to = options.to || $.effects.scaledDimensions( element, 0 );
3469
3470	$.effects.createPlaceholder( element );
3471
3472	if ( mode === "show" ) {
3473		temp = from;
3474		from = to;
3475		to = temp;
3476	}
3477
3478	// Set scaling factor
3479	factor = {
3480		from: {
3481			y: from.height / original.height,
3482			x: from.width / original.width
3483		},
3484		to: {
3485			y: to.height / original.height,
3486			x: to.width / original.width
3487		}
3488	};
3489
3490	// Scale the css box
3491	if ( scale === "box" || scale === "both" ) {
3492
3493		// Vertical props scaling
3494		if ( factor.from.y !== factor.to.y ) {
3495			from = $.effects.setTransition( element, vProps, factor.from.y, from );
3496			to = $.effects.setTransition( element, vProps, factor.to.y, to );
3497		}
3498
3499		// Horizontal props scaling
3500		if ( factor.from.x !== factor.to.x ) {
3501			from = $.effects.setTransition( element, hProps, factor.from.x, from );
3502			to = $.effects.setTransition( element, hProps, factor.to.x, to );
3503		}
3504	}
3505
3506	// Scale the content
3507	if ( scale === "content" || scale === "both" ) {
3508
3509		// Vertical props scaling
3510		if ( factor.from.y !== factor.to.y ) {
3511			from = $.effects.setTransition( element, cProps, factor.from.y, from );
3512			to = $.effects.setTransition( element, cProps, factor.to.y, to );
3513		}
3514	}
3515
3516	// Adjust the position properties based on the provided origin points
3517	if ( origin ) {
3518		baseline = $.effects.getBaseline( origin, original );
3519		from.top = ( original.outerHeight - from.outerHeight ) * baseline.y + pos.top;
3520		from.left = ( original.outerWidth - from.outerWidth ) * baseline.x + pos.left;
3521		to.top = ( original.outerHeight - to.outerHeight ) * baseline.y + pos.top;
3522		to.left = ( original.outerWidth - to.outerWidth ) * baseline.x + pos.left;
3523	}
3524	element.css( from );
3525
3526	// Animate the children if desired
3527	if ( scale === "content" || scale === "both" ) {
3528
3529		vProps = vProps.concat( [ "marginTop", "marginBottom" ] ).concat( cProps );
3530		hProps = hProps.concat( [ "marginLeft", "marginRight" ] );
3531
3532		// Only animate children with width attributes specified
3533		// TODO: is this right? should we include anything with css width specified as well
3534		element.find( "*[width]" ).each( function() {
3535			var child = $( this ),
3536				childOriginal = $.effects.scaledDimensions( child ),
3537				childFrom = {
3538					height: childOriginal.height * factor.from.y,
3539					width: childOriginal.width * factor.from.x,
3540					outerHeight: childOriginal.outerHeight * factor.from.y,
3541					outerWidth: childOriginal.outerWidth * factor.from.x
3542				},
3543				childTo = {
3544					height: childOriginal.height * factor.to.y,
3545					width: childOriginal.width * factor.to.x,
3546					outerHeight: childOriginal.height * factor.to.y,
3547					outerWidth: childOriginal.width * factor.to.x
3548				};
3549
3550			// Vertical props scaling
3551			if ( factor.from.y !== factor.to.y ) {
3552				childFrom = $.effects.setTransition( child, vProps, factor.from.y, childFrom );
3553				childTo = $.effects.setTransition( child, vProps, factor.to.y, childTo );
3554			}
3555
3556			// Horizontal props scaling
3557			if ( factor.from.x !== factor.to.x ) {
3558				childFrom = $.effects.setTransition( child, hProps, factor.from.x, childFrom );
3559				childTo = $.effects.setTransition( child, hProps, factor.to.x, childTo );
3560			}
3561
3562			if ( restore ) {
3563				$.effects.saveStyle( child );
3564			}
3565
3566			// Animate children
3567			child.css( childFrom );
3568			child.animate( childTo, options.duration, options.easing, function() {
3569
3570				// Restore children
3571				if ( restore ) {
3572					$.effects.restoreStyle( child );
3573				}
3574			} );
3575		} );
3576	}
3577
3578	// Animate
3579	element.animate( to, {
3580		queue: false,
3581		duration: options.duration,
3582		easing: options.easing,
3583		complete: function() {
3584
3585			var offset = element.offset();
3586
3587			if ( to.opacity === 0 ) {
3588				element.css( "opacity", from.opacity );
3589			}
3590
3591			if ( !restore ) {
3592				element
3593					.css( "position", position === "static" ? "relative" : position )
3594					.offset( offset );
3595
3596				// Need to save style here so that automatic style restoration
3597				// doesn't restore to the original styles from before the animation.
3598				$.effects.saveStyle( element );
3599			}
3600
3601			done();
3602		}
3603	} );
3604
3605} );
3606
3607
3608/*!
3609 * jQuery UI Effects Scale 1.12.1
3610 * http://jqueryui.com
3611 *
3612 * Copyright jQuery Foundation and other contributors
3613 * Released under the MIT license.
3614 * http://jquery.org/license
3615 */
3616
3617//>>label: Scale Effect
3618//>>group: Effects
3619//>>description: Grows or shrinks an element and its content.
3620//>>docs: http://api.jqueryui.com/scale-effect/
3621//>>demos: http://jqueryui.com/effect/
3622
3623
3624
3625var effectsEffectScale = $.effects.define( "scale", function( options, done ) {
3626
3627	// Create element
3628	var el = $( this ),
3629		mode = options.mode,
3630		percent = parseInt( options.percent, 10 ) ||
3631			( parseInt( options.percent, 10 ) === 0 ? 0 : ( mode !== "effect" ? 0 : 100 ) ),
3632
3633		newOptions = $.extend( true, {
3634			from: $.effects.scaledDimensions( el ),
3635			to: $.effects.scaledDimensions( el, percent, options.direction || "both" ),
3636			origin: options.origin || [ "middle", "center" ]
3637		}, options );
3638
3639	// Fade option to support puff
3640	if ( options.fade ) {
3641		newOptions.from.opacity = 1;
3642		newOptions.to.opacity = 0;
3643	}
3644
3645	$.effects.effect.size.call( this, newOptions, done );
3646} );
3647
3648
3649/*!
3650 * jQuery UI Effects Puff 1.12.1
3651 * http://jqueryui.com
3652 *
3653 * Copyright jQuery Foundation and other contributors
3654 * Released under the MIT license.
3655 * http://jquery.org/license
3656 */
3657
3658//>>label: Puff Effect
3659//>>group: Effects
3660//>>description: Creates a puff effect by scaling the element up and hiding it at the same time.
3661//>>docs: http://api.jqueryui.com/puff-effect/
3662//>>demos: http://jqueryui.com/effect/
3663
3664
3665
3666var effectsEffectPuff = $.effects.define( "puff", "hide", function( options, done ) {
3667	var newOptions = $.extend( true, {}, options, {
3668		fade: true,
3669		percent: parseInt( options.percent, 10 ) || 150
3670	} );
3671
3672	$.effects.effect.scale.call( this, newOptions, done );
3673} );
3674
3675
3676/*!
3677 * jQuery UI Effects Pulsate 1.12.1
3678 * http://jqueryui.com
3679 *
3680 * Copyright jQuery Foundation and other contributors
3681 * Released under the MIT license.
3682 * http://jquery.org/license
3683 */
3684
3685//>>label: Pulsate Effect
3686//>>group: Effects
3687//>>description: Pulsates an element n times by changing the opacity to zero and back.
3688//>>docs: http://api.jqueryui.com/pulsate-effect/
3689//>>demos: http://jqueryui.com/effect/
3690
3691
3692
3693var effectsEffectPulsate = $.effects.define( "pulsate", "show", function( options, done ) {
3694	var element = $( this ),
3695		mode = options.mode,
3696		show = mode === "show",
3697		hide = mode === "hide",
3698		showhide = show || hide,
3699
3700		// Showing or hiding leaves off the "last" animation
3701		anims = ( ( options.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ),
3702		duration = options.duration / anims,
3703		animateTo = 0,
3704		i = 1,
3705		queuelen = element.queue().length;
3706
3707	if ( show || !element.is( ":visible" ) ) {
3708		element.css( "opacity", 0 ).show();
3709		animateTo = 1;
3710	}
3711
3712	// Anims - 1 opacity "toggles"
3713	for ( ; i < anims; i++ ) {
3714		element.animate( { opacity: animateTo }, duration, options.easing );
3715		animateTo = 1 - animateTo;
3716	}
3717
3718	element.animate( { opacity: animateTo }, duration, options.easing );
3719
3720	element.queue( done );
3721
3722	$.effects.unshift( element, queuelen, anims + 1 );
3723} );
3724
3725
3726/*!
3727 * jQuery UI Effects Shake 1.12.1
3728 * http://jqueryui.com
3729 *
3730 * Copyright jQuery Foundation and other contributors
3731 * Released under the MIT license.
3732 * http://jquery.org/license
3733 */
3734
3735//>>label: Shake Effect
3736//>>group: Effects
3737//>>description: Shakes an element horizontally or vertically n times.
3738//>>docs: http://api.jqueryui.com/shake-effect/
3739//>>demos: http://jqueryui.com/effect/
3740
3741
3742
3743var effectsEffectShake = $.effects.define( "shake", function( options, done ) {
3744
3745	var i = 1,
3746		element = $( this ),
3747		direction = options.direction || "left",
3748		distance = options.distance || 20,
3749		times = options.times || 3,
3750		anims = times * 2 + 1,
3751		speed = Math.round( options.duration / anims ),
3752		ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
3753		positiveMotion = ( direction === "up" || direction === "left" ),
3754		animation = {},
3755		animation1 = {},
3756		animation2 = {},
3757
3758		queuelen = element.queue().length;
3759
3760	$.effects.createPlaceholder( element );
3761
3762	// Animation
3763	animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance;
3764	animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2;
3765	animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2;
3766
3767	// Animate
3768	element.animate( animation, speed, options.easing );
3769
3770	// Shakes
3771	for ( ; i < times; i++ ) {
3772		element
3773			.animate( animation1, speed, options.easing )
3774			.animate( animation2, speed, options.easing );
3775	}
3776
3777	element
3778		.animate( animation1, speed, options.easing )
3779		.animate( animation, speed / 2, options.easing )
3780		.queue( done );
3781
3782	$.effects.unshift( element, queuelen, anims + 1 );
3783} );
3784
3785
3786/*!
3787 * jQuery UI Effects Slide 1.12.1
3788 * http://jqueryui.com
3789 *
3790 * Copyright jQuery Foundation and other contributors
3791 * Released under the MIT license.
3792 * http://jquery.org/license
3793 */
3794
3795//>>label: Slide Effect
3796//>>group: Effects
3797//>>description: Slides an element in and out of the viewport.
3798//>>docs: http://api.jqueryui.com/slide-effect/
3799//>>demos: http://jqueryui.com/effect/
3800
3801
3802
3803var effectsEffectSlide = $.effects.define( "slide", "show", function( options, done ) {
3804	var startClip, startRef,
3805		element = $( this ),
3806		map = {
3807			up: [ "bottom", "top" ],
3808			down: [ "top", "bottom" ],
3809			left: [ "right", "left" ],
3810			right: [ "left", "right" ]
3811		},
3812		mode = options.mode,
3813		direction = options.direction || "left",
3814		ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
3815		positiveMotion = ( direction === "up" || direction === "left" ),
3816		distance = options.distance ||
3817			element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ),
3818		animation = {};
3819
3820	$.effects.createPlaceholder( element );
3821
3822	startClip = element.cssClip();
3823	startRef = element.position()[ ref ];
3824
3825	// Define hide animation
3826	animation[ ref ] = ( positiveMotion ? -1 : 1 ) * distance + startRef;
3827	animation.clip = element.cssClip();
3828	animation.clip[ map[ direction ][ 1 ] ] = animation.clip[ map[ direction ][ 0 ] ];
3829
3830	// Reverse the animation if we're showing
3831	if ( mode === "show" ) {
3832		element.cssClip( animation.clip );
3833		element.css( ref, animation[ ref ] );
3834		animation.clip = startClip;
3835		animation[ ref ] = startRef;
3836	}
3837
3838	// Actually animate
3839	element.animate( animation, {
3840		queue: false,
3841		duration: options.duration,
3842		easing: options.easing,
3843		complete: done
3844	} );
3845} );
3846
3847
3848/*!
3849 * jQuery UI Effects Transfer 1.12.1
3850 * http://jqueryui.com
3851 *
3852 * Copyright jQuery Foundation and other contributors
3853 * Released under the MIT license.
3854 * http://jquery.org/license
3855 */
3856
3857//>>label: Transfer Effect
3858//>>group: Effects
3859//>>description: Displays a transfer effect from one element to another.
3860//>>docs: http://api.jqueryui.com/transfer-effect/
3861//>>demos: http://jqueryui.com/effect/
3862
3863
3864
3865var effect;
3866if ( $.uiBackCompat !== false ) {
3867	effect = $.effects.define( "transfer", function( options, done ) {
3868		$( this ).transfer( options, done );
3869	} );
3870}
3871var effectsEffectTransfer = effect;
3872
3873
3874/*!
3875 * jQuery UI Focusable 1.12.1
3876 * http://jqueryui.com
3877 *
3878 * Copyright jQuery Foundation and other contributors
3879 * Released under the MIT license.
3880 * http://jquery.org/license
3881 */
3882
3883//>>label: :focusable Selector
3884//>>group: Core
3885//>>description: Selects elements which can be focused.
3886//>>docs: http://api.jqueryui.com/focusable-selector/
3887
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" ) && visible( $( element ) );
3926};
3927
3928// Support: IE 8 only
3929// IE 8 doesn't resolve inherit to visible/hidden for computed values
3930function visible( element ) {
3931	var visibility = element.css( "visibility" );
3932	while ( visibility === "inherit" ) {
3933		element = element.parent();
3934		visibility = element.css( "visibility" );
3935	}
3936	return visibility !== "hidden";
3937}
3938
3939$.extend( $.expr[ ":" ], {
3940	focusable: function( element ) {
3941		return $.ui.focusable( element, $.attr( element, "tabindex" ) != null );
3942	}
3943} );
3944
3945var focusable = $.ui.focusable;
3946
3947
3948
3949
3950// Support: IE8 Only
3951// IE8 does not support the form attribute and when it is supplied. It overwrites the form prop
3952// with a string, so we need to find the proper form.
3953var form = $.fn.form = function() {
3954	return typeof this[ 0 ].form === "string" ? this.closest( "form" ) : $( this[ 0 ].form );
3955};
3956
3957
3958/*!
3959 * jQuery UI Form Reset Mixin 1.12.1
3960 * http://jqueryui.com
3961 *
3962 * Copyright jQuery Foundation and other contributors
3963 * Released under the MIT license.
3964 * http://jquery.org/license
3965 */
3966
3967//>>label: Form Reset Mixin
3968//>>group: Core
3969//>>description: Refresh input widgets when their form is reset
3970//>>docs: http://api.jqueryui.com/form-reset-mixin/
3971
3972
3973
3974var formResetMixin = $.ui.formResetMixin = {
3975	_formResetHandler: function() {
3976		var form = $( this );
3977
3978		// Wait for the form reset to actually happen before refreshing
3979		setTimeout( function() {
3980			var instances = form.data( "ui-form-reset-instances" );
3981			$.each( instances, function() {
3982				this.refresh();
3983			} );
3984		} );
3985	},
3986
3987	_bindFormResetHandler: function() {
3988		this.form = this.element.form();
3989		if ( !this.form.length ) {
3990			return;
3991		}
3992
3993		var instances = this.form.data( "ui-form-reset-instances" ) || [];
3994		if ( !instances.length ) {
3995
3996			// We don't use _on() here because we use a single event handler per form
3997			this.form.on( "reset.ui-form-reset", this._formResetHandler );
3998		}
3999		instances.push( this );
4000		this.form.data( "ui-form-reset-instances", instances );
4001	},
4002
4003	_unbindFormResetHandler: function() {
4004		if ( !this.form.length ) {
4005			return;
4006		}
4007
4008		var instances = this.form.data( "ui-form-reset-instances" );
4009		instances.splice( $.inArray( this, instances ), 1 );
4010		if ( instances.length ) {
4011			this.form.data( "ui-form-reset-instances", instances );
4012		} else {
4013			this.form
4014				.removeData( "ui-form-reset-instances" )
4015				.off( "reset.ui-form-reset" );
4016		}
4017	}
4018};
4019
4020
4021/*!
4022 * jQuery UI Support for jQuery core 1.7.x 1.12.1
4023 * http://jqueryui.com
4024 *
4025 * Copyright jQuery Foundation and other contributors
4026 * Released under the MIT license.
4027 * http://jquery.org/license
4028 *
4029 */
4030
4031//>>label: jQuery 1.7 Support
4032//>>group: Core
4033//>>description: Support version 1.7.x of jQuery core
4034
4035
4036
4037// Support: jQuery 1.7 only
4038// Not a great way to check versions, but since we only support 1.7+ and only
4039// need to detect <1.8, this is a simple check that should suffice. Checking
4040// for "1.7." would be a bit safer, but the version string is 1.7, not 1.7.0
4041// and we'll never reach 1.70.0 (if we do, we certainly won't be supporting
4042// 1.7 anymore). See #11197 for why we're not using feature detection.
4043if ( $.fn.jquery.substring( 0, 3 ) === "1.7" ) {
4044
4045	// Setters for .innerWidth(), .innerHeight(), .outerWidth(), .outerHeight()
4046	// Unlike jQuery Core 1.8+, these only support numeric values to set the
4047	// dimensions in pixels
4048	$.each( [ "Width", "Height" ], function( i, name ) {
4049		var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
4050			type = name.toLowerCase(),
4051			orig = {
4052				innerWidth: $.fn.innerWidth,
4053				innerHeight: $.fn.innerHeight,
4054				outerWidth: $.fn.outerWidth,
4055				outerHeight: $.fn.outerHeight
4056			};
4057
4058		function reduce( elem, size, border, margin ) {
4059			$.each( side, function() {
4060				size -= parseFloat( $.css( elem, "padding" + this ) ) || 0;
4061				if ( border ) {
4062					size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0;
4063				}
4064				if ( margin ) {
4065					size -= parseFloat( $.css( elem, "margin" + this ) ) || 0;
4066				}
4067			} );
4068			return size;
4069		}
4070
4071		$.fn[ "inner" + name ] = function( size ) {
4072			if ( size === undefined ) {
4073				return orig[ "inner" + name ].call( this );
4074			}
4075
4076			return this.each( function() {
4077				$( this ).css( type, reduce( this, size ) + "px" );
4078			} );
4079		};
4080
4081		$.fn[ "outer" + name ] = function( size, margin ) {
4082			if ( typeof size !== "number" ) {
4083				return orig[ "outer" + name ].call( this, size );
4084			}
4085
4086			return this.each( function() {
4087				$( this ).css( type, reduce( this, size, true, margin ) + "px" );
4088			} );
4089		};
4090	} );
4091
4092	$.fn.addBack = function( selector ) {
4093		return this.add( selector == null ?
4094			this.prevObject : this.prevObject.filter( selector )
4095		);
4096	};
4097}
4098
4099;
4100/*!
4101 * jQuery UI Keycode 1.12.1
4102 * http://jqueryui.com
4103 *
4104 * Copyright jQuery Foundation and other contributors
4105 * Released under the MIT license.
4106 * http://jquery.org/license
4107 */
4108
4109//>>label: Keycode
4110//>>group: Core
4111//>>description: Provide keycodes as keynames
4112//>>docs: http://api.jqueryui.com/jQuery.ui.keyCode/
4113
4114
4115var keycode = $.ui.keyCode = {
4116	BACKSPACE: 8,
4117	COMMA: 188,
4118	DELETE: 46,
4119	DOWN: 40,
4120	END: 35,
4121	ENTER: 13,
4122	ESCAPE: 27,
4123	HOME: 36,
4124	LEFT: 37,
4125	PAGE_DOWN: 34,
4126	PAGE_UP: 33,
4127	PERIOD: 190,
4128	RIGHT: 39,
4129	SPACE: 32,
4130	TAB: 9,
4131	UP: 38
4132};
4133
4134
4135
4136
4137// Internal use only
4138var escapeSelector = $.ui.escapeSelector = ( function() {
4139	var selectorEscape = /([!"#$%&'()*+,./:;<=>?@[\]^`{|}~])/g;
4140	return function( selector ) {
4141		return selector.replace( selectorEscape, "\\$1" );
4142	};
4143} )();
4144
4145
4146/*!
4147 * jQuery UI Labels 1.12.1
4148 * http://jqueryui.com
4149 *
4150 * Copyright jQuery Foundation and other contributors
4151 * Released under the MIT license.
4152 * http://jquery.org/license
4153 */
4154
4155//>>label: labels
4156//>>group: Core
4157//>>description: Find all the labels associated with a given input
4158//>>docs: http://api.jqueryui.com/labels/
4159
4160
4161
4162var labels = $.fn.labels = function() {
4163	var ancestor, selector, id, labels, ancestors;
4164
4165	// Check control.labels first
4166	if ( this[ 0 ].labels && this[ 0 ].labels.length ) {
4167		return this.pushStack( this[ 0 ].labels );
4168	}
4169
4170	// Support: IE <= 11, FF <= 37, Android <= 2.3 only
4171	// Above browsers do not support control.labels. Everything below is to support them
4172	// as well as document fragments. control.labels does not work on document fragments
4173	labels = this.eq( 0 ).parents( "label" );
4174
4175	// Look for the label based on the id
4176	id = this.attr( "id" );
4177	if ( id ) {
4178
4179		// We don't search against the document in case the element
4180		// is disconnected from the DOM
4181		ancestor = this.eq( 0 ).parents().last();
4182
4183		// Get a full set of top level ancestors
4184		ancestors = ancestor.add( ancestor.length ? ancestor.siblings() : this.siblings() );
4185
4186		// Create a selector for the label based on the id
4187		selector = "label[for='" + $.ui.escapeSelector( id ) + "']";
4188
4189		labels = labels.add( ancestors.find( selector ).addBack( selector ) );
4190
4191	}
4192
4193	// Return whatever we have found for labels
4194	return this.pushStack( labels );
4195};
4196
4197
4198/*!
4199 * jQuery UI Scroll Parent 1.12.1
4200 * http://jqueryui.com
4201 *
4202 * Copyright jQuery Foundation and other contributors
4203 * Released under the MIT license.
4204 * http://jquery.org/license
4205 */
4206
4207//>>label: scrollParent
4208//>>group: Core
4209//>>description: Get the closest ancestor element that is scrollable.
4210//>>docs: http://api.jqueryui.com/scrollParent/
4211
4212
4213
4214var scrollParent = $.fn.scrollParent = function( includeHidden ) {
4215	var position = this.css( "position" ),
4216		excludeStaticParent = position === "absolute",
4217		overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/,
4218		scrollParent = this.parents().filter( function() {
4219			var parent = $( this );
4220			if ( excludeStaticParent && parent.css( "position" ) === "static" ) {
4221				return false;
4222			}
4223			return overflowRegex.test( parent.css( "overflow" ) + parent.css( "overflow-y" ) +
4224				parent.css( "overflow-x" ) );
4225		} ).eq( 0 );
4226
4227	return position === "fixed" || !scrollParent.length ?
4228		$( this[ 0 ].ownerDocument || document ) :
4229		scrollParent;
4230};
4231
4232
4233/*!
4234 * jQuery UI Tabbable 1.12.1
4235 * http://jqueryui.com
4236 *
4237 * Copyright jQuery Foundation and other contributors
4238 * Released under the MIT license.
4239 * http://jquery.org/license
4240 */
4241
4242//>>label: :tabbable Selector
4243//>>group: Core
4244//>>description: Selects elements which can be tabbed to.
4245//>>docs: http://api.jqueryui.com/tabbable-selector/
4246
4247
4248
4249var tabbable = $.extend( $.expr[ ":" ], {
4250	tabbable: function( element ) {
4251		var tabIndex = $.attr( element, "tabindex" ),
4252			hasTabindex = tabIndex != null;
4253		return ( !hasTabindex || tabIndex >= 0 ) && $.ui.focusable( element, hasTabindex );
4254	}
4255} );
4256
4257
4258/*!
4259 * jQuery UI Unique ID 1.12.1
4260 * http://jqueryui.com
4261 *
4262 * Copyright jQuery Foundation and other contributors
4263 * Released under the MIT license.
4264 * http://jquery.org/license
4265 */
4266
4267//>>label: uniqueId
4268//>>group: Core
4269//>>description: Functions to generate and remove uniqueId's
4270//>>docs: http://api.jqueryui.com/uniqueId/
4271
4272
4273
4274var uniqueId = $.fn.extend( {
4275	uniqueId: ( function() {
4276		var uuid = 0;
4277
4278		return function() {
4279			return this.each( function() {
4280				if ( !this.id ) {
4281					this.id = "ui-id-" + ( ++uuid );
4282				}
4283			} );
4284		};
4285	} )(),
4286
4287	removeUniqueId: function() {
4288		return this.each( function() {
4289			if ( /^ui-id-\d+$/.test( this.id ) ) {
4290				$( this ).removeAttr( "id" );
4291			}
4292		} );
4293	}
4294} );
4295
4296
4297/*!
4298 * jQuery UI Accordion 1.12.1
4299 * http://jqueryui.com
4300 *
4301 * Copyright jQuery Foundation and other contributors
4302 * Released under the MIT license.
4303 * http://jquery.org/license
4304 */
4305
4306//>>label: Accordion
4307//>>group: Widgets
4308// jscs:disable maximumLineLength
4309//>>description: Displays collapsible content panels for presenting information in a limited amount of space.
4310// jscs:enable maximumLineLength
4311//>>docs: http://api.jqueryui.com/accordion/
4312//>>demos: http://jqueryui.com/accordion/
4313//>>css.structure: ../../themes/base/core.css
4314//>>css.structure: ../../themes/base/accordion.css
4315//>>css.theme: ../../themes/base/theme.css
4316
4317
4318
4319var widgetsAccordion = $.widget( "ui.accordion", {
4320	version: "1.12.1",
4321	options: {
4322		active: 0,
4323		animate: {},
4324		classes: {
4325			"ui-accordion-header": "ui-corner-top",
4326			"ui-accordion-header-collapsed": "ui-corner-all",
4327			"ui-accordion-content": "ui-corner-bottom"
4328		},
4329		collapsible: false,
4330		event: "click",
4331		header: "> li > :first-child, > :not(li):even",
4332		heightStyle: "auto",
4333		icons: {
4334			activeHeader: "ui-icon-triangle-1-s",
4335			header: "ui-icon-triangle-1-e"
4336		},
4337
4338		// Callbacks
4339		activate: null,
4340		beforeActivate: null
4341	},
4342
4343	hideProps: {
4344		borderTopWidth: "hide",
4345		borderBottomWidth: "hide",
4346		paddingTop: "hide",
4347		paddingBottom: "hide",
4348		height: "hide"
4349	},
4350
4351	showProps: {
4352		borderTopWidth: "show",
4353		borderBottomWidth: "show",
4354		paddingTop: "show",
4355		paddingBottom: "show",
4356		height: "show"
4357	},
4358
4359	_create: function() {
4360		var options = this.options;
4361
4362		this.prevShow = this.prevHide = $();
4363		this._addClass( "ui-accordion", "ui-widget ui-helper-reset" );
4364		this.element.attr( "role", "tablist" );
4365
4366		// Don't allow collapsible: false and active: false / null
4367		if ( !options.collapsible && ( options.active === false || options.active == null ) ) {
4368			options.active = 0;
4369		}
4370
4371		this._processPanels();
4372
4373		// handle negative values
4374		if ( options.active < 0 ) {
4375			options.active += this.headers.length;
4376		}
4377		this._refresh();
4378	},
4379
4380	_getCreateEventData: function() {
4381		return {
4382			header: this.active,
4383			panel: !this.active.length ? $() : this.active.next()
4384		};
4385	},
4386
4387	_createIcons: function() {
4388		var icon, children,
4389			icons = this.options.icons;
4390
4391		if ( icons ) {
4392			icon = $( "<span>" );
4393			this._addClass( icon, "ui-accordion-header-icon", "ui-icon " + icons.header );
4394			icon.prependTo( this.headers );
4395			children = this.active.children( ".ui-accordion-header-icon" );
4396			this._removeClass( children, icons.header )
4397				._addClass( children, null, icons.activeHeader )
4398				._addClass( this.headers, "ui-accordion-icons" );
4399		}
4400	},
4401
4402	_destroyIcons: function() {
4403		this._removeClass( this.headers, "ui-accordion-icons" );
4404		this.headers.children( ".ui-accordion-header-icon" ).remove();
4405	},
4406
4407	_destroy: function() {
4408		var contents;
4409
4410		// Clean up main element
4411		this.element.removeAttr( "role" );
4412
4413		// Clean up headers
4414		this.headers
4415			.removeAttr( "role aria-expanded aria-selected aria-controls tabIndex" )
4416			.removeUniqueId();
4417
4418		this._destroyIcons();
4419
4420		// Clean up content panels
4421		contents = this.headers.next()
4422			.css( "display", "" )
4423			.removeAttr( "role aria-hidden aria-labelledby" )
4424			.removeUniqueId();
4425
4426		if ( this.options.heightStyle !== "content" ) {
4427			contents.css( "height", "" );
4428		}
4429	},
4430
4431	_setOption: function( key, value ) {
4432		if ( key === "active" ) {
4433
4434			// _activate() will handle invalid values and update this.options
4435			this._activate( value );
4436			return;
4437		}
4438
4439		if ( key === "event" ) {
4440			if ( this.options.event ) {
4441				this._off( this.headers, this.options.event );
4442			}
4443			this._setupEvents( value );
4444		}
4445
4446		this._super( key, value );
4447
4448		// Setting collapsible: false while collapsed; open first panel
4449		if ( key === "collapsible" && !value && this.options.active === false ) {
4450			this._activate( 0 );
4451		}
4452
4453		if ( key === "icons" ) {
4454			this._destroyIcons();
4455			if ( value ) {
4456				this._createIcons();
4457			}
4458		}
4459	},
4460
4461	_setOptionDisabled: function( value ) {
4462		this._super( value );
4463
4464		this.element.attr( "aria-disabled", value );
4465
4466		// Support: IE8 Only
4467		// #5332 / #6059 - opacity doesn't cascade to positioned elements in IE
4468		// so we need to add the disabled class to the headers and panels
4469		this._toggleClass( null, "ui-state-disabled", !!value );
4470		this._toggleClass( this.headers.add( this.headers.next() ), null, "ui-state-disabled",
4471			!!value );
4472	},
4473
4474	_keydown: function( event ) {
4475		if ( event.altKey || event.ctrlKey ) {
4476			return;
4477		}
4478
4479		var keyCode = $.ui.keyCode,
4480			length = this.headers.length,
4481			currentIndex = this.headers.index( event.target ),
4482			toFocus = false;
4483
4484		switch ( event.keyCode ) {
4485		case keyCode.RIGHT:
4486		case keyCode.DOWN:
4487			toFocus = this.headers[ ( currentIndex + 1 ) % length ];
4488			break;
4489		case keyCode.LEFT:
4490		case keyCode.UP:
4491			toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
4492			break;
4493		case keyCode.SPACE:
4494		case keyCode.ENTER:
4495			this._eventHandler( event );
4496			break;
4497		case keyCode.HOME:
4498			toFocus = this.headers[ 0 ];
4499			break;
4500		case keyCode.END:
4501			toFocus = this.headers[ length - 1 ];
4502			break;
4503		}
4504
4505		if ( toFocus ) {
4506			$( event.target ).attr( "tabIndex", -1 );
4507			$( toFocus ).attr( "tabIndex", 0 );
4508			$( toFocus ).trigger( "focus" );
4509			event.preventDefault();
4510		}
4511	},
4512
4513	_panelKeyDown: function( event ) {
4514		if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) {
4515			$( event.currentTarget ).prev().trigger( "focus" );
4516		}
4517	},
4518
4519	refresh: function() {
4520		var options = this.options;
4521		this._processPanels();
4522
4523		// Was collapsed or no panel
4524		if ( ( options.active === false && options.collapsible === true ) ||
4525				!this.headers.length ) {
4526			options.active = false;
4527			this.active = $();
4528
4529		// active false only when collapsible is true
4530		} else if ( options.active === false ) {
4531			this._activate( 0 );
4532
4533		// was active, but active panel is gone
4534		} else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
4535
4536			// all remaining panel are disabled
4537			if ( this.headers.length === this.headers.find( ".ui-state-disabled" ).length ) {
4538				options.active = false;
4539				this.active = $();
4540
4541			// activate previous panel
4542			} else {
4543				this._activate( Math.max( 0, options.active - 1 ) );
4544			}
4545
4546		// was active, active panel still exists
4547		} else {
4548
4549			// make sure active index is correct
4550			options.active = this.headers.index( this.active );
4551		}
4552
4553		this._destroyIcons();
4554
4555		this._refresh();
4556	},
4557
4558	_processPanels: function() {
4559		var prevHeaders = this.headers,
4560			prevPanels = this.panels;
4561
4562		this.headers = this.element.find( this.options.header );
4563		this._addClass( this.headers, "ui-accordion-header ui-accordion-header-collapsed",
4564			"ui-state-default" );
4565
4566		this.panels = this.headers.next().filter( ":not(.ui-accordion-content-active)" ).hide();
4567		this._addClass( this.panels, "ui-accordion-content", "ui-helper-reset ui-widget-content" );
4568
4569		// Avoid memory leaks (#10056)
4570		if ( prevPanels ) {
4571			this._off( prevHeaders.not( this.headers ) );
4572			this._off( prevPanels.not( this.panels ) );
4573		}
4574	},
4575
4576	_refresh: function() {
4577		var maxHeight,
4578			options = this.options,
4579			heightStyle = options.heightStyle,
4580			parent = this.element.parent();
4581
4582		this.active = this._findActive( options.active );
4583		this._addClass( this.active, "ui-accordion-header-active", "ui-state-active" )
4584			._removeClass( this.active, "ui-accordion-header-collapsed" );
4585		this._addClass( this.active.next(), "ui-accordion-content-active" );
4586		this.active.next().show();
4587
4588		this.headers
4589			.attr( "role", "tab" )
4590			.each( function() {
4591				var header = $( this ),
4592					headerId = header.uniqueId().attr( "id" ),
4593					panel = header.next(),
4594					panelId = panel.uniqueId().attr( "id" );
4595				header.attr( "aria-controls", panelId );
4596				panel.attr( "aria-labelledby", headerId );
4597			} )
4598			.next()
4599				.attr( "role", "tabpanel" );
4600
4601		this.headers
4602			.not( this.active )
4603				.attr( {
4604					"aria-selected": "false",
4605					"aria-expanded": "false",
4606					tabIndex: -1
4607				} )
4608				.next()
4609					.attr( {
4610						"aria-hidden": "true"
4611					} )
4612					.hide();
4613
4614		// Make sure at least one header is in the tab order
4615		if ( !this.active.length ) {
4616			this.headers.eq( 0 ).attr( "tabIndex", 0 );
4617		} else {
4618			this.active.attr( {
4619				"aria-selected": "true",
4620				"aria-expanded": "true",
4621				tabIndex: 0
4622			} )
4623				.next()
4624					.attr( {
4625						"aria-hidden": "false"
4626					} );
4627		}
4628
4629		this._createIcons();
4630
4631		this._setupEvents( options.event );
4632
4633		if ( heightStyle === "fill" ) {
4634			maxHeight = parent.height();
4635			this.element.siblings( ":visible" ).each( function() {
4636				var elem = $( this ),
4637					position = elem.css( "position" );
4638
4639				if ( position === "absolute" || position === "fixed" ) {
4640					return;
4641				}
4642				maxHeight -= elem.outerHeight( true );
4643			} );
4644
4645			this.headers.each( function() {
4646				maxHeight -= $( this ).outerHeight( true );
4647			} );
4648
4649			this.headers.next()
4650				.each( function() {
4651					$( this ).height( Math.max( 0, maxHeight -
4652						$( this ).innerHeight() + $( this ).height() ) );
4653				} )
4654				.css( "overflow", "auto" );
4655		} else if ( heightStyle === "auto" ) {
4656			maxHeight = 0;
4657			this.headers.next()
4658				.each( function() {
4659					var isVisible = $( this ).is( ":visible" );
4660					if ( !isVisible ) {
4661						$( this ).show();
4662					}
4663					maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() );
4664					if ( !isVisible ) {
4665						$( this ).hide();
4666					}
4667				} )
4668				.height( maxHeight );
4669		}
4670	},
4671
4672	_activate: function( index ) {
4673		var active = this._findActive( index )[ 0 ];
4674
4675		// Trying to activate the already active panel
4676		if ( active === this.active[ 0 ] ) {
4677			return;
4678		}
4679
4680		// Trying to collapse, simulate a click on the currently active header
4681		active = active || this.active[ 0 ];
4682
4683		this._eventHandler( {
4684			target: active,
4685			currentTarget: active,
4686			preventDefault: $.noop
4687		} );
4688	},
4689
4690	_findActive: function( selector ) {
4691		return typeof selector === "number" ? this.headers.eq( selector ) : $();
4692	},
4693
4694	_setupEvents: function( event ) {
4695		var events = {
4696			keydown: "_keydown"
4697		};
4698		if ( event ) {
4699			$.each( event.split( " " ), function( index, eventName ) {
4700				events[ eventName ] = "_eventHandler";
4701			} );
4702		}
4703
4704		this._off( this.headers.add( this.headers.next() ) );
4705		this._on( this.headers, events );
4706		this._on( this.headers.next(), { keydown: "_panelKeyDown" } );
4707		this._hoverable( this.headers );
4708		this._focusable( this.headers );
4709	},
4710
4711	_eventHandler: function( event ) {
4712		var activeChildren, clickedChildren,
4713			options = this.options,
4714			active = this.active,
4715			clicked = $( event.currentTarget ),
4716			clickedIsActive = clicked[ 0 ] === active[ 0 ],
4717			collapsing = clickedIsActive && options.collapsible,
4718			toShow = collapsing ? $() : clicked.next(),
4719			toHide = active.next(),
4720			eventData = {
4721				oldHeader: active,
4722				oldPanel: toHide,
4723				newHeader: collapsing ? $() : clicked,
4724				newPanel: toShow
4725			};
4726
4727		event.preventDefault();
4728
4729		if (
4730
4731				// click on active header, but not collapsible
4732				( clickedIsActive && !options.collapsible ) ||
4733
4734				// allow canceling activation
4735				( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
4736			return;
4737		}
4738
4739		options.active = collapsing ? false : this.headers.index( clicked );
4740
4741		// When the call to ._toggle() comes after the class changes
4742		// it causes a very odd bug in IE 8 (see #6720)
4743		this.active = clickedIsActive ? $() : clicked;
4744		this._toggle( eventData );
4745
4746		// Switch classes
4747		// corner classes on the previously active header stay after the animation
4748		this._removeClass( active, "ui-accordion-header-active", "ui-state-active" );
4749		if ( options.icons ) {
4750			activeChildren = active.children( ".ui-accordion-header-icon" );
4751			this._removeClass( activeChildren, null, options.icons.activeHeader )
4752				._addClass( activeChildren, null, options.icons.header );
4753		}
4754
4755		if ( !clickedIsActive ) {
4756			this._removeClass( clicked, "ui-accordion-header-collapsed" )
4757				._addClass( clicked, "ui-accordion-header-active", "ui-state-active" );
4758			if ( options.icons ) {
4759				clickedChildren = clicked.children( ".ui-accordion-header-icon" );
4760				this._removeClass( clickedChildren, null, options.icons.header )
4761					._addClass( clickedChildren, null, options.icons.activeHeader );
4762			}
4763
4764			this._addClass( clicked.next(), "ui-accordion-content-active" );
4765		}
4766	},
4767
4768	_toggle: function( data ) {
4769		var toShow = data.newPanel,
4770			toHide = this.prevShow.length ? this.prevShow : data.oldPanel;
4771
4772		// Handle activating a panel during the animation for another activation
4773		this.prevShow.add( this.prevHide ).stop( true, true );
4774		this.prevShow = toShow;
4775		this.prevHide = toHide;
4776
4777		if ( this.options.animate ) {
4778			this._animate( toShow, toHide, data );
4779		} else {
4780			toHide.hide();
4781			toShow.show();
4782			this._toggleComplete( data );
4783		}
4784
4785		toHide.attr( {
4786			"aria-hidden": "true"
4787		} );
4788		toHide.prev().attr( {
4789			"aria-selected": "false",
4790			"aria-expanded": "false"
4791		} );
4792
4793		// if we're switching panels, remove the old header from the tab order
4794		// if we're opening from collapsed state, remove the previous header from the tab order
4795		// if we're collapsing, then keep the collapsing header in the tab order
4796		if ( toShow.length && toHide.length ) {
4797			toHide.prev().attr( {
4798				"tabIndex": -1,
4799				"aria-expanded": "false"
4800			} );
4801		} else if ( toShow.length ) {
4802			this.headers.filter( function() {
4803				return parseInt( $( this ).attr( "tabIndex" ), 10 ) === 0;
4804			} )
4805				.attr( "tabIndex", -1 );
4806		}
4807
4808		toShow
4809			.attr( "aria-hidden", "false" )
4810			.prev()
4811				.attr( {
4812					"aria-selected": "true",
4813					"aria-expanded": "true",
4814					tabIndex: 0
4815				} );
4816	},
4817
4818	_animate: function( toShow, toHide, data ) {
4819		var total, easing, duration,
4820			that = this,
4821			adjust = 0,
4822			boxSizing = toShow.css( "box-sizing" ),
4823			down = toShow.length &&
4824				( !toHide.length || ( toShow.index() < toHide.index() ) ),
4825			animate = this.options.animate || {},
4826			options = down && animate.down || animate,
4827			complete = function() {
4828				that._toggleComplete( data );
4829			};
4830
4831		if ( typeof options === "number" ) {
4832			duration = options;
4833		}
4834		if ( typeof options === "string" ) {
4835			easing = options;
4836		}
4837
4838		// fall back from options to animation in case of partial down settings
4839		easing = easing || options.easing || animate.easing;
4840		duration = duration || options.duration || animate.duration;
4841
4842		if ( !toHide.length ) {
4843			return toShow.animate( this.showProps, duration, easing, complete );
4844		}
4845		if ( !toShow.length ) {
4846			return toHide.animate( this.hideProps, duration, easing, complete );
4847		}
4848
4849		total = toShow.show().outerHeight();
4850		toHide.animate( this.hideProps, {
4851			duration: duration,
4852			easing: easing,
4853			step: function( now, fx ) {
4854				fx.now = Math.round( now );
4855			}
4856		} );
4857		toShow
4858			.hide()
4859			.animate( this.showProps, {
4860				duration: duration,
4861				easing: easing,
4862				complete: complete,
4863				step: function( now, fx ) {
4864					fx.now = Math.round( now );
4865					if ( fx.prop !== "height" ) {
4866						if ( boxSizing === "content-box" ) {
4867							adjust += fx.now;
4868						}
4869					} else if ( that.options.heightStyle !== "content" ) {
4870						fx.now = Math.round( total - toHide.outerHeight() - adjust );
4871						adjust = 0;
4872					}
4873				}
4874			} );
4875	},
4876
4877	_toggleComplete: function( data ) {
4878		var toHide = data.oldPanel,
4879			prev = toHide.prev();
4880
4881		this._removeClass( toHide, "ui-accordion-content-active" );
4882		this._removeClass( prev, "ui-accordion-header-active" )
4883			._addClass( prev, "ui-accordion-header-collapsed" );
4884
4885		// Work around for rendering bug in IE (#5421)
4886		if ( toHide.length ) {
4887			toHide.parent()[ 0 ].className = toHide.parent()[ 0 ].className;
4888		}
4889		this._trigger( "activate", null, data );
4890	}
4891} );
4892
4893
4894
4895var safeActiveElement = $.ui.safeActiveElement = function( document ) {
4896	var activeElement;
4897
4898	// Support: IE 9 only
4899	// IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe>
4900	try {
4901		activeElement = document.activeElement;
4902	} catch ( error ) {
4903		activeElement = document.body;
4904	}
4905
4906	// Support: IE 9 - 11 only
4907	// IE may return null instead of an element
4908	// Interestingly, this only seems to occur when NOT in an iframe
4909	if ( !activeElement ) {
4910		activeElement = document.body;
4911	}
4912
4913	// Support: IE 11 only
4914	// IE11 returns a seemingly empty object in some cases when accessing
4915	// document.activeElement from an <iframe>
4916	if ( !activeElement.nodeName ) {
4917		activeElement = document.body;
4918	}
4919
4920	return activeElement;
4921};
4922
4923
4924/*!
4925 * jQuery UI Menu 1.12.1
4926 * http://jqueryui.com
4927 *
4928 * Copyright jQuery Foundation and other contributors
4929 * Released under the MIT license.
4930 * http://jquery.org/license
4931 */
4932
4933//>>label: Menu
4934//>>group: Widgets
4935//>>description: Creates nestable menus.
4936//>>docs: http://api.jqueryui.com/menu/
4937//>>demos: http://jqueryui.com/menu/
4938//>>css.structure: ../../themes/base/core.css
4939//>>css.structure: ../../themes/base/menu.css
4940//>>css.theme: ../../themes/base/theme.css
4941
4942
4943
4944var widgetsMenu = $.widget( "ui.menu", {
4945	version: "1.12.1",
4946	defaultElement: "<ul>",
4947	delay: 300,
4948	options: {
4949		icons: {
4950			submenu: "ui-icon-caret-1-e"
4951		},
4952		items: "> *",
4953		menus: "ul",
4954		position: {
4955			my: "left top",
4956			at: "right top"
4957		},
4958		role: "menu",
4959
4960		// Callbacks
4961		blur: null,
4962		focus: null,
4963		select: null
4964	},
4965
4966	_create: function() {
4967		this.activeMenu = this.element;
4968
4969		// Flag used to prevent firing of the click handler
4970		// as the event bubbles up through nested menus
4971		this.mouseHandled = false;
4972		this.element
4973			.uniqueId()
4974			.attr( {
4975				role: this.options.role,
4976				tabIndex: 0
4977			} );
4978
4979		this._addClass( "ui-menu", "ui-widget ui-widget-content" );
4980		this._on( {
4981
4982			// Prevent focus from sticking to links inside menu after clicking
4983			// them (focus should always stay on UL during navigation).
4984			"mousedown .ui-menu-item": function( event ) {
4985				event.preventDefault();
4986			},
4987			"click .ui-menu-item": function( event ) {
4988				var target = $( event.target );
4989				var active = $( $.ui.safeActiveElement( this.document[ 0 ] ) );
4990				if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) {
4991					this.select( event );
4992
4993					// Only set the mouseHandled flag if the event will bubble, see #9469.
4994					if ( !event.isPropagationStopped() ) {
4995						this.mouseHandled = true;
4996					}
4997
4998					// Open submenu on click
4999					if ( target.has( ".ui-menu" ).length ) {
5000						this.expand( event );
5001					} else if ( !this.element.is( ":focus" ) &&
5002							active.closest( ".ui-menu" ).length ) {
5003
5004						// Redirect focus to the menu
5005						this.element.trigger( "focus", [ true ] );
5006
5007						// If the active item is on the top level, let it stay active.
5008						// Otherwise, blur the active item since it is no longer visible.
5009						if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) {
5010							clearTimeout( this.timer );
5011						}
5012					}
5013				}
5014			},
5015			"mouseenter .ui-menu-item": function( event ) {
5016
5017				// Ignore mouse events while typeahead is active, see #10458.
5018				// Prevents focusing the wrong item when typeahead causes a scroll while the mouse
5019				// is over an item in the menu
5020				if ( this.previousFilter ) {
5021					return;
5022				}
5023
5024				var actualTarget = $( event.target ).closest( ".ui-menu-item" ),
5025					target = $( event.currentTarget );
5026
5027				// Ignore bubbled events on parent items, see #11641
5028				if ( actualTarget[ 0 ] !== target[ 0 ] ) {
5029					return;
5030				}
5031
5032				// Remove ui-state-active class from siblings of the newly focused menu item
5033				// to avoid a jump caused by adjacent elements both having a class with a border
5034				this._removeClass( target.siblings().children( ".ui-state-active" ),
5035					null, "ui-state-active" );
5036				this.focus( event, target );
5037			},
5038			mouseleave: "collapseAll",
5039			"mouseleave .ui-menu": "collapseAll",
5040			focus: function( event, keepActiveItem ) {
5041
5042				// If there's already an active item, keep it active
5043				// If not, activate the first item
5044				var item = this.active || this.element.find( this.options.items ).eq( 0 );
5045
5046				if ( !keepActiveItem ) {
5047					this.focus( event, item );
5048				}
5049			},
5050			blur: function( event ) {
5051				this._delay( function() {
5052					var notContained = !$.contains(
5053						this.element[ 0 ],
5054						$.ui.safeActiveElement( this.document[ 0 ] )
5055					);
5056					if ( notContained ) {
5057						this.collapseAll( event );
5058					}
5059				} );
5060			},
5061			keydown: "_keydown"
5062		} );
5063
5064		this.refresh();
5065
5066		// Clicks outside of a menu collapse any open menus
5067		this._on( this.document, {
5068			click: function( event ) {
5069				if ( this._closeOnDocumentClick( event ) ) {
5070					this.collapseAll( event );
5071				}
5072
5073				// Reset the mouseHandled flag
5074				this.mouseHandled = false;
5075			}
5076		} );
5077	},
5078
5079	_destroy: function() {
5080		var items = this.element.find( ".ui-menu-item" )
5081				.removeAttr( "role aria-disabled" ),
5082			submenus = items.children( ".ui-menu-item-wrapper" )
5083				.removeUniqueId()
5084				.removeAttr( "tabIndex role aria-haspopup" );
5085
5086		// Destroy (sub)menus
5087		this.element
5088			.removeAttr( "aria-activedescendant" )
5089			.find( ".ui-menu" ).addBack()
5090				.removeAttr( "role aria-labelledby aria-expanded aria-hidden aria-disabled " +
5091					"tabIndex" )
5092				.removeUniqueId()
5093				.show();
5094
5095		submenus.children().each( function() {
5096			var elem = $( this );
5097			if ( elem.data( "ui-menu-submenu-caret" ) ) {
5098				elem.remove();
5099			}
5100		} );
5101	},
5102
5103	_keydown: function( event ) {
5104		var match, prev, character, skip,
5105			preventDefault = true;
5106
5107		switch ( event.keyCode ) {
5108		case $.ui.keyCode.PAGE_UP:
5109			this.previousPage( event );
5110			break;
5111		case $.ui.keyCode.PAGE_DOWN:
5112			this.nextPage( event );
5113			break;
5114		case $.ui.keyCode.HOME:
5115			this._move( "first", "first", event );
5116			break;
5117		case $.ui.keyCode.END:
5118			this._move( "last", "last", event );
5119			break;
5120		case $.ui.keyCode.UP:
5121			this.previous( event );
5122			break;
5123		case $.ui.keyCode.DOWN:
5124			this.next( event );
5125			break;
5126		case $.ui.keyCode.LEFT:
5127			this.collapse( event );
5128			break;
5129		case $.ui.keyCode.RIGHT:
5130			if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
5131				this.expand( event );
5132			}
5133			break;
5134		case $.ui.keyCode.ENTER:
5135		case $.ui.keyCode.SPACE:
5136			this._activate( event );
5137			break;
5138		case $.ui.keyCode.ESCAPE:
5139			this.collapse( event );
5140			break;
5141		default:
5142			preventDefault = false;
5143			prev = this.previousFilter || "";
5144			skip = false;
5145
5146			// Support number pad values
5147			character = event.keyCode >= 96 && event.keyCode <= 105 ?
5148				( event.keyCode - 96 ).toString() : String.fromCharCode( event.keyCode );
5149
5150			clearTimeout( this.filterTimer );
5151
5152			if ( character === prev ) {
5153				skip = true;
5154			} else {
5155				character = prev + character;
5156			}
5157
5158			match = this._filterMenuItems( character );
5159			match = skip && match.index( this.active.next() ) !== -1 ?
5160				this.active.nextAll( ".ui-menu-item" ) :
5161				match;
5162
5163			// If no matches on the current filter, reset to the last character pressed
5164			// to move down the menu to the first item that starts with that character
5165			if ( !match.length ) {
5166				character = String.fromCharCode( event.keyCode );
5167				match = this._filterMenuItems( character );
5168			}
5169
5170			if ( match.length ) {
5171				this.focus( event, match );
5172				this.previousFilter = character;
5173				this.filterTimer = this._delay( function() {
5174					delete this.previousFilter;
5175				}, 1000 );
5176			} else {
5177				delete this.previousFilter;
5178			}
5179		}
5180
5181		if ( preventDefault ) {
5182			event.preventDefault();
5183		}
5184	},
5185
5186	_activate: function( event ) {
5187		if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
5188			if ( this.active.children( "[aria-haspopup='true']" ).length ) {
5189				this.expand( event );
5190			} else {
5191				this.select( event );
5192			}
5193		}
5194	},
5195
5196	refresh: function() {
5197		var menus, items, newSubmenus, newItems, newWrappers,
5198			that = this,
5199			icon = this.options.icons.submenu,
5200			submenus = this.element.find( this.options.menus );
5201
5202		this._toggleClass( "ui-menu-icons", null, !!this.element.find( ".ui-icon" ).length );
5203
5204		// Initialize nested menus
5205		newSubmenus = submenus.filter( ":not(.ui-menu)" )
5206			.hide()
5207			.attr( {
5208				role: this.options.role,
5209				"aria-hidden": "true",
5210				"aria-expanded": "false"
5211			} )
5212			.each( function() {
5213				var menu = $( this ),
5214					item = menu.prev(),
5215					submenuCaret = $( "<span>" ).data( "ui-menu-submenu-caret", true );
5216
5217				that._addClass( submenuCaret, "ui-menu-icon", "ui-icon " + icon );
5218				item
5219					.attr( "aria-haspopup", "true" )
5220					.prepend( submenuCaret );
5221				menu.attr( "aria-labelledby", item.attr( "id" ) );
5222			} );
5223
5224		this._addClass( newSubmenus, "ui-menu", "ui-widget ui-widget-content ui-front" );
5225
5226		menus = submenus.add( this.element );
5227		items = menus.find( this.options.items );
5228
5229		// Initialize menu-items containing spaces and/or dashes only as dividers
5230		items.not( ".ui-menu-item" ).each( function() {
5231			var item = $( this );
5232			if ( that._isDivider( item ) ) {
5233				that._addClass( item, "ui-menu-divider", "ui-widget-content" );
5234			}
5235		} );
5236
5237		// Don't refresh list items that are already adapted
5238		newItems = items.not( ".ui-menu-item, .ui-menu-divider" );
5239		newWrappers = newItems.children()
5240			.not( ".ui-menu" )
5241				.uniqueId()
5242				.attr( {
5243					tabIndex: -1,
5244					role: this._itemRole()
5245				} );
5246		this._addClass( newItems, "ui-menu-item" )
5247			._addClass( newWrappers, "ui-menu-item-wrapper" );
5248
5249		// Add aria-disabled attribute to any disabled menu item
5250		items.filter( ".ui-state-disabled" ).attr( "aria-disabled", "true" );
5251
5252		// If the active item has been removed, blur the menu
5253		if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
5254			this.blur();
5255		}
5256	},
5257
5258	_itemRole: function() {
5259		return {
5260			menu: "menuitem",
5261			listbox: "option"
5262		}[ this.options.role ];
5263	},
5264
5265	_setOption: function( key, value ) {
5266		if ( key === "icons" ) {
5267			var icons = this.element.find( ".ui-menu-icon" );
5268			this._removeClass( icons, null, this.options.icons.submenu )
5269				._addClass( icons, null, value.submenu );
5270		}
5271		this._super( key, value );
5272	},
5273
5274	_setOptionDisabled: function( value ) {
5275		this._super( value );
5276
5277		this.element.attr( "aria-disabled", String( value ) );
5278		this._toggleClass( null, "ui-state-disabled", !!value );
5279	},
5280
5281	focus: function( event, item ) {
5282		var nested, focused, activeParent;
5283		this.blur( event, event && event.type === "focus" );
5284
5285		this._scrollIntoView( item );
5286
5287		this.active = item.first();
5288
5289		focused = this.active.children( ".ui-menu-item-wrapper" );
5290		this._addClass( focused, null, "ui-state-active" );
5291
5292		// Only update aria-activedescendant if there's a role
5293		// otherwise we assume focus is managed elsewhere
5294		if ( this.options.role ) {
5295			this.element.attr( "aria-activedescendant", focused.attr( "id" ) );
5296		}
5297
5298		// Highlight active parent menu item, if any
5299		activeParent = this.active
5300			.parent()
5301				.closest( ".ui-menu-item" )
5302					.children( ".ui-menu-item-wrapper" );
5303		this._addClass( activeParent, null, "ui-state-active" );
5304
5305		if ( event && event.type === "keydown" ) {
5306			this._close();
5307		} else {
5308			this.timer = this._delay( function() {
5309				this._close();
5310			}, this.delay );
5311		}
5312
5313		nested = item.children( ".ui-menu" );
5314		if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) {
5315			this._startOpening( nested );
5316		}
5317		this.activeMenu = item.parent();
5318
5319		this._trigger( "focus", event, { item: item } );
5320	},
5321
5322	_scrollIntoView: function( item ) {
5323		var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
5324		if ( this._hasScroll() ) {
5325			borderTop = parseFloat( $.css( this.activeMenu[ 0 ], "borderTopWidth" ) ) || 0;
5326			paddingTop = parseFloat( $.css( this.activeMenu[ 0 ], "paddingTop" ) ) || 0;
5327			offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
5328			scroll = this.activeMenu.scrollTop();
5329			elementHeight = this.activeMenu.height();
5330			itemHeight = item.outerHeight();
5331
5332			if ( offset < 0 ) {
5333				this.activeMenu.scrollTop( scroll + offset );
5334			} else if ( offset + itemHeight > elementHeight ) {
5335				this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );
5336			}
5337		}
5338	},
5339
5340	blur: function( event, fromFocus ) {
5341		if ( !fromFocus ) {
5342			clearTimeout( this.timer );
5343		}
5344
5345		if ( !this.active ) {
5346			return;
5347		}
5348
5349		this._removeClass( this.active.children( ".ui-menu-item-wrapper" ),
5350			null, "ui-state-active" );
5351
5352		this._trigger( "blur", event, { item: this.active } );
5353		this.active = null;
5354	},
5355
5356	_startOpening: function( submenu ) {
5357		clearTimeout( this.timer );
5358
5359		// Don't open if already open fixes a Firefox bug that caused a .5 pixel
5360		// shift in the submenu position when mousing over the caret icon
5361		if ( submenu.attr( "aria-hidden" ) !== "true" ) {
5362			return;
5363		}
5364
5365		this.timer = this._delay( function() {
5366			this._close();
5367			this._open( submenu );
5368		}, this.delay );
5369	},
5370
5371	_open: function( submenu ) {
5372		var position = $.extend( {
5373			of: this.active
5374		}, this.options.position );
5375
5376		clearTimeout( this.timer );
5377		this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) )
5378			.hide()
5379			.attr( "aria-hidden", "true" );
5380
5381		submenu
5382			.show()
5383			.removeAttr( "aria-hidden" )
5384			.attr( "aria-expanded", "true" )
5385			.position( position );
5386	},
5387
5388	collapseAll: function( event, all ) {
5389		clearTimeout( this.timer );
5390		this.timer = this._delay( function() {
5391
5392			// If we were passed an event, look for the submenu that contains the event
5393			var currentMenu = all ? this.element :
5394				$( event && event.target ).closest( this.element.find( ".ui-menu" ) );
5395
5396			// If we found no valid submenu ancestor, use the main menu to close all
5397			// sub menus anyway
5398			if ( !currentMenu.length ) {
5399				currentMenu = this.element;
5400			}
5401
5402			this._close( currentMenu );
5403
5404			this.blur( event );
5405
5406			// Work around active item staying active after menu is blurred
5407			this._removeClass( currentMenu.find( ".ui-state-active" ), null, "ui-state-active" );
5408
5409			this.activeMenu = currentMenu;
5410		}, this.delay );
5411	},
5412
5413	// With no arguments, closes the currently active menu - if nothing is active
5414	// it closes all menus.  If passed an argument, it will search for menus BELOW
5415	_close: function( startMenu ) {
5416		if ( !startMenu ) {
5417			startMenu = this.active ? this.active.parent() : this.element;
5418		}
5419
5420		startMenu.find( ".ui-menu" )
5421			.hide()
5422			.attr( "aria-hidden", "true" )
5423			.attr( "aria-expanded", "false" );
5424	},
5425
5426	_closeOnDocumentClick: function( event ) {
5427		return !$( event.target ).closest( ".ui-menu" ).length;
5428	},
5429
5430	_isDivider: function( item ) {
5431
5432		// Match hyphen, em dash, en dash
5433		return !/[^\-\u2014\u2013\s]/.test( item.text() );
5434	},
5435
5436	collapse: function( event ) {
5437		var newItem = this.active &&
5438			this.active.parent().closest( ".ui-menu-item", this.element );
5439		if ( newItem && newItem.length ) {
5440			this._close();
5441			this.focus( event, newItem );
5442		}
5443	},
5444
5445	expand: function( event ) {
5446		var newItem = this.active &&
5447			this.active
5448				.children( ".ui-menu " )
5449					.find( this.options.items )
5450						.first();
5451
5452		if ( newItem && newItem.length ) {
5453			this._open( newItem.parent() );
5454
5455			// Delay so Firefox will not hide activedescendant change in expanding submenu from AT
5456			this._delay( function() {
5457				this.focus( event, newItem );
5458			} );
5459		}
5460	},
5461
5462	next: function( event ) {
5463		this._move( "next", "first", event );
5464	},
5465
5466	previous: function( event ) {
5467		this._move( "prev", "last", event );
5468	},
5469
5470	isFirstItem: function() {
5471		return this.active && !this.active.prevAll( ".ui-menu-item" ).length;
5472	},
5473
5474	isLastItem: function() {
5475		return this.active && !this.active.nextAll( ".ui-menu-item" ).length;
5476	},
5477
5478	_move: function( direction, filter, event ) {
5479		var next;
5480		if ( this.active ) {
5481			if ( direction === "first" || direction === "last" ) {
5482				next = this.active
5483					[ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )
5484					.eq( -1 );
5485			} else {
5486				next = this.active
5487					[ direction + "All" ]( ".ui-menu-item" )
5488					.eq( 0 );
5489			}
5490		}
5491		if ( !next || !next.length || !this.active ) {
5492			next = this.activeMenu.find( this.options.items )[ filter ]();
5493		}
5494
5495		this.focus( event, next );
5496	},
5497
5498	nextPage: function( event ) {
5499		var item, base, height;
5500
5501		if ( !this.active ) {
5502			this.next( event );
5503			return;
5504		}
5505		if ( this.isLastItem() ) {
5506			return;
5507		}
5508		if ( this._hasScroll() ) {
5509			base = this.active.offset().top;
5510			height = this.element.height();
5511			this.active.nextAll( ".ui-menu-item" ).each( function() {
5512				item = $( this );
5513				return item.offset().top - base - height < 0;
5514			} );
5515
5516			this.focus( event, item );
5517		} else {
5518			this.focus( event, this.activeMenu.find( this.options.items )
5519				[ !this.active ? "first" : "last" ]() );
5520		}
5521	},
5522
5523	previousPage: function( event ) {
5524		var item, base, height;
5525		if ( !this.active ) {
5526			this.next( event );
5527			return;
5528		}
5529		if ( this.isFirstItem() ) {
5530			return;
5531		}
5532		if ( this._hasScroll() ) {
5533			base = this.active.offset().top;
5534			height = this.element.height();
5535			this.active.prevAll( ".ui-menu-item" ).each( function() {
5536				item = $( this );
5537				return item.offset().top - base + height > 0;
5538			} );
5539
5540			this.focus( event, item );
5541		} else {
5542			this.focus( event, this.activeMenu.find( this.options.items ).first() );
5543		}
5544	},
5545
5546	_hasScroll: function() {
5547		return this.element.outerHeight() < this.element.prop( "scrollHeight" );
5548	},
5549
5550	select: function( event ) {
5551
5552		// TODO: It should never be possible to not have an active item at this
5553		// point, but the tests don't trigger mouseenter before click.
5554		this.active = this.active || $( event.target ).closest( ".ui-menu-item" );
5555		var ui = { item: this.active };
5556		if ( !this.active.has( ".ui-menu" ).length ) {
5557			this.collapseAll( event, true );
5558		}
5559		this._trigger( "select", event, ui );
5560	},
5561
5562	_filterMenuItems: function( character ) {
5563		var escapedCharacter = character.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ),
5564			regex = new RegExp( "^" + escapedCharacter, "i" );
5565
5566		return this.activeMenu
5567			.find( this.options.items )
5568
5569				// Only match on items, not dividers or other content (#10571)
5570				.filter( ".ui-menu-item" )
5571					.filter( function() {
5572						return regex.test(
5573							$.trim( $( this ).children( ".ui-menu-item-wrapper" ).text() ) );
5574					} );
5575	}
5576} );
5577
5578
5579/*!
5580 * jQuery UI Autocomplete 1.12.1
5581 * http://jqueryui.com
5582 *
5583 * Copyright jQuery Foundation and other contributors
5584 * Released under the MIT license.
5585 * http://jquery.org/license
5586 */
5587
5588//>>label: Autocomplete
5589//>>group: Widgets
5590//>>description: Lists suggested words as the user is typing.
5591//>>docs: http://api.jqueryui.com/autocomplete/
5592//>>demos: http://jqueryui.com/autocomplete/
5593//>>css.structure: ../../themes/base/core.css
5594//>>css.structure: ../../themes/base/autocomplete.css
5595//>>css.theme: ../../themes/base/theme.css
5596
5597
5598
5599$.widget( "ui.autocomplete", {
5600	version: "1.12.1",
5601	defaultElement: "<input>",
5602	options: {
5603		appendTo: null,
5604		autoFocus: false,
5605		delay: 300,
5606		minLength: 1,
5607		position: {
5608			my: "left top",
5609			at: "left bottom",
5610			collision: "none"
5611		},
5612		source: null,
5613
5614		// Callbacks
5615		change: null,
5616		close: null,
5617		focus: null,
5618		open: null,
5619		response: null,
5620		search: null,
5621		select: null
5622	},
5623
5624	requestIndex: 0,
5625	pending: 0,
5626
5627	_create: function() {
5628
5629		// Some browsers only repeat keydown events, not keypress events,
5630		// so we use the suppressKeyPress flag to determine if we've already
5631		// handled the keydown event. #7269
5632		// Unfortunately the code for & in keypress is the same as the up arrow,
5633		// so we use the suppressKeyPressRepeat flag to avoid handling keypress
5634		// events when we know the keydown event was used to modify the
5635		// search term. #7799
5636		var suppressKeyPress, suppressKeyPressRepeat, suppressInput,
5637			nodeName = this.element[ 0 ].nodeName.toLowerCase(),
5638			isTextarea = nodeName === "textarea",
5639			isInput = nodeName === "input";
5640
5641		// Textareas are always multi-line
5642		// Inputs are always single-line, even if inside a contentEditable element
5643		// IE also treats inputs as contentEditable
5644		// All other element types are determined by whether or not they're contentEditable
5645		this.isMultiLine = isTextarea || !isInput && this._isContentEditable( this.element );
5646
5647		this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ];
5648		this.isNewMenu = true;
5649
5650		this._addClass( "ui-autocomplete-input" );
5651		this.element.attr( "autocomplete", "off" );
5652
5653		this._on( this.element, {
5654			keydown: function( event ) {
5655				if ( this.element.prop( "readOnly" ) ) {
5656					suppressKeyPress = true;
5657					suppressInput = true;
5658					suppressKeyPressRepeat = true;
5659					return;
5660				}
5661
5662				suppressKeyPress = false;
5663				suppressInput = false;
5664				suppressKeyPressRepeat = false;
5665				var keyCode = $.ui.keyCode;
5666				switch ( event.keyCode ) {
5667				case keyCode.PAGE_UP:
5668					suppressKeyPress = true;
5669					this._move( "previousPage", event );
5670					break;
5671				case keyCode.PAGE_DOWN:
5672					suppressKeyPress = true;
5673					this._move( "nextPage", event );
5674					break;
5675				case keyCode.UP:
5676					suppressKeyPress = true;
5677					this._keyEvent( "previous", event );
5678					break;
5679				case keyCode.DOWN:
5680					suppressKeyPress = true;
5681					this._keyEvent( "next", event );
5682					break;
5683				case keyCode.ENTER:
5684
5685					// when menu is open and has focus
5686					if ( this.menu.active ) {
5687
5688						// #6055 - Opera still allows the keypress to occur
5689						// which causes forms to submit
5690						suppressKeyPress = true;
5691						event.preventDefault();
5692						this.menu.select( event );
5693					}
5694					break;
5695				case keyCode.TAB:
5696					if ( this.menu.active ) {
5697						this.menu.select( event );
5698					}
5699					break;
5700				case keyCode.ESCAPE:
5701					if ( this.menu.element.is( ":visible" ) ) {
5702						if ( !this.isMultiLine ) {
5703							this._value( this.term );
5704						}
5705						this.close( event );
5706
5707						// Different browsers have different default behavior for escape
5708						// Single press can mean undo or clear
5709						// Double press in IE means clear the whole form
5710						event.preventDefault();
5711					}
5712					break;
5713				default:
5714					suppressKeyPressRepeat = true;
5715
5716					// search timeout should be triggered before the input value is changed
5717					this._searchTimeout( event );
5718					break;
5719				}
5720			},
5721			keypress: function( event ) {
5722				if ( suppressKeyPress ) {
5723					suppressKeyPress = false;
5724					if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
5725						event.preventDefault();
5726					}
5727					return;
5728				}
5729				if ( suppressKeyPressRepeat ) {
5730					return;
5731				}
5732
5733				// Replicate some key handlers to allow them to repeat in Firefox and Opera
5734				var keyCode = $.ui.keyCode;
5735				switch ( event.keyCode ) {
5736				case keyCode.PAGE_UP:
5737					this._move( "previousPage", event );
5738					break;
5739				case keyCode.PAGE_DOWN:
5740					this._move( "nextPage", event );
5741					break;
5742				case keyCode.UP:
5743					this._keyEvent( "previous", event );
5744					break;
5745				case keyCode.DOWN:
5746					this._keyEvent( "next", event );
5747					break;
5748				}
5749			},
5750			input: function( event ) {
5751				if ( suppressInput ) {
5752					suppressInput = false;
5753					event.preventDefault();
5754					return;
5755				}
5756				this._searchTimeout( event );
5757			},
5758			focus: function() {
5759				this.selectedItem = null;
5760				this.previous = this._value();
5761			},
5762			blur: function( event ) {
5763				if ( this.cancelBlur ) {
5764					delete this.cancelBlur;
5765					return;
5766				}
5767
5768				clearTimeout( this.searching );
5769				this.close( event );
5770				this._change( event );
5771			}
5772		} );
5773
5774		this._initSource();
5775		this.menu = $( "<ul>" )
5776			.appendTo( this._appendTo() )
5777			.menu( {
5778
5779				// disable ARIA support, the live region takes care of that
5780				role: null
5781			} )
5782			.hide()
5783			.menu( "instance" );
5784
5785		this._addClass( this.menu.element, "ui-autocomplete", "ui-front" );
5786		this._on( this.menu.element, {
5787			mousedown: function( event ) {
5788
5789				// prevent moving focus out of the text field
5790				event.preventDefault();
5791
5792				// IE doesn't prevent moving focus even with event.preventDefault()
5793				// so we set a flag to know when we should ignore the blur event
5794				this.cancelBlur = true;
5795				this._delay( function() {
5796					delete this.cancelBlur;
5797
5798					// Support: IE 8 only
5799					// Right clicking a menu item or selecting text from the menu items will
5800					// result in focus moving out of the input. However, we've already received
5801					// and ignored the blur event because of the cancelBlur flag set above. So
5802					// we restore focus to ensure that the menu closes properly based on the user's
5803					// next actions.
5804					if ( this.element[ 0 ] !== $.ui.safeActiveElement( this.document[ 0 ] ) ) {
5805						this.element.trigger( "focus" );
5806					}
5807				} );
5808			},
5809			menufocus: function( event, ui ) {
5810				var label, item;
5811
5812				// support: Firefox
5813				// Prevent accidental activation of menu items in Firefox (#7024 #9118)
5814				if ( this.isNewMenu ) {
5815					this.isNewMenu = false;
5816					if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {
5817						this.menu.blur();
5818
5819						this.document.one( "mousemove", function() {
5820							$( event.target ).trigger( event.originalEvent );
5821						} );
5822
5823						return;
5824					}
5825				}
5826
5827				item = ui.item.data( "ui-autocomplete-item" );
5828				if ( false !== this._trigger( "focus", event, { item: item } ) ) {
5829
5830					// use value to match what will end up in the input, if it was a key event
5831					if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
5832						this._value( item.value );
5833					}
5834				}
5835
5836				// Announce the value in the liveRegion
5837				label = ui.item.attr( "aria-label" ) || item.value;
5838				if ( label && $.trim( label ).length ) {
5839					this.liveRegion.children().hide();
5840					$( "<div>" ).text( label ).appendTo( this.liveRegion );
5841				}
5842			},
5843			menuselect: function( event, ui ) {
5844				var item = ui.item.data( "ui-autocomplete-item" ),
5845					previous = this.previous;
5846
5847				// Only trigger when focus was lost (click on menu)
5848				if ( this.element[ 0 ] !== $.ui.safeActiveElement( this.document[ 0 ] ) ) {
5849					this.element.trigger( "focus" );
5850					this.previous = previous;
5851
5852					// #6109 - IE triggers two focus events and the second
5853					// is asynchronous, so we need to reset the previous
5854					// term synchronously and asynchronously :-(
5855					this._delay( function() {
5856						this.previous = previous;
5857						this.selectedItem = item;
5858					} );
5859				}
5860
5861				if ( false !== this._trigger( "select", event, { item: item } ) ) {
5862					this._value( item.value );
5863				}
5864
5865				// reset the term after the select event
5866				// this allows custom select handling to work properly
5867				this.term = this._value();
5868
5869				this.close( event );
5870				this.selectedItem = item;
5871			}
5872		} );
5873
5874		this.liveRegion = $( "<div>", {
5875			role: "status",
5876			"aria-live": "assertive",
5877			"aria-relevant": "additions"
5878		} )
5879			.appendTo( this.document[ 0 ].body );
5880
5881		this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" );
5882
5883		// Turning off autocomplete prevents the browser from remembering the
5884		// value when navigating through history, so we re-enable autocomplete
5885		// if the page is unloaded before the widget is destroyed. #7790
5886		this._on( this.window, {
5887			beforeunload: function() {
5888				this.element.removeAttr( "autocomplete" );
5889			}
5890		} );
5891	},
5892
5893	_destroy: function() {
5894		clearTimeout( this.searching );
5895		this.element.removeAttr( "autocomplete" );
5896		this.menu.element.remove();
5897		this.liveRegion.remove();
5898	},
5899
5900	_setOption: function( key, value ) {
5901		this._super( key, value );
5902		if ( key === "source" ) {
5903			this._initSource();
5904		}
5905		if ( key === "appendTo" ) {
5906			this.menu.element.appendTo( this._appendTo() );
5907		}
5908		if ( key === "disabled" && value && this.xhr ) {
5909			this.xhr.abort();
5910		}
5911	},
5912
5913	_isEventTargetInWidget: function( event ) {
5914		var menuElement = this.menu.element[ 0 ];
5915
5916		return event.target === this.element[ 0 ] ||
5917			event.target === menuElement ||
5918			$.contains( menuElement, event.target );
5919	},
5920
5921	_closeOnClickOutside: function( event ) {
5922		if ( !this._isEventTargetInWidget( event ) ) {
5923			this.close();
5924		}
5925	},
5926
5927	_appendTo: function() {
5928		var element = this.options.appendTo;
5929
5930		if ( element ) {
5931			element = element.jquery || element.nodeType ?
5932				$( element ) :
5933				this.document.find( element ).eq( 0 );
5934		}
5935
5936		if ( !element || !element[ 0 ] ) {
5937			element = this.element.closest( ".ui-front, dialog" );
5938		}
5939
5940		if ( !element.length ) {
5941			element = this.document[ 0 ].body;
5942		}
5943
5944		return element;
5945	},
5946
5947	_initSource: function() {
5948		var array, url,
5949			that = this;
5950		if ( $.isArray( this.options.source ) ) {
5951			array = this.options.source;
5952			this.source = function( request, response ) {
5953				response( $.ui.autocomplete.filter( array, request.term ) );
5954			};
5955		} else if ( typeof this.options.source === "string" ) {
5956			url = this.options.source;
5957			this.source = function( request, response ) {
5958				if ( that.xhr ) {
5959					that.xhr.abort();
5960				}
5961				that.xhr = $.ajax( {
5962					url: url,
5963					data: request,
5964					dataType: "json",
5965					success: function( data ) {
5966						response( data );
5967					},
5968					error: function() {
5969						response( [] );
5970					}
5971				} );
5972			};
5973		} else {
5974			this.source = this.options.source;
5975		}
5976	},
5977
5978	_searchTimeout: function( event ) {
5979		clearTimeout( this.searching );
5980		this.searching = this._delay( function() {
5981
5982			// Search if the value has changed, or if the user retypes the same value (see #7434)
5983			var equalValues = this.term === this._value(),
5984				menuVisible = this.menu.element.is( ":visible" ),
5985				modifierKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
5986
5987			if ( !equalValues || ( equalValues && !menuVisible && !modifierKey ) ) {
5988				this.selectedItem = null;
5989				this.search( null, event );
5990			}
5991		}, this.options.delay );
5992	},
5993
5994	search: function( value, event ) {
5995		value = value != null ? value : this._value();
5996
5997		// Always save the actual value, not the one passed as an argument
5998		this.term = this._value();
5999
6000		if ( value.length < this.options.minLength ) {
6001			return this.close( event );
6002		}
6003
6004		if ( this._trigger( "search", event ) === false ) {
6005			return;
6006		}
6007
6008		return this._search( value );
6009	},
6010
6011	_search: function( value ) {
6012		this.pending++;
6013		this._addClass( "ui-autocomplete-loading" );
6014		this.cancelSearch = false;
6015
6016		this.source( { term: value }, this._response() );
6017	},
6018
6019	_response: function() {
6020		var index = ++this.requestIndex;
6021
6022		return $.proxy( function( content ) {
6023			if ( index === this.requestIndex ) {
6024				this.__response( content );
6025			}
6026
6027			this.pending--;
6028			if ( !this.pending ) {
6029				this._removeClass( "ui-autocomplete-loading" );
6030			}
6031		}, this );
6032	},
6033
6034	__response: function( content ) {
6035		if ( content ) {
6036			content = this._normalize( content );
6037		}
6038		this._trigger( "response", null, { content: content } );
6039		if ( !this.options.disabled && content && content.length && !this.cancelSearch ) {
6040			this._suggest( content );
6041			this._trigger( "open" );
6042		} else {
6043
6044			// use ._close() instead of .close() so we don't cancel future searches
6045			this._close();
6046		}
6047	},
6048
6049	close: function( event ) {
6050		this.cancelSearch = true;
6051		this._close( event );
6052	},
6053
6054	_close: function( event ) {
6055
6056		// Remove the handler that closes the menu on outside clicks
6057		this._off( this.document, "mousedown" );
6058
6059		if ( this.menu.element.is( ":visible" ) ) {
6060			this.menu.element.hide();
6061			this.menu.blur();
6062			this.isNewMenu = true;
6063			this._trigger( "close", event );
6064		}
6065	},
6066
6067	_change: function( event ) {
6068		if ( this.previous !== this._value() ) {
6069			this._trigger( "change", event, { item: this.selectedItem } );
6070		}
6071	},
6072
6073	_normalize: function( items ) {
6074
6075		// assume all items have the right format when the first item is complete
6076		if ( items.length && items[ 0 ].label && items[ 0 ].value ) {
6077			return items;
6078		}
6079		return $.map( items, function( item ) {
6080			if ( typeof item === "string" ) {
6081				return {
6082					label: item,
6083					value: item
6084				};
6085			}
6086			return $.extend( {}, item, {
6087				label: item.label || item.value,
6088				value: item.value || item.label
6089			} );
6090		} );
6091	},
6092
6093	_suggest: function( items ) {
6094		var ul = this.menu.element.empty();
6095		this._renderMenu( ul, items );
6096		this.isNewMenu = true;
6097		this.menu.refresh();
6098
6099		// Size and position menu
6100		ul.show();
6101		this._resizeMenu();
6102		ul.position( $.extend( {
6103			of: this.element
6104		}, this.options.position ) );
6105
6106		if ( this.options.autoFocus ) {
6107			this.menu.next();
6108		}
6109
6110		// Listen for interactions outside of the widget (#6642)
6111		this._on( this.document, {
6112			mousedown: "_closeOnClickOutside"
6113		} );
6114	},
6115
6116	_resizeMenu: function() {
6117		var ul = this.menu.element;
6118		ul.outerWidth( Math.max(
6119
6120			// Firefox wraps long text (possibly a rounding bug)
6121			// so we add 1px to avoid the wrapping (#7513)
6122			ul.width( "" ).outerWidth() + 1,
6123			this.element.outerWidth()
6124		) );
6125	},
6126
6127	_renderMenu: function( ul, items ) {
6128		var that = this;
6129		$.each( items, function( index, item ) {
6130			that._renderItemData( ul, item );
6131		} );
6132	},
6133
6134	_renderItemData: function( ul, item ) {
6135		return this._renderItem( ul, item ).data( "ui-autocomplete-item", item );
6136	},
6137
6138	_renderItem: function( ul, item ) {
6139		return $( "<li>" )
6140			.append( $( "<div>" ).text( item.label ) )
6141			.appendTo( ul );
6142	},
6143
6144	_move: function( direction, event ) {
6145		if ( !this.menu.element.is( ":visible" ) ) {
6146			this.search( null, event );
6147			return;
6148		}
6149		if ( this.menu.isFirstItem() && /^previous/.test( direction ) ||
6150				this.menu.isLastItem() && /^next/.test( direction ) ) {
6151
6152			if ( !this.isMultiLine ) {
6153				this._value( this.term );
6154			}
6155
6156			this.menu.blur();
6157			return;
6158		}
6159		this.menu[ direction ]( event );
6160	},
6161
6162	widget: function() {
6163		return this.menu.element;
6164	},
6165
6166	_value: function() {
6167		return this.valueMethod.apply( this.element, arguments );
6168	},
6169
6170	_keyEvent: function( keyEvent, event ) {
6171		if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
6172			this._move( keyEvent, event );
6173
6174			// Prevents moving cursor to beginning/end of the text field in some browsers
6175			event.preventDefault();
6176		}
6177	},
6178
6179	// Support: Chrome <=50
6180	// We should be able to just use this.element.prop( "isContentEditable" )
6181	// but hidden elements always report false in Chrome.
6182	// https://code.google.com/p/chromium/issues/detail?id=313082
6183	_isContentEditable: function( element ) {
6184		if ( !element.length ) {
6185			return false;
6186		}
6187
6188		var editable = element.prop( "contentEditable" );
6189
6190		if ( editable === "inherit" ) {
6191		  return this._isContentEditable( element.parent() );
6192		}
6193
6194		return editable === "true";
6195	}
6196} );
6197
6198$.extend( $.ui.autocomplete, {
6199	escapeRegex: function( value ) {
6200		return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
6201	},
6202	filter: function( array, term ) {
6203		var matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), "i" );
6204		return $.grep( array, function( value ) {
6205			return matcher.test( value.label || value.value || value );
6206		} );
6207	}
6208} );
6209
6210// Live region extension, adding a `messages` option
6211// NOTE: This is an experimental API. We are still investigating
6212// a full solution for string manipulation and internationalization.
6213$.widget( "ui.autocomplete", $.ui.autocomplete, {
6214	options: {
6215		messages: {
6216			noResults: "No search results.",
6217			results: function( amount ) {
6218				return amount + ( amount > 1 ? " results are" : " result is" ) +
6219					" available, use up and down arrow keys to navigate.";
6220			}
6221		}
6222	},
6223
6224	__response: function( content ) {
6225		var message;
6226		this._superApply( arguments );
6227		if ( this.options.disabled || this.cancelSearch ) {
6228			return;
6229		}
6230		if ( content && content.length ) {
6231			message = this.options.messages.results( content.length );
6232		} else {
6233			message = this.options.messages.noResults;
6234		}
6235		this.liveRegion.children().hide();
6236		$( "<div>" ).text( message ).appendTo( this.liveRegion );
6237	}
6238} );
6239
6240var widgetsAutocomplete = $.ui.autocomplete;
6241
6242
6243/*!
6244 * jQuery UI Controlgroup 1.12.1
6245 * http://jqueryui.com
6246 *
6247 * Copyright jQuery Foundation and other contributors
6248 * Released under the MIT license.
6249 * http://jquery.org/license
6250 */
6251
6252//>>label: Controlgroup
6253//>>group: Widgets
6254//>>description: Visually groups form control widgets
6255//>>docs: http://api.jqueryui.com/controlgroup/
6256//>>demos: http://jqueryui.com/controlgroup/
6257//>>css.structure: ../../themes/base/core.css
6258//>>css.structure: ../../themes/base/controlgroup.css
6259//>>css.theme: ../../themes/base/theme.css
6260
6261
6262var controlgroupCornerRegex = /ui-corner-([a-z]){2,6}/g;
6263
6264var widgetsControlgroup = $.widget( "ui.controlgroup", {
6265	version: "1.12.1",
6266	defaultElement: "<div>",
6267	options: {
6268		direction: "horizontal",
6269		disabled: null,
6270		onlyVisible: true,
6271		items: {
6272			"button": "input[type=button], input[type=submit], input[type=reset], button, a",
6273			"controlgroupLabel": ".ui-controlgroup-label",
6274			"checkboxradio": "input[type='checkbox'], input[type='radio']",
6275			"selectmenu": "select",
6276			"spinner": ".ui-spinner-input"
6277		}
6278	},
6279
6280	_create: function() {
6281		this._enhance();
6282	},
6283
6284	// To support the enhanced option in jQuery Mobile, we isolate DOM manipulation
6285	_enhance: function() {
6286		this.element.attr( "role", "toolbar" );
6287		this.refresh();
6288	},
6289
6290	_destroy: function() {
6291		this._callChildMethod( "destroy" );
6292		this.childWidgets.removeData( "ui-controlgroup-data" );
6293		this.element.removeAttr( "role" );
6294		if ( this.options.items.controlgroupLabel ) {
6295			this.element
6296				.find( this.options.items.controlgroupLabel )
6297				.find( ".ui-controlgroup-label-contents" )
6298				.contents().unwrap();
6299		}
6300	},
6301
6302	_initWidgets: function() {
6303		var that = this,
6304			childWidgets = [];
6305
6306		// First we iterate over each of the items options
6307		$.each( this.options.items, function( widget, selector ) {
6308			var labels;
6309			var options = {};
6310
6311			// Make sure the widget has a selector set
6312			if ( !selector ) {
6313				return;
6314			}
6315
6316			if ( widget === "controlgroupLabel" ) {
6317				labels = that.element.find( selector );
6318				labels.each( function() {
6319					var element = $( this );
6320
6321					if ( element.children( ".ui-controlgroup-label-contents" ).length ) {
6322						return;
6323					}
6324					element.contents()
6325						.wrapAll( "<span class='ui-controlgroup-label-contents'></span>" );
6326				} );
6327				that._addClass( labels, null, "ui-widget ui-widget-content ui-state-default" );
6328				childWidgets = childWidgets.concat( labels.get() );
6329				return;
6330			}
6331
6332			// Make sure the widget actually exists
6333			if ( !$.fn[ widget ] ) {
6334				return;
6335			}
6336
6337			// We assume everything is in the middle to start because we can't determine
6338			// first / last elements until all enhancments are done.
6339			if ( that[ "_" + widget + "Options" ] ) {
6340				options = that[ "_" + widget + "Options" ]( "middle" );
6341			} else {
6342				options = { classes: {} };
6343			}
6344
6345			// Find instances of this widget inside controlgroup and init them
6346			that.element
6347				.find( selector )
6348				.each( function() {
6349					var element = $( this );
6350					var instance = element[ widget ]( "instance" );
6351
6352					// We need to clone the default options for this type of widget to avoid
6353					// polluting the variable options which has a wider scope than a single widget.
6354					var instanceOptions = $.widget.extend( {}, options );
6355
6356					// If the button is the child of a spinner ignore it
6357					// TODO: Find a more generic solution
6358					if ( widget === "button" && element.parent( ".ui-spinner" ).length ) {
6359						return;
6360					}
6361
6362					// Create the widget if it doesn't exist
6363					if ( !instance ) {
6364						instance = element[ widget ]()[ widget ]( "instance" );
6365					}
6366					if ( instance ) {
6367						instanceOptions.classes =
6368							that._resolveClassesValues( instanceOptions.classes, instance );
6369					}
6370					element[ widget ]( instanceOptions );
6371
6372					// Store an instance of the controlgroup to be able to reference
6373					// from the outermost element for changing options and refresh
6374					var widgetElement = element[ widget ]( "widget" );
6375					$.data( widgetElement[ 0 ], "ui-controlgroup-data",
6376						instance ? instance : element[ widget ]( "instance" ) );
6377
6378					childWidgets.push( widgetElement[ 0 ] );
6379				} );
6380		} );
6381
6382		this.childWidgets = $( $.unique( childWidgets ) );
6383		this._addClass( this.childWidgets, "ui-controlgroup-item" );
6384	},
6385
6386	_callChildMethod: function( method ) {
6387		this.childWidgets.each( function() {
6388			var element = $( this ),
6389				data = element.data( "ui-controlgroup-data" );
6390			if ( data && data[ method ] ) {
6391				data[ method ]();
6392			}
6393		} );
6394	},
6395
6396	_updateCornerClass: function( element, position ) {
6397		var remove = "ui-corner-top ui-corner-bottom ui-corner-left ui-corner-right ui-corner-all";
6398		var add = this._buildSimpleOptions( position, "label" ).classes.label;
6399
6400		this._removeClass( element, null, remove );
6401		this._addClass( element, null, add );
6402	},
6403
6404	_buildSimpleOptions: function( position, key ) {
6405		var direction = this.options.direction === "vertical";
6406		var result = {
6407			classes: {}
6408		};
6409		result.classes[ key ] = {
6410			"middle": "",
6411			"first": "ui-corner-" + ( direction ? "top" : "left" ),
6412			"last": "ui-corner-" + ( direction ? "bottom" : "right" ),
6413			"only": "ui-corner-all"
6414		}[ position ];
6415
6416		return result;
6417	},
6418
6419	_spinnerOptions: function( position ) {
6420		var options = this._buildSimpleOptions( position, "ui-spinner" );
6421
6422		options.classes[ "ui-spinner-up" ] = "";
6423		options.classes[ "ui-spinner-down" ] = "";
6424
6425		return options;
6426	},
6427
6428	_buttonOptions: function( position ) {
6429		return this._buildSimpleOptions( position, "ui-button" );
6430	},
6431
6432	_checkboxradioOptions: function( position ) {
6433		return this._buildSimpleOptions( position, "ui-checkboxradio-label" );
6434	},
6435
6436	_selectmenuOptions: function( position ) {
6437		var direction = this.options.direction === "vertical";
6438		return {
6439			width: direction ? "auto" : false,
6440			classes: {
6441				middle: {
6442					"ui-selectmenu-button-open": "",
6443					"ui-selectmenu-button-closed": ""
6444				},
6445				first: {
6446					"ui-selectmenu-button-open": "ui-corner-" + ( direction ? "top" : "tl" ),
6447					"ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "top" : "left" )
6448				},
6449				last: {
6450					"ui-selectmenu-button-open": direction ? "" : "ui-corner-tr",
6451					"ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "bottom" : "right" )
6452				},
6453				only: {
6454					"ui-selectmenu-button-open": "ui-corner-top",
6455					"ui-selectmenu-button-closed": "ui-corner-all"
6456				}
6457
6458			}[ position ]
6459		};
6460	},
6461
6462	_resolveClassesValues: function( classes, instance ) {
6463		var result = {};
6464		$.each( classes, function( key ) {
6465			var current = instance.options.classes[ key ] || "";
6466			current = $.trim( current.replace( controlgroupCornerRegex, "" ) );
6467			result[ key ] = ( current + " " + classes[ key ] ).replace( /\s+/g, " " );
6468		} );
6469		return result;
6470	},
6471
6472	_setOption: function( key, value ) {
6473		if ( key === "direction" ) {
6474			this._removeClass( "ui-controlgroup-" + this.options.direction );
6475		}
6476
6477		this._super( key, value );
6478		if ( key === "disabled" ) {
6479			this._callChildMethod( value ? "disable" : "enable" );
6480			return;
6481		}
6482
6483		this.refresh();
6484	},
6485
6486	refresh: function() {
6487		var children,
6488			that = this;
6489
6490		this._addClass( "ui-controlgroup ui-controlgroup-" + this.options.direction );
6491
6492		if ( this.options.direction === "horizontal" ) {
6493			this._addClass( null, "ui-helper-clearfix" );
6494		}
6495		this._initWidgets();
6496
6497		children = this.childWidgets;
6498
6499		// We filter here because we need to track all childWidgets not just the visible ones
6500		if ( this.options.onlyVisible ) {
6501			children = children.filter( ":visible" );
6502		}
6503
6504		if ( children.length ) {
6505
6506			// We do this last because we need to make sure all enhancment is done
6507			// before determining first and last
6508			$.each( [ "first", "last" ], function( index, value ) {
6509				var instance = children[ value ]().data( "ui-controlgroup-data" );
6510
6511				if ( instance && that[ "_" + instance.widgetName + "Options" ] ) {
6512					var options = that[ "_" + instance.widgetName + "Options" ](
6513						children.length === 1 ? "only" : value
6514					);
6515					options.classes = that._resolveClassesValues( options.classes, instance );
6516					instance.element[ instance.widgetName ]( options );
6517				} else {
6518					that._updateCornerClass( children[ value ](), value );
6519				}
6520			} );
6521
6522			// Finally call the refresh method on each of the child widgets.
6523			this._callChildMethod( "refresh" );
6524		}
6525	}
6526} );
6527
6528/*!
6529 * jQuery UI Checkboxradio 1.12.1
6530 * http://jqueryui.com
6531 *
6532 * Copyright jQuery Foundation and other contributors
6533 * Released under the MIT license.
6534 * http://jquery.org/license
6535 */
6536
6537//>>label: Checkboxradio
6538//>>group: Widgets
6539//>>description: Enhances a form with multiple themeable checkboxes or radio buttons.
6540//>>docs: http://api.jqueryui.com/checkboxradio/
6541//>>demos: http://jqueryui.com/checkboxradio/
6542//>>css.structure: ../../themes/base/core.css
6543//>>css.structure: ../../themes/base/button.css
6544//>>css.structure: ../../themes/base/checkboxradio.css
6545//>>css.theme: ../../themes/base/theme.css
6546
6547
6548
6549$.widget( "ui.checkboxradio", [ $.ui.formResetMixin, {
6550	version: "1.12.1",
6551	options: {
6552		disabled: null,
6553		label: null,
6554		icon: true,
6555		classes: {
6556			"ui-checkboxradio-label": "ui-corner-all",
6557			"ui-checkboxradio-icon": "ui-corner-all"
6558		}
6559	},
6560
6561	_getCreateOptions: function() {
6562		var disabled, labels;
6563		var that = this;
6564		var options = this._super() || {};
6565
6566		// We read the type here, because it makes more sense to throw a element type error first,
6567		// rather then the error for lack of a label. Often if its the wrong type, it
6568		// won't have a label (e.g. calling on a div, btn, etc)
6569		this._readType();
6570
6571		labels = this.element.labels();
6572
6573		// If there are multiple labels, use the last one
6574		this.label = $( labels[ labels.length - 1 ] );
6575		if ( !this.label.length ) {
6576			$.error( "No label found for checkboxradio widget" );
6577		}
6578
6579		this.originalLabel = "";
6580
6581		// We need to get the label text but this may also need to make sure it does not contain the
6582		// input itself.
6583		this.label.contents().not( this.element[ 0 ] ).each( function() {
6584
6585			// The label contents could be text, html, or a mix. We concat each element to get a
6586			// string representation of the label, without the input as part of it.
6587			that.originalLabel += this.nodeType === 3 ? $( this ).text() : this.outerHTML;
6588		} );
6589
6590		// Set the label option if we found label text
6591		if ( this.originalLabel ) {
6592			options.label = this.originalLabel;
6593		}
6594
6595		disabled = this.element[ 0 ].disabled;
6596		if ( disabled != null ) {
6597			options.disabled = disabled;
6598		}
6599		return options;
6600	},
6601
6602	_create: function() {
6603		var checked = this.element[ 0 ].checked;
6604
6605		this._bindFormResetHandler();
6606
6607		if ( this.options.disabled == null ) {
6608			this.options.disabled = this.element[ 0 ].disabled;
6609		}
6610
6611		this._setOption( "disabled", this.options.disabled );
6612		this._addClass( "ui-checkboxradio", "ui-helper-hidden-accessible" );
6613		this._addClass( this.label, "ui-checkboxradio-label", "ui-button ui-widget" );
6614
6615		if ( this.type === "radio" ) {
6616			this._addClass( this.label, "ui-checkboxradio-radio-label" );
6617		}
6618
6619		if ( this.options.label && this.options.label !== this.originalLabel ) {
6620			this._updateLabel();
6621		} else if ( this.originalLabel ) {
6622			this.options.label = this.originalLabel;
6623		}
6624
6625		this._enhance();
6626
6627		if ( checked ) {
6628			this._addClass( this.label, "ui-checkboxradio-checked", "ui-state-active" );
6629			if ( this.icon ) {
6630				this._addClass( this.icon, null, "ui-state-hover" );
6631			}
6632		}
6633
6634		this._on( {
6635			change: "_toggleClasses",
6636			focus: function() {
6637				this._addClass( this.label, null, "ui-state-focus ui-visual-focus" );
6638			},
6639			blur: function() {
6640				this._removeClass( this.label, null, "ui-state-focus ui-visual-focus" );
6641			}
6642		} );
6643	},
6644
6645	_readType: function() {
6646		var nodeName = this.element[ 0 ].nodeName.toLowerCase();
6647		this.type = this.element[ 0 ].type;
6648		if ( nodeName !== "input" || !/radio|checkbox/.test( this.type ) ) {
6649			$.error( "Can't create checkboxradio on element.nodeName=" + nodeName +
6650				" and element.type=" + this.type );
6651		}
6652	},
6653
6654	// Support jQuery Mobile enhanced option
6655	_enhance: function() {
6656		this._updateIcon( this.element[ 0 ].checked );
6657	},
6658
6659	widget: function() {
6660		return this.label;
6661	},
6662
6663	_getRadioGroup: function() {
6664		var group;
6665		var name = this.element[ 0 ].name;
6666		var nameSelector = "input[name='" + $.ui.escapeSelector( name ) + "']";
6667
6668		if ( !name ) {
6669			return $( [] );
6670		}
6671
6672		if ( this.form.length ) {
6673			group = $( this.form[ 0 ].elements ).filter( nameSelector );
6674		} else {
6675
6676			// Not inside a form, check all inputs that also are not inside a form
6677			group = $( nameSelector ).filter( function() {
6678				return $( this ).form().length === 0;
6679			} );
6680		}
6681
6682		return group.not( this.element );
6683	},
6684
6685	_toggleClasses: function() {
6686		var checked = this.element[ 0 ].checked;
6687		this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked );
6688
6689		if ( this.options.icon && this.type === "checkbox" ) {
6690			this._toggleClass( this.icon, null, "ui-icon-check ui-state-checked", checked )
6691				._toggleClass( this.icon, null, "ui-icon-blank", !checked );
6692		}
6693
6694		if ( this.type === "radio" ) {
6695			this._getRadioGroup()
6696				.each( function() {
6697					var instance = $( this ).checkboxradio( "instance" );
6698
6699					if ( instance ) {
6700						instance._removeClass( instance.label,
6701							"ui-checkboxradio-checked", "ui-state-active" );
6702					}
6703				} );
6704		}
6705	},
6706
6707	_destroy: function() {
6708		this._unbindFormResetHandler();
6709
6710		if ( this.icon ) {
6711			this.icon.remove();
6712			this.iconSpace.remove();
6713		}
6714	},
6715
6716	_setOption: function( key, value ) {
6717
6718		// We don't allow the value to be set to nothing
6719		if ( key === "label" && !value ) {
6720			return;
6721		}
6722
6723		this._super( key, value );
6724
6725		if ( key === "disabled" ) {
6726			this._toggleClass( this.label, null, "ui-state-disabled", value );
6727			this.element[ 0 ].disabled = value;
6728
6729			// Don't refresh when setting disabled
6730			return;
6731		}
6732		this.refresh();
6733	},
6734
6735	_updateIcon: function( checked ) {
6736		var toAdd = "ui-icon ui-icon-background ";
6737
6738		if ( this.options.icon ) {
6739			if ( !this.icon ) {
6740				this.icon = $( "<span>" );
6741				this.iconSpace = $( "<span> </span>" );
6742				this._addClass( this.iconSpace, "ui-checkboxradio-icon-space" );
6743			}
6744
6745			if ( this.type === "checkbox" ) {
6746				toAdd += checked ? "ui-icon-check ui-state-checked" : "ui-icon-blank";
6747				this._removeClass( this.icon, null, checked ? "ui-icon-blank" : "ui-icon-check" );
6748			} else {
6749				toAdd += "ui-icon-blank";
6750			}
6751			this._addClass( this.icon, "ui-checkboxradio-icon", toAdd );
6752			if ( !checked ) {
6753				this._removeClass( this.icon, null, "ui-icon-check ui-state-checked" );
6754			}
6755			this.icon.prependTo( this.label ).after( this.iconSpace );
6756		} else if ( this.icon !== undefined ) {
6757			this.icon.remove();
6758			this.iconSpace.remove();
6759			delete this.icon;
6760		}
6761	},
6762
6763	_updateLabel: function() {
6764
6765		// Remove the contents of the label ( minus the icon, icon space, and input )
6766		var contents = this.label.contents().not( this.element[ 0 ] );
6767		if ( this.icon ) {
6768			contents = contents.not( this.icon[ 0 ] );
6769		}
6770		if ( this.iconSpace ) {
6771			contents = contents.not( this.iconSpace[ 0 ] );
6772		}
6773		contents.remove();
6774
6775		this.label.append( this.options.label );
6776	},
6777
6778	refresh: function() {
6779		var checked = this.element[ 0 ].checked,
6780			isDisabled = this.element[ 0 ].disabled;
6781
6782		this._updateIcon( checked );
6783		this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked );
6784		if ( this.options.label !== null ) {
6785			this._updateLabel();
6786		}
6787
6788		if ( isDisabled !== this.options.disabled ) {
6789			this._setOptions( { "disabled": isDisabled } );
6790		}
6791	}
6792
6793} ] );
6794
6795var widgetsCheckboxradio = $.ui.checkboxradio;
6796
6797
6798/*!
6799 * jQuery UI Button 1.12.1
6800 * http://jqueryui.com
6801 *
6802 * Copyright jQuery Foundation and other contributors
6803 * Released under the MIT license.
6804 * http://jquery.org/license
6805 */
6806
6807//>>label: Button
6808//>>group: Widgets
6809//>>description: Enhances a form with themeable buttons.
6810//>>docs: http://api.jqueryui.com/button/
6811//>>demos: http://jqueryui.com/button/
6812//>>css.structure: ../../themes/base/core.css
6813//>>css.structure: ../../themes/base/button.css
6814//>>css.theme: ../../themes/base/theme.css
6815
6816
6817
6818$.widget( "ui.button", {
6819	version: "1.12.1",
6820	defaultElement: "<button>",
6821	options: {
6822		classes: {
6823			"ui-button": "ui-corner-all"
6824		},
6825		disabled: null,
6826		icon: null,
6827		iconPosition: "beginning",
6828		label: null,
6829		showLabel: true
6830	},
6831
6832	_getCreateOptions: function() {
6833		var disabled,
6834
6835			// This is to support cases like in jQuery Mobile where the base widget does have
6836			// an implementation of _getCreateOptions
6837			options = this._super() || {};
6838
6839		this.isInput = this.element.is( "input" );
6840
6841		disabled = this.element[ 0 ].disabled;
6842		if ( disabled != null ) {
6843			options.disabled = disabled;
6844		}
6845
6846		this.originalLabel = this.isInput ? this.element.val() : this.element.html();
6847		if ( this.originalLabel ) {
6848			options.label = this.originalLabel;
6849		}
6850
6851		return options;
6852	},
6853
6854	_create: function() {
6855		if ( !this.option.showLabel & !this.options.icon ) {
6856			this.options.showLabel = true;
6857		}
6858
6859		// We have to check the option again here even though we did in _getCreateOptions,
6860		// because null may have been passed on init which would override what was set in
6861		// _getCreateOptions
6862		if ( this.options.disabled == null ) {
6863			this.options.disabled = this.element[ 0 ].disabled || false;
6864		}
6865
6866		this.hasTitle = !!this.element.attr( "title" );
6867
6868		// Check to see if the label needs to be set or if its already correct
6869		if ( this.options.label && this.options.label !== this.originalLabel ) {
6870			if ( this.isInput ) {
6871				this.element.val( this.options.label );
6872			} else {
6873				this.element.html( this.options.label );
6874			}
6875		}
6876		this._addClass( "ui-button", "ui-widget" );
6877		this._setOption( "disabled", this.options.disabled );
6878		this._enhance();
6879
6880		if ( this.element.is( "a" ) ) {
6881			this._on( {
6882				"keyup": function( event ) {
6883					if ( event.keyCode === $.ui.keyCode.SPACE ) {
6884						event.preventDefault();
6885
6886						// Support: PhantomJS <= 1.9, IE 8 Only
6887						// If a native click is available use it so we actually cause navigation
6888						// otherwise just trigger a click event
6889						if ( this.element[ 0 ].click ) {
6890							this.element[ 0 ].click();
6891						} else {
6892							this.element.trigger( "click" );
6893						}
6894					}
6895				}
6896			} );
6897		}
6898	},
6899
6900	_enhance: function() {
6901		if ( !this.element.is( "button" ) ) {
6902			this.element.attr( "role", "button" );
6903		}
6904
6905		if ( this.options.icon ) {
6906			this._updateIcon( "icon", this.options.icon );
6907			this._updateTooltip();
6908		}
6909	},
6910
6911	_updateTooltip: function() {
6912		this.title = this.element.attr( "title" );
6913
6914		if ( !this.options.showLabel && !this.title ) {
6915			this.element.attr( "title", this.options.label );
6916		}
6917	},
6918
6919	_updateIcon: function( option, value ) {
6920		var icon = option !== "iconPosition",
6921			position = icon ? this.options.iconPosition : value,
6922			displayBlock = position === "top" || position === "bottom";
6923
6924		// Create icon
6925		if ( !this.icon ) {
6926			this.icon = $( "<span>" );
6927
6928			this._addClass( this.icon, "ui-button-icon", "ui-icon" );
6929
6930			if ( !this.options.showLabel ) {
6931				this._addClass( "ui-button-icon-only" );
6932			}
6933		} else if ( icon ) {
6934
6935			// If we are updating the icon remove the old icon class
6936			this._removeClass( this.icon, null, this.options.icon );
6937		}
6938
6939		// If we are updating the icon add the new icon class
6940		if ( icon ) {
6941			this._addClass( this.icon, null, value );
6942		}
6943
6944		this._attachIcon( position );
6945
6946		// If the icon is on top or bottom we need to add the ui-widget-icon-block class and remove
6947		// the iconSpace if there is one.
6948		if ( displayBlock ) {
6949			this._addClass( this.icon, null, "ui-widget-icon-block" );
6950			if ( this.iconSpace ) {
6951				this.iconSpace.remove();
6952			}
6953		} else {
6954
6955			// Position is beginning or end so remove the ui-widget-icon-block class and add the
6956			// space if it does not exist
6957			if ( !this.iconSpace ) {
6958				this.iconSpace = $( "<span> </span>" );
6959				this._addClass( this.iconSpace, "ui-button-icon-space" );
6960			}
6961			this._removeClass( this.icon, null, "ui-wiget-icon-block" );
6962			this._attachIconSpace( position );
6963		}
6964	},
6965
6966	_destroy: function() {
6967		this.element.removeAttr( "role" );
6968
6969		if ( this.icon ) {
6970			this.icon.remove();
6971		}
6972		if ( this.iconSpace ) {
6973			this.iconSpace.remove();
6974		}
6975		if ( !this.hasTitle ) {
6976			this.element.removeAttr( "title" );
6977		}
6978	},
6979
6980	_attachIconSpace: function( iconPosition ) {
6981		this.icon[ /^(?:end|bottom)/.test( iconPosition ) ? "before" : "after" ]( this.iconSpace );
6982	},
6983
6984	_attachIcon: function( iconPosition ) {
6985		this.element[ /^(?:end|bottom)/.test( iconPosition ) ? "append" : "prepend" ]( this.icon );
6986	},
6987
6988	_setOptions: function( options ) {
6989		var newShowLabel = options.showLabel === undefined ?
6990				this.options.showLabel :
6991				options.showLabel,
6992			newIcon = options.icon === undefined ? this.options.icon : options.icon;
6993
6994		if ( !newShowLabel && !newIcon ) {
6995			options.showLabel = true;
6996		}
6997		this._super( options );
6998	},
6999
7000	_setOption: function( key, value ) {
7001		if ( key === "icon" ) {
7002			if ( value ) {
7003				this._updateIcon( key, value );
7004			} else if ( this.icon ) {
7005				this.icon.remove();
7006				if ( this.iconSpace ) {
7007					this.iconSpace.remove();
7008				}
7009			}
7010		}
7011
7012		if ( key === "iconPosition" ) {
7013			this._updateIcon( key, value );
7014		}
7015
7016		// Make sure we can't end up with a button that has neither text nor icon
7017		if ( key === "showLabel" ) {
7018				this._toggleClass( "ui-button-icon-only", null, !value );
7019				this._updateTooltip();
7020		}
7021
7022		if ( key === "label" ) {
7023			if ( this.isInput ) {
7024				this.element.val( value );
7025			} else {
7026
7027				// If there is an icon, append it, else nothing then append the value
7028				// this avoids removal of the icon when setting label text
7029				this.element.html( value );
7030				if ( this.icon ) {
7031					this._attachIcon( this.options.iconPosition );
7032					this._attachIconSpace( this.options.iconPosition );
7033				}
7034			}
7035		}
7036
7037		this._super( key, value );
7038
7039		if ( key === "disabled" ) {
7040			this._toggleClass( null, "ui-state-disabled", value );
7041			this.element[ 0 ].disabled = value;
7042			if ( value ) {
7043				this.element.blur();
7044			}
7045		}
7046	},
7047
7048	refresh: function() {
7049
7050		// Make sure to only check disabled if its an element that supports this otherwise
7051		// check for the disabled class to determine state
7052		var isDisabled = this.element.is( "input, button" ) ?
7053			this.element[ 0 ].disabled : this.element.hasClass( "ui-button-disabled" );
7054
7055		if ( isDisabled !== this.options.disabled ) {
7056			this._setOptions( { disabled: isDisabled } );
7057		}
7058
7059		this._updateTooltip();
7060	}
7061} );
7062
7063// DEPRECATED
7064if ( $.uiBackCompat !== false ) {
7065
7066	// Text and Icons options
7067	$.widget( "ui.button", $.ui.button, {
7068		options: {
7069			text: true,
7070			icons: {
7071				primary: null,
7072				secondary: null
7073			}
7074		},
7075
7076		_create: function() {
7077			if ( this.options.showLabel && !this.options.text ) {
7078				this.options.showLabel = this.options.text;
7079			}
7080			if ( !this.options.showLabel && this.options.text ) {
7081				this.options.text = this.options.showLabel;
7082			}
7083			if ( !this.options.icon && ( this.options.icons.primary ||
7084					this.options.icons.secondary ) ) {
7085				if ( this.options.icons.primary ) {
7086					this.options.icon = this.options.icons.primary;
7087				} else {
7088					this.options.icon = this.options.icons.secondary;
7089					this.options.iconPosition = "end";
7090				}
7091			} else if ( this.options.icon ) {
7092				this.options.icons.primary = this.options.icon;
7093			}
7094			this._super();
7095		},
7096
7097		_setOption: function( key, value ) {
7098			if ( key === "text" ) {
7099				this._super( "showLabel", value );
7100				return;
7101			}
7102			if ( key === "showLabel" ) {
7103				this.options.text = value;
7104			}
7105			if ( key === "icon" ) {
7106				this.options.icons.primary = value;
7107			}
7108			if ( key === "icons" ) {
7109				if ( value.primary ) {
7110					this._super( "icon", value.primary );
7111					this._super( "iconPosition", "beginning" );
7112				} else if ( value.secondary ) {
7113					this._super( "icon", value.secondary );
7114					this._super( "iconPosition", "end" );
7115				}
7116			}
7117			this._superApply( arguments );
7118		}
7119	} );
7120
7121	$.fn.button = ( function( orig ) {
7122		return function() {
7123			if ( !this.length || ( this.length && this[ 0 ].tagName !== "INPUT" ) ||
7124					( this.length && this[ 0 ].tagName === "INPUT" && (
7125						this.attr( "type" ) !== "checkbox" && this.attr( "type" ) !== "radio"
7126					) ) ) {
7127				return orig.apply( this, arguments );
7128			}
7129			if ( !$.ui.checkboxradio ) {
7130				$.error( "Checkboxradio widget missing" );
7131			}
7132			if ( arguments.length === 0 ) {
7133				return this.checkboxradio( {
7134					"icon": false
7135				} );
7136			}
7137			return this.checkboxradio.apply( this, arguments );
7138		};
7139	} )( $.fn.button );
7140
7141	$.fn.buttonset = function() {
7142		if ( !$.ui.controlgroup ) {
7143			$.error( "Controlgroup widget missing" );
7144		}
7145		if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" && arguments[ 2 ] ) {
7146			return this.controlgroup.apply( this,
7147				[ arguments[ 0 ], "items.button", arguments[ 2 ] ] );
7148		}
7149		if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" ) {
7150			return this.controlgroup.apply( this, [ arguments[ 0 ], "items.button" ] );
7151		}
7152		if ( typeof arguments[ 0 ] === "object" && arguments[ 0 ].items ) {
7153			arguments[ 0 ].items = {
7154				button: arguments[ 0 ].items
7155			};
7156		}
7157		return this.controlgroup.apply( this, arguments );
7158	};
7159}
7160
7161var widgetsButton = $.ui.button;
7162
7163
7164// jscs:disable maximumLineLength
7165/* jscs:disable requireCamelCaseOrUpperCaseIdentifiers */
7166/*!
7167 * jQuery UI Datepicker 1.12.1
7168 * http://jqueryui.com
7169 *
7170 * Copyright jQuery Foundation and other contributors
7171
7172 * Released under the MIT license.
7173 * http://jquery.org/license
7174 */
7175
7176//>>label: Datepicker
7177//>>group: Widgets
7178//>>description: Displays a calendar from an input or inline for selecting dates.
7179//>>docs: http://api.jqueryui.com/datepicker/
7180//>>demos: http://jqueryui.com/datepicker/
7181//>>css.structure: ../../themes/base/core.css
7182//>>css.structure: ../../themes/base/datepicker.css
7183//>>css.theme: ../../themes/base/theme.css
7184
7185
7186
7187$.extend( $.ui, { datepicker: { version: "1.12.1" } } );
7188
7189var datepicker_instActive;
7190
7191function datepicker_getZindex( elem ) {
7192	var position, value;
7193	while ( elem.length && elem[ 0 ] !== document ) {
7194
7195		// Ignore z-index if position is set to a value where z-index is ignored by the browser
7196		// This makes behavior of this function consistent across browsers
7197		// WebKit always returns auto if the element is positioned
7198		position = elem.css( "position" );
7199		if ( position === "absolute" || position === "relative" || position === "fixed" ) {
7200
7201			// IE returns 0 when zIndex is not specified
7202			// other browsers return a string
7203			// we ignore the case of nested elements with an explicit value of 0
7204			// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
7205			value = parseInt( elem.css( "zIndex" ), 10 );
7206			if ( !isNaN( value ) && value !== 0 ) {
7207				return value;
7208			}
7209		}
7210		elem = elem.parent();
7211	}
7212
7213	return 0;
7214}
7215/* Date picker manager.
7216   Use the singleton instance of this class, $.datepicker, to interact with the date picker.
7217   Settings for (groups of) date pickers are maintained in an instance object,
7218   allowing multiple different settings on the same page. */
7219
7220function Datepicker() {
7221	this._curInst = null; // The current instance in use
7222	this._keyEvent = false; // If the last event was a key event
7223	this._disabledInputs = []; // List of date picker inputs that have been disabled
7224	this._datepickerShowing = false; // True if the popup picker is showing , false if not
7225	this._inDialog = false; // True if showing within a "dialog", false if not
7226	this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division
7227	this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class
7228	this._appendClass = "ui-datepicker-append"; // The name of the append marker class
7229	this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class
7230	this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class
7231	this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class
7232	this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class
7233	this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class
7234	this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class
7235	this.regional = []; // Available regional settings, indexed by language code
7236	this.regional[ "" ] = { // Default regional settings
7237		closeText: "Done", // Display text for close link
7238		prevText: "Prev", // Display text for previous month link
7239		nextText: "Next", // Display text for next month link
7240		currentText: "Today", // Display text for current month link
7241		monthNames: [ "January","February","March","April","May","June",
7242			"July","August","September","October","November","December" ], // Names of months for drop-down and formatting
7243		monthNamesShort: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ], // For formatting
7244		dayNames: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], // For formatting
7245		dayNamesShort: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], // For formatting
7246		dayNamesMin: [ "Su","Mo","Tu","We","Th","Fr","Sa" ], // Column headings for days starting at Sunday
7247		weekHeader: "Wk", // Column header for week of the year
7248		dateFormat: "mm/dd/yy", // See format options on parseDate
7249		firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
7250		isRTL: false, // True if right-to-left language, false if left-to-right
7251		showMonthAfterYear: false, // True if the year select precedes month, false for month then year
7252		yearSuffix: "" // Additional text to append to the year in the month headers
7253	};
7254	this._defaults = { // Global defaults for all the date picker instances
7255		showOn: "focus", // "focus" for popup on focus,
7256			// "button" for trigger button, or "both" for either
7257		showAnim: "fadeIn", // Name of jQuery animation for popup
7258		showOptions: {}, // Options for enhanced animations
7259		defaultDate: null, // Used when field is blank: actual date,
7260			// +/-number for offset from today, null for today
7261		appendText: "", // Display text following the input box, e.g. showing the format
7262		buttonText: "...", // Text for trigger button
7263		buttonImage: "", // URL for trigger button image
7264		buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
7265		hideIfNoPrevNext: false, // True to hide next/previous month links
7266			// if not applicable, false to just disable them
7267		navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
7268		gotoCurrent: false, // True if today link goes back to current selection instead
7269		changeMonth: false, // True if month can be selected directly, false if only prev/next
7270		changeYear: false, // True if year can be selected directly, false if only prev/next
7271		yearRange: "c-10:c+10", // Range of years to display in drop-down,
7272			// either relative to today's year (-nn:+nn), relative to currently displayed year
7273			// (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
7274		showOtherMonths: false, // True to show dates in other months, false to leave blank
7275		selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
7276		showWeek: false, // True to show week of the year, false to not show it
7277		calculateWeek: this.iso8601Week, // How to calculate the week of the year,
7278			// takes a Date and returns the number of the week for it
7279		shortYearCutoff: "+10", // Short year values < this are in the current century,
7280			// > this are in the previous century,
7281			// string value starting with "+" for current year + value
7282		minDate: null, // The earliest selectable date, or null for no limit
7283		maxDate: null, // The latest selectable date, or null for no limit
7284		duration: "fast", // Duration of display/closure
7285		beforeShowDay: null, // Function that takes a date and returns an array with
7286			// [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "",
7287			// [2] = cell title (optional), e.g. $.datepicker.noWeekends
7288		beforeShow: null, // Function that takes an input field and
7289			// returns a set of custom settings for the date picker
7290		onSelect: null, // Define a callback function when a date is selected
7291		onChangeMonthYear: null, // Define a callback function when the month or year is changed
7292		onClose: null, // Define a callback function when the datepicker is closed
7293		numberOfMonths: 1, // Number of months to show at a time
7294		showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
7295		stepMonths: 1, // Number of months to step back/forward
7296		stepBigMonths: 12, // Number of months to step back/forward for the big links
7297		altField: "", // Selector for an alternate field to store selected dates into
7298		altFormat: "", // The date format to use for the alternate field
7299		constrainInput: true, // The input is constrained by the current date format
7300		showButtonPanel: false, // True to show button panel, false to not show it
7301		autoSize: false, // True to size the input for the date format, false to leave as is
7302		disabled: false // The initial disabled state
7303	};
7304	$.extend( this._defaults, this.regional[ "" ] );
7305	this.regional.en = $.extend( true, {}, this.regional[ "" ] );
7306	this.regional[ "en-US" ] = $.extend( true, {}, this.regional.en );
7307	this.dpDiv = datepicker_bindHover( $( "<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) );
7308}
7309
7310$.extend( Datepicker.prototype, {
7311	/* Class name added to elements to indicate already configured with a date picker. */
7312	markerClassName: "hasDatepicker",
7313
7314	//Keep track of the maximum number of rows displayed (see #7043)
7315	maxRows: 4,
7316
7317	// TODO rename to "widget" when switching to widget factory
7318	_widgetDatepicker: function() {
7319		return this.dpDiv;
7320	},
7321
7322	/* Override the default settings for all instances of the date picker.
7323	 * @param  settings  object - the new settings to use as defaults (anonymous object)
7324	 * @return the manager object
7325	 */
7326	setDefaults: function( settings ) {
7327		datepicker_extendRemove( this._defaults, settings || {} );
7328		return this;
7329	},
7330
7331	/* Attach the date picker to a jQuery selection.
7332	 * @param  target	element - the target input field or division or span
7333	 * @param  settings  object - the new settings to use for this date picker instance (anonymous)
7334	 */
7335	_attachDatepicker: function( target, settings ) {
7336		var nodeName, inline, inst;
7337		nodeName = target.nodeName.toLowerCase();
7338		inline = ( nodeName === "div" || nodeName === "span" );
7339		if ( !target.id ) {
7340			this.uuid += 1;
7341			target.id = "dp" + this.uuid;
7342		}
7343		inst = this._newInst( $( target ), inline );
7344		inst.settings = $.extend( {}, settings || {} );
7345		if ( nodeName === "input" ) {
7346			this._connectDatepicker( target, inst );
7347		} else if ( inline ) {
7348			this._inlineDatepicker( target, inst );
7349		}
7350	},
7351
7352	/* Create a new instance object. */
7353	_newInst: function( target, inline ) {
7354		var id = target[ 0 ].id.replace( /([^A-Za-z0-9_\-])/g, "\\\\$1" ); // escape jQuery meta chars
7355		return { id: id, input: target, // associated target
7356			selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
7357			drawMonth: 0, drawYear: 0, // month being drawn
7358			inline: inline, // is datepicker inline or not
7359			dpDiv: ( !inline ? this.dpDiv : // presentation div
7360			datepicker_bindHover( $( "<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) ) ) };
7361	},
7362
7363	/* Attach the date picker to an input field. */
7364	_connectDatepicker: function( target, inst ) {
7365		var input = $( target );
7366		inst.append = $( [] );
7367		inst.trigger = $( [] );
7368		if ( input.hasClass( this.markerClassName ) ) {
7369			return;
7370		}
7371		this._attachments( input, inst );
7372		input.addClass( this.markerClassName ).on( "keydown", this._doKeyDown ).
7373			on( "keypress", this._doKeyPress ).on( "keyup", this._doKeyUp );
7374		this._autoSize( inst );
7375		$.data( target, "datepicker", inst );
7376
7377		//If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
7378		if ( inst.settings.disabled ) {
7379			this._disableDatepicker( target );
7380		}
7381	},
7382
7383	/* Make attachments based on settings. */
7384	_attachments: function( input, inst ) {
7385		var showOn, buttonText, buttonImage,
7386			appendText = this._get( inst, "appendText" ),
7387			isRTL = this._get( inst, "isRTL" );
7388
7389		if ( inst.append ) {
7390			inst.append.remove();
7391		}
7392		if ( appendText ) {
7393			inst.append = $( "<span class='" + this._appendClass + "'>" + appendText + "</span>" );
7394			input[ isRTL ? "before" : "after" ]( inst.append );
7395		}
7396
7397		input.off( "focus", this._showDatepicker );
7398
7399		if ( inst.trigger ) {
7400			inst.trigger.remove();
7401		}
7402
7403		showOn = this._get( inst, "showOn" );
7404		if ( showOn === "focus" || showOn === "both" ) { // pop-up date picker when in the marked field
7405			input.on( "focus", this._showDatepicker );
7406		}
7407		if ( showOn === "button" || showOn === "both" ) { // pop-up date picker when button clicked
7408			buttonText = this._get( inst, "buttonText" );
7409			buttonImage = this._get( inst, "buttonImage" );
7410			inst.trigger = $( this._get( inst, "buttonImageOnly" ) ?
7411				$( "<img/>" ).addClass( this._triggerClass ).
7412					attr( { src: buttonImage, alt: buttonText, title: buttonText } ) :
7413				$( "<button type='button'></button>" ).addClass( this._triggerClass ).
7414					html( !buttonImage ? buttonText : $( "<img/>" ).attr(
7415					{ src:buttonImage, alt:buttonText, title:buttonText } ) ) );
7416			input[ isRTL ? "before" : "after" ]( inst.trigger );
7417			inst.trigger.on( "click", function() {
7418				if ( $.datepicker._datepickerShowing && $.datepicker._lastInput === input[ 0 ] ) {
7419					$.datepicker._hideDatepicker();
7420				} else if ( $.datepicker._datepickerShowing && $.datepicker._lastInput !== input[ 0 ] ) {
7421					$.datepicker._hideDatepicker();
7422					$.datepicker._showDatepicker( input[ 0 ] );
7423				} else {
7424					$.datepicker._showDatepicker( input[ 0 ] );
7425				}
7426				return false;
7427			} );
7428		}
7429	},
7430
7431	/* Apply the maximum length for the date format. */
7432	_autoSize: function( inst ) {
7433		if ( this._get( inst, "autoSize" ) && !inst.inline ) {
7434			var findMax, max, maxI, i,
7435				date = new Date( 2009, 12 - 1, 20 ), // Ensure double digits
7436				dateFormat = this._get( inst, "dateFormat" );
7437
7438			if ( dateFormat.match( /[DM]/ ) ) {
7439				findMax = function( names ) {
7440					max = 0;
7441					maxI = 0;
7442					for ( i = 0; i < names.length; i++ ) {
7443						if ( names[ i ].length > max ) {
7444							max = names[ i ].length;
7445							maxI = i;
7446						}
7447					}
7448					return maxI;
7449				};
7450				date.setMonth( findMax( this._get( inst, ( dateFormat.match( /MM/ ) ?
7451					"monthNames" : "monthNamesShort" ) ) ) );
7452				date.setDate( findMax( this._get( inst, ( dateFormat.match( /DD/ ) ?
7453					"dayNames" : "dayNamesShort" ) ) ) + 20 - date.getDay() );
7454			}
7455			inst.input.attr( "size", this._formatDate( inst, date ).length );
7456		}
7457	},
7458
7459	/* Attach an inline date picker to a div. */
7460	_inlineDatepicker: function( target, inst ) {
7461		var divSpan = $( target );
7462		if ( divSpan.hasClass( this.markerClassName ) ) {
7463			return;
7464		}
7465		divSpan.addClass( this.markerClassName ).append( inst.dpDiv );
7466		$.data( target, "datepicker", inst );
7467		this._setDate( inst, this._getDefaultDate( inst ), true );
7468		this._updateDatepicker( inst );
7469		this._updateAlternate( inst );
7470
7471		//If disabled option is true, disable the datepicker before showing it (see ticket #5665)
7472		if ( inst.settings.disabled ) {
7473			this._disableDatepicker( target );
7474		}
7475
7476		// Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
7477		// http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
7478		inst.dpDiv.css( "display", "block" );
7479	},
7480
7481	/* Pop-up the date picker in a "dialog" box.
7482	 * @param  input element - ignored
7483	 * @param  date	string or Date - the initial date to display
7484	 * @param  onSelect  function - the function to call when a date is selected
7485	 * @param  settings  object - update the dialog date picker instance's settings (anonymous object)
7486	 * @param  pos int[2] - coordinates for the dialog's position within the screen or
7487	 *					event - with x/y coordinates or
7488	 *					leave empty for default (screen centre)
7489	 * @return the manager object
7490	 */
7491	_dialogDatepicker: function( input, date, onSelect, settings, pos ) {
7492		var id, browserWidth, browserHeight, scrollX, scrollY,
7493			inst = this._dialogInst; // internal instance
7494
7495		if ( !inst ) {
7496			this.uuid += 1;
7497			id = "dp" + this.uuid;
7498			this._dialogInput = $( "<input type='text' id='" + id +
7499				"' style='position: absolute; top: -100px; width: 0px;'/>" );
7500			this._dialogInput.on( "keydown", this._doKeyDown );
7501			$( "body" ).append( this._dialogInput );
7502			inst = this._dialogInst = this._newInst( this._dialogInput, false );
7503			inst.settings = {};
7504			$.data( this._dialogInput[ 0 ], "datepicker", inst );
7505		}
7506		datepicker_extendRemove( inst.settings, settings || {} );
7507		date = ( date && date.constructor === Date ? this._formatDate( inst, date ) : date );
7508		this._dialogInput.val( date );
7509
7510		this._pos = ( pos ? ( pos.length ? pos : [ pos.pageX, pos.pageY ] ) : null );
7511		if ( !this._pos ) {
7512			browserWidth = document.documentElement.clientWidth;
7513			browserHeight = document.documentElement.clientHeight;
7514			scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
7515			scrollY = document.documentElement.scrollTop || document.body.scrollTop;
7516			this._pos = // should use actual width/height below
7517				[ ( browserWidth / 2 ) - 100 + scrollX, ( browserHeight / 2 ) - 150 + scrollY ];
7518		}
7519
7520		// Move input on screen for focus, but hidden behind dialog
7521		this._dialogInput.css( "left", ( this._pos[ 0 ] + 20 ) + "px" ).css( "top", this._pos[ 1 ] + "px" );
7522		inst.settings.onSelect = onSelect;
7523		this._inDialog = true;
7524		this.dpDiv.addClass( this._dialogClass );
7525		this._showDatepicker( this._dialogInput[ 0 ] );
7526		if ( $.blockUI ) {
7527			$.blockUI( this.dpDiv );
7528		}
7529		$.data( this._dialogInput[ 0 ], "datepicker", inst );
7530		return this;
7531	},
7532
7533	/* Detach a datepicker from its control.
7534	 * @param  target	element - the target input field or division or span
7535	 */
7536	_destroyDatepicker: function( target ) {
7537		var nodeName,
7538			$target = $( target ),
7539			inst = $.data( target, "datepicker" );
7540
7541		if ( !$target.hasClass( this.markerClassName ) ) {
7542			return;
7543		}
7544
7545		nodeName = target.nodeName.toLowerCase();
7546		$.removeData( target, "datepicker" );
7547		if ( nodeName === "input" ) {
7548			inst.append.remove();
7549			inst.trigger.remove();
7550			$target.removeClass( this.markerClassName ).
7551				off( "focus", this._showDatepicker ).
7552				off( "keydown", this._doKeyDown ).
7553				off( "keypress", this._doKeyPress ).
7554				off( "keyup", this._doKeyUp );
7555		} else if ( nodeName === "div" || nodeName === "span" ) {
7556			$target.removeClass( this.markerClassName ).empty();
7557		}
7558
7559		if ( datepicker_instActive === inst ) {
7560			datepicker_instActive = null;
7561		}
7562	},
7563
7564	/* Enable the date picker to a jQuery selection.
7565	 * @param  target	element - the target input field or division or span
7566	 */
7567	_enableDatepicker: function( target ) {
7568		var nodeName, inline,
7569			$target = $( target ),
7570			inst = $.data( target, "datepicker" );
7571
7572		if ( !$target.hasClass( this.markerClassName ) ) {
7573			return;
7574		}
7575
7576		nodeName = target.nodeName.toLowerCase();
7577		if ( nodeName === "input" ) {
7578			target.disabled = false;
7579			inst.trigger.filter( "button" ).
7580				each( function() { this.disabled = false; } ).end().
7581				filter( "img" ).css( { opacity: "1.0", cursor: "" } );
7582		} else if ( nodeName === "div" || nodeName === "span" ) {
7583			inline = $target.children( "." + this._inlineClass );
7584			inline.children().removeClass( "ui-state-disabled" );
7585			inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ).
7586				prop( "disabled", false );
7587		}
7588		this._disabledInputs = $.map( this._disabledInputs,
7589			function( value ) { return ( value === target ? null : value ); } ); // delete entry
7590	},
7591
7592	/* Disable the date picker to a jQuery selection.
7593	 * @param  target	element - the target input field or division or span
7594	 */
7595	_disableDatepicker: function( target ) {
7596		var nodeName, inline,
7597			$target = $( target ),
7598			inst = $.data( target, "datepicker" );
7599
7600		if ( !$target.hasClass( this.markerClassName ) ) {
7601			return;
7602		}
7603
7604		nodeName = target.nodeName.toLowerCase();
7605		if ( nodeName === "input" ) {
7606			target.disabled = true;
7607			inst.trigger.filter( "button" ).
7608				each( function() { this.disabled = true; } ).end().
7609				filter( "img" ).css( { opacity: "0.5", cursor: "default" } );
7610		} else if ( nodeName === "div" || nodeName === "span" ) {
7611			inline = $target.children( "." + this._inlineClass );
7612			inline.children().addClass( "ui-state-disabled" );
7613			inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ).
7614				prop( "disabled", true );
7615		}
7616		this._disabledInputs = $.map( this._disabledInputs,
7617			function( value ) { return ( value === target ? null : value ); } ); // delete entry
7618		this._disabledInputs[ this._disabledInputs.length ] = target;
7619	},
7620
7621	/* Is the first field in a jQuery collection disabled as a datepicker?
7622	 * @param  target	element - the target input field or division or span
7623	 * @return boolean - true if disabled, false if enabled
7624	 */
7625	_isDisabledDatepicker: function( target ) {
7626		if ( !target ) {
7627			return false;
7628		}
7629		for ( var i = 0; i < this._disabledInputs.length; i++ ) {
7630			if ( this._disabledInputs[ i ] === target ) {
7631				return true;
7632			}
7633		}
7634		return false;
7635	},
7636
7637	/* Retrieve the instance data for the target control.
7638	 * @param  target  element - the target input field or division or span
7639	 * @return  object - the associated instance data
7640	 * @throws  error if a jQuery problem getting data
7641	 */
7642	_getInst: function( target ) {
7643		try {
7644			return $.data( target, "datepicker" );
7645		}
7646		catch ( err ) {
7647			throw "Missing instance data for this datepicker";
7648		}
7649	},
7650
7651	/* Update or retrieve the settings for a date picker attached to an input field or division.
7652	 * @param  target  element - the target input field or division or span
7653	 * @param  name	object - the new settings to update or
7654	 *				string - the name of the setting to change or retrieve,
7655	 *				when retrieving also "all" for all instance settings or
7656	 *				"defaults" for all global defaults
7657	 * @param  value   any - the new value for the setting
7658	 *				(omit if above is an object or to retrieve a value)
7659	 */
7660	_optionDatepicker: function( target, name, value ) {
7661		var settings, date, minDate, maxDate,
7662			inst = this._getInst( target );
7663
7664		if ( arguments.length === 2 && typeof name === "string" ) {
7665			return ( name === "defaults" ? $.extend( {}, $.datepicker._defaults ) :
7666				( inst ? ( name === "all" ? $.extend( {}, inst.settings ) :
7667				this._get( inst, name ) ) : null ) );
7668		}
7669
7670		settings = name || {};
7671		if ( typeof name === "string" ) {
7672			settings = {};
7673			settings[ name ] = value;
7674		}
7675
7676		if ( inst ) {
7677			if ( this._curInst === inst ) {
7678				this._hideDatepicker();
7679			}
7680
7681			date = this._getDateDatepicker( target, true );
7682			minDate = this._getMinMaxDate( inst, "min" );
7683			maxDate = this._getMinMaxDate( inst, "max" );
7684			datepicker_extendRemove( inst.settings, settings );
7685
7686			// reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
7687			if ( minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined ) {
7688				inst.settings.minDate = this._formatDate( inst, minDate );
7689			}
7690			if ( maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined ) {
7691				inst.settings.maxDate = this._formatDate( inst, maxDate );
7692			}
7693			if ( "disabled" in settings ) {
7694				if ( settings.disabled ) {
7695					this._disableDatepicker( target );
7696				} else {
7697					this._enableDatepicker( target );
7698				}
7699			}
7700			this._attachments( $( target ), inst );
7701			this._autoSize( inst );
7702			this._setDate( inst, date );
7703			this._updateAlternate( inst );
7704			this._updateDatepicker( inst );
7705		}
7706	},
7707
7708	// Change method deprecated
7709	_changeDatepicker: function( target, name, value ) {
7710		this._optionDatepicker( target, name, value );
7711	},
7712
7713	/* Redraw the date picker attached to an input field or division.
7714	 * @param  target  element - the target input field or division or span
7715	 */
7716	_refreshDatepicker: function( target ) {
7717		var inst = this._getInst( target );
7718		if ( inst ) {
7719			this._updateDatepicker( inst );
7720		}
7721	},
7722
7723	/* Set the dates for a jQuery selection.
7724	 * @param  target element - the target input field or division or span
7725	 * @param  date	Date - the new date
7726	 */
7727	_setDateDatepicker: function( target, date ) {
7728		var inst = this._getInst( target );
7729		if ( inst ) {
7730			this._setDate( inst, date );
7731			this._updateDatepicker( inst );
7732			this._updateAlternate( inst );
7733		}
7734	},
7735
7736	/* Get the date(s) for the first entry in a jQuery selection.
7737	 * @param  target element - the target input field or division or span
7738	 * @param  noDefault boolean - true if no default date is to be used
7739	 * @return Date - the current date
7740	 */
7741	_getDateDatepicker: function( target, noDefault ) {
7742		var inst = this._getInst( target );
7743		if ( inst && !inst.inline ) {
7744			this._setDateFromField( inst, noDefault );
7745		}
7746		return ( inst ? this._getDate( inst ) : null );
7747	},
7748
7749	/* Handle keystrokes. */
7750	_doKeyDown: function( event ) {
7751		var onSelect, dateStr, sel,
7752			inst = $.datepicker._getInst( event.target ),
7753			handled = true,
7754			isRTL = inst.dpDiv.is( ".ui-datepicker-rtl" );
7755
7756		inst._keyEvent = true;
7757		if ( $.datepicker._datepickerShowing ) {
7758			switch ( event.keyCode ) {
7759				case 9: $.datepicker._hideDatepicker();
7760						handled = false;
7761						break; // hide on tab out
7762				case 13: sel = $( "td." + $.datepicker._dayOverClass + ":not(." +
7763									$.datepicker._currentClass + ")", inst.dpDiv );
7764						if ( sel[ 0 ] ) {
7765							$.datepicker._selectDay( event.target, inst.selectedMonth, inst.selectedYear, sel[ 0 ] );
7766						}
7767
7768						onSelect = $.datepicker._get( inst, "onSelect" );
7769						if ( onSelect ) {
7770							dateStr = $.datepicker._formatDate( inst );
7771
7772							// Trigger custom callback
7773							onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] );
7774						} else {
7775							$.datepicker._hideDatepicker();
7776						}
7777
7778						return false; // don't submit the form
7779				case 27: $.datepicker._hideDatepicker();
7780						break; // hide on escape
7781				case 33: $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
7782							-$.datepicker._get( inst, "stepBigMonths" ) :
7783							-$.datepicker._get( inst, "stepMonths" ) ), "M" );
7784						break; // previous month/year on page up/+ ctrl
7785				case 34: $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
7786							+$.datepicker._get( inst, "stepBigMonths" ) :
7787							+$.datepicker._get( inst, "stepMonths" ) ), "M" );
7788						break; // next month/year on page down/+ ctrl
7789				case 35: if ( event.ctrlKey || event.metaKey ) {
7790							$.datepicker._clearDate( event.target );
7791						}
7792						handled = event.ctrlKey || event.metaKey;
7793						break; // clear on ctrl or command +end
7794				case 36: if ( event.ctrlKey || event.metaKey ) {
7795							$.datepicker._gotoToday( event.target );
7796						}
7797						handled = event.ctrlKey || event.metaKey;
7798						break; // current on ctrl or command +home
7799				case 37: if ( event.ctrlKey || event.metaKey ) {
7800							$.datepicker._adjustDate( event.target, ( isRTL ? +1 : -1 ), "D" );
7801						}
7802						handled = event.ctrlKey || event.metaKey;
7803
7804						// -1 day on ctrl or command +left
7805						if ( event.originalEvent.altKey ) {
7806							$.datepicker._adjustDate( event.target, ( event.ctrlKey ?
7807								-$.datepicker._get( inst, "stepBigMonths" ) :
7808								-$.datepicker._get( inst, "stepMonths" ) ), "M" );
7809						}
7810
7811						// next month/year on alt +left on Mac
7812						break;
7813				case 38: if ( event.ctrlKey || event.metaKey ) {
7814							$.datepicker._adjustDate( event.target, -7, "D" );
7815						}
7816						handled = event.ctrlKey || event.metaKey;
7817						break; // -1 week on ctrl or command +up
7818				case 39: if ( event.ctrlKey || event.metaKey ) {
7819							$.datepicker._adjustDate( event.target, ( isRTL ? -1 : +1 ), "D" );
7820						}
7821						handled = event.ctrlKey || event.metaKey;
7822
7823						// +1 day on ctrl or command +right
7824						if ( event.originalEvent.altKey ) {
7825							$.datepicker._adjustDate( event.target, ( event.ctrlKey ?
7826								+$.datepicker._get( inst, "stepBigMonths" ) :
7827								+$.datepicker._get( inst, "stepMonths" ) ), "M" );
7828						}
7829
7830						// next month/year on alt +right
7831						break;
7832				case 40: if ( event.ctrlKey || event.metaKey ) {
7833							$.datepicker._adjustDate( event.target, +7, "D" );
7834						}
7835						handled = event.ctrlKey || event.metaKey;
7836						break; // +1 week on ctrl or command +down
7837				default: handled = false;
7838			}
7839		} else if ( event.keyCode === 36 && event.ctrlKey ) { // display the date picker on ctrl+home
7840			$.datepicker._showDatepicker( this );
7841		} else {
7842			handled = false;
7843		}
7844
7845		if ( handled ) {
7846			event.preventDefault();
7847			event.stopPropagation();
7848		}
7849	},
7850
7851	/* Filter entered characters - based on date format. */
7852	_doKeyPress: function( event ) {
7853		var chars, chr,
7854			inst = $.datepicker._getInst( event.target );
7855
7856		if ( $.datepicker._get( inst, "constrainInput" ) ) {
7857			chars = $.datepicker._possibleChars( $.datepicker._get( inst, "dateFormat" ) );
7858			chr = String.fromCharCode( event.charCode == null ? event.keyCode : event.charCode );
7859			return event.ctrlKey || event.metaKey || ( chr < " " || !chars || chars.indexOf( chr ) > -1 );
7860		}
7861	},
7862
7863	/* Synchronise manual entry and field/alternate field. */
7864	_doKeyUp: function( event ) {
7865		var date,
7866			inst = $.datepicker._getInst( event.target );
7867
7868		if ( inst.input.val() !== inst.lastVal ) {
7869			try {
7870				date = $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ),
7871					( inst.input ? inst.input.val() : null ),
7872					$.datepicker._getFormatConfig( inst ) );
7873
7874				if ( date ) { // only if valid
7875					$.datepicker._setDateFromField( inst );
7876					$.datepicker._updateAlternate( inst );
7877					$.datepicker._updateDatepicker( inst );
7878				}
7879			}
7880			catch ( err ) {
7881			}
7882		}
7883		return true;
7884	},
7885
7886	/* Pop-up the date picker for a given input field.
7887	 * If false returned from beforeShow event handler do not show.
7888	 * @param  input  element - the input field attached to the date picker or
7889	 *					event - if triggered by focus
7890	 */
7891	_showDatepicker: function( input ) {
7892		input = input.target || input;
7893		if ( input.nodeName.toLowerCase() !== "input" ) { // find from button/image trigger
7894			input = $( "input", input.parentNode )[ 0 ];
7895		}
7896
7897		if ( $.datepicker._isDisabledDatepicker( input ) || $.datepicker._lastInput === input ) { // already here
7898			return;
7899		}
7900
7901		var inst, beforeShow, beforeShowSettings, isFixed,
7902			offset, showAnim, duration;
7903
7904		inst = $.datepicker._getInst( input );
7905		if ( $.datepicker._curInst && $.datepicker._curInst !== inst ) {
7906			$.datepicker._curInst.dpDiv.stop( true, true );
7907			if ( inst && $.datepicker._datepickerShowing ) {
7908				$.datepicker._hideDatepicker( $.datepicker._curInst.input[ 0 ] );
7909			}
7910		}
7911
7912		beforeShow = $.datepicker._get( inst, "beforeShow" );
7913		beforeShowSettings = beforeShow ? beforeShow.apply( input, [ input, inst ] ) : {};
7914		if ( beforeShowSettings === false ) {
7915			return;
7916		}
7917		datepicker_extendRemove( inst.settings, beforeShowSettings );
7918
7919		inst.lastVal = null;
7920		$.datepicker._lastInput = input;
7921		$.datepicker._setDateFromField( inst );
7922
7923		if ( $.datepicker._inDialog ) { // hide cursor
7924			input.value = "";
7925		}
7926		if ( !$.datepicker._pos ) { // position below input
7927			$.datepicker._pos = $.datepicker._findPos( input );
7928			$.datepicker._pos[ 1 ] += input.offsetHeight; // add the height
7929		}
7930
7931		isFixed = false;
7932		$( input ).parents().each( function() {
7933			isFixed |= $( this ).css( "position" ) === "fixed";
7934			return !isFixed;
7935		} );
7936
7937		offset = { left: $.datepicker._pos[ 0 ], top: $.datepicker._pos[ 1 ] };
7938		$.datepicker._pos = null;
7939
7940		//to avoid flashes on Firefox
7941		inst.dpDiv.empty();
7942
7943		// determine sizing offscreen
7944		inst.dpDiv.css( { position: "absolute", display: "block", top: "-1000px" } );
7945		$.datepicker._updateDatepicker( inst );
7946
7947		// fix width for dynamic number of date pickers
7948		// and adjust position before showing
7949		offset = $.datepicker._checkOffset( inst, offset, isFixed );
7950		inst.dpDiv.css( { position: ( $.datepicker._inDialog && $.blockUI ?
7951			"static" : ( isFixed ? "fixed" : "absolute" ) ), display: "none",
7952			left: offset.left + "px", top: offset.top + "px" } );
7953
7954		if ( !inst.inline ) {
7955			showAnim = $.datepicker._get( inst, "showAnim" );
7956			duration = $.datepicker._get( inst, "duration" );
7957			inst.dpDiv.css( "z-index", datepicker_getZindex( $( input ) ) + 1 );
7958			$.datepicker._datepickerShowing = true;
7959
7960			if ( $.effects && $.effects.effect[ showAnim ] ) {
7961				inst.dpDiv.show( showAnim, $.datepicker._get( inst, "showOptions" ), duration );
7962			} else {
7963				inst.dpDiv[ showAnim || "show" ]( showAnim ? duration : null );
7964			}
7965
7966			if ( $.datepicker._shouldFocusInput( inst ) ) {
7967				inst.input.trigger( "focus" );
7968			}
7969
7970			$.datepicker._curInst = inst;
7971		}
7972	},
7973
7974	/* Generate the date picker content. */
7975	_updateDatepicker: function( inst ) {
7976		this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
7977		datepicker_instActive = inst; // for delegate hover events
7978		inst.dpDiv.empty().append( this._generateHTML( inst ) );
7979		this._attachHandlers( inst );
7980
7981		var origyearshtml,
7982			numMonths = this._getNumberOfMonths( inst ),
7983			cols = numMonths[ 1 ],
7984			width = 17,
7985			activeCell = inst.dpDiv.find( "." + this._dayOverClass + " a" );
7986
7987		if ( activeCell.length > 0 ) {
7988			datepicker_handleMouseover.apply( activeCell.get( 0 ) );
7989		}
7990
7991		inst.dpDiv.removeClass( "ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4" ).width( "" );
7992		if ( cols > 1 ) {
7993			inst.dpDiv.addClass( "ui-datepicker-multi-" + cols ).css( "width", ( width * cols ) + "em" );
7994		}
7995		inst.dpDiv[ ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ? "add" : "remove" ) +
7996			"Class" ]( "ui-datepicker-multi" );
7997		inst.dpDiv[ ( this._get( inst, "isRTL" ) ? "add" : "remove" ) +
7998			"Class" ]( "ui-datepicker-rtl" );
7999
8000		if ( inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {
8001			inst.input.trigger( "focus" );
8002		}
8003
8004		// Deffered render of the years select (to avoid flashes on Firefox)
8005		if ( inst.yearshtml ) {
8006			origyearshtml = inst.yearshtml;
8007			setTimeout( function() {
8008
8009				//assure that inst.yearshtml didn't change.
8010				if ( origyearshtml === inst.yearshtml && inst.yearshtml ) {
8011					inst.dpDiv.find( "select.ui-datepicker-year:first" ).replaceWith( inst.yearshtml );
8012				}
8013				origyearshtml = inst.yearshtml = null;
8014			}, 0 );
8015		}
8016	},
8017
8018	// #6694 - don't focus the input if it's already focused
8019	// this breaks the change event in IE
8020	// Support: IE and jQuery <1.9
8021	_shouldFocusInput: function( inst ) {
8022		return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" );
8023	},
8024
8025	/* Check positioning to remain on screen. */
8026	_checkOffset: function( inst, offset, isFixed ) {
8027		var dpWidth = inst.dpDiv.outerWidth(),
8028			dpHeight = inst.dpDiv.outerHeight(),
8029			inputWidth = inst.input ? inst.input.outerWidth() : 0,
8030			inputHeight = inst.input ? inst.input.outerHeight() : 0,
8031			viewWidth = document.documentElement.clientWidth + ( isFixed ? 0 : $( document ).scrollLeft() ),
8032			viewHeight = document.documentElement.clientHeight + ( isFixed ? 0 : $( document ).scrollTop() );
8033
8034		offset.left -= ( this._get( inst, "isRTL" ) ? ( dpWidth - inputWidth ) : 0 );
8035		offset.left -= ( isFixed && offset.left === inst.input.offset().left ) ? $( document ).scrollLeft() : 0;
8036		offset.top -= ( isFixed && offset.top === ( inst.input.offset().top + inputHeight ) ) ? $( document ).scrollTop() : 0;
8037
8038		// Now check if datepicker is showing outside window viewport - move to a better place if so.
8039		offset.left -= Math.min( offset.left, ( offset.left + dpWidth > viewWidth && viewWidth > dpWidth ) ?
8040			Math.abs( offset.left + dpWidth - viewWidth ) : 0 );
8041		offset.top -= Math.min( offset.top, ( offset.top + dpHeight > viewHeight && viewHeight > dpHeight ) ?
8042			Math.abs( dpHeight + inputHeight ) : 0 );
8043
8044		return offset;
8045	},
8046
8047	/* Find an object's position on the screen. */
8048	_findPos: function( obj ) {
8049		var position,
8050			inst = this._getInst( obj ),
8051			isRTL = this._get( inst, "isRTL" );
8052
8053		while ( obj && ( obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.hidden( obj ) ) ) {
8054			obj = obj[ isRTL ? "previousSibling" : "nextSibling" ];
8055		}
8056
8057		position = $( obj ).offset();
8058		return [ position.left, position.top ];
8059	},
8060
8061	/* Hide the date picker from view.
8062	 * @param  input  element - the input field attached to the date picker
8063	 */
8064	_hideDatepicker: function( input ) {
8065		var showAnim, duration, postProcess, onClose,
8066			inst = this._curInst;
8067
8068		if ( !inst || ( input && inst !== $.data( input, "datepicker" ) ) ) {
8069			return;
8070		}
8071
8072		if ( this._datepickerShowing ) {
8073			showAnim = this._get( inst, "showAnim" );
8074			duration = this._get( inst, "duration" );
8075			postProcess = function() {
8076				$.datepicker._tidyDialog( inst );
8077			};
8078
8079			// DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed
8080			if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) {
8081				inst.dpDiv.hide( showAnim, $.datepicker._get( inst, "showOptions" ), duration, postProcess );
8082			} else {
8083				inst.dpDiv[ ( showAnim === "slideDown" ? "slideUp" :
8084					( showAnim === "fadeIn" ? "fadeOut" : "hide" ) ) ]( ( showAnim ? duration : null ), postProcess );
8085			}
8086
8087			if ( !showAnim ) {
8088				postProcess();
8089			}
8090			this._datepickerShowing = false;
8091
8092			onClose = this._get( inst, "onClose" );
8093			if ( onClose ) {
8094				onClose.apply( ( inst.input ? inst.input[ 0 ] : null ), [ ( inst.input ? inst.input.val() : "" ), inst ] );
8095			}
8096
8097			this._lastInput = null;
8098			if ( this._inDialog ) {
8099				this._dialogInput.css( { position: "absolute", left: "0", top: "-100px" } );
8100				if ( $.blockUI ) {
8101					$.unblockUI();
8102					$( "body" ).append( this.dpDiv );
8103				}
8104			}
8105			this._inDialog = false;
8106		}
8107	},
8108
8109	/* Tidy up after a dialog display. */
8110	_tidyDialog: function( inst ) {
8111		inst.dpDiv.removeClass( this._dialogClass ).off( ".ui-datepicker-calendar" );
8112	},
8113
8114	/* Close date picker if clicked elsewhere. */
8115	_checkExternalClick: function( event ) {
8116		if ( !$.datepicker._curInst ) {
8117			return;
8118		}
8119
8120		var $target = $( event.target ),
8121			inst = $.datepicker._getInst( $target[ 0 ] );
8122
8123		if ( ( ( $target[ 0 ].id !== $.datepicker._mainDivId &&
8124				$target.parents( "#" + $.datepicker._mainDivId ).length === 0 &&
8125				!$target.hasClass( $.datepicker.markerClassName ) &&
8126				!$target.closest( "." + $.datepicker._triggerClass ).length &&
8127				$.datepicker._datepickerShowing && !( $.datepicker._inDialog && $.blockUI ) ) ) ||
8128			( $target.hasClass( $.datepicker.markerClassName ) && $.datepicker._curInst !== inst ) ) {
8129				$.datepicker._hideDatepicker();
8130		}
8131	},
8132
8133	/* Adjust one of the date sub-fields. */
8134	_adjustDate: function( id, offset, period ) {
8135		var target = $( id ),
8136			inst = this._getInst( target[ 0 ] );
8137
8138		if ( this._isDisabledDatepicker( target[ 0 ] ) ) {
8139			return;
8140		}
8141		this._adjustInstDate( inst, offset +
8142			( period === "M" ? this._get( inst, "showCurrentAtPos" ) : 0 ), // undo positioning
8143			period );
8144		this._updateDatepicker( inst );
8145	},
8146
8147	/* Action for current link. */
8148	_gotoToday: function( id ) {
8149		var date,
8150			target = $( id ),
8151			inst = this._getInst( target[ 0 ] );
8152
8153		if ( this._get( inst, "gotoCurrent" ) && inst.currentDay ) {
8154			inst.selectedDay = inst.currentDay;
8155			inst.drawMonth = inst.selectedMonth = inst.currentMonth;
8156			inst.drawYear = inst.selectedYear = inst.currentYear;
8157		} else {
8158			date = new Date();
8159			inst.selectedDay = date.getDate();
8160			inst.drawMonth = inst.selectedMonth = date.getMonth();
8161			inst.drawYear = inst.selectedYear = date.getFullYear();
8162		}
8163		this._notifyChange( inst );
8164		this._adjustDate( target );
8165	},
8166
8167	/* Action for selecting a new month/year. */
8168	_selectMonthYear: function( id, select, period ) {
8169		var target = $( id ),
8170			inst = this._getInst( target[ 0 ] );
8171
8172		inst[ "selected" + ( period === "M" ? "Month" : "Year" ) ] =
8173		inst[ "draw" + ( period === "M" ? "Month" : "Year" ) ] =
8174			parseInt( select.options[ select.selectedIndex ].value, 10 );
8175
8176		this._notifyChange( inst );
8177		this._adjustDate( target );
8178	},
8179
8180	/* Action for selecting a day. */
8181	_selectDay: function( id, month, year, td ) {
8182		var inst,
8183			target = $( id );
8184
8185		if ( $( td ).hasClass( this._unselectableClass ) || this._isDisabledDatepicker( target[ 0 ] ) ) {
8186			return;
8187		}
8188
8189		inst = this._getInst( target[ 0 ] );
8190		inst.selectedDay = inst.currentDay = $( "a", td ).html();
8191		inst.selectedMonth = inst.currentMonth = month;
8192		inst.selectedYear = inst.currentYear = year;
8193		this._selectDate( id, this._formatDate( inst,
8194			inst.currentDay, inst.currentMonth, inst.currentYear ) );
8195	},
8196
8197	/* Erase the input field and hide the date picker. */
8198	_clearDate: function( id ) {
8199		var target = $( id );
8200		this._selectDate( target, "" );
8201	},
8202
8203	/* Update the input field with the selected date. */
8204	_selectDate: function( id, dateStr ) {
8205		var onSelect,
8206			target = $( id ),
8207			inst = this._getInst( target[ 0 ] );
8208
8209		dateStr = ( dateStr != null ? dateStr : this._formatDate( inst ) );
8210		if ( inst.input ) {
8211			inst.input.val( dateStr );
8212		}
8213		this._updateAlternate( inst );
8214
8215		onSelect = this._get( inst, "onSelect" );
8216		if ( onSelect ) {
8217			onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] );  // trigger custom callback
8218		} else if ( inst.input ) {
8219			inst.input.trigger( "change" ); // fire the change event
8220		}
8221
8222		if ( inst.inline ) {
8223			this._updateDatepicker( inst );
8224		} else {
8225			this._hideDatepicker();
8226			this._lastInput = inst.input[ 0 ];
8227			if ( typeof( inst.input[ 0 ] ) !== "object" ) {
8228				inst.input.trigger( "focus" ); // restore focus
8229			}
8230			this._lastInput = null;
8231		}
8232	},
8233
8234	/* Update any alternate field to synchronise with the main field. */
8235	_updateAlternate: function( inst ) {
8236		var altFormat, date, dateStr,
8237			altField = this._get( inst, "altField" );
8238
8239		if ( altField ) { // update alternate field too
8240			altFormat = this._get( inst, "altFormat" ) || this._get( inst, "dateFormat" );
8241			date = this._getDate( inst );
8242			dateStr = this.formatDate( altFormat, date, this._getFormatConfig( inst ) );
8243			$( altField ).val( dateStr );
8244		}
8245	},
8246
8247	/* Set as beforeShowDay function to prevent selection of weekends.
8248	 * @param  date  Date - the date to customise
8249	 * @return [boolean, string] - is this date selectable?, what is its CSS class?
8250	 */
8251	noWeekends: function( date ) {
8252		var day = date.getDay();
8253		return [ ( day > 0 && day < 6 ), "" ];
8254	},
8255
8256	/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
8257	 * @param  date  Date - the date to get the week for
8258	 * @return  number - the number of the week within the year that contains this date
8259	 */
8260	iso8601Week: function( date ) {
8261		var time,
8262			checkDate = new Date( date.getTime() );
8263
8264		// Find Thursday of this week starting on Monday
8265		checkDate.setDate( checkDate.getDate() + 4 - ( checkDate.getDay() || 7 ) );
8266
8267		time = checkDate.getTime();
8268		checkDate.setMonth( 0 ); // Compare with Jan 1
8269		checkDate.setDate( 1 );
8270		return Math.floor( Math.round( ( time - checkDate ) / 86400000 ) / 7 ) + 1;
8271	},
8272
8273	/* Parse a string value into a date object.
8274	 * See formatDate below for the possible formats.
8275	 *
8276	 * @param  format string - the expected format of the date
8277	 * @param  value string - the date in the above format
8278	 * @param  settings Object - attributes include:
8279	 *					shortYearCutoff  number - the cutoff year for determining the century (optional)
8280	 *					dayNamesShort	string[7] - abbreviated names of the days from Sunday (optional)
8281	 *					dayNames		string[7] - names of the days from Sunday (optional)
8282	 *					monthNamesShort string[12] - abbreviated names of the months (optional)
8283	 *					monthNames		string[12] - names of the months (optional)
8284	 * @return  Date - the extracted date value or null if value is blank
8285	 */
8286	parseDate: function( format, value, settings ) {
8287		if ( format == null || value == null ) {
8288			throw "Invalid arguments";
8289		}
8290
8291		value = ( typeof value === "object" ? value.toString() : value + "" );
8292		if ( value === "" ) {
8293			return null;
8294		}
8295
8296		var iFormat, dim, extra,
8297			iValue = 0,
8298			shortYearCutoffTemp = ( settings ? settings.shortYearCutoff : null ) || this._defaults.shortYearCutoff,
8299			shortYearCutoff = ( typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp :
8300				new Date().getFullYear() % 100 + parseInt( shortYearCutoffTemp, 10 ) ),
8301			dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort,
8302			dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames,
8303			monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort,
8304			monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames,
8305			year = -1,
8306			month = -1,
8307			day = -1,
8308			doy = -1,
8309			literal = false,
8310			date,
8311
8312			// Check whether a format character is doubled
8313			lookAhead = function( match ) {
8314				var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
8315				if ( matches ) {
8316					iFormat++;
8317				}
8318				return matches;
8319			},
8320
8321			// Extract a number from the string value
8322			getNumber = function( match ) {
8323				var isDoubled = lookAhead( match ),
8324					size = ( match === "@" ? 14 : ( match === "!" ? 20 :
8325					( match === "y" && isDoubled ? 4 : ( match === "o" ? 3 : 2 ) ) ) ),
8326					minSize = ( match === "y" ? size : 1 ),
8327					digits = new RegExp( "^\\d{" + minSize + "," + size + "}" ),
8328					num = value.substring( iValue ).match( digits );
8329				if ( !num ) {
8330					throw "Missing number at position " + iValue;
8331				}
8332				iValue += num[ 0 ].length;
8333				return parseInt( num[ 0 ], 10 );
8334			},
8335
8336			// Extract a name from the string value and convert to an index
8337			getName = function( match, shortNames, longNames ) {
8338				var index = -1,
8339					names = $.map( lookAhead( match ) ? longNames : shortNames, function( v, k ) {
8340						return [ [ k, v ] ];
8341					} ).sort( function( a, b ) {
8342						return -( a[ 1 ].length - b[ 1 ].length );
8343					} );
8344
8345				$.each( names, function( i, pair ) {
8346					var name = pair[ 1 ];
8347					if ( value.substr( iValue, name.length ).toLowerCase() === name.toLowerCase() ) {
8348						index = pair[ 0 ];
8349						iValue += name.length;
8350						return false;
8351					}
8352				} );
8353				if ( index !== -1 ) {
8354					return index + 1;
8355				} else {
8356					throw "Unknown name at position " + iValue;
8357				}
8358			},
8359
8360			// Confirm that a literal character matches the string value
8361			checkLiteral = function() {
8362				if ( value.charAt( iValue ) !== format.charAt( iFormat ) ) {
8363					throw "Unexpected literal at position " + iValue;
8364				}
8365				iValue++;
8366			};
8367
8368		for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
8369			if ( literal ) {
8370				if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
8371					literal = false;
8372				} else {
8373					checkLiteral();
8374				}
8375			} else {
8376				switch ( format.charAt( iFormat ) ) {
8377					case "d":
8378						day = getNumber( "d" );
8379						break;
8380					case "D":
8381						getName( "D", dayNamesShort, dayNames );
8382						break;
8383					case "o":
8384						doy = getNumber( "o" );
8385						break;
8386					case "m":
8387						month = getNumber( "m" );
8388						break;
8389					case "M":
8390						month = getName( "M", monthNamesShort, monthNames );
8391						break;
8392					case "y":
8393						year = getNumber( "y" );
8394						break;
8395					case "@":
8396						date = new Date( getNumber( "@" ) );
8397						year = date.getFullYear();
8398						month = date.getMonth() + 1;
8399						day = date.getDate();
8400						break;
8401					case "!":
8402						date = new Date( ( getNumber( "!" ) - this._ticksTo1970 ) / 10000 );
8403						year = date.getFullYear();
8404						month = date.getMonth() + 1;
8405						day = date.getDate();
8406						break;
8407					case "'":
8408						if ( lookAhead( "'" ) ) {
8409							checkLiteral();
8410						} else {
8411							literal = true;
8412						}
8413						break;
8414					default:
8415						checkLiteral();
8416				}
8417			}
8418		}
8419
8420		if ( iValue < value.length ) {
8421			extra = value.substr( iValue );
8422			if ( !/^\s+/.test( extra ) ) {
8423				throw "Extra/unparsed characters found in date: " + extra;
8424			}
8425		}
8426
8427		if ( year === -1 ) {
8428			year = new Date().getFullYear();
8429		} else if ( year < 100 ) {
8430			year += new Date().getFullYear() - new Date().getFullYear() % 100 +
8431				( year <= shortYearCutoff ? 0 : -100 );
8432		}
8433
8434		if ( doy > -1 ) {
8435			month = 1;
8436			day = doy;
8437			do {
8438				dim = this._getDaysInMonth( year, month - 1 );
8439				if ( day <= dim ) {
8440					break;
8441				}
8442				month++;
8443				day -= dim;
8444			} while ( true );
8445		}
8446
8447		date = this._daylightSavingAdjust( new Date( year, month - 1, day ) );
8448		if ( date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day ) {
8449			throw "Invalid date"; // E.g. 31/02/00
8450		}
8451		return date;
8452	},
8453
8454	/* Standard date formats. */
8455	ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601)
8456	COOKIE: "D, dd M yy",
8457	ISO_8601: "yy-mm-dd",
8458	RFC_822: "D, d M y",
8459	RFC_850: "DD, dd-M-y",
8460	RFC_1036: "D, d M y",
8461	RFC_1123: "D, d M yy",
8462	RFC_2822: "D, d M yy",
8463	RSS: "D, d M y", // RFC 822
8464	TICKS: "!",
8465	TIMESTAMP: "@",
8466	W3C: "yy-mm-dd", // ISO 8601
8467
8468	_ticksTo1970: ( ( ( 1970 - 1 ) * 365 + Math.floor( 1970 / 4 ) - Math.floor( 1970 / 100 ) +
8469		Math.floor( 1970 / 400 ) ) * 24 * 60 * 60 * 10000000 ),
8470
8471	/* Format a date object into a string value.
8472	 * The format can be combinations of the following:
8473	 * d  - day of month (no leading zero)
8474	 * dd - day of month (two digit)
8475	 * o  - day of year (no leading zeros)
8476	 * oo - day of year (three digit)
8477	 * D  - day name short
8478	 * DD - day name long
8479	 * m  - month of year (no leading zero)
8480	 * mm - month of year (two digit)
8481	 * M  - month name short
8482	 * MM - month name long
8483	 * y  - year (two digit)
8484	 * yy - year (four digit)
8485	 * @ - Unix timestamp (ms since 01/01/1970)
8486	 * ! - Windows ticks (100ns since 01/01/0001)
8487	 * "..." - literal text
8488	 * '' - single quote
8489	 *
8490	 * @param  format string - the desired format of the date
8491	 * @param  date Date - the date value to format
8492	 * @param  settings Object - attributes include:
8493	 *					dayNamesShort	string[7] - abbreviated names of the days from Sunday (optional)
8494	 *					dayNames		string[7] - names of the days from Sunday (optional)
8495	 *					monthNamesShort string[12] - abbreviated names of the months (optional)
8496	 *					monthNames		string[12] - names of the months (optional)
8497	 * @return  string - the date in the above format
8498	 */
8499	formatDate: function( format, date, settings ) {
8500		if ( !date ) {
8501			return "";
8502		}
8503
8504		var iFormat,
8505			dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort,
8506			dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames,
8507			monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort,
8508			monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames,
8509
8510			// Check whether a format character is doubled
8511			lookAhead = function( match ) {
8512				var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
8513				if ( matches ) {
8514					iFormat++;
8515				}
8516				return matches;
8517			},
8518
8519			// Format a number, with leading zero if necessary
8520			formatNumber = function( match, value, len ) {
8521				var num = "" + value;
8522				if ( lookAhead( match ) ) {
8523					while ( num.length < len ) {
8524						num = "0" + num;
8525					}
8526				}
8527				return num;
8528			},
8529
8530			// Format a name, short or long as requested
8531			formatName = function( match, value, shortNames, longNames ) {
8532				return ( lookAhead( match ) ? longNames[ value ] : shortNames[ value ] );
8533			},
8534			output = "",
8535			literal = false;
8536
8537		if ( date ) {
8538			for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
8539				if ( literal ) {
8540					if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
8541						literal = false;
8542					} else {
8543						output += format.charAt( iFormat );
8544					}
8545				} else {
8546					switch ( format.charAt( iFormat ) ) {
8547						case "d":
8548							output += formatNumber( "d", date.getDate(), 2 );
8549							break;
8550						case "D":
8551							output += formatName( "D", date.getDay(), dayNamesShort, dayNames );
8552							break;
8553						case "o":
8554							output += formatNumber( "o",
8555								Math.round( ( new Date( date.getFullYear(), date.getMonth(), date.getDate() ).getTime() - new Date( date.getFullYear(), 0, 0 ).getTime() ) / 86400000 ), 3 );
8556							break;
8557						case "m":
8558							output += formatNumber( "m", date.getMonth() + 1, 2 );
8559							break;
8560						case "M":
8561							output += formatName( "M", date.getMonth(), monthNamesShort, monthNames );
8562							break;
8563						case "y":
8564							output += ( lookAhead( "y" ) ? date.getFullYear() :
8565								( date.getFullYear() % 100 < 10 ? "0" : "" ) + date.getFullYear() % 100 );
8566							break;
8567						case "@":
8568							output += date.getTime();
8569							break;
8570						case "!":
8571							output += date.getTime() * 10000 + this._ticksTo1970;
8572							break;
8573						case "'":
8574							if ( lookAhead( "'" ) ) {
8575								output += "'";
8576							} else {
8577								literal = true;
8578							}
8579							break;
8580						default:
8581							output += format.charAt( iFormat );
8582					}
8583				}
8584			}
8585		}
8586		return output;
8587	},
8588
8589	/* Extract all possible characters from the date format. */
8590	_possibleChars: function( format ) {
8591		var iFormat,
8592			chars = "",
8593			literal = false,
8594
8595			// Check whether a format character is doubled
8596			lookAhead = function( match ) {
8597				var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
8598				if ( matches ) {
8599					iFormat++;
8600				}
8601				return matches;
8602			};
8603
8604		for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
8605			if ( literal ) {
8606				if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
8607					literal = false;
8608				} else {
8609					chars += format.charAt( iFormat );
8610				}
8611			} else {
8612				switch ( format.charAt( iFormat ) ) {
8613					case "d": case "m": case "y": case "@":
8614						chars += "0123456789";
8615						break;
8616					case "D": case "M":
8617						return null; // Accept anything
8618					case "'":
8619						if ( lookAhead( "'" ) ) {
8620							chars += "'";
8621						} else {
8622							literal = true;
8623						}
8624						break;
8625					default:
8626						chars += format.charAt( iFormat );
8627				}
8628			}
8629		}
8630		return chars;
8631	},
8632
8633	/* Get a setting value, defaulting if necessary. */
8634	_get: function( inst, name ) {
8635		return inst.settings[ name ] !== undefined ?
8636			inst.settings[ name ] : this._defaults[ name ];
8637	},
8638
8639	/* Parse existing date and initialise date picker. */
8640	_setDateFromField: function( inst, noDefault ) {
8641		if ( inst.input.val() === inst.lastVal ) {
8642			return;
8643		}
8644
8645		var dateFormat = this._get( inst, "dateFormat" ),
8646			dates = inst.lastVal = inst.input ? inst.input.val() : null,
8647			defaultDate = this._getDefaultDate( inst ),
8648			date = defaultDate,
8649			settings = this._getFormatConfig( inst );
8650
8651		try {
8652			date = this.parseDate( dateFormat, dates, settings ) || defaultDate;
8653		} catch ( event ) {
8654			dates = ( noDefault ? "" : dates );
8655		}
8656		inst.selectedDay = date.getDate();
8657		inst.drawMonth = inst.selectedMonth = date.getMonth();
8658		inst.drawYear = inst.selectedYear = date.getFullYear();
8659		inst.currentDay = ( dates ? date.getDate() : 0 );
8660		inst.currentMonth = ( dates ? date.getMonth() : 0 );
8661		inst.currentYear = ( dates ? date.getFullYear() : 0 );
8662		this._adjustInstDate( inst );
8663	},
8664
8665	/* Retrieve the default date shown on opening. */
8666	_getDefaultDate: function( inst ) {
8667		return this._restrictMinMax( inst,
8668			this._determineDate( inst, this._get( inst, "defaultDate" ), new Date() ) );
8669	},
8670
8671	/* A date may be specified as an exact value or a relative one. */
8672	_determineDate: function( inst, date, defaultDate ) {
8673		var offsetNumeric = function( offset ) {
8674				var date = new Date();
8675				date.setDate( date.getDate() + offset );
8676				return date;
8677			},
8678			offsetString = function( offset ) {
8679				try {
8680					return $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ),
8681						offset, $.datepicker._getFormatConfig( inst ) );
8682				}
8683				catch ( e ) {
8684
8685					// Ignore
8686				}
8687
8688				var date = ( offset.toLowerCase().match( /^c/ ) ?
8689					$.datepicker._getDate( inst ) : null ) || new Date(),
8690					year = date.getFullYear(),
8691					month = date.getMonth(),
8692					day = date.getDate(),
8693					pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,
8694					matches = pattern.exec( offset );
8695
8696				while ( matches ) {
8697					switch ( matches[ 2 ] || "d" ) {
8698						case "d" : case "D" :
8699							day += parseInt( matches[ 1 ], 10 ); break;
8700						case "w" : case "W" :
8701							day += parseInt( matches[ 1 ], 10 ) * 7; break;
8702						case "m" : case "M" :
8703							month += parseInt( matches[ 1 ], 10 );
8704							day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) );
8705							break;
8706						case "y": case "Y" :
8707							year += parseInt( matches[ 1 ], 10 );
8708							day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) );
8709							break;
8710					}
8711					matches = pattern.exec( offset );
8712				}
8713				return new Date( year, month, day );
8714			},
8715			newDate = ( date == null || date === "" ? defaultDate : ( typeof date === "string" ? offsetString( date ) :
8716				( typeof date === "number" ? ( isNaN( date ) ? defaultDate : offsetNumeric( date ) ) : new Date( date.getTime() ) ) ) );
8717
8718		newDate = ( newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate );
8719		if ( newDate ) {
8720			newDate.setHours( 0 );
8721			newDate.setMinutes( 0 );
8722			newDate.setSeconds( 0 );
8723			newDate.setMilliseconds( 0 );
8724		}
8725		return this._daylightSavingAdjust( newDate );
8726	},
8727
8728	/* Handle switch to/from daylight saving.
8729	 * Hours may be non-zero on daylight saving cut-over:
8730	 * > 12 when midnight changeover, but then cannot generate
8731	 * midnight datetime, so jump to 1AM, otherwise reset.
8732	 * @param  date  (Date) the date to check
8733	 * @return  (Date) the corrected date
8734	 */
8735	_daylightSavingAdjust: function( date ) {
8736		if ( !date ) {
8737			return null;
8738		}
8739		date.setHours( date.getHours() > 12 ? date.getHours() + 2 : 0 );
8740		return date;
8741	},
8742
8743	/* Set the date(s) directly. */
8744	_setDate: function( inst, date, noChange ) {
8745		var clear = !date,
8746			origMonth = inst.selectedMonth,
8747			origYear = inst.selectedYear,
8748			newDate = this._restrictMinMax( inst, this._determineDate( inst, date, new Date() ) );
8749
8750		inst.selectedDay = inst.currentDay = newDate.getDate();
8751		inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
8752		inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
8753		if ( ( origMonth !== inst.selectedMonth || origYear !== inst.selectedYear ) && !noChange ) {
8754			this._notifyChange( inst );
8755		}
8756		this._adjustInstDate( inst );
8757		if ( inst.input ) {
8758			inst.input.val( clear ? "" : this._formatDate( inst ) );
8759		}
8760	},
8761
8762	/* Retrieve the date(s) directly. */
8763	_getDate: function( inst ) {
8764		var startDate = ( !inst.currentYear || ( inst.input && inst.input.val() === "" ) ? null :
8765			this._daylightSavingAdjust( new Date(
8766			inst.currentYear, inst.currentMonth, inst.currentDay ) ) );
8767			return startDate;
8768	},
8769
8770	/* Attach the onxxx handlers.  These are declared statically so
8771	 * they work with static code transformers like Caja.
8772	 */
8773	_attachHandlers: function( inst ) {
8774		var stepMonths = this._get( inst, "stepMonths" ),
8775			id = "#" + inst.id.replace( /\\\\/g, "\\" );
8776		inst.dpDiv.find( "[data-handler]" ).map( function() {
8777			var handler = {
8778				prev: function() {
8779					$.datepicker._adjustDate( id, -stepMonths, "M" );
8780				},
8781				next: function() {
8782					$.datepicker._adjustDate( id, +stepMonths, "M" );
8783				},
8784				hide: function() {
8785					$.datepicker._hideDatepicker();
8786				},
8787				today: function() {
8788					$.datepicker._gotoToday( id );
8789				},
8790				selectDay: function() {
8791					$.datepicker._selectDay( id, +this.getAttribute( "data-month" ), +this.getAttribute( "data-year" ), this );
8792					return false;
8793				},
8794				selectMonth: function() {
8795					$.datepicker._selectMonthYear( id, this, "M" );
8796					return false;
8797				},
8798				selectYear: function() {
8799					$.datepicker._selectMonthYear( id, this, "Y" );
8800					return false;
8801				}
8802			};
8803			$( this ).on( this.getAttribute( "data-event" ), handler[ this.getAttribute( "data-handler" ) ] );
8804		} );
8805	},
8806
8807	/* Generate the HTML for the current state of the date picker. */
8808	_generateHTML: function( inst ) {
8809		var maxDraw, prevText, prev, nextText, next, currentText, gotoDate,
8810			controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,
8811			monthNames, monthNamesShort, beforeShowDay, showOtherMonths,
8812			selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,
8813			cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,
8814			printDate, dRow, tbody, daySettings, otherMonth, unselectable,
8815			tempDate = new Date(),
8816			today = this._daylightSavingAdjust(
8817				new Date( tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate() ) ), // clear time
8818			isRTL = this._get( inst, "isRTL" ),
8819			showButtonPanel = this._get( inst, "showButtonPanel" ),
8820			hideIfNoPrevNext = this._get( inst, "hideIfNoPrevNext" ),
8821			navigationAsDateFormat = this._get( inst, "navigationAsDateFormat" ),
8822			numMonths = this._getNumberOfMonths( inst ),
8823			showCurrentAtPos = this._get( inst, "showCurrentAtPos" ),
8824			stepMonths = this._get( inst, "stepMonths" ),
8825			isMultiMonth = ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ),
8826			currentDate = this._daylightSavingAdjust( ( !inst.currentDay ? new Date( 9999, 9, 9 ) :
8827				new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) ),
8828			minDate = this._getMinMaxDate( inst, "min" ),
8829			maxDate = this._getMinMaxDate( inst, "max" ),
8830			drawMonth = inst.drawMonth - showCurrentAtPos,
8831			drawYear = inst.drawYear;
8832
8833		if ( drawMonth < 0 ) {
8834			drawMonth += 12;
8835			drawYear--;
8836		}
8837		if ( maxDate ) {
8838			maxDraw = this._daylightSavingAdjust( new Date( maxDate.getFullYear(),
8839				maxDate.getMonth() - ( numMonths[ 0 ] * numMonths[ 1 ] ) + 1, maxDate.getDate() ) );
8840			maxDraw = ( minDate && maxDraw < minDate ? minDate : maxDraw );
8841			while ( this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 ) ) > maxDraw ) {
8842				drawMonth--;
8843				if ( drawMonth < 0 ) {
8844					drawMonth = 11;
8845					drawYear--;
8846				}
8847			}
8848		}
8849		inst.drawMonth = drawMonth;
8850		inst.drawYear = drawYear;
8851
8852		prevText = this._get( inst, "prevText" );
8853		prevText = ( !navigationAsDateFormat ? prevText : this.formatDate( prevText,
8854			this._daylightSavingAdjust( new Date( drawYear, drawMonth - stepMonths, 1 ) ),
8855			this._getFormatConfig( inst ) ) );
8856
8857		prev = ( this._canAdjustMonth( inst, -1, drawYear, drawMonth ) ?
8858			"<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click'" +
8859			" title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w" ) + "'>" + prevText + "</span></a>" :
8860			( hideIfNoPrevNext ? "" : "<a class='ui-datepicker-prev ui-corner-all ui-state-disabled' title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w" ) + "'>" + prevText + "</span></a>" ) );
8861
8862		nextText = this._get( inst, "nextText" );
8863		nextText = ( !navigationAsDateFormat ? nextText : this.formatDate( nextText,
8864			this._daylightSavingAdjust( new Date( drawYear, drawMonth + stepMonths, 1 ) ),
8865			this._getFormatConfig( inst ) ) );
8866
8867		next = ( this._canAdjustMonth( inst, +1, drawYear, drawMonth ) ?
8868			"<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click'" +
8869			" title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e" ) + "'>" + nextText + "</span></a>" :
8870			( hideIfNoPrevNext ? "" : "<a class='ui-datepicker-next ui-corner-all ui-state-disabled' title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e" ) + "'>" + nextText + "</span></a>" ) );
8871
8872		currentText = this._get( inst, "currentText" );
8873		gotoDate = ( this._get( inst, "gotoCurrent" ) && inst.currentDay ? currentDate : today );
8874		currentText = ( !navigationAsDateFormat ? currentText :
8875			this.formatDate( currentText, gotoDate, this._getFormatConfig( inst ) ) );
8876
8877		controls = ( !inst.inline ? "<button type='button' class='ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all' data-handler='hide' data-event='click'>" +
8878			this._get( inst, "closeText" ) + "</button>" : "" );
8879
8880		buttonPanel = ( showButtonPanel ) ? "<div class='ui-datepicker-buttonpane ui-widget-content'>" + ( isRTL ? controls : "" ) +
8881			( this._isInRange( inst, gotoDate ) ? "<button type='button' class='ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all' data-handler='today' data-event='click'" +
8882			">" + currentText + "</button>" : "" ) + ( isRTL ? "" : controls ) + "</div>" : "";
8883
8884		firstDay = parseInt( this._get( inst, "firstDay" ), 10 );
8885		firstDay = ( isNaN( firstDay ) ? 0 : firstDay );
8886
8887		showWeek = this._get( inst, "showWeek" );
8888		dayNames = this._get( inst, "dayNames" );
8889		dayNamesMin = this._get( inst, "dayNamesMin" );
8890		monthNames = this._get( inst, "monthNames" );
8891		monthNamesShort = this._get( inst, "monthNamesShort" );
8892		beforeShowDay = this._get( inst, "beforeShowDay" );
8893		showOtherMonths = this._get( inst, "showOtherMonths" );
8894		selectOtherMonths = this._get( inst, "selectOtherMonths" );
8895		defaultDate = this._getDefaultDate( inst );
8896		html = "";
8897
8898		for ( row = 0; row < numMonths[ 0 ]; row++ ) {
8899			group = "";
8900			this.maxRows = 4;
8901			for ( col = 0; col < numMonths[ 1 ]; col++ ) {
8902				selectedDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, inst.selectedDay ) );
8903				cornerClass = " ui-corner-all";
8904				calender = "";
8905				if ( isMultiMonth ) {
8906					calender += "<div class='ui-datepicker-group";
8907					if ( numMonths[ 1 ] > 1 ) {
8908						switch ( col ) {
8909							case 0: calender += " ui-datepicker-group-first";
8910								cornerClass = " ui-corner-" + ( isRTL ? "right" : "left" ); break;
8911							case numMonths[ 1 ] - 1: calender += " ui-datepicker-group-last";
8912								cornerClass = " ui-corner-" + ( isRTL ? "left" : "right" ); break;
8913							default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break;
8914						}
8915					}
8916					calender += "'>";
8917				}
8918				calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" +
8919					( /all|left/.test( cornerClass ) && row === 0 ? ( isRTL ? next : prev ) : "" ) +
8920					( /all|right/.test( cornerClass ) && row === 0 ? ( isRTL ? prev : next ) : "" ) +
8921					this._generateMonthYearHeader( inst, drawMonth, drawYear, minDate, maxDate,
8922					row > 0 || col > 0, monthNames, monthNamesShort ) + // draw month headers
8923					"</div><table class='ui-datepicker-calendar'><thead>" +
8924					"<tr>";
8925				thead = ( showWeek ? "<th class='ui-datepicker-week-col'>" + this._get( inst, "weekHeader" ) + "</th>" : "" );
8926				for ( dow = 0; dow < 7; dow++ ) { // days of the week
8927					day = ( dow + firstDay ) % 7;
8928					thead += "<th scope='col'" + ( ( dow + firstDay + 6 ) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "" ) + ">" +
8929						"<span title='" + dayNames[ day ] + "'>" + dayNamesMin[ day ] + "</span></th>";
8930				}
8931				calender += thead + "</tr></thead><tbody>";
8932				daysInMonth = this._getDaysInMonth( drawYear, drawMonth );
8933				if ( drawYear === inst.selectedYear && drawMonth === inst.selectedMonth ) {
8934					inst.selectedDay = Math.min( inst.selectedDay, daysInMonth );
8935				}
8936				leadDays = ( this._getFirstDayOfMonth( drawYear, drawMonth ) - firstDay + 7 ) % 7;
8937				curRows = Math.ceil( ( leadDays + daysInMonth ) / 7 ); // calculate the number of rows to generate
8938				numRows = ( isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows ); //If multiple months, use the higher number of rows (see #7043)
8939				this.maxRows = numRows;
8940				printDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 - leadDays ) );
8941				for ( dRow = 0; dRow < numRows; dRow++ ) { // create date picker rows
8942					calender += "<tr>";
8943					tbody = ( !showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
8944						this._get( inst, "calculateWeek" )( printDate ) + "</td>" );
8945					for ( dow = 0; dow < 7; dow++ ) { // create date picker days
8946						daySettings = ( beforeShowDay ?
8947							beforeShowDay.apply( ( inst.input ? inst.input[ 0 ] : null ), [ printDate ] ) : [ true, "" ] );
8948						otherMonth = ( printDate.getMonth() !== drawMonth );
8949						unselectable = ( otherMonth && !selectOtherMonths ) || !daySettings[ 0 ] ||
8950							( minDate && printDate < minDate ) || ( maxDate && printDate > maxDate );
8951						tbody += "<td class='" +
8952							( ( dow + firstDay + 6 ) % 7 >= 5 ? " ui-datepicker-week-end" : "" ) + // highlight weekends
8953							( otherMonth ? " ui-datepicker-other-month" : "" ) + // highlight days from other months
8954							( ( printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent ) || // user pressed key
8955							( defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime() ) ?
8956
8957							// or defaultDate is current printedDate and defaultDate is selectedDate
8958							" " + this._dayOverClass : "" ) + // highlight selected day
8959							( unselectable ? " " + this._unselectableClass + " ui-state-disabled" : "" ) +  // highlight unselectable days
8960							( otherMonth && !showOtherMonths ? "" : " " + daySettings[ 1 ] + // highlight custom dates
8961							( printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "" ) + // highlight selected day
8962							( printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "" ) ) + "'" + // highlight today (if different)
8963							( ( !otherMonth || showOtherMonths ) && daySettings[ 2 ] ? " title='" + daySettings[ 2 ].replace( /'/g, "&#39;" ) + "'" : "" ) + // cell title
8964							( unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'" ) + ">" + // actions
8965							( otherMonth && !showOtherMonths ? "&#xa0;" : // display for other months
8966							( unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" +
8967							( printDate.getTime() === today.getTime() ? " ui-state-highlight" : "" ) +
8968							( printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "" ) + // highlight selected day
8969							( otherMonth ? " ui-priority-secondary" : "" ) + // distinguish dates from other months
8970							"' href='#'>" + printDate.getDate() + "</a>" ) ) + "</td>"; // display selectable date
8971						printDate.setDate( printDate.getDate() + 1 );
8972						printDate = this._daylightSavingAdjust( printDate );
8973					}
8974					calender += tbody + "</tr>";
8975				}
8976				drawMonth++;
8977				if ( drawMonth > 11 ) {
8978					drawMonth = 0;
8979					drawYear++;
8980				}
8981				calender += "</tbody></table>" + ( isMultiMonth ? "</div>" +
8982							( ( numMonths[ 0 ] > 0 && col === numMonths[ 1 ] - 1 ) ? "<div class='ui-datepicker-row-break'></div>" : "" ) : "" );
8983				group += calender;
8984			}
8985			html += group;
8986		}
8987		html += buttonPanel;
8988		inst._keyEvent = false;
8989		return html;
8990	},
8991
8992	/* Generate the month and year header. */
8993	_generateMonthYearHeader: function( inst, drawMonth, drawYear, minDate, maxDate,
8994			secondary, monthNames, monthNamesShort ) {
8995
8996		var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,
8997			changeMonth = this._get( inst, "changeMonth" ),
8998			changeYear = this._get( inst, "changeYear" ),
8999			showMonthAfterYear = this._get( inst, "showMonthAfterYear" ),
9000			html = "<div class='ui-datepicker-title'>",
9001			monthHtml = "";
9002
9003		// Month selection
9004		if ( secondary || !changeMonth ) {
9005			monthHtml += "<span class='ui-datepicker-month'>" + monthNames[ drawMonth ] + "</span>";
9006		} else {
9007			inMinYear = ( minDate && minDate.getFullYear() === drawYear );
9008			inMaxYear = ( maxDate && maxDate.getFullYear() === drawYear );
9009			monthHtml += "<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>";
9010			for ( month = 0; month < 12; month++ ) {
9011				if ( ( !inMinYear || month >= minDate.getMonth() ) && ( !inMaxYear || month <= maxDate.getMonth() ) ) {
9012					monthHtml += "<option value='" + month + "'" +
9013						( month === drawMonth ? " selected='selected'" : "" ) +
9014						">" + monthNamesShort[ month ] + "</option>";
9015				}
9016			}
9017			monthHtml += "</select>";
9018		}
9019
9020		if ( !showMonthAfterYear ) {
9021			html += monthHtml + ( secondary || !( changeMonth && changeYear ) ? "&#xa0;" : "" );
9022		}
9023
9024		// Year selection
9025		if ( !inst.yearshtml ) {
9026			inst.yearshtml = "";
9027			if ( secondary || !changeYear ) {
9028				html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
9029			} else {
9030
9031				// determine range of years to display
9032				years = this._get( inst, "yearRange" ).split( ":" );
9033				thisYear = new Date().getFullYear();
9034				determineYear = function( value ) {
9035					var year = ( value.match( /c[+\-].*/ ) ? drawYear + parseInt( value.substring( 1 ), 10 ) :
9036						( value.match( /[+\-].*/ ) ? thisYear + parseInt( value, 10 ) :
9037						parseInt( value, 10 ) ) );
9038					return ( isNaN( year ) ? thisYear : year );
9039				};
9040				year = determineYear( years[ 0 ] );
9041				endYear = Math.max( year, determineYear( years[ 1 ] || "" ) );
9042				year = ( minDate ? Math.max( year, minDate.getFullYear() ) : year );
9043				endYear = ( maxDate ? Math.min( endYear, maxDate.getFullYear() ) : endYear );
9044				inst.yearshtml += "<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>";
9045				for ( ; year <= endYear; year++ ) {
9046					inst.yearshtml += "<option value='" + year + "'" +
9047						( year === drawYear ? " selected='selected'" : "" ) +
9048						">" + year + "</option>";
9049				}
9050				inst.yearshtml += "</select>";
9051
9052				html += inst.yearshtml;
9053				inst.yearshtml = null;
9054			}
9055		}
9056
9057		html += this._get( inst, "yearSuffix" );
9058		if ( showMonthAfterYear ) {
9059			html += ( secondary || !( changeMonth && changeYear ) ? "&#xa0;" : "" ) + monthHtml;
9060		}
9061		html += "</div>"; // Close datepicker_header
9062		return html;
9063	},
9064
9065	/* Adjust one of the date sub-fields. */
9066	_adjustInstDate: function( inst, offset, period ) {
9067		var year = inst.selectedYear + ( period === "Y" ? offset : 0 ),
9068			month = inst.selectedMonth + ( period === "M" ? offset : 0 ),
9069			day = Math.min( inst.selectedDay, this._getDaysInMonth( year, month ) ) + ( period === "D" ? offset : 0 ),
9070			date = this._restrictMinMax( inst, this._daylightSavingAdjust( new Date( year, month, day ) ) );
9071
9072		inst.selectedDay = date.getDate();
9073		inst.drawMonth = inst.selectedMonth = date.getMonth();
9074		inst.drawYear = inst.selectedYear = date.getFullYear();
9075		if ( period === "M" || period === "Y" ) {
9076			this._notifyChange( inst );
9077		}
9078	},
9079
9080	/* Ensure a date is within any min/max bounds. */
9081	_restrictMinMax: function( inst, date ) {
9082		var minDate = this._getMinMaxDate( inst, "min" ),
9083			maxDate = this._getMinMaxDate( inst, "max" ),
9084			newDate = ( minDate && date < minDate ? minDate : date );
9085		return ( maxDate && newDate > maxDate ? maxDate : newDate );
9086	},
9087
9088	/* Notify change of month/year. */
9089	_notifyChange: function( inst ) {
9090		var onChange = this._get( inst, "onChangeMonthYear" );
9091		if ( onChange ) {
9092			onChange.apply( ( inst.input ? inst.input[ 0 ] : null ),
9093				[ inst.selectedYear, inst.selectedMonth + 1, inst ] );
9094		}
9095	},
9096
9097	/* Determine the number of months to show. */
9098	_getNumberOfMonths: function( inst ) {
9099		var numMonths = this._get( inst, "numberOfMonths" );
9100		return ( numMonths == null ? [ 1, 1 ] : ( typeof numMonths === "number" ? [ 1, numMonths ] : numMonths ) );
9101	},
9102
9103	/* Determine the current maximum date - ensure no time components are set. */
9104	_getMinMaxDate: function( inst, minMax ) {
9105		return this._determineDate( inst, this._get( inst, minMax + "Date" ), null );
9106	},
9107
9108	/* Find the number of days in a given month. */
9109	_getDaysInMonth: function( year, month ) {
9110		return 32 - this._daylightSavingAdjust( new Date( year, month, 32 ) ).getDate();
9111	},
9112
9113	/* Find the day of the week of the first of a month. */
9114	_getFirstDayOfMonth: function( year, month ) {
9115		return new Date( year, month, 1 ).getDay();
9116	},
9117
9118	/* Determines if we should allow a "next/prev" month display change. */
9119	_canAdjustMonth: function( inst, offset, curYear, curMonth ) {
9120		var numMonths = this._getNumberOfMonths( inst ),
9121			date = this._daylightSavingAdjust( new Date( curYear,
9122			curMonth + ( offset < 0 ? offset : numMonths[ 0 ] * numMonths[ 1 ] ), 1 ) );
9123
9124		if ( offset < 0 ) {
9125			date.setDate( this._getDaysInMonth( date.getFullYear(), date.getMonth() ) );
9126		}
9127		return this._isInRange( inst, date );
9128	},
9129
9130	/* Is the given date in the accepted range? */
9131	_isInRange: function( inst, date ) {
9132		var yearSplit, currentYear,
9133			minDate = this._getMinMaxDate( inst, "min" ),
9134			maxDate = this._getMinMaxDate( inst, "max" ),
9135			minYear = null,
9136			maxYear = null,
9137			years = this._get( inst, "yearRange" );
9138			if ( years ) {
9139				yearSplit = years.split( ":" );
9140				currentYear = new Date().getFullYear();
9141				minYear = parseInt( yearSplit[ 0 ], 10 );
9142				maxYear = parseInt( yearSplit[ 1 ], 10 );
9143				if ( yearSplit[ 0 ].match( /[+\-].*/ ) ) {
9144					minYear += currentYear;
9145				}
9146				if ( yearSplit[ 1 ].match( /[+\-].*/ ) ) {
9147					maxYear += currentYear;
9148				}
9149			}
9150
9151		return ( ( !minDate || date.getTime() >= minDate.getTime() ) &&
9152			( !maxDate || date.getTime() <= maxDate.getTime() ) &&
9153			( !minYear || date.getFullYear() >= minYear ) &&
9154			( !maxYear || date.getFullYear() <= maxYear ) );
9155	},
9156
9157	/* Provide the configuration settings for formatting/parsing. */
9158	_getFormatConfig: function( inst ) {
9159		var shortYearCutoff = this._get( inst, "shortYearCutoff" );
9160		shortYearCutoff = ( typeof shortYearCutoff !== "string" ? shortYearCutoff :
9161			new Date().getFullYear() % 100 + parseInt( shortYearCutoff, 10 ) );
9162		return { shortYearCutoff: shortYearCutoff,
9163			dayNamesShort: this._get( inst, "dayNamesShort" ), dayNames: this._get( inst, "dayNames" ),
9164			monthNamesShort: this._get( inst, "monthNamesShort" ), monthNames: this._get( inst, "monthNames" ) };
9165	},
9166
9167	/* Format the given date for display. */
9168	_formatDate: function( inst, day, month, year ) {
9169		if ( !day ) {
9170			inst.currentDay = inst.selectedDay;
9171			inst.currentMonth = inst.selectedMonth;
9172			inst.currentYear = inst.selectedYear;
9173		}
9174		var date = ( day ? ( typeof day === "object" ? day :
9175			this._daylightSavingAdjust( new Date( year, month, day ) ) ) :
9176			this._daylightSavingAdjust( new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) );
9177		return this.formatDate( this._get( inst, "dateFormat" ), date, this._getFormatConfig( inst ) );
9178	}
9179} );
9180
9181/*
9182 * Bind hover events for datepicker elements.
9183 * Done via delegate so the binding only occurs once in the lifetime of the parent div.
9184 * Global datepicker_instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
9185 */
9186function datepicker_bindHover( dpDiv ) {
9187	var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";
9188	return dpDiv.on( "mouseout", selector, function() {
9189			$( this ).removeClass( "ui-state-hover" );
9190			if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) {
9191				$( this ).removeClass( "ui-datepicker-prev-hover" );
9192			}
9193			if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) {
9194				$( this ).removeClass( "ui-datepicker-next-hover" );
9195			}
9196		} )
9197		.on( "mouseover", selector, datepicker_handleMouseover );
9198}
9199
9200function datepicker_handleMouseover() {
9201	if ( !$.datepicker._isDisabledDatepicker( datepicker_instActive.inline ? datepicker_instActive.dpDiv.parent()[ 0 ] : datepicker_instActive.input[ 0 ] ) ) {
9202		$( this ).parents( ".ui-datepicker-calendar" ).find( "a" ).removeClass( "ui-state-hover" );
9203		$( this ).addClass( "ui-state-hover" );
9204		if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) {
9205			$( this ).addClass( "ui-datepicker-prev-hover" );
9206		}
9207		if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) {
9208			$( this ).addClass( "ui-datepicker-next-hover" );
9209		}
9210	}
9211}
9212
9213/* jQuery extend now ignores nulls! */
9214function datepicker_extendRemove( target, props ) {
9215	$.extend( target, props );
9216	for ( var name in props ) {
9217		if ( props[ name ] == null ) {
9218			target[ name ] = props[ name ];
9219		}
9220	}
9221	return target;
9222}
9223
9224/* Invoke the datepicker functionality.
9225   @param  options  string - a command, optionally followed by additional parameters or
9226					Object - settings for attaching new datepicker functionality
9227   @return  jQuery object */
9228$.fn.datepicker = function( options ) {
9229
9230	/* Verify an empty collection wasn't passed - Fixes #6976 */
9231	if ( !this.length ) {
9232		return this;
9233	}
9234
9235	/* Initialise the date picker. */
9236	if ( !$.datepicker.initialized ) {
9237		$( document ).on( "mousedown", $.datepicker._checkExternalClick );
9238		$.datepicker.initialized = true;
9239	}
9240
9241	/* Append datepicker main container to body if not exist. */
9242	if ( $( "#" + $.datepicker._mainDivId ).length === 0 ) {
9243		$( "body" ).append( $.datepicker.dpDiv );
9244	}
9245
9246	var otherArgs = Array.prototype.slice.call( arguments, 1 );
9247	if ( typeof options === "string" && ( options === "isDisabled" || options === "getDate" || options === "widget" ) ) {
9248		return $.datepicker[ "_" + options + "Datepicker" ].
9249			apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) );
9250	}
9251	if ( options === "option" && arguments.length === 2 && typeof arguments[ 1 ] === "string" ) {
9252		return $.datepicker[ "_" + options + "Datepicker" ].
9253			apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) );
9254	}
9255	return this.each( function() {
9256		typeof options === "string" ?
9257			$.datepicker[ "_" + options + "Datepicker" ].
9258				apply( $.datepicker, [ this ].concat( otherArgs ) ) :
9259			$.datepicker._attachDatepicker( this, options );
9260	} );
9261};
9262
9263$.datepicker = new Datepicker(); // singleton instance
9264$.datepicker.initialized = false;
9265$.datepicker.uuid = new Date().getTime();
9266$.datepicker.version = "1.12.1";
9267
9268var widgetsDatepicker = $.datepicker;
9269
9270
9271
9272
9273// This file is deprecated
9274var ie = $.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() );
9275
9276/*!
9277 * jQuery UI Mouse 1.12.1
9278 * http://jqueryui.com
9279 *
9280 * Copyright jQuery Foundation and other contributors
9281 * Released under the MIT license.
9282 * http://jquery.org/license
9283 */
9284
9285//>>label: Mouse
9286//>>group: Widgets
9287//>>description: Abstracts mouse-based interactions to assist in creating certain widgets.
9288//>>docs: http://api.jqueryui.com/mouse/
9289
9290
9291
9292var mouseHandled = false;
9293$( document ).on( "mouseup", function() {
9294	mouseHandled = false;
9295} );
9296
9297var widgetsMouse = $.widget( "ui.mouse", {
9298	version: "1.12.1",
9299	options: {
9300		cancel: "input, textarea, button, select, option",
9301		distance: 1,
9302		delay: 0
9303	},
9304	_mouseInit: function() {
9305		var that = this;
9306
9307		this.element
9308			.on( "mousedown." + this.widgetName, function( event ) {
9309				return that._mouseDown( event );
9310			} )
9311			.on( "click." + this.widgetName, function( event ) {
9312				if ( true === $.data( event.target, that.widgetName + ".preventClickEvent" ) ) {
9313					$.removeData( event.target, that.widgetName + ".preventClickEvent" );
9314					event.stopImmediatePropagation();
9315					return false;
9316				}
9317			} );
9318
9319		this.started = false;
9320	},
9321
9322	// TODO: make sure destroying one instance of mouse doesn't mess with
9323	// other instances of mouse
9324	_mouseDestroy: function() {
9325		this.element.off( "." + this.widgetName );
9326		if ( this._mouseMoveDelegate ) {
9327			this.document
9328				.off( "mousemove." + this.widgetName, this._mouseMoveDelegate )
9329				.off( "mouseup." + this.widgetName, this._mouseUpDelegate );
9330		}
9331	},
9332
9333	_mouseDown: function( event ) {
9334
9335		// don't let more than one widget handle mouseStart
9336		if ( mouseHandled ) {
9337			return;
9338		}
9339
9340		this._mouseMoved = false;
9341
9342		// We may have missed mouseup (out of window)
9343		( this._mouseStarted && this._mouseUp( event ) );
9344
9345		this._mouseDownEvent = event;
9346
9347		var that = this,
9348			btnIsLeft = ( event.which === 1 ),
9349
9350			// event.target.nodeName works around a bug in IE 8 with
9351			// disabled inputs (#7620)
9352			elIsCancel = ( typeof this.options.cancel === "string" && event.target.nodeName ?
9353				$( event.target ).closest( this.options.cancel ).length : false );
9354		if ( !btnIsLeft || elIsCancel || !this._mouseCapture( event ) ) {
9355			return true;
9356		}
9357
9358		this.mouseDelayMet = !this.options.delay;
9359		if ( !this.mouseDelayMet ) {
9360			this._mouseDelayTimer = setTimeout( function() {
9361				that.mouseDelayMet = true;
9362			}, this.options.delay );
9363		}
9364
9365		if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) {
9366			this._mouseStarted = ( this._mouseStart( event ) !== false );
9367			if ( !this._mouseStarted ) {
9368				event.preventDefault();
9369				return true;
9370			}
9371		}
9372
9373		// Click event may never have fired (Gecko & Opera)
9374		if ( true === $.data( event.target, this.widgetName + ".preventClickEvent" ) ) {
9375			$.removeData( event.target, this.widgetName + ".preventClickEvent" );
9376		}
9377
9378		// These delegates are required to keep context
9379		this._mouseMoveDelegate = function( event ) {
9380			return that._mouseMove( event );
9381		};
9382		this._mouseUpDelegate = function( event ) {
9383			return that._mouseUp( event );
9384		};
9385
9386		this.document
9387			.on( "mousemove." + this.widgetName, this._mouseMoveDelegate )
9388			.on( "mouseup." + this.widgetName, this._mouseUpDelegate );
9389
9390		event.preventDefault();
9391
9392		mouseHandled = true;
9393		return true;
9394	},
9395
9396	_mouseMove: function( event ) {
9397
9398		// Only check for mouseups outside the document if you've moved inside the document
9399		// at least once. This prevents the firing of mouseup in the case of IE<9, which will
9400		// fire a mousemove event if content is placed under the cursor. See #7778
9401		// Support: IE <9
9402		if ( this._mouseMoved ) {
9403
9404			// IE mouseup check - mouseup happened when mouse was out of window
9405			if ( $.ui.ie && ( !document.documentMode || document.documentMode < 9 ) &&
9406					!event.button ) {
9407				return this._mouseUp( event );
9408
9409			// Iframe mouseup check - mouseup occurred in another document
9410			} else if ( !event.which ) {
9411
9412				// Support: Safari <=8 - 9
9413				// Safari sets which to 0 if you press any of the following keys
9414				// during a drag (#14461)
9415				if ( event.originalEvent.altKey || event.originalEvent.ctrlKey ||
9416						event.originalEvent.metaKey || event.originalEvent.shiftKey ) {
9417					this.ignoreMissingWhich = true;
9418				} else if ( !this.ignoreMissingWhich ) {
9419					return this._mouseUp( event );
9420				}
9421			}
9422		}
9423
9424		if ( event.which || event.button ) {
9425			this._mouseMoved = true;
9426		}
9427
9428		if ( this._mouseStarted ) {
9429			this._mouseDrag( event );
9430			return event.preventDefault();
9431		}
9432
9433		if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) {
9434			this._mouseStarted =
9435				( this._mouseStart( this._mouseDownEvent, event ) !== false );
9436			( this._mouseStarted ? this._mouseDrag( event ) : this._mouseUp( event ) );
9437		}
9438
9439		return !this._mouseStarted;
9440	},
9441
9442	_mouseUp: function( event ) {
9443		this.document
9444			.off( "mousemove." + this.widgetName, this._mouseMoveDelegate )
9445			.off( "mouseup." + this.widgetName, this._mouseUpDelegate );
9446
9447		if ( this._mouseStarted ) {
9448			this._mouseStarted = false;
9449
9450			if ( event.target === this._mouseDownEvent.target ) {
9451				$.data( event.target, this.widgetName + ".preventClickEvent", true );
9452			}
9453
9454			this._mouseStop( event );
9455		}
9456
9457		if ( this._mouseDelayTimer ) {
9458			clearTimeout( this._mouseDelayTimer );
9459			delete this._mouseDelayTimer;
9460		}
9461
9462		this.ignoreMissingWhich = false;
9463		mouseHandled = false;
9464		event.preventDefault();
9465	},
9466
9467	_mouseDistanceMet: function( event ) {
9468		return ( Math.max(
9469				Math.abs( this._mouseDownEvent.pageX - event.pageX ),
9470				Math.abs( this._mouseDownEvent.pageY - event.pageY )
9471			) >= this.options.distance
9472		);
9473	},
9474
9475	_mouseDelayMet: function( /* event */ ) {
9476		return this.mouseDelayMet;
9477	},
9478
9479	// These are placeholder methods, to be overriden by extending plugin
9480	_mouseStart: function( /* event */ ) {},
9481	_mouseDrag: function( /* event */ ) {},
9482	_mouseStop: function( /* event */ ) {},
9483	_mouseCapture: function( /* event */ ) { return true; }
9484} );
9485
9486
9487
9488
9489// $.ui.plugin is deprecated. Use $.widget() extensions instead.
9490var plugin = $.ui.plugin = {
9491	add: function( module, option, set ) {
9492		var i,
9493			proto = $.ui[ module ].prototype;
9494		for ( i in set ) {
9495			proto.plugins[ i ] = proto.plugins[ i ] || [];
9496			proto.plugins[ i ].push( [ option, set[ i ] ] );
9497		}
9498	},
9499	call: function( instance, name, args, allowDisconnected ) {
9500		var i,
9501			set = instance.plugins[ name ];
9502
9503		if ( !set ) {
9504			return;
9505		}
9506
9507		if ( !allowDisconnected && ( !instance.element[ 0 ].parentNode ||
9508				instance.element[ 0 ].parentNode.nodeType === 11 ) ) {
9509			return;
9510		}
9511
9512		for ( i = 0; i < set.length; i++ ) {
9513			if ( instance.options[ set[ i ][ 0 ] ] ) {
9514				set[ i ][ 1 ].apply( instance.element, args );
9515			}
9516		}
9517	}
9518};
9519
9520
9521
9522var safeBlur = $.ui.safeBlur = function( element ) {
9523
9524	// Support: IE9 - 10 only
9525	// If the <body> is blurred, IE will switch windows, see #9420
9526	if ( element && element.nodeName.toLowerCase() !== "body" ) {
9527		$( element ).trigger( "blur" );
9528	}
9529};
9530
9531
9532
9533/*!
9534 * jQuery UI Selectmenu 1.12.1
9535 * http://jqueryui.com
9536 *
9537 * Copyright jQuery Foundation and other contributors
9538 * Released under the MIT license.
9539 * http://jquery.org/license
9540 */
9541
9542//>>label: Selectmenu
9543//>>group: Widgets
9544// jscs:disable maximumLineLength
9545//>>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.
9546// jscs:enable maximumLineLength
9547//>>docs: http://api.jqueryui.com/selectmenu/
9548//>>demos: http://jqueryui.com/selectmenu/
9549//>>css.structure: ../../themes/base/core.css
9550//>>css.structure: ../../themes/base/selectmenu.css, ../../themes/base/button.css
9551//>>css.theme: ../../themes/base/theme.css
9552
9553
9554
9555var widgetsSelectmenu = $.widget( "ui.selectmenu", [ $.ui.formResetMixin, {
9556	version: "1.12.1",
9557	defaultElement: "<select>",
9558	options: {
9559		appendTo: null,
9560		classes: {
9561			"ui-selectmenu-button-open": "ui-corner-top",
9562			"ui-selectmenu-button-closed": "ui-corner-all"
9563		},
9564		disabled: null,
9565		icons: {
9566			button: "ui-icon-triangle-1-s"
9567		},
9568		position: {
9569			my: "left top",
9570			at: "left bottom",
9571			collision: "none"
9572		},
9573		width: false,
9574
9575		// Callbacks
9576		change: null,
9577		close: null,
9578		focus: null,
9579		open: null,
9580		select: null
9581	},
9582
9583	_create: function() {
9584		var selectmenuId = this.element.uniqueId().attr( "id" );
9585		this.ids = {
9586			element: selectmenuId,
9587			button: selectmenuId + "-button",
9588			menu: selectmenuId + "-menu"
9589		};
9590
9591		this._drawButton();
9592		this._drawMenu();
9593		this._bindFormResetHandler();
9594
9595		this._rendered = false;
9596		this.menuItems = $();
9597	},
9598
9599	_drawButton: function() {
9600		var icon,
9601			that = this,
9602			item = this._parseOption(
9603				this.element.find( "option:selected" ),
9604				this.element[ 0 ].selectedIndex
9605			);
9606
9607		// Associate existing label with the new button
9608		this.labels = this.element.labels().attr( "for", this.ids.button );
9609		this._on( this.labels, {
9610			click: function( event ) {
9611				this.button.focus();
9612				event.preventDefault();
9613			}
9614		} );
9615
9616		// Hide original select element
9617		this.element.hide();
9618
9619		// Create button
9620		this.button = $( "<span>", {
9621			tabindex: this.options.disabled ? -1 : 0,
9622			id: this.ids.button,
9623			role: "combobox",
9624			"aria-expanded": "false",
9625			"aria-autocomplete": "list",
9626			"aria-owns": this.ids.menu,
9627			"aria-haspopup": "true",
9628			title: this.element.attr( "title" )
9629		} )
9630			.insertAfter( this.element );
9631
9632		this._addClass( this.button, "ui-selectmenu-button ui-selectmenu-button-closed",
9633			"ui-button ui-widget" );
9634
9635		icon = $( "<span>" ).appendTo( this.button );
9636		this._addClass( icon, "ui-selectmenu-icon", "ui-icon " + this.options.icons.button );
9637		this.buttonItem = this._renderButtonItem( item )
9638			.appendTo( this.button );
9639
9640		if ( this.options.width !== false ) {
9641			this._resizeButton();
9642		}
9643
9644		this._on( this.button, this._buttonEvents );
9645		this.button.one( "focusin", function() {
9646
9647			// Delay rendering the menu items until the button receives focus.
9648			// The menu may have already been rendered via a programmatic open.
9649			if ( !that._rendered ) {
9650				that._refreshMenu();
9651			}
9652		} );
9653	},
9654
9655	_drawMenu: function() {
9656		var that = this;
9657
9658		// Create menu
9659		this.menu = $( "<ul>", {
9660			"aria-hidden": "true",
9661			"aria-labelledby": this.ids.button,
9662			id: this.ids.menu
9663		} );
9664
9665		// Wrap menu
9666		this.menuWrap = $( "<div>" ).append( this.menu );
9667		this._addClass( this.menuWrap, "ui-selectmenu-menu", "ui-front" );
9668		this.menuWrap.appendTo( this._appendTo() );
9669
9670		// Initialize menu widget
9671		this.menuInstance = this.menu
9672			.menu( {
9673				classes: {
9674					"ui-menu": "ui-corner-bottom"
9675				},
9676				role: "listbox",
9677				select: function( event, ui ) {
9678					event.preventDefault();
9679
9680					// Support: IE8
9681					// If the item was selected via a click, the text selection
9682					// will be destroyed in IE
9683					that._setSelection();
9684
9685					that._select( ui.item.data( "ui-selectmenu-item" ), event );
9686				},
9687				focus: function( event, ui ) {
9688					var item = ui.item.data( "ui-selectmenu-item" );
9689
9690					// Prevent inital focus from firing and check if its a newly focused item
9691					if ( that.focusIndex != null && item.index !== that.focusIndex ) {
9692						that._trigger( "focus", event, { item: item } );
9693						if ( !that.isOpen ) {
9694							that._select( item, event );
9695						}
9696					}
9697					that.focusIndex = item.index;
9698
9699					that.button.attr( "aria-activedescendant",
9700						that.menuItems.eq( item.index ).attr( "id" ) );
9701				}
9702			} )
9703			.menu( "instance" );
9704
9705		// Don't close the menu on mouseleave
9706		this.menuInstance._off( this.menu, "mouseleave" );
9707
9708		// Cancel the menu's collapseAll on document click
9709		this.menuInstance._closeOnDocumentClick = function() {
9710			return false;
9711		};
9712
9713		// Selects often contain empty items, but never contain dividers
9714		this.menuInstance._isDivider = function() {
9715			return false;
9716		};
9717	},
9718
9719	refresh: function() {
9720		this._refreshMenu();
9721		this.buttonItem.replaceWith(
9722			this.buttonItem = this._renderButtonItem(
9723
9724				// Fall back to an empty object in case there are no options
9725				this._getSelectedItem().data( "ui-selectmenu-item" ) || {}
9726			)
9727		);
9728		if ( this.options.width === null ) {
9729			this._resizeButton();
9730		}
9731	},
9732
9733	_refreshMenu: function() {
9734		var item,
9735			options = this.element.find( "option" );
9736
9737		this.menu.empty();
9738
9739		this._parseOptions( options );
9740		this._renderMenu( this.menu, this.items );
9741
9742		this.menuInstance.refresh();
9743		this.menuItems = this.menu.find( "li" )
9744			.not( ".ui-selectmenu-optgroup" )
9745				.find( ".ui-menu-item-wrapper" );
9746
9747		this._rendered = true;
9748
9749		if ( !options.length ) {
9750			return;
9751		}
9752
9753		item = this._getSelectedItem();
9754
9755		// Update the menu to have the correct item focused
9756		this.menuInstance.focus( null, item );
9757		this._setAria( item.data( "ui-selectmenu-item" ) );
9758
9759		// Set disabled state
9760		this._setOption( "disabled", this.element.prop( "disabled" ) );
9761	},
9762
9763	open: function( event ) {
9764		if ( this.options.disabled ) {
9765			return;
9766		}
9767
9768		// If this is the first time the menu is being opened, render the items
9769		if ( !this._rendered ) {
9770			this._refreshMenu();
9771		} else {
9772
9773			// Menu clears focus on close, reset focus to selected item
9774			this._removeClass( this.menu.find( ".ui-state-active" ), null, "ui-state-active" );
9775			this.menuInstance.focus( null, this._getSelectedItem() );
9776		}
9777
9778		// If there are no options, don't open the menu
9779		if ( !this.menuItems.length ) {
9780			return;
9781		}
9782
9783		this.isOpen = true;
9784		this._toggleAttr();
9785		this._resizeMenu();
9786		this._position();
9787
9788		this._on( this.document, this._documentClick );
9789
9790		this._trigger( "open", event );
9791	},
9792
9793	_position: function() {
9794		this.menuWrap.position( $.extend( { of: this.button }, this.options.position ) );
9795	},
9796
9797	close: function( event ) {
9798		if ( !this.isOpen ) {
9799			return;
9800		}
9801
9802		this.isOpen = false;
9803		this._toggleAttr();
9804
9805		this.range = null;
9806		this._off( this.document );
9807
9808		this._trigger( "close", event );
9809	},
9810
9811	widget: function() {
9812		return this.button;
9813	},
9814
9815	menuWidget: function() {
9816		return this.menu;
9817	},
9818
9819	_renderButtonItem: function( item ) {
9820		var buttonItem = $( "<span>" );
9821
9822		this._setText( buttonItem, item.label );
9823		this._addClass( buttonItem, "ui-selectmenu-text" );
9824
9825		return buttonItem;
9826	},
9827
9828	_renderMenu: function( ul, items ) {
9829		var that = this,
9830			currentOptgroup = "";
9831
9832		$.each( items, function( index, item ) {
9833			var li;
9834
9835			if ( item.optgroup !== currentOptgroup ) {
9836				li = $( "<li>", {
9837					text: item.optgroup
9838				} );
9839				that._addClass( li, "ui-selectmenu-optgroup", "ui-menu-divider" +
9840					( item.element.parent( "optgroup" ).prop( "disabled" ) ?
9841						" ui-state-disabled" :
9842						"" ) );
9843
9844				li.appendTo( ul );
9845
9846				currentOptgroup = item.optgroup;
9847			}
9848
9849			that._renderItemData( ul, item );
9850		} );
9851	},
9852
9853	_renderItemData: function( ul, item ) {
9854		return this._renderItem( ul, item ).data( "ui-selectmenu-item", item );
9855	},
9856
9857	_renderItem: function( ul, item ) {
9858		var li = $( "<li>" ),
9859			wrapper = $( "<div>", {
9860				title: item.element.attr( "title" )
9861			} );
9862
9863		if ( item.disabled ) {
9864			this._addClass( li, null, "ui-state-disabled" );
9865		}
9866		this._setText( wrapper, item.label );
9867
9868		return li.append( wrapper ).appendTo( ul );
9869	},
9870
9871	_setText: function( element, value ) {
9872		if ( value ) {
9873			element.text( value );
9874		} else {
9875			element.html( "&#160;" );
9876		}
9877	},
9878
9879	_move: function( direction, event ) {
9880		var item, next,
9881			filter = ".ui-menu-item";
9882
9883		if ( this.isOpen ) {
9884			item = this.menuItems.eq( this.focusIndex ).parent( "li" );
9885		} else {
9886			item = this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( "li" );
9887			filter += ":not(.ui-state-disabled)";
9888		}
9889
9890		if ( direction === "first" || direction === "last" ) {
9891			next = item[ direction === "first" ? "prevAll" : "nextAll" ]( filter ).eq( -1 );
9892		} else {
9893			next = item[ direction + "All" ]( filter ).eq( 0 );
9894		}
9895
9896		if ( next.length ) {
9897			this.menuInstance.focus( event, next );
9898		}
9899	},
9900
9901	_getSelectedItem: function() {
9902		return this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( "li" );
9903	},
9904
9905	_toggle: function( event ) {
9906		this[ this.isOpen ? "close" : "open" ]( event );
9907	},
9908
9909	_setSelection: function() {
9910		var selection;
9911
9912		if ( !this.range ) {
9913			return;
9914		}
9915
9916		if ( window.getSelection ) {
9917			selection = window.getSelection();
9918			selection.removeAllRanges();
9919			selection.addRange( this.range );
9920
9921		// Support: IE8
9922		} else {
9923			this.range.select();
9924		}
9925
9926		// Support: IE
9927		// Setting the text selection kills the button focus in IE, but
9928		// restoring the focus doesn't kill the selection.
9929		this.button.focus();
9930	},
9931
9932	_documentClick: {
9933		mousedown: function( event ) {
9934			if ( !this.isOpen ) {
9935				return;
9936			}
9937
9938			if ( !$( event.target ).closest( ".ui-selectmenu-menu, #" +
9939					$.ui.escapeSelector( this.ids.button ) ).length ) {
9940				this.close( event );
9941			}
9942		}
9943	},
9944
9945	_buttonEvents: {
9946
9947		// Prevent text selection from being reset when interacting with the selectmenu (#10144)
9948		mousedown: function() {
9949			var selection;
9950
9951			if ( window.getSelection ) {
9952				selection = window.getSelection();
9953				if ( selection.rangeCount ) {
9954					this.range = selection.getRangeAt( 0 );
9955				}
9956
9957			// Support: IE8
9958			} else {
9959				this.range = document.selection.createRange();
9960			}
9961		},
9962
9963		click: function( event ) {
9964			this._setSelection();
9965			this._toggle( event );
9966		},
9967
9968		keydown: function( event ) {
9969			var preventDefault = true;
9970			switch ( event.keyCode ) {
9971			case $.ui.keyCode.TAB:
9972			case $.ui.keyCode.ESCAPE:
9973				this.close( event );
9974				preventDefault = false;
9975				break;
9976			case $.ui.keyCode.ENTER:
9977				if ( this.isOpen ) {
9978					this._selectFocusedItem( event );
9979				}
9980				break;
9981			case $.ui.keyCode.UP:
9982				if ( event.altKey ) {
9983					this._toggle( event );
9984				} else {
9985					this._move( "prev", event );
9986				}
9987				break;
9988			case $.ui.keyCode.DOWN:
9989				if ( event.altKey ) {
9990					this._toggle( event );
9991				} else {
9992					this._move( "next", event );
9993				}
9994				break;
9995			case $.ui.keyCode.SPACE:
9996				if ( this.isOpen ) {
9997					this._selectFocusedItem( event );
9998				} else {
9999					this._toggle( event );
10000				}
10001				break;
10002			case $.ui.keyCode.LEFT:
10003				this._move( "prev", event );
10004				break;
10005			case $.ui.keyCode.RIGHT:
10006				this._move( "next", event );
10007				break;
10008			case $.ui.keyCode.HOME:
10009			case $.ui.keyCode.PAGE_UP:
10010				this._move( "first", event );
10011				break;
10012			case $.ui.keyCode.END:
10013			case $.ui.keyCode.PAGE_DOWN:
10014				this._move( "last", event );
10015				break;
10016			default:
10017				this.menu.trigger( event );
10018				preventDefault = false;
10019			}
10020
10021			if ( preventDefault ) {
10022				event.preventDefault();
10023			}
10024		}
10025	},
10026
10027	_selectFocusedItem: function( event ) {
10028		var item = this.menuItems.eq( this.focusIndex ).parent( "li" );
10029		if ( !item.hasClass( "ui-state-disabled" ) ) {
10030			this._select( item.data( "ui-selectmenu-item" ), event );
10031		}
10032	},
10033
10034	_select: function( item, event ) {
10035		var oldIndex = this.element[ 0 ].selectedIndex;
10036
10037		// Change native select element
10038		this.element[ 0 ].selectedIndex = item.index;
10039		this.buttonItem.replaceWith( this.buttonItem = this._renderButtonItem( item ) );
10040		this._setAria( item );
10041		this._trigger( "select", event, { item: item } );
10042
10043		if ( item.index !== oldIndex ) {
10044			this._trigger( "change", event, { item: item } );
10045		}
10046
10047		this.close( event );
10048	},
10049
10050	_setAria: function( item ) {
10051		var id = this.menuItems.eq( item.index ).attr( "id" );
10052
10053		this.button.attr( {
10054			"aria-labelledby": id,
10055			"aria-activedescendant": id
10056		} );
10057		this.menu.attr( "aria-activedescendant", id );
10058	},
10059
10060	_setOption: function( key, value ) {
10061		if ( key === "icons" ) {
10062			var icon = this.button.find( "span.ui-icon" );
10063			this._removeClass( icon, null, this.options.icons.button )
10064				._addClass( icon, null, value.button );
10065		}
10066
10067		this._super( key, value );
10068
10069		if ( key === "appendTo" ) {
10070			this.menuWrap.appendTo( this._appendTo() );
10071		}
10072
10073		if ( key === "width" ) {
10074			this._resizeButton();
10075		}
10076	},
10077
10078	_setOptionDisabled: function( value ) {
10079		this._super( value );
10080
10081		this.menuInstance.option( "disabled", value );
10082		this.button.attr( "aria-disabled", value );
10083		this._toggleClass( this.button, null, "ui-state-disabled", value );
10084
10085		this.element.prop( "disabled", value );
10086		if ( value ) {
10087			this.button.attr( "tabindex", -1 );
10088			this.close();
10089		} else {
10090			this.button.attr( "tabindex", 0 );
10091		}
10092	},
10093
10094	_appendTo: function() {
10095		var element = this.options.appendTo;
10096
10097		if ( element ) {
10098			element = element.jquery || element.nodeType ?
10099				$( element ) :
10100				this.document.find( element ).eq( 0 );
10101		}
10102
10103		if ( !element || !element[ 0 ] ) {
10104			element = this.element.closest( ".ui-front, dialog" );
10105		}
10106
10107		if ( !element.length ) {
10108			element = this.document[ 0 ].body;
10109		}
10110
10111		return element;
10112	},
10113
10114	_toggleAttr: function() {
10115		this.button.attr( "aria-expanded", this.isOpen );
10116
10117		// We can't use two _toggleClass() calls here, because we need to make sure
10118		// we always remove classes first and add them second, otherwise if both classes have the
10119		// same theme class, it will be removed after we add it.
10120		this._removeClass( this.button, "ui-selectmenu-button-" +
10121			( this.isOpen ? "closed" : "open" ) )
10122			._addClass( this.button, "ui-selectmenu-button-" +
10123				( this.isOpen ? "open" : "closed" ) )
10124			._toggleClass( this.menuWrap, "ui-selectmenu-open", null, this.isOpen );
10125
10126		this.menu.attr( "aria-hidden", !this.isOpen );
10127	},
10128
10129	_resizeButton: function() {
10130		var width = this.options.width;
10131
10132		// For `width: false`, just remove inline style and stop
10133		if ( width === false ) {
10134			this.button.css( "width", "" );
10135			return;
10136		}
10137
10138		// For `width: null`, match the width of the original element
10139		if ( width === null ) {
10140			width = this.element.show().outerWidth();
10141			this.element.hide();
10142		}
10143
10144		this.button.outerWidth( width );
10145	},
10146
10147	_resizeMenu: function() {
10148		this.menu.outerWidth( Math.max(
10149			this.button.outerWidth(),
10150
10151			// Support: IE10
10152			// IE10 wraps long text (possibly a rounding bug)
10153			// so we add 1px to avoid the wrapping
10154			this.menu.width( "" ).outerWidth() + 1
10155		) );
10156	},
10157
10158	_getCreateOptions: function() {
10159		var options = this._super();
10160
10161		options.disabled = this.element.prop( "disabled" );
10162
10163		return options;
10164	},
10165
10166	_parseOptions: function( options ) {
10167		var that = this,
10168			data = [];
10169		options.each( function( index, item ) {
10170			data.push( that._parseOption( $( item ), index ) );
10171		} );
10172		this.items = data;
10173	},
10174
10175	_parseOption: function( option, index ) {
10176		var optgroup = option.parent( "optgroup" );
10177
10178		return {
10179			element: option,
10180			index: index,
10181			value: option.val(),
10182			label: option.text(),
10183			optgroup: optgroup.attr( "label" ) || "",
10184			disabled: optgroup.prop( "disabled" ) || option.prop( "disabled" )
10185		};
10186	},
10187
10188	_destroy: function() {
10189		this._unbindFormResetHandler();
10190		this.menuWrap.remove();
10191		this.button.remove();
10192		this.element.show();
10193		this.element.removeUniqueId();
10194		this.labels.attr( "for", this.ids.element );
10195	}
10196} ] );
10197
10198
10199/*!
10200 * jQuery UI Slider 1.12.1
10201 * http://jqueryui.com
10202 *
10203 * Copyright jQuery Foundation and other contributors
10204 * Released under the MIT license.
10205 * http://jquery.org/license
10206 */
10207
10208//>>label: Slider
10209//>>group: Widgets
10210//>>description: Displays a flexible slider with ranges and accessibility via keyboard.
10211//>>docs: http://api.jqueryui.com/slider/
10212//>>demos: http://jqueryui.com/slider/
10213//>>css.structure: ../../themes/base/core.css
10214//>>css.structure: ../../themes/base/slider.css
10215//>>css.theme: ../../themes/base/theme.css
10216
10217
10218
10219var widgetsSlider = $.widget( "ui.slider", $.ui.mouse, {
10220	version: "1.12.1",
10221	widgetEventPrefix: "slide",
10222
10223	options: {
10224		animate: false,
10225		classes: {
10226			"ui-slider": "ui-corner-all",
10227			"ui-slider-handle": "ui-corner-all",
10228
10229			// Note: ui-widget-header isn't the most fittingly semantic framework class for this
10230			// element, but worked best visually with a variety of themes
10231			"ui-slider-range": "ui-corner-all ui-widget-header"
10232		},
10233		distance: 0,
10234		max: 100,
10235		min: 0,
10236		orientation: "horizontal",
10237		range: false,
10238		step: 1,
10239		value: 0,
10240		values: null,
10241
10242		// Callbacks
10243		change: null,
10244		slide: null,
10245		start: null,
10246		stop: null
10247	},
10248
10249	// Number of pages in a slider
10250	// (how many times can you page up/down to go through the whole range)
10251	numPages: 5,
10252
10253	_create: function() {
10254		this._keySliding = false;
10255		this._mouseSliding = false;
10256		this._animateOff = true;
10257		this._handleIndex = null;
10258		this._detectOrientation();
10259		this._mouseInit();
10260		this._calculateNewMax();
10261
10262		this._addClass( "ui-slider ui-slider-" + this.orientation,
10263			"ui-widget ui-widget-content" );
10264
10265		this._refresh();
10266
10267		this._animateOff = false;
10268	},
10269
10270	_refresh: function() {
10271		this._createRange();
10272		this._createHandles();
10273		this._setupEvents();
10274		this._refreshValue();
10275	},
10276
10277	_createHandles: function() {
10278		var i, handleCount,
10279			options = this.options,
10280			existingHandles = this.element.find( ".ui-slider-handle" ),
10281			handle = "<span tabindex='0'></span>",
10282			handles = [];
10283
10284		handleCount = ( options.values && options.values.length ) || 1;
10285
10286		if ( existingHandles.length > handleCount ) {
10287			existingHandles.slice( handleCount ).remove();
10288			existingHandles = existingHandles.slice( 0, handleCount );
10289		}
10290
10291		for ( i = existingHandles.length; i < handleCount; i++ ) {
10292			handles.push( handle );
10293		}
10294
10295		this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) );
10296
10297		this._addClass( this.handles, "ui-slider-handle", "ui-state-default" );
10298
10299		this.handle = this.handles.eq( 0 );
10300
10301		this.handles.each( function( i ) {
10302			$( this )
10303				.data( "ui-slider-handle-index", i )
10304				.attr( "tabIndex", 0 );
10305		} );
10306	},
10307
10308	_createRange: function() {
10309		var options = this.options;
10310
10311		if ( options.range ) {
10312			if ( options.range === true ) {
10313				if ( !options.values ) {
10314					options.values = [ this._valueMin(), this._valueMin() ];
10315				} else if ( options.values.length && options.values.length !== 2 ) {
10316					options.values = [ options.values[ 0 ], options.values[ 0 ] ];
10317				} else if ( $.isArray( options.values ) ) {
10318					options.values = options.values.slice( 0 );
10319				}
10320			}
10321
10322			if ( !this.range || !this.range.length ) {
10323				this.range = $( "<div>" )
10324					.appendTo( this.element );
10325
10326				this._addClass( this.range, "ui-slider-range" );
10327			} else {
10328				this._removeClass( this.range, "ui-slider-range-min ui-slider-range-max" );
10329
10330				// Handle range switching from true to min/max
10331				this.range.css( {
10332					"left": "",
10333					"bottom": ""
10334				} );
10335			}
10336			if ( options.range === "min" || options.range === "max" ) {
10337				this._addClass( this.range, "ui-slider-range-" + options.range );
10338			}
10339		} else {
10340			if ( this.range ) {
10341				this.range.remove();
10342			}
10343			this.range = null;
10344		}
10345	},
10346
10347	_setupEvents: function() {
10348		this._off( this.handles );
10349		this._on( this.handles, this._handleEvents );
10350		this._hoverable( this.handles );
10351		this._focusable( this.handles );
10352	},
10353
10354	_destroy: function() {
10355		this.handles.remove();
10356		if ( this.range ) {
10357			this.range.remove();
10358		}
10359
10360		this._mouseDestroy();
10361	},
10362
10363	_mouseCapture: function( event ) {
10364		var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle,
10365			that = this,
10366			o = this.options;
10367
10368		if ( o.disabled ) {
10369			return false;
10370		}
10371
10372		this.elementSize = {
10373			width: this.element.outerWidth(),
10374			height: this.element.outerHeight()
10375		};
10376		this.elementOffset = this.element.offset();
10377
10378		position = { x: event.pageX, y: event.pageY };
10379		normValue = this._normValueFromMouse( position );
10380		distance = this._valueMax() - this._valueMin() + 1;
10381		this.handles.each( function( i ) {
10382			var thisDistance = Math.abs( normValue - that.values( i ) );
10383			if ( ( distance > thisDistance ) ||
10384				( distance === thisDistance &&
10385					( i === that._lastChangedValue || that.values( i ) === o.min ) ) ) {
10386				distance = thisDistance;
10387				closestHandle = $( this );
10388				index = i;
10389			}
10390		} );
10391
10392		allowed = this._start( event, index );
10393		if ( allowed === false ) {
10394			return false;
10395		}
10396		this._mouseSliding = true;
10397
10398		this._handleIndex = index;
10399
10400		this._addClass( closestHandle, null, "ui-state-active" );
10401		closestHandle.trigger( "focus" );
10402
10403		offset = closestHandle.offset();
10404		mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" );
10405		this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
10406			left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
10407			top: event.pageY - offset.top -
10408				( closestHandle.height() / 2 ) -
10409				( parseInt( closestHandle.css( "borderTopWidth" ), 10 ) || 0 ) -
10410				( parseInt( closestHandle.css( "borderBottomWidth" ), 10 ) || 0 ) +
10411				( parseInt( closestHandle.css( "marginTop" ), 10 ) || 0 )
10412		};
10413
10414		if ( !this.handles.hasClass( "ui-state-hover" ) ) {
10415			this._slide( event, index, normValue );
10416		}
10417		this._animateOff = true;
10418		return true;
10419	},
10420
10421	_mouseStart: function() {
10422		return true;
10423	},
10424
10425	_mouseDrag: function( event ) {
10426		var position = { x: event.pageX, y: event.pageY },
10427			normValue = this._normValueFromMouse( position );
10428
10429		this._slide( event, this._handleIndex, normValue );
10430
10431		return false;
10432	},
10433
10434	_mouseStop: function( event ) {
10435		this._removeClass( this.handles, null, "ui-state-active" );
10436		this._mouseSliding = false;
10437
10438		this._stop( event, this._handleIndex );
10439		this._change( event, this._handleIndex );
10440
10441		this._handleIndex = null;
10442		this._clickOffset = null;
10443		this._animateOff = false;
10444
10445		return false;
10446	},
10447
10448	_detectOrientation: function() {
10449		this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
10450	},
10451
10452	_normValueFromMouse: function( position ) {
10453		var pixelTotal,
10454			pixelMouse,
10455			percentMouse,
10456			valueTotal,
10457			valueMouse;
10458
10459		if ( this.orientation === "horizontal" ) {
10460			pixelTotal = this.elementSize.width;
10461			pixelMouse = position.x - this.elementOffset.left -
10462				( this._clickOffset ? this._clickOffset.left : 0 );
10463		} else {
10464			pixelTotal = this.elementSize.height;
10465			pixelMouse = position.y - this.elementOffset.top -
10466				( this._clickOffset ? this._clickOffset.top : 0 );
10467		}
10468
10469		percentMouse = ( pixelMouse / pixelTotal );
10470		if ( percentMouse > 1 ) {
10471			percentMouse = 1;
10472		}
10473		if ( percentMouse < 0 ) {
10474			percentMouse = 0;
10475		}
10476		if ( this.orientation === "vertical" ) {
10477			percentMouse = 1 - percentMouse;
10478		}
10479
10480		valueTotal = this._valueMax() - this._valueMin();
10481		valueMouse = this._valueMin() + percentMouse * valueTotal;
10482
10483		return this._trimAlignValue( valueMouse );
10484	},
10485
10486	_uiHash: function( index, value, values ) {
10487		var uiHash = {
10488			handle: this.handles[ index ],
10489			handleIndex: index,
10490			value: value !== undefined ? value : this.value()
10491		};
10492
10493		if ( this._hasMultipleValues() ) {
10494			uiHash.value = value !== undefined ? value : this.values( index );
10495			uiHash.values = values || this.values();
10496		}
10497
10498		return uiHash;
10499	},
10500
10501	_hasMultipleValues: function() {
10502		return this.options.values && this.options.values.length;
10503	},
10504
10505	_start: function( event, index ) {
10506		return this._trigger( "start", event, this._uiHash( index ) );
10507	},
10508
10509	_slide: function( event, index, newVal ) {
10510		var allowed, otherVal,
10511			currentValue = this.value(),
10512			newValues = this.values();
10513
10514		if ( this._hasMultipleValues() ) {
10515			otherVal = this.values( index ? 0 : 1 );
10516			currentValue = this.values( index );
10517
10518			if ( this.options.values.length === 2 && this.options.range === true ) {
10519				newVal =  index === 0 ? Math.min( otherVal, newVal ) : Math.max( otherVal, newVal );
10520			}
10521
10522			newValues[ index ] = newVal;
10523		}
10524
10525		if ( newVal === currentValue ) {
10526			return;
10527		}
10528
10529		allowed = this._trigger( "slide", event, this._uiHash( index, newVal, newValues ) );
10530
10531		// A slide can be canceled by returning false from the slide callback
10532		if ( allowed === false ) {
10533			return;
10534		}
10535
10536		if ( this._hasMultipleValues() ) {
10537			this.values( index, newVal );
10538		} else {
10539			this.value( newVal );
10540		}
10541	},
10542
10543	_stop: function( event, index ) {
10544		this._trigger( "stop", event, this._uiHash( index ) );
10545	},
10546
10547	_change: function( event, index ) {
10548		if ( !this._keySliding && !this._mouseSliding ) {
10549
10550			//store the last changed value index for reference when handles overlap
10551			this._lastChangedValue = index;
10552			this._trigger( "change", event, this._uiHash( index ) );
10553		}
10554	},
10555
10556	value: function( newValue ) {
10557		if ( arguments.length ) {
10558			this.options.value = this._trimAlignValue( newValue );
10559			this._refreshValue();
10560			this._change( null, 0 );
10561			return;
10562		}
10563
10564		return this._value();
10565	},
10566
10567	values: function( index, newValue ) {
10568		var vals,
10569			newValues,
10570			i;
10571
10572		if ( arguments.length > 1 ) {
10573			this.options.values[ index ] = this._trimAlignValue( newValue );
10574			this._refreshValue();
10575			this._change( null, index );
10576			return;
10577		}
10578
10579		if ( arguments.length ) {
10580			if ( $.isArray( arguments[ 0 ] ) ) {
10581				vals = this.options.values;
10582				newValues = arguments[ 0 ];
10583				for ( i = 0; i < vals.length; i += 1 ) {
10584					vals[ i ] = this._trimAlignValue( newValues[ i ] );
10585					this._change( null, i );
10586				}
10587				this._refreshValue();
10588			} else {
10589				if ( this._hasMultipleValues() ) {
10590					return this._values( index );
10591				} else {
10592					return this.value();
10593				}
10594			}
10595		} else {
10596			return this._values();
10597		}
10598	},
10599
10600	_setOption: function( key, value ) {
10601		var i,
10602			valsLength = 0;
10603
10604		if ( key === "range" && this.options.range === true ) {
10605			if ( value === "min" ) {
10606				this.options.value = this._values( 0 );
10607				this.options.values = null;
10608			} else if ( value === "max" ) {
10609				this.options.value = this._values( this.options.values.length - 1 );
10610				this.options.values = null;
10611			}
10612		}
10613
10614		if ( $.isArray( this.options.values ) ) {
10615			valsLength = this.options.values.length;
10616		}
10617
10618		this._super( key, value );
10619
10620		switch ( key ) {
10621			case "orientation":
10622				this._detectOrientation();
10623				this._removeClass( "ui-slider-horizontal ui-slider-vertical" )
10624					._addClass( "ui-slider-" + this.orientation );
10625				this._refreshValue();
10626				if ( this.options.range ) {
10627					this._refreshRange( value );
10628				}
10629
10630				// Reset positioning from previous orientation
10631				this.handles.css( value === "horizontal" ? "bottom" : "left", "" );
10632				break;
10633			case "value":
10634				this._animateOff = true;
10635				this._refreshValue();
10636				this._change( null, 0 );
10637				this._animateOff = false;
10638				break;
10639			case "values":
10640				this._animateOff = true;
10641				this._refreshValue();
10642
10643				// Start from the last handle to prevent unreachable handles (#9046)
10644				for ( i = valsLength - 1; i >= 0; i-- ) {
10645					this._change( null, i );
10646				}
10647				this._animateOff = false;
10648				break;
10649			case "step":
10650			case "min":
10651			case "max":
10652				this._animateOff = true;
10653				this._calculateNewMax();
10654				this._refreshValue();
10655				this._animateOff = false;
10656				break;
10657			case "range":
10658				this._animateOff = true;
10659				this._refresh();
10660				this._animateOff = false;
10661				break;
10662		}
10663	},
10664
10665	_setOptionDisabled: function( value ) {
10666		this._super( value );
10667
10668		this._toggleClass( null, "ui-state-disabled", !!value );
10669	},
10670
10671	//internal value getter
10672	// _value() returns value trimmed by min and max, aligned by step
10673	_value: function() {
10674		var val = this.options.value;
10675		val = this._trimAlignValue( val );
10676
10677		return val;
10678	},
10679
10680	//internal values getter
10681	// _values() returns array of values trimmed by min and max, aligned by step
10682	// _values( index ) returns single value trimmed by min and max, aligned by step
10683	_values: function( index ) {
10684		var val,
10685			vals,
10686			i;
10687
10688		if ( arguments.length ) {
10689			val = this.options.values[ index ];
10690			val = this._trimAlignValue( val );
10691
10692			return val;
10693		} else if ( this._hasMultipleValues() ) {
10694
10695			// .slice() creates a copy of the array
10696			// this copy gets trimmed by min and max and then returned
10697			vals = this.options.values.slice();
10698			for ( i = 0; i < vals.length; i += 1 ) {
10699				vals[ i ] = this._trimAlignValue( vals[ i ] );
10700			}
10701
10702			return vals;
10703		} else {
10704			return [];
10705		}
10706	},
10707
10708	// Returns the step-aligned value that val is closest to, between (inclusive) min and max
10709	_trimAlignValue: function( val ) {
10710		if ( val <= this._valueMin() ) {
10711			return this._valueMin();
10712		}
10713		if ( val >= this._valueMax() ) {
10714			return this._valueMax();
10715		}
10716		var step = ( this.options.step > 0 ) ? this.options.step : 1,
10717			valModStep = ( val - this._valueMin() ) % step,
10718			alignValue = val - valModStep;
10719
10720		if ( Math.abs( valModStep ) * 2 >= step ) {
10721			alignValue += ( valModStep > 0 ) ? step : ( -step );
10722		}
10723
10724		// Since JavaScript has problems with large floats, round
10725		// the final value to 5 digits after the decimal point (see #4124)
10726		return parseFloat( alignValue.toFixed( 5 ) );
10727	},
10728
10729	_calculateNewMax: function() {
10730		var max = this.options.max,
10731			min = this._valueMin(),
10732			step = this.options.step,
10733			aboveMin = Math.round( ( max - min ) / step ) * step;
10734		max = aboveMin + min;
10735		if ( max > this.options.max ) {
10736
10737			//If max is not divisible by step, rounding off may increase its value
10738			max -= step;
10739		}
10740		this.max = parseFloat( max.toFixed( this._precision() ) );
10741	},
10742
10743	_precision: function() {
10744		var precision = this._precisionOf( this.options.step );
10745		if ( this.options.min !== null ) {
10746			precision = Math.max( precision, this._precisionOf( this.options.min ) );
10747		}
10748		return precision;
10749	},
10750
10751	_precisionOf: function( num ) {
10752		var str = num.toString(),
10753			decimal = str.indexOf( "." );
10754		return decimal === -1 ? 0 : str.length - decimal - 1;
10755	},
10756
10757	_valueMin: function() {
10758		return this.options.min;
10759	},
10760
10761	_valueMax: function() {
10762		return this.max;
10763	},
10764
10765	_refreshRange: function( orientation ) {
10766		if ( orientation === "vertical" ) {
10767			this.range.css( { "width": "", "left": "" } );
10768		}
10769		if ( orientation === "horizontal" ) {
10770			this.range.css( { "height": "", "bottom": "" } );
10771		}
10772	},
10773
10774	_refreshValue: function() {
10775		var lastValPercent, valPercent, value, valueMin, valueMax,
10776			oRange = this.options.range,
10777			o = this.options,
10778			that = this,
10779			animate = ( !this._animateOff ) ? o.animate : false,
10780			_set = {};
10781
10782		if ( this._hasMultipleValues() ) {
10783			this.handles.each( function( i ) {
10784				valPercent = ( that.values( i ) - that._valueMin() ) / ( that._valueMax() -
10785					that._valueMin() ) * 100;
10786				_set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
10787				$( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
10788				if ( that.options.range === true ) {
10789					if ( that.orientation === "horizontal" ) {
10790						if ( i === 0 ) {
10791							that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
10792								left: valPercent + "%"
10793							}, o.animate );
10794						}
10795						if ( i === 1 ) {
10796							that.range[ animate ? "animate" : "css" ]( {
10797								width: ( valPercent - lastValPercent ) + "%"
10798							}, {
10799								queue: false,
10800								duration: o.animate
10801							} );
10802						}
10803					} else {
10804						if ( i === 0 ) {
10805							that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
10806								bottom: ( valPercent ) + "%"
10807							}, o.animate );
10808						}
10809						if ( i === 1 ) {
10810							that.range[ animate ? "animate" : "css" ]( {
10811								height: ( valPercent - lastValPercent ) + "%"
10812							}, {
10813								queue: false,
10814								duration: o.animate
10815							} );
10816						}
10817					}
10818				}
10819				lastValPercent = valPercent;
10820			} );
10821		} else {
10822			value = this.value();
10823			valueMin = this._valueMin();
10824			valueMax = this._valueMax();
10825			valPercent = ( valueMax !== valueMin ) ?
10826					( value - valueMin ) / ( valueMax - valueMin ) * 100 :
10827					0;
10828			_set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
10829			this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
10830
10831			if ( oRange === "min" && this.orientation === "horizontal" ) {
10832				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
10833					width: valPercent + "%"
10834				}, o.animate );
10835			}
10836			if ( oRange === "max" && this.orientation === "horizontal" ) {
10837				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
10838					width: ( 100 - valPercent ) + "%"
10839				}, o.animate );
10840			}
10841			if ( oRange === "min" && this.orientation === "vertical" ) {
10842				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
10843					height: valPercent + "%"
10844				}, o.animate );
10845			}
10846			if ( oRange === "max" && this.orientation === "vertical" ) {
10847				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
10848					height: ( 100 - valPercent ) + "%"
10849				}, o.animate );
10850			}
10851		}
10852	},
10853
10854	_handleEvents: {
10855		keydown: function( event ) {
10856			var allowed, curVal, newVal, step,
10857				index = $( event.target ).data( "ui-slider-handle-index" );
10858
10859			switch ( event.keyCode ) {
10860				case $.ui.keyCode.HOME:
10861				case $.ui.keyCode.END:
10862				case $.ui.keyCode.PAGE_UP:
10863				case $.ui.keyCode.PAGE_DOWN:
10864				case $.ui.keyCode.UP:
10865				case $.ui.keyCode.RIGHT:
10866				case $.ui.keyCode.DOWN:
10867				case $.ui.keyCode.LEFT:
10868					event.preventDefault();
10869					if ( !this._keySliding ) {
10870						this._keySliding = true;
10871						this._addClass( $( event.target ), null, "ui-state-active" );
10872						allowed = this._start( event, index );
10873						if ( allowed === false ) {
10874							return;
10875						}
10876					}
10877					break;
10878			}
10879
10880			step = this.options.step;
10881			if ( this._hasMultipleValues() ) {
10882				curVal = newVal = this.values( index );
10883			} else {
10884				curVal = newVal = this.value();
10885			}
10886
10887			switch ( event.keyCode ) {
10888				case $.ui.keyCode.HOME:
10889					newVal = this._valueMin();
10890					break;
10891				case $.ui.keyCode.END:
10892					newVal = this._valueMax();
10893					break;
10894				case $.ui.keyCode.PAGE_UP:
10895					newVal = this._trimAlignValue(
10896						curVal + ( ( this._valueMax() - this._valueMin() ) / this.numPages )
10897					);
10898					break;
10899				case $.ui.keyCode.PAGE_DOWN:
10900					newVal = this._trimAlignValue(
10901						curVal - ( ( this._valueMax() - this._valueMin() ) / this.numPages ) );
10902					break;
10903				case $.ui.keyCode.UP:
10904				case $.ui.keyCode.RIGHT:
10905					if ( curVal === this._valueMax() ) {
10906						return;
10907					}
10908					newVal = this._trimAlignValue( curVal + step );
10909					break;
10910				case $.ui.keyCode.DOWN:
10911				case $.ui.keyCode.LEFT:
10912					if ( curVal === this._valueMin() ) {
10913						return;
10914					}
10915					newVal = this._trimAlignValue( curVal - step );
10916					break;
10917			}
10918
10919			this._slide( event, index, newVal );
10920		},
10921		keyup: function( event ) {
10922			var index = $( event.target ).data( "ui-slider-handle-index" );
10923
10924			if ( this._keySliding ) {
10925				this._keySliding = false;
10926				this._stop( event, index );
10927				this._change( event, index );
10928				this._removeClass( $( event.target ), null, "ui-state-active" );
10929			}
10930		}
10931	}
10932} );
10933
10934
10935/*!
10936 * jQuery UI Sortable 1.12.1
10937 * http://jqueryui.com
10938 *
10939 * Copyright jQuery Foundation and other contributors
10940 * Released under the MIT license.
10941 * http://jquery.org/license
10942 */
10943
10944//>>label: Sortable
10945//>>group: Interactions
10946//>>description: Enables items in a list to be sorted using the mouse.
10947//>>docs: http://api.jqueryui.com/sortable/
10948//>>demos: http://jqueryui.com/sortable/
10949//>>css.structure: ../../themes/base/sortable.css
10950
10951
10952
10953var widgetsSortable = $.widget( "ui.sortable", $.ui.mouse, {
10954	version: "1.12.1",
10955	widgetEventPrefix: "sort",
10956	ready: false,
10957	options: {
10958		appendTo: "parent",
10959		axis: false,
10960		connectWith: false,
10961		containment: false,
10962		cursor: "auto",
10963		cursorAt: false,
10964		dropOnEmpty: true,
10965		forcePlaceholderSize: false,
10966		forceHelperSize: false,
10967		grid: false,
10968		handle: false,
10969		helper: "original",
10970		items: "> *",
10971		opacity: false,
10972		placeholder: false,
10973		revert: false,
10974		scroll: true,
10975		scrollSensitivity: 20,
10976		scrollSpeed: 20,
10977		scope: "default",
10978		tolerance: "intersect",
10979		zIndex: 1000,
10980
10981		// Callbacks
10982		activate: null,
10983		beforeStop: null,
10984		change: null,
10985		deactivate: null,
10986		out: null,
10987		over: null,
10988		receive: null,
10989		remove: null,
10990		sort: null,
10991		start: null,
10992		stop: null,
10993		update: null
10994	},
10995
10996	_isOverAxis: function( x, reference, size ) {
10997		return ( x >= reference ) && ( x < ( reference + size ) );
10998	},
10999
11000	_isFloating: function( item ) {
11001		return ( /left|right/ ).test( item.css( "float" ) ) ||
11002			( /inline|table-cell/ ).test( item.css( "display" ) );
11003	},
11004
11005	_create: function() {
11006		this.containerCache = {};
11007		this._addClass( "ui-sortable" );
11008
11009		//Get the items
11010		this.refresh();
11011
11012		//Let's determine the parent's offset
11013		this.offset = this.element.offset();
11014
11015		//Initialize mouse events for interaction
11016		this._mouseInit();
11017
11018		this._setHandleClassName();
11019
11020		//We're ready to go
11021		this.ready = true;
11022
11023	},
11024
11025	_setOption: function( key, value ) {
11026		this._super( key, value );
11027
11028		if ( key === "handle" ) {
11029			this._setHandleClassName();
11030		}
11031	},
11032
11033	_setHandleClassName: function() {
11034		var that = this;
11035		this._removeClass( this.element.find( ".ui-sortable-handle" ), "ui-sortable-handle" );
11036		$.each( this.items, function() {
11037			that._addClass(
11038				this.instance.options.handle ?
11039					this.item.find( this.instance.options.handle ) :
11040					this.item,
11041				"ui-sortable-handle"
11042			);
11043		} );
11044	},
11045
11046	_destroy: function() {
11047		this._mouseDestroy();
11048
11049		for ( var i = this.items.length - 1; i >= 0; i-- ) {
11050			this.items[ i ].item.removeData( this.widgetName + "-item" );
11051		}
11052
11053		return this;
11054	},
11055
11056	_mouseCapture: function( event, overrideHandle ) {
11057		var currentItem = null,
11058			validHandle = false,
11059			that = this;
11060
11061		if ( this.reverting ) {
11062			return false;
11063		}
11064
11065		if ( this.options.disabled || this.options.type === "static" ) {
11066			return false;
11067		}
11068
11069		//We have to refresh the items data once first
11070		this._refreshItems( event );
11071
11072		//Find out if the clicked node (or one of its parents) is a actual item in this.items
11073		$( event.target ).parents().each( function() {
11074			if ( $.data( this, that.widgetName + "-item" ) === that ) {
11075				currentItem = $( this );
11076				return false;
11077			}
11078		} );
11079		if ( $.data( event.target, that.widgetName + "-item" ) === that ) {
11080			currentItem = $( event.target );
11081		}
11082
11083		if ( !currentItem ) {
11084			return false;
11085		}
11086		if ( this.options.handle && !overrideHandle ) {
11087			$( this.options.handle, currentItem ).find( "*" ).addBack().each( function() {
11088				if ( this === event.target ) {
11089					validHandle = true;
11090				}
11091			} );
11092			if ( !validHandle ) {
11093				return false;
11094			}
11095		}
11096
11097		this.currentItem = currentItem;
11098		this._removeCurrentsFromItems();
11099		return true;
11100
11101	},
11102
11103	_mouseStart: function( event, overrideHandle, noActivation ) {
11104
11105		var i, body,
11106			o = this.options;
11107
11108		this.currentContainer = this;
11109
11110		//We only need to call refreshPositions, because the refreshItems call has been moved to
11111		// mouseCapture
11112		this.refreshPositions();
11113
11114		//Create and append the visible helper
11115		this.helper = this._createHelper( event );
11116
11117		//Cache the helper size
11118		this._cacheHelperProportions();
11119
11120		/*
11121		 * - Position generation -
11122		 * This block generates everything position related - it's the core of draggables.
11123		 */
11124
11125		//Cache the margins of the original element
11126		this._cacheMargins();
11127
11128		//Get the next scrolling parent
11129		this.scrollParent = this.helper.scrollParent();
11130
11131		//The element's absolute position on the page minus margins
11132		this.offset = this.currentItem.offset();
11133		this.offset = {
11134			top: this.offset.top - this.margins.top,
11135			left: this.offset.left - this.margins.left
11136		};
11137
11138		$.extend( this.offset, {
11139			click: { //Where the click happened, relative to the element
11140				left: event.pageX - this.offset.left,
11141				top: event.pageY - this.offset.top
11142			},
11143			parent: this._getParentOffset(),
11144
11145			// This is a relative to absolute position minus the actual position calculation -
11146			// only used for relative positioned helper
11147			relative: this._getRelativeOffset()
11148		} );
11149
11150		// Only after we got the offset, we can change the helper's position to absolute
11151		// TODO: Still need to figure out a way to make relative sorting possible
11152		this.helper.css( "position", "absolute" );
11153		this.cssPosition = this.helper.css( "position" );
11154
11155		//Generate the original position
11156		this.originalPosition = this._generatePosition( event );
11157		this.originalPageX = event.pageX;
11158		this.originalPageY = event.pageY;
11159
11160		//Adjust the mouse offset relative to the helper if "cursorAt" is supplied
11161		( o.cursorAt && this._adjustOffsetFromHelper( o.cursorAt ) );
11162
11163		//Cache the former DOM position
11164		this.domPosition = {
11165			prev: this.currentItem.prev()[ 0 ],
11166			parent: this.currentItem.parent()[ 0 ]
11167		};
11168
11169		// If the helper is not the original, hide the original so it's not playing any role during
11170		// the drag, won't cause anything bad this way
11171		if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {
11172			this.currentItem.hide();
11173		}
11174
11175		//Create the placeholder
11176		this._createPlaceholder();
11177
11178		//Set a containment if given in the options
11179		if ( o.containment ) {
11180			this._setContainment();
11181		}
11182
11183		if ( o.cursor && o.cursor !== "auto" ) { // cursor option
11184			body = this.document.find( "body" );
11185
11186			// Support: IE
11187			this.storedCursor = body.css( "cursor" );
11188			body.css( "cursor", o.cursor );
11189
11190			this.storedStylesheet =
11191				$( "<style>*{ cursor: " + o.cursor + " !important; }</style>" ).appendTo( body );
11192		}
11193
11194		if ( o.opacity ) { // opacity option
11195			if ( this.helper.css( "opacity" ) ) {
11196				this._storedOpacity = this.helper.css( "opacity" );
11197			}
11198			this.helper.css( "opacity", o.opacity );
11199		}
11200
11201		if ( o.zIndex ) { // zIndex option
11202			if ( this.helper.css( "zIndex" ) ) {
11203				this._storedZIndex = this.helper.css( "zIndex" );
11204			}
11205			this.helper.css( "zIndex", o.zIndex );
11206		}
11207
11208		//Prepare scrolling
11209		if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
11210				this.scrollParent[ 0 ].tagName !== "HTML" ) {
11211			this.overflowOffset = this.scrollParent.offset();
11212		}
11213
11214		//Call callbacks
11215		this._trigger( "start", event, this._uiHash() );
11216
11217		//Recache the helper size
11218		if ( !this._preserveHelperProportions ) {
11219			this._cacheHelperProportions();
11220		}
11221
11222		//Post "activate" events to possible containers
11223		if ( !noActivation ) {
11224			for ( i = this.containers.length - 1; i >= 0; i-- ) {
11225				this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) );
11226			}
11227		}
11228
11229		//Prepare possible droppables
11230		if ( $.ui.ddmanager ) {
11231			$.ui.ddmanager.current = this;
11232		}
11233
11234		if ( $.ui.ddmanager && !o.dropBehaviour ) {
11235			$.ui.ddmanager.prepareOffsets( this, event );
11236		}
11237
11238		this.dragging = true;
11239
11240		this._addClass( this.helper, "ui-sortable-helper" );
11241
11242		// Execute the drag once - this causes the helper not to be visiblebefore getting its
11243		// correct position
11244		this._mouseDrag( event );
11245		return true;
11246
11247	},
11248
11249	_mouseDrag: function( event ) {
11250		var i, item, itemElement, intersection,
11251			o = this.options,
11252			scrolled = false;
11253
11254		//Compute the helpers position
11255		this.position = this._generatePosition( event );
11256		this.positionAbs = this._convertPositionTo( "absolute" );
11257
11258		if ( !this.lastPositionAbs ) {
11259			this.lastPositionAbs = this.positionAbs;
11260		}
11261
11262		//Do scrolling
11263		if ( this.options.scroll ) {
11264			if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
11265					this.scrollParent[ 0 ].tagName !== "HTML" ) {
11266
11267				if ( ( this.overflowOffset.top + this.scrollParent[ 0 ].offsetHeight ) -
11268						event.pageY < o.scrollSensitivity ) {
11269					this.scrollParent[ 0 ].scrollTop =
11270						scrolled = this.scrollParent[ 0 ].scrollTop + o.scrollSpeed;
11271				} else if ( event.pageY - this.overflowOffset.top < o.scrollSensitivity ) {
11272					this.scrollParent[ 0 ].scrollTop =
11273						scrolled = this.scrollParent[ 0 ].scrollTop - o.scrollSpeed;
11274				}
11275
11276				if ( ( this.overflowOffset.left + this.scrollParent[ 0 ].offsetWidth ) -
11277						event.pageX < o.scrollSensitivity ) {
11278					this.scrollParent[ 0 ].scrollLeft = scrolled =
11279						this.scrollParent[ 0 ].scrollLeft + o.scrollSpeed;
11280				} else if ( event.pageX - this.overflowOffset.left < o.scrollSensitivity ) {
11281					this.scrollParent[ 0 ].scrollLeft = scrolled =
11282						this.scrollParent[ 0 ].scrollLeft - o.scrollSpeed;
11283				}
11284
11285			} else {
11286
11287				if ( event.pageY - this.document.scrollTop() < o.scrollSensitivity ) {
11288					scrolled = this.document.scrollTop( this.document.scrollTop() - o.scrollSpeed );
11289				} else if ( this.window.height() - ( event.pageY - this.document.scrollTop() ) <
11290						o.scrollSensitivity ) {
11291					scrolled = this.document.scrollTop( this.document.scrollTop() + o.scrollSpeed );
11292				}
11293
11294				if ( event.pageX - this.document.scrollLeft() < o.scrollSensitivity ) {
11295					scrolled = this.document.scrollLeft(
11296						this.document.scrollLeft() - o.scrollSpeed
11297					);
11298				} else if ( this.window.width() - ( event.pageX - this.document.scrollLeft() ) <
11299						o.scrollSensitivity ) {
11300					scrolled = this.document.scrollLeft(
11301						this.document.scrollLeft() + o.scrollSpeed
11302					);
11303				}
11304
11305			}
11306
11307			if ( scrolled !== false && $.ui.ddmanager && !o.dropBehaviour ) {
11308				$.ui.ddmanager.prepareOffsets( this, event );
11309			}
11310		}
11311
11312		//Regenerate the absolute position used for position checks
11313		this.positionAbs = this._convertPositionTo( "absolute" );
11314
11315		//Set the helper position
11316		if ( !this.options.axis || this.options.axis !== "y" ) {
11317			this.helper[ 0 ].style.left = this.position.left + "px";
11318		}
11319		if ( !this.options.axis || this.options.axis !== "x" ) {
11320			this.helper[ 0 ].style.top = this.position.top + "px";
11321		}
11322
11323		//Rearrange
11324		for ( i = this.items.length - 1; i >= 0; i-- ) {
11325
11326			//Cache variables and intersection, continue if no intersection
11327			item = this.items[ i ];
11328			itemElement = item.item[ 0 ];
11329			intersection = this._intersectsWithPointer( item );
11330			if ( !intersection ) {
11331				continue;
11332			}
11333
11334			// Only put the placeholder inside the current Container, skip all
11335			// items from other containers. This works because when moving
11336			// an item from one container to another the
11337			// currentContainer is switched before the placeholder is moved.
11338			//
11339			// Without this, moving items in "sub-sortables" can cause
11340			// the placeholder to jitter between the outer and inner container.
11341			if ( item.instance !== this.currentContainer ) {
11342				continue;
11343			}
11344
11345			// Cannot intersect with itself
11346			// no useless actions that have been done before
11347			// no action if the item moved is the parent of the item checked
11348			if ( itemElement !== this.currentItem[ 0 ] &&
11349				this.placeholder[ intersection === 1 ? "next" : "prev" ]()[ 0 ] !== itemElement &&
11350				!$.contains( this.placeholder[ 0 ], itemElement ) &&
11351				( this.options.type === "semi-dynamic" ?
11352					!$.contains( this.element[ 0 ], itemElement ) :
11353					true
11354				)
11355			) {
11356
11357				this.direction = intersection === 1 ? "down" : "up";
11358
11359				if ( this.options.tolerance === "pointer" || this._intersectsWithSides( item ) ) {
11360					this._rearrange( event, item );
11361				} else {
11362					break;
11363				}
11364
11365				this._trigger( "change", event, this._uiHash() );
11366				break;
11367			}
11368		}
11369
11370		//Post events to containers
11371		this._contactContainers( event );
11372
11373		//Interconnect with droppables
11374		if ( $.ui.ddmanager ) {
11375			$.ui.ddmanager.drag( this, event );
11376		}
11377
11378		//Call callbacks
11379		this._trigger( "sort", event, this._uiHash() );
11380
11381		this.lastPositionAbs = this.positionAbs;
11382		return false;
11383
11384	},
11385
11386	_mouseStop: function( event, noPropagation ) {
11387
11388		if ( !event ) {
11389			return;
11390		}
11391
11392		//If we are using droppables, inform the manager about the drop
11393		if ( $.ui.ddmanager && !this.options.dropBehaviour ) {
11394			$.ui.ddmanager.drop( this, event );
11395		}
11396
11397		if ( this.options.revert ) {
11398			var that = this,
11399				cur = this.placeholder.offset(),
11400				axis = this.options.axis,
11401				animation = {};
11402
11403			if ( !axis || axis === "x" ) {
11404				animation.left = cur.left - this.offset.parent.left - this.margins.left +
11405					( this.offsetParent[ 0 ] === this.document[ 0 ].body ?
11406						0 :
11407						this.offsetParent[ 0 ].scrollLeft
11408					);
11409			}
11410			if ( !axis || axis === "y" ) {
11411				animation.top = cur.top - this.offset.parent.top - this.margins.top +
11412					( this.offsetParent[ 0 ] === this.document[ 0 ].body ?
11413						0 :
11414						this.offsetParent[ 0 ].scrollTop
11415					);
11416			}
11417			this.reverting = true;
11418			$( this.helper ).animate(
11419				animation,
11420				parseInt( this.options.revert, 10 ) || 500,
11421				function() {
11422					that._clear( event );
11423				}
11424			);
11425		} else {
11426			this._clear( event, noPropagation );
11427		}
11428
11429		return false;
11430
11431	},
11432
11433	cancel: function() {
11434
11435		if ( this.dragging ) {
11436
11437			this._mouseUp( new $.Event( "mouseup", { target: null } ) );
11438
11439			if ( this.options.helper === "original" ) {
11440				this.currentItem.css( this._storedCSS );
11441				this._removeClass( this.currentItem, "ui-sortable-helper" );
11442			} else {
11443				this.currentItem.show();
11444			}
11445
11446			//Post deactivating events to containers
11447			for ( var i = this.containers.length - 1; i >= 0; i-- ) {
11448				this.containers[ i ]._trigger( "deactivate", null, this._uiHash( this ) );
11449				if ( this.containers[ i ].containerCache.over ) {
11450					this.containers[ i ]._trigger( "out", null, this._uiHash( this ) );
11451					this.containers[ i ].containerCache.over = 0;
11452				}
11453			}
11454
11455		}
11456
11457		if ( this.placeholder ) {
11458
11459			//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately,
11460			// it unbinds ALL events from the original node!
11461			if ( this.placeholder[ 0 ].parentNode ) {
11462				this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] );
11463			}
11464			if ( this.options.helper !== "original" && this.helper &&
11465					this.helper[ 0 ].parentNode ) {
11466				this.helper.remove();
11467			}
11468
11469			$.extend( this, {
11470				helper: null,
11471				dragging: false,
11472				reverting: false,
11473				_noFinalSort: null
11474			} );
11475
11476			if ( this.domPosition.prev ) {
11477				$( this.domPosition.prev ).after( this.currentItem );
11478			} else {
11479				$( this.domPosition.parent ).prepend( this.currentItem );
11480			}
11481		}
11482
11483		return this;
11484
11485	},
11486
11487	serialize: function( o ) {
11488
11489		var items = this._getItemsAsjQuery( o && o.connected ),
11490			str = [];
11491		o = o || {};
11492
11493		$( items ).each( function() {
11494			var res = ( $( o.item || this ).attr( o.attribute || "id" ) || "" )
11495				.match( o.expression || ( /(.+)[\-=_](.+)/ ) );
11496			if ( res ) {
11497				str.push(
11498					( o.key || res[ 1 ] + "[]" ) +
11499					"=" + ( o.key && o.expression ? res[ 1 ] : res[ 2 ] ) );
11500			}
11501		} );
11502
11503		if ( !str.length && o.key ) {
11504			str.push( o.key + "=" );
11505		}
11506
11507		return str.join( "&" );
11508
11509	},
11510
11511	toArray: function( o ) {
11512
11513		var items = this._getItemsAsjQuery( o && o.connected ),
11514			ret = [];
11515
11516		o = o || {};
11517
11518		items.each( function() {
11519			ret.push( $( o.item || this ).attr( o.attribute || "id" ) || "" );
11520		} );
11521		return ret;
11522
11523	},
11524
11525	/* Be careful with the following core functions */
11526	_intersectsWith: function( item ) {
11527
11528		var x1 = this.positionAbs.left,
11529			x2 = x1 + this.helperProportions.width,
11530			y1 = this.positionAbs.top,
11531			y2 = y1 + this.helperProportions.height,
11532			l = item.left,
11533			r = l + item.width,
11534			t = item.top,
11535			b = t + item.height,
11536			dyClick = this.offset.click.top,
11537			dxClick = this.offset.click.left,
11538			isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t &&
11539				( y1 + dyClick ) < b ),
11540			isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l &&
11541				( x1 + dxClick ) < r ),
11542			isOverElement = isOverElementHeight && isOverElementWidth;
11543
11544		if ( this.options.tolerance === "pointer" ||
11545			this.options.forcePointerForContainers ||
11546			( this.options.tolerance !== "pointer" &&
11547				this.helperProportions[ this.floating ? "width" : "height" ] >
11548				item[ this.floating ? "width" : "height" ] )
11549		) {
11550			return isOverElement;
11551		} else {
11552
11553			return ( l < x1 + ( this.helperProportions.width / 2 ) && // Right Half
11554				x2 - ( this.helperProportions.width / 2 ) < r && // Left Half
11555				t < y1 + ( this.helperProportions.height / 2 ) && // Bottom Half
11556				y2 - ( this.helperProportions.height / 2 ) < b ); // Top Half
11557
11558		}
11559	},
11560
11561	_intersectsWithPointer: function( item ) {
11562		var verticalDirection, horizontalDirection,
11563			isOverElementHeight = ( this.options.axis === "x" ) ||
11564				this._isOverAxis(
11565					this.positionAbs.top + this.offset.click.top, item.top, item.height ),
11566			isOverElementWidth = ( this.options.axis === "y" ) ||
11567				this._isOverAxis(
11568					this.positionAbs.left + this.offset.click.left, item.left, item.width ),
11569			isOverElement = isOverElementHeight && isOverElementWidth;
11570
11571		if ( !isOverElement ) {
11572			return false;
11573		}
11574
11575		verticalDirection = this._getDragVerticalDirection();
11576		horizontalDirection = this._getDragHorizontalDirection();
11577
11578		return this.floating ?
11579			( ( horizontalDirection === "right" || verticalDirection === "down" ) ? 2 : 1 )
11580			: ( verticalDirection && ( verticalDirection === "down" ? 2 : 1 ) );
11581
11582	},
11583
11584	_intersectsWithSides: function( item ) {
11585
11586		var isOverBottomHalf = this._isOverAxis( this.positionAbs.top +
11587				this.offset.click.top, item.top + ( item.height / 2 ), item.height ),
11588			isOverRightHalf = this._isOverAxis( this.positionAbs.left +
11589				this.offset.click.left, item.left + ( item.width / 2 ), item.width ),
11590			verticalDirection = this._getDragVerticalDirection(),
11591			horizontalDirection = this._getDragHorizontalDirection();
11592
11593		if ( this.floating && horizontalDirection ) {
11594			return ( ( horizontalDirection === "right" && isOverRightHalf ) ||
11595				( horizontalDirection === "left" && !isOverRightHalf ) );
11596		} else {
11597			return verticalDirection && ( ( verticalDirection === "down" && isOverBottomHalf ) ||
11598				( verticalDirection === "up" && !isOverBottomHalf ) );
11599		}
11600
11601	},
11602
11603	_getDragVerticalDirection: function() {
11604		var delta = this.positionAbs.top - this.lastPositionAbs.top;
11605		return delta !== 0 && ( delta > 0 ? "down" : "up" );
11606	},
11607
11608	_getDragHorizontalDirection: function() {
11609		var delta = this.positionAbs.left - this.lastPositionAbs.left;
11610		return delta !== 0 && ( delta > 0 ? "right" : "left" );
11611	},
11612
11613	refresh: function( event ) {
11614		this._refreshItems( event );
11615		this._setHandleClassName();
11616		this.refreshPositions();
11617		return this;
11618	},
11619
11620	_connectWith: function() {
11621		var options = this.options;
11622		return options.connectWith.constructor === String ?
11623			[ options.connectWith ] :
11624			options.connectWith;
11625	},
11626
11627	_getItemsAsjQuery: function( connected ) {
11628
11629		var i, j, cur, inst,
11630			items = [],
11631			queries = [],
11632			connectWith = this._connectWith();
11633
11634		if ( connectWith && connected ) {
11635			for ( i = connectWith.length - 1; i >= 0; i-- ) {
11636				cur = $( connectWith[ i ], this.document[ 0 ] );
11637				for ( j = cur.length - 1; j >= 0; j-- ) {
11638					inst = $.data( cur[ j ], this.widgetFullName );
11639					if ( inst && inst !== this && !inst.options.disabled ) {
11640						queries.push( [ $.isFunction( inst.options.items ) ?
11641							inst.options.items.call( inst.element ) :
11642							$( inst.options.items, inst.element )
11643								.not( ".ui-sortable-helper" )
11644								.not( ".ui-sortable-placeholder" ), inst ] );
11645					}
11646				}
11647			}
11648		}
11649
11650		queries.push( [ $.isFunction( this.options.items ) ?
11651			this.options.items
11652				.call( this.element, null, { options: this.options, item: this.currentItem } ) :
11653			$( this.options.items, this.element )
11654				.not( ".ui-sortable-helper" )
11655				.not( ".ui-sortable-placeholder" ), this ] );
11656
11657		function addItems() {
11658			items.push( this );
11659		}
11660		for ( i = queries.length - 1; i >= 0; i-- ) {
11661			queries[ i ][ 0 ].each( addItems );
11662		}
11663
11664		return $( items );
11665
11666	},
11667
11668	_removeCurrentsFromItems: function() {
11669
11670		var list = this.currentItem.find( ":data(" + this.widgetName + "-item)" );
11671
11672		this.items = $.grep( this.items, function( item ) {
11673			for ( var j = 0; j < list.length; j++ ) {
11674				if ( list[ j ] === item.item[ 0 ] ) {
11675					return false;
11676				}
11677			}
11678			return true;
11679		} );
11680
11681	},
11682
11683	_refreshItems: function( event ) {
11684
11685		this.items = [];
11686		this.containers = [ this ];
11687
11688		var i, j, cur, inst, targetData, _queries, item, queriesLength,
11689			items = this.items,
11690			queries = [ [ $.isFunction( this.options.items ) ?
11691				this.options.items.call( this.element[ 0 ], event, { item: this.currentItem } ) :
11692				$( this.options.items, this.element ), this ] ],
11693			connectWith = this._connectWith();
11694
11695		//Shouldn't be run the first time through due to massive slow-down
11696		if ( connectWith && this.ready ) {
11697			for ( i = connectWith.length - 1; i >= 0; i-- ) {
11698				cur = $( connectWith[ i ], this.document[ 0 ] );
11699				for ( j = cur.length - 1; j >= 0; j-- ) {
11700					inst = $.data( cur[ j ], this.widgetFullName );
11701					if ( inst && inst !== this && !inst.options.disabled ) {
11702						queries.push( [ $.isFunction( inst.options.items ) ?
11703							inst.options.items
11704								.call( inst.element[ 0 ], event, { item: this.currentItem } ) :
11705							$( inst.options.items, inst.element ), inst ] );
11706						this.containers.push( inst );
11707					}
11708				}
11709			}
11710		}
11711
11712		for ( i = queries.length - 1; i >= 0; i-- ) {
11713			targetData = queries[ i ][ 1 ];
11714			_queries = queries[ i ][ 0 ];
11715
11716			for ( j = 0, queriesLength = _queries.length; j < queriesLength; j++ ) {
11717				item = $( _queries[ j ] );
11718
11719				// Data for target checking (mouse manager)
11720				item.data( this.widgetName + "-item", targetData );
11721
11722				items.push( {
11723					item: item,
11724					instance: targetData,
11725					width: 0, height: 0,
11726					left: 0, top: 0
11727				} );
11728			}
11729		}
11730
11731	},
11732
11733	refreshPositions: function( fast ) {
11734
11735		// Determine whether items are being displayed horizontally
11736		this.floating = this.items.length ?
11737			this.options.axis === "x" || this._isFloating( this.items[ 0 ].item ) :
11738			false;
11739
11740		//This has to be redone because due to the item being moved out/into the offsetParent,
11741		// the offsetParent's position will change
11742		if ( this.offsetParent && this.helper ) {
11743			this.offset.parent = this._getParentOffset();
11744		}
11745
11746		var i, item, t, p;
11747
11748		for ( i = this.items.length - 1; i >= 0; i-- ) {
11749			item = this.items[ i ];
11750
11751			//We ignore calculating positions of all connected containers when we're not over them
11752			if ( item.instance !== this.currentContainer && this.currentContainer &&
11753					item.item[ 0 ] !== this.currentItem[ 0 ] ) {
11754				continue;
11755			}
11756
11757			t = this.options.toleranceElement ?
11758				$( this.options.toleranceElement, item.item ) :
11759				item.item;
11760
11761			if ( !fast ) {
11762				item.width = t.outerWidth();
11763				item.height = t.outerHeight();
11764			}
11765
11766			p = t.offset();
11767			item.left = p.left;
11768			item.top = p.top;
11769		}
11770
11771		if ( this.options.custom && this.options.custom.refreshContainers ) {
11772			this.options.custom.refreshContainers.call( this );
11773		} else {
11774			for ( i = this.containers.length - 1; i >= 0; i-- ) {
11775				p = this.containers[ i ].element.offset();
11776				this.containers[ i ].containerCache.left = p.left;
11777				this.containers[ i ].containerCache.top = p.top;
11778				this.containers[ i ].containerCache.width =
11779					this.containers[ i ].element.outerWidth();
11780				this.containers[ i ].containerCache.height =
11781					this.containers[ i ].element.outerHeight();
11782			}
11783		}
11784
11785		return this;
11786	},
11787
11788	_createPlaceholder: function( that ) {
11789		that = that || this;
11790		var className,
11791			o = that.options;
11792
11793		if ( !o.placeholder || o.placeholder.constructor === String ) {
11794			className = o.placeholder;
11795			o.placeholder = {
11796				element: function() {
11797
11798					var nodeName = that.currentItem[ 0 ].nodeName.toLowerCase(),
11799						element = $( "<" + nodeName + ">", that.document[ 0 ] );
11800
11801						that._addClass( element, "ui-sortable-placeholder",
11802								className || that.currentItem[ 0 ].className )
11803							._removeClass( element, "ui-sortable-helper" );
11804
11805					if ( nodeName === "tbody" ) {
11806						that._createTrPlaceholder(
11807							that.currentItem.find( "tr" ).eq( 0 ),
11808							$( "<tr>", that.document[ 0 ] ).appendTo( element )
11809						);
11810					} else if ( nodeName === "tr" ) {
11811						that._createTrPlaceholder( that.currentItem, element );
11812					} else if ( nodeName === "img" ) {
11813						element.attr( "src", that.currentItem.attr( "src" ) );
11814					}
11815
11816					if ( !className ) {
11817						element.css( "visibility", "hidden" );
11818					}
11819
11820					return element;
11821				},
11822				update: function( container, p ) {
11823
11824					// 1. If a className is set as 'placeholder option, we don't force sizes -
11825					// the class is responsible for that
11826					// 2. The option 'forcePlaceholderSize can be enabled to force it even if a
11827					// class name is specified
11828					if ( className && !o.forcePlaceholderSize ) {
11829						return;
11830					}
11831
11832					//If the element doesn't have a actual height by itself (without styles coming
11833					// from a stylesheet), it receives the inline height from the dragged item
11834					if ( !p.height() ) {
11835						p.height(
11836							that.currentItem.innerHeight() -
11837							parseInt( that.currentItem.css( "paddingTop" ) || 0, 10 ) -
11838							parseInt( that.currentItem.css( "paddingBottom" ) || 0, 10 ) );
11839					}
11840					if ( !p.width() ) {
11841						p.width(
11842							that.currentItem.innerWidth() -
11843							parseInt( that.currentItem.css( "paddingLeft" ) || 0, 10 ) -
11844							parseInt( that.currentItem.css( "paddingRight" ) || 0, 10 ) );
11845					}
11846				}
11847			};
11848		}
11849
11850		//Create the placeholder
11851		that.placeholder = $( o.placeholder.element.call( that.element, that.currentItem ) );
11852
11853		//Append it after the actual current item
11854		that.currentItem.after( that.placeholder );
11855
11856		//Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
11857		o.placeholder.update( that, that.placeholder );
11858
11859	},
11860
11861	_createTrPlaceholder: function( sourceTr, targetTr ) {
11862		var that = this;
11863
11864		sourceTr.children().each( function() {
11865			$( "<td>&#160;</td>", that.document[ 0 ] )
11866				.attr( "colspan", $( this ).attr( "colspan" ) || 1 )
11867				.appendTo( targetTr );
11868		} );
11869	},
11870
11871	_contactContainers: function( event ) {
11872		var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, cur, nearBottom,
11873			floating, axis,
11874			innermostContainer = null,
11875			innermostIndex = null;
11876
11877		// Get innermost container that intersects with item
11878		for ( i = this.containers.length - 1; i >= 0; i-- ) {
11879
11880			// Never consider a container that's located within the item itself
11881			if ( $.contains( this.currentItem[ 0 ], this.containers[ i ].element[ 0 ] ) ) {
11882				continue;
11883			}
11884
11885			if ( this._intersectsWith( this.containers[ i ].containerCache ) ) {
11886
11887				// If we've already found a container and it's more "inner" than this, then continue
11888				if ( innermostContainer &&
11889						$.contains(
11890							this.containers[ i ].element[ 0 ],
11891							innermostContainer.element[ 0 ] ) ) {
11892					continue;
11893				}
11894
11895				innermostContainer = this.containers[ i ];
11896				innermostIndex = i;
11897
11898			} else {
11899
11900				// container doesn't intersect. trigger "out" event if necessary
11901				if ( this.containers[ i ].containerCache.over ) {
11902					this.containers[ i ]._trigger( "out", event, this._uiHash( this ) );
11903					this.containers[ i ].containerCache.over = 0;
11904				}
11905			}
11906
11907		}
11908
11909		// If no intersecting containers found, return
11910		if ( !innermostContainer ) {
11911			return;
11912		}
11913
11914		// Move the item into the container if it's not there already
11915		if ( this.containers.length === 1 ) {
11916			if ( !this.containers[ innermostIndex ].containerCache.over ) {
11917				this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) );
11918				this.containers[ innermostIndex ].containerCache.over = 1;
11919			}
11920		} else {
11921
11922			// When entering a new container, we will find the item with the least distance and
11923			// append our item near it
11924			dist = 10000;
11925			itemWithLeastDistance = null;
11926			floating = innermostContainer.floating || this._isFloating( this.currentItem );
11927			posProperty = floating ? "left" : "top";
11928			sizeProperty = floating ? "width" : "height";
11929			axis = floating ? "pageX" : "pageY";
11930
11931			for ( j = this.items.length - 1; j >= 0; j-- ) {
11932				if ( !$.contains(
11933						this.containers[ innermostIndex ].element[ 0 ], this.items[ j ].item[ 0 ] )
11934				) {
11935					continue;
11936				}
11937				if ( this.items[ j ].item[ 0 ] === this.currentItem[ 0 ] ) {
11938					continue;
11939				}
11940
11941				cur = this.items[ j ].item.offset()[ posProperty ];
11942				nearBottom = false;
11943				if ( event[ axis ] - cur > this.items[ j ][ sizeProperty ] / 2 ) {
11944					nearBottom = true;
11945				}
11946
11947				if ( Math.abs( event[ axis ] - cur ) < dist ) {
11948					dist = Math.abs( event[ axis ] - cur );
11949					itemWithLeastDistance = this.items[ j ];
11950					this.direction = nearBottom ? "up" : "down";
11951				}
11952			}
11953
11954			//Check if dropOnEmpty is enabled
11955			if ( !itemWithLeastDistance && !this.options.dropOnEmpty ) {
11956				return;
11957			}
11958
11959			if ( this.currentContainer === this.containers[ innermostIndex ] ) {
11960				if ( !this.currentContainer.containerCache.over ) {
11961					this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash() );
11962					this.currentContainer.containerCache.over = 1;
11963				}
11964				return;
11965			}
11966
11967			itemWithLeastDistance ?
11968				this._rearrange( event, itemWithLeastDistance, null, true ) :
11969				this._rearrange( event, null, this.containers[ innermostIndex ].element, true );
11970			this._trigger( "change", event, this._uiHash() );
11971			this.containers[ innermostIndex ]._trigger( "change", event, this._uiHash( this ) );
11972			this.currentContainer = this.containers[ innermostIndex ];
11973
11974			//Update the placeholder
11975			this.options.placeholder.update( this.currentContainer, this.placeholder );
11976
11977			this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) );
11978			this.containers[ innermostIndex ].containerCache.over = 1;
11979		}
11980
11981	},
11982
11983	_createHelper: function( event ) {
11984
11985		var o = this.options,
11986			helper = $.isFunction( o.helper ) ?
11987				$( o.helper.apply( this.element[ 0 ], [ event, this.currentItem ] ) ) :
11988				( o.helper === "clone" ? this.currentItem.clone() : this.currentItem );
11989
11990		//Add the helper to the DOM if that didn't happen already
11991		if ( !helper.parents( "body" ).length ) {
11992			$( o.appendTo !== "parent" ?
11993				o.appendTo :
11994				this.currentItem[ 0 ].parentNode )[ 0 ].appendChild( helper[ 0 ] );
11995		}
11996
11997		if ( helper[ 0 ] === this.currentItem[ 0 ] ) {
11998			this._storedCSS = {
11999				width: this.currentItem[ 0 ].style.width,
12000				height: this.currentItem[ 0 ].style.height,
12001				position: this.currentItem.css( "position" ),
12002				top: this.currentItem.css( "top" ),
12003				left: this.currentItem.css( "left" )
12004			};
12005		}
12006
12007		if ( !helper[ 0 ].style.width || o.forceHelperSize ) {
12008			helper.width( this.currentItem.width() );
12009		}
12010		if ( !helper[ 0 ].style.height || o.forceHelperSize ) {
12011			helper.height( this.currentItem.height() );
12012		}
12013
12014		return helper;
12015
12016	},
12017
12018	_adjustOffsetFromHelper: function( obj ) {
12019		if ( typeof obj === "string" ) {
12020			obj = obj.split( " " );
12021		}
12022		if ( $.isArray( obj ) ) {
12023			obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 };
12024		}
12025		if ( "left" in obj ) {
12026			this.offset.click.left = obj.left + this.margins.left;
12027		}
12028		if ( "right" in obj ) {
12029			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
12030		}
12031		if ( "top" in obj ) {
12032			this.offset.click.top = obj.top + this.margins.top;
12033		}
12034		if ( "bottom" in obj ) {
12035			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
12036		}
12037	},
12038
12039	_getParentOffset: function() {
12040
12041		//Get the offsetParent and cache its position
12042		this.offsetParent = this.helper.offsetParent();
12043		var po = this.offsetParent.offset();
12044
12045		// This is a special case where we need to modify a offset calculated on start, since the
12046		// following happened:
12047		// 1. The position of the helper is absolute, so it's position is calculated based on the
12048		// next positioned parent
12049		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't
12050		// the document, which means that the scroll is included in the initial calculation of the
12051		// offset of the parent, and never recalculated upon drag
12052		if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== this.document[ 0 ] &&
12053				$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) {
12054			po.left += this.scrollParent.scrollLeft();
12055			po.top += this.scrollParent.scrollTop();
12056		}
12057
12058		// This needs to be actually done for all browsers, since pageX/pageY includes this
12059		// information with an ugly IE fix
12060		if ( this.offsetParent[ 0 ] === this.document[ 0 ].body ||
12061				( this.offsetParent[ 0 ].tagName &&
12062				this.offsetParent[ 0 ].tagName.toLowerCase() === "html" && $.ui.ie ) ) {
12063			po = { top: 0, left: 0 };
12064		}
12065
12066		return {
12067			top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ),
12068			left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 )
12069		};
12070
12071	},
12072
12073	_getRelativeOffset: function() {
12074
12075		if ( this.cssPosition === "relative" ) {
12076			var p = this.currentItem.position();
12077			return {
12078				top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) +
12079					this.scrollParent.scrollTop(),
12080				left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) +
12081					this.scrollParent.scrollLeft()
12082			};
12083		} else {
12084			return { top: 0, left: 0 };
12085		}
12086
12087	},
12088
12089	_cacheMargins: function() {
12090		this.margins = {
12091			left: ( parseInt( this.currentItem.css( "marginLeft" ), 10 ) || 0 ),
12092			top: ( parseInt( this.currentItem.css( "marginTop" ), 10 ) || 0 )
12093		};
12094	},
12095
12096	_cacheHelperProportions: function() {
12097		this.helperProportions = {
12098			width: this.helper.outerWidth(),
12099			height: this.helper.outerHeight()
12100		};
12101	},
12102
12103	_setContainment: function() {
12104
12105		var ce, co, over,
12106			o = this.options;
12107		if ( o.containment === "parent" ) {
12108			o.containment = this.helper[ 0 ].parentNode;
12109		}
12110		if ( o.containment === "document" || o.containment === "window" ) {
12111			this.containment = [
12112				0 - this.offset.relative.left - this.offset.parent.left,
12113				0 - this.offset.relative.top - this.offset.parent.top,
12114				o.containment === "document" ?
12115					this.document.width() :
12116					this.window.width() - this.helperProportions.width - this.margins.left,
12117				( o.containment === "document" ?
12118					( this.document.height() || document.body.parentNode.scrollHeight ) :
12119					this.window.height() || this.document[ 0 ].body.parentNode.scrollHeight
12120				) - this.helperProportions.height - this.margins.top
12121			];
12122		}
12123
12124		if ( !( /^(document|window|parent)$/ ).test( o.containment ) ) {
12125			ce = $( o.containment )[ 0 ];
12126			co = $( o.containment ).offset();
12127			over = ( $( ce ).css( "overflow" ) !== "hidden" );
12128
12129			this.containment = [
12130				co.left + ( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) +
12131					( parseInt( $( ce ).css( "paddingLeft" ), 10 ) || 0 ) - this.margins.left,
12132				co.top + ( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) +
12133					( parseInt( $( ce ).css( "paddingTop" ), 10 ) || 0 ) - this.margins.top,
12134				co.left + ( over ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -
12135					( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) -
12136					( parseInt( $( ce ).css( "paddingRight" ), 10 ) || 0 ) -
12137					this.helperProportions.width - this.margins.left,
12138				co.top + ( over ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -
12139					( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) -
12140					( parseInt( $( ce ).css( "paddingBottom" ), 10 ) || 0 ) -
12141					this.helperProportions.height - this.margins.top
12142			];
12143		}
12144
12145	},
12146
12147	_convertPositionTo: function( d, pos ) {
12148
12149		if ( !pos ) {
12150			pos = this.position;
12151		}
12152		var mod = d === "absolute" ? 1 : -1,
12153			scroll = this.cssPosition === "absolute" &&
12154				!( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
12155				$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ?
12156					this.offsetParent :
12157					this.scrollParent,
12158			scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName );
12159
12160		return {
12161			top: (
12162
12163				// The absolute mouse position
12164				pos.top	+
12165
12166				// Only for relative positioned nodes: Relative offset from element to offset parent
12167				this.offset.relative.top * mod +
12168
12169				// The offsetParent's offset without borders (offset + border)
12170				this.offset.parent.top * mod -
12171				( ( this.cssPosition === "fixed" ?
12172					-this.scrollParent.scrollTop() :
12173					( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod )
12174			),
12175			left: (
12176
12177				// The absolute mouse position
12178				pos.left +
12179
12180				// Only for relative positioned nodes: Relative offset from element to offset parent
12181				this.offset.relative.left * mod +
12182
12183				// The offsetParent's offset without borders (offset + border)
12184				this.offset.parent.left * mod	-
12185				( ( this.cssPosition === "fixed" ?
12186					-this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 :
12187					scroll.scrollLeft() ) * mod )
12188			)
12189		};
12190
12191	},
12192
12193	_generatePosition: function( event ) {
12194
12195		var top, left,
12196			o = this.options,
12197			pageX = event.pageX,
12198			pageY = event.pageY,
12199			scroll = this.cssPosition === "absolute" &&
12200				!( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
12201				$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ?
12202					this.offsetParent :
12203					this.scrollParent,
12204				scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName );
12205
12206		// This is another very weird special case that only happens for relative elements:
12207		// 1. If the css position is relative
12208		// 2. and the scroll parent is the document or similar to the offset parent
12209		// we have to refresh the relative offset during the scroll so there are no jumps
12210		if ( this.cssPosition === "relative" && !( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
12211				this.scrollParent[ 0 ] !== this.offsetParent[ 0 ] ) ) {
12212			this.offset.relative = this._getRelativeOffset();
12213		}
12214
12215		/*
12216		 * - Position constraining -
12217		 * Constrain the position to a mix of grid, containment.
12218		 */
12219
12220		if ( this.originalPosition ) { //If we are not dragging yet, we won't check for options
12221
12222			if ( this.containment ) {
12223				if ( event.pageX - this.offset.click.left < this.containment[ 0 ] ) {
12224					pageX = this.containment[ 0 ] + this.offset.click.left;
12225				}
12226				if ( event.pageY - this.offset.click.top < this.containment[ 1 ] ) {
12227					pageY = this.containment[ 1 ] + this.offset.click.top;
12228				}
12229				if ( event.pageX - this.offset.click.left > this.containment[ 2 ] ) {
12230					pageX = this.containment[ 2 ] + this.offset.click.left;
12231				}
12232				if ( event.pageY - this.offset.click.top > this.containment[ 3 ] ) {
12233					pageY = this.containment[ 3 ] + this.offset.click.top;
12234				}
12235			}
12236
12237			if ( o.grid ) {
12238				top = this.originalPageY + Math.round( ( pageY - this.originalPageY ) /
12239					o.grid[ 1 ] ) * o.grid[ 1 ];
12240				pageY = this.containment ?
12241					( ( top - this.offset.click.top >= this.containment[ 1 ] &&
12242						top - this.offset.click.top <= this.containment[ 3 ] ) ?
12243							top :
12244							( ( top - this.offset.click.top >= this.containment[ 1 ] ) ?
12245								top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) :
12246								top;
12247
12248				left = this.originalPageX + Math.round( ( pageX - this.originalPageX ) /
12249					o.grid[ 0 ] ) * o.grid[ 0 ];
12250				pageX = this.containment ?
12251					( ( left - this.offset.click.left >= this.containment[ 0 ] &&
12252						left - this.offset.click.left <= this.containment[ 2 ] ) ?
12253							left :
12254							( ( left - this.offset.click.left >= this.containment[ 0 ] ) ?
12255								left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) :
12256								left;
12257			}
12258
12259		}
12260
12261		return {
12262			top: (
12263
12264				// The absolute mouse position
12265				pageY -
12266
12267				// Click offset (relative to the element)
12268				this.offset.click.top -
12269
12270				// Only for relative positioned nodes: Relative offset from element to offset parent
12271				this.offset.relative.top -
12272
12273				// The offsetParent's offset without borders (offset + border)
12274				this.offset.parent.top +
12275				( ( this.cssPosition === "fixed" ?
12276					-this.scrollParent.scrollTop() :
12277					( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) )
12278			),
12279			left: (
12280
12281				// The absolute mouse position
12282				pageX -
12283
12284				// Click offset (relative to the element)
12285				this.offset.click.left -
12286
12287				// Only for relative positioned nodes: Relative offset from element to offset parent
12288				this.offset.relative.left -
12289
12290				// The offsetParent's offset without borders (offset + border)
12291				this.offset.parent.left +
12292				( ( this.cssPosition === "fixed" ?
12293					-this.scrollParent.scrollLeft() :
12294					scrollIsRootNode ? 0 : scroll.scrollLeft() ) )
12295			)
12296		};
12297
12298	},
12299
12300	_rearrange: function( event, i, a, hardRefresh ) {
12301
12302		a ? a[ 0 ].appendChild( this.placeholder[ 0 ] ) :
12303			i.item[ 0 ].parentNode.insertBefore( this.placeholder[ 0 ],
12304				( this.direction === "down" ? i.item[ 0 ] : i.item[ 0 ].nextSibling ) );
12305
12306		//Various things done here to improve the performance:
12307		// 1. we create a setTimeout, that calls refreshPositions
12308		// 2. on the instance, we have a counter variable, that get's higher after every append
12309		// 3. on the local scope, we copy the counter variable, and check in the timeout,
12310		// if it's still the same
12311		// 4. this lets only the last addition to the timeout stack through
12312		this.counter = this.counter ? ++this.counter : 1;
12313		var counter = this.counter;
12314
12315		this._delay( function() {
12316			if ( counter === this.counter ) {
12317
12318				//Precompute after each DOM insertion, NOT on mousemove
12319				this.refreshPositions( !hardRefresh );
12320			}
12321		} );
12322
12323	},
12324
12325	_clear: function( event, noPropagation ) {
12326
12327		this.reverting = false;
12328
12329		// We delay all events that have to be triggered to after the point where the placeholder
12330		// has been removed and everything else normalized again
12331		var i,
12332			delayedTriggers = [];
12333
12334		// We first have to update the dom position of the actual currentItem
12335		// Note: don't do it if the current item is already removed (by a user), or it gets
12336		// reappended (see #4088)
12337		if ( !this._noFinalSort && this.currentItem.parent().length ) {
12338			this.placeholder.before( this.currentItem );
12339		}
12340		this._noFinalSort = null;
12341
12342		if ( this.helper[ 0 ] === this.currentItem[ 0 ] ) {
12343			for ( i in this._storedCSS ) {
12344				if ( this._storedCSS[ i ] === "auto" || this._storedCSS[ i ] === "static" ) {
12345					this._storedCSS[ i ] = "";
12346				}
12347			}
12348			this.currentItem.css( this._storedCSS );
12349			this._removeClass( this.currentItem, "ui-sortable-helper" );
12350		} else {
12351			this.currentItem.show();
12352		}
12353
12354		if ( this.fromOutside && !noPropagation ) {
12355			delayedTriggers.push( function( event ) {
12356				this._trigger( "receive", event, this._uiHash( this.fromOutside ) );
12357			} );
12358		}
12359		if ( ( this.fromOutside ||
12360				this.domPosition.prev !==
12361				this.currentItem.prev().not( ".ui-sortable-helper" )[ 0 ] ||
12362				this.domPosition.parent !== this.currentItem.parent()[ 0 ] ) && !noPropagation ) {
12363
12364			// Trigger update callback if the DOM position has changed
12365			delayedTriggers.push( function( event ) {
12366				this._trigger( "update", event, this._uiHash() );
12367			} );
12368		}
12369
12370		// Check if the items Container has Changed and trigger appropriate
12371		// events.
12372		if ( this !== this.currentContainer ) {
12373			if ( !noPropagation ) {
12374				delayedTriggers.push( function( event ) {
12375					this._trigger( "remove", event, this._uiHash() );
12376				} );
12377				delayedTriggers.push( ( function( c ) {
12378					return function( event ) {
12379						c._trigger( "receive", event, this._uiHash( this ) );
12380					};
12381				} ).call( this, this.currentContainer ) );
12382				delayedTriggers.push( ( function( c ) {
12383					return function( event ) {
12384						c._trigger( "update", event, this._uiHash( this ) );
12385					};
12386				} ).call( this, this.currentContainer ) );
12387			}
12388		}
12389
12390		//Post events to containers
12391		function delayEvent( type, instance, container ) {
12392			return function( event ) {
12393				container._trigger( type, event, instance._uiHash( instance ) );
12394			};
12395		}
12396		for ( i = this.containers.length - 1; i >= 0; i-- ) {
12397			if ( !noPropagation ) {
12398				delayedTriggers.push( delayEvent( "deactivate", this, this.containers[ i ] ) );
12399			}
12400			if ( this.containers[ i ].containerCache.over ) {
12401				delayedTriggers.push( delayEvent( "out", this, this.containers[ i ] ) );
12402				this.containers[ i ].containerCache.over = 0;
12403			}
12404		}
12405
12406		//Do what was originally in plugins
12407		if ( this.storedCursor ) {
12408			this.document.find( "body" ).css( "cursor", this.storedCursor );
12409			this.storedStylesheet.remove();
12410		}
12411		if ( this._storedOpacity ) {
12412			this.helper.css( "opacity", this._storedOpacity );
12413		}
12414		if ( this._storedZIndex ) {
12415			this.helper.css( "zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex );
12416		}
12417
12418		this.dragging = false;
12419
12420		if ( !noPropagation ) {
12421			this._trigger( "beforeStop", event, this._uiHash() );
12422		}
12423
12424		//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately,
12425		// it unbinds ALL events from the original node!
12426		this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] );
12427
12428		if ( !this.cancelHelperRemoval ) {
12429			if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {
12430				this.helper.remove();
12431			}
12432			this.helper = null;
12433		}
12434
12435		if ( !noPropagation ) {
12436			for ( i = 0; i < delayedTriggers.length; i++ ) {
12437
12438				// Trigger all delayed events
12439				delayedTriggers[ i ].call( this, event );
12440			}
12441			this._trigger( "stop", event, this._uiHash() );
12442		}
12443
12444		this.fromOutside = false;
12445		return !this.cancelHelperRemoval;
12446
12447	},
12448
12449	_trigger: function() {
12450		if ( $.Widget.prototype._trigger.apply( this, arguments ) === false ) {
12451			this.cancel();
12452		}
12453	},
12454
12455	_uiHash: function( _inst ) {
12456		var inst = _inst || this;
12457		return {
12458			helper: inst.helper,
12459			placeholder: inst.placeholder || $( [] ),
12460			position: inst.position,
12461			originalPosition: inst.originalPosition,
12462			offset: inst.positionAbs,
12463			item: inst.currentItem,
12464			sender: _inst ? _inst.element : null
12465		};
12466	}
12467
12468} );
12469
12470
12471/*!
12472 * jQuery UI Spinner 1.12.1
12473 * http://jqueryui.com
12474 *
12475 * Copyright jQuery Foundation and other contributors
12476 * Released under the MIT license.
12477 * http://jquery.org/license
12478 */
12479
12480//>>label: Spinner
12481//>>group: Widgets
12482//>>description: Displays buttons to easily input numbers via the keyboard or mouse.
12483//>>docs: http://api.jqueryui.com/spinner/
12484//>>demos: http://jqueryui.com/spinner/
12485//>>css.structure: ../../themes/base/core.css
12486//>>css.structure: ../../themes/base/spinner.css
12487//>>css.theme: ../../themes/base/theme.css
12488
12489
12490
12491function spinnerModifer( fn ) {
12492	return function() {
12493		var previous = this.element.val();
12494		fn.apply( this, arguments );
12495		this._refresh();
12496		if ( previous !== this.element.val() ) {
12497			this._trigger( "change" );
12498		}
12499	};
12500}
12501
12502$.widget( "ui.spinner", {
12503	version: "1.12.1",
12504	defaultElement: "<input>",
12505	widgetEventPrefix: "spin",
12506	options: {
12507		classes: {
12508			"ui-spinner": "ui-corner-all",
12509			"ui-spinner-down": "ui-corner-br",
12510			"ui-spinner-up": "ui-corner-tr"
12511		},
12512		culture: null,
12513		icons: {
12514			down: "ui-icon-triangle-1-s",
12515			up: "ui-icon-triangle-1-n"
12516		},
12517		incremental: true,
12518		max: null,
12519		min: null,
12520		numberFormat: null,
12521		page: 10,
12522		step: 1,
12523
12524		change: null,
12525		spin: null,
12526		start: null,
12527		stop: null
12528	},
12529
12530	_create: function() {
12531
12532		// handle string values that need to be parsed
12533		this._setOption( "max", this.options.max );
12534		this._setOption( "min", this.options.min );
12535		this._setOption( "step", this.options.step );
12536
12537		// Only format if there is a value, prevents the field from being marked
12538		// as invalid in Firefox, see #9573.
12539		if ( this.value() !== "" ) {
12540
12541			// Format the value, but don't constrain.
12542			this._value( this.element.val(), true );
12543		}
12544
12545		this._draw();
12546		this._on( this._events );
12547		this._refresh();
12548
12549		// Turning off autocomplete prevents the browser from remembering the
12550		// value when navigating through history, so we re-enable autocomplete
12551		// if the page is unloaded before the widget is destroyed. #7790
12552		this._on( this.window, {
12553			beforeunload: function() {
12554				this.element.removeAttr( "autocomplete" );
12555			}
12556		} );
12557	},
12558
12559	_getCreateOptions: function() {
12560		var options = this._super();
12561		var element = this.element;
12562
12563		$.each( [ "min", "max", "step" ], function( i, option ) {
12564			var value = element.attr( option );
12565			if ( value != null && value.length ) {
12566				options[ option ] = value;
12567			}
12568		} );
12569
12570		return options;
12571	},
12572
12573	_events: {
12574		keydown: function( event ) {
12575			if ( this._start( event ) && this._keydown( event ) ) {
12576				event.preventDefault();
12577			}
12578		},
12579		keyup: "_stop",
12580		focus: function() {
12581			this.previous = this.element.val();
12582		},
12583		blur: function( event ) {
12584			if ( this.cancelBlur ) {
12585				delete this.cancelBlur;
12586				return;
12587			}
12588
12589			this._stop();
12590			this._refresh();
12591			if ( this.previous !== this.element.val() ) {
12592				this._trigger( "change", event );
12593			}
12594		},
12595		mousewheel: function( event, delta ) {
12596			if ( !delta ) {
12597				return;
12598			}
12599			if ( !this.spinning && !this._start( event ) ) {
12600				return false;
12601			}
12602
12603			this._spin( ( delta > 0 ? 1 : -1 ) * this.options.step, event );
12604			clearTimeout( this.mousewheelTimer );
12605			this.mousewheelTimer = this._delay( function() {
12606				if ( this.spinning ) {
12607					this._stop( event );
12608				}
12609			}, 100 );
12610			event.preventDefault();
12611		},
12612		"mousedown .ui-spinner-button": function( event ) {
12613			var previous;
12614
12615			// We never want the buttons to have focus; whenever the user is
12616			// interacting with the spinner, the focus should be on the input.
12617			// If the input is focused then this.previous is properly set from
12618			// when the input first received focus. If the input is not focused
12619			// then we need to set this.previous based on the value before spinning.
12620			previous = this.element[ 0 ] === $.ui.safeActiveElement( this.document[ 0 ] ) ?
12621				this.previous : this.element.val();
12622			function checkFocus() {
12623				var isActive = this.element[ 0 ] === $.ui.safeActiveElement( this.document[ 0 ] );
12624				if ( !isActive ) {
12625					this.element.trigger( "focus" );
12626					this.previous = previous;
12627
12628					// support: IE
12629					// IE sets focus asynchronously, so we need to check if focus
12630					// moved off of the input because the user clicked on the button.
12631					this._delay( function() {
12632						this.previous = previous;
12633					} );
12634				}
12635			}
12636
12637			// Ensure focus is on (or stays on) the text field
12638			event.preventDefault();
12639			checkFocus.call( this );
12640
12641			// Support: IE
12642			// IE doesn't prevent moving focus even with event.preventDefault()
12643			// so we set a flag to know when we should ignore the blur event
12644			// and check (again) if focus moved off of the input.
12645			this.cancelBlur = true;
12646			this._delay( function() {
12647				delete this.cancelBlur;
12648				checkFocus.call( this );
12649			} );
12650
12651			if ( this._start( event ) === false ) {
12652				return;
12653			}
12654
12655			this._repeat( null, $( event.currentTarget )
12656				.hasClass( "ui-spinner-up" ) ? 1 : -1, event );
12657		},
12658		"mouseup .ui-spinner-button": "_stop",
12659		"mouseenter .ui-spinner-button": function( event ) {
12660
12661			// button will add ui-state-active if mouse was down while mouseleave and kept down
12662			if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) {
12663				return;
12664			}
12665
12666			if ( this._start( event ) === false ) {
12667				return false;
12668			}
12669			this._repeat( null, $( event.currentTarget )
12670				.hasClass( "ui-spinner-up" ) ? 1 : -1, event );
12671		},
12672
12673		// TODO: do we really want to consider this a stop?
12674		// shouldn't we just stop the repeater and wait until mouseup before
12675		// we trigger the stop event?
12676		"mouseleave .ui-spinner-button": "_stop"
12677	},
12678
12679	// Support mobile enhanced option and make backcompat more sane
12680	_enhance: function() {
12681		this.uiSpinner = this.element
12682			.attr( "autocomplete", "off" )
12683			.wrap( "<span>" )
12684			.parent()
12685
12686				// Add buttons
12687				.append(
12688					"<a></a><a></a>"
12689				);
12690	},
12691
12692	_draw: function() {
12693		this._enhance();
12694
12695		this._addClass( this.uiSpinner, "ui-spinner", "ui-widget ui-widget-content" );
12696		this._addClass( "ui-spinner-input" );
12697
12698		this.element.attr( "role", "spinbutton" );
12699
12700		// Button bindings
12701		this.buttons = this.uiSpinner.children( "a" )
12702			.attr( "tabIndex", -1 )
12703			.attr( "aria-hidden", true )
12704			.button( {
12705				classes: {
12706					"ui-button": ""
12707				}
12708			} );
12709
12710		// TODO: Right now button does not support classes this is already updated in button PR
12711		this._removeClass( this.buttons, "ui-corner-all" );
12712
12713		this._addClass( this.buttons.first(), "ui-spinner-button ui-spinner-up" );
12714		this._addClass( this.buttons.last(), "ui-spinner-button ui-spinner-down" );
12715		this.buttons.first().button( {
12716			"icon": this.options.icons.up,
12717			"showLabel": false
12718		} );
12719		this.buttons.last().button( {
12720			"icon": this.options.icons.down,
12721			"showLabel": false
12722		} );
12723
12724		// IE 6 doesn't understand height: 50% for the buttons
12725		// unless the wrapper has an explicit height
12726		if ( this.buttons.height() > Math.ceil( this.uiSpinner.height() * 0.5 ) &&
12727				this.uiSpinner.height() > 0 ) {
12728			this.uiSpinner.height( this.uiSpinner.height() );
12729		}
12730	},
12731
12732	_keydown: function( event ) {
12733		var options = this.options,
12734			keyCode = $.ui.keyCode;
12735
12736		switch ( event.keyCode ) {
12737		case keyCode.UP:
12738			this._repeat( null, 1, event );
12739			return true;
12740		case keyCode.DOWN:
12741			this._repeat( null, -1, event );
12742			return true;
12743		case keyCode.PAGE_UP:
12744			this._repeat( null, options.page, event );
12745			return true;
12746		case keyCode.PAGE_DOWN:
12747			this._repeat( null, -options.page, event );
12748			return true;
12749		}
12750
12751		return false;
12752	},
12753
12754	_start: function( event ) {
12755		if ( !this.spinning && this._trigger( "start", event ) === false ) {
12756			return false;
12757		}
12758
12759		if ( !this.counter ) {
12760			this.counter = 1;
12761		}
12762		this.spinning = true;
12763		return true;
12764	},
12765
12766	_repeat: function( i, steps, event ) {
12767		i = i || 500;
12768
12769		clearTimeout( this.timer );
12770		this.timer = this._delay( function() {
12771			this._repeat( 40, steps, event );
12772		}, i );
12773
12774		this._spin( steps * this.options.step, event );
12775	},
12776
12777	_spin: function( step, event ) {
12778		var value = this.value() || 0;
12779
12780		if ( !this.counter ) {
12781			this.counter = 1;
12782		}
12783
12784		value = this._adjustValue( value + step * this._increment( this.counter ) );
12785
12786		if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false ) {
12787			this._value( value );
12788			this.counter++;
12789		}
12790	},
12791
12792	_increment: function( i ) {
12793		var incremental = this.options.incremental;
12794
12795		if ( incremental ) {
12796			return $.isFunction( incremental ) ?
12797				incremental( i ) :
12798				Math.floor( i * i * i / 50000 - i * i / 500 + 17 * i / 200 + 1 );
12799		}
12800
12801		return 1;
12802	},
12803
12804	_precision: function() {
12805		var precision = this._precisionOf( this.options.step );
12806		if ( this.options.min !== null ) {
12807			precision = Math.max( precision, this._precisionOf( this.options.min ) );
12808		}
12809		return precision;
12810	},
12811
12812	_precisionOf: function( num ) {
12813		var str = num.toString(),
12814			decimal = str.indexOf( "." );
12815		return decimal === -1 ? 0 : str.length - decimal - 1;
12816	},
12817
12818	_adjustValue: function( value ) {
12819		var base, aboveMin,
12820			options = this.options;
12821
12822		// Make sure we're at a valid step
12823		// - find out where we are relative to the base (min or 0)
12824		base = options.min !== null ? options.min : 0;
12825		aboveMin = value - base;
12826
12827		// - round to the nearest step
12828		aboveMin = Math.round( aboveMin / options.step ) * options.step;
12829
12830		// - rounding is based on 0, so adjust back to our base
12831		value = base + aboveMin;
12832
12833		// Fix precision from bad JS floating point math
12834		value = parseFloat( value.toFixed( this._precision() ) );
12835
12836		// Clamp the value
12837		if ( options.max !== null && value > options.max ) {
12838			return options.max;
12839		}
12840		if ( options.min !== null && value < options.min ) {
12841			return options.min;
12842		}
12843
12844		return value;
12845	},
12846
12847	_stop: function( event ) {
12848		if ( !this.spinning ) {
12849			return;
12850		}
12851
12852		clearTimeout( this.timer );
12853		clearTimeout( this.mousewheelTimer );
12854		this.counter = 0;
12855		this.spinning = false;
12856		this._trigger( "stop", event );
12857	},
12858
12859	_setOption: function( key, value ) {
12860		var prevValue, first, last;
12861
12862		if ( key === "culture" || key === "numberFormat" ) {
12863			prevValue = this._parse( this.element.val() );
12864			this.options[ key ] = value;
12865			this.element.val( this._format( prevValue ) );
12866			return;
12867		}
12868
12869		if ( key === "max" || key === "min" || key === "step" ) {
12870			if ( typeof value === "string" ) {
12871				value = this._parse( value );
12872			}
12873		}
12874		if ( key === "icons" ) {
12875			first = this.buttons.first().find( ".ui-icon" );
12876			this._removeClass( first, null, this.options.icons.up );
12877			this._addClass( first, null, value.up );
12878			last = this.buttons.last().find( ".ui-icon" );
12879			this._removeClass( last, null, this.options.icons.down );
12880			this._addClass( last, null, value.down );
12881		}
12882
12883		this._super( key, value );
12884	},
12885
12886	_setOptionDisabled: function( value ) {
12887		this._super( value );
12888
12889		this._toggleClass( this.uiSpinner, null, "ui-state-disabled", !!value );
12890		this.element.prop( "disabled", !!value );
12891		this.buttons.button( value ? "disable" : "enable" );
12892	},
12893
12894	_setOptions: spinnerModifer( function( options ) {
12895		this._super( options );
12896	} ),
12897
12898	_parse: function( val ) {
12899		if ( typeof val === "string" && val !== "" ) {
12900			val = window.Globalize && this.options.numberFormat ?
12901				Globalize.parseFloat( val, 10, this.options.culture ) : +val;
12902		}
12903		return val === "" || isNaN( val ) ? null : val;
12904	},
12905
12906	_format: function( value ) {
12907		if ( value === "" ) {
12908			return "";
12909		}
12910		return window.Globalize && this.options.numberFormat ?
12911			Globalize.format( value, this.options.numberFormat, this.options.culture ) :
12912			value;
12913	},
12914
12915	_refresh: function() {
12916		this.element.attr( {
12917			"aria-valuemin": this.options.min,
12918			"aria-valuemax": this.options.max,
12919
12920			// TODO: what should we do with values that can't be parsed?
12921			"aria-valuenow": this._parse( this.element.val() )
12922		} );
12923	},
12924
12925	isValid: function() {
12926		var value = this.value();
12927
12928		// Null is invalid
12929		if ( value === null ) {
12930			return false;
12931		}
12932
12933		// If value gets adjusted, it's invalid
12934		return value === this._adjustValue( value );
12935	},
12936
12937	// Update the value without triggering change
12938	_value: function( value, allowAny ) {
12939		var parsed;
12940		if ( value !== "" ) {
12941			parsed = this._parse( value );
12942			if ( parsed !== null ) {
12943				if ( !allowAny ) {
12944					parsed = this._adjustValue( parsed );
12945				}
12946				value = this._format( parsed );
12947			}
12948		}
12949		this.element.val( value );
12950		this._refresh();
12951	},
12952
12953	_destroy: function() {
12954		this.element
12955			.prop( "disabled", false )
12956			.removeAttr( "autocomplete role aria-valuemin aria-valuemax aria-valuenow" );
12957
12958		this.uiSpinner.replaceWith( this.element );
12959	},
12960
12961	stepUp: spinnerModifer( function( steps ) {
12962		this._stepUp( steps );
12963	} ),
12964	_stepUp: function( steps ) {
12965		if ( this._start() ) {
12966			this._spin( ( steps || 1 ) * this.options.step );
12967			this._stop();
12968		}
12969	},
12970
12971	stepDown: spinnerModifer( function( steps ) {
12972		this._stepDown( steps );
12973	} ),
12974	_stepDown: function( steps ) {
12975		if ( this._start() ) {
12976			this._spin( ( steps || 1 ) * -this.options.step );
12977			this._stop();
12978		}
12979	},
12980
12981	pageUp: spinnerModifer( function( pages ) {
12982		this._stepUp( ( pages || 1 ) * this.options.page );
12983	} ),
12984
12985	pageDown: spinnerModifer( function( pages ) {
12986		this._stepDown( ( pages || 1 ) * this.options.page );
12987	} ),
12988
12989	value: function( newVal ) {
12990		if ( !arguments.length ) {
12991			return this._parse( this.element.val() );
12992		}
12993		spinnerModifer( this._value ).call( this, newVal );
12994	},
12995
12996	widget: function() {
12997		return this.uiSpinner;
12998	}
12999} );
13000
13001// DEPRECATED
13002// TODO: switch return back to widget declaration at top of file when this is removed
13003if ( $.uiBackCompat !== false ) {
13004
13005	// Backcompat for spinner html extension points
13006	$.widget( "ui.spinner", $.ui.spinner, {
13007		_enhance: function() {
13008			this.uiSpinner = this.element
13009				.attr( "autocomplete", "off" )
13010				.wrap( this._uiSpinnerHtml() )
13011				.parent()
13012
13013					// Add buttons
13014					.append( this._buttonHtml() );
13015		},
13016		_uiSpinnerHtml: function() {
13017			return "<span>";
13018		},
13019
13020		_buttonHtml: function() {
13021			return "<a></a><a></a>";
13022		}
13023	} );
13024}
13025
13026var widgetsSpinner = $.ui.spinner;
13027
13028
13029/*!
13030 * jQuery UI Tabs 1.12.1
13031 * http://jqueryui.com
13032 *
13033 * Copyright jQuery Foundation and other contributors
13034 * Released under the MIT license.
13035 * http://jquery.org/license
13036 */
13037
13038//>>label: Tabs
13039//>>group: Widgets
13040//>>description: Transforms a set of container elements into a tab structure.
13041//>>docs: http://api.jqueryui.com/tabs/
13042//>>demos: http://jqueryui.com/tabs/
13043//>>css.structure: ../../themes/base/core.css
13044//>>css.structure: ../../themes/base/tabs.css
13045//>>css.theme: ../../themes/base/theme.css
13046
13047
13048
13049$.widget( "ui.tabs", {
13050	version: "1.12.1",
13051	delay: 300,
13052	options: {
13053		active: null,
13054		classes: {
13055			"ui-tabs": "ui-corner-all",
13056			"ui-tabs-nav": "ui-corner-all",
13057			"ui-tabs-panel": "ui-corner-bottom",
13058			"ui-tabs-tab": "ui-corner-top"
13059		},
13060		collapsible: false,
13061		event: "click",
13062		heightStyle: "content",
13063		hide: null,
13064		show: null,
13065
13066		// Callbacks
13067		activate: null,
13068		beforeActivate: null,
13069		beforeLoad: null,
13070		load: null
13071	},
13072
13073	_isLocal: ( function() {
13074		var rhash = /#.*$/;
13075
13076		return function( anchor ) {
13077			var anchorUrl, locationUrl;
13078
13079			anchorUrl = anchor.href.replace( rhash, "" );
13080			locationUrl = location.href.replace( rhash, "" );
13081
13082			// Decoding may throw an error if the URL isn't UTF-8 (#9518)
13083			try {
13084				anchorUrl = decodeURIComponent( anchorUrl );
13085			} catch ( error ) {}
13086			try {
13087				locationUrl = decodeURIComponent( locationUrl );
13088			} catch ( error ) {}
13089
13090			return anchor.hash.length > 1 && anchorUrl === locationUrl;
13091		};
13092	} )(),
13093
13094	_create: function() {
13095		var that = this,
13096			options = this.options;
13097
13098		this.running = false;
13099
13100		this._addClass( "ui-tabs", "ui-widget ui-widget-content" );
13101		this._toggleClass( "ui-tabs-collapsible", null, options.collapsible );
13102
13103		this._processTabs();
13104		options.active = this._initialActive();
13105
13106		// Take disabling tabs via class attribute from HTML
13107		// into account and update option properly.
13108		if ( $.isArray( options.disabled ) ) {
13109			options.disabled = $.unique( options.disabled.concat(
13110				$.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) {
13111					return that.tabs.index( li );
13112				} )
13113			) ).sort();
13114		}
13115
13116		// Check for length avoids error when initializing empty list
13117		if ( this.options.active !== false && this.anchors.length ) {
13118			this.active = this._findActive( options.active );
13119		} else {
13120			this.active = $();
13121		}
13122
13123		this._refresh();
13124
13125		if ( this.active.length ) {
13126			this.load( options.active );
13127		}
13128	},
13129
13130	_initialActive: function() {
13131		var active = this.options.active,
13132			collapsible = this.options.collapsible,
13133			locationHash = location.hash.substring( 1 );
13134
13135		if ( active === null ) {
13136
13137			// check the fragment identifier in the URL
13138			if ( locationHash ) {
13139				this.tabs.each( function( i, tab ) {
13140					if ( $( tab ).attr( "aria-controls" ) === locationHash ) {
13141						active = i;
13142						return false;
13143					}
13144				} );
13145			}
13146
13147			// Check for a tab marked active via a class
13148			if ( active === null ) {
13149				active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) );
13150			}
13151
13152			// No active tab, set to false
13153			if ( active === null || active === -1 ) {
13154				active = this.tabs.length ? 0 : false;
13155			}
13156		}
13157
13158		// Handle numbers: negative, out of range
13159		if ( active !== false ) {
13160			active = this.tabs.index( this.tabs.eq( active ) );
13161			if ( active === -1 ) {
13162				active = collapsible ? false : 0;
13163			}
13164		}
13165
13166		// Don't allow collapsible: false and active: false
13167		if ( !collapsible && active === false && this.anchors.length ) {
13168			active = 0;
13169		}
13170
13171		return active;
13172	},
13173
13174	_getCreateEventData: function() {
13175		return {
13176			tab: this.active,
13177			panel: !this.active.length ? $() : this._getPanelForTab( this.active )
13178		};
13179	},
13180
13181	_tabKeydown: function( event ) {
13182		var focusedTab = $( $.ui.safeActiveElement( this.document[ 0 ] ) ).closest( "li" ),
13183			selectedIndex = this.tabs.index( focusedTab ),
13184			goingForward = true;
13185
13186		if ( this._handlePageNav( event ) ) {
13187			return;
13188		}
13189
13190		switch ( event.keyCode ) {
13191		case $.ui.keyCode.RIGHT:
13192		case $.ui.keyCode.DOWN:
13193			selectedIndex++;
13194			break;
13195		case $.ui.keyCode.UP:
13196		case $.ui.keyCode.LEFT:
13197			goingForward = false;
13198			selectedIndex--;
13199			break;
13200		case $.ui.keyCode.END:
13201			selectedIndex = this.anchors.length - 1;
13202			break;
13203		case $.ui.keyCode.HOME:
13204			selectedIndex = 0;
13205			break;
13206		case $.ui.keyCode.SPACE:
13207
13208			// Activate only, no collapsing
13209			event.preventDefault();
13210			clearTimeout( this.activating );
13211			this._activate( selectedIndex );
13212			return;
13213		case $.ui.keyCode.ENTER:
13214
13215			// Toggle (cancel delayed activation, allow collapsing)
13216			event.preventDefault();
13217			clearTimeout( this.activating );
13218
13219			// Determine if we should collapse or activate
13220			this._activate( selectedIndex === this.options.active ? false : selectedIndex );
13221			return;
13222		default:
13223			return;
13224		}
13225
13226		// Focus the appropriate tab, based on which key was pressed
13227		event.preventDefault();
13228		clearTimeout( this.activating );
13229		selectedIndex = this._focusNextTab( selectedIndex, goingForward );
13230
13231		// Navigating with control/command key will prevent automatic activation
13232		if ( !event.ctrlKey && !event.metaKey ) {
13233
13234			// Update aria-selected immediately so that AT think the tab is already selected.
13235			// Otherwise AT may confuse the user by stating that they need to activate the tab,
13236			// but the tab will already be activated by the time the announcement finishes.
13237			focusedTab.attr( "aria-selected", "false" );
13238			this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" );
13239
13240			this.activating = this._delay( function() {
13241				this.option( "active", selectedIndex );
13242			}, this.delay );
13243		}
13244	},
13245
13246	_panelKeydown: function( event ) {
13247		if ( this._handlePageNav( event ) ) {
13248			return;
13249		}
13250
13251		// Ctrl+up moves focus to the current tab
13252		if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {
13253			event.preventDefault();
13254			this.active.trigger( "focus" );
13255		}
13256	},
13257
13258	// Alt+page up/down moves focus to the previous/next tab (and activates)
13259	_handlePageNav: function( event ) {
13260		if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {
13261			this._activate( this._focusNextTab( this.options.active - 1, false ) );
13262			return true;
13263		}
13264		if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {
13265			this._activate( this._focusNextTab( this.options.active + 1, true ) );
13266			return true;
13267		}
13268	},
13269
13270	_findNextTab: function( index, goingForward ) {
13271		var lastTabIndex = this.tabs.length - 1;
13272
13273		function constrain() {
13274			if ( index > lastTabIndex ) {
13275				index = 0;
13276			}
13277			if ( index < 0 ) {
13278				index = lastTabIndex;
13279			}
13280			return index;
13281		}
13282
13283		while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {
13284			index = goingForward ? index + 1 : index - 1;
13285		}
13286
13287		return index;
13288	},
13289
13290	_focusNextTab: function( index, goingForward ) {
13291		index = this._findNextTab( index, goingForward );
13292		this.tabs.eq( index ).trigger( "focus" );
13293		return index;
13294	},
13295
13296	_setOption: function( key, value ) {
13297		if ( key === "active" ) {
13298
13299			// _activate() will handle invalid values and update this.options
13300			this._activate( value );
13301			return;
13302		}
13303
13304		this._super( key, value );
13305
13306		if ( key === "collapsible" ) {
13307			this._toggleClass( "ui-tabs-collapsible", null, value );
13308
13309			// Setting collapsible: false while collapsed; open first panel
13310			if ( !value && this.options.active === false ) {
13311				this._activate( 0 );
13312			}
13313		}
13314
13315		if ( key === "event" ) {
13316			this._setupEvents( value );
13317		}
13318
13319		if ( key === "heightStyle" ) {
13320			this._setupHeightStyle( value );
13321		}
13322	},
13323
13324	_sanitizeSelector: function( hash ) {
13325		return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : "";
13326	},
13327
13328	refresh: function() {
13329		var options = this.options,
13330			lis = this.tablist.children( ":has(a[href])" );
13331
13332		// Get disabled tabs from class attribute from HTML
13333		// this will get converted to a boolean if needed in _refresh()
13334		options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) {
13335			return lis.index( tab );
13336		} );
13337
13338		this._processTabs();
13339
13340		// Was collapsed or no tabs
13341		if ( options.active === false || !this.anchors.length ) {
13342			options.active = false;
13343			this.active = $();
13344
13345		// was active, but active tab is gone
13346		} else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {
13347
13348			// all remaining tabs are disabled
13349			if ( this.tabs.length === options.disabled.length ) {
13350				options.active = false;
13351				this.active = $();
13352
13353			// activate previous tab
13354			} else {
13355				this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );
13356			}
13357
13358		// was active, active tab still exists
13359		} else {
13360
13361			// make sure active index is correct
13362			options.active = this.tabs.index( this.active );
13363		}
13364
13365		this._refresh();
13366	},
13367
13368	_refresh: function() {
13369		this._setOptionDisabled( this.options.disabled );
13370		this._setupEvents( this.options.event );
13371		this._setupHeightStyle( this.options.heightStyle );
13372
13373		this.tabs.not( this.active ).attr( {
13374			"aria-selected": "false",
13375			"aria-expanded": "false",
13376			tabIndex: -1
13377		} );
13378		this.panels.not( this._getPanelForTab( this.active ) )
13379			.hide()
13380			.attr( {
13381				"aria-hidden": "true"
13382			} );
13383
13384		// Make sure one tab is in the tab order
13385		if ( !this.active.length ) {
13386			this.tabs.eq( 0 ).attr( "tabIndex", 0 );
13387		} else {
13388			this.active
13389				.attr( {
13390					"aria-selected": "true",
13391					"aria-expanded": "true",
13392					tabIndex: 0
13393				} );
13394			this._addClass( this.active, "ui-tabs-active", "ui-state-active" );
13395			this._getPanelForTab( this.active )
13396				.show()
13397				.attr( {
13398					"aria-hidden": "false"
13399				} );
13400		}
13401	},
13402
13403	_processTabs: function() {
13404		var that = this,
13405			prevTabs = this.tabs,
13406			prevAnchors = this.anchors,
13407			prevPanels = this.panels;
13408
13409		this.tablist = this._getList().attr( "role", "tablist" );
13410		this._addClass( this.tablist, "ui-tabs-nav",
13411			"ui-helper-reset ui-helper-clearfix ui-widget-header" );
13412
13413		// Prevent users from focusing disabled tabs via click
13414		this.tablist
13415			.on( "mousedown" + this.eventNamespace, "> li", function( event ) {
13416				if ( $( this ).is( ".ui-state-disabled" ) ) {
13417					event.preventDefault();
13418				}
13419			} )
13420
13421			// Support: IE <9
13422			// Preventing the default action in mousedown doesn't prevent IE
13423			// from focusing the element, so if the anchor gets focused, blur.
13424			// We don't have to worry about focusing the previously focused
13425			// element since clicking on a non-focusable element should focus
13426			// the body anyway.
13427			.on( "focus" + this.eventNamespace, ".ui-tabs-anchor", function() {
13428				if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) {
13429					this.blur();
13430				}
13431			} );
13432
13433		this.tabs = this.tablist.find( "> li:has(a[href])" )
13434			.attr( {
13435				role: "tab",
13436				tabIndex: -1
13437			} );
13438		this._addClass( this.tabs, "ui-tabs-tab", "ui-state-default" );
13439
13440		this.anchors = this.tabs.map( function() {
13441			return $( "a", this )[ 0 ];
13442		} )
13443			.attr( {
13444				role: "presentation",
13445				tabIndex: -1
13446			} );
13447		this._addClass( this.anchors, "ui-tabs-anchor" );
13448
13449		this.panels = $();
13450
13451		this.anchors.each( function( i, anchor ) {
13452			var selector, panel, panelId,
13453				anchorId = $( anchor ).uniqueId().attr( "id" ),
13454				tab = $( anchor ).closest( "li" ),
13455				originalAriaControls = tab.attr( "aria-controls" );
13456
13457			// Inline tab
13458			if ( that._isLocal( anchor ) ) {
13459				selector = anchor.hash;
13460				panelId = selector.substring( 1 );
13461				panel = that.element.find( that._sanitizeSelector( selector ) );
13462
13463			// remote tab
13464			} else {
13465
13466				// If the tab doesn't already have aria-controls,
13467				// generate an id by using a throw-away element
13468				panelId = tab.attr( "aria-controls" ) || $( {} ).uniqueId()[ 0 ].id;
13469				selector = "#" + panelId;
13470				panel = that.element.find( selector );
13471				if ( !panel.length ) {
13472					panel = that._createPanel( panelId );
13473					panel.insertAfter( that.panels[ i - 1 ] || that.tablist );
13474				}
13475				panel.attr( "aria-live", "polite" );
13476			}
13477
13478			if ( panel.length ) {
13479				that.panels = that.panels.add( panel );
13480			}
13481			if ( originalAriaControls ) {
13482				tab.data( "ui-tabs-aria-controls", originalAriaControls );
13483			}
13484			tab.attr( {
13485				"aria-controls": panelId,
13486				"aria-labelledby": anchorId
13487			} );
13488			panel.attr( "aria-labelledby", anchorId );
13489		} );
13490
13491		this.panels.attr( "role", "tabpanel" );
13492		this._addClass( this.panels, "ui-tabs-panel", "ui-widget-content" );
13493
13494		// Avoid memory leaks (#10056)
13495		if ( prevTabs ) {
13496			this._off( prevTabs.not( this.tabs ) );
13497			this._off( prevAnchors.not( this.anchors ) );
13498			this._off( prevPanels.not( this.panels ) );
13499		}
13500	},
13501
13502	// Allow overriding how to find the list for rare usage scenarios (#7715)
13503	_getList: function() {
13504		return this.tablist || this.element.find( "ol, ul" ).eq( 0 );
13505	},
13506
13507	_createPanel: function( id ) {
13508		return $( "<div>" )
13509			.attr( "id", id )
13510			.data( "ui-tabs-destroy", true );
13511	},
13512
13513	_setOptionDisabled: function( disabled ) {
13514		var currentItem, li, i;
13515
13516		if ( $.isArray( disabled ) ) {
13517			if ( !disabled.length ) {
13518				disabled = false;
13519			} else if ( disabled.length === this.anchors.length ) {
13520				disabled = true;
13521			}
13522		}
13523
13524		// Disable tabs
13525		for ( i = 0; ( li = this.tabs[ i ] ); i++ ) {
13526			currentItem = $( li );
13527			if ( disabled === true || $.inArray( i, disabled ) !== -1 ) {
13528				currentItem.attr( "aria-disabled", "true" );
13529				this._addClass( currentItem, null, "ui-state-disabled" );
13530			} else {
13531				currentItem.removeAttr( "aria-disabled" );
13532				this._removeClass( currentItem, null, "ui-state-disabled" );
13533			}
13534		}
13535
13536		this.options.disabled = disabled;
13537
13538		this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null,
13539			disabled === true );
13540	},
13541
13542	_setupEvents: function( event ) {
13543		var events = {};
13544		if ( event ) {
13545			$.each( event.split( " " ), function( index, eventName ) {
13546				events[ eventName ] = "_eventHandler";
13547			} );
13548		}
13549
13550		this._off( this.anchors.add( this.tabs ).add( this.panels ) );
13551
13552		// Always prevent the default action, even when disabled
13553		this._on( true, this.anchors, {
13554			click: function( event ) {
13555				event.preventDefault();
13556			}
13557		} );
13558		this._on( this.anchors, events );
13559		this._on( this.tabs, { keydown: "_tabKeydown" } );
13560		this._on( this.panels, { keydown: "_panelKeydown" } );
13561
13562		this._focusable( this.tabs );
13563		this._hoverable( this.tabs );
13564	},
13565
13566	_setupHeightStyle: function( heightStyle ) {
13567		var maxHeight,
13568			parent = this.element.parent();
13569
13570		if ( heightStyle === "fill" ) {
13571			maxHeight = parent.height();
13572			maxHeight -= this.element.outerHeight() - this.element.height();
13573
13574			this.element.siblings( ":visible" ).each( function() {
13575				var elem = $( this ),
13576					position = elem.css( "position" );
13577
13578				if ( position === "absolute" || position === "fixed" ) {
13579					return;
13580				}
13581				maxHeight -= elem.outerHeight( true );
13582			} );
13583
13584			this.element.children().not( this.panels ).each( function() {
13585				maxHeight -= $( this ).outerHeight( true );
13586			} );
13587
13588			this.panels.each( function() {
13589				$( this ).height( Math.max( 0, maxHeight -
13590					$( this ).innerHeight() + $( this ).height() ) );
13591			} )
13592				.css( "overflow", "auto" );
13593		} else if ( heightStyle === "auto" ) {
13594			maxHeight = 0;
13595			this.panels.each( function() {
13596				maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
13597			} ).height( maxHeight );
13598		}
13599	},
13600
13601	_eventHandler: function( event ) {
13602		var options = this.options,
13603			active = this.active,
13604			anchor = $( event.currentTarget ),
13605			tab = anchor.closest( "li" ),
13606			clickedIsActive = tab[ 0 ] === active[ 0 ],
13607			collapsing = clickedIsActive && options.collapsible,
13608			toShow = collapsing ? $() : this._getPanelForTab( tab ),
13609			toHide = !active.length ? $() : this._getPanelForTab( active ),
13610			eventData = {
13611				oldTab: active,
13612				oldPanel: toHide,
13613				newTab: collapsing ? $() : tab,
13614				newPanel: toShow
13615			};
13616
13617		event.preventDefault();
13618
13619		if ( tab.hasClass( "ui-state-disabled" ) ||
13620
13621				// tab is already loading
13622				tab.hasClass( "ui-tabs-loading" ) ||
13623
13624				// can't switch durning an animation
13625				this.running ||
13626
13627				// click on active header, but not collapsible
13628				( clickedIsActive && !options.collapsible ) ||
13629
13630				// allow canceling activation
13631				( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
13632			return;
13633		}
13634
13635		options.active = collapsing ? false : this.tabs.index( tab );
13636
13637		this.active = clickedIsActive ? $() : tab;
13638		if ( this.xhr ) {
13639			this.xhr.abort();
13640		}
13641
13642		if ( !toHide.length && !toShow.length ) {
13643			$.error( "jQuery UI Tabs: Mismatching fragment identifier." );
13644		}
13645
13646		if ( toShow.length ) {
13647			this.load( this.tabs.index( tab ), event );
13648		}
13649		this._toggle( event, eventData );
13650	},
13651
13652	// Handles show/hide for selecting tabs
13653	_toggle: function( event, eventData ) {
13654		var that = this,
13655			toShow = eventData.newPanel,
13656			toHide = eventData.oldPanel;
13657
13658		this.running = true;
13659
13660		function complete() {
13661			that.running = false;
13662			that._trigger( "activate", event, eventData );
13663		}
13664
13665		function show() {
13666			that._addClass( eventData.newTab.closest( "li" ), "ui-tabs-active", "ui-state-active" );
13667
13668			if ( toShow.length && that.options.show ) {
13669				that._show( toShow, that.options.show, complete );
13670			} else {
13671				toShow.show();
13672				complete();
13673			}
13674		}
13675
13676		// Start out by hiding, then showing, then completing
13677		if ( toHide.length && this.options.hide ) {
13678			this._hide( toHide, this.options.hide, function() {
13679				that._removeClass( eventData.oldTab.closest( "li" ),
13680					"ui-tabs-active", "ui-state-active" );
13681				show();
13682			} );
13683		} else {
13684			this._removeClass( eventData.oldTab.closest( "li" ),
13685				"ui-tabs-active", "ui-state-active" );
13686			toHide.hide();
13687			show();
13688		}
13689
13690		toHide.attr( "aria-hidden", "true" );
13691		eventData.oldTab.attr( {
13692			"aria-selected": "false",
13693			"aria-expanded": "false"
13694		} );
13695
13696		// If we're switching tabs, remove the old tab from the tab order.
13697		// If we're opening from collapsed state, remove the previous tab from the tab order.
13698		// If we're collapsing, then keep the collapsing tab in the tab order.
13699		if ( toShow.length && toHide.length ) {
13700			eventData.oldTab.attr( "tabIndex", -1 );
13701		} else if ( toShow.length ) {
13702			this.tabs.filter( function() {
13703				return $( this ).attr( "tabIndex" ) === 0;
13704			} )
13705				.attr( "tabIndex", -1 );
13706		}
13707
13708		toShow.attr( "aria-hidden", "false" );
13709		eventData.newTab.attr( {
13710			"aria-selected": "true",
13711			"aria-expanded": "true",
13712			tabIndex: 0
13713		} );
13714	},
13715
13716	_activate: function( index ) {
13717		var anchor,
13718			active = this._findActive( index );
13719
13720		// Trying to activate the already active panel
13721		if ( active[ 0 ] === this.active[ 0 ] ) {
13722			return;
13723		}
13724
13725		// Trying to collapse, simulate a click on the current active header
13726		if ( !active.length ) {
13727			active = this.active;
13728		}
13729
13730		anchor = active.find( ".ui-tabs-anchor" )[ 0 ];
13731		this._eventHandler( {
13732			target: anchor,
13733			currentTarget: anchor,
13734			preventDefault: $.noop
13735		} );
13736	},
13737
13738	_findActive: function( index ) {
13739		return index === false ? $() : this.tabs.eq( index );
13740	},
13741
13742	_getIndex: function( index ) {
13743
13744		// meta-function to give users option to provide a href string instead of a numerical index.
13745		if ( typeof index === "string" ) {
13746			index = this.anchors.index( this.anchors.filter( "[href$='" +
13747				$.ui.escapeSelector( index ) + "']" ) );
13748		}
13749
13750		return index;
13751	},
13752
13753	_destroy: function() {
13754		if ( this.xhr ) {
13755			this.xhr.abort();
13756		}
13757
13758		this.tablist
13759			.removeAttr( "role" )
13760			.off( this.eventNamespace );
13761
13762		this.anchors
13763			.removeAttr( "role tabIndex" )
13764			.removeUniqueId();
13765
13766		this.tabs.add( this.panels ).each( function() {
13767			if ( $.data( this, "ui-tabs-destroy" ) ) {
13768				$( this ).remove();
13769			} else {
13770				$( this ).removeAttr( "role tabIndex " +
13771					"aria-live aria-busy aria-selected aria-labelledby aria-hidden aria-expanded" );
13772			}
13773		} );
13774
13775		this.tabs.each( function() {
13776			var li = $( this ),
13777				prev = li.data( "ui-tabs-aria-controls" );
13778			if ( prev ) {
13779				li
13780					.attr( "aria-controls", prev )
13781					.removeData( "ui-tabs-aria-controls" );
13782			} else {
13783				li.removeAttr( "aria-controls" );
13784			}
13785		} );
13786
13787		this.panels.show();
13788
13789		if ( this.options.heightStyle !== "content" ) {
13790			this.panels.css( "height", "" );
13791		}
13792	},
13793
13794	enable: function( index ) {
13795		var disabled = this.options.disabled;
13796		if ( disabled === false ) {
13797			return;
13798		}
13799
13800		if ( index === undefined ) {
13801			disabled = false;
13802		} else {
13803			index = this._getIndex( index );
13804			if ( $.isArray( disabled ) ) {
13805				disabled = $.map( disabled, function( num ) {
13806					return num !== index ? num : null;
13807				} );
13808			} else {
13809				disabled = $.map( this.tabs, function( li, num ) {
13810					return num !== index ? num : null;
13811				} );
13812			}
13813		}
13814		this._setOptionDisabled( disabled );
13815	},
13816
13817	disable: function( index ) {
13818		var disabled = this.options.disabled;
13819		if ( disabled === true ) {
13820			return;
13821		}
13822
13823		if ( index === undefined ) {
13824			disabled = true;
13825		} else {
13826			index = this._getIndex( index );
13827			if ( $.inArray( index, disabled ) !== -1 ) {
13828				return;
13829			}
13830			if ( $.isArray( disabled ) ) {
13831				disabled = $.merge( [ index ], disabled ).sort();
13832			} else {
13833				disabled = [ index ];
13834			}
13835		}
13836		this._setOptionDisabled( disabled );
13837	},
13838
13839	load: function( index, event ) {
13840		index = this._getIndex( index );
13841		var that = this,
13842			tab = this.tabs.eq( index ),
13843			anchor = tab.find( ".ui-tabs-anchor" ),
13844			panel = this._getPanelForTab( tab ),
13845			eventData = {
13846				tab: tab,
13847				panel: panel
13848			},
13849			complete = function( jqXHR, status ) {
13850				if ( status === "abort" ) {
13851					that.panels.stop( false, true );
13852				}
13853
13854				that._removeClass( tab, "ui-tabs-loading" );
13855				panel.removeAttr( "aria-busy" );
13856
13857				if ( jqXHR === that.xhr ) {
13858					delete that.xhr;
13859				}
13860			};
13861
13862		// Not remote
13863		if ( this._isLocal( anchor[ 0 ] ) ) {
13864			return;
13865		}
13866
13867		this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );
13868
13869		// Support: jQuery <1.8
13870		// jQuery <1.8 returns false if the request is canceled in beforeSend,
13871		// but as of 1.8, $.ajax() always returns a jqXHR object.
13872		if ( this.xhr && this.xhr.statusText !== "canceled" ) {
13873			this._addClass( tab, "ui-tabs-loading" );
13874			panel.attr( "aria-busy", "true" );
13875
13876			this.xhr
13877				.done( function( response, status, jqXHR ) {
13878
13879					// support: jQuery <1.8
13880					// http://bugs.jquery.com/ticket/11778
13881					setTimeout( function() {
13882						panel.html( response );
13883						that._trigger( "load", event, eventData );
13884
13885						complete( jqXHR, status );
13886					}, 1 );
13887				} )
13888				.fail( function( jqXHR, status ) {
13889
13890					// support: jQuery <1.8
13891					// http://bugs.jquery.com/ticket/11778
13892					setTimeout( function() {
13893						complete( jqXHR, status );
13894					}, 1 );
13895				} );
13896		}
13897	},
13898
13899	_ajaxSettings: function( anchor, event, eventData ) {
13900		var that = this;
13901		return {
13902
13903			// Support: IE <11 only
13904			// Strip any hash that exists to prevent errors with the Ajax request
13905			url: anchor.attr( "href" ).replace( /#.*$/, "" ),
13906			beforeSend: function( jqXHR, settings ) {
13907				return that._trigger( "beforeLoad", event,
13908					$.extend( { jqXHR: jqXHR, ajaxSettings: settings }, eventData ) );
13909			}
13910		};
13911	},
13912
13913	_getPanelForTab: function( tab ) {
13914		var id = $( tab ).attr( "aria-controls" );
13915		return this.element.find( this._sanitizeSelector( "#" + id ) );
13916	}
13917} );
13918
13919// DEPRECATED
13920// TODO: Switch return back to widget declaration at top of file when this is removed
13921if ( $.uiBackCompat !== false ) {
13922
13923	// Backcompat for ui-tab class (now ui-tabs-tab)
13924	$.widget( "ui.tabs", $.ui.tabs, {
13925		_processTabs: function() {
13926			this._superApply( arguments );
13927			this._addClass( this.tabs, "ui-tab" );
13928		}
13929	} );
13930}
13931
13932var widgetsTabs = $.ui.tabs;
13933
13934
13935
13936
13937}));

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.