1/*! jQuery UI - v1.12.1 - 2018-12-06
2* http://jqueryui.com
3* Includes: widget.js, position.js, keycode.js, unique-id.js, widgets/autocomplete.js, widgets/menu.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 Keycode 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: Keycode
1244//>>group: Core
1245//>>description: Provide keycodes as keynames
1246//>>docs: http://api.jqueryui.com/jQuery.ui.keyCode/
1247
1248
1249var keycode = $.ui.keyCode = {
1250	BACKSPACE: 8,
1251	COMMA: 188,
1252	DELETE: 46,
1253	DOWN: 40,
1254	END: 35,
1255	ENTER: 13,
1256	ESCAPE: 27,
1257	HOME: 36,
1258	LEFT: 37,
1259	PAGE_DOWN: 34,
1260	PAGE_UP: 33,
1261	PERIOD: 190,
1262	RIGHT: 39,
1263	SPACE: 32,
1264	TAB: 9,
1265	UP: 38
1266};
1267
1268
1269/*!
1270 * jQuery UI Unique ID 1.12.1
1271 * http://jqueryui.com
1272 *
1273 * Copyright jQuery Foundation and other contributors
1274 * Released under the MIT license.
1275 * http://jquery.org/license
1276 */
1277
1278//>>label: uniqueId
1279//>>group: Core
1280//>>description: Functions to generate and remove uniqueId's
1281//>>docs: http://api.jqueryui.com/uniqueId/
1282
1283
1284
1285var uniqueId = $.fn.extend( {
1286	uniqueId: ( function() {
1287		var uuid = 0;
1288
1289		return function() {
1290			return this.each( function() {
1291				if ( !this.id ) {
1292					this.id = "ui-id-" + ( ++uuid );
1293				}
1294			} );
1295		};
1296	} )(),
1297
1298	removeUniqueId: function() {
1299		return this.each( function() {
1300			if ( /^ui-id-\d+$/.test( this.id ) ) {
1301				$( this ).removeAttr( "id" );
1302			}
1303		} );
1304	}
1305} );
1306
1307
1308
1309var safeActiveElement = $.ui.safeActiveElement = function( document ) {
1310	var activeElement;
1311
1312	// Support: IE 9 only
1313	// IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe>
1314	try {
1315		activeElement = document.activeElement;
1316	} catch ( error ) {
1317		activeElement = document.body;
1318	}
1319
1320	// Support: IE 9 - 11 only
1321	// IE may return null instead of an element
1322	// Interestingly, this only seems to occur when NOT in an iframe
1323	if ( !activeElement ) {
1324		activeElement = document.body;
1325	}
1326
1327	// Support: IE 11 only
1328	// IE11 returns a seemingly empty object in some cases when accessing
1329	// document.activeElement from an <iframe>
1330	if ( !activeElement.nodeName ) {
1331		activeElement = document.body;
1332	}
1333
1334	return activeElement;
1335};
1336
1337
1338/*!
1339 * jQuery UI Menu 1.12.1
1340 * http://jqueryui.com
1341 *
1342 * Copyright jQuery Foundation and other contributors
1343 * Released under the MIT license.
1344 * http://jquery.org/license
1345 */
1346
1347//>>label: Menu
1348//>>group: Widgets
1349//>>description: Creates nestable menus.
1350//>>docs: http://api.jqueryui.com/menu/
1351//>>demos: http://jqueryui.com/menu/
1352//>>css.structure: ../../themes/base/core.css
1353//>>css.structure: ../../themes/base/menu.css
1354//>>css.theme: ../../themes/base/theme.css
1355
1356
1357
1358var widgetsMenu = $.widget( "ui.menu", {
1359	version: "1.12.1",
1360	defaultElement: "<ul>",
1361	delay: 300,
1362	options: {
1363		icons: {
1364			submenu: "ui-icon-caret-1-e"
1365		},
1366		items: "> *",
1367		menus: "ul",
1368		position: {
1369			my: "left top",
1370			at: "right top"
1371		},
1372		role: "menu",
1373
1374		// Callbacks
1375		blur: null,
1376		focus: null,
1377		select: null
1378	},
1379
1380	_create: function() {
1381		this.activeMenu = this.element;
1382
1383		// Flag used to prevent firing of the click handler
1384		// as the event bubbles up through nested menus
1385		this.mouseHandled = false;
1386		this.element
1387			.uniqueId()
1388			.attr( {
1389				role: this.options.role,
1390				tabIndex: 0
1391			} );
1392
1393		this._addClass( "ui-menu", "ui-widget ui-widget-content" );
1394		this._on( {
1395
1396			// Prevent focus from sticking to links inside menu after clicking
1397			// them (focus should always stay on UL during navigation).
1398			"mousedown .ui-menu-item": function( event ) {
1399				event.preventDefault();
1400			},
1401			"click .ui-menu-item": function( event ) {
1402				var target = $( event.target );
1403				var active = $( $.ui.safeActiveElement( this.document[ 0 ] ) );
1404				if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) {
1405					this.select( event );
1406
1407					// Only set the mouseHandled flag if the event will bubble, see #9469.
1408					if ( !event.isPropagationStopped() ) {
1409						this.mouseHandled = true;
1410					}
1411
1412					// Open submenu on click
1413					if ( target.has( ".ui-menu" ).length ) {
1414						this.expand( event );
1415					} else if ( !this.element.is( ":focus" ) &&
1416							active.closest( ".ui-menu" ).length ) {
1417
1418						// Redirect focus to the menu
1419						this.element.trigger( "focus", [ true ] );
1420
1421						// If the active item is on the top level, let it stay active.
1422						// Otherwise, blur the active item since it is no longer visible.
1423						if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) {
1424							clearTimeout( this.timer );
1425						}
1426					}
1427				}
1428			},
1429			"mouseenter .ui-menu-item": function( event ) {
1430
1431				// Ignore mouse events while typeahead is active, see #10458.
1432				// Prevents focusing the wrong item when typeahead causes a scroll while the mouse
1433				// is over an item in the menu
1434				if ( this.previousFilter ) {
1435					return;
1436				}
1437
1438				var actualTarget = $( event.target ).closest( ".ui-menu-item" ),
1439					target = $( event.currentTarget );
1440
1441				// Ignore bubbled events on parent items, see #11641
1442				if ( actualTarget[ 0 ] !== target[ 0 ] ) {
1443					return;
1444				}
1445
1446				// Remove ui-state-active class from siblings of the newly focused menu item
1447				// to avoid a jump caused by adjacent elements both having a class with a border
1448				this._removeClass( target.siblings().children( ".ui-state-active" ),
1449					null, "ui-state-active" );
1450				this.focus( event, target );
1451			},
1452			mouseleave: "collapseAll",
1453			"mouseleave .ui-menu": "collapseAll",
1454			focus: function( event, keepActiveItem ) {
1455
1456				// If there's already an active item, keep it active
1457				// If not, activate the first item
1458				var item = this.active || this.element.find( this.options.items ).eq( 0 );
1459
1460				if ( !keepActiveItem ) {
1461					this.focus( event, item );
1462				}
1463			},
1464			blur: function( event ) {
1465				this._delay( function() {
1466					var notContained = !$.contains(
1467						this.element[ 0 ],
1468						$.ui.safeActiveElement( this.document[ 0 ] )
1469					);
1470					if ( notContained ) {
1471						this.collapseAll( event );
1472					}
1473				} );
1474			},
1475			keydown: "_keydown"
1476		} );
1477
1478		this.refresh();
1479
1480		// Clicks outside of a menu collapse any open menus
1481		this._on( this.document, {
1482			click: function( event ) {
1483				if ( this._closeOnDocumentClick( event ) ) {
1484					this.collapseAll( event );
1485				}
1486
1487				// Reset the mouseHandled flag
1488				this.mouseHandled = false;
1489			}
1490		} );
1491	},
1492
1493	_destroy: function() {
1494		var items = this.element.find( ".ui-menu-item" )
1495				.removeAttr( "role aria-disabled" ),
1496			submenus = items.children( ".ui-menu-item-wrapper" )
1497				.removeUniqueId()
1498				.removeAttr( "tabIndex role aria-haspopup" );
1499
1500		// Destroy (sub)menus
1501		this.element
1502			.removeAttr( "aria-activedescendant" )
1503			.find( ".ui-menu" ).addBack()
1504				.removeAttr( "role aria-labelledby aria-expanded aria-hidden aria-disabled " +
1505					"tabIndex" )
1506				.removeUniqueId()
1507				.show();
1508
1509		submenus.children().each( function() {
1510			var elem = $( this );
1511			if ( elem.data( "ui-menu-submenu-caret" ) ) {
1512				elem.remove();
1513			}
1514		} );
1515	},
1516
1517	_keydown: function( event ) {
1518		var match, prev, character, skip,
1519			preventDefault = true;
1520
1521		switch ( event.keyCode ) {
1522		case $.ui.keyCode.PAGE_UP:
1523			this.previousPage( event );
1524			break;
1525		case $.ui.keyCode.PAGE_DOWN:
1526			this.nextPage( event );
1527			break;
1528		case $.ui.keyCode.HOME:
1529			this._move( "first", "first", event );
1530			break;
1531		case $.ui.keyCode.END:
1532			this._move( "last", "last", event );
1533			break;
1534		case $.ui.keyCode.UP:
1535			this.previous( event );
1536			break;
1537		case $.ui.keyCode.DOWN:
1538			this.next( event );
1539			break;
1540		case $.ui.keyCode.LEFT:
1541			this.collapse( event );
1542			break;
1543		case $.ui.keyCode.RIGHT:
1544			if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
1545				this.expand( event );
1546			}
1547			break;
1548		case $.ui.keyCode.ENTER:
1549		case $.ui.keyCode.SPACE:
1550			this._activate( event );
1551			break;
1552		case $.ui.keyCode.ESCAPE:
1553			this.collapse( event );
1554			break;
1555		default:
1556			preventDefault = false;
1557			prev = this.previousFilter || "";
1558			skip = false;
1559
1560			// Support number pad values
1561			character = event.keyCode >= 96 && event.keyCode <= 105 ?
1562				( event.keyCode - 96 ).toString() : String.fromCharCode( event.keyCode );
1563
1564			clearTimeout( this.filterTimer );
1565
1566			if ( character === prev ) {
1567				skip = true;
1568			} else {
1569				character = prev + character;
1570			}
1571
1572			match = this._filterMenuItems( character );
1573			match = skip && match.index( this.active.next() ) !== -1 ?
1574				this.active.nextAll( ".ui-menu-item" ) :
1575				match;
1576
1577			// If no matches on the current filter, reset to the last character pressed
1578			// to move down the menu to the first item that starts with that character
1579			if ( !match.length ) {
1580				character = String.fromCharCode( event.keyCode );
1581				match = this._filterMenuItems( character );
1582			}
1583
1584			if ( match.length ) {
1585				this.focus( event, match );
1586				this.previousFilter = character;
1587				this.filterTimer = this._delay( function() {
1588					delete this.previousFilter;
1589				}, 1000 );
1590			} else {
1591				delete this.previousFilter;
1592			}
1593		}
1594
1595		if ( preventDefault ) {
1596			event.preventDefault();
1597		}
1598	},
1599
1600	_activate: function( event ) {
1601		if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
1602			if ( this.active.children( "[aria-haspopup='true']" ).length ) {
1603				this.expand( event );
1604			} else {
1605				this.select( event );
1606			}
1607		}
1608	},
1609
1610	refresh: function() {
1611		var menus, items, newSubmenus, newItems, newWrappers,
1612			that = this,
1613			icon = this.options.icons.submenu,
1614			submenus = this.element.find( this.options.menus );
1615
1616		this._toggleClass( "ui-menu-icons", null, !!this.element.find( ".ui-icon" ).length );
1617
1618		// Initialize nested menus
1619		newSubmenus = submenus.filter( ":not(.ui-menu)" )
1620			.hide()
1621			.attr( {
1622				role: this.options.role,
1623				"aria-hidden": "true",
1624				"aria-expanded": "false"
1625			} )
1626			.each( function() {
1627				var menu = $( this ),
1628					item = menu.prev(),
1629					submenuCaret = $( "<span>" ).data( "ui-menu-submenu-caret", true );
1630
1631				that._addClass( submenuCaret, "ui-menu-icon", "ui-icon " + icon );
1632				item
1633					.attr( "aria-haspopup", "true" )
1634					.prepend( submenuCaret );
1635				menu.attr( "aria-labelledby", item.attr( "id" ) );
1636			} );
1637
1638		this._addClass( newSubmenus, "ui-menu", "ui-widget ui-widget-content ui-front" );
1639
1640		menus = submenus.add( this.element );
1641		items = menus.find( this.options.items );
1642
1643		// Initialize menu-items containing spaces and/or dashes only as dividers
1644		items.not( ".ui-menu-item" ).each( function() {
1645			var item = $( this );
1646			if ( that._isDivider( item ) ) {
1647				that._addClass( item, "ui-menu-divider", "ui-widget-content" );
1648			}
1649		} );
1650
1651		// Don't refresh list items that are already adapted
1652		newItems = items.not( ".ui-menu-item, .ui-menu-divider" );
1653		newWrappers = newItems.children()
1654			.not( ".ui-menu" )
1655				.uniqueId()
1656				.attr( {
1657					tabIndex: -1,
1658					role: this._itemRole()
1659				} );
1660		this._addClass( newItems, "ui-menu-item" )
1661			._addClass( newWrappers, "ui-menu-item-wrapper" );
1662
1663		// Add aria-disabled attribute to any disabled menu item
1664		items.filter( ".ui-state-disabled" ).attr( "aria-disabled", "true" );
1665
1666		// If the active item has been removed, blur the menu
1667		if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
1668			this.blur();
1669		}
1670	},
1671
1672	_itemRole: function() {
1673		return {
1674			menu: "menuitem",
1675			listbox: "option"
1676		}[ this.options.role ];
1677	},
1678
1679	_setOption: function( key, value ) {
1680		if ( key === "icons" ) {
1681			var icons = this.element.find( ".ui-menu-icon" );
1682			this._removeClass( icons, null, this.options.icons.submenu )
1683				._addClass( icons, null, value.submenu );
1684		}
1685		this._super( key, value );
1686	},
1687
1688	_setOptionDisabled: function( value ) {
1689		this._super( value );
1690
1691		this.element.attr( "aria-disabled", String( value ) );
1692		this._toggleClass( null, "ui-state-disabled", !!value );
1693	},
1694
1695	focus: function( event, item ) {
1696		var nested, focused, activeParent;
1697		this.blur( event, event && event.type === "focus" );
1698
1699		this._scrollIntoView( item );
1700
1701		this.active = item.first();
1702
1703		focused = this.active.children( ".ui-menu-item-wrapper" );
1704		this._addClass( focused, null, "ui-state-active" );
1705
1706		// Only update aria-activedescendant if there's a role
1707		// otherwise we assume focus is managed elsewhere
1708		if ( this.options.role ) {
1709			this.element.attr( "aria-activedescendant", focused.attr( "id" ) );
1710		}
1711
1712		// Highlight active parent menu item, if any
1713		activeParent = this.active
1714			.parent()
1715				.closest( ".ui-menu-item" )
1716					.children( ".ui-menu-item-wrapper" );
1717		this._addClass( activeParent, null, "ui-state-active" );
1718
1719		if ( event && event.type === "keydown" ) {
1720			this._close();
1721		} else {
1722			this.timer = this._delay( function() {
1723				this._close();
1724			}, this.delay );
1725		}
1726
1727		nested = item.children( ".ui-menu" );
1728		if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) {
1729			this._startOpening( nested );
1730		}
1731		this.activeMenu = item.parent();
1732
1733		this._trigger( "focus", event, { item: item } );
1734	},
1735
1736	_scrollIntoView: function( item ) {
1737		var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
1738		if ( this._hasScroll() ) {
1739			borderTop = parseFloat( $.css( this.activeMenu[ 0 ], "borderTopWidth" ) ) || 0;
1740			paddingTop = parseFloat( $.css( this.activeMenu[ 0 ], "paddingTop" ) ) || 0;
1741			offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
1742			scroll = this.activeMenu.scrollTop();
1743			elementHeight = this.activeMenu.height();
1744			itemHeight = item.outerHeight();
1745
1746			if ( offset < 0 ) {
1747				this.activeMenu.scrollTop( scroll + offset );
1748			} else if ( offset + itemHeight > elementHeight ) {
1749				this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );
1750			}
1751		}
1752	},
1753
1754	blur: function( event, fromFocus ) {
1755		if ( !fromFocus ) {
1756			clearTimeout( this.timer );
1757		}
1758
1759		if ( !this.active ) {
1760			return;
1761		}
1762
1763		this._removeClass( this.active.children( ".ui-menu-item-wrapper" ),
1764			null, "ui-state-active" );
1765
1766		this._trigger( "blur", event, { item: this.active } );
1767		this.active = null;
1768	},
1769
1770	_startOpening: function( submenu ) {
1771		clearTimeout( this.timer );
1772
1773		// Don't open if already open fixes a Firefox bug that caused a .5 pixel
1774		// shift in the submenu position when mousing over the caret icon
1775		if ( submenu.attr( "aria-hidden" ) !== "true" ) {
1776			return;
1777		}
1778
1779		this.timer = this._delay( function() {
1780			this._close();
1781			this._open( submenu );
1782		}, this.delay );
1783	},
1784
1785	_open: function( submenu ) {
1786		var position = $.extend( {
1787			of: this.active
1788		}, this.options.position );
1789
1790		clearTimeout( this.timer );
1791		this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) )
1792			.hide()
1793			.attr( "aria-hidden", "true" );
1794
1795		submenu
1796			.show()
1797			.removeAttr( "aria-hidden" )
1798			.attr( "aria-expanded", "true" )
1799			.position( position );
1800	},
1801
1802	collapseAll: function( event, all ) {
1803		clearTimeout( this.timer );
1804		this.timer = this._delay( function() {
1805
1806			// If we were passed an event, look for the submenu that contains the event
1807			var currentMenu = all ? this.element :
1808				$( event && event.target ).closest( this.element.find( ".ui-menu" ) );
1809
1810			// If we found no valid submenu ancestor, use the main menu to close all
1811			// sub menus anyway
1812			if ( !currentMenu.length ) {
1813				currentMenu = this.element;
1814			}
1815
1816			this._close( currentMenu );
1817
1818			this.blur( event );
1819
1820			// Work around active item staying active after menu is blurred
1821			this._removeClass( currentMenu.find( ".ui-state-active" ), null, "ui-state-active" );
1822
1823			this.activeMenu = currentMenu;
1824		}, this.delay );
1825	},
1826
1827	// With no arguments, closes the currently active menu - if nothing is active
1828	// it closes all menus.  If passed an argument, it will search for menus BELOW
1829	_close: function( startMenu ) {
1830		if ( !startMenu ) {
1831			startMenu = this.active ? this.active.parent() : this.element;
1832		}
1833
1834		startMenu.find( ".ui-menu" )
1835			.hide()
1836			.attr( "aria-hidden", "true" )
1837			.attr( "aria-expanded", "false" );
1838	},
1839
1840	_closeOnDocumentClick: function( event ) {
1841		return !$( event.target ).closest( ".ui-menu" ).length;
1842	},
1843
1844	_isDivider: function( item ) {
1845
1846		// Match hyphen, em dash, en dash
1847		return !/[^\-\u2014\u2013\s]/.test( item.text() );
1848	},
1849
1850	collapse: function( event ) {
1851		var newItem = this.active &&
1852			this.active.parent().closest( ".ui-menu-item", this.element );
1853		if ( newItem && newItem.length ) {
1854			this._close();
1855			this.focus( event, newItem );
1856		}
1857	},
1858
1859	expand: function( event ) {
1860		var newItem = this.active &&
1861			this.active
1862				.children( ".ui-menu " )
1863					.find( this.options.items )
1864						.first();
1865
1866		if ( newItem && newItem.length ) {
1867			this._open( newItem.parent() );
1868
1869			// Delay so Firefox will not hide activedescendant change in expanding submenu from AT
1870			this._delay( function() {
1871				this.focus( event, newItem );
1872			} );
1873		}
1874	},
1875
1876	next: function( event ) {
1877		this._move( "next", "first", event );
1878	},
1879
1880	previous: function( event ) {
1881		this._move( "prev", "last", event );
1882	},
1883
1884	isFirstItem: function() {
1885		return this.active && !this.active.prevAll( ".ui-menu-item" ).length;
1886	},
1887
1888	isLastItem: function() {
1889		return this.active && !this.active.nextAll( ".ui-menu-item" ).length;
1890	},
1891
1892	_move: function( direction, filter, event ) {
1893		var next;
1894		if ( this.active ) {
1895			if ( direction === "first" || direction === "last" ) {
1896				next = this.active
1897					[ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )
1898					.eq( -1 );
1899			} else {
1900				next = this.active
1901					[ direction + "All" ]( ".ui-menu-item" )
1902					.eq( 0 );
1903			}
1904		}
1905		if ( !next || !next.length || !this.active ) {
1906			next = this.activeMenu.find( this.options.items )[ filter ]();
1907		}
1908
1909		this.focus( event, next );
1910	},
1911
1912	nextPage: function( event ) {
1913		var item, base, height;
1914
1915		if ( !this.active ) {
1916			this.next( event );
1917			return;
1918		}
1919		if ( this.isLastItem() ) {
1920			return;
1921		}
1922		if ( this._hasScroll() ) {
1923			base = this.active.offset().top;
1924			height = this.element.height();
1925			this.active.nextAll( ".ui-menu-item" ).each( function() {
1926				item = $( this );
1927				return item.offset().top - base - height < 0;
1928			} );
1929
1930			this.focus( event, item );
1931		} else {
1932			this.focus( event, this.activeMenu.find( this.options.items )
1933				[ !this.active ? "first" : "last" ]() );
1934		}
1935	},
1936
1937	previousPage: function( event ) {
1938		var item, base, height;
1939		if ( !this.active ) {
1940			this.next( event );
1941			return;
1942		}
1943		if ( this.isFirstItem() ) {
1944			return;
1945		}
1946		if ( this._hasScroll() ) {
1947			base = this.active.offset().top;
1948			height = this.element.height();
1949			this.active.prevAll( ".ui-menu-item" ).each( function() {
1950				item = $( this );
1951				return item.offset().top - base + height > 0;
1952			} );
1953
1954			this.focus( event, item );
1955		} else {
1956			this.focus( event, this.activeMenu.find( this.options.items ).first() );
1957		}
1958	},
1959
1960	_hasScroll: function() {
1961		return this.element.outerHeight() < this.element.prop( "scrollHeight" );
1962	},
1963
1964	select: function( event ) {
1965
1966		// TODO: It should never be possible to not have an active item at this
1967		// point, but the tests don't trigger mouseenter before click.
1968		this.active = this.active || $( event.target ).closest( ".ui-menu-item" );
1969		var ui = { item: this.active };
1970		if ( !this.active.has( ".ui-menu" ).length ) {
1971			this.collapseAll( event, true );
1972		}
1973		this._trigger( "select", event, ui );
1974	},
1975
1976	_filterMenuItems: function( character ) {
1977		var escapedCharacter = character.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ),
1978			regex = new RegExp( "^" + escapedCharacter, "i" );
1979
1980		return this.activeMenu
1981			.find( this.options.items )
1982
1983				// Only match on items, not dividers or other content (#10571)
1984				.filter( ".ui-menu-item" )
1985					.filter( function() {
1986						return regex.test(
1987							$.trim( $( this ).children( ".ui-menu-item-wrapper" ).text() ) );
1988					} );
1989	}
1990} );
1991
1992
1993/*!
1994 * jQuery UI Autocomplete 1.12.1
1995 * http://jqueryui.com
1996 *
1997 * Copyright jQuery Foundation and other contributors
1998 * Released under the MIT license.
1999 * http://jquery.org/license
2000 */
2001
2002//>>label: Autocomplete
2003//>>group: Widgets
2004//>>description: Lists suggested words as the user is typing.
2005//>>docs: http://api.jqueryui.com/autocomplete/
2006//>>demos: http://jqueryui.com/autocomplete/
2007//>>css.structure: ../../themes/base/core.css
2008//>>css.structure: ../../themes/base/autocomplete.css
2009//>>css.theme: ../../themes/base/theme.css
2010
2011
2012
2013$.widget( "ui.autocomplete", {
2014	version: "1.12.1",
2015	defaultElement: "<input>",
2016	options: {
2017		appendTo: null,
2018		autoFocus: false,
2019		delay: 300,
2020		minLength: 1,
2021		position: {
2022			my: "left top",
2023			at: "left bottom",
2024			collision: "none"
2025		},
2026		source: null,
2027
2028		// Callbacks
2029		change: null,
2030		close: null,
2031		focus: null,
2032		open: null,
2033		response: null,
2034		search: null,
2035		select: null
2036	},
2037
2038	requestIndex: 0,
2039	pending: 0,
2040
2041	_create: function() {
2042
2043		// Some browsers only repeat keydown events, not keypress events,
2044		// so we use the suppressKeyPress flag to determine if we've already
2045		// handled the keydown event. #7269
2046		// Unfortunately the code for & in keypress is the same as the up arrow,
2047		// so we use the suppressKeyPressRepeat flag to avoid handling keypress
2048		// events when we know the keydown event was used to modify the
2049		// search term. #7799
2050		var suppressKeyPress, suppressKeyPressRepeat, suppressInput,
2051			nodeName = this.element[ 0 ].nodeName.toLowerCase(),
2052			isTextarea = nodeName === "textarea",
2053			isInput = nodeName === "input";
2054
2055		// Textareas are always multi-line
2056		// Inputs are always single-line, even if inside a contentEditable element
2057		// IE also treats inputs as contentEditable
2058		// All other element types are determined by whether or not they're contentEditable
2059		this.isMultiLine = isTextarea || !isInput && this._isContentEditable( this.element );
2060
2061		this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ];
2062		this.isNewMenu = true;
2063
2064		this._addClass( "ui-autocomplete-input" );
2065		this.element.attr( "autocomplete", "off" );
2066
2067		this._on( this.element, {
2068			keydown: function( event ) {
2069				if ( this.element.prop( "readOnly" ) ) {
2070					suppressKeyPress = true;
2071					suppressInput = true;
2072					suppressKeyPressRepeat = true;
2073					return;
2074				}
2075
2076				suppressKeyPress = false;
2077				suppressInput = false;
2078				suppressKeyPressRepeat = false;
2079				var keyCode = $.ui.keyCode;
2080				switch ( event.keyCode ) {
2081				case keyCode.PAGE_UP:
2082					suppressKeyPress = true;
2083					this._move( "previousPage", event );
2084					break;
2085				case keyCode.PAGE_DOWN:
2086					suppressKeyPress = true;
2087					this._move( "nextPage", event );
2088					break;
2089				case keyCode.UP:
2090					suppressKeyPress = true;
2091					this._keyEvent( "previous", event );
2092					break;
2093				case keyCode.DOWN:
2094					suppressKeyPress = true;
2095					this._keyEvent( "next", event );
2096					break;
2097				case keyCode.ENTER:
2098
2099					// when menu is open and has focus
2100					if ( this.menu.active ) {
2101
2102						// #6055 - Opera still allows the keypress to occur
2103						// which causes forms to submit
2104						suppressKeyPress = true;
2105						event.preventDefault();
2106						this.menu.select( event );
2107					}
2108					break;
2109				case keyCode.TAB:
2110					if ( this.menu.active ) {
2111						this.menu.select( event );
2112					}
2113					break;
2114				case keyCode.ESCAPE:
2115					if ( this.menu.element.is( ":visible" ) ) {
2116						if ( !this.isMultiLine ) {
2117							this._value( this.term );
2118						}
2119						this.close( event );
2120
2121						// Different browsers have different default behavior for escape
2122						// Single press can mean undo or clear
2123						// Double press in IE means clear the whole form
2124						event.preventDefault();
2125					}
2126					break;
2127				default:
2128					suppressKeyPressRepeat = true;
2129
2130					// search timeout should be triggered before the input value is changed
2131					this._searchTimeout( event );
2132					break;
2133				}
2134			},
2135			keypress: function( event ) {
2136				if ( suppressKeyPress ) {
2137					suppressKeyPress = false;
2138					if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
2139						event.preventDefault();
2140					}
2141					return;
2142				}
2143				if ( suppressKeyPressRepeat ) {
2144					return;
2145				}
2146
2147				// Replicate some key handlers to allow them to repeat in Firefox and Opera
2148				var keyCode = $.ui.keyCode;
2149				switch ( event.keyCode ) {
2150				case keyCode.PAGE_UP:
2151					this._move( "previousPage", event );
2152					break;
2153				case keyCode.PAGE_DOWN:
2154					this._move( "nextPage", event );
2155					break;
2156				case keyCode.UP:
2157					this._keyEvent( "previous", event );
2158					break;
2159				case keyCode.DOWN:
2160					this._keyEvent( "next", event );
2161					break;
2162				}
2163			},
2164			input: function( event ) {
2165				if ( suppressInput ) {
2166					suppressInput = false;
2167					event.preventDefault();
2168					return;
2169				}
2170				this._searchTimeout( event );
2171			},
2172			focus: function() {
2173				this.selectedItem = null;
2174				this.previous = this._value();
2175			},
2176			blur: function( event ) {
2177				if ( this.cancelBlur ) {
2178					delete this.cancelBlur;
2179					return;
2180				}
2181
2182				clearTimeout( this.searching );
2183				this.close( event );
2184				this._change( event );
2185			}
2186		} );
2187
2188		this._initSource();
2189		this.menu = $( "<ul>" )
2190			.appendTo( this._appendTo() )
2191			.menu( {
2192
2193				// disable ARIA support, the live region takes care of that
2194				role: null
2195			} )
2196			.hide()
2197			.menu( "instance" );
2198
2199		this._addClass( this.menu.element, "ui-autocomplete", "ui-front" );
2200		this._on( this.menu.element, {
2201			mousedown: function( event ) {
2202
2203				// prevent moving focus out of the text field
2204				event.preventDefault();
2205
2206				// IE doesn't prevent moving focus even with event.preventDefault()
2207				// so we set a flag to know when we should ignore the blur event
2208				this.cancelBlur = true;
2209				this._delay( function() {
2210					delete this.cancelBlur;
2211
2212					// Support: IE 8 only
2213					// Right clicking a menu item or selecting text from the menu items will
2214					// result in focus moving out of the input. However, we've already received
2215					// and ignored the blur event because of the cancelBlur flag set above. So
2216					// we restore focus to ensure that the menu closes properly based on the user's
2217					// next actions.
2218					if ( this.element[ 0 ] !== $.ui.safeActiveElement( this.document[ 0 ] ) ) {
2219						this.element.trigger( "focus" );
2220					}
2221				} );
2222			},
2223			menufocus: function( event, ui ) {
2224				var label, item;
2225
2226				// support: Firefox
2227				// Prevent accidental activation of menu items in Firefox (#7024 #9118)
2228				if ( this.isNewMenu ) {
2229					this.isNewMenu = false;
2230					if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {
2231						this.menu.blur();
2232
2233						this.document.one( "mousemove", function() {
2234							$( event.target ).trigger( event.originalEvent );
2235						} );
2236
2237						return;
2238					}
2239				}
2240
2241				item = ui.item.data( "ui-autocomplete-item" );
2242				if ( false !== this._trigger( "focus", event, { item: item } ) ) {
2243
2244					// use value to match what will end up in the input, if it was a key event
2245					if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
2246						this._value( item.value );
2247					}
2248				}
2249
2250				// Announce the value in the liveRegion
2251				label = ui.item.attr( "aria-label" ) || item.value;
2252				if ( label && $.trim( label ).length ) {
2253					this.liveRegion.children().hide();
2254					$( "<div>" ).text( label ).appendTo( this.liveRegion );
2255				}
2256			},
2257			menuselect: function( event, ui ) {
2258				var item = ui.item.data( "ui-autocomplete-item" ),
2259					previous = this.previous;
2260
2261				// Only trigger when focus was lost (click on menu)
2262				if ( this.element[ 0 ] !== $.ui.safeActiveElement( this.document[ 0 ] ) ) {
2263					this.element.trigger( "focus" );
2264					this.previous = previous;
2265
2266					// #6109 - IE triggers two focus events and the second
2267					// is asynchronous, so we need to reset the previous
2268					// term synchronously and asynchronously :-(
2269					this._delay( function() {
2270						this.previous = previous;
2271						this.selectedItem = item;
2272					} );
2273				}
2274
2275				if ( false !== this._trigger( "select", event, { item: item } ) ) {
2276					this._value( item.value );
2277				}
2278
2279				// reset the term after the select event
2280				// this allows custom select handling to work properly
2281				this.term = this._value();
2282
2283				this.close( event );
2284				this.selectedItem = item;
2285			}
2286		} );
2287
2288		this.liveRegion = $( "<div>", {
2289			role: "status",
2290			"aria-live": "assertive",
2291			"aria-relevant": "additions"
2292		} )
2293			.appendTo( this.document[ 0 ].body );
2294
2295		this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" );
2296
2297		// Turning off autocomplete prevents the browser from remembering the
2298		// value when navigating through history, so we re-enable autocomplete
2299		// if the page is unloaded before the widget is destroyed. #7790
2300		this._on( this.window, {
2301			beforeunload: function() {
2302				this.element.removeAttr( "autocomplete" );
2303			}
2304		} );
2305	},
2306
2307	_destroy: function() {
2308		clearTimeout( this.searching );
2309		this.element.removeAttr( "autocomplete" );
2310		this.menu.element.remove();
2311		this.liveRegion.remove();
2312	},
2313
2314	_setOption: function( key, value ) {
2315		this._super( key, value );
2316		if ( key === "source" ) {
2317			this._initSource();
2318		}
2319		if ( key === "appendTo" ) {
2320			this.menu.element.appendTo( this._appendTo() );
2321		}
2322		if ( key === "disabled" && value && this.xhr ) {
2323			this.xhr.abort();
2324		}
2325	},
2326
2327	_isEventTargetInWidget: function( event ) {
2328		var menuElement = this.menu.element[ 0 ];
2329
2330		return event.target === this.element[ 0 ] ||
2331			event.target === menuElement ||
2332			$.contains( menuElement, event.target );
2333	},
2334
2335	_closeOnClickOutside: function( event ) {
2336		if ( !this._isEventTargetInWidget( event ) ) {
2337			this.close();
2338		}
2339	},
2340
2341	_appendTo: function() {
2342		var element = this.options.appendTo;
2343
2344		if ( element ) {
2345			element = element.jquery || element.nodeType ?
2346				$( element ) :
2347				this.document.find( element ).eq( 0 );
2348		}
2349
2350		if ( !element || !element[ 0 ] ) {
2351			element = this.element.closest( ".ui-front, dialog" );
2352		}
2353
2354		if ( !element.length ) {
2355			element = this.document[ 0 ].body;
2356		}
2357
2358		return element;
2359	},
2360
2361	_initSource: function() {
2362		var array, url,
2363			that = this;
2364		if ( $.isArray( this.options.source ) ) {
2365			array = this.options.source;
2366			this.source = function( request, response ) {
2367				response( $.ui.autocomplete.filter( array, request.term ) );
2368			};
2369		} else if ( typeof this.options.source === "string" ) {
2370			url = this.options.source;
2371			this.source = function( request, response ) {
2372				if ( that.xhr ) {
2373					that.xhr.abort();
2374				}
2375				that.xhr = $.ajax( {
2376					url: url,
2377					data: request,
2378					dataType: "json",
2379					success: function( data ) {
2380						response( data );
2381					},
2382					error: function() {
2383						response( [] );
2384					}
2385				} );
2386			};
2387		} else {
2388			this.source = this.options.source;
2389		}
2390	},
2391
2392	_searchTimeout: function( event ) {
2393		clearTimeout( this.searching );
2394		this.searching = this._delay( function() {
2395
2396			// Search if the value has changed, or if the user retypes the same value (see #7434)
2397			var equalValues = this.term === this._value(),
2398				menuVisible = this.menu.element.is( ":visible" ),
2399				modifierKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
2400
2401			if ( !equalValues || ( equalValues && !menuVisible && !modifierKey ) ) {
2402				this.selectedItem = null;
2403				this.search( null, event );
2404			}
2405		}, this.options.delay );
2406	},
2407
2408	search: function( value, event ) {
2409		value = value != null ? value : this._value();
2410
2411		// Always save the actual value, not the one passed as an argument
2412		this.term = this._value();
2413
2414		if ( value.length < this.options.minLength ) {
2415			return this.close( event );
2416		}
2417
2418		if ( this._trigger( "search", event ) === false ) {
2419			return;
2420		}
2421
2422		return this._search( value );
2423	},
2424
2425	_search: function( value ) {
2426		this.pending++;
2427		this._addClass( "ui-autocomplete-loading" );
2428		this.cancelSearch = false;
2429
2430		this.source( { term: value }, this._response() );
2431	},
2432
2433	_response: function() {
2434		var index = ++this.requestIndex;
2435
2436		return $.proxy( function( content ) {
2437			if ( index === this.requestIndex ) {
2438				this.__response( content );
2439			}
2440
2441			this.pending--;
2442			if ( !this.pending ) {
2443				this._removeClass( "ui-autocomplete-loading" );
2444			}
2445		}, this );
2446	},
2447
2448	__response: function( content ) {
2449		if ( content ) {
2450			content = this._normalize( content );
2451		}
2452		this._trigger( "response", null, { content: content } );
2453		if ( !this.options.disabled && content && content.length && !this.cancelSearch ) {
2454			this._suggest( content );
2455			this._trigger( "open" );
2456		} else {
2457
2458			// use ._close() instead of .close() so we don't cancel future searches
2459			this._close();
2460		}
2461	},
2462
2463	close: function( event ) {
2464		this.cancelSearch = true;
2465		this._close( event );
2466	},
2467
2468	_close: function( event ) {
2469
2470		// Remove the handler that closes the menu on outside clicks
2471		this._off( this.document, "mousedown" );
2472
2473		if ( this.menu.element.is( ":visible" ) ) {
2474			this.menu.element.hide();
2475			this.menu.blur();
2476			this.isNewMenu = true;
2477			this._trigger( "close", event );
2478		}
2479	},
2480
2481	_change: function( event ) {
2482		if ( this.previous !== this._value() ) {
2483			this._trigger( "change", event, { item: this.selectedItem } );
2484		}
2485	},
2486
2487	_normalize: function( items ) {
2488
2489		// assume all items have the right format when the first item is complete
2490		if ( items.length && items[ 0 ].label && items[ 0 ].value ) {
2491			return items;
2492		}
2493		return $.map( items, function( item ) {
2494			if ( typeof item === "string" ) {
2495				return {
2496					label: item,
2497					value: item
2498				};
2499			}
2500			return $.extend( {}, item, {
2501				label: item.label || item.value,
2502				value: item.value || item.label
2503			} );
2504		} );
2505	},
2506
2507	_suggest: function( items ) {
2508		var ul = this.menu.element.empty();
2509		this._renderMenu( ul, items );
2510		this.isNewMenu = true;
2511		this.menu.refresh();
2512
2513		// Size and position menu
2514		ul.show();
2515		this._resizeMenu();
2516		ul.position( $.extend( {
2517			of: this.element
2518		}, this.options.position ) );
2519
2520		if ( this.options.autoFocus ) {
2521			this.menu.next();
2522		}
2523
2524		// Listen for interactions outside of the widget (#6642)
2525		this._on( this.document, {
2526			mousedown: "_closeOnClickOutside"
2527		} );
2528	},
2529
2530	_resizeMenu: function() {
2531		var ul = this.menu.element;
2532		ul.outerWidth( Math.max(
2533
2534			// Firefox wraps long text (possibly a rounding bug)
2535			// so we add 1px to avoid the wrapping (#7513)
2536			ul.width( "" ).outerWidth() + 1,
2537			this.element.outerWidth()
2538		) );
2539	},
2540
2541	_renderMenu: function( ul, items ) {
2542		var that = this;
2543		$.each( items, function( index, item ) {
2544			that._renderItemData( ul, item );
2545		} );
2546	},
2547
2548	_renderItemData: function( ul, item ) {
2549		return this._renderItem( ul, item ).data( "ui-autocomplete-item", item );
2550	},
2551
2552	_renderItem: function( ul, item ) {
2553		return $( "<li>" )
2554			.append( $( "<div>" ).text( item.label ) )
2555			.appendTo( ul );
2556	},
2557
2558	_move: function( direction, event ) {
2559		if ( !this.menu.element.is( ":visible" ) ) {
2560			this.search( null, event );
2561			return;
2562		}
2563		if ( this.menu.isFirstItem() && /^previous/.test( direction ) ||
2564				this.menu.isLastItem() && /^next/.test( direction ) ) {
2565
2566			if ( !this.isMultiLine ) {
2567				this._value( this.term );
2568			}
2569
2570			this.menu.blur();
2571			return;
2572		}
2573		this.menu[ direction ]( event );
2574	},
2575
2576	widget: function() {
2577		return this.menu.element;
2578	},
2579
2580	_value: function() {
2581		return this.valueMethod.apply( this.element, arguments );
2582	},
2583
2584	_keyEvent: function( keyEvent, event ) {
2585		if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
2586			this._move( keyEvent, event );
2587
2588			// Prevents moving cursor to beginning/end of the text field in some browsers
2589			event.preventDefault();
2590		}
2591	},
2592
2593	// Support: Chrome <=50
2594	// We should be able to just use this.element.prop( "isContentEditable" )
2595	// but hidden elements always report false in Chrome.
2596	// https://code.google.com/p/chromium/issues/detail?id=313082
2597	_isContentEditable: function( element ) {
2598		if ( !element.length ) {
2599			return false;
2600		}
2601
2602		var editable = element.prop( "contentEditable" );
2603
2604		if ( editable === "inherit" ) {
2605		  return this._isContentEditable( element.parent() );
2606		}
2607
2608		return editable === "true";
2609	}
2610} );
2611
2612$.extend( $.ui.autocomplete, {
2613	escapeRegex: function( value ) {
2614		return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
2615	},
2616	filter: function( array, term ) {
2617		var matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), "i" );
2618		return $.grep( array, function( value ) {
2619			return matcher.test( value.label || value.value || value );
2620		} );
2621	}
2622} );
2623
2624// Live region extension, adding a `messages` option
2625// NOTE: This is an experimental API. We are still investigating
2626// a full solution for string manipulation and internationalization.
2627$.widget( "ui.autocomplete", $.ui.autocomplete, {
2628	options: {
2629		messages: {
2630			noResults: "No search results.",
2631			results: function( amount ) {
2632				return amount + ( amount > 1 ? " results are" : " result is" ) +
2633					" available, use up and down arrow keys to navigate.";
2634			}
2635		}
2636	},
2637
2638	__response: function( content ) {
2639		var message;
2640		this._superApply( arguments );
2641		if ( this.options.disabled || this.cancelSearch ) {
2642			return;
2643		}
2644		if ( content && content.length ) {
2645			message = this.options.messages.results( content.length );
2646		} else {
2647			message = this.options.messages.noResults;
2648		}
2649		this.liveRegion.children().hide();
2650		$( "<div>" ).text( message ).appendTo( this.liveRegion );
2651	}
2652} );
2653
2654var widgetsAutocomplete = $.ui.autocomplete;
2655
2656
2657
2658
2659}));