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