Tag description update API
[wolnelektury.git] / src / wolnelektury / static / contrib / jquery-ui-1.13.1.custom / jquery-ui.js
1 /*! jQuery UI - v1.13.1 - 2022-02-02
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         "use strict";
8         
9         if ( typeof define === "function" && define.amd ) {
10
11                 // AMD. Register as an anonymous module.
12                 define( [ "jquery" ], factory );
13         } else {
14
15                 // Browser globals
16                 factory( jQuery );
17         }
18 } )( function( $ ) {
19 "use strict";
20
21 $.ui = $.ui || {};
22
23 var version = $.ui.version = "1.13.1";
24
25
26 /*!
27  * jQuery UI Widget 1.13.1
28  * http://jqueryui.com
29  *
30  * Copyright jQuery Foundation and other contributors
31  * Released under the MIT license.
32  * http://jquery.org/license
33  */
34
35 //>>label: Widget
36 //>>group: Core
37 //>>description: Provides a factory for creating stateful widgets with a common API.
38 //>>docs: http://api.jqueryui.com/jQuery.widget/
39 //>>demos: http://jqueryui.com/widget/
40
41
42 var widgetUuid = 0;
43 var widgetHasOwnProperty = Array.prototype.hasOwnProperty;
44 var widgetSlice = Array.prototype.slice;
45
46 $.cleanData = ( function( orig ) {
47         return function( elems ) {
48                 var events, elem, i;
49                 for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) {
50
51                         // Only trigger remove when necessary to save time
52                         events = $._data( elem, "events" );
53                         if ( events && events.remove ) {
54                                 $( elem ).triggerHandler( "remove" );
55                         }
56                 }
57                 orig( elems );
58         };
59 } )( $.cleanData );
60
61 $.widget = function( name, base, prototype ) {
62         var existingConstructor, constructor, basePrototype;
63
64         // ProxiedPrototype allows the provided prototype to remain unmodified
65         // so that it can be used as a mixin for multiple widgets (#8876)
66         var proxiedPrototype = {};
67
68         var namespace = name.split( "." )[ 0 ];
69         name = name.split( "." )[ 1 ];
70         var fullName = namespace + "-" + name;
71
72         if ( !prototype ) {
73                 prototype = base;
74                 base = $.Widget;
75         }
76
77         if ( Array.isArray( prototype ) ) {
78                 prototype = $.extend.apply( null, [ {} ].concat( prototype ) );
79         }
80
81         // Create selector for plugin
82         $.expr.pseudos[ fullName.toLowerCase() ] = function( elem ) {
83                 return !!$.data( elem, fullName );
84         };
85
86         $[ namespace ] = $[ namespace ] || {};
87         existingConstructor = $[ namespace ][ name ];
88         constructor = $[ namespace ][ name ] = function( options, element ) {
89
90                 // Allow instantiation without "new" keyword
91                 if ( !this || !this._createWidget ) {
92                         return new constructor( options, element );
93                 }
94
95                 // Allow instantiation without initializing for simple inheritance
96                 // must use "new" keyword (the code above always passes args)
97                 if ( arguments.length ) {
98                         this._createWidget( options, element );
99                 }
100         };
101
102         // Extend with the existing constructor to carry over any static properties
103         $.extend( constructor, existingConstructor, {
104                 version: prototype.version,
105
106                 // Copy the object used to create the prototype in case we need to
107                 // redefine the widget later
108                 _proto: $.extend( {}, prototype ),
109
110                 // Track widgets that inherit from this widget in case this widget is
111                 // redefined after a widget inherits from it
112                 _childConstructors: []
113         } );
114
115         basePrototype = new base();
116
117         // We need to make the options hash a property directly on the new instance
118         // otherwise we'll modify the options hash on the prototype that we're
119         // inheriting from
120         basePrototype.options = $.widget.extend( {}, basePrototype.options );
121         $.each( prototype, function( prop, value ) {
122                 if ( typeof value !== "function" ) {
123                         proxiedPrototype[ prop ] = value;
124                         return;
125                 }
126                 proxiedPrototype[ prop ] = ( function() {
127                         function _super() {
128                                 return base.prototype[ prop ].apply( this, arguments );
129                         }
130
131                         function _superApply( args ) {
132                                 return base.prototype[ prop ].apply( this, args );
133                         }
134
135                         return function() {
136                                 var __super = this._super;
137                                 var __superApply = this._superApply;
138                                 var returnValue;
139
140                                 this._super = _super;
141                                 this._superApply = _superApply;
142
143                                 returnValue = value.apply( this, arguments );
144
145                                 this._super = __super;
146                                 this._superApply = __superApply;
147
148                                 return returnValue;
149                         };
150                 } )();
151         } );
152         constructor.prototype = $.widget.extend( basePrototype, {
153
154                 // TODO: remove support for widgetEventPrefix
155                 // always use the name + a colon as the prefix, e.g., draggable:start
156                 // don't prefix for widgets that aren't DOM-based
157                 widgetEventPrefix: existingConstructor ? ( basePrototype.widgetEventPrefix || name ) : name
158         }, proxiedPrototype, {
159                 constructor: constructor,
160                 namespace: namespace,
161                 widgetName: name,
162                 widgetFullName: fullName
163         } );
164
165         // If this widget is being redefined then we need to find all widgets that
166         // are inheriting from it and redefine all of them so that they inherit from
167         // the new version of this widget. We're essentially trying to replace one
168         // level in the prototype chain.
169         if ( existingConstructor ) {
170                 $.each( existingConstructor._childConstructors, function( i, child ) {
171                         var childPrototype = child.prototype;
172
173                         // Redefine the child widget using the same prototype that was
174                         // originally used, but inherit from the new version of the base
175                         $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor,
176                                 child._proto );
177                 } );
178
179                 // Remove the list of existing child constructors from the old constructor
180                 // so the old child constructors can be garbage collected
181                 delete existingConstructor._childConstructors;
182         } else {
183                 base._childConstructors.push( constructor );
184         }
185
186         $.widget.bridge( name, constructor );
187
188         return constructor;
189 };
190
191 $.widget.extend = function( target ) {
192         var input = widgetSlice.call( arguments, 1 );
193         var inputIndex = 0;
194         var inputLength = input.length;
195         var key;
196         var value;
197
198         for ( ; inputIndex < inputLength; inputIndex++ ) {
199                 for ( key in input[ inputIndex ] ) {
200                         value = input[ inputIndex ][ key ];
201                         if ( widgetHasOwnProperty.call( input[ inputIndex ], key ) && value !== undefined ) {
202
203                                 // Clone objects
204                                 if ( $.isPlainObject( value ) ) {
205                                         target[ key ] = $.isPlainObject( target[ key ] ) ?
206                                                 $.widget.extend( {}, target[ key ], value ) :
207
208                                                 // Don't extend strings, arrays, etc. with objects
209                                                 $.widget.extend( {}, value );
210
211                                 // Copy everything else by reference
212                                 } else {
213                                         target[ key ] = value;
214                                 }
215                         }
216                 }
217         }
218         return target;
219 };
220
221 $.widget.bridge = function( name, object ) {
222         var fullName = object.prototype.widgetFullName || name;
223         $.fn[ name ] = function( options ) {
224                 var isMethodCall = typeof options === "string";
225                 var args = widgetSlice.call( arguments, 1 );
226                 var returnValue = this;
227
228                 if ( isMethodCall ) {
229
230                         // If this is an empty collection, we need to have the instance method
231                         // return undefined instead of the jQuery instance
232                         if ( !this.length && options === "instance" ) {
233                                 returnValue = undefined;
234                         } else {
235                                 this.each( function() {
236                                         var methodValue;
237                                         var instance = $.data( this, fullName );
238
239                                         if ( options === "instance" ) {
240                                                 returnValue = instance;
241                                                 return false;
242                                         }
243
244                                         if ( !instance ) {
245                                                 return $.error( "cannot call methods on " + name +
246                                                         " prior to initialization; " +
247                                                         "attempted to call method '" + options + "'" );
248                                         }
249
250                                         if ( typeof instance[ options ] !== "function" ||
251                                                 options.charAt( 0 ) === "_" ) {
252                                                 return $.error( "no such method '" + options + "' for " + name +
253                                                         " widget instance" );
254                                         }
255
256                                         methodValue = instance[ options ].apply( instance, args );
257
258                                         if ( methodValue !== instance && methodValue !== undefined ) {
259                                                 returnValue = methodValue && methodValue.jquery ?
260                                                         returnValue.pushStack( methodValue.get() ) :
261                                                         methodValue;
262                                                 return false;
263                                         }
264                                 } );
265                         }
266                 } else {
267
268                         // Allow multiple hashes to be passed on init
269                         if ( args.length ) {
270                                 options = $.widget.extend.apply( null, [ options ].concat( args ) );
271                         }
272
273                         this.each( function() {
274                                 var instance = $.data( this, fullName );
275                                 if ( instance ) {
276                                         instance.option( options || {} );
277                                         if ( instance._init ) {
278                                                 instance._init();
279                                         }
280                                 } else {
281                                         $.data( this, fullName, new object( options, this ) );
282                                 }
283                         } );
284                 }
285
286                 return returnValue;
287         };
288 };
289
290 $.Widget = function( /* options, element */ ) {};
291 $.Widget._childConstructors = [];
292
293 $.Widget.prototype = {
294         widgetName: "widget",
295         widgetEventPrefix: "",
296         defaultElement: "<div>",
297
298         options: {
299                 classes: {},
300                 disabled: false,
301
302                 // Callbacks
303                 create: null
304         },
305
306         _createWidget: function( options, element ) {
307                 element = $( element || this.defaultElement || this )[ 0 ];
308                 this.element = $( element );
309                 this.uuid = widgetUuid++;
310                 this.eventNamespace = "." + this.widgetName + this.uuid;
311
312                 this.bindings = $();
313                 this.hoverable = $();
314                 this.focusable = $();
315                 this.classesElementLookup = {};
316
317                 if ( element !== this ) {
318                         $.data( element, this.widgetFullName, this );
319                         this._on( true, this.element, {
320                                 remove: function( event ) {
321                                         if ( event.target === element ) {
322                                                 this.destroy();
323                                         }
324                                 }
325                         } );
326                         this.document = $( element.style ?
327
328                                 // Element within the document
329                                 element.ownerDocument :
330
331                                 // Element is window or document
332                                 element.document || element );
333                         this.window = $( this.document[ 0 ].defaultView || this.document[ 0 ].parentWindow );
334                 }
335
336                 this.options = $.widget.extend( {},
337                         this.options,
338                         this._getCreateOptions(),
339                         options );
340
341                 this._create();
342
343                 if ( this.options.disabled ) {
344                         this._setOptionDisabled( this.options.disabled );
345                 }
346
347                 this._trigger( "create", null, this._getCreateEventData() );
348                 this._init();
349         },
350
351         _getCreateOptions: function() {
352                 return {};
353         },
354
355         _getCreateEventData: $.noop,
356
357         _create: $.noop,
358
359         _init: $.noop,
360
361         destroy: function() {
362                 var that = this;
363
364                 this._destroy();
365                 $.each( this.classesElementLookup, function( key, value ) {
366                         that._removeClass( value, key );
367                 } );
368
369                 // We can probably remove the unbind calls in 2.0
370                 // all event bindings should go through this._on()
371                 this.element
372                         .off( this.eventNamespace )
373                         .removeData( this.widgetFullName );
374                 this.widget()
375                         .off( this.eventNamespace )
376                         .removeAttr( "aria-disabled" );
377
378                 // Clean up events and states
379                 this.bindings.off( this.eventNamespace );
380         },
381
382         _destroy: $.noop,
383
384         widget: function() {
385                 return this.element;
386         },
387
388         option: function( key, value ) {
389                 var options = key;
390                 var parts;
391                 var curOption;
392                 var i;
393
394                 if ( arguments.length === 0 ) {
395
396                         // Don't return a reference to the internal hash
397                         return $.widget.extend( {}, this.options );
398                 }
399
400                 if ( typeof key === "string" ) {
401
402                         // Handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
403                         options = {};
404                         parts = key.split( "." );
405                         key = parts.shift();
406                         if ( parts.length ) {
407                                 curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
408                                 for ( i = 0; i < parts.length - 1; i++ ) {
409                                         curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
410                                         curOption = curOption[ parts[ i ] ];
411                                 }
412                                 key = parts.pop();
413                                 if ( arguments.length === 1 ) {
414                                         return curOption[ key ] === undefined ? null : curOption[ key ];
415                                 }
416                                 curOption[ key ] = value;
417                         } else {
418                                 if ( arguments.length === 1 ) {
419                                         return this.options[ key ] === undefined ? null : this.options[ key ];
420                                 }
421                                 options[ key ] = value;
422                         }
423                 }
424
425                 this._setOptions( options );
426
427                 return this;
428         },
429
430         _setOptions: function( options ) {
431                 var key;
432
433                 for ( key in options ) {
434                         this._setOption( key, options[ key ] );
435                 }
436
437                 return this;
438         },
439
440         _setOption: function( key, value ) {
441                 if ( key === "classes" ) {
442                         this._setOptionClasses( value );
443                 }
444
445                 this.options[ key ] = value;
446
447                 if ( key === "disabled" ) {
448                         this._setOptionDisabled( value );
449                 }
450
451                 return this;
452         },
453
454         _setOptionClasses: function( value ) {
455                 var classKey, elements, currentElements;
456
457                 for ( classKey in value ) {
458                         currentElements = this.classesElementLookup[ classKey ];
459                         if ( value[ classKey ] === this.options.classes[ classKey ] ||
460                                         !currentElements ||
461                                         !currentElements.length ) {
462                                 continue;
463                         }
464
465                         // We are doing this to create a new jQuery object because the _removeClass() call
466                         // on the next line is going to destroy the reference to the current elements being
467                         // tracked. We need to save a copy of this collection so that we can add the new classes
468                         // below.
469                         elements = $( currentElements.get() );
470                         this._removeClass( currentElements, classKey );
471
472                         // We don't use _addClass() here, because that uses this.options.classes
473                         // for generating the string of classes. We want to use the value passed in from
474                         // _setOption(), this is the new value of the classes option which was passed to
475                         // _setOption(). We pass this value directly to _classes().
476                         elements.addClass( this._classes( {
477                                 element: elements,
478                                 keys: classKey,
479                                 classes: value,
480                                 add: true
481                         } ) );
482                 }
483         },
484
485         _setOptionDisabled: function( value ) {
486                 this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, !!value );
487
488                 // If the widget is becoming disabled, then nothing is interactive
489                 if ( value ) {
490                         this._removeClass( this.hoverable, null, "ui-state-hover" );
491                         this._removeClass( this.focusable, null, "ui-state-focus" );
492                 }
493         },
494
495         enable: function() {
496                 return this._setOptions( { disabled: false } );
497         },
498
499         disable: function() {
500                 return this._setOptions( { disabled: true } );
501         },
502
503         _classes: function( options ) {
504                 var full = [];
505                 var that = this;
506
507                 options = $.extend( {
508                         element: this.element,
509                         classes: this.options.classes || {}
510                 }, options );
511
512                 function bindRemoveEvent() {
513                         var nodesToBind = [];
514
515                         options.element.each( function( _, element ) {
516                                 var isTracked = $.map( that.classesElementLookup, function( elements ) {
517                                         return elements;
518                                 } )
519                                         .some( function( elements ) {
520                                                 return elements.is( element );
521                                         } );
522
523                                 if ( !isTracked ) {
524                                         nodesToBind.push( element );
525                                 }
526                         } );
527
528                         that._on( $( nodesToBind ), {
529                                 remove: "_untrackClassesElement"
530                         } );
531                 }
532
533                 function processClassString( classes, checkOption ) {
534                         var current, i;
535                         for ( i = 0; i < classes.length; i++ ) {
536                                 current = that.classesElementLookup[ classes[ i ] ] || $();
537                                 if ( options.add ) {
538                                         bindRemoveEvent();
539                                         current = $( $.uniqueSort( current.get().concat( options.element.get() ) ) );
540                                 } else {
541                                         current = $( current.not( options.element ).get() );
542                                 }
543                                 that.classesElementLookup[ classes[ i ] ] = current;
544                                 full.push( classes[ i ] );
545                                 if ( checkOption && options.classes[ classes[ i ] ] ) {
546                                         full.push( options.classes[ classes[ i ] ] );
547                                 }
548                         }
549                 }
550
551                 if ( options.keys ) {
552                         processClassString( options.keys.match( /\S+/g ) || [], true );
553                 }
554                 if ( options.extra ) {
555                         processClassString( options.extra.match( /\S+/g ) || [] );
556                 }
557
558                 return full.join( " " );
559         },
560
561         _untrackClassesElement: function( event ) {
562                 var that = this;
563                 $.each( that.classesElementLookup, function( key, value ) {
564                         if ( $.inArray( event.target, value ) !== -1 ) {
565                                 that.classesElementLookup[ key ] = $( value.not( event.target ).get() );
566                         }
567                 } );
568
569                 this._off( $( event.target ) );
570         },
571
572         _removeClass: function( element, keys, extra ) {
573                 return this._toggleClass( element, keys, extra, false );
574         },
575
576         _addClass: function( element, keys, extra ) {
577                 return this._toggleClass( element, keys, extra, true );
578         },
579
580         _toggleClass: function( element, keys, extra, add ) {
581                 add = ( typeof add === "boolean" ) ? add : extra;
582                 var shift = ( typeof element === "string" || element === null ),
583                         options = {
584                                 extra: shift ? keys : extra,
585                                 keys: shift ? element : keys,
586                                 element: shift ? this.element : element,
587                                 add: add
588                         };
589                 options.element.toggleClass( this._classes( options ), add );
590                 return this;
591         },
592
593         _on: function( suppressDisabledCheck, element, handlers ) {
594                 var delegateElement;
595                 var instance = this;
596
597                 // No suppressDisabledCheck flag, shuffle arguments
598                 if ( typeof suppressDisabledCheck !== "boolean" ) {
599                         handlers = element;
600                         element = suppressDisabledCheck;
601                         suppressDisabledCheck = false;
602                 }
603
604                 // No element argument, shuffle and use this.element
605                 if ( !handlers ) {
606                         handlers = element;
607                         element = this.element;
608                         delegateElement = this.widget();
609                 } else {
610                         element = delegateElement = $( element );
611                         this.bindings = this.bindings.add( element );
612                 }
613
614                 $.each( handlers, function( event, handler ) {
615                         function handlerProxy() {
616
617                                 // Allow widgets to customize the disabled handling
618                                 // - disabled as an array instead of boolean
619                                 // - disabled class as method for disabling individual parts
620                                 if ( !suppressDisabledCheck &&
621                                                 ( instance.options.disabled === true ||
622                                                 $( this ).hasClass( "ui-state-disabled" ) ) ) {
623                                         return;
624                                 }
625                                 return ( typeof handler === "string" ? instance[ handler ] : handler )
626                                         .apply( instance, arguments );
627                         }
628
629                         // Copy the guid so direct unbinding works
630                         if ( typeof handler !== "string" ) {
631                                 handlerProxy.guid = handler.guid =
632                                         handler.guid || handlerProxy.guid || $.guid++;
633                         }
634
635                         var match = event.match( /^([\w:-]*)\s*(.*)$/ );
636                         var eventName = match[ 1 ] + instance.eventNamespace;
637                         var selector = match[ 2 ];
638
639                         if ( selector ) {
640                                 delegateElement.on( eventName, selector, handlerProxy );
641                         } else {
642                                 element.on( eventName, handlerProxy );
643                         }
644                 } );
645         },
646
647         _off: function( element, eventName ) {
648                 eventName = ( eventName || "" ).split( " " ).join( this.eventNamespace + " " ) +
649                         this.eventNamespace;
650                 element.off( eventName );
651
652                 // Clear the stack to avoid memory leaks (#10056)
653                 this.bindings = $( this.bindings.not( element ).get() );
654                 this.focusable = $( this.focusable.not( element ).get() );
655                 this.hoverable = $( this.hoverable.not( element ).get() );
656         },
657
658         _delay: function( handler, delay ) {
659                 function handlerProxy() {
660                         return ( typeof handler === "string" ? instance[ handler ] : handler )
661                                 .apply( instance, arguments );
662                 }
663                 var instance = this;
664                 return setTimeout( handlerProxy, delay || 0 );
665         },
666
667         _hoverable: function( element ) {
668                 this.hoverable = this.hoverable.add( element );
669                 this._on( element, {
670                         mouseenter: function( event ) {
671                                 this._addClass( $( event.currentTarget ), null, "ui-state-hover" );
672                         },
673                         mouseleave: function( event ) {
674                                 this._removeClass( $( event.currentTarget ), null, "ui-state-hover" );
675                         }
676                 } );
677         },
678
679         _focusable: function( element ) {
680                 this.focusable = this.focusable.add( element );
681                 this._on( element, {
682                         focusin: function( event ) {
683                                 this._addClass( $( event.currentTarget ), null, "ui-state-focus" );
684                         },
685                         focusout: function( event ) {
686                                 this._removeClass( $( event.currentTarget ), null, "ui-state-focus" );
687                         }
688                 } );
689         },
690
691         _trigger: function( type, event, data ) {
692                 var prop, orig;
693                 var callback = this.options[ type ];
694
695                 data = data || {};
696                 event = $.Event( event );
697                 event.type = ( type === this.widgetEventPrefix ?
698                         type :
699                         this.widgetEventPrefix + type ).toLowerCase();
700
701                 // The original event may come from any element
702                 // so we need to reset the target on the new event
703                 event.target = this.element[ 0 ];
704
705                 // Copy original event properties over to the new event
706                 orig = event.originalEvent;
707                 if ( orig ) {
708                         for ( prop in orig ) {
709                                 if ( !( prop in event ) ) {
710                                         event[ prop ] = orig[ prop ];
711                                 }
712                         }
713                 }
714
715                 this.element.trigger( event, data );
716                 return !( typeof callback === "function" &&
717                         callback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false ||
718                         event.isDefaultPrevented() );
719         }
720 };
721
722 $.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
723         $.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
724                 if ( typeof options === "string" ) {
725                         options = { effect: options };
726                 }
727
728                 var hasOptions;
729                 var effectName = !options ?
730                         method :
731                         options === true || typeof options === "number" ?
732                                 defaultEffect :
733                                 options.effect || defaultEffect;
734
735                 options = options || {};
736                 if ( typeof options === "number" ) {
737                         options = { duration: options };
738                 } else if ( options === true ) {
739                         options = {};
740                 }
741
742                 hasOptions = !$.isEmptyObject( options );
743                 options.complete = callback;
744
745                 if ( options.delay ) {
746                         element.delay( options.delay );
747                 }
748
749                 if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
750                         element[ method ]( options );
751                 } else if ( effectName !== method && element[ effectName ] ) {
752                         element[ effectName ]( options.duration, options.easing, callback );
753                 } else {
754                         element.queue( function( next ) {
755                                 $( this )[ method ]();
756                                 if ( callback ) {
757                                         callback.call( element[ 0 ] );
758                                 }
759                                 next();
760                         } );
761                 }
762         };
763 } );
764
765 var widget = $.widget;
766
767
768 /*!
769  * jQuery UI Position 1.13.1
770  * http://jqueryui.com
771  *
772  * Copyright jQuery Foundation and other contributors
773  * Released under the MIT license.
774  * http://jquery.org/license
775  *
776  * http://api.jqueryui.com/position/
777  */
778
779 //>>label: Position
780 //>>group: Core
781 //>>description: Positions elements relative to other elements.
782 //>>docs: http://api.jqueryui.com/position/
783 //>>demos: http://jqueryui.com/position/
784
785
786 ( function() {
787 var cachedScrollbarWidth,
788         max = Math.max,
789         abs = Math.abs,
790         rhorizontal = /left|center|right/,
791         rvertical = /top|center|bottom/,
792         roffset = /[\+\-]\d+(\.[\d]+)?%?/,
793         rposition = /^\w+/,
794         rpercent = /%$/,
795         _position = $.fn.position;
796
797 function getOffsets( offsets, width, height ) {
798         return [
799                 parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
800                 parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
801         ];
802 }
803
804 function parseCss( element, property ) {
805         return parseInt( $.css( element, property ), 10 ) || 0;
806 }
807
808 function isWindow( obj ) {
809         return obj != null && obj === obj.window;
810 }
811
812 function getDimensions( elem ) {
813         var raw = elem[ 0 ];
814         if ( raw.nodeType === 9 ) {
815                 return {
816                         width: elem.width(),
817                         height: elem.height(),
818                         offset: { top: 0, left: 0 }
819                 };
820         }
821         if ( isWindow( raw ) ) {
822                 return {
823                         width: elem.width(),
824                         height: elem.height(),
825                         offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
826                 };
827         }
828         if ( raw.preventDefault ) {
829                 return {
830                         width: 0,
831                         height: 0,
832                         offset: { top: raw.pageY, left: raw.pageX }
833                 };
834         }
835         return {
836                 width: elem.outerWidth(),
837                 height: elem.outerHeight(),
838                 offset: elem.offset()
839         };
840 }
841
842 $.position = {
843         scrollbarWidth: function() {
844                 if ( cachedScrollbarWidth !== undefined ) {
845                         return cachedScrollbarWidth;
846                 }
847                 var w1, w2,
848                         div = $( "<div style=" +
849                                 "'display:block;position:absolute;width:200px;height:200px;overflow:hidden;'>" +
850                                 "<div style='height:300px;width:auto;'></div></div>" ),
851                         innerDiv = div.children()[ 0 ];
852
853                 $( "body" ).append( div );
854                 w1 = innerDiv.offsetWidth;
855                 div.css( "overflow", "scroll" );
856
857                 w2 = innerDiv.offsetWidth;
858
859                 if ( w1 === w2 ) {
860                         w2 = div[ 0 ].clientWidth;
861                 }
862
863                 div.remove();
864
865                 return ( cachedScrollbarWidth = w1 - w2 );
866         },
867         getScrollInfo: function( within ) {
868                 var overflowX = within.isWindow || within.isDocument ? "" :
869                                 within.element.css( "overflow-x" ),
870                         overflowY = within.isWindow || within.isDocument ? "" :
871                                 within.element.css( "overflow-y" ),
872                         hasOverflowX = overflowX === "scroll" ||
873                                 ( overflowX === "auto" && within.width < within.element[ 0 ].scrollWidth ),
874                         hasOverflowY = overflowY === "scroll" ||
875                                 ( overflowY === "auto" && within.height < within.element[ 0 ].scrollHeight );
876                 return {
877                         width: hasOverflowY ? $.position.scrollbarWidth() : 0,
878                         height: hasOverflowX ? $.position.scrollbarWidth() : 0
879                 };
880         },
881         getWithinInfo: function( element ) {
882                 var withinElement = $( element || window ),
883                         isElemWindow = isWindow( withinElement[ 0 ] ),
884                         isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9,
885                         hasOffset = !isElemWindow && !isDocument;
886                 return {
887                         element: withinElement,
888                         isWindow: isElemWindow,
889                         isDocument: isDocument,
890                         offset: hasOffset ? $( element ).offset() : { left: 0, top: 0 },
891                         scrollLeft: withinElement.scrollLeft(),
892                         scrollTop: withinElement.scrollTop(),
893                         width: withinElement.outerWidth(),
894                         height: withinElement.outerHeight()
895                 };
896         }
897 };
898
899 $.fn.position = function( options ) {
900         if ( !options || !options.of ) {
901                 return _position.apply( this, arguments );
902         }
903
904         // Make a copy, we don't want to modify arguments
905         options = $.extend( {}, options );
906
907         var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
908
909                 // Make sure string options are treated as CSS selectors
910                 target = typeof options.of === "string" ?
911                         $( document ).find( options.of ) :
912                         $( options.of ),
913
914                 within = $.position.getWithinInfo( options.within ),
915                 scrollInfo = $.position.getScrollInfo( within ),
916                 collision = ( options.collision || "flip" ).split( " " ),
917                 offsets = {};
918
919         dimensions = getDimensions( target );
920         if ( target[ 0 ].preventDefault ) {
921
922                 // Force left top to allow flipping
923                 options.at = "left top";
924         }
925         targetWidth = dimensions.width;
926         targetHeight = dimensions.height;
927         targetOffset = dimensions.offset;
928
929         // Clone to reuse original targetOffset later
930         basePosition = $.extend( {}, targetOffset );
931
932         // Force my and at to have valid horizontal and vertical positions
933         // if a value is missing or invalid, it will be converted to center
934         $.each( [ "my", "at" ], function() {
935                 var pos = ( options[ this ] || "" ).split( " " ),
936                         horizontalOffset,
937                         verticalOffset;
938
939                 if ( pos.length === 1 ) {
940                         pos = rhorizontal.test( pos[ 0 ] ) ?
941                                 pos.concat( [ "center" ] ) :
942                                 rvertical.test( pos[ 0 ] ) ?
943                                         [ "center" ].concat( pos ) :
944                                         [ "center", "center" ];
945                 }
946                 pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
947                 pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
948
949                 // Calculate offsets
950                 horizontalOffset = roffset.exec( pos[ 0 ] );
951                 verticalOffset = roffset.exec( pos[ 1 ] );
952                 offsets[ this ] = [
953                         horizontalOffset ? horizontalOffset[ 0 ] : 0,
954                         verticalOffset ? verticalOffset[ 0 ] : 0
955                 ];
956
957                 // Reduce to just the positions without the offsets
958                 options[ this ] = [
959                         rposition.exec( pos[ 0 ] )[ 0 ],
960                         rposition.exec( pos[ 1 ] )[ 0 ]
961                 ];
962         } );
963
964         // Normalize collision option
965         if ( collision.length === 1 ) {
966                 collision[ 1 ] = collision[ 0 ];
967         }
968
969         if ( options.at[ 0 ] === "right" ) {
970                 basePosition.left += targetWidth;
971         } else if ( options.at[ 0 ] === "center" ) {
972                 basePosition.left += targetWidth / 2;
973         }
974
975         if ( options.at[ 1 ] === "bottom" ) {
976                 basePosition.top += targetHeight;
977         } else if ( options.at[ 1 ] === "center" ) {
978                 basePosition.top += targetHeight / 2;
979         }
980
981         atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
982         basePosition.left += atOffset[ 0 ];
983         basePosition.top += atOffset[ 1 ];
984
985         return this.each( function() {
986                 var collisionPosition, using,
987                         elem = $( this ),
988                         elemWidth = elem.outerWidth(),
989                         elemHeight = elem.outerHeight(),
990                         marginLeft = parseCss( this, "marginLeft" ),
991                         marginTop = parseCss( this, "marginTop" ),
992                         collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) +
993                                 scrollInfo.width,
994                         collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) +
995                                 scrollInfo.height,
996                         position = $.extend( {}, basePosition ),
997                         myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
998
999                 if ( options.my[ 0 ] === "right" ) {
1000                         position.left -= elemWidth;
1001                 } else if ( options.my[ 0 ] === "center" ) {
1002                         position.left -= elemWidth / 2;
1003                 }
1004
1005                 if ( options.my[ 1 ] === "bottom" ) {
1006                         position.top -= elemHeight;
1007                 } else if ( options.my[ 1 ] === "center" ) {
1008                         position.top -= elemHeight / 2;
1009                 }
1010
1011                 position.left += myOffset[ 0 ];
1012                 position.top += myOffset[ 1 ];
1013
1014                 collisionPosition = {
1015                         marginLeft: marginLeft,
1016                         marginTop: marginTop
1017                 };
1018
1019                 $.each( [ "left", "top" ], function( i, dir ) {
1020                         if ( $.ui.position[ collision[ i ] ] ) {
1021                                 $.ui.position[ collision[ i ] ][ dir ]( position, {
1022                                         targetWidth: targetWidth,
1023                                         targetHeight: targetHeight,
1024                                         elemWidth: elemWidth,
1025                                         elemHeight: elemHeight,
1026                                         collisionPosition: collisionPosition,
1027                                         collisionWidth: collisionWidth,
1028                                         collisionHeight: collisionHeight,
1029                                         offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
1030                                         my: options.my,
1031                                         at: options.at,
1032                                         within: within,
1033                                         elem: elem
1034                                 } );
1035                         }
1036                 } );
1037
1038                 if ( options.using ) {
1039
1040                         // Adds feedback as second argument to using callback, if present
1041                         using = function( props ) {
1042                                 var left = targetOffset.left - position.left,
1043                                         right = left + targetWidth - elemWidth,
1044                                         top = targetOffset.top - position.top,
1045                                         bottom = top + targetHeight - elemHeight,
1046                                         feedback = {
1047                                                 target: {
1048                                                         element: target,
1049                                                         left: targetOffset.left,
1050                                                         top: targetOffset.top,
1051                                                         width: targetWidth,
1052                                                         height: targetHeight
1053                                                 },
1054                                                 element: {
1055                                                         element: elem,
1056                                                         left: position.left,
1057                                                         top: position.top,
1058                                                         width: elemWidth,
1059                                                         height: elemHeight
1060                                                 },
1061                                                 horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
1062                                                 vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
1063                                         };
1064                                 if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
1065                                         feedback.horizontal = "center";
1066                                 }
1067                                 if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
1068                                         feedback.vertical = "middle";
1069                                 }
1070                                 if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
1071                                         feedback.important = "horizontal";
1072                                 } else {
1073                                         feedback.important = "vertical";
1074                                 }
1075                                 options.using.call( this, props, feedback );
1076                         };
1077                 }
1078
1079                 elem.offset( $.extend( position, { using: using } ) );
1080         } );
1081 };
1082
1083 $.ui.position = {
1084         fit: {
1085                 left: function( position, data ) {
1086                         var within = data.within,
1087                                 withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
1088                                 outerWidth = within.width,
1089                                 collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1090                                 overLeft = withinOffset - collisionPosLeft,
1091                                 overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
1092                                 newOverRight;
1093
1094                         // Element is wider than within
1095                         if ( data.collisionWidth > outerWidth ) {
1096
1097                                 // Element is initially over the left side of within
1098                                 if ( overLeft > 0 && overRight <= 0 ) {
1099                                         newOverRight = position.left + overLeft + data.collisionWidth - outerWidth -
1100                                                 withinOffset;
1101                                         position.left += overLeft - newOverRight;
1102
1103                                 // Element is initially over right side of within
1104                                 } else if ( overRight > 0 && overLeft <= 0 ) {
1105                                         position.left = withinOffset;
1106
1107                                 // Element is initially over both left and right sides of within
1108                                 } else {
1109                                         if ( overLeft > overRight ) {
1110                                                 position.left = withinOffset + outerWidth - data.collisionWidth;
1111                                         } else {
1112                                                 position.left = withinOffset;
1113                                         }
1114                                 }
1115
1116                         // Too far left -> align with left edge
1117                         } else if ( overLeft > 0 ) {
1118                                 position.left += overLeft;
1119
1120                         // Too far right -> align with right edge
1121                         } else if ( overRight > 0 ) {
1122                                 position.left -= overRight;
1123
1124                         // Adjust based on position and margin
1125                         } else {
1126                                 position.left = max( position.left - collisionPosLeft, position.left );
1127                         }
1128                 },
1129                 top: function( position, data ) {
1130                         var within = data.within,
1131                                 withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
1132                                 outerHeight = data.within.height,
1133                                 collisionPosTop = position.top - data.collisionPosition.marginTop,
1134                                 overTop = withinOffset - collisionPosTop,
1135                                 overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
1136                                 newOverBottom;
1137
1138                         // Element is taller than within
1139                         if ( data.collisionHeight > outerHeight ) {
1140
1141                                 // Element is initially over the top of within
1142                                 if ( overTop > 0 && overBottom <= 0 ) {
1143                                         newOverBottom = position.top + overTop + data.collisionHeight - outerHeight -
1144                                                 withinOffset;
1145                                         position.top += overTop - newOverBottom;
1146
1147                                 // Element is initially over bottom of within
1148                                 } else if ( overBottom > 0 && overTop <= 0 ) {
1149                                         position.top = withinOffset;
1150
1151                                 // Element is initially over both top and bottom of within
1152                                 } else {
1153                                         if ( overTop > overBottom ) {
1154                                                 position.top = withinOffset + outerHeight - data.collisionHeight;
1155                                         } else {
1156                                                 position.top = withinOffset;
1157                                         }
1158                                 }
1159
1160                         // Too far up -> align with top
1161                         } else if ( overTop > 0 ) {
1162                                 position.top += overTop;
1163
1164                         // Too far down -> align with bottom edge
1165                         } else if ( overBottom > 0 ) {
1166                                 position.top -= overBottom;
1167
1168                         // Adjust based on position and margin
1169                         } else {
1170                                 position.top = max( position.top - collisionPosTop, position.top );
1171                         }
1172                 }
1173         },
1174         flip: {
1175                 left: function( position, data ) {
1176                         var within = data.within,
1177                                 withinOffset = within.offset.left + within.scrollLeft,
1178                                 outerWidth = within.width,
1179                                 offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
1180                                 collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1181                                 overLeft = collisionPosLeft - offsetLeft,
1182                                 overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
1183                                 myOffset = data.my[ 0 ] === "left" ?
1184                                         -data.elemWidth :
1185                                         data.my[ 0 ] === "right" ?
1186                                                 data.elemWidth :
1187                                                 0,
1188                                 atOffset = data.at[ 0 ] === "left" ?
1189                                         data.targetWidth :
1190                                         data.at[ 0 ] === "right" ?
1191                                                 -data.targetWidth :
1192                                                 0,
1193                                 offset = -2 * data.offset[ 0 ],
1194                                 newOverRight,
1195                                 newOverLeft;
1196
1197                         if ( overLeft < 0 ) {
1198                                 newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth -
1199                                         outerWidth - withinOffset;
1200                                 if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
1201                                         position.left += myOffset + atOffset + offset;
1202                                 }
1203                         } else if ( overRight > 0 ) {
1204                                 newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset +
1205                                         atOffset + offset - offsetLeft;
1206                                 if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
1207                                         position.left += myOffset + atOffset + offset;
1208                                 }
1209                         }
1210                 },
1211                 top: function( position, data ) {
1212                         var within = data.within,
1213                                 withinOffset = within.offset.top + within.scrollTop,
1214                                 outerHeight = within.height,
1215                                 offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
1216                                 collisionPosTop = position.top - data.collisionPosition.marginTop,
1217                                 overTop = collisionPosTop - offsetTop,
1218                                 overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
1219                                 top = data.my[ 1 ] === "top",
1220                                 myOffset = top ?
1221                                         -data.elemHeight :
1222                                         data.my[ 1 ] === "bottom" ?
1223                                                 data.elemHeight :
1224                                                 0,
1225                                 atOffset = data.at[ 1 ] === "top" ?
1226                                         data.targetHeight :
1227                                         data.at[ 1 ] === "bottom" ?
1228                                                 -data.targetHeight :
1229                                                 0,
1230                                 offset = -2 * data.offset[ 1 ],
1231                                 newOverTop,
1232                                 newOverBottom;
1233                         if ( overTop < 0 ) {
1234                                 newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight -
1235                                         outerHeight - withinOffset;
1236                                 if ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) {
1237                                         position.top += myOffset + atOffset + offset;
1238                                 }
1239                         } else if ( overBottom > 0 ) {
1240                                 newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset +
1241                                         offset - offsetTop;
1242                                 if ( newOverTop > 0 || abs( newOverTop ) < overBottom ) {
1243                                         position.top += myOffset + atOffset + offset;
1244                                 }
1245                         }
1246                 }
1247         },
1248         flipfit: {
1249                 left: function() {
1250                         $.ui.position.flip.left.apply( this, arguments );
1251                         $.ui.position.fit.left.apply( this, arguments );
1252                 },
1253                 top: function() {
1254                         $.ui.position.flip.top.apply( this, arguments );
1255                         $.ui.position.fit.top.apply( this, arguments );
1256                 }
1257         }
1258 };
1259
1260 } )();
1261
1262 var position = $.ui.position;
1263
1264
1265 /*!
1266  * jQuery UI Keycode 1.13.1
1267  * http://jqueryui.com
1268  *
1269  * Copyright jQuery Foundation and other contributors
1270  * Released under the MIT license.
1271  * http://jquery.org/license
1272  */
1273
1274 //>>label: Keycode
1275 //>>group: Core
1276 //>>description: Provide keycodes as keynames
1277 //>>docs: http://api.jqueryui.com/jQuery.ui.keyCode/
1278
1279
1280 var keycode = $.ui.keyCode = {
1281         BACKSPACE: 8,
1282         COMMA: 188,
1283         DELETE: 46,
1284         DOWN: 40,
1285         END: 35,
1286         ENTER: 13,
1287         ESCAPE: 27,
1288         HOME: 36,
1289         LEFT: 37,
1290         PAGE_DOWN: 34,
1291         PAGE_UP: 33,
1292         PERIOD: 190,
1293         RIGHT: 39,
1294         SPACE: 32,
1295         TAB: 9,
1296         UP: 38
1297 };
1298
1299
1300 /*!
1301  * jQuery UI Unique ID 1.13.1
1302  * http://jqueryui.com
1303  *
1304  * Copyright jQuery Foundation and other contributors
1305  * Released under the MIT license.
1306  * http://jquery.org/license
1307  */
1308
1309 //>>label: uniqueId
1310 //>>group: Core
1311 //>>description: Functions to generate and remove uniqueId's
1312 //>>docs: http://api.jqueryui.com/uniqueId/
1313
1314
1315 var uniqueId = $.fn.extend( {
1316         uniqueId: ( function() {
1317                 var uuid = 0;
1318
1319                 return function() {
1320                         return this.each( function() {
1321                                 if ( !this.id ) {
1322                                         this.id = "ui-id-" + ( ++uuid );
1323                                 }
1324                         } );
1325                 };
1326         } )(),
1327
1328         removeUniqueId: function() {
1329                 return this.each( function() {
1330                         if ( /^ui-id-\d+$/.test( this.id ) ) {
1331                                 $( this ).removeAttr( "id" );
1332                         }
1333                 } );
1334         }
1335 } );
1336
1337
1338
1339 var safeActiveElement = $.ui.safeActiveElement = function( document ) {
1340         var activeElement;
1341
1342         // Support: IE 9 only
1343         // IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe>
1344         try {
1345                 activeElement = document.activeElement;
1346         } catch ( error ) {
1347                 activeElement = document.body;
1348         }
1349
1350         // Support: IE 9 - 11 only
1351         // IE may return null instead of an element
1352         // Interestingly, this only seems to occur when NOT in an iframe
1353         if ( !activeElement ) {
1354                 activeElement = document.body;
1355         }
1356
1357         // Support: IE 11 only
1358         // IE11 returns a seemingly empty object in some cases when accessing
1359         // document.activeElement from an <iframe>
1360         if ( !activeElement.nodeName ) {
1361                 activeElement = document.body;
1362         }
1363
1364         return activeElement;
1365 };
1366
1367
1368 /*!
1369  * jQuery UI Menu 1.13.1
1370  * http://jqueryui.com
1371  *
1372  * Copyright jQuery Foundation and other contributors
1373  * Released under the MIT license.
1374  * http://jquery.org/license
1375  */
1376
1377 //>>label: Menu
1378 //>>group: Widgets
1379 //>>description: Creates nestable menus.
1380 //>>docs: http://api.jqueryui.com/menu/
1381 //>>demos: http://jqueryui.com/menu/
1382 //>>css.structure: ../../themes/base/core.css
1383 //>>css.structure: ../../themes/base/menu.css
1384 //>>css.theme: ../../themes/base/theme.css
1385
1386
1387 var widgetsMenu = $.widget( "ui.menu", {
1388         version: "1.13.1",
1389         defaultElement: "<ul>",
1390         delay: 300,
1391         options: {
1392                 icons: {
1393                         submenu: "ui-icon-caret-1-e"
1394                 },
1395                 items: "> *",
1396                 menus: "ul",
1397                 position: {
1398                         my: "left top",
1399                         at: "right top"
1400                 },
1401                 role: "menu",
1402
1403                 // Callbacks
1404                 blur: null,
1405                 focus: null,
1406                 select: null
1407         },
1408
1409         _create: function() {
1410                 this.activeMenu = this.element;
1411
1412                 // Flag used to prevent firing of the click handler
1413                 // as the event bubbles up through nested menus
1414                 this.mouseHandled = false;
1415                 this.lastMousePosition = { x: null, y: null };
1416                 this.element
1417                         .uniqueId()
1418                         .attr( {
1419                                 role: this.options.role,
1420                                 tabIndex: 0
1421                         } );
1422
1423                 this._addClass( "ui-menu", "ui-widget ui-widget-content" );
1424                 this._on( {
1425
1426                         // Prevent focus from sticking to links inside menu after clicking
1427                         // them (focus should always stay on UL during navigation).
1428                         "mousedown .ui-menu-item": function( event ) {
1429                                 event.preventDefault();
1430
1431                                 this._activateItem( event );
1432                         },
1433                         "click .ui-menu-item": function( event ) {
1434                                 var target = $( event.target );
1435                                 var active = $( $.ui.safeActiveElement( this.document[ 0 ] ) );
1436                                 if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) {
1437                                         this.select( event );
1438
1439                                         // Only set the mouseHandled flag if the event will bubble, see #9469.
1440                                         if ( !event.isPropagationStopped() ) {
1441                                                 this.mouseHandled = true;
1442                                         }
1443
1444                                         // Open submenu on click
1445                                         if ( target.has( ".ui-menu" ).length ) {
1446                                                 this.expand( event );
1447                                         } else if ( !this.element.is( ":focus" ) &&
1448                                                         active.closest( ".ui-menu" ).length ) {
1449
1450                                                 // Redirect focus to the menu
1451                                                 this.element.trigger( "focus", [ true ] );
1452
1453                                                 // If the active item is on the top level, let it stay active.
1454                                                 // Otherwise, blur the active item since it is no longer visible.
1455                                                 if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) {
1456                                                         clearTimeout( this.timer );
1457                                                 }
1458                                         }
1459                                 }
1460                         },
1461                         "mouseenter .ui-menu-item": "_activateItem",
1462                         "mousemove .ui-menu-item": "_activateItem",
1463                         mouseleave: "collapseAll",
1464                         "mouseleave .ui-menu": "collapseAll",
1465                         focus: function( event, keepActiveItem ) {
1466
1467                                 // If there's already an active item, keep it active
1468                                 // If not, activate the first item
1469                                 var item = this.active || this._menuItems().first();
1470
1471                                 if ( !keepActiveItem ) {
1472                                         this.focus( event, item );
1473                                 }
1474                         },
1475                         blur: function( event ) {
1476                                 this._delay( function() {
1477                                         var notContained = !$.contains(
1478                                                 this.element[ 0 ],
1479                                                 $.ui.safeActiveElement( this.document[ 0 ] )
1480                                         );
1481                                         if ( notContained ) {
1482                                                 this.collapseAll( event );
1483                                         }
1484                                 } );
1485                         },
1486                         keydown: "_keydown"
1487                 } );
1488
1489                 this.refresh();
1490
1491                 // Clicks outside of a menu collapse any open menus
1492                 this._on( this.document, {
1493                         click: function( event ) {
1494                                 if ( this._closeOnDocumentClick( event ) ) {
1495                                         this.collapseAll( event, true );
1496                                 }
1497
1498                                 // Reset the mouseHandled flag
1499                                 this.mouseHandled = false;
1500                         }
1501                 } );
1502         },
1503
1504         _activateItem: function( event ) {
1505
1506                 // Ignore mouse events while typeahead is active, see #10458.
1507                 // Prevents focusing the wrong item when typeahead causes a scroll while the mouse
1508                 // is over an item in the menu
1509                 if ( this.previousFilter ) {
1510                         return;
1511                 }
1512
1513                 // If the mouse didn't actually move, but the page was scrolled, ignore the event (#9356)
1514                 if ( event.clientX === this.lastMousePosition.x &&
1515                                 event.clientY === this.lastMousePosition.y ) {
1516                         return;
1517                 }
1518
1519                 this.lastMousePosition = {
1520                         x: event.clientX,
1521                         y: event.clientY
1522                 };
1523
1524                 var actualTarget = $( event.target ).closest( ".ui-menu-item" ),
1525                         target = $( event.currentTarget );
1526
1527                 // Ignore bubbled events on parent items, see #11641
1528                 if ( actualTarget[ 0 ] !== target[ 0 ] ) {
1529                         return;
1530                 }
1531
1532                 // If the item is already active, there's nothing to do
1533                 if ( target.is( ".ui-state-active" ) ) {
1534                         return;
1535                 }
1536
1537                 // Remove ui-state-active class from siblings of the newly focused menu item
1538                 // to avoid a jump caused by adjacent elements both having a class with a border
1539                 this._removeClass( target.siblings().children( ".ui-state-active" ),
1540                         null, "ui-state-active" );
1541                 this.focus( event, target );
1542         },
1543
1544         _destroy: function() {
1545                 var items = this.element.find( ".ui-menu-item" )
1546                                 .removeAttr( "role aria-disabled" ),
1547                         submenus = items.children( ".ui-menu-item-wrapper" )
1548                                 .removeUniqueId()
1549                                 .removeAttr( "tabIndex role aria-haspopup" );
1550
1551                 // Destroy (sub)menus
1552                 this.element
1553                         .removeAttr( "aria-activedescendant" )
1554                         .find( ".ui-menu" ).addBack()
1555                                 .removeAttr( "role aria-labelledby aria-expanded aria-hidden aria-disabled " +
1556                                         "tabIndex" )
1557                                 .removeUniqueId()
1558                                 .show();
1559
1560                 submenus.children().each( function() {
1561                         var elem = $( this );
1562                         if ( elem.data( "ui-menu-submenu-caret" ) ) {
1563                                 elem.remove();
1564                         }
1565                 } );
1566         },
1567
1568         _keydown: function( event ) {
1569                 var match, prev, character, skip,
1570                         preventDefault = true;
1571
1572                 switch ( event.keyCode ) {
1573                 case $.ui.keyCode.PAGE_UP:
1574                         this.previousPage( event );
1575                         break;
1576                 case $.ui.keyCode.PAGE_DOWN:
1577                         this.nextPage( event );
1578                         break;
1579                 case $.ui.keyCode.HOME:
1580                         this._move( "first", "first", event );
1581                         break;
1582                 case $.ui.keyCode.END:
1583                         this._move( "last", "last", event );
1584                         break;
1585                 case $.ui.keyCode.UP:
1586                         this.previous( event );
1587                         break;
1588                 case $.ui.keyCode.DOWN:
1589                         this.next( event );
1590                         break;
1591                 case $.ui.keyCode.LEFT:
1592                         this.collapse( event );
1593                         break;
1594                 case $.ui.keyCode.RIGHT:
1595                         if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
1596                                 this.expand( event );
1597                         }
1598                         break;
1599                 case $.ui.keyCode.ENTER:
1600                 case $.ui.keyCode.SPACE:
1601                         this._activate( event );
1602                         break;
1603                 case $.ui.keyCode.ESCAPE:
1604                         this.collapse( event );
1605                         break;
1606                 default:
1607                         preventDefault = false;
1608                         prev = this.previousFilter || "";
1609                         skip = false;
1610
1611                         // Support number pad values
1612                         character = event.keyCode >= 96 && event.keyCode <= 105 ?
1613                                 ( event.keyCode - 96 ).toString() : String.fromCharCode( event.keyCode );
1614
1615                         clearTimeout( this.filterTimer );
1616
1617                         if ( character === prev ) {
1618                                 skip = true;
1619                         } else {
1620                                 character = prev + character;
1621                         }
1622
1623                         match = this._filterMenuItems( character );
1624                         match = skip && match.index( this.active.next() ) !== -1 ?
1625                                 this.active.nextAll( ".ui-menu-item" ) :
1626                                 match;
1627
1628                         // If no matches on the current filter, reset to the last character pressed
1629                         // to move down the menu to the first item that starts with that character
1630                         if ( !match.length ) {
1631                                 character = String.fromCharCode( event.keyCode );
1632                                 match = this._filterMenuItems( character );
1633                         }
1634
1635                         if ( match.length ) {
1636                                 this.focus( event, match );
1637                                 this.previousFilter = character;
1638                                 this.filterTimer = this._delay( function() {
1639                                         delete this.previousFilter;
1640                                 }, 1000 );
1641                         } else {
1642                                 delete this.previousFilter;
1643                         }
1644                 }
1645
1646                 if ( preventDefault ) {
1647                         event.preventDefault();
1648                 }
1649         },
1650
1651         _activate: function( event ) {
1652                 if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
1653                         if ( this.active.children( "[aria-haspopup='true']" ).length ) {
1654                                 this.expand( event );
1655                         } else {
1656                                 this.select( event );
1657                         }
1658                 }
1659         },
1660
1661         refresh: function() {
1662                 var menus, items, newSubmenus, newItems, newWrappers,
1663                         that = this,
1664                         icon = this.options.icons.submenu,
1665                         submenus = this.element.find( this.options.menus );
1666
1667                 this._toggleClass( "ui-menu-icons", null, !!this.element.find( ".ui-icon" ).length );
1668
1669                 // Initialize nested menus
1670                 newSubmenus = submenus.filter( ":not(.ui-menu)" )
1671                         .hide()
1672                         .attr( {
1673                                 role: this.options.role,
1674                                 "aria-hidden": "true",
1675                                 "aria-expanded": "false"
1676                         } )
1677                         .each( function() {
1678                                 var menu = $( this ),
1679                                         item = menu.prev(),
1680                                         submenuCaret = $( "<span>" ).data( "ui-menu-submenu-caret", true );
1681
1682                                 that._addClass( submenuCaret, "ui-menu-icon", "ui-icon " + icon );
1683                                 item
1684                                         .attr( "aria-haspopup", "true" )
1685                                         .prepend( submenuCaret );
1686                                 menu.attr( "aria-labelledby", item.attr( "id" ) );
1687                         } );
1688
1689                 this._addClass( newSubmenus, "ui-menu", "ui-widget ui-widget-content ui-front" );
1690
1691                 menus = submenus.add( this.element );
1692                 items = menus.find( this.options.items );
1693
1694                 // Initialize menu-items containing spaces and/or dashes only as dividers
1695                 items.not( ".ui-menu-item" ).each( function() {
1696                         var item = $( this );
1697                         if ( that._isDivider( item ) ) {
1698                                 that._addClass( item, "ui-menu-divider", "ui-widget-content" );
1699                         }
1700                 } );
1701
1702                 // Don't refresh list items that are already adapted
1703                 newItems = items.not( ".ui-menu-item, .ui-menu-divider" );
1704                 newWrappers = newItems.children()
1705                         .not( ".ui-menu" )
1706                                 .uniqueId()
1707                                 .attr( {
1708                                         tabIndex: -1,
1709                                         role: this._itemRole()
1710                                 } );
1711                 this._addClass( newItems, "ui-menu-item" )
1712                         ._addClass( newWrappers, "ui-menu-item-wrapper" );
1713
1714                 // Add aria-disabled attribute to any disabled menu item
1715                 items.filter( ".ui-state-disabled" ).attr( "aria-disabled", "true" );
1716
1717                 // If the active item has been removed, blur the menu
1718                 if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
1719                         this.blur();
1720                 }
1721         },
1722
1723         _itemRole: function() {
1724                 return {
1725                         menu: "menuitem",
1726                         listbox: "option"
1727                 }[ this.options.role ];
1728         },
1729
1730         _setOption: function( key, value ) {
1731                 if ( key === "icons" ) {
1732                         var icons = this.element.find( ".ui-menu-icon" );
1733                         this._removeClass( icons, null, this.options.icons.submenu )
1734                                 ._addClass( icons, null, value.submenu );
1735                 }
1736                 this._super( key, value );
1737         },
1738
1739         _setOptionDisabled: function( value ) {
1740                 this._super( value );
1741
1742                 this.element.attr( "aria-disabled", String( value ) );
1743                 this._toggleClass( null, "ui-state-disabled", !!value );
1744         },
1745
1746         focus: function( event, item ) {
1747                 var nested, focused, activeParent;
1748                 this.blur( event, event && event.type === "focus" );
1749
1750                 this._scrollIntoView( item );
1751
1752                 this.active = item.first();
1753
1754                 focused = this.active.children( ".ui-menu-item-wrapper" );
1755                 this._addClass( focused, null, "ui-state-active" );
1756
1757                 // Only update aria-activedescendant if there's a role
1758                 // otherwise we assume focus is managed elsewhere
1759                 if ( this.options.role ) {
1760                         this.element.attr( "aria-activedescendant", focused.attr( "id" ) );
1761                 }
1762
1763                 // Highlight active parent menu item, if any
1764                 activeParent = this.active
1765                         .parent()
1766                                 .closest( ".ui-menu-item" )
1767                                         .children( ".ui-menu-item-wrapper" );
1768                 this._addClass( activeParent, null, "ui-state-active" );
1769
1770                 if ( event && event.type === "keydown" ) {
1771                         this._close();
1772                 } else {
1773                         this.timer = this._delay( function() {
1774                                 this._close();
1775                         }, this.delay );
1776                 }
1777
1778                 nested = item.children( ".ui-menu" );
1779                 if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) {
1780                         this._startOpening( nested );
1781                 }
1782                 this.activeMenu = item.parent();
1783
1784                 this._trigger( "focus", event, { item: item } );
1785         },
1786
1787         _scrollIntoView: function( item ) {
1788                 var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
1789                 if ( this._hasScroll() ) {
1790                         borderTop = parseFloat( $.css( this.activeMenu[ 0 ], "borderTopWidth" ) ) || 0;
1791                         paddingTop = parseFloat( $.css( this.activeMenu[ 0 ], "paddingTop" ) ) || 0;
1792                         offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
1793                         scroll = this.activeMenu.scrollTop();
1794                         elementHeight = this.activeMenu.height();
1795                         itemHeight = item.outerHeight();
1796
1797                         if ( offset < 0 ) {
1798                                 this.activeMenu.scrollTop( scroll + offset );
1799                         } else if ( offset + itemHeight > elementHeight ) {
1800                                 this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );
1801                         }
1802                 }
1803         },
1804
1805         blur: function( event, fromFocus ) {
1806                 if ( !fromFocus ) {
1807                         clearTimeout( this.timer );
1808                 }
1809
1810                 if ( !this.active ) {
1811                         return;
1812                 }
1813
1814                 this._removeClass( this.active.children( ".ui-menu-item-wrapper" ),
1815                         null, "ui-state-active" );
1816
1817                 this._trigger( "blur", event, { item: this.active } );
1818                 this.active = null;
1819         },
1820
1821         _startOpening: function( submenu ) {
1822                 clearTimeout( this.timer );
1823
1824                 // Don't open if already open fixes a Firefox bug that caused a .5 pixel
1825                 // shift in the submenu position when mousing over the caret icon
1826                 if ( submenu.attr( "aria-hidden" ) !== "true" ) {
1827                         return;
1828                 }
1829
1830                 this.timer = this._delay( function() {
1831                         this._close();
1832                         this._open( submenu );
1833                 }, this.delay );
1834         },
1835
1836         _open: function( submenu ) {
1837                 var position = $.extend( {
1838                         of: this.active
1839                 }, this.options.position );
1840
1841                 clearTimeout( this.timer );
1842                 this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) )
1843                         .hide()
1844                         .attr( "aria-hidden", "true" );
1845
1846                 submenu
1847                         .show()
1848                         .removeAttr( "aria-hidden" )
1849                         .attr( "aria-expanded", "true" )
1850                         .position( position );
1851         },
1852
1853         collapseAll: function( event, all ) {
1854                 clearTimeout( this.timer );
1855                 this.timer = this._delay( function() {
1856
1857                         // If we were passed an event, look for the submenu that contains the event
1858                         var currentMenu = all ? this.element :
1859                                 $( event && event.target ).closest( this.element.find( ".ui-menu" ) );
1860
1861                         // If we found no valid submenu ancestor, use the main menu to close all
1862                         // sub menus anyway
1863                         if ( !currentMenu.length ) {
1864                                 currentMenu = this.element;
1865                         }
1866
1867                         this._close( currentMenu );
1868
1869                         this.blur( event );
1870
1871                         // Work around active item staying active after menu is blurred
1872                         this._removeClass( currentMenu.find( ".ui-state-active" ), null, "ui-state-active" );
1873
1874                         this.activeMenu = currentMenu;
1875                 }, all ? 0 : this.delay );
1876         },
1877
1878         // With no arguments, closes the currently active menu - if nothing is active
1879         // it closes all menus.  If passed an argument, it will search for menus BELOW
1880         _close: function( startMenu ) {
1881                 if ( !startMenu ) {
1882                         startMenu = this.active ? this.active.parent() : this.element;
1883                 }
1884
1885                 startMenu.find( ".ui-menu" )
1886                         .hide()
1887                         .attr( "aria-hidden", "true" )
1888                         .attr( "aria-expanded", "false" );
1889         },
1890
1891         _closeOnDocumentClick: function( event ) {
1892                 return !$( event.target ).closest( ".ui-menu" ).length;
1893         },
1894
1895         _isDivider: function( item ) {
1896
1897                 // Match hyphen, em dash, en dash
1898                 return !/[^\-\u2014\u2013\s]/.test( item.text() );
1899         },
1900
1901         collapse: function( event ) {
1902                 var newItem = this.active &&
1903                         this.active.parent().closest( ".ui-menu-item", this.element );
1904                 if ( newItem && newItem.length ) {
1905                         this._close();
1906                         this.focus( event, newItem );
1907                 }
1908         },
1909
1910         expand: function( event ) {
1911                 var newItem = this.active && this._menuItems( this.active.children( ".ui-menu" ) ).first();
1912
1913                 if ( newItem && newItem.length ) {
1914                         this._open( newItem.parent() );
1915
1916                         // Delay so Firefox will not hide activedescendant change in expanding submenu from AT
1917                         this._delay( function() {
1918                                 this.focus( event, newItem );
1919                         } );
1920                 }
1921         },
1922
1923         next: function( event ) {
1924                 this._move( "next", "first", event );
1925         },
1926
1927         previous: function( event ) {
1928                 this._move( "prev", "last", event );
1929         },
1930
1931         isFirstItem: function() {
1932                 return this.active && !this.active.prevAll( ".ui-menu-item" ).length;
1933         },
1934
1935         isLastItem: function() {
1936                 return this.active && !this.active.nextAll( ".ui-menu-item" ).length;
1937         },
1938
1939         _menuItems: function( menu ) {
1940                 return ( menu || this.element )
1941                         .find( this.options.items )
1942                         .filter( ".ui-menu-item" );
1943         },
1944
1945         _move: function( direction, filter, event ) {
1946                 var next;
1947                 if ( this.active ) {
1948                         if ( direction === "first" || direction === "last" ) {
1949                                 next = this.active
1950                                         [ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )
1951                                         .last();
1952                         } else {
1953                                 next = this.active
1954                                         [ direction + "All" ]( ".ui-menu-item" )
1955                                         .first();
1956                         }
1957                 }
1958                 if ( !next || !next.length || !this.active ) {
1959                         next = this._menuItems( this.activeMenu )[ filter ]();
1960                 }
1961
1962                 this.focus( event, next );
1963         },
1964
1965         nextPage: function( event ) {
1966                 var item, base, height;
1967
1968                 if ( !this.active ) {
1969                         this.next( event );
1970                         return;
1971                 }
1972                 if ( this.isLastItem() ) {
1973                         return;
1974                 }
1975                 if ( this._hasScroll() ) {
1976                         base = this.active.offset().top;
1977                         height = this.element.innerHeight();
1978
1979                         // jQuery 3.2 doesn't include scrollbars in innerHeight, add it back.
1980                         if ( $.fn.jquery.indexOf( "3.2." ) === 0 ) {
1981                                 height += this.element[ 0 ].offsetHeight - this.element.outerHeight();
1982                         }
1983
1984                         this.active.nextAll( ".ui-menu-item" ).each( function() {
1985                                 item = $( this );
1986                                 return item.offset().top - base - height < 0;
1987                         } );
1988
1989                         this.focus( event, item );
1990                 } else {
1991                         this.focus( event, this._menuItems( this.activeMenu )
1992                                 [ !this.active ? "first" : "last" ]() );
1993                 }
1994         },
1995
1996         previousPage: function( event ) {
1997                 var item, base, height;
1998                 if ( !this.active ) {
1999                         this.next( event );
2000                         return;
2001                 }
2002                 if ( this.isFirstItem() ) {
2003                         return;
2004                 }
2005                 if ( this._hasScroll() ) {
2006                         base = this.active.offset().top;
2007                         height = this.element.innerHeight();
2008
2009                         // jQuery 3.2 doesn't include scrollbars in innerHeight, add it back.
2010                         if ( $.fn.jquery.indexOf( "3.2." ) === 0 ) {
2011                                 height += this.element[ 0 ].offsetHeight - this.element.outerHeight();
2012                         }
2013
2014                         this.active.prevAll( ".ui-menu-item" ).each( function() {
2015                                 item = $( this );
2016                                 return item.offset().top - base + height > 0;
2017                         } );
2018
2019                         this.focus( event, item );
2020                 } else {
2021                         this.focus( event, this._menuItems( this.activeMenu ).first() );
2022                 }
2023         },
2024
2025         _hasScroll: function() {
2026                 return this.element.outerHeight() < this.element.prop( "scrollHeight" );
2027         },
2028
2029         select: function( event ) {
2030
2031                 // TODO: It should never be possible to not have an active item at this
2032                 // point, but the tests don't trigger mouseenter before click.
2033                 this.active = this.active || $( event.target ).closest( ".ui-menu-item" );
2034                 var ui = { item: this.active };
2035                 if ( !this.active.has( ".ui-menu" ).length ) {
2036                         this.collapseAll( event, true );
2037                 }
2038                 this._trigger( "select", event, ui );
2039         },
2040
2041         _filterMenuItems: function( character ) {
2042                 var escapedCharacter = character.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ),
2043                         regex = new RegExp( "^" + escapedCharacter, "i" );
2044
2045                 return this.activeMenu
2046                         .find( this.options.items )
2047
2048                                 // Only match on items, not dividers or other content (#10571)
2049                                 .filter( ".ui-menu-item" )
2050                                         .filter( function() {
2051                                                 return regex.test(
2052                                                         String.prototype.trim.call(
2053                                                                 $( this ).children( ".ui-menu-item-wrapper" ).text() ) );
2054                                         } );
2055         }
2056 } );
2057
2058
2059 /*!
2060  * jQuery UI Autocomplete 1.13.1
2061  * http://jqueryui.com
2062  *
2063  * Copyright jQuery Foundation and other contributors
2064  * Released under the MIT license.
2065  * http://jquery.org/license
2066  */
2067
2068 //>>label: Autocomplete
2069 //>>group: Widgets
2070 //>>description: Lists suggested words as the user is typing.
2071 //>>docs: http://api.jqueryui.com/autocomplete/
2072 //>>demos: http://jqueryui.com/autocomplete/
2073 //>>css.structure: ../../themes/base/core.css
2074 //>>css.structure: ../../themes/base/autocomplete.css
2075 //>>css.theme: ../../themes/base/theme.css
2076
2077
2078 $.widget( "ui.autocomplete", {
2079         version: "1.13.1",
2080         defaultElement: "<input>",
2081         options: {
2082                 appendTo: null,
2083                 autoFocus: false,
2084                 delay: 300,
2085                 minLength: 1,
2086                 position: {
2087                         my: "left top",
2088                         at: "left bottom",
2089                         collision: "none"
2090                 },
2091                 source: null,
2092
2093                 // Callbacks
2094                 change: null,
2095                 close: null,
2096                 focus: null,
2097                 open: null,
2098                 response: null,
2099                 search: null,
2100                 select: null
2101         },
2102
2103         requestIndex: 0,
2104         pending: 0,
2105         liveRegionTimer: null,
2106
2107         _create: function() {
2108
2109                 // Some browsers only repeat keydown events, not keypress events,
2110                 // so we use the suppressKeyPress flag to determine if we've already
2111                 // handled the keydown event. #7269
2112                 // Unfortunately the code for & in keypress is the same as the up arrow,
2113                 // so we use the suppressKeyPressRepeat flag to avoid handling keypress
2114                 // events when we know the keydown event was used to modify the
2115                 // search term. #7799
2116                 var suppressKeyPress, suppressKeyPressRepeat, suppressInput,
2117                         nodeName = this.element[ 0 ].nodeName.toLowerCase(),
2118                         isTextarea = nodeName === "textarea",
2119                         isInput = nodeName === "input";
2120
2121                 // Textareas are always multi-line
2122                 // Inputs are always single-line, even if inside a contentEditable element
2123                 // IE also treats inputs as contentEditable
2124                 // All other element types are determined by whether or not they're contentEditable
2125                 this.isMultiLine = isTextarea || !isInput && this._isContentEditable( this.element );
2126
2127                 this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ];
2128                 this.isNewMenu = true;
2129
2130                 this._addClass( "ui-autocomplete-input" );
2131                 this.element.attr( "autocomplete", "off" );
2132
2133                 this._on( this.element, {
2134                         keydown: function( event ) {
2135                                 if ( this.element.prop( "readOnly" ) ) {
2136                                         suppressKeyPress = true;
2137                                         suppressInput = true;
2138                                         suppressKeyPressRepeat = true;
2139                                         return;
2140                                 }
2141
2142                                 suppressKeyPress = false;
2143                                 suppressInput = false;
2144                                 suppressKeyPressRepeat = false;
2145                                 var keyCode = $.ui.keyCode;
2146                                 switch ( event.keyCode ) {
2147                                 case keyCode.PAGE_UP:
2148                                         suppressKeyPress = true;
2149                                         this._move( "previousPage", event );
2150                                         break;
2151                                 case keyCode.PAGE_DOWN:
2152                                         suppressKeyPress = true;
2153                                         this._move( "nextPage", event );
2154                                         break;
2155                                 case keyCode.UP:
2156                                         suppressKeyPress = true;
2157                                         this._keyEvent( "previous", event );
2158                                         break;
2159                                 case keyCode.DOWN:
2160                                         suppressKeyPress = true;
2161                                         this._keyEvent( "next", event );
2162                                         break;
2163                                 case keyCode.ENTER:
2164
2165                                         // when menu is open and has focus
2166                                         if ( this.menu.active ) {
2167
2168                                                 // #6055 - Opera still allows the keypress to occur
2169                                                 // which causes forms to submit
2170                                                 suppressKeyPress = true;
2171                                                 event.preventDefault();
2172                                                 this.menu.select( event );
2173                                         }
2174                                         break;
2175                                 case keyCode.TAB:
2176                                         if ( this.menu.active ) {
2177                                                 this.menu.select( event );
2178                                         }
2179                                         break;
2180                                 case keyCode.ESCAPE:
2181                                         if ( this.menu.element.is( ":visible" ) ) {
2182                                                 if ( !this.isMultiLine ) {
2183                                                         this._value( this.term );
2184                                                 }
2185                                                 this.close( event );
2186
2187                                                 // Different browsers have different default behavior for escape
2188                                                 // Single press can mean undo or clear
2189                                                 // Double press in IE means clear the whole form
2190                                                 event.preventDefault();
2191                                         }
2192                                         break;
2193                                 default:
2194                                         suppressKeyPressRepeat = true;
2195
2196                                         // search timeout should be triggered before the input value is changed
2197                                         this._searchTimeout( event );
2198                                         break;
2199                                 }
2200                         },
2201                         keypress: function( event ) {
2202                                 if ( suppressKeyPress ) {
2203                                         suppressKeyPress = false;
2204                                         if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
2205                                                 event.preventDefault();
2206                                         }
2207                                         return;
2208                                 }
2209                                 if ( suppressKeyPressRepeat ) {
2210                                         return;
2211                                 }
2212
2213                                 // Replicate some key handlers to allow them to repeat in Firefox and Opera
2214                                 var keyCode = $.ui.keyCode;
2215                                 switch ( event.keyCode ) {
2216                                 case keyCode.PAGE_UP:
2217                                         this._move( "previousPage", event );
2218                                         break;
2219                                 case keyCode.PAGE_DOWN:
2220                                         this._move( "nextPage", event );
2221                                         break;
2222                                 case keyCode.UP:
2223                                         this._keyEvent( "previous", event );
2224                                         break;
2225                                 case keyCode.DOWN:
2226                                         this._keyEvent( "next", event );
2227                                         break;
2228                                 }
2229                         },
2230                         input: function( event ) {
2231                                 if ( suppressInput ) {
2232                                         suppressInput = false;
2233                                         event.preventDefault();
2234                                         return;
2235                                 }
2236                                 this._searchTimeout( event );
2237                         },
2238                         focus: function() {
2239                                 this.selectedItem = null;
2240                                 this.previous = this._value();
2241                         },
2242                         blur: function( event ) {
2243                                 clearTimeout( this.searching );
2244                                 this.close( event );
2245                                 this._change( event );
2246                         }
2247                 } );
2248
2249                 this._initSource();
2250                 this.menu = $( "<ul>" )
2251                         .appendTo( this._appendTo() )
2252                         .menu( {
2253
2254                                 // disable ARIA support, the live region takes care of that
2255                                 role: null
2256                         } )
2257                         .hide()
2258
2259                         // Support: IE 11 only, Edge <= 14
2260                         // For other browsers, we preventDefault() on the mousedown event
2261                         // to keep the dropdown from taking focus from the input. This doesn't
2262                         // work for IE/Edge, causing problems with selection and scrolling (#9638)
2263                         // Happily, IE and Edge support an "unselectable" attribute that
2264                         // prevents an element from receiving focus, exactly what we want here.
2265                         .attr( {
2266                                 "unselectable": "on"
2267                         } )
2268                         .menu( "instance" );
2269
2270                 this._addClass( this.menu.element, "ui-autocomplete", "ui-front" );
2271                 this._on( this.menu.element, {
2272                         mousedown: function( event ) {
2273
2274                                 // Prevent moving focus out of the text field
2275                                 event.preventDefault();
2276                         },
2277                         menufocus: function( event, ui ) {
2278                                 var label, item;
2279
2280                                 // support: Firefox
2281                                 // Prevent accidental activation of menu items in Firefox (#7024 #9118)
2282                                 if ( this.isNewMenu ) {
2283                                         this.isNewMenu = false;
2284                                         if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {
2285                                                 this.menu.blur();
2286
2287                                                 this.document.one( "mousemove", function() {
2288                                                         $( event.target ).trigger( event.originalEvent );
2289                                                 } );
2290
2291                                                 return;
2292                                         }
2293                                 }
2294
2295                                 item = ui.item.data( "ui-autocomplete-item" );
2296                                 if ( false !== this._trigger( "focus", event, { item: item } ) ) {
2297
2298                                         // use value to match what will end up in the input, if it was a key event
2299                                         if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
2300                                                 this._value( item.value );
2301                                         }
2302                                 }
2303
2304                                 // Announce the value in the liveRegion
2305                                 label = ui.item.attr( "aria-label" ) || item.value;
2306                                 if ( label && String.prototype.trim.call( label ).length ) {
2307                                         clearTimeout( this.liveRegionTimer );
2308                                         this.liveRegionTimer = this._delay( function() {
2309                                                 this.liveRegion.html( $( "<div>" ).text( label ) );
2310                                         }, 100 );
2311                                 }
2312                         },
2313                         menuselect: function( event, ui ) {
2314                                 var item = ui.item.data( "ui-autocomplete-item" ),
2315                                         previous = this.previous;
2316
2317                                 // Only trigger when focus was lost (click on menu)
2318                                 if ( this.element[ 0 ] !== $.ui.safeActiveElement( this.document[ 0 ] ) ) {
2319                                         this.element.trigger( "focus" );
2320                                         this.previous = previous;
2321
2322                                         // #6109 - IE triggers two focus events and the second
2323                                         // is asynchronous, so we need to reset the previous
2324                                         // term synchronously and asynchronously :-(
2325                                         this._delay( function() {
2326                                                 this.previous = previous;
2327                                                 this.selectedItem = item;
2328                                         } );
2329                                 }
2330
2331                                 if ( false !== this._trigger( "select", event, { item: item } ) ) {
2332                                         this._value( item.value );
2333                                 }
2334
2335                                 // reset the term after the select event
2336                                 // this allows custom select handling to work properly
2337                                 this.term = this._value();
2338
2339                                 this.close( event );
2340                                 this.selectedItem = item;
2341                         }
2342                 } );
2343
2344                 this.liveRegion = $( "<div>", {
2345                         role: "status",
2346                         "aria-live": "assertive",
2347                         "aria-relevant": "additions"
2348                 } )
2349                         .appendTo( this.document[ 0 ].body );
2350
2351                 this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" );
2352
2353                 // Turning off autocomplete prevents the browser from remembering the
2354                 // value when navigating through history, so we re-enable autocomplete
2355                 // if the page is unloaded before the widget is destroyed. #7790
2356                 this._on( this.window, {
2357                         beforeunload: function() {
2358                                 this.element.removeAttr( "autocomplete" );
2359                         }
2360                 } );
2361         },
2362
2363         _destroy: function() {
2364                 clearTimeout( this.searching );
2365                 this.element.removeAttr( "autocomplete" );
2366                 this.menu.element.remove();
2367                 this.liveRegion.remove();
2368         },
2369
2370         _setOption: function( key, value ) {
2371                 this._super( key, value );
2372                 if ( key === "source" ) {
2373                         this._initSource();
2374                 }
2375                 if ( key === "appendTo" ) {
2376                         this.menu.element.appendTo( this._appendTo() );
2377                 }
2378                 if ( key === "disabled" && value && this.xhr ) {
2379                         this.xhr.abort();
2380                 }
2381         },
2382
2383         _isEventTargetInWidget: function( event ) {
2384                 var menuElement = this.menu.element[ 0 ];
2385
2386                 return event.target === this.element[ 0 ] ||
2387                         event.target === menuElement ||
2388                         $.contains( menuElement, event.target );
2389         },
2390
2391         _closeOnClickOutside: function( event ) {
2392                 if ( !this._isEventTargetInWidget( event ) ) {
2393                         this.close();
2394                 }
2395         },
2396
2397         _appendTo: function() {
2398                 var element = this.options.appendTo;
2399
2400                 if ( element ) {
2401                         element = element.jquery || element.nodeType ?
2402                                 $( element ) :
2403                                 this.document.find( element ).eq( 0 );
2404                 }
2405
2406                 if ( !element || !element[ 0 ] ) {
2407                         element = this.element.closest( ".ui-front, dialog" );
2408                 }
2409
2410                 if ( !element.length ) {
2411                         element = this.document[ 0 ].body;
2412                 }
2413
2414                 return element;
2415         },
2416
2417         _initSource: function() {
2418                 var array, url,
2419                         that = this;
2420                 if ( Array.isArray( this.options.source ) ) {
2421                         array = this.options.source;
2422                         this.source = function( request, response ) {
2423                                 response( $.ui.autocomplete.filter( array, request.term ) );
2424                         };
2425                 } else if ( typeof this.options.source === "string" ) {
2426                         url = this.options.source;
2427                         this.source = function( request, response ) {
2428                                 if ( that.xhr ) {
2429                                         that.xhr.abort();
2430                                 }
2431                                 that.xhr = $.ajax( {
2432                                         url: url,
2433                                         data: request,
2434                                         dataType: "json",
2435                                         success: function( data ) {
2436                                                 response( data );
2437                                         },
2438                                         error: function() {
2439                                                 response( [] );
2440                                         }
2441                                 } );
2442                         };
2443                 } else {
2444                         this.source = this.options.source;
2445                 }
2446         },
2447
2448         _searchTimeout: function( event ) {
2449                 clearTimeout( this.searching );
2450                 this.searching = this._delay( function() {
2451
2452                         // Search if the value has changed, or if the user retypes the same value (see #7434)
2453                         var equalValues = this.term === this._value(),
2454                                 menuVisible = this.menu.element.is( ":visible" ),
2455                                 modifierKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
2456
2457                         if ( !equalValues || ( equalValues && !menuVisible && !modifierKey ) ) {
2458                                 this.selectedItem = null;
2459                                 this.search( null, event );
2460                         }
2461                 }, this.options.delay );
2462         },
2463
2464         search: function( value, event ) {
2465                 value = value != null ? value : this._value();
2466
2467                 // Always save the actual value, not the one passed as an argument
2468                 this.term = this._value();
2469
2470                 if ( value.length < this.options.minLength ) {
2471                         return this.close( event );
2472                 }
2473
2474                 if ( this._trigger( "search", event ) === false ) {
2475                         return;
2476                 }
2477
2478                 return this._search( value );
2479         },
2480
2481         _search: function( value ) {
2482                 this.pending++;
2483                 this._addClass( "ui-autocomplete-loading" );
2484                 this.cancelSearch = false;
2485
2486                 this.source( { term: value }, this._response() );
2487         },
2488
2489         _response: function() {
2490                 var index = ++this.requestIndex;
2491
2492                 return function( content ) {
2493                         if ( index === this.requestIndex ) {
2494                                 this.__response( content );
2495                         }
2496
2497                         this.pending--;
2498                         if ( !this.pending ) {
2499                                 this._removeClass( "ui-autocomplete-loading" );
2500                         }
2501                 }.bind( this );
2502         },
2503
2504         __response: function( content ) {
2505                 if ( content ) {
2506                         content = this._normalize( content );
2507                 }
2508                 this._trigger( "response", null, { content: content } );
2509                 if ( !this.options.disabled && content && content.length && !this.cancelSearch ) {
2510                         this._suggest( content );
2511                         this._trigger( "open" );
2512                 } else {
2513
2514                         // use ._close() instead of .close() so we don't cancel future searches
2515                         this._close();
2516                 }
2517         },
2518
2519         close: function( event ) {
2520                 this.cancelSearch = true;
2521                 this._close( event );
2522         },
2523
2524         _close: function( event ) {
2525
2526                 // Remove the handler that closes the menu on outside clicks
2527                 this._off( this.document, "mousedown" );
2528
2529                 if ( this.menu.element.is( ":visible" ) ) {
2530                         this.menu.element.hide();
2531                         this.menu.blur();
2532                         this.isNewMenu = true;
2533                         this._trigger( "close", event );
2534                 }
2535         },
2536
2537         _change: function( event ) {
2538                 if ( this.previous !== this._value() ) {
2539                         this._trigger( "change", event, { item: this.selectedItem } );
2540                 }
2541         },
2542
2543         _normalize: function( items ) {
2544
2545                 // assume all items have the right format when the first item is complete
2546                 if ( items.length && items[ 0 ].label && items[ 0 ].value ) {
2547                         return items;
2548                 }
2549                 return $.map( items, function( item ) {
2550                         if ( typeof item === "string" ) {
2551                                 return {
2552                                         label: item,
2553                                         value: item
2554                                 };
2555                         }
2556                         return $.extend( {}, item, {
2557                                 label: item.label || item.value,
2558                                 value: item.value || item.label
2559                         } );
2560                 } );
2561         },
2562
2563         _suggest: function( items ) {
2564                 var ul = this.menu.element.empty();
2565                 this._renderMenu( ul, items );
2566                 this.isNewMenu = true;
2567                 this.menu.refresh();
2568
2569                 // Size and position menu
2570                 ul.show();
2571                 this._resizeMenu();
2572                 ul.position( $.extend( {
2573                         of: this.element
2574                 }, this.options.position ) );
2575
2576                 if ( this.options.autoFocus ) {
2577                         this.menu.next();
2578                 }
2579
2580                 // Listen for interactions outside of the widget (#6642)
2581                 this._on( this.document, {
2582                         mousedown: "_closeOnClickOutside"
2583                 } );
2584         },
2585
2586         _resizeMenu: function() {
2587                 var ul = this.menu.element;
2588                 ul.outerWidth( Math.max(
2589
2590                         // Firefox wraps long text (possibly a rounding bug)
2591                         // so we add 1px to avoid the wrapping (#7513)
2592                         ul.width( "" ).outerWidth() + 1,
2593                         this.element.outerWidth()
2594                 ) );
2595         },
2596
2597         _renderMenu: function( ul, items ) {
2598                 var that = this;
2599                 $.each( items, function( index, item ) {
2600                         that._renderItemData( ul, item );
2601                 } );
2602         },
2603
2604         _renderItemData: function( ul, item ) {
2605                 return this._renderItem( ul, item ).data( "ui-autocomplete-item", item );
2606         },
2607
2608         _renderItem: function( ul, item ) {
2609                 return $( "<li>" )
2610                         .append( $( "<div>" ).text( item.label ) )
2611                         .appendTo( ul );
2612         },
2613
2614         _move: function( direction, event ) {
2615                 if ( !this.menu.element.is( ":visible" ) ) {
2616                         this.search( null, event );
2617                         return;
2618                 }
2619                 if ( this.menu.isFirstItem() && /^previous/.test( direction ) ||
2620                                 this.menu.isLastItem() && /^next/.test( direction ) ) {
2621
2622                         if ( !this.isMultiLine ) {
2623                                 this._value( this.term );
2624                         }
2625
2626                         this.menu.blur();
2627                         return;
2628                 }
2629                 this.menu[ direction ]( event );
2630         },
2631
2632         widget: function() {
2633                 return this.menu.element;
2634         },
2635
2636         _value: function() {
2637                 return this.valueMethod.apply( this.element, arguments );
2638         },
2639
2640         _keyEvent: function( keyEvent, event ) {
2641                 if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
2642                         this._move( keyEvent, event );
2643
2644                         // Prevents moving cursor to beginning/end of the text field in some browsers
2645                         event.preventDefault();
2646                 }
2647         },
2648
2649         // Support: Chrome <=50
2650         // We should be able to just use this.element.prop( "isContentEditable" )
2651         // but hidden elements always report false in Chrome.
2652         // https://code.google.com/p/chromium/issues/detail?id=313082
2653         _isContentEditable: function( element ) {
2654                 if ( !element.length ) {
2655                         return false;
2656                 }
2657
2658                 var editable = element.prop( "contentEditable" );
2659
2660                 if ( editable === "inherit" ) {
2661                         return this._isContentEditable( element.parent() );
2662                 }
2663
2664                 return editable === "true";
2665         }
2666 } );
2667
2668 $.extend( $.ui.autocomplete, {
2669         escapeRegex: function( value ) {
2670                 return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
2671         },
2672         filter: function( array, term ) {
2673                 var matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), "i" );
2674                 return $.grep( array, function( value ) {
2675                         return matcher.test( value.label || value.value || value );
2676                 } );
2677         }
2678 } );
2679
2680 // Live region extension, adding a `messages` option
2681 // NOTE: This is an experimental API. We are still investigating
2682 // a full solution for string manipulation and internationalization.
2683 $.widget( "ui.autocomplete", $.ui.autocomplete, {
2684         options: {
2685                 messages: {
2686                         noResults: "No search results.",
2687                         results: function( amount ) {
2688                                 return amount + ( amount > 1 ? " results are" : " result is" ) +
2689                                         " available, use up and down arrow keys to navigate.";
2690                         }
2691                 }
2692         },
2693
2694         __response: function( content ) {
2695                 var message;
2696                 this._superApply( arguments );
2697                 if ( this.options.disabled || this.cancelSearch ) {
2698                         return;
2699                 }
2700                 if ( content && content.length ) {
2701                         message = this.options.messages.results( content.length );
2702                 } else {
2703                         message = this.options.messages.noResults;
2704                 }
2705                 clearTimeout( this.liveRegionTimer );
2706                 this.liveRegionTimer = this._delay( function() {
2707                         this.liveRegion.html( $( "<div>" ).text( message ) );
2708                 }, 100 );
2709         }
2710 } );
2711
2712 var widgetsAutocomplete = $.ui.autocomplete;
2713
2714
2715
2716
2717 } );